changeset 83067:b44978264e1d

Merged in changes from CVS HEAD Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-118 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-119 src/keyboard.c (adjust_point_for_property): #ifdef-out dodgy xassert * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-120 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-107
author Karoly Lorentey <lorentey@elte.hu>
date Sat, 28 Feb 2004 04:52:40 +0000
parents 887bb2eb4a89 (current diff) 6c578d781772 (diff)
children 90ccc0dc0d3f
files lisp/ChangeLog lisp/faces.el src/dispnew.c src/keyboard.c src/keyboard.h src/lisp.h src/macterm.c src/sysdep.c src/termhooks.h src/w32inevt.c src/w32term.c src/window.c src/xsmfns.c src/xterm.c src/xterm.h
diffstat 26 files changed, 1084 insertions(+), 1074 deletions(-) [+]
line wrap: on
line diff
--- a/etc/NEWS	Sat Feb 28 01:33:17 2004 +0000
+++ b/etc/NEWS	Sat Feb 28 04:52:40 2004 +0000
@@ -713,6 +713,13 @@
 the extended number of colors, and defines the appropriate entries for
 all of these colors.
 
++++
+*** Emacs now uses the full range of available colors for the default
+faces when running on a color terminal, including 16-, 88-, and
+256-color xterms.  This means that when you run "emacs -nw" on an
+88-color or 256-color xterm, you will see essentially the same face
+colors as on X.
+
 ---
 *** There's a new support for colors on `rxvt' terminal emulator.
 
@@ -1822,6 +1829,13 @@
 configuration files.
 
 * Lisp Changes in Emacs 21.4
++++
+** New face attribute `min-colors' can be used to tailor the face color
+to the number of colors supported by a display, and define the
+foreground and background colors accordingly so that they look best on
+a terminal that supports at least this many colors.  This is now the
+preferred method for defining default faces in a way that makes a good
+use of the capabilities of the display.
 
 ** New function 'define-fringe-bitmap' can now be used to change the
 built-in fringe bitmaps, as well as create new fringe bitmaps.
--- a/lisp/ChangeLog	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/ChangeLog	Sat Feb 28 04:52:40 2004 +0000
@@ -1,3 +1,56 @@
+2004-02-28  Kim F. Storm  <storm@cua.dk>
+
+	* gdb-ui.el (breakpoint-enabled-icon, breakpoint-disabled-icon): 
+	Initialize margin area images to nil.
+	(breakpoint-bitmap): New defvar for breakpoint fringe bitmaps.
+	(breakpoint-enabled-bitmap-face)
+	(breakpoint-disabled-bitmap-face): New faces for bpt in fringe.
+	(gdb-info-breakpoints-custom): Use gdb-remove-breakpoint-icons.
+	(gdb-info-breakpoints-custom): Use gdb-put-breakpoint-icon.
+	(gdb-mouse-toggle-breakpoint): Handle bpt in fringe.
+	(gdb-reset): Use gdb-remove-breakpoint-icons.
+	(gdb-put-string): Add dprop arg to specify alternative display
+	property (for setting fringe bitmap).
+	(gdb-remove-strings): Doc fix.
+	(gdb-put-breakpoint-icon): New defun which displays a breakpoint
+	icon in fringe (if available), or else as icon or text in display
+	margin.  Creates necessary icons in breakpoint-bitmap,
+	breakpoint-enabled-icon, and/or breakpoint-disabled-icon.  Also
+	make left window margin if required.
+	(gdb-remove-breakpoint-icons): New defun to remove breakpoint
+	icons inserted by gdb-put-breakpoint-icon.  Remove left margin if
+	no longer needed.
+	(gdb-assembler-custom): Use gdb-remove-breakpoint-icons and
+	gdb-put-breakpoint-icon.
+	(gdb-assembler-mode): Don't set left-margin-width here.
+
+2004-02-27  Kevin Ryde  <user42@zip.com.au>
+
+	* info-look.el: In scheme-mode symbol regexp, disallow backquote and
+        comma, so that it DTRT in macros.
+
+2004-02-27  Markus Rost  <rost@mathematik.uni-bielefeld.de>
+
+	* progmodes/sh-script.el (sh-shell-arg)
+	(sh-require-final-newline, sh-assignment-regexp, sh-builtins)
+	(sh-leading-keywords, sh-other-keywords): Fix custom type.
+
+2004-02-27  Dan Nicolaescu  <dann@ics.uci.edu>
+
+	* faces.el (face-spec-set-match-display): Add a new  attribute,
+	`min-colors'. 
+	(region, highlight, secondary-selection): Use `min-colors`.
+
+	* custom.el (defface): Add documentation for `min-colors'.
+
+	* font-lock.el (font-lock-comment-face, font-lock-string-face)
+	(font-lock-keyword-face, font-lock-function-name-face)
+	(font-lock-variable-name-face, font-lock-constant-face): Use
+	`min-colors`.
+
+	* isearch.el (isearch, isearch-lazy-highlight-face): Use
+	`min-colors'. 
+
 2004-02-25  Vinicius Jose Latorre  <viniciusjl@ig.com.br>
 
 	* ebnf2ps.el: Doc fix.  For compatibility with Emacs 20, define
--- a/lisp/custom.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/custom.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1,6 +1,7 @@
 ;;; custom.el --- tools for declaring and initializing options
 ;;
-;; Copyright (C) 1996, 1997, 1999, 2001, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 1999, 2001, 2002, 2004
+;;  Free Software Foundation, Inc.
 ;;
 ;; Author: Per Abrahamsen <abraham@dina.kvl.dk>
 ;; Maintainer: FSF
@@ -306,6 +307,10 @@
 `background' (what color is used for the background text)
   Should be one of `light' or `dark'.
 
+`min-colors' (the minimum number of colors the frame should support)
+  Should be an integer, it is compared with the result of
+  `display-color-cells'.
+
 Read the section about customization in the Emacs Lisp manual for more
 information."
   ;; It is better not to use backquote in this file,
--- a/lisp/faces.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/faces.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1,6 +1,6 @@
 ;;; faces.el --- Lisp faces
 
-;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002
+;; Copyright (C) 1992,1993,1994,1995,1996,1998,1999,2000,2001,2002,2004
 ;;   Free Software Foundation, Inc.
 
 ;; Maintainer: FSF
@@ -1314,6 +1314,8 @@
 				  (not (featurep 'motif)))
 			     (and (memq 'x-toolkit options)
 				  (featurep 'x-toolkit))))
+			((eq req 'min-colors)
+			 (>= (display-color-cells frame) (car options)))
 			((eq req 'class)
 			 (memq (frame-parameter frame 'display-type) options))
 			((eq req 'background)
@@ -1892,14 +1894,18 @@
       (append minibuffer-prompt-properties (list 'face 'minibuffer-prompt)))
 
 (defface region
-  '((((type tty) (class color))
+  '((((class color) (min-colors 88) (background dark))
+     :background "blue3")
+    (((class color) (min-colors 88) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 16) (background dark))
+     :background "blue3")
+    (((class color) (min-colors 16) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 8))
      :background "blue" :foreground "white")
     (((type tty) (class mono))
      :inverse-video t)
-    (((class color) (background dark))
-     :background "blue3")
-    (((class color) (background light))
-     :background "lightgoldenrod2")
     (t :background "gray"))
   "Basic face for highlighting the region."
   :version "21.1"
@@ -1990,24 +1996,32 @@
 
 
 (defface highlight
-  '((((type tty) (class color))
+  '((((class color) (min-colors 88) (background light))
+     :background "darkseagreen2")
+    (((class color) (min-colors 88) (background dark))
+     :background "darkolivegreen")
+    (((class color) (min-colors 16) (background light))
+     :background "darkseagreen2")
+    (((class color) (min-colors 16) (background dark))
+     :background "darkolivegreen")
+    (((class color) (min-colors 8))
      :background "green" :foreground "black")
-    (((class color) (background light))
-     :background "darkseagreen2")
-    (((class color) (background dark))
-     :background "darkolivegreen")
     (t :inverse-video t))
   "Basic face for highlighting."
   :group 'basic-faces)
 
 
 (defface secondary-selection
-  '((((type tty) (class color))
+  '((((class color) (min-colors 88) (background light))
+     :background "yellow")
+    (((class color) (min-colors 88) (background dark))
+     :background "SkyBlue4")
+    (((class color) (min-colors 16) (background light))
+     :background "yellow")
+    (((class color) (min-colors 16) (background dark))
+     :background "SkyBlue4")
+    (((class color) (min-colors 8))
      :background "cyan" :foreground "black")
-    (((class color) (background light))
-     :background "yellow")
-    (((class color) (background dark))
-     :background "SkyBlue4")
     (t :inverse-video t))
   "Basic face for displaying the secondary selection."
   :group 'basic-faces)
--- a/lisp/font-lock.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/font-lock.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1,6 +1,6 @@
 ;;; font-lock.el --- Electric font lock mode
 
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999, 2000, 2001, 02, 2003
+;; Copyright (C) 1992, 93, 94, 95, 96, 97, 98, 1999, 2000, 2001, 02, 2003, 2004
 ;;  Free Software Foundation, Inc.
 
 ;; Author: jwz, then rms, then sm
@@ -1560,24 +1560,34 @@
 ;; But now we do it the custom way.  Note that `defface' will not overwrite any
 ;; faces declared above via `custom-declare-face'.
 (defface font-lock-comment-face
-  '((((type tty pc) (class color) (background light)) (:foreground "red"))
-    (((type tty pc) (class color) (background dark)) (:foreground "red1"))
-    (((class grayscale) (background light))
+  '((((class grayscale) (background light))
      (:foreground "DimGray" :weight bold :slant italic))
     (((class grayscale) (background dark))
      (:foreground "LightGray" :weight bold :slant italic))
-    (((class color) (background light)) (:foreground "Firebrick"))
-    (((class color) (background dark)) (:foreground "chocolate1"))
+    (((class color) (min-colors 88) (background light)) 
+     (:foreground "Firebrick"))
+    (((class color) (min-colors 88) (background dark)) 
+     (:foreground "chocolate1"))
+    (((class color) (min-colors 16) (background light)) 
+     (:foreground "red"))
+    (((class color) (min-colors 16) (background dark)) 
+     (:foreground "red1"))
+    (((class color) (min-colors 8) (background light)) 
+     (:foreground "red"))
+    (((class color) (min-colors 8) (background dark)) 
+     (:foreground "red1"))
     (t (:weight bold :slant italic)))
   "Font Lock mode face used to highlight comments."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-string-face
-  '((((type tty) (class color)) (:foreground "green"))
-    (((class grayscale) (background light)) (:foreground "DimGray" :slant italic))
+  '((((class grayscale) (background light)) (:foreground "DimGray" :slant italic))
     (((class grayscale) (background dark)) (:foreground "LightGray" :slant italic))
-    (((class color) (background light)) (:foreground "RosyBrown"))
-    (((class color) (background dark)) (:foreground "LightSalmon"))
+    (((class color) (min-colors 88) (background light)) (:foreground "RosyBrown"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "LightSalmon"))
+    (((class color) (min-colors 16) (background light)) (:foreground "RosyBrown"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "LightSalmon"))
+    (((class color) (min-colors 8)) (:foreground "green"))
     (t (:slant italic)))
   "Font Lock mode face used to highlight strings."
   :group 'font-lock-highlighting-faces)
@@ -1588,71 +1598,84 @@
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-keyword-face
-  '((((type tty) (class color)) (:foreground "cyan" :weight bold))
-    (((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
+  '((((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
     (((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
-    (((class color) (background light)) (:foreground "Purple"))
-    (((class color) (background dark)) (:foreground "Cyan"))
+    (((class color) (min-colors 88) (background light)) (:foreground "Purple"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "Cyan"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Purple"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "Cyan"))
+    (((class color) (min-colors 8)) (:foreground "cyan" :weight bold))
     (t (:weight bold)))
   "Font Lock mode face used to highlight keywords."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-builtin-face
-  '((((type tty) (class color)) (:foreground "blue" :weight light))
-    (((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
+  '((((class grayscale) (background light)) (:foreground "LightGray" :weight bold))
     (((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
-    (((class color) (background light)) (:foreground "Orchid"))
-    (((class color) (background dark)) (:foreground "LightSteelBlue"))
+    (((class color) (min-colors 88) (background light)) (:foreground "Orchid"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "LightSteelBlue"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Orchid"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "LightSteelBlue"))
+    (((class color) (min-colors 8)) (:foreground "blue" :weight bold))
     (t (:weight bold)))
   "Font Lock mode face used to highlight builtins."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-function-name-face
-  '((((type tty) (class color)) (:foreground "blue" :weight bold))
-    (((class color) (background light)) (:foreground "Blue"))
-    (((class color) (background dark)) (:foreground "LightSkyBlue"))
+  '((((class color) (min-colors 88) (background light)) (:foreground "Blue"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "LightSkyBlue"))
+    (((class color) (min-colors 16) (background light)) (:foreground "Blue"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "LightSkyBlue"))
+    (((class color) (min-colors 8)) (:foreground "blue" :weight bold))
     (t (:inverse-video t :weight bold)))
   "Font Lock mode face used to highlight function names."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-variable-name-face
-  '((((type tty) (class color)) (:foreground "yellow" :weight light))
-    (((class grayscale) (background light))
+  '((((class grayscale) (background light))
      (:foreground "Gray90" :weight bold :slant italic))
     (((class grayscale) (background dark))
      (:foreground "DimGray" :weight bold :slant italic))
-    (((class color) (background light)) (:foreground "DarkGoldenrod"))
-    (((class color) (background dark)) (:foreground "LightGoldenrod"))
+    (((class color) (min-colors 88) (background light)) (:foreground "DarkGoldenrod"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "LightGoldenrod"))
+    (((class color) (min-colors 16) (background light)) (:foreground "DarkGoldenrod"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "LightGoldenrod"))
+    (((class color) (min-colors 8)) (:foreground "yellow" :weight light))
     (t (:weight bold :slant italic)))
   "Font Lock mode face used to highlight variable names."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-type-face
-  '((((type tty) (class color)) (:foreground "green"))
-    (((class grayscale) (background light)) (:foreground "Gray90" :weight bold))
+  '((((class grayscale) (background light)) (:foreground "Gray90" :weight bold))
     (((class grayscale) (background dark)) (:foreground "DimGray" :weight bold))
-    (((class color) (background light)) (:foreground "ForestGreen"))
-    (((class color) (background dark)) (:foreground "PaleGreen"))
+    (((class color) (min-colors 88) (background light)) (:foreground "ForestGreen"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "PaleGreen"))
+    (((class color) (min-colors 16) (background light)) (:foreground "ForestGreen"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "PaleGreen"))
+    (((class color) (min-colors 8)) (:foreground "green"))
     (t (:weight bold :underline t)))
   "Font Lock mode face used to highlight type and classes."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-constant-face
-  '((((type tty) (class color)) (:foreground "magenta"))
-    (((class grayscale) (background light))
+  '((((class grayscale) (background light))
      (:foreground "LightGray" :weight bold :underline t))
     (((class grayscale) (background dark))
      (:foreground "Gray50" :weight bold :underline t))
-    (((class color) (background light)) (:foreground "CadetBlue"))
-    (((class color) (background dark)) (:foreground "Aquamarine"))
+    (((class color) (min-colors 88) (background light)) (:foreground "CadetBlue"))
+    (((class color) (min-colors 88) (background dark)) (:foreground "Aquamarine"))
+    (((class color) (min-colors 16) (background light)) (:foreground "CadetBlue"))
+    (((class color) (min-colors 16) (background dark)) (:foreground "Aquamarine"))
+    (((class color) (min-colors 8)) (:foreground "magenta"))
     (t (:weight bold :underline t)))
   "Font Lock mode face used to highlight constants and labels."
   :group 'font-lock-highlighting-faces)
 
 (defface font-lock-warning-face
-  '((((type tty) (class color)) (:foreground "red"))
-    (((class color) (background light)) (:foreground "Red" :weight bold))
-    (((class color) (background dark)) (:foreground "Pink" :weight bold))
+  '((((class color) (min-colors 88) (background light)) (:foreground "Red" :weight bold))
+    (((class color) (min-colors 88) (background dark)) (:foreground "Pink" :weight bold))
+    (((class color) (min-colors 16) (background light)) (:foreground "Red" :weight bold))
+    (((class color) (min-colors 16) (background dark)) (:foreground "Pink" :weight bold))    (((class color) (min-colors 8)) (:foreground "red"))
     (t (:inverse-video t :weight bold)))
   "Font Lock mode face used to highlight warnings."
   :group 'font-lock-highlighting-faces)
--- a/lisp/gdb-ui.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/gdb-ui.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1017,16 +1017,28 @@
 0 0 0 1 0 1 0 1 0 0"
   "PBM data used for disabled breakpoint icon.")
 
-(defvar breakpoint-enabled-icon
-  (find-image `((:type xpm :data ,breakpoint-xpm-data :ascent 100)
-		(:type pbm :data ,breakpoint-enabled-pbm-data :ascent 100)))
+(defvar breakpoint-enabled-icon nil
   "Icon for enabled breakpoint in display margin")
 
-(defvar breakpoint-disabled-icon
-  (find-image `((:type xpm :data ,breakpoint-xpm-data :conversion disabled :ascent 100)
-		(:type pbm :data ,breakpoint-disabled-pbm-data :ascent 100)))
+(defvar breakpoint-disabled-icon nil
   "Icon for disabled breakpoint in display margin")
 
+(defvar breakpoint-bitmap nil
+  "Bitmap for breakpoint in fringe")
+
+(defface breakpoint-enabled-bitmap-face
+  '((t
+     :inherit fringe
+     :foreground "red"))
+  "Face for enabled breakpoint icon in fringe.")
+
+(defface breakpoint-disabled-bitmap-face
+  '((t
+     :inherit fringe
+     :foreground "grey60"))
+  "Face for disabled breakpoint icon in fringe.")
+
+
 ;;-put breakpoint icons in relevant margins (even those set in the GUD buffer)
 (defun gdb-info-breakpoints-custom ()
   (let ((flag)(address))
@@ -1036,9 +1048,7 @@
       (with-current-buffer buffer
 	(if (and (eq gud-minor-mode 'gdba)
 		 (not (string-match "^\*" (buffer-name))))
-	    (if (display-images-p)
-		(remove-images (point-min) (point-max))
-	      (gdb-remove-strings (point-min) (point-max))))))
+	    (gdb-remove-breakpoint-icons (point-min) (point-max)))))
     (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
       (save-excursion
 	(goto-char (point-min))
@@ -1064,35 +1074,11 @@
 			  (save-current-buffer
 			    (set (make-local-variable 'gud-minor-mode) 'gdba)
 			    (set (make-local-variable 'tool-bar-map)
-				 gud-tool-bar-map)
-			    (setq left-margin-width 2)
-			    (if (get-buffer-window (current-buffer))
-				(set-window-margins (get-buffer-window
-						     (current-buffer))
-						    left-margin-width
-						    right-margin-width)))
+				 gud-tool-bar-map))
 			  ;; only want one breakpoint icon at each location
 			  (save-excursion
 			    (goto-line (string-to-number line))
-			    (let ((start (progn (beginning-of-line)
-						(- (point) 1)))
-				  (end (progn (end-of-line) (+ (point) 1))))
-			      (if (display-images-p)
-				  (progn
-				    (remove-images start end)
-				    (if (eq ?y flag)
-					(put-image breakpoint-enabled-icon
-						   (+ start 1)
-						   "breakpoint icon enabled"
-						   'left-margin)
-				      (put-image breakpoint-disabled-icon
-						 (+ start 1)
-						 "breakpoint icon disabled"
-						 'left-margin)))
-				(gdb-remove-strings start end)
-				(if (eq ?y flag)
-				    (gdb-put-string "B" (+ start 1))
-				  (gdb-put-string "b" (+ start 1))))))))))))
+			    (gdb-put-breakpoint-icon (eq flag ?y)))))))))
 	  (end-of-line)))))
   (if (gdb-get-buffer 'gdb-assembler-buffer) (gdb-assembler-custom)))
 
@@ -1106,7 +1092,10 @@
 	(with-selected-window (posn-window posn)
 	  (save-excursion
 	    (goto-char (posn-point posn))
-	    (if (posn-object posn)
+	    (if (or (posn-object posn)
+		    (and breakpoint-bitmap
+			 (eq (car (fringe-bitmaps-at-pos (posn-point posn)))
+			     breakpoint-bitmap)))
 		(gud-remove nil)
 	      (gud-break nil)))))))
 
