Merged in changes from CVS trunk
[bpt/emacs.git] / src / w32term.c
index 1c4e680..7f3b6b6 100644 (file)
@@ -221,8 +221,6 @@ static int input_signal_count;
 
 extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
-extern Lisp_Object Qface, Qmouse_face;
-
 #ifndef USE_CRT_DLL
 extern int errno;
 #endif
@@ -542,6 +540,9 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
                                output_cursor.x, output_cursor.y);
 
       x_draw_vertical_border (w);
+
+      draw_window_fringes (w);
+
       UNBLOCK_INPUT;
     }
 
@@ -626,11 +627,7 @@ x_after_update_window_line (desired_row)
   xassert (w);
 
   if (!desired_row->mode_line_p && !w->pseudo_window_p)
-    {
-      BLOCK_INPUT;
-      draw_row_fringe_bitmaps (w, desired_row);
-      UNBLOCK_INPUT;
-    }
+    desired_row->redraw_fringe_bitmaps_p = 1;
 
   /* When a window has disappeared, make sure that no rest of
      full-width rows stays visible in the internal border.  Could
@@ -680,34 +677,79 @@ w32_draw_fringe_bitmap (w, row, p)
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   HDC hdc;
   struct face *face = p->face;
+  int rowY;
 
   hdc = get_frame_dc (f);
 
   /* Must clip because of partially visible lines.  */
-  w32_clip_to_row (w, row, hdc);
+  rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
+  if (p->y < rowY)
+    {
+      /* Adjust position of "bottom aligned" bitmap on partially
+        visible last row.  */
+      int oldY = row->y;
+      int oldVH = row->visible_height;
+      row->visible_height = p->h;
+      row->y -= rowY - p->y;
+      w32_clip_to_row (w, row, hdc);
+      row->y = oldY;
+      row->visible_height = oldVH;
+    }
+  else
+    w32_clip_to_row (w, row, hdc);
 
-  if (p->bx >= 0)
+  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 != NO_FRINGE_BITMAP)
+  if (p->which)
     {
       HBITMAP pixmap = fringe_bmp[p->which];
       HDC compat_hdc;
       HANDLE horig_obj;
 
       compat_hdc = CreateCompatibleDC (hdc);
+
       SaveDC (hdc);
 
       horig_obj = SelectObject (compat_hdc, pixmap);
-      SetTextColor (hdc, face->background);
-      SetBkColor (hdc, face->foreground);
 
-      BitBlt (hdc, p->x, p->y, p->wd, p->h,
-             compat_hdc, 0, p->dh,
-             SRCCOPY);
+      /* Paint overlays transparently.  */
+      if (p->overlay_p)
+       {
+         HBRUSH h_brush, h_orig_brush;
+
+         SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
+         SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
+         h_brush = CreateSolidBrush (face->foreground);
+         h_orig_brush = SelectObject (hdc, h_brush);
+
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 DSTINVERT);
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 0x2E064A);
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 DSTINVERT);
+
+         SelectObject (hdc, h_orig_brush);
+         DeleteObject (h_brush);
+       }
+      else
+       {
+         SetTextColor (hdc, face->background);
+         SetBkColor (hdc, (p->cursor_p
+                           ? f->output_data.w32->cursor_pixel
+                           : face->foreground));
+
+         BitBlt (hdc, p->x, p->y, p->wd, p->h,
+                 compat_hdc, 0, p->dh,
+                 SRCCOPY);
+       }
 
       SelectObject (compat_hdc, horig_obj);
       DeleteDC (compat_hdc);
@@ -719,6 +761,25 @@ w32_draw_fringe_bitmap (w, row, p)
   release_frame_dc (f, hdc);
 }
 
