changeset 108056:9bc5da284bcf

Merge from mainline.
author Katsumi Yamaoka <yamaoka@jpl.org>
date Tue, 20 Apr 2010 22:45:12 +0000
parents 9247fef2ee7f (current diff) 734b50109edf (diff)
children 92bb32f41a3a
files
diffstat 32 files changed, 1767 insertions(+), 1199 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Mon Apr 19 22:46:02 2010 +0000
+++ b/lisp/ChangeLog	Tue Apr 20 22:45:12 2010 +0000
@@ -1,3 +1,15 @@
+2010-04-20  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* vc-dispatcher.el (vc-finish-logentry): Don't mess so badly with the
+	windows/frames.
+
+	* emacs-lisp/lisp.el (lisp-completion-at-point): Complete around point.
+	I.e. include text after point in the completion region.
+	Also, return nil when we're not after/in a symbol.
+
+	* international/mule-cmds.el (view-hello-file): Don't fiddle with the
+	default enable-multibyte-characters.
+
 2010-04-19  Stefan Monnier  <monnier@iro.umontreal.ca>
 
 	* international/mule.el: Help the user choose a valid coding-system.
--- a/lisp/emacs-lisp/lisp.el	Mon Apr 19 22:46:02 2010 +0000
+++ b/lisp/emacs-lisp/lisp.el	Tue Apr 20 22:45:12 2010 +0000
@@ -631,12 +631,11 @@
 
 (defun lisp-completion-at-point (&optional predicate)
   ;; FIXME: the `end' could be after point?
-  (let* ((end (point))
+  (let* ((pos (point))
          (beg (with-syntax-table emacs-lisp-mode-syntax-table
                 (save-excursion
                   (backward-sexp 1)
-                  (while (= (char-syntax (following-char)) ?\')
-                    (forward-char 1))
+                  (skip-syntax-forward "'")
                   (point))))
          (predicate
           (or predicate
@@ -656,12 +655,21 @@
                       ;; Maybe a `let' varlist or something.
                       nil
                     ;; Else, we assume that a function name is expected.
-                    'fboundp))))))
-    (list beg end obarray
-          :predicate predicate
-          :annotate-function
+                    'fboundp)))))
+         (end
+          (unless (or (eq beg (point-max))
+                      (member (char-syntax (char-after beg)) '(?\( ?\))))
+            (save-excursion
+              (goto-char beg)
+              (forward-sexp 1)
+              (when (>= (point) pos)
+                (point))))))
+    (when end
+      (list beg end obarray
+            :predicate predicate
+            :annotate-function
             (unless (eq predicate 'fboundp)
-              (lambda (str) (if (fboundp (intern-soft str)) " <f>"))))))
+              (lambda (str) (if (fboundp (intern-soft str)) " <f>")))))))
 
 ;; arch-tag: aa7fa8a4-2e6f-4e9b-9cd9-fef06340e67e
 ;;; lisp.el ends here
--- a/lisp/international/mule-cmds.el	Mon Apr 19 22:46:02 2010 +0000
+++ b/lisp/international/mule-cmds.el	Tue Apr 20 22:45:12 2010 +0000
@@ -286,8 +286,7 @@
   "Display the HELLO file, which lists many languages and characters."
   (interactive)
   ;; We have to decode the file in any environment.
