(last_event_timestamp): Declare, but don't define.
[bpt/emacs.git] / src / w32fns.c
index 22a5149..4753caf 100644 (file)
@@ -1,5 +1,5 @@
 /* Functions for the Win32 window system.
-   Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation.
+   Copyright (C) 1989, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 /* Added by Kevin Gallo */
 
@@ -40,10 +41,37 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern void abort ();
 extern void free_frame_menubar ();
 extern struct scroll_bar *x_window_to_scroll_bar ();
+extern int quit_char;
 
 /* The colormap for converting color names to RGB values */
 Lisp_Object Vwin32_color_map;
 
+/* Non nil if alt key presses are passed on to Windows.  */
+Lisp_Object Vwin32_pass_alt_to_system;
+
+/* Non nil if alt key is translated to meta_modifier, nil if it is translated
+   to alt_modifier.  */
+Lisp_Object Vwin32_alt_is_meta;
+
+/* Non nil if left window, right window, and application key events
+   are passed on to Windows.  */
+Lisp_Object Vwin32_pass_optional_keys_to_system;
+
+/* Switch to control whether we inhibit requests for italicised fonts (which
+   are synthesized, look ugly, and are trashed by cursor movement under NT). */
+Lisp_Object Vwin32_enable_italics;
+
+/* Enable palette management. */
+Lisp_Object Vwin32_enable_palette;
+
+/* Control how close left/right button down events must be to
+   be converted to a middle button down event. */
+Lisp_Object Vwin32_mouse_button_tolerance;
+
+/* Minimum interval between mouse movement (and scroll bar drag)
+   events that are passed on to the event loop. */
+Lisp_Object Vwin32_mouse_move_interval;
+
 /* The name we're using in resource queries.  */
 Lisp_Object Vx_resource_name;
 
@@ -106,7 +134,6 @@ Lisp_Object Qborder_width;
 Lisp_Object Qbox;
 Lisp_Object Qcursor_color;
 Lisp_Object Qcursor_type;
-Lisp_Object Qfont;
 Lisp_Object Qforeground_color;
 Lisp_Object Qgeometry;
 Lisp_Object Qicon_left;
@@ -131,6 +158,20 @@ Lisp_Object Quser_position;
 Lisp_Object Quser_size;
 Lisp_Object Qdisplay;
 
+/* State variables for emulating a three button mouse. */
+#define LMOUSE 1
+#define MMOUSE 2
+#define RMOUSE 4
+
+static int button_state = 0;
+static Win32Msg saved_mouse_button_msg;
+static unsigned mouse_button_timer;    /* non-zero when timer is active */
+static Win32Msg saved_mouse_move_msg;
+static unsigned mouse_move_timer;
+
+#define MOUSE_BUTTON_ID        1
+#define MOUSE_MOVE_ID  2
+
 /* The below are defined in frame.c.  */
 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
 extern Lisp_Object Qunsplittable, Qmenu_bar_lines;
@@ -139,6 +180,10 @@ extern Lisp_Object Vwindow_system_version;
 
 extern Lisp_Object last_mouse_scroll_bar;
 extern int last_mouse_scroll_bar_pos;
+
+/* From win32term.c. */
+extern Lisp_Object Vwin32_num_mouse_buttons;
+
 Time last_mouse_movement_time;
 
 \f
@@ -815,25 +860,90 @@ x_report_frame_params (f, alistptr)
 }
 \f
 
-#if 0
-DEFUN ("win32-rgb", Fwin32_rgb, Swin32_rgb, 3, 3, 0,
-       "Convert RGB numbers to a windows color reference.")
-    (red, green, blue)
-    Lisp_Object red, green, blue;
+DEFUN ("win32-define-rgb-color", Fwin32_define_rgb_color, Swin32_define_rgb_color, 4, 4, 0,
+  "Convert RGB numbers to a windows color reference and associate with NAME (a string).\n\
+This adds or updates a named color to win32-color-map, making it available for use.\n\
+The original entry's RGB ref is returned, or nil if the entry is new.")
+    (red, green, blue, name)
+    Lisp_Object red, green, blue, name;
 {
-    Lisp_Object rgb;
+  Lisp_Object rgb;
+  Lisp_Object oldrgb = Qnil;
+  Lisp_Object entry;
+
+  CHECK_NUMBER (red, 0);
+  CHECK_NUMBER (green, 0);
+  CHECK_NUMBER (blue, 0);
+  CHECK_STRING (name, 0);
+
+  XSET (rgb, Lisp_Int, RGB(XUINT (red), XUINT (green), XUINT (blue)));
 
-    CHECK_NUMBER (red, 0);
-    CHECK_NUMBER (green, 0);
-    CHECK_NUMBER (blue, 0);
+  BLOCK_INPUT;
+
+  /* replace existing entry in win32-color-map or add new entry. */
+  entry = Fassoc (name, Vwin32_color_map);
+  if (NILP (entry))
+    {
+      entry = Fcons (name, rgb);
+      Vwin32_color_map = Fcons (entry, Vwin32_color_map);
+    }
+  else
+    {
+      oldrgb = Fcdr (entry);
+      Fsetcdr (entry, rgb);
+    }
 
-    XSET (rgb, Lisp_Int, RGB(XUINT(red), XUINT(green), XUINT(blue)));
+  UNBLOCK_INPUT;
 
-    return (rgb);
+  return (oldrgb);
 }
 
+DEFUN ("win32-load-color-file", Fwin32_load_color_file, Swin32_load_color_file, 1, 1, 0,
+  "Create an alist of color entries from an external file (ie. rgb.txt).\n\
+Assign this value to win32-color-map to replace the existing color map.\n\
+\
+The file should define one named RGB color per line like so:\
+  R G B   name\n\
+where R,G,B are numbers between 0 and 255 and name is an arbitrary string.")
+    (filename)
+    Lisp_Object filename;
+{
+  FILE *fp;
+  Lisp_Object cmap = Qnil;
+  Lisp_Object abspath;
+
+  CHECK_STRING (filename, 0);
+  abspath = Fexpand_file_name (filename, Qnil);
+
+  fp = fopen (XSTRING (filename)->data, "rt");
+  if (fp)
+    {
+      char buf[512];
+      int red, green, blue;
+      int num;
+
+      BLOCK_INPUT;
+
+      while (fgets (buf, sizeof (buf), fp) != NULL) {
+       if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
+         {
+           char *name = buf + num;
+           num = strlen (name) - 1;
+           if (name[num] == '\n')
+             name[num] = 0;
+           cmap = Fcons (Fcons (build_string (name),
+                                make_number (RGB (red, green, blue))),
+                         cmap);
+         }
+      }
+      fclose (fp);
+
+      UNBLOCK_INPUT;
+    }
+
+  return cmap;
+}
 