@@ -1691,18 +1680,10 @@
 	  (if (memq gud-minor-mode '(gdba pdb))
 	      (if (string-match "^\*.+*$" (buffer-name))
 		  (kill-buffer nil)
-		(if (display-images-p)
-		    (remove-images (point-min) (point-max))
-		  (gdb-remove-strings (point-min) (point-max)))
-		(setq left-margin-width 0)
+		(gdb-remove-breakpoint-icons (point-min) (point-max) t)
 		(setq gud-minor-mode nil)
 		(kill-local-variable 'tool-bar-map)
-		(setq gud-running nil)
-		(if (get-buffer-window (current-buffer))
-		    (set-window-margins (get-buffer-window
-					 (current-buffer))
-					left-margin-width
-					right-margin-width))))))))
+		(setq gud-running nil)))))))
 
 (defun gdb-source-info ()
   "Find the source file where the program starts and displays it with related
@@ -1733,7 +1714,7 @@
     (other-window 1)))
 
 ;;from put-image
-(defun gdb-put-string (putstring pos)
+(defun gdb-put-string (putstring pos &optional dprop)
   "Put string PUTSTRING in front of POS in the current buffer.
 PUTSTRING is displayed by putting an overlay into the current buffer with a
 `before-string' STRING that has a `display' property whose value is
@@ -1741,7 +1722,8 @@
   (let ((gdb-string "x")
 	(buffer (current-buffer)))
     (let ((overlay (make-overlay pos pos buffer))
-	  (prop (list (list 'margin 'left-margin) putstring)))
+	  (prop (or dprop
+		    (list (list 'margin 'left-margin) putstring))))
       (put-text-property 0 (length gdb-string) 'display prop gdb-string)
       (overlay-put overlay 'put-break t)
       (overlay-put overlay 'before-string gdb-string))))
@@ -1749,7 +1731,7 @@
 ;;from remove-images
 (defun gdb-remove-strings (start end &optional buffer)
   "Remove strings between START and END in BUFFER.
-Remove only strings that were put in BUFFER with calls to `put-string'.
+Remove only strings that were put in BUFFER with calls to `gdb-put-string'.
 BUFFER nil or omitted means use the current buffer."
   (unless buffer
     (setq buffer (current-buffer)))
@@ -1760,6 +1742,72 @@
 	  (delete-overlay overlay)))
       (setq overlays (cdr overlays)))))
 
+(defun gdb-put-breakpoint-icon (enabled)
+  (let ((start (progn (beginning-of-line) (- (point) 1)))
+	(end (progn (end-of-line) (+ (point) 1))))
+    (gdb-remove-breakpoint-icons start end)
+    (if (display-images-p)
+	(if (>= (car (window-fringes)) 8)
+	    (gdb-put-string 
+	     nil (1+ start)
+	     `(left-fringe 
+	       ,(or breakpoint-bitmap
+		    (setq breakpoint-bitmap
+			  (define-fringe-bitmap
+			    "\x3c\x7e\xff\xff\xff\xff\x7e\x3c")))
+	       ,(if enabled
+		    'breakpoint-enabled-bitmap-face
+		  'breakpoint-disabled-bitmap-face)))
+	  (when (< left-margin-width 2)
+	    (save-current-buffer
+	      (setq left-margin-width 2)
+	      (if (get-buffer-window (current-buffer))
+		  (set-window-margins (get-buffer-window
+				       (current-buffer))
+				      left-margin-width
+				      right-margin-width))))
+	  (put-image
+	   (if enabled
+	       (or breakpoint-enabled-icon
+		   (setq breakpoint-enabled-icon
+			 (find-image `((:type xpm :data 
+					      ,breakpoint-xpm-data
+					      :ascent 100 :pointer hand)
+				       (:type pbm :data
+					      ,breakpoint-enabled-pbm-data
+					      :ascent 100 :pointer hand)))))
+	     (or breakpoint-disabled-icon
+		 (setq breakpoint-disabled-icon
+		       (find-image `((:type xpm :data
+					    ,breakpoint-xpm-data
+					    :conversion disabled
+					    :ascent 100)
+				     (:type pbm :data
+					    ,breakpoint-disabled-pbm-data
+					    :ascent 100))))))
+	   (+ start 1) nil 'left-margin))
+      (when (< left-margin-width 2)
+	(save-current-buffer
+	  (setq left-margin-width 2)
+	  (if (get-buffer-window (current-buffer))
+	      (set-window-margins (get-buffer-window
+				   (current-buffer))
+				  left-margin-width
+				  right-margin-width))))
+      (gdb-put-string (if enabled "B" "b") (1+ start)))))
+
+(defun gdb-remove-breakpoint-icons (start end &optional remove-margin)
+  (gdb-remove-strings start end)
+  (if (display-images-p)
+      (remove-images start end))
+  (when remove-margin
+    (setq left-margin-width 0)
+    (if (get-buffer-window (current-buffer))
+	(set-window-margins (get-buffer-window
+			     (current-buffer))
+			    left-margin-width
+			    right-margin-width))))
+
 (defun gdb-put-arrow (putstring pos)
   "Put arrow string PUTSTRING in the left margin in front of POS
 in the current buffer.  PUTSTRING is displayed by putting an
@@ -1813,9 +1861,7 @@
 		  (setq gdb-arrow-position (point))
 		  (gdb-put-arrow "=>" (point))))))
       ;; remove all breakpoint-icons in assembler buffer before updating.
-      (if (display-images-p)
-	  (remove-images (point-min) (point-max))
-	(gdb-remove-strings (point-min) (point-max))))
+      (gdb-remove-breakpoint-icons (point-min) (point-max)))
     (with-current-buffer (gdb-get-buffer 'gdb-breakpoints-buffer)
       (goto-char (point-min))
       (while (< (point) (- (point-max) 1))
@@ -1832,24 +1878,7 @@
 	      (with-current-buffer buffer
 		  (goto-char (point-min))
 		  (if (re-search-forward address nil t)
-		      (let ((start (progn (beginning-of-line) (- (point) 1)))
-			    (end (progn (end-of-line) (+ (point) 1))))
-			(if (display-images-p)
-			    (progn
-			      (remove-images start end)
-			      (if (eq ?y flag)
-				  (put-image breakpoint-enabled-icon
-					     (+ start 1)
-					     "breakpoint icon enabled"
-					     'left-margin)
-				(put-image breakpoint-disabled-icon
-					   (+ start 1)
-					   "breakpoint icon disabled"
-					   'left-margin)))
-			  (gdb-remove-strings start end)
-			  (if (eq ?y flag)
-			      (gdb-put-string "B" (+ start 1))
-			    (gdb-put-string "b" (+ start 1)))))))))))
+		      (gdb-put-breakpoint-icon (eq flag ?y))))))))
     (if (not (equal gdb-current-address "main"))
 	(set-window-point (get-buffer-window buffer) gdb-arrow-position))))
 
@@ -1864,7 +1893,6 @@
 \\{gdb-assembler-mode-map}"
   (setq major-mode 'gdb-assembler-mode)
   (setq mode-name "Machine")
-  (setq left-margin-width 2)
   (setq fringes-outside-margins t)
   (setq buffer-read-only t)
   (use-local-map gdb-assembler-mode-map)
--- a/lisp/info-look.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/info-look.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1,7 +1,7 @@
 ;;; info-look.el --- major-mode-sensitive Info index lookup facility
 ;; An older version of this was known as libc.el.
 
-;; Copyright (C) 1995,96,97,98,99,2001,2003  Free Software Foundation, Inc.
+;; Copyright (C) 1995,96,97,98,99,2001,2003,2004  Free Software Foundation, Inc.
 
 ;; Author: Ralph Schleicher <rs@nunatak.allgaeu.org>
 ;;         (did not show signs of life (Nov 2001)  -stef)
@@ -808,7 +808,7 @@
 
 (info-lookup-maybe-add-help
  :mode 'scheme-mode
- :regexp "[^()'\" \t\n]+"
+ :regexp "[^()`',\" \t\n]+"
  :ignore-case t
  ;; Aubrey Jaffer's rendition from <URL:ftp://ftp-swiss.ai.mit.edu/pub/scm>
  :doc-spec '(("(r5rs)Index" nil
--- a/lisp/isearch.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/isearch.el	Sat Feb 28 04:52:40 2004 +0000
@@ -1,6 +1,6 @@
 ;;; isearch.el --- incremental search minor mode
 
-;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 01, 2003
+;; Copyright (C) 1992, 93, 94, 95, 96, 97, 1999, 2000, 01, 2003, 2004
 ;;   Free Software Foundation, Inc.
 
 ;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
@@ -2128,26 +2128,30 @@
   :group 'isearch)
 
 (defface isearch
-  '((((type tty pc) (class color))
-     (:background "magenta4" :foreground "cyan1"))
-    (((class color) (background light))
+  '((((class color) (min-colors 88) (background light))
      ;; The background must not be too dark, for that means
      ;; the character is hard to see when the cursor is there.
      (:background "magenta2" :foreground "lightskyblue1"))
-    (((class color) (background dark))
+    (((class color) (min-colors 88) (background dark))
      (:background "palevioletred2" :foreground "brown4"))
+    (((class color) (min-colors 16))
+     (:background "magenta4" :foreground "cyan1"))
+    (((class color) (min-colors 8))
+     (:background "magenta4" :foreground "cyan1"))
     (t (:inverse-video t)))
   "Face for highlighting Isearch matches."
   :group 'isearch-faces)
 (defvar isearch 'isearch)
 
 (defface isearch-lazy-highlight-face
-  '((((type tty pc) (class color))
+  '((((class color) (min-colors 88) (background light))
+     (:background "paleturquoise"))
+    (((class color) (min-colors 88) (background dark))
+     (:background "paleturquoise4"))
+    (((class color) (min-colors 16))
      (:background "turquoise3"))
-    (((class color) (background light))
-     (:background "paleturquoise"))
-    (((class color) (background dark))
-     (:background "paleturquoise4"))
+    (((class color) (min-colors 8))
+     (:background "turquoise3"))
     (t (:underline t)))
   "Face for lazy highlighting of Isearch matches other than the current one."
   :group 'isearch-faces)
--- a/lisp/progmodes/sh-script.el	Sat Feb 28 01:33:17 2004 +0000
+++ b/lisp/progmodes/sh-script.el	Sat Feb 28 04:52:40 2004 +0000
@@ -315,9 +315,7 @@
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice (const :tag "No Arguments" nil)
 			       (string :tag "Arguments")
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 (defcustom sh-imenu-generic-expression
@@ -498,9 +496,7 @@
 See `sh-feature'."
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice (const :tag "require" t)
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 
@@ -515,9 +511,7 @@
 sign.  See `sh-feature'."
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice regexp
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 
@@ -639,9 +633,7 @@
 implemented as aliases.  See `sh-feature'."
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice (repeat string)
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 
@@ -663,9 +655,7 @@
 flow of control or syntax.  See `sh-feature'."
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice (repeat string)
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 
@@ -702,9 +692,7 @@
 See `sh-feature'."
   :type '(repeat (cons (symbol :tag "Shell")
 		       (choice (repeat string)
-			       (cons :format "Evaluate: %v"
-				     (const :format "" eval)
-				     sexp))))
+			       (sexp :format "Evaluate: %v"))))
   :group 'sh-script)
 
 
--- a/lispref/ChangeLog	Sat Feb 28 01:33:17 2004 +0000
+++ b/lispref/ChangeLog	Sat Feb 28 04:52:40 2004 +0000
@@ -1,3 +1,8 @@
+2004-02-27  Dan Nicolaescu  <dann@ics.uci.edu>
+
+	* display.texi (Defining Faces): Add description for min-colors.
+	Update example.
+
 2004-02-23  Luc Teirlinck  <teirllm@auburn.edu>
 
 	* abbrevs.texi: Various corrections and clarifications in addition
--- a/lispref/display.texi	Sat Feb 28 01:33:17 2004 +0000
+++ b/lispref/display.texi	Sat Feb 28 04:52:40 2004 +0000
@@ -1623,6 +1623,10 @@
 @item background
 The kind of background---either @code{light} or @code{dark}.
 
+@item min-colors
+An integer that represents the minimum number of colors the frame should
+support, it is compared with the result of @code{display-color-cells}.
+
 @item supports
 Whether or not the frame can display the face attributes given in
 @var{value}@dots{} (@pxref{Face Attributes}).  See the documentation
@@ -1644,17 +1648,20 @@
 
 @example
 @group
-(defface region
-  `((((type tty) (class color))
-     (:background "blue" :foreground "white"))
+  '((((class color) (min-colors 88) (background dark))
+     :background "blue3")
 @end group
+    (((class color) (min-colors 88) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 16) (background dark))
+     :background "blue3")
+    (((class color) (min-colors 16) (background light))
+     :background "lightgoldenrod2")
+    (((class color) (min-colors 8))
+     :background "blue" :foreground "white")
     (((type tty) (class mono))
-     (:inverse-video t))
-    (((class color) (background dark))
-     (:background "blue"))
-    (((class color) (background light))
-     (:background "lightblue"))
-    (t (:background "gray")))
+     :inverse-video t)
+    (t :background "gray"))
 @group
   "Basic face for highlighting the region."
   :group 'basic-faces)
--- a/src/ChangeLog	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/ChangeLog	Sat Feb 28 04:52:40 2004 +0000
@@ -1,3 +1,91 @@
+2004-02-28  Miles Bader  <miles@gnu.org>
+
+	* keyboard.c (adjust_point_for_property): #ifdef-out dodgy xassert.
+
+2004-02-28  Kim F. Storm  <storm@cua.dk>
+
+	* keyboard.c (kbd_buffer_store_event_hold): New function to store
+	an event into kbd fifo, but with special handling of quit event;
+	a quit event is saved for later, and further events are discarded
+	until the saved quit event has been processed.
+	(kbd_buffer_store_event): Use kbd_buffer_store_event_hold.
+	(gen_help_event): Store help event in kbd fifo.
+	(NREAD_INPUT_EVENTS): Remove.
+	(read_avail_input): Adapt to new read_socket_hook interface.
+	Remove allocation and initialization of local input_event buffer,
+	as read_socket_hook stores events directly in fifo.  Allocate and
+	initialize local hold_quit event to handle postponed quit event
+	(and store it if set by kbd_buffer_store_event_hold).
+
+	* keyboard.h (kbd_buffer_store_event_hold): Add prototype.
+	(gen_help_event): Fix prototype.
+
+	* macterm.c (XTread_socket):  Remove bufp_r and
+	numcharsp args.  Add hold_quit arg.
+	Rework to use just one, local, inev input_event. Store inev
+	directly in fifo using kbd_buffer_store_event_hold.
+
+	* sysdep.c (BUFFER_SIZE_FACTOR): Remove.
+	(read_input_waiting): Adapt to new read_socket_hook interface.
+	Remove allocation and initialization of local input_event buffer,
+	as read_socket_hook stores events directly in fifo.  Allocate and
+	initialize local hold_quit event to handle postponed quit event
+	(and store it if set by kbd_buffer_store_event_hold).
+
+	* term.c (read_socket_hook): Fix arg list. 
+
+	* termhooks.h (read_socket_hook): Fix prototype.
+
+	* w32inevt.c (w32_console_read_socket): Remove bufp_r and
+	numcharsp args.  Add hold_quit arg.
+	Rework to use just one, local, inev input_event. Store inev
+	directly in fifo using kbd_buffer_store_event_hold.
+
+	* w32inevt.h (w32_console_mouse_position): Fix prototype.
+
+	* w32term.c (w32_read_socket): Remove bufp_r and numcharsp args.
+	Add hold_quit arg. Rework to use just one, local, inev
+	input_event. Store inev directly in fifo using
+	kbd_buffer_store_event_hold.  Update count in one place.
+	Postpone call to gen_help_event until inev is stored; use new
+	local do_help for this.
+	Remove local emacs_event in handing of ButtonPress event; just use
+	inev instead (so no reason to copy it later).
+
+	* xsmfns.c (x_session_check_input): Remove numchars arg.
+
+	* xterm.c (x_focus_changed, x_detect_focus_change): Remove
+	numchars arg.  Always store event into bufp arg.  Return nothing.
+	Callers changed accordingly.
+	(glyph_rect): Simplify.
+	(STORE_KEYSYM_FOR_DEBUG): New macro.
+	(SET_SAVED_MENU_EVENT): Use inev instead of bufp, etc.
+	(current_bufp, current_numcharsp) [USE_GTK]: Remove.
+	(current_hold_quit) [USE_GTK]: Add.
+	(event_handler_gdk): Adapt to new handle_one_xevent.
+	(handle_one_xevent): Remove bufp_r and numcharsp args.
+	Add hold_quit arg. Rework to use just one, local, inev
+	input_event. Store inev directly in fifo using
+	kbd_buffer_store_event_hold.  Update count in one place.
+	Postpone call to gen_help_event until inev is stored; use new
+	local do_help for this.
+	Simplify handling of keysyms (consolidate common code).  Fix bug
+	where count was updated with nchars instead of nbytes.
+	Remove local emacs_event in handing of ButtonPress event; just use
+	inev instead (so no reason to copy it later).
+	Remove `out' label.  Rename label `ret' to `done'; add various
+	`goto done' to clarify code flow in deeply nested blocks.
+	(x_dispatch_event): Simplify as handle_one_xevent now calls
+	kbd_buffer_store_event itself.
+	(XTread_socket): Remove bufp_r and numcharsp args. Add hold_quit
+	arg.  Call handle_one_xevent with new arglist.  Store event from
+	x_session_check_input in fifo.
+	[USE_GTK]: Setup current_hold_quit.
+	Decrement handling_signal before unblocking input.
+	(x_initialize) [USE_GTK]: Initialize current_count.
+
+	* xterm.h (x_session_check_input): Fix prototype.
+
 2004-02-26  YAMAMOTO Mitsuharu  <mituharu@math.s.chiba-u.ac.jp>
 	
 	* s/darwin.h (LD_SWITCH_SYSTEM_TEMACS): Add `-framework
--- a/src/dispnew.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/dispnew.c	Sat Feb 28 04:52:40 2004 +0000
@@ -4137,16 +4137,6 @@
 	  changed_p = 1;
 	}
 
-      /* Update the header line after scrolling because a new header
-	 line would otherwise overwrite lines at the top of the window
-	 that can be scrolled.  */
-      if (header_line_row && header_line_row->enabled_p)
-	{
-	  header_line_row->y = 0;
-	  update_window_line (w, 0, &mouse_face_overwritten_p);
-	  changed_p = 1;
-	}
-
       /* Update the rest of the lines.  */
       for (n_updated = 0; row < end && (force_p || !input_pending); ++row)
 	if (row->enabled_p)
@@ -4183,6 +4173,16 @@
 
     set_cursor:
 
+      /* Update the header line after scrolling because a new header
+	 line would otherwise overwrite lines at the top of the window
+	 that can be scrolled.  */
+      if (header_line_row && header_line_row->enabled_p)
+	{
+	  header_line_row->y = 0;
+	  update_window_line (w, 0, &mouse_face_overwritten_p);
+	  changed_p = 1;
+	}
+
       /* Fix the appearance of overlapping/overlapped rows.  */
       if (!paused_p && !w->pseudo_window_p)
 	{
--- a/src/keyboard.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/keyboard.c	Sat Feb 28 04:52:40 2004 +0000
@@ -1916,7 +1916,12 @@
 		      : (PT < last_pt ? beg : end));
 	      check_composition = check_display = 1;
 	    }
+#if 0 /* This assertion isn't correct, because SET_PT may end up setting
+	 the point to something other than its argument, due to
+	 point-motion hooks, intangibility, etc.  */
 	  xassert (PT == beg || PT == end);
+#endif
+
 	  /* Pretend the area doesn't exist if the buffer is not
 	     modified.  */
 	  if (!modified && !ellipsis && beg < end)
@@ -3516,9 +3521,32 @@
 kbd_buffer_store_event (event)
      register struct input_event *event;
 {
+  kbd_buffer_store_event_hold (event, 0);
+}
+
+/* Store EVENT obtained at interrupt level into kbd_buffer, fifo.
+
+   If HOLD_QUIT is 0, just stuff EVENT into the fifo.
+   Else, if HOLD_QUIT.kind != NO_EVENT, discard EVENT.
+   Else, if EVENT is a quit event, store the quit event
+   in HOLD_QUIT, and return (thus ignoring further events).
+
+   This is used in read_avail_input to postpone the processing
+   of the quit event until all subsequent input events have been
+   parsed (and discarded).
+ */
+
+void
+kbd_buffer_store_event_hold (event, hold_quit)
+     register struct input_event *event;
+     struct input_event *hold_quit;
+{
   if (event->kind == NO_EVENT)
     abort ();
 
+  if (hold_quit && hold_quit->kind != NO_EVENT)
+    return;
+
   if (event->kind == ASCII_KEYSTROKE_EVENT)
     {
       register int c = event->code & 0377;
@@ -3560,6 +3588,12 @@
 	    }
 #endif
 
+	  if (hold_quit)
+	    {
+	      bcopy (event, (char *) hold_quit, sizeof (*event));
+	      return;
+	    }
+
 	  /* If this results in a quit_char being returned to Emacs as
 	     input, set Vlast_event_frame properly.  If this doesn't
 	     get returned to Emacs as an event, the next event read
@@ -3589,7 +3623,9 @@
      Just ignore the second one.  */
   else if (event->kind == BUFFER_SWITCH_EVENT
 	   && kbd_fetch_ptr != kbd_store_ptr
-	   && kbd_store_ptr->kind == BUFFER_SWITCH_EVENT)
+	   && ((kbd_store_ptr == kbd_buffer
+		? kbd_buffer + KBD_BUFFER_SIZE - 1
+		: kbd_store_ptr - 1)->kind) == BUFFER_SWITCH_EVENT)
     return;
 
   if (kbd_store_ptr - kbd_buffer == KBD_BUFFER_SIZE)
@@ -3648,24 +3684,22 @@
 
    Value is the number of input_events generated.  */
 
-int
-gen_help_event (bufp, size, help, frame, window, object, pos)
-     struct input_event *bufp;
-     int size;
+void
+gen_help_event (help, frame, window, object, pos)
      Lisp_Object help, frame, object, window;
      int pos;
 {
-  if (size >= 1)
-    {
-      bufp->kind = HELP_EVENT;
-      bufp->frame_or_window = frame;
-      bufp->arg = object;
-      bufp->x = WINDOWP (window) ? window : frame;
-      bufp->y = help;
-      bufp->code = pos;
-      return 1;
-    }
-  return 0;
+  struct input_event event;
+
+  EVENT_INIT (event);
+
+  event.kind = HELP_EVENT;
+  event.frame_or_window = frame;
+  event.arg = object;
+  event.x = WINDOWP (window) ? window : frame;
+  event.y = help;
+  event.code = pos;
+  kbd_buffer_store_event (&event);
 }
 
 
@@ -6570,15 +6604,7 @@
    only when SIGIO is blocked.
 
    Returns the number of keyboard chars read, or -1 meaning
-   this is a bad time to try to read input.
-
-   Typically, there are just a few available input events to be read
-   here, so we really don't need to allocate and initialize a big
-   buffer of input_events as we used to do.  Instead, we just allocate
-   a small buffer of input events -- and then poll for more input if we
-   read a full buffer of input events.  */
-
-#define NREAD_INPUT_EVENTS 512
+   this is a bad time to try to read input.  */
 
 static int
 read_avail_input (expected)
@@ -6600,59 +6626,47 @@
           int discard = 0;
           int nr;
 
-          do {
-            struct input_event buf[NREAD_INPUT_EVENTS];
-
-            for (i = 0; i < NREAD_INPUT_EVENTS; i++)
-              EVENT_INIT (buf[i]);
-
-            /* No need for FIONREAD or fcntl; just say don't wait.  */
-            nr = (*d->read_socket_hook) (d, buf, NREAD_INPUT_EVENTS, expected);
-
-            if (nr > 0)
-              {
-                /* We've got input. */
-                nread += nr;
-                expected = 0;
-
-                /* Scan the chars for C-g and store them in kbd_buffer.  */
-                for (i = 0; !discard && i < nr; i++)
-                  {
-                    kbd_buffer_store_event (&buf[i]);
-                    /* Don't look at input that follows a C-g too closely.
-                       This reduces lossage due to autorepeat on C-g.  */
-                    if (buf[i].kind == ASCII_KEYSTROKE_EVENT
-                        && buf[i].code == quit_char)
-                      discard = 1;
-                  }
-              }
-            else if (nr == -1)          /* Not OK to read input now. */
-              {
-                err = 1;
-              }
-            else if (nr == -2)          /* Non-transient error. */
-              {
-                /* The display device terminated; it should be closed. */
-
-                /* Kill Emacs if this was our last display. */
-                if (! display_list->next_display)
-                  /* Formerly simply reported no input, but that
-                     sometimes led to a failure of Emacs to terminate.
-                     SIGHUP seems appropriate if we can't reach the
-                     terminal.  */
-                  /* ??? Is it really right to send the signal just to
-                     this process rather than to the whole process
-                     group?  Perhaps on systems with FIONREAD Emacs is
-                     alone in its group.  */
-                  kill (getpid (), SIGHUP);
-
-                /* XXX Is calling delete_display safe here?  It calls Fdelete_frame. */
-                if (d->delete_display_hook)
-                  (*d->delete_display_hook) (d);
-                else
-                  delete_display (d);
-              }
-          } while (nr == NREAD_INPUT_EVENTS);
+          struct input_event hold_quit;
+
+          EVENT_INIT (hold_quit);
+          hold_quit.kind = NO_EVENT;
+
+          /* No need for FIONREAD or fcntl; just say don't wait.  */
+          while (nr = (*d->read_socket_hook) (d, expected, &hold_quit), nr > 0)
+            {
+              nread += nr;
+              expected = 0;
+            }
+          
+          if (nr == -1)          /* Not OK to read input now. */
+            {
+              err = 1;
+            }
+          else if (nr == -2)          /* Non-transient error. */
+            {
+              /* The display device terminated; it should be closed. */
+              
+              /* Kill Emacs if this was our last display. */
+              if (! display_list->next_display)
+                /* Formerly simply reported no input, but that
+                   sometimes led to a failure of Emacs to terminate.
+                   SIGHUP seems appropriate if we can't reach the
+                   terminal.  */
+                /* ??? Is it really right to send the signal just to
+                   this process rather than to the whole process
+                   group?  Perhaps on systems with FIONREAD Emacs is
+                   alone in its group.  */
+                kill (getpid (), SIGHUP);
+              
+              /* XXX Is calling delete_display safe here?  It calls Fdelete_frame. */
+              if (d->delete_display_hook)
+                (*d->delete_display_hook) (d);
+              else
+                delete_display (d);
+            }
+
+          if (hold_quit.kind != NO_EVENT)
+            kbd_buffer_store_event (&hold_quit);
         }
 
       d = next;
@@ -6672,13 +6686,13 @@
 
 int
 tty_read_avail_input (struct display *display,
-                      struct input_event *buf,
-                      int numchars, int expected)
-{
-  /* Using numchars here avoids reading more than the buf can
-     really hold.  That may prevent loss of characters on some systems
-     when input is stuffed at us.  */
-  unsigned char cbuf[numchars];
+                      int expected,
+                      struct input_event *hold_quit)
+{
+  /* Using KBD_BUFFER_SIZE - 1 here avoids reading more than
+     the kbd_buffer can really hold.  That may prevent loss
+     of characters on some systems when input is stuffed at us.  */
+  unsigned char cbuf[KBD_BUFFER_SIZE - 1];
   int n_to_read, i;
   struct tty_display_info *tty = display->display_info.tty;
   int nread = 0;
@@ -6785,19 +6799,28 @@
 
   for (i = 0; i < nread; i++)
     {
-      buf[i].kind = ASCII_KEYSTROKE_EVENT;
-      buf[i].modifiers = 0;
+      struct input_event buf;
+      EVENT_INIT (buf);
+      buf.kind = ASCII_KEYSTROKE_EVENT;
+      buf.modifiers = 0;
       if (tty->meta_key == 1 && (cbuf[i] & 0x80))
-        buf[i].modifiers = meta_modifier;
+        buf.modifiers = meta_modifier;
       if (tty->meta_key != 2)
         cbuf[i] &= ~0x80;
-
-      buf[i].code = cbuf[i];
+      
+      buf.code = cbuf[i];
       /* Set the frame corresponding to the active tty.  Note that the
          value of selected_frame is not reliable here, redisplay tends
          to temporarily change it. */
-      buf[i].frame_or_window = tty->top_frame;
-      buf[i].arg = Qnil;
+      buf.frame_or_window = tty->top_frame;
+      buf.arg = Qnil;
+      
+      kbd_buffer_store_event (&buf);
+      /* Don't look at input that follows a C-g too closely.
+         This reduces lossage due to autorepeat on C-g.  */
+      if (buf.kind == ASCII_KEYSTROKE_EVENT
+          && buf.code == quit_char)
+        break;
     }
 
   return nread;
--- a/src/keyboard.h	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/keyboard.h	Sat Feb 28 04:52:40 2004 +0000
@@ -329,19 +329,21 @@
 extern void timer_stop_idle P_ ((void));
 extern int lucid_event_type_list_p P_ ((Lisp_Object));
 extern void kbd_buffer_store_event P_ ((struct input_event *));
+extern void kbd_buffer_store_event_hold P_ ((struct input_event *,
+					     struct input_event *));
 #ifdef POLL_FOR_INPUT
 extern void poll_for_input_1 P_ ((void));
 #endif
 extern void show_help_echo P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
 				Lisp_Object, int));