-  (letf (((default-value 'enable-multibyte-characters) t)
-	 (coding-system-for-read 'iso-2022-7bit))
+  (letf ((coding-system-for-read 'iso-2022-7bit))
 	(view-file (expand-file-name "HELLO" data-directory))))
 
 (defun universal-coding-system-argument (coding-system)
--- a/lisp/vc-dispatcher.el	Mon Apr 19 22:46:02 2010 +0000
+++ b/lisp/vc-dispatcher.el	Tue Apr 20 22:45:12 2010 +0000
@@ -599,8 +599,7 @@
 	(log-extra vc-log-extra)
 	(log-entry (buffer-string))
 	(extra-flags log-edit-extra-flags)
-	(after-hook vc-log-after-operation-hook)
-	(tmp-vc-parent-buffer vc-parent-buffer))
+	(after-hook vc-log-after-operation-hook))
     (pop-to-buffer vc-parent-buffer)
     ;; OK, do it to it
     (save-excursion
@@ -617,9 +616,11 @@
 	   (delete-windows-on logbuf (selected-frame))
 	   ;; Kill buffer and delete any other dedicated windows/frames.
 	   (kill-buffer logbuf))
-	  (logbuf (pop-to-buffer logbuf)
-		  (bury-buffer)
-		  (pop-to-buffer tmp-vc-parent-buffer)))
+	  (logbuf
+           (with-selected-window (or (get-buffer-window logbuf 0)
+                                     (selected-window))
+             (with-current-buffer logbuf
+               (bury-buffer)))))
     ;; Now make sure we see the expanded headers
     (when log-fileset
       (mapc
--- a/nt/ChangeLog	Mon Apr 19 22:46:02 2010 +0000
+++ b/nt/ChangeLog	Tue Apr 20 22:45:12 2010 +0000
@@ -1,3 +1,7 @@
+2010-04-20  Lewis Perin  <perin@panix.com>  (tiny change)
+
+	* emacs.manifest: Add trustInfo section to Windows manifest.
+
 2010-03-10  Chong Yidong  <cyd@stupidchicken.com>
 
 	* Branch for 23.2.
--- a/nt/emacs.manifest	Mon Apr 19 22:46:02 2010 +0000
+++ b/nt/emacs.manifest	Tue Apr 20 22:45:12 2010 +0000
@@ -8,4 +8,14 @@
                         language="*"/>
     </dependentAssembly>
   </dependency>
-</assembly>
\ No newline at end of file
+  <assemblyIdentity version="1.0.0.0" processorArchitecture="X86"
+		    name="emacs" type="win32"/>
+  <description>GNU Emacs</description>
+  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
+    <security>
+      <requestedPrivileges>
+        <requestedExecutionLevel level="asInvoker"/>
+      </requestedPrivileges>
+    </security>
+  </trustInfo>
+</assembly>
--- a/src/ChangeLog	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/ChangeLog	Tue Apr 20 22:45:12 2010 +0000
@@ -1,9 +1,169 @@
+2010-04-20  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	* data.c (Fmake_variable_buffer_local, Fmake_local_variable):
+	Just signal a warning rather than an error when inside a let.
+	(Fmake_variable_frame_local): Add the same test.
+
+	* font.c (syms_of_font): Make the style table vars read-only.
+
+	* buffer.h (struct buffer): Remove unused var `direction_reversed'.
+	* buffer.c (init_buffer_once, syms_of_buffer): Remove its initialization.
+
+	* bidi.c (bidi_initialize): Simplify fallback_paragraph_*_re init.
+
+2010-04-20  Eli Zaretskii  <eliz@gnu.org>
+
+	Fix R2L paragraph display on TTY.
+
+	* xdisp.c (unproduce_glyphs): New function.
+	(display_line): Use it when produced glyphs are discarded from R2L
+	glyph rows.
+	(append_composite_glyph): In R2L rows, prepend the glyph rather
+	than appending it.
+
+	* term.c (append_composite_glyph): In R2L rows, prepend the glyph
+	rather than append it.  Set up the resolved_level and bidi_type
+	attributes of the appended glyph.
+	(produce_special_glyphs): Mirror the backslash continuation
+	character in R2L lines.
+
+	Implement display of R2L paragraphs in GUI sessions.
+
+	* xdisp.c [HAVE_WINDOW_SYSTEM]: Add prototype for
+	append_stretch_glyph.
+	(set_cursor_from_row) <cursor_x>: Remove unused variable.  Fix
+	off-by-one error in computing x at end of text in the row.
+	(append_stretch_glyph): In reversed row, prepend the glyph rather
+	than append it.  Set resolved_level and bidi_type of the glyph.
+	(extend_face_to_end_of_line): If the row is reversed, prepend a
+	stretch glyph whose width is such that the rightmost glyph will be
+	drawn at the right margin of the window.  Fix off-by-one error on
+	TTY frames in testing whether a line needs face extension.  Fix
+	face extension at ZV.  If this is the last glyph row, use
+	DEFAULT_FACE_ID, to avoid painting the rest of the window with the
+	region face.
+	(set_cursor_from_row, display_line): Use
+	MATRIX_ROW_CONTINUATION_LINE_P instead of testing value of
+	row->continuation_lines_width.
+	(next_element_from_buffer): Don't call bidi_paragraph_init if we
+	are at ZV.  Fixes a crash when reseated to ZV by
+	try_window_reusing_current_matrix.
+	(display_and_set_cursor, erase_phys_cursor): Handle negative HPOS,
+	which happens with R2L glyph rows.  Fixes a crash when inserting a
+	character at end of an R2L line.
+	(set_cursor_from_row): Don't be fooled by truncated rows: don't
+	treat them as having zero-width characters.  Improve comments.
+	Don't reverse pos_before and pos_after for reversed glyph rows.
+	Set cursor.x to negative value when the cursor might be on the
+	left fringe.
+	(IT_OVERFLOW_NEWLINE_INTO_FRINGE): For R2L lines, consider the
+	left fringe, not the right one.
+	(notice_overwritten_cursor, draw_phys_cursor_glyph)
+	(erase_phys_cursor): For reversed cursor_row, support cursor on
+	the left fringe.
+
+	* fringe.c (update_window_fringes): For R2L rows, swap the bitmaps
+	of continuation indicators on the fringes.
+	(draw_fringe_bitmap): For reversed glyph rows, allow cursor on the
+	left fringe.
+
+	* w32term.c (w32_draw_window_cursor): For reversed glyph rows,
+	draw cursor on the left fringe.
+
+	* xterm.c (x_draw_window_cursor): For reversed glyph rows, draw
+	cursor on the left fringe.
+
+	* dispnew.c (update_text_area): Handle reversed desired rows when
+	the cursor is on the left fringe.
+	(set_window_cursor_after_update): Limit cursor's hpos by -1 from
+	below, not by 0, for when the cursor is on the left fringe.
+
+2010-04-20  Jan Djärv  <jan.h.d@swipnet.se>
+
+	* gtkutil.c (xg_event_is_for_scrollbar): Check if grabbed
+	widget is a scrollbar.
+
+2010-04-20  Kenichi Handa  <handa@m17n.org>
+
+	* charset.c (char_charset): Consider Vcharset_non_preferred_head
+	only when the arg CHARSET_LIST is nil.
+
+2010-04-20  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+	Make variable forwarding explicit rather the using special values.
+	Basically, this makes the structure of buffer-local values and object
+	forwarding explicit in the type of Lisp_Symbols rather than use
+	special Lisp_Objects for that.  This tends to lead to slightly more
+	verbose code, but is more C-like, simpler, and makes it easier to make
+	sure we handled all cases, among other things by letting the compiler
+	help us check it.
+	* lisp.h (enum Lisp_Misc_Type, union Lisp_Misc):
+	Removing forwarding objects.
+	(enum Lisp_Fwd_Type, enum symbol_redirect, union Lisp_Fwd): New types.
+	(struct Lisp_Symbol): Make the various forms of variable-forwarding
+	explicit rather than hiding them inside Lisp_Object "values".
+	(XFWDTYPE): New macro.
+	(XINTFWD, XBOOLFWD, XOBJFWD, XKBOARD_OBJFWD): Redefine.
+	(XBUFFER_LOCAL_VALUE): Remove.
+	(SYMBOL_VAL, SYMBOL_ALIAS, SYMBOL_BLV, SYMBOL_FWD, SET_SYMBOL_VAL)
+	(SET_SYMBOL_ALIAS, SET_SYMBOL_BLV, SET_SYMBOL_FWD): New macros.
+	(SYMBOL_VALUE, SET_SYMBOL_VALUE): Remove.
+	(struct Lisp_Intfwd, struct Lisp_Boolfwd, struct Lisp_Objfwd)
+	(struct Lisp_Buffer_Objfwd, struct Lisp_Kboard_Objfwd):
+	Remove the Lisp_Misc_* header.
+	(struct Lisp_Buffer_Local_Value): Redefine.
+	(BLV_FOUND, SET_BLV_FOUND, BLV_VALUE, SET_BLV_VALUE): New macros.
+	(struct Lisp_Misc_Any): Add filler to get the right size.
+	(struct Lisp_Free): Use struct Lisp_Misc_Any rather than struct
+	Lisp_Intfwd.
+	(DEFVAR_LISP, DEFVAR_LISP_NOPRO, DEFVAR_BOOL, DEFVAR_INT)
+	(DEFVAR_KBOARD): Allocate a forwarding object.
+	* data.c (do_blv_forwarding, store_blv_forwarding): New macros.
+	(let_shadows_global_binding_p): New function.
+	(union Lisp_Val_Fwd): New type.
+	(make_blv): New function.
+	(swap_in_symval_forwarding, indirect_variable, do_symval_forwarding)
+	(store_symval_forwarding, swap_in_global_binding, Fboundp)
+	(swap_in_symval_forwarding, find_symbol_value, Fset)
+	(let_shadows_buffer_binding_p, set_internal, default_value)
+	(Fset_default, Fmake_variable_buffer_local, Fmake_local_variable)
+	(Fkill_local_variable, Fmake_variable_frame_local)
+	(Flocal_variable_p, Flocal_variable_if_set_p)
+	(Fvariable_binding_locus):
+	* xdisp.c (select_frame_for_redisplay):
+	* lread.c (Fintern, Funintern, init_obarray, defvar_int)
+	(defvar_bool, defvar_lisp_nopro, defvar_lisp, defvar_kboard):
+	* frame.c (store_frame_param):
+	* eval.c (Fdefvaralias, Fuser_variable_p, specbind, unbind_to):
+	* bytecode.c (Fbyte_code) <varref, varset>: Adapt to the new symbol
+	value structure.
+	* buffer.c (PER_BUFFER_SYMBOL): Move from buffer.h.
+	(clone_per_buffer_values): Only adjust markers into the current buffer.
+	(reset_buffer_local_variables): PER_BUFFER_IDX is never -2.
+	(Fbuffer_local_value, set_buffer_internal_1)
+	(swap_out_buffer_local_variables):
+	Adapt to the new symbol value structure.
+	(DEFVAR_PER_BUFFER): Allocate a Lisp_Buffer_Objfwd object.
+	(defvar_per_buffer): Take a new arg for the fwd object.
+	(buffer_lisp_local_variables): Return a proper alist (different fix
+	for bug#4138).
+	* alloc.c (Fmake_symbol): Use SET_SYMBOL_VAL.
+	(Fgarbage_collect): Don't handle buffer_defaults specially.
+	(mark_object): Handle new symbol value structure rather than the old
+	special Lisp_Misc_* objects.
+	(gc_sweep) <symbols>: Free also the buffer-local-value objects.
+	* term.c (set_tty_color_mode):
+	* bidi.c (bidi_initialize): Don't access the ->value field directly.
+	* buffer.h (PER_BUFFER_VAR_OFFSET): Don't bother with
+	a buffer_local_flags.
+	* print.c (print_object): Get rid of impossible forwarding objects.
+
 2010-04-19  Eli Zaretskii  <eliz@gnu.org>
 
 	* bidi.c (bidi_get_type, bidi_get_category)
 	(bidi_at_paragraph_end, bidi_resolve_weak, bidi_resolve_neutral)
-	(bidi_type_of_next_char, bidi_level_of_next_char): Declare
-	static.  Use `INLINE' rather than `inline'.
+	(bidi_type_of_next_char, bidi_level_of_next_char):
+	Declare static.  Use `INLINE' rather than `inline'.
 
 2010-04-19  Juanma Barranquero  <lekktu@gmail.com>
 
@@ -40,6 +200,8 @@
 
 	* .gdbinit (xsubchartable): New command.
 
+2010-04-19  Eli Zaretskii  <eliz@gnu.org>
+
 	* xdisp.c (display_line): Don't write beyond the last glyph row in
 	the desired matrix.  Fixes a crash in "emacs -nw" (bug#5972), see
 	http://lists.gnu.org/archive/html/emacs-devel/2010-04/msg00075.html
--- a/src/alloc.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/alloc.c	Tue Apr 20 22:45:12 2010 +0000
@@ -1365,7 +1365,7 @@
   pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
   pthread_mutex_init (&alloc_mutex, &attr);
 #else  /* !DOUG_LEA_MALLOC */
-  /* Some systems such as Solaris 2.6 doesn't have a recursive mutex,
+  /* Some systems such as Solaris 2.6 don't have a recursive mutex,
      and the bundled gmalloc.c doesn't require it.  */
   pthread_mutex_init (&alloc_mutex, NULL);
 #endif /* !DOUG_LEA_MALLOC */
@@ -3193,13 +3193,13 @@
   p = XSYMBOL (val);
   p->xname = name;
   p->plist = Qnil;
-  p->value = Qunbound;
+  p->redirect = SYMBOL_PLAINVAL;
+  SET_SYMBOL_VAL (p, Qunbound);
   p->function = Qunbound;
   p->next = NULL;
   p->gcmarkbit = 0;
   p->interned = SYMBOL_UNINTERNED;
   p->constant = 0;
-  p->indirect_variable = 0;
   consing_since_gc += sizeof (struct Lisp_Symbol);
   symbols_consed++;
   return val;
@@ -5581,17 +5581,42 @@
 	  break;
 	CHECK_ALLOCATED_AND_LIVE (live_symbol_p);
 	ptr->gcmarkbit = 1;
-	mark_object (ptr->value);
 	mark_object (ptr->function);
 	mark_object (ptr->plist);
-
+	switch (ptr->redirect)
+	  {
+	  case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break;
+	  case SYMBOL_VARALIAS:
+	    {
+	      Lisp_Object tem;
+	      XSETSYMBOL (tem, SYMBOL_ALIAS (ptr));
+	      mark_object (tem);
+	      break;
+	    }
+	  case SYMBOL_LOCALIZED:
+	    {
+	      struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr);
+	      /* If the value is forwarded to a buffer or keyboard field,
+		 these are marked when we see the corresponding object.
+		 And if it's forwarded to a C variable, either it's not
+		 a Lisp_Object var, or it's staticpro'd already.  */
+	      mark_object (blv->where);
+	      mark_object (blv->valcell);
+	      mark_object (blv->defcell);
+	      break;
+	    }
+	  case SYMBOL_FORWARDED:
+	    /* If the value is forwarded to a buffer or keyboard field,
+	       these are marked when we see the corresponding object.
+	       And if it's forwarded to a C variable, either it's not
+	       a Lisp_Object var, or it's staticpro'd already.  */
+	    break;
+	  default: abort ();
+	  }
 	if (!PURE_POINTER_P (XSTRING (ptr->xname)))
 	  MARK_STRING (XSTRING (ptr->xname));
 	MARK_INTERVAL_TREE (STRING_INTERVALS (ptr->xname));
 
-	/* Note that we do not mark the obarray of the symbol.
-	   It is safe not to do so because nothing accesses that
-	   slot except to check whether it is nil.  */
 	ptr = ptr->next;
 	if (ptr)
 	  {
@@ -5610,22 +5635,6 @@
 
       switch (XMISCTYPE (obj))
 	{
-	case Lisp_Misc_Buffer_Local_Value:
-	  {
-	    register struct Lisp_Buffer_Local_Value *ptr
-	      = XBUFFER_LOCAL_VALUE (obj);
-	    /* If the cdr is nil, avoid recursion for the car.  */
-	    if (EQ (ptr->cdr, Qnil))
-	      {
-		obj = ptr->realvalue;
-		goto loop;
-	      }
-	    mark_object (ptr->realvalue);
-	    mark_object (ptr->buffer);
-	    mark_object (ptr->frame);
-	    obj = ptr->cdr;
-	    goto loop;
-	  }
 
 	case Lisp_Misc_Marker:
 	  /* DO NOT mark thru the marker's chain.
@@ -5633,17 +5642,6 @@
 	     instead, markers are removed from the chain when freed by gc.  */
 	  break;
 
-	case Lisp_Misc_Intfwd:
-	case Lisp_Misc_Boolfwd:
-	case Lisp_Misc_Objfwd:
-	case Lisp_Misc_Buffer_Objfwd:
-	case Lisp_Misc_Kboard_Objfwd:
-	  /* Don't bother with Lisp_Buffer_Objfwd,
-	     since all markable slots in current buffer marked anyway.  */
-	  /* Don't need to do Lisp_Objfwd, since the places they point
-	     are protected with staticpro.  */
-	  break;
-
 	case Lisp_Misc_Save_Value:
 #if GC_MARK_STACK
 	  {
@@ -6048,6 +6046,8 @@
 
 	    if (!sym->gcmarkbit && !pure_p)
 	      {
+		if (sym->redirect == SYMBOL_LOCALIZED)
+		  xfree (SYMBOL_BLV (sym));
 		sym->next = symbol_free_list;
 		symbol_free_list = sym;
 #if GC_MARK_STACK
--- a/src/bidi.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/bidi.c	Tue Apr 20 22:45:12 2010 +0000
@@ -399,20 +399,18 @@
 			  bidi_type[i].to ? bidi_type[i].to : bidi_type[i].from,
 			  make_number (bidi_type[i].type));
 
-  fallback_paragraph_start_re =
-    XSYMBOL (Fintern_soft (build_string ("paragraph-start"), Qnil))->value;
+  Qparagraph_start = intern ("paragraph-start");
+  staticpro (&Qparagraph_start);
+  fallback_paragraph_start_re = Fsymbol_value (Qparagraph_start);
   if (!STRINGP (fallback_paragraph_start_re))
     fallback_paragraph_start_re = build_string ("\f\\|[ \t]*$");
   staticpro (&fallback_paragraph_start_re);
-  Qparagraph_start = intern ("paragraph-start");
-  staticpro (&Qparagraph_start);
-  fallback_paragraph_separate_re =
-    XSYMBOL (Fintern_soft (build_string ("paragraph-separate"), Qnil))->value;
+  Qparagraph_separate = intern ("paragraph-separate");
+  staticpro (&Qparagraph_separate);
+  fallback_paragraph_separate_re = Fsymbol_value (Qparagraph_separate);
   if (!STRINGP (fallback_paragraph_separate_re))
     fallback_paragraph_separate_re = build_string ("[ \t\f]*$");
   staticpro (&fallback_paragraph_separate_re);
-  Qparagraph_separate = intern ("paragraph-separate");
-  staticpro (&Qparagraph_separate);
   bidi_initialized = 1;
 }
 
@@ -752,6 +750,7 @@
 static EMACS_INT
 bidi_at_paragraph_end (EMACS_INT charpos, EMACS_INT bytepos)
 {
+  /* FIXME: Why Fbuffer_local_value rather than just Fsymbol_value?  */
   Lisp_Object sep_re = Fbuffer_local_value (Qparagraph_separate,
 					    Fcurrent_buffer ());
   Lisp_Object start_re = Fbuffer_local_value (Qparagraph_start,
@@ -830,6 +829,7 @@
 static EMACS_INT
 bidi_find_paragraph_start (EMACS_INT pos, EMACS_INT pos_byte)
 {
+  /* FIXME: Why Fbuffer_local_value rather than just Fsymbol_value?  */
   Lisp_Object re = Fbuffer_local_value (Qparagraph_start, Fcurrent_buffer ());
   EMACS_INT limit = ZV, limit_byte = ZV_BYTE;
 
@@ -879,7 +879,6 @@
       int ch, ch_len;
       EMACS_INT pos;
       bidi_type_t type;
-      EMACS_INT sep_len;
 
       /* If we are inside a paragraph separator, we are just waiting
 	 for the separator to be exhausted; use the previous paragraph
--- a/src/buffer.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/buffer.c	Tue Apr 20 22:45:12 2010 +0000
@@ -78,9 +78,6 @@
    be a DEFVAR_PER_BUFFER for the slot, there is no default value for it;
    and the corresponding slot in buffer_defaults is not used.
 
-   If a slot is -2, then there is no DEFVAR_PER_BUFFER for it,
-   but there is a default value which is copied into each buffer.
-
    If a slot in this structure corresponding to a DEFVAR_PER_BUFFER is
    zero, that is a bug */
 
@@ -94,6 +91,12 @@
 /* A Lisp_Object pointer to the above, used for staticpro */
 static Lisp_Object Vbuffer_local_symbols;
 
+/* Return the symbol of the per-buffer variable at offset OFFSET in
+   the buffer structure.  */
+
+#define PER_BUFFER_SYMBOL(OFFSET) \
+      (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_symbols))
+
 /* Flags indicating which built-in buffer-local variables
    are permanent locals.  */
 static char buffer_permanent_local_flags[MAX_PER_BUFFER_VARS];
@@ -507,7 +510,7 @@
 	continue;
 
       obj = PER_BUFFER_VALUE (from, offset);
-      if (MARKERP (obj))
+      if (MARKERP (obj) && XMARKER (obj)->buffer == from)
 	{
 	  struct Lisp_Marker *m = XMARKER (obj);
 	  obj = Fmake_marker ();
@@ -770,9 +773,7 @@
     {
       Lisp_Object tmp, prop, last = Qnil;
       for (tmp = b->local_var_alist; CONSP (tmp); tmp = XCDR (tmp))
-	if (CONSP (XCAR (tmp))
-	    && SYMBOLP (XCAR (XCAR (tmp)))
-	    && !NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
+	if (!NILP (prop = Fget (XCAR (XCAR (tmp)), Qpermanent_local)))
 	  {
 	    /* If permanent-local, keep it.  */
 	    last = tmp;
@@ -822,9 +823,7 @@
       int idx = PER_BUFFER_IDX (offset);
       if ((idx > 0
 	   && (permanent_too
-	       || buffer_permanent_local_flags[idx] == 0))
-	  /* Is -2 used anywhere?  */
-	  || idx == -2)
+	       || buffer_permanent_local_flags[idx] == 0)))
 	PER_BUFFER_VALUE (b, offset) = PER_BUFFER_DEFAULT (offset);
     }
 }
@@ -938,59 +937,49 @@
   CHECK_SYMBOL (variable);
   CHECK_BUFFER (buffer);
   buf = XBUFFER (buffer);
-
-  sym = indirect_variable (XSYMBOL (variable));
-  XSETSYMBOL (variable, sym);
-
-  /* Look in local_var_list */
-  result = Fassoc (variable, buf->local_var_alist);
-  if (NILP (result))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      int offset, idx;
-      int found = 0;
-
-      /* Look in special slots */
-      /* buffer-local Lisp variables start at `undo_list',
-	 tho only the ones from `name' on are GC'd normally.  */
-      for (offset = PER_BUFFER_VAR_OFFSET (undo_list);
-	   offset < sizeof (struct buffer);
-	   /* sizeof EMACS_INT == sizeof Lisp_Object */
-	   offset += (sizeof (EMACS_INT)))
-	{
-	  idx = PER_BUFFER_IDX (offset);
-	  if ((idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
-	      && SYMBOLP (PER_BUFFER_SYMBOL (offset))
-	      && EQ (PER_BUFFER_SYMBOL (offset), variable))
-	    {
-	      result = PER_BUFFER_VALUE (buf, offset);
-	      found = 1;
-	      break;
-	    }
-	}
-
-      if (!found)
-	result = Fdefault_value (variable);
-    }
-  else
-    {
-      Lisp_Object valcontents;
-      Lisp_Object current_alist_element;
-
-      /* What binding is loaded right now?  */
-      valcontents = sym->value;
-      current_alist_element
-	= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-
-      /* The value of the currently loaded binding is not
-	 stored in it, but rather in the realvalue slot.
-	 Store that value into the binding it belongs to
-	 in case that is the one we are about to use.  */
-
-      Fsetcdr (current_alist_element,
-	       do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
-
-      /* Now get the (perhaps updated) value out of the binding.  */
-      result = XCDR (result);
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: result = SYMBOL_VAL (sym); break;
+    case SYMBOL_LOCALIZED:
+      { /* Look in local_var_alist.  */
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	XSETSYMBOL (variable, sym); /* Update In case of aliasing.  */
+	result = Fassoc (variable, buf->local_var_alist);
+	if (!NILP (result))
+	  {
+	    if (blv->fwd)
+	      { /* What binding is loaded right now?  */
+		Lisp_Object current_alist_element = blv->valcell;
+
+		/* The value of the currently loaded binding is not
+		   stored in it, but rather in the realvalue slot.
+		   Store that value into the binding it belongs to
+		   in case that is the one we are about to use.  */
+
+		XSETCDR (current_alist_element,
+			 do_symval_forwarding (blv->fwd));
+	      }
+	    /* Now get the (perhaps updated) value out of the binding.  */
+	    result = XCDR (result);
+	  }
+	else
+	  result = Fdefault_value (variable);
+	break;
+      }
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *fwd = SYMBOL_FWD (sym);
+	if (BUFFER_OBJFWDP (fwd))
+	  result = PER_BUFFER_VALUE (buf, XBUFFER_OBJFWD (fwd)->offset);
+	else
+	  result = Fdefault_value (variable);
+	break;
+      }
+    default: abort ();
     }
 
   if (!EQ (result, Qunbound))
@@ -1025,12 +1014,7 @@
       if (buf != current_buffer)
 	val = XCDR (elt);
 
-      /* If symbol is unbound, put just the symbol in the list.  */
-      if (EQ (val, Qunbound))
-	result = Fcons (XCAR (elt), result);
-      /* Otherwise, put (symbol . value) in the list.  */
-      else
-	result = Fcons (Fcons (XCAR (elt), val), result);
+      result = Fcons (Fcons (XCAR (elt), val), result);
     }
 
   return result;
@@ -1862,8 +1846,7 @@
      register struct buffer *b;
 {
   register struct buffer *old_buf;
-  register Lisp_Object tail, valcontents;
-  Lisp_Object tem;
+  register Lisp_Object tail;
 
 #ifdef USE_MMAP_FOR_BUFFERS
   if (b->text->beg == NULL)
@@ -1935,34 +1918,21 @@
   /* Look down buffer's list of local Lisp variables
      to find and update any that forward into C variables. */
 
-  for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
+  do
     {
-      if (CONSP (XCAR (tail))
-	  && SYMBOLP (XCAR (XCAR (tail)))
-	  && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))),
-	      (BUFFER_LOCAL_VALUEP (valcontents)))
-	  && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
-	      (BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
-	/* Just reference the variable to cause it to become set for
-	   this buffer.  */
-	Fsymbol_value (XCAR (XCAR (tail)));
+      for (tail = b->local_var_alist; CONSP (tail); tail = XCDR (tail))
+	{
+	  Lisp_Object var = XCAR (XCAR (tail));
+	  struct Lisp_Symbol *sym = XSYMBOL (var);
+	  if (sym->redirect == SYMBOL_LOCALIZED /* Just to be sure.  */
+	      && SYMBOL_BLV (sym)->fwd)
+	    /* Just reference the variable
+	       to cause it to become set for this buffer.  */
+	    Fsymbol_value (var);
+	}
     }
-
   /* Do the same with any others that were local to the previous buffer */
-
-  if (old_buf)
-    for (tail = old_buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
-      {
-	if (CONSP (tail)
-	    && SYMBOLP (XCAR (XCAR (tail)))
-	    && (valcontents = SYMBOL_VALUE (XCAR (XCAR (tail))),
-		(BUFFER_LOCAL_VALUEP (valcontents)))
-	    && (tem = XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
-		(BOOLFWDP (tem) || INTFWDP (tem) || OBJFWDP (tem))))
-	  /* Just reference the variable to cause it to become set for
-	     this buffer.  */
-	  Fsymbol_value (XCAR (XCAR (tail)));
-      }
+  while (b != old_buf && (b = old_buf, b));
 }
 
 /* Switch to buffer B temporarily for redisplay purposes.
@@ -2677,23 +2647,22 @@
 swap_out_buffer_local_variables (b)
      struct buffer *b;
 {
-  Lisp_Object oalist, alist, sym, buffer;
+  Lisp_Object oalist, alist, buffer;
 
   XSETBUFFER (buffer, b);
   oalist = b->local_var_alist;
 
   for (alist = oalist; CONSP (alist); alist = XCDR (alist))
     {
-      if (CONSP (XCAR (alist))
-	  && (sym = XCAR (XCAR (alist)), SYMBOLP (sym))
-	  /* Need not do anything if some other buffer's binding is
-	     now encached.  */
-	  && EQ (XBUFFER_LOCAL_VALUE (SYMBOL_VALUE (sym))->buffer,
-		 buffer))
+      Lisp_Object sym = XCAR (XCAR (alist));
+      eassert (XSYMBOL (sym)->redirect == SYMBOL_LOCALIZED);
+      /* Need not do anything if some other buffer's binding is
+	 now encached.  */
+      if (EQ (SYMBOL_BLV (XSYMBOL (sym))->where, buffer))
 	{
 	  /* Symbol is set up for this buffer's old local value:
 	     swap it out!  */
-	  swap_in_global_binding (sym);
+	  swap_in_global_binding (XSYMBOL (sym));
 	}
     }
 }
@@ -5162,7 +5131,9 @@
   /* Make sure all markable slots in buffer_defaults
      are initialized reasonably, so mark_buffer won't choke.  */
   reset_buffer (&buffer_defaults);
+  eassert (EQ (buffer_defaults.name, make_number (0)));
   reset_buffer_local_variables (&buffer_defaults, 1);
+  eassert (EQ (buffer_local_symbols.name, make_number (0)));
   reset_buffer (&buffer_local_symbols);
   reset_buffer_local_variables (&buffer_local_symbols, 1);
   /* Prevent GC from getting confused.  */
@@ -5204,7 +5175,6 @@
   buffer_defaults.word_wrap = Qnil;
   buffer_defaults.ctl_arrow = Qt;
   buffer_defaults.bidi_display_reordering = Qnil;
-  buffer_defaults.direction_reversed = Qnil;
   buffer_defaults.bidi_paragraph_direction = Qnil;
   buffer_defaults.cursor_type = Qt;
   buffer_defaults.extra_line_spacing = Qnil;
@@ -5291,7 +5261,6 @@
   XSETFASTINT (buffer_local_flags.cache_long_line_scans, idx); ++idx;
   XSETFASTINT (buffer_local_flags.category_table, idx); ++idx;
   XSETFASTINT (buffer_local_flags.bidi_display_reordering, idx); ++idx;
-  XSETFASTINT (buffer_local_flags.direction_reversed, idx); ++idx;
   XSETFASTINT (buffer_local_flags.bidi_paragraph_direction, idx); ++idx;
   XSETFASTINT (buffer_local_flags.buffer_file_coding_system, idx);
   /* Make this one a permanent local.  */
@@ -5421,33 +5390,41 @@
    in the buffer that is current now. */
 
 /* TYPE is nil for a general Lisp variable.
-   An integer specifies a type; then only LIsp values
+   An integer specifies a type; then only Lisp values
    with that type code are allowed (except that nil is allowed too).
-   LNAME is the LIsp-level variable name.
+   LNAME is the Lisp-level variable name.
    VNAME is the name of the buffer slot.
    DOC is a dummy where you write the doc string as a comment.  */
-#define DEFVAR_PER_BUFFER(lname, vname, type, doc)  \
- defvar_per_buffer (lname, vname, type, 0)
+#define DEFVAR_PER_BUFFER(lname, vname, type, doc)			\
+  do {									\
+    static struct Lisp_Buffer_Objfwd bo_fwd;				\
+    defvar_per_buffer (&bo_fwd, lname, vname, type, 0);			\
+  } while (0)
 
 static void
-defvar_per_buffer (namestring, address, type, doc)
+defvar_per_buffer (bo_fwd, namestring, address, type, doc)
+     struct Lisp_Buffer_Objfwd *bo_fwd;
      char *namestring;
      Lisp_Object *address;
      Lisp_Object type;
      char *doc;
 {
-  Lisp_Object sym, val;
+  struct Lisp_Symbol *sym;
   int offset;
 
-  sym = intern (namestring);
-  val = allocate_misc ();
+  sym = XSYMBOL (intern (namestring));
   offset = (char *)address - (char *)current_buffer;
 
-  XMISCTYPE (val) = Lisp_Misc_Buffer_Objfwd;
-  XBUFFER_OBJFWD (val)->offset = offset;
-  XBUFFER_OBJFWD (val)->slottype = type;
-  SET_SYMBOL_VALUE (sym, val);
-  PER_BUFFER_SYMBOL (offset) = sym;
+  bo_fwd->type = Lisp_Fwd_Buffer_Obj;
+  bo_fwd->offset = offset;
+  bo_fwd->slottype = type;
+  sym->redirect = SYMBOL_FORWARDED;
+  {
+    /* I tried to do the job without a cast, but it seems impossible.
+       union Lisp_Fwd *fwd; &(fwd->u_buffer_objfwd) = bo_fwd;  */
+    SET_SYMBOL_FWD (sym, (union Lisp_Fwd *)bo_fwd);
+  }
+  XSETSYMBOL (PER_BUFFER_SYMBOL (offset), sym);
 
   if (PER_BUFFER_IDX (offset) == 0)
     /* Did a DEFVAR_PER_BUFFER without initializing the corresponding
@@ -5805,11 +5782,6 @@
 
 This variable is never applied to a way of decoding a file while reading it.  */);
 
-  DEFVAR_PER_BUFFER ("direction-reversed",
-		     &current_buffer->direction_reversed, Qnil,
-		     doc: /* Non-nil means set beginning of lines at the right edge of the window.
-See also the variable `bidi-display-reordering'.  */);
-
   DEFVAR_PER_BUFFER ("bidi-display-reordering",
 		     &current_buffer->bidi_display_reordering, Qnil,
 		     doc: /* Non-nil means reorder bidirectional text for display in the visual order.
@@ -5818,12 +5790,12 @@
   DEFVAR_PER_BUFFER ("bidi-paragraph-direction",
 		     &current_buffer->bidi_paragraph_direction, Qnil,
 		     doc: /* *If non-nil, forces directionality of text paragraphs in the buffer.
-			     
+
 If this is nil (the default), the direction of each paragraph is
 determined by the first strong directional character of its text.
 The values of `right-to-left' and `left-to-right' override that.
 Any other value is treated as nil.
-			     
+
 This variable has no effect unless the buffer's value of
 \`bidi-display-reordering' is non-nil.  */);
 
--- a/src/buffer.h	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/buffer.h	Tue Apr 20 22:45:12 2010 +0000
@@ -107,6 +107,11 @@
 #define BUF_BEG(buf) (BEG)
 #define BUF_BEG_BYTE(buf) (BEG_BYTE)
 
+/* !!!FIXME:  all the BUF_BEGV/BUF_ZV/BUF_PT macros are flawed:
+   on indirect (or base) buffers, that value is only correct if that buffer
+   is the current_buffer, or if the buffer's text hasn't been modified (via
+   an indirect buffer) since it was last current.  */
+
 /* Position of beginning of accessible range of buffer.  */
 #define BUF_BEGV(buf) ((buf)->begv)
 #define BUF_BEGV_BYTE(buf) ((buf)->begv_byte)
@@ -313,7 +318,7 @@
  - (ptr - (current_buffer)->text->beg <= (unsigned) (GPT_BYTE - BEG_BYTE) ? 0 : GAP_SIZE) \
  + BEG_BYTE)
 
-/* Return character at position POS.  */
+/* Return character at byte position POS.  */
 
 #define FETCH_CHAR(pos)				      	\
   (!NILP (current_buffer->enable_multibyte_characters)	\
@@ -327,7 +332,7 @@
 /* Variables used locally in FETCH_MULTIBYTE_CHAR.  */
 extern unsigned char *_fetch_multibyte_char_p;
 
-/* Return character code of multi-byte form at position POS.  If POS
+/* Return character code of multi-byte form at byte position POS.  If POS
    doesn't point the head of valid multi-byte form, only the byte at
    POS is returned.  No range checking.  */
 
@@ -336,7 +341,7 @@
 			       + (pos) + BEG_ADDR - BEG_BYTE),	 	\
    STRING_CHAR (_fetch_multibyte_char_p))
 
-/* Return character at position POS.  If the current buffer is unibyte
+/* Return character at byte position POS.  If the current buffer is unibyte
    and the character is not ASCII, make the returning character
    multibyte.  */
 
@@ -447,7 +452,10 @@
     /* The markers that refer to this buffer.
        This is actually a single marker ---
        successive elements in its marker `chain'
-       are the other markers referring to this buffer.  */
+       are the other markers referring to this buffer.
+       This is a singly linked unordered list, which means that it's
+       very cheap to add a marker to the list and it's also very cheap
+       to move a marker within a buffer.  */
     struct Lisp_Marker *markers;
 
     /* Usually 0.  Temporarily set to 1 in decode_coding_gap to
@@ -671,9 +679,6 @@
   /* Non-nil means reorder bidirectional text for display in the
      visual order.  */
   Lisp_Object bidi_display_reordering;
-  /* Non-nil means set beginning of lines at the right edge of
-     windows.  */
-  Lisp_Object direction_reversed;
   /* If non-nil, specifies which direction of text to force in all the
      paragraphs of the buffer.  Nil means determine paragraph
      direction dynamically for each paragraph.  */
@@ -843,6 +848,7 @@
    be a Lisp-level local variable for the slot, it has no default value,
    and the corresponding slot in buffer_defaults is not used.  */
 
+
 extern struct buffer buffer_local_flags;
 
 /* For each buffer slot, this points to the Lisp symbol name
@@ -948,7 +954,7 @@
    from the start of a buffer structure.  */
 
 #define PER_BUFFER_VAR_OFFSET(VAR) \
-    ((char *) &buffer_local_flags.VAR - (char *) &buffer_local_flags)
+  ((char *) &((struct buffer *)0)->VAR - (char *) ((struct buffer *)0))
 
 /* Return the index of buffer-local variable VAR.  Each per-buffer
    variable has an index > 0 associated with it, except when it always
@@ -1013,11 +1019,5 @@
 #define PER_BUFFER_VALUE(BUFFER, OFFSET) \
       (*(Lisp_Object *)((OFFSET) + (char *) (BUFFER)))
 
-/* Return the symbol of the per-buffer variable at offset OFFSET in
-   the buffer structure.  */
-
-#define PER_BUFFER_SYMBOL(OFFSET) \
-      (*(Lisp_Object *)((OFFSET) + (char *) &buffer_local_symbols))
-
 /* arch-tag: 679305dd-d41c-4a50-b170-3caf5c97b2d1
    (do not change this comment) */
--- a/src/bytecode.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/bytecode.c	Tue Apr 20 22:45:12 2010 +0000
@@ -505,8 +505,9 @@
 	    v1 = vectorp[op];
 	    if (SYMBOLP (v1))
 	      {
-		v2 = SYMBOL_VALUE (v1);
-		if (MISCP (v2) || EQ (v2, Qunbound))
+		if (XSYMBOL (v1)->redirect != SYMBOL_PLAINVAL
+		    || (v2 = SYMBOL_VAL (XSYMBOL (v1)),
+			EQ (v2, Qunbound)))
 		  {
 		    BEFORE_POTENTIAL_GC ();
 		    v2 = Fsymbol_value (v1);
@@ -597,10 +598,9 @@
 	    /* Inline the most common case.  */
 	    if (SYMBOLP (sym)
 		&& !EQ (val, Qunbound)
-		&& !XSYMBOL (sym)->indirect_variable
-		&& !SYMBOL_CONSTANT_P (sym)
-		&& !MISCP (XSYMBOL (sym)->value))
-	      XSYMBOL (sym)->value = val;
+		&& !XSYMBOL (sym)->redirect
+		&& !SYMBOL_CONSTANT_P (sym))
+	      XSYMBOL (sym)->val.value = val;
 	    else
 	      {
 		BEFORE_POTENTIAL_GC ();
--- a/src/character.h	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/character.h	Tue Apr 20 22:45:12 2010 +0000
@@ -296,7 +296,7 @@
 
 /* If P is after LIMIT, advance P to the previous character boundary.
    Assumes that P is already at a character boundary of the same
-   mulitbyte form whose beginning address is LIMIT.  */
+   multibyte form whose beginning address is LIMIT.  */
 
 #define PREV_CHAR_BOUNDARY(p, limit)					\
   do {									\
--- a/src/charset.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/charset.c	Tue Apr 20 22:45:12 2010 +0000
@@ -2082,8 +2082,9 @@
 	  return charset;
 	}
       charset_list = XCDR (charset_list);
-      if (c <= MAX_UNICODE_CHAR
-	 && EQ (charset_list, Vcharset_non_preferred_head))
+      if (! maybe_null
+	  && c <= MAX_UNICODE_CHAR
+	  && EQ (charset_list, Vcharset_non_preferred_head))
 	return CHARSET_FROM_ID (charset_unicode);
     }
   return (maybe_null ? NULL
--- a/src/coding.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/coding.c	Tue Apr 20 22:45:12 2010 +0000
@@ -6408,7 +6408,7 @@
 			{
 			  /* We didn't find an 8-bit code.  We may
 			     have found a null-byte, but it's very
-			     rare that a binary file confirm to
+			     rare that a binary file conforms to
 			     ISO-2022.  */
 			  src = src_end;
 			  coding->head_ascii = src - coding->source;
--- a/src/data.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/data.c	Tue Apr 20 22:45:12 2010 +0000
@@ -91,7 +91,7 @@
 
 Lisp_Object Qinteractive_form;
 
-static Lisp_Object swap_in_symval_forwarding P_ ((Lisp_Object, Lisp_Object));
+static void swap_in_symval_forwarding (struct Lisp_Symbol *, struct Lisp_Buffer_Local_Value *);
 
 Lisp_Object Vmost_positive_fixnum, Vmost_negative_fixnum;
 
@@ -582,12 +582,35 @@
      register Lisp_Object symbol;
 {
   Lisp_Object valcontents;
+  struct Lisp_Symbol *sym;
   CHECK_SYMBOL (symbol);
-
-  valcontents = SYMBOL_VALUE (symbol);
-
-  if (BUFFER_LOCAL_VALUEP (valcontents))
-    valcontents = swap_in_symval_forwarding (symbol, valcontents);
+  sym = XSYMBOL (symbol);
+
+ start:
+  switch (sym->redirect)
+    {
+    case SYMBOL_PLAINVAL: valcontents = SYMBOL_VAL (sym); break;
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_LOCALIZED:
+      {
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	if (blv->fwd)
+	  /* In set_internal, we un-forward vars when their value is
+    	     set to Qunbound. */
+    	  return Qt;
+	else
+	  {
+	    swap_in_symval_forwarding (sym, blv);
+	    valcontents = BLV_VALUE (blv);
+	  }
+	break;
+      }
+    case SYMBOL_FORWARDED:
+      /* In set_internal, we un-forward vars when their value is
+	 set to Qunbound. */
+      return Qt;
+    default: abort ();
+    }
 
   return (EQ (valcontents, Qunbound) ? Qnil : Qt);
 }
@@ -824,14 +847,14 @@
 
   hare = tortoise = symbol;
 
-  while (hare->indirect_variable)
+  while (hare->redirect == SYMBOL_VARALIAS)
     {
-      hare = XSYMBOL (hare->value);
-      if (!hare->indirect_variable)
+      hare = SYMBOL_ALIAS (hare);
+      if (hare->redirect != SYMBOL_VARALIAS)
 	break;
 
-      hare = XSYMBOL (hare->value);
-      tortoise = XSYMBOL (tortoise->value);
+      hare = SYMBOL_ALIAS (hare);
+      tortoise = SYMBOL_ALIAS (tortoise);
 
       if (hare == tortoise)
 	{
@@ -865,44 +888,46 @@
    This does not handle buffer-local variables; use
    swap_in_symval_forwarding for that.  */
 
+#define do_blv_forwarding(blv) \
+  ((blv)->forwarded ? do_symval_forwarding (BLV_FWD (blv)) : BLV_VALUE (blv))
+
 Lisp_Object
 do_symval_forwarding (valcontents)
-     register Lisp_Object valcontents;
+     register union Lisp_Fwd *valcontents;
 {
   register Lisp_Object val;
-  if (MISCP (valcontents))
-    switch (XMISCTYPE (valcontents))
-      {
-      case Lisp_Misc_Intfwd:
-	XSETINT (val, *XINTFWD (valcontents)->intvar);
-	return val;
-
-      case Lisp_Misc_Boolfwd:
-	return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
-
-      case Lisp_Misc_Objfwd:
-	return *XOBJFWD (valcontents)->objvar;
-
-      case Lisp_Misc_Buffer_Objfwd:
-	return PER_BUFFER_VALUE (current_buffer,
-				 XBUFFER_OBJFWD (valcontents)->offset);
-
-      case Lisp_Misc_Kboard_Objfwd:
-        /* We used to simply use current_kboard here, but from Lisp
-           code, it's value is often unexpected.  It seems nicer to
-           allow constructions like this to work as intuitively expected:
-
-           	(with-selected-frame frame
-                   (define-key local-function-map "\eOP" [f1]))
-
-           On the other hand, this affects the semantics of
-           last-command and real-last-command, and people may rely on
-           that.  I took a quick look at the Lisp codebase, and I
-           don't think anything will break.  --lorentey  */
-	return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
-				+ (char *)FRAME_KBOARD (SELECTED_FRAME ()));
-      }
-  return valcontents;
+  switch (XFWDTYPE (valcontents))
+    {
+    case Lisp_Fwd_Int:
+      XSETINT (val, *XINTFWD (valcontents)->intvar);
+      return val;
+
+    case Lisp_Fwd_Bool:
+      return (*XBOOLFWD (valcontents)->boolvar ? Qt : Qnil);
+
+    case Lisp_Fwd_Obj:
+      return *XOBJFWD (valcontents)->objvar;
+
+    case Lisp_Fwd_Buffer_Obj:
+      return PER_BUFFER_VALUE (current_buffer,
+			       XBUFFER_OBJFWD (valcontents)->offset);
+
+    case Lisp_Fwd_Kboard_Obj:
+      /* We used to simply use current_kboard here, but from Lisp
+	 code, it's value is often unexpected.  It seems nicer to
+	 allow constructions like this to work as intuitively expected:
+
+	 (with-selected-frame frame
+	 (define-key local-function-map "\eOP" [f1]))
+
+	 On the other hand, this affects the semantics of
+	 last-command and real-last-command, and people may rely on
+	 that.  I took a quick look at the Lisp codebase, and I
+	 don't think anything will break.  --lorentey  */
+      return *(Lisp_Object *)(XKBOARD_OBJFWD (valcontents)->offset
+			      + (char *)FRAME_KBOARD (SELECTED_FRAME ()));
+    default: abort ();
+    }
 }
 
 /* Store NEWVAL into SYMBOL, where VALCONTENTS is found in the value cell
@@ -913,102 +938,93 @@
    BUF non-zero means set the value in buffer BUF instead of the
    current buffer.  This only plays a role for per-buffer variables.  */
 
-void
-store_symval_forwarding (symbol, valcontents, newval, buf)
-     Lisp_Object symbol;
-     register Lisp_Object valcontents, newval;
+#define store_blv_forwarding(blv, newval, buf)			\
+  do {								\
+    if ((blv)->forwarded)					\
+      store_symval_forwarding (BLV_FWD (blv), (newval), (buf));	\
+    else							\
+      SET_BLV_VALUE (blv, newval);				\
+  } while (0)
+
+static void
+store_symval_forwarding (/* symbol, */ valcontents, newval, buf)
+     /* struct Lisp_Symbol *symbol; */
+     union Lisp_Fwd *valcontents;
+     register Lisp_Object newval;
      struct buffer *buf;
 {
-  switch (SWITCH_ENUM_CAST (XTYPE (valcontents)))
+  switch (XFWDTYPE (valcontents))
     {
-    case Lisp_Misc:
-      switch (XMISCTYPE (valcontents))
+    case Lisp_Fwd_Int:
+      CHECK_NUMBER (newval);
+      *XINTFWD (valcontents)->intvar = XINT (newval);
+      break;
+      
+    case Lisp_Fwd_Bool:
+      *XBOOLFWD (valcontents)->boolvar = !NILP (newval);
+      break;
+      
+    case Lisp_Fwd_Obj:
+      *XOBJFWD (valcontents)->objvar = newval;
+      
+      /* If this variable is a default for something stored
+	 in the buffer itself, such as default-fill-column,
+	 find the buffers that don't have local values for it
+	 and update them.  */
+      if (XOBJFWD (valcontents)->objvar > (Lisp_Object *) &buffer_defaults
+	  && XOBJFWD (valcontents)->objvar < (Lisp_Object *) (&buffer_defaults + 1))
 	{
-	case Lisp_Misc_Intfwd:
-	  CHECK_NUMBER (newval);
-	  *XINTFWD (valcontents)->intvar = XINT (newval);
-	  /* This can never happen since intvar points to an EMACS_INT
-	     which is at least large enough to hold a Lisp_Object.
-             if (*XINTFWD (valcontents)->intvar != XINT (newval))
-	       error ("Value out of range for variable `%s'",
-	   	   SDATA (SYMBOL_NAME (symbol))); */
-	  break;
-
-	case Lisp_Misc_Boolfwd:
-	  *XBOOLFWD (valcontents)->boolvar = !NILP (newval);
-	  break;
-
-	case Lisp_Misc_Objfwd:
-	  *XOBJFWD (valcontents)->objvar = newval;
-
-	  /* If this variable is a default for something stored
-	     in the buffer itself, such as default-fill-column,
-	     find the buffers that don't have local values for it
-	     and update them.  */
-	  if (XOBJFWD (valcontents)->objvar > (Lisp_Object *) &buffer_defaults
-	      && XOBJFWD (valcontents)->objvar < (Lisp_Object *) (&buffer_defaults + 1))
+	  int offset = ((char *) XOBJFWD (valcontents)->objvar
+			- (char *) &buffer_defaults);
+	  int idx = PER_BUFFER_IDX (offset);
+	  
+	  Lisp_Object tail;
+	  
+	  if (idx <= 0)
+	    break;
+	  
+	  for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
 	    {
-	      int offset = ((char *) XOBJFWD (valcontents)->objvar
-			    - (char *) &buffer_defaults);
-	      int idx = PER_BUFFER_IDX (offset);
-
-	      Lisp_Object tail;
-
-	      if (idx <= 0)
-		break;
-
-	      for (tail = Vbuffer_alist; CONSP (tail); tail = XCDR (tail))
-		{
-		  Lisp_Object buf;
-		  struct buffer *b;
-
-		  buf = Fcdr (XCAR (tail));
-		  if (!BUFFERP (buf)) continue;
-		  b = XBUFFER (buf);
-
-		  if (! PER_BUFFER_VALUE_P (b, idx))
-		    PER_BUFFER_VALUE (b, offset) = newval;
-		}
+	      Lisp_Object buf;
+	      struct buffer *b;
+
+	      buf = Fcdr (XCAR (tail));
+	      if (!BUFFERP (buf)) continue;
+	      b = XBUFFER (buf);
+
+	      if (! PER_BUFFER_VALUE_P (b, idx))
+		PER_BUFFER_VALUE (b, offset) = newval;
 	    }
-	  break;
-
-	case Lisp_Misc_Buffer_Objfwd:
-	  {
-	    int offset = XBUFFER_OBJFWD (valcontents)->offset;
-	    Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype;
-
-	    if (!(NILP (type) || NILP (newval)
-		  || (XINT (type) == LISP_INT_TAG
-		      ? INTEGERP (newval)
-		      : XTYPE (newval) == XINT (type))))
-	      buffer_slot_type_mismatch (newval, XINT (type));
-
-	    if (buf == NULL)
-	      buf = current_buffer;
-	    PER_BUFFER_VALUE (buf, offset) = newval;
-	  }
-	  break;
-
-	case Lisp_Misc_Kboard_Objfwd:
-	  {
-	    char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ());
-	    char *p = base + XKBOARD_OBJFWD (valcontents)->offset;
-	    *(Lisp_Object *) p = newval;
-	  }
-	  break;
-
-	default:
-	  goto def;
 	}
       break;
 
+    case Lisp_Fwd_Buffer_Obj:
+      {
+	int offset = XBUFFER_OBJFWD (valcontents)->offset;
+	Lisp_Object type = XBUFFER_OBJFWD (valcontents)->slottype;
+
+	if (!(NILP (type) || NILP (newval)
+	      || (XINT (type) == LISP_INT_TAG
+		  ? INTEGERP (newval)
+		  : XTYPE (newval) == XINT (type))))
+	  buffer_slot_type_mismatch (newval, XINT (type));
+
+	if (buf == NULL)
+	  buf = current_buffer;
+	PER_BUFFER_VALUE (buf, offset) = newval;
+      }
+      break;
+
+    case Lisp_Fwd_Kboard_Obj:
+      {
+	char *base = (char *) FRAME_KBOARD (SELECTED_FRAME ());
+	char *p = base + XKBOARD_OBJFWD (valcontents)->offset;
+	*(Lisp_Object *) p = newval;
+      }
+      break;
+
     default:
-    def:
-      valcontents = SYMBOL_VALUE (symbol);
-      if (BUFFER_LOCAL_VALUEP (valcontents))
-	XBUFFER_LOCAL_VALUE (valcontents)->realvalue = newval;
-      else
-	SET_SYMBOL_VALUE (symbol, newval);
+      abort (); /* goto def; */
     }
 }
 
@@ -1017,25 +1033,22 @@
 
 void
 swap_in_global_binding (symbol)
-     Lisp_Object symbol;
+     struct Lisp_Symbol *symbol;
 {
-  Lisp_Object valcontents = SYMBOL_VALUE (symbol);
-  struct Lisp_Buffer_Local_Value *blv = XBUFFER_LOCAL_VALUE (valcontents);
-  Lisp_Object cdr = blv->cdr;
+  struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (symbol);
 
   /* Unload the previously loaded binding.  */
-  Fsetcdr (XCAR (cdr),
-	   do_symval_forwarding (blv->realvalue));
+  if (blv->fwd)
+    SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd));
 
   /* Select the global binding in the symbol.  */
-  XSETCAR (cdr, cdr);
-  store_symval_forwarding (symbol, blv->realvalue, XCDR (cdr), NULL);
+  blv->valcell = blv->defcell;
+  if (blv->fwd)
+    store_symval_forwarding (blv->fwd, XCDR (blv->defcell), NULL);
 
   /* Indicate that the global binding is set up now.  */
-  blv->frame = Qnil;
-  blv->buffer = Qnil;
-  blv->found_for_frame = 0;
-  blv->found_for_buffer = 0;
+  blv->where = Qnil;
+  SET_BLV_FOUND (blv, 0);
 }
 
 /* Set up the buffer-local symbol SYMBOL for validity in the current buffer.
@@ -1045,55 +1058,50 @@
    Return the value forwarded one step past the buffer-local stage.
    This could be another forwarding pointer.  */
 
-static Lisp_Object
-swap_in_symval_forwarding (symbol, valcontents)
-     Lisp_Object symbol, valcontents;
+static void
+swap_in_symval_forwarding (symbol, blv)
+     struct Lisp_Symbol *symbol;
+     struct Lisp_Buffer_Local_Value *blv;
 {
   register Lisp_Object tem1;
 
-  tem1 = XBUFFER_LOCAL_VALUE (valcontents)->buffer;
+  eassert (blv == SYMBOL_BLV (symbol));
+
+  tem1 = blv->where;
 
   if (NILP (tem1)
-      || current_buffer != XBUFFER (tem1)
-      || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
-	  && ! EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame)))
+      || (blv->frame_local
+	  ? !EQ (selected_frame, tem1)
+	  : current_buffer != XBUFFER (tem1)))
     {
-      struct Lisp_Symbol *sym = XSYMBOL (symbol);
-      if (sym->indirect_variable)
-	{
-	  sym = indirect_variable (sym);
-	  XSETSYMBOL (symbol, sym);
-	}
 
       /* Unload the previously loaded binding.  */
-      tem1 = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-      Fsetcdr (tem1,
-	       do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
+      tem1 = blv->valcell;
+      if (blv->fwd)
+	SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd));
       /* Choose the new binding.  */