-#else
 /* The default colors for the win32 color map */
 typedef struct colormap_t 
 {
@@ -843,246 +953,246 @@ typedef struct colormap_t
 
 colormap_t win32_color_map[] = 
 {
-  {"snow"                      , RGB (255,250,250)},
-  {"ghost white"               , RGB (248,248,255)},
-  {"GhostWhite"                , RGB (248,248,255)},
-  {"white smoke"               , RGB (245,245,245)},
-  {"WhiteSmoke"                , RGB (245,245,245)},
-  {"gainsboro"                 , RGB (220,220,220)},
-  {"floral white"              , RGB (255,250,240)},
-  {"FloralWhite"               , RGB (255,250,240)},
-  {"old lace"                  , RGB (253,245,230)},
-  {"OldLace"                   , RGB (253,245,230)},
-  {"linen"                     , RGB (250,240,230)},
-  {"antique white"             , RGB (250,235,215)},
-  {"AntiqueWhite"              , RGB (250,235,215)},
-  {"papaya whip"               , RGB (255,239,213)},
-  {"PapayaWhip"                , RGB (255,239,213)},
-  {"blanched almond"           , RGB (255,235,205)},
-  {"BlanchedAlmond"            , RGB (255,235,205)},
-  {"bisque"                    , RGB (255,228,196)},
-  {"peach puff"                , RGB (255,218,185)},
-  {"PeachPuff"                 , RGB (255,218,185)},
-  {"navajo white"              , RGB (255,222,173)},
-  {"NavajoWhite"               , RGB (255,222,173)},
-  {"moccasin"                  , RGB (255,228,181)},
-  {"cornsilk"                  , RGB (255,248,220)},
-  {"ivory"                     , RGB (255,255,240)},
-  {"lemon chiffon"             , RGB (255,250,205)},
-  {"LemonChiffon"              , RGB (255,250,205)},
-  {"seashell"                  , RGB (255,245,238)},
-  {"honeydew"                  , RGB (240,255,240)},
-  {"mint cream"                , RGB (245,255,250)},
-  {"MintCream"                 , RGB (245,255,250)},
-  {"azure"                     , RGB (240,255,255)},
-  {"alice blue"                , RGB (240,248,255)},
-  {"AliceBlue"                 , RGB (240,248,255)},
-  {"lavender"                  , RGB (230,230,250)},
-  {"lavender blush"            , RGB (255,240,245)},
-  {"LavenderBlush"             , RGB (255,240,245)},
-  {"misty rose"                , RGB (255,228,225)},
-  {"MistyRose"                 , RGB (255,228,225)},
-  {"white"                     , RGB (255,255,255)},
-  {"black"                     , RGB (  0,  0,  0)},
-  {"dark slate gray"           , RGB ( 47, 79, 79)},
-  {"DarkSlateGray"             , RGB ( 47, 79, 79)},
-  {"dark slate grey"           , RGB ( 47, 79, 79)},
-  {"DarkSlateGrey"             , RGB ( 47, 79, 79)},
-  {"dim gray"                  , RGB (105,105,105)},
-  {"DimGray"                   , RGB (105,105,105)},
-  {"dim grey"                  , RGB (105,105,105)},
-  {"DimGrey"                   , RGB (105,105,105)},
-  {"slate gray"                , RGB (112,128,144)},
-  {"SlateGray"                 , RGB (112,128,144)},
-  {"slate grey"                , RGB (112,128,144)},
-  {"SlateGrey"                 , RGB (112,128,144)},
-  {"light slate gray"          , RGB (119,136,153)},
-  {"LightSlateGray"            , RGB (119,136,153)},
-  {"light slate grey"          , RGB (119,136,153)},
-  {"LightSlateGrey"            , RGB (119,136,153)},
-  {"gray"                      , RGB (190,190,190)},
-  {"grey"                      , RGB (190,190,190)},
-  {"light grey"                , RGB (211,211,211)},
-  {"LightGrey"                 , RGB (211,211,211)},
-  {"light gray"                , RGB (211,211,211)},
-  {"LightGray"                 , RGB (211,211,211)},
-  {"midnight blue"             , RGB ( 25, 25,112)},
-  {"MidnightBlue"              , RGB ( 25, 25,112)},
-  {"navy"                      , RGB (  0,  0,128)},
-  {"navy blue"                 , RGB (  0,  0,128)},
-  {"NavyBlue"                  , RGB (  0,  0,128)},
-  {"cornflower blue"           , RGB (100,149,237)},
-  {"CornflowerBlue"            , RGB (100,149,237)},
-  {"dark slate blue"           , RGB ( 72, 61,139)},
-  {"DarkSlateBlue"             , RGB ( 72, 61,139)},
-  {"slate blue"                , RGB (106, 90,205)},
-  {"SlateBlue"                 , RGB (106, 90,205)},
-  {"medium slate blue"         , RGB (123,104,238)},
-  {"MediumSlateBlue"           , RGB (123,104,238)},
-  {"light slate blue"          , RGB (132,112,255)},
-  {"LightSlateBlue"            , RGB (132,112,255)},
-  {"medium blue"               , RGB (  0,  0,205)},
-  {"MediumBlue"                , RGB (  0,  0,205)},
-  {"royal blue"                , RGB ( 65,105,225)},
-  {"RoyalBlue"                 , RGB ( 65,105,225)},
-  {"blue"                      , RGB (  0,  0,255)},
-  {"dodger blue"               , RGB ( 30,144,255)},
-  {"DodgerBlue"                , RGB ( 30,144,255)},
-  {"deep sky blue"             , RGB (  0,191,255)},
-  {"DeepSkyBlue"               , RGB (  0,191,255)},
-  {"sky blue"                  , RGB (135,206,235)},
-  {"SkyBlue"                   , RGB (135,206,235)},
-  {"light sky blue"            , RGB (135,206,250)},
-  {"LightSkyBlue"              , RGB (135,206,250)},
-  {"steel blue"                , RGB ( 70,130,180)},
-  {"SteelBlue"                 , RGB ( 70,130,180)},
-  {"light steel blue"          , RGB (176,196,222)},
-  {"LightSteelBlue"            , RGB (176,196,222)},
-  {"light blue"                , RGB (173,216,230)},
-  {"LightBlue"                 , RGB (173,216,230)},
-  {"powder blue"               , RGB (176,224,230)},
-  {"PowderBlue"                , RGB (176,224,230)},
-  {"pale turquoise"            , RGB (175,238,238)},
-  {"PaleTurquoise"             , RGB (175,238,238)},
-  {"dark turquoise"            , RGB (  0,206,209)},
-  {"DarkTurquoise"             , RGB (  0,206,209)},
-  {"medium turquoise"          , RGB ( 72,209,204)},
-  {"MediumTurquoise"           , RGB ( 72,209,204)},
-  {"turquoise"                 , RGB ( 64,224,208)},
-  {"cyan"                      , RGB (  0,255,255)},
-  {"light cyan"                , RGB (224,255,255)},
-  {"LightCyan"                 , RGB (224,255,255)},
-  {"cadet blue"                , RGB ( 95,158,160)},
-  {"CadetBlue"                 , RGB ( 95,158,160)},
-  {"medium aquamarine"         , RGB (102,205,170)},
-  {"MediumAquamarine"          , RGB (102,205,170)},
-  {"aquamarine"                , RGB (127,255,212)},
-  {"dark green"                , RGB (  0,100,  0)},
-  {"DarkGreen"                 , RGB (  0,100,  0)},
-  {"dark olive green"          , RGB ( 85,107, 47)},
-  {"DarkOliveGreen"            , RGB ( 85,107, 47)},
-  {"dark sea green"            , RGB (143,188,143)},
-  {"DarkSeaGreen"              , RGB (143,188,143)},
-  {"sea green"                 , RGB ( 46,139, 87)},
-  {"SeaGreen"                  , RGB ( 46,139, 87)},
-  {"medium sea green"          , RGB ( 60,179,113)},
-  {"MediumSeaGreen"            , RGB ( 60,179,113)},
-  {"light sea green"           , RGB ( 32,178,170)},
-  {"LightSeaGreen"             , RGB ( 32,178,170)},
-  {"pale green"                , RGB (152,251,152)},
-  {"PaleGreen"                 , RGB (152,251,152)},
-  {"spring green"              , RGB (  0,255,127)},
-  {"SpringGreen"               , RGB (  0,255,127)},
-  {"lawn green"                , RGB (124,252,  0)},
-  {"LawnGreen"                 , RGB (124,252,  0)},
-  {"green"                     , RGB (  0,255,  0)},
-  {"chartreuse"                , RGB (127,255,  0)},
-  {"medium spring green"       , RGB (  0,250,154)},
-  {"MediumSpringGreen"         , RGB (  0,250,154)},
-  {"green yellow"              , RGB (173,255, 47)},
-  {"GreenYellow"               , RGB (173,255, 47)},
-  {"lime green"                , RGB ( 50,205, 50)},
-  {"LimeGreen"                 , RGB ( 50,205, 50)},
-  {"yellow green"              , RGB (154,205, 50)},
-  {"YellowGreen"               , RGB (154,205, 50)},
-  {"forest green"              , RGB ( 34,139, 34)},
-  {"ForestGreen"               , RGB ( 34,139, 34)},
-  {"olive drab"                , RGB (107,142, 35)},
-  {"OliveDrab"                 , RGB (107,142, 35)},
-  {"dark khaki"                , RGB (189,183,107)},
-  {"DarkKhaki"                 , RGB (189,183,107)},
-  {"khaki"                     , RGB (240,230,140)},
-  {"pale goldenrod"            , RGB (238,232,170)},
-  {"PaleGoldenrod"             , RGB (238,232,170)},
-  {"light goldenrod yellow"    , RGB (250,250,210)},
-  {"LightGoldenrodYellow"      , RGB (250,250,210)},
-  {"light yellow"              , RGB (255,255,224)},
-  {"LightYellow"               , RGB (255,255,224)},
-  {"yellow"                    , RGB (255,255,  0)},
-  {"gold"                      , RGB (255,215,  0)},
-  {"light goldenrod"           , RGB (238,221,130)},
-  {"LightGoldenrod"            , RGB (238,221,130)},
-  {"goldenrod"                 , RGB (218,165, 32)},
-  {"dark goldenrod"            , RGB (184,134, 11)},
-  {"DarkGoldenrod"             , RGB (184,134, 11)},
-  {"rosy brown"                , RGB (188,143,143)},
-  {"RosyBrown"                 , RGB (188,143,143)},
-  {"indian red"                , RGB (205, 92, 92)},
-  {"IndianRed"                 , RGB (205, 92, 92)},
-  {"saddle brown"              , RGB (139, 69, 19)},
-  {"SaddleBrown"               , RGB (139, 69, 19)},
-  {"sienna"                    , RGB (160, 82, 45)},
-  {"peru"                      , RGB (205,133, 63)},
-  {"burlywood"                 , RGB (222,184,135)},
-  {"beige"                     , RGB (245,245,220)},
-  {"wheat"                     , RGB (245,222,179)},
-  {"sandy brown"               , RGB (244,164, 96)},
-  {"SandyBrown"                , RGB (244,164, 96)},
-  {"tan"                       , RGB (210,180,140)},
-  {"chocolate"                 , RGB (210,105, 30)},
-  {"firebrick"                 , RGB (178,34, 34)},
-  {"brown"                     , RGB (165,42, 42)},
-  {"dark salmon"               , RGB (233,150,122)},
-  {"DarkSalmon"                , RGB (233,150,122)},
-  {"salmon"                    , RGB (250,128,114)},
-  {"light salmon"              , RGB (255,160,122)},
-  {"LightSalmon"               , RGB (255,160,122)},
-  {"orange"                    , RGB (255,165,  0)},
-  {"dark orange"               , RGB (255,140,  0)},
-  {"DarkOrange"                , RGB (255,140,  0)},
-  {"coral"                     , RGB (255,127, 80)},
-  {"light coral"               , RGB (240,128,128)},
-  {"LightCoral"                , RGB (240,128,128)},
-  {"tomato"                    , RGB (255, 99, 71)},
-  {"orange red"                , RGB (255, 69,  0)},
-  {"OrangeRed"                 , RGB (255, 69,  0)},
-  {"red"                       , RGB (255,  0,  0)},
-  {"hot pink"                  , RGB (255,105,180)},
-  {"HotPink"                   , RGB (255,105,180)},
-  {"deep pink"                 , RGB (255, 20,147)},
-  {"DeepPink"                  , RGB (255, 20,147)},
-  {"pink"                      , RGB (255,192,203)},
-  {"light pink"                , RGB (255,182,193)},
-  {"LightPink"                 , RGB (255,182,193)},
-  {"pale violet red"           , RGB (219,112,147)},
-  {"PaleVioletRed"             , RGB (219,112,147)},
-  {"maroon"                    , RGB (176, 48, 96)},
-  {"medium violet red"         , RGB (199, 21,133)},
-  {"MediumVioletRed"           , RGB (199, 21,133)},
-  {"violet red"                , RGB (208, 32,144)},
-  {"VioletRed"                 , RGB (208, 32,144)},
-  {"magenta"                   , RGB (255,  0,255)},
-  {"violet"                    , RGB (238,130,238)},
-  {"plum"                      , RGB (221,160,221)},
-  {"orchid"                    , RGB (218,112,214)},
-  {"medium orchid"             , RGB (186, 85,211)},
-  {"MediumOrchid"              , RGB (186, 85,211)},
-  {"dark orchid"               , RGB (153, 50,204)},
-  {"DarkOrchid"                , RGB (153, 50,204)},
-  {"dark violet"               , RGB (148,  0,211)},
-  {"DarkViolet"                , RGB (148,  0,211)},
-  {"blue violet"               , RGB (138, 43,226)},
-  {"BlueViolet"                , RGB (138, 43,226)},
-  {"purple"                    , RGB (160, 32,240)},
-  {"medium purple"             , RGB (147,112,219)},
-  {"MediumPurple"              , RGB (147,112,219)},
-  {"thistle"                   , RGB (216,191,216)},
-  {"gray0"                     , RGB (  0,  0,  0)},
-  {"grey0"                     , RGB (  0,  0,  0)},
-  {"dark grey"                 , RGB (169,169,169)},
-  {"DarkGrey"                  , RGB (169,169,169)},
-  {"dark gray"                 , RGB (169,169,169)},
-  {"DarkGray"                  , RGB (169,169,169)},
-  {"dark blue"                 , RGB (  0,  0,139)},
-  {"DarkBlue"                  , RGB (  0,  0,139)},
-  {"dark cyan"                 , RGB (  0,139,139)},
-  {"DarkCyan"                  , RGB (  0,139,139)},
-  {"dark magenta"              , RGB (139,  0,139)},
-  {"DarkMagenta"               , RGB (139,  0,139)},
-  {"dark red"                  , RGB (139,  0,  0)},
-  {"DarkRed"                   , RGB (139,  0,  0)},
-  {"light green"               , RGB (144,238,144)},
-  {"LightGreen"                , RGB (144,238,144)},
+  {"snow"                      , PALETTERGB (255,250,250)},
+  {"ghost white"               , PALETTERGB (248,248,255)},
+  {"GhostWhite"                , PALETTERGB (248,248,255)},
+  {"white smoke"               , PALETTERGB (245,245,245)},
+  {"WhiteSmoke"                , PALETTERGB (245,245,245)},
+  {"gainsboro"                 , PALETTERGB (220,220,220)},
+  {"floral white"              , PALETTERGB (255,250,240)},
+  {"FloralWhite"               , PALETTERGB (255,250,240)},
+  {"old lace"                  , PALETTERGB (253,245,230)},
+  {"OldLace"                   , PALETTERGB (253,245,230)},
+  {"linen"                     , PALETTERGB (250,240,230)},
+  {"antique white"             , PALETTERGB (250,235,215)},
+  {"AntiqueWhite"              , PALETTERGB (250,235,215)},
+  {"papaya whip"               , PALETTERGB (255,239,213)},
+  {"PapayaWhip"                , PALETTERGB (255,239,213)},
+  {"blanched almond"           , PALETTERGB (255,235,205)},
+  {"BlanchedAlmond"            , PALETTERGB (255,235,205)},
+  {"bisque"                    , PALETTERGB (255,228,196)},
+  {"peach puff"                , PALETTERGB (255,218,185)},
+  {"PeachPuff"                 , PALETTERGB (255,218,185)},
+  {"navajo white"              , PALETTERGB (255,222,173)},
+  {"NavajoWhite"               , PALETTERGB (255,222,173)},
+  {"moccasin"                  , PALETTERGB (255,228,181)},
+  {"cornsilk"                  , PALETTERGB (255,248,220)},
+  {"ivory"                     , PALETTERGB (255,255,240)},
+  {"lemon chiffon"             , PALETTERGB (255,250,205)},
+  {"LemonChiffon"              , PALETTERGB (255,250,205)},
+  {"seashell"                  , PALETTERGB (255,245,238)},
+  {"honeydew"                  , PALETTERGB (240,255,240)},
+  {"mint cream"                , PALETTERGB (245,255,250)},
+  {"MintCream"                 , PALETTERGB (245,255,250)},
+  {"azure"                     , PALETTERGB (240,255,255)},
+  {"alice blue"                , PALETTERGB (240,248,255)},
+  {"AliceBlue"                 , PALETTERGB (240,248,255)},
+  {"lavender"                  , PALETTERGB (230,230,250)},
+  {"lavender blush"            , PALETTERGB (255,240,245)},
+  {"LavenderBlush"             , PALETTERGB (255,240,245)},
+  {"misty rose"                , PALETTERGB (255,228,225)},
+  {"MistyRose"                 , PALETTERGB (255,228,225)},
+  {"white"                     , PALETTERGB (255,255,255)},
+  {"black"                     , PALETTERGB (  0,  0,  0)},
+  {"dark slate gray"           , PALETTERGB ( 47, 79, 79)},
+  {"DarkSlateGray"             , PALETTERGB ( 47, 79, 79)},
+  {"dark slate grey"           , PALETTERGB ( 47, 79, 79)},
+  {"DarkSlateGrey"             , PALETTERGB ( 47, 79, 79)},
+  {"dim gray"                  , PALETTERGB (105,105,105)},
+  {"DimGray"                   , PALETTERGB (105,105,105)},
+  {"dim grey"                  , PALETTERGB (105,105,105)},
+  {"DimGrey"                   , PALETTERGB (105,105,105)},
+  {"slate gray"                , PALETTERGB (112,128,144)},
+  {"SlateGray"                 , PALETTERGB (112,128,144)},
+  {"slate grey"                , PALETTERGB (112,128,144)},
+  {"SlateGrey"                 , PALETTERGB (112,128,144)},
+  {"light slate gray"          , PALETTERGB (119,136,153)},
+  {"LightSlateGray"            , PALETTERGB (119,136,153)},
+  {"light slate grey"          , PALETTERGB (119,136,153)},
+  {"LightSlateGrey"            , PALETTERGB (119,136,153)},
+  {"gray"                      , PALETTERGB (190,190,190)},
+  {"grey"                      , PALETTERGB (190,190,190)},
+  {"light grey"                , PALETTERGB (211,211,211)},
+  {"LightGrey"                 , PALETTERGB (211,211,211)},
+  {"light gray"                , PALETTERGB (211,211,211)},
+  {"LightGray"                 , PALETTERGB (211,211,211)},
+  {"midnight blue"             , PALETTERGB ( 25, 25,112)},
+  {"MidnightBlue"              , PALETTERGB ( 25, 25,112)},
+  {"navy"                      , PALETTERGB (  0,  0,128)},
+  {"navy blue"                 , PALETTERGB (  0,  0,128)},
+  {"NavyBlue"                  , PALETTERGB (  0,  0,128)},
+  {"cornflower blue"           , PALETTERGB (100,149,237)},
+  {"CornflowerBlue"            , PALETTERGB (100,149,237)},
+  {"dark slate blue"           , PALETTERGB ( 72, 61,139)},
+  {"DarkSlateBlue"             , PALETTERGB ( 72, 61,139)},
+  {"slate blue"                , PALETTERGB (106, 90,205)},
+  {"SlateBlue"                 , PALETTERGB (106, 90,205)},
+  {"medium slate blue"         , PALETTERGB (123,104,238)},
+  {"MediumSlateBlue"           , PALETTERGB (123,104,238)},
+  {"light slate blue"          , PALETTERGB (132,112,255)},
+  {"LightSlateBlue"            , PALETTERGB (132,112,255)},
+  {"medium blue"               , PALETTERGB (  0,  0,205)},
+  {"MediumBlue"                , PALETTERGB (  0,  0,205)},
+  {"royal blue"                , PALETTERGB ( 65,105,225)},
+  {"RoyalBlue"                 , PALETTERGB ( 65,105,225)},
+  {"blue"                      , PALETTERGB (  0,  0,255)},
+  {"dodger blue"               , PALETTERGB ( 30,144,255)},
+  {"DodgerBlue"                , PALETTERGB ( 30,144,255)},
+  {"deep sky blue"             , PALETTERGB (  0,191,255)},
+  {"DeepSkyBlue"               , PALETTERGB (  0,191,255)},
+  {"sky blue"                  , PALETTERGB (135,206,235)},
+  {"SkyBlue"                   , PALETTERGB (135,206,235)},
+  {"light sky blue"            , PALETTERGB (135,206,250)},
+  {"LightSkyBlue"              , PALETTERGB (135,206,250)},
+  {"steel blue"                , PALETTERGB ( 70,130,180)},
+  {"SteelBlue"                 , PALETTERGB ( 70,130,180)},
+  {"light steel blue"          , PALETTERGB (176,196,222)},
+  {"LightSteelBlue"            , PALETTERGB (176,196,222)},
+  {"light blue"                , PALETTERGB (173,216,230)},
+  {"LightBlue"                 , PALETTERGB (173,216,230)},
+  {"powder blue"               , PALETTERGB (176,224,230)},
+  {"PowderBlue"                , PALETTERGB (176,224,230)},
+  {"pale turquoise"            , PALETTERGB (175,238,238)},
+  {"PaleTurquoise"             , PALETTERGB (175,238,238)},
+  {"dark turquoise"            , PALETTERGB (  0,206,209)},
+  {"DarkTurquoise"             , PALETTERGB (  0,206,209)},
+  {"medium turquoise"          , PALETTERGB ( 72,209,204)},
+  {"MediumTurquoise"           , PALETTERGB ( 72,209,204)},
+  {"turquoise"                 , PALETTERGB ( 64,224,208)},
+  {"cyan"                      , PALETTERGB (  0,255,255)},
+  {"light cyan"                , PALETTERGB (224,255,255)},
+  {"LightCyan"                 , PALETTERGB (224,255,255)},
+  {"cadet blue"                , PALETTERGB ( 95,158,160)},
+  {"CadetBlue"                 , PALETTERGB ( 95,158,160)},
+  {"medium aquamarine"         , PALETTERGB (102,205,170)},
+  {"MediumAquamarine"          , PALETTERGB (102,205,170)},
+  {"aquamarine"                , PALETTERGB (127,255,212)},
+  {"dark green"                , PALETTERGB (  0,100,  0)},
+  {"DarkGreen"                 , PALETTERGB (  0,100,  0)},
+  {"dark olive green"          , PALETTERGB ( 85,107, 47)},
+  {"DarkOliveGreen"            , PALETTERGB ( 85,107, 47)},
+  {"dark sea green"            , PALETTERGB (143,188,143)},
+  {"DarkSeaGreen"              , PALETTERGB (143,188,143)},
+  {"sea green"                 , PALETTERGB ( 46,139, 87)},
+  {"SeaGreen"                  , PALETTERGB ( 46,139, 87)},
+  {"medium sea green"          , PALETTERGB ( 60,179,113)},
+  {"MediumSeaGreen"            , PALETTERGB ( 60,179,113)},
+  {"light sea green"           , PALETTERGB ( 32,178,170)},
+  {"LightSeaGreen"             , PALETTERGB ( 32,178,170)},
+  {"pale green"                , PALETTERGB (152,251,152)},
+  {"PaleGreen"                 , PALETTERGB (152,251,152)},
+  {"spring green"              , PALETTERGB (  0,255,127)},
+  {"SpringGreen"               , PALETTERGB (  0,255,127)},
+  {"lawn green"                , PALETTERGB (124,252,  0)},
+  {"LawnGreen"                 , PALETTERGB (124,252,  0)},
+  {"green"                     , PALETTERGB (  0,255,  0)},
+  {"chartreuse"                , PALETTERGB (127,255,  0)},
+  {"medium spring green"       , PALETTERGB (  0,250,154)},
+  {"MediumSpringGreen"         , PALETTERGB (  0,250,154)},
+  {"green yellow"              , PALETTERGB (173,255, 47)},
+  {"GreenYellow"               , PALETTERGB (173,255, 47)},
+  {"lime green"                , PALETTERGB ( 50,205, 50)},
+  {"LimeGreen"                 , PALETTERGB ( 50,205, 50)},
+  {"yellow green"              , PALETTERGB (154,205, 50)},
+  {"YellowGreen"               , PALETTERGB (154,205, 50)},
+  {"forest green"              , PALETTERGB ( 34,139, 34)},
+  {"ForestGreen"               , PALETTERGB ( 34,139, 34)},
+  {"olive drab"                , PALETTERGB (107,142, 35)},
+  {"OliveDrab"                 , PALETTERGB (107,142, 35)},
+  {"dark khaki"                , PALETTERGB (189,183,107)},
+  {"DarkKhaki"                 , PALETTERGB (189,183,107)},
+  {"khaki"                     , PALETTERGB (240,230,140)},
+  {"pale goldenrod"            , PALETTERGB (238,232,170)},
+  {"PaleGoldenrod"             , PALETTERGB (238,232,170)},
+  {"light goldenrod yellow"    , PALETTERGB (250,250,210)},
+  {"LightGoldenrodYellow"      , PALETTERGB (250,250,210)},
+  {"light yellow"              , PALETTERGB (255,255,224)},
+  {"LightYellow"               , PALETTERGB (255,255,224)},
+  {"yellow"                    , PALETTERGB (255,255,  0)},
+  {"gold"                      , PALETTERGB (255,215,  0)},
+  {"light goldenrod"           , PALETTERGB (238,221,130)},
+  {"LightGoldenrod"            , PALETTERGB (238,221,130)},
+  {"goldenrod"                 , PALETTERGB (218,165, 32)},
+  {"dark goldenrod"            , PALETTERGB (184,134, 11)},
+  {"DarkGoldenrod"             , PALETTERGB (184,134, 11)},
+  {"rosy brown"                , PALETTERGB (188,143,143)},
+  {"RosyBrown"                 , PALETTERGB (188,143,143)},
+  {"indian red"                , PALETTERGB (205, 92, 92)},
+  {"IndianRed"                 , PALETTERGB (205, 92, 92)},
+  {"saddle brown"              , PALETTERGB (139, 69, 19)},
+  {"SaddleBrown"               , PALETTERGB (139, 69, 19)},
+  {"sienna"                    , PALETTERGB (160, 82, 45)},
+  {"peru"                      , PALETTERGB (205,133, 63)},
+  {"burlywood"                 , PALETTERGB (222,184,135)},
+  {"beige"                     , PALETTERGB (245,245,220)},
+  {"wheat"                     , PALETTERGB (245,222,179)},
+  {"sandy brown"               , PALETTERGB (244,164, 96)},
+  {"SandyBrown"                , PALETTERGB (244,164, 96)},
+  {"tan"                       , PALETTERGB (210,180,140)},
+  {"chocolate"                 , PALETTERGB (210,105, 30)},
+  {"firebrick"                 , PALETTERGB (178,34, 34)},
+  {"brown"                     , PALETTERGB (165,42, 42)},
+  {"dark salmon"               , PALETTERGB (233,150,122)},
+  {"DarkSalmon"                , PALETTERGB (233,150,122)},
+  {"salmon"                    , PALETTERGB (250,128,114)},
+  {"light salmon"              , PALETTERGB (255,160,122)},
+  {"LightSalmon"               , PALETTERGB (255,160,122)},
+  {"orange"                    , PALETTERGB (255,165,  0)},
+  {"dark orange"               , PALETTERGB (255,140,  0)},
+  {"DarkOrange"                , PALETTERGB (255,140,  0)},
+  {"coral"                     , PALETTERGB (255,127, 80)},
+  {"light coral"               , PALETTERGB (240,128,128)},
+  {"LightCoral"                , PALETTERGB (240,128,128)},
+  {"tomato"                    , PALETTERGB (255, 99, 71)},
+  {"orange red"                , PALETTERGB (255, 69,  0)},
+  {"OrangeRed"                 , PALETTERGB (255, 69,  0)},
+  {"red"                       , PALETTERGB (255,  0,  0)},
+  {"hot pink"                  , PALETTERGB (255,105,180)},
+  {"HotPink"                   , PALETTERGB (255,105,180)},
+  {"deep pink"                 , PALETTERGB (255, 20,147)},
+  {"DeepPink"                  , PALETTERGB (255, 20,147)},
+  {"pink"                      , PALETTERGB (255,192,203)},
+  {"light pink"                , PALETTERGB (255,182,193)},
+  {"LightPink"                 , PALETTERGB (255,182,193)},
+  {"pale violet red"           , PALETTERGB (219,112,147)},
+  {"PaleVioletRed"             , PALETTERGB (219,112,147)},
+  {"maroon"                    , PALETTERGB (176, 48, 96)},
+  {"medium violet red"         , PALETTERGB (199, 21,133)},
+  {"MediumVioletRed"           , PALETTERGB (199, 21,133)},
+  {"violet red"                , PALETTERGB (208, 32,144)},
+  {"VioletRed"                 , PALETTERGB (208, 32,144)},
+  {"magenta"                   , PALETTERGB (255,  0,255)},
+  {"violet"                    , PALETTERGB (238,130,238)},
+  {"plum"                      , PALETTERGB (221,160,221)},
+  {"orchid"                    , PALETTERGB (218,112,214)},
+  {"medium orchid"             , PALETTERGB (186, 85,211)},
+  {"MediumOrchid"              , PALETTERGB (186, 85,211)},
+  {"dark orchid"               , PALETTERGB (153, 50,204)},
+  {"DarkOrchid"                , PALETTERGB (153, 50,204)},
+  {"dark violet"               , PALETTERGB (148,  0,211)},
+  {"DarkViolet"                , PALETTERGB (148,  0,211)},
+  {"blue violet"               , PALETTERGB (138, 43,226)},
+  {"BlueViolet"                , PALETTERGB (138, 43,226)},
+  {"purple"                    , PALETTERGB (160, 32,240)},
+  {"medium purple"             , PALETTERGB (147,112,219)},
+  {"MediumPurple"              , PALETTERGB (147,112,219)},
+  {"thistle"                   , PALETTERGB (216,191,216)},
+  {"gray0"                     , PALETTERGB (  0,  0,  0)},
+  {"grey0"                     , PALETTERGB (  0,  0,  0)},
+  {"dark grey"                 , PALETTERGB (169,169,169)},
+  {"DarkGrey"                  , PALETTERGB (169,169,169)},
+  {"dark gray"                 , PALETTERGB (169,169,169)},
+  {"DarkGray"                  , PALETTERGB (169,169,169)},
+  {"dark blue"                 , PALETTERGB (  0,  0,139)},
+  {"DarkBlue"                  , PALETTERGB (  0,  0,139)},
+  {"dark cyan"                 , PALETTERGB (  0,139,139)},
+  {"DarkCyan"                  , PALETTERGB (  0,139,139)},
+  {"dark magenta"              , PALETTERGB (139,  0,139)},
+  {"DarkMagenta"               , PALETTERGB (139,  0,139)},
+  {"dark red"                  , PALETTERGB (139,  0,  0)},
+  {"DarkRed"                   , PALETTERGB (139,  0,  0)},
+  {"light green"               , PALETTERGB (144,238,144)},
+  {"LightGreen"                , PALETTERGB (144,238,144)},
 };
 
 DEFUN ("win32-default-color-map", Fwin32_default_color_map, Swin32_default_color_map,
@@ -1107,7 +1217,6 @@ DEFUN ("win32-default-color-map", Fwin32_default_color_map, Swin32_default_color
   
   return (cmap);
 }
-#endif
 
 Lisp_Object 
 win32_to_x_color (rgb)
@@ -1160,6 +1269,122 @@ x_to_win32_color (colorname)
   return ret;
 }
 
+
+void
+win32_regenerate_palette (FRAME_PTR f)
+{
+  struct win32_palette_entry * list;
+  LOGPALETTE *          log_palette;
+  HPALETTE              new_palette;
+  int                   i;
+
+  /* don't bother trying to create palette if not supported */
+  if (! FRAME_WIN32_DISPLAY_INFO (f)->has_palette)
+    return;
+
+  log_palette = (LOGPALETTE *)
+    alloca (sizeof (LOGPALETTE) +
+            FRAME_WIN32_DISPLAY_INFO (f)->num_colors * sizeof (PALETTEENTRY));
+  log_palette->palVersion = 0x300;
+  log_palette->palNumEntries = FRAME_WIN32_DISPLAY_INFO (f)->num_colors;
+
+  list = FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+  for (i = 0;
+       i < FRAME_WIN32_DISPLAY_INFO (f)->num_colors;
+       i++, list = list->next)
+    log_palette->palPalEntry[i] = list->entry;
+
+  new_palette = CreatePalette (log_palette);
+
+  enter_crit ();
+
+  if (FRAME_WIN32_DISPLAY_INFO (f)->palette)
+    DeleteObject (FRAME_WIN32_DISPLAY_INFO (f)->palette);
+  FRAME_WIN32_DISPLAY_INFO (f)->palette = new_palette;
+
+  /* Realize display palette and garbage all frames. */
+  release_frame_dc (f, get_frame_dc (f));
+
+  leave_crit ();
+}
+
+#define WIN32_COLOR(pe)  RGB (pe.peRed, pe.peGreen, pe.peBlue)
+#define SET_WIN32_COLOR(pe, color) \
+  do \
+    { \
+      pe.peRed = GetRValue (color); \
+      pe.peGreen = GetGValue (color); \
+      pe.peBlue = GetBValue (color); \
+      pe.peFlags = 0; \
+    } while (0)
+
+#if 0
+/* Keep these around in case we ever want to track color usage. */
+void
+win32_map_color (FRAME_PTR f, COLORREF color)
+{
+  struct win32_palette_entry * list = FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+
+  if (NILP (Vwin32_enable_palette))
+    return;
+
+  /* check if color is already mapped */
+  while (list)
+    {
+      if (WIN32_COLOR (list->entry) == color)
+        {
+         ++list->refcount;
+         return;
+       }
+      list = list->next;
+    }
+
+  /* not already mapped, so add to list and recreate Windows palette */
+  list = (struct win32_palette_entry *)
+    xmalloc (sizeof (struct win32_palette_entry));
+  SET_WIN32_COLOR (list->entry, color);
+  list->refcount = 1;
+  list->next = FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+  FRAME_WIN32_DISPLAY_INFO (f)->color_list = list;
+  FRAME_WIN32_DISPLAY_INFO (f)->num_colors++;
+
+  /* set flag that palette must be regenerated */
+  FRAME_WIN32_DISPLAY_INFO (f)->regen_palette = TRUE;
+}
+
+void
+win32_unmap_color (FRAME_PTR f, COLORREF color)
+{
+  struct win32_palette_entry * list = FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+  struct win32_palette_entry **prev = &FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+
+  if (NILP (Vwin32_enable_palette))
+    return;
+
+  /* check if color is already mapped */
+  while (list)
+    {
+      if (WIN32_COLOR (list->entry) == color)
+        {
+         if (--list->refcount == 0)
+           {
+             *prev = list->next;
+             xfree (list);
+             FRAME_WIN32_DISPLAY_INFO (f)->num_colors--;
+             break;
+           }
+         else
+           return;
+       }
+      prev = &list->next;
+      list = list->next;
+    }
+
+  /* set flag that palette must be regenerated */
+  FRAME_WIN32_DISPLAY_INFO (f)->regen_palette = TRUE;
+}
+#endif
+
 /* Decide if color named COLOR is valid for the display associated with
    the selected frame; if so, return the rgb values in COLOR_DEF.
    If ALLOC is nonzero, allocate a new colormap cell.  */
@@ -1177,9 +1402,42 @@ defined_color (f, color, color_def, alloc)
 
   if (!NILP (tem)) 
     {
-      *color_def = XUINT (tem);
+      if (!NILP (Vwin32_enable_palette))
+       {
+         struct win32_palette_entry * entry =
+           FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+         struct win32_palette_entry ** prev =
+           &FRAME_WIN32_DISPLAY_INFO (f)->color_list;
+      
+         /* check if color is already mapped */
+         while (entry)
+           {
+             if (WIN32_COLOR (entry->entry) == XUINT (tem))
+               break;
+             prev = &entry->next;
+             entry = entry->next;
+           }
+
+         if (entry == NULL && alloc)
+           {
+             /* not already mapped, so add to list */
+             entry = (struct win32_palette_entry *)
+               xmalloc (sizeof (struct win32_palette_entry));
+             SET_WIN32_COLOR (entry->entry, XUINT (tem));
+             entry->next = NULL;
+             *prev = entry;
+             FRAME_WIN32_DISPLAY_INFO (f)->num_colors++;
+
+             /* set flag that palette must be regenerated */
+             FRAME_WIN32_DISPLAY_INFO (f)->regen_palette = TRUE;
+           }
+       }
+      /* Ensure COLORREF value is snapped to nearest color in (default)
+        palette by simulating the PALETTERGB macro.  This works whether
+        or not the display device has a palette. */
+      *color_def = XUINT (tem) | 0x2000000;
       return 1;
-    } 
+    }
   else 
     {
       return 0;
@@ -1233,6 +1491,7 @@ x_set_foreground_color (f, arg, oldval)
 {
   f->output_data.win32->foreground_pixel
     = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
+
   if (FRAME_WIN32_WINDOW (f) != 0)
     {
       recompute_basic_faces (f);
@@ -2322,7 +2581,7 @@ win32_init_class (hinst)
 {
   WNDCLASS wc;
 
-  wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
+  wc.style = CS_HREDRAW | CS_VREDRAW;
   wc.lpfnWndProc = (WNDPROC) win32_wnd_proc;
   wc.cbClsExtra = 0;
   wc.cbWndExtra = WND_EXTRA_BYTES;
@@ -2381,9 +2640,238 @@ win32_createwindow (f)
       SetWindowLong (hwnd, WND_X_UNITS_INDEX, FONT_WIDTH (f->output_data.win32->font));
       SetWindowLong (hwnd, WND_Y_UNITS_INDEX, f->output_data.win32->line_height);
       SetWindowLong (hwnd, WND_BACKGROUND_INDEX, f->output_data.win32->background_pixel);
+
+      /* Do this to discard the default setting specified by our parent. */
+      ShowWindow (hwnd, SW_HIDE);
+    }
+}
+
+/* Convert between the modifier bits Win32 uses and the modifier bits
+   Emacs uses.  */
+unsigned int
+win32_get_modifiers ()
+{
+  return (((GetKeyState (VK_SHIFT)&0x8000)   ? shift_modifier  : 0) |
+         ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier   : 0) |
+          ((GetKeyState (VK_MENU)&0x8000)    ? 
+          ((NILP (Vwin32_alt_is_meta)) ? alt_modifier : meta_modifier) : 0));
+}
+
+void 
+my_post_msg (wmsg, hwnd, msg, wParam, lParam)
+     Win32Msg * wmsg;
+     HWND hwnd;
+     UINT msg;
+     WPARAM wParam;
+     LPARAM lParam;
+{
+  wmsg->msg.hwnd = hwnd;
+  wmsg->msg.message = msg;
+  wmsg->msg.wParam = wParam;
+  wmsg->msg.lParam = lParam;
+  wmsg->msg.time = GetMessageTime ();
+
+  post_msg (wmsg);
+}
+
+/* GetKeyState and MapVirtualKey on Win95 do not actually distinguish
+   between left and right keys as advertised.  We test for this
+   support dynamically, and set a flag when the support is absent.  If
+   absent, we keep track of the left and right control and alt keys
+   ourselves.  This is particularly necessary on keyboards that rely
+   upon the AltGr key, which is represented as having the left control
+   and right alt keys pressed.  For these keyboards, we need to know
+   when the left alt key has been pressed in addition to the AltGr key
+   so that we can properly support M-AltGr-key sequences (such as M-@
+   on Swedish keyboards).  */
+
+#define EMACS_LCONTROL 0
+#define EMACS_RCONTROL 1
+#define EMACS_LMENU    2
+#define EMACS_RMENU    3
+
+static int modifiers[4];
+static int modifiers_recorded;
+static int modifier_key_support_tested;
+
+static void
+test_modifier_support (unsigned int wparam)
+{
+  unsigned int l, r;
+
+  if (wparam != VK_CONTROL && wparam != VK_MENU)
+    return;
+  if (wparam == VK_CONTROL)
+    {
+      l = VK_LCONTROL;
+      r = VK_RCONTROL;
+    }
+  else
+    {
+      l = VK_LMENU;
+      r = VK_RMENU;
+    }
+  if (!(GetKeyState (l) & 0x8000) && !(GetKeyState (r) & 0x8000))
+    modifiers_recorded = 1;
+  else
+    modifiers_recorded = 0;
+  modifier_key_support_tested = 1;
+}
+
+static void
+record_keydown (unsigned int wparam, unsigned int lparam)
+{
+  int i;
+
+  if (!modifier_key_support_tested)
+    test_modifier_support (wparam);
+
+  if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
+    return;
+
+  if (wparam == VK_CONTROL)
+    i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
+  else
+    i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
+
+  modifiers[i] = 1;
+}
+
+static void
+record_keyup (unsigned int wparam, unsigned int lparam)
+{
+  int i;
+
+  if ((wparam != VK_CONTROL && wparam != VK_MENU) || !modifiers_recorded)
+    return;
+
+  if (wparam == VK_CONTROL)
+    i = (lparam & 0x1000000) ? EMACS_RCONTROL : EMACS_LCONTROL;
+  else
+    i = (lparam & 0x1000000) ? EMACS_RMENU : EMACS_LMENU;
+
+  modifiers[i] = 0;
+}
+
+/* Emacs can lose focus while a modifier key has been pressed.  When
+   it regains focus, be conservative and clear all modifiers since 
+   we cannot reconstruct the left and right modifier state.  */
+static void
+reset_modifiers ()
+{
+  SHORT ctrl, alt;
+
+  if (!modifiers_recorded)
+    return;
+
+  ctrl = GetAsyncKeyState (VK_CONTROL);
+  alt = GetAsyncKeyState (VK_MENU);
+
+  if (ctrl == 0 || alt == 0)
+    /* Emacs doesn't have keyboard focus.  Do nothing.  */
+    return;
+
+  if (!(ctrl & 0x08000))
+    /* Clear any recorded control modifier state.  */
+    modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
+
+  if (!(alt & 0x08000))
+    /* Clear any recorded alt modifier state.  */
+    modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
+
+  /* Otherwise, leave the modifier state as it was when Emacs lost
+     keyboard focus.  */
+}
+
+/* Synchronize modifier state with what is reported with the current
+   keystroke.  Even if we cannot distinguish between left and right
+   modifier keys, we know that, if no modifiers are set, then neither
+   the left or right modifier should be set.  */
+static void
+sync_modifiers ()
+{
+  if (!modifiers_recorded)
+    return;
+
+  if (!(GetKeyState (VK_CONTROL) & 0x8000)) 
+    modifiers[EMACS_RCONTROL] = modifiers[EMACS_LCONTROL] = 0;
+
+  if (!(GetKeyState (VK_MENU) & 0x8000)) 
+    modifiers[EMACS_RMENU] = modifiers[EMACS_LMENU] = 0;
+}
+
+static int
+modifier_set (int vkey)
+{
+  if (vkey == VK_CAPITAL)
+    return (GetKeyState (vkey) & 0x1);
+  if (!modifiers_recorded)
+    return (GetKeyState (vkey) & 0x8000);
+
+  switch (vkey)
+    {
+    case VK_LCONTROL:
+      return modifiers[EMACS_LCONTROL];
+    case VK_RCONTROL:
+      return modifiers[EMACS_RCONTROL];
+    case VK_LMENU:
+      return modifiers[EMACS_LMENU];
+    case VK_RMENU:
+      return modifiers[EMACS_RMENU];
+    default:
+      break;
     }
+  return (GetKeyState (vkey) & 0x8000);
+}
+
+/* We map the VK_* modifiers into console modifier constants
+   so that we can use the same routines to handle both console
+   and window input.  */
+
+static int
+construct_modifiers (unsigned int wparam, unsigned int lparam)
+{
+  int mods;
+
+  if (wparam != VK_CONTROL && wparam != VK_MENU)
+    mods = GetLastError ();
+
+  mods = 0;
+  mods |= (modifier_set (VK_SHIFT)) ? SHIFT_PRESSED : 0;
+  mods |= (modifier_set (VK_CAPITAL)) ? CAPSLOCK_ON : 0;
+  mods |= (modifier_set (VK_LCONTROL)) ? LEFT_CTRL_PRESSED : 0;
+  mods |= (modifier_set (VK_RCONTROL)) ? RIGHT_CTRL_PRESSED : 0;
+  mods |= (modifier_set (VK_LMENU)) ? LEFT_ALT_PRESSED : 0;
+  mods |= (modifier_set (VK_RMENU)) ? RIGHT_ALT_PRESSED : 0;
+
+  return mods;
+}
+
+static unsigned int
+map_keypad_keys (unsigned int wparam, unsigned int lparam)
+{
+  unsigned int extended = (lparam & 0x1000000L);
+
+  if (wparam < VK_CLEAR || wparam > VK_DELETE)
+    return wparam;
+
+  if (wparam == VK_RETURN)
+    return (extended ? VK_NUMPAD_ENTER : VK_RETURN);
+
+  if (wparam >= VK_PRIOR && wparam <= VK_DOWN)
+    return (!extended ? (VK_NUMPAD_PRIOR + (wparam - VK_PRIOR)) : wparam);
+
+  if (wparam == VK_INSERT || wparam == VK_DELETE)
+    return (!extended ? (VK_NUMPAD_INSERT + (wparam - VK_INSERT)) : wparam);
+
+  if (wparam == VK_CLEAR)
+    return (!extended ? VK_NUMPAD_CLEAR : wparam);
+
+  return wparam;
 }
 
+/* Main message dispatch loop. */
+
 DWORD 
 win_msg_worker (dw)
      DWORD dw;
@@ -2426,53 +2914,6 @@ win_msg_worker (dw)
   return (0);
 }
 
