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