1/* Graphical user interface functions for the Microsoft W32 API.
2   Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3                 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING.  If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.  */
21
22/* Added by Kevin Gallo */
23
24#include <config.h>
25
26#include <signal.h>
27#include <stdio.h>
28#include <limits.h>
29#include <errno.h>
30
31#include "lisp.h"
32#include "charset.h"
33#include "dispextern.h"
34#include "w32term.h"
35#include "keyboard.h"
36#include "frame.h"
37#include "window.h"
38#include "buffer.h"
39#include "fontset.h"
40#include "intervals.h"
41#include "blockinput.h"
42#include "epaths.h"
43#include "w32heap.h"
44#include "termhooks.h"
45#include "coding.h"
46#include "ccl.h"
47#include "systime.h"
48
49#include "bitmaps/gray.xbm"
50
51#include <commdlg.h>
52#include <shellapi.h>
53#include <ctype.h>
54#include <winspool.h>
55
56#include <dlgs.h>
57#define FILE_NAME_TEXT_FIELD edt1
58
59void syms_of_w32fns ();
60void globals_of_w32fns ();
61
62extern void free_frame_menubar ();
63extern double atof ();
64extern int w32_console_toggle_lock_key P_ ((int, Lisp_Object));
65extern void w32_menu_display_help P_ ((HWND, HMENU, UINT, UINT));
66extern void w32_free_menu_strings P_ ((HWND));
67extern XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
68
69extern int quit_char;
70
71extern char *lispy_function_keys[];
72
73/* The gray bitmap `bitmaps/gray'.  This is done because w32term.c uses
74   it, and including `bitmaps/gray' more than once is a problem when
75   config.h defines `static' as an empty replacement string.  */
76
77int gray_bitmap_width = gray_width;
78int gray_bitmap_height = gray_height;
79unsigned char *gray_bitmap_bits = gray_bits;
80
81/* The colormap for converting color names to RGB values */
82Lisp_Object Vw32_color_map;
83
84/* Non nil if alt key presses are passed on to Windows.  */
85Lisp_Object Vw32_pass_alt_to_system;
86
87/* Non nil if alt key is translated to meta_modifier, nil if it is translated
88   to alt_modifier.  */
89Lisp_Object Vw32_alt_is_meta;
90
91/* If non-zero, the windows virtual key code for an alternative quit key. */
92int w32_quit_key;
93
94/* Non nil if left window key events are passed on to Windows (this only
95   affects whether "tapping" the key opens the Start menu).  */
96Lisp_Object Vw32_pass_lwindow_to_system;
97
98/* Non nil if right window key events are passed on to Windows (this
99   only affects whether "tapping" the key opens the Start menu).  */
100Lisp_Object Vw32_pass_rwindow_to_system;
101
102/* Virtual key code used to generate "phantom" key presses in order
103   to stop system from acting on Windows key events.  */
104Lisp_Object Vw32_phantom_key_code;
105
106/* Modifier associated with the left "Windows" key, or nil to act as a
107   normal key.  */
108Lisp_Object Vw32_lwindow_modifier;
109
110/* Modifier associated with the right "Windows" key, or nil to act as a
111   normal key.  */
112Lisp_Object Vw32_rwindow_modifier;
113
114/* Modifier associated with the "Apps" key, or nil to act as a normal
115   key.  */
116Lisp_Object Vw32_apps_modifier;
117
118/* Value is nil if Num Lock acts as a function key.  */
119Lisp_Object Vw32_enable_num_lock;
120
121/* Value is nil if Caps Lock acts as a function key.  */
122Lisp_Object Vw32_enable_caps_lock;
123
124/* Modifier associated with Scroll Lock, or nil to act as a normal key.  */
125Lisp_Object Vw32_scroll_lock_modifier;
126
127/* Switch to control whether we inhibit requests for synthesized bold
128   and italic versions of fonts.  */
129int w32_enable_synthesized_fonts;
130
131/* Enable palette management. */
132Lisp_Object Vw32_enable_palette;
133
134/* Control how close left/right button down events must be to
135   be converted to a middle button down event. */
136int w32_mouse_button_tolerance;
137
138/* Minimum interval between mouse movement (and scroll bar drag)
139   events that are passed on to the event loop. */
140int w32_mouse_move_interval;
141
142/* Flag to indicate if XBUTTON events should be passed on to Windows.  */
143int w32_pass_extra_mouse_buttons_to_system;
144
145/* Non nil if no window manager is in use.  */
146Lisp_Object Vx_no_window_manager;
147
148/* Non-zero means we're allowed to display a hourglass pointer.  */
149
150int display_hourglass_p;
151
152/* The background and shape of the mouse pointer, and shape when not
153   over text or in the modeline.  */
154
155Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
156Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
157
158/* The shape when over mouse-sensitive text.  */
159
160Lisp_Object Vx_sensitive_text_pointer_shape;
161
162#ifndef IDC_HAND
163#define IDC_HAND MAKEINTRESOURCE(32649)
164#endif
165
166/* Color of chars displayed in cursor box.  */
167
168Lisp_Object Vx_cursor_fore_pixel;
169
170/* Nonzero if using Windows.  */
171
172static int w32_in_use;
173
174/* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.  */
175
176Lisp_Object Vx_pixel_size_width_font_regexp;
177
178/* Alist of bdf fonts and the files that define them.  */
179Lisp_Object Vw32_bdf_filename_alist;
180
181/* A flag to control whether fonts are matched strictly or not.  */
182int w32_strict_fontnames;
183
184/* A flag to control whether we should only repaint if GetUpdateRect
185   indicates there is an update region.  */
186int w32_strict_painting;
187
188/* Associative list linking character set strings to Windows codepages. */
189Lisp_Object Vw32_charset_info_alist;
190
191/* VIETNAMESE_CHARSET is not defined in some versions of MSVC.  */
192#ifndef VIETNAMESE_CHARSET
193#define VIETNAMESE_CHARSET 163
194#endif
195
196Lisp_Object Qnone;
197Lisp_Object Qsuppress_icon;
198Lisp_Object Qundefined_color;
199Lisp_Object Qcancel_timer;
200Lisp_Object Qhyper;
201Lisp_Object Qsuper;
202Lisp_Object Qmeta;
203Lisp_Object Qalt;
204Lisp_Object Qctrl;
205Lisp_Object Qcontrol;
206Lisp_Object Qshift;
207
208Lisp_Object Qw32_charset_ansi;
209Lisp_Object Qw32_charset_default;
210Lisp_Object Qw32_charset_symbol;
211Lisp_Object Qw32_charset_shiftjis;
212Lisp_Object Qw32_charset_hangeul;
213Lisp_Object Qw32_charset_gb2312;
214Lisp_Object Qw32_charset_chinesebig5;
215Lisp_Object Qw32_charset_oem;
216
217#ifndef JOHAB_CHARSET
218#define JOHAB_CHARSET 130
219#endif
220#ifdef JOHAB_CHARSET
221Lisp_Object Qw32_charset_easteurope;
222Lisp_Object Qw32_charset_turkish;
223Lisp_Object Qw32_charset_baltic;
224Lisp_Object Qw32_charset_russian;
225Lisp_Object Qw32_charset_arabic;
226Lisp_Object Qw32_charset_greek;
227Lisp_Object Qw32_charset_hebrew;
228Lisp_Object Qw32_charset_vietnamese;
229Lisp_Object Qw32_charset_thai;
230Lisp_Object Qw32_charset_johab;
231Lisp_Object Qw32_charset_mac;
232#endif
233
234#ifdef UNICODE_CHARSET
235Lisp_Object Qw32_charset_unicode;
236#endif
237
238/* The ANSI codepage.  */
239int w32_ansi_code_page;
240
241/* Prefix for system colors.  */
242#define SYSTEM_COLOR_PREFIX "System"
243#define SYSTEM_COLOR_PREFIX_LEN (sizeof (SYSTEM_COLOR_PREFIX) - 1)
244
245/* State variables for emulating a three button mouse. */
246#define LMOUSE 1
247#define MMOUSE 2
248#define RMOUSE 4
249
250static int button_state = 0;
251static W32Msg saved_mouse_button_msg;
252static unsigned mouse_button_timer = 0;	/* non-zero when timer is active */
253static W32Msg saved_mouse_move_msg;
254static unsigned mouse_move_timer = 0;
255
256/* Window that is tracking the mouse.  */
257static HWND track_mouse_window;
258
259typedef BOOL (WINAPI * TrackMouseEvent_Proc)
260  (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
261
262TrackMouseEvent_Proc track_mouse_event_fn = NULL;
263ClipboardSequence_Proc clipboard_sequence_fn = NULL;
264extern AppendMenuW_Proc unicode_append_menu;
265
266/* W95 mousewheel handler */
267unsigned int msh_mousewheel = 0;
268
269/* Timers */
270#define MOUSE_BUTTON_ID	1
271#define MOUSE_MOVE_ID	2
272#define MENU_FREE_ID 3
273/* The delay (milliseconds) before a menu is freed after WM_EXITMENULOOP
274   is received.  */
275#define MENU_FREE_DELAY 1000
276static unsigned menu_free_timer = 0;
277
278/* The below are defined in frame.c.  */
279
280extern Lisp_Object Vwindow_system_version;
281
282#ifdef GLYPH_DEBUG
283int image_cache_refcount, dpyinfo_refcount;
284#endif
285
286
287/* From w32term.c. */
288extern int w32_num_mouse_buttons;
289extern Lisp_Object Vw32_recognize_altgr;
290
291extern HWND w32_system_caret_hwnd;
292
293extern int w32_system_caret_height;
294extern int w32_system_caret_x;
295extern int w32_system_caret_y;
296extern int w32_use_visible_system_caret;
297
298static HWND w32_visible_system_caret_hwnd;
299
300/* From w32menu.c  */
301extern HMENU current_popup_menu;
302static int menubar_in_use = 0;
303
304
305/* Error if we are not connected to MS-Windows.  */
306void
307check_w32 ()
308{
309  if (! w32_in_use)
310    error ("MS-Windows not in use or not initialized");
311}
312
313/* Nonzero if we can use mouse menus.
314   You should not call this unless HAVE_MENUS is defined.  */
315
316int
317have_menus_p ()
318{
319  return w32_in_use;
320}
321
322/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
323   and checking validity for W32.  */
324
325FRAME_PTR
326check_x_frame (frame)
327     Lisp_Object frame;
328{
329  FRAME_PTR f;
330
331  if (NILP (frame))
332    frame = selected_frame;
333  CHECK_LIVE_FRAME (frame);
334  f = XFRAME (frame);
335  if (! FRAME_W32_P (f))
336    error ("Non-W32 frame used");
337  return f;
338}
339
340/* Let the user specify a display with a frame.
341   nil stands for the selected frame--or, if that is not a w32 frame,
342   the first display on the list.  */
343
344struct w32_display_info *
345check_x_display_info (frame)
346     Lisp_Object frame;
347{
348  if (NILP (frame))
349    {
350      struct frame *sf = XFRAME (selected_frame);
351
352      if (FRAME_W32_P (sf) && FRAME_LIVE_P (sf))
353	return FRAME_W32_DISPLAY_INFO (sf);
354      else
355	return &one_w32_display_info;
356    }
357  else if (STRINGP (frame))
358    return x_display_info_for_name (frame);
359  else
360    {
361      FRAME_PTR f;
362
363      CHECK_LIVE_FRAME (frame);
364      f = XFRAME (frame);
365      if (! FRAME_W32_P (f))
366	error ("Non-W32 frame used");
367      return FRAME_W32_DISPLAY_INFO (f);
368    }
369}
370
371/* Return the Emacs frame-object corresponding to an w32 window.
372   It could be the frame's main window or an icon window.  */
373
374/* This function can be called during GC, so use GC_xxx type test macros.  */
375
376struct frame *
377x_window_to_frame (dpyinfo, wdesc)
378     struct w32_display_info *dpyinfo;
379     HWND wdesc;
380{
381  Lisp_Object tail, frame;
382  struct frame *f;
383
384  for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
385    {
386      frame = XCAR (tail);
387      if (!GC_FRAMEP (frame))
388        continue;
389      f = XFRAME (frame);
390      if (!FRAME_W32_P (f) || FRAME_W32_DISPLAY_INFO (f) != dpyinfo)
391	continue;
392      if (f->output_data.w32->hourglass_window == wdesc)
393        return f;
394
395      if (FRAME_W32_WINDOW (f) == wdesc)
396        return f;
397    }
398  return 0;
399}
400
401
402static Lisp_Object unwind_create_frame P_ ((Lisp_Object));
403static Lisp_Object unwind_create_tip_frame P_ ((Lisp_Object));
404static void my_create_window P_ ((struct frame *));
405static void my_create_tip_window P_ ((struct frame *));
406
407/* TODO: Native Input Method support; see x_create_im.  */
408void x_set_foreground_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
409void x_set_background_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
410void x_set_mouse_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
411void x_set_cursor_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
412void x_set_border_color P_ ((struct frame *, Lisp_Object, Lisp_Object));
413void x_set_cursor_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
414void x_set_icon_type P_ ((struct frame *, Lisp_Object, Lisp_Object));
415void x_set_icon_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
416void x_explicitly_set_name P_ ((struct frame *, Lisp_Object, Lisp_Object));
417void x_set_menu_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
418void x_set_title P_ ((struct frame *, Lisp_Object, Lisp_Object));
419void x_set_tool_bar_lines P_ ((struct frame *, Lisp_Object, Lisp_Object));
420static void x_edge_detection P_ ((struct frame *, struct image *, Lisp_Object,
421				  Lisp_Object));
422
423
424
425
426/* Store the screen positions of frame F into XPTR and YPTR.
427   These are the positions of the containing window manager window,
428   not Emacs's own window.  */
429
430void
431x_real_positions (f, xptr, yptr)
432     FRAME_PTR f;
433     int *xptr, *yptr;
434{
435  POINT pt;
436  RECT rect;
437
438  GetClientRect(FRAME_W32_WINDOW(f), &rect);
439  AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f));
440
441  pt.x = rect.left;
442  pt.y = rect.top;
443
444  ClientToScreen (FRAME_W32_WINDOW(f), &pt);
445
446  /* Remember x_pixels_diff and y_pixels_diff.  */
447  f->x_pixels_diff = pt.x - rect.left;
448  f->y_pixels_diff = pt.y - rect.top;
449
450  *xptr = pt.x;
451  *yptr = pt.y;
452}
453
454
455
456DEFUN ("w32-define-rgb-color", Fw32_define_rgb_color,
457       Sw32_define_rgb_color, 4, 4, 0,
458       doc: /* Convert RGB numbers to a windows color reference and associate with NAME.
459This adds or updates a named color to w32-color-map, making it
460available for use.  The original entry's RGB ref is returned, or nil
461if the entry is new.  */)
462    (red, green, blue, name)
463    Lisp_Object red, green, blue, name;
464{
465  Lisp_Object rgb;
466  Lisp_Object oldrgb = Qnil;
467  Lisp_Object entry;
468
469  CHECK_NUMBER (red);
470  CHECK_NUMBER (green);
471  CHECK_NUMBER (blue);
472  CHECK_STRING (name);
473
474  XSETINT (rgb, RGB(XUINT (red), XUINT (green), XUINT (blue)));
475
476  BLOCK_INPUT;
477
478  /* replace existing entry in w32-color-map or add new entry. */
479  entry = Fassoc (name, Vw32_color_map);
480  if (NILP (entry))
481    {
482      entry = Fcons (name, rgb);
483      Vw32_color_map = Fcons (entry, Vw32_color_map);
484    }
485  else
486    {
487      oldrgb = Fcdr (entry);
488      Fsetcdr (entry, rgb);
489    }
490
491  UNBLOCK_INPUT;
492
493  return (oldrgb);
494}
495
496DEFUN ("w32-load-color-file", Fw32_load_color_file,
497       Sw32_load_color_file, 1, 1, 0,
498       doc: /* Create an alist of color entries from an external file.
499Assign this value to w32-color-map to replace the existing color map.
500
501The file should define one named RGB color per line like so:
502  R G B   name
503where R,G,B are numbers between 0 and 255 and name is an arbitrary string.  */)
504    (filename)
505    Lisp_Object filename;
506{
507  FILE *fp;
508  Lisp_Object cmap = Qnil;
509  Lisp_Object abspath;
510
511  CHECK_STRING (filename);
512  abspath = Fexpand_file_name (filename, Qnil);
513
514  fp = fopen (SDATA (filename), "rt");
515  if (fp)
516    {
517      char buf[512];
518      int red, green, blue;
519      int num;
520
521      BLOCK_INPUT;
522
523      while (fgets (buf, sizeof (buf), fp) != NULL) {
524	if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
525	  {
526	    char *name = buf + num;
527	    num = strlen (name) - 1;
528	    if (name[num] == '\n')
529	      name[num] = 0;
530	    cmap = Fcons (Fcons (build_string (name),
531				 make_number (RGB (red, green, blue))),
532			  cmap);
533	  }
534      }
535      fclose (fp);
536
537      UNBLOCK_INPUT;
538    }
539
540  return cmap;
541}
542
543/* The default colors for the w32 color map */
544typedef struct colormap_t
545{
546  char *name;
547  COLORREF colorref;
548} colormap_t;
549
550colormap_t w32_color_map[] =
551{
552  {"snow"                      , PALETTERGB (255,250,250)},
553  {"ghost white"               , PALETTERGB (248,248,255)},
554  {"GhostWhite"                , PALETTERGB (248,248,255)},
555  {"white smoke"               , PALETTERGB (245,245,245)},
556  {"WhiteSmoke"                , PALETTERGB (245,245,245)},
557  {"gainsboro"                 , PALETTERGB (220,220,220)},
558  {"floral white"              , PALETTERGB (255,250,240)},
559  {"FloralWhite"               , PALETTERGB (255,250,240)},
560  {"old lace"                  , PALETTERGB (253,245,230)},
561  {"OldLace"                   , PALETTERGB (253,245,230)},
562  {"linen"                     , PALETTERGB (250,240,230)},
563  {"antique white"             , PALETTERGB (250,235,215)},
564  {"AntiqueWhite"              , PALETTERGB (250,235,215)},
565  {"papaya whip"               , PALETTERGB (255,239,213)},
566  {"PapayaWhip"                , PALETTERGB (255,239,213)},
567  {"blanched almond"           , PALETTERGB (255,235,205)},
568  {"BlanchedAlmond"            , PALETTERGB (255,235,205)},
569  {"bisque"                    , PALETTERGB (255,228,196)},
570  {"peach puff"                , PALETTERGB (255,218,185)},
571  {"PeachPuff"                 , PALETTERGB (255,218,185)},
572  {"navajo white"              , PALETTERGB (255,222,173)},
573  {"NavajoWhite"               , PALETTERGB (255,222,173)},
574  {"moccasin"                  , PALETTERGB (255,228,181)},
575  {"cornsilk"                  , PALETTERGB (255,248,220)},
576  {"ivory"                     , PALETTERGB (255,255,240)},
577  {"lemon chiffon"             , PALETTERGB (255,250,205)},
578  {"LemonChiffon"              , PALETTERGB (255,250,205)},
579  {"seashell"                  , PALETTERGB (255,245,238)},
580  {"honeydew"                  , PALETTERGB (240,255,240)},
581  {"mint cream"                , PALETTERGB (245,255,250)},
582  {"MintCream"                 , PALETTERGB (245,255,250)},
583  {"azure"                     , PALETTERGB (240,255,255)},
584  {"alice blue"                , PALETTERGB (240,248,255)},
585  {"AliceBlue"                 , PALETTERGB (240,248,255)},
586  {"lavender"                  , PALETTERGB (230,230,250)},
587  {"lavender blush"            , PALETTERGB (255,240,245)},
588  {"LavenderBlush"             , PALETTERGB (255,240,245)},
589  {"misty rose"                , PALETTERGB (255,228,225)},
590  {"MistyRose"                 , PALETTERGB (255,228,225)},
591  {"white"                     , PALETTERGB (255,255,255)},
592  {"black"                     , PALETTERGB (  0,  0,  0)},
593  {"dark slate gray"           , PALETTERGB ( 47, 79, 79)},
594  {"DarkSlateGray"             , PALETTERGB ( 47, 79, 79)},
595  {"dark slate grey"           , PALETTERGB ( 47, 79, 79)},
596  {"DarkSlateGrey"             , PALETTERGB ( 47, 79, 79)},
597  {"dim gray"                  , PALETTERGB (105,105,105)},
598  {"DimGray"                   , PALETTERGB (105,105,105)},
599  {"dim grey"                  , PALETTERGB (105,105,105)},
600  {"DimGrey"                   , PALETTERGB (105,105,105)},
601  {"slate gray"                , PALETTERGB (112,128,144)},
602  {"SlateGray"                 , PALETTERGB (112,128,144)},
603  {"slate grey"                , PALETTERGB (112,128,144)},
604  {"SlateGrey"                 , PALETTERGB (112,128,144)},
605  {"light slate gray"          , PALETTERGB (119,136,153)},
606  {"LightSlateGray"            , PALETTERGB (119,136,153)},
607  {"light slate grey"          , PALETTERGB (119,136,153)},
608  {"LightSlateGrey"            , PALETTERGB (119,136,153)},
609  {"gray"                      , PALETTERGB (190,190,190)},
610  {"grey"                      , PALETTERGB (190,190,190)},
611  {"light grey"                , PALETTERGB (211,211,211)},
612  {"LightGrey"                 , PALETTERGB (211,211,211)},
613  {"light gray"                , PALETTERGB (211,211,211)},
614  {"LightGray"                 , PALETTERGB (211,211,211)},
615  {"midnight blue"             , PALETTERGB ( 25, 25,112)},
616  {"MidnightBlue"              , PALETTERGB ( 25, 25,112)},
617  {"navy"                      , PALETTERGB (  0,  0,128)},
618  {"navy blue"                 , PALETTERGB (  0,  0,128)},
619  {"NavyBlue"                  , PALETTERGB (  0,  0,128)},
620  {"cornflower blue"           , PALETTERGB (100,149,237)},
621  {"CornflowerBlue"            , PALETTERGB (100,149,237)},
622  {"dark slate blue"           , PALETTERGB ( 72, 61,139)},
623  {"DarkSlateBlue"             , PALETTERGB ( 72, 61,139)},
624  {"slate blue"                , PALETTERGB (106, 90,205)},
625  {"SlateBlue"                 , PALETTERGB (106, 90,205)},
626  {"medium slate blue"         , PALETTERGB (123,104,238)},
627  {"MediumSlateBlue"           , PALETTERGB (123,104,238)},
628  {"light slate blue"          , PALETTERGB (132,112,255)},
629  {"LightSlateBlue"            , PALETTERGB (132,112,255)},
630  {"medium blue"               , PALETTERGB (  0,  0,205)},
631  {"MediumBlue"                , PALETTERGB (  0,  0,205)},
632  {"royal blue"                , PALETTERGB ( 65,105,225)},
633  {"RoyalBlue"                 , PALETTERGB ( 65,105,225)},
634  {"blue"                      , PALETTERGB (  0,  0,255)},
635  {"dodger blue"               , PALETTERGB ( 30,144,255)},
636  {"DodgerBlue"                , PALETTERGB ( 30,144,255)},
637  {"deep sky blue"             , PALETTERGB (  0,191,255)},
638  {"DeepSkyBlue"               , PALETTERGB (  0,191,255)},
639  {"sky blue"                  , PALETTERGB (135,206,235)},
640  {"SkyBlue"                   , PALETTERGB (135,206,235)},
641  {"light sky blue"            , PALETTERGB (135,206,250)},
642  {"LightSkyBlue"              , PALETTERGB (135,206,250)},
643  {"steel blue"                , PALETTERGB ( 70,130,180)},
644  {"SteelBlue"                 , PALETTERGB ( 70,130,180)},
645  {"light steel blue"          , PALETTERGB (176,196,222)},
646  {"LightSteelBlue"            , PALETTERGB (176,196,222)},
647  {"light blue"                , PALETTERGB (173,216,230)},
648  {"LightBlue"                 , PALETTERGB (173,216,230)},
649  {"powder blue"               , PALETTERGB (176,224,230)},
650  {"PowderBlue"                , PALETTERGB (176,224,230)},
651  {"pale turquoise"            , PALETTERGB (175,238,238)},
652  {"PaleTurquoise"             , PALETTERGB (175,238,238)},
653  {"dark turquoise"            , PALETTERGB (  0,206,209)},
654  {"DarkTurquoise"             , PALETTERGB (  0,206,209)},
655  {"medium turquoise"          , PALETTERGB ( 72,209,204)},
656  {"MediumTurquoise"           , PALETTERGB ( 72,209,204)},
657  {"turquoise"                 , PALETTERGB ( 64,224,208)},
658  {"cyan"                      , PALETTERGB (  0,255,255)},
659  {"light cyan"                , PALETTERGB (224,255,255)},
660  {"LightCyan"                 , PALETTERGB (224,255,255)},
661  {"cadet blue"                , PALETTERGB ( 95,158,160)},
662  {"CadetBlue"                 , PALETTERGB ( 95,158,160)},
663  {"medium aquamarine"         , PALETTERGB (102,205,170)},
664  {"MediumAquamarine"          , PALETTERGB (102,205,170)},
665  {"aquamarine"                , PALETTERGB (127,255,212)},
666  {"dark green"                , PALETTERGB (  0,100,  0)},
667  {"DarkGreen"                 , PALETTERGB (  0,100,  0)},
668  {"dark olive green"          , PALETTERGB ( 85,107, 47)},
669  {"DarkOliveGreen"            , PALETTERGB ( 85,107, 47)},
670  {"dark sea green"            , PALETTERGB (143,188,143)},
671  {"DarkSeaGreen"              , PALETTERGB (143,188,143)},
672  {"sea green"                 , PALETTERGB ( 46,139, 87)},
673  {"SeaGreen"                  , PALETTERGB ( 46,139, 87)},
674  {"medium sea green"          , PALETTERGB ( 60,179,113)},
675  {"MediumSeaGreen"            , PALETTERGB ( 60,179,113)},
676  {"light sea green"           , PALETTERGB ( 32,178,170)},
677  {"LightSeaGreen"             , PALETTERGB ( 32,178,170)},
678  {"pale green"                , PALETTERGB (152,251,152)},
679  {"PaleGreen"                 , PALETTERGB (152,251,152)},
680  {"spring green"              , PALETTERGB (  0,255,127)},
681  {"SpringGreen"               , PALETTERGB (  0,255,127)},
682  {"lawn green"                , PALETTERGB (124,252,  0)},
683  {"LawnGreen"                 , PALETTERGB (124,252,  0)},
684  {"green"                     , PALETTERGB (  0,255,  0)},
685  {"chartreuse"                , PALETTERGB (127,255,  0)},
686  {"medium spring green"       , PALETTERGB (  0,250,154)},
687  {"MediumSpringGreen"         , PALETTERGB (  0,250,154)},
688  {"green yellow"              , PALETTERGB (173,255, 47)},
689  {"GreenYellow"               , PALETTERGB (173,255, 47)},
690  {"lime green"                , PALETTERGB ( 50,205, 50)},
691  {"LimeGreen"                 , PALETTERGB ( 50,205, 50)},
692  {"yellow green"              , PALETTERGB (154,205, 50)},
693  {"YellowGreen"               , PALETTERGB (154,205, 50)},
694  {"forest green"              , PALETTERGB ( 34,139, 34)},
695  {"ForestGreen"               , PALETTERGB ( 34,139, 34)},
696  {"olive drab"                , PALETTERGB (107,142, 35)},
697  {"OliveDrab"                 , PALETTERGB (107,142, 35)},
698  {"dark khaki"                , PALETTERGB (189,183,107)},
699  {"DarkKhaki"                 , PALETTERGB (189,183,107)},
700  {"khaki"                     , PALETTERGB (240,230,140)},
701  {"pale goldenrod"            , PALETTERGB (238,232,170)},
702  {"PaleGoldenrod"             , PALETTERGB (238,232,170)},
703  {"light goldenrod yellow"    , PALETTERGB (250,250,210)},
704  {"LightGoldenrodYellow"      , PALETTERGB (250,250,210)},
705  {"light yellow"              , PALETTERGB (255,255,224)},
706  {"LightYellow"               , PALETTERGB (255,255,224)},
707  {"yellow"                    , PALETTERGB (255,255,  0)},
708  {"gold"                      , PALETTERGB (255,215,  0)},
709  {"light goldenrod"           , PALETTERGB (238,221,130)},
710  {"LightGoldenrod"            , PALETTERGB (238,221,130)},
711  {"goldenrod"                 , PALETTERGB (218,165, 32)},
712  {"dark goldenrod"            , PALETTERGB (184,134, 11)},
713  {"DarkGoldenrod"             , PALETTERGB (184,134, 11)},
714  {"rosy brown"                , PALETTERGB (188,143,143)},
715  {"RosyBrown"                 , PALETTERGB (188,143,143)},
716  {"indian red"                , PALETTERGB (205, 92, 92)},
717  {"IndianRed"                 , PALETTERGB (205, 92, 92)},
718  {"saddle brown"              , PALETTERGB (139, 69, 19)},
719  {"SaddleBrown"               , PALETTERGB (139, 69, 19)},
720  {"sienna"                    , PALETTERGB (160, 82, 45)},
721  {"peru"                      , PALETTERGB (205,133, 63)},
722  {"burlywood"                 , PALETTERGB (222,184,135)},
723  {"beige"                     , PALETTERGB (245,245,220)},
724  {"wheat"                     , PALETTERGB (245,222,179)},
725  {"sandy brown"               , PALETTERGB (244,164, 96)},
726  {"SandyBrown"                , PALETTERGB (244,164, 96)},
727  {"tan"                       , PALETTERGB (210,180,140)},
728  {"chocolate"                 , PALETTERGB (210,105, 30)},
729  {"firebrick"                 , PALETTERGB (178,34, 34)},
730  {"brown"                     , PALETTERGB (165,42, 42)},
731  {"dark salmon"               , PALETTERGB (233,150,122)},
732  {"DarkSalmon"                , PALETTERGB (233,150,122)},
733  {"salmon"                    , PALETTERGB (250,128,114)},
734  {"light salmon"              , PALETTERGB (255,160,122)},
735  {"LightSalmon"               , PALETTERGB (255,160,122)},
736  {"orange"                    , PALETTERGB (255,165,  0)},
737  {"dark orange"               , PALETTERGB (255,140,  0)},
738  {"DarkOrange"                , PALETTERGB (255,140,  0)},
739  {"coral"                     , PALETTERGB (255,127, 80)},
740  {"light coral"               , PALETTERGB (240,128,128)},
741  {"LightCoral"                , PALETTERGB (240,128,128)},
742  {"tomato"                    , PALETTERGB (255, 99, 71)},
743  {"orange red"                , PALETTERGB (255, 69,  0)},
744  {"OrangeRed"                 , PALETTERGB (255, 69,  0)},
745  {"red"                       , PALETTERGB (255,  0,  0)},
746  {"hot pink"                  , PALETTERGB (255,105,180)},
747  {"HotPink"                   , PALETTERGB (255,105,180)},
748  {"deep pink"                 , PALETTERGB (255, 20,147)},
749  {"DeepPink"                  , PALETTERGB (255, 20,147)},
750  {"pink"                      , PALETTERGB (255,192,203)},
751  {"light pink"                , PALETTERGB (255,182,193)},
752  {"LightPink"                 , PALETTERGB (255,182,193)},
753  {"pale violet red"           , PALETTERGB (219,112,147)},
754  {"PaleVioletRed"             , PALETTERGB (219,112,147)},
755  {"maroon"                    , PALETTERGB (176, 48, 96)},
756  {"medium violet red"         , PALETTERGB (199, 21,133)},
757  {"MediumVioletRed"           , PALETTERGB (199, 21,133)},
758  {"violet red"                , PALETTERGB (208, 32,144)},
759  {"VioletRed"                 , PALETTERGB (208, 32,144)},
760  {"magenta"                   , PALETTERGB (255,  0,255)},
761  {"violet"                    , PALETTERGB (238,130,238)},
762  {"plum"                      , PALETTERGB (221,160,221)},
763  {"orchid"                    , PALETTERGB (218,112,214)},
764  {"medium orchid"             , PALETTERGB (186, 85,211)},
765  {"MediumOrchid"              , PALETTERGB (186, 85,211)},
766  {"dark orchid"               , PALETTERGB (153, 50,204)},
767  {"DarkOrchid"                , PALETTERGB (153, 50,204)},
768  {"dark violet"               , PALETTERGB (148,  0,211)},
769  {"DarkViolet"                , PALETTERGB (148,  0,211)},
770  {"blue violet"               , PALETTERGB (138, 43,226)},
771  {"BlueViolet"                , PALETTERGB (138, 43,226)},
772  {"purple"                    , PALETTERGB (160, 32,240)},
773  {"medium purple"             , PALETTERGB (147,112,219)},
774  {"MediumPurple"              , PALETTERGB (147,112,219)},
775  {"thistle"                   , PALETTERGB (216,191,216)},
776  {"gray0"                     , PALETTERGB (  0,  0,  0)},
777  {"grey0"                     , PALETTERGB (  0,  0,  0)},
778  {"dark grey"                 , PALETTERGB (169,169,169)},
779  {"DarkGrey"                  , PALETTERGB (169,169,169)},
780  {"dark gray"                 , PALETTERGB (169,169,169)},
781  {"DarkGray"                  , PALETTERGB (169,169,169)},
782  {"dark blue"                 , PALETTERGB (  0,  0,139)},
783  {"DarkBlue"                  , PALETTERGB (  0,  0,139)},
784  {"dark cyan"                 , PALETTERGB (  0,139,139)},
785  {"DarkCyan"                  , PALETTERGB (  0,139,139)},
786  {"dark magenta"              , PALETTERGB (139,  0,139)},
787  {"DarkMagenta"               , PALETTERGB (139,  0,139)},
788  {"dark red"                  , PALETTERGB (139,  0,  0)},
789  {"DarkRed"                   , PALETTERGB (139,  0,  0)},
790  {"light green"               , PALETTERGB (144,238,144)},
791  {"LightGreen"                , PALETTERGB (144,238,144)},
792};
793
794DEFUN ("w32-default-color-map", Fw32_default_color_map, Sw32_default_color_map,
795       0, 0, 0, doc: /* Return the default color map.  */)
796     ()
797{
798  int i;
799  colormap_t *pc = w32_color_map;
800  Lisp_Object cmap;
801
802  BLOCK_INPUT;
803
804  cmap = Qnil;
805
806  for (i = 0; i < sizeof (w32_color_map) / sizeof (w32_color_map[0]);
807       pc++, i++)
808    cmap = Fcons (Fcons (build_string (pc->name),
809			 make_number (pc->colorref)),
810		  cmap);
811
812  UNBLOCK_INPUT;
813
814  return (cmap);
815}
816
817Lisp_Object
818w32_to_x_color (rgb)
819     Lisp_Object rgb;
820{
821  Lisp_Object color;
822
823  CHECK_NUMBER (rgb);
824
825  BLOCK_INPUT;
826
827  color = Frassq (rgb, Vw32_color_map);
828
829  UNBLOCK_INPUT;
830
831  if (!NILP (color))
832    return (Fcar (color));
833  else
834    return Qnil;
835}
836
837static Lisp_Object
838w32_color_map_lookup (colorname)
839     char *colorname;
840{
841  Lisp_Object tail, ret = Qnil;
842
843  BLOCK_INPUT;
844
845  for (tail = Vw32_color_map; !NILP (tail); tail = Fcdr (tail))
846    {
847      register Lisp_Object elt, tem;
848
849      elt = Fcar (tail);
850      if (!CONSP (elt)) continue;
851
852      tem = Fcar (elt);
853
854      if (lstrcmpi (SDATA (tem), colorname) == 0)
855	{
856	  ret = Fcdr (elt);
857	  break;
858	}
859
860      QUIT;
861    }
862
863
864  UNBLOCK_INPUT;
865
866  return ret;
867}
868
869
870static void
871add_system_logical_colors_to_map (system_colors)
872     Lisp_Object *system_colors;
873{
874  HKEY colors_key;
875
876  /* Other registry operations are done with input blocked.  */
877  BLOCK_INPUT;
878
879  /* Look for "Control Panel/Colors" under User and Machine registry
880     settings.  */
881  if (RegOpenKeyEx (HKEY_CURRENT_USER, "Control Panel\\Colors", 0,
882		    KEY_READ, &colors_key) == ERROR_SUCCESS
883      || RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Control Panel\\Colors", 0,
884		       KEY_READ, &colors_key) == ERROR_SUCCESS)
885    {
886      /* List all keys.  */
887      char color_buffer[64];
888      char full_name_buffer[MAX_PATH + SYSTEM_COLOR_PREFIX_LEN];
889      int index = 0;
890      DWORD name_size, color_size;
891      char *name_buffer = full_name_buffer + SYSTEM_COLOR_PREFIX_LEN;
892
893      name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
894      color_size = sizeof (color_buffer);
895
896      strcpy (full_name_buffer, SYSTEM_COLOR_PREFIX);
897
898      while (RegEnumValueA (colors_key, index, name_buffer, &name_size,
899			    NULL, NULL, color_buffer, &color_size)
900	     == ERROR_SUCCESS)
901	{
902	  int r, g, b;
903	  if (sscanf (color_buffer, " %u %u %u", &r, &g, &b) == 3)
904	    *system_colors = Fcons (Fcons (build_string (full_name_buffer),
905					   make_number (RGB (r, g, b))),
906				    *system_colors);
907
908	  name_size = sizeof (full_name_buffer) - SYSTEM_COLOR_PREFIX_LEN;
909	  color_size = sizeof (color_buffer);
910	  index++;
911	}
912      RegCloseKey (colors_key);
913    }
914
915  UNBLOCK_INPUT;
916}
917
918
919static Lisp_Object
920x_to_w32_color (colorname)
921     char * colorname;
922{
923  register Lisp_Object ret = Qnil;
924
925  BLOCK_INPUT;
926
927  if (colorname[0] == '#')
928    {
929      /* Could be an old-style RGB Device specification.  */
930      char *color;
931      int size;
932      color = colorname + 1;
933
934      size = strlen(color);
935      if (size == 3 || size == 6 || size == 9 || size == 12)
936	{
937	  UINT colorval;
938	  int i, pos;
939	  pos = 0;
940	  size /= 3;
941	  colorval = 0;
942
943	  for (i = 0; i < 3; i++)
944	    {
945	      char *end;
946	      char t;
947	      unsigned long value;
948
949	      /* The check for 'x' in the following conditional takes into
950		 account the fact that strtol allows a "0x" in front of
951		 our numbers, and we don't.  */
952	      if (!isxdigit(color[0]) || color[1] == 'x')
953		break;
954	      t = color[size];
955	      color[size] = '\0';
956	      value = strtoul(color, &end, 16);
957	      color[size] = t;
958	      if (errno == ERANGE || end - color != size)
959		break;
960	      switch (size)
961		{
962		case 1:
963		  value = value * 0x10;
964		  break;
965		case 2:
966		  break;
967		case 3:
968		  value /= 0x10;
969		  break;
970		case 4:
971		  value /= 0x100;
972		  break;
973		}
974	      colorval |= (value << pos);
975	      pos += 0x8;
976	      if (i == 2)
977		{
978		  UNBLOCK_INPUT;
979		  XSETINT (ret, colorval);
980		  return ret;
981		}
982	      color = end;
983	    }
984	}
985    }
986  else if (strnicmp(colorname, "rgb:", 4) == 0)
987    {
988      char *color;
989      UINT colorval;
990      int i, pos;
991      pos = 0;
992
993      colorval = 0;
994      color = colorname + 4;
995      for (i = 0; i < 3; i++)
996	{
997	  char *end;
998	  unsigned long value;
999
1000	  /* The check for 'x' in the following conditional takes into
1001	     account the fact that strtol allows a "0x" in front of
1002	     our numbers, and we don't.  */
1003	  if (!isxdigit(color[0]) || color[1] == 'x')
1004	    break;
1005	  value = strtoul(color, &end, 16);
1006	  if (errno == ERANGE)
1007	    break;
1008	  switch (end - color)
1009	    {
1010	    case 1:
1011	      value = value * 0x10 + value;
1012	      break;
1013	    case 2:
1014	      break;
1015	    case 3:
1016	      value /= 0x10;
1017	      break;
1018	    case 4:
1019	      value /= 0x100;
1020	      break;
1021	    default:
1022	      value = ULONG_MAX;
1023	    }
1024	  if (value == ULONG_MAX)
1025	    break;
1026	  colorval |= (value << pos);
1027	  pos += 0x8;
1028	  if (i == 2)
1029	    {
1030	      if (*end != '\0')
1031		break;
1032	      UNBLOCK_INPUT;
1033	      XSETINT (ret, colorval);
1034	      return ret;
1035	    }
1036	  if (*end != '/')
1037	    break;
1038	  color = end + 1;
1039	}
1040    }
1041  else if (strnicmp(colorname, "rgbi:", 5) == 0)
1042    {
1043      /* This is an RGB Intensity specification.  */
1044      char *color;
1045      UINT colorval;
1046      int i, pos;
1047      pos = 0;
1048
1049      colorval = 0;
1050      color = colorname + 5;
1051      for (i = 0; i < 3; i++)
1052	{
1053	  char *end;
1054	  double value;
1055	  UINT val;
1056
1057	  value = strtod(color, &end);
1058	  if (errno == ERANGE)
1059	    break;
1060	  if (value < 0.0 || value > 1.0)
1061	    break;
1062	  val = (UINT)(0x100 * value);
1063	  /* We used 0x100 instead of 0xFF to give a continuous
1064             range between 0.0 and 1.0 inclusive.  The next statement
1065             fixes the 1.0 case.  */
1066	  if (val == 0x100)
1067	    val = 0xFF;
1068	  colorval |= (val << pos);
1069	  pos += 0x8;
1070	  if (i == 2)
1071	    {
1072	      if (*end != '\0')
1073		break;
1074	      UNBLOCK_INPUT;
1075	      XSETINT (ret, colorval);
1076	      return ret;
1077	    }
1078	  if (*end != '/')
1079	    break;
1080	  color = end + 1;
1081	}
1082    }
1083  /* I am not going to attempt to handle any of the CIE color schemes
1084     or TekHVC, since I don't know the algorithms for conversion to
1085     RGB.  */
1086
1087  /* If we fail to lookup the color name in w32_color_map, then check the
1088     colorname to see if it can be crudely approximated: If the X color
1089     ends in a number (e.g., "darkseagreen2"), strip the number and
1090     return the result of looking up the base color name.  */
1091  ret = w32_color_map_lookup (colorname);
1092  if (NILP (ret))
1093    {
1094      int len = strlen (colorname);
1095
1096      if (isdigit (colorname[len - 1]))
1097	{
1098	  char *ptr, *approx = alloca (len + 1);
1099
1100	  strcpy (approx, colorname);
1101	  ptr = &approx[len - 1];
1102	  while (ptr > approx && isdigit (*ptr))
1103	      *ptr-- = '\0';
1104
1105	  ret = w32_color_map_lookup (approx);
1106	}
1107    }
1108
1109  UNBLOCK_INPUT;
1110  return ret;
1111}
1112
1113void
1114w32_regenerate_palette (FRAME_PTR f)
1115{
1116  struct w32_palette_entry * list;
1117  LOGPALETTE *          log_palette;
1118  HPALETTE              new_palette;
1119  int                   i;
1120
1121  /* don't bother trying to create palette if not supported */
1122  if (! FRAME_W32_DISPLAY_INFO (f)->has_palette)
1123    return;
1124
1125  log_palette = (LOGPALETTE *)
1126    alloca (sizeof (LOGPALETTE) +
1127	     FRAME_W32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
1128  log_palette->palVersion = 0x300;
1129  log_palette->palNumEntries = FRAME_W32_DISPLAY_INFO (f)->num_colors;
1130
1131  list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1132  for (i = 0;
1133       i < FRAME_W32_DISPLAY_INFO (f)->num_colors;
1134       i++, list = list->next)
1135    log_palette->palPalEntry[i] = list->entry;
1136
1137  new_palette = CreatePalette (log_palette);
1138
1139  enter_crit ();
1140
1141  if (FRAME_W32_DISPLAY_INFO (f)->palette)
1142    DeleteObject (FRAME_W32_DISPLAY_INFO (f)->palette);
1143  FRAME_W32_DISPLAY_INFO (f)->palette = new_palette;
1144
1145  /* Realize display palette and garbage all frames. */
1146  release_frame_dc (f, get_frame_dc (f));
1147
1148  leave_crit ();
1149}
1150
1151#define W32_COLOR(pe)  RGB (pe.peRed, pe.peGreen, pe.peBlue)
1152#define SET_W32_COLOR(pe, color) \
1153  do \
1154    { \
1155      pe.peRed = GetRValue (color); \
1156      pe.peGreen = GetGValue (color); \
1157      pe.peBlue = GetBValue (color); \
1158      pe.peFlags = 0; \
1159    } while (0)
1160
1161#if 0
1162/* Keep these around in case we ever want to track color usage. */
1163void
1164w32_map_color (FRAME_PTR f, COLORREF color)
1165{
1166  struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1167
1168  if (NILP (Vw32_enable_palette))
1169    return;
1170
1171  /* check if color is already mapped */
1172  while (list)
1173    {
1174      if (W32_COLOR (list->entry) == color)
1175        {
1176	  ++list->refcount;
1177	  return;
1178	}
1179      list = list->next;
1180    }
1181
1182  /* not already mapped, so add to list and recreate Windows palette */
1183  list = (struct w32_palette_entry *)
1184    xmalloc (sizeof (struct w32_palette_entry));
1185  SET_W32_COLOR (list->entry, color);
1186  list->refcount = 1;
1187  list->next = FRAME_W32_DISPLAY_INFO (f)->color_list;
1188  FRAME_W32_DISPLAY_INFO (f)->color_list = list;
1189  FRAME_W32_DISPLAY_INFO (f)->num_colors++;
1190
1191  /* set flag that palette must be regenerated */
1192  FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1193}
1194
1195void
1196w32_unmap_color (FRAME_PTR f, COLORREF color)
1197{
1198  struct w32_palette_entry * list = FRAME_W32_DISPLAY_INFO (f)->color_list;
1199  struct w32_palette_entry **prev = &FRAME_W32_DISPLAY_INFO (f)->color_list;
1200
1201  if (NILP (Vw32_enable_palette))
1202    return;
1203
1204  /* check if color is already mapped */
1205  while (list)
1206    {
1207      if (W32_COLOR (list->entry) == color)
1208        {
1209	  if (--list->refcount == 0)
1210	    {
1211	      *prev = list->next;
1212	      xfree (list);
1213	      FRAME_W32_DISPLAY_INFO (f)->num_colors--;
1214	      break;
1215	    }
1216	  else
1217	    return;
1218	}
1219      prev = &list->next;
1220      list = list->next;
1221    }
1222
1223  /* set flag that palette must be regenerated */
1224  FRAME_W32_DISPLAY_INFO (f)->regen_palette = TRUE;
1225}
1226#endif
1227
1228
1229/* Gamma-correct COLOR on frame F.  */
1230
1231void
1232gamma_correct (f, color)
1233     struct frame *f;
1234     COLORREF *color;
1235{
1236  if (f->gamma)
1237    {
1238      *color = PALETTERGB (
1239        pow (GetRValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1240        pow (GetGValue (*color) / 255.0, f->gamma) * 255.0 + 0.5,
1241        pow (GetBValue (*color) / 255.0, f->gamma) * 255.0 + 0.5);
1242    }
1243}
1244
1245
1246/* Decide if color named COLOR is valid for the display associated with
1247   the selected frame; if so, return the rgb values in COLOR_DEF.
1248   If ALLOC is nonzero, allocate a new colormap cell.  */
1249
1250int
1251w32_defined_color (f, color, color_def, alloc)
1252     FRAME_PTR f;
1253     char *color;
1254     XColor *color_def;
1255     int alloc;
1256{
1257  register Lisp_Object tem;
1258  COLORREF w32_color_ref;
1259
1260  tem = x_to_w32_color (color);
1261
1262  if (!NILP (tem))
1263    {
1264      if (f)
1265        {
1266          /* Apply gamma correction.  */
1267          w32_color_ref = XUINT (tem);
1268          gamma_correct (f, &w32_color_ref);
1269          XSETINT (tem, w32_color_ref);
1270        }
1271
1272      /* Map this color to the palette if it is enabled. */
1273      if (!NILP (Vw32_enable_palette))
1274	{
1275	  struct w32_palette_entry * entry =
1276	    one_w32_display_info.color_list;
1277	  struct w32_palette_entry ** prev =
1278	    &one_w32_display_info.color_list;
1279
1280	  /* check if color is already mapped */
1281	  while (entry)
1282	    {
1283	      if (W32_COLOR (entry->entry) == XUINT (tem))
1284		break;
1285	      prev = &entry->next;
1286	      entry = entry->next;
1287	    }
1288
1289	  if (entry == NULL && alloc)
1290	    {
1291	      /* not already mapped, so add to list */
1292	      entry = (struct w32_palette_entry *)
1293		xmalloc (sizeof (struct w32_palette_entry));
1294	      SET_W32_COLOR (entry->entry, XUINT (tem));
1295	      entry->next = NULL;
1296	      *prev = entry;
1297	      one_w32_display_info.num_colors++;
1298
1299	      /* set flag that palette must be regenerated */
1300	      one_w32_display_info.regen_palette = TRUE;
1301	    }
1302	}
1303      /* Ensure COLORREF value is snapped to nearest color in (default)
1304	 palette by simulating the PALETTERGB macro.  This works whether
1305	 or not the display device has a palette. */
1306      w32_color_ref = XUINT (tem) | 0x2000000;
1307
1308      color_def->pixel = w32_color_ref;
1309      color_def->red = GetRValue (w32_color_ref) * 256;
1310      color_def->green = GetGValue (w32_color_ref) * 256;
1311      color_def->blue = GetBValue (w32_color_ref) * 256;
1312
1313      return 1;
1314    }
1315  else
1316    {
1317      return 0;
1318    }
1319}
1320
1321/* Given a string ARG naming a color, compute a pixel value from it
1322   suitable for screen F.
1323   If F is not a color screen, return DEF (default) regardless of what
1324   ARG says.  */
1325
1326int
1327x_decode_color (f, arg, def)
1328     FRAME_PTR f;
1329     Lisp_Object arg;
1330     int def;
1331{
1332  XColor cdef;
1333
1334  CHECK_STRING (arg);
1335
1336  if (strcmp (SDATA (arg), "black") == 0)
1337    return BLACK_PIX_DEFAULT (f);
1338  else if (strcmp (SDATA (arg), "white") == 0)
1339    return WHITE_PIX_DEFAULT (f);
1340
1341  if ((FRAME_W32_DISPLAY_INFO (f)->n_planes * FRAME_W32_DISPLAY_INFO (f)->n_cbits) == 1)
1342    return def;
1343
1344  /* w32_defined_color is responsible for coping with failures
1345     by looking for a near-miss.  */
1346  if (w32_defined_color (f, SDATA (arg), &cdef, 1))
1347    return cdef.pixel;
1348
1349  /* defined_color failed; return an ultimate default.  */
1350  return def;
1351}
1352
1353
1354
1355/* Functions called only from `x_set_frame_param'
1356   to set individual parameters.
1357
1358   If FRAME_W32_WINDOW (f) is 0,
1359   the frame is being created and its window does not exist yet.
1360   In that case, just record the parameter's new value
1361   in the standard place; do not attempt to change the window.  */
1362
1363void
1364x_set_foreground_color (f, arg, oldval)
1365     struct frame *f;
1366     Lisp_Object arg, oldval;
1367{
1368  struct w32_output *x = f->output_data.w32;
1369  PIX_TYPE fg, old_fg;
1370
1371  fg = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1372  old_fg = FRAME_FOREGROUND_PIXEL (f);
1373  FRAME_FOREGROUND_PIXEL (f) = fg;
1374
1375  if (FRAME_W32_WINDOW (f) != 0)
1376    {
1377      if (x->cursor_pixel == old_fg)
1378	x->cursor_pixel = fg;
1379
1380      update_face_from_frame_parameter (f, Qforeground_color, arg);
1381      if (FRAME_VISIBLE_P (f))
1382        redraw_frame (f);
1383    }
1384}
1385
1386void
1387x_set_background_color (f, arg, oldval)
1388     struct frame *f;
1389     Lisp_Object arg, oldval;
1390{
1391  FRAME_BACKGROUND_PIXEL (f)
1392    = x_decode_color (f, arg, WHITE_PIX_DEFAULT (f));
1393
1394  if (FRAME_W32_WINDOW (f) != 0)
1395    {
1396      SetWindowLong (FRAME_W32_WINDOW (f), WND_BACKGROUND_INDEX,
1397                     FRAME_BACKGROUND_PIXEL (f));
1398
1399      update_face_from_frame_parameter (f, Qbackground_color, arg);
1400
1401      if (FRAME_VISIBLE_P (f))
1402        redraw_frame (f);
1403    }
1404}
1405
1406void
1407x_set_mouse_color (f, arg, oldval)
1408     struct frame *f;
1409     Lisp_Object arg, oldval;
1410{
1411  Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
1412  int count;
1413  int mask_color;
1414
1415  if (!EQ (Qnil, arg))
1416    f->output_data.w32->mouse_pixel
1417      = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1418  mask_color = FRAME_BACKGROUND_PIXEL (f);
1419
1420  /* Don't let pointers be invisible.  */
1421  if (mask_color == f->output_data.w32->mouse_pixel
1422	&& mask_color == FRAME_BACKGROUND_PIXEL (f))
1423    f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
1424
1425#if 0 /* TODO : cursor changes */
1426  BLOCK_INPUT;
1427
1428  /* It's not okay to crash if the user selects a screwy cursor.  */
1429  count = x_catch_errors (FRAME_W32_DISPLAY (f));
1430
1431  if (!EQ (Qnil, Vx_pointer_shape))
1432    {
1433      CHECK_NUMBER (Vx_pointer_shape);
1434      cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XINT (Vx_pointer_shape));
1435    }
1436  else
1437    cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1438  x_check_errors (FRAME_W32_DISPLAY (f), "bad text pointer cursor: %s");
1439
1440  if (!EQ (Qnil, Vx_nontext_pointer_shape))
1441    {
1442      CHECK_NUMBER (Vx_nontext_pointer_shape);
1443      nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1444					  XINT (Vx_nontext_pointer_shape));
1445    }
1446  else
1447    nontext_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_left_ptr);
1448  x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1449
1450  if (!EQ (Qnil, Vx_hourglass_pointer_shape))
1451    {
1452      CHECK_NUMBER (Vx_hourglass_pointer_shape);
1453      hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1454					    XINT (Vx_hourglass_pointer_shape));
1455    }
1456  else
1457    hourglass_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_watch);
1458  x_check_errors (FRAME_W32_DISPLAY (f), "bad busy pointer cursor: %s");
1459
1460  x_check_errors (FRAME_W32_DISPLAY (f), "bad nontext pointer cursor: %s");
1461  if (!EQ (Qnil, Vx_mode_pointer_shape))
1462    {
1463      CHECK_NUMBER (Vx_mode_pointer_shape);
1464      mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f),
1465				       XINT (Vx_mode_pointer_shape));
1466    }
1467  else
1468    mode_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_xterm);
1469  x_check_errors (FRAME_W32_DISPLAY (f), "bad modeline pointer cursor: %s");
1470
1471  if (!EQ (Qnil, Vx_sensitive_text_pointer_shape))
1472    {
1473      CHECK_NUMBER (Vx_sensitive_text_pointer_shape);
1474      hand_cursor
1475	= XCreateFontCursor (FRAME_W32_DISPLAY (f),
1476			     XINT (Vx_sensitive_text_pointer_shape));
1477    }
1478  else
1479    hand_cursor = XCreateFontCursor (FRAME_W32_DISPLAY (f), XC_crosshair);
1480
1481  if (!NILP (Vx_window_horizontal_drag_shape))
1482    {
1483      CHECK_NUMBER (Vx_window_horizontal_drag_shape);
1484      horizontal_drag_cursor
1485	= XCreateFontCursor (FRAME_X_DISPLAY (f),
1486			     XINT (Vx_window_horizontal_drag_shape));
1487    }
1488  else
1489    horizontal_drag_cursor
1490      = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
1491
1492  /* Check and report errors with the above calls.  */
1493  x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
1494  x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
1495
1496  {
1497    XColor fore_color, back_color;
1498
1499    fore_color.pixel = f->output_data.w32->mouse_pixel;
1500    back_color.pixel = mask_color;
1501    XQueryColor (FRAME_W32_DISPLAY (f),
1502		 DefaultColormap (FRAME_W32_DISPLAY (f),
1503				  DefaultScreen (FRAME_W32_DISPLAY (f))),
1504		 &fore_color);
1505    XQueryColor (FRAME_W32_DISPLAY (f),
1506		 DefaultColormap (FRAME_W32_DISPLAY (f),
1507				  DefaultScreen (FRAME_W32_DISPLAY (f))),
1508		 &back_color);
1509    XRecolorCursor (FRAME_W32_DISPLAY (f), cursor,
1510		    &fore_color, &back_color);
1511    XRecolorCursor (FRAME_W32_DISPLAY (f), nontext_cursor,
1512		    &fore_color, &back_color);
1513    XRecolorCursor (FRAME_W32_DISPLAY (f), mode_cursor,
1514		    &fore_color, &back_color);
1515    XRecolorCursor (FRAME_W32_DISPLAY (f), hand_cursor,
1516                    &fore_color, &back_color);
1517    XRecolorCursor (FRAME_W32_DISPLAY (f), hourglass_cursor,
1518                    &fore_color, &back_color);
1519  }
1520
1521  if (FRAME_W32_WINDOW (f) != 0)
1522    XDefineCursor (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), cursor);
1523
1524  if (cursor != f->output_data.w32->text_cursor && f->output_data.w32->text_cursor != 0)
1525    XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->text_cursor);
1526  f->output_data.w32->text_cursor = cursor;
1527
1528  if (nontext_cursor != f->output_data.w32->nontext_cursor
1529      && f->output_data.w32->nontext_cursor != 0)
1530    XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->nontext_cursor);
1531  f->output_data.w32->nontext_cursor = nontext_cursor;
1532
1533  if (hourglass_cursor != f->output_data.w32->hourglass_cursor
1534      && f->output_data.w32->hourglass_cursor != 0)
1535    XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hourglass_cursor);
1536  f->output_data.w32->hourglass_cursor = hourglass_cursor;
1537
1538  if (mode_cursor != f->output_data.w32->modeline_cursor
1539      && f->output_data.w32->modeline_cursor != 0)
1540    XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->modeline_cursor);
1541  f->output_data.w32->modeline_cursor = mode_cursor;
1542
1543  if (hand_cursor != f->output_data.w32->hand_cursor
1544      && f->output_data.w32->hand_cursor != 0)
1545    XFreeCursor (FRAME_W32_DISPLAY (f), f->output_data.w32->hand_cursor);
1546  f->output_data.w32->hand_cursor = hand_cursor;
1547
1548  XFlush (FRAME_W32_DISPLAY (f));
1549  UNBLOCK_INPUT;
1550
1551  update_face_from_frame_parameter (f, Qmouse_color, arg);
1552#endif /* TODO */
1553}
1554
1555/* Defined in w32term.c. */
1556void
1557x_set_cursor_color (f, arg, oldval)
1558     struct frame *f;
1559     Lisp_Object arg, oldval;
1560{
1561  unsigned long fore_pixel, pixel;
1562
1563  if (!NILP (Vx_cursor_fore_pixel))
1564    fore_pixel = x_decode_color (f, Vx_cursor_fore_pixel,
1565                                 WHITE_PIX_DEFAULT (f));
1566  else
1567    fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1568
1569  pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1570
1571  /* Make sure that the cursor color differs from the background color.  */
1572  if (pixel == FRAME_BACKGROUND_PIXEL (f))
1573    {
1574      pixel = f->output_data.w32->mouse_pixel;
1575      if (pixel == fore_pixel)
1576	fore_pixel = FRAME_BACKGROUND_PIXEL (f);
1577    }
1578
1579  f->output_data.w32->cursor_foreground_pixel = fore_pixel;
1580  f->output_data.w32->cursor_pixel = pixel;
1581
1582  if (FRAME_W32_WINDOW (f) != 0)
1583    {
1584      BLOCK_INPUT;
1585      /* Update frame's cursor_gc.  */
1586      f->output_data.w32->cursor_gc->foreground = fore_pixel;
1587      f->output_data.w32->cursor_gc->background = pixel;
1588
1589      UNBLOCK_INPUT;
1590
1591      if (FRAME_VISIBLE_P (f))
1592	{
1593	  x_update_cursor (f, 0);
1594	  x_update_cursor (f, 1);
1595	}
1596    }
1597
1598  update_face_from_frame_parameter (f, Qcursor_color, arg);
1599}
1600
1601/* Set the border-color of frame F to pixel value PIX.
1602   Note that this does not fully take effect if done before
1603   F has a window.  */
1604
1605void
1606x_set_border_pixel (f, pix)
1607     struct frame *f;
1608     int pix;
1609{
1610
1611  f->output_data.w32->border_pixel = pix;
1612
1613  if (FRAME_W32_WINDOW (f) != 0 && f->border_width > 0)
1614    {
1615      if (FRAME_VISIBLE_P (f))
1616        redraw_frame (f);
1617    }
1618}
1619
1620/* Set the border-color of frame F to value described by ARG.
1621   ARG can be a string naming a color.
1622   The border-color is used for the border that is drawn by the server.
1623   Note that this does not fully take effect if done before
1624   F has a window; it must be redone when the window is created.  */
1625
1626void
1627x_set_border_color (f, arg, oldval)
1628     struct frame *f;
1629     Lisp_Object arg, oldval;
1630{
1631  int pix;
1632
1633  CHECK_STRING (arg);
1634  pix = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
1635  x_set_border_pixel (f, pix);
1636  update_face_from_frame_parameter (f, Qborder_color, arg);
1637}
1638
1639
1640void
1641x_set_cursor_type (f, arg, oldval)
1642     FRAME_PTR f;
1643     Lisp_Object arg, oldval;
1644{
1645  set_frame_cursor_types (f, arg);
1646
1647  /* Make sure the cursor gets redrawn.  */
1648  cursor_type_changed = 1;
1649}
1650
1651void
1652x_set_icon_type (f, arg, oldval)
1653     struct frame *f;
1654     Lisp_Object arg, oldval;
1655{
1656  int result;
1657
1658  if (NILP (arg) && NILP (oldval))
1659    return;
1660
1661  if (STRINGP (arg) && STRINGP (oldval)
1662      && EQ (Fstring_equal (oldval, arg), Qt))
1663    return;
1664
1665  if (SYMBOLP (arg) && SYMBOLP (oldval) && EQ (arg, oldval))
1666    return;
1667
1668  BLOCK_INPUT;
1669
1670  result = x_bitmap_icon (f, arg);
1671  if (result)
1672    {
1673      UNBLOCK_INPUT;
1674      error ("No icon window available");
1675    }
1676
1677  UNBLOCK_INPUT;
1678}
1679
1680void
1681x_set_icon_name (f, arg, oldval)
1682     struct frame *f;
1683     Lisp_Object arg, oldval;
1684{
1685  if (STRINGP (arg))
1686    {
1687      if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
1688	return;
1689    }
1690  else if (!NILP (arg) || NILP (oldval))
1691    return;
1692
1693  f->icon_name = arg;
1694
1695#if 0
1696  if (f->output_data.w32->icon_bitmap != 0)
1697    return;
1698
1699  BLOCK_INPUT;
1700
1701  result = x_text_icon (f,
1702			(char *) SDATA ((!NILP (f->icon_name)
1703					 ? f->icon_name
1704					 : !NILP (f->title)
1705					 ? f->title
1706					 : f->name)));
1707
1708  if (result)
1709    {
1710      UNBLOCK_INPUT;
1711      error ("No icon window available");
1712    }
1713
1714  /* If the window was unmapped (and its icon was mapped),
1715     the new icon is not mapped, so map the window in its stead.  */
1716  if (FRAME_VISIBLE_P (f))
1717    {
1718#ifdef USE_X_TOOLKIT
1719      XtPopup (f->output_data.w32->widget, XtGrabNone);
1720#endif
1721      XMapWindow (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f));
1722    }
1723
1724  XFlush (FRAME_W32_DISPLAY (f));
1725  UNBLOCK_INPUT;
1726#endif
1727}
1728
1729
1730void
1731x_set_menu_bar_lines (f, value, oldval)
1732     struct frame *f;
1733     Lisp_Object value, oldval;
1734{
1735  int nlines;
1736  int olines = FRAME_MENU_BAR_LINES (f);
1737
1738  /* Right now, menu bars don't work properly in minibuf-only frames;
1739     most of the commands try to apply themselves to the minibuffer
1740     frame itself, and get an error because you can't switch buffers
1741     in or split the minibuffer window.  */
1742  if (FRAME_MINIBUF_ONLY_P (f))
1743    return;
1744
1745  if (INTEGERP (value))
1746    nlines = XINT (value);
1747  else
1748    nlines = 0;
1749
1750  FRAME_MENU_BAR_LINES (f) = 0;
1751  if (nlines)
1752    FRAME_EXTERNAL_MENU_BAR (f) = 1;
1753  else
1754    {
1755      if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1756	free_frame_menubar (f);
1757      FRAME_EXTERNAL_MENU_BAR (f) = 0;
1758
1759      /* Adjust the frame size so that the client (text) dimensions
1760	 remain the same.  This depends on FRAME_EXTERNAL_MENU_BAR being
1761	 set correctly.  */
1762      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
1763      do_pending_window_change (0);
1764    }
1765  adjust_glyphs (f);
1766}
1767
1768
1769/* Set the number of lines used for the tool bar of frame F to VALUE.
1770   VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL
1771   is the old number of tool bar lines.  This function changes the
1772   height of all windows on frame F to match the new tool bar height.
1773   The frame's height doesn't change.  */
1774
1775void
1776x_set_tool_bar_lines (f, value, oldval)
1777     struct frame *f;
1778     Lisp_Object value, oldval;
1779{
1780  int delta, nlines, root_height;
1781  Lisp_Object root_window;
1782
1783  /* Treat tool bars like menu bars.  */
1784  if (FRAME_MINIBUF_ONLY_P (f))
1785    return;
1786
1787  /* Use VALUE only if an integer >= 0.  */
1788  if (INTEGERP (value) && XINT (value) >= 0)
1789    nlines = XFASTINT (value);
1790  else
1791    nlines = 0;
1792
1793  /* Make sure we redisplay all windows in this frame.  */
1794  ++windows_or_buffers_changed;
1795
1796  delta = nlines - FRAME_TOOL_BAR_LINES (f);
1797
1798  /* Don't resize the tool-bar to more than we have room for.  */
1799  root_window = FRAME_ROOT_WINDOW (f);
1800  root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
1801  if (root_height - delta < 1)
1802    {
1803      delta = root_height - 1;
1804      nlines = FRAME_TOOL_BAR_LINES (f) + delta;
1805    }
1806
1807  FRAME_TOOL_BAR_LINES (f) = nlines;
1808  change_window_heights (root_window, delta);
1809  adjust_glyphs (f);
1810
1811  /* We also have to make sure that the internal border at the top of
1812     the frame, below the menu bar or tool bar, is redrawn when the
1813     tool bar disappears.  This is so because the internal border is
1814     below the tool bar if one is displayed, but is below the menu bar
1815     if there isn't a tool bar.  The tool bar draws into the area
1816     below the menu bar.  */
1817  if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
1818    {
1819      updating_frame = f;
1820      clear_frame ();
1821      clear_current_matrices (f);
1822      updating_frame = NULL;
1823    }
1824
1825  /* If the tool bar gets smaller, the internal border below it
1826     has to be cleared.  It was formerly part of the display
1827     of the larger tool bar, and updating windows won't clear it.  */
1828  if (delta < 0)
1829    {
1830      int height = FRAME_INTERNAL_BORDER_WIDTH (f);
1831      int width = FRAME_PIXEL_WIDTH (f);
1832      int y = nlines * FRAME_LINE_HEIGHT (f);
1833
1834      BLOCK_INPUT;
1835      {
1836        HDC hdc = get_frame_dc (f);
1837        w32_clear_area (f, hdc, 0, y, width, height);
1838        release_frame_dc (f, hdc);
1839      }
1840      UNBLOCK_INPUT;
1841
1842      if (WINDOWP (f->tool_bar_window))
1843	clear_glyph_matrix (XWINDOW (f->tool_bar_window)->current_matrix);
1844    }
1845}
1846
1847
1848/* Change the name of frame F to NAME.  If NAME is nil, set F's name to
1849       w32_id_name.
1850
1851   If EXPLICIT is non-zero, that indicates that lisp code is setting the
1852       name; if NAME is a string, set F's name to NAME and set
1853       F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1854
1855   If EXPLICIT is zero, that indicates that Emacs redisplay code is
1856       suggesting a new name, which lisp code should override; if
1857       F->explicit_name is set, ignore the new name; otherwise, set it.  */
1858
1859void
1860x_set_name (f, name, explicit)
1861     struct frame *f;
1862     Lisp_Object name;
1863     int explicit;
1864{
1865  /* Make sure that requests from lisp code override requests from
1866     Emacs redisplay code.  */
1867  if (explicit)
1868    {
1869      /* If we're switching from explicit to implicit, we had better
1870	 update the mode lines and thereby update the title.  */
1871      if (f->explicit_name && NILP (name))
1872	update_mode_lines = 1;
1873
1874      f->explicit_name = ! NILP (name);
1875    }
1876  else if (f->explicit_name)
1877    return;
1878
1879  /* If NAME is nil, set the name to the w32_id_name.  */
1880  if (NILP (name))
1881    {
1882      /* Check for no change needed in this very common case
1883	 before we do any consing.  */
1884      if (!strcmp (FRAME_W32_DISPLAY_INFO (f)->w32_id_name,
1885		   SDATA (f->name)))
1886	return;
1887      name = build_string (FRAME_W32_DISPLAY_INFO (f)->w32_id_name);
1888    }
1889  else
1890    CHECK_STRING (name);
1891
1892  /* Don't change the name if it's already NAME.  */
1893  if (! NILP (Fstring_equal (name, f->name)))
1894    return;
1895
1896  f->name = name;
1897
1898  /* For setting the frame title, the title parameter should override
1899     the name parameter.  */
1900  if (! NILP (f->title))
1901    name = f->title;
1902
1903  if (FRAME_W32_WINDOW (f))
1904    {
1905      if (STRING_MULTIBYTE (name))
1906	name = ENCODE_SYSTEM (name);
1907
1908      BLOCK_INPUT;
1909      SetWindowText(FRAME_W32_WINDOW (f), SDATA (name));
1910      UNBLOCK_INPUT;
1911    }
1912}
1913
1914/* This function should be called when the user's lisp code has
1915   specified a name for the frame; the name will override any set by the
1916   redisplay code.  */
1917void
1918x_explicitly_set_name (f, arg, oldval)
1919     FRAME_PTR f;
1920     Lisp_Object arg, oldval;
1921{
1922  x_set_name (f, arg, 1);
1923}
1924
1925/* This function should be called by Emacs redisplay code to set the
1926   name; names set this way will never override names set by the user's
1927   lisp code.  */
1928void
1929x_implicitly_set_name (f, arg, oldval)
1930     FRAME_PTR f;
1931     Lisp_Object arg, oldval;
1932{
1933  x_set_name (f, arg, 0);
1934}
1935
1936/* Change the title of frame F to NAME.
1937   If NAME is nil, use the frame name as the title.
1938
1939   If EXPLICIT is non-zero, that indicates that lisp code is setting the
1940       name; if NAME is a string, set F's name to NAME and set
1941       F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
1942
1943   If EXPLICIT is zero, that indicates that Emacs redisplay code is
1944       suggesting a new name, which lisp code should override; if
1945       F->explicit_name is set, ignore the new name; otherwise, set it.  */
1946
1947void
1948x_set_title (f, name, old_name)
1949     struct frame *f;
1950     Lisp_Object name, old_name;
1951{
1952  /* Don't change the title if it's already NAME.  */
1953  if (EQ (name, f->title))
1954    return;
1955
1956  update_mode_lines = 1;
1957
1958  f->title = name;
1959
1960  if (NILP (name))
1961    name = f->name;
1962
1963  if (FRAME_W32_WINDOW (f))
1964    {
1965      if (STRING_MULTIBYTE (name))
1966	name = ENCODE_SYSTEM (name);
1967
1968      BLOCK_INPUT;
1969      SetWindowText(FRAME_W32_WINDOW (f), SDATA (name));
1970      UNBLOCK_INPUT;
1971    }
1972}
1973
1974
1975void x_set_scroll_bar_default_width (f)
1976     struct frame *f;
1977{
1978  int wid = FRAME_COLUMN_WIDTH (f);
1979
1980  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
1981  FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
1982				      wid - 1) / wid;
1983}
1984
1985
1986/* Subroutines of creating a frame.  */
1987
1988
1989/* Return the value of parameter PARAM.
1990
1991   First search ALIST, then Vdefault_frame_alist, then the X defaults
1992   database, using ATTRIBUTE as the attribute name and CLASS as its class.
1993
1994   Convert the resource to the type specified by desired_type.
1995
1996   If no default is specified, return Qunbound.  If you call
1997   w32_get_arg, make sure you deal with Qunbound in a reasonable way,
1998   and don't let it get stored in any Lisp-visible variables!  */
1999
2000static Lisp_Object
2001w32_get_arg (alist, param, attribute, class, type)
2002     Lisp_Object alist, param;
2003     char *attribute;
2004     char *class;
2005     enum resource_types type;
2006{
2007  return x_get_arg (check_x_display_info (Qnil),
2008		    alist, param, attribute, class, type);
2009}
2010
2011
2012Cursor
2013w32_load_cursor (LPCTSTR name)
2014{
2015  /* Try first to load cursor from application resource.  */
2016  Cursor cursor = LoadImage ((HINSTANCE) GetModuleHandle(NULL),
2017			     name, IMAGE_CURSOR, 0, 0,
2018			     LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
2019  if (!cursor)
2020    {
2021      /* Then try to load a shared predefined cursor.  */
2022      cursor = LoadImage (NULL, name, IMAGE_CURSOR, 0, 0,
2023			  LR_DEFAULTCOLOR | LR_DEFAULTSIZE | LR_SHARED);
2024    }
2025  return cursor;
2026}
2027
2028extern LRESULT CALLBACK w32_wnd_proc ();
2029
2030BOOL
2031w32_init_class (hinst)
2032     HINSTANCE hinst;
2033{
2034  WNDCLASS wc;
2035
2036  wc.style = CS_HREDRAW | CS_VREDRAW;
2037  wc.lpfnWndProc = (WNDPROC) w32_wnd_proc;
2038  wc.cbClsExtra = 0;
2039  wc.cbWndExtra = WND_EXTRA_BYTES;
2040  wc.hInstance = hinst;
2041  wc.hIcon = LoadIcon (hinst, EMACS_CLASS);
2042  wc.hCursor = w32_load_cursor (IDC_ARROW);
2043  wc.hbrBackground = NULL; /* GetStockObject (WHITE_BRUSH);  */
2044  wc.lpszMenuName = NULL;
2045  wc.lpszClassName = EMACS_CLASS;
2046
2047  return (RegisterClass (&wc));
2048}
2049
2050HWND
2051w32_createscrollbar (f, bar)
2052     struct frame *f;
2053     struct scroll_bar * bar;
2054{
2055  return (CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE,
2056			/* Position and size of scroll bar.  */
2057			XINT(bar->left) + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
2058                        XINT(bar->top),
2059			XINT(bar->width) - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
2060                        XINT(bar->height),
2061			FRAME_W32_WINDOW (f),
2062			NULL,
2063			hinst,
2064			NULL));
2065}
2066
2067void
2068w32_createwindow (f)
2069     struct frame *f;
2070{
2071  HWND hwnd;
2072  RECT rect;
2073  Lisp_Object top = Qunbound;
2074  Lisp_Object left = Qunbound;
2075
2076  rect.left = rect.top = 0;
2077  rect.right = FRAME_PIXEL_WIDTH (f);
2078  rect.bottom = FRAME_PIXEL_HEIGHT (f);
2079
2080  AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
2081		    FRAME_EXTERNAL_MENU_BAR (f));
2082
2083  /* Do first time app init */
2084
2085  if (!hprevinst)
2086    {
2087      w32_init_class (hinst);
2088    }
2089
2090  if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
2091    {
2092      XSETINT (left, f->left_pos);
2093      XSETINT (top, f->top_pos);
2094    }
2095  else if (EQ (left, Qunbound) && EQ (top, Qunbound))
2096    {
2097      /* When called with RES_TYPE_NUMBER, w32_get_arg will return zero
2098	 for anything that is not a number and is not Qunbound.  */
2099      left = w32_get_arg (Qnil, Qleft, "left", "Left", RES_TYPE_NUMBER);
2100      top = w32_get_arg (Qnil, Qtop, "top", "Top", RES_TYPE_NUMBER);
2101    }
2102
2103  FRAME_W32_WINDOW (f) = hwnd
2104    = CreateWindow (EMACS_CLASS,
2105		    f->namebuf,
2106		    f->output_data.w32->dwStyle | WS_CLIPCHILDREN,
2107		    EQ (left, Qunbound) ? CW_USEDEFAULT : XINT (left),
2108		    EQ (top, Qunbound) ? CW_USEDEFAULT : XINT (top),
2109		    rect.right - rect.left,
2110		    rect.bottom - rect.top,
2111		    NULL,
2112		    NULL,
2113		    hinst,
2114		    NULL);
2115
2116  if (hwnd)
2117    {
2118      SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
2119      SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
2120      SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
2121      SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
2122      SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
2123
2124      /* Enable drag-n-drop.  */
2125      DragAcceptFiles (hwnd, TRUE);
2126
2127      /* Do this to discard the default setting specified by our parent. */
2128      ShowWindow (hwnd, SW_HIDE);
2129
2130      /* Update frame positions. */
2131      GetWindowRect (hwnd, &rect);
2132      f->left_pos = rect.left;
2133      f->top_pos = rect.top;
2134    }
2135}
2136
2137void
2138my_post_msg (wmsg, hwnd, msg, wParam, lParam)
2139     W32Msg * wmsg;
2140     HWND hwnd;
2141     UINT msg;
2142     WPARAM wParam;
2143     LPARAM lParam;
2144{
2145  wmsg->msg.hwnd = hwnd;
2146  wmsg->msg.message = msg;
2147  wmsg->msg.wParam = wParam;
2148  wmsg->msg.lParam = lParam;
2149  wmsg->msg.time = GetMessageTime ();
2150
2151  post_msg (wmsg);
2152}
2153
2154/* GetKeyState and MapVirtualKey on Windows 95 do not actually distinguish
2155   between left and right keys as advertised.  We test for this
2156   support dynamically, and set a flag when the support is absent.  If
2157   absent, we keep track of the left and right control and alt keys
2158   ourselves.  This is particularly necessary on keyboards that rely
2159   upon the AltGr key, which is represented as having the left control
2160   and right alt keys pressed.  For these keyboards, we need to know
2161   when the left alt key has been pressed in addition to the AltGr key
2162   so that we can properly support M-AltGr-key sequences (such as M-@
2163   on Swedish keyboards).  */
2164
2165#define EMACS_LCONTROL 0
2166#define EMACS_RCONTROL 1
2167#define EMACS_LMENU    2
2168#define EMACS_RMENU    3
2169
2170static int modifiers[4];
2171static int modifiers_recorded;
2172static int modifier_key_support_tested;
2173
2174static void
2175test_modifier_support (unsigned int wparam)
2176{
2177  unsigned int l, r;
2178
2179  if (wparam != VK_CONTROL && wparam != VK_MENU)
2180    return;
2181  if (wparam == VK_CONTROL)
2182    {
2183      l = VK_LCONTROL;
2184      r = VK_RCONTROL;
2185    }
2186  else
2187    {
2188      l = VK_LMENU;
2189      r = VK_RMENU;
2190    }
2191  if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
2192    modifiers_recorded = 1;
2193  else
2194    modifiers_recorded = 0;
2195  modifier_key_support_tested = 1;
2196}
2197
2198static void
2199record_keydown (unsigned int wparam, unsigned int lparam)
2200{
2201  int i;
2202
2203  if (!modifier_key_support_tested)
2204    test_modifier_support (wparam);
2205
2206  if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
2207    return;
2208
2209  if (wparam == VK_CONTROL)
2210    i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
2211  else
2212    i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2213
2214  modifiers[i] = 1;
2215}
2216
2217static void
2218record_keyup (unsigned int wparam, unsigned int lparam)
2219{
2220  int i;
2221
2222  if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
2223    return;
2224
2225  if (wparam == VK_CONTROL)
2226    i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
2227  else
2228    i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
2229
2230  modifiers[i] = 0;
2231}
2232
2233/* Emacs can lose focus while a modifier key has been pressed.  When
2234   it regains focus, be conservative and clear all modifiers since
2235   we cannot reconstruct the left and right modifier state.  */
2236static void
2237reset_modifiers ()
2238{
2239  SHORT ctrl, alt;
2240
2241  if (GetFocus () == NULL)
2242    /* Emacs doesn't have keyboard focus.  Do nothing.  */
2243    return;
2244
2245  ctrl = GetAsyncKeyState (VK_CONTROL);
2246  alt = GetAsyncKeyState (VK_MENU);
2247
2248  if (!(ctrl & 0x08000))
2249    /* Clear any recorded control modifier state.  */
2250    modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
2251
2252  if (!(alt & 0x08000))
2253    /* Clear any recorded alt modifier state.  */
2254    modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
2255
2256  /* Update the state of all modifier keys, because modifiers used in
2257     hot-key combinations can get stuck on if Emacs loses focus as a
2258     result of a hot-key being pressed.  */
2259  {
2260    BYTE keystate[256];
2261
2262#define CURRENT_STATE(key) ((GetAsyncKeyState (key) & 0x8000) >> 8)
2263
2264    GetKeyboardState (keystate);
2265    keystate[VK_SHIFT] = CURRENT_STATE (VK_SHIFT);
2266    keystate[VK_CONTROL] = CURRENT_STATE (VK_CONTROL);
2267    keystate[VK_LCONTROL] = CURRENT_STATE (VK_LCONTROL);
2268    keystate[VK_RCONTROL] = CURRENT_STATE (VK_RCONTROL);
2269    keystate[VK_MENU] = CURRENT_STATE (VK_MENU);
2270    keystate[VK_LMENU] = CURRENT_STATE (VK_LMENU);
2271    keystate[VK_RMENU] = CURRENT_STATE (VK_RMENU);
2272    keystate[VK_LWIN] = CURRENT_STATE (VK_LWIN);
2273    keystate[VK_RWIN] = CURRENT_STATE (VK_RWIN);
2274    keystate[VK_APPS] = CURRENT_STATE (VK_APPS);
2275    SetKeyboardState (keystate);
2276  }
2277}
2278
2279/* Synchronize modifier state with what is reported with the current
2280   keystroke.  Even if we cannot distinguish between left and right
2281   modifier keys, we know that, if no modifiers are set, then neither
2282   the left or right modifier should be set.  */
2283static void
2284sync_modifiers ()
2285{
2286  if (!modifiers_recorded)
2287    return;
2288
2289  if (!(GetKeyState (VK_CONTROL) & 0x8000))
2290    modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
2291
2292  if (!(GetKeyState (VK_MENU) & 0x8000))
2293    modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
2294}
2295
2296static int
2297modifier_set (int vkey)
2298{
2299  if (vkey == VK_CAPITAL || vkey == VK_SCROLL)
2300    return (GetKeyState (vkey) & 0x1);
2301  if (!modifiers_recorded)
2302    return (GetKeyState (vkey) & 0x8000);
2303
2304  switch (vkey)
2305    {
2306    case VK_LCONTROL:
2307      return modifiers[EMACS_LCONTROL];
2308    case VK_RCONTROL:
2309      return modifiers[EMACS_RCONTROL];
2310    case VK_LMENU:
2311      return modifiers[EMACS_LMENU];
2312    case VK_RMENU:
2313      return modifiers[EMACS_RMENU];
2314    }
2315  return (GetKeyState (vkey) & 0x8000);
2316}
2317
2318/* Convert between the modifier bits W32 uses and the modifier bits
2319   Emacs uses.  */
2320
2321unsigned int
2322w32_key_to_modifier (int key)
2323{
2324  Lisp_Object key_mapping;
2325
2326  switch (key)
2327    {
2328    case VK_LWIN:
2329      key_mapping = Vw32_lwindow_modifier;
2330      break;
2331    case VK_RWIN:
2332      key_mapping = Vw32_rwindow_modifier;
2333      break;
2334    case VK_APPS:
2335      key_mapping = Vw32_apps_modifier;
2336      break;
2337    case VK_SCROLL:
2338      key_mapping = Vw32_scroll_lock_modifier;
2339      break;
2340    default:
2341      key_mapping = Qnil;
2342    }
2343
2344  /* NB. This code runs in the input thread, asychronously to the lisp
2345     thread, so we must be careful to ensure access to lisp data is
2346     thread-safe.  The following code is safe because the modifier
2347     variable values are updated atomically from lisp and symbols are
2348     not relocated by GC.  Also, we don't have to worry about seeing GC
2349     markbits here.  */
2350  if (EQ (key_mapping, Qhyper))
2351    return hyper_modifier;
2352  if (EQ (key_mapping, Qsuper))
2353    return super_modifier;
2354  if (EQ (key_mapping, Qmeta))
2355    return meta_modifier;
2356  if (EQ (key_mapping, Qalt))
2357    return alt_modifier;
2358  if (EQ (key_mapping, Qctrl))
2359    return ctrl_modifier;
2360  if (EQ (key_mapping, Qcontrol)) /* synonym for ctrl */
2361    return ctrl_modifier;
2362  if (EQ (key_mapping, Qshift))
2363    return shift_modifier;
2364
2365  /* Don't generate any modifier if not explicitly requested.  */
2366  return 0;
2367}
2368
2369unsigned int
2370w32_get_modifiers ()
2371{
2372  return ((modifier_set (VK_SHIFT)   ? shift_modifier : 0) |
2373	  (modifier_set (VK_CONTROL) ? ctrl_modifier  : 0) |
2374	  (modifier_set (VK_LWIN)    ? w32_key_to_modifier (VK_LWIN) : 0) |
2375	  (modifier_set (VK_RWIN)    ? w32_key_to_modifier (VK_RWIN) : 0) |
2376	  (modifier_set (VK_APPS)    ? w32_key_to_modifier (VK_APPS) : 0) |
2377	  (modifier_set (VK_SCROLL)  ? w32_key_to_modifier (VK_SCROLL) : 0) |
2378          (modifier_set (VK_MENU)    ?
2379	   ((NILP (Vw32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
2380}
2381
2382/* We map the VK_* modifiers into console modifier constants
2383   so that we can use the same routines to handle both console
2384   and window input.  */
2385
2386static int
2387construct_console_modifiers ()
2388{
2389  int mods;
2390
2391  mods = 0;
2392  mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
2393  mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
2394  mods |= (modifier_set (VK_SCROLL)) ? SCROLLLOCK_ON : 0;
2395  mods |= (modifier_set (VK_NUMLOCK)) ? NUMLOCK_ON : 0;
2396  mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
2397  mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
2398  mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
2399  mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
2400  mods |= (modifier_set (VK_LWIN)) ? LEFT_WIN_PRESSED : 0;
2401  mods |= (modifier_set (VK_RWIN)) ? RIGHT_WIN_PRESSED : 0;
2402  mods |= (modifier_set (VK_APPS)) ? APPS_PRESSED : 0;
2403
2404  return mods;
2405}
2406
2407static int
2408w32_get_key_modifiers (unsigned int wparam, unsigned int lparam)
2409{
2410  int mods;
2411
2412  /* Convert to emacs modifiers.  */
2413  mods = w32_kbd_mods_to_emacs (construct_console_modifiers (), wparam);
2414
2415  return mods;
2416}
2417
2418unsigned int
2419map_keypad_keys (unsigned int virt_key, unsigned int extended)
2420{
2421  if (virt_key < VK_CLEAR || virt_key > VK_DELETE)
2422    return virt_key;
2423
2424  if (virt_key == VK_RETURN)
2425    return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
2426
2427  if (virt_key >= VK_PRIOR && virt_key <= VK_DOWN)
2428    return (!extended ? (VK_NUMPAD_PRIOR + (virt_key - VK_PRIOR)) : virt_key);
2429
2430  if (virt_key == VK_INSERT || virt_key == VK_DELETE)
2431    return (!extended ? (VK_NUMPAD_INSERT + (virt_key - VK_INSERT)) : virt_key);
2432
2433  if (virt_key == VK_CLEAR)
2434    return (!extended ? VK_NUMPAD_CLEAR : virt_key);
2435
2436  return virt_key;
2437}
2438
2439/* List of special key combinations which w32 would normally capture,
2440   but emacs should grab instead.  Not directly visible to lisp, to
2441   simplify synchronization.  Each item is an integer encoding a virtual
2442   key code and modifier combination to capture.  */
2443Lisp_Object w32_grabbed_keys;
2444
2445#define HOTKEY(vk,mods)       make_number (((vk) & 255) | ((mods) << 8))
2446#define HOTKEY_ID(k)          (XFASTINT (k) & 0xbfff)
2447#define HOTKEY_VK_CODE(k)     (XFASTINT (k) & 255)
2448#define HOTKEY_MODIFIERS(k)   (XFASTINT (k) >> 8)
2449
2450#define RAW_HOTKEY_ID(k)        ((k) & 0xbfff)
2451#define RAW_HOTKEY_VK_CODE(k)   ((k) & 255)
2452#define RAW_HOTKEY_MODIFIERS(k) ((k) >> 8)
2453
2454/* Register hot-keys for reserved key combinations when Emacs has
2455   keyboard focus, since this is the only way Emacs can receive key
2456   combinations like Alt-Tab which are used by the system.  */
2457
2458static void
2459register_hot_keys (hwnd)
2460     HWND hwnd;
2461{
2462  Lisp_Object keylist;
2463
2464  /* Use GC_CONSP, since we are called asynchronously.  */
2465  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
2466    {
2467      Lisp_Object key = XCAR (keylist);
2468
2469      /* Deleted entries get set to nil.  */
2470      if (!INTEGERP (key))
2471	continue;
2472
2473      RegisterHotKey (hwnd, HOTKEY_ID (key),
2474		      HOTKEY_MODIFIERS (key), HOTKEY_VK_CODE (key));
2475    }
2476}
2477
2478static void
2479unregister_hot_keys (hwnd)
2480     HWND hwnd;
2481{
2482  Lisp_Object keylist;
2483
2484  /* Use GC_CONSP, since we are called asynchronously.  */
2485  for (keylist = w32_grabbed_keys; GC_CONSP (keylist); keylist = XCDR (keylist))
2486    {
2487      Lisp_Object key = XCAR (keylist);
2488
2489      if (!INTEGERP (key))
2490	continue;
2491
2492      UnregisterHotKey (hwnd, HOTKEY_ID (key));
2493    }
2494}
2495
2496/* Main message dispatch loop. */
2497
2498static void
2499w32_msg_pump (deferred_msg * msg_buf)
2500{
2501  MSG msg;
2502  int result;
2503  HWND focus_window;
2504
2505  msh_mousewheel = RegisterWindowMessage (MSH_MOUSEWHEEL);
2506
2507  while (GetMessage (&msg, NULL, 0, 0))
2508    {
2509      if (msg.hwnd == NULL)
2510	{
2511	  switch (msg.message)
2512	    {
2513	    case WM_NULL:
2514	      /* Produced by complete_deferred_msg; just ignore.  */
2515	      break;
2516	    case WM_EMACS_CREATEWINDOW:
2517	      w32_createwindow ((struct frame *) msg.wParam);
2518	      if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2519		abort ();
2520	      break;
2521	    case WM_EMACS_SETLOCALE:
2522	      SetThreadLocale (msg.wParam);
2523	      /* Reply is not expected.  */
2524	      break;
2525	    case WM_EMACS_SETKEYBOARDLAYOUT:
2526	      result = (int) ActivateKeyboardLayout ((HKL) msg.wParam, 0);
2527	      if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
2528				      result, 0))
2529		abort ();
2530	      break;
2531	    case WM_EMACS_REGISTER_HOT_KEY:
2532	      focus_window = GetFocus ();
2533	      if (focus_window != NULL)
2534		RegisterHotKey (focus_window,
2535				RAW_HOTKEY_ID (msg.wParam),
2536				RAW_HOTKEY_MODIFIERS (msg.wParam),
2537				RAW_HOTKEY_VK_CODE (msg.wParam));
2538	      /* Reply is not expected.  */
2539	      break;
2540	    case WM_EMACS_UNREGISTER_HOT_KEY:
2541	      focus_window = GetFocus ();
2542	      if (focus_window != NULL)
2543		UnregisterHotKey (focus_window, RAW_HOTKEY_ID (msg.wParam));
2544	      /* Mark item as erased.  NB: this code must be
2545                 thread-safe.  The next line is okay because the cons
2546                 cell is never made into garbage and is not relocated by
2547                 GC.  */
2548	      XSETCAR ((Lisp_Object) ((EMACS_INT) msg.lParam), Qnil);
2549	      if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2550		abort ();
2551	      break;
2552	    case WM_EMACS_TOGGLE_LOCK_KEY:
2553	      {
2554		int vk_code = (int) msg.wParam;
2555		int cur_state = (GetKeyState (vk_code) & 1);
2556		Lisp_Object new_state = (Lisp_Object) ((EMACS_INT) msg.lParam);
2557
2558		/* NB: This code must be thread-safe.  It is safe to
2559                   call NILP because symbols are not relocated by GC,
2560                   and pointer here is not touched by GC (so the markbit
2561                   can't be set).  Numbers are safe because they are
2562                   immediate values.  */
2563		if (NILP (new_state)
2564		    || (NUMBERP (new_state)
2565			&& ((XUINT (new_state)) & 1) != cur_state))
2566		  {
2567		    one_w32_display_info.faked_key = vk_code;
2568
2569		    keybd_event ((BYTE) vk_code,
2570				 (BYTE) MapVirtualKey (vk_code, 0),
2571				 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2572		    keybd_event ((BYTE) vk_code,
2573				 (BYTE) MapVirtualKey (vk_code, 0),
2574				 KEYEVENTF_EXTENDEDKEY | 0, 0);
2575		    keybd_event ((BYTE) vk_code,
2576				 (BYTE) MapVirtualKey (vk_code, 0),
2577				 KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
2578		    cur_state = !cur_state;
2579		  }
2580		if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE,
2581					cur_state, 0))
2582		  abort ();
2583	      }
2584	      break;
2585	    default:
2586	      DebPrint (("msg %x not expected by w32_msg_pump\n", msg.message));
2587	    }
2588	}
2589      else
2590	{
2591	  DispatchMessage (&msg);
2592	}
2593
2594      /* Exit nested loop when our deferred message has completed.  */
2595      if (msg_buf->completed)
2596	break;
2597    }
2598}
2599
2600deferred_msg * deferred_msg_head;
2601
2602static deferred_msg *
2603find_deferred_msg (HWND hwnd, UINT msg)
2604{
2605  deferred_msg * item;
2606
2607  /* Don't actually need synchronization for read access, since
2608     modification of single pointer is always atomic.  */
2609  /* enter_crit (); */
2610
2611  for (item = deferred_msg_head; item != NULL; item = item->next)
2612    if (item->w32msg.msg.hwnd == hwnd
2613	&& item->w32msg.msg.message == msg)
2614      break;
2615
2616  /* leave_crit (); */
2617
2618  return item;
2619}
2620
2621static LRESULT
2622send_deferred_msg (deferred_msg * msg_buf,
2623		   HWND hwnd,
2624		   UINT msg,
2625		   WPARAM wParam,
2626		   LPARAM lParam)
2627{
2628  /* Only input thread can send deferred messages.  */
2629  if (GetCurrentThreadId () != dwWindowsThreadId)
2630    abort ();
2631
2632  /* It is an error to send a message that is already deferred.  */
2633  if (find_deferred_msg (hwnd, msg) != NULL)
2634    abort ();
2635
2636  /* Enforced synchronization is not needed because this is the only
2637     function that alters deferred_msg_head, and the following critical
2638     section is guaranteed to only be serially reentered (since only the
2639     input thread can call us).  */
2640
2641  /* enter_crit (); */
2642
2643  msg_buf->completed = 0;
2644  msg_buf->next = deferred_msg_head;
2645  deferred_msg_head = msg_buf;
2646  my_post_msg (&msg_buf->w32msg, hwnd, msg, wParam, lParam);
2647
2648  /* leave_crit (); */
2649
2650  /* Start a new nested message loop to process other messages until
2651     this one is completed.  */
2652  w32_msg_pump (msg_buf);
2653
2654  deferred_msg_head = msg_buf->next;
2655
2656  return msg_buf->result;
2657}
2658
2659void
2660complete_deferred_msg (HWND hwnd, UINT msg, LRESULT result)
2661{
2662  deferred_msg * msg_buf = find_deferred_msg (hwnd, msg);
2663
2664  if (msg_buf == NULL)
2665    /* Message may have been cancelled, so don't abort().  */
2666    return;
2667
2668  msg_buf->result = result;
2669  msg_buf->completed = 1;
2670
2671  /* Ensure input thread is woken so it notices the completion.  */
2672  PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
2673}
2674
2675void
2676cancel_all_deferred_msgs ()
2677{
2678  deferred_msg * item;
2679
2680  /* Don't actually need synchronization for read access, since
2681     modification of single pointer is always atomic.  */
2682  /* enter_crit (); */
2683
2684  for (item = deferred_msg_head; item != NULL; item = item->next)
2685    {
2686      item->result = 0;
2687      item->completed = 1;
2688    }
2689
2690  /* leave_crit (); */
2691
2692  /* Ensure input thread is woken so it notices the completion.  */
2693  PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0);
2694}
2695
2696DWORD WINAPI
2697w32_msg_worker (void *arg)
2698{
2699  MSG msg;
2700  deferred_msg dummy_buf;
2701
2702  /* Ensure our message queue is created */
2703
2704  PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
2705
2706  if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0))
2707    abort ();
2708
2709  memset (&dummy_buf, 0, sizeof (dummy_buf));
2710  dummy_buf.w32msg.msg.hwnd = NULL;
2711  dummy_buf.w32msg.msg.message = WM_NULL;
2712
2713  /* This is the inital message loop which should only exit when the
2714     application quits.  */
2715  w32_msg_pump (&dummy_buf);
2716
2717  return 0;
2718}
2719
2720static void
2721signal_user_input ()
2722{
2723  /* Interrupt any lisp that wants to be interrupted by input.  */
2724  if (!NILP (Vthrow_on_input))
2725    {
2726      Vquit_flag = Vthrow_on_input;
2727      /* If we're inside a function that wants immediate quits,
2728	 do it now.  */
2729      if (immediate_quit && NILP (Vinhibit_quit))
2730	{
2731	  immediate_quit = 0;
2732	  QUIT;
2733	}
2734    }
2735}
2736
2737
2738static void
2739post_character_message (hwnd, msg, wParam, lParam, modifiers)
2740     HWND hwnd;
2741     UINT msg;
2742     WPARAM wParam;
2743     LPARAM lParam;
2744     DWORD  modifiers;
2745
2746{
2747  W32Msg wmsg;
2748
2749  wmsg.dwModifiers = modifiers;
2750
2751  /* Detect quit_char and set quit-flag directly.  Note that we
2752     still need to post a message to ensure the main thread will be
2753     woken up if blocked in sys_select(), but we do NOT want to post
2754     the quit_char message itself (because it will usually be as if
2755     the user had typed quit_char twice).  Instead, we post a dummy
2756     message that has no particular effect. */
2757  {
2758    int c = wParam;
2759    if (isalpha (c) && wmsg.dwModifiers == ctrl_modifier)
2760      c = make_ctrl_char (c) & 0377;
2761    if (c == quit_char
2762	|| (wmsg.dwModifiers == 0 &&
2763	    w32_quit_key && wParam == w32_quit_key))
2764      {
2765	Vquit_flag = Qt;
2766
2767	/* The choice of message is somewhat arbitrary, as long as
2768	   the main thread handler just ignores it. */
2769	msg = WM_NULL;
2770
2771	/* Interrupt any blocking system calls.  */
2772	signal_quit ();
2773
2774	/* As a safety precaution, forcibly complete any deferred
2775           messages.  This is a kludge, but I don't see any particularly
2776           clean way to handle the situation where a deferred message is
2777           "dropped" in the lisp thread, and will thus never be
2778           completed, eg. by the user trying to activate the menubar
2779           when the lisp thread is busy, and then typing C-g when the
2780           menubar doesn't open promptly (with the result that the
2781           menubar never responds at all because the deferred
2782           WM_INITMENU message is never completed).  Another problem
2783           situation is when the lisp thread calls SendMessage (to send
2784           a window manager command) when a message has been deferred;
2785           the lisp thread gets blocked indefinitely waiting for the
2786           deferred message to be completed, which itself is waiting for
2787           the lisp thread to respond.
2788
2789	   Note that we don't want to block the input thread waiting for
2790	   a reponse from the lisp thread (although that would at least
2791	   solve the deadlock problem above), because we want to be able
2792	   to receive C-g to interrupt the lisp thread.  */
2793	cancel_all_deferred_msgs ();
2794      }
2795    else
2796      signal_user_input ();
2797  }
2798
2799  my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2800}
2801
2802/* Main window procedure */
2803
2804LRESULT CALLBACK
2805w32_wnd_proc (hwnd, msg, wParam, lParam)
2806     HWND hwnd;
2807     UINT msg;
2808     WPARAM wParam;
2809     LPARAM lParam;
2810{
2811  struct frame *f;
2812  struct w32_display_info *dpyinfo = &one_w32_display_info;
2813  W32Msg wmsg;
2814  int windows_translate;
2815  int key;
2816
2817  /* Note that it is okay to call x_window_to_frame, even though we are
2818     not running in the main lisp thread, because frame deletion
2819     requires the lisp thread to synchronize with this thread.  Thus, if
2820     a frame struct is returned, it can be used without concern that the
2821     lisp thread might make it disappear while we are using it.
2822
2823     NB. Walking the frame list in this thread is safe (as long as
2824     writes of Lisp_Object slots are atomic, which they are on Windows).
2825     Although delete-frame can destructively modify the frame list while
2826     we are walking it, a garbage collection cannot occur until after
2827     delete-frame has synchronized with this thread.
2828
2829     It is also safe to use functions that make GDI calls, such as
2830     w32_clear_rect, because these functions must obtain a DC handle
2831     from the frame struct using get_frame_dc which is thread-aware.  */
2832
2833  switch (msg)
2834    {
2835    case WM_ERASEBKGND:
2836      f = x_window_to_frame (dpyinfo, hwnd);
2837      if (f)
2838	{
2839          HDC hdc = get_frame_dc (f);
2840	  GetUpdateRect (hwnd, &wmsg.rect, FALSE);
2841	  w32_clear_rect (f, hdc, &wmsg.rect);
2842          release_frame_dc (f, hdc);
2843
2844#if defined (W32_DEBUG_DISPLAY)
2845          DebPrint (("WM_ERASEBKGND (frame %p): erasing %d,%d-%d,%d\n",
2846		     f,
2847                     wmsg.rect.left, wmsg.rect.top,
2848		     wmsg.rect.right, wmsg.rect.bottom));
2849#endif /* W32_DEBUG_DISPLAY */
2850	}
2851      return 1;
2852    case WM_PALETTECHANGED:
2853      /* ignore our own changes */
2854      if ((HWND)wParam != hwnd)
2855        {
2856	  f = x_window_to_frame (dpyinfo, hwnd);
2857	  if (f)
2858	    /* get_frame_dc will realize our palette and force all
2859	       frames to be redrawn if needed. */
2860	    release_frame_dc (f, get_frame_dc (f));
2861	}
2862      return 0;
2863    case WM_PAINT:
2864      {
2865  	PAINTSTRUCT paintStruct;
2866        RECT update_rect;
2867	bzero (&update_rect, sizeof (update_rect));
2868
2869	f = x_window_to_frame (dpyinfo, hwnd);
2870	if (f == 0)
2871	  {
2872            DebPrint (("WM_PAINT received for unknown window %p\n", hwnd));
2873	    return 0;
2874	  }
2875
2876        /* MSDN Docs say not to call BeginPaint if GetUpdateRect
2877           fails.  Apparently this can happen under some
2878           circumstances.  */
2879        if (GetUpdateRect (hwnd, &update_rect, FALSE) || !w32_strict_painting)
2880          {
2881            enter_crit ();
2882            BeginPaint (hwnd, &paintStruct);
2883
2884	    /* The rectangles returned by GetUpdateRect and BeginPaint
2885	       do not always match.  Play it safe by assuming both areas
2886	       are invalid.  */
2887	    UnionRect (&(wmsg.rect), &update_rect, &(paintStruct.rcPaint));
2888
2889#if defined (W32_DEBUG_DISPLAY)
2890            DebPrint (("WM_PAINT (frame %p): painting %d,%d-%d,%d\n",
2891		       f,
2892		       wmsg.rect.left, wmsg.rect.top,
2893		       wmsg.rect.right, wmsg.rect.bottom));
2894            DebPrint (("  [update region is %d,%d-%d,%d]\n",
2895                       update_rect.left, update_rect.top,
2896                       update_rect.right, update_rect.bottom));
2897#endif
2898            EndPaint (hwnd, &paintStruct);
2899            leave_crit ();
2900
2901            my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2902
2903            return 0;
2904          }
2905
2906	/* If GetUpdateRect returns 0 (meaning there is no update
2907           region), assume the whole window needs to be repainted.  */
2908	GetClientRect(hwnd, &wmsg.rect);
2909	my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2910        return 0;
2911      }
2912
2913    case WM_INPUTLANGCHANGE:
2914      /* Inform lisp thread of keyboard layout changes.  */
2915      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
2916
2917      /* Clear dead keys in the keyboard state; for simplicity only
2918         preserve modifier key states.  */
2919      {
2920	int i;
2921	BYTE keystate[256];
2922
2923	GetKeyboardState (keystate);
2924	for (i = 0; i < 256; i++)
2925	  if (1
2926	      && i != VK_SHIFT
2927	      && i != VK_LSHIFT
2928	      && i != VK_RSHIFT
2929	      && i != VK_CAPITAL
2930	      && i != VK_NUMLOCK
2931	      && i != VK_SCROLL
2932	      && i != VK_CONTROL
2933	      && i != VK_LCONTROL
2934	      && i != VK_RCONTROL
2935	      && i != VK_MENU
2936	      && i != VK_LMENU
2937	      && i != VK_RMENU
2938	      && i != VK_LWIN
2939	      && i != VK_RWIN)
2940	    keystate[i] = 0;
2941	SetKeyboardState (keystate);
2942      }
2943      goto dflt;
2944
2945    case WM_HOTKEY:
2946      /* Synchronize hot keys with normal input.  */
2947      PostMessage (hwnd, WM_KEYDOWN, HIWORD (lParam), 0);
2948      return (0);
2949
2950    case WM_KEYUP:
2951    case WM_SYSKEYUP:
2952      record_keyup (wParam, lParam);
2953      goto dflt;
2954
2955    case WM_KEYDOWN:
2956    case WM_SYSKEYDOWN:
2957      /* Ignore keystrokes we fake ourself; see below.  */
2958      if (dpyinfo->faked_key == wParam)
2959	{
2960	  dpyinfo->faked_key = 0;
2961	  /* Make sure TranslateMessage sees them though (as long as
2962	     they don't produce WM_CHAR messages).  This ensures that
2963	     indicator lights are toggled promptly on Windows 9x, for
2964	     example.  */
2965	  if (lispy_function_keys[wParam] != 0)
2966	    {
2967	      windows_translate = 1;
2968	      goto translate;
2969	    }
2970	  return 0;
2971	}
2972
2973      /* Synchronize modifiers with current keystroke.  */
2974      sync_modifiers ();
2975      record_keydown (wParam, lParam);
2976      wParam = map_keypad_keys (wParam, (lParam & 0x1000000L) != 0);
2977
2978      windows_translate = 0;
2979
2980      switch (wParam)
2981	{
2982	case VK_LWIN:
2983	  if (NILP (Vw32_pass_lwindow_to_system))
2984	    {
2985	      /* Prevent system from acting on keyup (which opens the
2986		 Start menu if no other key was pressed) by simulating a
2987		 press of Space which we will ignore.  */
2988	      if (GetAsyncKeyState (wParam) & 1)
2989		{
2990		  if (NUMBERP (Vw32_phantom_key_code))
2991		    key = XUINT (Vw32_phantom_key_code) & 255;
2992		  else
2993		    key = VK_SPACE;
2994		  dpyinfo->faked_key = key;
2995		  keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
2996		}
2997	    }
2998	  if (!NILP (Vw32_lwindow_modifier))
2999	    return 0;
3000	  break;
3001	case VK_RWIN:
3002	  if (NILP (Vw32_pass_rwindow_to_system))
3003	    {
3004	      if (GetAsyncKeyState (wParam) & 1)
3005		{
3006		  if (NUMBERP (Vw32_phantom_key_code))
3007		    key = XUINT (Vw32_phantom_key_code) & 255;
3008		  else
3009		    key = VK_SPACE;
3010		  dpyinfo->faked_key = key;
3011		  keybd_event (key, (BYTE) MapVirtualKey (key, 0), 0, 0);
3012		}
3013	    }
3014	  if (!NILP (Vw32_rwindow_modifier))
3015	    return 0;
3016	  break;
3017  	case VK_APPS:
3018	  if (!NILP (Vw32_apps_modifier))
3019	    return 0;
3020	  break;
3021	case VK_MENU:
3022	  if (NILP (Vw32_pass_alt_to_system))
3023	    /* Prevent DefWindowProc from activating the menu bar if an
3024               Alt key is pressed and released by itself.  */
3025	    return 0;
3026	  windows_translate = 1;
3027	  break;
3028	case VK_CAPITAL:
3029	  /* Decide whether to treat as modifier or function key.  */
3030	  if (NILP (Vw32_enable_caps_lock))
3031	    goto disable_lock_key;
3032	  windows_translate = 1;
3033	  break;
3034	case VK_NUMLOCK:
3035	  /* Decide whether to treat as modifier or function key.  */
3036	  if (NILP (Vw32_enable_num_lock))
3037	    goto disable_lock_key;
3038	  windows_translate = 1;
3039	  break;
3040	case VK_SCROLL:
3041	  /* Decide whether to treat as modifier or function key.  */
3042	  if (NILP (Vw32_scroll_lock_modifier))
3043	    goto disable_lock_key;
3044	  windows_translate = 1;
3045	  break;
3046	disable_lock_key:
3047	  /* Ensure the appropriate lock key state (and indicator light)
3048             remains in the same state. We do this by faking another
3049             press of the relevant key.  Apparently, this really is the
3050             only way to toggle the state of the indicator lights.  */
3051	  dpyinfo->faked_key = wParam;
3052	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3053		       KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3054	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3055		       KEYEVENTF_EXTENDEDKEY | 0, 0);
3056	  keybd_event ((BYTE) wParam, (BYTE) MapVirtualKey (wParam, 0),
3057		       KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
3058	  /* Ensure indicator lights are updated promptly on Windows 9x
3059             (TranslateMessage apparently does this), after forwarding
3060             input event.  */
3061	  post_character_message (hwnd, msg, wParam, lParam,
3062				  w32_get_key_modifiers (wParam, lParam));
3063	  windows_translate = 1;
3064	  break;
3065	case VK_CONTROL:
3066	case VK_SHIFT:
3067	case VK_PROCESSKEY:  /* Generated by IME.  */
3068	  windows_translate = 1;
3069	  break;
3070	case VK_CANCEL:
3071	  /* Windows maps Ctrl-Pause (aka Ctrl-Break) into VK_CANCEL,
3072             which is confusing for purposes of key binding; convert
3073	     VK_CANCEL events into VK_PAUSE events.  */
3074	  wParam = VK_PAUSE;
3075	  break;
3076	case VK_PAUSE:
3077	  /* Windows maps Ctrl-NumLock into VK_PAUSE, which is confusing
3078             for purposes of key binding; convert these back into
3079             VK_NUMLOCK events, at least when we want to see NumLock key
3080             presses.  (Note that there is never any possibility that
3081             VK_PAUSE with Ctrl really is C-Pause as per above.)  */
3082	  if (NILP (Vw32_enable_num_lock) && modifier_set (VK_CONTROL))
3083	    wParam = VK_NUMLOCK;
3084	  break;
3085	default:
3086	  /* If not defined as a function key, change it to a WM_CHAR message. */
3087	  if (lispy_function_keys[wParam] == 0)
3088	    {
3089	      DWORD modifiers = construct_console_modifiers ();
3090
3091	      if (!NILP (Vw32_recognize_altgr)
3092		  && modifier_set (VK_LCONTROL) && modifier_set (VK_RMENU))
3093		{
3094		  /* Always let TranslateMessage handle AltGr key chords;
3095		     for some reason, ToAscii doesn't always process AltGr
3096		     chords correctly.  */
3097		  windows_translate = 1;
3098		}
3099	      else if ((modifiers & (~SHIFT_PRESSED & ~CAPSLOCK_ON)) != 0)
3100		{
3101		  /* Handle key chords including any modifiers other
3102		     than shift directly, in order to preserve as much
3103		     modifier information as possible.  */
3104		  if ('A' <= wParam && wParam <= 'Z')
3105		    {
3106		      /* Don't translate modified alphabetic keystrokes,
3107			 so the user doesn't need to constantly switch
3108			 layout to type control or meta keystrokes when
3109			 the normal layout translates alphabetic
3110			 characters to non-ascii characters.  */
3111		      if (!modifier_set (VK_SHIFT))
3112			wParam += ('a' - 'A');
3113		      msg = WM_CHAR;
3114		    }
3115		  else
3116		    {
3117		      /* Try to handle other keystrokes by determining the
3118			 base character (ie. translating the base key plus
3119			 shift modifier).  */
3120		      int add;
3121		      int isdead = 0;
3122		      KEY_EVENT_RECORD key;
3123
3124		      key.bKeyDown = TRUE;
3125		      key.wRepeatCount = 1;
3126		      key.wVirtualKeyCode = wParam;
3127		      key.wVirtualScanCode = (lParam & 0xFF0000) >> 16;
3128		      key.uChar.AsciiChar = 0;
3129		      key.dwControlKeyState = modifiers;
3130
3131		      add = w32_kbd_patch_key (&key);
3132		      /* 0 means an unrecognised keycode, negative means
3133			 dead key.  Ignore both.  */
3134		      while (--add >= 0)
3135			{
3136			  /* Forward asciified character sequence.  */
3137			  post_character_message
3138			    (hwnd, WM_CHAR, key.uChar.AsciiChar, lParam,
3139			     w32_get_key_modifiers (wParam, lParam));
3140			  w32_kbd_patch_key (&key);
3141			}
3142		      return 0;
3143		    }
3144		}
3145	      else
3146		{
3147		  /* Let TranslateMessage handle everything else.  */
3148		  windows_translate = 1;
3149		}
3150	    }
3151	}
3152
3153    translate:
3154      if (windows_translate)
3155	{
3156	  MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
3157
3158	  windows_msg.time = GetMessageTime ();
3159	  TranslateMessage (&windows_msg);
3160	  goto dflt;
3161	}
3162
3163      /* Fall through */
3164
3165    case WM_SYSCHAR:
3166    case WM_CHAR:
3167      post_character_message (hwnd, msg, wParam, lParam,
3168			      w32_get_key_modifiers (wParam, lParam));
3169      break;
3170
3171      /* Simulate middle mouse button events when left and right buttons
3172	 are used together, but only if user has two button mouse. */
3173    case WM_LBUTTONDOWN:
3174    case WM_RBUTTONDOWN:
3175      if (w32_num_mouse_buttons > 2)
3176	goto handle_plain_button;
3177
3178      {
3179	int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
3180	int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
3181
3182	if (button_state & this)
3183	  return 0;
3184
3185	if (button_state == 0)
3186	  SetCapture (hwnd);
3187
3188	button_state |= this;
3189
3190	if (button_state & other)
3191	  {
3192	    if (mouse_button_timer)
3193	      {
3194		KillTimer (hwnd, mouse_button_timer);
3195		mouse_button_timer = 0;
3196
3197		/* Generate middle mouse event instead. */
3198		msg = WM_MBUTTONDOWN;
3199		button_state |= MMOUSE;
3200	      }
3201	    else if (button_state & MMOUSE)
3202	      {
3203		/* Ignore button event if we've already generated a
3204		   middle mouse down event.  This happens if the
3205		   user releases and press one of the two buttons
3206		   after we've faked a middle mouse event. */
3207		return 0;
3208	      }
3209	    else
3210	      {
3211		/* Flush out saved message. */
3212		post_msg (&saved_mouse_button_msg);
3213	      }
3214	    wmsg.dwModifiers = w32_get_modifiers ();
3215	    my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3216	    signal_user_input ();
3217
3218	    /* Clear message buffer. */
3219	    saved_mouse_button_msg.msg.hwnd = 0;
3220	  }
3221	else
3222	  {
3223	    /* Hold onto message for now. */
3224	    mouse_button_timer =
3225	      SetTimer (hwnd, MOUSE_BUTTON_ID,
3226			w32_mouse_button_tolerance, NULL);
3227	    saved_mouse_button_msg.msg.hwnd = hwnd;
3228	    saved_mouse_button_msg.msg.message = msg;
3229	    saved_mouse_button_msg.msg.wParam = wParam;
3230	    saved_mouse_button_msg.msg.lParam = lParam;
3231	    saved_mouse_button_msg.msg.time = GetMessageTime ();
3232	    saved_mouse_button_msg.dwModifiers = w32_get_modifiers ();
3233	  }
3234      }
3235      return 0;
3236
3237    case WM_LBUTTONUP:
3238    case WM_RBUTTONUP:
3239      if (w32_num_mouse_buttons > 2)
3240	goto handle_plain_button;
3241
3242      {
3243	int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
3244	int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
3245
3246	if ((button_state & this) == 0)
3247	  return 0;
3248
3249	button_state &= ~this;
3250
3251	if (button_state & MMOUSE)
3252	  {
3253	    /* Only generate event when second button is released. */
3254	    if ((button_state & other) == 0)
3255	      {
3256		msg = WM_MBUTTONUP;
3257		button_state &= ~MMOUSE;
3258
3259		if (button_state) abort ();
3260	      }
3261	    else
3262	      return 0;
3263	  }
3264	else
3265	  {
3266	    /* Flush out saved message if necessary. */
3267	    if (saved_mouse_button_msg.msg.hwnd)
3268	      {
3269		post_msg (&saved_mouse_button_msg);
3270	      }
3271	  }
3272	wmsg.dwModifiers = w32_get_modifiers ();
3273	my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3274	signal_user_input ();
3275
3276	/* Always clear message buffer and cancel timer. */
3277	saved_mouse_button_msg.msg.hwnd = 0;
3278	KillTimer (hwnd, mouse_button_timer);
3279	mouse_button_timer = 0;
3280
3281	if (button_state == 0)
3282	  ReleaseCapture ();
3283      }
3284      return 0;
3285
3286    case WM_XBUTTONDOWN:
3287    case WM_XBUTTONUP:
3288      if (w32_pass_extra_mouse_buttons_to_system)
3289	goto dflt;
3290      /* else fall through and process them.  */
3291    case WM_MBUTTONDOWN:
3292    case WM_MBUTTONUP:
3293    handle_plain_button:
3294      {
3295	BOOL up;
3296	int button;
3297
3298	/* Ignore middle and extra buttons as long as the menu is active.  */
3299	f = x_window_to_frame (dpyinfo, hwnd);
3300	if (f && f->output_data.w32->menubar_active)
3301	  return 0;
3302
3303	if (parse_button (msg, HIWORD (wParam), &button, &up))
3304	  {
3305	    if (up) ReleaseCapture ();
3306	    else SetCapture (hwnd);
3307	    button = (button == 0) ? LMOUSE :
3308	      ((button == 1) ? MMOUSE  : RMOUSE);
3309	    if (up)
3310	      button_state &= ~button;
3311	    else
3312	      button_state |= button;
3313	  }
3314      }
3315
3316      wmsg.dwModifiers = w32_get_modifiers ();
3317      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3318      signal_user_input ();
3319
3320      /* Need to return true for XBUTTON messages, false for others,
3321         to indicate that we processed the message.  */
3322      return (msg == WM_XBUTTONDOWN || msg == WM_XBUTTONUP);
3323
3324    case WM_MOUSEMOVE:
3325      /* Ignore mouse movements as long as the menu is active.  These
3326	 movements are processed by the window manager anyway, and
3327	 it's wrong to handle them as if they happened on the
3328	 underlying frame.  */
3329      f = x_window_to_frame (dpyinfo, hwnd);
3330      if (f && f->output_data.w32->menubar_active)
3331	return 0;
3332
3333      /* If the mouse has just moved into the frame, start tracking
3334	 it, so we will be notified when it leaves the frame.  Mouse
3335	 tracking only works under W98 and NT4 and later. On earlier
3336	 versions, there is no way of telling when the mouse leaves the
3337	 frame, so we just have to put up with help-echo and mouse
3338	 highlighting remaining while the frame is not active.  */
3339      if (track_mouse_event_fn && !track_mouse_window)
3340	{
3341	  TRACKMOUSEEVENT tme;
3342	  tme.cbSize = sizeof (tme);
3343	  tme.dwFlags = TME_LEAVE;
3344	  tme.hwndTrack = hwnd;
3345
3346	  track_mouse_event_fn (&tme);
3347	  track_mouse_window = hwnd;
3348	}
3349    case WM_VSCROLL:
3350      if (w32_mouse_move_interval <= 0
3351	  || (msg == WM_MOUSEMOVE && button_state == 0))
3352  	{
3353	  wmsg.dwModifiers = w32_get_modifiers ();
3354	  my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3355	  return 0;
3356  	}
3357
3358      /* Hang onto mouse move and scroll messages for a bit, to avoid
3359	 sending such events to Emacs faster than it can process them.
3360	 If we get more events before the timer from the first message
3361	 expires, we just replace the first message. */
3362
3363      if (saved_mouse_move_msg.msg.hwnd == 0)
3364	mouse_move_timer =
3365	  SetTimer (hwnd, MOUSE_MOVE_ID,
3366		    w32_mouse_move_interval, NULL);
3367
3368      /* Hold onto message for now. */
3369      saved_mouse_move_msg.msg.hwnd = hwnd;
3370      saved_mouse_move_msg.msg.message = msg;
3371      saved_mouse_move_msg.msg.wParam = wParam;
3372      saved_mouse_move_msg.msg.lParam = lParam;
3373      saved_mouse_move_msg.msg.time = GetMessageTime ();
3374      saved_mouse_move_msg.dwModifiers = w32_get_modifiers ();
3375
3376      return 0;
3377
3378    case WM_MOUSEWHEEL:
3379      wmsg.dwModifiers = w32_get_modifiers ();
3380      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3381      signal_user_input ();
3382      return 0;
3383
3384    case WM_DROPFILES:
3385      wmsg.dwModifiers = w32_get_modifiers ();
3386      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3387      signal_user_input ();
3388      return 0;
3389
3390    case WM_TIMER:
3391      /* Flush out saved messages if necessary. */
3392      if (wParam == mouse_button_timer)
3393	{
3394	  if (saved_mouse_button_msg.msg.hwnd)
3395	    {
3396	      post_msg (&saved_mouse_button_msg);
3397	      signal_user_input ();
3398	      saved_mouse_button_msg.msg.hwnd = 0;
3399	    }
3400	  KillTimer (hwnd, mouse_button_timer);
3401	  mouse_button_timer = 0;
3402	}
3403      else if (wParam == mouse_move_timer)
3404	{
3405	  if (saved_mouse_move_msg.msg.hwnd)
3406	    {
3407	      post_msg (&saved_mouse_move_msg);
3408	      saved_mouse_move_msg.msg.hwnd = 0;
3409	    }
3410	  KillTimer (hwnd, mouse_move_timer);
3411	  mouse_move_timer = 0;
3412	}
3413      else if (wParam == menu_free_timer)
3414	{
3415	  KillTimer (hwnd, menu_free_timer);
3416	  menu_free_timer = 0;
3417	  f = x_window_to_frame (dpyinfo, hwnd);
3418          /* If a popup menu is active, don't wipe its strings.  */
3419	  if (menubar_in_use
3420              && current_popup_menu == NULL)
3421	    {
3422	      /* Free memory used by owner-drawn and help-echo strings.  */
3423	      w32_free_menu_strings (hwnd);
3424	      f->output_data.w32->menubar_active = 0;
3425              menubar_in_use = 0;
3426	    }
3427	}
3428      return 0;
3429
3430    case WM_NCACTIVATE:
3431      /* Windows doesn't send us focus messages when putting up and
3432	 taking down a system popup dialog as for Ctrl-Alt-Del on Windows 95.
3433	 The only indication we get that something happened is receiving
3434	 this message afterwards.  So this is a good time to reset our
3435	 keyboard modifiers' state. */
3436      reset_modifiers ();
3437      goto dflt;
3438
3439    case WM_INITMENU:
3440      button_state = 0;
3441      ReleaseCapture ();
3442      /* We must ensure menu bar is fully constructed and up to date
3443	 before allowing user interaction with it.  To achieve this
3444	 we send this message to the lisp thread and wait for a
3445	 reply (whose value is not actually needed) to indicate that
3446	 the menu bar is now ready for use, so we can now return.
3447
3448	 To remain responsive in the meantime, we enter a nested message
3449	 loop that can process all other messages.
3450
3451	 However, we skip all this if the message results from calling
3452	 TrackPopupMenu - in fact, we must NOT attempt to send the lisp
3453	 thread a message because it is blocked on us at this point.  We
3454	 set menubar_active before calling TrackPopupMenu to indicate
3455	 this (there is no possibility of confusion with real menubar
3456	 being active).  */
3457
3458      f = x_window_to_frame (dpyinfo, hwnd);
3459      if (f
3460	  && (f->output_data.w32->menubar_active
3461	      /* We can receive this message even in the absence of a
3462		 menubar (ie. when the system menu is activated) - in this
3463		 case we do NOT want to forward the message, otherwise it
3464		 will cause the menubar to suddenly appear when the user
3465		 had requested it to be turned off!  */
3466	      || f->output_data.w32->menubar_widget == NULL))
3467	return 0;
3468
3469      {
3470	deferred_msg msg_buf;
3471
3472	/* Detect if message has already been deferred; in this case
3473	   we cannot return any sensible value to ignore this.  */
3474	if (find_deferred_msg (hwnd, msg) != NULL)
3475	  abort ();
3476
3477        menubar_in_use = 1;
3478
3479	return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam);
3480      }
3481
3482    case WM_EXITMENULOOP:
3483      f = x_window_to_frame (dpyinfo, hwnd);
3484
3485      /* If a menu is still active, check again after a short delay,
3486	 since Windows often (always?) sends the WM_EXITMENULOOP
3487	 before the corresponding WM_COMMAND message.
3488         Don't do this if a popup menu is active, since it is only
3489         menubar menus that require cleaning up in this way.
3490      */
3491      if (f && menubar_in_use && current_popup_menu == NULL)
3492	menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL);
3493      goto dflt;
3494
3495    case WM_MENUSELECT:
3496      /* Direct handling of help_echo in menus.  Should be safe now
3497	 that we generate the help_echo by placing a help event in the
3498	 keyboard buffer.  */
3499      {
3500	HMENU menu = (HMENU) lParam;
3501	UINT menu_item = (UINT) LOWORD (wParam);
3502	UINT flags = (UINT) HIWORD (wParam);
3503
3504	w32_menu_display_help (hwnd, menu, menu_item, flags);
3505      }
3506      return 0;
3507
3508    case WM_MEASUREITEM:
3509      f = x_window_to_frame (dpyinfo, hwnd);
3510      if (f)
3511	{
3512	  MEASUREITEMSTRUCT * pMis = (MEASUREITEMSTRUCT *) lParam;
3513
3514	  if (pMis->CtlType == ODT_MENU)
3515	    {
3516	      /* Work out dimensions for popup menu titles. */
3517	      char * title = (char *) pMis->itemData;
3518	      HDC hdc = GetDC (hwnd);
3519	      HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
3520	      LOGFONT menu_logfont;
3521	      HFONT old_font;
3522	      SIZE size;
3523
3524	      GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
3525	      menu_logfont.lfWeight = FW_BOLD;
3526	      menu_font = CreateFontIndirect (&menu_logfont);
3527	      old_font = SelectObject (hdc, menu_font);
3528
3529              pMis->itemHeight = GetSystemMetrics (SM_CYMENUSIZE);
3530              if (title)
3531                {
3532		  if (unicode_append_menu)
3533		    GetTextExtentPoint32W (hdc, (WCHAR *) title,
3534					   wcslen ((WCHAR *) title),
3535					   &size);
3536		  else
3537		    GetTextExtentPoint32 (hdc, title, strlen (title), &size);
3538
3539                  pMis->itemWidth = size.cx;
3540                  if (pMis->itemHeight < size.cy)
3541                    pMis->itemHeight = size.cy;
3542                }
3543              else
3544                pMis->itemWidth = 0;
3545
3546	      SelectObject (hdc, old_font);
3547	      DeleteObject (menu_font);
3548	      ReleaseDC (hwnd, hdc);
3549	      return TRUE;
3550	    }
3551	}
3552      return 0;
3553
3554    case WM_DRAWITEM:
3555      f = x_window_to_frame (dpyinfo, hwnd);
3556      if (f)
3557	{
3558	  DRAWITEMSTRUCT * pDis = (DRAWITEMSTRUCT *) lParam;
3559
3560	  if (pDis->CtlType == ODT_MENU)
3561	    {
3562	      /* Draw popup menu title. */
3563	      char * title = (char *) pDis->itemData;
3564              if (title)
3565                {
3566                  HDC hdc = pDis->hDC;
3567                  HFONT menu_font = GetCurrentObject (hdc, OBJ_FONT);
3568                  LOGFONT menu_logfont;
3569                  HFONT old_font;
3570
3571                  GetObject (menu_font, sizeof (menu_logfont), &menu_logfont);
3572                  menu_logfont.lfWeight = FW_BOLD;
3573                  menu_font = CreateFontIndirect (&menu_logfont);
3574                  old_font = SelectObject (hdc, menu_font);
3575
3576		  /* Always draw title as if not selected.  */
3577		  if (unicode_append_menu)
3578		    ExtTextOutW (hdc,
3579				 pDis->rcItem.left
3580				 + GetSystemMetrics (SM_CXMENUCHECK),
3581				 pDis->rcItem.top,
3582				 ETO_OPAQUE, &pDis->rcItem,
3583				 (WCHAR *) title,
3584				 wcslen ((WCHAR *) title), NULL);
3585		  else
3586		    ExtTextOut (hdc,
3587				pDis->rcItem.left
3588				+ GetSystemMetrics (SM_CXMENUCHECK),
3589				pDis->rcItem.top,
3590				ETO_OPAQUE, &pDis->rcItem,
3591				title, strlen (title), NULL);
3592
3593                  SelectObject (hdc, old_font);
3594                  DeleteObject (menu_font);
3595                }
3596	      return TRUE;
3597	    }
3598	}
3599      return 0;
3600
3601#if 0
3602      /* Still not right - can't distinguish between clicks in the
3603	 client area of the frame from clicks forwarded from the scroll
3604	 bars - may have to hook WM_NCHITTEST to remember the mouse
3605	 position and then check if it is in the client area ourselves.  */
3606    case WM_MOUSEACTIVATE:
3607      /* Discard the mouse click that activates a frame, allowing the
3608	 user to click anywhere without changing point (or worse!).
3609	 Don't eat mouse clicks on scrollbars though!!  */
3610      if (LOWORD (lParam) == HTCLIENT )
3611	return MA_ACTIVATEANDEAT;
3612      goto dflt;
3613#endif
3614
3615    case WM_MOUSELEAVE:
3616      /* No longer tracking mouse.  */
3617      track_mouse_window = NULL;
3618
3619    case WM_ACTIVATEAPP:
3620    case WM_ACTIVATE:
3621    case WM_WINDOWPOSCHANGED:
3622    case WM_SHOWWINDOW:
3623      /* Inform lisp thread that a frame might have just been obscured
3624	 or exposed, so should recheck visibility of all frames.  */
3625      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3626      goto dflt;
3627
3628    case WM_SETFOCUS:
3629      dpyinfo->faked_key = 0;
3630      reset_modifiers ();
3631      register_hot_keys (hwnd);
3632      goto command;
3633    case WM_KILLFOCUS:
3634      unregister_hot_keys (hwnd);
3635      button_state = 0;
3636      ReleaseCapture ();
3637      /* Relinquish the system caret.  */
3638      if (w32_system_caret_hwnd)
3639	{
3640	  w32_visible_system_caret_hwnd = NULL;
3641	  w32_system_caret_hwnd = NULL;
3642	  DestroyCaret ();
3643	}
3644      goto command;
3645    case WM_COMMAND:
3646      menubar_in_use = 0;
3647      f = x_window_to_frame (dpyinfo, hwnd);
3648      if (f && HIWORD (wParam) == 0)
3649	{
3650	  if (menu_free_timer)
3651	    {
3652	      KillTimer (hwnd, menu_free_timer);
3653	      menu_free_timer = 0;
3654	    }
3655	}
3656    case WM_MOVE:
3657    case WM_SIZE:
3658    command:
3659      wmsg.dwModifiers = w32_get_modifiers ();
3660      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3661      goto dflt;
3662
3663    case WM_CLOSE:
3664      wmsg.dwModifiers = w32_get_modifiers ();
3665      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3666      return 0;
3667
3668    case WM_WINDOWPOSCHANGING:
3669      /* Don't restrict the sizing of tip frames.  */
3670      if (hwnd == tip_window)
3671	return 0;
3672      {
3673	WINDOWPLACEMENT wp;
3674	LPWINDOWPOS lppos = (WINDOWPOS *) lParam;
3675
3676	wp.length = sizeof (WINDOWPLACEMENT);
3677	GetWindowPlacement (hwnd, &wp);
3678
3679	if (wp.showCmd != SW_SHOWMINIMIZED && (lppos->flags & SWP_NOSIZE) == 0)
3680	  {
3681	    RECT rect;
3682	    int wdiff;
3683	    int hdiff;
3684	    DWORD font_width;
3685	    DWORD line_height;
3686	    DWORD internal_border;
3687	    DWORD scrollbar_extra;
3688	    RECT wr;
3689
3690	    wp.length = sizeof(wp);
3691	    GetWindowRect (hwnd, &wr);
3692
3693	    enter_crit ();
3694
3695	    font_width = GetWindowLong (hwnd, WND_FONTWIDTH_INDEX);
3696	    line_height = GetWindowLong (hwnd, WND_LINEHEIGHT_INDEX);
3697	    internal_border = GetWindowLong (hwnd, WND_BORDER_INDEX);
3698	    scrollbar_extra = GetWindowLong (hwnd, WND_SCROLLBAR_INDEX);
3699
3700	    leave_crit ();
3701
3702	    memset (&rect, 0, sizeof (rect));
3703	    AdjustWindowRect (&rect, GetWindowLong (hwnd, GWL_STYLE),
3704			      GetMenu (hwnd) != NULL);
3705
3706	    /* Force width and height of client area to be exact
3707	       multiples of the character cell dimensions.  */
3708	    wdiff = (lppos->cx - (rect.right - rect.left)
3709		     - 2 * internal_border - scrollbar_extra)
3710	      % font_width;
3711	    hdiff = (lppos->cy - (rect.bottom - rect.top)
3712		     - 2 * internal_border)
3713	      % line_height;
3714
3715	    if (wdiff || hdiff)
3716	      {
3717		/* For right/bottom sizing we can just fix the sizes.
3718		   However for top/left sizing we will need to fix the X
3719		   and Y positions as well.  */
3720
3721		int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK);
3722		int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK);
3723
3724		lppos->cx = max (lppos->cx - wdiff, cx_mintrack);
3725		lppos->cy = max (lppos->cy - hdiff, cy_mintrack);
3726
3727		if (wp.showCmd != SW_SHOWMAXIMIZED
3728		    && (lppos->flags & SWP_NOMOVE) == 0)
3729		  {
3730		    if (lppos->x != wr.left || lppos->y != wr.top)
3731		      {
3732			lppos->x += wdiff;
3733			lppos->y += hdiff;
3734		      }
3735		    else
3736		      {
3737			lppos->flags |= SWP_NOMOVE;
3738		      }
3739		  }
3740
3741		return 0;
3742	      }
3743	  }
3744      }
3745
3746      goto dflt;
3747
3748    case WM_GETMINMAXINFO:
3749      /* Hack to allow resizing the Emacs frame above the screen size.
3750	 Note that Windows 9x limits coordinates to 16-bits.  */
3751      ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767;
3752      ((LPMINMAXINFO) lParam)->ptMaxTrackSize.y = 32767;
3753      return 0;
3754
3755    case WM_SETCURSOR:
3756      if (LOWORD (lParam) == HTCLIENT)
3757	return 0;
3758
3759      goto dflt;
3760
3761    case WM_EMACS_SETCURSOR:
3762      {
3763	Cursor cursor = (Cursor) wParam;
3764	if (cursor)
3765	  SetCursor (cursor);
3766	return 0;
3767      }
3768
3769    case WM_EMACS_CREATESCROLLBAR:
3770      return (LRESULT) w32_createscrollbar ((struct frame *) wParam,
3771					    (struct scroll_bar *) lParam);
3772
3773    case WM_EMACS_SHOWWINDOW:
3774      return ShowWindow ((HWND) wParam, (WPARAM) lParam);
3775
3776    case WM_EMACS_SETFOREGROUND:
3777      {
3778        HWND foreground_window;
3779        DWORD foreground_thread, retval;
3780
3781        /* On NT 5.0, and apparently Windows 98, it is necessary to
3782           attach to the thread that currently has focus in order to
3783           pull the focus away from it.  */
3784        foreground_window = GetForegroundWindow ();
3785	foreground_thread = GetWindowThreadProcessId (foreground_window, NULL);
3786        if (!foreground_window
3787            || foreground_thread == GetCurrentThreadId ()
3788            || !AttachThreadInput (GetCurrentThreadId (),
3789                                   foreground_thread, TRUE))
3790          foreground_thread = 0;
3791
3792        retval = SetForegroundWindow ((HWND) wParam);
3793
3794        /* Detach from the previous foreground thread.  */
3795        if (foreground_thread)
3796          AttachThreadInput (GetCurrentThreadId (),
3797                             foreground_thread, FALSE);
3798
3799        return retval;
3800      }
3801
3802    case WM_EMACS_SETWINDOWPOS:
3803      {
3804	WINDOWPOS * pos = (WINDOWPOS *) wParam;
3805	return SetWindowPos (hwnd, pos->hwndInsertAfter,
3806			     pos->x, pos->y, pos->cx, pos->cy, pos->flags);
3807      }
3808
3809    case WM_EMACS_DESTROYWINDOW:
3810      DragAcceptFiles ((HWND) wParam, FALSE);
3811      return DestroyWindow ((HWND) wParam);
3812
3813    case WM_EMACS_HIDE_CARET:
3814      return HideCaret (hwnd);
3815
3816    case WM_EMACS_SHOW_CARET:
3817      return ShowCaret (hwnd);
3818
3819    case WM_EMACS_DESTROY_CARET:
3820      w32_system_caret_hwnd = NULL;
3821      w32_visible_system_caret_hwnd = NULL;
3822      return DestroyCaret ();
3823
3824    case WM_EMACS_TRACK_CARET:
3825      /* If there is currently no system caret, create one.  */
3826      if (w32_system_caret_hwnd == NULL)
3827	{
3828	  /* Use the default caret width, and avoid changing it
3829	     unneccesarily, as it confuses screen reader software.  */
3830	  w32_system_caret_hwnd = hwnd;
3831	  CreateCaret (hwnd, NULL, 0,
3832		       w32_system_caret_height);
3833	}
3834
3835      if (!SetCaretPos (w32_system_caret_x, w32_system_caret_y))
3836	return 0;
3837      /* Ensure visible caret gets turned on when requested.  */
3838      else if (w32_use_visible_system_caret
3839	       && w32_visible_system_caret_hwnd != hwnd)
3840	{
3841	  w32_visible_system_caret_hwnd = hwnd;
3842	  return ShowCaret (hwnd);
3843	}
3844      /* Ensure visible caret gets turned off when requested.  */
3845      else if (!w32_use_visible_system_caret
3846	       && w32_visible_system_caret_hwnd)
3847	{
3848	  w32_visible_system_caret_hwnd = NULL;
3849	  return HideCaret (hwnd);
3850	}
3851      else
3852	return 1;
3853
3854    case WM_EMACS_TRACKPOPUPMENU:
3855      {
3856	UINT flags;
3857	POINT *pos;
3858	int retval;
3859	pos = (POINT *)lParam;
3860	flags = TPM_CENTERALIGN;
3861	if (button_state & LMOUSE)
3862	  flags |= TPM_LEFTBUTTON;
3863	else if (button_state & RMOUSE)
3864	  flags |= TPM_RIGHTBUTTON;
3865
3866	/* Remember we did a SetCapture on the initial mouse down event,
3867	   so for safety, we make sure the capture is cancelled now.  */
3868	ReleaseCapture ();
3869	button_state = 0;
3870
3871	/* Use menubar_active to indicate that WM_INITMENU is from
3872           TrackPopupMenu below, and should be ignored.  */
3873	f = x_window_to_frame (dpyinfo, hwnd);
3874	if (f)
3875	  f->output_data.w32->menubar_active = 1;
3876
3877	if (TrackPopupMenu ((HMENU)wParam, flags, pos->x, pos->y,
3878			    0, hwnd, NULL))
3879	  {
3880	    MSG amsg;
3881	    /* Eat any mouse messages during popupmenu */
3882	    while (PeekMessage (&amsg, hwnd, WM_MOUSEFIRST, WM_MOUSELAST,
3883				PM_REMOVE));
3884	    /* Get the menu selection, if any */
3885	    if (PeekMessage (&amsg, hwnd, WM_COMMAND, WM_COMMAND, PM_REMOVE))
3886	      {
3887		retval =  LOWORD (amsg.wParam);
3888	      }
3889	    else
3890	      {
3891		retval = 0;
3892	      }
3893	  }
3894	else
3895	  {
3896	    retval = -1;
3897	  }
3898
3899	return retval;
3900      }
3901
3902    default:
3903      /* Check for messages registered at runtime. */
3904      if (msg == msh_mousewheel)
3905	{
3906	  wmsg.dwModifiers = w32_get_modifiers ();
3907	  my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
3908	  signal_user_input ();
3909	  return 0;
3910	}
3911
3912    dflt:
3913      return DefWindowProc (hwnd, msg, wParam, lParam);
3914    }
3915
3916
3917  /* The most common default return code for handled messages is 0.  */
3918  return 0;
3919}
3920
3921static void
3922my_create_window (f)
3923     struct frame * f;
3924{
3925  MSG msg;
3926
3927  if (!PostThreadMessage (dwWindowsThreadId, WM_EMACS_CREATEWINDOW, (WPARAM)f, 0))
3928    abort ();
3929  GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
3930}
3931
3932
3933/* Create a tooltip window. Unlike my_create_window, we do not do this
3934   indirectly via the Window thread, as we do not need to process Window
3935   messages for the tooltip.  Creating tooltips indirectly also creates
3936   deadlocks when tooltips are created for menu items.  */
3937static void
3938my_create_tip_window (f)
3939     struct frame *f;
3940{
3941  RECT rect;
3942
3943  rect.left = rect.top = 0;
3944  rect.right = FRAME_PIXEL_WIDTH (f);
3945  rect.bottom = FRAME_PIXEL_HEIGHT (f);
3946
3947  AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
3948		    FRAME_EXTERNAL_MENU_BAR (f));
3949
3950  tip_window = FRAME_W32_WINDOW (f)
3951    = CreateWindow (EMACS_CLASS,
3952		    f->namebuf,
3953		    f->output_data.w32->dwStyle,
3954		    f->left_pos,
3955		    f->top_pos,
3956		    rect.right - rect.left,
3957		    rect.bottom - rect.top,
3958		    FRAME_W32_WINDOW (SELECTED_FRAME ()), /* owner */
3959		    NULL,
3960		    hinst,
3961		    NULL);
3962
3963  if (tip_window)
3964    {
3965      SetWindowLong (tip_window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
3966      SetWindowLong (tip_window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
3967      SetWindowLong (tip_window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
3968      SetWindowLong (tip_window, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
3969
3970      /* Tip frames have no scrollbars.  */
3971      SetWindowLong (tip_window, WND_SCROLLBAR_INDEX, 0);
3972
3973      /* Do this to discard the default setting specified by our parent. */
3974      ShowWindow (tip_window, SW_HIDE);
3975    }
3976}
3977
3978
3979/* Create and set up the w32 window for frame F.  */
3980
3981static void
3982w32_window (f, window_prompting, minibuffer_only)
3983     struct frame *f;
3984     long window_prompting;
3985     int minibuffer_only;
3986{
3987  BLOCK_INPUT;
3988
3989  /* Use the resource name as the top-level window name
3990     for looking up resources.  Make a non-Lisp copy
3991     for the window manager, so GC relocation won't bother it.
3992
3993     Elsewhere we specify the window name for the window manager.  */
3994
3995  {
3996    char *str = (char *) SDATA (Vx_resource_name);
3997    f->namebuf = (char *) xmalloc (strlen (str) + 1);
3998    strcpy (f->namebuf, str);
3999  }
4000
4001  my_create_window (f);
4002
4003  validate_x_resource_name ();
4004
4005  /* x_set_name normally ignores requests to set the name if the
4006     requested name is the same as the current name.  This is the one
4007     place where that assumption isn't correct; f->name is set, but
4008     the server hasn't been told.  */
4009  {
4010    Lisp_Object name;
4011    int explicit = f->explicit_name;
4012
4013    f->explicit_name = 0;
4014    name = f->name;
4015    f->name = Qnil;
4016    x_set_name (f, name, explicit);
4017  }
4018
4019  UNBLOCK_INPUT;
4020
4021  if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
4022    initialize_frame_menubar (f);
4023
4024  if (FRAME_W32_WINDOW (f) == 0)
4025    error ("Unable to create window");
4026}
4027
4028/* Handle the icon stuff for this window.  Perhaps later we might
4029   want an x_set_icon_position which can be called interactively as
4030   well.  */
4031
4032static void
4033x_icon (f, parms)
4034     struct frame *f;
4035     Lisp_Object parms;
4036{
4037  Lisp_Object icon_x, icon_y;
4038
4039  /* Set the position of the icon.  Note that Windows 95 groups all
4040     icons in the tray.  */
4041  icon_x = w32_get_arg (parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
4042  icon_y = w32_get_arg (parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
4043  if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
4044    {
4045      CHECK_NUMBER (icon_x);
4046      CHECK_NUMBER (icon_y);
4047    }
4048  else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
4049    error ("Both left and top icon corners of icon must be specified");
4050
4051  BLOCK_INPUT;
4052
4053  if (! EQ (icon_x, Qunbound))
4054    x_wm_set_icon_position (f, XINT (icon_x), XINT (icon_y));
4055
4056#if 0 /* TODO */
4057  /* Start up iconic or window? */
4058  x_wm_set_window_state
4059    (f, (EQ (w32_get_arg (parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL), Qicon)
4060	 ? IconicState
4061	 : NormalState));
4062
4063  x_text_icon (f, (char *) SDATA ((!NILP (f->icon_name)
4064				     ? f->icon_name
4065				     : f->name)));
4066#endif
4067
4068  UNBLOCK_INPUT;
4069}
4070
4071
4072static void
4073x_make_gc (f)
4074     struct frame *f;
4075{
4076  XGCValues gc_values;
4077
4078  BLOCK_INPUT;
4079
4080  /* Create the GC's of this frame.
4081     Note that many default values are used.  */
4082
4083  /* Normal video */
4084  gc_values.font = FRAME_FONT (f);
4085
4086  /* Cursor has cursor-color background, background-color foreground.  */
4087  gc_values.foreground = FRAME_BACKGROUND_PIXEL (f);
4088  gc_values.background = f->output_data.w32->cursor_pixel;
4089  f->output_data.w32->cursor_gc
4090    = XCreateGC (NULL, FRAME_W32_WINDOW (f),
4091		 (GCFont | GCForeground | GCBackground),
4092		 &gc_values);
4093
4094  /* Reliefs.  */
4095  f->output_data.w32->white_relief.gc = 0;
4096  f->output_data.w32->black_relief.gc = 0;
4097
4098  UNBLOCK_INPUT;
4099}
4100
4101
4102/* Handler for signals raised during x_create_frame and
4103   x_create_top_frame.  FRAME is the frame which is partially
4104   constructed.  */
4105
4106static Lisp_Object
4107unwind_create_frame (frame)
4108     Lisp_Object frame;
4109{
4110  struct frame *f = XFRAME (frame);
4111
4112  /* If frame is ``official'', nothing to do.  */
4113  if (!CONSP (Vframe_list) || !EQ (XCAR (Vframe_list), frame))
4114    {
4115#ifdef GLYPH_DEBUG
4116      struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4117#endif
4118
4119      x_free_frame_resources (f);
4120
4121      /* Check that reference counts are indeed correct.  */
4122      xassert (dpyinfo->reference_count == dpyinfo_refcount);
4123      xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
4124
4125      return Qt;
4126    }
4127
4128  return Qnil;
4129}
4130
4131
4132DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
4133       1, 1, 0,
4134       doc: /* Make a new window, which is called a \"frame\" in Emacs terms.
4135Returns an Emacs frame object.
4136PARAMETERS is an alist of frame parameters.
4137If the parameters specify that the frame should not have a minibuffer,
4138and do not specify a specific minibuffer window to use,
4139then `default-minibuffer-frame' must be a frame whose minibuffer can
4140be shared by the new frame.
4141
4142This function is an internal primitive--use `make-frame' instead.  */)
4143  (parameters)
4144     Lisp_Object parameters;
4145{
4146  struct frame *f;
4147  Lisp_Object frame, tem;
4148  Lisp_Object name;
4149  int minibuffer_only = 0;
4150  long window_prompting = 0;
4151  int width, height;
4152  int count = SPECPDL_INDEX ();
4153  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
4154  Lisp_Object display;
4155  struct w32_display_info *dpyinfo = NULL;
4156  Lisp_Object parent;
4157  struct kboard *kb;
4158
4159  check_w32 ();
4160
4161  /* Use this general default value to start with
4162     until we know if this frame has a specified name.  */
4163  Vx_resource_name = Vinvocation_name;
4164
4165  display = w32_get_arg (parameters, Qdisplay, 0, 0, RES_TYPE_STRING);
4166  if (EQ (display, Qunbound))
4167    display = Qnil;
4168  dpyinfo = check_x_display_info (display);
4169#ifdef MULTI_KBOARD
4170  kb = dpyinfo->kboard;
4171#else
4172  kb = &the_only_kboard;
4173#endif
4174
4175  name = w32_get_arg (parameters, Qname, "name", "Name", RES_TYPE_STRING);
4176  if (!STRINGP (name)
4177      && ! EQ (name, Qunbound)
4178      && ! NILP (name))
4179    error ("Invalid frame name--not a string or nil");
4180
4181  if (STRINGP (name))
4182    Vx_resource_name = name;
4183
4184  /* See if parent window is specified.  */
4185  parent = w32_get_arg (parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER);
4186  if (EQ (parent, Qunbound))
4187    parent = Qnil;
4188  if (! NILP (parent))
4189    CHECK_NUMBER (parent);
4190
4191  /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
4192  /* No need to protect DISPLAY because that's not used after passing
4193     it to make_frame_without_minibuffer.  */
4194  frame = Qnil;
4195  GCPRO4 (parameters, parent, name, frame);
4196  tem = w32_get_arg (parameters, Qminibuffer, "minibuffer", "Minibuffer",
4197                     RES_TYPE_SYMBOL);
4198  if (EQ (tem, Qnone) || NILP (tem))
4199    f = make_frame_without_minibuffer (Qnil, kb, display);
4200  else if (EQ (tem, Qonly))
4201    {
4202      f = make_minibuffer_frame ();
4203      minibuffer_only = 1;
4204    }
4205  else if (WINDOWP (tem))
4206    f = make_frame_without_minibuffer (tem, kb, display);
4207  else
4208    f = make_frame (1);
4209
4210  XSETFRAME (frame, f);
4211
4212  /* Note that Windows does support scroll bars.  */
4213  FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
4214
4215  /* By default, make scrollbars the system standard width. */
4216  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
4217
4218  f->output_method = output_w32;
4219  f->output_data.w32 =
4220    (struct w32_output *) xmalloc (sizeof (struct w32_output));
4221  bzero (f->output_data.w32, sizeof (struct w32_output));
4222  FRAME_FONTSET (f) = -1;
4223  record_unwind_protect (unwind_create_frame, frame);
4224
4225  f->icon_name
4226    = w32_get_arg (parameters, Qicon_name, "iconName", "Title", RES_TYPE_STRING);
4227  if (! STRINGP (f->icon_name))
4228    f->icon_name = Qnil;
4229
4230/*  FRAME_W32_DISPLAY_INFO (f) = dpyinfo; */
4231#ifdef MULTI_KBOARD
4232  FRAME_KBOARD (f) = kb;
4233#endif
4234
4235  /* Specify the parent under which to make this window.  */
4236
4237  if (!NILP (parent))
4238    {
4239      f->output_data.w32->parent_desc = (Window) XFASTINT (parent);
4240      f->output_data.w32->explicit_parent = 1;
4241    }
4242  else
4243    {
4244      f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
4245      f->output_data.w32->explicit_parent = 0;
4246    }
4247
4248  /* Set the name; the functions to which we pass f expect the name to
4249     be set.  */
4250  if (EQ (name, Qunbound) || NILP (name))
4251    {
4252      f->name = build_string (dpyinfo->w32_id_name);
4253      f->explicit_name = 0;
4254    }
4255  else
4256    {
4257      f->name = name;
4258      f->explicit_name = 1;
4259      /* use the frame's title when getting resources for this frame.  */
4260      specbind (Qx_resource_name, name);
4261    }
4262
4263  /* Extract the window parameters from the supplied values
4264     that are needed to determine window geometry.  */
4265  {
4266    Lisp_Object font;
4267
4268    font = w32_get_arg (parameters, Qfont, "font", "Font", RES_TYPE_STRING);
4269
4270    BLOCK_INPUT;
4271    /* First, try whatever font the caller has specified.  */
4272    if (STRINGP (font))
4273      {
4274        tem = Fquery_fontset (font, Qnil);
4275        if (STRINGP (tem))
4276          font = x_new_fontset (f, SDATA (tem));
4277        else
4278          font = x_new_font (f, SDATA (font));
4279      }
4280    /* Try out a font which we hope has bold and italic variations.  */
4281    if (!STRINGP (font))
4282      font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
4283    if (! STRINGP (font))
4284      font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
4285    /* If those didn't work, look for something which will at least work.  */
4286    if (! STRINGP (font))
4287      font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
4288    UNBLOCK_INPUT;
4289    if (! STRINGP (font))
4290      font = build_string ("Fixedsys");
4291
4292    x_default_parameter (f, parameters, Qfont, font,
4293			 "font", "Font", RES_TYPE_STRING);
4294  }
4295
4296  x_default_parameter (f, parameters, Qborder_width, make_number (2),
4297		       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
4298  /* This defaults to 2 in order to match xterm.  We recognize either
4299     internalBorderWidth or internalBorder (which is what xterm calls
4300     it).  */
4301  if (NILP (Fassq (Qinternal_border_width, parameters)))
4302    {
4303      Lisp_Object value;
4304
4305      value = w32_get_arg (parameters, Qinternal_border_width,
4306                           "internalBorder", "InternalBorder", RES_TYPE_NUMBER);
4307      if (! EQ (value, Qunbound))
4308	parameters = Fcons (Fcons (Qinternal_border_width, value),
4309                            parameters);
4310    }
4311  /* Default internalBorderWidth to 0 on Windows to match other programs.  */
4312  x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
4313		       "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
4314  x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
4315		       "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
4316
4317  /* Also do the stuff which must be set before the window exists.  */
4318  x_default_parameter (f, parameters, Qforeground_color, build_string ("black"),
4319		       "foreground", "Foreground", RES_TYPE_STRING);
4320  x_default_parameter (f, parameters, Qbackground_color, build_string ("white"),
4321		       "background", "Background", RES_TYPE_STRING);
4322  x_default_parameter (f, parameters, Qmouse_color, build_string ("black"),
4323		       "pointerColor", "Foreground", RES_TYPE_STRING);
4324  x_default_parameter (f, parameters, Qcursor_color, build_string ("black"),
4325		       "cursorColor", "Foreground", RES_TYPE_STRING);
4326  x_default_parameter (f, parameters, Qborder_color, build_string ("black"),
4327		       "borderColor", "BorderColor", RES_TYPE_STRING);
4328  x_default_parameter (f, parameters, Qscreen_gamma, Qnil,
4329		       "screenGamma", "ScreenGamma", RES_TYPE_FLOAT);
4330  x_default_parameter (f, parameters, Qline_spacing, Qnil,
4331		       "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
4332  x_default_parameter (f, parameters, Qleft_fringe, Qnil,
4333		       "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
4334  x_default_parameter (f, parameters, Qright_fringe, Qnil,
4335		       "rightFringe", "RightFringe", RES_TYPE_NUMBER);
4336
4337
4338  /* Init faces before x_default_parameter is called for scroll-bar
4339     parameters because that function calls x_set_scroll_bar_width,
4340     which calls change_frame_size, which calls Fset_window_buffer,
4341     which runs hooks, which call Fvertical_motion.  At the end, we
4342     end up in init_iterator with a null face cache, which should not
4343     happen.  */
4344  init_frame_faces (f);
4345
4346  x_default_parameter (f, parameters, Qmenu_bar_lines, make_number (1),
4347		       "menuBar", "MenuBar", RES_TYPE_NUMBER);
4348  x_default_parameter (f, parameters, Qtool_bar_lines, make_number (1),
4349                       "toolBar", "ToolBar", RES_TYPE_NUMBER);
4350
4351  x_default_parameter (f, parameters, Qbuffer_predicate, Qnil,
4352		       "bufferPredicate", "BufferPredicate", RES_TYPE_SYMBOL);
4353  x_default_parameter (f, parameters, Qtitle, Qnil,
4354		       "title", "Title", RES_TYPE_STRING);
4355  x_default_parameter (f, parameters, Qfullscreen, Qnil,
4356                       "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
4357
4358  f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
4359  f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
4360
4361  f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
4362  f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
4363  f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
4364  f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND);
4365  f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
4366  f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
4367
4368  window_prompting = x_figure_window_size (f, parameters, 1);
4369
4370  tem = w32_get_arg (parameters, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
4371  f->no_split = minibuffer_only || EQ (tem, Qt);
4372
4373  w32_window (f, window_prompting, minibuffer_only);
4374  x_icon (f, parameters);
4375
4376  x_make_gc (f);
4377
4378  /* Now consider the frame official.  */
4379  FRAME_W32_DISPLAY_INFO (f)->reference_count++;
4380  Vframe_list = Fcons (frame, Vframe_list);
4381
4382  /* We need to do this after creating the window, so that the
4383     icon-creation functions can say whose icon they're describing.  */
4384  x_default_parameter (f, parameters, Qicon_type, Qnil,
4385		       "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
4386
4387  x_default_parameter (f, parameters, Qauto_raise, Qnil,
4388		       "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4389  x_default_parameter (f, parameters, Qauto_lower, Qnil,
4390		       "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
4391  x_default_parameter (f, parameters, Qcursor_type, Qbox,
4392		       "cursorType", "CursorType", RES_TYPE_SYMBOL);
4393  x_default_parameter (f, parameters, Qscroll_bar_width, Qnil,
4394		       "scrollBarWidth", "ScrollBarWidth", RES_TYPE_NUMBER);
4395
4396  /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
4397     Change will not be effected unless different from the current
4398     FRAME_LINES (f).  */
4399  width = FRAME_COLS (f);
4400  height = FRAME_LINES (f);
4401
4402  FRAME_LINES (f) = 0;
4403  SET_FRAME_COLS (f, 0);
4404  change_frame_size (f, height, width, 1, 0, 0);
4405
4406  /* Tell the server what size and position, etc, we want, and how
4407     badly we want them.  This should be done after we have the menu
4408     bar so that its size can be taken into account.  */
4409  BLOCK_INPUT;
4410  x_wm_set_size_hint (f, window_prompting, 0);
4411  UNBLOCK_INPUT;
4412
4413  /* Make the window appear on the frame and enable display, unless
4414     the caller says not to.  However, with explicit parent, Emacs
4415     cannot control visibility, so don't try.  */
4416  if (! f->output_data.w32->explicit_parent)
4417    {
4418      Lisp_Object visibility;
4419
4420      visibility = w32_get_arg (parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
4421      if (EQ (visibility, Qunbound))
4422	visibility = Qt;
4423
4424      if (EQ (visibility, Qicon))
4425	x_iconify_frame (f);
4426      else if (! NILP (visibility))
4427	x_make_frame_visible (f);
4428      else
4429	/* Must have been Qnil.  */
4430	;
4431    }
4432  UNGCPRO;
4433
4434  /* Make sure windows on this frame appear in calls to next-window
4435     and similar functions.  */
4436  Vwindow_list = Qnil;
4437
4438  return unbind_to (count, frame);
4439}
4440
4441/* FRAME is used only to get a handle on the X display.  We don't pass the
4442   display info directly because we're called from frame.c, which doesn't
4443   know about that structure.  */
4444Lisp_Object
4445x_get_focus_frame (frame)
4446     struct frame *frame;
4447{
4448  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (frame);
4449  Lisp_Object xfocus;
4450  if (! dpyinfo->w32_focus_frame)
4451    return Qnil;
4452
4453  XSETFRAME (xfocus, dpyinfo->w32_focus_frame);
4454  return xfocus;
4455}
4456
4457DEFUN ("w32-focus-frame", Fw32_focus_frame, Sw32_focus_frame, 1, 1, 0,
4458       doc: /* Give FRAME input focus, raising to foreground if necessary.  */)
4459  (frame)
4460     Lisp_Object frame;
4461{
4462  x_focus_on_frame (check_x_frame (frame));
4463  return Qnil;
4464}
4465
4466
4467/* Return the charset portion of a font name.  */
4468char * xlfd_charset_of_font (char * fontname)
4469{
4470  char *charset, *encoding;
4471
4472  encoding = strrchr(fontname, '-');
4473  if (!encoding || encoding == fontname)
4474    return NULL;
4475
4476  for (charset = encoding - 1; charset >= fontname; charset--)
4477    if (*charset == '-')
4478      break;
4479
4480  if (charset == fontname || strcmp(charset, "-*-*") == 0)
4481    return NULL;
4482
4483  return charset + 1;
4484}
4485
4486struct font_info *w32_load_bdf_font (struct frame *f, char *fontname,
4487                                     int size, char* filename);
4488static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names);
4489static BOOL w32_to_x_font (LOGFONT * lplf, char * lpxstr, int len,
4490			   char * charset);
4491static BOOL x_to_w32_font (char *lpxstr, LOGFONT *lplogfont);
4492
4493static struct font_info *
4494w32_load_system_font (f,fontname,size)
4495     struct frame *f;
4496     char * fontname;
4497     int size;
4498{
4499  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4500  Lisp_Object font_names;
4501
4502  /* Get a list of all the fonts that match this name.  Once we
4503     have a list of matching fonts, we compare them against the fonts
4504     we already have loaded by comparing names.  */
4505  font_names = w32_list_fonts (f, build_string (fontname), size, 100);
4506
4507  if (!NILP (font_names))
4508  {
4509      Lisp_Object tail;
4510      int i;
4511
4512      /* First check if any are already loaded, as that is cheaper
4513         than loading another one. */
4514      for (i = 0; i < dpyinfo->n_fonts; i++)
4515	for (tail = font_names; CONSP (tail); tail = XCDR (tail))
4516	  if (dpyinfo->font_table[i].name
4517              && (!strcmp (dpyinfo->font_table[i].name,
4518                           SDATA (XCAR (tail)))
4519                  || !strcmp (dpyinfo->font_table[i].full_name,
4520                              SDATA (XCAR (tail)))))
4521	    return (dpyinfo->font_table + i);
4522
4523      fontname = (char *) SDATA (XCAR (font_names));
4524    }
4525  else if (w32_strict_fontnames)
4526    {
4527      /* If EnumFontFamiliesEx was available, we got a full list of
4528         fonts back so stop now to avoid the possibility of loading a
4529         random font.  If we had to fall back to EnumFontFamilies, the
4530         list is incomplete, so continue whether the font we want was
4531         listed or not. */
4532      HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
4533      FARPROC enum_font_families_ex
4534        = GetProcAddress (gdi32, "EnumFontFamiliesExA");
4535      if (enum_font_families_ex)
4536        return NULL;
4537    }
4538
4539  /* Load the font and add it to the table. */
4540  {
4541    char *full_name, *encoding, *charset;
4542    XFontStruct *font;
4543    struct font_info *fontp;
4544    LOGFONT lf;
4545    BOOL ok;
4546    int codepage;
4547    int i;
4548
4549    if (!fontname || !x_to_w32_font (fontname, &lf))
4550      return (NULL);
4551
4552    if (!*lf.lfFaceName)
4553        /* If no name was specified for the font, we get a random font
4554           from CreateFontIndirect - this is not particularly
4555           desirable, especially since CreateFontIndirect does not
4556           fill out the missing name in lf, so we never know what we
4557           ended up with. */
4558      return NULL;
4559
4560    lf.lfQuality = DEFAULT_QUALITY;
4561
4562    font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
4563    bzero (font, sizeof (*font));
4564
4565    /* Set bdf to NULL to indicate that this is a Windows font.  */
4566    font->bdf = NULL;
4567
4568    BLOCK_INPUT;
4569
4570    font->hfont = CreateFontIndirect (&lf);
4571
4572    if (font->hfont == NULL)
4573      {
4574	ok = FALSE;
4575      }
4576    else
4577      {
4578	HDC hdc;
4579	HANDLE oldobj;
4580
4581        codepage = w32_codepage_for_font (fontname);
4582
4583	hdc = GetDC (dpyinfo->root_window);
4584	oldobj = SelectObject (hdc, font->hfont);
4585
4586	ok = GetTextMetrics (hdc, &font->tm);
4587        if (codepage == CP_UNICODE)
4588          font->double_byte_p = 1;
4589        else
4590	  {
4591	    /* Unfortunately, some fonts (eg. MingLiU, a big5 ttf font)
4592               don't report themselves as double byte fonts, when
4593               patently they are.  So instead of trusting
4594               GetFontLanguageInfo, we check the properties of the
4595               codepage directly, since that is ultimately what we are
4596               working from anyway.  */
4597	    /* font->double_byte_p = GetFontLanguageInfo(hdc) & GCP_DBCS; */
4598	    CPINFO cpi = {0};
4599	    GetCPInfo (codepage, &cpi);
4600	    font->double_byte_p = cpi.MaxCharSize > 1;
4601	  }
4602
4603	SelectObject (hdc, oldobj);
4604	ReleaseDC (dpyinfo->root_window, hdc);
4605        /* Fill out details in lf according to the font that was
4606           actually loaded.  */
4607        lf.lfHeight = font->tm.tmInternalLeading - font->tm.tmHeight;
4608        lf.lfWidth = font->tm.tmMaxCharWidth;
4609        lf.lfWeight = font->tm.tmWeight;
4610        lf.lfItalic = font->tm.tmItalic;
4611        lf.lfCharSet = font->tm.tmCharSet;
4612        lf.lfPitchAndFamily = ((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH)
4613                               ? VARIABLE_PITCH : FIXED_PITCH);
4614        lf.lfOutPrecision = ((font->tm.tmPitchAndFamily & TMPF_VECTOR)
4615                             ? OUT_STROKE_PRECIS : OUT_STRING_PRECIS);
4616
4617	w32_cache_char_metrics (font);
4618      }
4619
4620    UNBLOCK_INPUT;
4621
4622    if (!ok)
4623      {
4624	w32_unload_font (dpyinfo, font);
4625	return (NULL);
4626      }
4627
4628    /* Find a free slot in the font table.  */
4629    for (i = 0; i < dpyinfo->n_fonts; ++i)
4630      if (dpyinfo->font_table[i].name == NULL)
4631	break;
4632
4633    /* If no free slot found, maybe enlarge the font table.  */
4634    if (i == dpyinfo->n_fonts
4635	&& dpyinfo->n_fonts == dpyinfo->font_table_size)
4636      {
4637	int sz;
4638	dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
4639	sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
4640	dpyinfo->font_table
4641	  = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
4642      }
4643
4644    fontp = dpyinfo->font_table + i;
4645    if (i == dpyinfo->n_fonts)
4646      ++dpyinfo->n_fonts;
4647
4648    /* Now fill in the slots of *FONTP.  */
4649    BLOCK_INPUT;
4650    bzero (fontp, sizeof (*fontp));
4651    fontp->font = font;
4652    fontp->font_idx = i;
4653    fontp->name = (char *) xmalloc (strlen (fontname) + 1);
4654    bcopy (fontname, fontp->name, strlen (fontname) + 1);
4655
4656    if (lf.lfPitchAndFamily == FIXED_PITCH)
4657      {
4658	/* Fixed width font.  */
4659	fontp->average_width = fontp->space_width = FONT_WIDTH (font);
4660      }
4661    else
4662      {
4663	wchar_t space = 32;
4664	XCharStruct* pcm;
4665	pcm = w32_per_char_metric (font, &space, ANSI_FONT);
4666	if (pcm)
4667	  fontp->space_width = pcm->width;
4668	else
4669	  fontp->space_width = FONT_WIDTH (font);
4670
4671	fontp->average_width = font->tm.tmAveCharWidth;
4672      }
4673
4674    charset = xlfd_charset_of_font (fontname);
4675
4676  /* Cache the W32 codepage for a font.  This makes w32_encode_char
4677     (called for every glyph during redisplay) much faster.  */
4678    fontp->codepage = codepage;
4679
4680    /* Work out the font's full name.  */
4681    full_name = (char *)xmalloc (100);
4682    if (full_name && w32_to_x_font (&lf, full_name, 100, charset))
4683        fontp->full_name = full_name;
4684    else
4685      {
4686        /* If all else fails - just use the name we used to load it.  */
4687        xfree (full_name);
4688        fontp->full_name = fontp->name;
4689      }
4690
4691    fontp->size = FONT_WIDTH (font);
4692    fontp->height = FONT_HEIGHT (font);
4693
4694    /* The slot `encoding' specifies how to map a character
4695       code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
4696       the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
4697       (0:0x20..0x7F, 1:0xA0..0xFF,
4698       (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
4699       2:0xA020..0xFF7F).  For the moment, we don't know which charset
4700       uses this font.  So, we set information in fontp->encoding[1]
4701       which is never used by any charset.  If mapping can't be
4702       decided, set FONT_ENCODING_NOT_DECIDED.  */
4703
4704    /* SJIS fonts need to be set to type 4, all others seem to work as
4705       type FONT_ENCODING_NOT_DECIDED.  */
4706    encoding = strrchr (fontp->name, '-');
4707    if (encoding && strnicmp (encoding+1, "sjis", 4) == 0)
4708      fontp->encoding[1] = 4;
4709    else
4710      fontp->encoding[1] = FONT_ENCODING_NOT_DECIDED;
4711
4712    /* The following three values are set to 0 under W32, which is
4713       what they get set to if XGetFontProperty fails under X.  */
4714    fontp->baseline_offset = 0;
4715    fontp->relative_compose = 0;
4716    fontp->default_ascent = 0;
4717
4718    /* Set global flag fonts_changed_p to non-zero if the font loaded
4719       has a character with a smaller width than any other character
4720       before, or if the font loaded has a smaller height than any
4721       other font loaded before.  If this happens, it will make a
4722       glyph matrix reallocation necessary.  */
4723    fonts_changed_p |= x_compute_min_glyph_bounds (f);
4724    UNBLOCK_INPUT;
4725    return fontp;
4726  }
4727}
4728
4729/* Load font named FONTNAME of size SIZE for frame F, and return a
4730   pointer to the structure font_info while allocating it dynamically.
4731   If loading fails, return NULL. */
4732struct font_info *
4733w32_load_font (f,fontname,size)
4734struct frame *f;
4735char * fontname;
4736int size;
4737{
4738  Lisp_Object bdf_fonts;
4739  struct font_info *retval = NULL;
4740  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
4741
4742  bdf_fonts = w32_list_bdf_fonts (build_string (fontname), 1);
4743
4744  while (!retval && CONSP (bdf_fonts))
4745    {
4746      char *bdf_name, *bdf_file;
4747      Lisp_Object bdf_pair;
4748      int i;
4749
4750      bdf_name = SDATA (XCAR (bdf_fonts));
4751      bdf_pair = Fassoc (XCAR (bdf_fonts), Vw32_bdf_filename_alist);
4752      bdf_file = SDATA (XCDR (bdf_pair));
4753
4754      // If the font is already loaded, do not load it again.
4755      for (i = 0; i < dpyinfo->n_fonts; i++)
4756	{
4757	  if ((dpyinfo->font_table[i].name
4758	       && !strcmp (dpyinfo->font_table[i].name, bdf_name))
4759	      || (dpyinfo->font_table[i].full_name
4760		  && !strcmp (dpyinfo->font_table[i].full_name, bdf_name)))
4761	    return dpyinfo->font_table + i;
4762	}
4763
4764      retval = w32_load_bdf_font (f, bdf_name, size, bdf_file);
4765
4766      bdf_fonts = XCDR (bdf_fonts);
4767    }
4768
4769  if (retval)
4770    return retval;
4771
4772  return w32_load_system_font(f, fontname, size);
4773}
4774
4775
4776void
4777w32_unload_font (dpyinfo, font)
4778     struct w32_display_info *dpyinfo;
4779     XFontStruct * font;
4780{
4781  if (font)
4782    {
4783      if (font->per_char) xfree (font->per_char);
4784      if (font->bdf) w32_free_bdf_font (font->bdf);
4785
4786      if (font->hfont) DeleteObject(font->hfont);
4787      xfree (font);
4788    }
4789}
4790
4791/* The font conversion stuff between x and w32 */
4792
4793/* X font string is as follows (from faces.el)
4794 * (let ((- 		"[-?]")
4795 *      (foundry	"[^-]+")
4796 *      (family 	"[^-]+")
4797 *      (weight		"\\(bold\\|demibold\\|medium\\)")		; 1
4798 *      (weight\?	"\\([^-]*\\)")					; 1
4799 *      (slant		"\\([ior]\\)")					; 2
4800 *      (slant\?	"\\([^-]?\\)")					; 2
4801 *      (swidth		"\\([^-]*\\)")					; 3
4802 *      (adstyle	"[^-]*")					; 4
4803 *      (pixelsize	"[0-9]+")
4804 *      (pointsize	"[0-9][0-9]+")
4805 *      (resx		"[0-9][0-9]+")
4806 *      (resy		"[0-9][0-9]+")
4807 *      (spacing	"[cmp?*]")
4808 *      (avgwidth	"[0-9]+")
4809 *      (registry	"[^-]+")
4810 *      (encoding	"[^-]+")
4811 *      )
4812 */
4813
4814static LONG
4815x_to_w32_weight (lpw)
4816     char * lpw;
4817{
4818  if (!lpw) return (FW_DONTCARE);
4819
4820  if (stricmp (lpw,"heavy") == 0)             return FW_HEAVY;
4821  else if (stricmp (lpw,"extrabold") == 0)    return FW_EXTRABOLD;
4822  else if (stricmp (lpw,"bold") == 0)         return FW_BOLD;
4823  else if (stricmp (lpw,"demibold") == 0)     return FW_SEMIBOLD;
4824  else if (stricmp (lpw,"semibold") == 0)     return FW_SEMIBOLD;
4825  else if (stricmp (lpw,"medium") == 0)       return FW_MEDIUM;
4826  else if (stricmp (lpw,"normal") == 0)       return FW_NORMAL;
4827  else if (stricmp (lpw,"light") == 0)        return FW_LIGHT;
4828  else if (stricmp (lpw,"extralight") == 0)   return FW_EXTRALIGHT;
4829  else if (stricmp (lpw,"thin") == 0)         return FW_THIN;
4830  else
4831    return FW_DONTCARE;
4832}
4833
4834
4835static char *
4836w32_to_x_weight (fnweight)
4837     int fnweight;
4838{
4839  if (fnweight >= FW_HEAVY)      return "heavy";
4840  if (fnweight >= FW_EXTRABOLD)  return "extrabold";
4841  if (fnweight >= FW_BOLD)       return "bold";
4842  if (fnweight >= FW_SEMIBOLD)   return "demibold";
4843  if (fnweight >= FW_MEDIUM)     return "medium";
4844  if (fnweight >= FW_NORMAL)     return "normal";
4845  if (fnweight >= FW_LIGHT)      return "light";
4846  if (fnweight >= FW_EXTRALIGHT) return "extralight";
4847  if (fnweight >= FW_THIN)       return "thin";
4848  else
4849    return "*";
4850}
4851
4852static LONG
4853x_to_w32_charset (lpcs)
4854    char * lpcs;
4855{
4856  Lisp_Object this_entry, w32_charset;
4857  char *charset;
4858  int len = strlen (lpcs);
4859
4860  /* Support "*-#nnn" format for unknown charsets.  */
4861  if (strncmp (lpcs, "*-#", 3) == 0)
4862    return atoi (lpcs + 3);
4863
4864  /* Handle wildcards by ignoring them; eg. treat "big5*-*" as "big5".  */
4865  charset = alloca (len + 1);
4866  strcpy (charset, lpcs);
4867  lpcs = strchr (charset, '*');
4868  if (lpcs)
4869    *lpcs = 0;
4870
4871  /* Look through w32-charset-info-alist for the character set.
4872     Format of each entry is
4873       (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
4874  */
4875  this_entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
4876
4877  if (NILP(this_entry))
4878    {
4879      /* At startup, we want iso8859-1 fonts to come up properly. */
4880      if (stricmp(charset, "iso8859-1") == 0)
4881        return ANSI_CHARSET;
4882      else
4883        return DEFAULT_CHARSET;
4884    }
4885
4886  w32_charset = Fcar (Fcdr (this_entry));
4887
4888  /* Translate Lisp symbol to number.  */
4889  if (EQ (w32_charset, Qw32_charset_ansi))
4890    return ANSI_CHARSET;
4891  if (EQ (w32_charset, Qw32_charset_symbol))
4892    return SYMBOL_CHARSET;
4893  if (EQ (w32_charset, Qw32_charset_shiftjis))
4894    return SHIFTJIS_CHARSET;
4895  if (EQ (w32_charset, Qw32_charset_hangeul))
4896    return HANGEUL_CHARSET;
4897  if (EQ (w32_charset, Qw32_charset_chinesebig5))
4898    return CHINESEBIG5_CHARSET;
4899  if (EQ (w32_charset, Qw32_charset_gb2312))
4900    return GB2312_CHARSET;
4901  if (EQ (w32_charset, Qw32_charset_oem))
4902    return OEM_CHARSET;
4903#ifdef JOHAB_CHARSET
4904  if (EQ (w32_charset, Qw32_charset_johab))
4905    return JOHAB_CHARSET;
4906  if (EQ (w32_charset, Qw32_charset_easteurope))
4907    return EASTEUROPE_CHARSET;
4908  if (EQ (w32_charset, Qw32_charset_turkish))
4909    return TURKISH_CHARSET;
4910  if (EQ (w32_charset, Qw32_charset_baltic))
4911    return BALTIC_CHARSET;
4912  if (EQ (w32_charset, Qw32_charset_russian))
4913    return RUSSIAN_CHARSET;
4914  if (EQ (w32_charset, Qw32_charset_arabic))
4915    return ARABIC_CHARSET;
4916  if (EQ (w32_charset, Qw32_charset_greek))
4917    return GREEK_CHARSET;
4918  if (EQ (w32_charset, Qw32_charset_hebrew))
4919    return HEBREW_CHARSET;
4920  if (EQ (w32_charset, Qw32_charset_vietnamese))
4921    return VIETNAMESE_CHARSET;
4922  if (EQ (w32_charset, Qw32_charset_thai))
4923    return THAI_CHARSET;
4924  if (EQ (w32_charset, Qw32_charset_mac))
4925    return MAC_CHARSET;
4926#endif /* JOHAB_CHARSET */
4927#ifdef UNICODE_CHARSET
4928  if (EQ (w32_charset, Qw32_charset_unicode))
4929    return UNICODE_CHARSET;
4930#endif
4931
4932  return DEFAULT_CHARSET;
4933}
4934
4935
4936static char *
4937w32_to_x_charset (fncharset)
4938    int fncharset;
4939{
4940  static char buf[32];
4941  Lisp_Object charset_type;
4942
4943  switch (fncharset)
4944    {
4945    case ANSI_CHARSET:
4946      /* Handle startup case of w32-charset-info-alist not
4947         being set up yet. */
4948      if (NILP(Vw32_charset_info_alist))
4949        return "iso8859-1";
4950      charset_type = Qw32_charset_ansi;
4951      break;
4952    case DEFAULT_CHARSET:
4953      charset_type = Qw32_charset_default;
4954      break;
4955    case SYMBOL_CHARSET:
4956      charset_type = Qw32_charset_symbol;
4957      break;
4958    case SHIFTJIS_CHARSET:
4959      charset_type = Qw32_charset_shiftjis;
4960      break;
4961    case HANGEUL_CHARSET:
4962      charset_type = Qw32_charset_hangeul;
4963      break;
4964    case GB2312_CHARSET:
4965      charset_type = Qw32_charset_gb2312;
4966      break;
4967    case CHINESEBIG5_CHARSET:
4968      charset_type = Qw32_charset_chinesebig5;
4969      break;
4970    case OEM_CHARSET:
4971      charset_type = Qw32_charset_oem;
4972      break;
4973
4974      /* More recent versions of Windows (95 and NT4.0) define more
4975         character sets.  */
4976#ifdef EASTEUROPE_CHARSET
4977    case EASTEUROPE_CHARSET:
4978      charset_type = Qw32_charset_easteurope;
4979      break;
4980    case TURKISH_CHARSET:
4981      charset_type = Qw32_charset_turkish;
4982      break;
4983    case BALTIC_CHARSET:
4984      charset_type = Qw32_charset_baltic;
4985      break;
4986    case RUSSIAN_CHARSET:
4987      charset_type = Qw32_charset_russian;
4988      break;
4989    case ARABIC_CHARSET:
4990      charset_type = Qw32_charset_arabic;
4991      break;
4992    case GREEK_CHARSET:
4993      charset_type = Qw32_charset_greek;
4994      break;
4995    case HEBREW_CHARSET:
4996      charset_type = Qw32_charset_hebrew;
4997      break;
4998    case VIETNAMESE_CHARSET:
4999      charset_type = Qw32_charset_vietnamese;
5000      break;
5001    case THAI_CHARSET:
5002      charset_type = Qw32_charset_thai;
5003      break;
5004    case MAC_CHARSET:
5005      charset_type = Qw32_charset_mac;
5006      break;
5007    case JOHAB_CHARSET:
5008      charset_type = Qw32_charset_johab;
5009      break;
5010#endif
5011
5012#ifdef UNICODE_CHARSET
5013    case UNICODE_CHARSET:
5014      charset_type = Qw32_charset_unicode;
5015      break;
5016#endif
5017    default:
5018      /* Encode numerical value of unknown charset.  */
5019      sprintf (buf, "*-#%u", fncharset);
5020      return buf;
5021    }
5022
5023  {
5024    Lisp_Object rest;
5025    char * best_match = NULL;
5026
5027    /* Look through w32-charset-info-alist for the character set.
5028       Prefer ISO codepages, and prefer lower numbers in the ISO
5029       range. Only return charsets for codepages which are installed.
5030
5031       Format of each entry is
5032         (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5033    */
5034    for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
5035      {
5036        char * x_charset;
5037        Lisp_Object w32_charset;
5038        Lisp_Object codepage;
5039
5040        Lisp_Object this_entry = XCAR (rest);
5041
5042        /* Skip invalid entries in alist. */
5043        if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
5044            || !CONSP (XCDR (this_entry))
5045            || !SYMBOLP (XCAR (XCDR (this_entry))))
5046          continue;
5047
5048        x_charset = SDATA (XCAR (this_entry));
5049        w32_charset = XCAR (XCDR (this_entry));
5050        codepage = XCDR (XCDR (this_entry));
5051
5052        /* Look for Same charset and a valid codepage (or non-int
5053           which means ignore).  */
5054        if (EQ (w32_charset, charset_type)
5055            && (!INTEGERP (codepage) || XINT (codepage) == CP_DEFAULT
5056                || IsValidCodePage (XINT (codepage))))
5057          {
5058            /* If we don't have a match already, then this is the
5059               best.  */
5060            if (!best_match)
5061              best_match = x_charset;
5062            /* If this is an ISO codepage, and the best so far isn't,
5063               then this is better.  */
5064            else if (strnicmp (best_match, "iso", 3) != 0
5065                     && strnicmp (x_charset, "iso", 3) == 0)
5066              best_match = x_charset;
5067            /* If both are ISO8859 codepages, choose the one with the
5068               lowest number in the encoding field.  */
5069            else if (strnicmp (best_match, "iso8859-", 8) == 0
5070                     && strnicmp (x_charset, "iso8859-", 8) == 0)
5071              {
5072                int best_enc = atoi (best_match + 8);
5073                int this_enc = atoi (x_charset + 8);
5074                if (this_enc > 0 && this_enc < best_enc)
5075                  best_match = x_charset;
5076              }
5077          }
5078      }
5079
5080    /* If no match, encode the numeric value. */
5081    if (!best_match)
5082      {
5083        sprintf (buf, "*-#%u", fncharset);
5084        return buf;
5085      }
5086
5087    strncpy(buf, best_match, 31);
5088    buf[31] = '\0';
5089    return buf;
5090  }
5091}
5092
5093
5094/* Return all the X charsets that map to a font.  */
5095static Lisp_Object
5096w32_to_all_x_charsets (fncharset)
5097    int fncharset;
5098{
5099  static char buf[32];
5100  Lisp_Object charset_type;
5101  Lisp_Object retval = Qnil;
5102
5103  switch (fncharset)
5104    {
5105    case ANSI_CHARSET:
5106      /* Handle startup case of w32-charset-info-alist not
5107         being set up yet. */
5108      if (NILP(Vw32_charset_info_alist))
5109        return Fcons (build_string ("iso8859-1"), Qnil);
5110
5111      charset_type = Qw32_charset_ansi;
5112      break;
5113    case DEFAULT_CHARSET:
5114      charset_type = Qw32_charset_default;
5115      break;
5116    case SYMBOL_CHARSET:
5117      charset_type = Qw32_charset_symbol;
5118      break;
5119    case SHIFTJIS_CHARSET:
5120      charset_type = Qw32_charset_shiftjis;
5121      break;
5122    case HANGEUL_CHARSET:
5123      charset_type = Qw32_charset_hangeul;
5124      break;
5125    case GB2312_CHARSET:
5126      charset_type = Qw32_charset_gb2312;
5127      break;
5128    case CHINESEBIG5_CHARSET:
5129      charset_type = Qw32_charset_chinesebig5;
5130      break;
5131    case OEM_CHARSET:
5132      charset_type = Qw32_charset_oem;
5133      break;
5134
5135      /* More recent versions of Windows (95 and NT4.0) define more
5136         character sets.  */
5137#ifdef EASTEUROPE_CHARSET
5138    case EASTEUROPE_CHARSET:
5139      charset_type = Qw32_charset_easteurope;
5140      break;
5141    case TURKISH_CHARSET:
5142      charset_type = Qw32_charset_turkish;
5143      break;
5144    case BALTIC_CHARSET:
5145      charset_type = Qw32_charset_baltic;
5146      break;
5147    case RUSSIAN_CHARSET:
5148      charset_type = Qw32_charset_russian;
5149      break;
5150    case ARABIC_CHARSET:
5151      charset_type = Qw32_charset_arabic;
5152      break;
5153    case GREEK_CHARSET:
5154      charset_type = Qw32_charset_greek;
5155      break;
5156    case HEBREW_CHARSET:
5157      charset_type = Qw32_charset_hebrew;
5158      break;
5159    case VIETNAMESE_CHARSET:
5160      charset_type = Qw32_charset_vietnamese;
5161      break;
5162    case THAI_CHARSET:
5163      charset_type = Qw32_charset_thai;
5164      break;
5165    case MAC_CHARSET:
5166      charset_type = Qw32_charset_mac;
5167      break;
5168    case JOHAB_CHARSET:
5169      charset_type = Qw32_charset_johab;
5170      break;
5171#endif
5172
5173#ifdef UNICODE_CHARSET
5174    case UNICODE_CHARSET:
5175      charset_type = Qw32_charset_unicode;
5176      break;
5177#endif
5178    default:
5179      /* Encode numerical value of unknown charset.  */
5180      sprintf (buf, "*-#%u", fncharset);
5181      return Fcons (build_string (buf), Qnil);
5182    }
5183
5184  {
5185    Lisp_Object rest;
5186    /* Look through w32-charset-info-alist for the character set.
5187       Only return charsets for codepages which are installed.
5188
5189       Format of each entry in Vw32_charset_info_alist is
5190         (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE)).
5191    */
5192    for (rest = Vw32_charset_info_alist; CONSP (rest); rest = XCDR (rest))
5193      {
5194        Lisp_Object x_charset;
5195        Lisp_Object w32_charset;
5196        Lisp_Object codepage;
5197
5198        Lisp_Object this_entry = XCAR (rest);
5199
5200        /* Skip invalid entries in alist. */
5201        if (!CONSP (this_entry) || !STRINGP (XCAR (this_entry))
5202            || !CONSP (XCDR (this_entry))
5203            || !SYMBOLP (XCAR (XCDR (this_entry))))
5204          continue;
5205
5206        x_charset = XCAR (this_entry);
5207        w32_charset = XCAR (XCDR (this_entry));
5208        codepage = XCDR (XCDR (this_entry));
5209
5210        /* Look for Same charset and a valid codepage (or non-int
5211           which means ignore).  */
5212        if (EQ (w32_charset, charset_type)
5213            && (!INTEGERP (codepage) || XINT (codepage) == CP_DEFAULT
5214                || IsValidCodePage (XINT (codepage))))
5215          {
5216	    retval = Fcons (x_charset, retval);
5217          }
5218      }
5219
5220    /* If no match, encode the numeric value. */
5221    if (NILP (retval))
5222      {
5223        sprintf (buf, "*-#%u", fncharset);
5224        return Fcons (build_string (buf), Qnil);
5225      }
5226
5227    return retval;
5228  }
5229}
5230
5231/* Get the Windows codepage corresponding to the specified font.  The
5232   charset info in the font name is used to look up
5233   w32-charset-to-codepage-alist.  */
5234int
5235w32_codepage_for_font (char *fontname)
5236{
5237  Lisp_Object codepage, entry;
5238  char *charset_str, *charset, *end;
5239
5240  if (NILP (Vw32_charset_info_alist))
5241    return CP_DEFAULT;
5242
5243  /* Extract charset part of font string.  */
5244  charset = xlfd_charset_of_font (fontname);
5245
5246  if (!charset)
5247    return CP_UNKNOWN;
5248
5249  charset_str = (char *) alloca (strlen (charset) + 1);
5250  strcpy (charset_str, charset);
5251
5252#if 0
5253  /* Remove leading "*-".  */
5254  if (strncmp ("*-", charset_str, 2) == 0)
5255    charset = charset_str + 2;
5256  else
5257#endif
5258    charset = charset_str;
5259
5260  /* Stop match at wildcard (including preceding '-'). */
5261  if (end = strchr (charset, '*'))
5262      {
5263        if (end > charset && *(end-1) == '-')
5264          end--;
5265        *end = '\0';
5266      }
5267
5268  entry = Fassoc (build_string(charset), Vw32_charset_info_alist);
5269  if (NILP (entry))
5270    return CP_UNKNOWN;
5271
5272  codepage = Fcdr (Fcdr (entry));
5273
5274  if (NILP (codepage))
5275    return CP_8BIT;
5276  else if (XFASTINT (codepage) == XFASTINT (Qt))
5277    return CP_UNICODE;
5278  else if (INTEGERP (codepage))
5279    return XINT (codepage);
5280  else
5281    return CP_UNKNOWN;
5282}
5283
5284
5285static BOOL
5286w32_to_x_font (lplogfont, lpxstr, len, specific_charset)
5287     LOGFONT * lplogfont;
5288     char * lpxstr;
5289     int len;
5290     char * specific_charset;
5291{
5292  char* fonttype;
5293  char *fontname;
5294  char height_pixels[8];
5295  char height_dpi[8];
5296  char width_pixels[8];
5297  char *fontname_dash;
5298  int display_resy = (int) one_w32_display_info.resy;
5299  int display_resx = (int) one_w32_display_info.resx;
5300  int bufsz;
5301  struct coding_system coding;
5302
5303  if (!lpxstr) abort ();
5304
5305  if (!lplogfont)
5306    return FALSE;
5307
5308  if (lplogfont->lfOutPrecision == OUT_STRING_PRECIS)
5309    fonttype = "raster";
5310  else if (lplogfont->lfOutPrecision == OUT_STROKE_PRECIS)
5311    fonttype = "outline";
5312  else
5313    fonttype = "unknown";
5314
5315  setup_coding_system (Fcheck_coding_system (Vlocale_coding_system),
5316                       &coding);
5317  coding.src_multibyte = 0;
5318  coding.dst_multibyte = 1;
5319  coding.mode |= CODING_MODE_LAST_BLOCK;
5320  /* We explicitely disable composition handling because selection
5321     data should not contain any composition sequence.  */
5322  coding.composing = COMPOSITION_DISABLED;
5323  bufsz = decoding_buffer_size (&coding, LF_FACESIZE);
5324
5325  fontname = alloca(sizeof(*fontname) * bufsz);
5326  decode_coding (&coding, lplogfont->lfFaceName, fontname,
5327                 strlen(lplogfont->lfFaceName), bufsz - 1);
5328  *(fontname + coding.produced) = '\0';
5329
5330  /* Replace dashes with underscores so the dashes are not
5331     misinterpreted.  */
5332  fontname_dash = fontname;
5333  while (fontname_dash = strchr (fontname_dash, '-'))
5334      *fontname_dash = '_';
5335
5336  if (lplogfont->lfHeight)
5337    {
5338      sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
5339      sprintf (height_dpi, "%u",
5340	       abs (lplogfont->lfHeight) * 720 / display_resy);
5341    }
5342  else
5343    {
5344      strcpy (height_pixels, "*");
5345      strcpy (height_dpi, "*");
5346    }
5347
5348#if 0 /* Never put the width in the xfld. It fails on fonts with
5349	 double-width characters.  */
5350  if (lplogfont->lfWidth)
5351    sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
5352  else
5353#endif
5354    strcpy (width_pixels, "*");
5355
5356  _snprintf (lpxstr, len - 1,
5357	     "-%s-%s-%s-%c-normal-normal-%s-%s-%d-%d-%c-%s-%s",
5358             fonttype,                               /* foundry */
5359	     fontname,                               /* family */
5360	     w32_to_x_weight (lplogfont->lfWeight),  /* weight */
5361	     lplogfont->lfItalic?'i':'r',            /* slant */
5362                                                     /* setwidth name */
5363                                                     /* add style name */
5364	     height_pixels,                          /* pixel size */
5365	     height_dpi,                             /* point size */
5366             display_resx,                           /* resx */
5367             display_resy,                           /* resy */
5368	     ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH)
5369             ? 'p' : 'c',                            /* spacing */
5370	     width_pixels,                           /* avg width */
5371	     specific_charset ? specific_charset
5372             : w32_to_x_charset (lplogfont->lfCharSet)
5373             /* charset registry and encoding */
5374	     );
5375
5376  lpxstr[len - 1] = 0;		/* just to be sure */
5377  return (TRUE);
5378}
5379
5380static BOOL
5381x_to_w32_font (lpxstr, lplogfont)
5382     char * lpxstr;
5383     LOGFONT * lplogfont;
5384{
5385  struct coding_system coding;
5386
5387  if (!lplogfont) return (FALSE);
5388
5389  memset (lplogfont, 0, sizeof (*lplogfont));
5390
5391  /* Set default value for each field.  */
5392#if 1
5393  lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
5394  lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
5395  lplogfont->lfQuality = DEFAULT_QUALITY;
5396#else
5397  /* go for maximum quality */
5398  lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
5399  lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
5400  lplogfont->lfQuality = PROOF_QUALITY;
5401#endif
5402
5403  lplogfont->lfCharSet = DEFAULT_CHARSET;
5404  lplogfont->lfWeight = FW_DONTCARE;
5405  lplogfont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
5406
5407  if (!lpxstr)
5408    return FALSE;
5409
5410  /* Provide a simple escape mechanism for specifying Windows font names
5411   * directly -- if font spec does not beginning with '-', assume this
5412   * format:
5413   *   "<font name>[:height in pixels[:width in pixels[:weight]]]"
5414   */
5415
5416  if (*lpxstr == '-')
5417    {
5418      int fields, tem;
5419      char name[50], weight[20], slant, pitch, pixels[10], height[10],
5420        width[10], resy[10], remainder[50];
5421      char * encoding;
5422      int dpi = (int) one_w32_display_info.resy;
5423
5424      fields = sscanf (lpxstr,
5425		       "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%9[^-]-%c-%9[^-]-%49s",
5426		       name, weight, &slant, pixels, height, resy, &pitch, width, remainder);
5427      if (fields == EOF)
5428	return (FALSE);
5429
5430      /* In the general case when wildcards cover more than one field,
5431	 we don't know which field is which, so don't fill any in.
5432	 However, we need to cope with this particular form, which is
5433	 generated by font_list_1 (invoked by try_font_list):
5434	     "-raster-6x10-*-gb2312*-*"
5435	 and make sure to correctly parse the charset field.  */
5436      if (fields == 3)
5437	{
5438	  fields = sscanf (lpxstr,
5439			   "-%*[^-]-%49[^-]-*-%49s",
5440			   name, remainder);
5441	}
5442      else if (fields < 9)
5443	{
5444	  fields = 0;
5445	  remainder[0] = 0;
5446	}
5447
5448      if (fields > 0 && name[0] != '*')
5449        {
5450	  int bufsize;
5451	  unsigned char *buf;
5452
5453          setup_coding_system
5454            (Fcheck_coding_system (Vlocale_coding_system), &coding);
5455	  coding.src_multibyte = 1;
5456	  coding.dst_multibyte = 0;
5457	  /* Need to set COMPOSITION_DISABLED, otherwise Emacs crashes in
5458	     encode_coding_iso2022 trying to dereference a null pointer.  */
5459	  coding.composing = COMPOSITION_DISABLED;
5460	  if (coding.type == coding_type_iso2022)
5461	    coding.flags |= CODING_FLAG_ISO_SAFE;
5462	  bufsize = encoding_buffer_size (&coding, strlen (name));
5463	  buf = (unsigned char *) alloca (bufsize);
5464          coding.mode |= CODING_MODE_LAST_BLOCK;
5465          encode_coding (&coding, name, buf, strlen (name), bufsize);
5466	  if (coding.produced >= LF_FACESIZE)
5467	    coding.produced = LF_FACESIZE - 1;
5468	  buf[coding.produced] = 0;
5469	  strcpy (lplogfont->lfFaceName, buf);
5470	}
5471      else
5472        {
5473	  lplogfont->lfFaceName[0] = '\0';
5474	}
5475
5476      fields--;
5477
5478      lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
5479
5480      fields--;
5481
5482      lplogfont->lfItalic = (fields > 0 && slant == 'i');
5483
5484      fields--;
5485
5486      if (fields > 0 && pixels[0] != '*')
5487	lplogfont->lfHeight = atoi (pixels);
5488
5489      fields--;
5490      fields--;
5491      if (fields > 0 && resy[0] != '*')
5492        {
5493          tem = atoi (resy);
5494          if (tem > 0) dpi = tem;
5495        }
5496
5497      if (fields > -1 && lplogfont->lfHeight == 0 && height[0] != '*')
5498	lplogfont->lfHeight = atoi (height) * dpi / 720;
5499
5500      if (fields > 0)
5501      lplogfont->lfPitchAndFamily =
5502	(fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
5503
5504      fields--;
5505
5506      if (fields > 0 && width[0] != '*')
5507	lplogfont->lfWidth = atoi (width) / 10;
5508
5509      fields--;
5510
5511      /* Strip the trailing '-' if present. (it shouldn't be, as it
5512         fails the test against xlfd-tight-regexp in fontset.el).  */
5513      {
5514	int len = strlen (remainder);
5515	if (len > 0 && remainder[len-1] == '-')
5516	  remainder[len-1] = 0;
5517      }
5518      encoding = remainder;
5519#if 0
5520      if (strncmp (encoding, "*-", 2) == 0)
5521	encoding += 2;
5522#endif
5523      lplogfont->lfCharSet = x_to_w32_charset (encoding);
5524    }
5525  else
5526    {
5527      int fields;
5528      char name[100], height[10], width[10], weight[20];
5529
5530      fields = sscanf (lpxstr,
5531		       "%99[^:]:%9[^:]:%9[^:]:%19s",
5532		       name, height, width, weight);
5533
5534      if (fields == EOF) return (FALSE);
5535
5536      if (fields > 0)
5537        {
5538	  strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
5539	  lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
5540	}
5541      else
5542        {
5543	  lplogfont->lfFaceName[0] = 0;
5544	}
5545
5546      fields--;
5547
5548      if (fields > 0)
5549	lplogfont->lfHeight = atoi (height);
5550
5551      fields--;
5552
5553      if (fields > 0)
5554	lplogfont->lfWidth = atoi (width);
5555
5556      fields--;
5557
5558      lplogfont->lfWeight = x_to_w32_weight ((fields > 0 ? weight : ""));
5559    }
5560
5561  /* This makes TrueType fonts work better. */
5562  lplogfont->lfHeight = - abs (lplogfont->lfHeight);
5563
5564  return (TRUE);
5565}
5566
5567/* Strip the pixel height and point height from the given xlfd, and
5568   return the pixel height. If no pixel height is specified, calculate
5569   one from the point height, or if that isn't defined either, return
5570   0 (which usually signifies a scalable font).
5571*/
5572static int
5573xlfd_strip_height (char *fontname)
5574{
5575  int pixel_height, field_number;
5576  char *read_from, *write_to;
5577
5578  xassert (fontname);
5579
5580  pixel_height = field_number = 0;
5581  write_to = NULL;
5582
5583  /* Look for height fields.  */
5584  for (read_from = fontname; *read_from; read_from++)
5585    {
5586      if (*read_from == '-')
5587        {
5588          field_number++;
5589          if (field_number == 7) /* Pixel height.  */
5590            {
5591              read_from++;
5592              write_to = read_from;
5593
5594              /* Find end of field.  */
5595              for (;*read_from && *read_from != '-'; read_from++)
5596                ;
5597
5598              /* Split the fontname at end of field.  */
5599              if (*read_from)
5600                {
5601                  *read_from = '\0';
5602                  read_from++;
5603                }
5604              pixel_height = atoi (write_to);
5605              /* Blank out field. */
5606              if (read_from > write_to)
5607                {
5608                  *write_to = '-';
5609                  write_to++;
5610                }
5611              /* If the pixel height field is at the end (partial xlfd),
5612                 return now.  */
5613              else
5614                return pixel_height;
5615
5616              /* If we got a pixel height, the point height can be
5617                 ignored. Just blank it out and break now.  */
5618              if (pixel_height)
5619                {
5620                  /* Find end of point size field.  */
5621                  for (; *read_from && *read_from != '-'; read_from++)
5622                    ;
5623
5624                  if (*read_from)
5625                    read_from++;
5626
5627                  /* Blank out the point size field.  */
5628                  if (read_from > write_to)
5629                    {
5630                      *write_to = '-';
5631                      write_to++;
5632                    }
5633                  else
5634                    return pixel_height;
5635
5636                  break;
5637                }
5638              /* If the point height is already blank, break now.  */
5639              if (*read_from == '-')
5640                {
5641                  read_from++;
5642                  break;
5643                }
5644            }
5645          else if (field_number == 8)
5646            {
5647              /* If we didn't get a pixel height, try to get the point
5648                 height and convert that.  */
5649              int point_size;
5650              char *point_size_start = read_from++;
5651
5652              /* Find end of field.  */
5653              for (; *read_from && *read_from != '-'; read_from++)
5654                ;
5655
5656              if (*read_from)
5657                {
5658                  *read_from = '\0';
5659                  read_from++;
5660                }
5661
5662              point_size = atoi (point_size_start);
5663
5664              /* Convert to pixel height. */
5665              pixel_height = point_size
5666                           * one_w32_display_info.height_in / 720;
5667
5668              /* Blank out this field and break.  */
5669              *write_to = '-';
5670              write_to++;
5671              break;
5672            }
5673        }
5674    }
5675
5676  /* Shift the rest of the font spec into place.  */
5677  if (write_to && read_from > write_to)
5678    {
5679      for (; *read_from; read_from++, write_to++)
5680        *write_to = *read_from;
5681      *write_to = '\0';
5682    }
5683
5684  return pixel_height;
5685}
5686
5687/* Assume parameter 1 is fully qualified, no wildcards. */
5688static BOOL
5689w32_font_match (fontname, pattern)
5690    char * fontname;
5691    char * pattern;
5692{
5693  char *ptr;
5694  char *font_name_copy;
5695  char *regex = alloca (strlen (pattern) * 2 + 3);
5696
5697  font_name_copy = alloca (strlen (fontname) + 1);
5698  strcpy (font_name_copy, fontname);
5699
5700  ptr = regex;
5701  *ptr++ = '^';
5702
5703  /* Turn pattern into a regexp and do a regexp match.  */
5704  for (; *pattern; pattern++)
5705    {
5706      if (*pattern == '?')
5707        *ptr++ = '.';
5708      else if (*pattern == '*')
5709        {
5710          *ptr++ = '.';
5711          *ptr++ = '*';
5712        }
5713      else
5714        *ptr++ = *pattern;
5715    }
5716  *ptr = '$';
5717  *(ptr + 1) = '\0';
5718
5719  /* Strip out font heights and compare them seperately, since
5720     rounding error can cause mismatches. This also allows a
5721     comparison between a font that declares only a pixel height and a
5722     pattern that declares the point height.
5723  */
5724  {
5725    int font_height, pattern_height;
5726
5727    font_height = xlfd_strip_height (font_name_copy);
5728    pattern_height = xlfd_strip_height (regex);
5729
5730    /* Compare now, and don't bother doing expensive regexp matching
5731       if the heights differ.  */
5732    if (font_height && pattern_height && (font_height != pattern_height))
5733      return FALSE;
5734  }
5735
5736  return (fast_string_match_ignore_case (build_string (regex),
5737                                         build_string(font_name_copy)) >= 0);
5738}
5739
5740/* Callback functions, and a structure holding info they need, for
5741   listing system fonts on W32. We need one set of functions to do the
5742   job properly, but these don't work on NT 3.51 and earlier, so we
5743   have a second set which don't handle character sets properly to
5744   fall back on.
5745
5746   In both cases, there are two passes made. The first pass gets one
5747   font from each family, the second pass lists all the fonts from
5748   each family.  */
5749
5750typedef struct enumfont_t
5751{
5752  HDC hdc;
5753  int numFonts;
5754  LOGFONT logfont;
5755  XFontStruct *size_ref;
5756  Lisp_Object pattern;
5757  Lisp_Object list;
5758} enumfont_t;
5759
5760
5761static void
5762enum_font_maybe_add_to_list (enumfont_t *, LOGFONT *, char *, Lisp_Object);
5763
5764
5765static int CALLBACK
5766enum_font_cb2 (lplf, lptm, FontType, lpef)
5767    ENUMLOGFONT * lplf;
5768    NEWTEXTMETRIC * lptm;
5769    int FontType;
5770    enumfont_t * lpef;
5771{
5772  /* Ignore struck out and underlined versions of fonts.  */
5773  if (lplf->elfLogFont.lfStrikeOut || lplf->elfLogFont.lfUnderline)
5774    return 1;
5775
5776  /* Only return fonts with names starting with @ if they were
5777     explicitly specified, since Microsoft uses an initial @ to
5778     denote fonts for vertical writing, without providing a more
5779     convenient way of identifying them.  */
5780  if (lplf->elfLogFont.lfFaceName[0] == '@'
5781      && lpef->logfont.lfFaceName[0] != '@')
5782    return 1;
5783
5784  /* Check that the character set matches if it was specified */
5785  if (lpef->logfont.lfCharSet != DEFAULT_CHARSET &&
5786      lplf->elfLogFont.lfCharSet != lpef->logfont.lfCharSet)
5787    return 1;
5788
5789  if (FontType == RASTER_FONTTYPE)
5790    {
5791      /* DBCS raster fonts have problems displaying, so skip them.  */
5792      int charset = lplf->elfLogFont.lfCharSet;
5793      if (charset == SHIFTJIS_CHARSET
5794	  || charset == HANGEUL_CHARSET
5795	  || charset == CHINESEBIG5_CHARSET
5796	  || charset == GB2312_CHARSET
5797#ifdef JOHAB_CHARSET
5798	  || charset == JOHAB_CHARSET
5799#endif
5800	  )
5801	return 1;
5802    }
5803
5804  {
5805    char buf[100];
5806    Lisp_Object width = Qnil;
5807    Lisp_Object charset_list = Qnil;
5808    char *charset = NULL;
5809
5810    /* Truetype fonts do not report their true metrics until loaded */
5811    if (FontType != RASTER_FONTTYPE)
5812      {
5813	if (!NILP (lpef->pattern))
5814	  {
5815	    /* Scalable fonts are as big as you want them to be.  */
5816	    lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
5817	    lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
5818	    width = make_number (lpef->logfont.lfWidth);
5819	  }
5820	else
5821	  {
5822	    lplf->elfLogFont.lfHeight = 0;
5823	    lplf->elfLogFont.lfWidth = 0;
5824	  }
5825      }
5826
5827    /* Make sure the height used here is the same as everywhere
5828       else (ie character height, not cell height).  */
5829    if (lplf->elfLogFont.lfHeight > 0)
5830      {
5831        /* lptm can be trusted for RASTER fonts, but not scalable ones. */
5832        if (FontType == RASTER_FONTTYPE)
5833          lplf->elfLogFont.lfHeight = lptm->tmInternalLeading - lptm->tmHeight;
5834        else
5835          lplf->elfLogFont.lfHeight = -lplf->elfLogFont.lfHeight;
5836      }
5837
5838    if (!NILP (lpef->pattern))
5839      {
5840        charset = xlfd_charset_of_font (SDATA (lpef->pattern));
5841
5842	/* We already checked charsets above, but DEFAULT_CHARSET
5843           slipped through.  So only allow exact matches for DEFAULT_CHARSET.  */
5844	if (charset
5845	    && strncmp (charset, "*-*", 3) != 0
5846	    && lpef->logfont.lfCharSet == DEFAULT_CHARSET
5847	    && strcmp (charset, w32_to_x_charset (DEFAULT_CHARSET)) != 0)
5848	  return 1;
5849      }
5850
5851    if (charset)
5852      charset_list = Fcons (build_string (charset), Qnil);
5853    else
5854      charset_list = w32_to_all_x_charsets (lplf->elfLogFont.lfCharSet);
5855
5856    /* Loop through the charsets.  */
5857    for ( ; CONSP (charset_list); charset_list = Fcdr (charset_list))
5858      {
5859	Lisp_Object this_charset = Fcar (charset_list);
5860	charset = SDATA (this_charset);
5861
5862	/* List bold and italic variations if w32-enable-synthesized-fonts
5863	   is non-nil and this is a plain font.  */
5864	if (w32_enable_synthesized_fonts
5865	    && lplf->elfLogFont.lfWeight == FW_NORMAL
5866	    && lplf->elfLogFont.lfItalic == FALSE)
5867	  {
5868	    enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
5869					 charset, width);
5870	    /* bold.  */
5871	    lplf->elfLogFont.lfWeight = FW_BOLD;
5872	    enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
5873					 charset, width);
5874	    /* bold italic.  */
5875	    lplf->elfLogFont.lfItalic = TRUE;
5876	    enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
5877					 charset, width);
5878	    /* italic.  */
5879	    lplf->elfLogFont.lfWeight = FW_NORMAL;
5880	    enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
5881					 charset, width);
5882	  }
5883	else
5884	  enum_font_maybe_add_to_list (lpef, &(lplf->elfLogFont),
5885				       charset, width);
5886      }
5887  }
5888
5889  return 1;
5890}
5891
5892static void
5893enum_font_maybe_add_to_list (lpef, logfont, match_charset, width)
5894     enumfont_t * lpef;
5895     LOGFONT * logfont;
5896     char * match_charset;
5897     Lisp_Object width;
5898{
5899  char buf[100];
5900
5901  if (!w32_to_x_font (logfont, buf, 100, match_charset))
5902    return;
5903
5904  if (NILP (lpef->pattern)
5905      || w32_font_match (buf, SDATA (lpef->pattern)))
5906    {
5907      /* Check if we already listed this font.  This may happen if
5908         w32_enable_synthesized_fonts is non-nil, and there are real
5909         bold and italic versions of the font.  */
5910      Lisp_Object font_name = build_string (buf);
5911      if (NILP (Fmember (font_name, lpef->list)))
5912	{
5913	  Lisp_Object entry = Fcons (font_name, width);
5914	  lpef->list = Fcons (entry, lpef->list);
5915	  lpef->numFonts++;
5916	}
5917    }
5918}
5919
5920
5921static int CALLBACK
5922enum_font_cb1 (lplf, lptm, FontType, lpef)
5923     ENUMLOGFONT * lplf;
5924     NEWTEXTMETRIC * lptm;
5925     int FontType;
5926     enumfont_t * lpef;
5927{
5928  return EnumFontFamilies (lpef->hdc,
5929			   lplf->elfLogFont.lfFaceName,
5930			   (FONTENUMPROC) enum_font_cb2,
5931			   (LPARAM) lpef);
5932}
5933
5934
5935static int CALLBACK
5936enum_fontex_cb2 (lplf, lptm, font_type, lpef)
5937     ENUMLOGFONTEX * lplf;
5938     NEWTEXTMETRICEX * lptm;
5939     int font_type;
5940     enumfont_t * lpef;
5941{
5942  /* We are not interested in the extra info we get back from the 'Ex
5943     version - only the fact that we get character set variations
5944     enumerated seperately.  */
5945  return enum_font_cb2 ((ENUMLOGFONT *) lplf, (NEWTEXTMETRIC *) lptm,
5946                        font_type, lpef);
5947}
5948
5949static int CALLBACK
5950enum_fontex_cb1 (lplf, lptm, font_type, lpef)
5951     ENUMLOGFONTEX * lplf;
5952     NEWTEXTMETRICEX * lptm;
5953     int font_type;
5954     enumfont_t * lpef;
5955{
5956  HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
5957  FARPROC enum_font_families_ex
5958    = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
5959  /* We don't really expect EnumFontFamiliesEx to disappear once we
5960     get here, so don't bother handling it gracefully.  */
5961  if (enum_font_families_ex == NULL)
5962    error ("gdi32.dll has disappeared!");
5963  return enum_font_families_ex (lpef->hdc,
5964                                &lplf->elfLogFont,
5965                                (FONTENUMPROC) enum_fontex_cb2,
5966                                (LPARAM) lpef, 0);
5967}
5968
5969/* Interface to fontset handler. (adapted from mw32font.c in Meadow
5970   and xterm.c in Emacs 20.3) */
5971
5972static Lisp_Object w32_list_bdf_fonts (Lisp_Object pattern, int max_names)
5973{
5974  char *fontname, *ptnstr;
5975  Lisp_Object list, tem, newlist = Qnil;
5976  int n_fonts = 0;
5977
5978  list = Vw32_bdf_filename_alist;
5979  ptnstr = SDATA (pattern);
5980
5981  for ( ; CONSP (list); list = XCDR (list))
5982    {
5983      tem = XCAR (list);
5984      if (CONSP (tem))
5985        fontname = SDATA (XCAR (tem));
5986      else if (STRINGP (tem))
5987        fontname = SDATA (tem);
5988      else
5989        continue;
5990
5991      if (w32_font_match (fontname, ptnstr))
5992        {
5993          newlist = Fcons (XCAR (tem), newlist);
5994          n_fonts++;
5995          if (max_names >= 0 && n_fonts >= max_names)
5996            break;
5997        }
5998    }
5999
6000  return newlist;
6001}
6002
6003
6004/* Return a list of names of available fonts matching PATTERN on frame
6005   F.  If SIZE is not 0, it is the size (maximum bound width) of fonts
6006   to be listed.  Frame F NULL means we have not yet created any
6007   frame, which means we can't get proper size info, as we don't have
6008   a device context to use for GetTextMetrics.
6009   MAXNAMES sets a limit on how many fonts to match.  If MAXNAMES is
6010   negative, then all matching fonts are returned.  */
6011
6012Lisp_Object
6013w32_list_fonts (f, pattern, size, maxnames)
6014     struct frame *f;
6015     Lisp_Object pattern;
6016     int size;
6017     int maxnames;
6018{
6019  Lisp_Object patterns, key = Qnil, tem, tpat;
6020  Lisp_Object list = Qnil, newlist = Qnil, second_best = Qnil;
6021  struct w32_display_info *dpyinfo = &one_w32_display_info;
6022  int n_fonts = 0;
6023
6024  patterns = Fassoc (pattern, Valternate_fontname_alist);
6025  if (NILP (patterns))
6026    patterns = Fcons (pattern, Qnil);
6027
6028  for (; CONSP (patterns); patterns = XCDR (patterns))
6029    {
6030      enumfont_t ef;
6031      int codepage;
6032
6033      tpat = XCAR (patterns);
6034
6035      if (!STRINGP (tpat))
6036        continue;
6037
6038      /* Avoid expensive EnumFontFamilies functions if we are not
6039         going to be able to output one of these anyway. */
6040      codepage = w32_codepage_for_font (SDATA (tpat));
6041      if (codepage != CP_8BIT && codepage != CP_UNICODE
6042          && codepage != CP_DEFAULT && codepage != CP_UNKNOWN
6043	  && !IsValidCodePage(codepage))
6044        continue;
6045
6046      /* See if we cached the result for this particular query.
6047         The cache is an alist of the form:
6048           ((PATTERN (FONTNAME . WIDTH) ...) ...)
6049      */
6050      if (tem = XCDR (dpyinfo->name_list_element),
6051          !NILP (list = Fassoc (tpat, tem)))
6052        {
6053          list = Fcdr_safe (list);
6054          /* We have a cached list. Don't have to get the list again.  */
6055          goto label_cached;
6056        }
6057
6058      BLOCK_INPUT;
6059      /* At first, put PATTERN in the cache.  */
6060      ef.pattern = tpat;
6061      ef.list = Qnil;
6062      ef.numFonts = 0;
6063
6064      /* Use EnumFontFamiliesEx where it is available, as it knows
6065         about character sets.  Fall back to EnumFontFamilies for
6066         older versions of NT that don't support the 'Ex function.  */
6067      x_to_w32_font (SDATA (tpat), &ef.logfont);
6068      {
6069        LOGFONT font_match_pattern;
6070        HMODULE gdi32 = GetModuleHandle ("gdi32.dll");
6071        FARPROC enum_font_families_ex
6072          = GetProcAddress ( gdi32, "EnumFontFamiliesExA");
6073
6074        /* We do our own pattern matching so we can handle wildcards.  */
6075        font_match_pattern.lfFaceName[0] = 0;
6076        font_match_pattern.lfPitchAndFamily = 0;
6077        /* We can use the charset, because if it is a wildcard it will
6078           be DEFAULT_CHARSET anyway.  */
6079        font_match_pattern.lfCharSet = ef.logfont.lfCharSet;
6080
6081        ef.hdc = GetDC (dpyinfo->root_window);
6082
6083        if (enum_font_families_ex)
6084          enum_font_families_ex (ef.hdc,
6085                                 &font_match_pattern,
6086                                 (FONTENUMPROC) enum_fontex_cb1,
6087                                 (LPARAM) &ef, 0);
6088        else
6089          EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1,
6090                            (LPARAM)&ef);
6091
6092        ReleaseDC (dpyinfo->root_window, ef.hdc);
6093      }
6094
6095      UNBLOCK_INPUT;
6096      list = ef.list;
6097
6098      /* Make a list of the fonts we got back.
6099         Store that in the font cache for the display. */
6100      XSETCDR (dpyinfo->name_list_element,
6101	       Fcons (Fcons (tpat, list),
6102		      XCDR (dpyinfo->name_list_element)));
6103
6104    label_cached:
6105      if (NILP (list)) continue; /* Try the remaining alternatives.  */
6106
6107      newlist = second_best = Qnil;
6108
6109      /* Make a list of the fonts that have the right width.  */
6110      for (; CONSP (list); list = XCDR (list))
6111        {
6112          int found_size;
6113          tem = XCAR (list);
6114
6115          if (!CONSP (tem))
6116            continue;
6117          if (NILP (XCAR (tem)))
6118            continue;
6119          if (!size)
6120            {
6121              newlist = Fcons (XCAR (tem), newlist);
6122              n_fonts++;
6123              if (maxnames >= 0 && n_fonts >= maxnames)
6124                break;
6125              else
6126                continue;
6127            }
6128          if (!INTEGERP (XCDR (tem)))
6129            {
6130              /* Since we don't yet know the size of the font, we must
6131                 load it and try GetTextMetrics.  */
6132              W32FontStruct thisinfo;
6133              LOGFONT lf;
6134              HDC hdc;
6135              HANDLE oldobj;
6136
6137              if (!x_to_w32_font (SDATA (XCAR (tem)), &lf))
6138                continue;
6139
6140              BLOCK_INPUT;
6141              thisinfo.bdf = NULL;
6142              thisinfo.hfont = CreateFontIndirect (&lf);
6143              if (thisinfo.hfont == NULL)
6144                continue;
6145
6146              hdc = GetDC (dpyinfo->root_window);
6147              oldobj = SelectObject (hdc, thisinfo.hfont);
6148              if (GetTextMetrics (hdc, &thisinfo.tm))
6149                XSETCDR (tem, make_number (FONT_WIDTH (&thisinfo)));
6150              else
6151                XSETCDR (tem, make_number (0));
6152              SelectObject (hdc, oldobj);
6153              ReleaseDC (dpyinfo->root_window, hdc);
6154              DeleteObject(thisinfo.hfont);
6155              UNBLOCK_INPUT;
6156            }
6157          found_size = XINT (XCDR (tem));
6158          if (found_size == size)
6159            {
6160              newlist = Fcons (XCAR (tem), newlist);
6161              n_fonts++;
6162              if (maxnames >= 0 && n_fonts >= maxnames)
6163                break;
6164            }
6165          /* keep track of the closest matching size in case
6166             no exact match is found.  */
6167          else if (found_size > 0)
6168            {
6169              if (NILP (second_best))
6170                second_best = tem;
6171
6172              else if (found_size < size)
6173                {
6174                  if (XINT (XCDR (second_best)) > size
6175                      || XINT (XCDR (second_best)) < found_size)
6176                    second_best = tem;
6177                }
6178              else
6179                {
6180                  if (XINT (XCDR (second_best)) > size
6181                      && XINT (XCDR (second_best)) >
6182                      found_size)
6183                    second_best = tem;
6184                }
6185            }
6186        }
6187
6188      if (!NILP (newlist))
6189        break;
6190      else if (!NILP (second_best))
6191        {
6192          newlist = Fcons (XCAR (second_best), Qnil);
6193          break;
6194        }
6195    }
6196
6197  /* Include any bdf fonts.  */
6198  if (n_fonts < maxnames || maxnames < 0)
6199  {
6200    Lisp_Object combined[2];
6201    combined[0] = w32_list_bdf_fonts (pattern, maxnames - n_fonts);
6202    combined[1] = newlist;
6203    newlist = Fnconc(2, combined);
6204  }
6205
6206  return newlist;
6207}
6208
6209
6210/* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
6211struct font_info *
6212w32_get_font_info (f, font_idx)
6213     FRAME_PTR f;
6214     int font_idx;
6215{
6216  return (FRAME_W32_FONT_TABLE (f) + font_idx);
6217}
6218
6219
6220struct font_info*
6221w32_query_font (struct frame *f, char *fontname)
6222{
6223  int i;
6224  struct font_info *pfi;
6225
6226  pfi = FRAME_W32_FONT_TABLE (f);
6227
6228  for (i = 0; i < one_w32_display_info.n_fonts ;i++, pfi++)
6229    {
6230      if (stricmp(pfi->name, fontname) == 0) return pfi;
6231    }
6232
6233  return NULL;
6234}
6235
6236/* Find a CCL program for a font specified by FONTP, and set the member
6237 `encoder' of the structure.  */
6238
6239void
6240w32_find_ccl_program (fontp)
6241     struct font_info *fontp;
6242{
6243  Lisp_Object list, elt;
6244
6245  for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6246    {
6247      elt = XCAR (list);
6248      if (CONSP (elt)
6249	  && STRINGP (XCAR (elt))
6250	  && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6251	      >= 0))
6252	break;
6253    }
6254  if (! NILP (list))
6255    {
6256      struct ccl_program *ccl
6257	= (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6258
6259      if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6260	xfree (ccl);
6261      else
6262	fontp->font_encoder = ccl;
6263    }
6264}
6265
6266/* directory-files from dired.c.  */
6267Lisp_Object Fdirectory_files P_((Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object));
6268
6269
6270/* Find BDF files in a specified directory.  (use GCPRO when calling,
6271   as this calls lisp to get a directory listing).  */
6272static Lisp_Object
6273w32_find_bdf_fonts_in_dir (Lisp_Object directory)
6274{
6275  Lisp_Object filelist, list = Qnil;
6276  char fontname[100];
6277
6278  if (!STRINGP(directory))
6279    return Qnil;
6280
6281  filelist = Fdirectory_files (directory, Qt,
6282			       build_string (".*\\.[bB][dD][fF]"), Qt);
6283
6284  for ( ; CONSP(filelist); filelist = XCDR (filelist))
6285    {
6286      Lisp_Object filename = XCAR (filelist);
6287      if (w32_BDF_to_x_font (SDATA (filename), fontname, 100))
6288          store_in_alist (&list, build_string (fontname), filename);
6289    }
6290  return list;
6291}
6292
6293DEFUN ("w32-find-bdf-fonts", Fw32_find_bdf_fonts, Sw32_find_bdf_fonts,
6294       1, 1, 0,
6295       doc: /* Return a list of BDF fonts in DIRECTORY.
6296The list is suitable for appending to `w32-bdf-filename-alist'.
6297Fonts which do not contain an xlfd description will not be included
6298in the list.  DIRECTORY may be a list of directories.  */)
6299     (directory)
6300     Lisp_Object directory;
6301{
6302  Lisp_Object list = Qnil;
6303  struct gcpro gcpro1, gcpro2;
6304
6305  if (!CONSP (directory))
6306    return w32_find_bdf_fonts_in_dir (directory);
6307
6308  for ( ; CONSP (directory); directory = XCDR (directory))
6309    {
6310      Lisp_Object pair[2];
6311      pair[0] = list;
6312      pair[1] = Qnil;
6313      GCPRO2 (directory, list);
6314      pair[1] = w32_find_bdf_fonts_in_dir( XCAR (directory) );
6315      list = Fnconc( 2, pair );
6316      UNGCPRO;
6317    }
6318  return list;
6319}
6320
6321
6322DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
6323       doc: /* Internal function called by `color-defined-p', which see.  */)
6324  (color, frame)
6325     Lisp_Object color, frame;
6326{
6327  XColor foo;
6328  FRAME_PTR f = check_x_frame (frame);
6329
6330  CHECK_STRING (color);
6331
6332  if (w32_defined_color (f, SDATA (color), &foo, 0))
6333    return Qt;
6334  else
6335    return Qnil;
6336}
6337
6338DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
6339       doc: /* Internal function called by `color-values', which see.  */)
6340  (color, frame)
6341     Lisp_Object color, frame;
6342{
6343  XColor foo;
6344  FRAME_PTR f = check_x_frame (frame);
6345
6346  CHECK_STRING (color);
6347
6348  if (w32_defined_color (f, SDATA (color), &foo, 0))
6349    return list3 (make_number ((GetRValue (foo.pixel) << 8)
6350			       | GetRValue (foo.pixel)),
6351		  make_number ((GetGValue (foo.pixel) << 8)
6352			       | GetGValue (foo.pixel)),
6353		  make_number ((GetBValue (foo.pixel) << 8)
6354			       | GetBValue (foo.pixel)));
6355  else
6356    return Qnil;
6357}
6358
6359DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
6360       doc: /* Internal function called by `display-color-p', which see.  */)
6361  (display)
6362     Lisp_Object display;
6363{
6364  struct w32_display_info *dpyinfo = check_x_display_info (display);
6365
6366  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 2)
6367    return Qnil;
6368
6369  return Qt;
6370}
6371
6372DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
6373       Sx_display_grayscale_p, 0, 1, 0,
6374       doc: /* Return t if DISPLAY supports shades of gray.
6375Note that color displays do support shades of gray.
6376The optional argument DISPLAY specifies which display to ask about.
6377DISPLAY should be either a frame or a display name (a string).
6378If omitted or nil, that stands for the selected frame's display.  */)
6379  (display)
6380     Lisp_Object display;
6381{
6382  struct w32_display_info *dpyinfo = check_x_display_info (display);
6383
6384  if ((dpyinfo->n_planes * dpyinfo->n_cbits) <= 1)
6385    return Qnil;
6386
6387  return Qt;
6388}
6389
6390DEFUN ("x-display-pixel-width", Fx_display_pixel_width,
6391       Sx_display_pixel_width, 0, 1, 0,
6392       doc: /* Returns the width in pixels of DISPLAY.
6393The optional argument DISPLAY specifies which display to ask about.
6394DISPLAY should be either a frame or a display name (a string).
6395If omitted or nil, that stands for the selected frame's display.  */)
6396  (display)
6397     Lisp_Object display;
6398{
6399  struct w32_display_info *dpyinfo = check_x_display_info (display);
6400
6401  return make_number (dpyinfo->width);
6402}
6403
6404DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
6405       Sx_display_pixel_height, 0, 1, 0,
6406       doc: /* Returns the height in pixels of DISPLAY.
6407The optional argument DISPLAY specifies which display to ask about.
6408DISPLAY should be either a frame or a display name (a string).
6409If omitted or nil, that stands for the selected frame's display.  */)
6410  (display)
6411     Lisp_Object display;
6412{
6413  struct w32_display_info *dpyinfo = check_x_display_info (display);
6414
6415  return make_number (dpyinfo->height);
6416}
6417
6418DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
6419       0, 1, 0,
6420       doc: /* Returns the number of bitplanes of DISPLAY.
6421The optional argument DISPLAY specifies which display to ask about.
6422DISPLAY should be either a frame or a display name (a string).
6423If omitted or nil, that stands for the selected frame's display.  */)
6424  (display)
6425     Lisp_Object display;
6426{
6427  struct w32_display_info *dpyinfo = check_x_display_info (display);
6428
6429  return make_number (dpyinfo->n_planes * dpyinfo->n_cbits);
6430}
6431
6432DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
6433       0, 1, 0,
6434       doc: /* Returns the number of color cells of DISPLAY.
6435The optional argument DISPLAY specifies which display to ask about.
6436DISPLAY should be either a frame or a display name (a string).
6437If omitted or nil, that stands for the selected frame's display.  */)
6438  (display)
6439     Lisp_Object display;
6440{
6441  struct w32_display_info *dpyinfo = check_x_display_info (display);
6442  HDC hdc;
6443  int cap;
6444
6445  hdc = GetDC (dpyinfo->root_window);
6446  if (dpyinfo->has_palette)
6447    cap = GetDeviceCaps (hdc, SIZEPALETTE);
6448  else
6449    cap = GetDeviceCaps (hdc, NUMCOLORS);
6450
6451  /* We force 24+ bit depths to 24-bit, both to prevent an overflow
6452     and because probably is more meaningful on Windows anyway */
6453  if (cap < 0)
6454    cap = 1 << min(dpyinfo->n_planes * dpyinfo->n_cbits, 24);
6455
6456  ReleaseDC (dpyinfo->root_window, hdc);
6457
6458  return make_number (cap);
6459}
6460
6461DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
6462       Sx_server_max_request_size,
6463       0, 1, 0,
6464       doc: /* Returns the maximum request size of the server of DISPLAY.
6465The optional argument DISPLAY specifies which display to ask about.
6466DISPLAY should be either a frame or a display name (a string).
6467If omitted or nil, that stands for the selected frame's display.  */)
6468  (display)
6469     Lisp_Object display;
6470{
6471  struct w32_display_info *dpyinfo = check_x_display_info (display);
6472
6473  return make_number (1);
6474}
6475
6476DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
6477       doc: /* Returns the "vendor ID" string of the W32 system (Microsoft).
6478The optional argument DISPLAY specifies which display to ask about.
6479DISPLAY should be either a frame or a display name (a string).
6480If omitted or nil, that stands for the selected frame's display.  */)
6481  (display)
6482     Lisp_Object display;
6483{
6484  return build_string ("Microsoft Corp.");
6485}
6486
6487DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
6488       doc: /* Returns the version numbers of the server of DISPLAY.
6489The value is a list of three integers: the major and minor
6490version numbers of the X Protocol in use, and the distributor-specific release
6491number.  See also the function `x-server-vendor'.
6492
6493The optional argument DISPLAY specifies which display to ask about.
6494DISPLAY should be either a frame or a display name (a string).
6495If omitted or nil, that stands for the selected frame's display.  */)
6496  (display)
6497     Lisp_Object display;
6498{
6499  return Fcons (make_number (w32_major_version),
6500		Fcons (make_number (w32_minor_version),
6501		       Fcons (make_number (w32_build_number), Qnil)));
6502}
6503
6504DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
6505       doc: /* Returns the number of screens on the server of DISPLAY.
6506The optional argument DISPLAY specifies which display to ask about.
6507DISPLAY should be either a frame or a display name (a string).
6508If omitted or nil, that stands for the selected frame's display.  */)
6509  (display)
6510     Lisp_Object display;
6511{
6512  return make_number (1);
6513}
6514
6515DEFUN ("x-display-mm-height", Fx_display_mm_height,
6516       Sx_display_mm_height, 0, 1, 0,
6517       doc: /* Returns the height in millimeters of DISPLAY.
6518The optional argument DISPLAY specifies which display to ask about.
6519DISPLAY should be either a frame or a display name (a string).
6520If omitted or nil, that stands for the selected frame's display.  */)
6521  (display)
6522     Lisp_Object display;
6523{
6524  struct w32_display_info *dpyinfo = check_x_display_info (display);
6525  HDC hdc;
6526  int cap;
6527
6528  hdc = GetDC (dpyinfo->root_window);
6529
6530  cap = GetDeviceCaps (hdc, VERTSIZE);
6531
6532  ReleaseDC (dpyinfo->root_window, hdc);
6533
6534  return make_number (cap);
6535}
6536
6537DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
6538       doc: /* Returns the width in millimeters of DISPLAY.
6539The optional argument DISPLAY specifies which display to ask about.
6540DISPLAY should be either a frame or a display name (a string).
6541If omitted or nil, that stands for the selected frame's display.  */)
6542  (display)
6543     Lisp_Object display;
6544{
6545  struct w32_display_info *dpyinfo = check_x_display_info (display);
6546
6547  HDC hdc;
6548  int cap;
6549
6550  hdc = GetDC (dpyinfo->root_window);
6551
6552  cap = GetDeviceCaps (hdc, HORZSIZE);
6553
6554  ReleaseDC (dpyinfo->root_window, hdc);
6555
6556  return make_number (cap);
6557}
6558
6559DEFUN ("x-display-backing-store", Fx_display_backing_store,
6560       Sx_display_backing_store, 0, 1, 0,
6561       doc: /* Returns an indication of whether DISPLAY does backing store.
6562The value may be `always', `when-mapped', or `not-useful'.
6563The optional argument DISPLAY specifies which display to ask about.
6564DISPLAY should be either a frame or a display name (a string).
6565If omitted or nil, that stands for the selected frame's display.  */)
6566  (display)
6567     Lisp_Object display;
6568{
6569  return intern ("not-useful");
6570}
6571
6572DEFUN ("x-display-visual-class", Fx_display_visual_class,
6573       Sx_display_visual_class, 0, 1, 0,
6574       doc: /* Returns the visual class of DISPLAY.
6575The value is one of the symbols `static-gray', `gray-scale',
6576`static-color', `pseudo-color', `true-color', or `direct-color'.
6577
6578The optional argument DISPLAY specifies which display to ask about.
6579DISPLAY should be either a frame or a display name (a string).
6580If omitted or nil, that stands for the selected frame's display.  */)
6581	(display)
6582     Lisp_Object display;
6583{
6584  struct w32_display_info *dpyinfo = check_x_display_info (display);
6585  Lisp_Object result = Qnil;
6586
6587  if (dpyinfo->has_palette)
6588      result = intern ("pseudo-color");
6589  else if (dpyinfo->n_planes * dpyinfo->n_cbits == 1)
6590      result = intern ("static-grey");
6591  else if (dpyinfo->n_planes * dpyinfo->n_cbits == 4)
6592      result = intern ("static-color");
6593  else if (dpyinfo->n_planes * dpyinfo->n_cbits > 8)
6594      result = intern ("true-color");
6595
6596  return result;
6597}
6598
6599DEFUN ("x-display-save-under", Fx_display_save_under,
6600       Sx_display_save_under, 0, 1, 0,
6601       doc: /* Returns t if DISPLAY supports the save-under feature.
6602The optional argument DISPLAY specifies which display to ask about.
6603DISPLAY should be either a frame or a display name (a string).
6604If omitted or nil, that stands for the selected frame's display.  */)
6605  (display)
6606     Lisp_Object display;
6607{
6608  return Qnil;
6609}
6610
6611int
6612x_pixel_width (f)
6613     register struct frame *f;
6614{
6615  return FRAME_PIXEL_WIDTH (f);
6616}
6617
6618int
6619x_pixel_height (f)
6620     register struct frame *f;
6621{
6622  return FRAME_PIXEL_HEIGHT (f);
6623}
6624
6625int
6626x_char_width (f)
6627     register struct frame *f;
6628{
6629  return FRAME_COLUMN_WIDTH (f);
6630}
6631
6632int
6633x_char_height (f)
6634     register struct frame *f;
6635{
6636  return FRAME_LINE_HEIGHT (f);
6637}
6638
6639int
6640x_screen_planes (f)
6641     register struct frame *f;
6642{
6643  return FRAME_W32_DISPLAY_INFO (f)->n_planes;
6644}
6645
6646/* Return the display structure for the display named NAME.
6647   Open a new connection if necessary.  */
6648
6649struct w32_display_info *
6650x_display_info_for_name (name)
6651     Lisp_Object name;
6652{
6653  Lisp_Object names;
6654  struct w32_display_info *dpyinfo;
6655
6656  CHECK_STRING (name);
6657
6658  for (dpyinfo = &one_w32_display_info, names = w32_display_name_list;
6659       dpyinfo;
6660       dpyinfo = dpyinfo->next, names = XCDR (names))
6661    {
6662      Lisp_Object tem;
6663      tem = Fstring_equal (XCAR (XCAR (names)), name);
6664      if (!NILP (tem))
6665	return dpyinfo;
6666    }
6667
6668  /* Use this general default value to start with.  */
6669  Vx_resource_name = Vinvocation_name;
6670
6671  validate_x_resource_name ();
6672
6673  dpyinfo = w32_term_init (name, (unsigned char *)0,
6674			     (char *) SDATA (Vx_resource_name));
6675
6676  if (dpyinfo == 0)
6677    error ("Cannot connect to server %s", SDATA (name));
6678
6679  w32_in_use = 1;
6680  XSETFASTINT (Vwindow_system_version, 3);
6681
6682  return dpyinfo;
6683}
6684
6685DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
6686       1, 3, 0, doc: /* Open a connection to a server.
6687DISPLAY is the name of the display to connect to.
6688Optional second arg XRM-STRING is a string of resources in xrdb format.
6689If the optional third arg MUST-SUCCEED is non-nil,
6690terminate Emacs if we can't open the connection.  */)
6691  (display, xrm_string, must_succeed)
6692     Lisp_Object display, xrm_string, must_succeed;
6693{
6694  unsigned char *xrm_option;
6695  struct w32_display_info *dpyinfo;
6696
6697  /* If initialization has already been done, return now to avoid
6698     overwriting critical parts of one_w32_display_info.  */
6699  if (w32_in_use)
6700    return Qnil;
6701
6702  CHECK_STRING (display);
6703  if (! NILP (xrm_string))
6704    CHECK_STRING (xrm_string);
6705
6706  if (! EQ (Vwindow_system, intern ("w32")))
6707    error ("Not using Microsoft Windows");
6708
6709  /* Allow color mapping to be defined externally; first look in user's
6710     HOME directory, then in Emacs etc dir for a file called rgb.txt. */
6711  {
6712    Lisp_Object color_file;
6713    struct gcpro gcpro1;
6714
6715    color_file = build_string("~/rgb.txt");
6716
6717    GCPRO1 (color_file);
6718
6719    if (NILP (Ffile_readable_p (color_file)))
6720      color_file =
6721	Fexpand_file_name (build_string ("rgb.txt"),
6722			   Fsymbol_value (intern ("data-directory")));
6723
6724    Vw32_color_map = Fw32_load_color_file (color_file);
6725
6726    UNGCPRO;
6727  }
6728  if (NILP (Vw32_color_map))
6729    Vw32_color_map = Fw32_default_color_map ();
6730
6731  /* Merge in system logical colors.  */
6732  add_system_logical_colors_to_map (&Vw32_color_map);
6733
6734  if (! NILP (xrm_string))
6735    xrm_option = (unsigned char *) SDATA (xrm_string);
6736  else
6737    xrm_option = (unsigned char *) 0;
6738
6739  /* Use this general default value to start with.  */
6740  /* First remove .exe suffix from invocation-name - it looks ugly. */
6741  {
6742    char basename[ MAX_PATH ], *str;
6743
6744    strcpy (basename, SDATA (Vinvocation_name));
6745    str = strrchr (basename, '.');
6746    if (str) *str = 0;
6747    Vinvocation_name = build_string (basename);
6748  }
6749  Vx_resource_name = Vinvocation_name;
6750
6751  validate_x_resource_name ();
6752
6753  /* This is what opens the connection and sets x_current_display.
6754     This also initializes many symbols, such as those used for input.  */
6755  dpyinfo = w32_term_init (display, xrm_option,
6756			     (char *) SDATA (Vx_resource_name));
6757
6758  if (dpyinfo == 0)
6759    {
6760      if (!NILP (must_succeed))
6761	fatal ("Cannot connect to server %s.\n",
6762	       SDATA (display));
6763      else
6764	error ("Cannot connect to server %s", SDATA (display));
6765    }
6766
6767  w32_in_use = 1;
6768
6769  XSETFASTINT (Vwindow_system_version, 3);
6770  return Qnil;
6771}
6772
6773DEFUN ("x-close-connection", Fx_close_connection,
6774       Sx_close_connection, 1, 1, 0,
6775       doc: /* Close the connection to DISPLAY's server.
6776For DISPLAY, specify either a frame or a display name (a string).
6777If DISPLAY is nil, that stands for the selected frame's display.  */)
6778  (display)
6779  Lisp_Object display;
6780{
6781  struct w32_display_info *dpyinfo = check_x_display_info (display);
6782  int i;
6783
6784  if (dpyinfo->reference_count > 0)
6785    error ("Display still has frames on it");
6786
6787  BLOCK_INPUT;
6788  /* Free the fonts in the font table.  */
6789  for (i = 0; i < dpyinfo->n_fonts; i++)
6790    if (dpyinfo->font_table[i].name)
6791      {
6792        if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
6793          xfree (dpyinfo->font_table[i].full_name);
6794        xfree (dpyinfo->font_table[i].name);
6795        w32_unload_font (dpyinfo, dpyinfo->font_table[i].font);
6796      }
6797  x_destroy_all_bitmaps (dpyinfo);
6798
6799  x_delete_display (dpyinfo);
6800  UNBLOCK_INPUT;
6801
6802  return Qnil;
6803}
6804
6805DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
6806       doc: /* Return the list of display names that Emacs has connections to.  */)
6807  ()
6808{
6809  Lisp_Object tail, result;
6810
6811  result = Qnil;
6812  for (tail = w32_display_name_list; ! NILP (tail); tail = XCDR (tail))
6813    result = Fcons (XCAR (XCAR (tail)), result);
6814
6815  return result;
6816}
6817
6818DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0,
6819       doc: /* This is a noop on W32 systems.  */)
6820     (on, display)
6821     Lisp_Object display, on;
6822{
6823  return Qnil;
6824}
6825
6826
6827
6828/***********************************************************************
6829                           Window properties
6830 ***********************************************************************/
6831
6832DEFUN ("x-change-window-property", Fx_change_window_property,
6833       Sx_change_window_property, 2, 6, 0,
6834       doc: /* Change window property PROP to VALUE on the X window of FRAME.
6835VALUE may be a string or a list of conses, numbers and/or strings.
6836If an element in the list is a string, it is converted to
6837an Atom and the value of the Atom is used.  If an element is a cons,
6838it is converted to a 32 bit number where the car is the 16 top bits and the
6839cdr is the lower 16 bits.
6840FRAME nil or omitted means use the selected frame.
6841If TYPE is given and non-nil, it is the name of the type of VALUE.
6842If TYPE is not given or nil, the type is STRING.
6843FORMAT gives the size in bits of each element if VALUE is a list.
6844It must be one of 8, 16 or 32.
6845If VALUE is a string or FORMAT is nil or not given, FORMAT defaults to 8.
6846If OUTER_P is non-nil, the property is changed for the outer X window of
6847FRAME.  Default is to change on the edit X window.
6848
6849Value is VALUE.  */)
6850     (prop, value, frame, type, format, outer_p)
6851     Lisp_Object prop, value, frame, type, format, outer_p;
6852{
6853#if 0 /* TODO : port window properties to W32 */
6854  struct frame *f = check_x_frame (frame);
6855  Atom prop_atom;
6856
6857  CHECK_STRING (prop);
6858  CHECK_STRING (value);
6859
6860  BLOCK_INPUT;
6861  prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
6862  XChangeProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
6863		   prop_atom, XA_STRING, 8, PropModeReplace,
6864		   SDATA (value), SCHARS (value));
6865
6866  /* Make sure the property is set when we return.  */
6867  XFlush (FRAME_W32_DISPLAY (f));
6868  UNBLOCK_INPUT;
6869
6870#endif /* TODO */
6871
6872  return value;
6873}
6874
6875
6876DEFUN ("x-delete-window-property", Fx_delete_window_property,
6877       Sx_delete_window_property, 1, 2, 0,
6878       doc: /* Remove window property PROP from X window of FRAME.
6879FRAME nil or omitted means use the selected frame.  Value is PROP.  */)
6880  (prop, frame)
6881     Lisp_Object prop, frame;
6882{
6883#if 0 /* TODO : port window properties to W32 */
6884
6885  struct frame *f = check_x_frame (frame);
6886  Atom prop_atom;
6887
6888  CHECK_STRING (prop);
6889  BLOCK_INPUT;
6890  prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
6891  XDeleteProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f), prop_atom);
6892
6893  /* Make sure the property is removed when we return.  */
6894  XFlush (FRAME_W32_DISPLAY (f));
6895  UNBLOCK_INPUT;
6896#endif  /* TODO */
6897
6898  return prop;
6899}
6900
6901
6902DEFUN ("x-window-property", Fx_window_property, Sx_window_property,
6903       1, 2, 0,
6904       doc: /* Value is the value of window property PROP on FRAME.
6905If FRAME is nil or omitted, use the selected frame.  Value is nil
6906if FRAME hasn't a property with name PROP or if PROP has no string
6907value.  */)
6908  (prop, frame)
6909     Lisp_Object prop, frame;
6910{
6911#if 0 /* TODO : port window properties to W32 */
6912
6913  struct frame *f = check_x_frame (frame);
6914  Atom prop_atom;
6915  int rc;
6916  Lisp_Object prop_value = Qnil;
6917  char *tmp_data = NULL;
6918  Atom actual_type;
6919  int actual_format;
6920  unsigned long actual_size, bytes_remaining;
6921
6922  CHECK_STRING (prop);
6923  BLOCK_INPUT;
6924  prop_atom = XInternAtom (FRAME_W32_DISPLAY (f), SDATA (prop), False);
6925  rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
6926			   prop_atom, 0, 0, False, XA_STRING,
6927			   &actual_type, &actual_format, &actual_size,
6928			   &bytes_remaining, (unsigned char **) &tmp_data);
6929  if (rc == Success)
6930    {
6931      int size = bytes_remaining;
6932
6933      XFree (tmp_data);
6934      tmp_data = NULL;
6935
6936      rc = XGetWindowProperty (FRAME_W32_DISPLAY (f), FRAME_W32_WINDOW (f),
6937			       prop_atom, 0, bytes_remaining,
6938			       False, XA_STRING,
6939			       &actual_type, &actual_format,
6940			       &actual_size, &bytes_remaining,
6941			       (unsigned char **) &tmp_data);
6942      if (rc == Success)
6943	prop_value = make_string (tmp_data, size);
6944
6945      XFree (tmp_data);
6946    }
6947
6948  UNBLOCK_INPUT;
6949
6950  return prop_value;
6951
6952#endif /* TODO */
6953  return Qnil;
6954}
6955
6956
6957
6958/***********************************************************************
6959				Busy cursor
6960 ***********************************************************************/
6961
6962/* If non-null, an asynchronous timer that, when it expires, displays
6963   an hourglass cursor on all frames.  */
6964
6965static struct atimer *hourglass_atimer;
6966
6967/* Non-zero means an hourglass cursor is currently shown.  */
6968
6969static int hourglass_shown_p;
6970
6971/* Number of seconds to wait before displaying an hourglass cursor.  */
6972
6973static Lisp_Object Vhourglass_delay;
6974
6975/* Default number of seconds to wait before displaying an hourglass
6976   cursor.  */
6977
6978#define DEFAULT_HOURGLASS_DELAY 1
6979
6980/* Function prototypes.  */
6981
6982static void show_hourglass P_ ((struct atimer *));
6983static void hide_hourglass P_ ((void));
6984
6985
6986/* Cancel a currently active hourglass timer, and start a new one.  */
6987
6988void
6989start_hourglass ()
6990{
6991#if 0 /* TODO: cursor shape changes.  */
6992  EMACS_TIME delay;
6993  int secs, usecs = 0;
6994
6995  cancel_hourglass ();
6996
6997  if (INTEGERP (Vhourglass_delay)
6998      && XINT (Vhourglass_delay) > 0)
6999    secs = XFASTINT (Vhourglass_delay);
7000  else if (FLOATP (Vhourglass_delay)
7001	   && XFLOAT_DATA (Vhourglass_delay) > 0)
7002    {
7003      Lisp_Object tem;
7004      tem = Ftruncate (Vhourglass_delay, Qnil);
7005      secs = XFASTINT (tem);
7006      usecs = (XFLOAT_DATA (Vhourglass_delay) - secs) * 1000000;
7007    }
7008  else
7009    secs = DEFAULT_HOURGLASS_DELAY;
7010
7011  EMACS_SET_SECS_USECS (delay, secs, usecs);
7012  hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
7013				   show_hourglass, NULL);
7014#endif
7015}
7016
7017
7018/* Cancel the hourglass cursor timer if active, hide an hourglass
7019   cursor if shown.  */
7020
7021void
7022cancel_hourglass ()
7023{
7024  if (hourglass_atimer)
7025    {
7026      cancel_atimer (hourglass_atimer);
7027      hourglass_atimer = NULL;
7028    }
7029
7030  if (hourglass_shown_p)
7031    hide_hourglass ();
7032}
7033
7034
7035/* Timer function of hourglass_atimer.  TIMER is equal to
7036   hourglass_atimer.
7037
7038   Display an hourglass cursor on all frames by mapping the frames'
7039   hourglass_window.  Set the hourglass_p flag in the frames'
7040   output_data.x structure to indicate that an hourglass cursor is
7041   shown on the frames.  */
7042
7043static void
7044show_hourglass (timer)
7045     struct atimer *timer;
7046{
7047#if 0  /* TODO: cursor shape changes.  */
7048  /* The timer implementation will cancel this timer automatically
7049     after this function has run.  Set hourglass_atimer to null
7050     so that we know the timer doesn't have to be canceled.  */
7051  hourglass_atimer = NULL;
7052
7053  if (!hourglass_shown_p)
7054    {
7055      Lisp_Object rest, frame;
7056
7057      BLOCK_INPUT;
7058
7059      FOR_EACH_FRAME (rest, frame)
7060	if (FRAME_W32_P (XFRAME (frame)))
7061	  {
7062	    struct frame *f = XFRAME (frame);
7063
7064	    f->output_data.w32->hourglass_p = 1;
7065
7066	    if (!f->output_data.w32->hourglass_window)
7067	      {
7068		unsigned long mask = CWCursor;
7069		XSetWindowAttributes attrs;
7070
7071		attrs.cursor = f->output_data.w32->hourglass_cursor;
7072
7073		f->output_data.w32->hourglass_window
7074		  = XCreateWindow (FRAME_X_DISPLAY (f),
7075				   FRAME_OUTER_WINDOW (f),
7076				   0, 0, 32000, 32000, 0, 0,
7077				   InputOnly,
7078				   CopyFromParent,
7079				   mask, &attrs);
7080	      }
7081
7082	    XMapRaised (FRAME_X_DISPLAY (f),
7083			f->output_data.w32->hourglass_window);
7084	    XFlush (FRAME_X_DISPLAY (f));
7085	  }
7086
7087      hourglass_shown_p = 1;
7088      UNBLOCK_INPUT;
7089    }
7090#endif
7091}
7092
7093
7094/* Hide the hourglass cursor on all frames, if it is currently shown.  */
7095
7096static void
7097hide_hourglass ()
7098{
7099#if 0 /* TODO: cursor shape changes.  */
7100  if (hourglass_shown_p)
7101    {
7102      Lisp_Object rest, frame;
7103
7104      BLOCK_INPUT;
7105      FOR_EACH_FRAME (rest, frame)
7106	{
7107	  struct frame *f = XFRAME (frame);
7108
7109	  if (FRAME_W32_P (f)
7110	      /* Watch out for newly created frames.  */
7111	      && f->output_data.x->hourglass_window)
7112	    {
7113	      XUnmapWindow (FRAME_X_DISPLAY (f),
7114			    f->output_data.x->hourglass_window);
7115	      /* Sync here because XTread_socket looks at the
7116		 hourglass_p flag that is reset to zero below.  */
7117	      XSync (FRAME_X_DISPLAY (f), False);
7118	      f->output_data.x->hourglass_p = 0;
7119	    }
7120	}
7121
7122      hourglass_shown_p = 0;
7123      UNBLOCK_INPUT;
7124    }
7125#endif
7126}
7127
7128
7129
7130/***********************************************************************
7131				Tool tips
7132 ***********************************************************************/
7133
7134static Lisp_Object x_create_tip_frame P_ ((struct w32_display_info *,
7135					   Lisp_Object, Lisp_Object));
7136static void compute_tip_xy P_ ((struct frame *, Lisp_Object, Lisp_Object,
7137				Lisp_Object, int, int, int *, int *));
7138
7139/* The frame of a currently visible tooltip.  */
7140
7141Lisp_Object tip_frame;
7142
7143/* If non-nil, a timer started that hides the last tooltip when it
7144   fires.  */
7145
7146Lisp_Object tip_timer;
7147Window tip_window;
7148
7149/* If non-nil, a vector of 3 elements containing the last args
7150   with which x-show-tip was called.  See there.  */
7151
7152Lisp_Object last_show_tip_args;
7153
7154/* Maximum size for tooltips; a cons (COLUMNS . ROWS).  */
7155
7156Lisp_Object Vx_max_tooltip_size;
7157
7158
7159static Lisp_Object
7160unwind_create_tip_frame (frame)
7161     Lisp_Object frame;
7162{
7163  Lisp_Object deleted;
7164
7165  deleted = unwind_create_frame (frame);
7166  if (EQ (deleted, Qt))
7167    {
7168      tip_window = NULL;
7169      tip_frame = Qnil;
7170    }
7171
7172  return deleted;
7173}
7174
7175
7176/* Create a frame for a tooltip on the display described by DPYINFO.
7177   PARMS is a list of frame parameters.  TEXT is the string to
7178   display in the tip frame.  Value is the frame.
7179
7180   Note that functions called here, esp. x_default_parameter can
7181   signal errors, for instance when a specified color name is
7182   undefined.  We have to make sure that we're in a consistent state
7183   when this happens.  */
7184
7185static Lisp_Object
7186x_create_tip_frame (dpyinfo, parms, text)
7187     struct w32_display_info *dpyinfo;
7188     Lisp_Object parms, text;
7189{
7190  struct frame *f;
7191  Lisp_Object frame, tem;
7192  Lisp_Object name;
7193  long window_prompting = 0;
7194  int width, height;
7195  int count = SPECPDL_INDEX ();
7196  struct gcpro gcpro1, gcpro2, gcpro3;
7197  struct kboard *kb;
7198  int face_change_count_before = face_change_count;
7199  Lisp_Object buffer;
7200  struct buffer *old_buffer;
7201
7202  check_w32 ();
7203
7204  /* Use this general default value to start with until we know if
7205     this frame has a specified name.  */
7206  Vx_resource_name = Vinvocation_name;
7207
7208#ifdef MULTI_KBOARD
7209  kb = dpyinfo->kboard;
7210#else
7211  kb = &the_only_kboard;
7212#endif
7213
7214  /* Get the name of the frame to use for resource lookup.  */
7215  name = w32_get_arg (parms, Qname, "name", "Name", RES_TYPE_STRING);
7216  if (!STRINGP (name)
7217      && !EQ (name, Qunbound)
7218      && !NILP (name))
7219    error ("Invalid frame name--not a string or nil");
7220  Vx_resource_name = name;
7221
7222  frame = Qnil;
7223  GCPRO3 (parms, name, frame);
7224  /* Make a frame without minibuffer nor mode-line.  */
7225  f = make_frame (0);
7226  f->wants_modeline = 0;
7227  XSETFRAME (frame, f);
7228
7229  buffer = Fget_buffer_create (build_string (" *tip*"));
7230  Fset_window_buffer (FRAME_ROOT_WINDOW (f), buffer, Qnil);
7231  old_buffer = current_buffer;
7232  set_buffer_internal_1 (XBUFFER (buffer));
7233  current_buffer->truncate_lines = Qnil;
7234  specbind (Qinhibit_read_only, Qt);
7235  specbind (Qinhibit_modification_hooks, Qt);
7236  Ferase_buffer ();
7237  Finsert (1, &text);
7238  set_buffer_internal_1 (old_buffer);
7239
7240  FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
7241  record_unwind_protect (unwind_create_tip_frame, frame);
7242
7243  /* By setting the output method, we're essentially saying that
7244     the frame is live, as per FRAME_LIVE_P.  If we get a signal
7245     from this point on, x_destroy_window might screw up reference
7246     counts etc.  */
7247  f->output_method = output_w32;
7248  f->output_data.w32 =
7249    (struct w32_output *) xmalloc (sizeof (struct w32_output));
7250  bzero (f->output_data.w32, sizeof (struct w32_output));
7251
7252  FRAME_FONTSET (f)  = -1;
7253  f->icon_name = Qnil;
7254
7255#if 0 /* GLYPH_DEBUG TODO: image support.  */
7256  image_cache_refcount = FRAME_X_IMAGE_CACHE (f)->refcount;
7257  dpyinfo_refcount = dpyinfo->reference_count;
7258#endif /* GLYPH_DEBUG */
7259#ifdef MULTI_KBOARD
7260  FRAME_KBOARD (f) = kb;
7261#endif
7262  f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
7263  f->output_data.w32->explicit_parent = 0;
7264
7265  /* Set the name; the functions to which we pass f expect the name to
7266     be set.  */
7267  if (EQ (name, Qunbound) || NILP (name))
7268    {
7269      f->name = build_string (dpyinfo->w32_id_name);
7270      f->explicit_name = 0;
7271    }
7272  else
7273    {
7274      f->name = name;
7275      f->explicit_name = 1;
7276      /* use the frame's title when getting resources for this frame.  */
7277      specbind (Qx_resource_name, name);
7278    }
7279
7280  /* Extract the window parameters from the supplied values
7281     that are needed to determine window geometry.  */
7282  {
7283    Lisp_Object font;
7284
7285    font = w32_get_arg (parms, Qfont, "font", "Font", RES_TYPE_STRING);
7286
7287    BLOCK_INPUT;
7288    /* First, try whatever font the caller has specified.  */
7289    if (STRINGP (font))
7290      {
7291	tem = Fquery_fontset (font, Qnil);
7292	if (STRINGP (tem))
7293	  font = x_new_fontset (f, SDATA (tem));
7294	else
7295	  font = x_new_font (f, SDATA (font));
7296      }
7297
7298    /* Try out a font which we hope has bold and italic variations.  */
7299    if (!STRINGP (font))
7300      font = x_new_font (f, "-*-Courier New-normal-r-*-*-*-100-*-*-c-*-iso8859-1");
7301    if (! STRINGP (font))
7302      font = x_new_font (f, "-*-Courier-normal-r-*-*-13-*-*-*-c-*-iso8859-1");
7303    /* If those didn't work, look for something which will at least work.  */
7304    if (! STRINGP (font))
7305      font = x_new_font (f, "-*-Fixedsys-normal-r-*-*-12-*-*-*-c-*-iso8859-1");
7306    UNBLOCK_INPUT;
7307    if (! STRINGP (font))
7308      font = build_string ("Fixedsys");
7309
7310    x_default_parameter (f, parms, Qfont, font,
7311			 "font", "Font", RES_TYPE_STRING);
7312  }
7313
7314  x_default_parameter (f, parms, Qborder_width, make_number (2),
7315		       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
7316  /* This defaults to 2 in order to match xterm.  We recognize either
7317     internalBorderWidth or internalBorder (which is what xterm calls
7318     it).  */
7319  if (NILP (Fassq (Qinternal_border_width, parms)))
7320    {
7321      Lisp_Object value;
7322
7323      value = w32_get_arg (parms, Qinternal_border_width,
7324			 "internalBorder", "internalBorder", RES_TYPE_NUMBER);
7325      if (! EQ (value, Qunbound))
7326	parms = Fcons (Fcons (Qinternal_border_width, value),
7327		       parms);
7328    }
7329  x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
7330		       "internalBorderWidth", "internalBorderWidth",
7331		       RES_TYPE_NUMBER);
7332
7333  /* Also do the stuff which must be set before the window exists.  */
7334  x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
7335		       "foreground", "Foreground", RES_TYPE_STRING);
7336  x_default_parameter (f, parms, Qbackground_color, build_string ("white"),
7337		       "background", "Background", RES_TYPE_STRING);
7338  x_default_parameter (f, parms, Qmouse_color, build_string ("black"),
7339		       "pointerColor", "Foreground", RES_TYPE_STRING);
7340  x_default_parameter (f, parms, Qcursor_color, build_string ("black"),
7341		       "cursorColor", "Foreground", RES_TYPE_STRING);
7342  x_default_parameter (f, parms, Qborder_color, build_string ("black"),
7343		       "borderColor", "BorderColor", RES_TYPE_STRING);
7344
7345  /* Init faces before x_default_parameter is called for scroll-bar
7346     parameters because that function calls x_set_scroll_bar_width,
7347     which calls change_frame_size, which calls Fset_window_buffer,
7348     which runs hooks, which call Fvertical_motion.  At the end, we
7349     end up in init_iterator with a null face cache, which should not
7350     happen.  */
7351  init_frame_faces (f);
7352
7353  f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
7354  f->output_data.w32->parent_desc = FRAME_W32_DISPLAY_INFO (f)->root_window;
7355
7356  window_prompting = x_figure_window_size (f, parms, 0);
7357
7358  /* No fringes on tip frame.  */
7359  f->fringe_cols = 0;
7360  f->left_fringe_width = 0;
7361  f->right_fringe_width = 0;
7362
7363  BLOCK_INPUT;
7364  my_create_tip_window (f);
7365  UNBLOCK_INPUT;
7366
7367  x_make_gc (f);
7368
7369  x_default_parameter (f, parms, Qauto_raise, Qnil,
7370		       "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
7371  x_default_parameter (f, parms, Qauto_lower, Qnil,
7372		       "autoLower", "AutoRaiseLower", RES_TYPE_BOOLEAN);
7373  x_default_parameter (f, parms, Qcursor_type, Qbox,
7374		       "cursorType", "CursorType", RES_TYPE_SYMBOL);
7375
7376  /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
7377     Change will not be effected unless different from the current
7378     FRAME_LINES (f).  */
7379  width = FRAME_COLS (f);
7380  height = FRAME_LINES (f);
7381  FRAME_LINES (f) = 0;
7382  SET_FRAME_COLS (f, 0);
7383  change_frame_size (f, height, width, 1, 0, 0);
7384
7385  /* Add `tooltip' frame parameter's default value. */
7386  if (NILP (Fframe_parameter (frame, intern ("tooltip"))))
7387    Fmodify_frame_parameters (frame, Fcons (Fcons (intern ("tooltip"), Qt),
7388					    Qnil));
7389
7390  /* Set up faces after all frame parameters are known.  This call
7391     also merges in face attributes specified for new frames.
7392
7393     Frame parameters may be changed if .Xdefaults contains
7394     specifications for the default font.  For example, if there is an
7395     `Emacs.default.attributeBackground: pink', the `background-color'
7396     attribute of the frame get's set, which let's the internal border
7397     of the tooltip frame appear in pink.  Prevent this.  */
7398  {
7399    Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
7400
7401    /* Set tip_frame here, so that */
7402    tip_frame = frame;
7403    call1 (Qface_set_after_frame_default, frame);
7404
7405    if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
7406      Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
7407					      Qnil));
7408  }
7409
7410  f->no_split = 1;
7411
7412  UNGCPRO;
7413
7414  /* It is now ok to make the frame official even if we get an error
7415     below.  And the frame needs to be on Vframe_list or making it
7416     visible won't work.  */
7417  Vframe_list = Fcons (frame, Vframe_list);
7418
7419  /* Now that the frame is official, it counts as a reference to
7420     its display.  */
7421  FRAME_W32_DISPLAY_INFO (f)->reference_count++;
7422
7423  /* Setting attributes of faces of the tooltip frame from resources
7424     and similar will increment face_change_count, which leads to the
7425     clearing of all current matrices.  Since this isn't necessary
7426     here, avoid it by resetting face_change_count to the value it
7427     had before we created the tip frame.  */
7428  face_change_count = face_change_count_before;
7429
7430  /* Discard the unwind_protect.  */
7431  return unbind_to (count, frame);
7432}
7433
7434
7435/* Compute where to display tip frame F.  PARMS is the list of frame
7436   parameters for F.  DX and DY are specified offsets from the current
7437   location of the mouse.  WIDTH and HEIGHT are the width and height
7438   of the tooltip.  Return coordinates relative to the root window of
7439   the display in *ROOT_X, and *ROOT_Y.  */
7440
7441static void
7442compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
7443     struct frame *f;
7444     Lisp_Object parms, dx, dy;
7445     int width, height;
7446     int *root_x, *root_y;
7447{
7448  Lisp_Object left, top;
7449
7450  /* User-specified position?  */
7451  left = Fcdr (Fassq (Qleft, parms));
7452  top  = Fcdr (Fassq (Qtop, parms));
7453
7454  /* Move the tooltip window where the mouse pointer is.  Resize and
7455     show it.  */
7456  if (!INTEGERP (left) || !INTEGERP (top))
7457    {
7458      POINT pt;
7459
7460      BLOCK_INPUT;
7461      GetCursorPos (&pt);
7462      *root_x = pt.x;
7463      *root_y = pt.y;
7464      UNBLOCK_INPUT;
7465    }
7466
7467  if (INTEGERP (top))
7468    *root_y = XINT (top);
7469  else if (*root_y + XINT (dy) <= 0)
7470    *root_y = 0; /* Can happen for negative dy */
7471  else if (*root_y + XINT (dy) + height <= FRAME_W32_DISPLAY_INFO (f)->height)
7472    /* It fits below the pointer */
7473      *root_y += XINT (dy);
7474  else if (height + XINT (dy) <= *root_y)
7475    /* It fits above the pointer.  */
7476    *root_y -= height + XINT (dy);
7477  else
7478    /* Put it on the top.  */
7479    *root_y = 0;
7480
7481  if (INTEGERP (left))
7482    *root_x = XINT (left);
7483  else if (*root_x + XINT (dx) <= 0)
7484    *root_x = 0; /* Can happen for negative dx */
7485  else if (*root_x + XINT (dx) + width <= FRAME_W32_DISPLAY_INFO (f)->width)
7486    /* It fits to the right of the pointer.  */
7487    *root_x += XINT (dx);
7488  else if (width + XINT (dx) <= *root_x)
7489    /* It fits to the left of the pointer.  */
7490    *root_x -= width + XINT (dx);
7491  else
7492    /* Put it left justified on the screen -- it ought to fit that way.  */
7493    *root_x = 0;
7494}
7495
7496
7497DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
7498       doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
7499A tooltip window is a small window displaying a string.
7500
7501This is an internal function; Lisp code should call `tooltip-show'.
7502
7503FRAME nil or omitted means use the selected frame.
7504
7505PARMS is an optional list of frame parameters which can be
7506used to change the tooltip's appearance.
7507
7508Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
7509means use the default timeout of 5 seconds.
7510
7511If the list of frame parameters PARMS contains a `left' parameter,
7512the tooltip is displayed at that x-position.  Otherwise it is
7513displayed at the mouse position, with offset DX added (default is 5 if
7514DX isn't specified).  Likewise for the y-position; if a `top' frame
7515parameter is specified, it determines the y-position of the tooltip
7516window, otherwise it is displayed at the mouse position, with offset
7517DY added (default is -10).
7518
7519A tooltip's maximum size is specified by `x-max-tooltip-size'.
7520Text larger than the specified size is clipped.  */)
7521  (string, frame, parms, timeout, dx, dy)
7522     Lisp_Object string, frame, parms, timeout, dx, dy;
7523{
7524  struct frame *f;
7525  struct window *w;
7526  int root_x, root_y;
7527  struct buffer *old_buffer;
7528  struct text_pos pos;
7529  int i, width, height;
7530  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
7531  int old_windows_or_buffers_changed = windows_or_buffers_changed;
7532  int count = SPECPDL_INDEX ();
7533
7534  specbind (Qinhibit_redisplay, Qt);
7535
7536  GCPRO4 (string, parms, frame, timeout);
7537
7538  CHECK_STRING (string);
7539  f = check_x_frame (frame);
7540  if (NILP (timeout))
7541    timeout = make_number (5);
7542  else
7543    CHECK_NATNUM (timeout);
7544
7545  if (NILP (dx))
7546    dx = make_number (5);
7547  else
7548    CHECK_NUMBER (dx);
7549
7550  if (NILP (dy))
7551    dy = make_number (-10);
7552  else
7553    CHECK_NUMBER (dy);
7554
7555  if (NILP (last_show_tip_args))
7556    last_show_tip_args = Fmake_vector (make_number (3), Qnil);
7557
7558  if (!NILP (tip_frame))
7559    {
7560      Lisp_Object last_string = AREF (last_show_tip_args, 0);
7561      Lisp_Object last_frame = AREF (last_show_tip_args, 1);
7562      Lisp_Object last_parms = AREF (last_show_tip_args, 2);
7563
7564      if (EQ (frame, last_frame)
7565	  && !NILP (Fequal (last_string, string))
7566	  && !NILP (Fequal (last_parms, parms)))
7567	{
7568	  struct frame *f = XFRAME (tip_frame);
7569
7570	  /* Only DX and DY have changed.  */
7571	  if (!NILP (tip_timer))
7572	    {
7573	      Lisp_Object timer = tip_timer;
7574	      tip_timer = Qnil;
7575	      call1 (Qcancel_timer, timer);
7576	    }
7577
7578	  BLOCK_INPUT;
7579	  compute_tip_xy (f, parms, dx, dy, FRAME_PIXEL_WIDTH (f),
7580			  FRAME_PIXEL_HEIGHT (f), &root_x, &root_y);
7581
7582	  /* Put tooltip in topmost group and in position.  */
7583	  SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
7584			root_x, root_y, 0, 0,
7585			SWP_NOSIZE | SWP_NOACTIVATE);
7586
7587	  /* Ensure tooltip is on top of other topmost windows (eg menus).  */
7588	  SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
7589			0, 0, 0, 0,
7590			SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
7591
7592	  UNBLOCK_INPUT;
7593	  goto start_timer;
7594	}
7595    }
7596
7597  /* Hide a previous tip, if any.  */
7598  Fx_hide_tip ();
7599
7600  ASET (last_show_tip_args, 0, string);
7601  ASET (last_show_tip_args, 1, frame);
7602  ASET (last_show_tip_args, 2, parms);
7603
7604  /* Add default values to frame parameters.  */
7605  if (NILP (Fassq (Qname, parms)))
7606    parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
7607  if (NILP (Fassq (Qinternal_border_width, parms)))
7608    parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
7609  if (NILP (Fassq (Qborder_width, parms)))
7610    parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
7611  if (NILP (Fassq (Qborder_color, parms)))
7612    parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
7613  if (NILP (Fassq (Qbackground_color, parms)))
7614    parms = Fcons (Fcons (Qbackground_color, build_string ("lightyellow")),
7615		   parms);
7616
7617  /* Block input until the tip has been fully drawn, to avoid crashes
7618     when drawing tips in menus.  */
7619  BLOCK_INPUT;
7620
7621  /* Create a frame for the tooltip, and record it in the global
7622     variable tip_frame.  */
7623  frame = x_create_tip_frame (FRAME_W32_DISPLAY_INFO (f), parms, string);
7624  f = XFRAME (frame);
7625
7626  /* Set up the frame's root window.  */
7627  w = XWINDOW (FRAME_ROOT_WINDOW (f));
7628  w->left_col = w->top_line = make_number (0);
7629
7630  if (CONSP (Vx_max_tooltip_size)
7631      && INTEGERP (XCAR (Vx_max_tooltip_size))
7632      && XINT (XCAR (Vx_max_tooltip_size)) > 0
7633      && INTEGERP (XCDR (Vx_max_tooltip_size))
7634      && XINT (XCDR (Vx_max_tooltip_size)) > 0)
7635    {
7636      w->total_cols = XCAR (Vx_max_tooltip_size);
7637      w->total_lines = XCDR (Vx_max_tooltip_size);
7638    }
7639  else
7640    {
7641      w->total_cols = make_number (80);
7642      w->total_lines = make_number (40);
7643    }
7644
7645  FRAME_TOTAL_COLS (f) = XINT (w->total_cols);
7646  adjust_glyphs (f);
7647  w->pseudo_window_p = 1;
7648
7649  /* Display the tooltip text in a temporary buffer.  */
7650  old_buffer = current_buffer;
7651  set_buffer_internal_1 (XBUFFER (XWINDOW (FRAME_ROOT_WINDOW (f))->buffer));
7652  current_buffer->truncate_lines = Qnil;
7653  clear_glyph_matrix (w->desired_matrix);
7654  clear_glyph_matrix (w->current_matrix);
7655  SET_TEXT_POS (pos, BEGV, BEGV_BYTE);
7656  try_window (FRAME_ROOT_WINDOW (f), pos, 0);
7657
7658  /* Compute width and height of the tooltip.  */
7659  width = height = 0;
7660  for (i = 0; i < w->desired_matrix->nrows; ++i)
7661    {
7662      struct glyph_row *row = &w->desired_matrix->rows[i];
7663      struct glyph *last;
7664      int row_width;
7665
7666      /* Stop at the first empty row at the end.  */
7667      if (!row->enabled_p || !row->displays_text_p)
7668	break;
7669
7670      /* Let the row go over the full width of the frame.  */
7671      row->full_width_p = 1;
7672
7673#ifdef TODO /* Investigate why some fonts need more width than is
7674	       calculated for some tooltips.  */
7675      /* There's a glyph at the end of rows that is use to place
7676	 the cursor there.  Don't include the width of this glyph.  */
7677      if (row->used[TEXT_AREA])
7678	{
7679	  last = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
7680	  row_width = row->pixel_width - last->pixel_width;
7681	}
7682      else
7683#endif
7684	row_width = row->pixel_width;
7685
7686      /* TODO: find why tips do not draw along baseline as instructed.  */
7687      height += row->height;
7688      width = max (width, row_width);
7689    }
7690
7691  /* Add the frame's internal border to the width and height the X
7692     window should have.  */
7693  height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
7694  width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
7695
7696  /* Move the tooltip window where the mouse pointer is.  Resize and
7697     show it.  */
7698  compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
7699
7700  {
7701    /* Adjust Window size to take border into account.  */
7702    RECT rect;
7703    rect.left = rect.top = 0;
7704    rect.right = width;
7705    rect.bottom = height;
7706    AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
7707		      FRAME_EXTERNAL_MENU_BAR (f));
7708
7709    /* Position and size tooltip, and put it in the topmost group.
7710       The add-on of 3 to the 5th argument is a kludge: without it,
7711       some fonts cause the last character of the tip to be truncated,
7712       for some obscure reason.  */
7713    SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOPMOST,
7714		  root_x, root_y, rect.right - rect.left + 3,
7715		  rect.bottom - rect.top, SWP_NOACTIVATE);
7716
7717    /* Ensure tooltip is on top of other topmost windows (eg menus).  */
7718    SetWindowPos (FRAME_W32_WINDOW (f), HWND_TOP,
7719		  0, 0, 0, 0,
7720		  SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
7721
7722    /* Let redisplay know that we have made the frame visible already.  */
7723    f->async_visible = 1;
7724
7725    ShowWindow (FRAME_W32_WINDOW (f), SW_SHOWNOACTIVATE);
7726  }
7727
7728  /* Draw into the window.  */
7729  w->must_be_updated_p = 1;
7730  update_single_window (w, 1);
7731
7732  UNBLOCK_INPUT;
7733
7734  /* Restore original current buffer.  */
7735  set_buffer_internal_1 (old_buffer);
7736  windows_or_buffers_changed = old_windows_or_buffers_changed;
7737
7738 start_timer:
7739  /* Let the tip disappear after timeout seconds.  */
7740  tip_timer = call3 (intern ("run-at-time"), timeout, Qnil,
7741		     intern ("x-hide-tip"));
7742
7743  UNGCPRO;
7744  return unbind_to (count, Qnil);
7745}
7746
7747
7748DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
7749       doc: /* Hide the current tooltip window, if there is any.
7750Value is t if tooltip was open, nil otherwise.  */)
7751  ()
7752{
7753  int count;
7754  Lisp_Object deleted, frame, timer;
7755  struct gcpro gcpro1, gcpro2;
7756
7757  /* Return quickly if nothing to do.  */
7758  if (NILP (tip_timer) && NILP (tip_frame))
7759    return Qnil;
7760
7761  frame = tip_frame;
7762  timer = tip_timer;
7763  GCPRO2 (frame, timer);
7764  tip_frame = tip_timer = deleted = Qnil;
7765
7766  count = SPECPDL_INDEX ();
7767  specbind (Qinhibit_redisplay, Qt);
7768  specbind (Qinhibit_quit, Qt);
7769
7770  if (!NILP (timer))
7771    call1 (Qcancel_timer, timer);
7772
7773  if (FRAMEP (frame))
7774    {
7775      Fdelete_frame (frame, Qnil);
7776      deleted = Qt;
7777    }
7778
7779  UNGCPRO;
7780  return unbind_to (count, deleted);
7781}
7782
7783
7784
7785/***********************************************************************
7786			File selection dialog
7787 ***********************************************************************/
7788extern Lisp_Object Qfile_name_history;
7789
7790/* Callback for altering the behaviour of the Open File dialog.
7791   Makes the Filename text field contain "Current Directory" and be
7792   read-only when "Directories" is selected in the filter.  This
7793   allows us to work around the fact that the standard Open File
7794   dialog does not support directories.  */
7795UINT CALLBACK
7796file_dialog_callback (hwnd, msg, wParam, lParam)
7797     HWND hwnd;
7798     UINT msg;
7799     WPARAM wParam;
7800     LPARAM lParam;
7801{
7802  if (msg == WM_NOTIFY)
7803    {
7804      OFNOTIFY * notify = (OFNOTIFY *)lParam;
7805      /* Detect when the Filter dropdown is changed.  */
7806      if (notify->hdr.code == CDN_TYPECHANGE
7807	  || notify->hdr.code == CDN_INITDONE)
7808	{
7809	  HWND dialog = GetParent (hwnd);
7810	  HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD);
7811
7812	  /* Directories is in index 2.  */
7813	  if (notify->lpOFN->nFilterIndex == 2)
7814	    {
7815	      CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD,
7816					       "Current Directory");
7817	      EnableWindow (edit_control, FALSE);
7818	    }
7819	  else
7820	    {
7821	      /* Don't override default filename on init done.  */
7822	      if (notify->hdr.code == CDN_TYPECHANGE)
7823		CommDlg_OpenSave_SetControlText (dialog,
7824						 FILE_NAME_TEXT_FIELD, "");
7825	      EnableWindow (edit_control, TRUE);
7826	    }
7827	}
7828    }
7829  return 0;
7830}
7831
7832/* Since we compile with _WIN32_WINNT set to 0x0400 (for NT4 compatibility)
7833   we end up with the old file dialogs. Define a big enough struct for the
7834   new dialog to trick GetOpenFileName into giving us the new dialogs on
7835   Windows 2000 and XP.  */
7836typedef struct
7837{
7838  OPENFILENAME real_details;
7839  void * pReserved;
7840  DWORD dwReserved;
7841  DWORD FlagsEx;
7842} NEWOPENFILENAME;
7843
7844
7845DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7846       doc: /* Read file name, prompting with PROMPT in directory DIR.
7847Use a file selection dialog.
7848Select DEFAULT-FILENAME in the dialog's file selection box, if
7849specified.  Ensure that file exists if MUSTMATCH is non-nil.
7850If ONLY-DIR-P is non-nil, the user can only select directories.  */)
7851  (prompt, dir, default_filename, mustmatch, only_dir_p)
7852     Lisp_Object prompt, dir, default_filename, mustmatch, only_dir_p;
7853{
7854  struct frame *f = SELECTED_FRAME ();
7855  Lisp_Object file = Qnil;
7856  int count = SPECPDL_INDEX ();
7857  struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
7858  char filename[MAX_PATH + 1];
7859  char init_dir[MAX_PATH + 1];
7860  int default_filter_index = 1; /* 1: All Files, 2: Directories only  */
7861
7862  GCPRO6 (prompt, dir, default_filename, mustmatch, only_dir_p, file);
7863  CHECK_STRING (prompt);
7864  CHECK_STRING (dir);
7865
7866  /* Create the dialog with PROMPT as title, using DIR as initial
7867     directory and using "*" as pattern.  */
7868  dir = Fexpand_file_name (dir, Qnil);
7869  strncpy (init_dir, SDATA (ENCODE_FILE (dir)), MAX_PATH);
7870  init_dir[MAX_PATH] = '\0';
7871  unixtodos_filename (init_dir);
7872
7873  if (STRINGP (default_filename))
7874    {
7875      char *file_name_only;
7876      char *full_path_name = SDATA (ENCODE_FILE (default_filename));
7877
7878      unixtodos_filename (full_path_name);
7879
7880      file_name_only = strrchr (full_path_name, '\\');
7881      if (!file_name_only)
7882        file_name_only = full_path_name;
7883      else
7884	file_name_only++;
7885
7886      strncpy (filename, file_name_only, MAX_PATH);
7887      filename[MAX_PATH] = '\0';
7888    }
7889  else
7890    filename[0] = '\0';
7891
7892  {
7893    NEWOPENFILENAME new_file_details;
7894    BOOL file_opened = FALSE;
7895    OPENFILENAME * file_details = &new_file_details.real_details;
7896
7897    /* Prevent redisplay.  */
7898    specbind (Qinhibit_redisplay, Qt);
7899    BLOCK_INPUT;
7900
7901    bzero (&new_file_details, sizeof (new_file_details));
7902    /* Apparently NT4 crashes if you give it an unexpected size.
7903       I'm not sure about Windows 9x, so play it safe.  */
7904    if (w32_major_version > 4 && w32_major_version < 95)
7905      file_details->lStructSize = sizeof (new_file_details);
7906    else
7907      file_details->lStructSize = sizeof (file_details);
7908
7909    file_details->hwndOwner = FRAME_W32_WINDOW (f);
7910    /* Undocumented Bug in Common File Dialog:
7911       If a filter is not specified, shell links are not resolved.  */
7912    file_details->lpstrFilter = "All Files (*.*)\0*.*\0Directories\0*|*\0\0";
7913    file_details->lpstrFile = filename;
7914    file_details->nMaxFile = sizeof (filename);
7915    file_details->lpstrInitialDir = init_dir;
7916    file_details->lpstrTitle = SDATA (prompt);
7917
7918    if (! NILP (only_dir_p))
7919      default_filter_index = 2;
7920
7921    file_details->nFilterIndex = default_filter_index;
7922
7923    file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
7924			  | OFN_EXPLORER | OFN_ENABLEHOOK);
7925    if (!NILP (mustmatch))
7926      {
7927	/* Require that the path to the parent directory exists.  */
7928	file_details->Flags |= OFN_PATHMUSTEXIST;
7929	/* If we are looking for a file, require that it exists.  */
7930	if (NILP (only_dir_p))
7931	  file_details->Flags |= OFN_FILEMUSTEXIST;
7932      }
7933
7934    file_details->lpfnHook = (LPOFNHOOKPROC) file_dialog_callback;
7935
7936    file_opened = GetOpenFileName (file_details);
7937
7938    UNBLOCK_INPUT;
7939
7940    if (file_opened)
7941      {
7942	dostounix_filename (filename);
7943
7944	if (file_details->nFilterIndex == 2)
7945	  {
7946	    /* "Directories" selected - strip dummy file name.  */
7947	    char * last = strrchr (filename, '/');
7948	    *last = '\0';
7949	  }
7950
7951	file = DECODE_FILE(build_string (filename));
7952      }
7953    /* User cancelled the dialog without making a selection.  */
7954    else if (!CommDlgExtendedError ())
7955      file = Qnil;
7956    /* An error occurred, fallback on reading from the mini-buffer.  */
7957    else
7958      file = Fcompleting_read (prompt, intern ("read-file-name-internal"),
7959			       dir, mustmatch, dir, Qfile_name_history,
7960			       default_filename, Qnil);
7961
7962    file = unbind_to (count, file);
7963  }
7964
7965  UNGCPRO;
7966
7967  /* Make "Cancel" equivalent to C-g.  */
7968  if (NILP (file))
7969    Fsignal (Qquit, Qnil);
7970
7971  return unbind_to (count, file);
7972}
7973
7974
7975
7976/***********************************************************************
7977                         w32 specialized functions
7978 ***********************************************************************/
7979
7980DEFUN ("w32-select-font", Fw32_select_font, Sw32_select_font, 0, 2, 0,
7981       doc: /* Select a font for the named FRAME using the W32 font dialog.
7982Returns an X-style font string corresponding to the selection.
7983
7984If FRAME is omitted or nil, it defaults to the selected frame.
7985If INCLUDE-PROPORTIONAL is non-nil, include proportional fonts
7986in the font selection dialog. */)
7987  (frame, include_proportional)
7988     Lisp_Object frame, include_proportional;
7989{
7990  FRAME_PTR f = check_x_frame (frame);
7991  CHOOSEFONT cf;
7992  LOGFONT lf;
7993  TEXTMETRIC tm;
7994  HDC hdc;
7995  HANDLE oldobj;
7996  char buf[100];
7997
7998  bzero (&cf, sizeof (cf));
7999  bzero (&lf, sizeof (lf));
8000
8001  cf.lStructSize = sizeof (cf);
8002  cf.hwndOwner = FRAME_W32_WINDOW (f);
8003  cf.Flags = CF_FORCEFONTEXIST | CF_SCREENFONTS | CF_NOVERTFONTS;
8004
8005  /* Unless include_proportional is non-nil, limit the selection to
8006     monospaced fonts.  */
8007  if (NILP (include_proportional))
8008    cf.Flags |= CF_FIXEDPITCHONLY;
8009
8010  cf.lpLogFont = &lf;
8011
8012  /* Initialize as much of the font details as we can from the current
8013     default font.  */
8014  hdc = GetDC (FRAME_W32_WINDOW (f));
8015  oldobj = SelectObject (hdc, FRAME_FONT (f)->hfont);
8016  GetTextFace (hdc, LF_FACESIZE, lf.lfFaceName);
8017  if (GetTextMetrics (hdc, &tm))
8018    {
8019      lf.lfHeight = tm.tmInternalLeading - tm.tmHeight;
8020      lf.lfWeight = tm.tmWeight;
8021      lf.lfItalic = tm.tmItalic;
8022      lf.lfUnderline = tm.tmUnderlined;
8023      lf.lfStrikeOut = tm.tmStruckOut;
8024      lf.lfCharSet = tm.tmCharSet;
8025      cf.Flags |= CF_INITTOLOGFONTSTRUCT;
8026    }
8027  SelectObject (hdc, oldobj);
8028  ReleaseDC (FRAME_W32_WINDOW (f), hdc);
8029
8030  if (!ChooseFont (&cf) || !w32_to_x_font (&lf, buf, 100, NULL))
8031      return Qnil;
8032
8033  return build_string (buf);
8034}
8035
8036DEFUN ("w32-send-sys-command", Fw32_send_sys_command,
8037       Sw32_send_sys_command, 1, 2, 0,
8038       doc: /* Send frame a Windows WM_SYSCOMMAND message of type COMMAND.
8039Some useful values for COMMAND are #xf030 to maximize frame (#xf020
8040to minimize), #xf120 to restore frame to original size, and #xf100
8041to activate the menubar for keyboard access.  #xf140 activates the
8042screen saver if defined.
8043
8044If optional parameter FRAME is not specified, use selected frame.  */)
8045  (command, frame)
8046     Lisp_Object command, frame;
8047{
8048  FRAME_PTR f = check_x_frame (frame);
8049
8050  CHECK_NUMBER (command);
8051
8052  PostMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, XINT (command), 0);
8053
8054  return Qnil;
8055}
8056
8057DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0,
8058       doc: /* Get Windows to perform OPERATION on DOCUMENT.
8059This is a wrapper around the ShellExecute system function, which
8060invokes the application registered to handle OPERATION for DOCUMENT.
8061
8062OPERATION is either nil or a string that names a supported operation.
8063What operations can be used depends on the particular DOCUMENT and its
8064handler application, but typically it is one of the following common
8065operations:
8066
8067 \"open\"    - open DOCUMENT, which could be a file, a directory, or an
8068               executable program.  If it is an application, that
8069               application is launched in the current buffer's default
8070               directory.  Otherwise, the application associated with
8071               DOCUMENT is launched in the buffer's default directory.
8072 \"print\"   - print DOCUMENT, which must be a file
8073 \"explore\" - start the Windows Explorer on DOCUMENT
8074 \"edit\"    - launch an editor and open DOCUMENT for editing; which
8075               editor is launched depends on the association for the
8076               specified DOCUMENT
8077 \"find\"    - initiate search starting from DOCUMENT which must specify
8078               a directory
8079 nil       - invoke the default OPERATION, or \"open\" if default is
8080               not defined or unavailable
8081
8082DOCUMENT is typically the name of a document file or a URL, but can
8083also be a program executable to run, or a directory to open in the
8084Windows Explorer.
8085
8086If DOCUMENT is a program executable, the optional arg PARAMETERS can
8087be a string containing command line parameters that will be passed to
8088the program; otherwise, PARAMETERS should be nil or unspecified.
8089
8090Second optional argument SHOW-FLAG can be used to control how the
8091application will be displayed when it is invoked.  If SHOW-FLAG is nil
8092or unspceified, the application is displayed normally, otherwise it is
8093an integer representing a ShowWindow flag:
8094
8095  0 - start hidden
8096  1 - start normally
8097  3 - start maximized
8098  6 - start minimized  */)
8099  (operation, document, parameters, show_flag)
8100     Lisp_Object operation, document, parameters, show_flag;
8101{
8102  Lisp_Object current_dir;
8103
8104  CHECK_STRING (document);
8105
8106  /* Encode filename and current directory.  */
8107  current_dir = ENCODE_FILE (current_buffer->directory);
8108  document = ENCODE_FILE (document);
8109  if ((int) ShellExecute (NULL,
8110			  (STRINGP (operation) ?
8111			   SDATA (operation) : NULL),
8112			  SDATA (document),
8113			  (STRINGP (parameters) ?
8114			   SDATA (parameters) : NULL),
8115			  SDATA (current_dir),
8116			  (INTEGERP (show_flag) ?
8117			   XINT (show_flag) : SW_SHOWDEFAULT))
8118      > 32)
8119    return Qt;
8120  error ("ShellExecute failed: %s", w32_strerror (0));
8121}
8122
8123/* Lookup virtual keycode from string representing the name of a
8124   non-ascii keystroke into the corresponding virtual key, using
8125   lispy_function_keys.  */
8126static int
8127lookup_vk_code (char *key)
8128{
8129  int i;
8130
8131  for (i = 0; i < 256; i++)
8132    if (lispy_function_keys[i] != 0
8133	&& strcmp (lispy_function_keys[i], key) == 0)
8134      return i;
8135
8136  return -1;
8137}
8138
8139/* Convert a one-element vector style key sequence to a hot key
8140   definition.  */
8141static Lisp_Object
8142w32_parse_hot_key (key)
8143     Lisp_Object key;
8144{
8145  /* Copied from Fdefine_key and store_in_keymap.  */
8146  register Lisp_Object c;
8147  int vk_code;
8148  int lisp_modifiers;
8149  int w32_modifiers;
8150  struct gcpro gcpro1;
8151
8152  CHECK_VECTOR (key);
8153
8154  if (XFASTINT (Flength (key)) != 1)
8155    return Qnil;
8156
8157  GCPRO1 (key);
8158
8159  c = Faref (key, make_number (0));
8160
8161  if (CONSP (c) && lucid_event_type_list_p (c))
8162    c = Fevent_convert_list (c);
8163
8164  UNGCPRO;
8165
8166  if (! INTEGERP (c) && ! SYMBOLP (c))
8167    error ("Key definition is invalid");
8168
8169  /* Work out the base key and the modifiers.  */
8170  if (SYMBOLP (c))
8171    {
8172      c = parse_modifiers (c);
8173      lisp_modifiers = XINT (Fcar (Fcdr (c)));
8174      c = Fcar (c);
8175      if (!SYMBOLP (c))
8176	abort ();
8177      vk_code = lookup_vk_code (SDATA (SYMBOL_NAME (c)));
8178    }
8179  else if (INTEGERP (c))
8180    {
8181      lisp_modifiers = XINT (c) & ~CHARACTERBITS;
8182      /* Many ascii characters are their own virtual key code.  */
8183      vk_code = XINT (c) & CHARACTERBITS;
8184    }
8185
8186  if (vk_code < 0 || vk_code > 255)
8187    return Qnil;
8188
8189  if ((lisp_modifiers & meta_modifier) != 0
8190      && !NILP (Vw32_alt_is_meta))
8191    lisp_modifiers |= alt_modifier;
8192
8193  /* Supply defs missing from mingw32.  */
8194#ifndef MOD_ALT
8195#define MOD_ALT         0x0001
8196#define MOD_CONTROL     0x0002
8197#define MOD_SHIFT       0x0004
8198#define MOD_WIN         0x0008
8199#endif
8200
8201  /* Convert lisp modifiers to Windows hot-key form.  */
8202  w32_modifiers  = (lisp_modifiers & hyper_modifier)    ? MOD_WIN : 0;
8203  w32_modifiers |= (lisp_modifiers & alt_modifier)      ? MOD_ALT : 0;
8204  w32_modifiers |= (lisp_modifiers & ctrl_modifier)     ? MOD_CONTROL : 0;
8205  w32_modifiers |= (lisp_modifiers & shift_modifier)    ? MOD_SHIFT : 0;
8206
8207  return HOTKEY (vk_code, w32_modifiers);
8208}
8209
8210DEFUN ("w32-register-hot-key", Fw32_register_hot_key,
8211       Sw32_register_hot_key, 1, 1, 0,
8212       doc: /* Register KEY as a hot-key combination.
8213Certain key combinations like Alt-Tab are reserved for system use on
8214Windows, and therefore are normally intercepted by the system.  However,
8215most of these key combinations can be received by registering them as
8216hot-keys, overriding their special meaning.
8217
8218KEY must be a one element key definition in vector form that would be
8219acceptable to `define-key' (e.g. [A-tab] for Alt-Tab).  The meta
8220modifier is interpreted as Alt if `w32-alt-is-meta' is t, and hyper
8221is always interpreted as the Windows modifier keys.
8222
8223The return value is the hotkey-id if registered, otherwise nil.  */)
8224  (key)
8225     Lisp_Object key;
8226{
8227  key = w32_parse_hot_key (key);
8228
8229  if (NILP (Fmemq (key, w32_grabbed_keys)))
8230    {
8231      /* Reuse an empty slot if possible.  */
8232      Lisp_Object item = Fmemq (Qnil, w32_grabbed_keys);
8233
8234      /* Safe to add new key to list, even if we have focus.  */
8235      if (NILP (item))
8236	w32_grabbed_keys = Fcons (key, w32_grabbed_keys);
8237      else
8238	XSETCAR (item, key);
8239
8240      /* Notify input thread about new hot-key definition, so that it
8241	 takes effect without needing to switch focus.  */
8242#ifdef USE_LISP_UNION_TYPE
8243      PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
8244			 (WPARAM) key.i, 0);
8245#else
8246      PostThreadMessage (dwWindowsThreadId, WM_EMACS_REGISTER_HOT_KEY,
8247			 (WPARAM) key, 0);
8248#endif
8249    }
8250
8251  return key;
8252}
8253
8254DEFUN ("w32-unregister-hot-key", Fw32_unregister_hot_key,
8255       Sw32_unregister_hot_key, 1, 1, 0,
8256       doc: /* Unregister KEY as a hot-key combination.  */)
8257  (key)
8258     Lisp_Object key;
8259{
8260  Lisp_Object item;
8261
8262  if (!INTEGERP (key))
8263    key = w32_parse_hot_key (key);
8264
8265  item = Fmemq (key, w32_grabbed_keys);
8266
8267  if (!NILP (item))
8268    {
8269      /* Notify input thread about hot-key definition being removed, so
8270	 that it takes effect without needing focus switch.  */
8271#ifdef USE_LISP_UNION_TYPE
8272      if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
8273			     (WPARAM) XINT (XCAR (item)), (LPARAM) item.i))
8274#else
8275      if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_UNREGISTER_HOT_KEY,
8276			     (WPARAM) XINT (XCAR (item)), (LPARAM) item))
8277
8278#endif
8279	{
8280	  MSG msg;
8281	  GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
8282	}
8283      return Qt;
8284    }
8285  return Qnil;
8286}
8287
8288DEFUN ("w32-registered-hot-keys", Fw32_registered_hot_keys,
8289       Sw32_registered_hot_keys, 0, 0, 0,
8290       doc: /* Return list of registered hot-key IDs.  */)
8291  ()
8292{
8293  return Fcopy_sequence (w32_grabbed_keys);
8294}
8295
8296DEFUN ("w32-reconstruct-hot-key", Fw32_reconstruct_hot_key,
8297       Sw32_reconstruct_hot_key, 1, 1, 0,
8298       doc: /* Convert hot-key ID to a lisp key combination.
8299usage: (w32-reconstruct-hot-key ID)  */)
8300  (hotkeyid)
8301     Lisp_Object hotkeyid;
8302{
8303  int vk_code, w32_modifiers;
8304  Lisp_Object key;
8305
8306  CHECK_NUMBER (hotkeyid);
8307
8308  vk_code = HOTKEY_VK_CODE (hotkeyid);
8309  w32_modifiers = HOTKEY_MODIFIERS (hotkeyid);
8310
8311  if (lispy_function_keys[vk_code])
8312    key = intern (lispy_function_keys[vk_code]);
8313  else
8314    key = make_number (vk_code);
8315
8316  key = Fcons (key, Qnil);
8317  if (w32_modifiers & MOD_SHIFT)
8318    key = Fcons (Qshift, key);
8319  if (w32_modifiers & MOD_CONTROL)
8320    key = Fcons (Qctrl, key);
8321  if (w32_modifiers & MOD_ALT)
8322    key = Fcons (NILP (Vw32_alt_is_meta) ? Qalt : Qmeta, key);
8323  if (w32_modifiers & MOD_WIN)
8324    key = Fcons (Qhyper, key);
8325
8326  return key;
8327}
8328
8329DEFUN ("w32-toggle-lock-key", Fw32_toggle_lock_key,
8330       Sw32_toggle_lock_key, 1, 2, 0,
8331       doc: /* Toggle the state of the lock key KEY.
8332KEY can be `capslock', `kp-numlock', or `scroll'.
8333If the optional parameter NEW-STATE is a number, then the state of KEY
8334is set to off if the low bit of NEW-STATE is zero, otherwise on.  */)
8335  (key, new_state)
8336     Lisp_Object key, new_state;
8337{
8338  int vk_code;
8339
8340  if (EQ (key, intern ("capslock")))
8341    vk_code = VK_CAPITAL;
8342  else if (EQ (key, intern ("kp-numlock")))
8343    vk_code = VK_NUMLOCK;
8344  else if (EQ (key, intern ("scroll")))
8345    vk_code = VK_SCROLL;
8346  else
8347    return Qnil;
8348
8349  if (!dwWindowsThreadId)
8350    return make_number (w32_console_toggle_lock_key (vk_code, new_state));
8351
8352#ifdef USE_LISP_UNION_TYPE
8353  if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
8354			 (WPARAM) vk_code, (LPARAM) new_state.i))
8355#else
8356  if (PostThreadMessage (dwWindowsThreadId, WM_EMACS_TOGGLE_LOCK_KEY,
8357			 (WPARAM) vk_code, (LPARAM) new_state))
8358#endif
8359    {
8360      MSG msg;
8361      GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
8362      return make_number (msg.wParam);
8363    }
8364  return Qnil;
8365}
8366
8367DEFUN ("w32-window-exists-p", Fw32_window_exists_p, Sw32_window_exists_p,
8368       2, 2, 0,
8369       doc: /* Return non-nil if a window exists with the specified CLASS and NAME.
8370
8371This is a direct interface to the Windows API FindWindow function.  */)
8372  (class, name)
8373Lisp_Object class, name;
8374{
8375  HWND hnd;
8376
8377  if (!NILP (class))
8378    CHECK_STRING (class);
8379  if (!NILP (name))
8380    CHECK_STRING (name);
8381
8382  hnd = FindWindow (STRINGP (class) ? ((LPCTSTR) SDATA (class)) : NULL,
8383		    STRINGP (name)  ? ((LPCTSTR) SDATA (name))  : NULL);
8384  if (!hnd)
8385    return Qnil;
8386  return Qt;
8387}
8388
8389
8390
8391DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0,
8392       doc: /* Return storage information about the file system FILENAME is on.
8393Value is a list of floats (TOTAL FREE AVAIL), where TOTAL is the total
8394storage of the file system, FREE is the free storage, and AVAIL is the
8395storage available to a non-superuser.  All 3 numbers are in bytes.
8396If the underlying system call fails, value is nil.  */)
8397  (filename)
8398  Lisp_Object filename;
8399{
8400  Lisp_Object encoded, value;
8401
8402  CHECK_STRING (filename);
8403  filename = Fexpand_file_name (filename, Qnil);
8404  encoded = ENCODE_FILE (filename);
8405
8406  value = Qnil;
8407
8408  /* Determining the required information on Windows turns out, sadly,
8409     to be more involved than one would hope.  The original Win32 api
8410     call for this will return bogus information on some systems, but we
8411     must dynamically probe for the replacement api, since that was
8412     added rather late on.  */
8413  {
8414    HMODULE hKernel = GetModuleHandle ("kernel32");
8415    BOOL (*pfn_GetDiskFreeSpaceEx)
8416      (char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
8417      = (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
8418
8419    /* On Windows, we may need to specify the root directory of the
8420       volume holding FILENAME.  */
8421    char rootname[MAX_PATH];
8422    char *name = SDATA (encoded);
8423
8424    /* find the root name of the volume if given */
8425    if (isalpha (name[0]) && name[1] == ':')
8426      {
8427	rootname[0] = name[0];
8428	rootname[1] = name[1];
8429	rootname[2] = '\\';
8430	rootname[3] = 0;
8431      }
8432    else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
8433      {
8434	char *str = rootname;
8435	int slashes = 4;
8436	do
8437	  {
8438	    if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
8439	      break;
8440	    *str++ = *name++;
8441	  }
8442	while ( *name );
8443
8444	*str++ = '\\';
8445	*str = 0;
8446      }
8447
8448    if (pfn_GetDiskFreeSpaceEx)
8449      {
8450	/* Unsigned large integers cannot be cast to double, so
8451	   use signed ones instead.  */
8452	LARGE_INTEGER availbytes;
8453	LARGE_INTEGER freebytes;
8454	LARGE_INTEGER totalbytes;
8455
8456	if (pfn_GetDiskFreeSpaceEx(rootname,
8457				   (ULARGE_INTEGER *)&availbytes,
8458				   (ULARGE_INTEGER *)&totalbytes,
8459				   (ULARGE_INTEGER *)&freebytes))
8460	  value = list3 (make_float ((double) totalbytes.QuadPart),
8461			 make_float ((double) freebytes.QuadPart),
8462			 make_float ((double) availbytes.QuadPart));
8463      }
8464    else
8465      {
8466	DWORD sectors_per_cluster;
8467	DWORD bytes_per_sector;
8468	DWORD free_clusters;
8469	DWORD total_clusters;
8470
8471	if (GetDiskFreeSpace(rootname,
8472			     &sectors_per_cluster,
8473			     &bytes_per_sector,
8474			     &free_clusters,
8475			     &total_clusters))
8476	  value = list3 (make_float ((double) total_clusters
8477				     * sectors_per_cluster * bytes_per_sector),
8478			 make_float ((double) free_clusters
8479				     * sectors_per_cluster * bytes_per_sector),
8480			 make_float ((double) free_clusters
8481				     * sectors_per_cluster * bytes_per_sector));
8482      }
8483  }
8484
8485  return value;
8486}
8487
8488DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
8489       0, 0, 0, doc: /* Return the name of Windows default printer device.  */)
8490     ()
8491{
8492  static char pname_buf[256];
8493  int err;
8494  HANDLE hPrn;
8495  PRINTER_INFO_2 *ppi2 = NULL;
8496  DWORD dwNeeded = 0, dwReturned = 0;
8497
8498  /* Retrieve the default string from Win.ini (the registry).
8499   * String will be in form "printername,drivername,portname".
8500   * This is the most portable way to get the default printer. */
8501  if (GetProfileString ("windows", "device", ",,", pname_buf, sizeof (pname_buf)) <= 0)
8502    return Qnil;
8503  /* printername precedes first "," character */
8504  strtok (pname_buf, ",");
8505  /* We want to know more than the printer name */
8506  if (!OpenPrinter (pname_buf, &hPrn, NULL))
8507    return Qnil;
8508  GetPrinter (hPrn, 2, NULL, 0, &dwNeeded);
8509  if (dwNeeded == 0)
8510    {
8511      ClosePrinter (hPrn);
8512      return Qnil;
8513    }
8514  /* Allocate memory for the PRINTER_INFO_2 struct */
8515  ppi2 = (PRINTER_INFO_2 *) xmalloc (dwNeeded);
8516  if (!ppi2)
8517    {
8518      ClosePrinter (hPrn);
8519      return Qnil;
8520    }
8521  /* Call GetPrinter() again with big enouth memory block */
8522  err = GetPrinter (hPrn, 2, (LPBYTE)ppi2, dwNeeded, &dwReturned);
8523  ClosePrinter (hPrn);
8524  if (!err)
8525    {
8526      xfree(ppi2);
8527      return Qnil;
8528    }
8529
8530  if (ppi2)
8531    {
8532      if (ppi2->Attributes & PRINTER_ATTRIBUTE_SHARED && ppi2->pServerName)
8533        {
8534	  /* a remote printer */
8535	  if (*ppi2->pServerName == '\\')
8536	    _snprintf(pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName,
8537		      ppi2->pShareName);
8538	  else
8539	    _snprintf(pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName,
8540		      ppi2->pShareName);
8541	  pname_buf[sizeof (pname_buf) - 1] = '\0';
8542	}
8543      else
8544        {
8545	  /* a local printer */
8546	  strncpy(pname_buf, ppi2->pPortName, sizeof (pname_buf));
8547	  pname_buf[sizeof (pname_buf) - 1] = '\0';
8548	  /* `pPortName' can include several ports, delimited by ','.
8549	   * we only use the first one. */
8550	  strtok(pname_buf, ",");
8551	}
8552      xfree(ppi2);
8553    }
8554
8555  return build_string (pname_buf);
8556}
8557
8558/***********************************************************************
8559			    Initialization
8560 ***********************************************************************/
8561
8562/* Keep this list in the same order as frame_parms in frame.c.
8563   Use 0 for unsupported frame parameters.  */
8564
8565frame_parm_handler w32_frame_parm_handlers[] =
8566{
8567  x_set_autoraise,
8568  x_set_autolower,
8569  x_set_background_color,
8570  x_set_border_color,
8571  x_set_border_width,
8572  x_set_cursor_color,
8573  x_set_cursor_type,
8574  x_set_font,
8575  x_set_foreground_color,
8576  x_set_icon_name,
8577  x_set_icon_type,
8578  x_set_internal_border_width,
8579  x_set_menu_bar_lines,
8580  x_set_mouse_color,
8581  x_explicitly_set_name,
8582  x_set_scroll_bar_width,
8583  x_set_title,
8584  x_set_unsplittable,
8585  x_set_vertical_scroll_bars,
8586  x_set_visibility,
8587  x_set_tool_bar_lines,
8588  0, /* x_set_scroll_bar_foreground, */
8589  0, /* x_set_scroll_bar_background, */
8590  x_set_screen_gamma,
8591  x_set_line_spacing,
8592  x_set_fringe_width,
8593  x_set_fringe_width,
8594  0, /* x_set_wait_for_wm, */
8595  x_set_fullscreen,
8596};
8597
8598void
8599syms_of_w32fns ()
8600{
8601  globals_of_w32fns ();
8602  /* This is zero if not using MS-Windows.  */
8603  w32_in_use = 0;
8604  track_mouse_window = NULL;
8605
8606  w32_visible_system_caret_hwnd = NULL;
8607
8608  Qnone = intern ("none");
8609  staticpro (&Qnone);
8610  Qsuppress_icon = intern ("suppress-icon");
8611  staticpro (&Qsuppress_icon);
8612  Qundefined_color = intern ("undefined-color");
8613  staticpro (&Qundefined_color);
8614  Qcancel_timer = intern ("cancel-timer");
8615  staticpro (&Qcancel_timer);
8616
8617  Qhyper = intern ("hyper");
8618  staticpro (&Qhyper);
8619  Qsuper = intern ("super");
8620  staticpro (&Qsuper);
8621  Qmeta = intern ("meta");
8622  staticpro (&Qmeta);
8623  Qalt = intern ("alt");
8624  staticpro (&Qalt);
8625  Qctrl = intern ("ctrl");
8626  staticpro (&Qctrl);
8627  Qcontrol = intern ("control");
8628  staticpro (&Qcontrol);
8629  Qshift = intern ("shift");
8630  staticpro (&Qshift);
8631  /* This is the end of symbol initialization.  */
8632
8633  /* Text property `display' should be nonsticky by default.  */
8634  Vtext_property_default_nonsticky
8635    = Fcons (Fcons (Qdisplay, Qt), Vtext_property_default_nonsticky);
8636
8637
8638  Fput (Qundefined_color, Qerror_conditions,
8639	Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
8640  Fput (Qundefined_color, Qerror_message,
8641	build_string ("Undefined color"));
8642
8643  staticpro (&w32_grabbed_keys);
8644  w32_grabbed_keys = Qnil;
8645
8646  DEFVAR_LISP ("w32-color-map", &Vw32_color_map,
8647	       doc: /* An array of color name mappings for Windows.  */);
8648  Vw32_color_map = Qnil;
8649
8650  DEFVAR_LISP ("w32-pass-alt-to-system", &Vw32_pass_alt_to_system,
8651	       doc: /* Non-nil if Alt key presses are passed on to Windows.
8652When non-nil, for example, Alt pressed and released and then space will
8653open the System menu.  When nil, Emacs processes the Alt key events, and
8654then silently swallows them.  */);
8655  Vw32_pass_alt_to_system = Qnil;
8656
8657  DEFVAR_LISP ("w32-alt-is-meta", &Vw32_alt_is_meta,
8658	       doc: /* Non-nil if the Alt key is to be considered the same as the META key.
8659When nil, Emacs will translate the Alt key to the ALT modifier, not to META.  */);
8660  Vw32_alt_is_meta = Qt;
8661
8662  DEFVAR_INT ("w32-quit-key", &w32_quit_key,
8663	       doc: /* If non-zero, the virtual key code for an alternative quit key.  */);
8664  w32_quit_key = 0;
8665
8666  DEFVAR_LISP ("w32-pass-lwindow-to-system",
8667	       &Vw32_pass_lwindow_to_system,
8668	       doc: /* If non-nil, the left \"Windows\" key is passed on to Windows.
8669
8670When non-nil, the Start menu is opened by tapping the key.
8671If you set this to nil, the left \"Windows\" key is processed by Emacs
8672according to the value of `w32-lwindow-modifier', which see.
8673
8674Note that some combinations of the left \"Windows\" key with other keys are
8675caught by Windows at low level, and so binding them in Emacs will have no
8676effect.  For example, <lwindow>-r always pops up the Windows Run dialog,
8677<lwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
8678the doc string of `w32-phantom-key-code'.  */);
8679  Vw32_pass_lwindow_to_system = Qt;
8680
8681  DEFVAR_LISP ("w32-pass-rwindow-to-system",
8682	       &Vw32_pass_rwindow_to_system,
8683	       doc: /* If non-nil, the right \"Windows\" key is passed on to Windows.
8684
8685When non-nil, the Start menu is opened by tapping the key.
8686If you set this to nil, the right \"Windows\" key is processed by Emacs
8687according to the value of `w32-rwindow-modifier', which see.
8688
8689Note that some combinations of the right \"Windows\" key with other keys are
8690caught by Windows at low level, and so binding them in Emacs will have no
8691effect.  For example, <rwindow>-r always pops up the Windows Run dialog,
8692<rwindow>-<Pause> pops up the "System Properties" dialog, etc.  However, see
8693the doc string of `w32-phantom-key-code'.  */);
8694  Vw32_pass_rwindow_to_system = Qt;
8695
8696  DEFVAR_LISP ("w32-phantom-key-code",
8697	       &Vw32_phantom_key_code,
8698	       doc: /* Virtual key code used to generate \"phantom\" key presses.
8699Value is a number between 0 and 255.
8700
8701Phantom key presses are generated in order to stop the system from
8702acting on \"Windows\" key events when `w32-pass-lwindow-to-system' or
8703`w32-pass-rwindow-to-system' is nil.  */);
8704  /* Although 255 is technically not a valid key code, it works and
8705     means that this hack won't interfere with any real key code.  */
8706  XSETINT (Vw32_phantom_key_code, 255);
8707
8708  DEFVAR_LISP ("w32-enable-num-lock",
8709	       &Vw32_enable_num_lock,
8710	       doc: /* If non-nil, the Num Lock key acts normally.
8711Set to nil to handle Num Lock as the `kp-numlock' key.  */);
8712  Vw32_enable_num_lock = Qt;
8713
8714  DEFVAR_LISP ("w32-enable-caps-lock",
8715	       &Vw32_enable_caps_lock,
8716	       doc: /* If non-nil, the Caps Lock key acts normally.
8717Set to nil to handle Caps Lock as the `capslock' key.  */);
8718  Vw32_enable_caps_lock = Qt;
8719
8720  DEFVAR_LISP ("w32-scroll-lock-modifier",
8721	       &Vw32_scroll_lock_modifier,
8722	       doc: /* Modifier to use for the Scroll Lock ON state.
8723The value can be hyper, super, meta, alt, control or shift for the
8724respective modifier, or nil to handle Scroll Lock as the `scroll' key.
8725Any other value will cause the Scroll Lock key to be ignored.  */);
8726  Vw32_scroll_lock_modifier = Qt;
8727
8728  DEFVAR_LISP ("w32-lwindow-modifier",
8729	       &Vw32_lwindow_modifier,
8730	       doc: /* Modifier to use for the left \"Windows\" key.
8731The value can be hyper, super, meta, alt, control or shift for the
8732respective modifier, or nil to appear as the `lwindow' key.
8733Any other value will cause the key to be ignored.  */);
8734  Vw32_lwindow_modifier = Qnil;
8735
8736  DEFVAR_LISP ("w32-rwindow-modifier",
8737	       &Vw32_rwindow_modifier,
8738	       doc: /* Modifier to use for the right \"Windows\" key.
8739The value can be hyper, super, meta, alt, control or shift for the
8740respective modifier, or nil to appear as the `rwindow' key.
8741Any other value will cause the key to be ignored.  */);
8742  Vw32_rwindow_modifier = Qnil;
8743
8744  DEFVAR_LISP ("w32-apps-modifier",
8745	       &Vw32_apps_modifier,
8746	       doc: /* Modifier to use for the \"Apps\" key.
8747The value can be hyper, super, meta, alt, control or shift for the
8748respective modifier, or nil to appear as the `apps' key.
8749Any other value will cause the key to be ignored.  */);
8750  Vw32_apps_modifier = Qnil;
8751
8752  DEFVAR_BOOL ("w32-enable-synthesized-fonts", &w32_enable_synthesized_fonts,
8753	       doc: /* Non-nil enables selection of artificially italicized and bold fonts.  */);
8754  w32_enable_synthesized_fonts = 0;
8755
8756  DEFVAR_LISP ("w32-enable-palette", &Vw32_enable_palette,
8757	       doc: /* Non-nil enables Windows palette management to map colors exactly.  */);
8758  Vw32_enable_palette = Qt;
8759
8760  DEFVAR_INT ("w32-mouse-button-tolerance",
8761	      &w32_mouse_button_tolerance,
8762	      doc: /* Analogue of double click interval for faking middle mouse events.
8763The value is the minimum time in milliseconds that must elapse between
8764left and right button down events before they are considered distinct events.
8765If both mouse buttons are depressed within this interval, a middle mouse
8766button down event is generated instead.  */);
8767  w32_mouse_button_tolerance = GetDoubleClickTime () / 2;
8768
8769  DEFVAR_INT ("w32-mouse-move-interval",
8770	      &w32_mouse_move_interval,
8771	      doc: /* Minimum interval between mouse move events.
8772The value is the minimum time in milliseconds that must elapse between
8773successive mouse move (or scroll bar drag) events before they are
8774reported as lisp events.  */);
8775  w32_mouse_move_interval = 0;
8776
8777  DEFVAR_BOOL ("w32-pass-extra-mouse-buttons-to-system",
8778	       &w32_pass_extra_mouse_buttons_to_system,
8779	       doc: /* If non-nil, the fourth and fifth mouse buttons are passed to Windows.
8780Recent versions of Windows support mice with up to five buttons.
8781Since most applications don't support these extra buttons, most mouse
8782drivers will allow you to map them to functions at the system level.
8783If this variable is non-nil, Emacs will pass them on, allowing the
8784system to handle them.  */);
8785  w32_pass_extra_mouse_buttons_to_system = 0;
8786
8787  DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
8788	       doc: /* The shape of the pointer when over text.
8789Changing the value does not affect existing frames
8790unless you set the mouse color.  */);
8791  Vx_pointer_shape = Qnil;
8792
8793  Vx_nontext_pointer_shape = Qnil;
8794
8795  Vx_mode_pointer_shape = Qnil;
8796
8797  DEFVAR_LISP ("x-hourglass-pointer-shape", &Vx_hourglass_pointer_shape,
8798	       doc: /* The shape of the pointer when Emacs is busy.
8799This variable takes effect when you create a new frame
8800or when you set the mouse color.  */);
8801  Vx_hourglass_pointer_shape = Qnil;
8802
8803  DEFVAR_BOOL ("display-hourglass", &display_hourglass_p,
8804	       doc: /* Non-zero means Emacs displays an hourglass pointer on window systems.  */);
8805  display_hourglass_p = 1;
8806
8807  DEFVAR_LISP ("hourglass-delay", &Vhourglass_delay,
8808	       doc: /* *Seconds to wait before displaying an hourglass pointer.
8809Value must be an integer or float.  */);
8810  Vhourglass_delay = make_number (DEFAULT_HOURGLASS_DELAY);
8811
8812  DEFVAR_LISP ("x-sensitive-text-pointer-shape",
8813	      &Vx_sensitive_text_pointer_shape,
8814	       doc: /* The shape of the pointer when over mouse-sensitive text.
8815This variable takes effect when you create a new frame
8816or when you set the mouse color.  */);
8817  Vx_sensitive_text_pointer_shape = Qnil;
8818
8819  DEFVAR_LISP ("x-window-horizontal-drag-cursor",
8820	      &Vx_window_horizontal_drag_shape,
8821	       doc: /* Pointer shape to use for indicating a window can be dragged horizontally.
8822This variable takes effect when you create a new frame
8823or when you set the mouse color.  */);
8824  Vx_window_horizontal_drag_shape = Qnil;
8825
8826  DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
8827	       doc: /* A string indicating the foreground color of the cursor box.  */);
8828  Vx_cursor_fore_pixel = Qnil;
8829
8830  DEFVAR_LISP ("x-max-tooltip-size", &Vx_max_tooltip_size,
8831	       doc: /* Maximum size for tooltips.
8832Value is a pair (COLUMNS . ROWS). Text larger than this is clipped.  */);
8833  Vx_max_tooltip_size = Fcons (make_number (80), make_number (40));
8834
8835  DEFVAR_LISP ("x-no-window-manager", &Vx_no_window_manager,
8836	       doc: /* Non-nil if no window manager is in use.
8837Emacs doesn't try to figure this out; this is always nil
8838unless you set it to something else.  */);
8839  /* We don't have any way to find this out, so set it to nil
8840     and maybe the user would like to set it to t.  */
8841  Vx_no_window_manager = Qnil;
8842
8843  DEFVAR_LISP ("x-pixel-size-width-font-regexp",
8844	       &Vx_pixel_size_width_font_regexp,
8845	       doc: /* Regexp matching a font name whose width is the same as `PIXEL_SIZE'.
8846
8847Since Emacs gets width of a font matching with this regexp from
8848PIXEL_SIZE field of the name, font finding mechanism gets faster for
8849such a font.  This is especially effective for such large fonts as
8850Chinese, Japanese, and Korean.  */);
8851  Vx_pixel_size_width_font_regexp = Qnil;
8852
8853  DEFVAR_LISP ("w32-bdf-filename-alist",
8854               &Vw32_bdf_filename_alist,
8855               doc: /* List of bdf fonts and their corresponding filenames.  */);
8856  Vw32_bdf_filename_alist = Qnil;
8857
8858  DEFVAR_BOOL ("w32-strict-fontnames",
8859               &w32_strict_fontnames,
8860	       doc: /* Non-nil means only use fonts that are exact matches for those requested.
8861Default is nil, which allows old fontnames that are not XLFD compliant,
8862and allows third-party CJK display to work by specifying false charset
8863fields to trick Emacs into translating to Big5, SJIS etc.
8864Setting this to t will prevent wrong fonts being selected when
8865fontsets are automatically created.  */);
8866  w32_strict_fontnames = 0;
8867
8868  DEFVAR_BOOL ("w32-strict-painting",
8869               &w32_strict_painting,
8870	       doc: /* Non-nil means use strict rules for repainting frames.
8871Set this to nil to get the old behavior for repainting; this should
8872only be necessary if the default setting causes problems.  */);
8873  w32_strict_painting = 1;
8874
8875  DEFVAR_LISP ("w32-charset-info-alist",
8876               &Vw32_charset_info_alist,
8877               doc: /* Alist linking Emacs character sets to Windows fonts and codepages.
8878Each entry should be of the form:
8879
8880   (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))
8881
8882where CHARSET_NAME is a string used in font names to identify the charset,
8883WINDOWS_CHARSET is a symbol that can be one of:
8884w32-charset-ansi, w32-charset-default, w32-charset-symbol,
8885w32-charset-shiftjis, w32-charset-hangeul, w32-charset-gb2312,
8886w32-charset-chinesebig5,
8887w32-charset-johab, w32-charset-hebrew,
8888w32-charset-arabic, w32-charset-greek, w32-charset-turkish,
8889w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,
8890w32-charset-russian, w32-charset-mac, w32-charset-baltic,
8891w32-charset-unicode,
8892or w32-charset-oem.
8893CODEPAGE should be an integer specifying the codepage that should be used
8894to display the character set, t to do no translation and output as Unicode,
8895or nil to do no translation and output as 8 bit (or multibyte on far-east
8896versions of Windows) characters.  */);
8897    Vw32_charset_info_alist = Qnil;
8898
8899  staticpro (&Qw32_charset_ansi);
8900  Qw32_charset_ansi = intern ("w32-charset-ansi");
8901  staticpro (&Qw32_charset_symbol);
8902  Qw32_charset_default = intern ("w32-charset-default");
8903  staticpro (&Qw32_charset_default);
8904  Qw32_charset_symbol = intern ("w32-charset-symbol");
8905  staticpro (&Qw32_charset_shiftjis);
8906  Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
8907  staticpro (&Qw32_charset_hangeul);
8908  Qw32_charset_hangeul = intern ("w32-charset-hangeul");
8909  staticpro (&Qw32_charset_chinesebig5);
8910  Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
8911  staticpro (&Qw32_charset_gb2312);
8912  Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
8913  staticpro (&Qw32_charset_oem);
8914  Qw32_charset_oem = intern ("w32-charset-oem");
8915
8916#ifdef JOHAB_CHARSET
8917  {
8918    static int w32_extra_charsets_defined = 1;
8919    DEFVAR_BOOL ("w32-extra-charsets-defined", &w32_extra_charsets_defined,
8920		 doc: /* Internal variable.  */);
8921
8922    staticpro (&Qw32_charset_johab);
8923    Qw32_charset_johab = intern ("w32-charset-johab");
8924    staticpro (&Qw32_charset_easteurope);
8925    Qw32_charset_easteurope = intern ("w32-charset-easteurope");
8926    staticpro (&Qw32_charset_turkish);
8927    Qw32_charset_turkish = intern ("w32-charset-turkish");
8928    staticpro (&Qw32_charset_baltic);
8929    Qw32_charset_baltic = intern ("w32-charset-baltic");
8930    staticpro (&Qw32_charset_russian);
8931    Qw32_charset_russian = intern ("w32-charset-russian");
8932    staticpro (&Qw32_charset_arabic);
8933    Qw32_charset_arabic = intern ("w32-charset-arabic");
8934    staticpro (&Qw32_charset_greek);
8935    Qw32_charset_greek = intern ("w32-charset-greek");
8936    staticpro (&Qw32_charset_hebrew);
8937    Qw32_charset_hebrew = intern ("w32-charset-hebrew");
8938    staticpro (&Qw32_charset_vietnamese);
8939    Qw32_charset_vietnamese = intern ("w32-charset-vietnamese");
8940    staticpro (&Qw32_charset_thai);
8941    Qw32_charset_thai = intern ("w32-charset-thai");
8942    staticpro (&Qw32_charset_mac);
8943    Qw32_charset_mac = intern ("w32-charset-mac");
8944  }
8945#endif
8946
8947#ifdef UNICODE_CHARSET
8948  {
8949    static int w32_unicode_charset_defined = 1;
8950    DEFVAR_BOOL ("w32-unicode-charset-defined",
8951                 &w32_unicode_charset_defined,
8952		 doc: /* Internal variable.  */);
8953
8954    staticpro (&Qw32_charset_unicode);
8955    Qw32_charset_unicode = intern ("w32-charset-unicode");
8956  }
8957#endif
8958
8959#if 0 /* TODO: Port to W32 */
8960  defsubr (&Sx_change_window_property);
8961  defsubr (&Sx_delete_window_property);
8962  defsubr (&Sx_window_property);
8963#endif
8964  defsubr (&Sxw_display_color_p);
8965  defsubr (&Sx_display_grayscale_p);
8966  defsubr (&Sxw_color_defined_p);
8967  defsubr (&Sxw_color_values);
8968  defsubr (&Sx_server_max_request_size);
8969  defsubr (&Sx_server_vendor);
8970  defsubr (&Sx_server_version);
8971  defsubr (&Sx_display_pixel_width);
8972  defsubr (&Sx_display_pixel_height);
8973  defsubr (&Sx_display_mm_width);
8974  defsubr (&Sx_display_mm_height);
8975  defsubr (&Sx_display_screens);
8976  defsubr (&Sx_display_planes);
8977  defsubr (&Sx_display_color_cells);
8978  defsubr (&Sx_display_visual_class);
8979  defsubr (&Sx_display_backing_store);
8980  defsubr (&Sx_display_save_under);
8981  defsubr (&Sx_create_frame);
8982  defsubr (&Sx_open_connection);
8983  defsubr (&Sx_close_connection);
8984  defsubr (&Sx_display_list);
8985  defsubr (&Sx_synchronize);
8986
8987  /* W32 specific functions */
8988
8989  defsubr (&Sw32_focus_frame);
8990  defsubr (&Sw32_select_font);
8991  defsubr (&Sw32_define_rgb_color);
8992  defsubr (&Sw32_default_color_map);
8993  defsubr (&Sw32_load_color_file);
8994  defsubr (&Sw32_send_sys_command);
8995  defsubr (&Sw32_shell_execute);
8996  defsubr (&Sw32_register_hot_key);
8997  defsubr (&Sw32_unregister_hot_key);
8998  defsubr (&Sw32_registered_hot_keys);
8999  defsubr (&Sw32_reconstruct_hot_key);
9000  defsubr (&Sw32_toggle_lock_key);
9001  defsubr (&Sw32_window_exists_p);
9002  defsubr (&Sw32_find_bdf_fonts);
9003
9004  defsubr (&Sfile_system_info);
9005  defsubr (&Sdefault_printer_name);
9006
9007  /* Setting callback functions for fontset handler.  */
9008  get_font_info_func = w32_get_font_info;
9009
9010#if 0 /* This function pointer doesn't seem to be used anywhere.
9011	 And the pointer assigned has the wrong type, anyway.  */
9012  list_fonts_func = w32_list_fonts;
9013#endif
9014
9015  load_font_func = w32_load_font;
9016  find_ccl_program_func = w32_find_ccl_program;
9017  query_font_func = w32_query_font;
9018  set_frame_fontset_func = x_set_font;
9019  check_window_system_func = check_w32;
9020
9021
9022  hourglass_atimer = NULL;
9023  hourglass_shown_p = 0;
9024  defsubr (&Sx_show_tip);
9025  defsubr (&Sx_hide_tip);
9026  tip_timer = Qnil;
9027  staticpro (&tip_timer);
9028  tip_frame = Qnil;
9029  staticpro (&tip_frame);
9030
9031  last_show_tip_args = Qnil;
9032  staticpro (&last_show_tip_args);
9033
9034  defsubr (&Sx_file_dialog);
9035}
9036
9037
9038/*
9039	globals_of_w32fns is used to initialize those global variables that
9040	must always be initialized on startup even when the global variable
9041	initialized is non zero (see the function main in emacs.c).
9042	globals_of_w32fns is called from syms_of_w32fns when the global
9043	variable initialized is 0 and directly from main when initialized
9044	is non zero.
9045 */
9046void globals_of_w32fns ()
9047{
9048  HMODULE user32_lib = GetModuleHandle ("user32.dll");
9049  /*
9050    TrackMouseEvent not available in all versions of Windows, so must load
9051    it dynamically.  Do it once, here, instead of every time it is used.
9052  */
9053  track_mouse_event_fn = (TrackMouseEvent_Proc)
9054    GetProcAddress (user32_lib, "TrackMouseEvent");
9055  /* ditto for GetClipboardSequenceNumber.  */
9056  clipboard_sequence_fn = (ClipboardSequence_Proc)
9057    GetProcAddress (user32_lib, "GetClipboardSequenceNumber");
9058
9059  DEFVAR_INT ("w32-ansi-code-page",
9060	      &w32_ansi_code_page,
9061	      doc: /* The ANSI code page used by the system.  */);
9062  w32_ansi_code_page = GetACP ();
9063}
9064
9065#undef abort
9066
9067void w32_abort (void) NO_RETURN;
9068
9069void
9070w32_abort()
9071{
9072  int button;
9073  button = MessageBox (NULL,
9074		       "A fatal error has occurred!\n\n"
9075		       "Would you like to attach a debugger?\n\n"
9076		       "Select YES to debug, NO to abort Emacs"
9077#if __GNUC__
9078		       "\n\n(type \"gdb -p <emacs-PID>\" and\n"
9079		       "\"continue\" inside GDB before clicking YES.)"
9080#endif
9081		       , "Emacs Abort Dialog",
9082		       MB_ICONEXCLAMATION | MB_TASKMODAL
9083		       | MB_SETFOREGROUND | MB_YESNO);
9084  switch (button)
9085    {
9086    case IDYES:
9087      DebugBreak ();
9088      exit (2);	/* tell the compiler we will never return */
9089    case IDNO:
9090    default:
9091      abort ();
9092      break;
9093    }
9094}
9095
9096/* For convenience when debugging.  */
9097int
9098w32_last_error()
9099{
9100  return GetLastError ();
9101}
9102
9103/* arch-tag: 707589ab-b9be-4638-8cdd-74629cc9b446
9104   (do not change this comment) */
9105