-HDC 
-map_mode (hdc)
-     HDC hdc;
-{
-  if (hdc) 
-    {
-#if 0
-      /* Make mapping mode be in 1/20 of point */
-      
-      SetMapMode (hdc, MM_ANISOTROPIC);
-      SetWindowExtEx (hdc, 1440, 1440, NULL);
-      SetViewportExtEx (hdc,
-                       GetDeviceCaps (hdc, LOGPIXELSX),
-                       GetDeviceCaps (hdc, LOGPIXELSY),
-                       NULL);
-#endif
-    }
-  return (hdc);
-}
-
-/* Convert between the modifier bits Win32 uses and the modifier bits
-   Emacs uses.  */
-unsigned int
-win32_get_modifiers ()
-{
-  return (((GetKeyState (VK_SHIFT)&0x8000)   ? shift_modifier  : 0) |
-         ((GetKeyState (VK_CONTROL)&0x8000) ? ctrl_modifier   : 0) |
-         ((GetKeyState (VK_MENU)&0x8000)    ? meta_modifier   : 0));
-}
-
-void 
-my_post_msg (wmsg, hwnd, msg, wParam, lParam)
-     Win32Msg * wmsg;
-     HWND hwnd;
-     UINT msg;
-     WPARAM wParam;
-     LPARAM lParam;
-{
-  wmsg->msg.hwnd = hwnd;
-  wmsg->msg.message = msg;
-  wmsg->msg.wParam = wParam;
-  wmsg->msg.lParam = lParam;
-  wmsg->msg.time = GetMessageTime ();
-
-  post_msg (wmsg);
-}
-
 /* Main window procedure */
 
 extern char *lispy_function_keys[];