+static void
+w32_define_fringe_bitmap (which, bits, h, wd)
+     int which;
+     unsigned short *bits;
+     int h, wd;
+{
+  fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
+}
+
+static void
+w32_destroy_fringe_bitmap (which)
+     int which;
+{
+  if (fringe_bmp[which])
+    DeleteObject (fringe_bmp[which]);
+  fringe_bmp[which] = 0;
+}
+
+
 \f
 /* This is called when starting Emacs and when restarting after
    suspend.  When starting Emacs, no window is mapped.  And nothing
@@ -895,7 +956,17 @@ w32_per_char_metric (font, char2b, font_type)
   BOOL retval;
 
   xassert (font && char2b);
-  xassert (font_type != UNKNOWN_FONT);
+
+  /* TODO: This function is currently called through the RIF, and in
+     some cases font_type is UNKNOWN_FONT. We currently allow the
+     cached metrics to be used, which seems to work, but in cases
+     where font_type is UNKNOWN_FONT, we probably haven't encoded
+     char2b appropriately. All callers need checking to see what they
+     are passing.  This is most likely to affect variable width fonts
+     outside the Latin-1 range, particularly in languages like Thai
+     that rely on rbearing and lbearing to provide composition. I
+     don't think that is working currently anyway, but we don't seem
+     to have anyone testing such languages on Windows.  */
 
   /* Handle the common cases quickly.  */
   if (!font->bdf && font->per_char == NULL)
@@ -904,6 +975,8 @@ w32_per_char_metric (font, char2b, font_type)
   else if (!font->bdf && *char2b < 128)
     return &font->per_char[*char2b];
 
+  xassert (font_type != UNKNOWN_FONT);
+
   pcm = &font->scratch;
 
   if (font_type == BDF_1D_FONT)