-extern int gen_help_event P_ ((struct input_event *, int, Lisp_Object,
-			       Lisp_Object, Lisp_Object, Lisp_Object, int));
+extern void gen_help_event P_ ((Lisp_Object, Lisp_Object, Lisp_Object,
+			       Lisp_Object, int));
 extern void kbd_buffer_store_help_event P_ ((Lisp_Object, Lisp_Object));
 extern Lisp_Object menu_item_eval_property P_ ((Lisp_Object));
 extern int  kbd_buffer_events_waiting P_ ((int));
 
-extern int tty_read_avail_input P_ ((struct display *,
-                                     struct input_event *, int, int));
+extern int tty_read_avail_input P_ ((struct display *, int,
+                                     struct input_event *));
 
 /* arch-tag: 769cbade-1ba9-4950-b886-db265b061aa3
    (do not change this comment) */
--- a/src/lisp.h	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/lisp.h	Sat Feb 28 04:52:40 2004 +0000
@@ -2380,7 +2380,6 @@
 extern int check_point_in_composition
 	P_ ((struct buffer *, int, struct buffer *, int));
 extern void redisplay_preserve_echo_area P_ ((int));
-extern void mark_window_display_accurate P_ ((Lisp_Object, int));
 extern void prepare_menu_bars P_ ((void));
 
 void set_frame_cursor_types P_ ((struct frame *, Lisp_Object));