-      tem1 = assq_no_quit (symbol, current_buffer->local_var_alist);
-      XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
-      XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
-      if (NILP (tem1))
-	{
-	  if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
-	    tem1 = assq_no_quit (symbol, XFRAME (selected_frame)->param_alist);
-	  if (! NILP (tem1))
-	    XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 1;
-	  else
-	    tem1 = XBUFFER_LOCAL_VALUE (valcontents)->cdr;
-	}
-      else
-	XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1;
+      {
+	Lisp_Object var;
+	XSETSYMBOL (var, symbol);
+	if (blv->frame_local)
+	  {
+	    tem1 = assq_no_quit (var, XFRAME (selected_frame)->param_alist);
+	    blv->where = selected_frame;
+	  }
+	else
+	  {
+	    tem1 = assq_no_quit (var, current_buffer->local_var_alist);
+	    XSETBUFFER (blv->where, current_buffer);
+	  }
+      }
+      if (!(blv->found = !NILP (tem1)))
+	tem1 = blv->defcell;
 
       /* Load the new binding.  */
-      XSETCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, tem1);
-      XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, current_buffer);
-      XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame;
-      store_symval_forwarding (symbol,
-			       XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
-			       Fcdr (tem1), NULL);
+      blv->valcell = tem1;
+      if (blv->fwd)
+	store_symval_forwarding (blv->fwd, BLV_VALUE (blv), NULL);
     }