@@ -2488,112 +2929,252 @@ win32_wnd_proc (hwnd, msg, wParam, lParam)
   LRESULT ret = 1;
   struct win32_display_info *dpyinfo = &one_win32_display_info;
   Win32Msg wmsg;
-  
+  int windows_translate;
+
+  /* Note that it is okay to call x_window_to_frame, even though we are
+     not running in the main lisp thread, because frame deletion
+     requires the lisp thread to synchronize with this thread.  Thus, if
+     a frame struct is returned, it can be used without concern that the
+     lisp thread might make it disappear while we are using it.
+
+     NB. Walking the frame list in this thread is safe (as long as
+     writes of Lisp_Object slots are atomic, which they are on Windows).
+     Although delete-frame can destructively modify the frame list while
+     we are walking it, a garbage collection cannot occur until after
+     delete-frame has synchronized with this thread.
+
+     It is also safe to use functions that make GDI calls, such as
+     win32_clear_rect, because these functions must obtain a DC handle
+     from the frame struct using get_frame_dc which is thread-aware.  */
+
   switch (msg) 
     {
     case WM_ERASEBKGND:
-      {
-       HBRUSH hb;
-       HANDLE oldobj;
-       RECT rect;
-       
-       GetClientRect (hwnd, &rect);
-       
-       hb = CreateSolidBrush (GetWindowLong (hwnd, WND_BACKGROUND_INDEX));
-       
-       oldobj = SelectObject ((HDC)wParam, hb);
-       
-       FillRect((HDC)wParam, &rect, hb);
-       
-       SelectObject((HDC)wParam, oldobj);
-       
-       DeleteObject (hb);
-       
-       return (0);
-      }
-    case WM_PAINT:
+      f = x_window_to_frame (dpyinfo, hwnd);
+      if (f)
+       {
+         GetUpdateRect (hwnd, &wmsg.rect, FALSE);
+         win32_clear_rect (f, NULL, &wmsg.rect);
+       }
+      return 1;
+    case WM_PALETTECHANGED:
+      /* ignore our own changes */
+      if ((HWND)wParam != hwnd)
+        {
+         f = x_window_to_frame (dpyinfo, hwnd);
+         if (f)
+           /* get_frame_dc will realize our palette and force all
+              frames to be redrawn if needed. */
+           release_frame_dc (f, get_frame_dc (f));
+       }
+      return 0;
+    case WM_PAINT:
       {
        PAINTSTRUCT paintStruct;
-                   
+
+       enter_crit ();
        BeginPaint (hwnd, &paintStruct);
        wmsg.rect = paintStruct.rcPaint;
        EndPaint (hwnd, &paintStruct);
-      
+       leave_crit ();
+
        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       
        return (0);
       }
-      
-    case WM_CREATE:
-      {
-       HDC hdc = my_get_dc (hwnd);
-
-       /* Make mapping mode be in 1/20 of point */
 
-       map_mode (hdc);
+    case WM_KEYUP:
+    case WM_SYSKEYUP:
+      record_keyup (wParam, lParam);
+      goto dflt;
 
-       ReleaseDC (hwnd, hdc);
-      }
-      
-      return (0);
     case WM_KEYDOWN:
     case WM_SYSKEYDOWN:
-#if 0
-      if (! ((wParam >= VK_BACK && wParam <= VK_TAB)
-            || (wParam >= VK_CLEAR && wParam <= VK_RETURN)
-            || (wParam == VK_ESCAPE)
-            || (wParam >= VK_PRIOR && wParam <= VK_HELP)
-            || (wParam >= VK_LWIN && wParam <= VK_APPS)
-            || (wParam >= VK_NUMPAD0 && wParam <= VK_F24)
-            || (wParam >= VK_NUMLOCK && wParam <= VK_SCROLL)
-            || (wParam >= VK_ATTN && wParam <= VK_OEM_CLEAR)
-            || !TranslateMessage (&msg1)))
-       {
-         goto dflt;
-       }
-#endif
-      
-      /* Check for special characters since translate message 
-        seems to always indicate true.  */
-      
-      if (wParam == VK_MENU
-         || wParam == VK_SHIFT
-         || wParam == VK_CONTROL
-         || wParam == VK_CAPITAL)
+      /* Synchronize modifiers with current keystroke.  */
+      sync_modifiers ();
+
+      record_keydown (wParam, lParam);
+
+      wParam = map_keypad_keys (wParam, lParam);
+
+      windows_translate = 0;
+      switch (wParam) {
+      case VK_LWIN:
+      case VK_RWIN:
+      case VK_APPS:
+       /* More support for these keys will likely be necessary.  */
+       if (!NILP (Vwin32_pass_optional_keys_to_system))
+         windows_translate = 1;
        break;
-      
-      /* Anything we do not have a name for needs to be translated or 
-        returned as ascii keystroke.  */
-      
-      if (lispy_function_keys[wParam] == 0)
+      case VK_MENU:
+       if (NILP (Vwin32_pass_alt_to_system)) 
+         return 0;
+       windows_translate = 1;
+       break;
+      case VK_CONTROL: 
+      case VK_CAPITAL: 
+      case VK_SHIFT:
+      case VK_NUMLOCK:
+      case VK_SCROLL: 
+       windows_translate = 1;
+       break;
+      default:
+       /* If not defined as a function key, change it to a WM_CHAR message. */
+       if (lispy_function_keys[wParam] == 0)
+         msg = WM_CHAR;
+       break;
+      }
+
+      if (windows_translate)
        {
-         MSG msg1;
-           
-         msg1.hwnd = hwnd;
-         msg1.message = msg;
-         msg1.wParam = wParam;
-         msg1.lParam = lParam;
-           
-         if (TranslateMessage (&msg1))
-           break;
-         else
-           msg = WM_CHAR;
+         MSG winmsg = { hwnd, msg, wParam, lParam, 0, {0,0} };
+
+         winmsg.time = GetMessageTime ();
+         TranslateMessage (&winmsg);
+         goto dflt;
        }
-      
+
       /* Fall through */
       
     case WM_SYSCHAR:
     case WM_CHAR:
-      wmsg.dwModifiers = win32_get_modifiers ();
-      
+      wmsg.dwModifiers = construct_modifiers (wParam, lParam);
+
+      enter_crit ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+
+#if 1
+      /* Detect quit_char and set quit-flag directly.  Note that we dow
+         this *after* posting the message to ensure the main thread will
+         be woken up if blocked in sys_select(). */
+      {
+       int c = wParam;
+       if (isalpha (c) && (wmsg.dwModifiers == LEFT_CTRL_PRESSED 
+                           || wmsg.dwModifiers == RIGHT_CTRL_PRESSED))
+         c = make_ctrl_char (c) & 0377;
+       if (c == quit_char)
+         Vquit_flag = Qt;
+      }
+#endif
+
+      leave_crit ();
       break;
+
+      /* Simulate middle mouse button events when left and right buttons
+        are used together, but only if user has two button mouse. */
     case WM_LBUTTONDOWN:
+    case WM_RBUTTONDOWN:
+      if (XINT (Vwin32_num_mouse_buttons) == 3)
+       goto handle_plain_button;
+
+      {
+       int this = (msg == WM_LBUTTONDOWN) ? LMOUSE : RMOUSE;
+       int other = (msg == WM_LBUTTONDOWN) ? RMOUSE : LMOUSE;
+
+       if (button_state & this)
+         return 0;
+
+       if (button_state == 0)
+         SetCapture (hwnd);
+
+       button_state |= this;
+
+       if (button_state & other)
+         {
+           if (mouse_button_timer)
+             {
+               KillTimer (hwnd, mouse_button_timer);
+               mouse_button_timer = 0;
+
+               /* Generate middle mouse event instead. */
+               msg = WM_MBUTTONDOWN;
+               button_state |= MMOUSE;
+             }
+           else if (button_state & MMOUSE)
+             {
+               /* Ignore button event if we've already generated a
+                  middle mouse down event.  This happens if the
+                  user releases and press one of the two buttons
+                  after we've faked a middle mouse event. */
+               return 0;
+             }
+           else
+             {
+               /* Flush out saved message. */
+               post_msg (&saved_mouse_button_msg);
+             }
+           wmsg.dwModifiers = win32_get_modifiers ();
+           my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+
+           /* Clear message buffer. */
+           saved_mouse_button_msg.msg.hwnd = 0;
+         }
+       else
+         {
+           /* Hold onto message for now. */
+           mouse_button_timer =
+             SetTimer (hwnd, MOUSE_BUTTON_ID, XINT (Vwin32_mouse_button_tolerance), NULL);
+           saved_mouse_button_msg.msg.hwnd = hwnd;
+           saved_mouse_button_msg.msg.message = msg;
+           saved_mouse_button_msg.msg.wParam = wParam;
+           saved_mouse_button_msg.msg.lParam = lParam;
+           saved_mouse_button_msg.msg.time = GetMessageTime ();
+           saved_mouse_button_msg.dwModifiers = win32_get_modifiers ();
+         }
+      }
+      return 0;
+
     case WM_LBUTTONUP:
+    case WM_RBUTTONUP:
+      if (XINT (Vwin32_num_mouse_buttons) == 3)
+       goto handle_plain_button;
+
+      {
+       int this = (msg == WM_LBUTTONUP) ? LMOUSE : RMOUSE;
+       int other = (msg == WM_LBUTTONUP) ? RMOUSE : LMOUSE;
+
+       if ((button_state & this) == 0)
+         return 0;
+
+       button_state &= ~this;
+
+       if (button_state & MMOUSE)
+         {
+           /* Only generate event when second button is released. */
+           if ((button_state & other) == 0)
+             {
+               msg = WM_MBUTTONUP;
+               button_state &= ~MMOUSE;
+
+               if (button_state) abort ();
+             }
+           else
+             return 0;
+         }
+       else
+         {
+           /* Flush out saved message if necessary. */
+           if (saved_mouse_button_msg.msg.hwnd)
+             {
+               post_msg (&saved_mouse_button_msg);
+             }
+         }
+       wmsg.dwModifiers = win32_get_modifiers ();
+       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+
+       /* Always clear message buffer and cancel timer. */
+       saved_mouse_button_msg.msg.hwnd = 0;
+       KillTimer (hwnd, mouse_button_timer);
+       mouse_button_timer = 0;
+
+       if (button_state == 0)
+         ReleaseCapture ();
+      }
+      return 0;
+
     case WM_MBUTTONDOWN:
     case WM_MBUTTONUP:
-    case WM_RBUTTONDOWN:
-    case WM_RBUTTONUP:
+    handle_plain_button:
       {
        BOOL up;
 
@@ -2605,20 +3186,87 @@ win32_wnd_proc (hwnd, msg, wParam, lParam)
       }
       
       wmsg.dwModifiers = win32_get_modifiers ();
-      
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
-      goto dflt;
+      return 0;
+
+    case WM_VSCROLL:
     case WM_MOUSEMOVE:
-    case WM_MOVE:
-    case WM_SIZE:
+      if (XINT (Vwin32_mouse_move_interval) <= 0
+         || (msg == WM_MOUSEMOVE && button_state == 0))
+       {
+         wmsg.dwModifiers = win32_get_modifiers ();
+         my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+         return 0;
+       }
+  
+      /* Hang onto mouse move and scroll messages for a bit, to avoid
+        sending such events to Emacs faster than it can process them.
+        If we get more events before the timer from the first message
+        expires, we just replace the first message. */
+
+      if (saved_mouse_move_msg.msg.hwnd == 0)
+       mouse_move_timer =
+         SetTimer (hwnd, MOUSE_MOVE_ID, XINT (Vwin32_mouse_move_interval), NULL);
+
+      /* Hold onto message for now. */
+      saved_mouse_move_msg.msg.hwnd = hwnd;
+      saved_mouse_move_msg.msg.message = msg;
+      saved_mouse_move_msg.msg.wParam = wParam;
+      saved_mouse_move_msg.msg.lParam = lParam;
+      saved_mouse_move_msg.msg.time = GetMessageTime ();
+      saved_mouse_move_msg.dwModifiers = win32_get_modifiers ();
+  
+      return 0;
+
+    case WM_TIMER:
+      /* Flush out saved messages if necessary. */
+      if (wParam == mouse_button_timer)
+       {
+         if (saved_mouse_button_msg.msg.hwnd)
+           {
+             post_msg (&saved_mouse_button_msg);
+             saved_mouse_button_msg.msg.hwnd = 0;
+           }
+         KillTimer (hwnd, mouse_button_timer);
+         mouse_button_timer = 0;
+       }
+      else if (wParam == mouse_move_timer)
+       {
+         if (saved_mouse_move_msg.msg.hwnd)
+           {
+             post_msg (&saved_mouse_move_msg);
+             saved_mouse_move_msg.msg.hwnd = 0;
+           }
+         KillTimer (hwnd, mouse_move_timer);
+         mouse_move_timer = 0;
+       }
+      return 0;
+  
+    case WM_NCACTIVATE:
+      /* Windows doesn't send us focus messages when putting up and
+        taking down a system popup dialog as for Ctrl-Alt-Del on Win95.
+        The only indication we get that something happened is receiving
+        this message afterwards.  So this is a good time to reset our
+        keyboard modifiers' state. */
+      reset_modifiers ();
+      goto dflt;
+
     case WM_SETFOCUS:
+      reset_modifiers ();
     case WM_KILLFOCUS:
-    case WM_CLOSE:
-    case WM_VSCROLL:
+    case WM_MOVE:
+    case WM_SIZE:
     case WM_SYSCOMMAND:
     case WM_COMMAND:
+      wmsg.dwModifiers = win32_get_modifiers ();
       my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
       goto dflt;
+
+    case WM_CLOSE:
+      wmsg.dwModifiers = win32_get_modifiers ();
+      my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      return 0;
+
     case WM_WINDOWPOSCHANGING:
       {
        WINDOWPLACEMENT wp;
@@ -2635,6 +3283,7 @@ win32_wnd_proc (hwnd, msg, wParam, lParam)
            DWORD dwYUnits;
            RECT wr;
            
+           wp.length = sizeof(wp);
            GetWindowRect (hwnd, &wr);
            
            enter_crit ();
@@ -2684,6 +3333,14 @@ win32_wnd_proc (hwnd, msg, wParam, lParam)
       if (ret == 0) return (0);
       
       goto dflt;
+    case WM_EMACS_SHOWWINDOW:
+      return ShowWindow (hwnd, wParam);
+    case WM_EMACS_SETWINDOWPOS:
+      {
+       Win32WindowPos * pos = (Win32WindowPos *) wParam;
+       return SetWindowPos (hwnd, pos->hwndAfter,
+                            pos->x, pos->y, pos->cx, pos->cy, pos->flags);
+      }
     case WM_EMACS_DESTROYWINDOW:
       DestroyWindow ((HWND) wParam);
       break;
@@ -2857,6 +3514,8 @@ This function is an internal primitive--use `make-frame' instead.")
 
   /* Note that Windows does support scroll bars.  */
   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
+  /* By default, make scrollbars the system standard width. */
+  f->scroll_bar_pixel_width = GetSystemMetrics (SM_CXVSCROLL);
 
   XSETFRAME (frame, f);
   GCPRO1 (frame);
@@ -2928,7 +3587,7 @@ This function is an internal primitive--use `make-frame' instead.")
       font = x_new_font (f, "-*-system-medium-r-normal-*-*-200-*-*-c-120-*-*");
 #endif
     if (! STRINGP (font))
-      font = x_new_font (f, "-*-terminal-medium-r-normal-*-*-180-*-*-c-120-*-*");
+      font = x_new_font (f, "-*-Fixedsys-*-r-*-*-12-90-*-*-c-*-*-*");
     UNBLOCK_INPUT;
     if (! STRINGP (font))
       font = build_string ("-*-system");
@@ -3080,90 +3739,64 @@ x_get_focus_frame (frame)
 }
 
 DEFUN ("focus-frame", Ffocus_frame, Sfocus_frame, 1, 1, 0,
-  "Set the focus on FRAME.")
+  "This function is obsolete, and does nothing.")
   (frame)
      Lisp_Object frame;
 {
-  CHECK_LIVE_FRAME (frame, 0);
-
-  if (FRAME_WIN32_P (XFRAME (frame)))
-    {
-      BLOCK_INPUT;
-      x_focus_on_frame (XFRAME (frame));
-      UNBLOCK_INPUT;
-      return frame;
-    }
-
   return Qnil;
 }
 
 DEFUN ("unfocus-frame", Funfocus_frame, Sunfocus_frame, 0, 0, 0,
-       "If a frame has been focused, release it.")
-     ()
+  "This function is obsolete, and does nothing.")
+  ()
 {
-  if (FRAME_WIN32_P (selected_frame))
-    {
-      struct win32_display_info *dpyinfo = FRAME_WIN32_DISPLAY_INFO (selected_frame);
-
-      if (dpyinfo->win32_focus_frame)
-       {
-         BLOCK_INPUT;
-         x_unfocus_frame (dpyinfo->win32_focus_frame);
-         UNBLOCK_INPUT;
-       }
-    }
-  
   return Qnil;
 }
 \f
