xref: /plan9-contrib/sys/src/cmd/gs/src/gdevwpr2.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
13ff48bf5SDavid du Colombier /* Copyright (C) 1989, 2000 Aladdin Enterprises.  All rights reserved.
27dd7cddfSDavid du Colombier 
3*593dc095SDavid du Colombier   This software is provided AS-IS with no warranty, either express or
4*593dc095SDavid du Colombier   implied.
57dd7cddfSDavid du Colombier 
6*593dc095SDavid du Colombier   This software is distributed under license and may not be copied,
7*593dc095SDavid du Colombier   modified or distributed except as expressly authorized under the terms
8*593dc095SDavid du Colombier   of the license contained in the file LICENSE in this distribution.
97dd7cddfSDavid du Colombier 
10*593dc095SDavid du Colombier   For more information about licensing, please refer to
11*593dc095SDavid du Colombier   http://www.ghostscript.com/licensing/. For information on
12*593dc095SDavid du Colombier   commercial licensing, go to http://www.artifex.com/licensing/ or
13*593dc095SDavid du Colombier   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14*593dc095SDavid du Colombier   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
157dd7cddfSDavid du Colombier */
167dd7cddfSDavid du Colombier 
17*593dc095SDavid du Colombier /* $Id: gdevwpr2.c,v 1.18 2004/08/05 17:02:36 stefan Exp $ */
187dd7cddfSDavid du Colombier /*
197dd7cddfSDavid du Colombier  * Microsoft Windows 3.n printer driver for Ghostscript.
207dd7cddfSDavid du Colombier  * Original version by Russell Lang and
217dd7cddfSDavid du Colombier  * L. Peter Deutsch, Aladdin Enterprises.
227dd7cddfSDavid du Colombier  * Modified by rjl 1995-03-29 to use BMP printer code
237dd7cddfSDavid du Colombier  * Modified by Pierre Arnaud 1999-02-18 (see description below)
247dd7cddfSDavid du Colombier  * Modified by lpd 1999-04-03 for compatibility with Borland C++ 4.5.
257dd7cddfSDavid du Colombier  * Modified by Pierre Arnaud 1999-10-03 (accept b&w printing on color printers).
267dd7cddfSDavid du Colombier  * Modified by Pierre Arnaud 1999-11-20 (accept lower resolution)
277dd7cddfSDavid du Colombier  * Bug fixed by Pierre Arnaud 2000-03-09 (win_pr2_put_params error when is_open)
283ff48bf5SDavid du Colombier  * Bug fixed by Pierre Arnaud 2000-03-20 (win_pr2_set_bpp did not set anti_alias)
293ff48bf5SDavid du Colombier  * Bug fixed by Pierre Arnaud 2000-03-22 (win_pr2_set_bpp depth was wrong)
303ff48bf5SDavid du Colombier  * Modified by Pierre Arnaud 2000-12-12 (mainly added support for Tumble)
313ff48bf5SDavid du Colombier  * Bug fixed by Pierre Arnaud 2000-12-18 (-dQueryUser now works from cmd line)
327dd7cddfSDavid du Colombier  */
337dd7cddfSDavid du Colombier 
347dd7cddfSDavid du Colombier /* This driver uses the printer default size and resolution and
357dd7cddfSDavid du Colombier  * ignores page size and resolution set using -gWIDTHxHEIGHT and
367dd7cddfSDavid du Colombier  * -rXxY.  You must still set the correct PageSize to get the
377dd7cddfSDavid du Colombier  * correct clipping path.
387dd7cddfSDavid du Colombier  * The code in win_pr2_getdc() does try to set the printer page
397dd7cddfSDavid du Colombier  * size from the PostScript PageSize, but it isn't working
407dd7cddfSDavid du Colombier  * reliably at the moment.
417dd7cddfSDavid du Colombier  *
427dd7cddfSDavid du Colombier  * This driver doesn't work with some Windows printer drivers.
437dd7cddfSDavid du Colombier  * The reason is unknown.  All printers to which I have access
447dd7cddfSDavid du Colombier  * work.
457dd7cddfSDavid du Colombier  *
467dd7cddfSDavid du Colombier  * rjl 1997-11-20
477dd7cddfSDavid du Colombier  */
487dd7cddfSDavid du Colombier 
493ff48bf5SDavid du Colombier /* Additions by Pierre Arnaud (Pierre.Arnaud@opac.ch)
507dd7cddfSDavid du Colombier  *
517dd7cddfSDavid du Colombier  * The driver has been extended in order to provide some run-time
527dd7cddfSDavid du Colombier  * feed-back about the default Windows printer and to give the user
537dd7cddfSDavid du Colombier  * the opportunity to select the printer's properties before the
547dd7cddfSDavid du Colombier  * device gets opened (and any spooling starts).
557dd7cddfSDavid du Colombier  *
567dd7cddfSDavid du Colombier  * The driver returns an additional property named "UserSettings".
577dd7cddfSDavid du Colombier  * This is a dictionary which contens are valid only after setting
587dd7cddfSDavid du Colombier  * the QueryUser property (see below). The UserSettings dict contains
597dd7cddfSDavid du Colombier  * the following keys:
607dd7cddfSDavid du Colombier  *
617dd7cddfSDavid du Colombier  *  DocumentRange  [begin end]		(int array, can be set)
627dd7cddfSDavid du Colombier  *	Defines the range of pages in the document; [1 10] would
637dd7cddfSDavid du Colombier  *	describe a document starting at page 1 and ending at page 10.
647dd7cddfSDavid du Colombier  *
657dd7cddfSDavid du Colombier  *  SelectedRange  [begin end]		(int array, can be set)
667dd7cddfSDavid du Colombier  *	Defines the pages the user wants to print.
677dd7cddfSDavid du Colombier  *
687dd7cddfSDavid du Colombier  *  MediaSize	   [width height]	(float array, read only)
697dd7cddfSDavid du Colombier  *	Current printer's media size.
707dd7cddfSDavid du Colombier  *
717dd7cddfSDavid du Colombier  *  Copies	   n			(integer, can be set)
727dd7cddfSDavid du Colombier  *	User selected number of copies.
737dd7cddfSDavid du Colombier  *
747dd7cddfSDavid du Colombier  *  PrintCopies    n			(integer, read only)
757dd7cddfSDavid du Colombier  *	Number of copies which must be printed by Ghostscript itself.
767dd7cddfSDavid du Colombier  *	This is still experimental.
777dd7cddfSDavid du Colombier  *
787dd7cddfSDavid du Colombier  *  DocumentName   name			(string, can be set)
797dd7cddfSDavid du Colombier  *	Name to be associated with the print job.
807dd7cddfSDavid du Colombier  *
817dd7cddfSDavid du Colombier  *  UserChangedSettings			(bool, read only)
827dd7cddfSDavid du Colombier  *	Set to 'true' if the last QueryUser operation succeeded.
837dd7cddfSDavid du Colombier  *
847dd7cddfSDavid du Colombier  *  Paper	   n			(integer, can be set)
857dd7cddfSDavid du Colombier  *	Windows paper selection (0 = automatic).
867dd7cddfSDavid du Colombier  *
877dd7cddfSDavid du Colombier  *  Orient	   n			(integer, can be set)
887dd7cddfSDavid du Colombier  *	Windows paper orientation (0 = automatic).
897dd7cddfSDavid du Colombier  *
907dd7cddfSDavid du Colombier  *  Color	   n			(integer, can be set)
917dd7cddfSDavid du Colombier  *	Windows color (0 = automatic, 1 = monochrome, 2 = color).
927dd7cddfSDavid du Colombier  *
937dd7cddfSDavid du Colombier  *  MaxResolution  n			(integer, can be set)
947dd7cddfSDavid du Colombier  *	Maximum resolution in pixels pet inch (0 = no maximum). If
957dd7cddfSDavid du Colombier  *	the printer has a higher resolution than the maximum, trim
967dd7cddfSDavid du Colombier  *	the used resolution to the best one (dpi_chosen <= dpi_max,
977dd7cddfSDavid du Colombier  *	with dpi_chosen = dpi_printer / ratio).
987dd7cddfSDavid du Colombier  */
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier /* Supported printer parameters are :
1017dd7cddfSDavid du Colombier  *
1027dd7cddfSDavid du Colombier  *  -dBitsPerPixel=n
1037dd7cddfSDavid du Colombier  *     Override what the Window printer driver returns.
1047dd7cddfSDavid du Colombier  *
1057dd7cddfSDavid du Colombier  *  -dNoCancel
1067dd7cddfSDavid du Colombier  *     Don't display cancel dialog box.  Useful for unattended or
1077dd7cddfSDavid du Colombier  *     console EXE operation.
1087dd7cddfSDavid du Colombier  *
1097dd7cddfSDavid du Colombier  *  -dQueryUser=n
1107dd7cddfSDavid du Colombier  *     Query user interactively for the destination printer, before
1117dd7cddfSDavid du Colombier  *     the device gets opened. This fills in the UserSettings dict
1127dd7cddfSDavid du Colombier  *     and the OutputFile name properties. The following values are
1137dd7cddfSDavid du Colombier  *     supported for n:
1147dd7cddfSDavid du Colombier  *     1 => show standard Print dialog
1157dd7cddfSDavid du Colombier  *     2 => show Print Setup dialog instead
1167dd7cddfSDavid du Colombier  *     3 => select default printer
1177dd7cddfSDavid du Colombier  *     other, does nothing
1187dd7cddfSDavid du Colombier  *
1197dd7cddfSDavid du Colombier  * The /Duplex & /Tumble keys of the setpagedevice dict are supported
1207dd7cddfSDavid du Colombier  * if the Windows printer supports duplex printing.
1217dd7cddfSDavid du Colombier  */
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier #include "gdevprn.h"
1247dd7cddfSDavid du Colombier #include "gdevpccm.h"
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier #include "windows_.h"
1277dd7cddfSDavid du Colombier #include <shellapi.h>
1287dd7cddfSDavid du Colombier #include "gp_mswin.h"
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier #include "gp.h"
1313ff48bf5SDavid du Colombier #include "gpcheck.h"
1327dd7cddfSDavid du Colombier #include "commdlg.h"
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier /* Make sure we cast to the correct structure type. */
1367dd7cddfSDavid du Colombier typedef struct gx_device_win_pr2_s gx_device_win_pr2;
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier #undef wdev
1397dd7cddfSDavid du Colombier #define wdev ((gx_device_win_pr2 *)dev)
1407dd7cddfSDavid du Colombier 
1417dd7cddfSDavid du Colombier /* Device procedures */
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier /* See gxdevice.h for the definitions of the procedures. */
1447dd7cddfSDavid du Colombier private dev_proc_open_device(win_pr2_open);
1457dd7cddfSDavid du Colombier private dev_proc_close_device(win_pr2_close);
1467dd7cddfSDavid du Colombier private dev_proc_print_page(win_pr2_print_page);
1477dd7cddfSDavid du Colombier private dev_proc_map_rgb_color(win_pr2_map_rgb_color);
1487dd7cddfSDavid du Colombier private dev_proc_map_color_rgb(win_pr2_map_color_rgb);
1497dd7cddfSDavid du Colombier private dev_proc_get_params(win_pr2_get_params);
1507dd7cddfSDavid du Colombier private dev_proc_put_params(win_pr2_put_params);
1517dd7cddfSDavid du Colombier 
1527dd7cddfSDavid du Colombier private void win_pr2_set_bpp(gx_device * dev, int depth);
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier private const gx_device_procs win_pr2_procs =
1557dd7cddfSDavid du Colombier prn_color_params_procs(win_pr2_open, gdev_prn_output_page, win_pr2_close,
1567dd7cddfSDavid du Colombier 		       win_pr2_map_rgb_color, win_pr2_map_color_rgb,
1577dd7cddfSDavid du Colombier 		       win_pr2_get_params, win_pr2_put_params);
1587dd7cddfSDavid du Colombier 
1593ff48bf5SDavid du Colombier #define PARENT_WINDOW  HWND_DESKTOP
1603ff48bf5SDavid du Colombier BOOL CALLBACK CancelDlgProc(HWND, UINT, WPARAM, LPARAM);
1613ff48bf5SDavid du Colombier BOOL CALLBACK AbortProc2(HDC, int);
1623ff48bf5SDavid du Colombier 
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier /* The device descriptor */
1657dd7cddfSDavid du Colombier typedef struct gx_device_win_pr2_s gx_device_win_pr2;
1667dd7cddfSDavid du Colombier struct gx_device_win_pr2_s {
1677dd7cddfSDavid du Colombier     gx_device_common;
1687dd7cddfSDavid du Colombier     gx_prn_device_common;
1697dd7cddfSDavid du Colombier     HDC hdcprn;
1707dd7cddfSDavid du Colombier     bool nocancel;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier     int doc_page_begin;		/* first page number in document */
1737dd7cddfSDavid du Colombier     int doc_page_end;		/* last page number in document */
1747dd7cddfSDavid du Colombier     int user_page_begin;	/* user's choice: first page to print */
1757dd7cddfSDavid du Colombier     int user_page_end;		/* user's choice: last page to print */
1767dd7cddfSDavid du Colombier     int user_copies;		/* user's choice: number of copies */
1777dd7cddfSDavid du Colombier     int print_copies;		/* number of times GS should print each page */
1787dd7cddfSDavid du Colombier     float user_media_size[2];	/* width/height of media selected by user */
1797dd7cddfSDavid du Colombier     char doc_name[200];		/* name of document for the spooler */
1807dd7cddfSDavid du Colombier     char paper_name[64];	/* name of selected paper format */
1817dd7cddfSDavid du Colombier     bool user_changed_settings;	/* true if user validated dialog */
1827dd7cddfSDavid du Colombier     int user_paper;		/* user's choice: paper format */
1837dd7cddfSDavid du Colombier     int user_orient;		/* user's choice: paper orientation */
1847dd7cddfSDavid du Colombier     int user_color;		/* user's choice: color format */
1857dd7cddfSDavid du Colombier     int max_dpi;		/* maximum resolution in DPI */
1867dd7cddfSDavid du Colombier     int ratio;			/* stretch ratio when printing */
1877dd7cddfSDavid du Colombier     int selected_bpp;		/* selected bpp, memorised by win_pr2_set_bpp */
1883ff48bf5SDavid du Colombier     bool tumble;		/* tumble setting (with duplex) */
1893ff48bf5SDavid du Colombier     int query_user;		/* query user (-dQueryUser) */
1907dd7cddfSDavid du Colombier 
1917dd7cddfSDavid du Colombier     HANDLE win32_hdevmode;	/* handle to device mode information */
1927dd7cddfSDavid du Colombier     HANDLE win32_hdevnames;	/* handle to device names information */
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier     DLGPROC lpfnAbortProc;
1957dd7cddfSDavid du Colombier     DLGPROC lpfnCancelProc;
1963ff48bf5SDavid du Colombier     HWND hDlgModeless;
1977dd7cddfSDavid du Colombier 
1983ff48bf5SDavid du Colombier     bool use_old_spool_name;	/* user prefers old \\spool\ name */
1997dd7cddfSDavid du Colombier     gx_device_win_pr2* original_device;	/* used to detect copies */
2007dd7cddfSDavid du Colombier };
2017dd7cddfSDavid du Colombier 
2027dd7cddfSDavid du Colombier gx_device_win_pr2 far_data gs_mswinpr2_device =
2037dd7cddfSDavid du Colombier {
2047dd7cddfSDavid du Colombier     prn_device_std_body(gx_device_win_pr2, win_pr2_procs, "mswinpr2",
2057dd7cddfSDavid du Colombier 		      DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72.0, 72.0,
2067dd7cddfSDavid du Colombier 			0, 0, 0, 0,
2077dd7cddfSDavid du Colombier 			0, win_pr2_print_page),		/* depth = 0 */
2087dd7cddfSDavid du Colombier     0,				/* hdcprn */
2097dd7cddfSDavid du Colombier     0,				/* nocancel */
2107dd7cddfSDavid du Colombier     0,				/* doc_page_begin */
2117dd7cddfSDavid du Colombier     0,				/* doc_page_end */
2127dd7cddfSDavid du Colombier     0,				/* user_page_begin */
2137dd7cddfSDavid du Colombier     0,				/* user_page_end */
2147dd7cddfSDavid du Colombier     1,				/* user_copies */
2157dd7cddfSDavid du Colombier     1,				/* print_copies */
2167dd7cddfSDavid du Colombier     { 0.0, 0.0 },		/* user_media_size */
2177dd7cddfSDavid du Colombier     { 0 },			/* doc_name */
2187dd7cddfSDavid du Colombier     { 0 },			/* paper_name */
2197dd7cddfSDavid du Colombier     0,				/* user_changed_settings */
2207dd7cddfSDavid du Colombier     0,				/* user_paper */
2217dd7cddfSDavid du Colombier     0,				/* user_orient */
2227dd7cddfSDavid du Colombier     0,				/* user_color */
2237dd7cddfSDavid du Colombier     0,				/* max_dpi */
2247dd7cddfSDavid du Colombier     0,				/* ratio */
2257dd7cddfSDavid du Colombier     0,				/* selected_bpp */
2263ff48bf5SDavid du Colombier     false,			/* tumble */
2273ff48bf5SDavid du Colombier     -1,				/* query_user */
2287dd7cddfSDavid du Colombier     NULL,			/* win32_hdevmode */
2297dd7cddfSDavid du Colombier     NULL,			/* win32_hdevnames */
2307dd7cddfSDavid du Colombier     NULL,			/* lpfnAbortProc */
2317dd7cddfSDavid du Colombier     NULL,			/* lpfnCancelProc */
232*593dc095SDavid du Colombier     NULL,			/* hDlgModeless */
2333ff48bf5SDavid du Colombier     false,			/* use_old_spool_name */
2347dd7cddfSDavid du Colombier     NULL			/* original_device */
2357dd7cddfSDavid du Colombier };
2367dd7cddfSDavid du Colombier 
2377dd7cddfSDavid du Colombier /********************************************************************************/
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier private int win_pr2_getdc(gx_device_win_pr2 * dev);
2407dd7cddfSDavid du Colombier private int win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
2417dd7cddfSDavid du Colombier private int win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
2427dd7cddfSDavid du Colombier private int win_pr2_print_setup_interaction(gx_device_win_pr2 * dev, int mode);
2437dd7cddfSDavid du Colombier private int win_pr2_write_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
2447dd7cddfSDavid du Colombier private int win_pr2_read_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
2457dd7cddfSDavid du Colombier private void win_pr2_copy_check(gx_device_win_pr2 * dev);
2467dd7cddfSDavid du Colombier 
2477dd7cddfSDavid du Colombier /********************************************************************************/
2487dd7cddfSDavid du Colombier 
2497dd7cddfSDavid du Colombier /* Open the win_pr2 driver */
2507dd7cddfSDavid du Colombier private int
win_pr2_open(gx_device * dev)2517dd7cddfSDavid du Colombier win_pr2_open(gx_device * dev)
2527dd7cddfSDavid du Colombier {
2537dd7cddfSDavid du Colombier     int code;
2547dd7cddfSDavid du Colombier     int depth;
2557dd7cddfSDavid du Colombier     PRINTDLG pd;
2567dd7cddfSDavid du Colombier     POINT offset;
2577dd7cddfSDavid du Colombier     POINT size;
2587dd7cddfSDavid du Colombier     float m[4];
2597dd7cddfSDavid du Colombier     FILE *pfile;
2607dd7cddfSDavid du Colombier     DOCINFO docinfo;
2617dd7cddfSDavid du Colombier     float ratio = 1.0;
2627dd7cddfSDavid du Colombier 
2637dd7cddfSDavid du Colombier     win_pr2_copy_check(wdev);
2647dd7cddfSDavid du Colombier 
2657dd7cddfSDavid du Colombier     /* get a HDC for the printer */
2667dd7cddfSDavid du Colombier     if ((wdev->win32_hdevmode) &&
2677dd7cddfSDavid du Colombier 	(wdev->win32_hdevnames)) {
2687dd7cddfSDavid du Colombier 	/* The user has already had the opportunity to choose the output */
2697dd7cddfSDavid du Colombier 	/* file interactively. Just use the specified parameters. */
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 	LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
2727dd7cddfSDavid du Colombier 	LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
2737dd7cddfSDavid du Colombier 
2747dd7cddfSDavid du Colombier 	const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
2757dd7cddfSDavid du Colombier 	const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
2767dd7cddfSDavid du Colombier 	const char* output = (char*)(devnames)+(devnames->wOutputOffset);
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier 	wdev->hdcprn = CreateDC(driver, device, output, devmode);
2797dd7cddfSDavid du Colombier 
2807dd7cddfSDavid du Colombier 	GlobalUnlock(wdev->win32_hdevmode);
2817dd7cddfSDavid du Colombier 	GlobalUnlock(wdev->win32_hdevnames);
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier 	if (wdev->hdcprn == NULL) {
2847dd7cddfSDavid du Colombier 	    return gs_error_Fatal;
2857dd7cddfSDavid du Colombier 	}
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier     } else if (!win_pr2_getdc(wdev)) {
2887dd7cddfSDavid du Colombier 	/* couldn't get a printer from -sOutputFile= */
2897dd7cddfSDavid du Colombier 	/* Prompt with dialog box */
2907dd7cddfSDavid du Colombier 
2917dd7cddfSDavid du Colombier 	LPDEVMODE devmode = NULL;
2927dd7cddfSDavid du Colombier 	memset(&pd, 0, sizeof(pd));
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 	pd.lStructSize = sizeof(pd);
2953ff48bf5SDavid du Colombier 	pd.hwndOwner = PARENT_WINDOW;
2967dd7cddfSDavid du Colombier 	pd.Flags = PD_RETURNDC;
2977dd7cddfSDavid du Colombier 	pd.nMinPage = wdev->doc_page_begin;
2987dd7cddfSDavid du Colombier 	pd.nMaxPage = wdev->doc_page_end;
2997dd7cddfSDavid du Colombier 	pd.nFromPage = wdev->user_page_begin;
3007dd7cddfSDavid du Colombier 	pd.nToPage = wdev->user_page_end;
3017dd7cddfSDavid du Colombier 	pd.nCopies = wdev->user_copies;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier 	if (!PrintDlg(&pd)) {
3047dd7cddfSDavid du Colombier 	    /* device not opened - exit ghostscript */
3057dd7cddfSDavid du Colombier 	    return gs_error_Fatal;	/* exit Ghostscript cleanly */
3067dd7cddfSDavid du Colombier 	}
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier 	devmode = GlobalLock(pd.hDevMode);
3097dd7cddfSDavid du Colombier 	win_pr2_update_dev(wdev,devmode);
3107dd7cddfSDavid du Colombier 	GlobalUnlock(pd.hDevMode);
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier 	if (wdev->win32_hdevmode)
3137dd7cddfSDavid du Colombier 	    GlobalFree(wdev->win32_hdevmode);
3147dd7cddfSDavid du Colombier 	if (wdev->win32_hdevnames)
3157dd7cddfSDavid du Colombier 	    GlobalFree(wdev->win32_hdevnames);
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	wdev->hdcprn = pd.hDC;
3187dd7cddfSDavid du Colombier 	wdev->win32_hdevmode = pd.hDevMode;
3197dd7cddfSDavid du Colombier 	wdev->win32_hdevnames = pd.hDevNames;
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier 	pd.hDevMode = NULL;
3227dd7cddfSDavid du Colombier 	pd.hDevNames = NULL;
3237dd7cddfSDavid du Colombier     }
3247dd7cddfSDavid du Colombier     if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_DIBTODEV)) {
3253ff48bf5SDavid du Colombier 	errprintf( "Windows printer does not have RC_DIBTODEV\n");
3267dd7cddfSDavid du Colombier 	DeleteDC(wdev->hdcprn);
3277dd7cddfSDavid du Colombier 	return gs_error_limitcheck;
3287dd7cddfSDavid du Colombier     }
3297dd7cddfSDavid du Colombier     /* initialise printer, install abort proc */
3303ff48bf5SDavid du Colombier     wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
3317dd7cddfSDavid du Colombier     SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);
3327dd7cddfSDavid du Colombier 
3337dd7cddfSDavid du Colombier     /*
3347dd7cddfSDavid du Colombier      * Some versions of the Windows headers include lpszDatatype and fwType,
3357dd7cddfSDavid du Colombier      * and some don't.  Since we want to set these fields to zero anyway,
3367dd7cddfSDavid du Colombier      * we just start by zeroing the whole structure.
3377dd7cddfSDavid du Colombier      */
3387dd7cddfSDavid du Colombier     memset(&docinfo, 0, sizeof(docinfo));
3397dd7cddfSDavid du Colombier     docinfo.cbSize = sizeof(docinfo);
3407dd7cddfSDavid du Colombier     docinfo.lpszDocName = wdev->doc_name;
3417dd7cddfSDavid du Colombier     /*docinfo.lpszOutput = NULL;*/
3427dd7cddfSDavid du Colombier     /*docinfo.lpszDatatype = NULL;*/
3437dd7cddfSDavid du Colombier     /*docinfo.fwType = 0;*/
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier     if (docinfo.lpszDocName[0] == 0) {
3467dd7cddfSDavid du Colombier 	docinfo.lpszDocName = "Ghostscript output";
3477dd7cddfSDavid du Colombier     }
3487dd7cddfSDavid du Colombier 
3497dd7cddfSDavid du Colombier     if (StartDoc(wdev->hdcprn, &docinfo) <= 0) {
3503ff48bf5SDavid du Colombier 	errprintf("Printer StartDoc failed (error %08x)\n", GetLastError());
3517dd7cddfSDavid du Colombier 	DeleteDC(wdev->hdcprn);
3527dd7cddfSDavid du Colombier 	return gs_error_limitcheck;
3537dd7cddfSDavid du Colombier     }
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier     dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
3567dd7cddfSDavid du Colombier     dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
3577dd7cddfSDavid du Colombier 
3587dd7cddfSDavid du Colombier     wdev->ratio = 1;
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier     if (wdev->max_dpi > 50) {
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 	float dpi_x = dev->x_pixels_per_inch;
3637dd7cddfSDavid du Colombier 	float dpi_y = dev->y_pixels_per_inch;
3647dd7cddfSDavid du Colombier 
3657dd7cddfSDavid du Colombier 	while ((dev->x_pixels_per_inch > wdev->max_dpi)
3667dd7cddfSDavid du Colombier 	    || (dev->y_pixels_per_inch > wdev->max_dpi)) {
3677dd7cddfSDavid du Colombier 	    ratio += 1.0;
3687dd7cddfSDavid du Colombier 	    wdev->ratio ++;
3697dd7cddfSDavid du Colombier 	    dev->x_pixels_per_inch = dpi_x / ratio;
3707dd7cddfSDavid du Colombier 	    dev->y_pixels_per_inch = dpi_y / ratio;
3717dd7cddfSDavid du Colombier 	}
3727dd7cddfSDavid du Colombier     }
3737dd7cddfSDavid du Colombier 
3747dd7cddfSDavid du Colombier     size.x = GetDeviceCaps(wdev->hdcprn, PHYSICALWIDTH);
3757dd7cddfSDavid du Colombier     size.y = GetDeviceCaps(wdev->hdcprn, PHYSICALHEIGHT);
3767dd7cddfSDavid du Colombier     gx_device_set_width_height(dev, (int)(size.x / ratio), (int)(size.y / ratio));
3777dd7cddfSDavid du Colombier     offset.x = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETX);
3787dd7cddfSDavid du Colombier     offset.y = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETY);
3797dd7cddfSDavid du Colombier 
3807dd7cddfSDavid du Colombier     /* m[] gives margins in inches */
3817dd7cddfSDavid du Colombier     m[0] /*left   */ = offset.x / dev->x_pixels_per_inch / ratio;
3827dd7cddfSDavid du Colombier     m[3] /*top    */ = offset.y / dev->y_pixels_per_inch / ratio;
3837dd7cddfSDavid du Colombier     m[2] /*right  */ = (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES)) / dev->x_pixels_per_inch / ratio;
3847dd7cddfSDavid du Colombier     m[1] /*bottom */ = (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES)) / dev->y_pixels_per_inch / ratio;
3857dd7cddfSDavid du Colombier     gx_device_set_margins(dev, m, true);
3867dd7cddfSDavid du Colombier 
3877dd7cddfSDavid du Colombier     depth = dev->color_info.depth;
3887dd7cddfSDavid du Colombier     if (depth == 0) {
3897dd7cddfSDavid du Colombier 	/* Set parameters that were unknown before opening device */
3907dd7cddfSDavid du Colombier 	/* Find out if the device supports color */
3917dd7cddfSDavid du Colombier 	/* We recognize 1, 4 (but use only 3), 8 and 24 bit color devices */
3927dd7cddfSDavid du Colombier 	depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
3937dd7cddfSDavid du Colombier     }
3947dd7cddfSDavid du Colombier     win_pr2_set_bpp(dev, depth);
3957dd7cddfSDavid du Colombier 
3967dd7cddfSDavid du Colombier     /* gdev_prn_open opens a temporary file which we don't want */
3977dd7cddfSDavid du Colombier     /* so we specify the name now so we can delete it later */
3987dd7cddfSDavid du Colombier     pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
3997dd7cddfSDavid du Colombier 				 wdev->fname, "wb");
4007dd7cddfSDavid du Colombier     fclose(pfile);
4017dd7cddfSDavid du Colombier     code = gdev_prn_open(dev);
4027dd7cddfSDavid du Colombier     /* delete unwanted temporary file */
4037dd7cddfSDavid du Colombier     unlink(wdev->fname);
4047dd7cddfSDavid du Colombier 
4057dd7cddfSDavid du Colombier     if (!wdev->nocancel) {
4067dd7cddfSDavid du Colombier 	/* inform user of progress with dialog box and allow cancel */
4077dd7cddfSDavid du Colombier 	wdev->lpfnCancelProc = (DLGPROC) CancelDlgProc;
4083ff48bf5SDavid du Colombier 	wdev->hDlgModeless = CreateDialog(phInstance, "CancelDlgBox",
4093ff48bf5SDavid du Colombier 				    PARENT_WINDOW, wdev->lpfnCancelProc);
4103ff48bf5SDavid du Colombier 	ShowWindow(wdev->hDlgModeless, SW_HIDE);
4117dd7cddfSDavid du Colombier     }
4127dd7cddfSDavid du Colombier     return code;
4137dd7cddfSDavid du Colombier };
4147dd7cddfSDavid du Colombier 
4157dd7cddfSDavid du Colombier /* Close the win_pr2 driver */
4167dd7cddfSDavid du Colombier private int
win_pr2_close(gx_device * dev)4177dd7cddfSDavid du Colombier win_pr2_close(gx_device * dev)
4187dd7cddfSDavid du Colombier {
4197dd7cddfSDavid du Colombier     int code;
4207dd7cddfSDavid du Colombier     int aborted = FALSE;
4217dd7cddfSDavid du Colombier 
4227dd7cddfSDavid du Colombier     win_pr2_copy_check(wdev);
4237dd7cddfSDavid du Colombier 
4247dd7cddfSDavid du Colombier     /* Free resources */
4257dd7cddfSDavid du Colombier 
4267dd7cddfSDavid du Colombier     if (!wdev->nocancel) {
4273ff48bf5SDavid du Colombier 	if (!wdev->hDlgModeless)
4287dd7cddfSDavid du Colombier 	    aborted = TRUE;
4297dd7cddfSDavid du Colombier 	else
4303ff48bf5SDavid du Colombier 	    DestroyWindow(wdev->hDlgModeless);
4313ff48bf5SDavid du Colombier 	wdev->hDlgModeless = 0;
4327dd7cddfSDavid du Colombier     }
4337dd7cddfSDavid du Colombier     if (aborted)
4347dd7cddfSDavid du Colombier 	AbortDoc(wdev->hdcprn);
4357dd7cddfSDavid du Colombier     else
4367dd7cddfSDavid du Colombier 	EndDoc(wdev->hdcprn);
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier     DeleteDC(wdev->hdcprn);
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier     if (wdev->win32_hdevmode != NULL) {
4417dd7cddfSDavid du Colombier 	GlobalFree(wdev->win32_hdevmode);
4427dd7cddfSDavid du Colombier 	wdev->win32_hdevmode = NULL;
4437dd7cddfSDavid du Colombier     }
4447dd7cddfSDavid du Colombier     if (wdev->win32_hdevnames != NULL) {
4457dd7cddfSDavid du Colombier 	GlobalFree(wdev->win32_hdevnames);
4467dd7cddfSDavid du Colombier 	wdev->win32_hdevnames = NULL;
4477dd7cddfSDavid du Colombier     }
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier     code = gdev_prn_close(dev);
4507dd7cddfSDavid du Colombier     return code;
4517dd7cddfSDavid du Colombier }
4527dd7cddfSDavid du Colombier 
4537dd7cddfSDavid du Colombier 
4547dd7cddfSDavid du Colombier /* ------ Internal routines ------ */
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier #undef wdev
4577dd7cddfSDavid du Colombier #define wdev ((gx_device_win_pr2 *)pdev)
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier /********************************************************************************/
4607dd7cddfSDavid du Colombier 
4617dd7cddfSDavid du Colombier /* ------ Private definitions ------ */
4627dd7cddfSDavid du Colombier 
4637dd7cddfSDavid du Colombier 
4647dd7cddfSDavid du Colombier /* new win_pr2_print_page routine */
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier /* Write BMP header to memory, then send bitmap to printer */
4677dd7cddfSDavid du Colombier /* one scan line at a time */
4687dd7cddfSDavid du Colombier private int
win_pr2_print_page(gx_device_printer * pdev,FILE * file)4697dd7cddfSDavid du Colombier win_pr2_print_page(gx_device_printer * pdev, FILE * file)
4707dd7cddfSDavid du Colombier {
4717dd7cddfSDavid du Colombier     int raster = gdev_prn_raster(pdev);
4727dd7cddfSDavid du Colombier 
4737dd7cddfSDavid du Colombier     /* BMP scan lines are padded to 32 bits. */
4747dd7cddfSDavid du Colombier     ulong bmp_raster = raster + (-raster & 3);
4757dd7cddfSDavid du Colombier     ulong bmp_raster_multi;
4767dd7cddfSDavid du Colombier     int scan_lines, yslice, lines, i;
4777dd7cddfSDavid du Colombier     int width;
4787dd7cddfSDavid du Colombier     int depth = pdev->color_info.depth;
4797dd7cddfSDavid du Colombier     byte *row;
4807dd7cddfSDavid du Colombier     int y;
4817dd7cddfSDavid du Colombier     int code = 0;		/* return code */
4827dd7cddfSDavid du Colombier     MSG msg;
4837dd7cddfSDavid du Colombier     char dlgtext[32];
4847dd7cddfSDavid du Colombier     HGLOBAL hrow;
4857dd7cddfSDavid du Colombier     int ratio = ((gx_device_win_pr2 *)pdev)->ratio;
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier     struct bmi_s {
4887dd7cddfSDavid du Colombier 	BITMAPINFOHEADER h;
4897dd7cddfSDavid du Colombier 	RGBQUAD pal[256];
4907dd7cddfSDavid du Colombier     } bmi;
4917dd7cddfSDavid du Colombier 
4927dd7cddfSDavid du Colombier     scan_lines = dev_print_scan_lines(pdev);
4937dd7cddfSDavid du Colombier     width = (int)(pdev->width - ((dev_l_margin(pdev) + dev_r_margin(pdev) -
4947dd7cddfSDavid du Colombier 				  dev_x_offset(pdev)) * pdev->x_pixels_per_inch));
4957dd7cddfSDavid du Colombier 
4967dd7cddfSDavid du Colombier     yslice = 65535 / bmp_raster;	/* max lines in 64k */
4977dd7cddfSDavid du Colombier     bmp_raster_multi = bmp_raster * yslice;
4987dd7cddfSDavid du Colombier     hrow = GlobalAlloc(0, bmp_raster_multi);
4997dd7cddfSDavid du Colombier     row = GlobalLock(hrow);
5007dd7cddfSDavid du Colombier     if (row == 0)		/* can't allocate row buffer */
5017dd7cddfSDavid du Colombier 	return_error(gs_error_VMerror);
5027dd7cddfSDavid du Colombier 
5037dd7cddfSDavid du Colombier     /* Write the info header. */
5047dd7cddfSDavid du Colombier 
5057dd7cddfSDavid du Colombier     bmi.h.biSize = sizeof(bmi.h);
5067dd7cddfSDavid du Colombier     bmi.h.biWidth = pdev->width;	/* wdev->mdev.width; */
5077dd7cddfSDavid du Colombier     bmi.h.biHeight = yslice;
5087dd7cddfSDavid du Colombier     bmi.h.biPlanes = 1;
5097dd7cddfSDavid du Colombier     bmi.h.biBitCount = pdev->color_info.depth;
5107dd7cddfSDavid du Colombier     bmi.h.biCompression = 0;
5117dd7cddfSDavid du Colombier     bmi.h.biSizeImage = 0;	/* default */
5127dd7cddfSDavid du Colombier     bmi.h.biXPelsPerMeter = 0;	/* default */
5137dd7cddfSDavid du Colombier     bmi.h.biYPelsPerMeter = 0;	/* default */
5147dd7cddfSDavid du Colombier 
5157dd7cddfSDavid du Colombier     StartPage(wdev->hdcprn);
5167dd7cddfSDavid du Colombier 
5177dd7cddfSDavid du Colombier     /* Write the palette. */
5187dd7cddfSDavid du Colombier 
5197dd7cddfSDavid du Colombier     if (depth <= 8) {
5207dd7cddfSDavid du Colombier 	int i;
5217dd7cddfSDavid du Colombier 	gx_color_value rgb[3];
5227dd7cddfSDavid du Colombier 	LPRGBQUAD pq;
5237dd7cddfSDavid du Colombier 
5247dd7cddfSDavid du Colombier 	bmi.h.biClrUsed = 1 << depth;
5257dd7cddfSDavid du Colombier 	bmi.h.biClrImportant = 1 << depth;
5267dd7cddfSDavid du Colombier 	for (i = 0; i != 1 << depth; i++) {
5277dd7cddfSDavid du Colombier 	    (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
5287dd7cddfSDavid du Colombier 					      (gx_color_index) i, rgb);
5297dd7cddfSDavid du Colombier 	    pq = &bmi.pal[i];
5307dd7cddfSDavid du Colombier 	    pq->rgbRed = gx_color_value_to_byte(rgb[0]);
5317dd7cddfSDavid du Colombier 	    pq->rgbGreen = gx_color_value_to_byte(rgb[1]);
5327dd7cddfSDavid du Colombier 	    pq->rgbBlue = gx_color_value_to_byte(rgb[2]);
5337dd7cddfSDavid du Colombier 	    pq->rgbReserved = 0;
5347dd7cddfSDavid du Colombier 	}
5357dd7cddfSDavid du Colombier     } else {
5367dd7cddfSDavid du Colombier 	bmi.h.biClrUsed = 0;
5377dd7cddfSDavid du Colombier 	bmi.h.biClrImportant = 0;
5387dd7cddfSDavid du Colombier     }
5397dd7cddfSDavid du Colombier 
5407dd7cddfSDavid du Colombier     if (!wdev->nocancel) {
5417dd7cddfSDavid du Colombier 	sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
5423ff48bf5SDavid du Colombier 	SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext);
5433ff48bf5SDavid du Colombier 	ShowWindow(wdev->hDlgModeless, SW_SHOW);
5447dd7cddfSDavid du Colombier     }
5457dd7cddfSDavid du Colombier     for (y = 0; y < scan_lines;) {
5467dd7cddfSDavid du Colombier 	/* copy slice to row buffer */
5477dd7cddfSDavid du Colombier 	if (y > scan_lines - yslice)
5487dd7cddfSDavid du Colombier 	    lines = scan_lines - y;
5497dd7cddfSDavid du Colombier 	else
5507dd7cddfSDavid du Colombier 	    lines = yslice;
5517dd7cddfSDavid du Colombier 	for (i = 0; i < lines; i++)
5527dd7cddfSDavid du Colombier 	    gdev_prn_copy_scan_lines(pdev, y + i,
5537dd7cddfSDavid du Colombier 			      row + (bmp_raster * (lines - 1 - i)), raster);
5547dd7cddfSDavid du Colombier 
5557dd7cddfSDavid du Colombier 	if (ratio > 1) {
5567dd7cddfSDavid du Colombier 	    StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio,
5577dd7cddfSDavid du Colombier 			  0, 0, pdev->width, lines,
5587dd7cddfSDavid du Colombier 			  row,
5597dd7cddfSDavid du Colombier 			  (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY);
5607dd7cddfSDavid du Colombier 	} else {
5617dd7cddfSDavid du Colombier 	    SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines,
5627dd7cddfSDavid du Colombier 			      0, 0, 0, lines,
5637dd7cddfSDavid du Colombier 			      row,
5647dd7cddfSDavid du Colombier 			      (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS);
5657dd7cddfSDavid du Colombier 	}
5667dd7cddfSDavid du Colombier 	y += lines;
5677dd7cddfSDavid du Colombier 
5687dd7cddfSDavid du Colombier 	if (!wdev->nocancel) {
5697dd7cddfSDavid du Colombier 	    /* inform user of progress */
5707dd7cddfSDavid du Colombier 	    sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
5713ff48bf5SDavid du Colombier 	    SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext);
5727dd7cddfSDavid du Colombier 	}
5737dd7cddfSDavid du Colombier 	/* process message loop */
5743ff48bf5SDavid du Colombier 	while (PeekMessage(&msg, wdev->hDlgModeless, 0, 0, PM_REMOVE)) {
5753ff48bf5SDavid du Colombier 	    if ((wdev->hDlgModeless == 0) || !IsDialogMessage(wdev->hDlgModeless, &msg)) {
5767dd7cddfSDavid du Colombier 		TranslateMessage(&msg);
5777dd7cddfSDavid du Colombier 		DispatchMessage(&msg);
5787dd7cddfSDavid du Colombier 	    }
5797dd7cddfSDavid du Colombier 	}
5803ff48bf5SDavid du Colombier 	if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) {
5817dd7cddfSDavid du Colombier 	    /* user pressed cancel button */
5827dd7cddfSDavid du Colombier 	    break;
5837dd7cddfSDavid du Colombier 	}
5847dd7cddfSDavid du Colombier     }
5857dd7cddfSDavid du Colombier 
5863ff48bf5SDavid du Colombier     if ((!wdev->nocancel) && (wdev->hDlgModeless == 0))
5877dd7cddfSDavid du Colombier 	code = gs_error_Fatal;	/* exit Ghostscript cleanly */
5887dd7cddfSDavid du Colombier     else {
5897dd7cddfSDavid du Colombier 	/* push out the page */
5907dd7cddfSDavid du Colombier 	if (!wdev->nocancel)
5913ff48bf5SDavid du Colombier 	    SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE),
5927dd7cddfSDavid du Colombier 			  "Ejecting page...");
5937dd7cddfSDavid du Colombier 	EndPage(wdev->hdcprn);
5947dd7cddfSDavid du Colombier 	if (!wdev->nocancel)
5953ff48bf5SDavid du Colombier 	    ShowWindow(wdev->hDlgModeless, SW_HIDE);
5967dd7cddfSDavid du Colombier     }
5977dd7cddfSDavid du Colombier 
5987dd7cddfSDavid du Colombier     GlobalUnlock(hrow);
5997dd7cddfSDavid du Colombier     GlobalFree(hrow);
6007dd7cddfSDavid du Colombier 
6017dd7cddfSDavid du Colombier     return code;
6027dd7cddfSDavid du Colombier }
6037dd7cddfSDavid du Colombier 
6047dd7cddfSDavid du Colombier /* combined color mappers */
6057dd7cddfSDavid du Colombier 
6067dd7cddfSDavid du Colombier /* 24-bit color mappers (taken from gdevmem2.c). */
6077dd7cddfSDavid du Colombier /* Note that Windows expects RGB values in the order B,G,R. */
6087dd7cddfSDavid du Colombier 
6097dd7cddfSDavid du Colombier /* Map a r-g-b color to a color index. */
6107dd7cddfSDavid du Colombier private gx_color_index
win_pr2_map_rgb_color(gx_device * dev,const gx_color_value cv[])611*593dc095SDavid du Colombier win_pr2_map_rgb_color(gx_device * dev, const gx_color_value cv[])
6127dd7cddfSDavid du Colombier {
613*593dc095SDavid du Colombier     gx_color_value r = cv[0];
614*593dc095SDavid du Colombier     gx_color_value g = cv[1];
615*593dc095SDavid du Colombier     gx_color_value b = cv[2];
6167dd7cddfSDavid du Colombier     switch (dev->color_info.depth) {
6177dd7cddfSDavid du Colombier 	case 1:
618*593dc095SDavid du Colombier 	    return gdev_prn_map_rgb_color(dev, cv);
6197dd7cddfSDavid du Colombier 	case 4:
6207dd7cddfSDavid du Colombier 	    /* use only 8 colors */
6217dd7cddfSDavid du Colombier 	    return (r > (gx_max_color_value / 2 + 1) ? 4 : 0) +
6227dd7cddfSDavid du Colombier 		(g > (gx_max_color_value / 2 + 1) ? 2 : 0) +
6237dd7cddfSDavid du Colombier 		(b > (gx_max_color_value / 2 + 1) ? 1 : 0);
6247dd7cddfSDavid du Colombier 	case 8:
625*593dc095SDavid du Colombier 	    return pc_8bit_map_rgb_color(dev, cv);
6267dd7cddfSDavid du Colombier 	case 24:
6277dd7cddfSDavid du Colombier 	    return gx_color_value_to_byte(r) +
6287dd7cddfSDavid du Colombier 		((uint) gx_color_value_to_byte(g) << 8) +
6297dd7cddfSDavid du Colombier 		((ulong) gx_color_value_to_byte(b) << 16);
6307dd7cddfSDavid du Colombier     }
6317dd7cddfSDavid du Colombier     return 0;			/* error */
6327dd7cddfSDavid du Colombier }
6337dd7cddfSDavid du Colombier 
6347dd7cddfSDavid du Colombier /* Map a color index to a r-g-b color. */
6357dd7cddfSDavid du Colombier private int
win_pr2_map_color_rgb(gx_device * dev,gx_color_index color,gx_color_value prgb[3])6367dd7cddfSDavid du Colombier win_pr2_map_color_rgb(gx_device * dev, gx_color_index color,
6377dd7cddfSDavid du Colombier 		      gx_color_value prgb[3])
6387dd7cddfSDavid du Colombier {
6397dd7cddfSDavid du Colombier     switch (dev->color_info.depth) {
6407dd7cddfSDavid du Colombier 	case 1:
6417dd7cddfSDavid du Colombier 	    gdev_prn_map_color_rgb(dev, color, prgb);
6427dd7cddfSDavid du Colombier 	    break;
6437dd7cddfSDavid du Colombier 	case 4:
6447dd7cddfSDavid du Colombier 	    /* use only 8 colors */
6457dd7cddfSDavid du Colombier 	    prgb[0] = (color & 4) ? gx_max_color_value : 0;
6467dd7cddfSDavid du Colombier 	    prgb[1] = (color & 2) ? gx_max_color_value : 0;
6477dd7cddfSDavid du Colombier 	    prgb[2] = (color & 1) ? gx_max_color_value : 0;
6487dd7cddfSDavid du Colombier 	    break;
6497dd7cddfSDavid du Colombier 	case 8:
6507dd7cddfSDavid du Colombier 	    pc_8bit_map_color_rgb(dev, color, prgb);
6517dd7cddfSDavid du Colombier 	    break;
6527dd7cddfSDavid du Colombier 	case 24:
6537dd7cddfSDavid du Colombier 	    prgb[2] = gx_color_value_from_byte(color >> 16);
6547dd7cddfSDavid du Colombier 	    prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
6557dd7cddfSDavid du Colombier 	    prgb[0] = gx_color_value_from_byte(color & 0xff);
6567dd7cddfSDavid du Colombier 	    break;
6577dd7cddfSDavid du Colombier     }
6587dd7cddfSDavid du Colombier     return 0;
6597dd7cddfSDavid du Colombier }
6607dd7cddfSDavid du Colombier 
6617dd7cddfSDavid du Colombier void
win_pr2_set_bpp(gx_device * dev,int depth)6627dd7cddfSDavid du Colombier win_pr2_set_bpp(gx_device * dev, int depth)
6637dd7cddfSDavid du Colombier {
6647dd7cddfSDavid du Colombier     if (depth > 8) {
6657dd7cddfSDavid du Colombier 	static const gx_device_color_info win_pr2_24color = dci_std_color(24);
6667dd7cddfSDavid du Colombier 
6677dd7cddfSDavid du Colombier 	dev->color_info = win_pr2_24color;
6683ff48bf5SDavid du Colombier 	depth = 24;
6697dd7cddfSDavid du Colombier     } else if (depth >= 8) {
6707dd7cddfSDavid du Colombier 	/* 8-bit (SuperVGA-style) color. */
6717dd7cddfSDavid du Colombier 	/* (Uses a fixed palette of 3,3,2 bits.) */
6727dd7cddfSDavid du Colombier 	static const gx_device_color_info win_pr2_8color = dci_pc_8bit;
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier 	dev->color_info = win_pr2_8color;
6753ff48bf5SDavid du Colombier 	depth = 8;
6767dd7cddfSDavid du Colombier     } else if (depth >= 3) {
6777dd7cddfSDavid du Colombier 	/* 3 plane printer */
6787dd7cddfSDavid du Colombier 	/* suitable for impact dot matrix CMYK printers */
6797dd7cddfSDavid du Colombier 	/* create 4-bit bitmap, but only use 8 colors */
6803ff48bf5SDavid du Colombier 	static const gx_device_color_info win_pr2_4color = dci_values(3, 4, 1, 1, 2, 2);
6817dd7cddfSDavid du Colombier 
6827dd7cddfSDavid du Colombier 	dev->color_info = win_pr2_4color;
6833ff48bf5SDavid du Colombier 	depth = 4;
6847dd7cddfSDavid du Colombier     } else {			/* default is black_and_white */
6857dd7cddfSDavid du Colombier 	static const gx_device_color_info win_pr2_1color = dci_std_color(1);
6867dd7cddfSDavid du Colombier 
6877dd7cddfSDavid du Colombier 	dev->color_info = win_pr2_1color;
6883ff48bf5SDavid du Colombier 	depth = 1;
6897dd7cddfSDavid du Colombier     }
6907dd7cddfSDavid du Colombier 
6917dd7cddfSDavid du Colombier     ((gx_device_win_pr2 *)dev)->selected_bpp = depth;
692*593dc095SDavid du Colombier 
693*593dc095SDavid du Colombier     /* copy encode/decode procedures */
694*593dc095SDavid du Colombier     dev->procs.encode_color = dev->procs.map_rgb_color;
695*593dc095SDavid du Colombier     dev->procs.decode_color = dev->procs.map_color_rgb;
696*593dc095SDavid du Colombier     if (depth == 1) {
697*593dc095SDavid du Colombier 	dev->procs.get_color_mapping_procs =
698*593dc095SDavid du Colombier 	    gx_default_DevGray_get_color_mapping_procs;
699*593dc095SDavid du Colombier 	dev->procs.get_color_comp_index =
700*593dc095SDavid du Colombier 	    gx_default_DevGray_get_color_comp_index;
701*593dc095SDavid du Colombier     }
702*593dc095SDavid du Colombier     else {
703*593dc095SDavid du Colombier 	dev->procs.get_color_mapping_procs =
704*593dc095SDavid du Colombier 	    gx_default_DevRGB_get_color_mapping_procs;
705*593dc095SDavid du Colombier 	dev->procs.get_color_comp_index =
706*593dc095SDavid du Colombier 	    gx_default_DevRGB_get_color_comp_index;
707*593dc095SDavid du Colombier     }
7087dd7cddfSDavid du Colombier }
7097dd7cddfSDavid du Colombier 
7107dd7cddfSDavid du Colombier /********************************************************************************/
7117dd7cddfSDavid du Colombier 
7127dd7cddfSDavid du Colombier /* Get device parameters */
7137dd7cddfSDavid du Colombier int
win_pr2_get_params(gx_device * pdev,gs_param_list * plist)7147dd7cddfSDavid du Colombier win_pr2_get_params(gx_device * pdev, gs_param_list * plist)
7157dd7cddfSDavid du Colombier {
7167dd7cddfSDavid du Colombier     int code = gdev_prn_get_params(pdev, plist);
7177dd7cddfSDavid du Colombier 
7187dd7cddfSDavid du Colombier     win_pr2_copy_check(wdev);
7197dd7cddfSDavid du Colombier 
7207dd7cddfSDavid du Colombier     if (code >= 0)
7217dd7cddfSDavid du Colombier 	code = param_write_bool(plist, "NoCancel",
7227dd7cddfSDavid du Colombier 				&(wdev->nocancel));
7237dd7cddfSDavid du Colombier     if (code >= 0)
724*593dc095SDavid du Colombier 	code = param_write_int(plist, "QueryUser",
7253ff48bf5SDavid du Colombier 				&(wdev->query_user));
7263ff48bf5SDavid du Colombier     if (code >= 0)
7277dd7cddfSDavid du Colombier 	code = win_pr2_write_user_settings(wdev, plist);
7287dd7cddfSDavid du Colombier 
7293ff48bf5SDavid du Colombier     if ((code >= 0) && (wdev->Duplex_set > 0))
7303ff48bf5SDavid du Colombier 	code = param_write_bool(plist, "Tumble",
7313ff48bf5SDavid du Colombier 				&(wdev->tumble));
7323ff48bf5SDavid du Colombier 
7337dd7cddfSDavid du Colombier     return code;
7347dd7cddfSDavid du Colombier }
7357dd7cddfSDavid du Colombier 
7367dd7cddfSDavid du Colombier 
7377dd7cddfSDavid du Colombier /* We implement this ourselves so that we can change BitsPerPixel */
7387dd7cddfSDavid du Colombier /* before the device is opened */
7397dd7cddfSDavid du Colombier int
win_pr2_put_params(gx_device * pdev,gs_param_list * plist)7407dd7cddfSDavid du Colombier win_pr2_put_params(gx_device * pdev, gs_param_list * plist)
7417dd7cddfSDavid du Colombier {
7427dd7cddfSDavid du Colombier     int ecode = 0, code;
7437dd7cddfSDavid du Colombier     int old_bpp = pdev->color_info.depth;
7447dd7cddfSDavid du Colombier     int bpp = old_bpp;
7453ff48bf5SDavid du Colombier     bool tumble   = wdev->tumble;
7467dd7cddfSDavid du Colombier     bool nocancel = wdev->nocancel;
7477dd7cddfSDavid du Colombier     int queryuser = 0;
7487dd7cddfSDavid du Colombier     bool old_duplex = wdev->Duplex;
7493ff48bf5SDavid du Colombier     bool old_tumble = wdev->tumble;
7507dd7cddfSDavid du Colombier     int  old_orient = wdev->user_orient;
7517dd7cddfSDavid du Colombier     int  old_color  = wdev->user_color;
7527dd7cddfSDavid du Colombier     int  old_paper  = wdev->user_paper;
7537dd7cddfSDavid du Colombier     int  old_mx_dpi = wdev->max_dpi;
7547dd7cddfSDavid du Colombier 
7557dd7cddfSDavid du Colombier     if (wdev->Duplex_set < 0) {
7567dd7cddfSDavid du Colombier 	wdev->Duplex_set = 0;
7577dd7cddfSDavid du Colombier 	wdev->Duplex = false;
7583ff48bf5SDavid du Colombier 	wdev->tumble = false;
7597dd7cddfSDavid du Colombier     }
7607dd7cddfSDavid du Colombier 
7617dd7cddfSDavid du Colombier     win_pr2_copy_check(wdev);
7627dd7cddfSDavid du Colombier 
7637dd7cddfSDavid du Colombier     code = win_pr2_read_user_settings(wdev, plist);
7647dd7cddfSDavid du Colombier 
7657dd7cddfSDavid du Colombier     switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
7667dd7cddfSDavid du Colombier 	case 0:
7677dd7cddfSDavid du Colombier 	    if (pdev->is_open) {
7687dd7cddfSDavid du Colombier 		if (wdev->selected_bpp == bpp) {
7697dd7cddfSDavid du Colombier 		    break;
7707dd7cddfSDavid du Colombier 		}
7717dd7cddfSDavid du Colombier 		ecode = gs_error_rangecheck;
7727dd7cddfSDavid du Colombier 	    } else {		/* change dev->color_info is valid before device is opened */
7737dd7cddfSDavid du Colombier 		win_pr2_set_bpp(pdev, bpp);
7747dd7cddfSDavid du Colombier 		break;
7757dd7cddfSDavid du Colombier 	    }
7767dd7cddfSDavid du Colombier 	    goto bppe;
7777dd7cddfSDavid du Colombier 	default:
7787dd7cddfSDavid du Colombier 	    ecode = code;
7797dd7cddfSDavid du Colombier 	  bppe:param_signal_error(plist, "BitsPerPixel", ecode);
7807dd7cddfSDavid du Colombier 	case 1:
7817dd7cddfSDavid du Colombier 	    break;
7827dd7cddfSDavid du Colombier     }
7837dd7cddfSDavid du Colombier 
7847dd7cddfSDavid du Colombier     switch (code = param_read_bool(plist, "NoCancel", &nocancel)) {
7857dd7cddfSDavid du Colombier 	case 0:
7867dd7cddfSDavid du Colombier 	    if (pdev->is_open) {
7877dd7cddfSDavid du Colombier 		if (wdev->nocancel == nocancel) {
7887dd7cddfSDavid du Colombier 		    break;
7897dd7cddfSDavid du Colombier 		}
7907dd7cddfSDavid du Colombier 		ecode = gs_error_rangecheck;
7917dd7cddfSDavid du Colombier 	    } else {
7927dd7cddfSDavid du Colombier 		wdev->nocancel = nocancel;
7937dd7cddfSDavid du Colombier 		break;
7947dd7cddfSDavid du Colombier 	    }
7957dd7cddfSDavid du Colombier 	    goto nocancele;
7967dd7cddfSDavid du Colombier 	default:
7977dd7cddfSDavid du Colombier 	    ecode = code;
7987dd7cddfSDavid du Colombier 	  nocancele:param_signal_error(plist, "NoCancel", ecode);
7997dd7cddfSDavid du Colombier 	case 1:
8007dd7cddfSDavid du Colombier 	    break;
8017dd7cddfSDavid du Colombier     }
8027dd7cddfSDavid du Colombier 
8033ff48bf5SDavid du Colombier     switch (code = param_read_bool(plist, "Tumble", &tumble)) {
8043ff48bf5SDavid du Colombier 	case 0:
8053ff48bf5SDavid du Colombier 	    wdev->tumble = tumble;
8063ff48bf5SDavid du Colombier 	    break;
8073ff48bf5SDavid du Colombier 	default:
8083ff48bf5SDavid du Colombier 	    ecode = code;
8093ff48bf5SDavid du Colombier 	    param_signal_error(plist, "Tumble", ecode);
8103ff48bf5SDavid du Colombier 	case 1:
8113ff48bf5SDavid du Colombier 	    break;
8123ff48bf5SDavid du Colombier     }
8133ff48bf5SDavid du Colombier 
8147dd7cddfSDavid du Colombier     switch (code = param_read_int(plist, "QueryUser", &queryuser)) {
8157dd7cddfSDavid du Colombier 	case 0:
8167dd7cddfSDavid du Colombier 	    if ((queryuser > 0) &&
8177dd7cddfSDavid du Colombier 		(queryuser < 4)) {
8187dd7cddfSDavid du Colombier 		win_pr2_print_setup_interaction(wdev, queryuser);
8197dd7cddfSDavid du Colombier 	    }
8207dd7cddfSDavid du Colombier 	    break;
8217dd7cddfSDavid du Colombier 	default:
8227dd7cddfSDavid du Colombier 	    ecode = code;
8237dd7cddfSDavid du Colombier 	    param_signal_error(plist, "QueryUser", ecode);
8247dd7cddfSDavid du Colombier 	case 1:
8257dd7cddfSDavid du Colombier 	    break;
8267dd7cddfSDavid du Colombier     }
8277dd7cddfSDavid du Colombier 
8287dd7cddfSDavid du Colombier     if (ecode >= 0)
8297dd7cddfSDavid du Colombier 	ecode = gdev_prn_put_params(pdev, plist);
8307dd7cddfSDavid du Colombier 
8317dd7cddfSDavid du Colombier     if (wdev->win32_hdevmode && wdev->hdcprn) {
8327dd7cddfSDavid du Colombier 	if ( (old_duplex != wdev->Duplex)
8333ff48bf5SDavid du Colombier 	  || (old_tumble != wdev->tumble)
8347dd7cddfSDavid du Colombier 	  || (old_orient != wdev->user_orient)
8357dd7cddfSDavid du Colombier 	  || (old_color  != wdev->user_color)
8367dd7cddfSDavid du Colombier 	  || (old_paper  != wdev->user_paper)
8377dd7cddfSDavid du Colombier 	  || (old_mx_dpi != wdev->max_dpi) ) {
8387dd7cddfSDavid du Colombier 
8397dd7cddfSDavid du Colombier 	    LPDEVMODE pdevmode = GlobalLock(wdev->win32_hdevmode);
8407dd7cddfSDavid du Colombier 
8417dd7cddfSDavid du Colombier 	    if (pdevmode) {
8427dd7cddfSDavid du Colombier 		win_pr2_update_win(wdev, pdevmode);
8437dd7cddfSDavid du Colombier 		ResetDC(wdev->hdcprn, pdevmode);
8447dd7cddfSDavid du Colombier 		GlobalUnlock(pdevmode);
8457dd7cddfSDavid du Colombier 	    }
8467dd7cddfSDavid du Colombier 	}
8477dd7cddfSDavid du Colombier     }
8487dd7cddfSDavid du Colombier 
8497dd7cddfSDavid du Colombier     return ecode;
8507dd7cddfSDavid du Colombier }
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier #undef wdev
8537dd7cddfSDavid du Colombier 
8547dd7cddfSDavid du Colombier /********************************************************************************/
8557dd7cddfSDavid du Colombier 
8567dd7cddfSDavid du Colombier 
8577dd7cddfSDavid du Colombier /* Get Device Context for printer */
8587dd7cddfSDavid du Colombier private int
win_pr2_getdc(gx_device_win_pr2 * wdev)8597dd7cddfSDavid du Colombier win_pr2_getdc(gx_device_win_pr2 * wdev)
8607dd7cddfSDavid du Colombier {
8617dd7cddfSDavid du Colombier     char *device;
8627dd7cddfSDavid du Colombier     char *devices;
8637dd7cddfSDavid du Colombier     char *p;
8647dd7cddfSDavid du Colombier     char driverbuf[512];
8657dd7cddfSDavid du Colombier     char *driver;
8667dd7cddfSDavid du Colombier     char *output;
8677dd7cddfSDavid du Colombier     char *devcap;
8687dd7cddfSDavid du Colombier     int devcapsize;
8697dd7cddfSDavid du Colombier     int size;
8707dd7cddfSDavid du Colombier 
8717dd7cddfSDavid du Colombier     int i, n;
8727dd7cddfSDavid du Colombier     POINT *pp;
8737dd7cddfSDavid du Colombier     int paperindex;
8747dd7cddfSDavid du Colombier     int paperwidth, paperheight;
8757dd7cddfSDavid du Colombier     int orientation;
8767dd7cddfSDavid du Colombier     int papersize;
8777dd7cddfSDavid du Colombier     char papername[64];
8787dd7cddfSDavid du Colombier     char drvname[32];
8797dd7cddfSDavid du Colombier     HINSTANCE hlib;
8807dd7cddfSDavid du Colombier     LPFNDEVMODE pfnExtDeviceMode;
8817dd7cddfSDavid du Colombier     LPFNDEVCAPS pfnDeviceCapabilities;
8827dd7cddfSDavid du Colombier     LPDEVMODE podevmode, pidevmode;
8837dd7cddfSDavid du Colombier 
8847dd7cddfSDavid du Colombier     HANDLE hprinter;
8857dd7cddfSDavid du Colombier 
8867dd7cddfSDavid du Colombier     /* first try to derive the printer name from -sOutputFile= */
8873ff48bf5SDavid du Colombier     /* is printer if name prefixed by \\spool\ or by %printer% */
8883ff48bf5SDavid du Colombier     if (is_spool(wdev->fname)) {
8897dd7cddfSDavid du Colombier 	device = wdev->fname + 8;	/* skip over \\spool\ */
8903ff48bf5SDavid du Colombier 	wdev->use_old_spool_name = true;
8913ff48bf5SDavid du Colombier     } else if (strncmp("%printer%",wdev->fname,9) == 0) {
8923ff48bf5SDavid du Colombier 	device = wdev->fname + 9;	/* skip over %printer% */
8933ff48bf5SDavid du Colombier 	wdev->use_old_spool_name = false;
8943ff48bf5SDavid du Colombier     } else {
8957dd7cddfSDavid du Colombier 	return FALSE;
8963ff48bf5SDavid du Colombier     }
8977dd7cddfSDavid du Colombier 
8987dd7cddfSDavid du Colombier     /* now try to match the printer name against the [Devices] section */
899*593dc095SDavid du Colombier     if ((devices = gs_malloc(wdev->memory, 4096, 1, "win_pr2_getdc")) == (char *)NULL)
9007dd7cddfSDavid du Colombier 	return FALSE;
9017dd7cddfSDavid du Colombier     GetProfileString("Devices", NULL, "", devices, 4096);
9027dd7cddfSDavid du Colombier     p = devices;
9037dd7cddfSDavid du Colombier     while (*p) {
9047dd7cddfSDavid du Colombier 	if (stricmp(p, device) == 0)
9057dd7cddfSDavid du Colombier 	    break;
9067dd7cddfSDavid du Colombier 	p += strlen(p) + 1;
9077dd7cddfSDavid du Colombier     }
9087dd7cddfSDavid du Colombier     if (*p == '\0')
9097dd7cddfSDavid du Colombier 	p = NULL;
910*593dc095SDavid du Colombier     gs_free(wdev->memory, devices, 4096, 1, "win_pr2_getdc");
9117dd7cddfSDavid du Colombier     if (p == NULL)
9127dd7cddfSDavid du Colombier 	return FALSE;		/* doesn't match an available printer */
9137dd7cddfSDavid du Colombier 
9147dd7cddfSDavid du Colombier     /* the printer exists, get the remaining information from win.ini */
9157dd7cddfSDavid du Colombier     GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
9167dd7cddfSDavid du Colombier     driver = strtok(driverbuf, ",");
9177dd7cddfSDavid du Colombier     output = strtok(NULL, ",");
9187dd7cddfSDavid du Colombier     if (is_win32s)
9197dd7cddfSDavid du Colombier     {
9207dd7cddfSDavid du Colombier 	strcpy(drvname, driver);
9217dd7cddfSDavid du Colombier 	strcat(drvname, ".drv");
9227dd7cddfSDavid du Colombier 	driver = drvname;
9237dd7cddfSDavid du Colombier     }
9247dd7cddfSDavid du Colombier 
9257dd7cddfSDavid du Colombier     if (!is_win32s) {		/* Win32 */
9267dd7cddfSDavid du Colombier 	if (!OpenPrinter(device, &hprinter, NULL))
9277dd7cddfSDavid du Colombier 	    return FALSE;
9287dd7cddfSDavid du Colombier 	size = DocumentProperties(NULL, hprinter, device, NULL, NULL, 0);
929*593dc095SDavid du Colombier 	if ((podevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
9307dd7cddfSDavid du Colombier 	    ClosePrinter(hprinter);
9317dd7cddfSDavid du Colombier 	    return FALSE;
9327dd7cddfSDavid du Colombier 	}
933*593dc095SDavid du Colombier 	if ((pidevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
934*593dc095SDavid du Colombier 	    gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
9357dd7cddfSDavid du Colombier 	    ClosePrinter(hprinter);
9367dd7cddfSDavid du Colombier 	    return FALSE;
9377dd7cddfSDavid du Colombier 	}
9387dd7cddfSDavid du Colombier 	DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);
9397dd7cddfSDavid du Colombier 	pfnDeviceCapabilities = (LPFNDEVCAPS) DeviceCapabilities;
9407dd7cddfSDavid du Colombier     } else
9417dd7cddfSDavid du Colombier     {				/* Win16 and Win32s */
9427dd7cddfSDavid du Colombier 	/* now load the printer driver */
9437dd7cddfSDavid du Colombier 	hlib = LoadLibrary(driver);
9447dd7cddfSDavid du Colombier 	if (hlib < (HINSTANCE) HINSTANCE_ERROR)
9457dd7cddfSDavid du Colombier 	    return FALSE;
9467dd7cddfSDavid du Colombier 
9477dd7cddfSDavid du Colombier 	/* call ExtDeviceMode() to get default parameters */
9487dd7cddfSDavid du Colombier 	pfnExtDeviceMode = (LPFNDEVMODE) GetProcAddress(hlib, "ExtDeviceMode");
9497dd7cddfSDavid du Colombier 	if (pfnExtDeviceMode == (LPFNDEVMODE) NULL) {
9507dd7cddfSDavid du Colombier 	    FreeLibrary(hlib);
9517dd7cddfSDavid du Colombier 	    return FALSE;
9527dd7cddfSDavid du Colombier 	}
9537dd7cddfSDavid du Colombier 	pfnDeviceCapabilities = (LPFNDEVCAPS) GetProcAddress(hlib, "DeviceCapabilities");
9547dd7cddfSDavid du Colombier 	if (pfnDeviceCapabilities == (LPFNDEVCAPS) NULL) {
9557dd7cddfSDavid du Colombier 	    FreeLibrary(hlib);
9567dd7cddfSDavid du Colombier 	    return FALSE;
9577dd7cddfSDavid du Colombier 	}
9587dd7cddfSDavid du Colombier 	size = pfnExtDeviceMode(NULL, hlib, NULL, device, output, NULL, NULL, 0);
959*593dc095SDavid du Colombier 	if ((podevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
9607dd7cddfSDavid du Colombier 	    FreeLibrary(hlib);
9617dd7cddfSDavid du Colombier 	    return FALSE;
9627dd7cddfSDavid du Colombier 	}
963*593dc095SDavid du Colombier 	if ((pidevmode = gs_malloc(wdev->memory, size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
964*593dc095SDavid du Colombier 	    gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
9657dd7cddfSDavid du Colombier 	    FreeLibrary(hlib);
9667dd7cddfSDavid du Colombier 	    return FALSE;
9677dd7cddfSDavid du Colombier 	}
9687dd7cddfSDavid du Colombier 	pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
9697dd7cddfSDavid du Colombier 			 NULL, NULL, DM_OUT_BUFFER);
9707dd7cddfSDavid du Colombier     }
9717dd7cddfSDavid du Colombier 
9727dd7cddfSDavid du Colombier     /* now find out what paper sizes are available */
9737dd7cddfSDavid du Colombier     devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL);
9747dd7cddfSDavid du Colombier     devcapsize *= sizeof(POINT);
975*593dc095SDavid du Colombier     if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
9767dd7cddfSDavid du Colombier 	return FALSE;
9777dd7cddfSDavid du Colombier     n = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL);
9787dd7cddfSDavid du Colombier     paperwidth = (int)(wdev->MediaSize[0] * 254 / 72);
9797dd7cddfSDavid du Colombier     paperheight = (int)(wdev->MediaSize[1] * 254 / 72);
9807dd7cddfSDavid du Colombier     papername[0] = '\0';
9817dd7cddfSDavid du Colombier     papersize = 0;
9827dd7cddfSDavid du Colombier     paperindex = -1;
9837dd7cddfSDavid du Colombier     orientation = 0;
9847dd7cddfSDavid du Colombier     pp = (POINT *) devcap;
9857dd7cddfSDavid du Colombier     for (i = 0; i < n; i++, pp++) {
9867dd7cddfSDavid du Colombier 	if ((pp->x < paperwidth + 20) && (pp->x > paperwidth - 20) &&
9877dd7cddfSDavid du Colombier 	    (pp->y < paperheight + 20) && (pp->y > paperheight - 20)) {
9887dd7cddfSDavid du Colombier 	    paperindex = i;
9897dd7cddfSDavid du Colombier 	    paperwidth = pp->x;
9907dd7cddfSDavid du Colombier 	    paperheight = pp->y;
9917dd7cddfSDavid du Colombier 	    orientation = DMORIENT_PORTRAIT;
9927dd7cddfSDavid du Colombier 	    break;
9937dd7cddfSDavid du Colombier 	}
9947dd7cddfSDavid du Colombier     }
9957dd7cddfSDavid du Colombier     if (paperindex < 0) {
9967dd7cddfSDavid du Colombier 	/* try again in landscape */
9977dd7cddfSDavid du Colombier 	pp = (POINT *) devcap;
9987dd7cddfSDavid du Colombier 	for (i = 0; i < n; i++, pp++) {
9997dd7cddfSDavid du Colombier 	    if ((pp->x < paperheight + 20) && (pp->x > paperheight - 20) &&
10007dd7cddfSDavid du Colombier 		(pp->y < paperwidth + 20) && (pp->y > paperwidth - 20)) {
10017dd7cddfSDavid du Colombier 		paperindex = i;
10027dd7cddfSDavid du Colombier 		paperwidth = pp->x;
10037dd7cddfSDavid du Colombier 		paperheight = pp->y;
10047dd7cddfSDavid du Colombier 		orientation = DMORIENT_LANDSCAPE;
10057dd7cddfSDavid du Colombier 		break;
10067dd7cddfSDavid du Colombier 	    }
10077dd7cddfSDavid du Colombier 	}
10087dd7cddfSDavid du Colombier     }
1009*593dc095SDavid du Colombier     gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
10107dd7cddfSDavid du Colombier 
10117dd7cddfSDavid du Colombier     /* get the dmPaperSize */
10127dd7cddfSDavid du Colombier     devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERS, NULL, NULL);
10137dd7cddfSDavid du Colombier     devcapsize *= sizeof(WORD);
1014*593dc095SDavid du Colombier     if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
10157dd7cddfSDavid du Colombier 	return FALSE;
10167dd7cddfSDavid du Colombier     n = pfnDeviceCapabilities(device, output, DC_PAPERS, devcap, NULL);
10177dd7cddfSDavid du Colombier     if ((paperindex >= 0) && (paperindex < n))
10187dd7cddfSDavid du Colombier 	papersize = ((WORD *) devcap)[paperindex];
1019*593dc095SDavid du Colombier     gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
10207dd7cddfSDavid du Colombier 
10217dd7cddfSDavid du Colombier     /* get the paper name */
10227dd7cddfSDavid du Colombier     devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
10237dd7cddfSDavid du Colombier     devcapsize *= 64;
1024*593dc095SDavid du Colombier     if ((devcap = gs_malloc(wdev->memory, devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
10257dd7cddfSDavid du Colombier 	return FALSE;
10267dd7cddfSDavid du Colombier     n = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL);
10277dd7cddfSDavid du Colombier     if ((paperindex >= 0) && (paperindex < n))
10287dd7cddfSDavid du Colombier 	strcpy(papername, devcap + paperindex * 64);
1029*593dc095SDavid du Colombier     gs_free(wdev->memory, devcap, devcapsize, 1, "win_pr2_getdc");
10307dd7cddfSDavid du Colombier 
10317dd7cddfSDavid du Colombier     memcpy(pidevmode, podevmode, size);
10327dd7cddfSDavid du Colombier 
10337dd7cddfSDavid du Colombier     pidevmode->dmFields = 0;
10347dd7cddfSDavid du Colombier 
10357dd7cddfSDavid du Colombier     wdev->paper_name[0] = 0;
10367dd7cddfSDavid du Colombier 
10377dd7cddfSDavid du Colombier     if ( (wdev->user_paper)
10387dd7cddfSDavid du Colombier       && (wdev->user_paper != papersize) ) {
10397dd7cddfSDavid du Colombier 	papersize = wdev->user_paper;
10407dd7cddfSDavid du Colombier 	paperheight = 0;
10417dd7cddfSDavid du Colombier 	paperwidth = 0;
10427dd7cddfSDavid du Colombier 	papername[0] = 0;
10437dd7cddfSDavid du Colombier     }
10447dd7cddfSDavid du Colombier     if (wdev->user_orient) {
10457dd7cddfSDavid du Colombier 	orientation = wdev->user_orient;
10467dd7cddfSDavid du Colombier     }
10477dd7cddfSDavid du Colombier 
10487dd7cddfSDavid du Colombier     pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
10497dd7cddfSDavid du Colombier     pidevmode->dmFields |= DM_DEFAULTSOURCE;
10507dd7cddfSDavid du Colombier     pidevmode->dmDefaultSource = 0;
10517dd7cddfSDavid du Colombier 
10527dd7cddfSDavid du Colombier     if (orientation) {
10537dd7cddfSDavid du Colombier 	wdev->user_orient = orientation;
10547dd7cddfSDavid du Colombier     }
10557dd7cddfSDavid du Colombier     if (papersize) {
10567dd7cddfSDavid du Colombier 	wdev->user_paper = papersize;
10577dd7cddfSDavid du Colombier 	strcpy (wdev->paper_name, papername);
10587dd7cddfSDavid du Colombier     }
10597dd7cddfSDavid du Colombier 
10607dd7cddfSDavid du Colombier     if (paperheight && paperwidth) {
10617dd7cddfSDavid du Colombier 	pidevmode->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
10627dd7cddfSDavid du Colombier 	pidevmode->dmPaperWidth = paperwidth;
10637dd7cddfSDavid du Colombier 	pidevmode->dmPaperLength = paperheight;
10647dd7cddfSDavid du Colombier         wdev->user_media_size[0] = paperwidth / 254.0 * 72.0;
10657dd7cddfSDavid du Colombier 	wdev->user_media_size[1] = paperheight / 254.0 * 72.0;
10667dd7cddfSDavid du Colombier     }
10677dd7cddfSDavid du Colombier 
10687dd7cddfSDavid du Colombier     if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
10697dd7cddfSDavid du Colombier 	wdev->Duplex_set = 1;
10707dd7cddfSDavid du Colombier     }
10717dd7cddfSDavid du Colombier 
10727dd7cddfSDavid du Colombier     win_pr2_update_win(wdev, pidevmode);
10737dd7cddfSDavid du Colombier 
10747dd7cddfSDavid du Colombier     if (!is_win32s) {
10757dd7cddfSDavid du Colombier 
10767dd7cddfSDavid du Colombier 	/* merge the entries */
10777dd7cddfSDavid du Colombier 	DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
10787dd7cddfSDavid du Colombier 	ClosePrinter(hprinter);
10797dd7cddfSDavid du Colombier 
10807dd7cddfSDavid du Colombier 	/* now get a DC */
10817dd7cddfSDavid du Colombier 	wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
10827dd7cddfSDavid du Colombier     } else
10837dd7cddfSDavid du Colombier     {				/* Win16 and Win32s */
10847dd7cddfSDavid du Colombier 	pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
10857dd7cddfSDavid du Colombier 			 pidevmode, NULL, DM_IN_BUFFER | DM_OUT_BUFFER);
10867dd7cddfSDavid du Colombier 	/* release the printer driver */
10877dd7cddfSDavid du Colombier 	FreeLibrary(hlib);
10887dd7cddfSDavid du Colombier 	/* now get a DC */
10897dd7cddfSDavid du Colombier 	if (is_win32s)
10907dd7cddfSDavid du Colombier 	    strtok(driver, ".");	/* remove .drv */
10917dd7cddfSDavid du Colombier 	wdev->hdcprn = CreateDC(driver, device, output, podevmode);
10927dd7cddfSDavid du Colombier     }
10937dd7cddfSDavid du Colombier 
10947dd7cddfSDavid du Colombier     if (wdev->win32_hdevmode == NULL) {
10957dd7cddfSDavid du Colombier 	wdev->win32_hdevmode = GlobalAlloc(0, sizeof(DEVMODE));
10967dd7cddfSDavid du Colombier     }
10977dd7cddfSDavid du Colombier 
10987dd7cddfSDavid du Colombier     if (wdev->win32_hdevmode) {
1099*593dc095SDavid du Colombier 	LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
11007dd7cddfSDavid du Colombier 	if (pdevmode) {
11017dd7cddfSDavid du Colombier 	    memcpy(pdevmode, podevmode, sizeof(DEVMODE));
11027dd7cddfSDavid du Colombier 	    GlobalUnlock(wdev->win32_hdevmode);
11037dd7cddfSDavid du Colombier 	}
11047dd7cddfSDavid du Colombier     }
11057dd7cddfSDavid du Colombier 
1106*593dc095SDavid du Colombier     gs_free(wdev->memory, pidevmode, size, 1, "win_pr2_getdc");
1107*593dc095SDavid du Colombier     gs_free(wdev->memory, podevmode, size, 1, "win_pr2_getdc");
11087dd7cddfSDavid du Colombier 
11097dd7cddfSDavid du Colombier     if (wdev->hdcprn != (HDC) NULL)
11107dd7cddfSDavid du Colombier 	return TRUE;		/* success */
11117dd7cddfSDavid du Colombier 
11127dd7cddfSDavid du Colombier     /* fall back to prompting user */
11137dd7cddfSDavid du Colombier     return FALSE;
11147dd7cddfSDavid du Colombier }
11157dd7cddfSDavid du Colombier 
11167dd7cddfSDavid du Colombier 
11177dd7cddfSDavid du Colombier /*
11187dd7cddfSDavid du Colombier  *  Minimalist update of the wdev parameters (mainly for the
11197dd7cddfSDavid du Colombier  *  UserSettings parameters).
11207dd7cddfSDavid du Colombier  */
11217dd7cddfSDavid du Colombier 
11227dd7cddfSDavid du Colombier private int
win_pr2_update_dev(gx_device_win_pr2 * dev,LPDEVMODE pdevmode)11237dd7cddfSDavid du Colombier win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
11247dd7cddfSDavid du Colombier {
11257dd7cddfSDavid du Colombier     if (pdevmode == 0)
11267dd7cddfSDavid du Colombier 	return FALSE;
11277dd7cddfSDavid du Colombier 
11287dd7cddfSDavid du Colombier     if (pdevmode->dmFields & DM_COLOR) {
11297dd7cddfSDavid du Colombier 	dev->user_color = pdevmode->dmColor;
11307dd7cddfSDavid du Colombier     }
11317dd7cddfSDavid du Colombier     if (pdevmode->dmFields & DM_ORIENTATION) {
11327dd7cddfSDavid du Colombier 	dev->user_orient = pdevmode->dmOrientation;
11337dd7cddfSDavid du Colombier     }
11347dd7cddfSDavid du Colombier     if (pdevmode->dmFields & DM_PAPERSIZE) {
11357dd7cddfSDavid du Colombier 	dev->user_paper = pdevmode->dmPaperSize;
11367dd7cddfSDavid du Colombier         dev->user_media_size[0] = pdevmode->dmPaperWidth / 254.0 * 72.0;
11377dd7cddfSDavid du Colombier 	dev->user_media_size[1] = pdevmode->dmPaperLength / 254.0 * 72.0;
11387dd7cddfSDavid du Colombier 	dev->paper_name[0] = 0;	    /* unknown paper size */
11397dd7cddfSDavid du Colombier     }
11407dd7cddfSDavid du Colombier     if (pdevmode->dmFields & DM_DUPLEX) {
11417dd7cddfSDavid du Colombier 	dev->Duplex_set = 1;
11427dd7cddfSDavid du Colombier 	dev->Duplex = pdevmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
11433ff48bf5SDavid du Colombier 	dev->tumble = pdevmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
11447dd7cddfSDavid du Colombier     }
11457dd7cddfSDavid du Colombier 
11467dd7cddfSDavid du Colombier     return TRUE;
11477dd7cddfSDavid du Colombier }
11487dd7cddfSDavid du Colombier 
11497dd7cddfSDavid du Colombier private int
win_pr2_update_win(gx_device_win_pr2 * dev,LPDEVMODE pdevmode)11507dd7cddfSDavid du Colombier win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
11517dd7cddfSDavid du Colombier {
11527dd7cddfSDavid du Colombier     if (dev->Duplex_set > 0) {
11537dd7cddfSDavid du Colombier 	pdevmode->dmFields |= DM_DUPLEX;
11547dd7cddfSDavid du Colombier 	pdevmode->dmDuplex = DMDUP_SIMPLEX;
11557dd7cddfSDavid du Colombier 	if (dev->Duplex) {
11563ff48bf5SDavid du Colombier 	    if (dev->tumble == false) {
11577dd7cddfSDavid du Colombier 		pdevmode->dmDuplex = DMDUP_VERTICAL;
11583ff48bf5SDavid du Colombier 	    } else {
11597dd7cddfSDavid du Colombier 		pdevmode->dmDuplex = DMDUP_HORIZONTAL;
11607dd7cddfSDavid du Colombier 	    }
11617dd7cddfSDavid du Colombier 	}
11627dd7cddfSDavid du Colombier     }
11637dd7cddfSDavid du Colombier 
11647dd7cddfSDavid du Colombier     if (dev->user_color) {
11657dd7cddfSDavid du Colombier 	pdevmode->dmColor = dev->user_color;
11667dd7cddfSDavid du Colombier 	pdevmode->dmFields |= DM_COLOR;
11677dd7cddfSDavid du Colombier     }
11687dd7cddfSDavid du Colombier 
11697dd7cddfSDavid du Colombier     if (dev->user_orient) {
11707dd7cddfSDavid du Colombier 	pdevmode->dmFields |= DM_ORIENTATION;
11717dd7cddfSDavid du Colombier 	pdevmode->dmOrientation = dev->user_orient;
11727dd7cddfSDavid du Colombier     }
11737dd7cddfSDavid du Colombier 
11747dd7cddfSDavid du Colombier     if (dev->user_paper) {
11757dd7cddfSDavid du Colombier 	pdevmode->dmFields |= DM_PAPERSIZE;
11767dd7cddfSDavid du Colombier 	pdevmode->dmPaperSize = dev->user_paper;
11777dd7cddfSDavid du Colombier     }
11783ff48bf5SDavid du Colombier     return 0;
11797dd7cddfSDavid du Colombier }
11807dd7cddfSDavid du Colombier 
11817dd7cddfSDavid du Colombier /********************************************************************************/
11827dd7cddfSDavid du Colombier 
11837dd7cddfSDavid du Colombier #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
11847dd7cddfSDavid du Colombier   switch ( code = pread(dict.list, (param_name = pname), &(pa)) )\
11857dd7cddfSDavid du Colombier   {\
11867dd7cddfSDavid du Colombier   case 0:\
11877dd7cddfSDavid du Colombier 	if ( (pa).size != psize )\
11887dd7cddfSDavid du Colombier 	  ecode = gs_note_error(gs_error_rangecheck);\
11897dd7cddfSDavid du Colombier 	else {
11907dd7cddfSDavid du Colombier /* The body of the processing code goes here. */
11917dd7cddfSDavid du Colombier /* If it succeeds, it should do a 'break'; */
11927dd7cddfSDavid du Colombier /* if it fails, it should set ecode and fall through. */
11937dd7cddfSDavid du Colombier #define END_ARRAY_PARAM(pa, e)\
11947dd7cddfSDavid du Colombier 	}\
11957dd7cddfSDavid du Colombier 	goto e;\
11967dd7cddfSDavid du Colombier   default:\
11977dd7cddfSDavid du Colombier 	ecode = code;\
11987dd7cddfSDavid du Colombier e:	param_signal_error(dict.list, param_name, ecode);\
11997dd7cddfSDavid du Colombier   case 1:\
12007dd7cddfSDavid du Colombier 	(pa).data = 0;		/* mark as not filled */\
12017dd7cddfSDavid du Colombier   }
12027dd7cddfSDavid du Colombier 
12037dd7cddfSDavid du Colombier 
12047dd7cddfSDavid du Colombier /* Put the user params from UserSettings into our */
12057dd7cddfSDavid du Colombier /* internal variables. */
12067dd7cddfSDavid du Colombier private int
win_pr2_read_user_settings(gx_device_win_pr2 * wdev,gs_param_list * plist)12077dd7cddfSDavid du Colombier win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
12087dd7cddfSDavid du Colombier {
12097dd7cddfSDavid du Colombier     gs_param_dict dict;
12107dd7cddfSDavid du Colombier     gs_param_string docn = { 0 };
12117dd7cddfSDavid du Colombier     const char* dict_name = "UserSettings";
12127dd7cddfSDavid du Colombier     const char* param_name = "";
12137dd7cddfSDavid du Colombier     int code = 0;
12147dd7cddfSDavid du Colombier     int ecode = 0;
12157dd7cddfSDavid du Colombier 
12167dd7cddfSDavid du Colombier     switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
12177dd7cddfSDavid du Colombier 	default:
12187dd7cddfSDavid du Colombier 	    param_signal_error(plist, dict_name, code);
12197dd7cddfSDavid du Colombier 	    return code;
12207dd7cddfSDavid du Colombier 	case 1:
12217dd7cddfSDavid du Colombier 	    break;
12227dd7cddfSDavid du Colombier 	case 0:
12237dd7cddfSDavid du Colombier 	    {
12247dd7cddfSDavid du Colombier 		gs_param_int_array ia;
12257dd7cddfSDavid du Colombier 
12267dd7cddfSDavid du Colombier 		BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
12277dd7cddfSDavid du Colombier 		if ((ia.data[0] < 0) ||
12287dd7cddfSDavid du Colombier 		    (ia.data[1] < 0) ||
12297dd7cddfSDavid du Colombier 		    (ia.data[0] > ia.data[1]))
12307dd7cddfSDavid du Colombier 		    ecode = gs_note_error(gs_error_rangecheck);
12317dd7cddfSDavid du Colombier 		wdev->doc_page_begin = ia.data[0];
12327dd7cddfSDavid du Colombier 		wdev->doc_page_end = ia.data[1];
12337dd7cddfSDavid du Colombier 		END_ARRAY_PARAM(ia, doc_range_error)
12347dd7cddfSDavid du Colombier 
12357dd7cddfSDavid du Colombier 		BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
12367dd7cddfSDavid du Colombier 		if ((ia.data[0] < 0) ||
12377dd7cddfSDavid du Colombier 		    (ia.data[1] < 0) ||
12387dd7cddfSDavid du Colombier 		    (ia.data[0] > ia.data[1]))
12397dd7cddfSDavid du Colombier 		    ecode = gs_note_error(gs_error_rangecheck);
12407dd7cddfSDavid du Colombier 		wdev->user_page_begin = ia.data[0];
12417dd7cddfSDavid du Colombier 		wdev->user_page_end = ia.data[1];
12427dd7cddfSDavid du Colombier 		END_ARRAY_PARAM(ia, sel_range_error)
12437dd7cddfSDavid du Colombier 
12447dd7cddfSDavid du Colombier 		param_read_int(dict.list, "Copies", &wdev->user_copies);
12457dd7cddfSDavid du Colombier 		param_read_int(dict.list, "Paper", &wdev->user_paper);
12467dd7cddfSDavid du Colombier 		param_read_int(dict.list, "Orientation", &wdev->user_orient);
12477dd7cddfSDavid du Colombier 		param_read_int(dict.list, "Color", &wdev->user_color);
12487dd7cddfSDavid du Colombier 		param_read_int(dict.list, "MaxResolution", &wdev->max_dpi);
12497dd7cddfSDavid du Colombier 
12507dd7cddfSDavid du Colombier 		switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
12517dd7cddfSDavid du Colombier 		    case 0:
12527dd7cddfSDavid du Colombier 			if (docn.size < sizeof(wdev->doc_name))
12537dd7cddfSDavid du Colombier 			    break;
12547dd7cddfSDavid du Colombier 			code = gs_error_rangecheck;
12557dd7cddfSDavid du Colombier 			/* fall through */
12567dd7cddfSDavid du Colombier 		    default:
12577dd7cddfSDavid du Colombier 			ecode = code;
12587dd7cddfSDavid du Colombier 			param_signal_error(plist, param_name, ecode);
12597dd7cddfSDavid du Colombier 			/* fall through */
12607dd7cddfSDavid du Colombier 		    case 1:
12617dd7cddfSDavid du Colombier 			docn.data = 0;
12627dd7cddfSDavid du Colombier 			break;
12637dd7cddfSDavid du Colombier 		}
12647dd7cddfSDavid du Colombier 
12657dd7cddfSDavid du Colombier 		param_end_read_dict(plist, dict_name, &dict);
12667dd7cddfSDavid du Colombier 
12677dd7cddfSDavid du Colombier 		if (docn.data) {
12687dd7cddfSDavid du Colombier 		    memcpy(wdev->doc_name, docn.data, docn.size);
12697dd7cddfSDavid du Colombier 		    wdev->doc_name[docn.size] = 0;
12707dd7cddfSDavid du Colombier 		}
12717dd7cddfSDavid du Colombier 
12727dd7cddfSDavid du Colombier 		wdev->print_copies = 1;
12737dd7cddfSDavid du Colombier 
12747dd7cddfSDavid du Colombier 		if (wdev->win32_hdevmode) {
12757dd7cddfSDavid du Colombier 		    LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
12767dd7cddfSDavid du Colombier 		    if (devmode) {
12777dd7cddfSDavid du Colombier 			devmode->dmCopies = wdev->user_copies;
12787dd7cddfSDavid du Colombier 			devmode->dmPaperSize = wdev->user_paper;
12797dd7cddfSDavid du Colombier 			devmode->dmOrientation = wdev->user_orient;
12807dd7cddfSDavid du Colombier 			devmode->dmColor = wdev->user_color;
12817dd7cddfSDavid du Colombier 			GlobalUnlock(wdev->win32_hdevmode);
12827dd7cddfSDavid du Colombier 		    }
12837dd7cddfSDavid du Colombier 		}
12847dd7cddfSDavid du Colombier 	    }
12857dd7cddfSDavid du Colombier 	    break;
12867dd7cddfSDavid du Colombier     }
12877dd7cddfSDavid du Colombier 
12887dd7cddfSDavid du Colombier     return code;
12897dd7cddfSDavid du Colombier }
12907dd7cddfSDavid du Colombier 
12917dd7cddfSDavid du Colombier 
12927dd7cddfSDavid du Colombier private int
win_pr2_write_user_settings(gx_device_win_pr2 * wdev,gs_param_list * plist)12937dd7cddfSDavid du Colombier win_pr2_write_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
12947dd7cddfSDavid du Colombier {
12957dd7cddfSDavid du Colombier     gs_param_dict dict;
12967dd7cddfSDavid du Colombier     gs_param_int_array range;
12977dd7cddfSDavid du Colombier     gs_param_float_array box;
12987dd7cddfSDavid du Colombier     gs_param_string docn;
12997dd7cddfSDavid du Colombier     gs_param_string papn;
13007dd7cddfSDavid du Colombier     int array[2];
13017dd7cddfSDavid du Colombier     const char* pname = "UserSettings";
13027dd7cddfSDavid du Colombier     int code;
13037dd7cddfSDavid du Colombier 
13047dd7cddfSDavid du Colombier     dict.size = 12;
13057dd7cddfSDavid du Colombier     code = param_begin_write_dict(plist, pname, &dict, false);
13067dd7cddfSDavid du Colombier     if (code < 0) return code;
13077dd7cddfSDavid du Colombier 
13087dd7cddfSDavid du Colombier     array[0] = wdev->doc_page_begin;
13097dd7cddfSDavid du Colombier     array[1] = wdev->doc_page_end;
13107dd7cddfSDavid du Colombier     range.data = array;
13117dd7cddfSDavid du Colombier     range.size = 2;
13127dd7cddfSDavid du Colombier     range.persistent = false;
13137dd7cddfSDavid du Colombier     code = param_write_int_array(dict.list, "DocumentRange", &range);
13147dd7cddfSDavid du Colombier     if (code < 0) goto error;
13157dd7cddfSDavid du Colombier 
13167dd7cddfSDavid du Colombier     array[0] = wdev->user_page_begin;
13177dd7cddfSDavid du Colombier     array[1] = wdev->user_page_end;
13187dd7cddfSDavid du Colombier     range.data = array;
13197dd7cddfSDavid du Colombier     range.size = 2;
13207dd7cddfSDavid du Colombier     range.persistent = false;
13217dd7cddfSDavid du Colombier     code = param_write_int_array(dict.list, "SelectedRange", &range);
13227dd7cddfSDavid du Colombier     if (code < 0) goto error;
13237dd7cddfSDavid du Colombier 
13247dd7cddfSDavid du Colombier     box.data = wdev->user_media_size;
13257dd7cddfSDavid du Colombier     box.size = 2;
13267dd7cddfSDavid du Colombier     box.persistent = false;
13277dd7cddfSDavid du Colombier     code = param_write_float_array(dict.list, "MediaSize", &box);
13287dd7cddfSDavid du Colombier     if (code < 0) goto error;
13297dd7cddfSDavid du Colombier 
13307dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "Copies", &wdev->user_copies);
13317dd7cddfSDavid du Colombier     if (code < 0) goto error;
13327dd7cddfSDavid du Colombier 
13337dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "Paper", &wdev->user_paper);
13347dd7cddfSDavid du Colombier     if (code < 0) goto error;
13357dd7cddfSDavid du Colombier 
13367dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "Orientation", &wdev->user_orient);
13377dd7cddfSDavid du Colombier     if (code < 0) goto error;
13387dd7cddfSDavid du Colombier 
13397dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "Color", &wdev->user_color);
13407dd7cddfSDavid du Colombier     if (code < 0) goto error;
13417dd7cddfSDavid du Colombier 
13427dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "MaxResolution", &wdev->max_dpi);
13437dd7cddfSDavid du Colombier     if (code < 0) goto error;
13447dd7cddfSDavid du Colombier 
13457dd7cddfSDavid du Colombier     code = param_write_int(dict.list, "PrintCopies", &wdev->print_copies);
13467dd7cddfSDavid du Colombier     if (code < 0) goto error;
13477dd7cddfSDavid du Colombier 
13487dd7cddfSDavid du Colombier     docn.data = (const byte*)wdev->doc_name;
13497dd7cddfSDavid du Colombier     docn.size = strlen(wdev->doc_name);
13507dd7cddfSDavid du Colombier     docn.persistent = false;
13517dd7cddfSDavid du Colombier 
13527dd7cddfSDavid du Colombier     code = param_write_string(dict.list, "DocumentName", &docn);
13537dd7cddfSDavid du Colombier     if (code < 0) goto error;
13547dd7cddfSDavid du Colombier 
13557dd7cddfSDavid du Colombier     papn.data = (const byte*)wdev->paper_name;
13567dd7cddfSDavid du Colombier     papn.size = strlen(wdev->paper_name);
13577dd7cddfSDavid du Colombier     papn.persistent = false;
13587dd7cddfSDavid du Colombier 
13597dd7cddfSDavid du Colombier     code = param_write_string(dict.list, "PaperName", &papn);
13607dd7cddfSDavid du Colombier     if (code < 0) goto error;
13617dd7cddfSDavid du Colombier 
13627dd7cddfSDavid du Colombier     code = param_write_bool(dict.list, "UserChangedSettings", &wdev->user_changed_settings);
13637dd7cddfSDavid du Colombier 
13647dd7cddfSDavid du Colombier error:
13657dd7cddfSDavid du Colombier     param_end_write_dict(plist, pname, &dict);
13667dd7cddfSDavid du Colombier     return code;
13677dd7cddfSDavid du Colombier }
13687dd7cddfSDavid du Colombier 
13697dd7cddfSDavid du Colombier /********************************************************************************/
13707dd7cddfSDavid du Colombier 
13717dd7cddfSDavid du Colombier /*  Show up a dialog for the user to choose a printer and a paper size.
13727dd7cddfSDavid du Colombier  *  If mode == 3, then automatically select the default Windows printer
13737dd7cddfSDavid du Colombier  *  instead of asking the user.
13747dd7cddfSDavid du Colombier  */
13757dd7cddfSDavid du Colombier 
13767dd7cddfSDavid du Colombier private int
win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev,int mode)13777dd7cddfSDavid du Colombier win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode)
13787dd7cddfSDavid du Colombier {
13797dd7cddfSDavid du Colombier     PRINTDLG pd;
13807dd7cddfSDavid du Colombier     LPDEVMODE  devmode;
13817dd7cddfSDavid du Colombier     LPDEVNAMES devnames;
13827dd7cddfSDavid du Colombier 
13837dd7cddfSDavid du Colombier     wdev->user_changed_settings = FALSE;
13843ff48bf5SDavid du Colombier     wdev->query_user = mode;
13857dd7cddfSDavid du Colombier 
13867dd7cddfSDavid du Colombier     memset(&pd, 0, sizeof(pd));
13877dd7cddfSDavid du Colombier     pd.lStructSize = sizeof(pd);
13883ff48bf5SDavid du Colombier     pd.hwndOwner = PARENT_WINDOW;
13897dd7cddfSDavid du Colombier 
13907dd7cddfSDavid du Colombier     switch (mode) {
13917dd7cddfSDavid du Colombier 	case 2:	pd.Flags = PD_PRINTSETUP; break;
13927dd7cddfSDavid du Colombier 	case 3:	pd.Flags = PD_RETURNDEFAULT; break;
13937dd7cddfSDavid du Colombier 	default: pd.Flags = 0; break;
13947dd7cddfSDavid du Colombier     }
13957dd7cddfSDavid du Colombier 
13967dd7cddfSDavid du Colombier     pd.Flags |= PD_USEDEVMODECOPIES;
13977dd7cddfSDavid du Colombier 
13987dd7cddfSDavid du Colombier     pd.nMinPage = wdev->doc_page_begin;
13997dd7cddfSDavid du Colombier     pd.nMaxPage = wdev->doc_page_end;
14007dd7cddfSDavid du Colombier     pd.nFromPage = wdev->user_page_begin;
14017dd7cddfSDavid du Colombier     pd.nToPage = wdev->user_page_end;
14027dd7cddfSDavid du Colombier     pd.nCopies = wdev->user_copies;
14037dd7cddfSDavid du Colombier 
14047dd7cddfSDavid du Colombier     /* Show the Print Setup dialog and let the user choose a printer
14057dd7cddfSDavid du Colombier      * and a paper size/orientation.
14067dd7cddfSDavid du Colombier      */
14077dd7cddfSDavid du Colombier 
14087dd7cddfSDavid du Colombier     if (!PrintDlg(&pd)) return FALSE;
14097dd7cddfSDavid du Colombier 
14107dd7cddfSDavid du Colombier     devmode = (LPDEVMODE) GlobalLock(pd.hDevMode);
14117dd7cddfSDavid du Colombier     devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);
14127dd7cddfSDavid du Colombier 
14137dd7cddfSDavid du Colombier     wdev->user_changed_settings = TRUE;
14143ff48bf5SDavid du Colombier     if (wdev->use_old_spool_name) {
14157dd7cddfSDavid du Colombier 	sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
14163ff48bf5SDavid du Colombier     } else {
14173ff48bf5SDavid du Colombier 	sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
14183ff48bf5SDavid du Colombier     }
14197dd7cddfSDavid du Colombier 
14207dd7cddfSDavid du Colombier     if (mode == 3) {
14217dd7cddfSDavid du Colombier 	devmode->dmCopies = wdev->user_copies * wdev->print_copies;
14227dd7cddfSDavid du Colombier 	pd.nCopies = 1;
14237dd7cddfSDavid du Colombier     }
14247dd7cddfSDavid du Colombier 
14257dd7cddfSDavid du Colombier     wdev->user_page_begin = pd.nFromPage;
14267dd7cddfSDavid du Colombier     wdev->user_page_end = pd.nToPage;
14277dd7cddfSDavid du Colombier     wdev->user_copies = devmode->dmCopies;
14287dd7cddfSDavid du Colombier     wdev->print_copies = pd.nCopies;
14297dd7cddfSDavid du Colombier     wdev->user_media_size[0] = devmode->dmPaperWidth / 254.0 * 72.0;
14307dd7cddfSDavid du Colombier     wdev->user_media_size[1] = devmode->dmPaperLength / 254.0 * 72.0;
14317dd7cddfSDavid du Colombier     wdev->user_paper = devmode->dmPaperSize;
14327dd7cddfSDavid du Colombier     wdev->user_orient = devmode->dmOrientation;
14337dd7cddfSDavid du Colombier     wdev->user_color = devmode->dmColor;
14347dd7cddfSDavid du Colombier 
14357dd7cddfSDavid du Colombier     if (devmode->dmFields & DM_DUPLEX) {
14367dd7cddfSDavid du Colombier 	wdev->Duplex_set = 1;
14377dd7cddfSDavid du Colombier 	wdev->Duplex = devmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
14383ff48bf5SDavid du Colombier 	wdev->tumble = devmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
14397dd7cddfSDavid du Colombier     }
14407dd7cddfSDavid du Colombier 
14417dd7cddfSDavid du Colombier     {
14427dd7cddfSDavid du Colombier 	float xppinch = 0;
14437dd7cddfSDavid du Colombier 	float yppinch = 0;
14447dd7cddfSDavid du Colombier 	const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
14457dd7cddfSDavid du Colombier 	const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
14467dd7cddfSDavid du Colombier 	const char* output = (char*)(devnames)+(devnames->wOutputOffset);
14477dd7cddfSDavid du Colombier 
14487dd7cddfSDavid du Colombier 	HDC hic = CreateIC(driver, device, output, devmode);
14497dd7cddfSDavid du Colombier 
14507dd7cddfSDavid du Colombier 	if (hic) {
14517dd7cddfSDavid du Colombier 	    xppinch = (float)GetDeviceCaps(hic, LOGPIXELSX);
14527dd7cddfSDavid du Colombier 	    yppinch = (float)GetDeviceCaps(hic, LOGPIXELSY);
14537dd7cddfSDavid du Colombier 	    wdev->user_media_size[0] = GetDeviceCaps(hic, PHYSICALWIDTH) * 72.0 / xppinch;
14547dd7cddfSDavid du Colombier 	    wdev->user_media_size[1] = GetDeviceCaps(hic, PHYSICALHEIGHT) * 72.0 / yppinch;
14557dd7cddfSDavid du Colombier 	    DeleteDC(hic);
14567dd7cddfSDavid du Colombier 	}
14577dd7cddfSDavid du Colombier     }
14587dd7cddfSDavid du Colombier 
14597dd7cddfSDavid du Colombier     devmode = NULL;
14607dd7cddfSDavid du Colombier     devnames = NULL;
14617dd7cddfSDavid du Colombier 
14627dd7cddfSDavid du Colombier     GlobalUnlock(pd.hDevMode);
14637dd7cddfSDavid du Colombier     GlobalUnlock(pd.hDevNames);
14647dd7cddfSDavid du Colombier 
14657dd7cddfSDavid du Colombier     if (wdev->win32_hdevmode != NULL) {
14667dd7cddfSDavid du Colombier 	GlobalFree(wdev->win32_hdevmode);
14677dd7cddfSDavid du Colombier     }
14687dd7cddfSDavid du Colombier     if (wdev->win32_hdevnames != NULL) {
14697dd7cddfSDavid du Colombier 	GlobalFree(wdev->win32_hdevnames);
14707dd7cddfSDavid du Colombier     }
14717dd7cddfSDavid du Colombier 
14727dd7cddfSDavid du Colombier     wdev->win32_hdevmode = pd.hDevMode;
14737dd7cddfSDavid du Colombier     wdev->win32_hdevnames = pd.hDevNames;
14747dd7cddfSDavid du Colombier 
14757dd7cddfSDavid du Colombier     return TRUE;
14767dd7cddfSDavid du Colombier }
14777dd7cddfSDavid du Colombier 
14787dd7cddfSDavid du Colombier /*  Check that we are dealing with an original device. If this
14797dd7cddfSDavid du Colombier  *  happens to be a copy made by "copydevice", we will have to
14807dd7cddfSDavid du Colombier  *  copy the original's handles to the associated Win32 params.
14817dd7cddfSDavid du Colombier  */
14827dd7cddfSDavid du Colombier 
14837dd7cddfSDavid du Colombier private void
win_pr2_copy_check(gx_device_win_pr2 * wdev)14847dd7cddfSDavid du Colombier win_pr2_copy_check(gx_device_win_pr2 * wdev)
14857dd7cddfSDavid du Colombier {
14867dd7cddfSDavid du Colombier     HGLOBAL hdevmode = wdev->win32_hdevmode;
14877dd7cddfSDavid du Colombier     HGLOBAL hdevnames = wdev->win32_hdevnames;
14887dd7cddfSDavid du Colombier     DWORD devmode_len = (hdevmode) ? GlobalSize(hdevmode) : 0;
14897dd7cddfSDavid du Colombier     DWORD devnames_len = (hdevnames) ? GlobalSize(hdevnames) : 0;
14907dd7cddfSDavid du Colombier 
14917dd7cddfSDavid du Colombier     if (wdev->original_device == wdev)
14927dd7cddfSDavid du Colombier 	return;
14937dd7cddfSDavid du Colombier 
14947dd7cddfSDavid du Colombier     wdev->hdcprn = NULL;
14957dd7cddfSDavid du Colombier     wdev->win32_hdevmode = NULL;
14967dd7cddfSDavid du Colombier     wdev->win32_hdevnames = NULL;
14977dd7cddfSDavid du Colombier 
14987dd7cddfSDavid du Colombier     wdev->original_device = wdev;
14997dd7cddfSDavid du Colombier 
15007dd7cddfSDavid du Colombier     if (devmode_len) {
15017dd7cddfSDavid du Colombier 	wdev->win32_hdevmode = GlobalAlloc(0, devmode_len);
15027dd7cddfSDavid du Colombier 	if (wdev->win32_hdevmode) {
15037dd7cddfSDavid du Colombier 	    memcpy(GlobalLock(wdev->win32_hdevmode), GlobalLock(hdevmode), devmode_len);
15047dd7cddfSDavid du Colombier 	    GlobalUnlock(wdev->win32_hdevmode);
15057dd7cddfSDavid du Colombier 	    GlobalUnlock(hdevmode);
15067dd7cddfSDavid du Colombier 	}
15077dd7cddfSDavid du Colombier     }
15087dd7cddfSDavid du Colombier 
15097dd7cddfSDavid du Colombier     if (devnames_len) {
15107dd7cddfSDavid du Colombier 	wdev->win32_hdevnames = GlobalAlloc(0, devnames_len);
15117dd7cddfSDavid du Colombier 	if (wdev->win32_hdevnames) {
15127dd7cddfSDavid du Colombier 	    memcpy(GlobalLock(wdev->win32_hdevnames), GlobalLock(hdevnames), devnames_len);
15137dd7cddfSDavid du Colombier 	    GlobalUnlock(wdev->win32_hdevnames);
15147dd7cddfSDavid du Colombier 	    GlobalUnlock(hdevnames);
15157dd7cddfSDavid du Colombier 	}
15167dd7cddfSDavid du Colombier     }
15177dd7cddfSDavid du Colombier }
15183ff48bf5SDavid du Colombier 
15193ff48bf5SDavid du Colombier 
15203ff48bf5SDavid du Colombier /* Modeless dialog box - Cancel printing */
15213ff48bf5SDavid du Colombier BOOL CALLBACK
CancelDlgProc(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)15223ff48bf5SDavid du Colombier CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
15233ff48bf5SDavid du Colombier {
15243ff48bf5SDavid du Colombier     switch (message) {
15253ff48bf5SDavid du Colombier 	case WM_INITDIALOG:
15263ff48bf5SDavid du Colombier 	    SetWindowText(hDlg, szAppName);
15273ff48bf5SDavid du Colombier 	    return TRUE;
15283ff48bf5SDavid du Colombier 	case WM_COMMAND:
15293ff48bf5SDavid du Colombier 	    switch (LOWORD(wParam)) {
15303ff48bf5SDavid du Colombier 		case IDCANCEL:
15313ff48bf5SDavid du Colombier 		    DestroyWindow(hDlg);
15323ff48bf5SDavid du Colombier 		    EndDialog(hDlg, 0);
15333ff48bf5SDavid du Colombier 		    return TRUE;
15343ff48bf5SDavid du Colombier 	    }
15353ff48bf5SDavid du Colombier     }
15363ff48bf5SDavid du Colombier     return FALSE;
15373ff48bf5SDavid du Colombier }
15383ff48bf5SDavid du Colombier 
15393ff48bf5SDavid du Colombier 
15403ff48bf5SDavid du Colombier BOOL CALLBACK
AbortProc2(HDC hdcPrn,int code)15413ff48bf5SDavid du Colombier AbortProc2(HDC hdcPrn, int code)
15423ff48bf5SDavid du Colombier {
1543*593dc095SDavid du Colombier     process_interrupts(NULL);
15443ff48bf5SDavid du Colombier     if (code == SP_OUTOFDISK)
15453ff48bf5SDavid du Colombier 	return (FALSE);		/* cancel job */
15463ff48bf5SDavid du Colombier     return (TRUE);
15473ff48bf5SDavid du Colombier }
15483ff48bf5SDavid du Colombier 
1549