-  return XBUFFER_LOCAL_VALUE (valcontents)->realvalue;
 }
 
 /* Find the value of a symbol, returning Qunbound if it's not bound.
@@ -1106,16 +1114,27 @@
 find_symbol_value (symbol)
      Lisp_Object symbol;
 {
-  register Lisp_Object valcontents;
-  register Lisp_Object val;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (symbol);
-  valcontents = SYMBOL_VALUE (symbol);
-
-  if (BUFFER_LOCAL_VALUEP (valcontents))
-    valcontents = swap_in_symval_forwarding (symbol, valcontents);
-
-  return do_symval_forwarding (valcontents);
+  sym = XSYMBOL (symbol);
+
+ start:
+  switch (sym->redirect)
+    {
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return SYMBOL_VAL (sym);
+    case SYMBOL_LOCALIZED:
+      {
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	swap_in_symval_forwarding (sym, blv);
+	return blv->fwd ? do_symval_forwarding (blv->fwd) : BLV_VALUE (blv);
+      }
+      /* FALLTHROUGH */
+    case SYMBOL_FORWARDED:
+      return do_symval_forwarding (SYMBOL_FWD (sym));
+    default: abort ();
+    }
 }
 
 DEFUN ("symbol-value", Fsymbol_value, Ssymbol_value, 1, 1, 0,
@@ -1137,26 +1156,25 @@
      (symbol, newval)
      register Lisp_Object symbol, newval;
 {
-  return set_internal (symbol, newval, current_buffer, 0);
+  set_internal (symbol, newval, current_buffer, 0);
+  return newval;
 }
 
 /* Return 1 if SYMBOL currently has a let-binding
    which was made in the buffer that is now current.  */
 
 static int
-let_shadows_buffer_binding_p (symbol)
-     struct Lisp_Symbol *symbol;
+let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol)
 {
-  volatile struct specbinding *p;
+  struct specbinding *p;
 
   for (p = specpdl_ptr - 1; p >= specpdl; p--)
     if (p->func == NULL
 	&& CONSP (p->symbol))
       {
 	struct Lisp_Symbol *let_bound_symbol = XSYMBOL (XCAR (p->symbol));
-	if ((symbol == let_bound_symbol
-	     || (let_bound_symbol->indirect_variable
-		 && symbol == indirect_variable (let_bound_symbol)))
+	eassert (let_bound_symbol->redirect != SYMBOL_VARALIAS);
+	if (symbol == let_bound_symbol
 	    && XBUFFER (XCDR (XCDR (p->symbol))) == current_buffer)
 	  break;
       }
@@ -1164,6 +1182,19 @@
   return p >= specpdl;
 }
 
+static int
+let_shadows_global_binding_p (symbol)
+     Lisp_Object symbol;
+{
+  struct specbinding *p;
+
+  for (p = specpdl_ptr - 1; p >= specpdl; p--)
+    if (p->func == NULL && EQ (p->symbol, symbol))
+      break;
+
+  return p >= specpdl;
+}
+
 /* Store the value NEWVAL into SYMBOL.
    If buffer-locality is an issue, BUF specifies which buffer to use.
    (0 stands for the current buffer.)
@@ -1172,133 +1203,155 @@
    local in every buffer where it is set, then we make it local.
    If BINDFLAG is nonzero, we don't do that.  */
 
-Lisp_Object
+void
 set_internal (symbol, newval, buf, bindflag)
      register Lisp_Object symbol, newval;
      struct buffer *buf;
      int bindflag;
 {
   int voide = EQ (newval, Qunbound);
-
-  register Lisp_Object valcontents, innercontents, tem1, current_alist_element;
+  struct Lisp_Symbol *sym;
+  Lisp_Object tem1;
 
   if (buf == 0)
     buf = current_buffer;
 
   /* If restoring in a dead buffer, do nothing.  */
   if (NILP (buf->name))
-    return newval;
+    return;
 
   CHECK_SYMBOL (symbol);
-  if (SYMBOL_CONSTANT_P (symbol)
-      && (NILP (Fkeywordp (symbol))
-	  || !EQ (newval, SYMBOL_VALUE (symbol))))
-    xsignal1 (Qsetting_constant, symbol);
-
-  innercontents = valcontents = SYMBOL_VALUE (symbol);
-
-  if (BUFFER_OBJFWDP (valcontents))
+  if (SYMBOL_CONSTANT_P (symbol))
     {
-      int offset = XBUFFER_OBJFWD (valcontents)->offset;
-      int idx = PER_BUFFER_IDX (offset);
-      if (idx > 0
-	  && !bindflag
-	  && !let_shadows_buffer_binding_p (XSYMBOL (symbol)))
-	SET_PER_BUFFER_VALUE_P (buf, idx, 1);
+      if (NILP (Fkeywordp (symbol))
+	  || !EQ (newval, Fsymbol_value (symbol)))
+	xsignal1 (Qsetting_constant, symbol);
+      else
+	/* Allow setting keywords to their own value.  */
+	return;
     }
-  else if (BUFFER_LOCAL_VALUEP (valcontents))
+
+  sym = XSYMBOL (symbol);
+
+ start:
+  switch (sym->redirect)
     {
-      /* valcontents is a struct Lisp_Buffer_Local_Value.   */
-      if (XSYMBOL (symbol)->indirect_variable)
-	XSETSYMBOL (symbol, indirect_variable (XSYMBOL (symbol)));
-
-      /* What binding is loaded right now?  */
-      current_alist_element
-	= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-
-      /* If the current buffer is not the buffer whose binding is
-	 loaded, or if there may be frame-local bindings and the frame
-	 isn't the right one, or if it's a Lisp_Buffer_Local_Value and
-	 the default binding is loaded, the loaded binding may be the
-	 wrong one.  */
-      if (!BUFFERP (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
-	  || buf != XBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer)
-	  || (XBUFFER_LOCAL_VALUE (valcontents)->check_frame
-	      && !EQ (selected_frame, XBUFFER_LOCAL_VALUE (valcontents)->frame))
-	  /* Also unload a global binding (if the var is local_if_set). */
-	  || (EQ (XCAR (current_alist_element),
-		  current_alist_element)))
-	{
-	  /* The currently loaded binding is not necessarily valid.
-	     We need to unload it, and choose a new binding.  */
-
-	  /* Write out `realvalue' to the old loaded binding.  */
-          Fsetcdr (current_alist_element,
-		   do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue));
-
-	  /* Find the new binding.  */
-	  tem1 = Fassq (symbol, buf->local_var_alist);
-	  XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 1;
-	  XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 0;
-
-	  if (NILP (tem1))
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: SET_SYMBOL_VAL (sym , newval); return;
+    case SYMBOL_LOCALIZED:
+      {
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	Lisp_Object tmp; XSETBUFFER (tmp, buf);
+
+	/* If the current buffer is not the buffer whose binding is
+	   loaded, or if there may be frame-local bindings and the frame
+	   isn't the right one, or if it's a Lisp_Buffer_Local_Value and
+	   the default binding is loaded, the loaded binding may be the
+	   wrong one.  */
+	if (!EQ (blv->where,
+		 blv->frame_local ? selected_frame : tmp)
+	    /* Also unload a global binding (if the var is local_if_set). */
+	    || (EQ (blv->valcell, blv->defcell)))
+	  {
+	    /* The currently loaded binding is not necessarily valid.
+	       We need to unload it, and choose a new binding.  */
+
+	    /* Write out `realvalue' to the old loaded binding.  */
+	    if (blv->fwd)
+	      SET_BLV_VALUE (blv, do_symval_forwarding (blv->fwd));
+
+	    /* Find the new binding.  */
 	    {
-	      /* This buffer still sees the default value.  */
-
-	      /* If the variable is not local_if_set,
-		 or if this is `let' rather than `set',
-		 make CURRENT-ALIST-ELEMENT point to itself,
-		 indicating that we're seeing the default value.
-		 Likewise if the variable has been let-bound
-		 in the current buffer.  */
-	      if (bindflag || !XBUFFER_LOCAL_VALUE (valcontents)->local_if_set
-		  || let_shadows_buffer_binding_p (XSYMBOL (symbol)))
+	      XSETSYMBOL (symbol, sym); /* May have changed via aliasing.  */
+	      if (blv->frame_local)
 		{
-		  XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
-
-		  if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
-		    tem1 = Fassq (symbol,
-				  XFRAME (selected_frame)->param_alist);
-
-		  if (! NILP (tem1))
-		    XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame = 1;
-		  else
-		    tem1 = XBUFFER_LOCAL_VALUE (valcontents)->cdr;
+		  tem1 = Fassq (symbol, XFRAME (selected_frame)->param_alist);
+		  blv->where = selected_frame;
 		}
-	      /* If it's a Lisp_Buffer_Local_Value, being set not bound,
-		 and we're not within a let that was made for this buffer,
-		 create a new buffer-local binding for the variable.
-		 That means, give this buffer a new assoc for a local value
-		 and load that binding.  */
 	      else
 		{
-		  tem1 = Fcons (symbol, XCDR (current_alist_element));
-		  buf->local_var_alist
-		    = Fcons (tem1, buf->local_var_alist);
+		  tem1 = Fassq (symbol, buf->local_var_alist);
+		  blv->where = tmp;
 		}
 	    }
-
-	  /* Record which binding is now loaded.  */
-	  XSETCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, tem1);
-
-	  /* Set `buffer' and `frame' slots for the binding now loaded.  */
-	  XSETBUFFER (XBUFFER_LOCAL_VALUE (valcontents)->buffer, buf);
-	  XBUFFER_LOCAL_VALUE (valcontents)->frame = selected_frame;
-	}
-      innercontents = XBUFFER_LOCAL_VALUE (valcontents)->realvalue;
-
-      /* Store the new value in the cons-cell.  */
-      XSETCDR (XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr), newval);
+	    blv->found = 1;
+
+	    if (NILP (tem1))
+	      {
+		/* This buffer still sees the default value.  */
+
+		/* If the variable is a Lisp_Some_Buffer_Local_Value,
+		   or if this is `let' rather than `set',
+		   make CURRENT-ALIST-ELEMENT point to itself,
+		   indicating that we're seeing the default value.
+		   Likewise if the variable has been let-bound
+		   in the current buffer.  */
+		if (bindflag || !blv->local_if_set
+		    || let_shadows_buffer_binding_p (sym))
+		  {
+		    blv->found = 0;
+		    tem1 = blv->defcell;
+		  }
+		/* If it's a local_if_set, being set not bound,
+		   and we're not within a let that was made for this buffer,
+		   create a new buffer-local binding for the variable.
+		   That means, give this buffer a new assoc for a local value
+		   and load that binding.  */
+		else
+		  {
+		    /* local_if_set is only supported for buffer-local
+		       bindings, not for frame-local bindings.  */
+		    eassert (!blv->frame_local);
+		    tem1 = Fcons (symbol, XCDR (blv->defcell));
+		    buf->local_var_alist
+		      = Fcons (tem1, buf->local_var_alist);
+		  }
+	      }
+
+	    /* Record which binding is now loaded.  */
+	    blv->valcell = tem1;
+	  }
+
+	/* Store the new value in the cons cell.  */
+	SET_BLV_VALUE (blv, newval);
+
+	if (blv->fwd)
+	  {
+	    if (voide)
+	      /* If storing void (making the symbol void), forward only through
+		 buffer-local indicator, not through Lisp_Objfwd, etc.  */
+	      blv->fwd = NULL;
+	    else
+	      store_symval_forwarding (blv->fwd, newval, buf);
+	  }
+	break;
+      }
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *innercontents = SYMBOL_FWD (sym);
+	if (BUFFER_OBJFWDP (innercontents))
+	  {
+	    int offset = XBUFFER_OBJFWD (innercontents)->offset;
+	    int idx = PER_BUFFER_IDX (offset);
+	    if (idx > 0
+		&& !bindflag
+		&& !let_shadows_buffer_binding_p (sym))
+	      SET_PER_BUFFER_VALUE_P (buf, idx, 1);
+	  }
+
+	if (voide)
+	  { /* If storing void (making the symbol void), forward only through
+	       buffer-local indicator, not through Lisp_Objfwd, etc.  */
+	    sym->redirect = SYMBOL_PLAINVAL;
+	    SET_SYMBOL_VAL (sym, newval);
+	  }
+	else
+	  store_symval_forwarding (/* sym, */ innercontents, newval, buf);
+	break;
+      }
+    default: abort ();
     }
-
-  /* If storing void (making the symbol void), forward only through
-     buffer-local indicator, not through Lisp_Objfwd, etc.  */
-  if (voide)
-    store_symval_forwarding (symbol, Qnil, newval, buf);
-  else
-    store_symval_forwarding (symbol, innercontents, newval, buf);
-
-  return newval;
+  return;
 }
 
 /* Access or set a buffer-local symbol's default value.  */
@@ -1310,38 +1363,46 @@
 default_value (symbol)
      Lisp_Object symbol;
 {
-  register Lisp_Object valcontents;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (symbol);
-  valcontents = SYMBOL_VALUE (symbol);
-
-  /* For a built-in buffer-local variable, get the default value
-     rather than letting do_symval_forwarding get the current value.  */
-  if (BUFFER_OBJFWDP (valcontents))
-    {
-      int offset = XBUFFER_OBJFWD (valcontents)->offset;
-      if (PER_BUFFER_IDX (offset) != 0)
-	return PER_BUFFER_DEFAULT (offset);
-    }
-
-  /* Handle user-created local variables.  */
-  if (BUFFER_LOCAL_VALUEP (valcontents))
+  sym = XSYMBOL (symbol);
+
+ start:
+  switch (sym->redirect)
     {
-      /* If var is set up for a buffer that lacks a local value for it,
-	 the current value is nominally the default value.
-	 But the `realvalue' slot may be more up to date, since
-	 ordinary setq stores just that slot.  So use that.  */
-      Lisp_Object current_alist_element, alist_element_car;
-      current_alist_element
-	= XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-      alist_element_car = XCAR (current_alist_element);
-      if (EQ (alist_element_car, current_alist_element))
-	return do_symval_forwarding (XBUFFER_LOCAL_VALUE (valcontents)->realvalue);
-      else
-	return XCDR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return SYMBOL_VAL (sym);
+    case SYMBOL_LOCALIZED:
+      {
+	/* If var is set up for a buffer that lacks a local value for it,
+	   the current value is nominally the default value.
+	   But the `realvalue' slot may be more up to date, since
+	   ordinary setq stores just that slot.  So use that.  */
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	if (blv->fwd && EQ (blv->valcell, blv->defcell))
+	  return do_symval_forwarding (blv->fwd);
+	else
+	  return XCDR (blv->defcell);
+      }
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *valcontents = SYMBOL_FWD (sym);
+
+	/* For a built-in buffer-local variable, get the default value
+	   rather than letting do_symval_forwarding get the current value.  */
+	if (BUFFER_OBJFWDP (valcontents))
+	  {
+	    int offset = XBUFFER_OBJFWD (valcontents)->offset;
+	    if (PER_BUFFER_IDX (offset) != 0)
+	      return PER_BUFFER_DEFAULT (offset);
+	  }
+
+	/* For other variables, get the current value.  */
+	return do_symval_forwarding (valcontents);
+      }
+    default: abort ();
     }
-  /* For other variables, get the current value.  */
-  return do_symval_forwarding (valcontents);
 }
 
 DEFUN ("default-boundp", Fdefault_boundp, Sdefault_boundp, 1, 1, 0,
@@ -1381,50 +1442,68 @@
      (symbol, value)
      Lisp_Object symbol, value;
 {
-  register Lisp_Object valcontents, current_alist_element, alist_element_buffer;
+  struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (symbol);
-  valcontents = SYMBOL_VALUE (symbol);
-
-  /* Handle variables like case-fold-search that have special slots
-     in the buffer.  Make them work apparently like Lisp_Buffer_Local_Value
-     variables.  */
-  if (BUFFER_OBJFWDP (valcontents))
+  if (SYMBOL_CONSTANT_P (symbol))
+    {
+      if (NILP (Fkeywordp (symbol))
+	  || !EQ (value, Fdefault_value (symbol)))
+	xsignal1 (Qsetting_constant, symbol);
+      else
+	/* Allow setting keywords to their own value.  */
+	return value;
+    }
+  sym = XSYMBOL (symbol);
+
+ start:
+  switch (sym->redirect)
     {
-      int offset = XBUFFER_OBJFWD (valcontents)->offset;
-      int idx = PER_BUFFER_IDX (offset);
-
-      PER_BUFFER_DEFAULT (offset) = value;
-
-      /* If this variable is not always local in all buffers,
-	 set it in the buffers that don't nominally have a local value.  */
-      if (idx > 0)
-	{
-	  struct buffer *b;
-
-	  for (b = all_buffers; b; b = b->next)
-	    if (!PER_BUFFER_VALUE_P (b, idx))
-	      PER_BUFFER_VALUE (b, offset) = value;
-	}
-      return value;
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return Fset (symbol, value);
+    case SYMBOL_LOCALIZED:
+      {
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+
+	/* Store new value into the DEFAULT-VALUE slot.  */
+	XSETCDR (blv->defcell, value);
+
+	/* If the default binding is now loaded, set the REALVALUE slot too.  */
+	if (blv->fwd && EQ (blv->defcell, blv->valcell))
+	  store_symval_forwarding (blv->fwd, value, NULL);
+	return value;
+      }
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *valcontents = SYMBOL_FWD (sym);
+
+	/* Handle variables like case-fold-search that have special slots
+	   in the buffer.
+	   Make them work apparently like Lisp_Buffer_Local_Value variables.  */
+	if (BUFFER_OBJFWDP (valcontents))
+	  {
+	    int offset = XBUFFER_OBJFWD (valcontents)->offset;
+	    int idx = PER_BUFFER_IDX (offset);
+
+	    PER_BUFFER_DEFAULT (offset) = value;
+
+	    /* If this variable is not always local in all buffers,
+	       set it in the buffers that don't nominally have a local value.  */
+	    if (idx > 0)
+	      {
+		struct buffer *b;
+
+		for (b = all_buffers; b; b = b->next)
+		  if (!PER_BUFFER_VALUE_P (b, idx))
+		    PER_BUFFER_VALUE (b, offset) = value;
+	      }
+	    return value;
+	  }
+	else
+	  return Fset (symbol, value);
+      }
+    default: abort ();
     }
-
-  if (!BUFFER_LOCAL_VALUEP (valcontents))
-    return Fset (symbol, value);
-
-  /* Store new value into the DEFAULT-VALUE slot.  */
-  XSETCDR (XBUFFER_LOCAL_VALUE (valcontents)->cdr, value);
-
-  /* If the default binding is now loaded, set the REALVALUE slot too.  */
-  current_alist_element
-    = XCAR (XBUFFER_LOCAL_VALUE (valcontents)->cdr);
-  alist_element_buffer = Fcar (current_alist_element);
-  if (EQ (alist_element_buffer, current_alist_element))
-    store_symval_forwarding (symbol,
-			     XBUFFER_LOCAL_VALUE (valcontents)->realvalue,
-			     value, NULL);
-
-  return value;
 }
 
 DEFUN ("setq-default", Fsetq_default, Ssetq_default, 0, UNEVALLED, 0,
@@ -1468,6 +1547,35 @@
 
 /* Lisp functions for creating and removing buffer-local variables.  */
 
+union Lisp_Val_Fwd
+  {
+    Lisp_Object value;
+    union Lisp_Fwd *fwd;
+  };
+
+static struct Lisp_Buffer_Local_Value *
+make_blv (struct Lisp_Symbol *sym, int forwarded, union Lisp_Val_Fwd valcontents)
+{
+  struct Lisp_Buffer_Local_Value *blv
+    = xmalloc (sizeof (struct Lisp_Buffer_Local_Value));
+  Lisp_Object symbol; XSETSYMBOL (symbol, sym);
+  Lisp_Object tem = Fcons (symbol, (forwarded
+				    ? do_symval_forwarding (valcontents.fwd)
+				    : valcontents.value));
+  /* Buffer_Local_Values cannot have as realval a buffer-local
+     or keyboard-local forwarding.  */
+  eassert (!(forwarded && BUFFER_OBJFWDP (valcontents.fwd)));
+  eassert (!(forwarded && KBOARD_OBJFWDP (valcontents.fwd)));
+  blv->fwd = forwarded ? valcontents.fwd : NULL;
+  blv->where = Qnil;
+  blv->frame_local = 0;
+  blv->local_if_set = 0;
+  blv->defcell = tem;
+  blv->valcell = tem;
+  SET_BLV_FOUND (blv, 0);
+  return blv;
+}
+
 DEFUN ("make-variable-buffer-local", Fmake_variable_buffer_local, Smake_variable_buffer_local,
        1, 1, "vMake Variable Buffer Local: ",
        doc: /* Make VARIABLE become buffer-local whenever it is set.
@@ -1485,42 +1593,58 @@
      (variable)
      register Lisp_Object variable;
 {
-  register Lisp_Object tem, valcontents, newval;
   struct Lisp_Symbol *sym;
+  struct Lisp_Buffer_Local_Value *blv = NULL;
+  union Lisp_Val_Fwd valcontents;
+  int forwarded;
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-
-  valcontents = sym->value;
-  if (sym->constant || KBOARD_OBJFWDP (valcontents))
-    error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
-
-  if (BUFFER_OBJFWDP (valcontents))
-    return variable;
-  else if (BUFFER_LOCAL_VALUEP (valcontents))
-    {
-      if (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
-	error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
-      newval = valcontents;
-    }
-  else
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      if (EQ (valcontents, Qunbound))
-	sym->value = Qnil;
-      tem = Fcons (Qnil, Fsymbol_value (variable));
-      XSETCAR (tem, tem);
-      newval = allocate_misc ();
-      XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-      XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
-      XBUFFER_LOCAL_VALUE (newval)->buffer = Fcurrent_buffer ();
-      XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
-      XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0;
-      XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
-      XBUFFER_LOCAL_VALUE (newval)->check_frame = 0;
-      XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-      sym->value = newval;
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL:
+      forwarded = 0; valcontents.value = SYMBOL_VAL (sym);
+      if (EQ (valcontents.value, Qunbound))
+	valcontents.value = Qnil;
+      break;
+    case SYMBOL_LOCALIZED:
+      blv = SYMBOL_BLV (sym);
+      if (blv->frame_local)
+	error ("Symbol %s may not be buffer-local",
+	       SDATA (SYMBOL_NAME (variable)));
+      break;
+    case SYMBOL_FORWARDED:
+      forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym);
+      if (KBOARD_OBJFWDP (valcontents.fwd))
+	error ("Symbol %s may not be buffer-local",
+	       SDATA (SYMBOL_NAME (variable)));
+      else if (BUFFER_OBJFWDP (valcontents.fwd))
+	return variable;
+      break;
+    default: abort ();
     }
-  XBUFFER_LOCAL_VALUE (newval)->local_if_set = 1;
+
+  if (sym->constant)
+    error ("Symbol %s may not be buffer-local", SDATA (SYMBOL_NAME (variable)));
+
+  if (!blv)
+    {
+      blv = make_blv (sym, forwarded, valcontents);
+      sym->redirect = SYMBOL_LOCALIZED;
+      SET_SYMBOL_BLV (sym, blv);
+      {
+	Lisp_Object symbol;
+	XSETSYMBOL (symbol, sym); /* In case `variable' is aliased.  */
+	if (let_shadows_global_binding_p (symbol))
+	  message ("Making %s buffer-local while let-bound!",
+		   SDATA (SYMBOL_NAME (variable)));
+      }
+    }
+
+  blv->local_if_set = 1;
   return variable;
 }
 
@@ -1547,82 +1671,97 @@
      (variable)
      register Lisp_Object variable;
 {
-  register Lisp_Object tem, valcontents;
+  register Lisp_Object tem;
+  int forwarded;
+  union Lisp_Val_Fwd valcontents;
   struct Lisp_Symbol *sym;
+  struct Lisp_Buffer_Local_Value *blv = NULL;
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-
-  valcontents = sym->value;
-  if (sym->constant || KBOARD_OBJFWDP (valcontents)
-      || (BUFFER_LOCAL_VALUEP (valcontents)
-	  && (XBUFFER_LOCAL_VALUE (valcontents)->check_frame)))
-    error ("Symbol %s may not be buffer-local", SDATA (sym->xname));
-
-  if ((BUFFER_LOCAL_VALUEP (valcontents)
-       && XBUFFER_LOCAL_VALUE (valcontents)->local_if_set)
-      || BUFFER_OBJFWDP (valcontents))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
+    {
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL:
+      forwarded = 0; valcontents.value = SYMBOL_VAL (sym); break;
+    case SYMBOL_LOCALIZED:
+      blv = SYMBOL_BLV (sym);
+      if (blv->frame_local)
+	error ("Symbol %s may not be buffer-local",
+	       SDATA (SYMBOL_NAME (variable)));
+      break;
+    case SYMBOL_FORWARDED:
+      forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym);
+      if (KBOARD_OBJFWDP (valcontents.fwd))
+	error ("Symbol %s may not be buffer-local",
+	       SDATA (SYMBOL_NAME (variable)));
+      break;
+    default: abort ();
+    }
+
+  if (sym->constant)
+    error ("Symbol %s may not be buffer-local",
+	   SDATA (SYMBOL_NAME (variable)));
+
+  if (blv ? blv->local_if_set
+      : (forwarded && BUFFER_OBJFWDP (valcontents.fwd)))
     {
       tem = Fboundp (variable);
-
       /* Make sure the symbol has a local value in this particular buffer,
 	 by setting it to the same value it already has.  */
       Fset (variable, (EQ (tem, Qt) ? Fsymbol_value (variable) : Qunbound));
       return variable;
     }
-  /* Make sure symbol is set up to hold per-buffer values.  */
-  if (!BUFFER_LOCAL_VALUEP (valcontents))
+  if (!blv)
     {
-      Lisp_Object newval;
-      tem = Fcons (Qnil, do_symval_forwarding (valcontents));
-      XSETCAR (tem, tem);
-      newval = allocate_misc ();
-      XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-      XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
-      XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil;
-      XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
-      XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0;
-      XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0;
-      XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
-      XBUFFER_LOCAL_VALUE (newval)->check_frame = 0;
-      XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-      sym->value = newval;
+      blv = make_blv (sym, forwarded, valcontents);
+      sym->redirect = SYMBOL_LOCALIZED;
+      SET_SYMBOL_BLV (sym, blv);
+      {
+	Lisp_Object symbol;
+	XSETSYMBOL (symbol, sym); /* In case `variable' is aliased.  */
+	if (let_shadows_global_binding_p (symbol))
+	  message ("Making %s local to %s while let-bound!",
+		   SDATA (SYMBOL_NAME (variable)),
+		   SDATA (current_buffer->name));
+      }
     }
+
   /* Make sure this buffer has its own value of symbol.  */
-  XSETSYMBOL (variable, sym);	/* Propagate variable indirections.  */
+  XSETSYMBOL (variable, sym);	/* Update in case of aliasing.  */
   tem = Fassq (variable, current_buffer->local_var_alist);
   if (NILP (tem))
     {
+      if (let_shadows_buffer_binding_p (sym))
+	message ("Making %s buffer-local while locally let-bound!",
+		 SDATA (SYMBOL_NAME (variable)));
+
       /* Swap out any local binding for some other buffer, and make
 	 sure the current value is permanently recorded, if it's the
 	 default value.  */
       find_symbol_value (variable);
 
       current_buffer->local_var_alist
-        = Fcons (Fcons (variable, XCDR (XBUFFER_LOCAL_VALUE (sym->value)->cdr)),
+        = Fcons (Fcons (variable, XCDR (blv->defcell)),
 		 current_buffer->local_var_alist);
 
       /* Make sure symbol does not think it is set up for this buffer;
 	 force it to look once again for this buffer's value.  */
-      {
-	Lisp_Object *pvalbuf;
-
-	valcontents = sym->value;
-
-	pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer;
-	if (current_buffer == XBUFFER (*pvalbuf))
-	  *pvalbuf = Qnil;
-	XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
-      }
+      if (current_buffer == XBUFFER (blv->where))
+	blv->where = Qnil;
+      /* blv->valcell = blv->defcell;
+       * SET_BLV_FOUND (blv, 0); */
+      blv->found = 0;
     }
 
   /* If the symbol forwards into a C variable, then load the binding
      for this buffer now.  If C code modifies the variable before we
      load the binding in, then that new value will clobber the default
      binding the next time we unload it.  */
-  valcontents = XBUFFER_LOCAL_VALUE (sym->value)->realvalue;
-  if (INTFWDP (valcontents) || BOOLFWDP (valcontents) || OBJFWDP (valcontents))
-    swap_in_symval_forwarding (variable, sym->value);
+  if (blv->fwd)
+    swap_in_symval_forwarding (sym, blv);
 
   return variable;
 }