-XFontStruct 
-*win32_load_font (dpyinfo,name)
+XFontStruct *
+win32_load_font (dpyinfo,name)
 struct win32_display_info *dpyinfo;
 char * name;
 {
   XFontStruct * font = NULL;
   BOOL ok;
-  
+
   {
     LOGFONT lf;
-       
-    if (!name || !x_to_win32_font(name, &lf)) 
+
+    if (!name || !x_to_win32_font (name, &lf))
       return (NULL);
-       
+
     font = (XFontStruct *) xmalloc (sizeof (XFontStruct));
-       
+
     if (!font) return (NULL);
-       
+
     BLOCK_INPUT;
-       
-    font->hfont = CreateFontIndirect(&lf);
+
+    font->hfont = CreateFontIndirect (&lf);
   }
-  
-    if (font->hfont == NULL) 
-      {
-       ok = FALSE;
-      } 
-    else 
-      {
-       HDC hdc;
-       HANDLE oldobj;
 
-       hdc = my_get_dc (dpyinfo->root_window);
-       
-       oldobj = SelectObject (hdc, font->hfont);
-       
-       ok = GetTextMetrics (hdc, &font->tm);
-       
-       SelectObject (hdc, oldobj);
-       
-       ReleaseDC (dpyinfo->root_window, hdc);
-      }
-  
+  if (font->hfont == NULL) 
+    {
+      ok = FALSE;
+    } 
+  else 
+    {
+      HDC hdc;
+      HANDLE oldobj;
+
+      hdc = GetDC (dpyinfo->root_window);
+      oldobj = SelectObject (hdc, font->hfont);
+      ok = GetTextMetrics (hdc, &font->tm);
+      SelectObject (hdc, oldobj);
+      ReleaseDC (dpyinfo->root_window, hdc);
+    }
+
   UNBLOCK_INPUT;
-  
+
   if (ok) return (font);
-  
-  win32_unload_font(dpyinfo, font);
+
+  win32_unload_font (dpyinfo, font);
   return (NULL);
 }
 
