Replace `abs' with `eabs'.
[bpt/emacs.git] / src / w32term.c
index c00fdb8..6a1d1c2 100644 (file)
@@ -1,12 +1,13 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-                 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
+                 1999, 2000, 2001, 2002, 2003, 2004, 2005,
+                 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
 GNU Emacs is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
@@ -57,8 +58,6 @@ Boston, MA 02110-1301, USA.  */
 #include "composite.h"
 #include "coding.h"
 
-#define abs(x) ((x) < 0 ? -(x) : (x))
-
 \f
 /* Fringe bitmaps.  */
 
@@ -217,10 +216,9 @@ extern int errno;
 extern EMACS_INT extra_keyboard_modifiers;
 
 static void x_update_window_end P_ ((struct window *, int, int));
-void w32_delete_display P_ ((struct w32_display_info *));
 static void w32_handle_tool_bar_click P_ ((struct frame *,
                                           struct input_event *));
-void w32_define_cursor P_ ((Window, Cursor));
+static void w32_define_cursor P_ ((Window, Cursor));
 
 void x_lower_frame P_ ((struct frame *));
 void x_scroll_bar_clear P_ ((struct frame *));
@@ -229,14 +227,14 @@ void x_raise_frame P_ ((struct frame *));
 void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
-void w32_initialize P_ ((void));
+static void w32_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 int x_compute_min_glyph_bounds P_ ((struct frame *));
 static void x_update_end P_ ((struct frame *));
 static void w32_frame_up_to_date P_ ((struct frame *));
-static void w32_set_terminal_modes P_ ((void));
-static void w32_reset_terminal_modes P_ ((void));
-static void x_clear_frame P_ ((void));
+static void w32_set_terminal_modes P_ ((struct terminal *));
+static void w32_reset_terminal_modes P_ ((struct terminal *));
+static void x_clear_frame P_ ((struct frame *));
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct w32_display_info *,
@@ -682,6 +680,60 @@ w32_draw_fringe_bitmap (w, row, p)
 
   hdc = get_frame_dc (f);
 
+  if (!p->overlay_p)
+    {
+      int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny;
+
+      /* If the fringe is adjacent to the left (right) scroll bar of a
+        leftmost (rightmost, respectively) window, then extend its
+        background to the gap between the fringe and the bar.  */
+      if ((WINDOW_LEFTMOST_P (w)
+          && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+         || (WINDOW_RIGHTMOST_P (w)
+             && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)))
+       {
+         int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
+
+         if (sb_width > 0)
+           {
+             int left = WINDOW_SCROLL_BAR_AREA_X (w);
+             int width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
+                          * FRAME_COLUMN_WIDTH (f));
+
+             if (bx < 0)
+               {
+                 /* Bitmap fills the fringe.  */
+                 if (left + width == p->x)
+                   bx = left + sb_width;
+                 else if (p->x + p->wd == left)
+                   bx = left;
+                 if (bx >= 0)
+                   {
+                     int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
+
+                     nx = width - sb_width;
+                     by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
+                                                           row->y));
+                     ny = row->visible_height;
+                   }
+               }
+             else
+               {
+                 if (left + width == bx)
+                   {
+                     bx = left + sb_width;
+                     nx += width - sb_width;
+                   }
+                 else if (bx + nx == left)
+                   nx += width - sb_width;
+               }
+           }
+       }
+
+      if (bx >= 0 && nx > 0)
+       w32_fill_area (f, hdc, face->background, bx, by, nx, ny);
+    }
+
   /* Must clip because of partially visible lines.  */
   rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
   if (p->y < rowY)
@@ -699,12 +751,6 @@ w32_draw_fringe_bitmap (w, row, p)
   else
     w32_clip_to_row (w, row, -1, hdc);
 
-  if (p->bx >= 0 && !p->overlay_p)
-    {
-      w32_fill_area (f, hdc, face->background,
-                    p->bx, p->by, p->nx, p->ny);
-    }
-
   if (p->which && p->which < max_fringe_bmp)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
@@ -800,7 +846,7 @@ w32_destroy_fringe_bitmap (which)
    rarely happens).  */
 
 static void