@@ -1634,31 +1773,43 @@
      (variable)
      register Lisp_Object variable;
 {
-  register Lisp_Object tem, valcontents;
+  register Lisp_Object tem;
+  struct Lisp_Buffer_Local_Value *blv;
   struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-
-  valcontents = sym->value;
-
-  if (BUFFER_OBJFWDP (valcontents))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      int offset = XBUFFER_OBJFWD (valcontents)->offset;
-      int idx = PER_BUFFER_IDX (offset);
-
-      if (idx > 0)
-	{
-	  SET_PER_BUFFER_VALUE_P (current_buffer, idx, 0);
-	  PER_BUFFER_VALUE (current_buffer, offset)
-	    = PER_BUFFER_DEFAULT (offset);
-	}
-      return variable;
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return variable;
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *valcontents = SYMBOL_FWD (sym);
+	if (BUFFER_OBJFWDP (valcontents))
+	  {
+	    int offset = XBUFFER_OBJFWD (valcontents)->offset;
+	    int idx = PER_BUFFER_IDX (offset);
+
+	    if (idx > 0)
+	      {
+		SET_PER_BUFFER_VALUE_P (current_buffer, idx, 0);
+		PER_BUFFER_VALUE (current_buffer, offset)
+		  = PER_BUFFER_DEFAULT (offset);
+	      }
+	  }
+	return variable;
+      }
+    case SYMBOL_LOCALIZED:
+      blv = SYMBOL_BLV (sym);
+      if (blv->frame_local)
+	return variable;
+      break;
+    default: abort ();
     }
 
-  if (!BUFFER_LOCAL_VALUEP (valcontents))
-    return variable;
-
   /* Get rid of this buffer's alist element, if any.  */
   XSETSYMBOL (variable, sym);	/* Propagate variable indirection.  */
   tem = Fassq (variable, current_buffer->local_var_alist);
@@ -1670,14 +1821,13 @@
      loaded, recompute its value.  We have to do it now, or else
      forwarded objects won't work right.  */
   {
-    Lisp_Object *pvalbuf, buf;
-    valcontents = sym->value;
-    pvalbuf = &XBUFFER_LOCAL_VALUE (valcontents)->buffer;
-    XSETBUFFER (buf, current_buffer);
-    if (EQ (buf, *pvalbuf))
+    Lisp_Object buf; XSETBUFFER (buf, current_buffer);
+    if (EQ (buf, blv->where))
       {
-	*pvalbuf = Qnil;
-	XBUFFER_LOCAL_VALUE (valcontents)->found_for_buffer = 0;
+	blv->where = Qnil;
+	/* blv->valcell = blv->defcell;
+	 * SET_BLV_FOUND (blv, 0); */
+	blv->found = 0;
 	find_symbol_value (variable);
       }
   }
@@ -1712,39 +1862,52 @@
      (variable)
      register Lisp_Object variable;
 {
-  register Lisp_Object tem, valcontents, newval;
+  int forwarded;
+  union Lisp_Val_Fwd valcontents;
   struct Lisp_Symbol *sym;
+  struct Lisp_Buffer_Local_Value *blv = NULL;
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-
-  valcontents = sym->value;
-  if (sym->constant || KBOARD_OBJFWDP (valcontents)
-      || BUFFER_OBJFWDP (valcontents))
-    error ("Symbol %s may not be frame-local", SDATA (sym->xname));
-
-  if (BUFFER_LOCAL_VALUEP (valcontents))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      if (!XBUFFER_LOCAL_VALUE (valcontents)->check_frame)
-	error ("Symbol %s may not be frame-local", SDATA (sym->xname));
-      return variable;
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL:
+      forwarded = 0; valcontents.value = SYMBOL_VAL (sym);
+      if (EQ (valcontents.value, Qunbound))
+	valcontents.value = Qnil;
+      break;
+    case SYMBOL_LOCALIZED:
+      if (SYMBOL_BLV (sym)->frame_local)
+	return variable;
+      else
+	error ("Symbol %s may not be frame-local",
+	       SDATA (SYMBOL_NAME (variable)));
+    case SYMBOL_FORWARDED:
+      forwarded = 1; valcontents.fwd = SYMBOL_FWD (sym);
+      if (KBOARD_OBJFWDP (valcontents.fwd) || BUFFER_OBJFWDP (valcontents.fwd))
+	error ("Symbol %s may not be frame-local",
+	       SDATA (SYMBOL_NAME (variable)));
+      break;
+    default: abort ();
     }
 
-  if (EQ (valcontents, Qunbound))
-    sym->value = Qnil;
-  tem = Fcons (Qnil, Fsymbol_value (variable));
-  XSETCAR (tem, tem);
-  newval = allocate_misc ();
-  XMISCTYPE (newval) = Lisp_Misc_Buffer_Local_Value;
-  XBUFFER_LOCAL_VALUE (newval)->realvalue = sym->value;
-  XBUFFER_LOCAL_VALUE (newval)->buffer = Qnil;
-  XBUFFER_LOCAL_VALUE (newval)->frame = Qnil;
-  XBUFFER_LOCAL_VALUE (newval)->local_if_set = 0;
-  XBUFFER_LOCAL_VALUE (newval)->found_for_buffer = 0;
-  XBUFFER_LOCAL_VALUE (newval)->found_for_frame = 0;
-  XBUFFER_LOCAL_VALUE (newval)->check_frame = 1;
-  XBUFFER_LOCAL_VALUE (newval)->cdr = tem;
-  sym->value = newval;
+  if (sym->constant)
+    error ("Symbol %s may not be frame-local", SDATA (SYMBOL_NAME (variable)));
+
+  blv = make_blv (sym, forwarded, valcontents);
+  blv->frame_local = 1;
+  sym->redirect = SYMBOL_LOCALIZED;
+  SET_SYMBOL_BLV (sym, blv);
+  {
+    Lisp_Object symbol;
+    XSETSYMBOL (symbol, sym); /* In case `variable' is aliased.  */
+    if (let_shadows_global_binding_p (symbol))
+      message ("Making %s frame-local while let-bound!",
+	       SDATA (SYMBOL_NAME (variable)));
+  }
   return variable;
 }
 
@@ -1755,7 +1918,6 @@
      (variable, buffer)
      register Lisp_Object variable, buffer;
 {
-  Lisp_Object valcontents;
   register struct buffer *buf;
   struct Lisp_Symbol *sym;
 
@@ -1768,29 +1930,46 @@
     }
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-  XSETSYMBOL (variable, sym);
-
-  valcontents = sym->value;
-  if (BUFFER_LOCAL_VALUEP (valcontents))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      Lisp_Object tail, elt;
-
-      for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
-	{
-	  elt = XCAR (tail);
-	  if (EQ (variable, XCAR (elt)))
-	    return Qt;
-	}
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return Qnil;
+    case SYMBOL_LOCALIZED:
+      {
+	Lisp_Object tail, elt, tmp;
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	XSETBUFFER (tmp, buf);
+	
+	for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
+	  {
+	    elt = XCAR (tail);
+	    if (EQ (variable, XCAR (elt)))
+	      {
+		eassert (!blv->frame_local);
+		eassert (BLV_FOUND (blv) || !EQ (blv->where, tmp));
+		return Qt;
+	      }
+	  }
+	eassert (!BLV_FOUND (blv) || !EQ (blv->where, tmp));
+	return Qnil;
+      }
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *valcontents = SYMBOL_FWD (sym);
+	if (BUFFER_OBJFWDP (valcontents))
+	  {
+	    int offset = XBUFFER_OBJFWD (valcontents)->offset;
+	    int idx = PER_BUFFER_IDX (offset);
+	    if (idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
+	      return Qt;
+	  }
+	return Qnil;
+      }
+    default: abort ();
     }
-  if (BUFFER_OBJFWDP (valcontents))
-    {
-      int offset = XBUFFER_OBJFWD (valcontents)->offset;
-      int idx = PER_BUFFER_IDX (offset);
-      if (idx == -1 || PER_BUFFER_VALUE_P (buf, idx))
-	return Qt;
-    }
-  return Qnil;
 }
 
 DEFUN ("local-variable-if-set-p", Flocal_variable_if_set_p, Slocal_variable_if_set_p,
@@ -1804,40 +1983,29 @@
      (variable, buffer)
      register Lisp_Object variable, buffer;
 {
-  Lisp_Object valcontents;
-  register struct buffer *buf;
   struct Lisp_Symbol *sym;
 
-  if (NILP (buffer))
-    buf = current_buffer;
-  else
-    {
-      CHECK_BUFFER (buffer);
-      buf = XBUFFER (buffer);
-    }
-
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
-  XSETSYMBOL (variable, sym);
-
-  valcontents = sym->value;
-
-  if (BUFFER_OBJFWDP (valcontents))
-    /* All these slots become local if they are set.  */
-    return Qt;
-  else if (BUFFER_LOCAL_VALUEP (valcontents))
+  sym = XSYMBOL (variable);
+
+ start:
+  switch (sym->redirect)
     {
-      Lisp_Object tail, elt;
-      if (XBUFFER_LOCAL_VALUE (valcontents)->local_if_set)
-	return Qt;
-      for (tail = buf->local_var_alist; CONSP (tail); tail = XCDR (tail))
-	{
-	  elt = XCAR (tail);
-	  if (EQ (variable, XCAR (elt)))
-	    return Qt;
-	}
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return Qnil;
+    case SYMBOL_LOCALIZED:
+      {
+	struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (sym);
+	if (blv->local_if_set)
+	  return Qt;
+	XSETSYMBOL (variable, sym); /* Update in case of aliasing.  */
+	return Flocal_variable_p (variable, buffer);
+      }
+    case SYMBOL_FORWARDED:
+      /* All BUFFER_OBJFWD slots become local if they are set.  */
+      return (BUFFER_OBJFWDP (SYMBOL_FWD (sym)) ? Qt : Qnil);
+    default: abort ();
     }
-  return Qnil;
 }
 
 DEFUN ("variable-binding-locus", Fvariable_binding_locus, Svariable_binding_locus,
@@ -1849,30 +2017,40 @@
      (variable)
      register Lisp_Object variable;
 {
-  Lisp_Object valcontents;
   struct Lisp_Symbol *sym;
 
   CHECK_SYMBOL (variable);
-  sym = indirect_variable (XSYMBOL (variable));
+  sym = XSYMBOL (variable);
 
   /* Make sure the current binding is actually swapped in.  */
   find_symbol_value (variable);
 
-  valcontents = sym->value;
-
-  if (BUFFER_LOCAL_VALUEP (valcontents)
-      || BUFFER_OBJFWDP (valcontents))
+ start:
+  switch (sym->redirect)
     {
+    case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+    case SYMBOL_PLAINVAL: return Qnil;
+    case SYMBOL_FORWARDED:
+      {
+	union Lisp_Fwd *valcontents = SYMBOL_FWD (sym);
+	if (KBOARD_OBJFWDP (valcontents))
+	  return Fframe_terminal (Fselected_frame ());
+	else if (!BUFFER_OBJFWDP (valcontents))
+	  return Qnil;
+      }
+      /* FALLTHROUGH */
+    case SYMBOL_LOCALIZED:
       /* For a local variable, record both the symbol and which
 	 buffer's or frame's value we are saving.  */
       if (!NILP (Flocal_variable_p (variable, Qnil)))
 	return Fcurrent_buffer ();
-      else if (BUFFER_LOCAL_VALUEP (valcontents)
-	       && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
-	return XBUFFER_LOCAL_VALUE (valcontents)->frame;
+      else if (sym->redirect == SYMBOL_LOCALIZED
+	       && BLV_FOUND (SYMBOL_BLV (sym)))
+	return SYMBOL_BLV (sym)->where;
+      else
+	return Qnil;
+    default: abort ();
     }
-
-  return Qnil;
 }
 
 /* This code is disabled now that we use the selected frame to return
--- a/src/dispextern.h	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/dispextern.h	Tue Apr 20 22:45:12 2010 +0000
@@ -1956,6 +1956,7 @@
   NUM_IT_METHODS
 };
 
+/* FIXME: What is this?  Why 5?  */
 #define IT_STACK_SIZE 5
 
 /* Iterator for composition (both for static and automatic).  */
--- a/src/dispnew.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/dispnew.c	Tue Apr 20 22:45:12 2010 +0000
@@ -4251,7 +4251,9 @@
 	     doesn't work with lbearing/rbearing), so we must do it
 	     this way.  */
 	  if (vpos == w->phys_cursor.vpos
-	      && w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])
+	      && (desired_row->reversed_p
+		  ? (w->phys_cursor.hpos < 0)
+		  : (w->phys_cursor.hpos >= desired_row->used[TEXT_AREA])))
 	    {
 	      w->phys_cursor_on_p = 0;
 	      x = -1;
@@ -4415,7 +4417,7 @@
     }
 
   /* Window cursor can be out of sync for horizontally split windows.  */
-  hpos = max (0, hpos);
+  hpos = max (-1, hpos); /* -1 is for when cursor is on the left fringe */
   hpos = min (w->current_matrix->matrix_w - 1, hpos);
   vpos = max (0, vpos);
   vpos = min (w->current_matrix->nrows - 1, vpos);
--- a/src/eval.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/eval.c	Tue Apr 20 22:45:12 2010 +0000
@@ -767,24 +767,46 @@
   CHECK_SYMBOL (new_alias);
   CHECK_SYMBOL (base_variable);
 
-  if (SYMBOL_CONSTANT_P (new_alias))
-    error ("Cannot make a constant an alias");
-
   sym = XSYMBOL (new_alias);
+
+  if (sym->constant)
+    if (sym->redirect == SYMBOL_VARALIAS)
+      sym->constant = 0;	/* Reset.  */
+    else
+      /* Not sure why.  */
+      error ("Cannot make a constant an alias");
+
+  switch (sym->redirect)
+    {
+    case SYMBOL_FORWARDED:
+      error ("Cannot make an internal variable an alias");
+    case SYMBOL_LOCALIZED:
+      error ("Don't know how to make a localized variable an alias");
+    }
+
   /* http://lists.gnu.org/archive/html/emacs-devel/2008-04/msg00834.html
-     If n_a is bound, but b_v is not, set the value of b_v to n_a.
-     This is for the sake of define-obsolete-variable-alias and user
-     customizations.  */
-  if (NILP (Fboundp (base_variable)) && !NILP (Fboundp (new_alias)))
-    XSYMBOL(base_variable)->value = sym->value;
-  sym->indirect_variable = 1;
-  sym->value = base_variable;
+     If n_a is bound, but b_v is not, set the value of b_v to n_a,
+     so that old-code that affects n_a before the aliasing is setup
+     still works.  */
+  if (NILP (Fboundp (base_variable)))
+    set_internal (base_variable, find_symbol_value (new_alias), NULL, 1);
+
+  {
+    struct specbinding *p;
+
+    for (p = specpdl_ptr - 1; p >= specpdl; p--)
+      if (p->func == NULL
+	  && (EQ (new_alias,
+		  CONSP (p->symbol) ? XCAR (p->symbol) : p->symbol)))
+	error ("Don't know how to make a let-bound variable an alias");
+  }
+
+  sym->redirect = SYMBOL_VARALIAS;
+  SET_SYMBOL_ALIAS (sym, XSYMBOL (base_variable));
   sym->constant = SYMBOL_CONSTANT_P (base_variable);
   LOADHIST_ATTACH (new_alias);
-  if (!NILP (docstring))
-    Fput (new_alias, Qvariable_documentation, docstring);
-  else
-    Fput (new_alias, Qvariable_documentation, Qnil);
+  /* Even if docstring is nil: remove old docstring.  */
+  Fput (new_alias, Qvariable_documentation, docstring);
 
   return base_variable;
 }
@@ -944,7 +966,7 @@
       return Qnil;
 
   /* If indirect and there's an alias loop, don't check anything else.  */
-  if (XSYMBOL (variable)->indirect_variable
+  if (XSYMBOL (variable)->redirect == SYMBOL_VARALIAS
       && NILP (internal_condition_case_1 (lisp_indirect_variable, variable,
                                           Qt, user_variable_p_eh)))
     return Qnil;
@@ -968,11 +990,11 @@
           || (!NILP (Fget (variable, intern ("custom-autoload")))))
         return Qt;
 
-      if (!XSYMBOL (variable)->indirect_variable)
+      if (!(XSYMBOL (variable)->redirect == SYMBOL_VARALIAS))
         return Qnil;
 
       /* An indirect variable?  Let's follow the chain.  */
-      variable = XSYMBOL (variable)->value;
+      XSETSYMBOL (variable, SYMBOL_ALIAS (XSYMBOL (variable)));
     }
 }
 
@@ -3263,78 +3285,94 @@
 specbind (symbol, value)
      Lisp_Object symbol, value;
 {
-  Lisp_Object valcontents;
+  struct Lisp_Symbol *sym;
+
+  eassert (!handling_signal);
 
   CHECK_SYMBOL (symbol);
+  sym = XSYMBOL (symbol);
   if (specpdl_ptr == specpdl + specpdl_size)
     grow_specpdl ();
 
-  /* The most common case is that of a non-constant symbol with a
-     trivial value.  Make that as fast as we can.  */
-  valcontents = SYMBOL_VALUE (symbol);
-  if (!MISCP (valcontents) && !SYMBOL_CONSTANT_P (symbol))
-    {
-      specpdl_ptr->symbol = symbol;
-      specpdl_ptr->old_value = valcontents;
-      specpdl_ptr->func = NULL;
-      ++specpdl_ptr;
-      SET_SYMBOL_VALUE (symbol, value);
-    }
-  else
+ start:
+  switch (sym->redirect)
     {
-      Lisp_Object ovalue = find_symbol_value (symbol);
-      specpdl_ptr->func = 0;
-      specpdl_ptr->old_value = ovalue;
-
-      valcontents = XSYMBOL (symbol)->value;
-
-      if (BUFFER_LOCAL_VALUEP (valcontents)
-	  || BUFFER_OBJFWDP (valcontents))
-	{
-	  Lisp_Object where, current_buffer;
-
-	  current_buffer = Fcurrent_buffer ();
-
-	  /* For a local variable, record both the symbol and which
-	     buffer's or frame's value we are saving.  */
-	  if (!NILP (Flocal_variable_p (symbol, Qnil)))
-	    where = current_buffer;
-	  else if (BUFFER_LOCAL_VALUEP (valcontents)
-		   && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame)
-	    where = XBUFFER_LOCAL_VALUE (valcontents)->frame;
+    case SYMBOL_VARALIAS:
+      sym = indirect_variable (sym); XSETSYMBOL (symbol, sym); goto start;
+    case SYMBOL_PLAINVAL:
+	{ /* The most common case is that of a non-constant symbol with a
+	     trivial value.  Make that as fast as we can.  */
+	  specpdl_ptr->symbol = symbol;
+	  specpdl_ptr->old_value = SYMBOL_VAL (sym);
+	  specpdl_ptr->func = NULL;
+	  ++specpdl_ptr;
+	  if (!sym->constant)
+	    SET_SYMBOL_VAL (sym, value);
 	  else
-	    where = Qnil;
-
-	  /* We're not using the `unused' slot in the specbinding
-	     structure because this would mean we have to do more
-	     work for simple variables.  */
-	  specpdl_ptr->symbol = Fcons (symbol, Fcons (where, current_buffer));
-
-	  /* If SYMBOL is a per-buffer variable which doesn't have a
-	     buffer-local value here, make the `let' change the global
-	     value by changing the value of SYMBOL in all buffers not
-	     having their own value.  This is consistent with what
-	     happens with other buffer-local variables.  */
-	  if (NILP (where)
-	      && BUFFER_OBJFWDP (valcontents))
-	    {
-	      ++specpdl_ptr;
-	      Fset_default (symbol, value);
-	      return;
-	    }
+	    set_internal (symbol, value, 0, 1);
+	  break;
 	}
-      else
-	specpdl_ptr->symbol = symbol;
-
-      specpdl_ptr++;
-      /* We used to do
-            if (BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue))
-	      store_symval_forwarding (symbol, ovalue, value, NULL);
-            else
-         but ovalue comes from find_symbol_value which should never return
-         such an internal value.  */
-      eassert (!(BUFFER_OBJFWDP (ovalue) || KBOARD_OBJFWDP (ovalue)));
-      set_internal (symbol, value, 0, 1);
+    case SYMBOL_LOCALIZED: case SYMBOL_FORWARDED:
+      {
+	Lisp_Object ovalue = find_symbol_value (symbol);
+	specpdl_ptr->func = 0;
+	specpdl_ptr->old_value = ovalue;
+
+	eassert (sym->redirect != SYMBOL_LOCALIZED
+		 || (EQ (SYMBOL_BLV (sym)->where,
+			 SYMBOL_BLV (sym)->frame_local ?
+			 Fselected_frame () : Fcurrent_buffer ())));
+
+	if (sym->redirect == SYMBOL_LOCALIZED
+	    || BUFFER_OBJFWDP (SYMBOL_FWD (sym)))
+	  {
+	    Lisp_Object where, cur_buf = Fcurrent_buffer ();
+
+	    /* For a local variable, record both the symbol and which
+	       buffer's or frame's value we are saving.  */
+	    if (!NILP (Flocal_variable_p (symbol, Qnil)))
+	      {
+		eassert (sym->redirect != SYMBOL_LOCALIZED
+			 || (BLV_FOUND (SYMBOL_BLV (sym))
+			     && EQ (cur_buf, SYMBOL_BLV (sym)->where)));
+		where = cur_buf;
+	      }
+	    else if (sym->redirect == SYMBOL_LOCALIZED
+		     && BLV_FOUND (SYMBOL_BLV (sym)))
+	      where = SYMBOL_BLV (sym)->where;
+	    else
+	      where = Qnil;
+
+	    /* We're not using the `unused' slot in the specbinding
+	       structure because this would mean we have to do more
+	       work for simple variables.  */
+	    /* FIXME: The third value `current_buffer' is only used in
+	       let_shadows_buffer_binding_p which is itself only used
+	       in set_internal for local_if_set.  */
+	    specpdl_ptr->symbol = Fcons (symbol, Fcons (where, cur_buf));
+
+	    /* If SYMBOL is a per-buffer variable which doesn't have a
+	       buffer-local value here, make the `let' change the global
+	       value by changing the value of SYMBOL in all buffers not
+	       having their own value.  This is consistent with what
+	       happens with other buffer-local variables.  */
+	    if (NILP (where)
+		&& sym->redirect == SYMBOL_FORWARDED)
+	      {
+		eassert (BUFFER_OBJFWDP (SYMBOL_FWD (sym)));
+		++specpdl_ptr;
+		Fset_default (symbol, value);
+		return;
+	      }
+	  }
+	else
+	  specpdl_ptr->symbol = symbol;
+
+	specpdl_ptr++;
+	set_internal (symbol, value, 0, 1);
+	break;
+      }
+    default: abort ();
     }
 }
 
@@ -3394,7 +3432,12 @@
 	  if (NILP (where))
 	    Fset_default (symbol, this_binding.old_value);
 	  else if (BUFFERP (where))
-	    set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
+	    if (!NILP (Flocal_variable_p (symbol, where)))
+	      set_internal (symbol, this_binding.old_value, XBUFFER (where), 1);
+	    /* else if (!NILP (Fbuffer_live_p (where)))
+	      error ("Unbinding local %s to global!", symbol); */
+            else
+              ;
 	  else
 	    set_internal (symbol, this_binding.old_value, NULL, 1);
 	}