@@ -3258,31 +3891,70 @@ x_to_win32_weight (lpw)
      char * lpw;
 {
   if (!lpw) return (FW_DONTCARE);
-  
-  if (stricmp (lpw, "bold") == 0)
-    return (FW_BOLD);
-  else if (stricmp (lpw, "demibold") == 0)
-    return (FW_SEMIBOLD);
-  else if (stricmp (lpw, "medium") == 0)
-    return (FW_MEDIUM);
-  else if (stricmp (lpw, "normal") == 0)
-    return (FW_NORMAL);
+
+  if (stricmp (lpw,"heavy") == 0)             return FW_HEAVY;
+  else if (stricmp (lpw,"extrabold") == 0)    return FW_EXTRABOLD;
+  else if (stricmp (lpw,"bold") == 0)         return FW_BOLD;
+  else if (stricmp (lpw,"demibold") == 0)     return FW_SEMIBOLD;
+  else if (stricmp (lpw,"medium") == 0)       return FW_MEDIUM;
+  else if (stricmp (lpw,"normal") == 0)       return FW_NORMAL;
+  else if (stricmp (lpw,"light") == 0)        return FW_LIGHT;
+  else if (stricmp (lpw,"extralight") == 0)   return FW_EXTRALIGHT;
+  else if (stricmp (lpw,"thin") == 0)         return FW_THIN;
   else
-    return (FW_DONTCARE);
+    return FW_DONTCARE;
 }
 
