Mercurial > hg > xemacs-beta
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 } |