@@ -3403,8 +3446,9 @@
 	  /* If variable has a trivial value (no forwarding), we can
 	     just set it.  No need to check for constant symbols here,
 	     since that was already done by specbind.  */
-	  if (!MISCP (SYMBOL_VALUE (this_binding.symbol)))
-	    SET_SYMBOL_VALUE (this_binding.symbol, this_binding.old_value);
+	  if (XSYMBOL (this_binding.symbol)->redirect == SYMBOL_PLAINVAL)
+	    SET_SYMBOL_VAL (XSYMBOL (this_binding.symbol),
+			    this_binding.old_value);
 	  else
 	    set_internal (this_binding.symbol, this_binding.old_value, 0, 1);
 	}
--- a/src/font.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/font.c	Tue Apr 20 22:45:12 2010 +0000
@@ -5376,22 +5376,30 @@
 gets the repertory information by an opened font and ENCODING.  */);
   Vfont_encoding_alist = Qnil;
 
+  /* FIXME: These 3 vars are not quite what they appear: setq on them
+     won't have any effect other than disconnect them from the style
+     table used by the font display code.  So we make them read-only,
+     to avoid this confusing situation.  */
+
   DEFVAR_LISP_NOPRO ("font-weight-table", &Vfont_weight_table,
 	       doc: /*  Vector of valid font weight values.
 Each element has the form:
     [NUMERIC-VALUE SYMBOLIC-NAME ALIAS-NAME ...]
 NUMERIC-VALUE is an integer, and SYMBOLIC-NAME and ALIAS-NAME are symbols. */);
   Vfont_weight_table = BUILD_STYLE_TABLE (weight_table);
+  XSYMBOL (intern_c_string ("font-weight-table"))->constant = 1;
 
   DEFVAR_LISP_NOPRO ("font-slant-table", &Vfont_slant_table,
 	       doc: /*  Vector of font slant symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_slant_table = BUILD_STYLE_TABLE (slant_table);
+  XSYMBOL (intern_c_string ("font-slant-table"))->constant = 1;
 
   DEFVAR_LISP_NOPRO ("font-width-table", &Vfont_width_table,
 	       doc: /*  Alist of font width symbols vs the corresponding numeric values.
 See `font-weight-table' for the format of the vector. */);
   Vfont_width_table = BUILD_STYLE_TABLE (width_table);
+  XSYMBOL (intern_c_string ("font-width-table"))->constant = 1;
 
   staticpro (&font_style_table);
   font_style_table = Fmake_vector (make_number (3), Qnil);
--- a/src/frame.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/frame.c	Tue Apr 20 22:45:12 2010 +0000
@@ -2298,13 +2298,20 @@
      without messing up the symbol's status.  */
   if (SYMBOLP (prop))
     {
-      Lisp_Object valcontents;
-      valcontents = SYMBOL_VALUE (prop);
-      if ((BUFFER_LOCAL_VALUEP (valcontents))
-	  && XBUFFER_LOCAL_VALUE (valcontents)->check_frame
-	  && XBUFFER_LOCAL_VALUE (valcontents)->found_for_frame
- 	  && XFRAME (XBUFFER_LOCAL_VALUE (valcontents)->frame) == f)
- 	swap_in_global_binding (prop);
+      struct Lisp_Symbol *sym = XSYMBOL (prop);
+    start:
+      switch (sym->redirect)
+	{
+	case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
+	case SYMBOL_PLAINVAL: case SYMBOL_FORWARDED: break;
+	case SYMBOL_LOCALIZED:
+	  { struct Lisp_Buffer_Local_Value *blv = sym->val.blv;
+	    if (blv->frame_local && BLV_FOUND (blv) && XFRAME (blv->where) == f)
+	      swap_in_global_binding (sym);
+	    break;
+	  }
+	default: abort ();
+	}
     }
 
   /* The tty color needed to be set before the frame's parameter
@@ -2520,6 +2527,8 @@
 	       || EQ (parameter, Qbackground_mode))
 	value = Fcdr (Fassq (parameter, f->param_alist));
       else
+	/* FIXME: Avoid this code path at all (as well as code duplication)
+	   by sharing more code with Fframe_parameters.  */
 	value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
     }
 
--- a/src/fringe.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/fringe.c	Tue Apr 20 22:45:12 2010 +0000
@@ -825,7 +825,7 @@
 {
   int overlay = 0;
 
-  if (!left_p && row->cursor_in_fringe_p)
+  if (left_p == row->reversed_p && row->cursor_in_fringe_p)
     {
       Lisp_Object cursor = Qnil;
 
@@ -857,7 +857,7 @@
 	  int bm = get_logical_cursor_bitmap (w, cursor);
 	  if (bm != NO_FRINGE_BITMAP)
 	    {
-	      draw_fringe_bitmap_1 (w, row, 0, 2, bm);
+	      draw_fringe_bitmap_1 (w, row, left_p, 2, bm);
 	      overlay = EQ (cursor, Qbox) ? 3 : 1;
 	    }
 	}
@@ -1090,7 +1090,8 @@
 		: LEFT_FRINGE (2, Qtop, 0));
       else if (row->indicate_eob_p && EQ (boundary_bot, Qleft))
 	left = LEFT_FRINGE (3, Qbottom, row->ends_at_zv_p);
-      else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
+      else if ((!row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row))
+	       || (row->reversed_p && row->continued_p))
 	left = LEFT_FRINGE (4, Qcontinuation, 0);
       else if (row->indicate_empty_line_p && EQ (empty_pos, Qleft))
 	left = LEFT_FRINGE (5, Qempty_line, 0);
@@ -1117,7 +1118,8 @@
 		 : RIGHT_FRINGE (2, Qtop, 0));
       else if (row->indicate_eob_p && EQ (boundary_bot, Qright))
 	right = RIGHT_FRINGE (3, Qbottom, row->ends_at_zv_p);
-      else if (row->continued_p)
+      else if ((!row->reversed_p && row->continued_p)
+	       || (row->reversed_p && MATRIX_ROW_CONTINUATION_LINE_P (row)))
 	right = RIGHT_FRINGE (4, Qcontinuation, 0);
       else if (row->indicate_top_line_p && EQ (arrow_top, Qright))
 	right = RIGHT_FRINGE (6, Qup, 0);
--- a/src/gtkutil.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/gtkutil.c	Tue Apr 20 22:45:12 2010 +0000
@@ -3371,8 +3371,8 @@
                || event->type == MotionNotify))
     {
       /* If we are releasing or moving the scroll bar, it has the grab.  */
-      retval = gtk_grab_get_current () != 0
-        && gtk_grab_get_current () != f->output_data.x->edit_widget;
+      GtkWidget *w = gtk_grab_get_current ();
+      retval = w != 0 && GTK_IS_SCROLLBAR (w);
     }
   
   return retval;
--- a/src/insdel.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/insdel.c	Tue Apr 20 22:45:12 2010 +0000
@@ -54,7 +54,7 @@
 Lisp_Object Fcombine_after_change_execute ();
 
 /* Non-nil means don't call the after-change-functions right away,
-   just record an element in Vcombine_after_change_calls_list.  */
+   just record an element in combine_after_change_list.  */
 Lisp_Object Vcombine_after_change_calls;
 
 /* List of elements of the form (BEG-UNCHANGED END-UNCHANGED CHANGE-AMOUNT)
--- a/src/keyboard.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/keyboard.c	Tue Apr 20 22:45:12 2010 +0000
@@ -1520,7 +1520,6 @@
 command_loop_1 ()
 {
   Lisp_Object cmd;
-  int lose;
   Lisp_Object keybuf[30];
   int i;
   int prev_modiff = 0;
--- a/src/lisp.h	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/lisp.h	Tue Apr 20 22:45:12 2010 +0000
@@ -223,13 +223,7 @@
   {
     Lisp_Misc_Free = 0x5eab,
     Lisp_Misc_Marker,
-    Lisp_Misc_Intfwd,
-    Lisp_Misc_Boolfwd,
-    Lisp_Misc_Objfwd,
-    Lisp_Misc_Buffer_Objfwd,
-    Lisp_Misc_Buffer_Local_Value,
     Lisp_Misc_Overlay,
-    Lisp_Misc_Kboard_Objfwd,
     Lisp_Misc_Save_Value,
     /* Currently floats are not a misc type,
        but let's define this in case we want to change that.  */
@@ -238,6 +232,18 @@
     Lisp_Misc_Limit
   };
 
+/* These are the types of forwarding objects used in the value slot
+   of symbols for special built-in variables whose value is stored in
+   C variables.  */
+enum Lisp_Fwd_Type
+  {
+    Lisp_Fwd_Int,		/* Fwd to a C `int' variable.  */
+    Lisp_Fwd_Bool,		/* Fwd to a C boolean var.  */
+    Lisp_Fwd_Obj,		/* Fwd to a C Lisp_Object variable.  */
+    Lisp_Fwd_Buffer_Obj,	/* Fwd to a Lisp_Object field of buffers.  */
+    Lisp_Fwd_Kboard_Obj,	/* Fwd to a Lisp_Object field of kboards.  */
+  };
+
 #ifndef GCTYPEBITS
 #define GCTYPEBITS 3
 #endif
@@ -566,17 +572,19 @@
 #define XMISCANY(a)	(eassert (MISCP (a)), &(XMISC(a)->u_any))
 #define XMISCTYPE(a)   (XMISCANY (a)->type)
 #define XMARKER(a)	(eassert (MARKERP (a)), &(XMISC(a)->u_marker))
-#define XINTFWD(a)	(eassert (INTFWDP (a)), &(XMISC(a)->u_intfwd))
-#define XBOOLFWD(a)	(eassert (BOOLFWDP (a)), &(XMISC(a)->u_boolfwd))
-#define XOBJFWD(a)	(eassert (OBJFWDP (a)), &(XMISC(a)->u_objfwd))
 #define XOVERLAY(a)	(eassert (OVERLAYP (a)), &(XMISC(a)->u_overlay))
 #define XSAVE_VALUE(a)	(eassert (SAVE_VALUEP (a)), &(XMISC(a)->u_save_value))
+
+/* Forwarding object types.  */
+
+#define XFWDTYPE(a)     (a->u_intfwd.type)
+#define XINTFWD(a)	(eassert (INTFWDP (a)), &((a)->u_intfwd))
+#define XBOOLFWD(a)	(eassert (BOOLFWDP (a)), &((a)->u_boolfwd))
+#define XOBJFWD(a)	(eassert (OBJFWDP (a)), &((a)->u_objfwd))
 #define XBUFFER_OBJFWD(a) \
-  (eassert (BUFFER_OBJFWDP (a)), &(XMISC(a)->u_buffer_objfwd))
-#define XBUFFER_LOCAL_VALUE(a) \
-  (eassert (BUFFER_LOCAL_VALUEP (a)), &(XMISC(a)->u_buffer_local_value))
+  (eassert (BUFFER_OBJFWDP (a)), &((a)->u_buffer_objfwd))
 #define XKBOARD_OBJFWD(a) \
-  (eassert (KBOARD_OBJFWDP (a)), &(XMISC(a)->u_kboard_objfwd))
+  (eassert (KBOARD_OBJFWDP (a)), &((a)->u_kboard_objfwd))
 
 /* Pseudovector types.  */
 
@@ -988,19 +996,32 @@
   SYMBOL_INTERNED_IN_INITIAL_OBARRAY = 2
 };
 
+enum symbol_redirect
+{
+  SYMBOL_PLAINVAL  = 4,
+  SYMBOL_VARALIAS  = 1,
+  SYMBOL_LOCALIZED = 2,
+  SYMBOL_FORWARDED   = 3
+};
+
 /* In a symbol, the markbit of the plist is used as the gc mark bit */
 
 struct Lisp_Symbol
 {
   unsigned gcmarkbit : 1;
 
-  /* Non-zero means symbol serves as a variable alias.  The symbol
-     holding the real value is found in the value slot.  */
-  unsigned indirect_variable : 1;
+  /* Indicates where the value can be found:
+     0 : it's a plain var, the value is in the `value' field.
+     1 : it's a varalias, the value is really in the `alias' symbol.
+     2 : it's a localized var, the value is in the `blv' object.
+     3 : it's a forwarding variable, the value is in `forward'.
+   */
+  enum symbol_redirect redirect : 3;
 
   /* Non-zero means symbol is constant, i.e. changing its value
-     should signal an error.  */
-  unsigned constant : 1;
+     should signal an error.  If the value is 3, then the var
+     can be changed, but only by `defconst'.  */
+  unsigned constant : 2;
 
   /* Interned state of the symbol.  This is an enumerator from
      enum symbol_interned.  */
@@ -1013,10 +1034,15 @@
   Lisp_Object xname;
 
   /* Value of the symbol or Qunbound if unbound.  If this symbol is a
-     defvaralias, `value' contains the symbol for which it is an
+     defvaralias, `alias' contains the symbol for which it is an
      alias.  Use the SYMBOL_VALUE and SET_SYMBOL_VALUE macros to get
      and set a symbol's value, to take defvaralias into account.  */
-  Lisp_Object value;
+  union {
+    Lisp_Object value;
+    struct Lisp_Symbol *alias;
+    struct Lisp_Buffer_Local_Value *blv;
+    union Lisp_Fwd *fwd;
+  } val;
 
   /* Function value of the symbol or Qunbound if not fboundp.  */
   Lisp_Object function;
@@ -1030,6 +1056,23 @@
 
 /* Value is name of symbol.  */
 
+#define SYMBOL_VAL(sym)   \
+  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value)
+#define SYMBOL_ALIAS(sym) \
+  (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias)
+#define SYMBOL_BLV(sym)   \
+  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv)
+#define SYMBOL_FWD(sym)   \
+  (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd)
+#define SET_SYMBOL_VAL(sym, v)     \
+  (eassert ((sym)->redirect == SYMBOL_PLAINVAL),  (sym)->val.value = (v))
+#define SET_SYMBOL_ALIAS(sym, v)   \
+  (eassert ((sym)->redirect == SYMBOL_VARALIAS),  (sym)->val.alias = (v))
+#define SET_SYMBOL_BLV(sym, v)     \
+  (eassert ((sym)->redirect == SYMBOL_LOCALIZED), (sym)->val.blv = (v))
+#define SET_SYMBOL_FWD(sym, v) \
+  (eassert ((sym)->redirect == SYMBOL_FORWARDED), (sym)->val.fwd = (v))
+
 #define SYMBOL_NAME(sym)  \
      LISP_MAKE_RVALUE (XSYMBOL (sym)->xname)
 
@@ -1049,24 +1092,6 @@
 
 #define SYMBOL_CONSTANT_P(sym)   XSYMBOL (sym)->constant
 
-/* Value is the value of SYM, with defvaralias taken into
-   account.  */
-
-#define SYMBOL_VALUE(sym)			\
-   (XSYMBOL (sym)->indirect_variable		\
-    ? indirect_variable (XSYMBOL (sym))->value	\
-    : XSYMBOL (sym)->value)
-
-/* Set SYM's value to VAL, taking defvaralias into account.  */
-
-#define SET_SYMBOL_VALUE(sym, val)				\
-     do {							\
-       if (XSYMBOL (sym)->indirect_variable)			\
-	 indirect_variable (XSYMBOL (sym))->value = (val);	\
-       else							\
-	 XSYMBOL (sym)->value = (val);				\
-     } while (0)
-
 
 /***********************************************************************
 			     Hash Tables
@@ -1200,9 +1225,11 @@
 
 struct Lisp_Misc_Any		/* Supertype of all Misc types.  */
 {
-  enum Lisp_Misc_Type type : 16;		/* = Lisp_Misc_Marker */
+  enum Lisp_Misc_Type type : 16;		/* = Lisp_Misc_??? */
   unsigned gcmarkbit : 1;
   int spacer : 15;
+  /* Make it as long as "Lisp_Free without padding". */
+  void *fill;
 };
 
 struct Lisp_Marker
@@ -1225,7 +1252,7 @@
      - Fmarker_buffer
      - Fset_marker: check eq(oldbuf, newbuf) to avoid unchain+rechain.
      - unchain_marker: to find the list from which to unchain.
-     - Fkill_buffer: to unchain the markers of current indirect buffer.
+     - Fkill_buffer: to only unchain the markers of current indirect buffer.
      */
   struct buffer *buffer;
 
@@ -1239,7 +1266,10 @@
   struct Lisp_Marker *next;
   /* This is the char position where the marker points.  */
   EMACS_INT charpos;
-  /* This is the byte position.  */
+  /* This is the byte position.
+     It's mostly used as a charpos<->bytepos cache (i.e. it's not directly
+     used to implement the functionality of markers, but rather to (ab)use
+     markers as a cache for char<->byte mappings).  */
   EMACS_INT bytepos;
 };
 
@@ -1249,9 +1279,7 @@
    specified int variable.  */
 struct Lisp_Intfwd
   {
-    int type : 16;	/* = Lisp_Misc_Intfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;	/* = Lisp_Fwd_Int */
     EMACS_INT *intvar;
   };
 
@@ -1261,9 +1289,7 @@
    nil if it is zero.  */
 struct Lisp_Boolfwd
   {
-    int type : 16;	/* = Lisp_Misc_Boolfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;	/* = Lisp_Fwd_Bool */
     int *boolvar;
   };
 
@@ -1273,9 +1299,7 @@
    specified variable.  */
 struct Lisp_Objfwd
   {
-    int type : 16;	/* = Lisp_Misc_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;	/* = Lisp_Fwd_Obj */
     Lisp_Object *objvar;
   };
 
@@ -1283,11 +1307,9 @@
    current buffer.  Value is byte index of slot within buffer.  */
 struct Lisp_Buffer_Objfwd
   {
-    int type : 16;	/* = Lisp_Misc_Buffer_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;	/* = Lisp_Fwd_Buffer_Obj */
+    int offset;
     Lisp_Object slottype; /* Qnil, Lisp_Int, Lisp_Symbol, or Lisp_String.  */
-    int offset;
   };
 
 /* struct Lisp_Buffer_Local_Value is used in a symbol value cell when
@@ -1316,48 +1338,51 @@
 
 struct Lisp_Buffer_Local_Value
   {
-    int type : 16;      /* = Lisp_Misc_Buffer_Local_Value  */
-    unsigned gcmarkbit : 1;
-    int spacer : 11;
-
     /* 1 means that merely setting the variable creates a local
        binding for the current buffer */
     unsigned int local_if_set : 1;
-    /* 1 means this variable is allowed to have frame-local bindings,
-       so check for them when looking for the proper binding.  */
-    unsigned int check_frame : 1;
-    /* 1 means that the binding now loaded was found
-       as a local binding for the buffer in the `buffer' slot.  */
-    unsigned int found_for_buffer : 1;
-    /* 1 means that the binding now loaded was found
-       as a local binding for the frame in the `frame' slot.  */
-    unsigned int found_for_frame : 1;
-    Lisp_Object realvalue;
-    /* The buffer and frame for which the loaded binding was found.  */
-    /* Having both is only needed if we want to allow variables that are
-       both buffer local and frame local (in which case, we currently give
-       precedence to the buffer-local binding).  I don't think such
-       a combination is desirable.  --Stef  */
-    Lisp_Object buffer, frame;
-
-    /* A cons cell, (LOADED-BINDING . DEFAULT-VALUE).
-
-       LOADED-BINDING is the binding now loaded.  It is a cons cell
-       whose cdr is the binding's value.  The cons cell may be an
-       element of a buffer's local-variable alist, or an element of a
-       frame's parameter alist, or it may be this cons cell.
-
-       DEFAULT-VALUE is the variable's default value, seen when the
-       current buffer and selected frame do not have their own
-       bindings for the variable.  When the default binding is loaded,
-       LOADED-BINDING is actually this very cons cell; thus, its car
-       points to itself.  */
-    Lisp_Object cdr;
+    /* 1 means this variable can have frame-local bindings, otherwise, it is
+       can have buffer-local bindings.  The two cannot be combined.  */
+    unsigned int frame_local : 1;
+    /* 1 means that the binding now loaded was found.
+       Presumably equivalent to (defcell!=valcell) */
+    unsigned int found : 1;
+    /* If non-NULL, a forwarding to the C var where it should also be set.  */
+    union Lisp_Fwd *fwd;	/* Should never be (Buffer|Kboard)_Objfwd.  */
+    /* The buffer or frame for which the loaded binding was found.  */
+    Lisp_Object where;
+    /* A cons cell that holds the default value.  It has the form
+       (SYMBOL . DEFAULT-VALUE).  */
+    Lisp_Object defcell;
+    /* The cons cell from `where's parameter alist.
+       It always has the form (SYMBOL . VALUE)
+       Note that if `forward' is non-nil, VALUE may be out of date.
+       Also if the currently loaded binding is the default binding, then
+       this is `eq'ual to defcell.  */
+    Lisp_Object valcell;
   };
 