--- a/src/macterm.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/macterm.c	Sat Feb 28 04:52:40 2004 +0000
@@ -8016,8 +8016,9 @@
 /* Emacs calls this whenever it wants to read an input event from the
    user. */
 int
-XTread_socket (struct input_event *bufp, int numchars, int expected)
-{
+XTread_socket (int sd, int expected, struct input_event *hold_quit)
+{
+  struct input_event inev;
   int count = 0;
 #if USE_CARBON_EVENTS
   OSStatus rneResult;
@@ -8042,9 +8043,6 @@
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();
-
   /* Don't poll for events to process (specifically updateEvt) if
      window update currently already in progress.  A call to redisplay
      (in do_window_update) can be preempted by another call to
@@ -8063,7 +8061,9 @@
      event to nil because keyboard.c protects incompletely processed
      event from being garbage collected by placing them in the
      kbd_buffer_gcpro vector.  */
-  bufp->arg = Qnil;
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
 
   event_mask = everyEvent;
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
@@ -8101,18 +8101,17 @@
 		GetEventParameter(eventRef, kEventParamMouseLocation,
 				  typeQDPoint, NULL, sizeof (Point),
 				  NULL, &point);
-		bufp->kind = WHEEL_EVENT;
-		bufp->code = 0;
-		bufp->modifiers = (mac_event_to_emacs_modifiers(eventRef)
-				   | ((delta < 0) ? down_modifier
-				                  : up_modifier));
+		inev.kind = WHEEL_EVENT;
+		inev.code = 0;
+		inev.modifiers = (mac_event_to_emacs_modifiers(eventRef)
+				  | ((delta < 0) ? down_modifier
+				     : up_modifier));
 		SetPort (GetWindowPort (window_ptr));
 		GlobalToLocal (&point);
-		XSETINT (bufp->x, point.h);
-		XSETINT (bufp->y, point.v);
-		XSETFRAME (bufp->frame_or_window, mwp->mFP);
-		bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
-		count++;
+		XSETINT (inev.x, point.h);
+		XSETINT (inev.y, point.v);
+		XSETFRAME (inev.frame_or_window, mwp->mFP);
+		inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
 	      }
 	    else
 	      SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
@@ -8161,28 +8160,27 @@
 	      GlobalToLocal (&mouse_loc);
 
 #if USE_CARBON_EVENTS
-	      bufp->code = mac_get_mouse_btn (eventRef);
+	      inev.code = mac_get_mouse_btn (eventRef);
 #else
-	      bufp_.code = mac_get_emulate_btn (er.modifiers);
-#endif
-              bufp->kind = SCROLL_BAR_CLICK_EVENT;
-              bufp->frame_or_window = tracked_scroll_bar->window;
-              bufp->part = scroll_bar_handle;
+	      inev.code = mac_get_emulate_btn (er.modifiers);
+#endif
+              inev.kind = SCROLL_BAR_CLICK_EVENT;
+              inev.frame_or_window = tracked_scroll_bar->window;
+              inev.part = scroll_bar_handle;
 #if USE_CARBON_EVENTS
-	      bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+	      inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-	      bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
-#endif
-              bufp->modifiers |= up_modifier;
-	      bufp->timestamp = er.when * (1000 / 60);
+	      inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+              inev.modifiers |= up_modifier;
+	      inev.timestamp = er.when * (1000 / 60);
 	        /* ticks to milliseconds */
 
-              XSETINT (bufp->x, tracked_scroll_bar->left + 2);
-              XSETINT (bufp->y, mouse_loc.v - 24);
+              XSETINT (inev.x, tracked_scroll_bar->left + 2);
+              XSETINT (inev.y, mouse_loc.v - 24);
               tracked_scroll_bar->dragging = Qnil;
               mouse_tracking_in_progress = mouse_tracking_none;
               tracked_scroll_bar = NULL;
-              count++;
               break;
             }
 
