XEmacs 21.2.30 "Hygeia".
[chise/xemacs-chise.git.1] / src / device-msw.c
1 /* device functions for mswindows.
2    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
3    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
4
5 This file is part of XEmacs.
6
7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 2, or (at your option) any
10 later version.
11
12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with XEmacs; see the file COPYING.  If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 /* Synched up with: Not in FSF. */
23
24 /* Authorship:
25
26    Original authors: Jamie Zawinski and the FSF
27    Rewritten by Ben Wing and Chuck Thompson.
28    Rewritten for mswindows by Jonathan Harris, November 1997 for 21.0.
29 */
30
31
32 #include <config.h>
33 #include "lisp.h"
34
35 #include "console-msw.h"
36 #include "console-stream.h"
37 #include "objects-msw.h"
38 #include "events.h"
39 #include "faces.h"
40 #include "frame.h"
41 #include "sysdep.h"
42
43 #include <winspool.h>
44
45 /* win32 DDE management library globals */
46 #ifdef HAVE_DRAGNDROP
47 DWORD mswindows_dde_mlid;
48 HSZ mswindows_dde_service;
49 HSZ mswindows_dde_topic_system;
50 HSZ mswindows_dde_item_open;
51 #endif
52
53 /* Control conversion of upper case file names to lower case.
54    nil means no, t means yes. */
55 Lisp_Object Vmswindows_downcase_file_names;
56
57 /* Control whether stat() attempts to determine file type and link count
58    exactly, at the expense of slower operation.  Since true hard links
59    are supported on NTFS volumes, this is only relevant on NT.  */
60 Lisp_Object Vmswindows_get_true_file_attributes;
61
62 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win;
63
64
65 /************************************************************************/
66 /*                               helpers                                */
67 /************************************************************************/
68
69 static Lisp_Object
70 build_syscolor_string (int idx)
71 {
72   return (idx < 0 ? Qnil : mswindows_color_to_string (GetSysColor (idx)));
73 }
74
75 static Lisp_Object
76 build_syscolor_cons (int index1, int index2)
77 {
78   Lisp_Object color1, color2;
79   struct gcpro gcpro1;
80   GCPRO1 (color1);
81   color1 = build_syscolor_string (index1);
82   color2 = build_syscolor_string (index2);
83   RETURN_UNGCPRO (Fcons (color1, color2));
84 }
85
86 static Lisp_Object
87 build_sysmetrics_cons (int index1, int index2)
88 {
89   return Fcons (index1 < 0 ? Qnil : make_int (GetSystemMetrics (index1)),
90                 index2 < 0 ? Qnil : make_int (GetSystemMetrics (index2)));
91 }
92
93 static Lisp_Object
94 build_devicecaps_cons (HDC hdc, int index1, int index2)
95 {
96   return Fcons (index1 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index1)),
97                 index2 < 0 ? Qnil : make_int (GetDeviceCaps (hdc, index2)));
98 }
99
100
101 \f
102 /************************************************************************/
103 /*                          display methods                             */
104 /************************************************************************/
105
106 static void
107 mswindows_init_device (struct device *d, Lisp_Object props)
108 {
109   WNDCLASSEX wc;
110   HDC hdc;
111
112   DEVICE_CLASS (d) = Qcolor;
113   DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1;
114   init_baud_rate (d);
115   init_one_device (d);
116
117   d->device_data = xnew_and_zero (struct mswindows_device);
118   hdc = CreateCompatibleDC (NULL);
119   assert (hdc!=NULL);
120   DEVICE_MSWINDOWS_LOGPIXELSX(d) =  GetDeviceCaps(hdc, LOGPIXELSX);
121   DEVICE_MSWINDOWS_LOGPIXELSY(d) =  GetDeviceCaps(hdc, LOGPIXELSY);
122   DEVICE_MSWINDOWS_PLANES(d) = GetDeviceCaps(hdc, PLANES);
123   /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS,
124      what should we return for a non-palette-based device? */
125   DEVICE_MSWINDOWS_CELLS(d) = GetDeviceCaps(hdc, SIZEPALETTE);
126   DEVICE_MSWINDOWS_HORZRES(d) = GetDeviceCaps(hdc, HORZRES);
127   DEVICE_MSWINDOWS_VERTRES(d) = GetDeviceCaps(hdc, VERTRES);
128   DEVICE_MSWINDOWS_HORZSIZE(d) = GetDeviceCaps(hdc, HORZSIZE);
129   DEVICE_MSWINDOWS_VERTSIZE(d) = GetDeviceCaps(hdc, VERTSIZE);
130   DEVICE_MSWINDOWS_BITSPIXEL(d) = GetDeviceCaps(hdc, BITSPIXEL);
131   DEVICE_MSWINDOWS_FONTLIST (d) = mswindows_enumerate_fonts (hdc);
132
133   DeleteDC (hdc);
134
135   /* Register the main window class */
136   wc.cbSize = sizeof (WNDCLASSEX);
137   wc.style = CS_OWNDC;  /* One DC per window */
138   wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc;
139   wc.cbClsExtra = 0;
140   wc.cbWndExtra = MSWINDOWS_WINDOW_EXTRA_BYTES;
141   /* This must match whatever is passed to CreateWIndowEx, NULL is ok
142      for this. */
143   wc.hInstance = NULL;  
144   wc.hIcon = LoadIcon (GetModuleHandle(NULL), XEMACS_CLASS);
145   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
146   /* Background brush is only used during sizing, when XEmacs cannot
147      take over */
148   wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
149   wc.lpszMenuName = NULL;
150
151   wc.lpszClassName = XEMACS_CLASS;
152   wc.hIconSm = (HICON) LoadImage (GetModuleHandle (NULL), XEMACS_CLASS,
153                           IMAGE_ICON, 16, 16, 0);
154   RegisterClassEx (&wc);
155
156 #ifdef HAVE_WIDGETS
157   xzero (wc);
158   /* Register the main window class */
159   wc.cbSize = sizeof (WNDCLASSEX);
160   wc.lpfnWndProc = (WNDPROC) mswindows_control_wnd_proc;
161   wc.lpszClassName = XEMACS_CONTROL_CLASS;
162   wc.hInstance = NULL;
163   RegisterClassEx (&wc);
164 #endif
165
166 #if defined (HAVE_TOOLBARS) || defined (HAVE_WIDGETS)
167   InitCommonControls ();
168 #endif
169 }
170
171 static void
172 mswindows_finish_init_device (struct device *d, Lisp_Object props)
173 {
174   /* Initialize DDE management library and our related globals. We execute a
175    * dde Open("file") by simulating a drop, so this depends on dnd support. */
176 #ifdef HAVE_DRAGNDROP
177   mswindows_dde_mlid = 0;
178   DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback,
179                  APPCMD_FILTERINITS|CBF_FAIL_SELFCONNECTIONS|CBF_FAIL_ADVISES|
180                  CBF_FAIL_POKES|CBF_FAIL_REQUESTS|CBF_SKIP_ALLNOTIFICATIONS, 0);
181   
182   mswindows_dde_service = DdeCreateStringHandle (mswindows_dde_mlid, XEMACS_CLASS, 0);
183   mswindows_dde_topic_system = DdeCreateStringHandle (mswindows_dde_mlid, SZDDESYS_TOPIC, 0);
184   mswindows_dde_item_open = DdeCreateStringHandle (mswindows_dde_mlid,
185                                                    TEXT(MSWINDOWS_DDE_ITEM_OPEN), 0);
186   DdeNameService (mswindows_dde_mlid, mswindows_dde_service, 0L, DNS_REGISTER);
187 #endif
188 }
189
190 static void
191 mswindows_delete_device (struct device *d)
192 {
193 #ifdef HAVE_DRAGNDROP
194   DdeNameService (mswindows_dde_mlid, 0L, 0L, DNS_UNREGISTER);
195   DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_item_open);
196   DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_topic_system);
197   DdeFreeStringHandle (mswindows_dde_mlid, mswindows_dde_service);
198   DdeUninitialize (mswindows_dde_mlid);
199 #endif
200
201   free (d->device_data);
202 }
203
204 static void
205 mswindows_mark_device (struct device *d)
206 {
207   mark_object (DEVICE_MSWINDOWS_FONTLIST (d));
208 }
209
210 static Lisp_Object
211 mswindows_device_system_metrics (struct device *d,
212                                  enum device_metrics m)
213 {
214   switch (m)
215     {
216     case DM_size_device:
217       return Fcons (make_int (DEVICE_MSWINDOWS_HORZRES(d)),
218                     make_int (DEVICE_MSWINDOWS_VERTRES(d)));
219       break;
220     case DM_device_dpi:
221       return Fcons (make_int (DEVICE_MSWINDOWS_LOGPIXELSX(d)),
222                     make_int (DEVICE_MSWINDOWS_LOGPIXELSY(d)));
223       break;
224     case DM_size_device_mm:
225       return Fcons (make_int (DEVICE_MSWINDOWS_HORZSIZE(d)),
226                     make_int (DEVICE_MSWINDOWS_VERTSIZE(d)));
227       break;
228     case DM_num_bit_planes:
229       /* this is what X means by bitplanes therefore we ought to be
230          consistent. num planes is always 1 under mswindows and
231          therefore useless */
232       return make_int (DEVICE_MSWINDOWS_BITSPIXEL(d));
233       break;
234     case DM_num_color_cells:
235       return make_int (DEVICE_MSWINDOWS_CELLS(d));
236       break;
237
238       /*** Colors ***/
239 #define FROB(met, fore, back)                           \
240     case DM_##met:                                      \
241       return build_syscolor_cons (fore, back);
242       
243       FROB (color_default, COLOR_WINDOWTEXT, COLOR_WINDOW);
244       FROB (color_select, COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHT);
245       FROB (color_balloon, COLOR_INFOTEXT, COLOR_INFOBK);
246       FROB (color_3d_face, COLOR_BTNTEXT, COLOR_BTNFACE);
247       FROB (color_3d_light, COLOR_3DHILIGHT, COLOR_3DLIGHT);
248       FROB (color_3d_dark, COLOR_3DDKSHADOW, COLOR_3DSHADOW);
249       FROB (color_menu, COLOR_MENUTEXT, COLOR_MENU);
250       FROB (color_menu_highlight, COLOR_HIGHLIGHTTEXT, COLOR_HIGHLIGHT);
251       FROB (color_menu_button, COLOR_MENUTEXT, COLOR_MENU);
252       FROB (color_menu_disabled, COLOR_GRAYTEXT, COLOR_MENU);
253       FROB (color_toolbar, COLOR_BTNTEXT, COLOR_BTNFACE);
254       FROB (color_scrollbar, COLOR_CAPTIONTEXT, COLOR_SCROLLBAR);
255       FROB (color_desktop, -1, COLOR_DESKTOP);
256       FROB (color_workspace, -1, COLOR_APPWORKSPACE);
257 #undef FROB
258
259       /*** Sizes ***/
260 #define FROB(met, index1, index2)                       \
261     case DM_##met:                                      \
262       return build_sysmetrics_cons (index1, index2);
263
264       FROB (size_cursor, SM_CXCURSOR, SM_CYCURSOR);
265       FROB (size_scrollbar, SM_CXVSCROLL, SM_CYHSCROLL);
266       FROB (size_menu, -1, SM_CYMENU);
267       FROB (size_icon, SM_CXICON, SM_CYICON);
268       FROB (size_icon_small, SM_CXSMICON, SM_CYSMICON);
269 #undef FROB
270
271     case DM_size_workspace:
272       {
273         RECT rc;
274         SystemParametersInfo (SPI_GETWORKAREA, 0, &rc, 0);
275         return Fcons (make_int (rc.right - rc.left),
276                       make_int (rc.bottom - rc.top));
277       }
278       /*
279         case DM_size_toolbar:
280         case DM_size_toolbar_button:
281         case DM_size_toolbar_border:
282       */
283
284       /*** Features ***/
285 #define FROB(met, index)                        \
286     case DM_##met:                              \
287       return make_int (GetSystemMetrics (index));
288
289       FROB (mouse_buttons, SM_CMOUSEBUTTONS);
290       FROB (swap_buttons, SM_SWAPBUTTON);
291       FROB (show_sounds, SM_SHOWSOUNDS);
292       FROB (slow_device, SM_SLOWMACHINE);
293       FROB (security, SM_SECURE);
294 #undef FROB
295
296     }
297
298   /* Do not know such property */
299   return Qunbound;
300 }
301
302 static unsigned int
303 mswindows_device_implementation_flags (void)
304 {
305   return XDEVIMPF_PIXEL_GEOMETRY;
306 }
307
308 \f
309 /************************************************************************/
310 /*                          printer methods                             */
311 /************************************************************************/
312
313 static void
314 signal_open_printer_error (struct device *d)
315 {
316   signal_simple_error ("Failed to open printer", DEVICE_CONNECTION (d));
317 }
318
319 static void
320 msprinter_init_device (struct device *d, Lisp_Object props)
321 {
322   char* printer_name;
323
324   DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1;
325
326   CHECK_STRING (DEVICE_CONNECTION (d));
327
328   TO_EXTERNAL_FORMAT (LISP_STRING, DEVICE_CONNECTION (d),
329                       C_STRING_ALLOCA, printer_name,
330                       Qctext);
331
332   d->device_data = xnew_and_zero (struct msprinter_device);
333
334   DEVICE_MSPRINTER_NAME(d) = xstrdup (printer_name);
335
336   if (!OpenPrinter (printer_name, &DEVICE_MSPRINTER_HPRINTER (d), NULL))
337     {
338       DEVICE_MSPRINTER_HPRINTER (d) = NULL;
339       signal_open_printer_error (d);
340     }
341
342   DEVICE_MSPRINTER_HDC (d) = CreateDC ("WINSPOOL", printer_name,
343                                        NULL, NULL);
344   if (DEVICE_MSPRINTER_HDC (d) == NULL)
345     signal_open_printer_error (d);
346
347   /* Determinie DEVMODE size and store the default DEVMODE */
348   DEVICE_MSPRINTER_DEVMODE_SIZE(d) = 
349     DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d),
350                         printer_name, NULL, NULL, 0);
351   if (DEVICE_MSPRINTER_DEVMODE_SIZE(d) <= 0)
352     signal_open_printer_error (d);
353
354   DEVICE_MSPRINTER_DEVMODE(d) =
355     (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d));
356   DocumentProperties (NULL, DEVICE_MSPRINTER_HPRINTER(d),
357                       printer_name, DEVICE_MSPRINTER_DEVMODE(d),
358                       NULL, DM_OUT_BUFFER);
359
360   /* We do not use printer fon list as we do with the display
361      device. Rather, we allow GDI to pick the closest match to the
362      display font. */
363   DEVICE_MSPRINTER_FONTLIST (d) = Qnil;
364
365   DEVICE_CLASS (d) = (GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), BITSPIXEL)
366                       * GetDeviceCaps (DEVICE_MSPRINTER_HDC (d), PLANES)
367                       > 1) ? Qcolor : Qmono;
368 }
369
370 static Lisp_Object
371 msprinter_device_system_metrics (struct device *d,
372                                  enum device_metrics m)
373 {
374   switch (m)
375     {
376       /* Device sizes - pixel and mm */
377 #define FROB(met, index1, index2)                       \
378     case DM_##met:                                      \
379       return build_devicecaps_cons                      \
380          (DEVICE_MSPRINTER_HDC(d), index1, index2);
381
382       FROB (size_device, PHYSICALWIDTH, PHYSICALHEIGHT);
383       FROB (size_device_mm, HORZSIZE, VERTSIZE);
384       FROB (size_workspace, HORZRES, VERTRES);
385       FROB (offset_workspace, PHYSICALOFFSETX, PHYSICALOFFSETY);
386       FROB (device_dpi, LOGPIXELSX, LOGPIXELSY);
387 #undef FROB
388
389     case DM_num_bit_planes:
390       /* this is what X means by bitplanes therefore we ought to be
391          consistent. num planes is always 1 under mswindows and
392          therefore useless */
393       return make_int (GetDeviceCaps (DEVICE_MSPRINTER_HDC(d), BITSPIXEL));
394
395     case DM_num_color_cells:    /* Prnters are non-palette devices */
396     case DM_slow_device:        /* Animation would be a really bad idea */
397     case DM_security:           /* Not provided by windows */
398       return Qzero;
399     }
400
401   /* Do not know such property */
402   return Qunbound;
403 }
404
405 static void
406 msprinter_delete_device (struct device *d)
407 {
408   if (d->device_data)
409     {
410       if (DEVICE_MSPRINTER_HPRINTER (d))
411         ClosePrinter (DEVICE_MSPRINTER_HPRINTER (d));
412       if (DEVICE_MSPRINTER_HDC (d))
413         DeleteDC (DEVICE_MSPRINTER_HDC (d));
414       if (DEVICE_MSPRINTER_NAME (d))
415         free (DEVICE_MSPRINTER_NAME (d));
416       if (DEVICE_MSPRINTER_DEVMODE (d))
417         free (DEVICE_MSPRINTER_DEVMODE (d));
418       if (DEVICE_MSPRINTER_DEVMODE_MIRROR (d))
419         free (DEVICE_MSPRINTER_DEVMODE_MIRROR (d));
420
421       free (d->device_data);
422     }
423 }
424
425 static void
426 msprinter_mark_device (struct device *d)
427 {
428   mark_object (DEVICE_MSPRINTER_FONTLIST (d));
429 }
430
431 static unsigned int
432 msprinter_device_implementation_flags (void)
433 {
434   return (  XDEVIMPF_PIXEL_GEOMETRY
435           | XDEVIMPF_IS_A_PRINTER
436           | XDEVIMPF_NO_AUTO_REDISPLAY
437           | XDEVIMPF_FRAMELESS_OK );
438 }
439
440 \f
441 /************************************************************************/
442 /*                      printer external functions                      */
443 /************************************************************************/
444
445 /* 
446  * Return a copy of default DEVMODE. The copy returned is in
447  * a static buffer which will be overwritten by next call.
448  */
449 DEVMODE*
450 msprinter_get_devmode_copy (struct device *d)
451 {
452   assert (DEVICE_MSPRINTER_P (d));
453
454   if (DEVICE_MSPRINTER_DEVMODE_MIRROR(d) == NULL)
455     DEVICE_MSPRINTER_DEVMODE_MIRROR(d) = 
456       (DEVMODE*) xmalloc (DEVICE_MSPRINTER_DEVMODE_SIZE(d));
457
458   memcpy (DEVICE_MSPRINTER_DEVMODE_MIRROR(d),
459           DEVICE_MSPRINTER_DEVMODE(d),
460           DEVICE_MSPRINTER_DEVMODE_SIZE(d));
461
462   return DEVICE_MSPRINTER_DEVMODE_MIRROR(d);
463 }
464
465 /*
466  * Apply settings from the DEVMODE. The settings are considered
467  * incremental to the default DEVMODE, so that changes in the
468  * passed structure supercede parameters of the printer.
469  *
470  * The passed structure is overwritten by the fuction call;
471  * complete printer settings are returned.
472  */
473 void
474 msprinter_apply_devmode (struct device *d, DEVMODE *devmode)
475 {
476   assert (DEVICE_MSPRINTER_P (d));
477
478   DocumentProperties (NULL,
479                       DEVICE_MSPRINTER_HPRINTER(d),
480                       DEVICE_MSPRINTER_NAME(d),
481                       devmode, devmode,
482                       DM_IN_BUFFER | DM_OUT_BUFFER);
483
484   ResetDC (DEVICE_MSPRINTER_HDC (d), devmode);
485 }
486
487 \f
488 /************************************************************************/
489 /*                            initialization                            */
490 /************************************************************************/
491
492 void
493 syms_of_device_mswindows (void)
494 {
495   defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win");
496   defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win");
497 }
498
499 void
500 console_type_create_device_mswindows (void)
501 {
502   CONSOLE_HAS_METHOD (mswindows, init_device);
503   CONSOLE_HAS_METHOD (mswindows, finish_init_device);
504   CONSOLE_HAS_METHOD (mswindows, mark_device);
505   CONSOLE_HAS_METHOD (mswindows, delete_device);
506   CONSOLE_HAS_METHOD (mswindows, device_system_metrics);
507   CONSOLE_HAS_METHOD (mswindows, device_implementation_flags);
508
509   CONSOLE_HAS_METHOD (msprinter, init_device);
510   CONSOLE_HAS_METHOD (msprinter, mark_device);
511   CONSOLE_HAS_METHOD (msprinter, delete_device);
512   CONSOLE_HAS_METHOD (msprinter, device_system_metrics);
513   CONSOLE_HAS_METHOD (msprinter, device_implementation_flags);
514 }
515
516
517 void
518 vars_of_device_mswindows (void)
519 {
520   DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /*
521 Non-nil means convert all-upper case file names to lower case.
522 This applies when performing completions and file name expansion.
523 */ );
524   Vmswindows_downcase_file_names = Qnil;
525
526   DEFVAR_LISP ("mswindows-get-true-file-attributes", &Vmswindows_get_true_file_attributes /*
527 Non-nil means determine accurate link count in file-attributes.
528 This option slows down file-attributes noticeably, so is disabled by
529 default.  Note that it is only useful for files on NTFS volumes,
530 where hard links are supported.
531 */ );
532   Vmswindows_get_true_file_attributes = Qnil;
533 }