+#define BLV_FOUND(blv) \
+  (eassert ((blv)->found == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found)
+#define SET_BLV_FOUND(blv, v) \
+  (eassert ((v) == !EQ ((blv)->defcell, (blv)->valcell)), (blv)->found = (v))
+
+#define BLV_VALUE(blv) (XCDR ((blv)->valcell))
+#define SET_BLV_VALUE(blv, v) (XSETCDR ((blv)->valcell, v))
+
 /* START and END are markers in the overlay's buffer, and
    PLIST is the overlay's property list.  */
 struct Lisp_Overlay
+/* An overlay's real data content is:
+   - plist
+   - buffer
+   - insertion type of both ends
+   - start & start_byte
+   - end & end_byte
+   - next (singly linked list of overlays).
+   - start_next and end_next (singly linked list of markers).
+   I.e. 9words plus 2 bits, 3words of which are for external linked lists.
+*/
   {
     enum Lisp_Misc_Type type : 16;	/* = Lisp_Misc_Overlay */
     unsigned gcmarkbit : 1;
@@ -1370,9 +1395,7 @@
    current kboard.  */
 struct Lisp_Kboard_Objfwd
   {
-    enum Lisp_Misc_Type type : 16;	/* = Lisp_Misc_Kboard_Objfwd */
-    unsigned gcmarkbit : 1;
-    int spacer : 15;
+    enum Lisp_Fwd_Type type;	/* = Lisp_Fwd_Kboard_Obj */
     int offset;
   };
 
@@ -1401,9 +1424,9 @@
 #ifdef USE_LSB_TAG
     /* Try to make sure that sizeof(Lisp_Misc) preserves TYPEBITS-alignment.
        This assumes that Lisp_Marker is the largest of the alternatives and
-       that Lisp_Intfwd has the same size as "Lisp_Free w/o padding".  */
+       that Lisp_Misc_Any has the same size as "Lisp_Free w/o padding".  */
     char padding[((((sizeof (struct Lisp_Marker) - 1) >> GCTYPEBITS) + 1)
-		  << GCTYPEBITS) - sizeof (struct Lisp_Intfwd)];
+		  << GCTYPEBITS) - sizeof (struct Lisp_Misc_Any)];
 #endif
   };
 
@@ -1414,15 +1437,18 @@
   {
     struct Lisp_Misc_Any u_any;	   /* Supertype of all Misc types.  */
     struct Lisp_Free u_free;	   /* Includes padding to force alignment.  */
-    struct Lisp_Marker u_marker;
-    struct Lisp_Intfwd u_intfwd;
-    struct Lisp_Boolfwd u_boolfwd;
-    struct Lisp_Objfwd u_objfwd;
-    struct Lisp_Buffer_Objfwd u_buffer_objfwd;
-    struct Lisp_Buffer_Local_Value u_buffer_local_value;
-    struct Lisp_Overlay u_overlay;
-    struct Lisp_Kboard_Objfwd u_kboard_objfwd;
-    struct Lisp_Save_Value u_save_value;
+    struct Lisp_Marker u_marker;			 /* 5 */
+    struct Lisp_Overlay u_overlay;			 /* 5 */
+    struct Lisp_Save_Value u_save_value;		 /* 3 */
+  };
+
+union Lisp_Fwd
+  {
+    struct Lisp_Intfwd u_intfwd;			 /* 2 */
+    struct Lisp_Boolfwd u_boolfwd;			 /* 2 */
+    struct Lisp_Objfwd u_objfwd;			 /* 2 */
+    struct Lisp_Buffer_Objfwd u_buffer_objfwd;		 /* 2 */
+    struct Lisp_Kboard_Objfwd u_kboard_objfwd;		 /* 2 */
   };
 
 /* Lisp floating point type */
@@ -1564,15 +1590,13 @@
 #define VECTORP(x)    (VECTORLIKEP (x) && !(XVECTOR (x)->size & PSEUDOVECTOR_FLAG))
 #define OVERLAYP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Overlay)
 #define MARKERP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Marker)
-#define INTFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Intfwd)
-#define BOOLFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Boolfwd)
-#define OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Objfwd)
-#define BUFFER_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Objfwd)
-#define BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Buffer_Local_Value)
-#define SOME_BUFFER_LOCAL_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Some_Buffer_Local_Value)
-#define KBOARD_OBJFWDP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Kboard_Objfwd)
 #define SAVE_VALUEP(x) (MISCP (x) && XMISCTYPE (x) == Lisp_Misc_Save_Value)
 
+#define INTFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Int)
+#define BOOLFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Bool)
+#define OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Obj)
+#define BUFFER_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Buffer_Obj)
+#define KBOARD_OBJFWDP(x) (XFWDTYPE (x) == Lisp_Fwd_Kboard_Obj)
 
 /* True if object X is a pseudovector whose code is CODE.  */
 #define PSEUDOVECTORP(x, code)					\
@@ -1789,24 +1813,44 @@
 #define MANY -2
 #define UNEVALLED -1
 
-extern void defvar_lisp (const char *, Lisp_Object *);
-extern void defvar_lisp_nopro (const char *, Lisp_Object *);
-extern void defvar_bool (const char *, int *);
-extern void defvar_int (const char *, EMACS_INT *);
-extern void defvar_kboard (const char *, int);
+extern void defvar_lisp (struct Lisp_Objfwd *, const char *, Lisp_Object *);
+extern void defvar_lisp_nopro (struct Lisp_Objfwd *, const char *, Lisp_Object *);
+extern void defvar_bool (struct Lisp_Boolfwd *, const char *, int *);
+extern void defvar_int (struct Lisp_Intfwd *, const char *, EMACS_INT *);
+extern void defvar_kboard (struct Lisp_Kboard_Objfwd *, const char *, int);
 
 /* Macros we use to define forwarded Lisp variables.
    These are used in the syms_of_FILENAME functions.  */
 
-#define DEFVAR_LISP(lname, vname, doc) defvar_lisp (lname, vname)
-#define DEFVAR_LISP_NOPRO(lname, vname, doc) defvar_lisp_nopro (lname, vname)
-#define DEFVAR_BOOL(lname, vname, doc) defvar_bool (lname, vname)
-#define DEFVAR_INT(lname, vname, doc) defvar_int (lname, vname)
-
-#define DEFVAR_KBOARD(lname, vname, doc) \
- defvar_kboard (lname, \
-		(int)((char *)(&current_kboard->vname) \
-		      - (char *)current_kboard))
+#define DEFVAR_LISP(lname, vname, doc)		\
+  do {						\
+    static struct Lisp_Objfwd o_fwd;		\
+    defvar_lisp (&o_fwd, lname, vname);		\
+  } while (0)
+#define DEFVAR_LISP_NOPRO(lname, vname, doc)	\
+  do {						\
+    static struct Lisp_Objfwd o_fwd;		\
+    defvar_lisp_nopro (&o_fwd, lname, vname);	\
+  } while (0)
+#define DEFVAR_BOOL(lname, vname, doc)		\
+  do {						\
+    static struct Lisp_Boolfwd b_fwd;		\
+    defvar_bool (&b_fwd, lname, vname);		\
+  } while (0)
+#define DEFVAR_INT(lname, vname, doc)		\
+  do {						\
+    static struct Lisp_Intfwd i_fwd;		\
+    defvar_int (&i_fwd, lname, vname);		\
+  } while (0)
+
+#define DEFVAR_KBOARD(lname, vname, doc)			\
+  do {								\
+    static struct Lisp_Kboard_Objfwd ko_fwd;			\
+    defvar_kboard (&ko_fwd,					\
+		   lname,					\
+		   (int)((char *)(&current_kboard->vname)	\
+			 - (char *)current_kboard));		\
+  } while (0)
 
 
 
@@ -2341,13 +2385,11 @@
 extern void args_out_of_range_3 P_ ((Lisp_Object, Lisp_Object,
 				     Lisp_Object)) NO_RETURN;
 extern Lisp_Object wrong_type_argument P_ ((Lisp_Object, Lisp_Object)) NO_RETURN;
-extern void store_symval_forwarding P_ ((Lisp_Object, Lisp_Object,
-					 Lisp_Object, struct buffer *));
-extern Lisp_Object do_symval_forwarding P_ ((Lisp_Object));
-extern Lisp_Object set_internal P_ ((Lisp_Object, Lisp_Object, struct buffer *, int));
+extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *);
+extern void set_internal (Lisp_Object, Lisp_Object, struct buffer *, int);
 extern void syms_of_data P_ ((void));
 extern void init_data P_ ((void));
-extern void swap_in_global_binding P_ ((Lisp_Object));
+extern void swap_in_global_binding P_ ((struct Lisp_Symbol *));
 
 /* Defined in cmds.c */
 EXFUN (Fend_of_line, 1);
@@ -3388,6 +3430,7 @@
 extern void fatal P_ ((const char *msgid, ...)) NO_RETURN;
 
 /* Defined in terminal.c */
+EXFUN (Fframe_terminal, 1);
 EXFUN (Fdelete_terminal, 2);
 extern void syms_of_terminal P_ ((void));
 
--- a/src/lread.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/lread.c	Tue Apr 20 22:45:12 2010 +0000
@@ -3687,7 +3687,8 @@
       && EQ (obarray, initial_obarray))
     {
       XSYMBOL (sym)->constant = 1;
-      XSYMBOL (sym)->value = sym;
+      XSYMBOL (sym)->redirect = SYMBOL_PLAINVAL;
+      SET_SYMBOL_VAL (XSYMBOL (sym), sym);
     }
 
   ptr = &XVECTOR (obarray)->contents[XINT (tem)];
@@ -3768,8 +3769,6 @@
        error ("Attempt to unintern t or nil"); */
 
   XSYMBOL (tem)->interned = SYMBOL_UNINTERNED;
-  XSYMBOL (tem)->constant = 0;
-  XSYMBOL (tem)->indirect_variable = 0;
 
   hash = oblookup_last_bucket_number;
 
@@ -3914,35 +3913,31 @@
 init_obarray ()
 {
   Lisp_Object oblength;
-  int hash;
-  Lisp_Object *tem;
 
   XSETFASTINT (oblength, OBARRAY_SIZE);
 
-  Qnil = Fmake_symbol (make_pure_c_string ("nil"));
   Vobarray = Fmake_vector (oblength, make_number (0));
   initial_obarray = Vobarray;
   staticpro (&initial_obarray);
-  /* Intern nil in the obarray */
-  XSYMBOL (Qnil)->interned = SYMBOL_INTERNED_IN_INITIAL_OBARRAY;
-  XSYMBOL (Qnil)->constant = 1;
-
-  /* These locals are to kludge around a pyramid compiler bug. */
-  hash = hash_string ("nil", 3);
-  /* Separate statement here to avoid VAXC bug. */
-  hash %= OBARRAY_SIZE;
-  tem = &XVECTOR (Vobarray)->contents[hash];
-  *tem = Qnil;
 
   Qunbound = Fmake_symbol (make_pure_c_string ("unbound"));
-  XSYMBOL (Qnil)->function = Qunbound;
-  XSYMBOL (Qunbound)->value = Qunbound;
+  /* Set temporary dummy values to Qnil and Vpurify_flag to satisfy the
+     NILP (Vpurify_flag) check in intern_c_string.  */
+  Qnil = make_number (-1); Vpurify_flag = make_number (1);
+  Qnil = intern_c_string ("nil");
+
+  /* Fmake_symbol inits fields of new symbols with Qunbound and Qnil,
+     so those two need to be fixed manally.  */
+  SET_SYMBOL_VAL (XSYMBOL (Qunbound), Qunbound);
   XSYMBOL (Qunbound)->function = Qunbound;
+  XSYMBOL (Qunbound)->plist = Qnil;
+  /* XSYMBOL (Qnil)->function = Qunbound; */
+  SET_SYMBOL_VAL (XSYMBOL (Qnil), Qnil);
+  XSYMBOL (Qnil)->constant = 1;
+  XSYMBOL (Qnil)->plist = Qnil;
 
   Qt = intern_c_string ("t");
-  XSYMBOL (Qnil)->value = Qnil;
-  XSYMBOL (Qnil)->plist = Qnil;
-  XSYMBOL (Qt)->value = Qt;
+  SET_SYMBOL_VAL (XSYMBOL (Qt), Qt);
   XSYMBOL (Qt)->constant = 1;
 
   /* Qt is correct even if CANNOT_DUMP.  loadup.el will set to nil at end.  */
@@ -3981,27 +3976,29 @@
    to a C variable of type int.  Sample call:
    DEFVAR_INT ("emacs-priority", &emacs_priority, "Documentation");  */
 void
-defvar_int (const char *namestring, EMACS_INT *address)
+defvar_int (struct Lisp_Intfwd *i_fwd,
+	    const char *namestring, EMACS_INT *address)
 {
-  Lisp_Object sym, val;
+  Lisp_Object sym;
   sym = intern_c_string (namestring);
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Intfwd;
-  XINTFWD (val)->intvar = address;
-  SET_SYMBOL_VALUE (sym, val);
+  i_fwd->type = Lisp_Fwd_Int;
+  i_fwd->intvar = address;
+  XSYMBOL (sym)->redirect = SYMBOL_FORWARDED;
+  SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)i_fwd);
 }
 
 /* Similar but define a variable whose value is t if address contains 1,
    nil if address contains 0.  */
 void
-defvar_bool (const char *namestring, int *address)
+defvar_bool (struct Lisp_Boolfwd *b_fwd,
+	     const char *namestring, int *address)
 {
-  Lisp_Object sym, val;
+  Lisp_Object sym;
   sym = intern_c_string (namestring);
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Boolfwd;
-  XBOOLFWD (val)->boolvar = address;
-  SET_SYMBOL_VALUE (sym, val);
+  b_fwd->type = Lisp_Fwd_Bool;
+  b_fwd->boolvar = address;
+  XSYMBOL (sym)->redirect = SYMBOL_FORWARDED;
+  SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)b_fwd);
   Vbyte_boolean_vars = Fcons (sym, Vbyte_boolean_vars);
 }
 
@@ -4011,20 +4008,22 @@
    gc-marked for some other reason, since marking the same slot twice
    can cause trouble with strings.  */
 void
-defvar_lisp_nopro (const char *namestring, Lisp_Object *address)
+defvar_lisp_nopro (struct Lisp_Objfwd *o_fwd,
+		   const char *namestring, Lisp_Object *address)
 {
-  Lisp_Object sym, val;
+  Lisp_Object sym;
   sym = intern_c_string (namestring);
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Objfwd;
-  XOBJFWD (val)->objvar = address;
-  SET_SYMBOL_VALUE (sym, val);
+  o_fwd->type = Lisp_Fwd_Obj;
+  o_fwd->objvar = address;
+  XSYMBOL (sym)->redirect = SYMBOL_FORWARDED;
+  SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)o_fwd);
 }
 
 void
-defvar_lisp (const char *namestring, Lisp_Object *address)
+defvar_lisp (struct Lisp_Objfwd *o_fwd,
+	     const char *namestring, Lisp_Object *address)
 {
-  defvar_lisp_nopro (namestring, address);
+  defvar_lisp_nopro (o_fwd, namestring, address);
   staticpro (address);
 }
 
@@ -4032,14 +4031,15 @@
    at a particular offset in the current kboard object.  */
 
 void
-defvar_kboard (const char *namestring, int offset)
+defvar_kboard (struct Lisp_Kboard_Objfwd *ko_fwd,
+	       const char *namestring, int offset)
 {
-  Lisp_Object sym, val;
+  Lisp_Object sym;
   sym = intern_c_string (namestring);
-  val = allocate_misc ();
-  XMISCTYPE (val) = Lisp_Misc_Kboard_Objfwd;
-  XKBOARD_OBJFWD (val)->offset = offset;
-  SET_SYMBOL_VALUE (sym, val);
+  ko_fwd->type = Lisp_Fwd_Kboard_Obj;
+  ko_fwd->offset = offset;
+  XSYMBOL (sym)->redirect = SYMBOL_FORWARDED;
+  SET_SYMBOL_FWD (XSYMBOL (sym), (union Lisp_Fwd *)ko_fwd);
 }
 
 /* Record the value of load-path used at the start of dumping
--- a/src/print.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/print.c	Tue Apr 20 22:45:12 2010 +0000
@@ -2267,70 +2267,6 @@
 	  strout ("#<misc free cell>", -1, -1, printcharfun, 0);
 	  break;
 
-	case Lisp_Misc_Intfwd:
-	  sprintf (buf, "#<intfwd to %ld>", (long) *XINTFWD (obj)->intvar);
-	  strout (buf, -1, -1, printcharfun, 0);
-	  break;
-
-	case Lisp_Misc_Boolfwd:
-	  sprintf (buf, "#<boolfwd to %s>",
-		   (*XBOOLFWD (obj)->boolvar ? "t" : "nil"));
-	  strout (buf, -1, -1, printcharfun, 0);
-	  break;
-
-	case Lisp_Misc_Objfwd:
-	  strout ("#<objfwd to ", -1, -1, printcharfun, 0);
-	  print_object (*XOBJFWD (obj)->objvar, printcharfun, escapeflag);
-	  PRINTCHAR ('>');
-	  break;
-
-	case Lisp_Misc_Buffer_Objfwd:
-	  strout ("#<buffer_objfwd to ", -1, -1, printcharfun, 0);
-	  print_object (PER_BUFFER_VALUE (current_buffer,
-					  XBUFFER_OBJFWD (obj)->offset),
-			printcharfun, escapeflag);
-	  PRINTCHAR ('>');
-	  break;
-
-	case Lisp_Misc_Kboard_Objfwd:
-	  strout ("#<kboard_objfwd to ", -1, -1, printcharfun, 0);
-	  print_object (*(Lisp_Object *) ((char *) current_kboard
-					  + XKBOARD_OBJFWD (obj)->offset),
-			printcharfun, escapeflag);
-	  PRINTCHAR ('>');
-	  break;
-
-	case Lisp_Misc_Buffer_Local_Value:
-	  strout ("#<buffer_local_value ", -1, -1, printcharfun, 0);
-	  if (XBUFFER_LOCAL_VALUE (obj)->local_if_set)
-	    strout ("[local-if-set] ", -1, -1, printcharfun, 0);
-	  strout ("[realvalue] ", -1, -1, printcharfun, 0);
-	  print_object (XBUFFER_LOCAL_VALUE (obj)->realvalue,
-			printcharfun, escapeflag);
-	  if (XBUFFER_LOCAL_VALUE (obj)->found_for_buffer)
-	    strout ("[local in buffer] ", -1, -1, printcharfun, 0);
-	  else
-	    strout ("[buffer] ", -1, -1, printcharfun, 0);
-	  print_object (XBUFFER_LOCAL_VALUE (obj)->buffer,
-			printcharfun, escapeflag);
-	  if (XBUFFER_LOCAL_VALUE (obj)->check_frame)
-	    {
-	      if (XBUFFER_LOCAL_VALUE (obj)->found_for_frame)
-		strout ("[local in frame] ", -1, -1, printcharfun, 0);
-	      else
-		strout ("[frame] ", -1, -1, printcharfun, 0);
-	      print_object (XBUFFER_LOCAL_VALUE (obj)->frame,
-			    printcharfun, escapeflag);
-	    }
-	  strout ("[alist-elt] ", -1, -1, printcharfun, 0);
-	  print_object (XCAR (XBUFFER_LOCAL_VALUE (obj)->cdr),
-			printcharfun, escapeflag);
-	  strout ("[default-value] ", -1, -1, printcharfun, 0);
-	  print_object (XCDR (XBUFFER_LOCAL_VALUE (obj)->cdr),
-			printcharfun, escapeflag);
-	  PRINTCHAR ('>');
-	  break;
-
 	case Lisp_Misc_Save_Value:
 	  strout ("#<save_value ", -1, -1, printcharfun, 0);
 	  sprintf(buf, "ptr=0x%08lx int=%d",
--- a/src/term.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/term.c	Tue Apr 20 22:45:12 2010 +0000
@@ -1589,7 +1589,6 @@
     }
 }
 
-
 /* Produce glyphs for the display element described by IT.  *IT
    specifies what we want to produce a glyph for (character, image, ...),
    and where in the glyph matrix we currently are (glyph row and hpos).
@@ -1808,6 +1807,17 @@
   glyph = it->glyph_row->glyphs[it->area] + it->glyph_row->used[it->area];
   if (glyph < it->glyph_row->glyphs[1 + it->area])
     {
+      /* If the glyph row is reversed, we need to prepend the glyph
+	 rather than append it.  */
+      if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
+	{
+	  struct glyph *g;
+
+	  /* Make room for the new glyph.  */
+	  for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
+	    g[1] = *g;
+	  glyph = it->glyph_row->glyphs[it->area];
+	}
       glyph->type = COMPOSITE_GLYPH;
       glyph->pixel_width = it->pixel_width;
       glyph->u.cmp.id = it->cmp_it.id;
@@ -1828,6 +1838,18 @@
       glyph->padding_p = 0;
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
+      if (it->bidi_p)
+	{
+	  glyph->resolved_level = it->bidi_it.resolved_level;
+	  if ((it->bidi_it.type & 7) != it->bidi_it.type)
+	    abort ();
+	  glyph->bidi_type = it->bidi_it.type;
+	}
+      else
+	{
+	  glyph->resolved_level = 0;
+	  glyph->bidi_type = UNKNOWN_BT;
+	}
 
       ++it->glyph_row->used[it->area];
       ++glyph;
@@ -1889,12 +1911,16 @@
 
   if (what == IT_CONTINUATION)
     {
-      /* Continuation glyph.  */
-      SET_GLYPH_FROM_CHAR (glyph, '\\');
+      /* Continuation glyph.  For R2L lines, we mirror it by hand.  */
+      if (it->bidi_it.paragraph_dir == R2L)
+	SET_GLYPH_FROM_CHAR (glyph, '/');
+      else
+	SET_GLYPH_FROM_CHAR (glyph, '\\');
       if (it->dp
 	  && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc))
 	  && GLYPH_CODE_CHAR_VALID_P (gc))
 	{
+	  /* FIXME: Should we mirror GC for R2L lines?  */
 	  SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
 	  spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
 	}
@@ -1907,6 +1933,7 @@
 	  && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc))
 	  && GLYPH_CODE_CHAR_VALID_P (gc))
 	{
+	  /* FIXME: Should we mirror GC for R2L lines?  */
 	  SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
 	  spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
 	}
