gdevwpr2.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532
  1. /* Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved.
  2. This file is part of AFPL Ghostscript.
  3. AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author or
  4. distributor accepts any responsibility for the consequences of using it, or
  5. for whether it serves any particular purpose or works at all, unless he or
  6. she says so in writing. Refer to the Aladdin Free Public License (the
  7. "License") for full details.
  8. Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. in a plain ASCII text file named PUBLIC. The License grants you the right
  10. to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. conditions described in the License. Among other things, the License
  12. requires that the copyright notice and this notice be preserved on all
  13. copies.
  14. */
  15. /*$Id: gdevwpr2.c,v 1.9 2001/03/26 11:28:20 ghostgum Exp $ */
  16. /*
  17. * Microsoft Windows 3.n printer driver for Ghostscript.
  18. * Original version by Russell Lang and
  19. * L. Peter Deutsch, Aladdin Enterprises.
  20. * Modified by rjl 1995-03-29 to use BMP printer code
  21. * Modified by Pierre Arnaud 1999-02-18 (see description below)
  22. * Modified by lpd 1999-04-03 for compatibility with Borland C++ 4.5.
  23. * Modified by Pierre Arnaud 1999-10-03 (accept b&w printing on color printers).
  24. * Modified by Pierre Arnaud 1999-11-20 (accept lower resolution)
  25. * Bug fixed by Pierre Arnaud 2000-03-09 (win_pr2_put_params error when is_open)
  26. * Bug fixed by Pierre Arnaud 2000-03-20 (win_pr2_set_bpp did not set anti_alias)
  27. * Bug fixed by Pierre Arnaud 2000-03-22 (win_pr2_set_bpp depth was wrong)
  28. * Modified by Pierre Arnaud 2000-12-12 (mainly added support for Tumble)
  29. * Bug fixed by Pierre Arnaud 2000-12-18 (-dQueryUser now works from cmd line)
  30. */
  31. /* This driver uses the printer default size and resolution and
  32. * ignores page size and resolution set using -gWIDTHxHEIGHT and
  33. * -rXxY. You must still set the correct PageSize to get the
  34. * correct clipping path.
  35. * The code in win_pr2_getdc() does try to set the printer page
  36. * size from the PostScript PageSize, but it isn't working
  37. * reliably at the moment.
  38. *
  39. * This driver doesn't work with some Windows printer drivers.
  40. * The reason is unknown. All printers to which I have access
  41. * work.
  42. *
  43. * rjl 1997-11-20
  44. */
  45. /* Additions by Pierre Arnaud (Pierre.Arnaud@opac.ch)
  46. *
  47. * The driver has been extended in order to provide some run-time
  48. * feed-back about the default Windows printer and to give the user
  49. * the opportunity to select the printer's properties before the
  50. * device gets opened (and any spooling starts).
  51. *
  52. * The driver returns an additional property named "UserSettings".
  53. * This is a dictionary which contens are valid only after setting
  54. * the QueryUser property (see below). The UserSettings dict contains
  55. * the following keys:
  56. *
  57. * DocumentRange [begin end] (int array, can be set)
  58. * Defines the range of pages in the document; [1 10] would
  59. * describe a document starting at page 1 and ending at page 10.
  60. *
  61. * SelectedRange [begin end] (int array, can be set)
  62. * Defines the pages the user wants to print.
  63. *
  64. * MediaSize [width height] (float array, read only)
  65. * Current printer's media size.
  66. *
  67. * Copies n (integer, can be set)
  68. * User selected number of copies.
  69. *
  70. * PrintCopies n (integer, read only)
  71. * Number of copies which must be printed by Ghostscript itself.
  72. * This is still experimental.
  73. *
  74. * DocumentName name (string, can be set)
  75. * Name to be associated with the print job.
  76. *
  77. * UserChangedSettings (bool, read only)
  78. * Set to 'true' if the last QueryUser operation succeeded.
  79. *
  80. * Paper n (integer, can be set)
  81. * Windows paper selection (0 = automatic).
  82. *
  83. * Orient n (integer, can be set)
  84. * Windows paper orientation (0 = automatic).
  85. *
  86. * Color n (integer, can be set)
  87. * Windows color (0 = automatic, 1 = monochrome, 2 = color).
  88. *
  89. * MaxResolution n (integer, can be set)
  90. * Maximum resolution in pixels pet inch (0 = no maximum). If
  91. * the printer has a higher resolution than the maximum, trim
  92. * the used resolution to the best one (dpi_chosen <= dpi_max,
  93. * with dpi_chosen = dpi_printer / ratio).
  94. */
  95. /* Supported printer parameters are :
  96. *
  97. * -dBitsPerPixel=n
  98. * Override what the Window printer driver returns.
  99. *
  100. * -dNoCancel
  101. * Don't display cancel dialog box. Useful for unattended or
  102. * console EXE operation.
  103. *
  104. * -dQueryUser=n
  105. * Query user interactively for the destination printer, before
  106. * the device gets opened. This fills in the UserSettings dict
  107. * and the OutputFile name properties. The following values are
  108. * supported for n:
  109. * 1 => show standard Print dialog
  110. * 2 => show Print Setup dialog instead
  111. * 3 => select default printer
  112. * other, does nothing
  113. *
  114. * The /Duplex & /Tumble keys of the setpagedevice dict are supported
  115. * if the Windows printer supports duplex printing.
  116. */
  117. #include "gdevprn.h"
  118. #include "gdevpccm.h"
  119. #include "windows_.h"
  120. #include <shellapi.h>
  121. #include "gp_mswin.h"
  122. #include "gp.h"
  123. #include "gpcheck.h"
  124. #include "commdlg.h"
  125. /* Make sure we cast to the correct structure type. */
  126. typedef struct gx_device_win_pr2_s gx_device_win_pr2;
  127. #undef wdev
  128. #define wdev ((gx_device_win_pr2 *)dev)
  129. /* Device procedures */
  130. /* See gxdevice.h for the definitions of the procedures. */
  131. private dev_proc_open_device(win_pr2_open);
  132. private dev_proc_close_device(win_pr2_close);
  133. private dev_proc_print_page(win_pr2_print_page);
  134. private dev_proc_map_rgb_color(win_pr2_map_rgb_color);
  135. private dev_proc_map_color_rgb(win_pr2_map_color_rgb);
  136. private dev_proc_get_params(win_pr2_get_params);
  137. private dev_proc_put_params(win_pr2_put_params);
  138. private void win_pr2_set_bpp(gx_device * dev, int depth);
  139. private const gx_device_procs win_pr2_procs =
  140. prn_color_params_procs(win_pr2_open, gdev_prn_output_page, win_pr2_close,
  141. win_pr2_map_rgb_color, win_pr2_map_color_rgb,
  142. win_pr2_get_params, win_pr2_put_params);
  143. #define PARENT_WINDOW HWND_DESKTOP
  144. BOOL CALLBACK CancelDlgProc(HWND, UINT, WPARAM, LPARAM);
  145. BOOL CALLBACK AbortProc2(HDC, int);
  146. /* The device descriptor */
  147. typedef struct gx_device_win_pr2_s gx_device_win_pr2;
  148. struct gx_device_win_pr2_s {
  149. gx_device_common;
  150. gx_prn_device_common;
  151. HDC hdcprn;
  152. bool nocancel;
  153. int doc_page_begin; /* first page number in document */
  154. int doc_page_end; /* last page number in document */
  155. int user_page_begin; /* user's choice: first page to print */
  156. int user_page_end; /* user's choice: last page to print */
  157. int user_copies; /* user's choice: number of copies */
  158. int print_copies; /* number of times GS should print each page */
  159. float user_media_size[2]; /* width/height of media selected by user */
  160. char doc_name[200]; /* name of document for the spooler */
  161. char paper_name[64]; /* name of selected paper format */
  162. bool user_changed_settings; /* true if user validated dialog */
  163. int user_paper; /* user's choice: paper format */
  164. int user_orient; /* user's choice: paper orientation */
  165. int user_color; /* user's choice: color format */
  166. int max_dpi; /* maximum resolution in DPI */
  167. int ratio; /* stretch ratio when printing */
  168. int selected_bpp; /* selected bpp, memorised by win_pr2_set_bpp */
  169. bool tumble; /* tumble setting (with duplex) */
  170. int query_user; /* query user (-dQueryUser) */
  171. HANDLE win32_hdevmode; /* handle to device mode information */
  172. HANDLE win32_hdevnames; /* handle to device names information */
  173. DLGPROC lpfnAbortProc;
  174. DLGPROC lpfnCancelProc;
  175. HWND hDlgModeless;
  176. bool use_old_spool_name; /* user prefers old \\spool\ name */
  177. gx_device_win_pr2* original_device; /* used to detect copies */
  178. };
  179. gx_device_win_pr2 far_data gs_mswinpr2_device =
  180. {
  181. prn_device_std_body(gx_device_win_pr2, win_pr2_procs, "mswinpr2",
  182. DEFAULT_WIDTH_10THS, DEFAULT_HEIGHT_10THS, 72.0, 72.0,
  183. 0, 0, 0, 0,
  184. 0, win_pr2_print_page), /* depth = 0 */
  185. 0, /* hdcprn */
  186. 0, /* nocancel */
  187. 0, /* doc_page_begin */
  188. 0, /* doc_page_end */
  189. 0, /* user_page_begin */
  190. 0, /* user_page_end */
  191. 1, /* user_copies */
  192. 1, /* print_copies */
  193. { 0.0, 0.0 }, /* user_media_size */
  194. { 0 }, /* doc_name */
  195. { 0 }, /* paper_name */
  196. 0, /* user_changed_settings */
  197. 0, /* user_paper */
  198. 0, /* user_orient */
  199. 0, /* user_color */
  200. 0, /* max_dpi */
  201. 0, /* ratio */
  202. 0, /* selected_bpp */
  203. false, /* tumble */
  204. -1, /* query_user */
  205. NULL, /* win32_hdevmode */
  206. NULL, /* win32_hdevnames */
  207. NULL, /* lpfnAbortProc */
  208. NULL, /* lpfnCancelProc */
  209. false, /* use_old_spool_name */
  210. NULL /* original_device */
  211. };
  212. /********************************************************************************/
  213. private int win_pr2_getdc(gx_device_win_pr2 * dev);
  214. private int win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
  215. private int win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode);
  216. private int win_pr2_print_setup_interaction(gx_device_win_pr2 * dev, int mode);
  217. private int win_pr2_write_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
  218. private int win_pr2_read_user_settings(gx_device_win_pr2 * dev, gs_param_list * plist);
  219. private void win_pr2_copy_check(gx_device_win_pr2 * dev);
  220. /********************************************************************************/
  221. /* Open the win_pr2 driver */
  222. private int
  223. win_pr2_open(gx_device * dev)
  224. {
  225. int code;
  226. int depth;
  227. PRINTDLG pd;
  228. POINT offset;
  229. POINT size;
  230. float m[4];
  231. FILE *pfile;
  232. DOCINFO docinfo;
  233. float ratio = 1.0;
  234. win_pr2_copy_check(wdev);
  235. /* get a HDC for the printer */
  236. if ((wdev->win32_hdevmode) &&
  237. (wdev->win32_hdevnames)) {
  238. /* The user has already had the opportunity to choose the output */
  239. /* file interactively. Just use the specified parameters. */
  240. LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
  241. LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
  242. const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
  243. const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
  244. const char* output = (char*)(devnames)+(devnames->wOutputOffset);
  245. wdev->hdcprn = CreateDC(driver, device, output, devmode);
  246. GlobalUnlock(wdev->win32_hdevmode);
  247. GlobalUnlock(wdev->win32_hdevnames);
  248. if (wdev->hdcprn == NULL) {
  249. return gs_error_Fatal;
  250. }
  251. } else if (!win_pr2_getdc(wdev)) {
  252. /* couldn't get a printer from -sOutputFile= */
  253. /* Prompt with dialog box */
  254. LPDEVMODE devmode = NULL;
  255. memset(&pd, 0, sizeof(pd));
  256. pd.lStructSize = sizeof(pd);
  257. pd.hwndOwner = PARENT_WINDOW;
  258. pd.Flags = PD_RETURNDC;
  259. pd.nMinPage = wdev->doc_page_begin;
  260. pd.nMaxPage = wdev->doc_page_end;
  261. pd.nFromPage = wdev->user_page_begin;
  262. pd.nToPage = wdev->user_page_end;
  263. pd.nCopies = wdev->user_copies;
  264. if (!PrintDlg(&pd)) {
  265. /* device not opened - exit ghostscript */
  266. return gs_error_Fatal; /* exit Ghostscript cleanly */
  267. }
  268. devmode = GlobalLock(pd.hDevMode);
  269. win_pr2_update_dev(wdev,devmode);
  270. GlobalUnlock(pd.hDevMode);
  271. if (wdev->win32_hdevmode)
  272. GlobalFree(wdev->win32_hdevmode);
  273. if (wdev->win32_hdevnames)
  274. GlobalFree(wdev->win32_hdevnames);
  275. wdev->hdcprn = pd.hDC;
  276. wdev->win32_hdevmode = pd.hDevMode;
  277. wdev->win32_hdevnames = pd.hDevNames;
  278. pd.hDevMode = NULL;
  279. pd.hDevNames = NULL;
  280. }
  281. if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_DIBTODEV)) {
  282. errprintf( "Windows printer does not have RC_DIBTODEV\n");
  283. DeleteDC(wdev->hdcprn);
  284. return gs_error_limitcheck;
  285. }
  286. /* initialise printer, install abort proc */
  287. wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
  288. SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);
  289. /*
  290. * Some versions of the Windows headers include lpszDatatype and fwType,
  291. * and some don't. Since we want to set these fields to zero anyway,
  292. * we just start by zeroing the whole structure.
  293. */
  294. memset(&docinfo, 0, sizeof(docinfo));
  295. docinfo.cbSize = sizeof(docinfo);
  296. docinfo.lpszDocName = wdev->doc_name;
  297. /*docinfo.lpszOutput = NULL;*/
  298. /*docinfo.lpszDatatype = NULL;*/
  299. /*docinfo.fwType = 0;*/
  300. if (docinfo.lpszDocName[0] == 0) {
  301. docinfo.lpszDocName = "Ghostscript output";
  302. }
  303. if (StartDoc(wdev->hdcprn, &docinfo) <= 0) {
  304. errprintf("Printer StartDoc failed (error %08x)\n", GetLastError());
  305. DeleteDC(wdev->hdcprn);
  306. return gs_error_limitcheck;
  307. }
  308. dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
  309. dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
  310. wdev->ratio = 1;
  311. if (wdev->max_dpi > 50) {
  312. float dpi_x = dev->x_pixels_per_inch;
  313. float dpi_y = dev->y_pixels_per_inch;
  314. while ((dev->x_pixels_per_inch > wdev->max_dpi)
  315. || (dev->y_pixels_per_inch > wdev->max_dpi)) {
  316. ratio += 1.0;
  317. wdev->ratio ++;
  318. dev->x_pixels_per_inch = dpi_x / ratio;
  319. dev->y_pixels_per_inch = dpi_y / ratio;
  320. }
  321. }
  322. size.x = GetDeviceCaps(wdev->hdcprn, PHYSICALWIDTH);
  323. size.y = GetDeviceCaps(wdev->hdcprn, PHYSICALHEIGHT);
  324. gx_device_set_width_height(dev, (int)(size.x / ratio), (int)(size.y / ratio));
  325. offset.x = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETX);
  326. offset.y = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETY);
  327. /* m[] gives margins in inches */
  328. m[0] /*left */ = offset.x / dev->x_pixels_per_inch / ratio;
  329. m[3] /*top */ = offset.y / dev->y_pixels_per_inch / ratio;
  330. m[2] /*right */ = (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES)) / dev->x_pixels_per_inch / ratio;
  331. m[1] /*bottom */ = (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES)) / dev->y_pixels_per_inch / ratio;
  332. gx_device_set_margins(dev, m, true);
  333. depth = dev->color_info.depth;
  334. if (depth == 0) {
  335. /* Set parameters that were unknown before opening device */
  336. /* Find out if the device supports color */
  337. /* We recognize 1, 4 (but use only 3), 8 and 24 bit color devices */
  338. depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
  339. }
  340. win_pr2_set_bpp(dev, depth);
  341. /* gdev_prn_open opens a temporary file which we don't want */
  342. /* so we specify the name now so we can delete it later */
  343. pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
  344. wdev->fname, "wb");
  345. fclose(pfile);
  346. code = gdev_prn_open(dev);
  347. /* delete unwanted temporary file */
  348. unlink(wdev->fname);
  349. if (!wdev->nocancel) {
  350. /* inform user of progress with dialog box and allow cancel */
  351. wdev->lpfnCancelProc = (DLGPROC) CancelDlgProc;
  352. wdev->hDlgModeless = CreateDialog(phInstance, "CancelDlgBox",
  353. PARENT_WINDOW, wdev->lpfnCancelProc);
  354. ShowWindow(wdev->hDlgModeless, SW_HIDE);
  355. }
  356. return code;
  357. };
  358. /* Close the win_pr2 driver */
  359. private int
  360. win_pr2_close(gx_device * dev)
  361. {
  362. int code;
  363. int aborted = FALSE;
  364. win_pr2_copy_check(wdev);
  365. /* Free resources */
  366. if (!wdev->nocancel) {
  367. if (!wdev->hDlgModeless)
  368. aborted = TRUE;
  369. else
  370. DestroyWindow(wdev->hDlgModeless);
  371. wdev->hDlgModeless = 0;
  372. }
  373. if (aborted)
  374. AbortDoc(wdev->hdcprn);
  375. else
  376. EndDoc(wdev->hdcprn);
  377. DeleteDC(wdev->hdcprn);
  378. if (wdev->win32_hdevmode != NULL) {
  379. GlobalFree(wdev->win32_hdevmode);
  380. wdev->win32_hdevmode = NULL;
  381. }
  382. if (wdev->win32_hdevnames != NULL) {
  383. GlobalFree(wdev->win32_hdevnames);
  384. wdev->win32_hdevnames = NULL;
  385. }
  386. code = gdev_prn_close(dev);
  387. return code;
  388. }
  389. /* ------ Internal routines ------ */
  390. #undef wdev
  391. #define wdev ((gx_device_win_pr2 *)pdev)
  392. /********************************************************************************/
  393. /* ------ Private definitions ------ */
  394. /* new win_pr2_print_page routine */
  395. /* Write BMP header to memory, then send bitmap to printer */
  396. /* one scan line at a time */
  397. private int
  398. win_pr2_print_page(gx_device_printer * pdev, FILE * file)
  399. {
  400. int raster = gdev_prn_raster(pdev);
  401. /* BMP scan lines are padded to 32 bits. */
  402. ulong bmp_raster = raster + (-raster & 3);
  403. ulong bmp_raster_multi;
  404. int scan_lines, yslice, lines, i;
  405. int width;
  406. int depth = pdev->color_info.depth;
  407. byte *row;
  408. int y;
  409. int code = 0; /* return code */
  410. MSG msg;
  411. char dlgtext[32];
  412. HGLOBAL hrow;
  413. int ratio = ((gx_device_win_pr2 *)pdev)->ratio;
  414. struct bmi_s {
  415. BITMAPINFOHEADER h;
  416. RGBQUAD pal[256];
  417. } bmi;
  418. scan_lines = dev_print_scan_lines(pdev);
  419. width = (int)(pdev->width - ((dev_l_margin(pdev) + dev_r_margin(pdev) -
  420. dev_x_offset(pdev)) * pdev->x_pixels_per_inch));
  421. yslice = 65535 / bmp_raster; /* max lines in 64k */
  422. bmp_raster_multi = bmp_raster * yslice;
  423. hrow = GlobalAlloc(0, bmp_raster_multi);
  424. row = GlobalLock(hrow);
  425. if (row == 0) /* can't allocate row buffer */
  426. return_error(gs_error_VMerror);
  427. /* Write the info header. */
  428. bmi.h.biSize = sizeof(bmi.h);
  429. bmi.h.biWidth = pdev->width; /* wdev->mdev.width; */
  430. bmi.h.biHeight = yslice;
  431. bmi.h.biPlanes = 1;
  432. bmi.h.biBitCount = pdev->color_info.depth;
  433. bmi.h.biCompression = 0;
  434. bmi.h.biSizeImage = 0; /* default */
  435. bmi.h.biXPelsPerMeter = 0; /* default */
  436. bmi.h.biYPelsPerMeter = 0; /* default */
  437. StartPage(wdev->hdcprn);
  438. /* Write the palette. */
  439. if (depth <= 8) {
  440. int i;
  441. gx_color_value rgb[3];
  442. LPRGBQUAD pq;
  443. bmi.h.biClrUsed = 1 << depth;
  444. bmi.h.biClrImportant = 1 << depth;
  445. for (i = 0; i != 1 << depth; i++) {
  446. (*dev_proc(pdev, map_color_rgb)) ((gx_device *) pdev,
  447. (gx_color_index) i, rgb);
  448. pq = &bmi.pal[i];
  449. pq->rgbRed = gx_color_value_to_byte(rgb[0]);
  450. pq->rgbGreen = gx_color_value_to_byte(rgb[1]);
  451. pq->rgbBlue = gx_color_value_to_byte(rgb[2]);
  452. pq->rgbReserved = 0;
  453. }
  454. } else {
  455. bmi.h.biClrUsed = 0;
  456. bmi.h.biClrImportant = 0;
  457. }
  458. if (!wdev->nocancel) {
  459. sprintf(dlgtext, "Printing page %d", (int)(pdev->PageCount) + 1);
  460. SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PRINTING), dlgtext);
  461. ShowWindow(wdev->hDlgModeless, SW_SHOW);
  462. }
  463. for (y = 0; y < scan_lines;) {
  464. /* copy slice to row buffer */
  465. if (y > scan_lines - yslice)
  466. lines = scan_lines - y;
  467. else
  468. lines = yslice;
  469. for (i = 0; i < lines; i++)
  470. gdev_prn_copy_scan_lines(pdev, y + i,
  471. row + (bmp_raster * (lines - 1 - i)), raster);
  472. if (ratio > 1) {
  473. StretchDIBits(wdev->hdcprn, 0, y*ratio, pdev->width*ratio, lines*ratio,
  474. 0, 0, pdev->width, lines,
  475. row,
  476. (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS, SRCCOPY);
  477. } else {
  478. SetDIBitsToDevice(wdev->hdcprn, 0, y, pdev->width, lines,
  479. 0, 0, 0, lines,
  480. row,
  481. (BITMAPINFO FAR *) & bmi, DIB_RGB_COLORS);
  482. }
  483. y += lines;
  484. if (!wdev->nocancel) {
  485. /* inform user of progress */
  486. sprintf(dlgtext, "%d%% done", (int)(y * 100L / scan_lines));
  487. SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE), dlgtext);
  488. }
  489. /* process message loop */
  490. while (PeekMessage(&msg, wdev->hDlgModeless, 0, 0, PM_REMOVE)) {
  491. if ((wdev->hDlgModeless == 0) || !IsDialogMessage(wdev->hDlgModeless, &msg)) {
  492. TranslateMessage(&msg);
  493. DispatchMessage(&msg);
  494. }
  495. }
  496. if ((!wdev->nocancel) && (wdev->hDlgModeless == 0)) {
  497. /* user pressed cancel button */
  498. break;
  499. }
  500. }
  501. if ((!wdev->nocancel) && (wdev->hDlgModeless == 0))
  502. code = gs_error_Fatal; /* exit Ghostscript cleanly */
  503. else {
  504. /* push out the page */
  505. if (!wdev->nocancel)
  506. SetWindowText(GetDlgItem(wdev->hDlgModeless, CANCEL_PCDONE),
  507. "Ejecting page...");
  508. EndPage(wdev->hdcprn);
  509. if (!wdev->nocancel)
  510. ShowWindow(wdev->hDlgModeless, SW_HIDE);
  511. }
  512. bmp_done:
  513. GlobalUnlock(hrow);
  514. GlobalFree(hrow);
  515. return code;
  516. }
  517. /* combined color mappers */
  518. /* 24-bit color mappers (taken from gdevmem2.c). */
  519. /* Note that Windows expects RGB values in the order B,G,R. */
  520. /* Map a r-g-b color to a color index. */
  521. private gx_color_index
  522. win_pr2_map_rgb_color(gx_device * dev, gx_color_value r, gx_color_value g,
  523. gx_color_value b)
  524. {
  525. switch (dev->color_info.depth) {
  526. case 1:
  527. return gdev_prn_map_rgb_color(dev, r, g, b);
  528. case 4:
  529. /* use only 8 colors */
  530. return (r > (gx_max_color_value / 2 + 1) ? 4 : 0) +
  531. (g > (gx_max_color_value / 2 + 1) ? 2 : 0) +
  532. (b > (gx_max_color_value / 2 + 1) ? 1 : 0);
  533. case 8:
  534. return pc_8bit_map_rgb_color(dev, r, g, b);
  535. case 24:
  536. return gx_color_value_to_byte(r) +
  537. ((uint) gx_color_value_to_byte(g) << 8) +
  538. ((ulong) gx_color_value_to_byte(b) << 16);
  539. }
  540. return 0; /* error */
  541. }
  542. /* Map a color index to a r-g-b color. */
  543. private int
  544. win_pr2_map_color_rgb(gx_device * dev, gx_color_index color,
  545. gx_color_value prgb[3])
  546. {
  547. switch (dev->color_info.depth) {
  548. case 1:
  549. gdev_prn_map_color_rgb(dev, color, prgb);
  550. break;
  551. case 4:
  552. /* use only 8 colors */
  553. prgb[0] = (color & 4) ? gx_max_color_value : 0;
  554. prgb[1] = (color & 2) ? gx_max_color_value : 0;
  555. prgb[2] = (color & 1) ? gx_max_color_value : 0;
  556. break;
  557. case 8:
  558. pc_8bit_map_color_rgb(dev, color, prgb);
  559. break;
  560. case 24:
  561. prgb[2] = gx_color_value_from_byte(color >> 16);
  562. prgb[1] = gx_color_value_from_byte((color >> 8) & 0xff);
  563. prgb[0] = gx_color_value_from_byte(color & 0xff);
  564. break;
  565. }
  566. return 0;
  567. }
  568. void
  569. win_pr2_set_bpp(gx_device * dev, int depth)
  570. {
  571. if (depth > 8) {
  572. static const gx_device_color_info win_pr2_24color = dci_std_color(24);
  573. dev->color_info = win_pr2_24color;
  574. depth = 24;
  575. } else if (depth >= 8) {
  576. /* 8-bit (SuperVGA-style) color. */
  577. /* (Uses a fixed palette of 3,3,2 bits.) */
  578. static const gx_device_color_info win_pr2_8color = dci_pc_8bit;
  579. dev->color_info = win_pr2_8color;
  580. depth = 8;
  581. } else if (depth >= 3) {
  582. /* 3 plane printer */
  583. /* suitable for impact dot matrix CMYK printers */
  584. /* create 4-bit bitmap, but only use 8 colors */
  585. static const gx_device_color_info win_pr2_4color = dci_values(3, 4, 1, 1, 2, 2);
  586. dev->color_info = win_pr2_4color;
  587. depth = 4;
  588. } else { /* default is black_and_white */
  589. static const gx_device_color_info win_pr2_1color = dci_std_color(1);
  590. dev->color_info = win_pr2_1color;
  591. depth = 1;
  592. }
  593. ((gx_device_win_pr2 *)dev)->selected_bpp = depth;
  594. }
  595. /********************************************************************************/
  596. /* Get device parameters */
  597. int
  598. win_pr2_get_params(gx_device * pdev, gs_param_list * plist)
  599. {
  600. int code = gdev_prn_get_params(pdev, plist);
  601. win_pr2_copy_check(wdev);
  602. if (code >= 0)
  603. code = param_write_bool(plist, "NoCancel",
  604. &(wdev->nocancel));
  605. if (code >= 0)
  606. code = param_write_bool(plist, "QueryUser",
  607. &(wdev->query_user));
  608. if (code >= 0)
  609. code = win_pr2_write_user_settings(wdev, plist);
  610. if ((code >= 0) && (wdev->Duplex_set > 0))
  611. code = param_write_bool(plist, "Tumble",
  612. &(wdev->tumble));
  613. return code;
  614. }
  615. /* We implement this ourselves so that we can change BitsPerPixel */
  616. /* before the device is opened */
  617. int
  618. win_pr2_put_params(gx_device * pdev, gs_param_list * plist)
  619. {
  620. int ecode = 0, code;
  621. int old_bpp = pdev->color_info.depth;
  622. int bpp = old_bpp;
  623. bool tumble = wdev->tumble;
  624. bool nocancel = wdev->nocancel;
  625. int queryuser = 0;
  626. bool old_duplex = wdev->Duplex;
  627. bool old_tumble = wdev->tumble;
  628. int old_orient = wdev->user_orient;
  629. int old_color = wdev->user_color;
  630. int old_paper = wdev->user_paper;
  631. int old_mx_dpi = wdev->max_dpi;
  632. if (wdev->Duplex_set < 0) {
  633. wdev->Duplex_set = 0;
  634. wdev->Duplex = false;
  635. wdev->tumble = false;
  636. }
  637. win_pr2_copy_check(wdev);
  638. code = win_pr2_read_user_settings(wdev, plist);
  639. switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
  640. case 0:
  641. if (pdev->is_open) {
  642. if (wdev->selected_bpp == bpp) {
  643. break;
  644. }
  645. ecode = gs_error_rangecheck;
  646. } else { /* change dev->color_info is valid before device is opened */
  647. win_pr2_set_bpp(pdev, bpp);
  648. break;
  649. }
  650. goto bppe;
  651. default:
  652. ecode = code;
  653. bppe:param_signal_error(plist, "BitsPerPixel", ecode);
  654. case 1:
  655. break;
  656. }
  657. switch (code = param_read_bool(plist, "NoCancel", &nocancel)) {
  658. case 0:
  659. if (pdev->is_open) {
  660. if (wdev->nocancel == nocancel) {
  661. break;
  662. }
  663. ecode = gs_error_rangecheck;
  664. } else {
  665. wdev->nocancel = nocancel;
  666. break;
  667. }
  668. goto nocancele;
  669. default:
  670. ecode = code;
  671. nocancele:param_signal_error(plist, "NoCancel", ecode);
  672. case 1:
  673. break;
  674. }
  675. switch (code = param_read_bool(plist, "Tumble", &tumble)) {
  676. case 0:
  677. wdev->tumble = tumble;
  678. break;
  679. default:
  680. ecode = code;
  681. param_signal_error(plist, "Tumble", ecode);
  682. case 1:
  683. break;
  684. }
  685. switch (code = param_read_int(plist, "QueryUser", &queryuser)) {
  686. case 0:
  687. if ((queryuser > 0) &&
  688. (queryuser < 4)) {
  689. win_pr2_print_setup_interaction(wdev, queryuser);
  690. }
  691. break;
  692. default:
  693. ecode = code;
  694. param_signal_error(plist, "QueryUser", ecode);
  695. case 1:
  696. break;
  697. }
  698. if (ecode >= 0)
  699. ecode = gdev_prn_put_params(pdev, plist);
  700. if (wdev->win32_hdevmode && wdev->hdcprn) {
  701. if ( (old_duplex != wdev->Duplex)
  702. || (old_tumble != wdev->tumble)
  703. || (old_orient != wdev->user_orient)
  704. || (old_color != wdev->user_color)
  705. || (old_paper != wdev->user_paper)
  706. || (old_mx_dpi != wdev->max_dpi) ) {
  707. LPDEVMODE pdevmode = GlobalLock(wdev->win32_hdevmode);
  708. if (pdevmode) {
  709. win_pr2_update_win(wdev, pdevmode);
  710. ResetDC(wdev->hdcprn, pdevmode);
  711. GlobalUnlock(pdevmode);
  712. }
  713. }
  714. }
  715. return ecode;
  716. }
  717. #undef wdev
  718. /********************************************************************************/
  719. /* Get Device Context for printer */
  720. private int
  721. win_pr2_getdc(gx_device_win_pr2 * wdev)
  722. {
  723. char *device;
  724. char *devices;
  725. char *p;
  726. char driverbuf[512];
  727. char *driver;
  728. char *output;
  729. char *devcap;
  730. int devcapsize;
  731. int size;
  732. int i, n;
  733. POINT *pp;
  734. int paperindex;
  735. int paperwidth, paperheight;
  736. int orientation;
  737. int papersize;
  738. char papername[64];
  739. char drvname[32];
  740. HINSTANCE hlib;
  741. LPFNDEVMODE pfnExtDeviceMode;
  742. LPFNDEVCAPS pfnDeviceCapabilities;
  743. LPDEVMODE podevmode, pidevmode;
  744. HANDLE hprinter;
  745. /* first try to derive the printer name from -sOutputFile= */
  746. /* is printer if name prefixed by \\spool\ or by %printer% */
  747. if (is_spool(wdev->fname)) {
  748. device = wdev->fname + 8; /* skip over \\spool\ */
  749. wdev->use_old_spool_name = true;
  750. } else if (strncmp("%printer%",wdev->fname,9) == 0) {
  751. device = wdev->fname + 9; /* skip over %printer% */
  752. wdev->use_old_spool_name = false;
  753. } else {
  754. return FALSE;
  755. }
  756. /* now try to match the printer name against the [Devices] section */
  757. if ((devices = gs_malloc(4096, 1, "win_pr2_getdc")) == (char *)NULL)
  758. return FALSE;
  759. GetProfileString("Devices", NULL, "", devices, 4096);
  760. p = devices;
  761. while (*p) {
  762. if (stricmp(p, device) == 0)
  763. break;
  764. p += strlen(p) + 1;
  765. }
  766. if (*p == '\0')
  767. p = NULL;
  768. gs_free(devices, 4096, 1, "win_pr2_getdc");
  769. if (p == NULL)
  770. return FALSE; /* doesn't match an available printer */
  771. /* the printer exists, get the remaining information from win.ini */
  772. GetProfileString("Devices", device, "", driverbuf, sizeof(driverbuf));
  773. driver = strtok(driverbuf, ",");
  774. output = strtok(NULL, ",");
  775. if (is_win32s)
  776. {
  777. strcpy(drvname, driver);
  778. strcat(drvname, ".drv");
  779. driver = drvname;
  780. }
  781. if (!is_win32s) { /* Win32 */
  782. if (!OpenPrinter(device, &hprinter, NULL))
  783. return FALSE;
  784. size = DocumentProperties(NULL, hprinter, device, NULL, NULL, 0);
  785. if ((podevmode = gs_malloc(size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
  786. ClosePrinter(hprinter);
  787. return FALSE;
  788. }
  789. if ((pidevmode = gs_malloc(size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
  790. gs_free(podevmode, size, 1, "win_pr2_getdc");
  791. ClosePrinter(hprinter);
  792. return FALSE;
  793. }
  794. DocumentProperties(NULL, hprinter, device, podevmode, NULL, DM_OUT_BUFFER);
  795. pfnDeviceCapabilities = (LPFNDEVCAPS) DeviceCapabilities;
  796. } else
  797. { /* Win16 and Win32s */
  798. /* now load the printer driver */
  799. hlib = LoadLibrary(driver);
  800. if (hlib < (HINSTANCE) HINSTANCE_ERROR)
  801. return FALSE;
  802. /* call ExtDeviceMode() to get default parameters */
  803. pfnExtDeviceMode = (LPFNDEVMODE) GetProcAddress(hlib, "ExtDeviceMode");
  804. if (pfnExtDeviceMode == (LPFNDEVMODE) NULL) {
  805. FreeLibrary(hlib);
  806. return FALSE;
  807. }
  808. pfnDeviceCapabilities = (LPFNDEVCAPS) GetProcAddress(hlib, "DeviceCapabilities");
  809. if (pfnDeviceCapabilities == (LPFNDEVCAPS) NULL) {
  810. FreeLibrary(hlib);
  811. return FALSE;
  812. }
  813. size = pfnExtDeviceMode(NULL, hlib, NULL, device, output, NULL, NULL, 0);
  814. if ((podevmode = gs_malloc(size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
  815. FreeLibrary(hlib);
  816. return FALSE;
  817. }
  818. if ((pidevmode = gs_malloc(size, 1, "win_pr2_getdc")) == (LPDEVMODE) NULL) {
  819. gs_free(podevmode, size, 1, "win_pr2_getdc");
  820. FreeLibrary(hlib);
  821. return FALSE;
  822. }
  823. pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
  824. NULL, NULL, DM_OUT_BUFFER);
  825. }
  826. /* now find out what paper sizes are available */
  827. devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, NULL, NULL);
  828. devcapsize *= sizeof(POINT);
  829. if ((devcap = gs_malloc(devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
  830. return FALSE;
  831. n = pfnDeviceCapabilities(device, output, DC_PAPERSIZE, devcap, NULL);
  832. paperwidth = (int)(wdev->MediaSize[0] * 254 / 72);
  833. paperheight = (int)(wdev->MediaSize[1] * 254 / 72);
  834. papername[0] = '\0';
  835. papersize = 0;
  836. paperindex = -1;
  837. orientation = 0;
  838. pp = (POINT *) devcap;
  839. for (i = 0; i < n; i++, pp++) {
  840. if ((pp->x < paperwidth + 20) && (pp->x > paperwidth - 20) &&
  841. (pp->y < paperheight + 20) && (pp->y > paperheight - 20)) {
  842. paperindex = i;
  843. paperwidth = pp->x;
  844. paperheight = pp->y;
  845. orientation = DMORIENT_PORTRAIT;
  846. break;
  847. }
  848. }
  849. if (paperindex < 0) {
  850. /* try again in landscape */
  851. pp = (POINT *) devcap;
  852. for (i = 0; i < n; i++, pp++) {
  853. if ((pp->x < paperheight + 20) && (pp->x > paperheight - 20) &&
  854. (pp->y < paperwidth + 20) && (pp->y > paperwidth - 20)) {
  855. paperindex = i;
  856. paperwidth = pp->x;
  857. paperheight = pp->y;
  858. orientation = DMORIENT_LANDSCAPE;
  859. break;
  860. }
  861. }
  862. }
  863. gs_free(devcap, devcapsize, 1, "win_pr2_getdc");
  864. /* get the dmPaperSize */
  865. devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERS, NULL, NULL);
  866. devcapsize *= sizeof(WORD);
  867. if ((devcap = gs_malloc(devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
  868. return FALSE;
  869. n = pfnDeviceCapabilities(device, output, DC_PAPERS, devcap, NULL);
  870. if ((paperindex >= 0) && (paperindex < n))
  871. papersize = ((WORD *) devcap)[paperindex];
  872. gs_free(devcap, devcapsize, 1, "win_pr2_getdc");
  873. /* get the paper name */
  874. devcapsize = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, NULL, NULL);
  875. devcapsize *= 64;
  876. if ((devcap = gs_malloc(devcapsize, 1, "win_pr2_getdc")) == (LPBYTE) NULL)
  877. return FALSE;
  878. n = pfnDeviceCapabilities(device, output, DC_PAPERNAMES, devcap, NULL);
  879. if ((paperindex >= 0) && (paperindex < n))
  880. strcpy(papername, devcap + paperindex * 64);
  881. gs_free(devcap, devcapsize, 1, "win_pr2_getdc");
  882. memcpy(pidevmode, podevmode, size);
  883. pidevmode->dmFields = 0;
  884. wdev->paper_name[0] = 0;
  885. if ( (wdev->user_paper)
  886. && (wdev->user_paper != papersize) ) {
  887. papersize = wdev->user_paper;
  888. paperheight = 0;
  889. paperwidth = 0;
  890. papername[0] = 0;
  891. }
  892. if (wdev->user_orient) {
  893. orientation = wdev->user_orient;
  894. }
  895. pidevmode->dmFields &= ~(DM_PAPERSIZE | DM_ORIENTATION | DM_COLOR | DM_PAPERLENGTH | DM_PAPERWIDTH | DM_DUPLEX);
  896. pidevmode->dmFields |= DM_DEFAULTSOURCE;
  897. pidevmode->dmDefaultSource = 0;
  898. if (orientation) {
  899. wdev->user_orient = orientation;
  900. }
  901. if (papersize) {
  902. wdev->user_paper = papersize;
  903. strcpy (wdev->paper_name, papername);
  904. }
  905. if (paperheight && paperwidth) {
  906. pidevmode->dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
  907. pidevmode->dmPaperWidth = paperwidth;
  908. pidevmode->dmPaperLength = paperheight;
  909. wdev->user_media_size[0] = paperwidth / 254.0 * 72.0;
  910. wdev->user_media_size[1] = paperheight / 254.0 * 72.0;
  911. }
  912. if (DeviceCapabilities(device, output, DC_DUPLEX, NULL, NULL)) {
  913. wdev->Duplex_set = 1;
  914. }
  915. win_pr2_update_win(wdev, pidevmode);
  916. if (!is_win32s) {
  917. /* merge the entries */
  918. DocumentProperties(NULL, hprinter, device, podevmode, pidevmode, DM_IN_BUFFER | DM_OUT_BUFFER);
  919. ClosePrinter(hprinter);
  920. /* now get a DC */
  921. wdev->hdcprn = CreateDC(driver, device, NULL, podevmode);
  922. } else
  923. { /* Win16 and Win32s */
  924. pfnExtDeviceMode(NULL, hlib, podevmode, device, output,
  925. pidevmode, NULL, DM_IN_BUFFER | DM_OUT_BUFFER);
  926. /* release the printer driver */
  927. FreeLibrary(hlib);
  928. /* now get a DC */
  929. if (is_win32s)
  930. strtok(driver, "."); /* remove .drv */
  931. wdev->hdcprn = CreateDC(driver, device, output, podevmode);
  932. }
  933. if (wdev->win32_hdevmode == NULL) {
  934. wdev->win32_hdevmode = GlobalAlloc(0, sizeof(DEVMODE));
  935. }
  936. if (wdev->win32_hdevmode) {
  937. LPDEVMODE pdevmode = (LPDEVMODE) GlobalLock(GlobalLock(wdev->win32_hdevmode));
  938. if (pdevmode) {
  939. memcpy(pdevmode, podevmode, sizeof(DEVMODE));
  940. GlobalUnlock(wdev->win32_hdevmode);
  941. }
  942. }
  943. gs_free(pidevmode, size, 1, "win_pr2_getdc");
  944. gs_free(podevmode, size, 1, "win_pr2_getdc");
  945. if (wdev->hdcprn != (HDC) NULL)
  946. return TRUE; /* success */
  947. /* fall back to prompting user */
  948. return FALSE;
  949. }
  950. /*
  951. * Minimalist update of the wdev parameters (mainly for the
  952. * UserSettings parameters).
  953. */
  954. private int
  955. win_pr2_update_dev(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
  956. {
  957. if (pdevmode == 0)
  958. return FALSE;
  959. if (pdevmode->dmFields & DM_COLOR) {
  960. dev->user_color = pdevmode->dmColor;
  961. }
  962. if (pdevmode->dmFields & DM_ORIENTATION) {
  963. dev->user_orient = pdevmode->dmOrientation;
  964. }
  965. if (pdevmode->dmFields & DM_PAPERSIZE) {
  966. dev->user_paper = pdevmode->dmPaperSize;
  967. dev->user_media_size[0] = pdevmode->dmPaperWidth / 254.0 * 72.0;
  968. dev->user_media_size[1] = pdevmode->dmPaperLength / 254.0 * 72.0;
  969. dev->paper_name[0] = 0; /* unknown paper size */
  970. }
  971. if (pdevmode->dmFields & DM_DUPLEX) {
  972. dev->Duplex_set = 1;
  973. dev->Duplex = pdevmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
  974. dev->tumble = pdevmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
  975. }
  976. return TRUE;
  977. }
  978. private int
  979. win_pr2_update_win(gx_device_win_pr2 * dev, LPDEVMODE pdevmode)
  980. {
  981. if (dev->Duplex_set > 0) {
  982. pdevmode->dmFields |= DM_DUPLEX;
  983. pdevmode->dmDuplex = DMDUP_SIMPLEX;
  984. if (dev->Duplex) {
  985. if (dev->tumble == false) {
  986. pdevmode->dmDuplex = DMDUP_VERTICAL;
  987. } else {
  988. pdevmode->dmDuplex = DMDUP_HORIZONTAL;
  989. }
  990. }
  991. }
  992. if (dev->user_color) {
  993. pdevmode->dmColor = dev->user_color;
  994. pdevmode->dmFields |= DM_COLOR;
  995. }
  996. if (dev->user_orient) {
  997. pdevmode->dmFields |= DM_ORIENTATION;
  998. pdevmode->dmOrientation = dev->user_orient;
  999. }
  1000. if (dev->user_paper) {
  1001. pdevmode->dmFields |= DM_PAPERSIZE;
  1002. pdevmode->dmPaperSize = dev->user_paper;
  1003. }
  1004. return 0;
  1005. }
  1006. /********************************************************************************/
  1007. #define BEGIN_ARRAY_PARAM(pread, pname, pa, psize, e)\
  1008. switch ( code = pread(dict.list, (param_name = pname), &(pa)) )\
  1009. {\
  1010. case 0:\
  1011. if ( (pa).size != psize )\
  1012. ecode = gs_note_error(gs_error_rangecheck);\
  1013. else {
  1014. /* The body of the processing code goes here. */
  1015. /* If it succeeds, it should do a 'break'; */
  1016. /* if it fails, it should set ecode and fall through. */
  1017. #define END_ARRAY_PARAM(pa, e)\
  1018. }\
  1019. goto e;\
  1020. default:\
  1021. ecode = code;\
  1022. e: param_signal_error(dict.list, param_name, ecode);\
  1023. case 1:\
  1024. (pa).data = 0; /* mark as not filled */\
  1025. }
  1026. /* Put the user params from UserSettings into our */
  1027. /* internal variables. */
  1028. private int
  1029. win_pr2_read_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
  1030. {
  1031. gs_param_dict dict;
  1032. gs_param_string docn = { 0 };
  1033. const char* dict_name = "UserSettings";
  1034. const char* param_name = "";
  1035. int code = 0;
  1036. int ecode = 0;
  1037. switch (code = param_begin_read_dict(plist, dict_name, &dict, false)) {
  1038. default:
  1039. param_signal_error(plist, dict_name, code);
  1040. return code;
  1041. case 1:
  1042. break;
  1043. case 0:
  1044. {
  1045. gs_param_int_array ia;
  1046. BEGIN_ARRAY_PARAM(param_read_int_array, "DocumentRange", ia, 2, ia)
  1047. if ((ia.data[0] < 0) ||
  1048. (ia.data[1] < 0) ||
  1049. (ia.data[0] > ia.data[1]))
  1050. ecode = gs_note_error(gs_error_rangecheck);
  1051. wdev->doc_page_begin = ia.data[0];
  1052. wdev->doc_page_end = ia.data[1];
  1053. END_ARRAY_PARAM(ia, doc_range_error)
  1054. BEGIN_ARRAY_PARAM(param_read_int_array, "SelectedRange", ia, 2, ia)
  1055. if ((ia.data[0] < 0) ||
  1056. (ia.data[1] < 0) ||
  1057. (ia.data[0] > ia.data[1]))
  1058. ecode = gs_note_error(gs_error_rangecheck);
  1059. wdev->user_page_begin = ia.data[0];
  1060. wdev->user_page_end = ia.data[1];
  1061. END_ARRAY_PARAM(ia, sel_range_error)
  1062. param_read_int(dict.list, "Copies", &wdev->user_copies);
  1063. param_read_int(dict.list, "Paper", &wdev->user_paper);
  1064. param_read_int(dict.list, "Orientation", &wdev->user_orient);
  1065. param_read_int(dict.list, "Color", &wdev->user_color);
  1066. param_read_int(dict.list, "MaxResolution", &wdev->max_dpi);
  1067. switch (code = param_read_string(dict.list, (param_name = "DocumentName"), &docn)) {
  1068. case 0:
  1069. if (docn.size < sizeof(wdev->doc_name))
  1070. break;
  1071. code = gs_error_rangecheck;
  1072. /* fall through */
  1073. default:
  1074. ecode = code;
  1075. param_signal_error(plist, param_name, ecode);
  1076. /* fall through */
  1077. case 1:
  1078. docn.data = 0;
  1079. break;
  1080. }
  1081. param_end_read_dict(plist, dict_name, &dict);
  1082. if (docn.data) {
  1083. memcpy(wdev->doc_name, docn.data, docn.size);
  1084. wdev->doc_name[docn.size] = 0;
  1085. }
  1086. wdev->print_copies = 1;
  1087. if (wdev->win32_hdevmode) {
  1088. LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
  1089. if (devmode) {
  1090. devmode->dmCopies = wdev->user_copies;
  1091. devmode->dmPaperSize = wdev->user_paper;
  1092. devmode->dmOrientation = wdev->user_orient;
  1093. devmode->dmColor = wdev->user_color;
  1094. GlobalUnlock(wdev->win32_hdevmode);
  1095. }
  1096. }
  1097. }
  1098. break;
  1099. }
  1100. return code;
  1101. }
  1102. private int
  1103. win_pr2_write_user_settings(gx_device_win_pr2 * wdev, gs_param_list * plist)
  1104. {
  1105. gs_param_dict dict;
  1106. gs_param_int_array range;
  1107. gs_param_float_array box;
  1108. gs_param_string docn;
  1109. gs_param_string papn;
  1110. int array[2];
  1111. const char* pname = "UserSettings";
  1112. int code;
  1113. dict.size = 12;
  1114. code = param_begin_write_dict(plist, pname, &dict, false);
  1115. if (code < 0) return code;
  1116. array[0] = wdev->doc_page_begin;
  1117. array[1] = wdev->doc_page_end;
  1118. range.data = array;
  1119. range.size = 2;
  1120. range.persistent = false;
  1121. code = param_write_int_array(dict.list, "DocumentRange", &range);
  1122. if (code < 0) goto error;
  1123. array[0] = wdev->user_page_begin;
  1124. array[1] = wdev->user_page_end;
  1125. range.data = array;
  1126. range.size = 2;
  1127. range.persistent = false;
  1128. code = param_write_int_array(dict.list, "SelectedRange", &range);
  1129. if (code < 0) goto error;
  1130. box.data = wdev->user_media_size;
  1131. box.size = 2;
  1132. box.persistent = false;
  1133. code = param_write_float_array(dict.list, "MediaSize", &box);
  1134. if (code < 0) goto error;
  1135. code = param_write_int(dict.list, "Copies", &wdev->user_copies);
  1136. if (code < 0) goto error;
  1137. code = param_write_int(dict.list, "Paper", &wdev->user_paper);
  1138. if (code < 0) goto error;
  1139. code = param_write_int(dict.list, "Orientation", &wdev->user_orient);
  1140. if (code < 0) goto error;
  1141. code = param_write_int(dict.list, "Color", &wdev->user_color);
  1142. if (code < 0) goto error;
  1143. code = param_write_int(dict.list, "MaxResolution", &wdev->max_dpi);
  1144. if (code < 0) goto error;
  1145. code = param_write_int(dict.list, "PrintCopies", &wdev->print_copies);
  1146. if (code < 0) goto error;
  1147. docn.data = (const byte*)wdev->doc_name;
  1148. docn.size = strlen(wdev->doc_name);
  1149. docn.persistent = false;
  1150. code = param_write_string(dict.list, "DocumentName", &docn);
  1151. if (code < 0) goto error;
  1152. papn.data = (const byte*)wdev->paper_name;
  1153. papn.size = strlen(wdev->paper_name);
  1154. papn.persistent = false;
  1155. code = param_write_string(dict.list, "PaperName", &papn);
  1156. if (code < 0) goto error;
  1157. code = param_write_bool(dict.list, "UserChangedSettings", &wdev->user_changed_settings);
  1158. error:
  1159. param_end_write_dict(plist, pname, &dict);
  1160. return code;
  1161. }
  1162. /********************************************************************************/
  1163. /* Show up a dialog for the user to choose a printer and a paper size.
  1164. * If mode == 3, then automatically select the default Windows printer
  1165. * instead of asking the user.
  1166. */
  1167. private int
  1168. win_pr2_print_setup_interaction(gx_device_win_pr2 * wdev, int mode)
  1169. {
  1170. PRINTDLG pd;
  1171. LPDEVMODE devmode;
  1172. LPDEVNAMES devnames;
  1173. wdev->user_changed_settings = FALSE;
  1174. wdev->query_user = mode;
  1175. memset(&pd, 0, sizeof(pd));
  1176. pd.lStructSize = sizeof(pd);
  1177. pd.hwndOwner = PARENT_WINDOW;
  1178. switch (mode) {
  1179. case 2: pd.Flags = PD_PRINTSETUP; break;
  1180. case 3: pd.Flags = PD_RETURNDEFAULT; break;
  1181. default: pd.Flags = 0; break;
  1182. }
  1183. pd.Flags |= PD_USEDEVMODECOPIES;
  1184. pd.nMinPage = wdev->doc_page_begin;
  1185. pd.nMaxPage = wdev->doc_page_end;
  1186. pd.nFromPage = wdev->user_page_begin;
  1187. pd.nToPage = wdev->user_page_end;
  1188. pd.nCopies = wdev->user_copies;
  1189. /* Show the Print Setup dialog and let the user choose a printer
  1190. * and a paper size/orientation.
  1191. */
  1192. if (!PrintDlg(&pd)) return FALSE;
  1193. devmode = (LPDEVMODE) GlobalLock(pd.hDevMode);
  1194. devnames = (LPDEVNAMES) GlobalLock(pd.hDevNames);
  1195. wdev->user_changed_settings = TRUE;
  1196. if (wdev->use_old_spool_name) {
  1197. sprintf(wdev->fname, "\\\\spool\\%s", (char*)(devnames)+(devnames->wDeviceOffset));
  1198. } else {
  1199. sprintf(wdev->fname, "%%printer%%%s", (char*)(devnames)+(devnames->wDeviceOffset));
  1200. }
  1201. if (mode == 3) {
  1202. devmode->dmCopies = wdev->user_copies * wdev->print_copies;
  1203. pd.nCopies = 1;
  1204. }
  1205. wdev->user_page_begin = pd.nFromPage;
  1206. wdev->user_page_end = pd.nToPage;
  1207. wdev->user_copies = devmode->dmCopies;
  1208. wdev->print_copies = pd.nCopies;
  1209. wdev->user_media_size[0] = devmode->dmPaperWidth / 254.0 * 72.0;
  1210. wdev->user_media_size[1] = devmode->dmPaperLength / 254.0 * 72.0;
  1211. wdev->user_paper = devmode->dmPaperSize;
  1212. wdev->user_orient = devmode->dmOrientation;
  1213. wdev->user_color = devmode->dmColor;
  1214. if (devmode->dmFields & DM_DUPLEX) {
  1215. wdev->Duplex_set = 1;
  1216. wdev->Duplex = devmode->dmDuplex == DMDUP_SIMPLEX ? false : true;
  1217. wdev->tumble = devmode->dmDuplex == DMDUP_HORIZONTAL ? true : false;
  1218. }
  1219. {
  1220. float xppinch = 0;
  1221. float yppinch = 0;
  1222. const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
  1223. const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
  1224. const char* output = (char*)(devnames)+(devnames->wOutputOffset);
  1225. HDC hic = CreateIC(driver, device, output, devmode);
  1226. if (hic) {
  1227. xppinch = (float)GetDeviceCaps(hic, LOGPIXELSX);
  1228. yppinch = (float)GetDeviceCaps(hic, LOGPIXELSY);
  1229. wdev->user_media_size[0] = GetDeviceCaps(hic, PHYSICALWIDTH) * 72.0 / xppinch;
  1230. wdev->user_media_size[1] = GetDeviceCaps(hic, PHYSICALHEIGHT) * 72.0 / yppinch;
  1231. DeleteDC(hic);
  1232. }
  1233. }
  1234. devmode = NULL;
  1235. devnames = NULL;
  1236. GlobalUnlock(pd.hDevMode);
  1237. GlobalUnlock(pd.hDevNames);
  1238. if (wdev->win32_hdevmode != NULL) {
  1239. GlobalFree(wdev->win32_hdevmode);
  1240. }
  1241. if (wdev->win32_hdevnames != NULL) {
  1242. GlobalFree(wdev->win32_hdevnames);
  1243. }
  1244. wdev->win32_hdevmode = pd.hDevMode;
  1245. wdev->win32_hdevnames = pd.hDevNames;
  1246. return TRUE;
  1247. }
  1248. /* Check that we are dealing with an original device. If this
  1249. * happens to be a copy made by "copydevice", we will have to
  1250. * copy the original's handles to the associated Win32 params.
  1251. */
  1252. private void
  1253. win_pr2_copy_check(gx_device_win_pr2 * wdev)
  1254. {
  1255. HGLOBAL hdevmode = wdev->win32_hdevmode;
  1256. HGLOBAL hdevnames = wdev->win32_hdevnames;
  1257. DWORD devmode_len = (hdevmode) ? GlobalSize(hdevmode) : 0;
  1258. DWORD devnames_len = (hdevnames) ? GlobalSize(hdevnames) : 0;
  1259. if (wdev->original_device == wdev)
  1260. return;
  1261. wdev->hdcprn = NULL;
  1262. wdev->win32_hdevmode = NULL;
  1263. wdev->win32_hdevnames = NULL;
  1264. wdev->original_device = wdev;
  1265. if (devmode_len) {
  1266. wdev->win32_hdevmode = GlobalAlloc(0, devmode_len);
  1267. if (wdev->win32_hdevmode) {
  1268. memcpy(GlobalLock(wdev->win32_hdevmode), GlobalLock(hdevmode), devmode_len);
  1269. GlobalUnlock(wdev->win32_hdevmode);
  1270. GlobalUnlock(hdevmode);
  1271. }
  1272. }
  1273. if (devnames_len) {
  1274. wdev->win32_hdevnames = GlobalAlloc(0, devnames_len);
  1275. if (wdev->win32_hdevnames) {
  1276. memcpy(GlobalLock(wdev->win32_hdevnames), GlobalLock(hdevnames), devnames_len);
  1277. GlobalUnlock(wdev->win32_hdevnames);
  1278. GlobalUnlock(hdevnames);
  1279. }
  1280. }
  1281. }
  1282. /* Modeless dialog box - Cancel printing */
  1283. BOOL CALLBACK
  1284. CancelDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1285. {
  1286. switch (message) {
  1287. case WM_INITDIALOG:
  1288. SetWindowText(hDlg, szAppName);
  1289. return TRUE;
  1290. case WM_COMMAND:
  1291. switch (LOWORD(wParam)) {
  1292. case IDCANCEL:
  1293. DestroyWindow(hDlg);
  1294. EndDialog(hDlg, 0);
  1295. return TRUE;
  1296. }
  1297. }
  1298. return FALSE;
  1299. }
  1300. BOOL CALLBACK
  1301. AbortProc2(HDC hdcPrn, int code)
  1302. {
  1303. process_interrupts();
  1304. if (code == SP_OUTOFDISK)
  1305. return (FALSE); /* cancel job */
  1306. return (TRUE);
  1307. }