@@ -8196,9 +8194,8 @@
 		  struct frame *f = ((mac_output *)
 				     GetWRefCon (FrontWindow ()))->mFP;
 		  saved_menu_event_location = er.where;
-		  bufp->kind = MENU_BAR_ACTIVATE_EVENT;
-		  XSETFRAME (bufp->frame_or_window, f);
-		  count++;
+		  inev.kind = MENU_BAR_ACTIVATE_EVENT;
+		  XSETFRAME (inev.frame_or_window, f);
 		}
 	      break;
 
@@ -8229,13 +8226,13 @@
 #endif
 
 #if USE_CARBON_EVENTS
-		  bufp->code = mac_get_mouse_btn (eventRef);
+		  inev.code = mac_get_mouse_btn (eventRef);
 #else
-		  bufp_.code = mac_get_emulate_btn (er.modifiers);
-#endif
-		  XSETINT (bufp->x, mouse_loc.h);
-		  XSETINT (bufp->y, mouse_loc.v);
-		  bufp->timestamp = er.when * (1000 / 60);
+		  inev.code = mac_get_emulate_btn (er.modifiers);
+#endif
+		  XSETINT (inev.x, mouse_loc.h);
+		  XSETINT (inev.y, mouse_loc.v);
+		  inev.timestamp = er.when * (1000 / 60);
 		    /* ticks to milliseconds */
 
 #if TARGET_API_MAC_CARBON
@@ -8247,7 +8244,7 @@
 		      struct scroll_bar *bar = (struct scroll_bar *)
 			GetControlReference (ch);
 		      x_scroll_bar_handle_click (bar, control_part_code, &er,
-						 bufp);
+						 &inev);
 		      if (er.what == mouseDown
 			  && control_part_code == kControlIndicatorPart)
 		        {
@@ -8264,22 +8261,22 @@
 		  else
 	            {
 		      Lisp_Object window;
-		      
-		      bufp->kind = MOUSE_CLICK_EVENT;
-		      XSETFRAME (bufp->frame_or_window, mwp->mFP);
+
+	              inev.kind = MOUSE_CLICK_EVENT;
+		      XSETFRAME (inev.frame_or_window, mwp->mFP);
 		      if (er.what == mouseDown)
 			mouse_tracking_in_progress
 			  = mouse_tracking_mouse_movement;
 		      else
 			mouse_tracking_in_progress = mouse_tracking_none;
-		      window = window_from_coordinates (mwp->mFP, bufp->x, bufp->y, 0, 0, 0, 1);
+		      window = window_from_coordinates (mwp->mFP, inev.x, inev.y, 0, 0, 0, 1);
 		      
 		      if (EQ (window, mwp->mFP->tool_bar_window))
 			{
 			  if (er.what == mouseDown)
-			    handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 1, 0);
+			    handle_tool_bar_click (mwp->mFP, inev.x, inev.y, 1, 0);
 			  else
-			    handle_tool_bar_click (mwp->mFP, bufp->x, bufp->y, 0,
+			    handle_tool_bar_click (mwp->mFP, inev.x, inev.y, 0,
 #if USE_CARBON_EVENTS
 						   mac_event_to_emacs_modifiers (eventRef)
 #else
@@ -8291,22 +8288,20 @@
 		    }
 
 #if USE_CARBON_EVENTS
-		  bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+		  inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-		  bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+		  inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
 
 	          switch (er.what)
 		    {
 		    case mouseDown:
-		      bufp->modifiers |= down_modifier;
+		      inev.modifiers |= down_modifier;
 		      break;
 		    case mouseUp:
-		      bufp->modifiers |= up_modifier;
+		      inev.modifiers |= up_modifier;
 		      break;
 		    }
-
-	          count++;
 	        }
 	      break;
 
@@ -8327,10 +8322,9 @@
 	    case inGoAway:
 	      if (TrackGoAway (window_ptr, er.where))
 	        {
-	          bufp->kind = DELETE_WINDOW_EVENT;
-	          XSETFRAME (bufp->frame_or_window,
+	          inev.kind = DELETE_WINDOW_EVENT;
+	          XSETFRAME (inev.frame_or_window,
 			     ((mac_output *) GetWRefCon (window_ptr))->mFP);
- 	          count++;
 	        }
 	      break;
 
@@ -8399,8 +8393,8 @@
 
 	  if (keycode_to_xkeysym (keycode, &xkeysym))
 	    {
-	      bufp->code = 0xff00 | xkeysym;
-	      bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
+	      inev.code = 0xff00 | xkeysym;
+	      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
 	    }
 	  else
 	    {
@@ -8419,12 +8413,12 @@
 		  int new_keycode = keycode | new_modifiers;
 		  Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
 		  unsigned long some_state = 0;
-		  bufp->code = KeyTranslate (kchr_ptr, new_keycode,
-					     &some_state) & 0xff;
+		  inev.code = KeyTranslate (kchr_ptr, new_keycode,
+					    &some_state) & 0xff;
 		}
 	      else
-		bufp->code = er.message & charCodeMask;
-	      bufp->kind = ASCII_KEYSTROKE_EVENT;
+		inev.code = er.message & charCodeMask;
+	      inev.kind = ASCII_KEYSTROKE_EVENT;
 	    }
 	}
 
@@ -8435,7 +8429,7 @@
 	   Mac keyboard to be used to enter non-ASCII iso-latin-1
 	   characters directly.  */
 	if (mac_keyboard_text_encoding != kTextEncodingMacRoman
-	    && bufp->kind == ASCII_KEYSTROKE_EVENT && bufp->code >= 128)
+	    && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
 	  {
 	    static TECObjectRef converter = NULL;
 	    OSStatus the_err = noErr;
@@ -8464,7 +8458,7 @@
 
 	    if (the_err == noErr)
 	      {
-		unsigned char ch = bufp->code;
+		unsigned char ch = inev.code;
 		ByteCount actual_input_length, actual_output_length;
 		unsigned char outch;
 
@@ -8475,25 +8469,23 @@
 		if (convert_status == noErr
 		    && actual_input_length == 1
 		    && actual_output_length == 1)
-		  bufp->code = outch;
+		  inev.code = outch;
 	      }
 	  }
 
 #if USE_CARBON_EVENTS
-	bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+	inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-	bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+	inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
 #endif
 
 	{
 	  mac_output *mwp
 	    = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
-	  XSETFRAME (bufp->frame_or_window, mwp->mFP);
+	  XSETFRAME (inev.frame_or_window, mwp->mFP);
 	}
 
-	bufp->timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
-
-	count++;
+	inev.timestamp = er.when * (1000 / 60);  /* ticks to milliseconds */
 	break;
 
       case kHighLevelEvent:
@@ -8521,21 +8513,21 @@
             if (wp && is_emacs_window(wp))
 	        f = ((mac_output *) GetWRefCon (wp))->mFP;
 
-            bufp->kind = DRAG_N_DROP_EVENT;
-            bufp->code = 0;
-            bufp->timestamp = er.when * (1000 / 60);
+            inev.kind = DRAG_N_DROP_EVENT;
+            inev.code = 0;
+            inev.timestamp = er.when * (1000 / 60);
 	      /* ticks to milliseconds */
 #if USE_CARBON_EVENTS
-	    bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+	    inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
 #else
-	    bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
-#endif
-
-            XSETINT (bufp->x, 0);
-            XSETINT (bufp->y, 0);
+	    inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+
+            XSETINT (inev.x, 0);
+            XSETINT (inev.y, 0);
 
             XSETFRAME (frame, f);
-            bufp->frame_or_window = Fcons (frame, drag_and_drop_file_list);
+            inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
 
             /* Regardless of whether Emacs was suspended or in the
                foreground, ask it to redraw its entire screen.
@@ -8552,8 +8544,6 @@
 #else /* not TARGET_API_MAC_CARBON */
               InvalRect (&(wp->portRect));
 #endif /* not TARGET_API_MAC_CARBON */
-
-            count++;
           }
       default:
 	break;
@@ -8622,8 +8612,13 @@
       }
   }
 
+  if (inev.kind != NO_EVENT)
+    {
+      kbd_buffer_store_event_hold (&inev, hold_quit);
+      count++;
+    }
+
   UNBLOCK_INPUT;
-
   return count;
 }
 
--- a/src/sysdep.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/sysdep.c	Sat Feb 28 04:52:40 2004 +0000
@@ -2711,13 +2711,6 @@
 /* Read keyboard input into the standard buffer,
    waiting for at least one character.  */
 
-/* Make all keyboard buffers much bigger when using a window system.  */
-#ifdef HAVE_WINDOW_SYSTEM
-#define BUFFER_SIZE_FACTOR 16
-#else
-#define BUFFER_SIZE_FACTOR 1
-#endif
-
 void
 read_input_waiting ()
 {
@@ -2728,26 +2721,19 @@
 
   if (read_socket_hook)
     {
-      struct input_event buf[256];
-      for (i = 0; i < 256; i++)
-	EVENT_INIT (buf[i]);
-      
+      struct input_event hold_quit;
+
+      EVENT_INIT (hold_quit);
+      hold_quit.kind = NO_EVENT;
+
       read_alarm_should_throw = 0;
       if (! setjmp (read_alarm_throw))
-	nread = (*read_socket_hook) (0, buf, 256, 1);
+	nread = (*read_socket_hook) (0, 1, &hold_quit);
       else
 	nread = -1;
 
-      /* Scan the chars for C-g and store them in kbd_buffer.  */
-      for (i = 0; i < nread; i++)
-	{
-	  kbd_buffer_store_event (&buf[i]);
-	  /* Don't look at input that follows a C-g too closely.
-	     This reduces lossage due to autorepeat on C-g.  */
-	  if (buf[i].kind == ASCII_KEYSTROKE_EVENT
-	      && buf[i].code == quit_char)
-	    break;
-	}
+      if (hold_quit.kind != NO_EVENT)
+	kbd_buffer_store_event (&hold_quit);
     }
   else
     {
--- a/src/termhooks.h	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/termhooks.h	Sat Feb 28 04:52:40 2004 +0000
@@ -489,10 +489,11 @@
      there is available input on at least one of the currently opened
      display devices -- but not necessarily on this device.
      Therefore, in most cases EXPECTED should be simply ignored.
-  */
+
+     XXX This documentation needs to be updated.  */
   int (*read_socket_hook) P_ ((struct display *display,
-                               struct input_event *buf,
-                               int size, int expected));
+                               int expected,
+                               struct input_event *hold_quit));
 
   /* Called when a frame's display becomes entirely up to date.  */
   void (*frame_up_to_date_hook) P_ ((struct frame *));
--- a/src/w32inevt.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/w32inevt.c	Sat Feb 28 04:52:40 2004 +0000
@@ -642,8 +642,7 @@
 }
 
 int
-w32_console_read_socket (struct input_event *bufp, int numchars,
-			 int expected)
+w32_console_read_socket (int sd, int expected, struct input_event *hold_quit)
 {
   BOOL no_events = TRUE;
   int nev, ret = 0, add;
@@ -670,27 +669,31 @@
 	  return nev;
         }
 