+
 char * 
 win32_to_x_weight (fnweight)
      int fnweight;
 {
-  if (fnweight >= FW_BOLD) 
-    return ("bold");
-  else if (fnweight >= FW_SEMIBOLD) 
-    return ("demibold");
-  else if (fnweight >= FW_MEDIUM) 
-    return ("medium");
-  else  
-    return ("normal");
+  if (fnweight >= FW_HEAVY)      return "heavy";
+  if (fnweight >= FW_EXTRABOLD)  return "extrabold";
+  if (fnweight >= FW_BOLD)       return "bold";
+  if (fnweight >= FW_SEMIBOLD)   return "semibold";
+  if (fnweight >= FW_MEDIUM)     return "medium";
+  if (fnweight >= FW_NORMAL)     return "normal";
+  if (fnweight >= FW_LIGHT)      return "light";
+  if (fnweight >= FW_EXTRALIGHT) return "extralight";
+  if (fnweight >= FW_THIN)       return "thin";
+  else
+    return "*";
+}
+
+LONG
+x_to_win32_charset (lpcs)
+    char * lpcs;
+{
+  if (!lpcs) return (0);
+
+  if (stricmp (lpcs,"ansi") == 0)               return ANSI_CHARSET;
+  else if (stricmp (lpcs,"iso8859-1") == 0)     return ANSI_CHARSET;
+  else if (stricmp (lpcs,"iso8859") == 0)       return ANSI_CHARSET;
+  else if (stricmp (lpcs,"oem") == 0)          return OEM_CHARSET;
+#ifdef UNICODE_CHARSET
+  else if (stricmp (lpcs,"unicode") == 0)       return UNICODE_CHARSET;
+  else if (stricmp (lpcs,"iso10646") == 0)      return UNICODE_CHARSET;
+#endif
+  else
+    return 0;
+}
+
+char *
+win32_to_x_charset (fncharset)
+    int fncharset;
+{
+  switch (fncharset)
+    {
+    case ANSI_CHARSET:     return "ansi";
+    case OEM_CHARSET:      return "oem";
+    case SYMBOL_CHARSET:   return "symbol";
+#ifdef UNICODE_CHARSET
+    case UNICODE_CHARSET:  return "unicode";
+#endif
+    }
+  return "*";
 }
 
 BOOL 