-w32_set_terminal_modes (void)
+w32_set_terminal_modes (struct terminal *term)
 {
 }
 
@@ -808,7 +854,7 @@ w32_set_terminal_modes (void)
    the W32 windows go away, and suspending requires no action. */
 
 static void
-w32_reset_terminal_modes (void)
+w32_reset_terminal_modes (struct terminal *term)
 {
 }
 
@@ -1542,7 +1588,7 @@ x_draw_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
+    x = s->x + eabs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -1591,7 +1637,10 @@ x_draw_glyph_string_foreground (s)
        {
          /* For overstriking (to simulate bold-face), draw the
             characters again shifted to the right by one pixel.  */
+         int old_BkMode = SetBkMode (s->hdc, TRANSPARENT);
          w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
+         if (old_BkMode && old_BkMode != TRANSPARENT)
+           SetBkMode (s->hdc, old_BkMode);
        }
     }
   if (s->font && s->font->hfont)
@@ -1611,7 +1660,7 @@ x_draw_composite_glyph_string_foreground (s)
      of S to the right of that box line.  */
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p)
-    x = s->x + abs (s->face->box_line_width);
+    x = s->x + eabs (s->face->box_line_width);
   else
     x = s->x;
 
@@ -1941,7 +1990,7 @@ x_draw_glyph_string_box (s)
                ? s->first_glyph
                : s->first_glyph + s->nchars - 1);
 
-  width = abs (s->face->box_line_width);
+  width = eabs (s->face->box_line_width);
   raised_p = s->face->box == FACE_RAISED_BOX;
   left_x = s->x;
   right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
@@ -1987,7 +2036,7 @@ x_draw_image_foreground (s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2080,7 +2129,7 @@ x_draw_image_relief (s)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2097,7 +2146,7 @@ x_draw_image_relief (s)
     }
   else
     {
-      thick = abs (s->img->relief);
+      thick = eabs (s->img->relief);
       raised_p = s->img->relief > 0;
     }
 
@@ -2134,7 +2183,7 @@ w32_draw_image_foreground_1 (s, pixmap)
   if (s->face->box != FACE_NO_BOX
       && s->first_glyph->left_box_line_p
       && s->slice.x == 0)
-    x += abs (s->face->box_line_width);
+    x += eabs (s->face->box_line_width);
 
   /* If there is a margin around the image, adjust x- and y-position
      by that margin.  */
@@ -2246,7 +2295,7 @@ x_draw_image_glyph_string (s)
      struct glyph_string *s;
 {
   int x, y;
-  int box_line_hwidth = abs (s->face->box_line_width);
+  int box_line_hwidth = eabs (s->face->box_line_width);
   int box_line_vwidth = max (s->face->box_line_width, 0);
   int height;
   HBITMAP pixmap = 0;
@@ -2543,10 +2592,10 @@ x_draw_glyph_string (s)
           unsigned long dy = 0, h = 1;
 
           if (s->face->overline_color_defaulted_p)
-        {
-          w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+           {
+             w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
                          s->y + dy, s->background_width, h);
-        }
+           }
           else
             {
               w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
@@ -2568,7 +2617,7 @@ x_draw_glyph_string (s)
             }
           else
             {
-              w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+              w32_fill_area (s->f, s->hdc, s->face->strike_through_color, s->x,
                              s->y + dy, s->width, h);
             }
         }
@@ -2604,16 +2653,10 @@ w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
    for X frames.  */
 
 static void
-x_delete_glyphs (n)
+x_delete_glyphs (f, n)
+     struct frame *f;
      register int n;
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -2625,15 +2668,8 @@ x_delete_glyphs (n)
    frame.  Otherwise clear the selected frame.  */
 
 static void
-x_clear_frame ()
+x_clear_frame (struct frame *f)
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -2660,18 +2696,14 @@ x_clear_frame ()
 /* Make audible bell.  */
 
 static void
