Mercurial > hg > xemacs-beta
comparison src/device-msw.c @ 410:de805c49cfc1 r21-2-35
Import from CVS: tag r21-2-35
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:19:21 +0200 |
parents | 501cfd01ee6d |
children | 697ef44129c6 |
comparison
equal
deleted
inserted
replaced
409:301b9ebbdf3b | 410:de805c49cfc1 |
---|---|
38 #include "events.h" | 38 #include "events.h" |
39 #include "faces.h" | 39 #include "faces.h" |
40 #include "frame.h" | 40 #include "frame.h" |
41 #include "sysdep.h" | 41 #include "sysdep.h" |
42 | 42 |
43 #if !(defined (__CYGWIN32__) || defined(__MINGW32__)) | 43 /* #### Andy, these includes might break cygwin compilation - kkm*/ |
44 #include <commdlg.h> | |
45 #include <winspool.h> | |
46 | |
47 #if !(defined (CYGWIN) || defined(MINGW)) | |
44 # include <objbase.h> /* For CoInitialize */ | 48 # include <objbase.h> /* For CoInitialize */ |
45 #endif | 49 #endif |
46 | 50 |
47 /* win32 DDE management library globals */ | 51 /* win32 DDE management library globals */ |
48 #ifdef HAVE_DRAGNDROP | 52 #ifdef HAVE_DRAGNDROP |
60 exactly, at the expense of slower operation. Since true hard links | 64 exactly, at the expense of slower operation. Since true hard links |
61 are supported on NTFS volumes, this is only relevant on NT. */ | 65 are supported on NTFS volumes, this is only relevant on NT. */ |
62 Lisp_Object Vmswindows_get_true_file_attributes; | 66 Lisp_Object Vmswindows_get_true_file_attributes; |
63 | 67 |
64 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win; | 68 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win; |
65 | 69 Lisp_Object Qdevmodep; |
70 | |
71 static Lisp_Object allocate_devmode (DEVMODE* src_devmode, int do_copy, | |
72 char* src_name, struct device *d); | |
66 | 73 |
67 /************************************************************************/ | 74 /************************************************************************/ |
68 /* helpers */ | 75 /* helpers */ |
69 /************************************************************************/ | 76 /************************************************************************/ |
70 | 77 |
97 { | 104 { |
98 return Fcons (index1 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index1)), | 105 return Fcons (index1 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index1)), |
99 index2 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index2))); | 106 index2 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index2))); |
100 } | 107 } |
101 | 108 |
102 | |
103 | 109 |
104 /************************************************************************/ | 110 /************************************************************************/ |
105 /* display methods */ | 111 /* display methods */ |
106 /************************************************************************/ | 112 /************************************************************************/ |
107 | 113 |
117 init_one_device (d); | 123 init_one_device (d); |
118 | 124 |
119 d->device_data = xnew_and_zero (struct mswindows_device); | 125 d->device_data = xnew_and_zero (struct mswindows_device); |
120 hdc = CreateCompatibleDC (NULL); | 126 hdc = CreateCompatibleDC (NULL); |
121 assert (hdc!=NULL); | 127 assert (hdc!=NULL); |
122 DEVICE_MSWINDOWS_LOGPIXELSX(d) = GetDeviceCaps(hdc, LOGPIXELSX); | 128 DEVICE_MSWINDOWS_HCDC(d) = hdc; |
123 DEVICE_MSWINDOWS_LOGPIXELSY(d) = GetDeviceCaps(hdc, LOGPIXELSY); | |
124 DEVICE_MSWINDOWS_PLANES(d) = GetDeviceCaps(hdc, PLANES); | |
125 /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS, | |
126 what should we return for a non-palette-based device? */ | |
127 DEVICE_MSWINDOWS_CELLS(d) = GetDeviceCaps(hdc, SIZEPALETTE); | |
128 DEVICE_MSWINDOWS_HORZRES(d) = GetDeviceCaps(hdc, HORZRES); | |
129 DEVICE_MSWINDOWS_VERTRES(d) = GetDeviceCaps(hdc, VERTRES); | |
130 DEVICE_MSWINDOWS_HORZSIZE(d) = GetDeviceCaps(hdc, HORZSIZE); | |
131 DEVICE_MSWINDOWS_VERTSIZE(d) = GetDeviceCaps(hdc, VERTSIZE); | |
132 DEVICE_MSWINDOWS_BITSPIXEL(d) = GetDeviceCaps(hdc, BITSPIXEL); | |
133 DEVICE_MSWINDOWS_FONTLIST (d) = mswindows_enumerate_fonts (hdc); | 129 DEVICE_MSWINDOWS_FONTLIST (d) = mswindows_enumerate_fonts (hdc); |
134 | 130 DEVICE_MSWINDOWS_UPDATE_TICK (d) = GetTickCount (); |
135 DEVICE_MSWINDOWS_HCDC(d) = hdc; | |
136 | 131 |
137 /* Register the main window class */ | 132 /* Register the main window class */ |
138 wc.cbSize = sizeof (WNDCLASSEX); | 133 wc.cbSize = sizeof (WNDCLASSEX); |
139 wc.style = CS_OWNDC; /* One DC per window */ | 134 wc.style = CS_OWNDC; /* One DC per window */ |
140 wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc; | 135 wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc; |
174 mswindows_finish_init_device (struct device *d, Lisp_Object props) | 169 mswindows_finish_init_device (struct device *d, Lisp_Object props) |
175 { | 170 { |
176 /* Initialize DDE management library and our related globals. We execute a | 171 /* Initialize DDE management library and our related globals. We execute a |
177 * dde Open("file") by simulating a drop, so this depends on dnd support. */ | 172 * dde Open("file") by simulating a drop, so this depends on dnd support. */ |
178 #ifdef HAVE_DRAGNDROP | 173 #ifdef HAVE_DRAGNDROP |
179 # if !(defined(__CYGWIN32__) || defined(__MINGW32__)) | 174 # if !(defined(CYGWIN) || defined(MINGW)) |
180 CoInitialize (NULL); | 175 CoInitialize (NULL); |
181 # endif | 176 # endif |
182 | 177 |
183 mswindows_dde_mlid = 0; | 178 mswindows_dde_mlid = 0; |
184 DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback, | 179 DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback, |
204 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_item_open); | 199 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_item_open); |
205 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_topic_system); | 200 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_topic_system); |
206 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_service); | 201 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_service); |
207 DdeUninitialize (mswindows_dde_mlid); | 202 DdeUninitialize (mswindows_dde_mlid); |
208 | 203 |
209 # if !(defined(__CYGWIN32__) || defined(__MINGW32__)) | 204 # if !(defined(CYGWIN) || defined(MINGW)) |
210 CoUninitialize (); | 205 CoUninitialize (); |
211 # endif | 206 # endif |
212 #endif | 207 #endif |
213 | 208 |
214 DeleteDC (DEVICE_MSWINDOWS_HCDC(d)); | 209 DeleteDC (DEVICE_MSWINDOWS_HCDC(d)); |
215 free (d->device_data); | 210 xfree (d->device_data); |
216 } | 211 } |
217 | 212 |
218 void | 213 void |
219 msw_get_workspace_coords (RECT *rc) | 214 mswindows_get_workspace_coords (RECT *rc) |
220 { | 215 { |
221 SystemParametersInfo (SPI_GETWORKAREA, 0, rc, 0); | 216 SystemParametersInfo (SPI_GETWORKAREA, 0, rc, 0); |
222 } | 217 } |
223 | 218 |
224 static void | 219 static void |
229 | 224 |
230 static Lisp_Object | 225 static Lisp_Object |
231 mswindows_device_system_metrics (struct device *d, | 226 mswindows_device_system_metrics (struct device *d, |
232 enum device_metrics m) | 227 enum device_metrics m) |
233 { | 228 { |
229 const HDC hdc = DEVICE_MSWINDOWS_HCDC(d); | |
230 | |
234 switch (m) | 231 switch (m) |
235 { | 232 { |
236 case DM_size_device: | 233 case DM_size_device: |
237 return Fcons (make_int (DEVICE_MSWINDOWS_HORZRES(d)), | 234 return Fcons (make_int (GetDeviceCaps (hdc, HORZRES)), |
238 make_int (DEVICE_MSWINDOWS_VERTRES(d))); | 235 make_int (GetDeviceCaps (hdc, VERTRES))); |
239 break; | 236 break; |
240 case DM_device_dpi: | 237 case DM_device_dpi: |
241 return Fcons (make_int (DEVICE_MSWINDOWS_LOGPIXELSX(d)), | 238 return Fcons (make_int (GetDeviceCaps (hdc, LOGPIXELSX)), |
242 make_int (DEVICE_MSWINDOWS_LOGPIXELSY(d))); | 239 make_int (GetDeviceCaps (hdc, LOGPIXELSY))); |
243 break; | 240 break; |
244 case DM_size_device_mm: | 241 case DM_size_device_mm: |
245 return Fcons (make_int (DEVICE_MSWINDOWS_HORZSIZE(d)), | 242 return Fcons (make_int (GetDeviceCaps (hdc, HORZSIZE)), |
246 make_int (DEVICE_MSWINDOWS_VERTSIZE(d))); | 243 make_int (GetDeviceCaps (hdc, VERTSIZE))); |
247 break; | 244 break; |
248 case DM_num_bit_planes: | 245 case DM_num_bit_planes: |
249 /* this is what X means by bitplanes therefore we ought to be | 246 /* this is what X means by bitplanes therefore we ought to be |
250 consistent. num planes is always 1 under mswindows and | 247 consistent. num planes is always 1 under mswindows and |
251 therefore useless */ | 248 therefore useless */ |
252 return make_int (DEVICE_MSWINDOWS_BITSPIXEL(d)); | 249 return make_int (GetDeviceCaps (hdc, BITSPIXEL)); |
253 break; | 250 break; |
254 case DM_num_color_cells: | 251 case DM_num_color_cells: |
255 return make_int (DEVICE_MSWINDOWS_CELLS(d)); | 252 /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS, |
253 what should we return for a non-palette-based device? */ | |
254 return make_int (GetDeviceCaps (hdc, SIZEPALETTE)); | |
256 break; | 255 break; |
257 | 256 |
258 /*** Colors ***/ | 257 /*** Colors ***/ |
259 #define FROB(met, fore, back) \ | 258 #define FROB(met, fore, back) \ |
260 case DM_##met: \ | 259 case DM_##met: \ |
289 #undef FROB | 288 #undef FROB |
290 | 289 |
291 case DM_size_workspace: | 290 case DM_size_workspace: |
292 { | 291 { |
293 RECT rc; | 292 RECT rc; |
294 msw_get_workspace_coords (&rc); | 293 mswindows_get_workspace_coords (&rc); |
295 return Fcons (make_int (rc.right - rc.left), | 294 return Fcons (make_int (rc.right - rc.left), |
296 make_int (rc.bottom - rc.top)); | 295 make_int (rc.bottom - rc.top)); |
297 } | 296 } |
298 | 297 |
299 case DM_offset_workspace: | 298 case DM_offset_workspace: |
300 { | 299 { |
301 RECT rc; | 300 RECT rc; |
302 msw_get_workspace_coords (&rc); | 301 mswindows_get_workspace_coords (&rc); |
303 return Fcons (make_int (rc.left), make_int (rc.top)); | 302 return Fcons (make_int (rc.left), make_int (rc.top)); |
304 } | 303 } |
305 | 304 |
306 /* | 305 /* |
307 case DM_size_toolbar: | 306 case DM_size_toolbar: |
333 return XDEVIMPF_PIXEL_GEOMETRY; | 332 return XDEVIMPF_PIXEL_GEOMETRY; |
334 } | 333 } |
335 | 334 |
336 | 335 |
337 /************************************************************************/ | 336 /************************************************************************/ |
338 /* printer methods */ | 337 /* printer helpers */ |
339 /************************************************************************/ | 338 /************************************************************************/ |
340 | 339 |
341 static void | 340 static void |
342 signal_open_printer_error (struct device *d) | 341 signal_open_printer_error (struct device *d) |
343 { | 342 { |
344 signal_simple_error ("Failed to open printer", DEVICE_CONNECTION (d)); | 343 signal_simple_error ("Failed to open printer", DEVICE_CONNECTION (d)); |
345 } | 344 } |
346 | 345 |
347 static void | 346 |
348 msprinter_init_device (struct device *d, Lisp_Object props) | 347 /* Helper function */ |
349 { | 348 static int |
350 char* printer_name; | 349 msprinter_init_device_internal (struct device *d, char* printer_name) |
351 | 350 { |
352 DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1; | |
353 | |
354 CHECK_STRING (DEVICE_CONNECTION (d)); | |
355 | |
356 TO_EXTERNAL_FORMAT (LISP_STRING, DEVICE_CONNECTION (d), | |
357 C_STRING_ALLOCA, printer_name, | |
358 Qctext); | |
359 | |
360 d->device_data = xnew_and_zero (struct msprinter_device); | |
361 | |
362 DEVICE_MSPRINTER_NAME(d) = xstrdup (printer_name); | 351 DEVICE_MSPRINTER_NAME(d) = xstrdup (printer_name); |
363 | 352 |
364 if (!OpenPrinter (printer_name, &DEVICE_MSPRINTER_HPRINTER (d), NULL)) | 353 if (!OpenPrinter (printer_name, &DEVICE_MSPRINTER_HPRINTER (d), NULL)) |
365 { | 354 { |
366 DEVICE_MSPRINTER_HPRINTER (d) = NULL; | 355 DEVICE_MSPRINTER_HPRINTER (d) = NULL; |
367 signal_open_printer_error (d); | 356 return 0; |
368 } | 357 } |
369 | 358 |
370 DEVICE_MSPRINTER_HDC (d) = CreateDC ("WINSPOOL", printer_name, | 359 DEVICE_MSPRINTER_HDC (d) = CreateDC ("WINSPOOL", printer_name, |
371 NULL, NULL); | 360 NULL, NULL); |
372 if (DEVICE_MSPRINTER_HDC (d) == NULL) | 361 if (DEVICE_MSPRINTER_HDC (d) == NULL) |
373 signal_open_printer_error (d); | 362 return 0; |
374 | 363 |
375 DEVICE_MSPRINTER_HCDC(d) = | 364 DEVICE_MSPRINTER_HCDC(d) = |
376 CreateCompatibleDC (DEVICE_MSPRINTER_HDC (d)); | 365 CreateCompatibleDC (DEVICE_MSPRINTER_HDC (d)); |
377 | 366 |
378 /* Determinie DEVMODE size and store the default DEVMODE */ | 367 DEVICE_CLASS (d) = (GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), BITSPIXEL) |
379 DEVICE_MSPRINTER_DEVMODE_SIZE(d) = | 368 * GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), PLANES) |
380 DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d), | 369 > 1) ? Qcolor : Qmono; |
381 printer_name, NULL, NULL, 0); | 370 return 1; |
382 if (DEVICE_MSPRINTER_DEVMODE_SIZE(d) <= 0) | 371 } |
383 signal_open_printer_error (d); | 372 |
384 | 373 static void |
385 DEVICE_MSPRINTER_DEVMODE(d) = | 374 msprinter_delete_device_internal (struct device *d) |
386 (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d)); | 375 { |
387 DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d), | 376 if (DEVICE_MSPRINTER_HPRINTER (d)) |
388 printer_name, DEVICE_MSPRINTER_DEVMODE(d), | 377 ClosePrinter (DEVICE_MSPRINTER_HPRINTER (d)); |
389 NULL, DM_OUT_BUFFER); | 378 if (DEVICE_MSPRINTER_HDC (d)) |
379 DeleteDC (DEVICE_MSPRINTER_HDC (d)); | |
380 if (DEVICE_MSPRINTER_HCDC (d)) | |
381 DeleteDC (DEVICE_MSPRINTER_HCDC (d)); | |
382 if (DEVICE_MSPRINTER_NAME (d)) | |
383 xfree (DEVICE_MSPRINTER_NAME (d)); | |
384 | |
385 DEVICE_MSPRINTER_FONTLIST (d) = Qnil; | |
386 } | |
387 | |
388 static int msprinter_reinit_device (struct device *d, char* devname) | |
389 { | |
390 msprinter_delete_device_internal (d); | |
391 return msprinter_init_device_internal (d, devname); | |
392 } | |
393 | |
394 | |
395 /************************************************************************/ | |
396 /* printer methods */ | |
397 /************************************************************************/ | |
398 | |
399 static void | |
400 msprinter_init_device (struct device *d, Lisp_Object props) | |
401 { | |
402 char* printer_name; | |
403 DEVMODE *pdm; | |
404 size_t dm_size; | |
405 | |
406 d->device_data = xnew_and_zero (struct msprinter_device); | |
407 | |
408 DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1; | |
409 DEVICE_MSPRINTER_DEVMODE(d) = Qnil; | |
390 | 410 |
391 /* We do not use printer fon list as we do with the display | 411 /* We do not use printer fon list as we do with the display |
392 device. Rather, we allow GDI to pick the closest match to the | 412 device. Rather, we allow GDI to pick the closest match to the |
393 display font. */ | 413 display font. */ |
394 DEVICE_MSPRINTER_FONTLIST (d) = Qnil; | 414 DEVICE_MSPRINTER_FONTLIST (d) = Qnil; |
395 | 415 |
396 DEVICE_CLASS (d) = (GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), BITSPIXEL) | 416 CHECK_STRING (DEVICE_CONNECTION (d)); |
397 * GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), PLANES) | 417 |
398 > 1) ? Qcolor : Qmono; | 418 TO_EXTERNAL_FORMAT (LISP_STRING, DEVICE_CONNECTION (d), |
419 C_STRING_ALLOCA, printer_name, | |
420 Qmswindows_tstr); | |
421 | |
422 if (!msprinter_init_device_internal (d, printer_name)) | |
423 signal_open_printer_error (d); | |
424 | |
425 /* Determinie DEVMODE size and store the default DEVMODE */ | |
426 dm_size = DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d), | |
427 printer_name, NULL, NULL, 0); | |
428 if (dm_size <= 0) | |
429 signal_open_printer_error (d); | |
430 | |
431 pdm = (DEVMODE*) xmalloc (dm_size); | |
432 DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d), | |
433 printer_name, pdm, | |
434 NULL, DM_OUT_BUFFER); | |
435 | |
436 assert (DEVMODE_SIZE (pdm) <= dm_size); | |
437 | |
438 DEVICE_MSPRINTER_DEVMODE(d) = | |
439 allocate_devmode (pdm, 0, printer_name, d); | |
440 | |
441 } | |
442 | |
443 static void | |
444 msprinter_delete_device (struct device *d) | |
445 { | |
446 if (d->device_data) | |
447 { | |
448 msprinter_delete_device_internal (d); | |
449 | |
450 /* Disassociate the selected devmode with the device */ | |
451 if (!NILP (DEVICE_MSPRINTER_DEVMODE (d))) | |
452 { | |
453 XDEVMODE (DEVICE_MSPRINTER_DEVMODE (d))->device = Qnil; | |
454 DEVICE_MSPRINTER_DEVMODE (d) = Qnil; | |
455 } | |
456 | |
457 xfree (d->device_data); | |
458 } | |
399 } | 459 } |
400 | 460 |
401 static Lisp_Object | 461 static Lisp_Object |
402 msprinter_device_system_metrics (struct device *d, | 462 msprinter_device_system_metrics (struct device *d, |
403 enum device_metrics m) | 463 enum device_metrics m) |
432 /* Do not know such property */ | 492 /* Do not know such property */ |
433 return Qunbound; | 493 return Qunbound; |
434 } | 494 } |
435 | 495 |
436 static void | 496 static void |
437 msprinter_delete_device (struct device *d) | |
438 { | |
439 if (d->device_data) | |
440 { | |
441 if (DEVICE_MSPRINTER_HPRINTER (d)) | |
442 ClosePrinter (DEVICE_MSPRINTER_HPRINTER (d)); | |
443 if (DEVICE_MSPRINTER_HDC (d)) | |
444 DeleteDC (DEVICE_MSPRINTER_HDC (d)); | |
445 if (DEVICE_MSPRINTER_HCDC (d)) | |
446 DeleteDC (DEVICE_MSPRINTER_HCDC (d)); | |
447 if (DEVICE_MSPRINTER_NAME (d)) | |
448 free (DEVICE_MSPRINTER_NAME (d)); | |
449 if (DEVICE_MSPRINTER_DEVMODE (d)) | |
450 free (DEVICE_MSPRINTER_DEVMODE (d)); | |
451 if (DEVICE_MSPRINTER_DEVMODE_MIRROR (d)) | |
452 free (DEVICE_MSPRINTER_DEVMODE_MIRROR (d)); | |
453 | |
454 free (d->device_data); | |
455 } | |
456 } | |
457 | |
458 static void | |
459 msprinter_mark_device (struct device *d) | 497 msprinter_mark_device (struct device *d) |
460 { | 498 { |
461 mark_object (DEVICE_MSPRINTER_FONTLIST (d)); | 499 mark_object (DEVICE_MSPRINTER_FONTLIST (d)); |
500 mark_object (DEVICE_MSPRINTER_DEVMODE (d)); | |
462 } | 501 } |
463 | 502 |
464 static unsigned int | 503 static unsigned int |
465 msprinter_device_implementation_flags (void) | 504 msprinter_device_implementation_flags (void) |
466 { | 505 { |
467 return ( XDEVIMPF_PIXEL_GEOMETRY | 506 return ( XDEVIMPF_PIXEL_GEOMETRY |
468 | XDEVIMPF_IS_A_PRINTER | 507 | XDEVIMPF_IS_A_PRINTER |
469 | XDEVIMPF_NO_AUTO_REDISPLAY | 508 | XDEVIMPF_NO_AUTO_REDISPLAY |
470 | XDEVIMPF_FRAMELESS_OK ); | 509 | XDEVIMPF_FRAMELESS_OK ); |
471 } | 510 } |
472 | |
473 | 511 |
474 /************************************************************************/ | 512 /************************************************************************/ |
475 /* printer external functions */ | 513 /* printer Lisp subroutines */ |
476 /************************************************************************/ | 514 /************************************************************************/ |
477 | 515 |
478 /* | 516 static void |
479 * Return a copy of default DEVMODE. The copy returned is in | 517 global_free_2_maybe (HGLOBAL hg1, HGLOBAL hg2) |
480 * a static buffer which will be overwritten by next call. | 518 { |
481 */ | 519 if (hg1 != NULL) |
482 DEVMODE* | 520 GlobalFree (hg1); |
483 msprinter_get_devmode_copy (struct device *d) | 521 if (hg2 != NULL) |
484 { | 522 GlobalFree (hg2); |
485 assert (DEVICE_MSPRINTER_P (d)); | 523 } |
486 | 524 |
487 if (DEVICE_MSPRINTER_DEVMODE_MIRROR(d) == NULL) | 525 static HGLOBAL |
488 DEVICE_MSPRINTER_DEVMODE_MIRROR(d) = | 526 devmode_to_hglobal (Lisp_Devmode *ldm) |
489 (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d)); | 527 { |
490 | 528 HGLOBAL hg = GlobalAlloc (GHND, XDEVMODE_SIZE (ldm)); |
491 memcpy (DEVICE_MSPRINTER_DEVMODE_MIRROR(d), | 529 memcpy (GlobalLock (hg), ldm->devmode, XDEVMODE_SIZE (ldm)); |
492 DEVICE_MSPRINTER_DEVMODE(d), | 530 GlobalUnlock (hg); |
493 DEVICE_MSPRINTER_DEVMODE_SIZE(d)); | 531 return hg; |
494 | 532 } |
495 return DEVICE_MSPRINTER_DEVMODE_MIRROR(d); | 533 |
496 } | 534 /* Returns 0 if the printer has been deleted due to a fatal I/O error, |
497 | 535 1 otherwise. */ |
498 /* | 536 static int |
499 * Apply settings from the DEVMODE. The settings are considered | 537 sync_printer_with_devmode (struct device* d, DEVMODE* devmode_in, |
500 * incremental to the default DEVMODE, so that changes in the | 538 DEVMODE* devmode_out, char* devname) |
501 * passed structure supercede parameters of the printer. | 539 { |
502 * | 540 /* Change connection if the device changed */ |
503 * The passed structure is overwritten by the fuction call; | 541 if (devname != NULL |
504 * complete printer settings are returned. | 542 && stricmp (devname, DEVICE_MSPRINTER_NAME(d)) != 0) |
505 */ | 543 { |
506 void | 544 Lisp_Object new_connection = build_ext_string (devname, Qmswindows_tstr); |
507 msprinter_apply_devmode (struct device *d, DEVMODE *devmode) | 545 struct gcpro gcpro1; |
508 { | 546 |
509 assert (DEVICE_MSPRINTER_P (d)); | 547 GCPRO1 (new_connection); |
510 | 548 DEVICE_CONNECTION (d) = Qnil; |
549 if (!NILP (Ffind_device (new_connection, Qmsprinter))) | |
550 { | |
551 /* We are in trouble - second msprinter for the same device. | |
552 Nothing wrong on the Windows side, just forge a unique | |
553 connection name. Use the memory address of d as a unique | |
554 suffix. */ | |
555 char* new_connext = alloca (strlen (devname + 11)); | |
556 sprintf (new_connext, "%s:%X", devname, d->header.uid); | |
557 new_connection = build_ext_string (devname, Qmswindows_tstr); | |
558 } | |
559 DEVICE_CONNECTION (d) = new_connection; | |
560 UNGCPRO; | |
561 | |
562 /* Reinitialize printer. The device can pop off in process */ | |
563 if (!msprinter_reinit_device (d, devname)) | |
564 { | |
565 /* Kaboom! */ | |
566 delete_device_internal (d, 1, 0, 1); | |
567 return 0; | |
568 } | |
569 } | |
570 | |
571 /* Apply the new devmode to the printer */ | |
511 DocumentProperties (NULL, | 572 DocumentProperties (NULL, |
512 DEVICE_MSPRINTER_HPRINTER(d), | 573 DEVICE_MSPRINTER_HPRINTER(d), |
513 DEVICE_MSPRINTER_NAME(d), | 574 DEVICE_MSPRINTER_NAME(d), |
514 devmode, devmode, | 575 devmode_out, devmode_in, |
515 DM_IN_BUFFER | DM_OUT_BUFFER); | 576 DM_IN_BUFFER | DM_OUT_BUFFER); |
516 | 577 |
517 /* #### ResetDC fails sometimes, Bill only know s why. | 578 /* #### ResetDC fails sometimes, Bill only knows why. |
518 The solution below looks more like a workaround to me, | 579 The solution below looks more like a workaround to me, |
519 although it might be fine. --kkm */ | 580 although it might be fine. --kkm */ |
520 if (ResetDC (DEVICE_MSPRINTER_HDC (d), devmode) == NULL) | 581 if (ResetDC (DEVICE_MSPRINTER_HDC (d), devmode_out) == NULL) |
521 { | 582 { |
522 DeleteDC (DEVICE_MSPRINTER_HDC (d)); | 583 DeleteDC (DEVICE_MSPRINTER_HDC (d)); |
523 DEVICE_MSPRINTER_HDC (d) = | 584 DEVICE_MSPRINTER_HDC (d) = |
524 CreateDC ("WINSPOOL", DEVICE_MSPRINTER_NAME(d), NULL, devmode); | 585 CreateDC ("WINSPOOL", DEVICE_MSPRINTER_NAME(d), NULL, devmode_out); |
525 } | 586 } |
587 | |
588 return 1; | |
589 } | |
590 | |
591 static void | |
592 handle_devmode_changes (Lisp_Devmode *ldm, HGLOBAL hDevNames, HGLOBAL hDevMode) | |
593 { | |
594 DEVNAMES* devnames = (DEVNAMES*) GlobalLock (hDevNames); | |
595 char *new_name = devnames ? (char*)devnames + devnames->wDeviceOffset : NULL; | |
596 DEVMODE* devmode = (DEVMODE*) GlobalLock (hDevMode); | |
597 | |
598 /* Size and name may have changed */ | |
599 ldm->devmode = xrealloc (ldm->devmode, DEVMODE_SIZE (devmode)); | |
600 if (new_name) | |
601 { | |
602 if (ldm->printer_name) | |
603 xfree (ldm->printer_name); | |
604 ldm->printer_name = xstrdup (new_name); | |
605 } | |
606 | |
607 if (!NILP (ldm->device)) | |
608 { | |
609 /* Apply the new devmode to the printer and get a compete one back */ | |
610 struct device *d = XDEVICE (ldm->device); | |
611 if (!sync_printer_with_devmode (d, devmode, ldm->devmode, new_name)) | |
612 { | |
613 global_free_2_maybe (hDevNames, hDevMode); | |
614 error ("Printer device initialization I/O error, device deleted."); | |
615 } | |
616 } | |
617 else | |
618 { | |
619 /* Just copy the devmode structure */ | |
620 memcpy (ldm->devmode, devmode, DEVMODE_SIZE (devmode)); | |
621 } | |
622 } | |
623 | |
624 static void | |
625 ensure_not_printing (struct device *d) | |
626 { | |
627 if (!NILP (DEVICE_FRAME_LIST (d))) | |
628 { | |
629 Lisp_Object device; | |
630 XSETDEVICE (device, d); | |
631 signal_simple_error ("Cannot change settings while print job is active", | |
632 device); | |
633 } | |
634 } | |
635 | |
636 static Lisp_Devmode * | |
637 decode_devmode (Lisp_Object dev) | |
638 { | |
639 if (DEVMODEP (dev)) | |
640 return XDEVMODE (dev); | |
641 else | |
642 { | |
643 struct device* d = decode_device (dev); | |
644 Lisp_Object device; | |
645 XSETDEVICE (device, d); | |
646 CHECK_MSPRINTER_DEVICE (device); | |
647 ensure_not_printing (d); | |
648 return XDEVMODE (DEVICE_MSPRINTER_DEVMODE (d)); | |
649 } | |
650 } | |
651 | |
652 /* | |
653 * DEV can be either a printer or devmode | |
654 * PRINT_P is non-zero for the Print dialog, zero for the | |
655 * Page Setup dialog | |
656 */ | |
657 static Lisp_Object | |
658 print_dialog_worker (Lisp_Object dev, int print_p) | |
659 { | |
660 Lisp_Devmode *ldm = decode_devmode (dev); | |
661 PRINTDLG pd; | |
662 | |
663 memset (&pd, 0, sizeof (pd)); | |
664 pd.lStructSize = sizeof (pd); | |
665 pd.hwndOwner = mswindows_get_selected_frame_hwnd (); | |
666 pd.hDevMode = devmode_to_hglobal (ldm); | |
667 pd.Flags = (PD_NOSELECTION | PD_USEDEVMODECOPIESANDCOLLATE | |
668 | (print_p ? 0 : PD_PRINTSETUP)); | |
669 pd.nMinPage = 0; | |
670 pd.nMaxPage = 0xFFFF; | |
671 | |
672 if (!PrintDlg (&pd)) | |
673 { | |
674 global_free_2_maybe (pd.hDevNames, pd.hDevMode); | |
675 return Qnil; | |
676 } | |
677 | |
678 handle_devmode_changes (ldm, pd.hDevNames, pd.hDevMode); | |
679 | |
680 /* Finally, build the resulting plist */ | |
681 { | |
682 Lisp_Object result = Qnil; | |
683 struct gcpro gcpro1; | |
684 GCPRO1 (result); | |
685 | |
686 /* Do consing in reverse order. | |
687 Number of copies */ | |
688 if (print_p) | |
689 result = Fcons (Qcopies, Fcons (make_int (pd.nCopies), result)); | |
690 | |
691 /* Page range */ | |
692 if (print_p && (pd.Flags & PD_PAGENUMS)) | |
693 { | |
694 result = Fcons (Qto_page, Fcons (make_int (pd.nToPage), result)); | |
695 result = Fcons (Qfrom_page, Fcons (make_int (pd.nFromPage), result)); | |
696 } | |
697 | |
698 /* Device name */ | |
699 result = Fcons (Qname, | |
700 Fcons (build_ext_string (ldm->printer_name, | |
701 Qmswindows_tstr), | |
702 result)); | |
703 UNGCPRO; | |
704 | |
705 global_free_2_maybe (pd.hDevNames, pd.hDevMode); | |
706 return result; | |
707 } | |
708 } | |
709 | |
710 DEFUN ("msprinter-print-setup-dialog", Fmsprinter_print_setup_dialog, 1, 1, 0, /* | |
711 Invoke Windows standard Printer Setup dialog. | |
712 This dialog is usually invoked when the user selects the Printer Setup | |
713 command. | |
714 | |
715 DEVICE must be either an 'msprinter device, or a printer settings | |
716 object. The function brings up the Printer Setup dialog, where the user | |
717 can select a different printer and/or change printer options. | |
718 Connection name can change as a result of selecting a different printer | |
719 device. If a printer is specified, then changes are stored into the | |
720 settings object currently selected into that printer. If a settings | |
721 object is supplied, then changes are recorded into it, and, it it is | |
722 selected into a printer, then changes are propagated to that printer | |
723 too. | |
724 | |
725 Return value is nil if the user has canceled the dialog. Otherwise, it | |
726 is a new plist, with the following properties: | |
727 name Printer device name, even if unchanged by the user. | |
728 | |
729 The printer device is destroyed and an error is signaled if new printer | |
730 is selected by the user, but cannot be initialized. | |
731 | |
732 See also `msprinter-print-dialog' and `msprinter-page-setup-dialog'. | |
733 */ | |
734 (device)) | |
735 { | |
736 return print_dialog_worker (device, 0); | |
737 } | |
738 | |
739 DEFUN ("msprinter-print-dialog", Fmsprinter_print_dialog, 1, 1, 0, /* | |
740 Invoke Windows standard Print dialog. | |
741 This dialog is usually invoked when the user selects the Print command. | |
742 After the user presses OK, the program should start actual printout. | |
743 | |
744 DEVICE must be either an 'msprinter device, or a printer settings | |
745 object. The function brings up the Print dialog, where the user can | |
746 select a different printer and/or change printer options. Connection | |
747 name can change as a result of selecting a different printer device. If | |
748 a printer is specified, then changes are stored into the settings object | |
749 currently selected into that printer. If a settings object is supplied, | |
750 then changes are recorded into it, and, it it is selected into a | |
751 printer, then changes are propagated to that printer | |
752 too. | |
753 | |
754 Return value is nil if the user has canceled the dialog. Otherwise, it | |
755 is a new plist, with the following properties: | |
756 name Printer device name, even if unchanged by the user. | |
757 from-page First page to print, 1-based. If not specified by the user, | |
758 then this value is not included in the plist. | |
759 to-page Last page to print, inclusive, 1-based. If not specified by | |
760 the user, then this value is not included in the plist. | |
761 copies Number of copies to print. Always returned. | |
762 | |
763 The DEVICE is destroyed and an error is signaled in case of | |
764 initialization problem with the new printer. | |
765 | |
766 See also `msprinter-setup-print-dialog' and | |
767 `msprinter-page-setup-dialog'. | |
768 */ | |
769 (device)) | |
770 { | |
771 return print_dialog_worker (device, 1); | |
772 } | |
773 | |
774 | |
775 static int | |
776 plist_get_margin (Lisp_Object plist, Lisp_Object prop) | |
777 { | |
778 Lisp_Object val = Fplist_get (plist, prop, make_int (1440)); | |
779 if (!INTP (val)) | |
780 signal_simple_error ("Margin value must be an integer", val); | |
781 | |
782 return MulDiv (XINT (val), 100, 144); | |
783 } | |
784 | |
785 static Lisp_Object | |
786 plist_set_margin (Lisp_Object plist, Lisp_Object prop, int margin, int mm_p) | |
787 { | |
788 Lisp_Object val = make_int (MulDiv (margin, 144, mm_p ? 2450 : 100)); | |
789 return Fcons (prop, Fcons (val, plist)); | |
790 } | |
791 | |
792 DEFUN ("msprinter-page-setup-dialog", Fmsprinter_page_setup_dialog, 1, 2, 0, /* | |
793 Invoke Windows standard Page Setup dialog. | |
794 This dialog is usually invoked in response to Page Setup command, and | |
795 used to chose such parameters as page orientation, print margins etc. | |
796 Note that this dialog contains the "Printer" button, which invokes | |
797 Printer Setup dialog (see `msprinter-print-setup-dialog') so that the | |
798 user can update the printer options or even select a different printer | |
799 as well. | |
800 | |
801 DEVICE must be either an 'msprinter device, or a printer settings | |
802 object. The function brings up the Page Setup dialog, where the user | |
803 can select a different printer and/or change printer options. | |
804 Connection name can change as a result of selecting a different printer | |
805 device. If a printer is specified, then changes are stored into the | |
806 settings object currently selected into that printer. If a settings | |
807 object is supplied, then changes are recorded into it, and, it it is | |
808 selected into a printer, then changes are propagated to that printer | |
809 too. | |
810 | |
811 PLIST is a plist of job properties; | |
812 see `default-msprinter-frame-plist' for the complete list. The plist | |
813 is used to initialize the dialog. | |
814 | |
815 Return value is nil if the user has canceled the dialog. Otherwise, | |
816 it is a new plist, containing the new list of properties. | |
817 | |
818 The DEVICE is destroyed and an error is signaled in case of | |
819 initialization problem with the new printer. | |
820 | |
821 See also `msprinter-print-setup-dialog' and `msprinter-print-dialog'. | |
822 */ | |
823 (device, plist)) | |
824 { | |
825 Lisp_Devmode *ldm = decode_devmode (device); | |
826 PAGESETUPDLG pd; | |
827 | |
828 memset (&pd, 0, sizeof (pd)); | |
829 pd.lStructSize = sizeof (pd); | |
830 pd.hwndOwner = mswindows_get_selected_frame_hwnd (); | |
831 pd.Flags = PSD_MARGINS; | |
832 pd.rtMargin.left = plist_get_margin (plist, Qleft_margin); | |
833 pd.rtMargin.top = plist_get_margin (plist, Qtop_margin); | |
834 pd.rtMargin.right = plist_get_margin (plist, Qright_margin); | |
835 pd.rtMargin.bottom = plist_get_margin (plist, Qbottom_margin); | |
836 pd.hDevMode = devmode_to_hglobal (ldm); | |
837 | |
838 if (!PageSetupDlg (&pd)) | |
839 { | |
840 global_free_2_maybe (pd.hDevNames, pd.hDevMode); | |
841 return Qnil; | |
842 } | |
843 | |
844 if (pd.hDevMode) | |
845 handle_devmode_changes (ldm, pd.hDevNames, pd.hDevMode); | |
846 | |
847 /* Finally, build the resulting plist */ | |
848 { | |
849 Lisp_Object result = Qnil; | |
850 int mm_p = pd.Flags & PSD_INHUNDREDTHSOFMILLIMETERS; | |
851 result = plist_set_margin (result, Qbottom_margin, pd.rtMargin.bottom, mm_p); | |
852 result = plist_set_margin (result, Qright_margin, pd.rtMargin.right, mm_p); | |
853 result = plist_set_margin (result, Qtop_margin, pd.rtMargin.top, mm_p); | |
854 result = plist_set_margin (result, Qleft_margin, pd.rtMargin.left, mm_p); | |
855 return result; | |
856 } | |
857 } | |
858 | |
859 DEFUN ("msprinter-get-settings", Fmsprinter_get_settings, 1, 1, 0, /* | |
860 Return the settings object currently used by DEVICE. | |
861 The object returned is not a copy, but rather a pointer to the | |
862 original one. Use `msprinter-settings-copy' to create a copy of it. | |
863 */ | |
864 (device)) | |
865 { | |
866 struct device *d = decode_device (device); | |
867 XSETDEVICE (device, d); | |
868 CHECK_MSPRINTER_DEVICE (device); | |
869 return DEVICE_MSPRINTER_DEVMODE (d); | |
870 } | |
871 | |
872 DEFUN ("msprinter-select-settings", Fmsprinter_select_settings, 2, 2, 0, /* | |
873 Select SETTINGS object into a DEVICE. | |
874 The settings from the settings object are immediately applied to the | |
875 printer, possibly changing even the target printer itself, and all | |
876 future changes are applied synchronously to the printer device and the | |
877 selected printer object, until a different settings object is selected | |
878 into the same printer. | |
879 | |
880 A settings object can be selected to no more than one printer at a time. | |
881 | |
882 If the supplied settings object is not specialized, it is specialized | |
883 for the printer immediately upon selection. The object can be | |
884 despecialized after it is unselected by calling the function | |
885 `msprinter-settings-despecialize'. | |
886 | |
887 Return value is the previously selected settings object. | |
888 */ | |
889 (device, settings)) | |
890 { | |
891 Lisp_Devmode *ldm; | |
892 struct device *d = decode_device (device); | |
893 | |
894 struct gcpro gcpro1; | |
895 GCPRO1 (settings); | |
896 | |
897 XSETDEVICE (device, d); | |
898 CHECK_MSPRINTER_DEVICE (device); | |
899 CHECK_DEVMODE (settings); | |
900 ldm = XDEVMODE (settings); | |
901 | |
902 if (!NILP (ldm->device)) | |
903 signal_simple_error ("The object is currently selected into a device", | |
904 settings); | |
905 | |
906 /* If the object being selected is de-specialized, then its | |
907 size is perhaps not enough to receive the new devmode. We can ask | |
908 for printer's devmode size here, because despecialized settings | |
909 cannot force switching to a different printer, as they supply no | |
910 printer name at all. */ | |
911 if (ldm->printer_name == NULL) | |
912 { | |
913 size_t dm_size = | |
914 DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d), | |
915 DEVICE_MSPRINTER_NAME(d), NULL, NULL, 0); | |
916 if (dm_size <= 0) | |
917 signal_simple_error ("Unable to specialize settings, printer error", | |
918 device); | |
919 | |
920 assert (XDEVMODE_SIZE (ldm) <= dm_size); | |
921 ldm->devmode = xrealloc (ldm->devmode, dm_size); | |
922 } | |
923 | |
924 /* If we bail out on signal here, no damage is done, except that | |
925 the stirage for the DEVMODE structure might be reallocated to | |
926 hold a larger one - not a big deal */ | |
927 if (!sync_printer_with_devmode (d, ldm->devmode, ldm->devmode, | |
928 ldm->printer_name)) | |
929 error ("Printer device initialization I/O error, device deleted."); | |
930 | |
931 if (ldm->printer_name == NULL) | |
932 ldm->printer_name = xstrdup (DEVICE_MSPRINTER_NAME(d)); | |
933 | |
934 { | |
935 Lisp_Object old_mode = DEVICE_MSPRINTER_DEVMODE (d); | |
936 ldm->device = device; | |
937 XDEVMODE (old_mode)->device = Qnil; | |
938 DEVICE_MSPRINTER_DEVMODE (d) = settings; | |
939 UNGCPRO; | |
940 return old_mode; | |
941 } | |
942 } | |
943 | |
944 DEFUN ("msprinter-apply-settings", Fmsprinter_apply_settings, 2, 2, 0, /* | |
945 Apply settings from a SETTINGS object to a 'msprinter DEVICE. | |
946 The settings from the settings object are immediately applied to the | |
947 printer, possibly changing even the target printer itself. The SETTING | |
948 object is not modified, unlike `msprinter-select-settings', and the | |
949 supplied object is not changed. The changes are immediately recorded | |
950 into the settings object which is currently selected into the printer | |
951 device. | |
952 | |
953 Return value is the currently selected settings object. | |
954 */ | |
955 (device, settings)) | |
956 { | |
957 Lisp_Devmode *ldm_current, *ldm_new; | |
958 struct device *d = decode_device (device); | |
959 | |
960 struct gcpro gcpro1; | |
961 GCPRO1 (settings); | |
962 | |
963 XSETDEVICE (device, d); | |
964 CHECK_MSPRINTER_DEVICE (device); | |
965 CHECK_DEVMODE (settings); | |
966 ldm_new = XDEVMODE (settings); | |
967 ldm_current = XDEVMODE (DEVICE_MSPRINTER_DEVMODE (d)); | |
968 | |
969 /* If the supplied devmode is not specialized, then the current | |
970 devmode size will always be sufficient, as the printer does | |
971 not change. If it is specialized, we must reallocate the cuttent | |
972 devmode storage to match with the supplied one, as it has the right | |
973 size for the new printer, if it is going to change. The correct | |
974 way is to use the largest of the two though, to keep the old | |
975 contents unchanged in case of preliminary exit. | |
976 */ | |
977 if (ldm_new->printer_name) | |
978 ldm_current->devmode = | |
979 (DEVMODE*) xrealloc (ldm_current->devmode, | |
980 max (XDEVMODE_SIZE (ldm_new), | |
981 XDEVMODE_SIZE (ldm_current))); | |
982 | |
983 if (!sync_printer_with_devmode (d, ldm_new->devmode, | |
984 ldm_current->devmode, | |
985 ldm_new->printer_name)) | |
986 error ("Printer device initialization I/O error, device deleted."); | |
987 | |
988 if (ldm_new->printer_name != NULL) | |
989 { | |
990 xfree (ldm_current->printer_name); | |
991 ldm_current->printer_name = xstrdup (ldm_new->printer_name); | |
992 } | |
993 | |
994 return DEVICE_MSPRINTER_DEVMODE (d); | |
995 } | |
996 | |
997 /************************************************************************/ | |
998 /* devmode */ | |
999 /************************************************************************/ | |
1000 | |
1001 static void | |
1002 print_devmode (Lisp_Object obj, Lisp_Object printcharfun, | |
1003 int escapeflag) | |
1004 { | |
1005 char buf[100]; | |
1006 Lisp_Devmode *dm = XDEVMODE (obj); | |
1007 if (print_readably) | |
1008 error ("printing unreadable object #<msprinter-settings 0x%x>", | |
1009 dm->header.uid); | |
1010 write_c_string ("#<msprinter-settings", printcharfun); | |
1011 if (dm->printer_name) | |
1012 { | |
1013 write_c_string (" for \"", printcharfun); | |
1014 write_c_string (dm->printer_name, printcharfun); | |
1015 write_c_string ("\"", printcharfun); | |
1016 } | |
1017 if (!NILP (dm->device)) | |
1018 { | |
1019 write_c_string (" (currently on ", printcharfun); | |
1020 print_internal (dm->device, printcharfun, 0); | |
1021 write_c_string (")", printcharfun); | |
1022 } | |
1023 sprintf (buf, " 0x%x>", dm->header.uid); | |
1024 write_c_string (buf, printcharfun); | |
1025 } | |
1026 | |
1027 static void | |
1028 finalize_devmode (void *header, int for_disksave) | |
1029 { | |
1030 Lisp_Devmode *dm = (Lisp_Devmode *) header; | |
1031 | |
1032 if (for_disksave) | |
1033 { | |
1034 Lisp_Object devmode; | |
1035 XSETDEVMODE (devmode, dm); | |
1036 signal_simple_error ( | |
1037 "Cannot dump XEmacs containing an msprinter-settings object", | |
1038 devmode); | |
1039 } | |
1040 | |
1041 assert (NILP (dm->device)); | |
1042 | |
1043 if (dm->printer_name) | |
1044 xfree (dm->printer_name); | |
1045 } | |
1046 | |
1047 static int | |
1048 equal_devmode (Lisp_Object obj1, Lisp_Object obj2, int depth) | |
1049 { | |
1050 Lisp_Devmode *dm1 = XDEVMODE (obj1); | |
1051 Lisp_Devmode *dm2 = XDEVMODE (obj2); | |
1052 | |
1053 if ((dm1->devmode != NULL) != (dm1->devmode != NULL)) | |
1054 return 0; | |
1055 if (dm1->devmode == NULL) | |
1056 return 1; | |
1057 if (memcmp (dm1->devmode, dm2->devmode, XDEVMODE_SIZE (dm1)) != 0) | |
1058 return 0; | |
1059 if (dm1->printer_name == NULL || dm2->printer_name == NULL) | |
1060 return 1; | |
1061 return stricmp (dm1->printer_name, dm2->printer_name) == 0; | |
1062 } | |
1063 | |
1064 static unsigned long | |
1065 hash_devmode (Lisp_Object obj, int depth) | |
1066 { | |
1067 Lisp_Devmode *dm = XDEVMODE (obj); | |
1068 | |
1069 return HASH3 (XDEVMODE_SIZE (dm), | |
1070 dm->devmode ? memory_hash (dm->devmode, XDEVMODE_SIZE (dm)) | |
1071 : 0, | |
1072 dm->printer_name ? string_hash (dm->printer_name) : 0); | |
1073 } | |
1074 | |
1075 DEFINE_LRECORD_IMPLEMENTATION ("msprinter-settings", devmode, | |
1076 0/*mark*/, print_devmode, finalize_devmode, | |
1077 equal_devmode, hash_devmode, 0/*description*/, | |
1078 Lisp_Devmode); | |
1079 static Lisp_Object | |
1080 allocate_devmode (DEVMODE* src_devmode, int do_copy, | |
1081 char* src_name, struct device *d) | |
1082 { | |
1083 Lisp_Devmode *dm; | |
1084 Lisp_Object ob; | |
1085 | |
1086 dm = alloc_lcrecord_type (Lisp_Devmode, &lrecord_devmode); | |
1087 | |
1088 if (d) | |
1089 XSETDEVICE (dm->device, d); | |
1090 else | |
1091 dm->device = Qnil; | |
1092 | |
1093 dm->printer_name = src_name ? xstrdup (src_name) : NULL; | |
1094 | |
1095 if (src_devmode != NULL && do_copy) | |
1096 { | |
1097 dm->devmode = (DEVMODE*) xmalloc (DEVMODE_SIZE (src_devmode)); | |
1098 memcpy (dm->devmode, src_devmode, DEVMODE_SIZE (src_devmode)); | |
1099 } | |
1100 else | |
1101 { | |
1102 dm->devmode = src_devmode; | |
1103 } | |
1104 | |
1105 XSETDEVMODE (ob, dm); | |
1106 return ob; | |
1107 } | |
1108 | |
1109 DEFUN ("msprinter-settings-copy", Fmsprinter_settings_copy, 1, 1, 0, /* | |
1110 Create and returns an exact copy of a printer settings object. | |
1111 */ | |
1112 (settings)) | |
1113 { | |
1114 Lisp_Devmode *dm; | |
1115 | |
1116 CHECK_DEVMODE (settings); | |
1117 dm = XDEVMODE (settings); | |
1118 | |
1119 return allocate_devmode (dm->devmode, 1, dm->printer_name, NULL); | |
1120 } | |
1121 | |
1122 DEFUN ("msprinter-settings-despecialize", Fmsprinter_settings_despecialize, 1, 1, 0, /* | |
1123 Erase printer-specific settings from a printer settings object. | |
1124 */ | |
1125 (settings)) | |
1126 { | |
1127 Lisp_Devmode *ldm; | |
1128 DEVMODE *dm; | |
1129 | |
1130 CHECK_DEVMODE (settings); | |
1131 ldm = XDEVMODE (settings); | |
1132 | |
1133 if (!NILP (ldm->device)) | |
1134 signal_simple_error ("The object is currently selected into a device", | |
1135 settings); | |
1136 | |
1137 dm = ldm->devmode; | |
1138 | |
1139 /* #### TODO. Either remove references to device specific bins, | |
1140 paper sizes etc, or signal an error of they are present. */ | |
1141 | |
1142 dm->dmDriverExtra = 0; | |
1143 dm->dmDeviceName[0] = '\0'; | |
1144 | |
1145 if (ldm->printer_name) | |
1146 xfree (ldm->printer_name); | |
1147 | |
1148 return Qnil; | |
526 } | 1149 } |
527 | 1150 |
528 | 1151 |
529 /************************************************************************/ | 1152 /************************************************************************/ |
530 /* initialization */ | 1153 /* initialization */ |
531 /************************************************************************/ | 1154 /************************************************************************/ |
532 | 1155 |
533 void | 1156 void |
534 syms_of_device_mswindows (void) | 1157 syms_of_device_mswindows (void) |
535 { | 1158 { |
1159 INIT_LRECORD_IMPLEMENTATION (devmode); | |
1160 | |
1161 DEFSUBR (Fmsprinter_print_setup_dialog); | |
1162 DEFSUBR (Fmsprinter_print_dialog); | |
1163 DEFSUBR (Fmsprinter_page_setup_dialog); | |
1164 DEFSUBR (Fmsprinter_get_settings); | |
1165 DEFSUBR (Fmsprinter_select_settings); | |
1166 DEFSUBR (Fmsprinter_apply_settings); | |
1167 DEFSUBR (Fmsprinter_settings_copy); | |
1168 DEFSUBR (Fmsprinter_settings_despecialize); | |
1169 | |
536 defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win"); | 1170 defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win"); |
537 defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win"); | 1171 defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win"); |
538 } | 1172 } |
539 | 1173 |
540 void | 1174 void |