-      while (nev > 0 && numchars > 0)
+      while (nev > 0)
         {
+	  struct input_event inev;
+
+	  EVENT_INIT (inev);
+	  inev.kind = NO_EVENT;
+	  inev.arg = Qnil;
+
 	  switch (queue_ptr->EventType)
             {
             case KEY_EVENT:
-	      add = key_event (&queue_ptr->Event.KeyEvent, bufp, &isdead);
+	      add = key_event (&queue_ptr->Event.KeyEvent, &inev, &isdead);
 	      if (add == -1) /* 95.7.25 by himi */
 		{
 		  queue_ptr--;
 		  add = 1;
 		}
-	      bufp += add;
-	      ret += add;
-	      numchars -= add;
+	      if (add)
+		kbd_buffer_store_event_hold (&inev, hold_quit);
 	      break;
 
             case MOUSE_EVENT:
-	      add = do_mouse_event (&queue_ptr->Event.MouseEvent, bufp);
-	      bufp += add;
-	      ret += add;
-	      numchars -= add;
+	      add = do_mouse_event (&queue_ptr->Event.MouseEvent, &inev);
+	      if (add)
+		kbd_buffer_store_event_hold (&inev, hold_quit);
 	      break;
 
             case WINDOW_BUFFER_SIZE_EVENT:
--- a/src/w32inevt.h	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/w32inevt.h	Sat Feb 28 04:52:40 2004 +0000
@@ -21,8 +21,8 @@
 #ifndef EMACS_W32INEVT_H
 #define EMACS_W32INEVT_H
 
-extern int w32_console_read_socket (int sd, struct input_event *bufp,
-				    int numchars, int expected);
+extern int w32_console_read_socket (int sd, int numchars,
+				    struct input_event *hold_quit);
 extern void w32_console_mouse_position (FRAME_PTR *f, int insist,
 					Lisp_Object *bar_window,
 					enum scroll_bar_part *part,
--- a/src/w32term.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/w32term.c	Sat Feb 28 04:52:40 2004 +0000
@@ -4122,8 +4122,6 @@
    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'.
 
@@ -4139,10 +4137,10 @@
 */
 
 int
-w32_read_socket (bufp, numchars, expected)
-     /* register */ struct input_event *bufp;
-     /* register */ int numchars;
+w32_read_socket (sd, expected, hold_quit)
+     register int sd;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   int check_visibility = 0;
@@ -4162,13 +4160,17 @@
   /* 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:
@@ -4197,12 +4199,8 @@
 		     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)))
@@ -4232,17 +4230,10 @@
 
 	  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;
 
@@ -4261,15 +4252,11 @@
 	      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;
 
@@ -4288,15 +4275,11 @@
 	      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;
 
@@ -4342,13 +4325,10 @@
 		     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;
@@ -4366,27 +4346,8 @@
              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;
-
-              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;
-            }
+	    do_help = 1;
+
           break;
 
 	case WM_LBUTTONDOWN:
@@ -4400,13 +4361,10 @@
 	  {
             /* 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;
@@ -4415,35 +4373,29 @@
 
 	    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),
@@ -4481,15 +4433,11 @@
 	    if (f)
 	      {
 
-		if ((!dpyinfo->w32_focus_frame
-		     || f == dpyinfo->w32_focus_frame)
-		    && (numchars >= 1))
+		if (!dpyinfo->w32_focus_frame
+		    || f == dpyinfo->w32_focus_frame)
 		  {
 		    /* Emit an Emacs wheel-up/down event.  */
-		    construct_mouse_wheel (bufp, &msg, f);
-		    bufp++;
-		    count++;
-		    numchars--;
+		    construct_mouse_wheel (&inev, &msg, f);
 		  }
 		/* Ignore any mouse motion that happened before this
 		   event; any subsequent mouse-movement Emacs events
@@ -4506,12 +4454,7 @@
 	  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:
@@ -4519,15 +4462,8 @@
 	    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;
 	  }
 
@@ -4603,12 +4539,8 @@
 		  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:
@@ -4633,12 +4565,8 @@
                       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)))
@@ -4706,16 +4634,7 @@
 		 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;
 
@@ -4765,16 +4684,7 @@
                  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;
@@ -4786,15 +4696,8 @@
 
 	  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;
 
@@ -4803,15 +4706,8 @@
 
 	  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;
 
@@ -4853,6 +4749,42 @@
 	    }
 	  break;
 	}
+
+      if (inev.kind != NO_EVENT)
+	{
+	  kbd_buffer_store_event_hold (&inev, hold_quit);
+	  count++;
+	}
+
+      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)
+		{
+		  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);
+	    }
+	  else
+	    {
+	      help_echo_string = Qnil;
+	      gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+	    }
+	  count++;
+	}
     }
 
   /* If the focus was just given to an autoraising frame,
@@ -5144,6 +5076,9 @@
 	 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);
 
--- a/src/window.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/window.c	Sat Feb 28 04:52:40 2004 +0000
@@ -2046,6 +2046,9 @@
 	    if (EQ (w->buffer, obj))
 	      {
 		mark_window_display_accurate (window, 0);
+		w->update_mode_line = Qt;
+		XBUFFER (obj)->prevent_redisplay_optimizations_p = 1;
+		++update_mode_lines;
 		best_window = window;
 	      }
 	    break;
@@ -3464,12 +3467,18 @@
   if (NILP (object))
     {
       windows_or_buffers_changed++;
+      update_mode_lines++;
       return Qt;
     }
 
   if (WINDOWP (object))
     {
+      struct window *w = XWINDOW (object);
       mark_window_display_accurate (object, 0);
+      w->update_mode_line = Qt;
+      if (BUFFERP (w->buffer))
+	XBUFFER (w->buffer)->prevent_redisplay_optimizations_p = 1;
+      ++update_mode_lines;
       return Qt;
     }
     
--- a/src/xsmfns.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/xsmfns.c	Sat Feb 28 04:52:40 2004 +0000
@@ -107,13 +107,10 @@
 
 /* Handle any messages from the session manager.  If no connection is
    open to a session manager, just return 0.
-   Otherwise returns the number of events stored in buffer BUFP,
-   which can hold up to *NUMCHARS characters.  At most one event is
-   stored, a SAVE_SESSION_EVENT. */
+   Otherwise returns 1 if SAVE_SESSION_EVENT is stored in buffer BUFP.  */
 int
-x_session_check_input (bufp, numchars)
+x_session_check_input (bufp)
      struct input_event *bufp;
-     int *numchars;
 {
   SELECT_TYPE read_fds;
   EMACS_TIME tmout;
@@ -147,16 +144,11 @@
 
   /* Check if smc_interact_CB was called and we shall generate a
      SAVE_SESSION_EVENT. */
-  if (*numchars > 0 && emacs_event.kind != NO_EVENT)
-    {
-      bcopy (&emacs_event, bufp, sizeof (struct input_event));
-      bufp++;
-      (*numchars)--;
+  if (emacs_event.kind == NO_EVENT)
+    return 0;
 
-      return 1;
-    }
-
-  return 0;
+  bcopy (&emacs_event, bufp, sizeof (struct input_event));
+  return 1;
 }
 
 /* Return non-zero if we have a connection to a session manager.*/
--- a/src/xterm.c	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/xterm.c	Sat Feb 28 04:52:40 2004 +0000
@@ -337,16 +337,10 @@
 static void frame_highlight P_ ((struct frame *));
 static void frame_unhighlight P_ ((struct frame *));
 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
-static int  x_focus_changed P_ ((int,
-                                 int,
-                                 struct x_display_info *,
-                                 struct frame *,
-                                 struct input_event *,
-                                 int));
-static int  x_detect_focus_change P_ ((struct x_display_info *,
-                                       XEvent *,
-                                       struct input_event *,
-                                       int));
+static void  x_focus_changed P_ ((int, int, struct x_display_info *,
+				  struct frame *, struct input_event *));
+static void x_detect_focus_change P_ ((struct x_display_info *,
+                                       XEvent *, struct input_event *));
 static void XTframe_rehighlight P_ ((struct frame *));
 static void x_frame_rehighlight P_ ((struct x_display_info *));
 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
@@ -365,11 +359,8 @@
 					    unsigned long *));
 static void x_check_fullscreen P_ ((struct frame *));
 static void x_check_expected_move P_ ((struct frame *));
-static int handle_one_xevent P_ ((struct x_display_info *,
-                                  XEvent *,
-                                  struct input_event **,
-                                  int *,
-                                  int *));
+static int handle_one_xevent P_ ((struct x_display_info *, XEvent *,
+				  int *, struct input_event *));
 
 
 /* Flush display of frame F, or of all frames if F is null.  */
@@ -3169,20 +3160,16 @@
 
 /* Handle FocusIn and FocusOut state changes for FRAME.
    If FRAME has focus and there exists more than one frame, puts
-   a FOCUS_IN_EVENT into BUFP.
-   Returns number of events inserted into BUFP. */
-
-static int
-x_focus_changed (type, state, dpyinfo, frame, bufp, numchars)
+   a FOCUS_IN_EVENT into *BUFP.  */
+
+static void
+x_focus_changed (type, state, dpyinfo, frame, bufp)
      int type;
      int state;
      struct x_display_info *dpyinfo;
      struct frame *frame;
      struct input_event *bufp;
-     int numchars;
-{
-  int nr_events = 0;
-
+{
   if (type == FocusIn)
     {
       if (dpyinfo->x_focus_event_frame != frame)
@@ -3192,17 +3179,12 @@
 
           /* Don't stop displaying the initial startup message
              for a switch-frame event we don't need.  */
-          if (numchars > 0
-              && GC_NILP (Vterminal_frame)
+          if (GC_NILP (Vterminal_frame)
               && GC_CONSP (Vframe_list)
               && !GC_NILP (XCDR (Vframe_list)))
             {
               bufp->kind = FOCUS_IN_EVENT;
               XSETFRAME (bufp->frame_or_window, frame);
-              bufp->arg = Qnil;
-              ++bufp;
-              numchars--;
-              ++nr_events;
             }
         }
 
@@ -3228,27 +3210,25 @@
         XUnsetICFocus (FRAME_XIC (frame));
 #endif
     }
-
-  return nr_events;
 }
 
 /* The focus may have changed.  Figure out if it is a real focus change,
    by checking both FocusIn/Out and Enter/LeaveNotify events.
 
-   Returns number of events inserted into BUFP. */
-
-static int
-x_detect_focus_change (dpyinfo, event, bufp, numchars)
+   Returns FOCUS_IN_EVENT event in *BUFP. */
+
+static void
+x_detect_focus_change (dpyinfo, event, bufp)
      struct x_display_info *dpyinfo;
      XEvent *event;
      struct input_event *bufp;
-     int numchars;
 {
   struct frame *frame;
   int nr_events = 0;
 
   frame = x_any_window_to_frame (dpyinfo, event->xany.window);
-  if (! frame) return nr_events;
+  if (! frame)
+    return;
 
   switch (event->type)
     {
@@ -3262,29 +3242,20 @@
         if (event->xcrossing.detail != NotifyInferior
             && event->xcrossing.focus
             && ! (focus_state & FOCUS_EXPLICIT))
-          nr_events = x_focus_changed ((event->type == EnterNotify
-                                        ? FocusIn : FocusOut),
-                                       FOCUS_IMPLICIT,
-                                       dpyinfo,
-                                       frame,
-                                       bufp,
-                                       numchars);
+          x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut),
+			   FOCUS_IMPLICIT,
+			   dpyinfo, frame, bufp);
       }
       break;
 
     case FocusIn:
     case FocusOut:
-      nr_events = x_focus_changed (event->type,
-                                   (event->xfocus.detail == NotifyPointer
-                                    ? FOCUS_IMPLICIT : FOCUS_EXPLICIT),
-                                   dpyinfo,
-                                   frame,
-                                   bufp,
-                                   numchars);
+      x_focus_changed (event->type,
+		       (event->xfocus.detail == NotifyPointer ?
+			FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+		       dpyinfo, frame, bufp);
       break;
     }
-
-  return nr_events;
 }
 
 
@@ -3629,35 +3600,39 @@
      XRectangle *rect;
 {
   Lisp_Object window;
-  int found = 0;
+  struct window *w;
+  struct glyph_row *r, *end_row;
 
   window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-  if (!NILP (window))
-    {
-      struct window *w = XWINDOW (window);
-      struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
-      struct glyph_row *end = r + w->current_matrix->nrows - 1;
-
-      for (; !found && r < end && r->enabled_p; ++r)
-	if (r->y >= y)
-	  {
-	    struct glyph *g = r->glyphs[TEXT_AREA];
-	    struct glyph *end = g + r->used[TEXT_AREA];
-	    int gx;
-
-	    for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
-	      if (gx >= x)
-		{
-		  rect->width = g->pixel_width;
-		  rect->height = r->height;
-		  rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
-		  rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
-		  found = 1;
-		}
-	  }
-    }
-
-  return found;
+  if (NILP (window))
+    return 0;
+
+  w = XWINDOW (window);
+  r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
+  end_row = r + w->current_matrix->nrows - 1;
+
+  for (; r < end_row && r->enabled_p; ++r)
+    {
+      if (r->y >= y)
+	{
+	  struct glyph *g = r->glyphs[TEXT_AREA];
+	  struct glyph *end = g + r->used[TEXT_AREA];
+	  int gx = r->x;
+	  while (g < end && gx < x)
+	    gx += g->pixel_width, ++g;
+	  if (g < end)
+	    {
+	      rect->width = g->pixel_width;
+	      rect->height = r->height;
+	      rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx);
+	      rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
+	      return 1;
+	    }
+	  break;
+	}
+    }
+
+  return 0;
 }
 
 
@@ -5657,6 +5632,11 @@
 static int temp_index;
 static short temp_buffer[100];
 
+#define STORE_KEYSYM_FOR_DEBUG(keysym)				\
+  if (temp_index == sizeof temp_buffer / sizeof (short))	\
+    temp_index = 0;						\
+  temp_buffer[temp_index++] = (keysym)
+
 /* Set this to nonzero to fake an "X I/O error"
    on a particular display.  */
 
@@ -5676,15 +5656,8 @@
            f->output_data.x->saved_menu_event				\
 	     = (XEvent *) xmalloc (sizeof (XEvent));			\
          bcopy (&event, f->output_data.x->saved_menu_event, size);	\
-         if (numchars >= 1)						\
-           {								\
-             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);				\
        }								\
      while (0)
 
@@ -5726,14 +5699,13 @@
 #endif
 
 #ifdef USE_GTK
-static struct input_event **current_bufp;
-static int *current_numcharsp;
 static int current_count;
 static int current_finish;
+static struct input_event *current_hold_quit;
 
 /* This is the filter function invoked by the GTK event loop.
    It is invoked before the XEvent is translated to a GdkEvent,
-   so we have a chanse to act on the event before GTK. */
+   so we have a chance to act on the event before GTK. */
 static GdkFilterReturn
 event_handler_gdk (gxev, ev, data)
      GdkXEvent *gxev;