-w32_ring_bell (void)
+w32_ring_bell (struct frame *f)
 {
-  struct frame *f;
-
-  f = SELECTED_FRAME ();
-
   BLOCK_INPUT;
 
   if (FRAME_W32_P (f) && visible_bell)
     {
       int i;
-      HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
+      HWND hwnd = FRAME_W32_WINDOW (f);
 
       for (i = 0; i < 5; i++)
        {
@@ -2681,7 +2713,7 @@ w32_ring_bell (void)
       FlashWindow (hwnd, FALSE);
     }
   else
-      w32_sys_ring_bell ();
+      w32_sys_ring_bell (f);
 
   UNBLOCK_INPUT;
 }
@@ -2708,16 +2740,10 @@ w32_set_terminal_window (n)
    lines or deleting -N lines at vertical position VPOS.  */
 
 static void
-x_ins_del_lines (vpos, n)
+x_ins_del_lines (f, vpos, n)
+     struct frame *f;
      int vpos, n;
 {
-  struct frame *f;
-
-  if (updating_frame)
-    f = updating_frame;
-  else
-    f = SELECTED_FRAME ();
-
   if (! FRAME_W32_P (f))
     return;
 
@@ -3122,7 +3148,8 @@ construct_mouse_wheel (result, msg, f)
   POINT p;
   int delta;
 
-  result->kind = WHEEL_EVENT;
+  result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
+                                                    : WHEEL_EVENT;
   result->code = 0;
   result->timestamp = msg->msg.time;
 
@@ -3274,7 +3301,7 @@ redo_mouse_highlight ()
                          HIWORD (last_mouse_motion_event.lParam));
 }
 
-void
+static void
 w32_define_cursor (window, cursor)
      Window window;
      Cursor cursor;
@@ -3470,25 +3497,51 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
      int portion, position, whole;
 {
   Window w = SCROLL_BAR_W32_WINDOW (bar);
-  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
+  /* We use the whole scroll-bar height in the calculations below, to
+     avoid strange effects like scrolling backwards when just clicking
+     on the handle (without moving it).  */
+  double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
+                 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
   int sb_page, sb_pos;
   BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
   SCROLLINFO si;
 
+  /* We used to change the nPage setting while dragging the handle,
+     but that had very strange effects (such as scrolling backwards
+     while dragging downwards).
+
+     Now, we don't change the nPage setting while dragging unless we
+     get near to the end of the buffer, in which case we often have to
+     resize the handle to "go all the way".  */
+
+  if (draggingp)
+    {
+      int near_bottom_p;
+      BLOCK_INPUT;
+      si.cbSize = sizeof (si);
+      si.fMask = SIF_POS | SIF_PAGE;
+      GetScrollInfo(w, SB_CTL, &si);
+      near_bottom_p = si.nPos + si.nPage >= range;
+      UNBLOCK_INPUT;
+      if (!near_bottom_p)
+       return;
+    }
+
   if (whole)
     {
       /* Position scroll bar at rock bottom if the bottom of the
          buffer is visible. This avoids shinking the thumb away
          to nothing if it is held at the bottom of the buffer.  */
-      if (position + portion >= whole)
-        {
-          sb_page = range * (whole - position) / whole
-            + VERTICAL_SCROLL_BAR_MIN_HANDLE;
-          sb_pos = range;
-        }
-
-      sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
-      sb_pos = position * range / whole;
+      if (position + portion >= whole && !draggingp)
+       {
+         sb_page = range * (whole - position) / whole;
+         sb_pos = range;
+       }
+      else
+       {
+         sb_pos = position * range / whole;
+         sb_page = (min (portion, (whole - position)) * range) / whole;
+       }
     }
   else
     {
@@ -3496,19 +3549,16 @@ w32_set_scroll_bar_thumb (bar, portion, position, whole)
       sb_pos = 0;
     }
 
+  sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
+
   BLOCK_INPUT;
 
   si.cbSize = sizeof (si);
-  /* Only update page size if currently dragging, to reduce
-     flicker effects.  */
-  if (draggingp)
-    si.fMask = SIF_PAGE;
-  else
-    si.fMask = SIF_PAGE | SIF_POS;
+  si.fMask = SIF_PAGE | SIF_POS;
   si.nPage = sb_page;
   si.nPos = sb_pos;
 
-  SetScrollInfo (w, SB_CTL, &si, !draggingp);
+  SetScrollInfo (w, SB_CTL, &si, TRUE);
 
   UNBLOCK_INPUT;
 }