@@ -3291,30 +3963,42 @@ win32_to_x_font (lplogfont, lpxstr, len)
      char * lpxstr;
      int len;
 {
-  if (!lpxstr) return (FALSE);
+  char height_pixels[8];
+  char height_dpi[8];
+  char width_pixels[8];
+
+  if (!lpxstr) abort ();
+
+  if (!lplogfont)
+    return FALSE;
 
-  if (lplogfont
+  if (lplogfont->lfHeight)
     {
-      int height = (lplogfont->lfHeight * 1440) 
-       / one_win32_display_info.height_in;
-      int width = (lplogfont->lfWidth * 1440) 
-       / one_win32_display_info.width_in;
-
-      height = abs (height);
-      _snprintf (lpxstr, len - 1,
-                "-*-%s-%s-%c-%s-%s-*-%d-*-*-%c-%d-*-*-",
-                lplogfont->lfFaceName,
-                win32_to_x_weight (lplogfont->lfWeight),
-                lplogfont->lfItalic ? 'i' : 'r',
-                "*", "*", 
-                height,
-                ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
-                width);
-    } 
-  else 
+      sprintf (height_pixels, "%u", abs (lplogfont->lfHeight));
+      sprintf (height_dpi, "%u",
+              (abs (lplogfont->lfHeight) * 720) / one_win32_display_info.height_in);
+    }
+  else
     {
-      strncpy (lpxstr, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*-", len - 1);
+      strcpy (height_pixels, "*");
+      strcpy (height_dpi, "*");
     }
+  if (lplogfont->lfWidth)
+    sprintf (width_pixels, "%u", lplogfont->lfWidth * 10);
+  else
+    strcpy (width_pixels, "*");
+
+  _snprintf (lpxstr, len - 1,
+            "-*-%s-%s-%c-*-*-%s-%s-*-*-%c-%s-*-%s-",
+            lplogfont->lfFaceName,
+            win32_to_x_weight (lplogfont->lfWeight),
+            lplogfont->lfItalic?'i':'r',
+            height_pixels,
+            height_dpi,
+            ((lplogfont->lfPitchAndFamily & 0x3) == VARIABLE_PITCH) ? 'p' : 'c',
+            width_pixels,
+            win32_to_x_charset (lplogfont->lfCharSet)
+            );
 
   lpxstr[len - 1] = 0;         /* just to be sure */
   return (TRUE);
@@ -3328,57 +4012,132 @@ x_to_win32_font (lpxstr, lplogfont)
   if (!lplogfont) return (FALSE);
   
   memset (lplogfont, 0, sizeof (*lplogfont));
-  
-  lplogfont->lfCharSet = OEM_CHARSET;
+
+#if 1
   lplogfont->lfOutPrecision = OUT_DEFAULT_PRECIS;
   lplogfont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
   lplogfont->lfQuality = DEFAULT_QUALITY;
+#else
+  /* go for maximum quality */
+  lplogfont->lfOutPrecision = OUT_STROKE_PRECIS;
+  lplogfont->lfClipPrecision = CLIP_STROKE_PRECIS;
+  lplogfont->lfQuality = PROOF_QUALITY;
+#endif
+
+  if (!lpxstr)
+    return FALSE;
+
+  /* Provide a simple escape mechanism for specifying Windows font names
+   * directly -- if font spec does not beginning with '-', assume this
+   * format:
+   *   "<font name>[:height in pixels[:width in pixels[:weight]]]"
+   */
   
-  if (lpxstr && *lpxstr == '-') lpxstr++;
-  
-  {
-    int fields;
-    char name[50], weight[20], slant, pitch, height[10], width[10];
-    
-    fields = (lpxstr
-             ? sscanf (lpxstr, 
-                       "%*[^-]-%[^-]-%[^-]-%c-%*[^-]-%*[^-]-%*[^-]-%[^-]-%*[^-]-%*[^-]-%c-%[^-]",
-                       name, weight, &slant, height, &pitch, width)
-             : 0);
-    
-    if (fields == EOF) return (FALSE);
-    
-    if (fields > 0 && name[0] != '*') 
-      {
-       strncpy (lplogfont->lfFaceName, name, LF_FACESIZE);
-      } 
-    else 
+  if (*lpxstr == '-')
+    {
+      int fields;
+      char name[50], weight[20], slant, pitch, pixels[10], height[10], width[10], remainder[20];
+      char * encoding;
+
+      fields = sscanf (lpxstr,
+                      "-%*[^-]-%49[^-]-%19[^-]-%c-%*[^-]-%*[^-]-%9[^-]-%9[^-]-%*[^-]-%*[^-]-%c-%9[^-]-%19s",
+                      name, weight, &slant, pixels, height, &pitch, width, remainder);
+
+      if (fields == EOF) return (FALSE);
+
+      if (fields > 0 && name[0] != '*')
+        {
+         strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
+         lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
+       }
+      else
+        {
+         lplogfont->lfFaceName[0] = 0;
+       }
+
+      fields--;
+
+      lplogfont->lfWeight = x_to_win32_weight ((fields > 0 ? weight : ""));
+
+      fields--;
+
+      if (!NILP (Vwin32_enable_italics))
+       lplogfont->lfItalic = (fields > 0 && slant == 'i');
+
+      fields--;
+
+      if (fields > 0 && pixels[0] != '*')
+       lplogfont->lfHeight = atoi (pixels);
+
+      fields--;
+
+      if (fields > 0 && lplogfont->lfHeight == 0 && height[0] != '*')
+       lplogfont->lfHeight = (atoi (height)
+                              * one_win32_display_info.height_in) / 720;
+
+      fields--;
+
+      lplogfont->lfPitchAndFamily =
+       (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
+
+      fields--;
+
+      if (fields > 0 && width[0] != '*')
+       lplogfont->lfWidth = atoi (width) / 10;
+
+      fields--;
+
+      /* Not all font specs include the registry field, so we allow for an
+        optional registry field before the encoding when parsing
+        remainder.  Also we strip the trailing '-' if present. */
       {
-       lplogfont->lfFaceName[0] = 0;
+       int len = strlen (remainder);
+       if (len > 0 && remainder[len-1] == '-')
+         remainder[len-1] = 0;
       }
-    
-    fields--;
-    
-    lplogfont->lfWeight = x_to_win32_weight((fields > 0 ? weight : ""));
-    
-    fields--;
-    
-    lplogfont->lfItalic = (fields > 0 && slant == 'i');
-    
-    fields--;
-    
-    if (fields > 0 && height[0] != '*')
-      lplogfont->lfHeight = (atoi (height) * one_win32_display_info.height_in) / 1440;
-    
-    fields--;
-    
-    lplogfont->lfPitchAndFamily = (fields > 0 && pitch == 'p') ? VARIABLE_PITCH : FIXED_PITCH;
-    
-    fields--;
-    
-    if (fields > 0 && width[0] != '*')
-      lplogfont->lfWidth = (atoi (width) * one_win32_display_info.width_in) / 1440;
-  }
+      encoding = remainder;
+      if (strncmp (encoding, "*-", 2) == 0)
+       encoding += 2;
+      lplogfont->lfCharSet = x_to_win32_charset (fields > 0 ? encoding : "");
+    }
+  else
+    {
+      int fields;
+      char name[100], height[10], width[10], weight[20];
+
+      fields = sscanf (lpxstr,
+                      "%99[^:]:%9[^:]:%9[^:]:%19s",
+                      name, height, width, weight);
+
+      if (fields == EOF) return (FALSE);
+
+      if (fields > 0)
+        {
+         strncpy (lplogfont->lfFaceName,name, LF_FACESIZE);
+         lplogfont->lfFaceName[LF_FACESIZE-1] = 0;
+       }
+      else
+        {
+         lplogfont->lfFaceName[0] = 0;
+       }
+
+      fields--;
+
+      if (fields > 0)
+       lplogfont->lfHeight = atoi (height);
+
+      fields--;
+
+      if (fields > 0)
+       lplogfont->lfWidth = atoi (width);
+
+      fields--;
+
+      lplogfont->lfWeight = x_to_win32_weight ((fields > 0 ? weight : ""));
+    }
+
+  /* This makes TrueType fonts work better. */
+  lplogfont->lfHeight = - abs (lplogfont->lfHeight);
   
   return (TRUE);
 }
@@ -3421,6 +4180,7 @@ typedef struct enumfont_t
 {
   HDC hdc;
   int numFonts;
+  LOGFONT logfont;
   XFontStruct *size_ref;
   Lisp_Object *pattern;
   Lisp_Object *head;
@@ -3442,6 +4202,12 @@ enum_font_cb2 (lplf, lptm, FontType, lpef)
   {
     char buf[100];
 
+    if (!NILP (*(lpef->pattern)) && FontType == TRUETYPE_FONTTYPE)
+      {
+       lplf->elfLogFont.lfHeight = lpef->logfont.lfHeight;
+       lplf->elfLogFont.lfWidth = lpef->logfont.lfWidth;
+      }
+
     if (!win32_to_x_font (lplf, buf, 100)) return (0);
 
     if (NILP (*(lpef->pattern)) || win32_font_match (buf, XSTRING (*(lpef->pattern))->data))
@@ -3570,9 +4336,10 @@ even if they match PATTERN and FACE.")
   ef.pattern = &pattern;
   ef.tail = ef.head = &namelist;
   ef.numFonts = 0;
+  x_to_win32_font (STRINGP (pattern) ? XSTRING (pattern)->data : NULL, &ef.logfont);
 
   {
-    ef.hdc = my_get_dc (FRAME_WIN32_WINDOW (f));
+    ef.hdc = GetDC (FRAME_WIN32_WINDOW (f));
 
     EnumFontFamilies (ef.hdc, NULL, (FONTENUMPROC) enum_font_cb1, (LPARAM)&ef);
     
@@ -3758,9 +4525,11 @@ If omitted or nil, that stands for the selected frame's display.")
   HDC hdc;
   int cap;
 
-  hdc = my_get_dc (dpyinfo->root_window);
-  
-  cap = GetDeviceCaps (hdc,NUMCOLORS);
+  hdc = GetDC (dpyinfo->root_window);
+  if (dpyinfo->has_palette)
+    cap = GetDeviceCaps (hdc,SIZEPALETTE);
+  else
+    cap = GetDeviceCaps (hdc,NUMCOLORS);
   
   ReleaseDC (dpyinfo->root_window, hdc);
   
@@ -3839,7 +4608,7 @@ If omitted or nil, that stands for the selected frame's display.")
   HDC hdc;
   int cap;
 
-  hdc = my_get_dc (dpyinfo->root_window);
+  hdc = GetDC (dpyinfo->root_window);
   
   cap = GetDeviceCaps (hdc, VERTSIZE);
   
@@ -3861,7 +4630,7 @@ If omitted or nil, that stands for the selected frame's display.")
   HDC hdc;
   int cap;
 
-  hdc = my_get_dc (dpyinfo->root_window);
+  hdc = GetDC (dpyinfo->root_window);
   
   cap = GetDeviceCaps (hdc, HORZSIZE);
   
@@ -4018,7 +4787,27 @@ terminate Emacs if we can't open the connection.")
   if (! NILP (xrm_string))
     CHECK_STRING (xrm_string, 1);
 
-  Vwin32_color_map = Fwin32_default_color_map ();
+  /* Allow color mapping to be defined externally; first look in user's
+     HOME directory, then in Emacs etc dir for a file called rgb.txt. */
+  {
+    Lisp_Object color_file;
+    struct gcpro gcpro1;
+
+    color_file = build_string("~/rgb.txt");
+
+    GCPRO1 (color_file);
+
+    if (NILP (Ffile_readable_p (color_file)))
+      color_file =
+       Fexpand_file_name (build_string ("rgb.txt"),
+                          Fsymbol_value (intern ("data-directory")));
+
+    Vwin32_color_map = Fwin32_load_color_file (color_file);
+
+    UNGCPRO;
+  }
+  if (NILP (Vwin32_color_map))
+    Vwin32_color_map = Fwin32_default_color_map ();
 
   if (! NILP (xrm_string))
     xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
@@ -4026,6 +4815,15 @@ terminate Emacs if we can't open the connection.")
     xrm_option = (unsigned char *) 0;
 
   /* Use this general default value to start with.  */
+  /* First remove .exe suffix from invocation-name - it looks ugly. */
+  {
+    char basename[ MAX_PATH ], *str;
+
+    strcpy (basename, XSTRING (Vinvocation_name)->data);
+    str = strrchr (basename, '.');
+    if (str) *str = 0;
+    Vinvocation_name = build_string (basename);
+  }
   Vx_resource_name = Vinvocation_name;
 
   validate_x_resource_name ();
@@ -4159,8 +4957,6 @@ syms_of_win32fns ()
   staticpro (&Qcursor_color);
   Qcursor_type = intern ("cursor-type");
   staticpro (&Qcursor_type);
-  Qfont = intern ("font");
-  staticpro (&Qfont);
   Qforeground_color = intern ("foreground-color");
   staticpro (&Qforeground_color);
   Qgeometry = intern ("geometry");
@@ -4218,6 +5014,48 @@ syms_of_win32fns ()
               "A array of color name mappings for windows.");
   Vwin32_color_map = Qnil;
 
+  DEFVAR_LISP ("win32-pass-alt-to-system", &Vwin32_pass_alt_to_system,
+              "Non-nil if alt key presses are passed on to Windows.\n\
+When non-nil, for example, alt pressed and released and then space will\n\
+open the System menu.  When nil, Emacs silently swallows alt key events.");
+  Vwin32_pass_alt_to_system = Qnil;
+
+  DEFVAR_LISP ("win32-alt-is-meta", &Vwin32_alt_is_meta,
+              "Non-nil if the alt key is to be considered the same as the meta key.\n\
+When nil, Emacs will translate the alt key to the Alt modifier, and not Meta.");
+  Vwin32_alt_is_meta = Qt;
+
+  DEFVAR_LISP ("win32-pass-optional-keys-to-system", 
+              &Vwin32_pass_optional_keys_to_system,
+              "Non-nil if the 'optional' keys (left window, right window,\n\
+and application keys) are passed on to Windows.");
+  Vwin32_pass_optional_keys_to_system = Qnil;
+
+  DEFVAR_LISP ("win32-enable-italics", &Vwin32_enable_italics,
+              "Non-nil enables selection of artificially italicized fonts.");
+  Vwin32_enable_italics = Qnil;
+
+  DEFVAR_LISP ("win32-enable-palette", &Vwin32_enable_palette,
+              "Non-nil enables Windows palette management to map colors exactly.");
+  Vwin32_enable_palette = Qt;
+
+  DEFVAR_INT ("win32-mouse-button-tolerance",
+             &Vwin32_mouse_button_tolerance,
+             "Analogue of double click interval for faking middle mouse events.\n\
+The value is the minimum time in milliseconds that must elapse between\n\
+left/right button down events before they are considered distinct events.\n\
+If both mouse buttons are depressed within this interval, a middle mouse\n\
+button down event is generated instead.");
+  XSETINT (Vwin32_mouse_button_tolerance, GetDoubleClickTime () / 2);
+
+  DEFVAR_INT ("win32-mouse-move-interval",
+             &Vwin32_mouse_move_interval,
+             "Minimum interval between mouse move events.\n\
+The value is the minimum time in milliseconds that must elapse between\n\
+successive mouse move (or scroll bar drag) events before they are\n\
+reported as lisp events.");
+  XSETINT (Vwin32_mouse_move_interval, 50);
+
   init_x_parm_symbols ();
 
   DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
@@ -4293,6 +5131,9 @@ unless you set it to something else.");
   /* Win32 specific functions */
 
   defsubr (&Swin32_select_font);
+  defsubr (&Swin32_define_rgb_color);
+  defsubr (&Swin32_default_color_map);
+  defsubr (&Swin32_load_color_file);
 }
 
 #undef abort
@@ -4300,9 +5141,24 @@ unless you set it to something else.");
 void 
 win32_abort()
 {
-    MessageBox (NULL,
-               "A fatal error has occurred - aborting!",
-               "Emacs Abort Dialog",
-               MB_OK|MB_ICONEXCLAMATION);
-    abort();
+  int button;
+  button = MessageBox (NULL,
+                      "A fatal error has occurred!\n\n"
+                      "Select Abort to exit, Retry to debug, Ignore to continue",
+                      "Emacs Abort Dialog",
+                      MB_ICONEXCLAMATION | MB_TASKMODAL
+                      | MB_SETFOREGROUND | MB_ABORTRETRYIGNORE);
+  switch (button)
+    {
+    case IDRETRY:
+      DebugBreak ();
+      break;
+    case IDIGNORE:
+      break;
+    case IDABORT:
+    default:
+      abort ();
+      break;
+    }
 }
+