@@ -5742,7 +5714,7 @@
 {
   XEvent *xev = (XEvent *) gxev;
 
-  if (current_numcharsp)
+  if (current_count >= 0)
     {
       struct x_display_info *dpyinfo;
 
@@ -5760,11 +5732,11 @@
       if (! dpyinfo)
         current_finish = X_EVENT_NORMAL;
       else
-        current_count += handle_one_xevent (dpyinfo,
-                                            xev,
-                                            current_bufp,
-                                            current_numcharsp,
-                                            &current_finish);
+	{
+	  current_count +=
+	    handle_one_xevent (dpyinfo, xev, &current_finish, 
+			       current_hold_quit);
+	}
     }
   else
     current_finish = x_dispatch_event (xev, xev->xany.display);
@@ -5783,28 +5755,29 @@
    *FINISH is zero if caller should continue reading events.
    *FINISH is X_EVENT_DROP if event should not be passed to the toolkit.
 
-   Events representing keys are stored in buffer *BUFP_R,
-   which can hold up to *NUMCHARSP characters.
    We return the number of characters stored into the buffer. */
 
 static int
-handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
+handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
      struct x_display_info *dpyinfo;
      XEvent *eventp;
-     /* register */ struct input_event **bufp_r;
-     /* register */ int *numcharsp;
      int *finish;
-{
+     struct input_event *hold_quit;
+{
+  struct input_event inev;
   int count = 0;
+  int do_help = 0;
   int nbytes = 0;
   struct frame *f;
   struct coding_system coding;
-  struct input_event *bufp = *bufp_r;
-  int numchars = *numcharsp;
   XEvent event = *eventp;
 
   *finish = X_EVENT_NORMAL;
 
+  EVENT_INIT (inev);
+  inev.kind = NO_EVENT;
+  inev.arg = Qnil;
+
   switch (event.type)
     {
     case ClientMessage:
@@ -5859,8 +5832,10 @@
                   }
                 /* Not certain about handling scroll bars here */
 #endif /* 0 */
+		goto done;
               }
-            else if (event.xclient.data.l[0]
+
+            if (event.xclient.data.l[0]
                      == dpyinfo->Xatom_wm_save_yourself)
               {
                 /* Save state modify the WM_COMMAND property to
@@ -5871,11 +5846,9 @@
                 /* If we have a session manager, don't set this.
                    KDE will then start two Emacsen, one for the
                    session manager and one for this. */
-                if (numchars > 0
 #ifdef HAVE_X_SM
-                    && ! x_session_have_connection ()
-#endif
-                    )
+                if (! x_session_have_connection ())
+#endif
                   {
                     f = x_top_window_to_frame (dpyinfo,
                                                event.xclient.window);
@@ -5890,41 +5863,36 @@
                                    event.xclient.window,
                                    0, 0);
                   }
+		goto done;
               }
-            else if (event.xclient.data.l[0]
-                     == dpyinfo->Xatom_wm_delete_window)
+
+            if (event.xclient.data.l[0]
+		== dpyinfo->Xatom_wm_delete_window)
               {
-                struct frame *f
-                  = x_any_window_to_frame (dpyinfo,
+                f = x_any_window_to_frame (dpyinfo,
                                            event.xclient.window);
-
-                if (f)
-                  {
-                    if (numchars == 0)
-                      abort ();
-
-                    bufp->kind = DELETE_WINDOW_EVENT;
-                    XSETFRAME (bufp->frame_or_window, f);
-                    bufp->arg = Qnil;
-                    bufp++;
-
-                    count += 1;
-                    numchars -= 1;
-                  }
-                else
-                  goto OTHER; /* May be a dialog that is to be removed  */
+                if (!f)
+		  goto OTHER; /* May be a dialog that is to be removed  */
+
+		inev.kind = DELETE_WINDOW_EVENT;
+		XSETFRAME (inev.frame_or_window, f);
+		goto done;
               }
+
+	    goto done;
           }
-        else if (event.xclient.message_type
+
+        if (event.xclient.message_type
                  == dpyinfo->Xatom_wm_configure_denied)
           {
+	    goto done;
           }
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_wm_window_moved)
+
+        if (event.xclient.message_type
+	    == dpyinfo->Xatom_wm_window_moved)
           {
             int new_x, new_y;
-            struct frame *f
-              = x_window_to_frame (dpyinfo, event.xclient.window);
+	    f = x_window_to_frame (dpyinfo, event.xclient.window);
 
             new_x = event.xclient.data.s[0];
             new_y = event.xclient.data.s[1];
@@ -5934,63 +5902,55 @@
                 f->left_pos = new_x;
                 f->top_pos = new_y;
               }
+	    goto done;
           }
+
 #ifdef HACK_EDITRES
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_editres)
+        if (event.xclient.message_type
+	    == dpyinfo->Xatom_editres)
           {
-            struct frame *f
-              = x_any_window_to_frame (dpyinfo, event.xclient.window);
+	    f = x_any_window_to_frame (dpyinfo, event.xclient.window);
             _XEditResCheckMessages (f->output_data.x->widget, NULL,
                                     &event, NULL);
+	    goto done;
           }
 #endif /* HACK_EDITRES */
-        else if ((event.xclient.message_type
-                  == dpyinfo->Xatom_DONE)
-                 || (event.xclient.message_type
-                     == dpyinfo->Xatom_PAGE))
+
+        if ((event.xclient.message_type
+	     == dpyinfo->Xatom_DONE)
+	    || (event.xclient.message_type
+		== dpyinfo->Xatom_PAGE))
           {
             /* Ghostview job completed.  Kill it.  We could
                reply with "Next" if we received "Page", but we
                currently never do because we are interested in
                images, only, which should have 1 page.  */
             Pixmap pixmap = (Pixmap) event.xclient.data.l[1];
-            struct frame *f
-              = x_window_to_frame (dpyinfo, event.xclient.window);
+	    f = x_window_to_frame (dpyinfo, event.xclient.window);
             x_kill_gs_process (pixmap, f);
             expose_frame (f, 0, 0, 0, 0);
+	    goto done;
           }
+
 #ifdef USE_TOOLKIT_SCROLL_BARS
         /* Scroll bar callbacks send a ClientMessage from which
            we construct an input_event.  */
-        else if (event.xclient.message_type
-                 == dpyinfo->Xatom_Scrollbar)
+        if (event.xclient.message_type
+	    == dpyinfo->Xatom_Scrollbar)
           {
-            x_scroll_bar_to_input_event (&event, bufp);
-            ++bufp, ++count, --numchars;
-            goto out;
+            x_scroll_bar_to_input_event (&event, &inev);
+	    *finish = X_EVENT_GOTO_OUT;
+            goto done;
           }
 #endif /* USE_TOOLKIT_SCROLL_BARS */
-        else
-          {
-            struct frame *f
-              = x_any_window_to_frame (dpyinfo, event.xclient.window);
-
-            if (f)
-              {
-                int ret = x_handle_dnd_message (f, &event.xclient,
-                                                dpyinfo, bufp);
-                if (ret > 0)
-                  {
-                    ++bufp, ++count, --numchars;
-                  }
-
-                if (ret != 0)
-                  *finish = X_EVENT_DROP;
-              }
-            else
-              goto OTHER;
-          }
+
+	f = x_any_window_to_frame (dpyinfo, event.xclient.window);
+
+	if (!f)
+	  goto OTHER;
+
+	if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev))
+	  *finish = X_EVENT_DROP;
       }
       break;
 
@@ -6010,19 +5970,11 @@
       {
         XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event;
 
-        if (numchars == 0)
-          abort ();
-
-        bufp->kind = SELECTION_CLEAR_EVENT;
-        SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-        SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-        SELECTION_EVENT_TIME (bufp) = eventp->time;
-        bufp->frame_or_window = Qnil;
-        bufp->arg = Qnil;
-        bufp++;
-
-        count += 1;
-        numchars -= 1;
+        inev.kind = SELECTION_CLEAR_EVENT;
+        SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
+        SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
+        SELECTION_EVENT_TIME (&inev) = eventp->time;
+        inev.frame_or_window = Qnil;
       }
       break;
 
@@ -6039,22 +5991,14 @@
           XSelectionRequestEvent *eventp
             = (XSelectionRequestEvent *) &event;
 
-          if (numchars == 0)
-            abort ();
-
-          bufp->kind = SELECTION_REQUEST_EVENT;
-          SELECTION_EVENT_DISPLAY (bufp) = eventp->display;
-          SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor;
-          SELECTION_EVENT_SELECTION (bufp) = eventp->selection;
-          SELECTION_EVENT_TARGET (bufp) = eventp->target;
-          SELECTION_EVENT_PROPERTY (bufp) = eventp->property;
-          SELECTION_EVENT_TIME (bufp) = eventp->time;
-          bufp->frame_or_window = Qnil;
-          bufp->arg = Qnil;
-          bufp++;
-
-          count += 1;
-          numchars -= 1;
+          inev.kind = SELECTION_REQUEST_EVENT;
+          SELECTION_EVENT_DISPLAY (&inev) = eventp->display;
+          SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor;
+          SELECTION_EVENT_SELECTION (&inev) = eventp->selection;
+          SELECTION_EVENT_TARGET (&inev) = eventp->target;
+          SELECTION_EVENT_PROPERTY (&inev) = eventp->property;
+          SELECTION_EVENT_TIME (&inev) = eventp->time;
+          inev.frame_or_window = Qnil;
         }
       break;
 
@@ -6084,7 +6028,6 @@
           FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
         }
       goto OTHER;
-      break;
 
     case Expose:
       f = x_window_to_frame (dpyinfo, event.xexpose.window);
@@ -6186,12 +6129,8 @@
             {
               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);
             }
         }
       goto OTHER;
@@ -6223,12 +6162,8 @@
 
           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)))
@@ -6289,6 +6224,7 @@
           int copy_bufsiz = sizeof (copy_buffer);
           int modifiers;
           Lisp_Object coding_system = Qlatin_1;
+	  Lisp_Object c;
 
           event.xkey.state
             |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f),
@@ -6382,49 +6318,37 @@
 
           orig_keysym = keysym;
 
-          if (numchars > 0)
-            {
-              Lisp_Object c;
-
-              /* First deal with keysyms which have defined
-                 translations to characters.  */
-              if (keysym >= 32 && keysym < 128)
-                /* Avoid explicitly decoding each ASCII character.  */
-                {
-                  bufp->kind = ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Now non-ASCII.  */
-              else if (HASH_TABLE_P (Vx_keysym_table)
-                       && (NATNUMP (c = Fgethash (make_number (keysym),
-                                                  Vx_keysym_table,
-                                                  Qnil))))
-                {
-                  bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
-                                ? ASCII_KEYSTROKE_EVENT
-                                : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                  bufp->code = XFASTINT (c);
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              /* Random non-modifier sorts of keysyms.  */
-              else if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
+ 	  /* Common for all keysym input events.  */
+ 	  XSETFRAME (inev.frame_or_window, f);
+ 	  inev.modifiers
+ 	    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers);
+ 	  inev.timestamp = event.xkey.time;
+
+ 	  /* First deal with keysyms which have defined
+ 	     translations to characters.  */
+ 	  if (keysym >= 32 && keysym < 128)
+ 	    /* Avoid explicitly decoding each ASCII character.  */
+ 	    {
+ 	      inev.kind = ASCII_KEYSTROKE_EVENT;
+ 	      inev.code = keysym;
+ 	      goto done_keysym;
+ 	    }
+ 
+ 	  /* Now non-ASCII.  */
+ 	  if (HASH_TABLE_P (Vx_keysym_table)
+ 	      && (NATNUMP (c = Fgethash (make_number (keysym),
+ 					 Vx_keysym_table,
+ 					 Qnil))))
+ 	    {
+ 	      inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c))
+ 			    ? ASCII_KEYSTROKE_EVENT
+ 			    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+ 	      inev.code = XFASTINT (c);
+ 	      goto done_keysym;
+ 	    }
+ 
+ 	  /* Random non-modifier sorts of keysyms.  */
+ 	  if (((keysym >= XK_BackSpace && keysym <= XK_Escape)
                         || keysym == XK_Delete
 #ifdef XK_ISO_Left_Tab
                         || (keysym >= XK_ISO_Left_Tab
@@ -6505,104 +6429,80 @@
                                  <= XK_ISO_Last_Group_Lock)
 #endif
                              ))