@@ -3611,6 +3661,7 @@ x_scroll_bar_create (w, top, left, width, height)
   XSETINT (bar->start, 0);
   XSETINT (bar->end, 0);
   bar->dragging = Qnil;
+  bar->fringe_extended_p = Qnil;
 
   /* Requires geometry to be set before call to create the real window */
 
@@ -3674,6 +3725,7 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
   struct scroll_bar *bar;
   int top, height, left, sb_left, width, sb_width;
   int window_y, window_height;
+  int fringe_extended_p;
 
   /* Get window dimensions.  */
   window_box (w, -1, 0, &window_y, 0, &window_height);
@@ -3693,9 +3745,20 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
 
   /* Compute the left edge of the scroll bar.  */
   if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
-    sb_left = left + width - sb_width - (width - sb_width) / 2;
+    sb_left = left + (WINDOW_RIGHTMOST_P (w) ? width - sb_width : 0);
+  else
+    sb_left = left + (WINDOW_LEFTMOST_P (w) ? 0 : width - sb_width);
+
+  if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
+    fringe_extended_p = (WINDOW_LEFTMOST_P (w)
+                        && WINDOW_LEFT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_LEFT_MARGIN_COLS (w) == 0));
   else
-    sb_left = left + (width - sb_width) / 2;
+    fringe_extended_p = (WINDOW_RIGHTMOST_P (w)
+                        && WINDOW_RIGHT_FRINGE_WIDTH (w)
+                        && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
+                            || WINDOW_RIGHT_MARGIN_COLS (w) == 0));
 
   /* Does the scroll bar exist yet?  */
   if (NILP (w->vertical_scroll_bar))
@@ -3705,7 +3768,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
       if (width > 0 && height > 0)
        {
          hdc = get_frame_dc (f);
-         w32_clear_area (f, hdc, left, top, width, height);
+         if (fringe_extended_p)
+           w32_clear_area (f, hdc, sb_left, top, sb_width, height);
+         else
+           w32_clear_area (f, hdc, left, top, width, height);
          release_frame_dc (f, hdc);
        }
       UNBLOCK_INPUT;
@@ -3724,7 +3790,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
       if ( XINT (bar->left) == sb_left
            && XINT (bar->top) == top
            && XINT (bar->width) ==  sb_width
-           && XINT (bar->height) == height )
+           && XINT (bar->height) == height
+          && !NILP (bar->fringe_extended_p) == fringe_extended_p )
         {
           /* Redraw after clear_frame. */
           if (!my_show_window (f, hwnd, SW_NORMAL))
@@ -3741,11 +3808,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
              hdc = get_frame_dc (f);
              /* Since Windows scroll bars are smaller than the space reserved
                 for them on the frame, we have to clear "under" them.  */
-             w32_clear_area (f, hdc,
-                             left,
-                             top,
-                             width,
-                             height);
+             if (fringe_extended_p)
+               w32_clear_area (f, hdc, sb_left, top, sb_width, height);
+             else
+               w32_clear_area (f, hdc, left, top, width, height);
              release_frame_dc (f, hdc);
            }
           /* Make sure scroll bar is "visible" before moving, to ensure the
@@ -3775,6 +3841,8 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
           UNBLOCK_INPUT;
         }
     }
+  bar->fringe_extended_p = fringe_extended_p ? Qt : Qnil;
+
   w32_set_scroll_bar_thumb (bar, portion, position, whole);
 
   XSETVECTOR (w->vertical_scroll_bar, bar);
@@ -4309,10 +4377,16 @@ w32_read_socket (sd, expected, hold_quit)
                  /* Window will be selected only when it is not
                     selected now and last mouse movement event was
                     not in it.  Minibuffer window will be selected
-                    iff it is active.  */
+                    only when it is active.  */
                  if (WINDOWP(window)
                      && !EQ (window, last_window)
-                     && !EQ (window, selected_window))
+                     && !EQ (window, selected_window)
+                     /* For click-to-focus window managers
+                        create event iff we don't leave the
+                        selected frame.  */
+                     && (focus_follows_mouse
+                         || (EQ (XWINDOW (window)->frame,
+                                 XWINDOW (selected_window)->frame))))
                    {
                      inev.kind = SELECT_WINDOW_EVENT;
                      inev.frame_or_window = window;
@@ -4417,6 +4491,7 @@ w32_read_socket (sd, expected, hold_quit)
          }
 
        case WM_MOUSEWHEEL:
