266c014d78c5538b79cc59624162465c9bbbef90
[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 "events.h"
38 #include "faces.h"
39 #include "frame.h"
40 #include "sysdep.h"
41
42 #ifndef __CYGWIN32__
43 #include <commctrl.h>
44 #else
45 #define FONTENUMPROC FONTENUMEXPROC
46 #define ntmTm ntmentm
47 #endif
48
49 /* win32 DDE management library globals */
50 #ifdef HAVE_DRAGNDROP
51 DWORD mswindows_dde_mlid;
52 HSZ mswindows_dde_service;
53 HSZ mswindows_dde_topic_system;
54 HSZ mswindows_dde_item_open;
55 #endif
56
57 /* Control conversion of upper case file names to lower case.
58    nil means no, t means yes. */
59 Lisp_Object Vmswindows_downcase_file_names;
60
61 /* Control whether stat() attempts to determine file type and link count
62    exactly, at the expense of slower operation.  Since true hard links
63    are supported on NTFS volumes, this is only relevant on NT.  */
64 Lisp_Object Vmswindows_get_true_file_attributes;
65
66 Lisp_Object Qinit_pre_mswindows_win, Qinit_post_mswindows_win;
67
68 struct font_enum_t
69 {
70   HDC hdc;
71   struct device *d;
72 };
73
74
75 /************************************************************************/
76 /*                               helpers                                */
77 /************************************************************************/
78
79 static int CALLBACK
80 font_enum_callback_2 (ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, 
81                       int FontType, struct font_enum_t *font_enum)
82 {
83   struct mswindows_font_enum *fontlist, **fonthead;
84   char fontname[MSW_FONTSIZE];
85
86   /* The enumerated font weights are not to be trusted because:
87    *  a) lpelfe->elfStyle is only filled in for TrueType fonts.
88    *  b) Not all Bold and Italic styles of all fonts (inluding some Vector,
89    *     Truetype and Raster fonts) are enumerated.
90    * I guess that fonts for which Bold and Italic styles are generated
91    * 'on-the-fly' are not enumerated. It would be overly restrictive to
92    * disallow Bold And Italic weights for these fonts, so we just leave
93    * weights unspecified. This means that we have to weed out duplicates of
94    * those fonts that do get enumerated with different weights. */
95
96   if (FontType == 0 /*vector*/ || FontType == TRUETYPE_FONTTYPE)
97     /* Scalable, so leave pointsize blank */
98     sprintf (fontname, "%s::::%s", lpelfe->elfLogFont.lfFaceName,
99              lpelfe->elfScript);
100   else
101     /* Formula for pointsize->height from LOGFONT docs in Platform SDK */
102     sprintf (fontname, "%s::%d::%s", lpelfe->elfLogFont.lfFaceName,
103              MulDiv (lpntme->ntmTm.tmHeight - lpntme->ntmTm.tmInternalLeading,
104                      72, DEVICE_MSWINDOWS_LOGPIXELSY (font_enum->d)),
105              lpelfe->elfScript);
106
107   fonthead = &DEVICE_MSWINDOWS_FONTLIST (font_enum->d);
108   fontlist = *fonthead;
109   while (fontlist)
110     if (!strcmp (fontname, fontlist->fontname))
111       return 1;         /* found a duplicate */
112     else
113       fontlist = fontlist->next;
114
115   /* Insert entry at head */
116   fontlist = *fonthead;
117   *fonthead = xmalloc (sizeof (struct mswindows_font_enum));
118   if (*fonthead == NULL)
119     {
120       *fonthead = fontlist;
121       return 0;
122     }
123   strcpy ((*fonthead)->fontname, fontname);
124   (*fonthead)->next = fontlist;
125   return 1;
126 }
127
128 static int CALLBACK
129 font_enum_callback_1 (ENUMLOGFONTEX *lpelfe, NEWTEXTMETRICEX *lpntme, 
130                       int FontType, struct font_enum_t *font_enum)
131 {
132   /* This function gets called once per facename per character set.
133    * We call a second callback to enumerate the fonts in each facename */
134   return EnumFontFamiliesEx (font_enum->hdc, &lpelfe->elfLogFont,
135                              (FONTENUMPROC) font_enum_callback_2,
136                              (LPARAM) font_enum, 0);
137 }
138
139 static Lisp_Object
140 build_syscolor_string (int index)
141 {
142   DWORD clr;
143   char buf[16];
144
145   if (index < 0)
146     return Qnil;
147
148   clr = GetSysColor (index);
149   sprintf (buf, "#%02X%02X%02X",
150            GetRValue (clr),
151            GetGValue (clr),
152            GetBValue (clr));
153   return build_string (buf);
154 }
155
156 static Lisp_Object
157 build_syscolor_cons (int index1, int index2)
158 {
159   Lisp_Object color1, color2;
160   struct gcpro gcpro1;
161   GCPRO1 (color1);
162   color1 = build_syscolor_string (index1);
163   color2 = build_syscolor_string (index2);
164   RETURN_UNGCPRO (Fcons (color1, color2));
165 }
166
167 static Lisp_Object
168 build_sysmetrics_cons (int index1, int index2)
169 {
170   return Fcons (index1 < 0 ? Qnil : make_int (GetSystemMetrics (index1)),
171                 index2 < 0 ? Qnil : make_int (GetSystemMetrics (index2)));
172 }
173
174
175 \f
176 /************************************************************************/
177 /*                               methods                                */
178 /************************************************************************/
179
180 static void
181 mswindows_init_device (struct device *d, Lisp_Object props)
182 {
183   WNDCLASSEX wc;
184   HDC hdc;
185   LOGFONT logfont;
186   struct font_enum_t font_enum;
187
188   DEVICE_CLASS (d) = Qcolor;
189   DEVICE_INFD (d) = DEVICE_OUTFD (d) = -1;
190   init_baud_rate (d);
191   init_one_device (d);
192
193   d->device_data = xnew_and_zero (struct mswindows_device);
194   hdc = CreateCompatibleDC (NULL);
195   assert (hdc!=NULL);
196   DEVICE_MSWINDOWS_LOGPIXELSX(d) =  GetDeviceCaps(hdc, LOGPIXELSX);
197   DEVICE_MSWINDOWS_LOGPIXELSY(d) =  GetDeviceCaps(hdc, LOGPIXELSY);
198   DEVICE_MSWINDOWS_PLANES(d) = GetDeviceCaps(hdc, PLANES);
199   /* #### SIZEPALETTE only valid if RC_PALETTE bit set in RASTERCAPS,
200      what should we return for a non-palette-based device? */
201   DEVICE_MSWINDOWS_CELLS(d) = GetDeviceCaps(hdc, SIZEPALETTE);
202   DEVICE_MSWINDOWS_HORZRES(d) = GetDeviceCaps(hdc, HORZRES);
203   DEVICE_MSWINDOWS_VERTRES(d) = GetDeviceCaps(hdc, VERTRES);
204   DEVICE_MSWINDOWS_HORZSIZE(d) = GetDeviceCaps(hdc, HORZSIZE);
205   DEVICE_MSWINDOWS_VERTSIZE(d) = GetDeviceCaps(hdc, VERTSIZE);
206   DEVICE_MSWINDOWS_BITSPIXEL(d) = GetDeviceCaps(hdc, BITSPIXEL);
207
208   DEVICE_MSWINDOWS_FONTLIST (d) = NULL;
209   logfont.lfCharSet = DEFAULT_CHARSET;
210   logfont.lfFaceName[0] = '\0';
211   logfont.lfPitchAndFamily = DEFAULT_PITCH;
212   font_enum.hdc = hdc;
213   font_enum.d = d;
214   EnumFontFamiliesEx (hdc, &logfont, (FONTENUMPROC) font_enum_callback_1,
215                       (LPARAM) (&font_enum), 0);
216   DeleteDC (hdc);
217
218   /* Register the main window class */
219   wc.cbSize = sizeof (WNDCLASSEX);
220   wc.style = CS_OWNDC;  /* One DC per window */
221   wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc;
222   wc.cbClsExtra = 0;
223   wc.cbWndExtra = MSWINDOWS_WINDOW_EXTRA_BYTES;
224   wc.hInstance = NULL;  /* ? */
225   wc.hIcon = LoadIcon (GetModuleHandle(NULL), XEMACS_CLASS);
226   wc.hCursor = LoadCursor (NULL, IDC_ARROW);
227   /* Background brush is only used during sizing, when XEmacs cannot
228      take over */
229   wc.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE + 1);
230   wc.lpszMenuName = NULL;
231
232   wc.lpszClassName = XEMACS_CLASS;
233   wc.hIconSm = LoadImage (GetModuleHandle (NULL), XEMACS_CLASS,
234                           IMAGE_ICON, 16, 16, 0);
235   RegisterClassEx (&wc);
236 #ifdef HAVE_TOOLBARS
237   InitCommonControls ();
238 #endif
239 }
240
241 static void
242 mswindows_finish_init_device (struct device *d, Lisp_Object props)
243 {
244   /* Initialise DDE management library and our related globals. We execute a
245    * dde Open("file") by simulating a drop, so this depends on dnd support. */
246 #ifdef HAVE_DRAGNDROP
247   mswindows_dde_mlid = 0;
248   DdeInitialize (&mswindows_dde_mlid, (PFNCALLBACK)mswindows_dde_callback,
249                  APPCMD_FILTERINITS|CBF_FAIL_SELFCONNECTIONS|CBF_FAIL_ADVISES|
250                  CBF_FAIL_POKES|CBF_FAIL_REQUESTS|CBF_SKIP_ALLNOTIFICATIONS, 0);
251   
252   mswindows_dde_service = DdeCreateStringHandle (mswindows_dde_mlid, XEMACS_CLASS, 0);
253   mswindows_dde_topic_system = DdeCreateStringHandle (mswindows_dde_mlid, SZDDESYS_TOPIC, 0);
254   mswindows_dde_item_open = DdeCreateStringHandle (mswindows_dde_mlid,
255                                                    TEXT(MSWINDOWS_DDE_ITEM_OPEN), 0);
256   DdeNameService (mswindows_dde_mlid, mswindows_dde_service, 0L, DNS_REGISTER);
257 #endif
258 }
259
260 static void
261 mswindows_delete_device (struct device *d)
262 {
263   struct mswindows_font_enum *fontlist, *next;
264
265   fontlist = DEVICE_MSWINDOWS_FONTLIST (d);
266   while (fontlist)
267     {
268       next = fontlist->next;
269       free (fontlist);
270       fontlist = next;
271     }
272
273 #ifdef HAVE_DRAGNDROP
274   DdeNameService (mswindows_dde_mlid, 0L, 0L, DNS_REGISTER);
275   DdeUninitialize (mswindows_dde_mlid);
276 #endif
277
278   free (d->device_data);
279 }
280
281 static Lisp_Object
282 mswindows_device_system_metrics (struct device *d,
283                                  enum device_metrics m)
284 {
285   switch (m)
286     {
287     case DM_size_device:
288       return Fcons (make_int (DEVICE_MSWINDOWS_HORZRES(d)),
289                     make_int (DEVICE_MSWINDOWS_VERTRES(d)));
290       break;
291     case DM_size_device_mm:
292       return Fcons (make_int (DEVICE_MSWINDOWS_HORZSIZE(d)),
293                     make_int (DEVICE_MSWINDOWS_VERTSIZE(d)));
294       break;
295     case DM_num_bit_planes:
296       /* this is what X means by bitplanes therefore we ought to be
297          consistent. num planes is always 1 under mswindows and
298          therefore useless */
299       return make_int (DEVICE_MSWINDOWS_BITSPIXEL(d));
300       break;
301     case DM_num_color_cells:
302       return make_int (DEVICE_MSWINDOWS_CELLS(d));
303       break;
304
305       /*** Colors ***/
306 #define FROB(met, index1, index2)                       \
307     case DM_##met:                                      \
308       return build_syscolor_cons (index1, index2);
309       
310       FROB (color_default, COLOR_WINDOW, COLOR_WINDOWTEXT);
311       FROB (color_select, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT);
312       FROB (color_balloon, COLOR_INFOBK, COLOR_INFOTEXT);
313       FROB (color_3d_face, COLOR_3DFACE, COLOR_BTNTEXT);
314       FROB (color_3d_light, COLOR_3DLIGHT, COLOR_3DHILIGHT);
315       FROB (color_3d_dark, COLOR_3DSHADOW, COLOR_3DDKSHADOW);
316       FROB (color_menu, COLOR_MENU, COLOR_MENUTEXT);
317       FROB (color_menu_highlight, COLOR_HIGHLIGHT, COLOR_HIGHLIGHTTEXT);
318       FROB (color_menu_button, COLOR_MENU, COLOR_MENUTEXT);
319       FROB (color_menu_disabled, COLOR_MENU, COLOR_GRAYTEXT);
320       FROB (color_toolbar, COLOR_BTNFACE, COLOR_BTNTEXT);
321       FROB (color_scrollbar, COLOR_SCROLLBAR, COLOR_CAPTIONTEXT);
322       FROB (color_desktop, -1, COLOR_DESKTOP);
323       FROB (color_workspace, -1, COLOR_APPWORKSPACE);
324 #undef FROB
325
326       /*** Sizes ***/
327 #define FROB(met, index1, index2)                       \
328     case DM_##met:                                      \
329       return build_sysmetrics_cons (index1, index2);
330
331       FROB (size_cursor, SM_CXCURSOR, SM_CYCURSOR);
332       FROB (size_scrollbar, SM_CXVSCROLL, SM_CYHSCROLL);
333       FROB (size_menu, -1, SM_CYMENU);
334       FROB (size_icon, SM_CXICON, SM_CYICON);
335       FROB (size_icon_small, SM_CXSMICON, SM_CYSMICON);
336 #undef FROB
337
338     case DM_size_workspace:
339       {
340         RECT rc;
341         SystemParametersInfo (SPI_GETWORKAREA, 0, &rc, 0);
342         return Fcons (make_int (rc.right - rc.left),
343                       make_int (rc.bottom - rc.top));
344       }
345       /*
346         case DM_size_toolbar:
347         case DM_size_toolbar_button:
348         case DM_size_toolbar_border:
349       */
350
351       /*** Features ***/
352 #define FROB(met, index)                        \
353     case DM_##met:                              \
354       return make_int (GetSystemMetrics (index));
355
356       FROB (mouse_buttons, SM_CMOUSEBUTTONS);
357       FROB (swap_buttons, SM_SWAPBUTTON);
358       FROB (show_sounds, SM_SHOWSOUNDS);
359       FROB (slow_device, SM_SLOWMACHINE);
360       FROB (security, SM_SECURE);
361 #undef FROB
362
363     }
364
365   /* Do not know such property */
366   return Qunbound;
367 }
368
369 static unsigned int
370 mswindows_device_implementation_flags (void)
371 {
372   return XDEVIMPF_PIXEL_GEOMETRY;
373 }
374
375 \f
376 /************************************************************************/
377 /*                            initialization                            */
378 /************************************************************************/
379
380 void
381 syms_of_device_mswindows (void)
382 {
383   defsymbol (&Qinit_pre_mswindows_win, "init-pre-mswindows-win");
384   defsymbol (&Qinit_post_mswindows_win, "init-post-mswindows-win");
385
386   DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /*
387 Non-nil means convert all-upper case file names to lower case.
388 This applies when performing completions and file name expansion.*/ );
389   Vmswindows_downcase_file_names = Qnil;
390
391   DEFVAR_LISP ("mswindows-get-true-file-attributes", &Vmswindows_get_true_file_attributes /*
392     "Non-nil means determine accurate link count in file-attributes.
393 This option slows down file-attributes noticeably, so is disabled by
394 default.  Note that it is only useful for files on NTFS volumes,
395 where hard links are supported.
396 */ );
397   Vmswindows_get_true_file_attributes = Qnil;
398 }
399
400 void
401 console_type_create_device_mswindows (void)
402 {
403   CONSOLE_HAS_METHOD (mswindows, init_device);
404   CONSOLE_HAS_METHOD (mswindows, finish_init_device);
405 /*  CONSOLE_HAS_METHOD (mswindows, mark_device); */
406   CONSOLE_HAS_METHOD (mswindows, delete_device);
407   CONSOLE_HAS_METHOD (mswindows, device_system_metrics);
408   CONSOLE_HAS_METHOD (mswindows, device_implementation_flags);
409 }
410
411 void
412 vars_of_device_mswindows (void)
413 {
414 }