-                {
-                  if (temp_index == sizeof temp_buffer / sizeof (short))
-                    temp_index = 0;
-                  temp_buffer[temp_index++] = keysym;
-                  /* make_lispy_event will convert this to a symbolic
-                     key.  */
-                  bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-                  bufp->code = keysym;
-                  XSETFRAME (bufp->frame_or_window, f);
-                  bufp->arg = Qnil;
-                  bufp->modifiers
-                    = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                              modifiers);
-                  bufp->timestamp = event.xkey.time;
-                  bufp++;
-                  count++;
-                  numchars--;
-                }
-              else if (numchars > nbytes)
-                {	/* Raw bytes, not keysym.  */
-                  register int i;
-                  register int c;
-                  int nchars, len;
-
-                  /* The input should be decoded with `coding_system'
-                     which depends on which X*LookupString function
-                     we used just above and the locale.  */
-                  setup_coding_system (coding_system, &coding);
-                  coding.src_multibyte = 0;
-                  coding.dst_multibyte = 1;
-                  /* The input is converted to events, thus we can't
-                     handle composition.  Anyway, there's no XIM that
-                     gives us composition information.  */
-                  coding.composing = COMPOSITION_DISABLED;
-
-                  for (i = 0; i < nbytes; i++)
-                    {
-                      if (temp_index == (sizeof temp_buffer
-                                         / sizeof (short)))
-                        temp_index = 0;
-                      temp_buffer[temp_index++] = copy_bufptr[i];
-                    }
-
-                  {
-                    /* Decode the input data.  */
-                    int require;
-                    unsigned char *p;
-
-                    require = decoding_buffer_size (&coding, nbytes);
-                    p = (unsigned char *) alloca (require);
-                    coding.mode |= CODING_MODE_LAST_BLOCK;
-                    /* We explicitly disable composition
-                       handling because key data should
-                       not contain any composition
-                       sequence.  */
-                    coding.composing = COMPOSITION_DISABLED;
-                    decode_coding (&coding, copy_bufptr, p,
-                                   nbytes, require);
-                    nbytes = coding.produced;
-                    nchars = coding.produced_char;
-                    copy_bufptr = p;
-                  }
-
-                  /* Convert the input data to a sequence of
-                     character events.  */
-                  for (i = 0; i < nbytes; i += len)
-                    {
-                      if (nchars == nbytes)
-                        c = copy_bufptr[i], len = 1;
-                      else
-                        c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
-                                                    nbytes - i, len);
-
-                      bufp->kind = (SINGLE_BYTE_CHAR_P (c)
-                                    ? ASCII_KEYSTROKE_EVENT
-                                    : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
-                      bufp->code = c;
-                      XSETFRAME (bufp->frame_or_window, f);
-                      bufp->arg = Qnil;
-                      bufp->modifiers
-                        = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f),
-                                                  modifiers);
-                      bufp->timestamp = event.xkey.time;
-                      bufp++;
-                    }
-
-                  count += nchars;
-                  numchars -= nchars;
-
-                  if (keysym == NoSymbol)
-                    break;
-                }
-              else
-                abort ();
-            }
-          else
-            abort ();
+	    {
+	      STORE_KEYSYM_FOR_DEBUG (keysym);
+	      /* make_lispy_event will convert this to a symbolic
+		 key.  */
+	      inev.kind = NON_ASCII_KEYSTROKE_EVENT;
+	      inev.code = keysym;
+	      goto done_keysym;
+	    }
+
+	  {	/* Raw bytes, not keysym.  */
+	    register int i;
+	    register int c;
+	    int nchars, len;
+
+	    /* The input should be decoded with `coding_system'
+	       which depends on which X*LookupString function
+	       we used just above and the locale.  */
+	    setup_coding_system (coding_system, &coding);
+	    coding.src_multibyte = 0;
+	    coding.dst_multibyte = 1;
+	    /* The input is converted to events, thus we can't
+	       handle composition.  Anyway, there's no XIM that
+	       gives us composition information.  */
+	    coding.composing = COMPOSITION_DISABLED;
+
+	    for (i = 0; i < nbytes; i++)
+	      {
+		STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
+	      }
+
+	    {
+	      /* Decode the input data.  */
+	      int require;
+	      unsigned char *p;
+
+	      require = decoding_buffer_size (&coding, nbytes);
+	      p = (unsigned char *) alloca (require);
+	      coding.mode |= CODING_MODE_LAST_BLOCK;
+	      /* We explicitly disable composition handling because
+		 key data should not contain any composition sequence.  */
+	      coding.composing = COMPOSITION_DISABLED;
+	      decode_coding (&coding, copy_bufptr, p, nbytes, require);
+	      nbytes = coding.produced;
+	      nchars = coding.produced_char;
+	      copy_bufptr = p;
+	    }
+
+	    /* Convert the input data to a sequence of
+	       character events.  */
+	    for (i = 0; i < nbytes; i += len)
+	      {
+		if (nchars == nbytes)
+		  c = copy_bufptr[i], len = 1;
+		else
+		  c = STRING_CHAR_AND_LENGTH (copy_bufptr + i,
+					      nbytes - i, len);
+		inev.kind = (SINGLE_BYTE_CHAR_P (c)
+			      ? ASCII_KEYSTROKE_EVENT
+			      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+		inev.code = c;
+		kbd_buffer_store_event_hold (&inev, hold_quit);
+	      }
+
+	    /* Previous code updated count by nchars rather than nbytes,
+	       but that seems bogus to me.  ++kfs  */
+	    count += nbytes;
+
+	    inev.kind = NO_EVENT;  /* Already stored above.  */
+
+	    if (keysym == NoSymbol)
+	      break;
+	  }
         }
+    done_keysym:
 #ifdef HAVE_X_I18N
       /* Don't dispatch this event since XtDispatchEvent calls
          XFilterEvent, and two calls in a row may freeze the
@@ -6623,63 +6523,38 @@
 #endif
 
     case EnterNotify:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-
-        f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
+      x_detect_focus_change (dpyinfo, &event, &inev);
+
+      f = x_any_window_to_frame (dpyinfo, event.xcrossing.window);
 
 #if 0
-        if (event.xcrossing.focus)
-          {
-            /* Avoid nasty pop/raise loops.  */
-            if (f && (!(f->auto_raise)
-                      || !(f->auto_lower)
-                      || (event.xcrossing.time - enter_timestamp) > 500))
-              {
-                x_new_focus_frame (dpyinfo, f);
-                enter_timestamp = event.xcrossing.time;
-              }
-          }
-        else if (f == dpyinfo->x_focus_frame)
-          x_new_focus_frame (dpyinfo, 0);
-#endif
-
-        /* EnterNotify counts as mouse movement,
-           so update things that depend on mouse position.  */
-        if (f && !f->output_data.x->hourglass_p)
-          note_mouse_movement (f, &event.xmotion);
-        goto OTHER;
-      }
+      if (event.xcrossing.focus)
+	{
+	  /* Avoid nasty pop/raise loops.  */
+	  if (f && (!(f->auto_raise)
+		    || !(f->auto_lower)
+		    || (event.xcrossing.time - enter_timestamp) > 500))
+	    {
+	      x_new_focus_frame (dpyinfo, f);
+	      enter_timestamp = event.xcrossing.time;
+	    }
+	}
+      else if (f == dpyinfo->x_focus_frame)
+	x_new_focus_frame (dpyinfo, 0);
+#endif
+
+      /* EnterNotify counts as mouse movement,
+	 so update things that depend on mouse position.  */
+      if (f && !f->output_data.x->hourglass_p)
+	note_mouse_movement (f, &event.xmotion);
+      goto OTHER;
 
     case FocusIn:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
+      x_detect_focus_change (dpyinfo, &event, &inev);
       goto OTHER;
 
     case LeaveNotify:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
+      x_detect_focus_change (dpyinfo, &event, &inev);
 
       f = x_top_window_to_frame (dpyinfo, event.xcrossing.window);
       if (f)
@@ -6697,31 +6572,12 @@
              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;
         }
       goto OTHER;
 
     case FocusOut:
-      {
-        int n;
-
-        n = x_detect_focus_change (dpyinfo, &event, bufp, numchars);
-        if (n > 0)
-          {
-            bufp += n, count += n, numchars -= n;
-          }
-      }
-
+      x_detect_focus_change (dpyinfo, &event, &inev);
       goto OTHER;
 
     case MotionNotify:
@@ -6759,13 +6615,10 @@
                    will be selected 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;
@@ -6792,22 +6645,7 @@
            has changed, generate a HELP_EVENT.  */
         if (!NILP (help_echo_string)
             || !NILP (previous_help_echo_string))
-          {
-            Lisp_Object frame;
-            int n;
-
-            if (f)
-              XSETFRAME (frame, f);
-            else
-              frame = Qnil;
-
-            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;
-          }
-
+	  do_help = 1;
         goto OTHER;
       }
 
@@ -6891,10 +6729,8 @@
       {
         /* 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;
 
-        emacs_event.kind = NO_EVENT;
         bzero (&compose_status, sizeof (compose_status));
 
         if (dpyinfo->grabbed
@@ -6934,7 +6770,7 @@
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
                   if (! popup_activated ())
 #endif
-                    construct_mouse_click (&emacs_event, &event, f);
+                    construct_mouse_click (&inev, &event, f);
                 }
           }
         else
@@ -6948,12 +6784,12 @@
                scroll bars.  */
             if (bar && event.xbutton.state & ControlMask)
               {
-                x_scroll_bar_handle_click (bar, &event, &emacs_event);
+                x_scroll_bar_handle_click (bar, &event, &inev);
                 *finish = X_EVENT_DROP;
               }
 #else /* not USE_TOOLKIT_SCROLL_BARS */
             if (bar)
-              x_scroll_bar_handle_click (bar, &event, &emacs_event);
+              x_scroll_bar_handle_click (bar, &event, &inev);
 #endif /* not USE_TOOLKIT_SCROLL_BARS */
           }
 
@@ -6974,14 +6810,6 @@
         else
           dpyinfo->grabbed &= ~(1 << event.xbutton.button);
 
-        if (numchars >= 1 && emacs_event.kind != NO_EVENT)
-          {
-            bcopy (&emacs_event, bufp, sizeof (struct input_event));
-            bufp++;
-            count++;
-            numchars--;
-          }
-
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
         f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window);
         /* For a down-event in the menu bar,
@@ -7068,16 +6896,38 @@
     break;
     }
 
-  goto ret;
-
- out:
-  *finish = X_EVENT_GOTO_OUT;
-
- ret:
-  *bufp_r = bufp;
-  *numcharsp = numchars;
+ done:
+  if (inev.kind != NO_EVENT)
+    {
+      kbd_buffer_store_event_hold (&inev, hold_quit);
+      count++;
+    }
+
+  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)
+	{
+	  any_help_event_p = 1;
+	  gen_help_event (help_echo_string, frame, help_echo_window,
+			  help_echo_object, help_echo_pos);
+	} 
+      else
+	{
+	  help_echo_string = Qnil;
+	  gen_help_event (Qnil, frame, Qnil, Qnil, 0);
+	}
+      count++;
+    }
+
   *eventp = event;
-
   return count;
 }
 
@@ -7093,28 +6943,12 @@
      Display *display;
 {
   struct x_display_info *dpyinfo;
-  struct input_event bufp[10];
-  struct input_event *bufpp;
-  int numchars = 10;
   int finish = X_EVENT_NORMAL;
 
-  for (bufpp = bufp; bufpp != bufp + 10; bufpp++)
-    EVENT_INIT (*bufpp);
-  bufpp = bufp;
-
   dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
-    {
-      int i, events;
-      events = handle_one_xevent (dpyinfo,
-                                  event,
-                                  &bufpp,
-                                  &numchars,
-                                  &finish);
-      for (i = 0; i < events; ++i)
-        kbd_buffer_store_event (&bufp[i]);
-    }
+    handle_one_xevent (dpyinfo, event, &finish, 0);
 
   return finish;
 }
@@ -7124,19 +6958,16 @@
    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'.
 
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (display, bufp, numchars, expected)
+XTread_socket (display, expected, hold_quit)
      struct display *display;
-     struct input_event *bufp;
-     int numchars;
      int expected;
+     struct input_event *hold_quit;
 {
   int count = 0;
   XEvent event;
@@ -7155,9 +6986,6 @@
   /* So people can tell when we have read the available input.  */
   input_signal_count++;
 
-  if (numchars <= 0)
-    abort ();			/* Don't think this happens.  */
-
   ++handling_signal;
 
   /* Find the display we are supposed to read input for.
@@ -7199,13 +7027,22 @@
 	}
 
 #ifdef HAVE_X_SM
-      BLOCK_INPUT;
-      count += x_session_check_input (bufp, &numchars);
-      UNBLOCK_INPUT;
+      {
+	struct input_event inev;
+	BLOCK_INPUT;
+	/* We don't need to EVENT_INIT (inev) here, as
+	   x_session_check_input copies an entire input_event.  */
+	if (x_session_check_input (&inev))
+	  {
+	    kbd_buffer_store_event_hold (&inev, hold_quit);
+	    count++;
+	  }
+	UNBLOCK_INPUT;
+      }
 #endif
 
 #ifndef USE_GTK
-      while (numchars > 0 && XPending (dpyinfo->display))
+      while (XPending (dpyinfo->display))
 	{
           int finish;
 
@@ -7218,11 +7055,7 @@
 #endif
 	  event_found = 1;
 
-          count += handle_one_xevent (dpyinfo,
-                                      &event,
-                                      &bufp,
-                                      &numchars,
-                                      &finish);
+          count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit);
 
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
@@ -7243,14 +7076,13 @@
   while (gtk_events_pending ())
     {
       current_count = count;
-      current_numcharsp = &numchars;
-      current_bufp = &bufp;
+      current_hold_quit = hold_quit;
 
       gtk_main_iteration ();
 
       count = current_count;
-      current_bufp = 0;
-      current_numcharsp = 0;
+      current_count = -1;
+      current_hold_quit = 0;
 
       if (current_finish == X_EVENT_GOTO_OUT)
         break;
@@ -7290,8 +7122,9 @@
       pending_autoraise_frame = 0;
     }
 
+  --handling_signal;
   UNBLOCK_INPUT;
-  --handling_signal;
+
   return count;
 }
 
@@ -11000,6 +10833,10 @@
   last_tool_bar_item = -1;
   any_help_event_p = 0;
 
+#ifdef USE_GTK
+  current_count = -1;
+#endif
+
   /* Try to use interrupt input; if we can't, then start polling.  */
   Fset_input_mode (Qt, Qnil, Qt, Qnil);
 
--- a/src/xterm.h	Sat Feb 28 01:33:17 2004 +0000
+++ b/src/xterm.h	Sat Feb 28 04:52:40 2004 +0000
@@ -1089,8 +1089,7 @@
 /* Defined in xsmfns.c */
 #ifdef HAVE_X_SM
 extern void x_session_initialize P_ ((struct x_display_info *dpyinfo));
-extern int x_session_check_input P_ ((struct input_event *bufp,
-                                      int *numchars));
+extern int x_session_check_input P_ ((struct input_event *bufp));
 extern int x_session_have_connection P_ ((void));
 #endif