+        case WM_MOUSEHWHEEL:
          {
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
@@ -4436,7 +4511,7 @@ w32_read_socket (sd, expected, hold_quit)
                /* Ignore any mouse motion that happened before this
                   event; any subsequent mouse-movement Emacs events
                   should reflect only motion after the
-                  ButtonPress.  */
+                  ButtonPress.  */
                f->mouse_moved = 0;
              }
            last_mouse_frame = f;
@@ -5843,8 +5918,8 @@ x_free_frame_resources (f)
 
   free_frame_menubar (f);
 
-  unload_color (f, f->output_data.x->foreground_pixel);
-  unload_color (f, f->output_data.x->background_pixel);
+  unload_color (f, FRAME_FOREGROUND_PIXEL (f));
+  unload_color (f, FRAME_BACKGROUND_PIXEL (f));
   unload_color (f, f->output_data.w32->cursor_pixel);
   unload_color (f, f->output_data.w32->cursor_foreground_pixel);
   unload_color (f, f->output_data.w32->border_pixel);
@@ -5883,14 +5958,13 @@ x_free_frame_resources (f)
 
 
 /* Destroy the window of frame F.  */
-
+void
 x_destroy_window (f)
      struct frame *f;
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
 
   x_free_frame_resources (f);
-
   dpyinfo->reference_count--;
 }
 
@@ -6150,6 +6224,132 @@ w32_make_rdb (xrm_option)
   return buffer;
 }
 