@@ -1111,9 +1184,9 @@ w32_text_out (s, x, y,chars,nchars)
      wchar_t * chars;
      int nchars;
 {
-  int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
-  if (s->gc->font->bdf)
-    w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
+  int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1;
+  if (s->font->bdf)
+    w32_BDF_TextOut (s->font->bdf, s->hdc,
                      x, y, (char *) chars, charset_dim,
                      nchars * charset_dim, 0);
   else if (s->first_glyph->font_type == UNICODE_FONT)
@@ -2916,10 +2989,22 @@ construct_mouse_wheel (result, msg, f)
      struct frame *f;
 {
   POINT p;
-  result->kind = MOUSE_CLICK_EVENT;
-  result->code = (GET_WHEEL_DELTA_WPARAM (msg->msg.wParam) < 0) ? 4 : 3;
+  int delta;
+
+  result->kind = WHEEL_EVENT;
+  result->code = 0;
   result->timestamp = msg->msg.time;
-  result->modifiers = msg->dwModifiers;
+
+  /* A WHEEL_DELTA positive value indicates that the wheel was rotated
+     forward, away from the user (up); a negative value indicates that
+     the wheel was rotated backward, toward the user (down).  */
+  delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
+
+  /* The up and down modifiers indicate if the wheel was rotated up or
+     down based on WHEEL_DELTA value.  */
+  result->modifiers = (msg->dwModifiers
+                       | ((delta < 0 ) ? down_modifier : up_modifier));
+
   p.x = LOWORD (msg->msg.lParam);
   p.y = HIWORD (msg->msg.lParam);
   ScreenToClient (msg->msg.hwnd, &p);
@@ -3040,7 +3125,6 @@ note_mouse_movement (frame, msg)
 static struct scroll_bar *x_window_to_scroll_bar ();
 static void x_scroll_bar_report_motion ();
 static void x_check_fullscreen P_ ((struct frame *));
-static void x_check_fullscreen_move P_ ((struct frame *));
 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
 
 
@@ -4038,8 +4122,6 @@ static short temp_buffer[100];
    This routine is called by the SIGIO handler.
    We return as soon as there are no more events to be read.
 
-   Events representing keys are stored in buffer BUFP,
-   which can hold up to NUMCHARS characters.
    We return the number of characters stored into the buffer,
    thus pretending to be `read'.
 
@@ -4055,11 +4137,10 @@ static short temp_buffer[100];
 */
 
 int
-w32_read_socket (sd, bufp, numchars, expected)
+w32_read_socket (sd, expected, hold_quit)
      register int sd;
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   int check_visibility = 0;
@@ -4079,13 +4160,17 @@ w32_read_socket (sd, bufp, numchars, expected)
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();                   /* Don't think this happens. */
-
   /* TODO: tool-bars, ghostscript integration, mouse
      cursors. */
   while (get_next_msg (&msg, FALSE))
     {
+      struct input_event inev;
+      int do_help = 0;
+
+      EVENT_INIT (inev);
+      inev.kind = NO_EVENT;
+      inev.arg = Qnil;
+
       switch (msg.msg.message)
        {
        case WM_PAINT:
@@ -4114,12 +4199,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                     visibility changes properly.  */
                  if (f->iconified)
                    {
-                     bufp->kind = DEICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
+                     inev.kind = DEICONIFY_EVENT;
+                     XSETFRAME (inev.frame_or_window, f);
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
@@ -4149,17 +4230,10 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = LANGUAGE_CHANGE_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.msg.lParam & 0xffff;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = LANGUAGE_CHANGE_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.code = msg.msg.wParam;
+             inev.modifiers = msg.msg.lParam & 0xffff;
            }
          break;
 
@@ -4171,22 +4245,18 @@ w32_read_socket (sd, bufp, numchars, expected)
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
-                 dpyinfo->mouse_face_hidden = 1;
                  clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_hidden = 1;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.dwModifiers;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->timestamp = msg.msg.time;
-             bufp++;
-             numchars--;
-             count++;
+             inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+             inev.code = msg.msg.wParam;
+             inev.modifiers = msg.dwModifiers;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.timestamp = msg.msg.time;
            }
          break;
 
@@ -4198,22 +4268,18 @@ w32_read_socket (sd, bufp, numchars, expected)
            {
              if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
                {
-                 dpyinfo->mouse_face_hidden = 1;
                  clear_mouse_face (dpyinfo);
+                 dpyinfo->mouse_face_hidden = 1;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
                temp_index = 0;
              temp_buffer[temp_index++] = msg.msg.wParam;
-             bufp->kind = ASCII_KEYSTROKE_EVENT;
-             bufp->code = msg.msg.wParam;
-             bufp->modifiers = msg.dwModifiers;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp->timestamp = msg.msg.time;
-             bufp++;
-             numchars--;
-             count++;
+             inev.kind = ASCII_KEYSTROKE_EVENT;
+             inev.code = msg.msg.wParam;
+             inev.modifiers = msg.dwModifiers;
+             XSETFRAME (inev.frame_or_window, f);
+             inev.timestamp = msg.msg.time;
            }
          break;
 
@@ -4259,13 +4325,10 @@ w32_read_socket (sd, bufp, numchars, expected)
                     iff it is active.  */
                  if (WINDOWP(window)
                      && !EQ (window, last_window)
-                     && !EQ (window, selected_window)
-                     && numchars > 0)
+                     && !EQ (window, selected_window))
                    {
-                     bufp->kind = SELECT_WINDOW_EVENT;
-                     bufp->frame_or_window = window;
-                     bufp->arg = Qnil;
-                     ++bufp, ++count, --numchars;
+                     inev.kind = SELECT_WINDOW_EVENT;
+                     inev.frame_or_window = window;
                    }
 
                  last_window=window;
@@ -4283,27 +4346,8 @@ w32_read_socket (sd, bufp, numchars, expected)
              has changed, generate a HELP_EVENT.  */
           if (help_echo_string != previous_help_echo_string ||
              (!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
-            {
-              Lisp_Object frame;
-              int n;
-
-             if (help_echo_string == Qnil)
-               {
-                 help_echo_object = help_echo_window = Qnil;
-                 help_echo_pos = -1;
-               }
-
-              if (f)
-                XSETFRAME (frame, f);
-              else
-                frame = Qnil;
+           do_help = 1;
 
-              any_help_event_p = 1;
-              n = gen_help_event (bufp, numchars, help_echo_string, frame,
-                                 help_echo_window, help_echo_object,
-                                 help_echo_pos);
-              bufp += n, count += n, numchars -= n;
-            }
           break;
 
        case WM_LBUTTONDOWN:
@@ -4317,13 +4361,10 @@ w32_read_socket (sd, bufp, numchars, expected)
          {
             /* If we decide we want to generate an event to be seen
                by the rest of Emacs, we put it here.  */
-            struct input_event emacs_event;
             int tool_bar_p = 0;
            int button;
            int up;
 
-            emacs_event.kind = NO_EVENT;
-
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
@@ -4332,35 +4373,29 @@ w32_read_socket (sd, bufp, numchars, expected)
 
            if (f)
              {
-                construct_mouse_click (&emacs_event, &msg, f);
+                construct_mouse_click (&inev, &msg, f);
 
                 /* Is this in the tool-bar?  */
                 if (WINDOWP (f->tool_bar_window)
                     && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
                   {
                     Lisp_Object window;
-                   int x = XFASTINT (emacs_event.x);
-                   int y = XFASTINT (emacs_event.y);
+                   int x = XFASTINT (inev.x);
+                   int y = XFASTINT (inev.y);
 
                     window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
 
                     if (EQ (window, f->tool_bar_window))
                       {
-                        w32_handle_tool_bar_click (f, &emacs_event);
+                        w32_handle_tool_bar_click (f, &inev);
                         tool_bar_p = 1;
                       }
                   }
 
-                if (!tool_bar_p)
-                  if (!dpyinfo->w32_focus_frame
-                      || f == dpyinfo->w32_focus_frame
-                      && (numchars >= 1))
-                    {
-                      construct_mouse_click (bufp, &msg, f);
-                      bufp++;
-                      count++;
-                      numchars--;
-                    }
+                if (tool_bar_p
+                   || (dpyinfo->w32_focus_frame
+                       && f != dpyinfo->w32_focus_frame))
+                 inev.kind = NO_EVENT;
              }
 
            parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
@@ -4389,15 +4424,6 @@ w32_read_socket (sd, bufp, numchars, expected)
 
        case WM_MOUSEWHEEL:
          {
-           /* Convert each Windows mouse wheel event in a couple of
-              Emacs mouse click down/up events.  Scrolling the wheel up
-              is associated to mouse button 4 and scrolling the wheel
-              down to the mouse button 5.  */
-           int button;
-           int up;
-
-           up = msg.dwModifiers & up_modifier;
-
            if (dpyinfo->grabbed && last_mouse_frame
                && FRAME_LIVE_P (last_mouse_frame))
              f = last_mouse_frame;
@@ -4406,70 +4432,21 @@ w32_read_socket (sd, bufp, numchars, expected)
 
            if (f)
              {
-               Lisp_Object window;
-               POINT p;
-               int x, y;
-
-               p.x = LOWORD (msg.msg.lParam);
-               p.y = HIWORD (msg.msg.lParam);
-               ScreenToClient (msg.msg.hwnd, &p);
-               x = XFASTINT (p.x);
-               y = XFASTINT (p.y);
-
-               window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
-
-               /* Ignore mouse wheel events not in a window.  */
-               if (!WINDOWP(window))
-                 break;
 
-               if ((!dpyinfo->w32_focus_frame
-                    || f == dpyinfo->w32_focus_frame)
-                   && (numchars >= 1))
+               if (!dpyinfo->w32_focus_frame
+                   || f == dpyinfo->w32_focus_frame)
                  {
-                   if ( !up )
-                     {
-                       /* Emit an Emacs mouse down message.  */
-                       msg.dwModifiers |= down_modifier;
-                       construct_mouse_wheel (bufp, &msg, f);
-                       bufp++;
-                       count++;
-                       numchars--;
-
-                       /* Push a simulated WM_MOUSEWHEEL up message.  */
-                       msg.dwModifiers &= ~down_modifier;
-                       msg.dwModifiers |= up_modifier;
-                       prepend_msg (&msg);
-                     }
-                   else
-                     {
-                       /* Emit an Emacs mouse up message.  */
-                       construct_mouse_wheel (bufp, &msg, f);
-                       bufp++;
-                       count++;
-                       numchars--;
-                     }
+                   /* Emit an Emacs wheel-up/down event.  */
+                   construct_mouse_wheel (&inev, &msg, f);
                  }
+               /* Ignore any mouse motion that happened before this
+                  event; any subsequent mouse-movement Emacs events
+                  should reflect only motion after the
+                  ButtonPress.  */
+               f->mouse_moved = 0;
              }
-
-           button = ( GET_WHEEL_DELTA_WPARAM (msg.msg.wParam) < 0 )? 4 : 3;
-
-           if (up)
-             {
-               dpyinfo->grabbed &= ~ (1 << button);
-             }
-           else
-             {
-               dpyinfo->grabbed |= (1 << button);
-               last_mouse_frame = f;
-               /* Ignore any mouse motion that happened
-                  before this event; any subsequent mouse-movement
-                  Emacs events should reflect only motion after
-                  the ButtonPress.  */
-               if (f != 0)
-                 f->mouse_moved = 0;
-
-               last_tool_bar_item = -1;
-             }
+           last_mouse_frame = f;
+           last_tool_bar_item = -1;
          }
          break;
 
@@ -4477,12 +4454,7 @@ w32_read_socket (sd, bufp, numchars, expected)
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
          if (f)
-           {
-             construct_drag_n_drop (bufp, &msg, f);
-             bufp++;
-             count++;
-             numchars--;
-           }
+           construct_drag_n_drop (&inev, &msg, f);
          break;
 
        case WM_VSCROLL:
@@ -4490,15 +4462,8 @@ w32_read_socket (sd, bufp, numchars, expected)
            struct scroll_bar *bar =
              x_window_to_scroll_bar ((HWND)msg.msg.lParam);
 
-           if (bar && numchars >= 1)
-             {
-               if (w32_scroll_bar_handle_click (bar, &msg, bufp))
-                 {
-                   bufp++;
-                   count++;
-                   numchars--;
-                 }
-             }
+           if (bar)
+             w32_scroll_bar_handle_click (bar, &msg, &inev);
            break;
          }
 
@@ -4506,7 +4471,6 @@ w32_read_socket (sd, bufp, numchars, expected)
          f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
          if (f)
            {
-             x_check_fullscreen_move(f);
              if (f->want_fullscreen & FULLSCREEN_WAIT)
                f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
            }
@@ -4575,12 +4539,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                  f->async_visible = 0;
                  f->async_iconified = 1;
 
-                 bufp->kind = ICONIFY_EVENT;
-                 XSETFRAME (bufp->frame_or_window, f);
-                 bufp->arg = Qnil;
-                 bufp++;
-                 count++;
-                 numchars--;
+                 inev.kind = ICONIFY_EVENT;
+                 XSETFRAME (inev.frame_or_window, f);
                  break;
 
                case SIZE_MAXIMIZED:
@@ -4605,12 +4565,8 @@ w32_read_socket (sd, bufp, numchars, expected)
                       f->left_pos = x;
                       f->top_pos = y;
 
-                     bufp->kind = DEICONIFY_EVENT;
-                     XSETFRAME (bufp->frame_or_window, f);
-                     bufp->arg = Qnil;
-                     bufp++;
-                     count++;
-                     numchars--;
+                     inev.kind = DEICONIFY_EVENT;
+                     XSETFRAME (inev.frame_or_window, f);
                    }
                  else if (! NILP (Vframe_list)
                           && ! NILP (XCDR (Vframe_list)))
@@ -4678,16 +4634,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                 Otherwise, the startup message is cleared when
                 the mouse leaves the frame.  */
              if (any_help_event_p)
-               {
-                 Lisp_Object frame;
-                 int n;
-
-                 XSETFRAME (frame, f);
-                 help_echo_string = Qnil;
-                 n = gen_help_event (bufp, numchars,
-                                     Qnil, frame, Qnil, Qnil, 0);
-                 bufp += n, count += n, numchars -= n;
-               }
+               do_help = -1;
            }
          break;
 
@@ -4737,16 +4684,7 @@ w32_read_socket (sd, bufp, numchars, expected)
                  Otherwise, the startup message is cleared when
                  the mouse leaves the frame.  */
               if (any_help_event_p)
-                {
-                  Lisp_Object frame;
-                  int n;
-
-                  XSETFRAME (frame, f);
-                  help_echo_string = Qnil;
-                  n = gen_help_event (bufp, numchars,
-                                      Qnil, frame, Qnil, Qnil, 0);
-                  bufp += n, count += n, numchars -=n;
-                }
+               do_help = -1;
             }
 
          dpyinfo->grabbed = 0;
@@ -4758,15 +4696,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = DELETE_WINDOW_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = DELETE_WINDOW_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
            }
          break;
 
@@ -4775,15 +4706,8 @@ w32_read_socket (sd, bufp, numchars, expected)
 
          if (f)
            {
-             if (numchars == 0)
-               abort ();
-
-             bufp->kind = MENU_BAR_ACTIVATE_EVENT;
-             XSETFRAME (bufp->frame_or_window, f);
-             bufp->arg = Qnil;
-             bufp++;
-             count++;
-             numchars--;
+             inev.kind = MENU_BAR_ACTIVATE_EVENT;
+             XSETFRAME (inev.frame_or_window, f);
            }
          break;
 
@@ -4816,29 +4740,50 @@ w32_read_socket (sd, bufp, numchars, expected)
          break;
 
        default:
-         /* Check for messages registered at runtime. */
+         /* Check for messages registered at runtime.  */
          if (msg.msg.message == msh_mousewheel)
            {
-             if (dpyinfo->grabbed && last_mouse_frame
-                 && FRAME_LIVE_P (last_mouse_frame))
-               f = last_mouse_frame;
-             else
-               f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
+             /* Forward MSH_MOUSEWHEEL as WM_MOUSEWHEEL.  */
+             msg.msg.message = WM_MOUSEWHEEL;
+             prepend_msg (&msg);
+           }
+         break;
+       }
+
+      if (inev.kind != NO_EVENT)
+       {
+         kbd_buffer_store_event_hold (&inev, hold_quit);
+         count++;
+       }
 
-             if (f)
+      if (do_help
+         && !(hold_quit && hold_quit->kind != NO_EVENT))
+       {
+         Lisp_Object frame;
+
+         if (f)
+           XSETFRAME (frame, f);
+         else
+           frame = Qnil;
+
+         if (do_help > 0)
+           {
+             if (help_echo_string == Qnil)
                {
-                 if ((!dpyinfo->w32_focus_frame
-                      || f == dpyinfo->w32_focus_frame)
-                     && (numchars >= 1))
-                   {
-                     construct_mouse_wheel (bufp, &msg, f);
-                     bufp++;
-                     count++;
-                     numchars--;
-                   }
+                 help_echo_object = help_echo_window = Qnil;
+                 help_echo_pos = -1;
                }
+
+             any_help_event_p = 1;
+             gen_help_event (help_echo_string, frame, help_echo_window,
+                             help_echo_object, help_echo_pos);
            }
-         break;
+         else
+           {
+             help_echo_string = Qnil;
+             gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+           }
+         count++;
        }
     }
 
@@ -5131,6 +5076,9 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
         cursor remains invisible.  */
       if (w32_use_visible_system_caret)
        {
+         /* Call to erase_phys_cursor here seems to use the
+            wrong values of w->phys_cursor, as they have been
+            overwritten before this function was called. */
          if (w->phys_cursor_type != NO_CURSOR)
            erase_phys_cursor (w);
 
@@ -5170,6 +5118,14 @@ w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, act
          PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
        }
 
+      if (glyph_row->exact_window_width_line_p
+         && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+       {
+         glyph_row->cursor_in_fringe_p = 1;
+         draw_fringe_bitmap (w, glyph_row, 0);
+         return;
+       }
+
       switch (cursor_type)
        {
        case HOLLOW_BOX_CURSOR:
@@ -5487,9 +5443,7 @@ x_check_fullscreen (f)
       x_fullscreen_adjust (f, &width, &height, &ign, &ign);
 
       /* We do not need to move the window, it shall be taken care of
-         when setting WM manager hints.
-         If the frame is visible already, the position is checked by
-         x_check_fullscreen_move. */
+         when setting WM manager hints.  */
       if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
           change_frame_size (f, height, width, 0, 1, 0);
@@ -5502,36 +5456,6 @@ x_check_fullscreen (f)
     }
 }
 
-/* If frame parameters are set after the frame is mapped, we need to move
-   the window.  This is done in xfns.c.
-   Some window managers moves the window to the right position, some
-   moves the outer window manager window to the specified position.
-   Here we check that we are in the right spot.  If not, make a second
-   move, assuming we are dealing with the second kind of window manager. */
-static void
-x_check_fullscreen_move (f)
-     struct frame *f;
-{
-  if (f->want_fullscreen & FULLSCREEN_MOVE_WAIT)
-  {
-    int expect_top = f->top_pos;
-    int expect_left = f->left_pos;
-
-    if (f->want_fullscreen & FULLSCREEN_HEIGHT)
-      expect_top = 0;
-    if (f->want_fullscreen & FULLSCREEN_WIDTH)
-      expect_left = 0;
-
-    if (expect_top != f->top_pos
-        || expect_left != f->left_pos)
-      x_set_offset (f, expect_left, expect_top, 1);
-
-    /* Just do this once */
-    f->want_fullscreen &= ~FULLSCREEN_MOVE_WAIT;
-  }
-}
-
-
 /* Call this to change the size of frame F's x-window.
    If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
    for this size change and subsequent size changes.
@@ -6280,32 +6204,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.  */
-  {
-    int i, j;
-
-    for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
-      {
-       int h = fringe_bitmaps[i].height;
-       int wd = fringe_bitmaps[i].width;
-       unsigned short *w32bits
-         = (unsigned short *)alloca (h * sizeof (unsigned short));
-       unsigned short *wb = w32bits;
-       unsigned char *bits = fringe_bitmaps[i].bits;
-       for (j = 0; j < h; j++)
-         {
-           static unsigned char swap_nibble[16]
-             = { 0x0, 0x8, 0x4, 0xc,    /* 0000 1000 0100 1100 */
-                 0x2, 0xa, 0x6, 0xe,    /* 0010 1010 0110 1110 */
-                 0x1, 0x9, 0x5, 0xd,    /* 0001 1001 0101 1101 */
-                 0x3, 0xb, 0x7, 0xf };  /* 0011 1011 0111 1111 */
-
-           unsigned char b = *bits++;
-           *wb++ = (unsigned short)((swap_nibble[b & 0xf]<<4)
-                                    | (swap_nibble[(b>>4) & 0xf]));
-         }
-       fringe_bmp[i] = CreateBitmap (wd, h, 1, 1, w32bits);
-      }
-  }
+  w32_init_fringe ();
 
 #ifndef F_SETOWN_BUG
 #ifdef F_SETOWN
@@ -6373,13 +6272,7 @@ x_delete_display (dpyinfo)
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->w32_id_name);
 
-  /* Destroy row bitmaps.  */
-  {
-    int i;
-
-    for (i = NO_FRINGE_BITMAP + 1; i < MAX_FRINGE_BITMAPS; i++)
-      DeleteObject (fringe_bmp[i]);
-  }
+  w32_reset_fringes ();
 }
 \f
 /* Set up use of W32.  */
@@ -6410,6 +6303,8 @@ static struct redisplay_interface w32_redisplay_interface =
   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 */
@@ -6445,12 +6340,13 @@ w32_initialize ()
   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 */
+  TTY_SCROLL_REGION_OK (CURTTY ()) = 1; /* we'll scroll partial frames */
+  TTY_CHAR_INS_DEL_OK (CURTTY ()) = 1;
+  TTY_LINE_INS_DEL_OK (CURTTY ()) = 1; /* we'll just blt 'em */
+  TTY_FAST_CLEAR_END_OF_LINE (CURTTY ()) = 1; /* X does this well */
+  TTY_MEMORY_BELOW_FRAME (CURTTY ()) = 0; /* we don't remember what
+                                                            scrolls off the
+                                                            bottom */
   baud_rate = 19200;
 
   w32_system_caret_hwnd = NULL;
@@ -6604,3 +6500,6 @@ the cursor have no effect.  */);
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }
+
+/* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
+   (do not change this comment) */