comparison src/device-msw.c @ 412:697ef44129c6 r21-2-14

Import from CVS: tag r21-2-14
author cvs
date Mon, 13 Aug 2007 11:20:41 +0200
parents de805c49cfc1
children da8ed4261e83
comparison
equal deleted inserted replaced
411:12e008d41344 412:697ef44129c6
32 #include <config.h> 32 #include <config.h>
33 #include "lisp.h" 33 #include "lisp.h"
34 34
35 #include "console-msw.h" 35 #include "console-msw.h"
36 #include "console-stream.h" 36 #include "console-stream.h"
37 #include "objects-msw.h"
38 #include "events.h" 37 #include "events.h"
39 #include "faces.h" 38 #include "faces.h"
40 #include "frame.h" 39 #include "frame.h"
41 #include "sysdep.h" 40 #include "sysdep.h"
42
43 /* #### Andy, these includes might break cygwin compilation - kkm*/
44 #include <commdlg.h>
45 #include <winspool.h>
46
47 #if !(defined (CYGWIN) || defined(MINGW))
48 # include <objbase.h> /* For CoInitialize */
49 #endif
50 41
51 /* win32 DDE management library globals */ 42 /* win32 DDE management library globals */
52 #ifdef HAVE_DRAGNDROP 43 #ifdef HAVE_DRAGNDROP
53 DWORD mswindows_dde_mlid; 44 DWORD mswindows_dde_mlid;
54 HSZ mswindows_dde_service; 45 HSZ mswindows_dde_service;
64 exactly, at the expense of slower operation. Since true hard links 55 exactly, at the expense of slower operation. Since true hard links
65 are supported on NTFS volumes, this is only relevant on NT. */ 56 are supported on NTFS volumes, this is only relevant on NT. */
66 Lisp_Object Vmswindows_get_true_file_attributes; 57 Lisp_Object Vmswindows_get_true_file_attributes;
67 58
68 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win; 59 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win;
69 Lisp_Object Qdevmodep; 60
70
71 static Lisp_Object allocate_devmode (DEVMODE* src_devmode, int do_copy,
72 char* src_name, struct device *d);
73 61
74 /************************************************************************/ 62 /************************************************************************/
75 /* helpers */ 63 /* helpers */
76 /************************************************************************/ 64 /************************************************************************/
77 65
78 static Lisp_Object 66 static Lisp_Object
79 build_syscolor_string (int idx) 67 build_syscolor_string (int index)
80 { 68 {
81 return (idx < 0 ? Qnil : mswindows_color_to_string (GetSysColor (idx))); 69 DWORD clr;
70 char buf[16];
71
72 if (index < 0)
73 return Qnil;
74
75 clr = GetSysColor (index);
76 sprintf (buf, "#%02X%02X%02X",
77 GetRValue (clr),
78 GetGValue (clr),
79 GetBValue (clr));
80 return build_string (buf);
82 } 81 }
83 82
84 static Lisp_Object 83 static Lisp_Object
85 build_syscolor_cons (int index1, int index2) 84 build_syscolor_cons (int index1, int index2)
86 { 85 {
97 { 96 {
98 return Fcons (index1 < 0 ? Qnil : make_int (GetSystemMetrics (index1)), 97 return Fcons (index1 < 0 ? Qnil : make_int (GetSystemMetrics (index1)),
99 index2 < 0 ? Qnil : make_int (GetSystemMetrics (index2))); 98 index2 < 0 ? Qnil : make_int (GetSystemMetrics (index2)));
100 } 99 }
101 100
102 static Lisp_Object
103 build_devicecaps_cons (HDC hdc, int index1, int index2)
104 {
105 return Fcons (index1 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index1)),
106 index2 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index2)));
107 }
108 101
109 102
110 /************************************************************************/ 103 /************************************************************************/
111 /* display methods */ 104 /* methods */
112 /************************************************************************/ 105 /************************************************************************/
113 106
114 static void 107 static void
115 mswindows_init_device (struct device *d, Lisp_Object props) 108 mswindows_init_device (struct device *d, Lisp_Object props)
116 { 109 {
123 init_one_device (d); 116 init_one_device (d);
124 117
125 d->device_data = xnew_and_zero (struct mswindows_device); 118 d->device_data = xnew_and_zero (struct mswindows_device);
126 hdc = CreateCompatibleDC (NULL); 119 hdc = CreateCompatibleDC (NULL);
127 assert (hdc!=NULL); 120 assert (hdc!=NULL);
128 DEVICE_MSWINDOWS_HCDC(d) = hdc; 121 DEVICE_MSWINDOWS_LOGPIXELSX(d) = GetDeviceCaps(hdc, LOGPIXELSX);
129 DEVICE_MSWINDOWS_FONTLIST (d) = mswindows_enumerate_fonts (hdc); 122 DEVICE_MSWINDOWS_LOGPIXELSY(d) = GetDeviceCaps(hdc, LOGPIXELSY);
130 DEVICE_MSWINDOWS_UPDATE_TICK (d) = GetTickCount (); 123 DEVICE_MSWINDOWS_PLANES(d) = GetDeviceCaps(hdc, PLANES);
124 /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS,
125 what should we return for a non-palette-based device? */
126 DEVICE_MSWINDOWS_CELLS(d) = GetDeviceCaps(hdc, SIZEPALETTE);
127 DEVICE_MSWINDOWS_HORZRES(d) = GetDeviceCaps(hdc, HORZRES);
128 DEVICE_MSWINDOWS_VERTRES(d) = GetDeviceCaps(hdc, VERTRES);
129 DEVICE_MSWINDOWS_HORZSIZE(d) = GetDeviceCaps(hdc, HORZSIZE);
130 DEVICE_MSWINDOWS_VERTSIZE(d) = GetDeviceCaps(hdc, VERTSIZE);
131 DEVICE_MSWINDOWS_BITSPIXEL(d) = GetDeviceCaps(hdc, BITSPIXEL);
132 DeleteDC (hdc);
133
134 mswindows_enumerate_fonts (d);
131 135
132 /* Register the main window class */ 136 /* Register the main window class */
133 wc.cbSize = sizeof (WNDCLASSEX); 137 wc.cbSize = sizeof (WNDCLASSEX);
134 wc.style = CS_OWNDC; /* One DC per window */ 138 wc.style = CS_OWNDC; /* One DC per window */
135 wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc; 139 wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc;
136 wc.cbClsExtra = 0; 140 wc.cbClsExtra = 0;
137 wc.cbWndExtra = MSWINDOWS_WINDOW_EXTRA_BYTES; 141 wc.cbWndExtra = MSWINDOWS_WINDOW_EXTRA_BYTES;
138 /* This must match whatever is passed to CreateWIndowEx, NULL is ok 142 wc.hInstance = NULL; /* ? */
139 for this. */
140 wc.hInstance = NULL;
141 wc.hIcon = LoadIcon (GetModuleHandle(NULL), XEMACS_CLASS); 143 wc.hIcon = LoadIcon (GetModuleHandle(NULL), XEMACS_CLASS);
142 wc.hCursor = LoadCursor (NULL, IDC_ARROW); 144 wc.hCursor = LoadCursor (NULL, IDC_ARROW);
143 /* Background brush is only used during sizing, when XEmacs cannot 145 /* Background brush is only used during sizing, when XEmacs cannot
144 take over */ 146 take over */
145 wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1); 147 wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
146 wc.lpszMenuName = NULL; 148 wc.lpszMenuName = NULL;
147 149
148 wc.lpszClassName = XEMACS_CLASS; 150 wc.lpszClassName = XEMACS_CLASS;
149 wc.hIconSm = (HICON) LoadImage (GetModuleHandle (NULL), XEMACS_CLASS, 151 wc.hIconSm = LoadImage (GetModuleHandle (NULL), XEMACS_CLASS,
150 IMAGE_ICON, 16, 16, 0); 152 IMAGE_ICON, 16, 16, 0);
151 RegisterClassEx (&wc); 153 RegisterClassEx (&wc);
152 154 #ifdef HAVE_TOOLBARS
153 #ifdef HAVE_WIDGETS
154 xzero (wc);
155 /* Register the main window class */
156 wc.cbSize = sizeof (WNDCLASSEX);
157 wc.lpfnWndProc = (WNDPROC) mswindows_control_wnd_proc;
158 wc.lpszClassName = XEMACS_CONTROL_CLASS;
159 wc.hInstance = NULL;
160 RegisterClassEx (&wc);
161 #endif
162
163 #if defined (HAVE_TOOLBARS) || defined (HAVE_WIDGETS)
164 InitCommonControls (); 155 InitCommonControls ();
165 #endif 156 #endif
166 } 157 }
167 158
168 static void 159 static void
169 mswindows_finish_init_device (struct device *d, Lisp_Object props) 160 mswindows_finish_init_device (struct device *d, Lisp_Object props)
170 { 161 {
171 /* Initialize DDE management library and our related globals. We execute a 162 /* Initialize DDE management library and our related globals. We execute a
172 * dde Open("file") by simulating a drop, so this depends on dnd support. */ 163 * dde Open("file") by simulating a drop, so this depends on dnd support. */
173 #ifdef HAVE_DRAGNDROP 164 #ifdef HAVE_DRAGNDROP
174 # if !(defined(CYGWIN) || defined(MINGW))
175 CoInitialize (NULL);
176 # endif
177
178 mswindows_dde_mlid = 0; 165 mswindows_dde_mlid = 0;
179 DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback, 166 DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback,
180 APPCMD_FILTERINITS|CBF_FAIL_SELFCONNECTIONS|CBF_FAIL_ADVISES| 167 APPCMD_FILTERINITS|CBF_FAIL_SELFCONNECTIONS|CBF_FAIL_ADVISES|
181 CBF_FAIL_POKES|CBF_FAIL_REQUESTS|CBF_SKIP_ALLNOTIFICATIONS, 168 CBF_FAIL_POKES|CBF_FAIL_REQUESTS|CBF_SKIP_ALLNOTIFICATIONS, 0);
182 0);
183 169
184 mswindows_dde_service = DdeCreateStringHandle (mswindows_dde_mlid, 170 mswindows_dde_service = DdeCreateStringHandle (mswindows_dde_mlid, XEMACS_CLASS, 0);
185 XEMACS_CLASS, 0); 171 mswindows_dde_topic_system = DdeCreateStringHandle (mswindows_dde_mlid, SZDDESYS_TOPIC, 0);
186 mswindows_dde_topic_system = DdeCreateStringHandle (mswindows_dde_mlid,
187 SZDDESYS_TOPIC, 0);
188 mswindows_dde_item_open = DdeCreateStringHandle (mswindows_dde_mlid, 172 mswindows_dde_item_open = DdeCreateStringHandle (mswindows_dde_mlid,
189 TEXT(MSWINDOWS_DDE_ITEM_OPEN), 0); 173 TEXT(MSWINDOWS_DDE_ITEM_OPEN), 0);
190 DdeNameService (mswindows_dde_mlid, mswindows_dde_service, 0L, DNS_REGISTER); 174 DdeNameService (mswindows_dde_mlid, mswindows_dde_service, 0L, DNS_REGISTER);
191 #endif 175 #endif
192 } 176 }
193 177
194 static void 178 static void
195 mswindows_delete_device (struct device *d) 179 mswindows_delete_device (struct device *d)
196 { 180 {
181 struct mswindows_font_enum *fontlist, *next;
182
183 fontlist = DEVICE_MSWINDOWS_FONTLIST (d);
184 while (fontlist)
185 {
186 next = fontlist->next;
187 free (fontlist);
188 fontlist = next;
189 }
190
197 #ifdef HAVE_DRAGNDROP 191 #ifdef HAVE_DRAGNDROP
198 DdeNameService (mswindows_dde_mlid, 0L, 0L, DNS_UNREGISTER); 192 DdeNameService (mswindows_dde_mlid, 0L, 0L, DNS_REGISTER);
199 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_item_open);
200 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_topic_system);
201 DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_service);
202 DdeUninitialize (mswindows_dde_mlid); 193 DdeUninitialize (mswindows_dde_mlid);
203
204 # if !(defined(CYGWIN) || defined(MINGW))
205 CoUninitialize ();
206 # endif
207 #endif 194 #endif
208 195
209 DeleteDC (DEVICE_MSWINDOWS_HCDC(d)); 196 free (d->device_data);
210 xfree (d->device_data);
211 }
212
213 void
214 mswindows_get_workspace_coords (RECT *rc)
215 {
216 SystemParametersInfo (SPI_GETWORKAREA, 0, rc, 0);
217 }
218
219 static void
220 mswindows_mark_device (struct device *d)
221 {
222 mark_object (DEVICE_MSWINDOWS_FONTLIST (d));
223 } 197 }
224 198
225 static Lisp_Object 199 static Lisp_Object
226 mswindows_device_system_metrics (struct device *d, 200 mswindows_device_system_metrics (struct device *d,
227 enum device_metrics m) 201 enum device_metrics m)
228 { 202 {
229 const HDC hdc = DEVICE_MSWINDOWS_HCDC(d);
230
231 switch (m) 203 switch (m)
232 { 204 {
233 case DM_size_device: 205 case DM_size_device:
234 return Fcons (make_int (GetDeviceCaps (hdc, HORZRES)), 206 return Fcons (make_int (DEVICE_MSWINDOWS_HORZRES(d)),
235 make_int (GetDeviceCaps (hdc, VERTRES))); 207 make_int (DEVICE_MSWINDOWS_VERTRES(d)));
236 break;
237 case DM_device_dpi:
238 return Fcons (make_int (GetDeviceCaps (hdc, LOGPIXELSX)),
239 make_int (GetDeviceCaps (hdc, LOGPIXELSY)));
240 break; 208 break;
241 case DM_size_device_mm: 209 case DM_size_device_mm:
242 return Fcons (make_int (GetDeviceCaps (hdc, HORZSIZE)), 210 return Fcons (make_int (DEVICE_MSWINDOWS_HORZSIZE(d)),
243 make_int (GetDeviceCaps (hdc, VERTSIZE))); 211 make_int (DEVICE_MSWINDOWS_VERTSIZE(d)));
244 break; 212 break;
245 case DM_num_bit_planes: 213 case DM_num_bit_planes:
246 /* this is what X means by bitplanes therefore we ought to be 214 /* this is what X means by bitplanes therefore we ought to be
247 consistent. num planes is always 1 under mswindows and 215 consistent. num planes is always 1 under mswindows and
248 therefore useless */ 216 therefore useless */
249 return make_int (GetDeviceCaps (hdc, BITSPIXEL)); 217 return make_int (DEVICE_MSWINDOWS_BITSPIXEL(d));
250 break; 218 break;
251 case DM_num_color_cells: 219 case DM_num_color_cells:
252 /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS, 220 return make_int (DEVICE_MSWINDOWS_CELLS(d));
253 what should we return for a non-palette-based device? */
254 return make_int (GetDeviceCaps (hdc, SIZEPALETTE));
255 break; 221 break;
256 222
257 /*** Colors ***/ 223 /*** Colors ***/
258 #define FROB(met, fore, back) \ 224 #define FROB(met, index1, index2) \
259 case DM_##met: \ 225 case DM_##met: \
260 return build_syscolor_cons (fore, back); 226 return build_syscolor_cons (index1, index2);
261 227
262 FROB (color_default, COLOR_WINDOWTEXT, COLOR_WINDOW); 228 FROB (color_default, COLOR_WINDOW, COLOR_WINDOWTEXT);
263 FROB (color_select, COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHT); 229 FROB (color_select, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT);
264 FROB (color_balloon, COLOR_INFOTEXT, COLOR_INFOBK); 230 FROB (color_balloon, COLOR_INFOBK, COLOR_INFOTEXT);
265 FROB (color_3d_face, COLOR_BTNTEXT, COLOR_BTNFACE); 231 FROB (color_3d_face, COLOR_3DFACE, COLOR_BTNTEXT);
266 FROB (color_3d_light, COLOR_3DHILIGHT, COLOR_3DLIGHT); 232 FROB (color_3d_light, COLOR_3DLIGHT, COLOR_3DHILIGHT);
267 FROB (color_3d_dark, COLOR_3DDKSHADOW, COLOR_3DSHADOW); 233 FROB (color_3d_dark, COLOR_3DSHADOW, COLOR_3DDKSHADOW);
268 FROB (color_menu, COLOR_MENUTEXT, COLOR_MENU); 234 FROB (color_menu, COLOR_MENU, COLOR_MENUTEXT);
269 FROB (color_menu_highlight, COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHT); 235 FROB (color_menu_highlight, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT);
270 FROB (color_menu_button, COLOR_MENUTEXT, COLOR_MENU); 236 FROB (color_menu_button, COLOR_MENU, COLOR_MENUTEXT);
271 FROB (color_menu_disabled, COLOR_GRAYTEXT, COLOR_MENU); 237 FROB (color_menu_disabled, COLOR_MENU, COLOR_GRAYTEXT);
272 FROB (color_toolbar, COLOR_BTNTEXT, COLOR_BTNFACE); 238 FROB (color_toolbar, COLOR_BTNFACE, COLOR_BTNTEXT);
273 FROB (color_scrollbar, COLOR_CAPTIONTEXT, COLOR_SCROLLBAR); 239 FROB (color_scrollbar, COLOR_SCROLLBAR, COLOR_CAPTIONTEXT);
274 FROB (color_desktop, -1, COLOR_DESKTOP); 240 FROB (color_desktop, -1, COLOR_DESKTOP);
275 FROB (color_workspace, -1, COLOR_APPWORKSPACE); 241 FROB (color_workspace, -1, COLOR_APPWORKSPACE);
276 #undef FROB 242 #undef FROB
277 243
278 /*** Sizes ***/ 244 /*** Sizes ***/
288 #undef FROB 254 #undef FROB
289 255
290 case DM_size_workspace: 256 case DM_size_workspace:
291 { 257 {
292 RECT rc; 258 RECT rc;
293 mswindows_get_workspace_coords (&rc); 259 SystemParametersInfo (SPI_GETWORKAREA, 0, &rc, 0);
294 return Fcons (make_int (rc.right - rc.left), 260 return Fcons (make_int (rc.right - rc.left),
295 make_int (rc.bottom - rc.top)); 261 make_int (rc.bottom - rc.top));
296 } 262 }
297
298 case DM_offset_workspace:
299 {
300 RECT rc;
301 mswindows_get_workspace_coords (&rc);
302 return Fcons (make_int (rc.left), make_int (rc.top));
303 }
304
305 /* 263 /*
306 case DM_size_toolbar: 264 case DM_size_toolbar:
307 case DM_size_toolbar_button: 265 case DM_size_toolbar_button:
308 case DM_size_toolbar_border: 266 case DM_size_toolbar_border:
309 */ 267 */
332 return XDEVIMPF_PIXEL_GEOMETRY; 290 return XDEVIMPF_PIXEL_GEOMETRY;
333 } 291 }
334 292
335 293
336 /************************************************************************/ 294 /************************************************************************/
337 /* printer helpers */
338 /************************************************************************/
339
340 static void
341 signal_open_printer_error (struct device *d)
342 {
343 signal_simple_error ("Failed to open printer", DEVICE_CONNECTION (d));
344 }
345
346
347 /* Helper function */
348 static int
349 msprinter_init_device_internal (struct device *d, char* printer_name)
350 {
351 DEVICE_MSPRINTER_NAME(d) = xstrdup (printer_name);
352
353 if (!OpenPrinter (printer_name, &DEVICE_MSPRINTER_HPRINTER (d), NULL))
354 {
355 DEVICE_MSPRINTER_HPRINTER (d) = NULL;
356 return 0;
357 }
358
359 DEVICE_MSPRINTER_HDC (d) = CreateDC ("WINSPOOL", printer_name,
360 NULL, NULL);
361 if (DEVICE_MSPRINTER_HDC (d) == NULL)
362 return 0;
363
364 DEVICE_MSPRINTER_HCDC(d) =
365 CreateCompatibleDC (DEVICE_MSPRINTER_HDC (d));
366
367 DEVICE_CLASS (d) = (GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), BITSPIXEL)
368 * GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), PLANES)
369 > 1) ? Qcolor : Qmono;
370 return 1;
371 }
372
373 static void
374 msprinter_delete_device_internal (struct device *d)
375 {
376 if (DEVICE_MSPRINTER_HPRINTER (d))
377 ClosePrinter (DEVICE_MSPRINTER_HPRINTER (d));
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;
410
411 /* We do not use printer fon list as we do with the display
412 device. Rather, we allow GDI to pick the closest match to the
413 display font. */
414 DEVICE_MSPRINTER_FONTLIST (d) = Qnil;
415
416 CHECK_STRING (DEVICE_CONNECTION (d));
417
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 }
459 }
460
461 static Lisp_Object
462 msprinter_device_system_metrics (struct device *d,
463 enum device_metrics m)
464 {
465 switch (m)
466 {
467 /* Device sizes - pixel and mm */
468 #define FROB(met, index1, index2) \
469 case DM_##met: \
470 return build_devicecaps_cons \
471 (DEVICE_MSPRINTER_HDC(d), index1, index2);
472
473 FROB (size_device, PHYSICALWIDTH, PHYSICALHEIGHT);
474 FROB (size_device_mm, HORZSIZE, VERTSIZE);
475 FROB (size_workspace, HORZRES, VERTRES);
476 FROB (offset_workspace, PHYSICALOFFSETX, PHYSICALOFFSETY);
477 FROB (device_dpi, LOGPIXELSX, LOGPIXELSY);
478 #undef FROB
479
480 case DM_num_bit_planes:
481 /* this is what X means by bitplanes therefore we ought to be
482 consistent. num planes is always 1 under mswindows and
483 therefore useless */
484 return make_int (GetDeviceCaps (DEVICE_MSPRINTER_HDC(d), BITSPIXEL));
485
486 case DM_num_color_cells: /* Prnters are non-palette devices */
487 case DM_slow_device: /* Animation would be a really bad idea */
488 case DM_security: /* Not provided by windows */
489 return Qzero;
490 }
491
492 /* Do not know such property */
493 return Qunbound;
494 }
495
496 static void
497 msprinter_mark_device (struct device *d)
498 {
499 mark_object (DEVICE_MSPRINTER_FONTLIST (d));
500 mark_object (DEVICE_MSPRINTER_DEVMODE (d));
501 }
502
503 static unsigned int
504 msprinter_device_implementation_flags (void)
505 {
506 return ( XDEVIMPF_PIXEL_GEOMETRY
507 | XDEVIMPF_IS_A_PRINTER
508 | XDEVIMPF_NO_AUTO_REDISPLAY
509 | XDEVIMPF_FRAMELESS_OK );
510 }
511
512 /************************************************************************/
513 /* printer Lisp subroutines */
514 /************************************************************************/
515
516 static void
517 global_free_2_maybe (HGLOBAL hg1, HGLOBAL hg2)
518 {
519 if (hg1 != NULL)
520 GlobalFree (hg1);
521 if (hg2 != NULL)
522 GlobalFree (hg2);
523 }
524
525 static HGLOBAL
526 devmode_to_hglobal (Lisp_Devmode *ldm)
527 {
528 HGLOBAL hg = GlobalAlloc (GHND, XDEVMODE_SIZE (ldm));
529 memcpy (GlobalLock (hg), ldm->devmode, XDEVMODE_SIZE (ldm));
530 GlobalUnlock (hg);
531 return hg;
532 }
533
534 /* Returns 0 if the printer has been deleted due to a fatal I/O error,
535 1 otherwise. */
536 static int
537 sync_printer_with_devmode (struct device* d, DEVMODE* devmode_in,
538 DEVMODE* devmode_out, char* devname)
539 {
540 /* Change connection if the device changed */
541 if (devname != NULL
542 && stricmp (devname, DEVICE_MSPRINTER_NAME(d)) != 0)
543 {
544 Lisp_Object new_connection = build_ext_string (devname, Qmswindows_tstr);
545 struct gcpro gcpro1;
546
547 GCPRO1 (new_connection);
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 */
572 DocumentProperties (NULL,
573 DEVICE_MSPRINTER_HPRINTER(d),
574 DEVICE_MSPRINTER_NAME(d),
575 devmode_out, devmode_in,
576 DM_IN_BUFFER | DM_OUT_BUFFER);
577
578 /* #### ResetDC fails sometimes, Bill only knows why.
579 The solution below looks more like a workaround to me,
580 although it might be fine. --kkm */
581 if (ResetDC (DEVICE_MSPRINTER_HDC (d), devmode_out) == NULL)
582 {
583 DeleteDC (DEVICE_MSPRINTER_HDC (d));
584 DEVICE_MSPRINTER_HDC (d) =
585 CreateDC ("WINSPOOL", DEVICE_MSPRINTER_NAME(d), NULL, devmode_out);
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;
1149 }
1150
1151
1152 /************************************************************************/
1153 /* initialization */ 295 /* initialization */
1154 /************************************************************************/ 296 /************************************************************************/
1155 297
1156 void 298 void
1157 syms_of_device_mswindows (void) 299 syms_of_device_mswindows (void)
1158 { 300 {
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
1170 defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win"); 301 defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win");
1171 defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win"); 302 defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win");
1172 } 303
1173
1174 void
1175 console_type_create_device_mswindows (void)
1176 {
1177 CONSOLE_HAS_METHOD (mswindows, init_device);
1178 CONSOLE_HAS_METHOD (mswindows, finish_init_device);
1179 CONSOLE_HAS_METHOD (mswindows, mark_device);
1180 CONSOLE_HAS_METHOD (mswindows, delete_device);
1181 CONSOLE_HAS_METHOD (mswindows, device_system_metrics);
1182 CONSOLE_HAS_METHOD (mswindows, device_implementation_flags);
1183
1184 CONSOLE_HAS_METHOD (msprinter, init_device);
1185 CONSOLE_HAS_METHOD (msprinter, mark_device);
1186 CONSOLE_HAS_METHOD (msprinter, delete_device);
1187 CONSOLE_HAS_METHOD (msprinter, device_system_metrics);
1188 CONSOLE_HAS_METHOD (msprinter, device_implementation_flags);
1189 }
1190
1191
1192 void
1193 vars_of_device_mswindows (void)
1194 {
1195 DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /* 304 DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /*
1196 Non-nil means convert all-upper case file names to lower case. 305 Non-nil means convert all-upper case file names to lower case.
1197 This applies when performing completions and file name expansion. 306 This applies when performing completions and file name expansion.
1198 */ ); 307 */ );
1199 Vmswindows_downcase_file_names = Qnil; 308 Vmswindows_downcase_file_names = Qnil;
1204 default. Note that it is only useful for files on NTFS volumes, 313 default. Note that it is only useful for files on NTFS volumes,
1205 where hard links are supported. 314 where hard links are supported.
1206 */ ); 315 */ );
1207 Vmswindows_get_true_file_attributes = Qnil; 316 Vmswindows_get_true_file_attributes = Qnil;
1208 } 317 }
318
319 void
320 console_type_create_device_mswindows (void)
321 {
322 CONSOLE_HAS_METHOD (mswindows, init_device);
323 CONSOLE_HAS_METHOD (mswindows, finish_init_device);
324 /* CONSOLE_HAS_METHOD (mswindows, mark_device); */
325 CONSOLE_HAS_METHOD (mswindows, delete_device);
326 CONSOLE_HAS_METHOD (mswindows, device_system_metrics);
327 CONSOLE_HAS_METHOD (mswindows, device_implementation_flags);
328 }
329
330 void
331 vars_of_device_mswindows (void)
332 {
333 }