+void
+x_flush (struct frame * f)
+{ /* Nothing to do */ }
+
+
+extern frame_parm_handler w32_frame_parm_handlers[];
+
+static struct redisplay_interface w32_redisplay_interface =
+{
+  w32_frame_parm_handlers,
+  x_produce_glyphs,
+  x_write_glyphs,
+  x_insert_glyphs,
+  x_clear_end_of_line,
+  x_scroll_run,
+  x_after_update_window_line,
+  x_update_window_begin,
+  x_update_window_end,
+  x_cursor_to,
+  x_flush,
+  0,  /* flush_display_optional */
+  x_clear_window_mouse_face,
+  w32_get_glyph_overhangs,
+  x_fix_overlapping_area,
+  w32_draw_fringe_bitmap,
+  w32_define_fringe_bitmap,
+  w32_destroy_fringe_bitmap,
+  w32_per_char_metric,
+  w32_encode_char,
+  NULL, /* w32_compute_glyph_string_overhangs */
+  x_draw_glyph_string,
+  w32_define_frame_cursor,
+  w32_clear_frame_area,
+  w32_draw_window_cursor,
+  w32_draw_vertical_window_border,
+  w32_shift_glyphs_for_insert
+};
+
+static void x_delete_terminal (struct terminal *term);
+
+static struct terminal *
+w32_create_terminal (struct w32_display_info *dpyinfo)
+{
+  struct terminal *terminal;
+
+  terminal = create_terminal ();
+
+  terminal->type = output_w32;
+  terminal->display_info.w32 = dpyinfo;
+  dpyinfo->terminal = terminal;
+
+  /* MSVC does not type K&R functions with no arguments correctly, and
+     so we must explicitly cast them.  */
+  terminal->clear_frame_hook = x_clear_frame;
+  terminal->ins_del_lines_hook = x_ins_del_lines;
+  terminal->delete_glyphs_hook = x_delete_glyphs;
+  terminal->ring_bell_hook = w32_ring_bell;
+  terminal->reset_terminal_modes_hook = w32_reset_terminal_modes;
+  terminal->set_terminal_modes_hook = w32_set_terminal_modes;
+  terminal->update_begin_hook = x_update_begin;
+  terminal->update_end_hook = x_update_end;
+  terminal->set_terminal_window_hook = w32_set_terminal_window;
+  terminal->read_socket_hook = w32_read_socket;
+  terminal->frame_up_to_date_hook = w32_frame_up_to_date;
+  terminal->mouse_position_hook = w32_mouse_position;
+  terminal->frame_rehighlight_hook = w32_frame_rehighlight;
+  terminal->frame_raise_lower_hook = w32_frame_raise_lower;
+  //  terminal->fullscreen_hook = XTfullscreen_hook;
+  terminal->set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
+  terminal->condemn_scroll_bars_hook = w32_condemn_scroll_bars;
+  terminal->redeem_scroll_bar_hook = w32_redeem_scroll_bar;
+  terminal->judge_scroll_bars_hook = w32_judge_scroll_bars;
+
+  terminal->delete_frame_hook = x_destroy_window;
+  terminal->delete_terminal_hook = x_delete_terminal;
+
+  terminal->rif = &w32_redisplay_interface;
+  terminal->scroll_region_ok = 1;    /* We'll scroll partial frames. */
+  terminal->char_ins_del_ok = 1;
+  terminal->line_ins_del_ok = 1;         /* We'll just blt 'em. */
+  terminal->fast_clear_end_of_line = 1;  /* X does this well. */
+  terminal->memory_below_frame = 0;   /* We don't remember what scrolls
+                                        off the bottom. */
+
+#ifdef MULTI_KBOARD
+  /* We don't yet support separate terminals on W32, so don't try to share
+     keyboards between virtual terminals that are on the same physical
+     terminal like X does.  */
+  terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
+  init_kboard (terminal->kboard);
+  terminal->kboard->next_kboard = all_kboards;
+  all_kboards = terminal->kboard;
+  /* Don't let the initial kboard remain current longer than necessary.
+     That would cause problems if a file loaded on startup tries to
+     prompt in the mini-buffer.  */
+  if (current_kboard == initial_kboard)
+    current_kboard = terminal->kboard;
+  terminal->kboard->reference_count++;
+#endif
+
+  return terminal;
+}
+
+static void
+x_delete_terminal (struct terminal *terminal)
+{
+  struct w32_display_info *dpyinfo = terminal->display_info.w32;
+  int i;
+
+  /* Protect against recursive calls.  Fdelete_frame in
+     delete_terminal calls us back when it deletes our last frame.  */
+  if (!terminal->name)
+    return;
+
+  BLOCK_INPUT;
+  /* Free the fonts in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+        DeleteObject (((XFontStruct*)(dpyinfo->font_table[i].font))->hfont);
+      }
+
+  x_delete_display (dpyinfo);
+  UNBLOCK_INPUT;
+}
+
 struct w32_display_info *
 w32_term_init (display_name, xrm_option, resource_name)
      Lisp_Object display_name;
@@ -6157,6 +6357,7 @@ w32_term_init (display_name, xrm_option, resource_name)
      char *resource_name;
 {
   struct w32_display_info *dpyinfo;
+  struct terminal *terminal;
   HDC hdc;
 
   BLOCK_INPUT;
@@ -6170,6 +6371,12 @@ w32_term_init (display_name, xrm_option, resource_name)
   w32_initialize_display_info (display_name);
 
   dpyinfo = &one_w32_display_info;
+  terminal = w32_create_terminal (dpyinfo);
+
+  /* Set the name of the terminal. */
+  terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
+  strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
+  terminal->name[SBYTES (display_name)] = 0;
 
   dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
 
@@ -6199,6 +6406,9 @@ w32_term_init (display_name, xrm_option, resource_name)
     w32_defined_color (0, "black", &color, 1);
   }
 
+  /* Add the default keyboard.  */
+  add_keyboard_wait_descriptor (0);
+
   /* Create Fringe Bitmaps and store them for later use.
 
      On W32, bitmaps are all unsigned short, as Windows requires
@@ -6206,7 +6416,7 @@ w32_term_init (display_name, xrm_option, resource_name)
      horizontally reflected compared to how they appear on X, so we
      need to bitswap and convert to unsigned shorts before creating
      the bitmaps.  */