@@ -2244,7 +2271,7 @@
      struct tty_display_info *tty;
      struct frame *f;
 {
-  Lisp_Object tem, val, color_mode_spec;
+  Lisp_Object tem, val;
   Lisp_Object color_mode;
   int mode;
   extern Lisp_Object Qtty_color_mode;
@@ -2256,12 +2283,13 @@
 
   if (INTEGERP (val))
     color_mode = val;
-  else
+  else if (SYMBOLP (tty_color_mode_alist))
     {
-      tem = (NILP (tty_color_mode_alist) ? Qnil
-	     : Fassq (val, XSYMBOL (tty_color_mode_alist)->value));
+      tem = Fassq (val, Fsymbol_value (tty_color_mode_alist));
       color_mode = CONSP (tem) ? XCDR (tem) : Qnil;
     }
+  else
+    color_mode = Qnil;
 
   mode = INTEGERP (color_mode) ? XINT (color_mode) : 0;
 
--- a/src/w32term.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/w32term.c	Tue Apr 20 22:45:12 2010 +0000
@@ -5136,10 +5136,12 @@
 	}
 
       if (glyph_row->exact_window_width_line_p
-	  && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+	  && (glyph_row->reversed_p
+	      ? (w->phys_cursor.hpos < 0)
+	      : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
 	{
 	  glyph_row->cursor_in_fringe_p = 1;
-	  draw_fringe_bitmap (w, glyph_row, 0);
+	  draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
 	  return;
 	}
 
--- a/src/xdisp.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/xdisp.c	Tue Apr 20 22:45:12 2010 +0000
@@ -404,12 +404,14 @@
 /* Test if overflow newline into fringe.  Called with iterator IT
    at or past right window margin, and with IT->current_x set.  */
 
-#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it)	\
-  (!NILP (Voverflow_newline_into_fringe)	\
-   && FRAME_WINDOW_P (it->f)			\
-   && WINDOW_RIGHT_FRINGE_WIDTH (it->w) > 0	\
-   && it->current_x == it->last_visible_x	\
-   && it->line_wrap != WORD_WRAP)
+#define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT)		\
+  (!NILP (Voverflow_newline_into_fringe)		\
+   && FRAME_WINDOW_P ((IT)->f)				\
+   && ((IT)->bidi_it.paragraph_dir == R2L		\
+       ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0)	\
+       : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0))	\
+   && (IT)->current_x == (IT)->last_visible_x		\
+   && (IT)->line_wrap != WORD_WRAP)
 
 #else /* !HAVE_WINDOW_SYSTEM */
 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) 0
@@ -1077,6 +1079,8 @@
 static void notice_overwritten_cursor P_ ((struct window *,
 					   enum glyph_row_area,
 					   int, int, int, int));
+static void append_stretch_glyph P_ ((struct it *, Lisp_Object,
+				      int, int, int));
 
 
 
@@ -6709,13 +6713,20 @@
     {
       it->bidi_it.charpos = IT_CHARPOS (*it);
       it->bidi_it.bytepos = IT_BYTEPOS (*it);
-      /* If we are at the beginning of a line, we can produce the next
-	 element right away.  */
-      if (it->bidi_it.bytepos == BEGV_BYTE
+      if (it->bidi_it.bytepos == ZV_BYTE)
+	{
+	  /* Nothing to do, but reset the FIRST_ELT flag, like
+	     bidi_paragraph_init does, because we are not going to
+	     call it.  */
+	  it->bidi_it.first_elt = 0;
+	}
+      else if (it->bidi_it.bytepos == BEGV_BYTE
 	  /* FIXME: Should support all Unicode line separators.  */
 	  || FETCH_CHAR (it->bidi_it.bytepos - 1) == '\n'
 	  || FETCH_CHAR (it->bidi_it.bytepos) == '\n')
 	{
+	  /* If we are at the beginning of a line, we can produce the
+	     next element right away.  */
 	  bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it);
 	  bidi_get_next_char_visually (&it->bidi_it);
 	}
@@ -11592,7 +11603,7 @@
 select_frame_for_redisplay (frame)
      Lisp_Object frame;
 {
-  Lisp_Object tail, symbol, val;
+  Lisp_Object tail, tem;
   Lisp_Object old = selected_frame;
   struct Lisp_Symbol *sym;
 
@@ -11600,20 +11611,18 @@
 
   selected_frame = frame;
 
-  do
-    {
-      for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
-	if (CONSP (XCAR (tail))
-	    && (symbol = XCAR (XCAR (tail)),
-		SYMBOLP (symbol))
-	    && (sym = indirect_variable (XSYMBOL (symbol)),
-		val = sym->value,
-		(BUFFER_LOCAL_VALUEP (val)))
-	    && XBUFFER_LOCAL_VALUE (val)->check_frame)
-	  /* Use find_symbol_value rather than Fsymbol_value
-	     to avoid an error if it is void.  */
-	  find_symbol_value (symbol);
-    } while (!EQ (frame, old) && (frame = old, 1));
+  do {
+    for (tail = XFRAME (frame)->param_alist; CONSP (tail); tail = XCDR (tail))
+      if (CONSP (XCAR (tail))
+	  && (tem = XCAR (XCAR (tail)),
+	      SYMBOLP (tem))
+	  && (sym = indirect_variable (XSYMBOL (tem)),
+	      sym->redirect == SYMBOL_LOCALIZED)
+	  && sym->val.blv->frame_local)
+	/* Use find_symbol_value rather than Fsymbol_value
+	   to avoid an error if it is void.  */
+	find_symbol_value (tem);
+  } while (!EQ (frame, old) && (frame = old, 1));
 }
 
 
@@ -12621,7 +12630,6 @@
   /* The last known character position in row.  */
   int last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
   int x = row->x;
-  int cursor_x = x;
   EMACS_INT pt_old = PT - delta;
   EMACS_INT pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
   EMACS_INT pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
@@ -12657,8 +12665,8 @@
 	    }
 	  while (end > glyph
 		 && INTEGERP ((end - 1)->object)
-		 /* CHARPOS is zero for blanks inserted by
-		    extend_face_to_end_of_line.  */
+		 /* CHARPOS is zero for blanks and stretch glyphs
+		    inserted by extend_face_to_end_of_line.  */
 		 && (end - 1)->charpos <= 0)
 	    --end;
 	  glyph_before = glyph - 1;
@@ -12672,9 +12680,6 @@
 	     to front, so swap the edge pointers.  */
 	  glyphs_end = end = glyph - 1;
 	  glyph += row->used[TEXT_AREA] - 1;
-	  /* Reverse the known positions in the row.  */
-	  last_pos = pos_after = MATRIX_ROW_START_CHARPOS (row) + delta;
-	  pos_before = MATRIX_ROW_END_CHARPOS (row) + delta;
 
 	  while (glyph > end + 1
 		 && INTEGERP (glyph->object)
@@ -12689,7 +12694,6 @@
 	     rightmost (first in the reading order) glyph.  */
 	  for (g = end + 1; g < glyph; g++)
 	    x += g->pixel_width;
-	  cursor_x = x;
 	  while (end < glyph
 		 && INTEGERP ((end + 1)->object)
 		 && (end + 1)->charpos <= 0)
@@ -12704,7 +12708,7 @@
 	 rightmost glyph.  Case in point: an empty last line that is
 	 part of an R2L paragraph.  */
       cursor = end - 1;
-      x = -1;	/* will be computed below, at lable compute_x */
+      x = -1;	/* will be computed below, at label compute_x */
     }
 
   /* Step 1: Try to find the glyph whose character position
@@ -12840,8 +12844,11 @@
 	    string_seen = 1;
 	  }
 	--glyph;
-	if (glyph == end)
-	  break;
+	if (glyph == glyphs_end) /* don't dereference outside TEXT_AREA */
+	  {
+	    x--;		/* can't use any pixel_width */
+	    break;
+	  }
 	x -= glyph->pixel_width;
     }
 
@@ -12881,7 +12888,10 @@
 	}
       else if (match_with_avoid_cursor
 	       /* zero-width characters produce no glyphs */
-	       || eabs (glyph_after - glyph_before) == 1)
+	       || ((row->reversed_p
+		    ? glyph_after > glyphs_end
+		    : glyph_after < glyphs_end)
+		   && eabs (glyph_after - glyph_before) == 1))
 	{
 	  cursor = glyph_after;
 	  x = -1;
@@ -13000,16 +13010,17 @@
 	}
     }
 
-  /* ROW could be part of a continued line, which might have other
-     rows whose start and end charpos occlude point.  Only set
-     w->cursor if we found a better approximation to the cursor
-     position than we have from previously examined rows.  */
+  /* ROW could be part of a continued line, which, under bidi
+     reordering, might have other rows whose start and end charpos
+     occlude point.  Only set w->cursor if we found a better
+     approximation to the cursor position than we have from previously
+     examined candidate rows belonging to the same continued line.  */
   if (/* we already have a candidate row */
       w->cursor.vpos >= 0
       /* that candidate is not the row we are processing */
       && MATRIX_ROW (matrix, w->cursor.vpos) != row
-      /* this row is part of a continued line */
-      && (row->continued_p || row->continuation_lines_width)
+      /* the row we are processing is part of a continued line */
+      && (row->continued_p || MATRIX_ROW_CONTINUATION_LINE_P (row))
       /* Make sure cursor.vpos specifies a row whose start and end
 	 charpos occlude point.  This is because some callers of this
 	 function leave cursor.vpos at the row where the cursor was
@@ -16852,9 +16863,11 @@
 
 
 /* Extend the face of the last glyph in the text area of IT->glyph_row
-   to the end of the display line.  Called from display_line.
-   If the glyph row is empty, add a space glyph to it so that we
-   know the face to draw.  Set the glyph row flag fill_line_p.  */
+   to the end of the display line.  Called from display_line.  If the
+   glyph row is empty, add a space glyph to it so that we know the
+   face to draw.  Set the glyph row flag fill_line_p.  If the glyph
+   row is R2L, prepend a stretch glyph to cover the empty space to the
+   left of the leftmost glyph.  */
 
 static void
 extend_face_to_end_of_line (it)
@@ -16863,15 +16876,17 @@
   struct face *face;
   struct frame *f = it->f;
 
-  /* If line is already filled, do nothing.  */
-  if (it->current_x >= it->last_visible_x)
+  /* If line is already filled, do nothing.  Non window-system frames
+     get a grace of one more ``pixel'' because their characters are
+     1-``pixel'' wide, so they hit the equality too early.  */
+  if (it->current_x >= it->last_visible_x + !FRAME_WINDOW_P (f))
     return;
 
   /* Face extension extends the background and box of IT->face_id
      to the end of the line.  If the background equals the background
      of the frame, we don't have to do anything.  */
   if (it->face_before_selective_p)
-    face = FACE_FROM_ID (it->f, it->saved_face_id);
+    face = FACE_FROM_ID (f, it->saved_face_id);
   else
     face = FACE_FROM_ID (f, it->face_id);
 
@@ -16879,7 +16894,8 @@
       && it->glyph_row->displays_text_p
       && face->box == FACE_NO_BOX
       && face->background == FRAME_BACKGROUND_PIXEL (f)
-      && !face->stipple)
+      && !face->stipple
+      && !it->glyph_row->reversed_p)
     return;
 
   /* Set the glyph row flag indicating that the face of the last glyph
@@ -16906,6 +16922,50 @@
 	  it->glyph_row->glyphs[TEXT_AREA][0].face_id = it->face_id;
 	  it->glyph_row->used[TEXT_AREA] = 1;
 	}
+#ifdef HAVE_WINDOW_SYSTEM
+      if (it->glyph_row->reversed_p)
+	{
+	  /* Prepend a stretch glyph to the row, such that the
+	     rightmost glyph will be drawn flushed all the way to the
+	     right margin of the window.  The stretch glyph that will
+	     occupy the empty space, if any, to the left of the
+	     glyphs.  */
+	  struct font *font = face->font ? face->font : FRAME_FONT (f);
+	  struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
+	  struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
+	  struct glyph *g;
+	  int row_width, stretch_ascent, stretch_width;
+	  struct text_pos saved_pos;
+	  int saved_face_id, saved_avoid_cursor;
+
+	  for (row_width = 0, g = row_start; g < row_end; g++)
+	    row_width += g->pixel_width;
+	  stretch_width = window_box_width (it->w, TEXT_AREA) - row_width;
+	  if (stretch_width > 0)
+	    {
+	      stretch_ascent =
+		(((it->ascent + it->descent)
+		  * FONT_BASE (font)) / FONT_HEIGHT (font));
+	      saved_pos = it->position;
+	      bzero (&it->position, sizeof it->position);
+	      saved_avoid_cursor = it->avoid_cursor_p;
+	      it->avoid_cursor_p = 1;
+	      saved_face_id = it->face_id;
+	      /* The last row's stretch glyph should get the default
+		 face, to avoid painting the rest of the window with
+		 the region face, if the region ends at ZV.  */
+	      if (it->glyph_row->ends_at_zv_p)
+		it->face_id = DEFAULT_FACE_ID;
+	      else
+		it->face_id = face->id;
+	      append_stretch_glyph (it, make_number (0), stretch_width,
+				    it->ascent + it->descent, stretch_ascent);
+	      it->position = saved_pos;
+	      it->avoid_cursor_p = saved_avoid_cursor;
+	      it->face_id = saved_face_id;
+	    }
+	}
+#endif	/* HAVE_WINDOW_SYSTEM */
     }
   else
     {
@@ -16924,7 +16984,13 @@
       it->object = make_number (0);
       it->c = ' ';
       it->len = 1;
-      it->face_id = face->id;
+      /* The last row's blank glyphs should get the default face, to
+	 avoid painting the rest of the window with the region face,
+	 if the region ends at ZV.  */
+      if (it->glyph_row->ends_at_zv_p)
+	it->face_id = DEFAULT_FACE_ID;
+      else
+	it->face_id = face->id;
 
       PRODUCE_GLYPHS (it);
 
@@ -17210,6 +17276,31 @@
 
 
 
+/* Remove N glyphs at the start of a reversed IT->glyph_row.  Called
+   only for R2L lines from display_line, when it decides that too many
+   glyphs were produced by PRODUCE_GLYPHS, and the line needs to be
+   continued.  */
+static void
+unproduce_glyphs (it, n)
+     struct it *it;
+     int n;
+{
+  struct glyph *glyph, *end;
+
+  xassert (it->glyph_row);
+  xassert (it->glyph_row->reversed_p);
+  xassert (it->area == TEXT_AREA);
+  xassert (n <= it->glyph_row->used[TEXT_AREA]);
+
+  if (n > it->glyph_row->used[TEXT_AREA])
+    n = it->glyph_row->used[TEXT_AREA];
+  glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
+  end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
+  for ( ; glyph < end; glyph++)
+    glyph[-n] = *glyph;
+}
+
+
 /* Construct the glyph row IT->glyph_row in the desired matrix of
    IT->w from text at the current position of IT.  See dispextern.h
    for an overview of struct it.  Value is non-zero if
@@ -17474,6 +17565,9 @@
 		      /* A padding glyph that doesn't fit on this line.
 			 This means the whole character doesn't fit
 			 on the line.  */
+		      if (row->reversed_p)
+			unproduce_glyphs (it, row->used[TEXT_AREA]
+					       - n_glyphs_before);
 		      row->used[TEXT_AREA] = n_glyphs_before;
 
 		      /* Fill the rest of the row with continuation
@@ -17496,6 +17590,9 @@
 		  else if (wrap_row_used > 0)
 		    {
 		    back_to_wrap:
+		      if (row->reversed_p)
+			unproduce_glyphs (it,
+					  row->used[TEXT_AREA] - wrap_row_used);
 		      *it = wrap_it;
 		      it->continuation_lines_width += wrap_x;
 		      row->used[TEXT_AREA] = wrap_row_used;
@@ -17531,6 +17628,9 @@
 		      /* Something other than a TAB that draws past
 			 the right edge of the window.  Restore
 			 positions to values before the element.  */
+		      if (row->reversed_p)
+			unproduce_glyphs (it, row->used[TEXT_AREA]
+					       - (n_glyphs_before + i));
 		      row->used[TEXT_AREA] = n_glyphs_before + i;
 
 		      /* Display continuation glyphs.  */
@@ -17636,9 +17736,22 @@
 	    {
 	      int i, n;
 
-	      for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
-		if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
-		  break;
+	      if (!row->reversed_p)
+		{
+		  for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
+		    if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
+		      break;
+		}
+	      else
+		{
+		  for (i = 0; i < row->used[TEXT_AREA]; i++)
+		    if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
+		      break;
+		  /* Remove padding glyphs at the front of ROW, to
+		     make room for the truncation glyphs we will be
+		     adding below.  */
+		  unproduce_glyphs (it, i);
+		}
 
 	      for (n = row->used[TEXT_AREA]; i < n; ++i)
 		{
@@ -17825,7 +17938,7 @@
 	      *it = save_it;
 	    }
 	  else if (!row->continued_p
-		   && row->continuation_lines_width
+		   && MATRIX_ROW_CONTINUATION_LINE_P (row)
 		   && it->eol_pos.charpos > 0)
 	    {
 	      /* Last row of a continued line.  Use the position
@@ -21495,6 +21608,17 @@
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
+      /* If the glyph row is reversed, we need to prepend the glyph
+	 rather than append it.  */
+      if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
+	{
+	  struct glyph *g;
+
+	  /* Make room for the new glyph.  */
+	  for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
+	    g[1] = *g;
+	  glyph = it->glyph_row->glyphs[it->area];
+	}
       glyph->charpos = CHARPOS (it->position);
       glyph->object = it->object;
       glyph->pixel_width = it->pixel_width;
@@ -21740,6 +21864,17 @@
   glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
   if (glyph < it->glyph_row->glyphs[area + 1])
     {
+      /* If the glyph row is reversed, we need to prepend the glyph
+	 rather than append it.  */
+      if (it->glyph_row->reversed_p && area == TEXT_AREA)
+	{
+	  struct glyph *g;
+
+	  /* Make room for the additional glyph.  */
+	  for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
+	    g[1] = *g;
+	  glyph = it->glyph_row->glyphs[area];
+	}
       glyph->charpos = CHARPOS (it->position);
       glyph->object = object;
       glyph->pixel_width = width;
@@ -21766,6 +21901,11 @@
 	    abort ();
 	  glyph->bidi_type = it->bidi_it.type;
 	}
+      else
+	{
+	  glyph->resolved_level = 0;
+	  glyph->bidi_type = UNKNOWN_BT;
+	}
       ++it->glyph_row->used[area];
     }
   else
@@ -23246,7 +23386,7 @@
   if (row->cursor_in_fringe_p)
     {
       row->cursor_in_fringe_p = 0;
-      draw_fringe_bitmap (w, row, 0);
+      draw_fringe_bitmap (w, row, row->reversed_p);
       w->phys_cursor_on_p = 0;
       return;
     }
@@ -23347,7 +23487,9 @@
   /* If cursor hpos is out of bounds, don't draw garbage.  This can
      happen in mini-buffer windows when switching between echo area
      glyphs and mini-buffer.  */
-  if (w->phys_cursor.hpos < row->used[TEXT_AREA])
+  if ((row->reversed_p
+       ? (w->phys_cursor.hpos >= 0)
+       : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
     {
       int on_p = w->phys_cursor_on_p;
       int x1;
@@ -23427,7 +23569,7 @@
   if (cursor_row->cursor_in_fringe_p)
     {
       cursor_row->cursor_in_fringe_p = 0;
-      draw_fringe_bitmap (w, cursor_row, 0);
+      draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
       goto mark_cursor_off;
     }
 
@@ -23436,7 +23578,9 @@
      should have cleared the cursor.  Note that we wouldn't be
      able to erase the cursor in this case because we don't have a
      cursor glyph at hand.  */
-  if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
+  if ((cursor_row->reversed_p
+       ? (w->phys_cursor.hpos < 0)
+       : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
     goto mark_cursor_off;
 
   /* If the cursor is in the mouse face area, redisplay that when
@@ -23452,7 +23596,7 @@
       /* Don't redraw the cursor's spot in mouse face if it is at the
 	 end of a line (on a newline).  The cursor appears there, but
 	 mouse highlighting does not.  */
-      && cursor_row->used[TEXT_AREA] > hpos)
+      && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
     mouse_face_here_p = 1;
 
   /* Maybe clear the display under the cursor.  */
@@ -23534,7 +23678,7 @@
 
   glyph = NULL;
   if (!glyph_row->exact_window_width_line_p
-      || hpos < glyph_row->used[TEXT_AREA])
+      || (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]))
     glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
 
   xassert (interrupt_input_blocked);
--- a/src/xterm.c	Mon Apr 19 22:46:02 2010 +0000
+++ b/src/xterm.c	Tue Apr 20 22:45:12 2010 +0000
@@ -7492,36 +7492,40 @@
       w->phys_cursor_on_p = 1;
 
       if (glyph_row->exact_window_width_line_p
-	  && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
+	  && (glyph_row->reversed_p
+	      ? (w->phys_cursor.hpos < 0)
+	      : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])))
 	{
 	  glyph_row->cursor_in_fringe_p = 1;
-	  draw_fringe_bitmap (w, glyph_row, 0);
+	  draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p);
 	}
       else
-      switch (cursor_type)
 	{
-	case HOLLOW_BOX_CURSOR:
-	  x_draw_hollow_cursor (w, glyph_row);
-	  break;
-
-	case FILLED_BOX_CURSOR:
-	  draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
-	  break;
-
-	case BAR_CURSOR:
-	  x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
-	  break;
-
-	case HBAR_CURSOR:
-	  x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
-	  break;
-
-	case NO_CURSOR:
-	  w->phys_cursor_width = 0;
-	  break;
-
-	default:
-	  abort ();
+	  switch (cursor_type)
+	    {
+	    case HOLLOW_BOX_CURSOR:
+	      x_draw_hollow_cursor (w, glyph_row);
+	      break;
+
+	    case FILLED_BOX_CURSOR:
+	      draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
+	      break;
+
+	    case BAR_CURSOR:
+	      x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
+	      break;
+
+	    case HBAR_CURSOR:
+	      x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
+	      break;
+
+	    case NO_CURSOR:
+	      w->phys_cursor_width = 0;
+	      break;
+
+	    default:
+	      abort ();
+	    }
 	}
 
 #ifdef HAVE_X_I18N