-  w32_init_fringe ();
+  w32_init_fringe (terminal->rif);
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
@@ -6230,7 +6440,6 @@ w32_term_init (display_name, xrm_option, resource_name)
 }
 \f
 /* Get rid of display DPYINFO, assuming all frames are already gone.  */
-
 void
 x_delete_display (dpyinfo)
      struct w32_display_info *dpyinfo;
@@ -6279,75 +6488,11 @@ x_delete_display (dpyinfo)
 \f
 /* Set up use of W32.  */
 
-DWORD w32_msg_worker ();
-
-void
-x_flush (struct frame * f)
-{ /* Nothing to do */ }
-
-extern frame_parm_handler w32_frame_parm_handlers[];
-
-static struct redisplay_interface w32_redisplay_interface =
-{
-  w32_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
-  0,  /* flush_display_optional */
-  x_clear_window_mouse_face,
-  w32_get_glyph_overhangs,
-  x_fix_overlapping_area,
-  w32_draw_fringe_bitmap,
-  w32_define_fringe_bitmap,
-  w32_destroy_fringe_bitmap,
-  w32_per_char_metric,
-  w32_encode_char,
-  NULL, /* w32_compute_glyph_string_overhangs */
-  x_draw_glyph_string,
-  w32_define_frame_cursor,
-  w32_clear_frame_area,
-  w32_draw_window_cursor,
-  w32_draw_vertical_window_border,
-  w32_shift_glyphs_for_insert
-};
+DWORD WINAPI w32_msg_worker (void * arg);
 
-void
+static void
 w32_initialize ()
 {
-  rif = &w32_redisplay_interface;
-
-  /* MSVC does not type K&R functions with no arguments correctly, and
-     so we must explicitly cast them.  */
-  clear_frame_hook = (void (*)(void)) x_clear_frame;
-  ring_bell_hook = (void (*)(void)) w32_ring_bell;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-
-  read_socket_hook = w32_read_socket;
-
-  frame_up_to_date_hook = w32_frame_up_to_date;
-
-  mouse_position_hook = w32_mouse_position;
-  frame_rehighlight_hook = w32_frame_rehighlight;
-  frame_raise_lower_hook = w32_frame_raise_lower;
-  set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
-  condemn_scroll_bars_hook = w32_condemn_scroll_bars;
-  redeem_scroll_bar_hook = w32_redeem_scroll_bar;
-  judge_scroll_bars_hook = w32_judge_scroll_bars;
-
-  scroll_region_ok = 1;         /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;          /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;   /* X does this well */
-  memory_below_frame = 0;       /* we don't remember what scrolls
-                                  off the bottom */
   baud_rate = 19200;
 
   w32_system_caret_hwnd = NULL;
@@ -6384,8 +6529,8 @@ w32_initialize ()
     PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
 
     hWindowsThread = CreateThread (NULL, 0,
-                              (LPTHREAD_START_ROUTINE) w32_msg_worker,
-                              0, 0, &dwWindowsThreadId);
+                                   w32_msg_worker,
+                                   0, 0, &dwWindowsThreadId);
 
     GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
   }
@@ -6513,7 +6658,7 @@ the cursor have no effect.  */);
   DEFVAR_BOOL ("x-use-underline-position-properties",
               &x_use_underline_position_properties,
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
-nil means ignore them.  If you encounter fonts with bogus
+A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
 to 4.1, set this to nil.
 
@@ -6523,9 +6668,9 @@ NOTE: Not supported on MS-Windows yet.  */);
   DEFVAR_BOOL ("x-underline-at-descent-line",
               &x_underline_at_descent_line,
      doc: /* *Non-nil means to draw the underline at the same place as the descent line.
-nil means to draw the underline according to the value of the variable
-`x-use-underline-position-properties', which is usually at the baseline
-level.  The default value is nil.  */);
+A value of nil means to draw the underline according to the value of the
+variable `x-use-underline-position-properties', which is usually at the
+baseline level.  The default value is nil.  */);
   x_underline_at_descent_line = 0;
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,