changeset 5052:92dc90c0bb40

merge
author Ben Wing <ben@xemacs.org>
date Sat, 20 Feb 2010 23:56:01 -0600
parents c3d372419e09 (current diff) 548f1f47eb82 (diff)
children 0e803dc6f096 eb17f0c176ac
files src/ChangeLog src/EmacsFrame.c src/console.c src/device-x.c src/events.c src/frame.c src/lisp.h src/mc-alloc.c src/window.c
diffstat 51 files changed, 2619 insertions(+), 1094 deletions(-) [+]
line wrap: on
line diff
--- a/man/ChangeLog	Sat Feb 20 18:57:55 2010 -0600
+++ b/man/ChangeLog	Sat Feb 20 23:56:01 2010 -0600
@@ -1,3 +1,26 @@
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* internals/internals.texi (Intro to Window and Frame Geometry):
+	Shrink diagram to fit when offset by five spaces as a result of
+	quoting.
+
+2010-02-16  Ben Wing  <ben@xemacs.org>
+
+	* internals/internals.texi (Top):
+	* internals/internals.texi (Modules for the Basic Displayable Lisp Objects):
+	* internals/internals.texi (Creating a Window-System Type):
+	* internals/internals.texi (Window and Frame Geometry):
+	* internals/internals.texi (Intro to Window and Frame Geometry):
+	* internals/internals.texi (The Frame):
+	* internals/internals.texi (The Non-Client Area):
+	* internals/internals.texi (The Client Area):
+	* internals/internals.texi (The Paned Area):
+	* internals/internals.texi (Text Areas):
+	* internals/internals.texi (The Displayable Area):
+	* internals/internals.texi (Which Functions Use Which?):
+	* internals/internals.texi (The Redisplay Mechanism):
+	Integrate the long comment in frame.c into the internals manual.
+
 2010-02-17  Jerry James  <james@xemacs.org>
 
 	* term.texi: Move to the eterm package.
--- a/man/internals/internals.texi	Sat Feb 20 18:57:55 2010 -0600
+++ b/man/internals/internals.texi	Sat Feb 20 23:56:01 2010 -0600
@@ -360,6 +360,7 @@
 * Multilingual Support::        
 * Consoles; Devices; Frames; Windows::  
 * Window-System Support::       
+* Window and Frame Geometry::   
 * The Redisplay Mechanism::     
 * Extents::                     
 * Faces::                       
@@ -596,6 +597,17 @@
 
 * Creating a Window-System Type::  
 
+Window and Frame Geometry
+
+* Intro to Window and Frame Geometry::  
+* The Frame::                   
+* The Non-Client Area::         
+* The Client Area::             
+* The Paned Area::              
+* Text Areas::                  
+* The Displayable Area::        
+* Which Functions Use Which?::  
+
 The Redisplay Mechanism
 
 * Critical Redisplay Sections::  
@@ -17668,7 +17680,7 @@
 types such as scrollbars.
 
 
-@node Window-System Support, The Redisplay Mechanism, Consoles; Devices; Frames; Windows, Top
+@node Window-System Support, Window and Frame Geometry, Consoles; Devices; Frames; Windows, Top
 @chapter Window-System Support
 @cindex window-system support
 @cindex window systems
@@ -17851,7 +17863,324 @@
 
 
 
-@node The Redisplay Mechanism, Extents, Window-System Support, Top
+@node Window and Frame Geometry, The Redisplay Mechanism, Window-System Support, Top
+@chapter Window and Frame Geometry
+
+@menu
+* Intro to Window and Frame Geometry::  
+* The Frame::                   
+* The Non-Client Area::         
+* The Client Area::             
+* The Paned Area::              
+* Text Areas::                  
+* The Displayable Area::        
+* Which Functions Use Which?::  
+@end menu
+
+@node Intro to Window and Frame Geometry, The Frame, Window and Frame Geometry, Window and Frame Geometry
+@section Intro to Window and Frame Geometry
+
+Here is an ASCII diagram:
+
+@example
++------------------------------------------------------------------------|
+|                         window-manager decoration                      |
+| +--------------------------------------------------------------------+ |
+| |                               menubar                              | |
+| ###################################################################### |
+| #                               toolbar                              # |
+| #--------------------------------------------------------------------# |
+| #  |                            gutter                            |  # |
+| #  |--------------------------------------------------------------|  # |
+| #  | |                  internal border width                   | |  # |
+| #  | | ******************************************************** | |  # |
+|w#  | | *                         |s|v*                      |s* | |  #w|
+|i#  | | *                         |c|e*                      |c* | |  #i|
+|n#  | | *                         |r|r*                      |r* | |  #n|
+|d#  | | *                         |o|t*                      |o* | |  #d|
+|o#  | | *        text area        |l|.*      text area       |l* | |  #o|
+|w#  | |i*                         |l| *                      |l*i| |  #w|
+|-#  | |n*                         |b|d*                      |b*n| |  #-|
+|m#  | |t*                         |a|i*                      |a*t| |  #m|
+|a#  | |.*                         |r|v*                      |r*.| |  #a|
+|n# t| | *-------------------------+-|i*----------------------+-* | |t #n|
+|a# o|g|b*        scrollbar        | |d*      scrollbar       | *b|g|o #a|
+|g# o|u|o*-------------------------+-|e*----------------------+-*o|u|o #g|
+|e# l|t|r*        modeline           |r*      modeline          *r|t|l #e|
+|r# b|t|d********************************************************d|t|b #r|
+| # a|e|e*   =..texttexttex....=   |s|v*                      |s*e|e|a # |
+|d# r|r|r*o m=..texttexttextt..=o m|c|e*                      |c*r|r|r #d|
+|e#  | | *u a=.exttexttextte...=u a|r|r*                      |r* | |  #e|
+|c#  | |w*t r=....texttexttex..=t r|o|t*                      |o*w| |  #c|
+|o#  | |i*s g=        etc.     =s g|l|.*      text area       |l*i| |  #o|
+|r#  | |d*i i=                 =i i|l| *                      |l*d| |  #r|
+|a#  | |t*d n=                 =d n|b|d*                      |b*t| |  #a|
+|t#  | |h*e  = inner text area =e  |a|i*                      |a*h| |  #t|
+|i#  | | *   =                 =   |r|v*                      |r* | |  #i|
+|o#  | | *---===================---+-|i*----------------------+-* | |  #o|
+|n#  | | *        scrollbar        | |d*      scrollbar       | * | |  #n|
+| #  | | *-------------------------+-|e*----------------------+-* | |  # |
+| #  | | *        modeline           |r*      modeline          * | |  # |
+| #  | | ******************************************************** | |  # |
+| #  | | *                        minibuffer                    * | |  # |
+| #  | | ******************************************************** | |  # |
+| #  | |                   internal border width                  | |  # |
+| #  |--------------------------------------------------------------|  # |
+| #  |                             gutter                           |  # |
+| #--------------------------------------------------------------------# |
+| #                                toolbar                             # |
+| ###################################################################### |
+|                          window manager decoration                     |
++------------------------------------------------------------------------+
+
+   # = boundary of client area; * = window boundaries, boundary of paned area
+   = = boundary of inner text area; . = inside margin area
+@end example
+
+Note in particular what happens at the corners, where a "corner box"
+occurs.  Top and bottom toolbars take precedence over left and right
+toolbars, extending out horizontally into the corner boxes.  Gutters
+work the same way.  The corner box where the scrollbars meet, however,
+is assigned to neither scrollbar, and is known as the "dead box"; it is
+an area that must be cleared specially.
+
+@node The Frame, The Non-Client Area, Intro to Window and Frame Geometry, Window and Frame Geometry
+@section The Frame
+
+The "top-level window area" is the entire area of a top-level window (or
+"frame").  The "client area" (a term from MS Windows) is the area of a
+top-level window that XEmacs draws into and manages with redisplay.
+This includes the toolbar, scrollbars, gutters, dividers, text area,
+modeline and minibuffer.  It does not include the menubar, title or
+outer borders.  The "non-client area" is the area of a top-level window
+outside of the client area and includes the menubar, title and outer
+borders.  Internally, all frame coordinates are relative to the client
+area.
+
+
+@node The Non-Client Area, The Client Area, The Frame, Window and Frame Geometry
+@section The Non-Client Area
+
+Under X, the non-client area is split into two parts:
+
+@enumerate
+@item
+The outer layer is the window-manager decorations: The title and
+borders.  These are controlled by the window manager, a separate process
+that controls the desktop, the location of icons, etc.  When a process
+tries to create a window, the window manager intercepts this action and
+"reparents" the window, placing another window around it which contains
+the window decorations, including the title bar, outer borders used for
+resizing, etc.  The window manager also implements any actions involving
+the decorations, such as the ability to resize a window by dragging its
+borders, move a window by dragging its title bar, etc.  If there is no
+window manager or you kill it, windows will have no decorations (and
+will lose them if they previously had any) and you will not be able to
+move or resize them.
+
+@item
+Inside of the window-manager decorations is the "shell", which is
+managed by the toolkit and widget libraries your program is linked with.
+The code in @file{*-x.c} uses the Xt toolkit and various possible widget
+libraries built on top of Xt, such as Motif, Athena, the "Lucid"
+widgets, etc.  Another possibility is GTK (@file{*-gtk.c}), which implements
+both the toolkit and widgets.  Under Xt, the "shell" window is an
+EmacsShell widget, containing an EmacsManager widget of the same size,
+which in turn contains a menubar widget and an EmacsFrame widget, inside
+of which is the client area. (The division into EmacsShell and
+EmacsManager is due to the complex and screwy geometry-management system
+in Xt [and X more generally].  The EmacsShell handles negotation with
+the window manager; the place of the EmacsManager widget is normally
+assumed by a widget that manages the geometry of its child widgets, but
+the EmacsManager widget just lets the XEmacs redisplay mechanism do the
+positioning.)
+@end enumerate
+
+Under Windows, the non-client area is managed by the window system.
+There is no division such as under X.  Part of the window-system API
+(@file{USER.DLL}) of Win32 includes functions to control the menubars, title,
+etc. and implements the move and resize behavior.  There @strong{is} an
+equivalent of the window manager, called the "shell", but it manages
+only the desktop, not the windows themselves.  The normal shell under
+Windows is @file{EXPLORER.EXE}; if you kill this, you will lose the bar
+containing the "Start" menu and tray and such, but the windows
+themselves will not be affected or lose their decorations.
+
+
+@node The Client Area, The Paned Area, The Non-Client Area, Window and Frame Geometry
+@section The Client Area
+
+Inside of the client area is the toolbars, the gutters (where the buffer
+tabs are displayed), the minibuffer, the internal border width, and one
+or more non-overlapping "windows" (this is old Emacs terminology, from
+before the time when frames existed at all; the standard terminology for
+this would be "pane").  Each window can contain a modeline, horizontal
+and/or vertical scrollbars, and (for non-rightmost windows) a vertical
+divider, surrounding a text area.
+
+The dimensions of the toolbars and gutters are determined by the formula
+(THICKNESS + 2 * BORDER-THICKNESS), where "thickness" is a cover term
+for height or width, as appropriate.  The height and width come from
+@code{default-toolbar-height} and @code{default-toolbar-width} and the specific
+versions of these (@code{top-toolbar-height}, @code{left-toolbar-width}, etc.).
+The border thickness comes from @code{default-toolbar-border-height} and
+@code{default-toolbar-border-width}, and the specific versions of these.  The
+gutter works exactly equivalently.
+
+Note that for any particular toolbar or gutter, it will only be
+displayed if [a] its visibility specifier (@code{default-toolbar-visible-p}
+etc.) is non-nil; [b] its thickness (@code{default-toolbar-height} etc.)  is
+greater than 0; [c] its contents (@code{default-toolbar} etc.) are non-nil.
+
+The position-specific toolbars interact with the default specifications
+as follows: If the value for a position-specific specifier is not
+defined in a particular domain (usually a window), and the position of
+that specifier is set as the default position (using
+@code{default-toolbar-position}), then the value from the corresponding
+default specifier in that domain will be used.  The gutters work the
+same.
+
+
+@node The Paned Area, Text Areas, The Client Area, Window and Frame Geometry
+@section The Paned Area
+
+The area occupied by the "windows" is called the paned area.  Note that
+this includes the minibuffer, which is just another window but is
+special-cased in XEmacs.  Each window can include a horizontal and/or
+vertical scrollbar, a modeline and a vertical divider to its right, as
+well as the text area.  Only non-rightmost windows can include a
+vertical divider. (The minibuffer normally does not include either
+modeline or scrollbars.)
+
+Note that, because the toolbars and gutters are controlled by
+specifiers, and specifiers can have window-specific and buffer-specific
+values, the size of the paned area can change depending on which window
+is selected: In other words, if the selected window or buffer changes,
+the entire paned area for the frame may change.
+
+
+@node Text Areas, The Displayable Area, The Paned Area, Window and Frame Geometry
+@section Text Areas, Fringes, Margins
+
+The space occupied by a window can be divided into the text area and the
+fringes.  The fringes include the modeline, scrollbars and vertical
+divider on the right side (if any); inside of this is the text area,
+where the text actually occurs.  Note that a window may or may not
+contain any of the elements that are part of the fringe -- this is
+controlled by specifiers, e.g. @code{has-modeline-p},
+@code{horizontal-scrollbar-visible-p}, @code{vertical-scrollbar-visible-p},
+@code{vertical-divider-always-visible-p}, etc.
+
+In addition, it is possible to set margins in the text area using the
+specifiers @code{left-margin-width} and @code{right-margin-width}.  When this is
+done, only the "inner text area" (the area inside of the margins) will
+be used for normal display of text; the margins will be used for glyphs
+with a layout policy of @code{outside-margin} (as set on an extent containing
+the glyph by @code{set-extent-begin-glyph-layout} or
+@code{set-extent-end-glyph-layout}).  However, the calculation of the text
+area size (e.g. in the function @code{window-text-area-width}) includes the
+margins.  Which margin is used depends on whether a glyph has been set
+as the begin-glyph or end-glyph of an extent (@code{set-extent-begin-glyph}
+etc.), using the left and right margins, respectively.
+
+Technically, the margins outside of the inner text area are known as the
+"outside margins".  The "inside margins" are in the inner text area and
+constitute the whitespace between the outside margins and the first or
+last non-whitespace character in a line; their width can vary from line
+to line.  Glyphs will be placed in the inside margin if their layout
+policy is @code{inside-margin} or @code{whitespace}, with @code{whitespace} glyphs on
+the inside and @code{inside-margin} glyphs on the outside.  Inside-margin
+glyphs can spill over into the outside margin if @code{use-left-overflow} or
+@code{use-right-overflow}, respectively, is non-nil.
+
+See the Lisp Reference manual, under Annotations, for more details.
+
+
+@node The Displayable Area, Which Functions Use Which?, Text Areas, Window and Frame Geometry
+@section The Displayable Area
+
+The "displayable area" is not so much an actual area as a convenient
+fiction.  It is the area used to convert between pixel and character
+dimensions for frames.  The character dimensions for a frame (e.g. as
+returned by @code{frame-width} and @code{frame-height} and set by
+@code{set-frame-width} and @code{set-frame-height}) are determined from the
+displayable area by dividing by the pixel size of the default font as
+instantiated in the frame. (For proportional fonts, the "average" width
+is used.  Under Windows, this is a built-in property of the fonts.
+Under X, this is based on the width of the lowercase 'n', or if this is
+zero then the width of the default character. [We prefer 'n' to the
+specified default character because many X fonts have a default
+character with a zero or otherwise non-representative width.])
+
+The displayable area is essentially the "theoretical" paned area of the
+frame excluding the rightmost and bottom-most scrollbars.  In this
+context, "theoretical" means that all calculations on based on
+frame-level values for toolbar, gutter and scrollbar thicknesses.
+Because these thicknesses are controlled by specifiers, and specifiers
+can have window-specific and buffer-specific values, these calculations
+may or may not reflect the actual size of the paned area or of the
+scrollbars when any particular window is selected.  Note also that the
+"displayable area" may not even be contiguous!  In particular, if the
+frame-level value of the horizontal scrollbar height is non-zero, then
+the displayable area includes the paned area above and below the bottom
+horizontal scrollbar but not the scrollbar itself.
+
+As a further twist, the character-dimension calculations are adjusted so
+that the truncation and continuation glyphs (see @code{truncation-glyph} and
+@code{continuation-glyph}) count as a single character even if they are wider
+than the default font width. (Technically, the character width is
+computed from the displayable-area width by subtracting the maximum of
+the truncation-glyph width, continuation-glyph width and default-font
+width before dividing by the default-font width, and then adding 1 to
+the result.) (The ultimate motivation for this kludge as well as the
+subtraction of the scrollbars, but not the minibuffer or bottom-most
+modeline, is to maintain compatibility with TTY's.)
+
+Despite all these concerns and kludges, however, the "displayable area"
+concept works well in practice and mostly ensures that by default the
+frame will actually fit 79 characters + continuation/truncation glyph.
+
+
+@node Which Functions Use Which?,  , The Displayable Area, Window and Frame Geometry
+@section Which Functions Use Which?
+
+@enumerate
+@item
+Top-level window area:
+
+@example
+set-frame-position
+@code{left} and @code{top} frame properties
+@end example
+
+@item
+Client area:
+
+@example
+frame-pixel-*, set-frame-pixel-*
+@end example
+
+@item
+Paned area:
+
+@example
+window-pixel-edges
+event-x-pixel, event-y-pixel, event-properties, make-event
+@end example
+
+@item
+Displayable area:
+
+@example
+frame-width, frame-height and other all functions specifying frame size
+  in characters
+frame-displayable-pixel-*
+@end example
+@end enumerate
+
+
+
+@node The Redisplay Mechanism, Extents, Window and Frame Geometry, Top
 @chapter The Redisplay Mechanism
 @cindex redisplay mechanism, the
 
--- a/src/ChangeLog	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/ChangeLog	Sat Feb 20 23:56:01 2010 -0600
@@ -118,6 +118,347 @@
 	speed up recompilation.
 
 
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* EmacsFrame.c (EmacsFrameRecomputeCellSize):
+	* faces.c (default_face_font_info):
+	* faces.c (default_face_width_and_height):
+	* faces.c (Fface_list):
+	* faces.h:
+	* frame-gtk.c (gtk_set_initial_frame_size):
+	* frame-gtk.c (gtk_set_frame_size):
+	* frame-gtk.c (gtk_recompute_cell_sizes):
+	* frame.c:
+	* frame.c (frame_conversion_internal_1):
+	* frame.c (change_frame_size_1):
+	* frame.c (change_frame_size):
+	* glyphs-msw.c (mswindows_combo_box_instantiate):
+	* glyphs-widget.c (widget_instantiate):
+	* glyphs-widget.c (tree_view_query_geometry):
+	* glyphs-widget.c (Fwidget_logical_to_character_width):
+	* glyphs-widget.c (Fwidget_logical_to_character_height):
+	* indent.c (vmotion_pixels):
+	* redisplay-output.c (get_cursor_size_and_location):
+	* redisplay-xlike-inc.c (XLIKE_output_eol_cursor):
+	* redisplay-xlike-inc.c (XLIKE_flash):
+	* redisplay.c (calculate_baseline):
+	* redisplay.c (start_with_point_on_display_line):
+	* redisplay.c (glyph_to_pixel_translation):
+	* redisplay.c (pixel_to_glyph_translation):
+	* window.c (margin_width_internal):
+	* window.c (frame_size_valid_p):
+	* window.c (frame_pixsize_valid_p):
+	* window.c (check_frame_size):
+	* window.c (set_window_pixsize):
+	* window.c (window_pixel_height_to_char_height):
+	* window.c (window_char_height_to_pixel_height):
+	* window.c (window_displayed_height):
+	* window.c (window_pixel_width_to_char_width):
+	* window.c (window_char_width_to_pixel_width):
+	* window.c (change_window_height):
+	* window.c (window_scroll):
+	* window.h:
+	IMPORTANT: Aidan and Carbon Repo, please pay attention and fix
+	appropriately!
+	
+	Rename: default_face_height_and_width -> default_face_width_and_height
+	and reverse width/height arguments.
+
+	Reverse width/height arguments to the following functions:
+	-- default_face_font_info
+	-- default_face_height_and_width (see above)
+	-- check_frame_size
+	-- frame_size_valid_p (made into a static function)
+
+	Fix a redisplay bug where args to default_face_height_and_width
+	were in the wrong order.
+	
+
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* syswindows.h:
+	Add table about GNU Emacs -> XEmacs Windows constants from
+	the internals manual.
+
+	* frame.c:
+	Shrink size of diagram consistent with internals manual.
+	
+	* alloc.c:
+	* compiler.h:
+	* console.c:
+	* events.c:
+	* gc.c (gc_stat_start_new_gc):
+	* gc.c (gc_stat_resume_gc):
+	* gc.c (kkcc_marking):
+	* gc.c (gc_1):
+	* gc.c (gc):
+	* objects-tty.c:
+	* redisplay-msw.c:
+	* redisplay-msw.c (mswindows_clear_region):
+	* syntax.c:
+	* syntax.c (ST_COMMENT_STYLE):
+	* sysdep.c:
+	Fix various compiler warnings.
+
+2010-02-16  Ben Wing  <ben@xemacs.org>
+
+	* frame-impl.h:
+	* frame-impl.h (FRAME_INTERNAL_BORDER_WIDTH):
+	* frame-impl.h (FRAME_REAL_TOOLBAR_BOUNDS):
+	* frame-impl.h (FRAME_REAL_TOP_TOOLBAR_BOUNDS):
+	* frame-impl.h (FRAME_BOTTOM_BORDER_START):
+	* frame-impl.h (FRAME_LEFT_BORDER_START):
+	* frame-impl.h (FRAME_RIGHT_BORDER_START):
+	* frame.c (frame_conversion_internal_1):
+	* frame.c (change_frame_size_1):
+	* redisplay-output.c (clear_left_border):
+	* redisplay-output.c (clear_right_border):
+	* redisplay-output.c (redisplay_clear_top_of_window):
+	* redisplay-output.c (redisplay_clear_to_window_end):
+	* redisplay-output.c (redisplay_clear_bottom_of_window):
+	Rename FRAME_BORDER_* to FRAME_INTERNAL_BORDER_*.  Add
+	general FRAME_INTERNAL_BORDER_SIZE().  Add FRAME_REAL_TOOLBAR_BOUNDS()
+	to encompass the entire size of the toolbar including its border.
+	Add specific top/left/bottom/right versions of this macro.
+	Rewrite FRAME_*_BORDER_START and FRAME_*_BORDER_END to take into use
+	FRAME_REAL_*_TOOLBAR_BOUNDS().  Add some comments about existing
+	problems in frame sizing and how they might be fixed.  Simplify
+	change_frame_size_1() using the macros just created.
+
+2010-02-15  Ben Wing  <ben@xemacs.org>
+
+	* frame.c (change_frame_size_1):
+	Simplify the logic in this function.
+
+	(1) Don't allow 0 as the value of height or width.  The old code
+	that tried to allow this was totally broken, anyway, so obviously
+	this never happens any more.
+
+	(2) Don't duplicate the code in frame_conversion_internal() that
+	converts displayable pixel size to total pixel size -- just call
+	that function.
+
+2010-02-15  Ben Wing  <ben@xemacs.org>
+
+	* EmacsFrame.c:
+	* EmacsFrame.c (EmacsFrameResize):
+	* console-msw-impl.h:
+	* console-msw-impl.h (struct mswindows_frame):
+	* console-msw-impl.h (FRAME_MSWINDOWS_TARGET_RECT):
+	* device-tty.c:
+	* device-tty.c (tty_asynch_device_change):
+	* event-msw.c:
+	* event-msw.c (mswindows_wnd_proc):
+	* faces.c (Fface_list):
+	* faces.h:
+	* frame-gtk.c:
+	* frame-gtk.c (gtk_set_initial_frame_size):
+	* frame-gtk.c (gtk_set_frame_size):
+	* frame-msw.c:
+	* frame-msw.c (mswindows_init_frame_1):
+	* frame-msw.c (mswindows_set_frame_size):
+	* frame-msw.c (mswindows_size_frame_internal):
+	* frame-msw.c (msprinter_init_frame_3):
+	* frame.c:
+	* frame.c (enum):
+	* frame.c (Fmake_frame):
+	* frame.c (adjust_frame_size):
+	* frame.c (store_minibuf_frame_prop):
+	* frame.c (Fframe_property):
+	* frame.c (Fframe_properties):
+	* frame.c (Fframe_displayable_pixel_height):
+	* frame.c (Fframe_displayable_pixel_width):
+	* frame.c (internal_set_frame_size):
+	* frame.c (Fset_frame_height):
+	* frame.c (Fset_frame_pixel_height):
+	* frame.c (Fset_frame_displayable_pixel_height):
+	* frame.c (Fset_frame_width):
+	* frame.c (Fset_frame_pixel_width):
+	* frame.c (Fset_frame_displayable_pixel_width):
+	* frame.c (Fset_frame_size):
+	* frame.c (Fset_frame_pixel_size):
+	* frame.c (Fset_frame_displayable_pixel_size):
+	* frame.c (frame_conversion_internal_1):
+	* frame.c (get_frame_displayable_pixel_size):
+	* frame.c (change_frame_size_1):
+	* frame.c (change_frame_size):
+	* frame.c (generate_title_string):
+	* frame.h:
+	* gtk-xemacs.c:
+	* gtk-xemacs.c (gtk_xemacs_size_request):
+	* gtk-xemacs.c (gtk_xemacs_size_allocate):
+	* gtk-xemacs.c (gtk_xemacs_paint):
+	* gutter.c:
+	* gutter.c (update_gutter_geometry):
+	* redisplay.c (end_hold_frame_size_changes):
+	* redisplay.c (redisplay_frame):
+	* toolbar.c:
+	* toolbar.c (update_frame_toolbars_geometry):
+	* window.c:
+	* window.c (frame_pixsize_valid_p):
+	* window.c (check_frame_size):
+	Various fixes to frame geometry to make it a bit easier to understand
+	and fix some bugs.
+
+	1. IMPORTANT: Some renamings.  Will need to be applied carefully to
+	the carbon repository, in the following order:
+
+	-- pixel_to_char_size -> pixel_to_frame_unit_size
+	-- char_to_pixel_size -> frame_unit_to_pixel_size
+	-- pixel_to_real_char_size -> pixel_to_char_size
+	-- char_to_real_pixel_size -> char_to_pixel_size
+	-- Reverse second and third arguments of change_frame_size() and
+	   change_frame_size_1() to try to make functions consistent in
+	   putting width before height.
+	-- Eliminate old round_size_to_char, because it didn't really
+	   do anything differently from round_size_to_real_char()
+	-- round_size_to_real_char -> round_size_to_char; any places that
+	   called the old round_size_to_char should just call the new one.
+
+	2. IMPORTANT FOR CARBON: The set_frame_size() method is now passed
+	   sizes in "frame units", like all other frame-sizing functions,
+	   rather than some hacked-up combination of char-cell units and
+	   total pixel size.  This only affects window systems that use
+	   "pixelated geometry", and I'm not sure if Carbon is one of them.
+	   MS Windows is pixelated, X and GTK are not.  For pixelated-geometry
+	   systems, the size in set_frame_size() is in displayable pixels
+	   rather than total pixels and needs to be converted appropriately;
+	   take a look at the changes made to mswindows_set_frame_size()
+	   method if necessary.
+	
+	3. Add a big long comment in frame.c describing how frame geometry
+	   works.
+
+	4. Remove MS Windows-specific character height and width fields,
+	   duplicative and unused.
+
+	5. frame-displayable-pixel-* and set-frame-displayable-pixel-*
+	   didn't use to work on MS Windows, but they do now.
+
+	6. In general, clean up the handling of "pixelated geometry" so
+	   that fewer functions have to worry about this.  This is really
+	   an abomination that should be removed entirely but that will
+	   have to happen later.  Fix some buggy code in
+	   frame_conversion_internal() that happened to "work" because it
+	   was countered by oppositely buggy code in change_frame_size().
+
+	7. Clean up some frame-size code in toolbar.c and use functions
+	   already provided in frame.c instead of rolling its own.
+
+	8. Fix check_frame_size() in window.c, which formerly didn't take
+	   pixelated geometry into account.
+
+
+2010-02-15  Ben Wing  <ben@xemacs.org>
+
+	* mc-alloc.c:
+	* mc-alloc.c (mc_realloc_1):
+	* mc-alloc.c (set_dirty_bit):
+	* mc-alloc.c (set_dirty_bit_for_address):
+	* mc-alloc.c (get_dirty_bit):
+	* mc-alloc.c (get_dirty_bit_for_address):
+	* mc-alloc.c (set_protection_bit):
+	* mc-alloc.c (set_protection_bit_for_address):
+	* mc-alloc.c (get_protection_bit):
+	* mc-alloc.c (get_protection_bit_for_address):
+	* mc-alloc.c (get_page_start):
+	* vdb-win32.c (win32_fault_handler):
+	* vdb.c:
+	Fix some compile warnings, make vdb test code conditional on
+	DEBUG_XEMACS.
+	
+2010-02-15  Ben Wing  <ben@xemacs.org>
+
+	* regex.c:
+	* regex.c (DEBUG_FAIL_PRINT1):
+	* regex.c (PUSH_FAILURE_POINT):
+	* regex.c (POP_FAILURE_POINT):
+	* regex.c (regex_compile):
+	* regex.c (re_match_2_internal):
+	* regex.h:
+	* search.c:
+	* search.c (search_buffer):
+	* search.c (debug_regexps_changed):
+	* search.c (vars_of_search):
+	Add an internal variable debug_regexps and a corresponding Lisp
+	variable `debug-regexps' that takes a list of areas in which to
+	display debugging info about regex compilation and matching
+	(currently three areas exist).  Use existing debugging code
+	already in regex.c and modify it so that it recognizes the
+	debug_regexps variable and the flags in it.
+
+	Rename variable `debug-xemacs-searches' to just `debug-searches',
+	consistent with other debug vars.
+
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* device-x.c (Fx_get_resource):
+	* dynarr.c:
+	* dynarr.c (Dynarr_realloc):
+	* dynarr.c (Dynarr_newf):
+	* dynarr.c (Dynarr_lisp_realloc):
+	* dynarr.c (Dynarr_lisp_newf):
+	* dynarr.c (Dynarr_resize):
+	* dynarr.c (Dynarr_insert_many):
+	* dynarr.c (Dynarr_delete_many):
+	* dynarr.c (Dynarr_memory_usage):
+	* dynarr.c (stack_like_free):
+	* file-coding.c (coding_reader):
+	* file-coding.c (gzip_convert):
+	* gutter.c (output_gutter):
+	* lisp.h:
+	* lisp.h (Dynarr_declare):
+	* lisp.h (DYNARR_SET_LISP_IMP):
+	* lisp.h (CHECK_NATNUM):
+	* profile.c (create_timing_profile_table):
+	* redisplay-output.c (sync_rune_structs):
+	* redisplay-output.c (sync_display_line_structs):
+	* redisplay-output.c (redisplay_output_window):
+	* redisplay.c:
+	* redisplay.c (get_display_block_from_line):
+	* redisplay.c (add_ichar_rune_1):
+	* redisplay.c (ensure_modeline_generated):
+	* redisplay.c (generate_displayable_area):
+	* redisplay.c (regenerate_window):
+	* redisplay.c (update_line_start_cache):
+	* signal.c:
+	* signal.c (check_quit):
+
+	Lots of rewriting of dynarr code.
+
+	(1) Lots of documentation added.  Also fix places that
+	referenced a now-bogus internals node concerning redisplay
+	critical sections.
+	
+	(2) Rename:
+
+	Dynarr_add_lisp_string -> Dynarr_add_ext_lisp_string
+	Dynarr_set_length -> Dynarr_set_lengthr ("restricted")
+	Dynarr_increment -> Dynarr_incrementr
+	Dynarr_resize_if -> Dynarr_resize_to_add
+
+	(3) New functions:
+
+	Dynarr_elsize = dy->elsize_
+	Dynarr_set_length(): Set length, resizing as necessary
+	Dynarr_set_length_and_zero(): Set length, resizing as necessary,
+	  zeroing out new elements
+	Dynarr_increase_length(), Dynarr_increase_length_and_zero():
+	  Optimization of Dynarr_set_length(), Dynarr_set_length_and_zero()
+	  when size is known to increase
+	Dynarr_resize_to_fit(): Resize as necessary to fit a given length.
+	Dynarr_set(): Set element at a given position, increasing length
+	  as necessary and setting any newly created positions to 0
+	
+	(4) Use Elemcount, Bytecount.
+
+	(5) Rewrite many macros as inline functions.
+
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* tests.c:
+	Fix operation of c-tests.
+
 2010-02-19  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* fns.c (split_string_by_ichar_1):
--- a/src/EmacsFrame.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/EmacsFrame.c	Sat Feb 20 23:56:01 2010 -0600
@@ -324,8 +324,8 @@
 
   update_various_frame_slots (ew);
 
-  pixel_to_char_size (f, ew->core.width, ew->core.height, &columns, &rows);
-  change_frame_size (f, rows, columns, 0);
+  pixel_to_frame_unit_size (f, ew->core.width, ew->core.height, &columns, &rows);
+  change_frame_size (f, columns, rows, 0);
 
   /* The code below is just plain wrong.  If the EmacsShell or EmacsManager
      needs to know, they should just ask.  If needed information is being
@@ -591,7 +591,7 @@
 
   assert (XtIsSubclass (w, emacsFrameClass));
 
-  default_face_height_and_width (wrap_frame (f), &ch, &cw);
+  default_face_width_and_height (wrap_frame (f), &cw, &ch);
   if (FRAME_X_TOP_LEVEL_FRAME_P (f))
     x_wm_set_cell_size (FRAME_X_SHELL_WIDGET (f), cw, ch);
 }
--- a/src/alloc.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/alloc.c	Sat Feb 20 23:56:01 2010 -0600
@@ -3438,6 +3438,8 @@
   Dynarr_add (mcpro_names, varname);
 }
 
+const Ascbyte *mcpro_name (int count);
+
 /* External debugging function: Return the name of the variable at offset
    COUNT. */
 const Ascbyte *
--- a/src/compiler.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/compiler.h	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* Compiler-specific definitions for XEmacs.
    Copyright (C) 1998-1999, 2003 Free Software Foundation, Inc.
    Copyright (C) 1994 Richard Mlynarik.
-   Copyright (C) 1995, 1996, 2000-2004 Ben Wing.
+   Copyright (C) 1995, 1996, 2000-2004, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -233,23 +233,44 @@
 #  define ATTRIBUTE_UNUSED
 # endif
 # define UNUSED(decl) UNUSED_ARG (decl) ATTRIBUTE_UNUSED
-# ifdef MULE
-#  define USED_IF_MULE(decl) decl
-# else
-#  define USED_IF_MULE(decl) UNUSED (decl)
-# endif
-# ifdef HAVE_XFT
-#  define USED_IF_XFT(decl) decl
-# else
-#  define USED_IF_XFT(decl) UNUSED (decl)
-# endif
-# ifdef HAVE_SCROLLBARS
-#  define USED_IF_SCROLLBARS(decl) decl
-# else
-#  define USED_IF_SCROLLBARS(decl) UNUSED (decl)
-# endif
 #endif /* UNUSED */
 
+/* Various macros for params/variables used or unused depending on
+   config flags. */
+
+#ifdef MULE
+# define USED_IF_MULE(decl) decl
+#else
+# define USED_IF_MULE(decl) UNUSED (decl)
+#endif
+#ifdef HAVE_XFT
+# define USED_IF_XFT(decl) decl
+#else
+# define USED_IF_XFT(decl) UNUSED (decl)
+#endif
+#ifdef HAVE_SCROLLBARS
+# define USED_IF_SCROLLBARS(decl) decl
+#else
+# define USED_IF_SCROLLBARS(decl) UNUSED (decl)
+#endif
+#ifdef NEW_GC
+# define USED_IF_NEW_GC(decl) decl
+# define UNUSED_IF_NEW_GC(decl) UNUSED (decl)
+#else
+# define USED_IF_NEW_GC(decl) UNUSED (decl)
+# define UNUSED_IF_NEW_GC(decl) decl
+#endif
+#ifdef HAVE_TTY
+#define USED_IF_TTY(decl) decl
+#else
+#define USED_IF_TTY(decl) UNUSED (decl)
+#endif
+#ifdef HAVE_TOOLBARS
+#define USED_IF_TOOLBARS(decl) decl
+#else
+#define USED_IF_TOOLBARS(decl) UNUSED (decl)
+#endif
+
 /* Declaration that variable or expression X is "used" to defeat
    "unused variable" warnings.  DON'T DO THIS FOR PARAMETERS IF IT ALL
    POSSIBLE.  Use an UNUSED() or USED_IF_*() declaration on the parameter
--- a/src/console-msw-impl.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/console-msw-impl.h	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* Define mswindows-specific console, device, and frame object for XEmacs.
    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
-   Copyright (C) 2001, 2002 Ben Wing.
+   Copyright (C) 2001, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -206,10 +206,6 @@
   /* Frame title hash value. See frame-msw.c */
   unsigned int title_checksum;
 
-  /* Real character width and height of the frame.
-     FRAME_{HEIGHT,WIDTH} do not work for pixel geometry! */
-  int charheight, charwidth;
-
 #ifdef MULE
   int cursor_x;
   int cursor_y;
@@ -259,8 +255,6 @@
  (FRAME_MSWINDOWS_DATA (f)->toolbar_checksum[pos])
 #define FRAME_MSWINDOWS_MENU_CHECKSUM(f)  (FRAME_MSWINDOWS_DATA (f)->menu_checksum)
 #define FRAME_MSWINDOWS_TITLE_CHECKSUM(f) (FRAME_MSWINDOWS_DATA (f)->title_checksum)
-#define FRAME_MSWINDOWS_CHARWIDTH(f)	  (FRAME_MSWINDOWS_DATA (f)->charwidth)
-#define FRAME_MSWINDOWS_CHARHEIGHT(f)	  (FRAME_MSWINDOWS_DATA (f)->charheight)
 #define FRAME_MSWINDOWS_TARGET_RECT(f)	  (FRAME_MSWINDOWS_DATA (f)->target_rect)
 
 #define FRAME_MSWINDOWS_POPUP(f)	  (FRAME_MSWINDOWS_DATA (f)->popup)
--- a/src/console.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/console.c	Sat Feb 20 23:56:01 2010 -0600
@@ -43,12 +43,6 @@
 #include "console-tty-impl.h"
 #endif
 
-#ifdef HAVE_TTY
-#define USED_IF_TTY(decl) decl
-#else
-#define USED_IF_TTY(decl) UNUSED (decl)
-#endif
-
 Lisp_Object Vconsole_list, Vselected_console;
 
 Lisp_Object Vcreate_console_hook, Vdelete_console_hook;
--- a/src/device-tty.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/device-tty.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* TTY device functions.
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1994, 1995 Free Software Foundation, Inc.
-   Copyright (C) 1996 Ben Wing.
+   Copyright (C) 1996, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -177,7 +177,7 @@
 
 	      /* We know the frame is tty because we made sure that the
 		 device is tty. */
-	      change_frame_size (f, height, width, 1);
+	      change_frame_size (f, width, height, 1);
 	    }
 	}
     }
--- a/src/device-x.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/device-x.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1564,9 +1564,9 @@
   db = XtDatabase (display);
   codesys = coding_system_of_xrm_database (db);
   Dynarr_add (name_Extbyte_dynarr, '.');
-  Dynarr_add_lisp_string (name_Extbyte_dynarr, name, Qbinary);
+  Dynarr_add_ext_lisp_string (name_Extbyte_dynarr, name, Qbinary);
   Dynarr_add (class_Extbyte_dynarr, '.');
-  Dynarr_add_lisp_string (class_Extbyte_dynarr, class_, Qbinary);
+  Dynarr_add_ext_lisp_string (class_Extbyte_dynarr, class_, Qbinary);
   Dynarr_add (name_Extbyte_dynarr,  '\0');
   Dynarr_add (class_Extbyte_dynarr, '\0');
 
--- a/src/dynarr.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/dynarr.c	Sat Feb 20 23:56:01 2010 -0600
@@ -25,16 +25,16 @@
 
 /*
 
-A "dynamic array" is a contiguous array of fixed-size elements where there
-is no upper limit (except available memory) on the number of elements in the
-array.  Because the elements are maintained contiguously, space is used
-efficiently (no per-element pointers necessary) and random access to a
-particular element is in constant time.  At any one point, the block of memory
-that holds the array has an upper limit; if this limit is exceeded, the
-memory is realloc()ed into a new array that is twice as big.  Assuming that
-the time to grow the array is on the order of the new size of the array
-block, this scheme has a provably constant amortized time (i.e. average
-time over all additions).
+A "dynamic array" or "dynarr" is a contiguous array of fixed-size elements
+where there is no upper limit (except available memory) on the number of
+elements in the array.  Because the elements are maintained contiguously,
+space is used efficiently (no per-element pointers necessary) and random
+access to a particular element is in constant time.  At any one point, the
+block of memory that holds the array has an upper limit; if this limit is
+exceeded, the memory is realloc()ed into a new array that is twice as big.
+Assuming that the time to grow the array is on the order of the new size of
+the array block, this scheme has a provably constant amortized time
+\(i.e. average time over all additions).
 
 When you add elements or retrieve elements, pointers are used.  Note that
 the element itself (of whatever size it is), and not the pointer to it,
@@ -52,12 +52,129 @@
 
 Use the following functions/macros:
 
+
+  ************* Dynarr creation *************
+
    void *Dynarr_new(type)
       [MACRO] Create a new dynamic-array object, with each element of the
       specified type.  The return value is cast to (type##_dynarr).
       This requires following the convention that types are declared in
       such a way that this type concatenation works.  In particular, TYPE
-      must be a symbol, not an arbitrary C type.
+      must be a symbol, not an arbitrary C type.  To make dynarrs of
+      complex types, a typedef must be declared, e.g.
+
+      typedef unsigned char *unsigned_char_ptr;
+
+      and then you can say
+
+      unsigned_char_ptr_dynarr *dyn = Dynarr_new (unsigned_char_ptr);
+
+   void *Dynarr_new2(dynarr_type, type)
+      [MACRO] Create a new dynamic-array object, with each element of the
+      specified type.  The array itself is of type DYNARR_TYPE.  This makes
+      it possible to create dynarrs over complex types without the need
+      to create typedefs, as described above.  Use is as follows:
+
+      ucharptr_dynarr *dyn = Dynarr_new2 (ucharptr_dynarr *, unsigned char *);
+
+   Dynarr_free(d)
+      Destroy a dynamic array and the memory allocated to it.
+
+  ************* Dynarr access *************
+
+   type Dynarr_at(d, i)
+      [MACRO] Return the element at the specified index.  The index must be
+      between 0 and Dynarr_largest(d), inclusive.  With error-checking
+      enabled, bounds checking on the index is in the form of asserts() --
+      an out-of-bounds index causes an abort.  The element itself is
+      returned, not a pointer to it.
+
+   type *Dynarr_atp(d, i)
+      [MACRO] Return a pointer to the element at the specified index.
+      Restrictions and bounds checking on the index is as for Dynarr_at.
+      The pointer may not be valid after an element is added to or
+      (conceivably) removed from the array, because this may trigger a
+      realloc() performed on the underlying dynarr storage, which may
+      involve moving the entire underlying storage to a new location in
+      memory.
+
+   type *Dynarr_begin(d)
+      [MACRO] Return a pointer to the first element in the dynarr.  See
+      Dynarr_atp() for warnings about when the pointer might become invalid.
+
+   type *Dynarr_lastp(d)
+      [MACRO] Return a pointer to the last element in the dynarr.  See
+      Dynarr_atp() for warnings about when the pointer might become invalid.
+
+   type *Dynarr_past_lastp(d)
+      [MACRO] Return a pointer to the beginning of the element just past the
+      last one.  WARNING: This may not point to valid memory; however, the
+      byte directly before will be pointer will be valid memory.  This macro
+      might be useful for various reasons, e.g. as a stopping point in a loop
+      (although Dynarr_lastp() could be used just as well) or as a place to
+      start writing elements if Dynarr_length() < Dynarr_largest().
+
+  ************* Dynarr length/size retrieval and setting *************
+
+   int Dynarr_length(d)
+      [MACRO] Return the number of elements currently in a dynamic array.
+
+   int Dynarr_largest(d)
+      [MACRO] Return the maximum value that Dynarr_length(d) would
+      ever have returned.  This is used esp. in the redisplay code,
+      which reuses dynarrs for performance reasons.
+
+   int Dynarr_max(d)
+      [MACRO] Return the maximum number of elements that can fit in the
+      dynarr before it needs to be resized.
+
+      Note that Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d).
+   
+   Bytecount Dynarr_sizeof(d)
+      [MACRO] Return the total size of the elements currently in dynarr
+      D.  This 
+
+   Dynarr_set_lengthr(d, len)
+      [MACRO] Set the length of D to LEN, which must be between 0 and
+      Dynarr_largest(d), inclusive.  With error-checking enabled, an
+      assertion failure will result from trying to set the length
+      to less than zero or greater than Dynarr_largest(d).  The
+      restriction to Dynarr_largest() is to ensure that
+
+   Dynarr_set_length(d, len)
+      [MACRO] Set the length of D to LEN, resizing the dynarr as
+      necessary to make sure enough space is available.  there are no
+      restrictions on LEN other than available memory and that it must
+      be at least 0.  Note that
+
+   Dynarr_set_length_and_zero(d, len)
+      [MACRO] Like Dynarr_set_length(d, len) but also, if increasing
+      the length, zero out the memory between the old and new lengths,
+      i.e. starting just past the previous last element and up through
+      the new last element.
+
+   Dynarr_incrementr(d)
+      [MACRO] Increments the length of D by 1.  Equivalent to
+      Dynarr_set_lengthr(d, Dynarr_length(d) + 1).
+
+   Dynarr_increment(d)
+      [MACRO] Increments the length of D by 1.  Equivalent to
+      Dynarr_set_length(d, Dynarr_length(d) + 1).
+
+   Dynarr_reset(d)
+      [MACRO] Reset the length of a dynamic array to 0.
+
+   Dynarr_resize(d, maxval)
+      Resize the internal dynarr storage to so that it can hold at least
+      MAXVAL elements.  Resizing is done using a geometric series
+      (repeatedly multiply the old maximum by a constant, normally 1.5,
+      till a large enough size is reached), so this will be efficient
+      even if resizing larger by one element at a time.  This is mostly
+      an internal function.
+
+
+
+  ************* Adding/deleting elements to/from a dynarr *************
 
    Dynarr_add(d, el)
       [MACRO] Add an element to the end of a dynamic array.  EL is a pointer
@@ -69,55 +186,47 @@
       should be contiguous in memory, starting at BASE.  If BASE if NULL,
       just make space for the elements; don't actually add them.
 
-   Dynarr_insert_many_at_start(d, base, len)
-      [MACRO] Append LEN elements to the beginning of the dynamic array.
+   Dynarr_prepend_many(d, base, len)
+      [MACRO] Prepend LEN elements to the beginning of the dynamic array.
       The elements should be contiguous in memory, starting at BASE.
       If BASE if NULL, just make space for the elements; don't actually
       add them.
 
-   Dynarr_insert_many(d, base, len, start)
+   Dynarr_insert_many(d, base, len, pos)
       Insert LEN elements to the dynamic array starting at position
-      START.  The elements should be contiguous in memory, starting at BASE.
+      POS.  The elements should be contiguous in memory, starting at BASE.
       If BASE if NULL, just make space for the elements; don't actually
       add them.
 
+   type Dynarr_pop(d)
+      [MACRO] Pop the last element off the dynarr and return it.
+
    Dynarr_delete(d, i)
       [MACRO] Delete an element from the dynamic array at position I.
 
-   Dynarr_delete_many(d, start, len)
+   Dynarr_delete_many(d, pos, len)
       Delete LEN elements from the dynamic array starting at position
-      START.
+      POS.
+
+   Dynarr_zero_many(d, pos, len)
+      Zero out LEN elements in the dynarr D starting at position POS.
 
    Dynarr_delete_by_pointer(d, p)
       [MACRO] Delete an element from the dynamic array at pointer P,
       which must point within the block of memory that stores the data.
       P should be obtained using Dynarr_atp().
 
-   int Dynarr_length(d)
-      [MACRO] Return the number of elements currently in a dynamic array.
-
-   int Dynarr_largest(d)
-      [MACRO] Return the maximum value that Dynarr_length(d) would
-      ever have returned.  This is used esp. in the redisplay code,
-      which reuses dynarrs for performance reasons.
-
-   type Dynarr_at(d, i)
-      [MACRO] Return the element at the specified index (no bounds checking
-      done on the index).  The element itself is returned, not a pointer
-      to it.
+  ************* Dynarr locking *************
 
-   type *Dynarr_atp(d, i)
-      [MACRO] Return a pointer to the element at the specified index (no
-      bounds checking done on the index).  The pointer may not be valid
-      after an element is added to or removed from the array.
+   Dynarr_lock(d)
+      Lock the dynarr against further locking or writing.  With error-checking
+      enabled, any attempts to write into a locked dynarr or re-lock an
+      already locked one will cause an assertion failure and abort.
 
-   Dynarr_reset(d)
-      [MACRO] Reset the length of a dynamic array to 0.
+   Dynarr_unlock(d)
+      Unlock a locked dynarr, allowing writing into it.
 
-   Dynarr_free(d)
-      Destroy a dynamic array and the memory allocated to it.
-
-Use the following global variable:
+  ************* Dynarr global variables *************
 
    Dynarr_min_size
       Minimum allowable size for a dynamic array when it is resized.
@@ -148,28 +257,28 @@
 };
 
 
-static int Dynarr_min_size = 8;
+static Elemcount Dynarr_min_size = 8;
 
 static void
-Dynarr_realloc (Dynarr *dy, int new_size)
+Dynarr_realloc (Dynarr *dy, Elemcount new_size)
 {
   if (DUMPEDP (dy->base))
     {
-      void *new_base = malloc (new_size * dy->elsize);
+      void *new_base = malloc (new_size * Dynarr_elsize (dy));
       memcpy (new_base, dy->base, 
 	      (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
-	      dy->elsize);
+	      Dynarr_elsize (dy));
       dy->base = new_base;
     }
   else
-    dy->base = xrealloc (dy->base, new_size * dy->elsize);
+    dy->base = xrealloc (dy->base, new_size * Dynarr_elsize (dy));
 }
 
 void *
-Dynarr_newf (int elsize)
+Dynarr_newf (Bytecount elsize)
 {
   Dynarr *d = xnew_and_zero (Dynarr);
-  d->elsize = elsize;
+  d->elsize_ = elsize;
 
   return d;
 }
@@ -182,23 +291,24 @@
 			       Dynarr);
 
 static void
-Dynarr_lisp_realloc (Dynarr *dy, int new_size)
+Dynarr_lisp_realloc (Dynarr *dy, Elemcount new_size)
 {
-  void *new_base = alloc_lrecord_array (dy->elsize, new_size, dy->lisp_imp);
+  void *new_base = alloc_lrecord_array (Dynarr_elsize (dy), new_size,
+					dy->lisp_imp);
   if (dy->base)
     memcpy (new_base, dy->base, 
 	    (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
-	    dy->elsize);
+	    Dynarr_elsize (dy));
   dy->base = new_base;
 }
 
 void *
-Dynarr_lisp_newf (int elsize, 
+Dynarr_lisp_newf (Bytecount elsize, 
 		  const struct lrecord_implementation *dynarr_imp, 
 		  const struct lrecord_implementation *imp)
 {
   Dynarr *d = (Dynarr *) alloc_lrecord (sizeof (Dynarr), dynarr_imp);
-  d->elsize = elsize;
+  d->elsize_ = elsize;
   d->lisp_imp = imp;
 
   return d;
@@ -208,7 +318,7 @@
 void
 Dynarr_resize (void *d, Elemcount size)
 {
-  int newsize;
+  Elemcount newsize;
   double multiplier;
   Dynarr *dy = (Dynarr *) Dynarr_verify (d);
 
@@ -218,7 +328,7 @@
     multiplier = 1.5;
 
   for (newsize = Dynarr_max (dy); newsize < size;)
-    newsize = max (Dynarr_min_size, (int) (multiplier * newsize));
+    newsize = max (Dynarr_min_size, (Elemcount) (multiplier * newsize));
 
   /* Don't do anything if the array is already big enough. */
   if (newsize > Dynarr_max (dy))
@@ -235,47 +345,46 @@
     }
 }
 
-/* Add a number of contiguous elements to the array starting at START. */
+/* Add a number of contiguous elements to the array starting at POS. */
+
 void
-Dynarr_insert_many (void *d, const void *el, int len, int start)
+Dynarr_insert_many (void *d, const void *base, Elemcount len, Elemcount pos)
 {
   Dynarr *dy = Dynarr_verify_mod (d);
-
-  Dynarr_resize_if (dy, len);
+  Elemcount old_len = Dynarr_length (dy);
 
   /* #### This could conceivably be wrong, if code wants to access stuff
      between len and largest. */
-  dynarr_checking_assert (start >= 0 && start <= Dynarr_length (dy));
+  dynarr_checking_assert (pos >= 0 && pos <= old_len);
+  dynarr_checking_assert (len >= 0);
+  Dynarr_increase_length (dy, old_len + len);
 
-  if (start != Dynarr_length (dy))
+  if (pos != old_len)
     {
-      memmove ((char *) dy->base + (start + len)*dy->elsize,
-	       (char *) dy->base + start*dy->elsize,
-	       (Dynarr_length (dy) - start)*dy->elsize);
+      memmove ((Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
+	       (Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
+	       (old_len - pos)*Dynarr_elsize (dy));
     }
   /* Some functions call us with a value of 0 to mean "reserve space but
      don't write into it" */
-  if (el)
-    memcpy ((char *) dy->base + start*dy->elsize, el, len*dy->elsize);
-
-  Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
-  (void) Dynarr_verify_mod (dy);
+  if (base)
+    memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
+	    len*Dynarr_elsize (dy));
 }
 
 void
-Dynarr_delete_many (void *d, int start, int len)
+Dynarr_delete_many (void *d, Elemcount pos, Elemcount len)
 {
   Dynarr *dy = Dynarr_verify_mod (d);
 
-  dynarr_checking_assert (start >= 0 && len >= 0 &&
-			  start + len <= Dynarr_length (dy));
+  dynarr_checking_assert (pos >= 0 && len >= 0 &&
+			  pos + len <= Dynarr_length (dy));
 
-  memmove ((char *) dy->base + start*dy->elsize,
-	   (char *) dy->base + (start + len)*dy->elsize,
-	   (Dynarr_length (dy) - start - len)*dy->elsize);
+  memmove ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy),
+	   (Rawbyte *) dy->base + (pos + len)*Dynarr_elsize (dy),
+	   (Dynarr_length (dy) - pos - len)*Dynarr_elsize (dy));
 
   Dynarr_set_length_1 (dy, Dynarr_length (dy) - len);
-  (void) Dynarr_verify_mod (dy);
 }
 
 void
@@ -304,9 +413,9 @@
 
 #ifdef MEMORY_USAGE_STATS
 
-/* Return memory usage for Dynarr D.  The returned value is the total
-   amount of bytes actually being used for the Dynarr, including all
-   overhead.  The extra amount of space in the Dynarr that is
+/* Return memory usage for dynarr D.  The returned value is the total
+   amount of bytes actually being used for the dynarr, including all
+   overhead.  The extra amount of space in the dynarr that is
    allocated beyond what was requested is returned in DYNARR_OVERHEAD
    in STATS.  The extra amount of space that malloc() allocates beyond
    what was requested of it is returned in MALLOC_OVERHEAD in STATS.
@@ -325,12 +434,13 @@
   if (dy->base)
     {
       Bytecount malloc_used =
-	malloced_storage_size (dy->base, dy->elsize * Dynarr_max (dy), 0);
-      /* #### This may or may not be correct.  Some Dynarrs would
+	malloced_storage_size (dy->base, Dynarr_elsize (dy) * Dynarr_max (dy),
+			       0);
+      /* #### This may or may not be correct.  Some dynarrs would
 	 prefer that we use dy->len instead of dy->largest here. */
-      Bytecount was_requested = dy->elsize * Dynarr_largest (dy);
+      Bytecount was_requested = Dynarr_elsize (dy) * Dynarr_largest (dy);
       Bytecount dynarr_overhead =
-	dy->elsize * (Dynarr_max (dy) - Dynarr_largest (dy));
+	Dynarr_elsize (dy) * (Dynarr_max (dy) - Dynarr_largest (dy));
 
       total += malloc_used;
       stats->was_requested += was_requested;
@@ -385,7 +495,7 @@
 void
 stack_like_free (void *val)
 {
-  int len = Dynarr_length (stack_like_in_use_list);
+  Elemcount len = Dynarr_length (stack_like_in_use_list);
   assert (len > 0);
   /* The vast majority of times, we will be called in a last-in first-out
      order, and the item at the end of the list will be the one we're
--- a/src/event-msw.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/event-msw.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* The mswindows event_stream interface.
    Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 1996, 2000, 2001, 2002, 2003, 2005 Ben Wing.
+   Copyright (C) 1996, 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing.
    Copyright (C) 1997 Jonathan Harris.
 
 This file is part of XEmacs.
@@ -3386,13 +3386,9 @@
 	      FRAME_PIXWIDTH (frame) = rect.right;
 	      FRAME_PIXHEIGHT (frame) = rect.bottom;
 
-	      pixel_to_real_char_size (frame, rect.right, rect.bottom,
-				       &FRAME_MSWINDOWS_CHARWIDTH (frame),
-				       &FRAME_MSWINDOWS_CHARHEIGHT (frame));
-
-	      pixel_to_char_size (frame, rect.right, rect.bottom, &columns,
+	      pixel_to_frame_unit_size (frame, rect.right, rect.bottom, &columns,
 				  &rows);
-	      change_frame_size (frame, rows, columns, 1);
+	      change_frame_size (frame, columns, rows, 1);
 
 	      /* If we are inside frame creation, we have to apply geometric
 		 properties now. */
@@ -3477,7 +3473,7 @@
 				GetMenu(hwnd) != NULL,
 				qxeGetWindowLong (hwnd, GWL_EXSTYLE));
 
-	    round_size_to_real_char (XFRAME (mswindows_find_frame (hwnd)),
+	    round_size_to_char (XFRAME (mswindows_find_frame (hwnd)),
 				     wp->cx - (ncsize.right - ncsize.left),
 				     wp->cy - (ncsize.bottom - ncsize.top),
 				     &pixwidth, &pixheight);
--- a/src/events.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/events.c	Sat Feb 20 23:56:01 2010 -0600
@@ -41,18 +41,6 @@
 
 #include "console-tty-impl.h" /* for stuff in character_to_event */
 
-#ifdef HAVE_TTY
-#define USED_IF_TTY(decl) decl
-#else
-#define USED_IF_TTY(decl) UNUSED (decl)
-#endif
-
-#ifdef HAVE_TOOLBARS
-#define USED_IF_TOOLBARS(decl) decl
-#else
-#define USED_IF_TOOLBARS(decl) UNUSED (decl)
-#endif
-
 /* Where old events go when they are explicitly deallocated.
    The event chain here is cut loose before GC, so these will be freed
    eventually.
--- a/src/faces.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/faces.c	Sat Feb 20 23:56:01 2010 -0600
@@ -723,7 +723,7 @@
 
 void
 default_face_font_info (Lisp_Object domain, int *ascent, int *descent,
-			int *height, int *width, int *proportional_p)
+			int *width, int *height, int *proportional_p)
 {
   Lisp_Object font_instance;
   struct face_cachel *cachel;
@@ -782,25 +782,9 @@
 }
 
 void
-default_face_height_and_width (Lisp_Object domain,
-			       int *height, int *width)
-{
-  default_face_font_info (domain, 0, 0, height, width, 0);
-}
-
-void
-default_face_height_and_width_1 (Lisp_Object domain,
-				 int *height, int *width)
+default_face_width_and_height (Lisp_Object domain, int *width, int *height)
 {
-  if (window_system_pixelated_geometry (domain))
-    {
-      if (height)
-	*height = 1;
-      if (width)
-	*width = 1;
-    }
-  else
-    default_face_height_and_width (domain, height, width);
+  default_face_font_info (domain, 0, 0, width, height, 0);
 }
 
 DEFUN ("face-list", Fface_list, 0, 1, 0, /*
--- a/src/faces.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/faces.h	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Face data structures.
    Copyright (C) 1995 Board of Trustees, University of Illinois.
-   Copyright (C) 1995, 2002 Ben Wing
+   Copyright (C) 1995, 2002, 2010 Ben Wing
 
 This file is part of XEmacs.
 
@@ -299,12 +299,10 @@
 void face_property_was_changed (Lisp_Object face, Lisp_Object property,
 				Lisp_Object locale);
 void default_face_font_info (Lisp_Object domain, int *ascent,
-			     int *descent, int *height, int *width,
+			     int *descent, int *width, int *height,
 			     int *proportional_p);
-void default_face_height_and_width (Lisp_Object domain,
-				    int *height, int *width);
-void default_face_height_and_width_1 (Lisp_Object domain,
-				      int *height, int *width);
+void default_face_width_and_height (Lisp_Object domain, int *width,
+				    int *height);
 
 #define FACE_CACHEL_FONT(cachel, charset) \
   (cachel->font[XCHARSET_LEADING_BYTE (charset) - MIN_LEADING_BYTE])
--- a/src/file-coding.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/file-coding.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1864,7 +1864,7 @@
 				  Dynarr_atp (str->convert_from, rejected),
 				  readmore);
 	/* Trim size down to how much we actually got */
-	Dynarr_set_length (str->convert_from, rejected + max (0, read_size));
+	Dynarr_set_lengthr (str->convert_from, rejected + max (0, read_size));
       }
 
       if (read_size < 0) /* LSTREAM_ERROR */
@@ -1898,7 +1898,7 @@
 	  memmove (Dynarr_begin (str->convert_from),
 		   Dynarr_atp (str->convert_from, processed),
 		   to_process - processed);
-	Dynarr_set_length (str->convert_from, to_process - processed);
+	Dynarr_set_lengthr (str->convert_from, to_process - processed);
       }
     }
 
@@ -4423,7 +4423,7 @@
 	  data->stream.avail_out = reserved;
 	  zerr = inflate (&data->stream, Z_NO_FLUSH);
 	  /* Lop off the unused portion */
-	  Dynarr_set_length (dst, Dynarr_length (dst) - data->stream.avail_out);
+	  Dynarr_set_lengthr (dst, Dynarr_length (dst) - data->stream.avail_out);
 	  if (zerr != Z_OK)
 	    break;
 	}
@@ -4483,7 +4483,7 @@
 	    deflate (&data->stream,
 		     str->eof ? Z_FINISH : Z_NO_FLUSH);
 	  /* Lop off the unused portion */
-	  Dynarr_set_length (dst, Dynarr_length (dst) - data->stream.avail_out);
+	  Dynarr_set_lengthr (dst, Dynarr_length (dst) - data->stream.avail_out);
 	  if (zerr != Z_OK)
 	    break;
 	}
--- a/src/frame-gtk.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/frame-gtk.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Functions for the GTK toolkit.
    Copyright (C) 1989, 1992-5, 1997 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 2002, 2003 Ben Wing.
+   Copyright (C) 1995, 1996, 2002, 2003, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -373,7 +373,7 @@
     {
       GdkWindowHints geometry_mask = GDK_HINT_RESIZE_INC;
       /* Deal with the cell size */
-      default_face_height_and_width (wrap_frame (f), &geometry.height_inc, &geometry.width_inc);
+      default_face_width_and_height (wrap_frame (f), &geometry.width_inc, &geometry.height_inc);
 
       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
 				     FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
@@ -384,7 +384,7 @@
   FRAME_HEIGHT (f) = h;
   FRAME_WIDTH (f) = w;
 
-  change_frame_size (f, h, w, 0);
+  change_frame_size (f, w, h, 0);
   {
     GtkRequisition req;
  
@@ -1191,13 +1191,14 @@
       GdkWindowHints geometry_mask = GDK_HINT_RESIZE_INC;
 
       /* Update the cell size */
-      default_face_height_and_width (wrap_frame (f), &geometry.height_inc, &geometry.width_inc);
+      default_face_width_and_height (wrap_frame (f), &geometry.width_inc,
+				     &geometry.height_inc);
 
       gtk_window_set_geometry_hints (GTK_WINDOW (shell),
 				     FRAME_GTK_TEXT_WIDGET (f), &geometry, geometry_mask);
     }
 
-  change_frame_size (f, rows, cols, 0);
+  change_frame_size (f, cols, rows, 0);
 
   {
     GtkRequisition req;
@@ -1372,7 +1373,7 @@
       gint width_inc = 10;
       gint height_inc = 10;
 
-      default_face_height_and_width (wrap_frame (frm), &height_inc, &width_inc);
+      default_face_width_and_height (wrap_frame (frm), &width_inc, &height_inc);
       geometry_mask = GDK_HINT_RESIZE_INC;
       geometry.width_inc = width_inc;
       geometry.height_inc = height_inc;
--- a/src/frame-impl.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/frame-impl.h	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Define frame-object for XEmacs.
    Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 1995 Ben Wing.
+   Copyright (C) 1995, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -543,8 +543,16 @@
 
 #endif /* FSFmacs */
 
-#define FRAME_BORDER_WIDTH(f) ((f)->internal_border_width)
-#define FRAME_BORDER_HEIGHT(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_WIDTH(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_HEIGHT(f) ((f)->internal_border_width)
+#define FRAME_INTERNAL_BORDER_SIZE(f, pos) ((f)->internal_border_width)
+
+/************************************************************************/
+/*	                        toolbars      				*/
+/************************************************************************/
+
+/*---------------- Theoretical and real toolbar values ----------------*/
+
 
 /* This returns the frame-local value; that tells you what you should
    use when computing the frame size.  It is *not* the actual toolbar
@@ -657,6 +665,10 @@
    ? FRAME_RAW_REAL_TOOLBAR_BORDER_WIDTH (f, pos)	\
    : 0)
 
+#define FRAME_REAL_TOOLBAR_BOUNDS(f, pos)		\
+  (FRAME_REAL_TOOLBAR_SIZE (f, pos) +			\
+   2 * FRAME_REAL_TOOLBAR_BORDER_WIDTH (f, pos))
+
 #define FRAME_REAL_TOP_TOOLBAR_HEIGHT(f) \
   FRAME_REAL_TOOLBAR_SIZE (f, TOP_TOOLBAR)
 #define FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT(f) \
@@ -684,32 +696,39 @@
 #define FRAME_REAL_RIGHT_TOOLBAR_VISIBLE(f) \
   FRAME_REAL_TOOLBAR_VISIBLE (f, RIGHT_TOOLBAR)
 
+#define FRAME_REAL_TOP_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, TOP_TOOLBAR)
+#define FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, BOTTOM_TOOLBAR)
+#define FRAME_REAL_LEFT_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, LEFT_TOOLBAR)
+#define FRAME_REAL_RIGHT_TOOLBAR_BOUNDS(f) \
+  FRAME_REAL_TOOLBAR_BOUNDS (f, RIGHT_TOOLBAR)
+
+/************************************************************************/
+/*         frame dimensions defined using toolbars and gutters          */
+/************************************************************************/
+
+/* #### These should be using the gutter sizes, but aren't yet */
+
 #define FRAME_TOP_BORDER_START(f)				\
-  (FRAME_REAL_TOP_TOOLBAR_HEIGHT (f) +				\
-   2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f))
+  FRAME_REAL_TOP_TOOLBAR_BOUNDS (f)
 #define FRAME_TOP_BORDER_END(f)					\
-  (FRAME_TOP_BORDER_START (f) + FRAME_BORDER_HEIGHT (f))
+  (FRAME_TOP_BORDER_START (f) + FRAME_INTERNAL_BORDER_HEIGHT (f))
 
 #define FRAME_BOTTOM_BORDER_START(f)				\
-  (FRAME_PIXHEIGHT (f) - FRAME_BORDER_HEIGHT (f) -		\
-   FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -			\
-   2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_BOTTOM_BORDER_END (f) - FRAME_INTERNAL_BORDER_HEIGHT (f))
 #define FRAME_BOTTOM_BORDER_END(f)				\
-  (FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f) -	\
-   2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_PIXHEIGHT (f) - FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS (f))
 
 #define FRAME_LEFT_BORDER_START(f)				\
-  (FRAME_REAL_LEFT_TOOLBAR_WIDTH (f) +				\
-   2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f))
+  FRAME_REAL_LEFT_TOOLBAR_BOUNDS (f)
 #define FRAME_LEFT_BORDER_END(f)				\
-  (FRAME_LEFT_BORDER_START (f) + FRAME_BORDER_WIDTH (f))
+  (FRAME_LEFT_BORDER_START (f) + FRAME_INTERNAL_BORDER_WIDTH (f))
 
 #define FRAME_RIGHT_BORDER_START(f)				\
-  (FRAME_PIXWIDTH (f) - FRAME_BORDER_WIDTH (f) -		\
-   FRAME_REAL_RIGHT_TOOLBAR_WIDTH(f) -                          \
-   2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f))
+  (FRAME_RIGHT_BORDER_END (f) - FRAME_INTERNAL_BORDER_WIDTH (f))
 #define FRAME_RIGHT_BORDER_END(f)				\
-  (FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f) -	\
-   2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH(f))
+  (FRAME_PIXWIDTH (f) - FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f))
 
 #endif /* INCLUDED_frame_impl_h_ */
--- a/src/frame-msw.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/frame-msw.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Functions for the mswindows window system.
    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 2001, 2002 Ben Wing.
+   Copyright (C) 1995, 1996, 2001, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -238,7 +238,7 @@
       GetWindowRect (hwnd_parent, &rect);
       rect_default.left = rect.left + POPUP_OFFSET;
       rect_default.top = rect.top + POPUP_OFFSET;
-      char_to_real_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
+      char_to_pixel_size (f, POPUP_WIDTH, POPUP_HEIGHT,
 			       &rect_default.width, &rect_default.height);
       FRAME_MSWINDOWS_POPUP (f) = 1;
     }
@@ -375,14 +375,14 @@
 mswindows_set_frame_size (struct frame *f, int width, int height)
 {
   RECT rect;
-  int columns, rows;
+  int pwidth, pheight;
+
+  change_frame_size (f, width, height, 0);
+  frame_unit_to_pixel_size (f, width, height, &pwidth, &pheight);
 
   rect.left = rect.top = 0;
-  rect.right = width;
-  rect.bottom = height;
-
-  pixel_to_char_size (f, rect.right, rect.bottom, &columns, &rows);
-  change_frame_size (f, rows, columns, 0);
+  rect.right = pwidth;
+  rect.bottom = pheight;
 
   /* This can call Lisp, because it runs the window procedure, which can
      call redisplay() */
@@ -741,7 +741,7 @@
   int pixel_width, pixel_height;
   int size_p = (dest->width >=0 || dest->height >=0);
   int move_p = (dest->top >=0 || dest->left >=0);
-  char_to_real_pixel_size (f, dest->width, dest->height, &pixel_width,
+  char_to_pixel_size (f, dest->width, dest->height, &pixel_width,
 			   &pixel_height);
 
   if (dest->width < 0)
@@ -940,7 +940,7 @@
 
   if (FRAME_MSPRINTER_CHARWIDTH (f) > 0)
     {
-      char_to_real_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH (f), 0,
+      char_to_pixel_size (f, FRAME_MSPRINTER_CHARWIDTH (f), 0,
 			       &frame_width, NULL);
       FRAME_MSPRINTER_RIGHT_MARGIN(f) =
 	MulDiv (physicalwidth - (frame_left + frame_width), 1440,
@@ -956,7 +956,7 @@
 
   if (FRAME_MSPRINTER_CHARHEIGHT (f) > 0)
     {
-      char_to_real_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT (f),
+      char_to_pixel_size (f, 0, FRAME_MSPRINTER_CHARHEIGHT (f),
 			       NULL, &frame_height);
 
       FRAME_MSPRINTER_BOTTOM_MARGIN(f) =
@@ -986,8 +986,8 @@
     int rows, columns;
     FRAME_PIXWIDTH (f) = frame_width;
     FRAME_PIXHEIGHT (f) = frame_height;
-    pixel_to_char_size (f, frame_width, frame_height, &columns, &rows);
-    change_frame_size (f, rows, columns, 0);
+    pixel_to_frame_unit_size (f, frame_width, frame_height, &columns, &rows);
+    change_frame_size (f, columns, rows, 0);
   }
 
   FRAME_MSPRINTER_PIXLEFT(f) = frame_left;
--- a/src/frame.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/frame.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Generic frame functions.
    Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 2002, 2003, 2005 Ben Wing.
+   Copyright (C) 1995, 1996, 2002, 2003, 2005, 2010 Ben Wing.
    Copyright (C) 1995 Sun Microsystems, Inc.
 
 This file is part of XEmacs.
@@ -24,6 +24,290 @@
 
 /* This file has been Mule-ized. */
 
+/* About window and frame geometry [ben]:
+
+   Here is an ASCII diagram:
+
++------------------------------------------------------------------------|
+|                         window-manager decoration                      |
+| +--------------------------------------------------------------------+ |
+| |                               menubar                              | |
+| ###################################################################### |
+| #                               toolbar                              # |
+| #--------------------------------------------------------------------# |
+| #  |                            gutter                            |  # |
+| #  |--------------------------------------------------------------|  # |
+| #  | |                  internal border width                   | |  # |
+| #  | | ******************************************************** | |  # |
+|w#  | | *                         |s|v*                      |s* | |  #w|
+|i#  | | *                         |c|e*                      |c* | |  #i|
+|n#  | | *                         |r|r*                      |r* | |  #n|
+|d#  | | *                         |o|t*                      |o* | |  #d|
+|o#  | | *        text area        |l|.*      text area       |l* | |  #o|
+|w#  | |i*                         |l| *                      |l*i| |  #w|
+|-#  | |n*                         |b|d*                      |b*n| |  #-|
+|m#  | |t*                         |a|i*                      |a*t| |  #m|
+|a#  | |.*                         |r|v*                      |r*.| |  #a|
+|n# t| | *-------------------------+-|i*----------------------+-* | |t #n|
+|a# o|g|b*        scrollbar        | |d*      scrollbar       | *b|g|o #a|
+|g# o|u|o*-------------------------+-|e*----------------------+-*o|u|o #g|
+|e# l|t|r*        modeline           |r*      modeline          *r|t|l #e|
+|r# b|t|d********************************************************d|t|b #r|
+| # a|e|e*   =..texttexttex....=   |s|v*                      |s*e|e|a # |
+|d# r|r|r*o m=..texttexttextt..=o m|c|e*                      |c*r|r|r #d|
+|e#  | | *u a=.exttexttextte...=u a|r|r*                      |r* | |  #e|
+|c#  | |w*t r=....texttexttex..=t r|o|t*                      |o*w| |  #c|
+|o#  | |i*s g=        etc.     =s g|l|.*      text area       |l*i| |  #o|
+|r#  | |d*i i=                 =i i|l| *                      |l*d| |  #r|
+|a#  | |t*d n=                 =d n|b|d*                      |b*t| |  #a|
+|t#  | |h*e  = inner text area =e  |a|i*                      |a*h| |  #t|
+|i#  | | *   =                 =   |r|v*                      |r* | |  #i|
+|o#  | | *---===================---+-|i*----------------------+-* | |  #o|
+|n#  | | *        scrollbar        | |d*      scrollbar       | * | |  #n|
+| #  | | *-------------------------+-|e*----------------------+-* | |  # |
+| #  | | *        modeline           |r*      modeline          * | |  # |
+| #  | | ******************************************************** | |  # |
+| #  | | *                        minibuffer                    * | |  # |
+| #  | | ******************************************************** | |  # |
+| #  | |                   internal border width                  | |  # |
+| #  |--------------------------------------------------------------|  # |
+| #  |                             gutter                           |  # |
+| #--------------------------------------------------------------------# |
+| #                                toolbar                             # |
+| ###################################################################### |
+|                          window manager decoration                     |
++------------------------------------------------------------------------+
+
+   # = boundary of client area; * = window boundaries, boundary of paned area
+   = = boundary of inner text area; . = inside margin area
+
+   Note in particular what happens at the corners, where a "corner box"
+   occurs.  Top and bottom toolbars take precedence over left and right
+   toolbars, extending out horizontally into the corner boxes.  Gutters
+   work the same way.  The corner box where the scrollbars meet, however,
+   is assigned to neither scrollbar, and is known as the "dead box"; it is
+   an area that must be cleared specially.
+
+   THE FRAME
+   ---------
+
+   The "top-level window area" is the entire area of a top-level window (or
+   "frame").  The "client area" (a term from MS Windows) is the area of a
+   top-level window that XEmacs draws into and manages with redisplay.
+   This includes the toolbar, scrollbars, gutters, dividers, text area,
+   modeline and minibuffer.  It does not include the menubar, title or
+   outer borders.  The "non-client area" is the area of a top-level window
+   outside of the client area and includes the menubar, title and outer
+   borders.  Internally, all frame coordinates are relative to the client
+   area.
+
+
+   THE NON-CLIENT AREA
+   -------------------
+
+   Under X, the non-client area is split into two parts:
+
+   (1) The outer layer is the window-manager decorations: The title and
+   borders.  These are controlled by the window manager, a separate process
+   that controls the desktop, the location of icons, etc.  When a process
+   tries to create a window, the window manager intercepts this action and
+   "reparents" the window, placing another window around it which contains
+   the window decorations, including the title bar, outer borders used for
+   resizing, etc.  The window manager also implements any actions involving
+   the decorations, such as the ability to resize a window by dragging its
+   borders, move a window by dragging its title bar, etc.  If there is no
+   window manager or you kill it, windows will have no decorations (and
+   will lose them if they previously had any) and you will not be able to
+   move or resize them.
+
+   (2) Inside of the window-manager decorations is the "shell", which is
+   managed by the toolkit and widget libraries your program is linked with.
+   The code in *-x.c uses the Xt toolkit and various possible widget
+   libraries built on top of Xt, such as Motif, Athena, the "Lucid"
+   widgets, etc.  Another possibility is GTK (*-gtk.c), which implements
+   both the toolkit and widgets.  Under Xt, the "shell" window is an
+   EmacsShell widget, containing an EmacsManager widget of the same size,
+   which in turn contains a menubar widget and an EmacsFrame widget, inside
+   of which is the client area. (The division into EmacsShell and
+   EmacsManager is due to the complex and screwy geometry-management system
+   in Xt [and X more generally].  The EmacsShell handles negotation with
+   the window manager; the place of the EmacsManager widget is normally
+   assumed by a widget that manages the geometry of its child widgets, but
+   the EmacsManager widget just lets the XEmacs redisplay mechanism do the
+   positioning.)
+
+   Under Windows, the non-client area is managed by the window system.
+   There is no division such as under X.  Part of the window-system API
+   (USER.DLL) of Win32 includes functions to control the menubars, title,
+   etc. and implements the move and resize behavior.  There *is* an
+   equivalent of the window manager, called the "shell", but it manages
+   only the desktop, not the windows themselves.  The normal shell under
+   Windows is EXPLORER.EXE; if you kill this, you will lose the bar
+   containing the "Start" menu and tray and such, but the windows
+   themselves will not be affected or lose their decorations.
+
+
+   THE CLIENT AREA
+   ---------------
+
+   Inside of the client area is the toolbars, the gutters (where the buffer
+   tabs are displayed), the minibuffer, the internal border width, and one
+   or more non-overlapping "windows" (this is old Emacs terminology, from
+   before the time when frames existed at all; the standard terminology for
+   this would be "pane").  Each window can contain a modeline, horizontal
+   and/or vertical scrollbars, and (for non-rightmost windows) a vertical
+   divider, surrounding a text area.
+
+   The dimensions of the toolbars and gutters are determined by the formula
+   (THICKNESS + 2 * BORDER-THICKNESS), where "thickness" is a cover term
+   for height or width, as appropriate.  The height and width come from
+   `default-toolbar-height' and `default-toolbar-width' and the specific
+   versions of these (`top-toolbar-height', `left-toolbar-width', etc.).
+   The border thickness comes from `default-toolbar-border-height' and
+   `default-toolbar-border-width', and the specific versions of these.  The
+   gutter works exactly equivalently.
+
+   Note that for any particular toolbar or gutter, it will only be
+   displayed if [a] its visibility specifier (`default-toolbar-visible-p'
+   etc.) is non-nil; [b] its thickness (`default-toolbar-height' etc.)  is
+   greater than 0; [c] its contents (`default-toolbar' etc.) are non-nil.
+
+   The position-specific toolbars interact with the default specifications
+   as follows: If the value for a position-specific specifier is not
+   defined in a particular domain (usually a window), and the position of
+   that specifier is set as the default position (using
+   `default-toolbar-position'), then the value from the corresponding
+   default specifier in that domain will be used.  The gutters work the
+   same.
+
+
+   THE PANED AREA
+   --------------
+
+   The area occupied by the "windows" is called the paned area.  Note that
+   this includes the minibuffer, which is just another window but is
+   special-cased in XEmacs.  Each window can include a horizontal and/or
+   vertical scrollbar, a modeline and a vertical divider to its right, as
+   well as the text area.  Only non-rightmost windows can include a
+   vertical divider. (The minibuffer normally does not include either
+   modeline or scrollbars.)
+
+   Note that, because the toolbars and gutters are controlled by
+   specifiers, and specifiers can have window-specific and buffer-specific
+   values, the size of the paned area can change depending on which window
+   is selected: In other words, if the selected window or buffer changes,
+   the entire paned area for the frame may change.
+
+
+   TEXT AREAS, FRINGES, MARGINS
+   ----------------------------
+
+   The space occupied by a window can be divided into the text area and the
+   fringes.  The fringes include the modeline, scrollbars and vertical
+   divider on the right side (if any); inside of this is the text area,
+   where the text actually occurs.  Note that a window may or may not
+   contain any of the elements that are part of the fringe -- this is
+   controlled by specifiers, e.g. `has-modeline-p',
+   `horizontal-scrollbar-visible-p', `vertical-scrollbar-visible-p',
+   `vertical-divider-always-visible-p', etc.
+
+   In addition, it is possible to set margins in the text area using the
+   specifiers `left-margin-width' and `right-margin-width'.  When this is
+   done, only the "inner text area" (the area inside of the margins) will
+   be used for normal display of text; the margins will be used for glyphs
+   with a layout policy of `outside-margin' (as set on an extent containing
+   the glyph by `set-extent-begin-glyph-layout' or
+   `set-extent-end-glyph-layout').  However, the calculation of the text
+   area size (e.g. in the function `window-text-area-width') includes the
+   margins.  Which margin is used depends on whether a glyph has been set
+   as the begin-glyph or end-glyph of an extent (`set-extent-begin-glyph'
+   etc.), using the left and right margins, respectively.
+
+   Technically, the margins outside of the inner text area are known as the
+   "outside margins".  The "inside margins" are in the inner text area and
+   constitute the whitespace between the outside margins and the first or
+   last non-whitespace character in a line; their width can vary from line
+   to line.  Glyphs will be placed in the inside margin if their layout
+   policy is `inside-margin' or `whitespace', with `whitespace' glyphs on
+   the inside and `inside-margin' glyphs on the outside.  Inside-margin
+   glyphs can spill over into the outside margin if `use-left-overflow' or
+   `use-right-overflow', respectively, is non-nil.
+
+   See the Lisp Reference manual, under Annotations, for more details.
+
+
+   THE DISPLAYABLE AREA
+   --------------------
+
+   The "displayable area" is not so much an actual area as a convenient
+   fiction.  It is the area used to convert between pixel and character
+   dimensions for frames.  The character dimensions for a frame (e.g. as
+   returned by `frame-width' and `frame-height' and set by
+   `set-frame-width' and `set-frame-height') are determined from the
+   displayable area by dividing by the pixel size of the default font as
+   instantiated in the frame. (For proportional fonts, the "average" width
+   is used.  Under Windows, this is a built-in property of the fonts.
+   Under X, this is based on the width of the lowercase 'n', or if this is
+   zero then the width of the default character. [We prefer 'n' to the
+   specified default character because many X fonts have a default
+   character with a zero or otherwise non-representative width.])
+
+   The displayable area is essentially the "theoretical" paned area of the
+   frame excluding the rightmost and bottom-most scrollbars.  In this
+   context, "theoretical" means that all calculations on based on
+   frame-level values for toolbar, gutter and scrollbar thicknesses.
+   Because these thicknesses are controlled by specifiers, and specifiers
+   can have window-specific and buffer-specific values, these calculations
+   may or may not reflect the actual size of the paned area or of the
+   scrollbars when any particular window is selected.  Note also that the
+   "displayable area" may not even be contiguous!  In particular, if the
+   frame-level value of the horizontal scrollbar height is non-zero, then
+   the displayable area includes the paned area above and below the bottom
+   horizontal scrollbar but not the scrollbar itself.
+
+   As a further twist, the character-dimension calculations are adjusted so
+   that the truncation and continuation glyphs (see `truncation-glyph' and
+   `continuation-glyph') count as a single character even if they are wider
+   than the default font width. (Technically, the character width is
+   computed from the displayable-area width by subtracting the maximum of
+   the truncation-glyph width, continuation-glyph width and default-font
+   width before dividing by the default-font width, and then adding 1 to
+   the result.) (The ultimate motivation for this kludge as well as the
+   subtraction of the scrollbars, but not the minibuffer or bottom-most
+   modeline, is to maintain compatibility with TTY's.)
+
+   Despite all these concerns and kludges, however, the "displayable area"
+   concept works well in practice and mostly ensures that by default the
+   frame will actually fit 79 characters + continuation/truncation glyph.
+
+
+   WHICH FUNCTIONS USE WHICH?
+   --------------------------
+
+   [1] Top-level window area:
+
+   set-frame-position
+   `left' and `top' frame properties
+
+   [2] Client area:
+
+   frame-pixel-*, set-frame-pixel-*
+
+   [3] Paned area:
+
+   window-pixel-edges
+   event-x-pixel, event-y-pixel, event-properties, make-event
+
+   [4] Displayable area:
+
+   frame-width, frame-height and other all functions specifying frame size
+     in characters
+   frame-displayable-pixel-*
+
+   --ben
+
+*/
+
 #include <config.h>
 #include "lisp.h"
 
@@ -120,18 +404,35 @@
 
 static void store_minibuf_frame_prop (struct frame *f, Lisp_Object val);
 
-typedef enum  {
+typedef enum
+{
   DISPLAYABLE_PIXEL_TO_CHAR,
+  CHAR_TO_DISPLAYABLE_PIXEL,
   TOTAL_PIXEL_TO_CHAR,
   CHAR_TO_TOTAL_PIXEL,
-  CHAR_TO_DISPLAYABLE_PIXEL
-} pixel_to_char_mode_t;
+  TOTAL_PIXEL_TO_DISPLAYABLE_PIXEL,
+  DISPLAYABLE_PIXEL_TO_TOTAL_PIXEL,
+}
+pixel_to_char_mode_t;
+
+enum frame_size_type
+{
+  SIZE_TOTAL_PIXEL,
+  SIZE_DISPLAYABLE_PIXEL,
+  SIZE_CHAR_CELL,
+  SIZE_FRAME_UNIT,
+};
 
 static void frame_conversion_internal (struct frame *f,
-				       pixel_to_char_mode_t pixel_to_char,
-				       int *pixel_width, int *pixel_height,
-				       int *char_width, int *char_height,
-				       int real_face);
+				       enum frame_size_type source,
+				       int source_width, int source_height,
+				       enum frame_size_type dest,
+				       int *dest_width, int *dest_height);
+static void get_frame_char_size (struct frame *f, int *out_width,
+				 int *out_height);
+static void get_frame_displayable_pixel_size (struct frame *f, int *out_width,
+					      int *out_height);
+
 static struct display_line title_string_display_line;
 /* Used by generate_title_string. Global because they get used so much that
    the dynamic allocation time adds up. */
@@ -658,7 +959,7 @@
 	  reset_glyph_cachels (XWINDOW (f->minibuffer_window));
 	}
 
-      change_frame_size (f, f->height, f->width, 0);
+      change_frame_size (f, f->width, f->height, 0);
     }
 
   MAYBE_FRAMEMETH (f, init_frame_2, (f, props));
@@ -703,7 +1004,7 @@
 	 earlier. */
       init_frame_gutters (f);
 
-      change_frame_size (f, f->height, f->width, 0);
+      change_frame_size (f, f->width, f->height, 0);
     }
 
   if (first_frame_on_device)
@@ -826,9 +1127,9 @@
   if (!keep_char_size)
     {
       int height, width;
-      pixel_to_char_size (f, FRAME_PIXWIDTH(f), FRAME_PIXHEIGHT(f),
+      pixel_to_frame_unit_size (f, FRAME_PIXWIDTH(f), FRAME_PIXHEIGHT(f),
 			  &width, &height);
-      change_frame_size (f, height, width, 0);
+      change_frame_size (f, width, height, 0);
       CLEAR_FRAME_SIZE_SLIPPED (f);
     }
 }
@@ -2310,9 +2611,6 @@
 /*                           frame properties                              */
 /***************************************************************************/
 
-static void internal_set_frame_size (struct frame *f, int cols, int rows,
-				     int pretend);
-
 static void
 store_minibuf_frame_prop (struct frame *f, Lisp_Object val)
 {
@@ -2607,17 +2905,9 @@
 
   if (EQ (Qheight, property) || EQ (Qwidth, property))
     {
-      if (window_system_pixelated_geometry (frame))
-	{
-	  int width, height;
-	  pixel_to_real_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
-				   &width, &height);
-	  return make_int (EQ (Qheight, property) ? height: width);
-	}
-      else
-	return make_int (EQ (Qheight, property) ?
-			 FRAME_HEIGHT (f) :
-			 FRAME_WIDTH  (f));
+      int width, height;
+      get_frame_char_size (f, &width, &height);
+      return make_int (EQ (Qheight, property) ? height : width);
     }
 
   /* NOTE: FSF returns Qnil instead of Qt for FRAME_HAS_MINIBUF_P.
@@ -2709,17 +2999,7 @@
 		  result);
   {
     int width, height;
-
-    if (window_system_pixelated_geometry (frame))
-      {
-	pixel_to_real_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
-				 &width, &height);
-      }
-    else
-      {
-	height = FRAME_HEIGHT (f);
-	width = FRAME_WIDTH (f);
-      }
+    get_frame_char_size (f, &width, &height);
     result = cons3 (Qwidth , make_int (width),  result);
     result = cons3 (Qheight, make_int (height), result);
   }
@@ -2745,20 +3025,10 @@
        (frame))
 {
   struct frame *f = decode_frame (frame);
-  int height, pheight;
-  frame = wrap_frame (f);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      height = FRAME_HEIGHT (f);
-
-      frame_conversion_internal (f, CHAR_TO_DISPLAYABLE_PIXEL,
-				 0, &pheight, 0, &height, 0);
-    }
-  else
-    pheight = FRAME_PIXHEIGHT (f);
-
-  return make_int (pheight);
+  int width, height;
+
+  get_frame_displayable_pixel_size (f, &width, &height);
+  return make_int (height);
 }
 
 DEFUN ("frame-pixel-width", Fframe_pixel_width, 0, 1, 0, /*
@@ -2775,20 +3045,10 @@
        (frame))
 {
   struct frame *f = decode_frame (frame);
-  int width, pwidth;
-  frame = wrap_frame (f);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      width = FRAME_WIDTH (f);
-
-      frame_conversion_internal (f, CHAR_TO_DISPLAYABLE_PIXEL,
-				 &pwidth, 0, &width, 0, 0);
-    }
-  else
-    pwidth = FRAME_PIXWIDTH (f);
-
-  return make_int (pwidth);
+  int width, height;
+
+  get_frame_displayable_pixel_size (f, &width, &height);
+  return make_int (width);
 }
 
 DEFUN ("frame-name", Fframe_name, 0, 1, 0, /*
@@ -2814,7 +3074,7 @@
   return make_int (decode_frame (frame)->modiff);
 }
 
-static void
+void
 internal_set_frame_size (struct frame *f, int cols, int rows, int pretend)
 {
   /* This can call Lisp.  See mswindows_set_frame_size(). */
@@ -2822,7 +3082,7 @@
   CLEAR_FRAME_SIZE_SLIPPED (f);
 
   if (pretend || !HAS_FRAMEMETH_P (f, set_frame_size))
-    change_frame_size (f, rows, cols, 0);
+    change_frame_size (f, cols, rows, 0);
   else
     FRAMEMETH (f, set_frame_size, (f, cols, rows));
 }
@@ -2836,23 +3096,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int height, width;
-  frame = wrap_frame (f);
+  int cwidth, cheight;
+  int guwidth, guheight;
+
   CHECK_INT (lines);
-
-  if (window_system_pixelated_geometry (frame))
-    {
-      char_to_real_pixel_size (f, 0, XINT (lines), 0, &height);
-      width = FRAME_PIXWIDTH (f);
-    }
-  else
-    {
-      height = XINT (lines);
-      width = FRAME_WIDTH (f);
-    }
-
-  internal_set_frame_size (f, width, height, !NILP (pretend));
-  return frame;
+  get_frame_char_size (f, &cwidth, &cheight);
+  cheight = XINT (lines);
+  frame_conversion_internal (f, SIZE_CHAR_CELL, cwidth, cheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-pixel-height", Fset_frame_pixel_height, 2, 3, 0, /*
@@ -2864,25 +3117,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int pheight, width;
-  frame = wrap_frame (f);
+  int pwidth, pheight;
+  int guwidth, guheight;
+
   CHECK_INT (height);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int h = XINT (height);
-      width = FRAME_WIDTH (f);
-
-      frame_conversion_internal (f, TOTAL_PIXEL_TO_CHAR, 0, &h, 0, &pheight, 0);
-    }
-  else
-    {
-      width = FRAME_PIXWIDTH (f);
-      pheight = XINT (height);
-    }
-
-  internal_set_frame_size (f, width, pheight, !NILP (pretend));
-  return frame;
+  pheight = XINT (height);
+  pwidth = FRAME_PIXWIDTH (f);
+  frame_conversion_internal (f, SIZE_TOTAL_PIXEL, pwidth, pheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-displayable-pixel-height", Fset_frame_displayable_pixel_height, 2, 3, 0, /*
@@ -2894,24 +3138,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int pheight, width;
-  frame = wrap_frame (f);
+  int pwidth, pheight;
+  int guwidth, guheight;
+
   CHECK_INT (height);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int h = XINT (height);
-      width = FRAME_WIDTH (f);
-      frame_conversion_internal (f, DISPLAYABLE_PIXEL_TO_CHAR, 0, &h, 0, &pheight, 0);
-    }
-  else
-    {
-      width = FRAME_PIXWIDTH (f);
-      pheight = XINT (height);
-    }
-
-  internal_set_frame_size (f, width, pheight, !NILP (pretend));
-  return frame;
+  get_frame_displayable_pixel_size (f, &pwidth, &pheight);
+  pheight = XINT (height);
+  frame_conversion_internal (f, SIZE_DISPLAYABLE_PIXEL, pwidth, pheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 
@@ -2924,23 +3160,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int width, height;
-  frame = wrap_frame (f);
+  int cwidth, cheight;
+  int guwidth, guheight;
+
   CHECK_INT (cols);
-
-  if (window_system_pixelated_geometry (frame))
-    {
-      char_to_real_pixel_size (f, XINT (cols), 0, &width, 0);
-      height = FRAME_PIXHEIGHT (f);
-    }
-  else
-    {
-      width = XINT (cols);
-      height = FRAME_HEIGHT (f);
-    }
-
-  internal_set_frame_size (f, width, height, !NILP (pretend));
-  return frame;
+  get_frame_char_size (f, &cwidth, &cheight);
+  cwidth = XINT (cols);
+  frame_conversion_internal (f, SIZE_CHAR_CELL, cwidth, cheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-pixel-width", Fset_frame_pixel_width, 2, 3, 0, /*
@@ -2952,24 +3181,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int height, pwidth;
-  frame = wrap_frame (f);
+  int pwidth, pheight;
+  int guwidth, guheight;
+
   CHECK_INT (width);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int w = XINT (width);
-      height = FRAME_HEIGHT (f);
-      frame_conversion_internal (f, TOTAL_PIXEL_TO_CHAR, &w, 0, &pwidth, 0, 0);
-    }
-  else
-    {
-      height = FRAME_PIXHEIGHT (f);
-      pwidth = XINT (width);
-    }
-
-  internal_set_frame_size (f, pwidth, height, !NILP (pretend));
-  return frame;
+  pwidth = XINT (width);
+  pheight = FRAME_PIXHEIGHT (f);
+  frame_conversion_internal (f, SIZE_TOTAL_PIXEL, pwidth, pheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-displayable-pixel-width", Fset_frame_displayable_pixel_width, 2, 3, 0, /*
@@ -2981,24 +3202,16 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int height, pwidth;
-  frame = wrap_frame (f);
+  int pwidth, pheight;
+  int guwidth, guheight;
+
   CHECK_INT (width);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int w = XINT (width);
-      height = FRAME_HEIGHT (f);
-      frame_conversion_internal (f, DISPLAYABLE_PIXEL_TO_CHAR, &w, 0, &pwidth, 0, 0);
-    }
-  else
-    {
-      height = FRAME_PIXHEIGHT (f);
-      pwidth = XINT (width);
-    }
-
-  internal_set_frame_size (f, pwidth, height, !NILP (pretend));
-  return frame;
+  get_frame_displayable_pixel_size (f, &pwidth, &pheight);
+  pwidth = XINT (width);
+  frame_conversion_internal (f, SIZE_DISPLAYABLE_PIXEL, pwidth, pheight,
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-size", Fset_frame_size, 3, 4, 0, /*
@@ -3010,21 +3223,14 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int height, width;
-  frame = wrap_frame (f);
+  int guwidth, guheight;
+
   CHECK_INT (cols);
   CHECK_INT (rows);
-
-  if (window_system_pixelated_geometry (frame))
-    char_to_real_pixel_size (f, XINT (cols), XINT (rows), &width, &height);
-  else
-    {
-      height = XINT (rows);
-      width = XINT (cols);
-    }
-
-  internal_set_frame_size (f, width, height, !NILP (pretend));
-  return frame;
+  frame_conversion_internal (f, SIZE_CHAR_CELL, XINT (cols), XINT (rows),
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-pixel-size", Fset_frame_pixel_size, 3, 4, 0, /*
@@ -3036,25 +3242,14 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int pheight, pwidth;
-  frame = wrap_frame (f);
+  int guwidth, guheight;
+
   CHECK_INT (width);
   CHECK_INT (height);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int w = XINT (width);
-      int h = XINT (height);
-      frame_conversion_internal (f, TOTAL_PIXEL_TO_CHAR, &w, &h, &pwidth, &pheight, 0);
-    }
-  else
-    {
-      pheight = XINT (height);
-      pwidth = XINT (width);
-    }
-
-  internal_set_frame_size (f, pwidth, pheight, !NILP (pretend));
-  return frame;
+  frame_conversion_internal (f, SIZE_TOTAL_PIXEL, XINT (width), XINT (height),
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-displayable-pixel-size", Fset_frame_displayable_pixel_size, 3, 4, 0, /*
@@ -3066,25 +3261,15 @@
 {
   /* This can call Lisp. */
   struct frame *f = decode_frame (frame);
-  int pheight, pwidth;
-  frame = wrap_frame (f);
+  int guwidth, guheight;
+
   CHECK_INT (width);
   CHECK_INT (height);
-
-  if (!window_system_pixelated_geometry (frame))
-    {
-      int w = XINT (width);
-      int h = XINT (height);
-      frame_conversion_internal (f, DISPLAYABLE_PIXEL_TO_CHAR, &w, &h, &pwidth, &pheight, 0);
-    }
-  else
-    {
-      pheight = XINT (height);
-      pwidth = XINT (width);
-    }
-
-  internal_set_frame_size (f, pwidth, pheight, !NILP (pretend));
-  return frame;
+  frame_conversion_internal (f, SIZE_DISPLAYABLE_PIXEL,
+			     XINT (width), XINT (height),
+			     SIZE_FRAME_UNIT, &guwidth, &guheight);
+  internal_set_frame_size (f, guwidth, guheight, !NILP (pretend));
+  return wrap_frame (f);
 }
 
 DEFUN ("set-frame-position", Fset_frame_position, 3, 3, 0, /*
@@ -3109,28 +3294,37 @@
 /* Frame size conversion functions moved here from EmacsFrame.c
    because they're generic and really don't belong in that file.
    Function get_default_char_pixel_size() removed because it's
-   exactly the same as default_face_height_and_width(). */
+   exactly the same as default_face_width_and_height().
+
+   Convert between total pixel size, displayable pixel size and
+   character-cell size.  Variables are either "in" or "out"
+   depending on the value of PIXEL_TO_CHAR.
+*/
 static void
-frame_conversion_internal (struct frame *f,
-			   pixel_to_char_mode_t pixel_to_char,
-			   int *pixel_width, int *pixel_height,
-			   int *char_width, int *char_height,
-			   int real_face)
+frame_conversion_internal_1 (struct frame *f,
+			     pixel_to_char_mode_t pixel_to_char,
+			     int *total_pixel_width, int *total_pixel_height,
+			     int *disp_pixel_width, int *disp_pixel_height,
+			     int *char_width, int *char_height)
 {
-  int cpw;
-  int cph;
+  int cpw, cph;
   int egw;
   int obw, obh, bdr;
   Lisp_Object frame, window;
 
   frame = wrap_frame (f);
-  if (real_face)
-    default_face_height_and_width (frame, &cph, &cpw);
-  else
-    default_face_height_and_width_1 (frame, &cph, &cpw);
+  default_face_width_and_height (frame, &cpw, &cph);
 
   window = FRAME_SELECTED_WINDOW (f);
 
+  /* #### It really seems like we should also be subtracting out the
+     theoretical gutter width and height, just like we do for toolbars.
+     There is currently a bug where if you call `set-frame-pixel-width'
+     on MS Windows (at least, possibly also X) things get confused and
+     the top of the root window overlaps the top gutter instead of being
+     below it.  This gets fixed next time you resize the frame using the
+     mouse.  Possibly this is caused by not handling the gutter height
+     here? */
   egw = max (glyph_width (Vcontinuation_glyph, window),
 	     glyph_width (Vtruncation_glyph, window));
   egw = max (egw, cpw);
@@ -3153,34 +3347,115 @@
     {
     case DISPLAYABLE_PIXEL_TO_CHAR:
       if (char_width)
-	*char_width = ROUND_UP (*pixel_width, cpw) / cpw;
+	*char_width = ROUND_UP (*disp_pixel_width, cpw) / cpw;
       if (char_height)
-	*char_height = ROUND_UP (*pixel_height, cph) / cph;
+	*char_height = ROUND_UP (*disp_pixel_height, cph) / cph;
+      break;
+    case CHAR_TO_DISPLAYABLE_PIXEL:
+      if (disp_pixel_width)
+	*disp_pixel_width = *char_width * cpw;
+      if (disp_pixel_height)
+	*disp_pixel_height = *char_height * cph;
       break;
     case TOTAL_PIXEL_TO_CHAR:
       /* Convert to chars so that the total frame size is pixel_width x
 	 pixel_height. */
       if (char_width)
-	*char_width = 1 + ((*pixel_width - egw) - bdr - obw) / cpw;
+	*char_width = 1 + ((*total_pixel_width - egw) - bdr - obw) / cpw;
       if (char_height)
-	*char_height = (*pixel_height - bdr - obh) / cph;
+	*char_height = (*total_pixel_height - bdr - obh) / cph;
       break;
     case CHAR_TO_TOTAL_PIXEL:
-      if (pixel_width)
-	*pixel_width = (*char_width - 1) * cpw + egw + bdr + obw;
-      if (pixel_height)
-	*pixel_height = *char_height * cph + bdr + obh;
+      if (total_pixel_width)
+	*total_pixel_width = (*char_width - 1) * cpw + egw + bdr + obw;
+      if (total_pixel_height)
+	*total_pixel_height = *char_height * cph + bdr + obh;
       break;
-    case CHAR_TO_DISPLAYABLE_PIXEL:
-      if (pixel_width)
-	*pixel_width = *char_width * cpw;
-      if (pixel_height)
-	*pixel_height = *char_height * cph;
+    case TOTAL_PIXEL_TO_DISPLAYABLE_PIXEL:
+      /* Convert to chars so that the total frame size is pixel_width x
+	 pixel_height. */
+      if (disp_pixel_width)
+	*disp_pixel_width = cpw + (*total_pixel_width - egw) - bdr - obw;
+      if (disp_pixel_height)
+	*disp_pixel_height = *total_pixel_height - bdr - obh;
+      break;
+    case DISPLAYABLE_PIXEL_TO_TOTAL_PIXEL:
+      if (total_pixel_width)
+	*total_pixel_width = *disp_pixel_width - cpw + egw + bdr + obw;
+      if (total_pixel_height)
+	*total_pixel_height = *disp_pixel_height + bdr + obh;
       break;
     }
 }
 
-/* This takes the size in pixels of the text area, and returns the number
+
+static enum frame_size_type
+canonicalize_frame_size_type (enum frame_size_type type, int pixgeom)
+{
+  if (type == SIZE_FRAME_UNIT)
+    {
+      if (pixgeom)
+	type = SIZE_DISPLAYABLE_PIXEL;
+      else
+	type = SIZE_CHAR_CELL;
+    }
+  return type;
+}
+
+/* Basic frame conversion function.  Convert source size to destination
+   size, where either of them can be in total pixels, displayable pixels,
+   frame units or character-cell units. */
+
+static void
+frame_conversion_internal (struct frame *f,
+			   enum frame_size_type source,
+			   int source_width, int source_height,
+			   enum frame_size_type dest,
+			   int *dest_width, int *dest_height)
+{
+  int pixgeom = window_system_pixelated_geometry (wrap_frame (f));
+  dest = canonicalize_frame_size_type (dest, pixgeom);
+  source = canonicalize_frame_size_type (source, pixgeom);
+  if (source == dest)
+    {
+      *dest_width = source_width;
+      *dest_height = source_height;
+    }
+  else if (source == SIZE_TOTAL_PIXEL && dest == SIZE_CHAR_CELL)
+    frame_conversion_internal_1 (f, TOTAL_PIXEL_TO_CHAR,
+				 &source_width, &source_height, 0, 0,
+				 dest_width, dest_height);
+  else if (source == SIZE_DISPLAYABLE_PIXEL && dest == SIZE_CHAR_CELL)
+    frame_conversion_internal_1 (f, DISPLAYABLE_PIXEL_TO_CHAR, 0, 0,
+				 &source_width, &source_height,
+				 dest_width, dest_height);
+  else if (source == SIZE_TOTAL_PIXEL && dest == SIZE_DISPLAYABLE_PIXEL)
+    frame_conversion_internal_1 (f, TOTAL_PIXEL_TO_DISPLAYABLE_PIXEL,
+				 &source_width, &source_height,
+				 dest_width, dest_height, 0, 0);
+  else if (dest == SIZE_TOTAL_PIXEL && source == SIZE_CHAR_CELL)
+    frame_conversion_internal_1 (f, CHAR_TO_TOTAL_PIXEL,
+				 dest_width, dest_height, 0, 0,
+				 &source_width, &source_height);
+  else if (dest == SIZE_DISPLAYABLE_PIXEL && source == SIZE_CHAR_CELL)
+    frame_conversion_internal_1 (f, CHAR_TO_DISPLAYABLE_PIXEL, 0, 0,
+				 dest_width, dest_height,
+				 &source_width, &source_height);
+  else if (dest == SIZE_TOTAL_PIXEL && source == SIZE_DISPLAYABLE_PIXEL)
+    frame_conversion_internal_1 (f, DISPLAYABLE_PIXEL_TO_TOTAL_PIXEL,
+				 dest_width, dest_height,
+				 &source_width, &source_height, 0, 0);
+  else
+    {
+      ABORT ();
+      if (dest_width)
+	*dest_width = 0;
+      if (dest_height)
+	*dest_height = 0;
+    }
+}
+
+/* This takes the size in pixels of the client area, and returns the number
    of characters that will fit there, taking into account the internal
    border width, and the pixel width of the line terminator glyphs (which
    always count as one "character" wide, even if they are not the same size
@@ -3191,35 +3466,56 @@
 
    Therefore the result is not necessarily a multiple of anything in
    particular.  */
+
 void
 pixel_to_char_size (struct frame *f, int pixel_width, int pixel_height,
 		    int *char_width, int *char_height)
 {
-  frame_conversion_internal (f, TOTAL_PIXEL_TO_CHAR,
-			     &pixel_width, &pixel_height, char_width,
-			     char_height, 0);
+  frame_conversion_internal (f, SIZE_TOTAL_PIXEL, pixel_width, pixel_height,
+			     SIZE_CHAR_CELL, char_width, char_height);
 }
 
-/* Given a character size, this returns the minimum number of pixels
-   necessary to display that many characters, taking into account the
-   internal border width, scrollbar height and width, toolbar heights and
-   widths and the size of the line terminator glyphs (assuming the line
-   terminators take up exactly one character position).
+/* Given a character size, this returns the minimum pixel size of the
+   client area necessary to display that many characters, taking into
+   account the internal border width, scrollbar height and width, toolbar
+   heights and widths and the size of the line terminator glyphs (assuming
+   the line terminators take up exactly one character position).
 
    Therefore the result is not necessarily a multiple of anything in
    particular.  */
+
 void
 char_to_pixel_size (struct frame *f, int char_width, int char_height,
 		    int *pixel_width, int *pixel_height)
 {
-  frame_conversion_internal (f, CHAR_TO_TOTAL_PIXEL,
-			     pixel_width, pixel_height, &char_width,
-			     &char_height, 0);
+  frame_conversion_internal (f, SIZE_CHAR_CELL, char_width, char_height,
+			     SIZE_TOTAL_PIXEL, pixel_width, pixel_height);
 }
 
-/* Given a pixel size, rounds DOWN to the smallest size in pixels necessary
-   to display the same number of characters as are displayable now.
- */
+/* Versions of the above that operate in "frame units" instead of
+   characters.  frame units are the same as characters except on
+   MS Windows and MS Printer frames, where they are displayable-area
+   pixels. */
+
+void
+pixel_to_frame_unit_size (struct frame *f, int pixel_width, int pixel_height,
+			 int *frame_unit_width, int *frame_unit_height)
+{
+  frame_conversion_internal (f, SIZE_TOTAL_PIXEL, pixel_width, pixel_height,
+			     SIZE_FRAME_UNIT, frame_unit_width,
+			     frame_unit_height);
+}
+
+void
+frame_unit_to_pixel_size (struct frame *f, int frame_unit_width,
+			 int frame_unit_height,
+			 int *pixel_width, int *pixel_height)
+{
+  frame_conversion_internal (f, SIZE_FRAME_UNIT, frame_unit_width,
+			     frame_unit_height,
+			     SIZE_TOTAL_PIXEL, pixel_width, pixel_height);
+}
+
 void
 round_size_to_char (struct frame *f, int in_width, int in_height,
 		    int *out_width, int *out_height)
@@ -3230,44 +3526,49 @@
   char_to_pixel_size (f, char_width, char_height, out_width, out_height);
 }
 
-/* Versions of the above which always account for real font metrics.
- */
-void
-pixel_to_real_char_size (struct frame *f, int pixel_width, int pixel_height,
-			 int *char_width, int *char_height)
+/* Get the frame size in character cells, recalculating on the fly.
+   #### The logic of this function follows former logic elsewhere,
+   which used FRAME_PIXWIDTH() on pixelated-geometry systems but
+   FRAME_WIDTH() on non-pixelated-geometry systems.  Not clear why not
+   always just use one or the other.
+
+   Why don't we just use FRAME_CHARWIDTH() etc. in get_frame_char_size()?
+   That wouldn't work because change_frame_size_1() depends on the
+   following function to *set* the values of FRAME_CHARWIDTH() etc.
+
+   But elsewhere I suppose we could use it.
+*/
+
+static void
+get_frame_char_size (struct frame *f, int *out_width, int *out_height)
 {
-  frame_conversion_internal (f, TOTAL_PIXEL_TO_CHAR,
-			     &pixel_width, &pixel_height, char_width,
-			     char_height, 1);
-}
-
-void
-char_to_real_pixel_size (struct frame *f, int char_width, int char_height,
-			 int *pixel_width, int *pixel_height)
-{
-  frame_conversion_internal (f, CHAR_TO_TOTAL_PIXEL,
-			     pixel_width, pixel_height, &char_width,
-			     &char_height, 1);
+  if (window_system_pixelated_geometry (wrap_frame (f)))
+    pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
+			out_width, out_height);
+  else
+    {
+      *out_width = FRAME_WIDTH (f);
+      *out_height = FRAME_HEIGHT (f);
+    }
 }
 
-void
-round_size_to_real_char (struct frame *f, int in_width, int in_height,
-			 int *out_width, int *out_height)
+static void
+get_frame_displayable_pixel_size (struct frame *f, int *out_width,
+				  int *out_height)
 {
-  int char_width;
-  int char_height;
-  pixel_to_real_char_size (f, in_width, in_height, &char_width, &char_height);
-  char_to_real_pixel_size (f, char_width, char_height, out_width, out_height);
+  frame_conversion_internal (f, SIZE_FRAME_UNIT, FRAME_WIDTH (f),
+			     FRAME_HEIGHT (f), SIZE_DISPLAYABLE_PIXEL,
+			     out_width, out_height);
 }
 
-/* Change the frame height and/or width.  Values may be given as zero to
-   indicate no change is to take place. */
+/* Change the frame height and/or width.  Values passed in are in
+   frame units (character cells on X/GTK, displayable-area pixels
+   on MS Windows or generally on pixelated-geometry window systems). */
 static void
-change_frame_size_1 (struct frame *f, int newheight, int newwidth)
+change_frame_size_1 (struct frame *f, int newwidth, int newheight)
 {
-  Lisp_Object frame;
   int new_pixheight, new_pixwidth;
-  int font_height, real_font_height, font_width;
+  int real_font_height, real_font_width;
 
   /* #### Chuck -- shouldn't we be checking to see if the frame
      is being "changed" to its existing size, and do nothing if so? */
@@ -3277,157 +3578,101 @@
      change occurs. --kyle */
   assert (!in_display && !hold_frame_size_changes);
 
-  frame = wrap_frame (f);
-
-  default_face_height_and_width (frame, &real_font_height, 0);
-  default_face_height_and_width_1 (frame, &font_height, &font_width);
+  /* We no longer allow bogus values passed in. */
+  assert (newheight && newwidth);
+
+  default_face_width_and_height (wrap_frame (f), &real_font_width,
+				 &real_font_height);
+
+  frame_conversion_internal (f, SIZE_FRAME_UNIT, newwidth, newheight,
+			     SIZE_TOTAL_PIXEL, &new_pixwidth,
+			     &new_pixheight);
 
   /* This size-change overrides any pending one for this frame.  */
   f->size_change_pending = 0;
   FRAME_NEW_HEIGHT (f) = 0;
   FRAME_NEW_WIDTH (f) = 0;
 
-  new_pixheight = newheight * font_height;
-  new_pixwidth = (newwidth - 1) * font_width;
-
-  /* #### dependency on FRAME_WIN_P should be removed. */
-  if (FRAME_WIN_P (f))
-    {
-      new_pixheight += FRAME_SCROLLBAR_HEIGHT (f);
-      new_pixwidth += FRAME_SCROLLBAR_WIDTH (f);
-    }
-
-  /* when frame_conversion_internal() calculated the number of rows/cols
-     in the frame, the theoretical toolbar sizes were subtracted out.
-     The calculations below adjust for real toolbar height/width in
-     frame, which may be different from frame spec, taking the above
-     fact into account */
-  new_pixheight +=
-    + FRAME_THEORETICAL_TOP_TOOLBAR_HEIGHT (f)
-    + 2 * FRAME_THEORETICAL_TOP_TOOLBAR_BORDER_WIDTH (f)
-    - FRAME_REAL_TOP_TOOLBAR_HEIGHT (f)
-    - 2 * FRAME_REAL_TOP_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixheight +=
-    + FRAME_THEORETICAL_BOTTOM_TOOLBAR_HEIGHT (f)
-    + 2 * FRAME_THEORETICAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f)
-    - FRAME_REAL_BOTTOM_TOOLBAR_HEIGHT (f)
-    - 2 * FRAME_REAL_BOTTOM_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixwidth +=
-    + FRAME_THEORETICAL_LEFT_TOOLBAR_WIDTH (f)
-    + 2 * FRAME_THEORETICAL_LEFT_TOOLBAR_BORDER_WIDTH (f)
-    - FRAME_REAL_LEFT_TOOLBAR_WIDTH (f)
-    - 2 * FRAME_REAL_LEFT_TOOLBAR_BORDER_WIDTH (f);
-
-  new_pixwidth +=
-    + FRAME_THEORETICAL_RIGHT_TOOLBAR_WIDTH (f)
-    + 2 * FRAME_THEORETICAL_RIGHT_TOOLBAR_BORDER_WIDTH (f)
-    - FRAME_REAL_RIGHT_TOOLBAR_WIDTH (f)
-    - 2 * FRAME_REAL_RIGHT_TOOLBAR_BORDER_WIDTH (f);
-
-  /* Adjust the width for the end glyph which may be a different width
-     than the default character width. */
-  {
-    int adjustment, trunc_width, cont_width;
-
-    trunc_width = glyph_width (Vtruncation_glyph,
-			       FRAME_SELECTED_WINDOW (f));
-    cont_width = glyph_width (Vcontinuation_glyph,
-			      FRAME_SELECTED_WINDOW (f));
-    adjustment = max (trunc_width, cont_width);
-    adjustment = max (adjustment, font_width);
-
-    new_pixwidth += adjustment;
-  }
-
-  /* If we don't have valid values, exit. */
-  if (!new_pixheight && !new_pixwidth)
-    return;
-
-  if (new_pixheight)
+  /* We need to remove the boundaries of the paned area (see top of file)
+     from the total-area pixel size, which is what we have now.
+
+     #### We should also be subtracting the internal borders. */
+  new_pixheight -=
+    (FRAME_REAL_TOP_TOOLBAR_BOUNDS (f)
+     + FRAME_REAL_BOTTOM_TOOLBAR_BOUNDS (f)
+     + FRAME_TOP_GUTTER_BOUNDS (f)
+     + FRAME_BOTTOM_GUTTER_BOUNDS (f));
+
+  new_pixwidth -=
+    (FRAME_REAL_LEFT_TOOLBAR_BOUNDS (f)
+     + FRAME_REAL_RIGHT_TOOLBAR_BOUNDS (f)
+     + FRAME_LEFT_GUTTER_BOUNDS (f)
+     + FRAME_RIGHT_GUTTER_BOUNDS (f));
+
+  XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top
+    = FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
+
+  if (FRAME_HAS_MINIBUF_P (f)
+      && ! FRAME_MINIBUF_ONLY_P (f))
+    /* Frame has both root and minibuffer.  */
     {
-      /* Adjust for gutters here so that we always get set
-	 properly. */
-      new_pixheight -=
-	(FRAME_TOP_GUTTER_BOUNDS (f)
-	 + FRAME_BOTTOM_GUTTER_BOUNDS (f));
-
-      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_top
-	= FRAME_TOP_BORDER_END (f) + FRAME_TOP_GUTTER_BOUNDS (f);
-
-      if (FRAME_HAS_MINIBUF_P (f)
-	  && ! FRAME_MINIBUF_ONLY_P (f))
-	/* Frame has both root and minibuffer.  */
-	{
-	  /*
-	   * Leave the minibuffer height the same if the frame has
-	   * been initialized, and the minibuffer height is tall
-	   * enough to display at least one line of text in the default
-	   * font, and the old minibuffer height is a multiple of the
-	   * default font height.  This should cause the minibuffer
-	   * height to be recomputed on font changes but not for
-	   * other frame size changes, which seems reasonable.
-	   */
-	  int old_minibuf_height =
-	    XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
-	  int minibuf_height =
-	    f->init_finished && (old_minibuf_height % real_font_height) == 0 ?
-	    max(old_minibuf_height, real_font_height) :
-	    real_font_height;
-	  set_window_pixheight (FRAME_ROOT_WINDOW (f),
-				/* - font_height for minibuffer */
-				new_pixheight - minibuf_height, 0);
-
-	  XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top =
-	    FRAME_TOP_BORDER_END (f) +
-	    FRAME_TOP_GUTTER_BOUNDS (f) +
-	    FRAME_BOTTOM_GUTTER_BOUNDS (f) +
-	    new_pixheight - minibuf_height;
-
-	  set_window_pixheight (FRAME_MINIBUF_WINDOW (f), minibuf_height, 0);
-	}
-      else
-	/* Frame has just one top-level window.  */
-	set_window_pixheight (FRAME_ROOT_WINDOW (f), new_pixheight, 0);
-
-      FRAME_HEIGHT (f) = newheight;
-      if (FRAME_TTY_P (f))
-	f->pixheight = newheight;
+      /*
+       * Leave the minibuffer height the same if the frame has
+       * been initialized, and the minibuffer height is tall
+       * enough to display at least one line of text in the default
+       * font, and the old minibuffer height is a multiple of the
+       * default font height.  This should cause the minibuffer
+       * height to be recomputed on font changes but not for
+       * other frame size changes, which seems reasonable.
+       */
+      int old_minibuf_height =
+	XWINDOW(FRAME_MINIBUF_WINDOW(f))->pixel_height;
+      int minibuf_height =
+	f->init_finished && (old_minibuf_height % real_font_height) == 0 ?
+	max(old_minibuf_height, real_font_height) :
+	real_font_height;
+      set_window_pixheight (FRAME_ROOT_WINDOW (f),
+			    /* - font_height for minibuffer */
+			    new_pixheight - minibuf_height, 0);
+
+      XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_top =
+	FRAME_TOP_BORDER_END (f) +
+	FRAME_TOP_GUTTER_BOUNDS (f) +
+	FRAME_BOTTOM_GUTTER_BOUNDS (f) +
+	new_pixheight - minibuf_height;
+
+      set_window_pixheight (FRAME_MINIBUF_WINDOW (f), minibuf_height, 0);
     }
-
-  if (new_pixwidth)
+  else
+    /* Frame has just one top-level window.  */
+    set_window_pixheight (FRAME_ROOT_WINDOW (f), new_pixheight, 0);
+
+  FRAME_HEIGHT (f) = newheight;
+  if (FRAME_TTY_P (f))
+    f->pixheight = newheight;
+
+  XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left =
+    FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f);
+  set_window_pixwidth (FRAME_ROOT_WINDOW (f), new_pixwidth, 0);
+
+  if (FRAME_HAS_MINIBUF_P (f))
     {
-      /* Adjust for gutters here so that we always get set
-	 properly. */
-      new_pixwidth -=
-	(FRAME_LEFT_GUTTER_BOUNDS (f)
-	 + FRAME_RIGHT_GUTTER_BOUNDS (f));
-
-      XWINDOW (FRAME_ROOT_WINDOW (f))->pixel_left =
+      XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_left =
 	FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f);
-      set_window_pixwidth (FRAME_ROOT_WINDOW (f), new_pixwidth, 0);
-
-      if (FRAME_HAS_MINIBUF_P (f))
-	{
-	  XWINDOW (FRAME_MINIBUF_WINDOW (f))->pixel_left =
-	    FRAME_LEFT_BORDER_END (f) + FRAME_LEFT_GUTTER_BOUNDS (f);
-	  set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), new_pixwidth, 0);
-	}
-
-      FRAME_WIDTH (f) = newwidth;
-      if (FRAME_TTY_P (f))
-	f->pixwidth = newwidth;
+      set_window_pixwidth (FRAME_MINIBUF_WINDOW (f), new_pixwidth, 0);
     }
 
-  if (window_system_pixelated_geometry (frame))
-    pixel_to_real_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
-			     &FRAME_CHARWIDTH (f), &FRAME_CHARHEIGHT (f));
-  else
-    {
-      FRAME_CHARWIDTH (f) = FRAME_WIDTH (f);
-      FRAME_CHARHEIGHT (f) = FRAME_HEIGHT (f);
-    }
+  FRAME_WIDTH (f) = newwidth;
+  if (FRAME_TTY_P (f))
+    f->pixwidth = newwidth;
+
+  /* #### On MS Windows, this references FRAME_PIXWIDTH() and FRAME_PIXHEIGHT().
+     I'm not sure we can count on those values being set.  Instead we should
+     use the total pixel size we got near the top by calling
+     frame_conversion_internal().  We should inline the logic in
+     get_frame_char_size() here and change that function so it just looks
+     at FRAME_CHARWIDTH() and FRAME_CHARHEIGHT(). */
+  get_frame_char_size (f, &FRAME_CHARWIDTH (f), &FRAME_CHARHEIGHT (f));
 
   MARK_FRAME_TOOLBARS_CHANGED (f);
   MARK_FRAME_GUTTERS_CHANGED (f);
@@ -3436,12 +3681,12 @@
 }
 
 void
-change_frame_size (struct frame *f, int newheight, int newwidth, int delay)
+change_frame_size (struct frame *f, int newwidth, int newheight, int delay)
 {
   /* sometimes we get passed a size that's too small (esp. when a
      client widget gets resized, since we have no control over this).
      So deal. */
-  check_frame_size (f, &newheight, &newwidth);
+  check_frame_size (f, &newwidth, &newheight);
 
   /* Unconditionally mark that the frame has changed size. This is
      because many things need to know after the
@@ -3468,10 +3713,10 @@
       Lisp_Object frmcons;
 
       DEVICE_FRAME_LOOP (frmcons, XDEVICE (FRAME_DEVICE (f)))
-	change_frame_size_1 (XFRAME (XCAR (frmcons)), newheight, newwidth);
+	change_frame_size_1 (XFRAME (XCAR (frmcons)), newwidth, newheight);
     }
   else
-    change_frame_size_1 (f, newheight, newwidth);
+    change_frame_size_1 (f, newwidth, newheight);
 }
 
 
--- a/src/frame.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/frame.h	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Define frame-object for XEmacs.
    Copyright (C) 1988, 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 1995, 2002 Ben Wing.
+   Copyright (C) 1995, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -120,22 +120,22 @@
 void update_frame_title (struct frame *f);
 Lisp_Object next_frame (Lisp_Object, Lisp_Object, Lisp_Object);
 Lisp_Object previous_frame (Lisp_Object, Lisp_Object, Lisp_Object);
+void pixel_to_frame_unit_size (struct frame *f, int pixel_width, int pixel_height,
+			 int *char_width, int *char_height);
+void frame_unit_to_pixel_size (struct frame *f, int char_width, int char_height,
+			 int *pixel_width, int *pixel_height);
 void pixel_to_char_size (struct frame *f, int pixel_width, int pixel_height,
 			 int *char_width, int *char_height);
 void char_to_pixel_size (struct frame *f, int char_width, int char_height,
 			 int *pixel_width, int *pixel_height);
 void round_size_to_char (struct frame *f, int in_width, int in_height,
 			 int *out_width, int *out_height);
-void pixel_to_real_char_size (struct frame *f, int pixel_width, int pixel_height,
-			 int *char_width, int *char_height);
-void char_to_real_pixel_size (struct frame *f, int char_width, int char_height,
-			 int *pixel_width, int *pixel_height);
-void round_size_to_real_char (struct frame *f, int in_width, int in_height,
-			      int *out_width, int *out_height);
 void change_frame_size (struct frame *frame,
 			int newlength, int newwidth,
 			int delay);
 void adjust_frame_size (struct frame *frame);
+void internal_set_frame_size (struct frame *f, int cols, int rows,
+			      int pretend);
 void frame_size_slipped (Lisp_Object specifier, struct frame *f,
 			 Lisp_Object oldval);
 void select_frame_1 (Lisp_Object frame);
--- a/src/gc.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/gc.c	Sat Feb 20 23:56:01 2010 -0600
@@ -184,7 +184,7 @@
   gc_state.stat[GC_STAT_IN_THIS_GC] = 0;	\
   GC_STAT_RESUME (stat)
 
-void
+static void
 gc_stat_start_new_gc (void)
 {
   gc_state.n_gc[GC_STAT_TOTAL]++;
@@ -201,7 +201,7 @@
   GC_STAT_RESTART (freed);
 } 
 
-void
+static void
 gc_stat_resume_gc (void)
 {
   gc_state.n_cycles[GC_STAT_TOTAL]++;
@@ -1022,20 +1022,14 @@
    on the kkcc_gc_stack. This function processes all elements on the stack
    according to their descriptions. */
 static void
-kkcc_marking (
-#ifdef NEW_GC
-	      int cnt
-#else /* not NEW_GC */
-	      int UNUSED(cnt)
-#endif /* not NEW_GC */ 
-	      )
+kkcc_marking (USED_IF_NEW_GC (cnt))
 {
   kkcc_gc_stack_entry *stack_entry = 0;
   void *data = 0;
   const struct memory_description *desc = 0;
   int pos;
 #ifdef NEW_GC
-  int count = cnt;
+  int obj_count = cnt;
 #endif /* NEW_GC */
 #ifdef DEBUG_XEMACS
   int level = 0;
@@ -1182,7 +1176,7 @@
 
 #ifdef NEW_GC
       if (cnt) 
-	if (!--count)
+	if (!--obj_count)
 	  break;
 #endif /* NEW_GC */
     }
@@ -1894,7 +1888,7 @@
 }
 
 
-void
+static void
 gc_1 (int incremental)
 {
   switch (GC_PHASE)
@@ -1930,7 +1924,8 @@
     }
 }
 
-void gc (int incremental)
+static void
+gc (int incremental)
 {
   if (gc_currently_forbidden
       || in_display
--- a/src/glyphs-msw.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/glyphs-msw.c	Sat Feb 20 23:56:01 2010 -0600
@@ -2780,7 +2780,7 @@
 		      pointer_bg, dest_mask, domain);
 
   /* We now have everything right apart from the height. */
-  default_face_font_info (domain, 0, 0, &height, 0, 0);
+  default_face_font_info (domain, 0, 0, 0, &height, 0);
   GET_LIST_LENGTH (items, len);
 
   height = (height + DEFAULT_WIDGET_BORDER_WIDTH * 2 ) * len;
--- a/src/glyphs-widget.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/glyphs-widget.c	Sat Feb 20 23:56:01 2010 -0600
@@ -811,7 +811,7 @@
   if (tw)
     {
       int charwidth;
-      default_face_font_info (domain, 0, 0, 0, &charwidth, 0);
+      default_face_font_info (domain, 0, 0, &charwidth, 0, 0);
       pw = ROUND_UP (charwidth * tw + 4 * widget_instance_border_width (ii), charwidth);
     }
 
@@ -827,7 +827,7 @@
 	}
       else 
 	{
-	  default_face_font_info (domain, 0, 0, &charheight, 0, 0);
+	  default_face_font_info (domain, 0, 0, 0, &charheight, 0);
 	}
       ph = (charheight + 2 * widget_instance_border_width (ii)) * th;
     }
@@ -949,7 +949,7 @@
     {
       int len, h;
       /* #### widget face would be better here. */
-      default_face_font_info (domain, 0, 0, &h, 0, 0);
+      default_face_font_info (domain, 0, 0, 0, &h, 0);
       GET_LIST_LENGTH (items, len);
       *height = len * h;
     }
@@ -1659,7 +1659,7 @@
   if (HAS_DEVMETH_P (DOMAIN_XDEVICE (domain), widget_border_width))
     border_width = DEVMETH (DOMAIN_XDEVICE (domain), widget_border_width, ());
 
-  default_face_font_info (domain, 0, 0, 0, &charwidth, 0);
+  default_face_font_info (domain, 0, 0, &charwidth, 0, 0);
   neww = ROUND_UP (charwidth * w + 4 * border_width + 2 * widget_spacing (domain), 
 		charwidth) / charwidth;
   
@@ -1693,7 +1693,7 @@
 
   h = XINT (height);
 
-  default_face_font_info (domain, 0, 0, &charheight, 0, 0);
+  default_face_font_info (domain, 0, 0, 0, &charheight, 0);
   newh = ROUND_UP (logical_unit_height (Fsymbol_name (Qwidget), 
 					Vwidget_face, domain) * h, charheight)
     / charheight;
--- a/src/gtk-xemacs.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/gtk-xemacs.c	Sat Feb 20 23:56:01 2010 -0600
@@ -4,6 +4,7 @@
 **
 ** Created by: William M. Perry
 ** Copyright (c) 2000 William M. Perry <wmperry@gnu.org>
+** Copyright (C) 2010 Ben Wing.
 **
 ** This file is part of XEmacs.
 **
@@ -275,7 +276,7 @@
 
     if (f)
       {
-	char_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f),
+	frame_unit_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f),
 			    &width, &height);
 	requisition->width = width;
 	requisition->height = height;
@@ -344,11 +345,11 @@
 	f->pixwidth = allocation->width;
 	f->pixheight = allocation->height;
 
-	pixel_to_char_size (f,
+	pixel_to_frame_unit_size (f,
 			    allocation->width,
 			    allocation->height, &columns, &rows);
 
-	change_frame_size (f, rows, columns, 1);
+	change_frame_size (f, columns, rows, 1);
       }
 }
 
--- a/src/gutter.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/gutter.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,5 +1,6 @@
 /* Gutter implementation.
    Copyright (C) 1999, 2000 Andy Piper.
+   Copyright (C) 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -450,7 +451,7 @@
       /* If the number of display lines has shrunk, adjust. */
       if (cdla_len > Dynarr_length (ddla))
 	{
-	  Dynarr_set_length (cdla, Dynarr_length (ddla));
+	  Dynarr_set_lengthr (cdla, Dynarr_length (ddla));
 	}
 
       /* grab coordinates of last line and blank after it. */
@@ -589,9 +590,9 @@
   if (FRAME_GUTTER_BOUNDS (f, pos) != f->current_gutter_bounds[pos])
     {
       int width, height;
-      pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
+      pixel_to_frame_unit_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
 			  &width, &height);
-      change_frame_size (f, height, width, 0);
+      change_frame_size (f, width, height, 0);
       MARK_FRAME_LAYOUT_CHANGED (f);
     }
 
--- a/src/indent.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/indent.c	Sat Feb 20 23:56:01 2010 -0600
@@ -801,7 +801,7 @@
   eobuf = BUF_ZV (XBUFFER (w->buffer));
   bobuf = BUF_BEGV (XBUFFER (w->buffer));
 
-  default_face_height_and_width (window, &defheight, NULL);
+  default_face_width_and_height (window, NULL, &defheight);
 
   /* guess num lines needed in line start cache + a few extra */
   abspix = abs (pixels);
--- a/src/lisp.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/lisp.h	Sat Feb 20 23:56:01 2010 -0600
@@ -317,8 +317,8 @@
 #ifdef ERROR_CHECK_STRUCTURES
 /* Check for problems with the catch list and specbind stack */
 #define ERROR_CHECK_CATCH
-/* Check for incoherent Dynarr structures, attempts to access Dynarr
-   positions out of range, reentrant use of Dynarrs through Dynarr locking,
+/* Check for incoherent dynarr structures, attempts to access Dynarr
+   positions out of range, reentrant use of dynarrs through dynarr locking,
    etc. */
 #define ERROR_CHECK_DYNARR
 /* Check for insufficient use of call_trapping_problems(), particularly
@@ -1456,7 +1456,7 @@
 
 /* We put typedefs here so that prototype declarations don't choke.
    Note that we don't actually declare the structures here (except
-   maybe for simple structures like Dynarrs); that keeps them private
+   maybe for simple structures like dynarrs); that keeps them private
    to the routines that actually use them. */
 
 /* ------------------------------- */
@@ -1722,7 +1722,7 @@
 }
 
 /************************************************************************/
-/**    Definitions of dynamic arrays (Dynarrs) and other allocators    **/
+/**    Definitions of dynamic arrays (dynarrs) and other allocators    **/
 /************************************************************************/
 
 BEGIN_C_DECLS
@@ -1748,7 +1748,7 @@
   type *base;					\
   DECLARE_DYNARR_LISP_IMP ()			\
   DECLARE_DYNARR_LOCKED ()			\
-  int elsize;					\
+  int elsize_;					\
   int len_;					\
   int largest_;					\
   int max_
@@ -1776,10 +1776,81 @@
 
 /************* Dynarr verification *************/
 
+/* Dynarr locking and verification.
+
+   [I] VERIFICATION
+
+   Verification routines simply return their basic argument, possibly
+   casted, but in the process perform some verification on it, aborting if
+   the verification fails.  The verification routines take FILE and LINE
+   parameters, and use them to output the file and line of the caller
+   when an abort occurs, rather than the file and line of the inline
+   function, which is less than useful.
+
+   There are three basic types of verification routines:
+
+   (1) Verify the dynarr itself.  This verifies the basic invariant
+   involving the length/size values:
+
+   0 <= Dynarr_length(d) <= Dynarr_largest(d) <= Dynarr_max(d)
+
+   (2) Verify the dynarr itself prior to modifying it.  This performs
+   the same verification as previously, but also checks that the
+   dynarr is not locked (see below).
+
+   (3) Verify a dynarr position.  Unfortunately we have to have
+   different verification routines depending on which kind of operation
+   is being performed:
+
+   (a) For Dynarr_at(), we check that the POS is bounded by Dynarr_largest(),
+       i.e. 0 <= POS < Dynarr_largest().
+   (b) For Dynarr_atp_allow_end(), we also have to allow
+       POS == Dynarr_largest().
+   (c) For Dynarr_atp(), we behave largely like Dynarr_at() but make a
+       special exception when POS == 0 and Dynarr_largest() == 0 -- see
+       comment below.
+   (d) Some other routines contain the POS verification within their code,
+       and make the check 0 <= POS < Dynarr_length() or
+       0 <= POS <= Dynarr_length().
+
+   #### It is not well worked-out whether and in what circumstances it's
+   allowed to use a position that is between Dynarr_length() and
+   Dynarr_largest().  The ideal solution is to never allow this, and require
+   instead that code first change the length before accessing higher
+   positions.  That would require looking through all the code that accesses
+   dynarrs and fixing it appropriately (especially redisplay code, and
+   especially redisplay code in the vicinity of a reference to
+   Dynarr_largest(), since such code usually checks explicitly to see whether
+   there is extra stuff between Dynarr_length() and Dynarr_largest().)
+
+   [II] LOCKING
+
+   The idea behind dynarr locking is simple: Locking a dynarr prevents
+   any modification from occurring, or rather, leads to an abort upon
+   any attempt to modify a dynarr.
+
+   Dynarr locking was originally added to catch some sporadic and hard-to-
+   debug crashes in the redisplay code where dynarrs appeared to be getting
+   corrupted in an unexpected fashion.  The solution was to lock the
+   dynarrs that were getting corrupted (in this case, the display-line
+   dynarrs) around calls to routines that weren't supposed to be changing
+   these dynarrs but might somehow be calling code that modified them.
+   This eventually revealed that there was a reentrancy problem with
+   redisplay that involved the QUIT mechanism and the processing done in
+   order to determine whether C-g had been pressed -- this processing
+   involves retrieving, processing and queueing pending events to see
+   whether any of them result in a C-g keypress.  However, at least under
+   MS Windows this can result in redisplay being called reentrantly.
+   For more info:--
+   
+  (Info-goto-node "(internals)Critical Redisplay Sections")
+
+*/
+
 #ifdef ERROR_CHECK_DYNARR
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_at (void *d, int pos, const Ascbyte *file, int line)
+Dynarr_verify_pos_at (void *d, Elemcount pos, const Ascbyte *file, int line)
 )
 {
   Dynarr *dy = (Dynarr *) d;
@@ -1791,7 +1862,7 @@
 
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_atp (void *d, int pos, const Ascbyte *file, int line)
+Dynarr_verify_pos_atp (void *d, Elemcount pos, const Ascbyte *file, int line)
 )
 {
   Dynarr *dy = (Dynarr *) d;
@@ -1831,7 +1902,7 @@
 
 DECLARE_INLINE_HEADER (
 int
-Dynarr_verify_pos_atp_allow_end (void *d, int pos, const Ascbyte *file,
+Dynarr_verify_pos_atp_allow_end (void *d, Elemcount pos, const Ascbyte *file,
 				 int line)
 )
 {
@@ -1874,30 +1945,42 @@
 
 #define Dynarr_verify(d) Dynarr_verify_1 (d, __FILE__, __LINE__)
 #define Dynarr_verify_mod(d) Dynarr_verify_mod_1 (d, __FILE__, __LINE__)
-#define Dynarr_lock(d)				\
-do {						\
-  Dynarr *dy = Dynarr_verify_mod (d);		\
-  dy->locked = 1;				\
-} while (0)
-#define Dynarr_unlock(d)			\
-do {						\
-  Dynarr *dy = Dynarr_verify (d);		\
-  dy->locked = 0;				\
-} while (0)
-#else
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_lock (void *d)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dy->locked = 1;
+}
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_unlock (void *d)
+)
+{
+  Dynarr *dy = Dynarr_verify (d);
+  assert (dy->locked);
+  dy->locked = 0;
+}
+
+#else /* not ERROR_CHECK_DYNARR */
+
 #define Dynarr_verify(d) ((Dynarr *) d)
 #define Dynarr_verify_mod(d) ((Dynarr *) d)
 #define Dynarr_lock(d) DO_NOTHING
 #define Dynarr_unlock(d) DO_NOTHING
+
 #endif /* ERROR_CHECK_DYNARR */
 
 /************* Dynarr creation *************/
 
-MODULE_API void *Dynarr_newf (int elsize);
+MODULE_API void *Dynarr_newf (Bytecount elsize);
 MODULE_API void Dynarr_free (void *d);
 
 #ifdef NEW_GC
-MODULE_API void *Dynarr_lisp_newf (int elsize,
+MODULE_API void *Dynarr_lisp_newf (Bytecount elsize,
 				   const struct lrecord_implementation 
 				   *dynarr_imp,
 				   const struct lrecord_implementation *imp);
@@ -1934,97 +2017,245 @@
 
 /************* Dynarr length/size retrieval and setting *************/
 
-/* Retrieve the length of a Dynarr.  The `+ 0' is to ensure that this cannot
+/* Retrieve the length of a dynarr.  The `+ 0' is to ensure that this cannot
    be used as an lvalue. */
 #define Dynarr_length(d) (Dynarr_verify (d)->len_ + 0)
-/* Retrieve the largest ever length seen of a Dynarr.  The `+ 0' is to
+/* Retrieve the largest ever length seen of a dynarr.  The `+ 0' is to
    ensure that this cannot be used as an lvalue. */
 #define Dynarr_largest(d) (Dynarr_verify (d)->largest_ + 0)
 /* Retrieve the number of elements that fit in the currently allocated
    space.  The `+ 0' is to ensure that this cannot be used as an lvalue. */
 #define Dynarr_max(d) (Dynarr_verify (d)->max_ + 0)
-/* Retrieve the advertised memory usage of a Dynarr, i.e. the number of
-   bytes occupied by the elements in the Dynarr, not counting any overhead. */
-#define Dynarr_sizeof(d) (Dynarr_length (d) * (d)->elsize)
-/* Actually set the length of a Dynarr.  This is a low-level routine that
-   should not be directly used; use Dynarr_set_length() instead if you need
-   to, but be very careful when doing so! */
-#define Dynarr_set_length_1(d, n)					\
-do {									\
-  Elemcount _dsl1_n = (n);						\
-  dynarr_checking_assert (_dsl1_n >= 0 && _dsl1_n <= Dynarr_max (d));	\
-  (void) Dynarr_verify_mod (d);						\
-  (d)->len_ = _dsl1_n;							\
-  /* Use the raw field references here otherwise we get a crash because	\
-     we've set the length but not yet fixed up the largest value. */	\
-  if ((d)->len_ > (d)->largest_)					\
-    (d)->largest_ = (d)->len_;						\
-  (void) Dynarr_verify_mod (d);						\
-} while (0)
-
-/* The following two defines will get you into real trouble if you aren't
-   careful.  But they can save a lot of execution time when used wisely. */
-#define Dynarr_set_length(d, n)						\
-do {									\
-  Elemcount _dsl_n = (n);						\
-  dynarr_checking_assert (_dsl_n >= 0 && _dsl_n <= Dynarr_largest (d)); \
-  Dynarr_set_length_1 (d, _dsl_n);					\
-} while (0)
-#define Dynarr_increment(d) \
-  Dynarr_set_length (d, Dynarr_length (d) + 1)
-
-/* Reset the Dynarr's length to 0. */
-#define Dynarr_reset(d) Dynarr_set_length (d, 0)
-
-MODULE_API void Dynarr_resize (void *dy, Elemcount size);
-
-#define Dynarr_resize_if(d, numels)			\
-do {							\
-  Elemcount _dri_numels = (numels);			\
-  if (Dynarr_length (d) + _dri_numels > Dynarr_max (d))	\
-    Dynarr_resize (d, Dynarr_length (d) + _dri_numels);	\
-} while (0)
+/* Return the size in bytes of an element in a dynarr. */
+#define Dynarr_elsize(d) (Dynarr_verify (d)->elsize_ + 0)
+/* Retrieve the advertised memory usage of a dynarr, i.e. the number of
+   bytes occupied by the elements in the dynarr, not counting any overhead. */
+#define Dynarr_sizeof(d) (Dynarr_length (d) * Dynarr_elsize (d))
+
+/* Actually set the length of a dynarr.  This is a low-level routine that
+   should not be directly used; use Dynarr_set_length() or
+   Dynarr_set_lengthr() instead. */
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length_1 (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= 0 && len <= Dynarr_max (dy));
+  /* Use the raw field references here otherwise we get a crash because
+     we've set the length but not yet fixed up the largest value. */
+  dy->len_ = len;
+  if (dy->len_ > dy->largest_)
+    dy->largest_ = dy->len_;
+  (void) Dynarr_verify_mod (d);
+}
+
+/* "Restricted set-length": Set the length of dynarr D to LEN,
+    which must be in the range [0, Dynarr_largest(d)]. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_lengthr (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= 0 && len <= Dynarr_largest (dy));
+  Dynarr_set_length_1 (dy, len);
+}
+
+/* "Restricted increment": Increment the length of dynarr D by 1; the resulting
+    length must be in the range [0, Dynarr_largest(d)]. */
+
+#define Dynarr_incrementr(d) Dynarr_set_lengthr (d, Dynarr_length (d) + 1)
+
+
+MODULE_API void Dynarr_resize (void *d, Elemcount size);
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_resize_to_fit (void *d, Elemcount size)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  if (size > Dynarr_max (dy))
+    Dynarr_resize (dy, size);
+}
+
+#define Dynarr_resize_to_add(d, numels)			\
+  Dynarr_resize_to_fit (d, Dynarr_length (d) + numels)
+
+/* This is an optimization.  This is like Dynarr_set_length() but the length
+   is guaranteed to be at least as big as the existing length. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_increase_length (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  dynarr_checking_assert (len >= Dynarr_length (dy));
+  Dynarr_resize_to_fit (dy, len);
+  Dynarr_set_length_1 (dy, len);
+}
+
+/* Set the length of dynarr D to LEN.  If the length increases, resize as
+   necessary to fit. (NOTE: This will leave uninitialized memory.  If you
+   aren't planning on immediately overwriting the memory, use
+   Dynarr_set_length_and_zero() to zero out all the memory that would
+   otherwise be uninitialized.) */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  if (old_len >= len)
+    Dynarr_set_lengthr (dy, len);
+  else
+    Dynarr_increase_length (d, len);
+}
+
+#define Dynarr_increment(d) Dynarr_increase_length (d, Dynarr_length (d) + 1)
+
+/* Zero LEN contiguous elements starting at POS. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_zero_many (void *d, Elemcount pos, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  memset ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), 0,
+	  len*Dynarr_elsize (dy));
+}
+
+/* This is an optimization.  This is like Dynarr_set_length_and_zero() but
+   the length is guaranteed to be at least as big as the existing
+   length. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_increase_length_and_zero (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  Dynarr_increase_length (dy, len);
+  Dynarr_zero_many (dy, old_len, len - old_len);
+}
+
+/* Set the length of dynarr D to LEN.  If the length increases, resize as
+   necessary to fit and zero out all the elements between the old and new
+   lengths. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_set_length_and_zero (void *d, Elemcount len)
+)
+{
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount old_len = Dynarr_length (dy);
+  if (old_len >= len)
+    Dynarr_set_lengthr (dy, len);
+  else
+    Dynarr_increase_length_and_zero (d, len);
+}
+
+/* Reset the dynarr's length to 0. */
+#define Dynarr_reset(d) Dynarr_set_lengthr (d, 0)
 
 #ifdef MEMORY_USAGE_STATS
 struct overhead_stats;
 Bytecount Dynarr_memory_usage (void *d, struct overhead_stats *stats);
 #endif
 
-/************* Adding/deleting elements to/from a Dynarr *************/
+/************* Adding/deleting elements to/from a dynarr *************/
+
+/* Set the Lisp implementation of the element at POS in dynarr D.  Only
+   does this if the dynarr holds Lisp objects of a particular type (the
+   objects themselves, not pointers to them), and only under NEW_GC. */
 
 #ifdef NEW_GC
-#define Dynarr_add(d, el)						\
+#define DYNARR_SET_LISP_IMP(d, pos)					\
 do {									\
-  const struct lrecord_implementation *imp = (d)->lisp_imp;		\
-  (void) Dynarr_verify_mod (d);						\
-  Dynarr_resize_if (d, 1);						\
-  ((d)->base)[Dynarr_length (d)] = (el);				\
-  if (imp)								\
+  if ((d)->lisp_imp)							\
     set_lheader_implementation						\
-     ((struct lrecord_header *)&(((d)->base)[Dynarr_length (d)]), imp);	\
-  Dynarr_set_length_1 (d, Dynarr_length (d) + 1);			\
-  (void) Dynarr_verify_mod (d);						\
+      ((struct lrecord_header *)&(((d)->base)[pos]), (d)->lisp_imp);	\
+} while (0)  
+#else
+#define DYNARR_SET_LISP_IMP(d, pos) DO_NOTHING
+#endif /* (not) NEW_GC */
+
+/* Add Element EL to the end of dynarr D. */
+
+#define Dynarr_add(d, el)			\
+do {						\
+  Elemcount _da_pos = Dynarr_length (d);	\
+  (void) Dynarr_verify_mod (d);			\
+  Dynarr_increment (d);				\
+  ((d)->base)[_da_pos] = (el);			\
+  DYNARR_SET_LISP_IMP (d, _da_pos);		\
 } while (0)
-#else /* not NEW_GC */
-#define Dynarr_add(d, el)				\
+
+/* Set EL as the element at position POS in dynarr D.
+   Expand the dynarr as necessary so that its length is enough to include
+   position POS within it, and zero out any new elements created as a
+   result of expansion, other than the one at POS. */
+
+#define Dynarr_set(d, pos, el)				\
 do {							\
+  Elemcount _ds_pos = (pos);				\
   (void) Dynarr_verify_mod (d);				\
-  Dynarr_resize_if (d, 1);				\
-  ((d)->base)[Dynarr_length (d)] = (el);		\
-  Dynarr_set_length_1 (d, Dynarr_length (d) + 1);	\
-  (void) Dynarr_verify_mod (d);				\
+  if (Dynarr_length (d) < _ds_pos + 1)			\
+    Dynarr_increase_length_and_zero (d, _ds_pos + 1);	\
+  ((d)->base)[_ds_pos] = (el);				\
+  DYNARR_SET_LISP_IMP (d, _ds_pos);			\
 } while (0)
-#endif /* not NEW_GC */
-
-
-MODULE_API void Dynarr_insert_many (void *d, const void *el, int len,
-				    int start);
-MODULE_API void Dynarr_delete_many (void *d, int start, int len);
-
-#define Dynarr_insert_many_at_start(d, el, len)	\
-  Dynarr_insert_many (d, el, len, 0)
+
+/* Add LEN contiguous elements, stored at BASE, to dynarr D.  If BASE is
+   NULL, reserve space but don't store anything. */
+
+DECLARE_INLINE_HEADER (
+void
+Dynarr_add_many (void *d, const void *base, Elemcount len)
+)
+{
+  /* This duplicates Dynarr_insert_many to some extent; but since it is
+     called so often, it seemed useful to remove the unnecessary stuff
+     from that function and to make it inline */
+  Dynarr *dy = Dynarr_verify_mod (d);
+  Elemcount pos = Dynarr_length (dy);
+  Dynarr_increase_length (dy, Dynarr_length (dy) + len);
+  if (base)
+    memcpy ((Rawbyte *) dy->base + pos*Dynarr_elsize (dy), base,
+	    len*Dynarr_elsize (dy));
+}
+
+/* Insert LEN elements, currently pointed to by BASE, into dynarr D
+   starting at position POS. */
+
+MODULE_API void Dynarr_insert_many (void *d, const void *base, Elemcount len,
+				    Elemcount pos);
+
+/* Prepend LEN elements, currently pointed to by BASE, to the beginning. */
+
+#define Dynarr_prepend_many(d, base, len) Dynarr_insert_many (d, base, len, 0)
+
+/* Add literal string S to dynarr D, which should hold chars or unsigned
+   chars.  The final zero byte is not stored. */
+
 #define Dynarr_add_literal_string(d, s) Dynarr_add_many (d, s, sizeof (s) - 1)
-#define Dynarr_add_lisp_string(d, s, codesys)			\
+
+/* Convert Lisp string S to an external encoding according to CODESYS and
+   add to dynarr D, which should hold chars or unsigned chars.  No final
+   zero byte is appended. */
+
+/* #### This should be an inline function but LISP_STRING_TO_SIZED_EXTERNAL
+   isn't declared yet. */
+
+#define Dynarr_add_ext_lisp_string(d, s, codesys)		\
 do {								\
   Lisp_Object dyna_ls_s = (s);					\
   Lisp_Object dyna_ls_cs = (codesys);				\
@@ -2036,34 +2267,28 @@
   Dynarr_add_many (d, dyna_ls_eb, dyna_ls_bc);			\
 } while (0)
 
-/* Add LEN contiguous elements to a Dynarr */
-
-DECLARE_INLINE_HEADER (
-void
-Dynarr_add_many (void *d, const void *el, int len)
-)
-{
-  /* This duplicates Dynarr_insert_many to some extent; but since it is
-     called so often, it seemed useful to remove the unnecessary stuff
-     from that function and to make it inline */
-  Dynarr *dy = Dynarr_verify_mod (d);
-  Dynarr_resize_if (dy, len);
-  /* Some functions call us with a value of 0 to mean "reserve space but
-     don't write into it" */
-  if (el)
-    memcpy ((char *) dy->base + Dynarr_sizeof (dy), el, len*dy->elsize);
-  Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
-  (void) Dynarr_verify_mod (dy);
-}
+/* Delete LEN elements starting at position POS. */
+
+MODULE_API void Dynarr_delete_many (void *d, Elemcount pos, Elemcount len);
+
+/* Pop off (i.e. delete) the last element from the dynarr and return it */
 
 #define Dynarr_pop(d)					\
   (dynarr_checking_assert (Dynarr_length (d) > 0),	\
    Dynarr_verify_mod (d)->len_--,			\
    Dynarr_at (d, Dynarr_length (d)))
-#define Dynarr_delete(d, i) Dynarr_delete_many (d, i, 1)
+
+/* Delete the item at POS */
+
+#define Dynarr_delete(d, pos) Dynarr_delete_many (d, pos, 1)
+
+/* Delete the item located at memory address P, which must be a `type *'
+   pointer, where `type' is the type of the elements of the dynarr. */
 #define Dynarr_delete_by_pointer(d, p) \
   Dynarr_delete_many (d, (p) - ((d)->base), 1)
 
+/* Delete all elements that are numerically equal to EL. */
+
 #define Dynarr_delete_object(d, el)		\
 do						\
 {						\
@@ -3201,11 +3426,11 @@
   return XREALINT (obj);
 }
 
-#else /* no error checking */
+#else /* not ERROR_CHECK_TYPES */
 
 #define XINT(obj) XREALINT (obj)
 
-#endif /* no error checking */
+#endif /* (not) ERROR_CHECK_TYPES */
 
 #define CHECK_INT(x) do {			\
   if (!INTP (x))				\
@@ -3217,6 +3442,10 @@
     x = wrong_type_argument (Qintegerp, x);	\
 } while (0)
 
+/* NOTE NOTE NOTE! This definition of "natural number" is mathematically
+   wrong.  Mathematically, a natural number is a positive integer; 0
+   isn't included.  This would be better called NONNEGINT(). */
+
 #define NATNUMP(x) (INTP (x) && XINT (x) >= 0)
 
 #define CHECK_NATNUM(x) do {			\
--- a/src/mc-alloc.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/mc-alloc.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,5 +1,6 @@
 /* New size-based allocator for XEmacs.
    Copyright (C) 2005 Marcus Crestani.
+   Copyright (C) 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -1578,7 +1579,7 @@
 
 /* Changes the size of the cell pointed to by ptr.
    Returns the new address of the new cell with new size. */
-void *
+static void *
 mc_realloc_1 (void *ptr, size_t size, int elemcount)
 {
   if (ptr)
@@ -1782,25 +1783,25 @@
 /*--- incremental garbage collector ----------------------------------*/
 
 /* access dirty bit of page header */
-void
+static void
 set_dirty_bit (page_header *ph, unsigned int value)
 {
   PH_DIRTY_BIT (ph) = value;
 }
 
-void
+static void
 set_dirty_bit_for_address (void *ptr, unsigned int value)
 {
   set_dirty_bit (get_page_header (ptr), value);
 }
 
-unsigned int
+static unsigned int
 get_dirty_bit (page_header *ph)
 {
   return PH_DIRTY_BIT (ph);
 }
 
-unsigned int
+static unsigned int
 get_dirty_bit_for_address (void *ptr)
 {
   return get_dirty_bit (get_page_header (ptr));
@@ -1808,25 +1809,25 @@
 
 
 /* access protection bit of page header */
-void
+static void
 set_protection_bit (page_header *ph, unsigned int value)
 {
   PH_PROTECTION_BIT (ph) = value;
 }
 
-void
+static void
 set_protection_bit_for_address (void *ptr, unsigned int value)
 {
   set_protection_bit (get_page_header (ptr), value);
 }
 
-unsigned int
+static unsigned int
 get_protection_bit (page_header *ph)
 {
   return PH_PROTECTION_BIT (ph);
 }
 
-unsigned int
+static unsigned int
 get_protection_bit_for_address (void *ptr)
 {
   return get_protection_bit (get_page_header (ptr));
@@ -1834,7 +1835,7 @@
 
 
 /* Returns the start of the page of the object pointed to by ptr. */
-void *
+static void *
 get_page_start (void *ptr)
 {
   return PH_HEAP_SPACE (get_page_header (ptr));
--- a/src/objects-tty.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/objects-tty.c	Sat Feb 20 23:56:01 2010 -0600
@@ -30,12 +30,6 @@
 #include "device.h"
 #include "charset.h"
 
-#ifdef NEW_GC
-# define UNUSED_IF_NEW_GC(decl) UNUSED (decl)
-#else
-# define UNUSED_IF_NEW_GC(decl) decl
-#endif
-
 /* An alist mapping from color names to a cons of (FG-STRING, BG-STRING). */
 Lisp_Object Vtty_color_alist;
 #if 0 /* This stuff doesn't quite work yet */
--- a/src/profile.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/profile.c	Sat Feb 20 23:56:01 2010 -0600
@@ -125,7 +125,7 @@
 {
   /* The hash code can safely be called from a signal handler except when
      it has to grow the hash table.  In this case, it calls realloc(),
-     which is not (in general) re-entrant.  The way we deal with this is
+     which is not (in general) reentrant.  The way we deal with this is
      documented at the top of this file. */
   if (!big_profile_table)
     big_profile_table = make_hash_table (2000);
--- a/src/redisplay-msw.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/redisplay-msw.c	Sat Feb 20 23:56:01 2010 -0600
@@ -2,7 +2,7 @@
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1994 Lucid, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 2001, 2002, 2003 Ben Wing.
+   Copyright (C) 2001, 2002, 2003, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -1208,12 +1208,7 @@
  given face.
  ****************************************************************************/
 static void
-mswindows_clear_region (
-#ifdef HAVE_SCROLLBARS
-			Lisp_Object locale,
-#else
-			Lisp_Object UNUSED (locale),
-#endif
+mswindows_clear_region (Lisp_Object USED_IF_SCROLLBARS (locale),
 			struct device *UNUSED (d), struct frame *f, 
 			face_index UNUSED (findex), int x, int y,
 			int width, int height, Lisp_Object fcolor,
--- a/src/redisplay-output.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/redisplay-output.c	Sat Feb 20 23:56:01 2010 -0600
@@ -83,7 +83,7 @@
 	 redisplay performance so avoiding all excess overhead is a
 	 good thing.  Is all of this true? */
       memcpy (cra->base, dra->base, sizeof (struct rune) * max_move);
-      Dynarr_set_length (cra, max_move);
+      Dynarr_set_lengthr (cra, max_move);
     }
   else
     Dynarr_reset (cra);
@@ -171,7 +171,7 @@
 	      tr = cdb->runes;
 	      memcpy (cdb, ddb, sizeof (struct display_block));
 	      cdb->runes = tr;
-	      Dynarr_increment (clp->display_blocks);
+	      Dynarr_incrementr (clp->display_blocks);
 	    }
 
 	  sync_rune_structs (w, cdb->runes, ddb->runes);
@@ -183,7 +183,7 @@
   else if (line >= Dynarr_length (cdla))
     {
       assert (line == Dynarr_length (cdla));
-      Dynarr_increment (cdla);
+      Dynarr_incrementr (cdla);
     }
 }
 
@@ -475,7 +475,7 @@
   rb = Dynarr_atp (db->runes, cursor_location);
   *cursor_start = rb->xpos;
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
   *cursor_height = defheight;
 
   if (rb->type == RUNE_BLANK)
@@ -638,7 +638,7 @@
 
   redisplay_clear_region (window, DEFAULT_INDEX,
 		FRAME_LEFT_BORDER_START (f), y,
-		FRAME_BORDER_WIDTH (f), height);
+		FRAME_INTERNAL_BORDER_WIDTH (f), height);
 }
 
 /*****************************************************************************
@@ -654,7 +654,7 @@
 
   redisplay_clear_region (window, DEFAULT_INDEX,
 		FRAME_RIGHT_BORDER_START (f),
-		y, FRAME_BORDER_WIDTH (f), height);
+		y, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 }
 
 /*****************************************************************************
@@ -2102,14 +2102,14 @@
 
       if (window_is_leftmost (w))
 	{
-	  x -= FRAME_BORDER_WIDTH (f);
-	  width += FRAME_BORDER_WIDTH (f);
+	  x -= FRAME_INTERNAL_BORDER_WIDTH (f);
+	  width += FRAME_INTERNAL_BORDER_WIDTH (f);
 	}
       if (window_is_rightmost (w))
-	width += FRAME_BORDER_WIDTH (f);
+	width += FRAME_INTERNAL_BORDER_WIDTH (f);
 
       y = FRAME_TOP_BORDER_START (f) - 1;
-      height = FRAME_BORDER_HEIGHT (f) + 1;
+      height = FRAME_INTERNAL_BORDER_HEIGHT (f) + 1;
 
       redisplay_clear_region (window, DEFAULT_INDEX, x, y, width, height);
     }
@@ -2145,7 +2145,7 @@
 
 	  if (window_is_leftmost (w))
 	    redisplay_clear_region (window, DEFAULT_INDEX, FRAME_LEFT_BORDER_START (f),
-				    ypos1, FRAME_BORDER_WIDTH (f), height);
+				    ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 
 	  if (bounds.left_in - bounds.left_out > 0)
 	    redisplay_clear_region (window,
@@ -2167,7 +2167,7 @@
 
 	  if (window_is_rightmost (w))
 	    redisplay_clear_region (window, DEFAULT_INDEX, FRAME_RIGHT_BORDER_START (f),
-				    ypos1, FRAME_BORDER_WIDTH (f), height);
+				    ypos1, FRAME_INTERNAL_BORDER_WIDTH (f), height);
 	}
     }
 }
@@ -2217,7 +2217,7 @@
   /* #### See if this can be made conditional on the frame
      changing size. */
   if (MINI_WINDOW_P (w))
-    ypos2 += FRAME_BORDER_HEIGHT (f);
+    ypos2 += FRAME_INTERNAL_BORDER_HEIGHT (f);
 
   if (min_start >= 0 && ypos1 < min_start)
     ypos1 = min_start;
@@ -2464,7 +2464,7 @@
   /* If the number of display lines has shrunk, adjust. */
   if (cdla_len > ddla_len)
     {
-      Dynarr_set_length (cdla, ddla_len);
+      Dynarr_set_lengthr (cdla, ddla_len);
     }
 
   /* Output a vertical divider between windows, if necessary. */
--- a/src/redisplay-xlike-inc.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/redisplay-xlike-inc.c	Sat Feb 20 23:56:01 2010 -0600
@@ -2056,7 +2056,7 @@
 
   gc = XLIKE_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil);
 
-  default_face_font_info (window, &defascent, 0, &defheight, 0, 0);
+  default_face_font_info (window, &defascent, 0, 0, &defheight, 0);
 
   /* make sure the cursor is entirely contained between y and y+height */
   cursor_height = min (defheight, height);
@@ -2188,7 +2188,7 @@
   gcv.graphics_exposures = XLIKE_FALSE;
   gc = gc_cache_lookup (DEVICE_XLIKE_GC_CACHE (XDEVICE (f->device)), &gcv,
 			XLIKE_GC_FOREGROUND | XLIKE_GC_FUNCTION | XLIKE_GC_EXPOSURES);
-  default_face_height_and_width (frame, &flash_height, 0);
+  default_face_width_and_height (frame, 0, &flash_height);
 
   /* If window is tall, flash top and bottom line.  */
   if (EQ (Vvisible_bell, Qtop_bottom) && w->pixel_height > 3 * flash_height)
--- a/src/redisplay.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/redisplay.c	Sat Feb 20 23:56:01 2010 -0600
@@ -728,7 +728,7 @@
 	  struct display_block *dbp = Dynarr_atp (dl->display_blocks, elt);
 
 	  /* "add" the block to the list */
-	  Dynarr_increment (dl->display_blocks);
+	  Dynarr_incrementr (dl->display_blocks);
 
 	  /* initialize and return */
 	  dbp->type = type;
@@ -924,8 +924,8 @@
       int scaled_default_font_ascent, scaled_default_font_descent;
 
       default_face_font_info (data->window, &default_font_ascent,
-			      &default_font_descent, &default_font_height,
-			      0, 0);
+			      &default_font_descent, 0, &default_font_height,
+			      0);
 
       scaled_default_font_ascent = data->max_pixmap_height *
 	default_font_ascent / default_font_height;
@@ -1221,7 +1221,7 @@
   if (local)
     Dynarr_add (data->db->runes, *crb);
   else
-    Dynarr_increment (data->db->runes);
+    Dynarr_incrementr (data->db->runes);
 
   data->pixpos += width;
 
@@ -4532,7 +4532,7 @@
       if (Dynarr_length (dla) == 0)
 	{
 	  if (Dynarr_largest (dla) > 0)
-	    Dynarr_increment (dla);
+	    Dynarr_incrementr (dla);
 	  else
 	    {
 	      struct display_line modeline;
@@ -5301,9 +5301,10 @@
 
 /*
 
-Info on Re-entrancy crashes, with backtraces given:
-
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+Info on reentrancy crashes, with backtraces given:
+
+  (Info-goto-node "(internals)Critical Redisplay Sections")
+
 */
 
 
@@ -5405,7 +5406,7 @@
       if (pos_of_dlp < 0)
 	Dynarr_add (dla, *dlp);
       else if (pos_of_dlp == Dynarr_length (dla))
-	Dynarr_increment (dla);
+	Dynarr_incrementr (dla);
       else
 	ABORT ();
 
@@ -5459,13 +5460,13 @@
   if (!in_display)
     depth = enter_redisplay_critical_section ();
 
-  /* This is one spot where a re-entrancy crash will occur, due to a check
+  /* This is one spot where a reentrancy crash will occur, due to a check
      in the dynarr to make sure it isn't "locked" */
 /*
 
-Info on Re-entrancy crashes, with backtraces given:
-
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+Info on reentrancy crashes, with backtraces given:
+
+  (Info-goto-node "(internals)Critical Redisplay Sections")
 */
 
   Dynarr_reset (dla);
@@ -5628,7 +5629,7 @@
       if (pos_of_dlp < 0)
 	Dynarr_add (dla, *dlp);
       else if (pos_of_dlp == Dynarr_length (dla))
-	Dynarr_increment (dla);
+	Dynarr_incrementr (dla);
       else
 	ABORT ();
 
@@ -6764,7 +6765,7 @@
 	{
 	  struct frame *f = XFRAME (XCAR (frmcons));
 	  if (f->size_change_pending)
-	    change_frame_size (f, f->new_height, f->new_width, 0);
+	    change_frame_size (f, f->new_width, f->new_height, 0);
 	}
     }
   return Qnil;
@@ -6901,7 +6902,7 @@
   /* Before we put a hold on frame size changes, attempt to process
      any which are already pending. */
   if (f->size_change_pending)
-    change_frame_size (f, f->new_height, f->new_width, 0);
+    change_frame_size (f, f->new_width, f->new_height, 0);
 
   /* If frame size might need to be changed, due to changed size
      of toolbars, scrollbars etc, change it now */
@@ -8316,7 +8317,7 @@
 	  int defheight;
 
 	  window = wrap_window (w);
-	  default_face_height_and_width (window, &defheight, 0);
+	  default_face_width_and_height (window, 0, &defheight);
 
 	  cur_elt = Dynarr_length (w->line_start_cache) - 1;
 
@@ -8469,7 +8470,7 @@
 	      return;
 	    }
 
-	  Dynarr_insert_many_at_start (cache, Dynarr_begin (internal_cache),
+	  Dynarr_prepend_many (cache, Dynarr_begin (internal_cache),
 			      ic_elt + 1);
 	}
 
@@ -8621,7 +8622,7 @@
   int defheight, defwidth;
 
   window = wrap_window (w);
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   /* If we get a bogus value indicating somewhere above or to the left of
      the window, use the first window line or character position
@@ -9290,7 +9291,7 @@
 	  int defheight;
 
 	  lwin = wrap_window (*w);
-	  default_face_height_and_width (lwin, 0, &defheight);
+	  default_face_width_and_height (lwin, 0, &defheight);
 
 	  *row += (adj_area / defheight);
 	}
--- a/src/regex.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/regex.c	Sat Feb 20 23:56:01 2010 -0600
@@ -5,7 +5,7 @@
 
    Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 1995, 2001, 2002, 2003 Ben Wing.
+   Copyright (C) 1995, 2001, 2002, 2003, 2010 Ben Wing.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -734,17 +734,48 @@
 #include <assert.h>
 #endif
 
-static int debug = 0;
+extern int debug_regexps;
 
 #define DEBUG_STATEMENT(e) e
-#define DEBUG_PRINT1(x) if (debug) printf (x)
-#define DEBUG_PRINT2(x1, x2) if (debug) printf (x1, x2)
-#define DEBUG_PRINT3(x1, x2, x3) if (debug) printf (x1, x2, x3)
-#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug) printf (x1, x2, x3, x4)
+
+#define DEBUG_PRINT1(x) if (debug_regexps) printf (x)
+#define DEBUG_PRINT2(x1, x2) if (debug_regexps) printf (x1, x2)
+#define DEBUG_PRINT3(x1, x2, x3) if (debug_regexps) printf (x1, x2, x3)
+#define DEBUG_PRINT4(x1, x2, x3, x4) if (debug_regexps) printf (x1, x2, x3, x4)
 #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e) 				\
-  if (debug) print_partial_compiled_pattern (s, e)
+  if (debug_regexps) print_partial_compiled_pattern (s, e)
 #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)			\
-  if (debug) print_double_string (w, s1, sz1, s2, sz2)
+  if (debug_regexps) print_double_string (w, s1, sz1, s2, sz2)
+
+#define DEBUG_FAIL_PRINT1(x) \
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT) printf (x)
+#define DEBUG_FAIL_PRINT2(x1, x2) \
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT) printf (x1, x2)
+#define DEBUG_FAIL_PRINT3(x1, x2, x3) \
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT) printf (x1, x2, x3)
+#define DEBUG_FAIL_PRINT4(x1, x2, x3, x4) \
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT) printf (x1, x2, x3, x4)
+#define DEBUG_FAIL_PRINT_COMPILED_PATTERN(p, s, e)	\
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT)		\
+    print_partial_compiled_pattern (s, e)
+#define DEBUG_FAIL_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)	\
+  if (debug_regexps & RE_DEBUG_FAILURE_POINT)			\
+    print_double_string (w, s1, sz1, s2, sz2)
+
+#define DEBUG_MATCH_PRINT1(x) \
+  if (debug_regexps & RE_DEBUG_MATCHING) printf (x)
+#define DEBUG_MATCH_PRINT2(x1, x2) \
+  if (debug_regexps & RE_DEBUG_MATCHING) printf (x1, x2)
+#define DEBUG_MATCH_PRINT3(x1, x2, x3) \
+  if (debug_regexps & RE_DEBUG_MATCHING) printf (x1, x2, x3)
+#define DEBUG_MATCH_PRINT4(x1, x2, x3, x4) \
+  if (debug_regexps & RE_DEBUG_MATCHING) printf (x1, x2, x3, x4)
+#define DEBUG_MATCH_PRINT_COMPILED_PATTERN(p, s, e)	\
+  if (debug_regexps & RE_DEBUG_MATCHING)		\
+    print_partial_compiled_pattern (s, e)
+#define DEBUG_MATCH_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)	\
+  if (debug_regexps & RE_DEBUG_MATCHING)			\
+    print_double_string (w, s1, sz1, s2, sz2)
 
 
 /* Print the fastmap in human-readable form.  */
@@ -1133,6 +1164,7 @@
 #endif
 
 #define DEBUG_STATEMENT(e)
+
 #define DEBUG_PRINT1(x)
 #define DEBUG_PRINT2(x1, x2)
 #define DEBUG_PRINT3(x1, x2, x3)
@@ -1140,6 +1172,20 @@
 #define DEBUG_PRINT_COMPILED_PATTERN(p, s, e)
 #define DEBUG_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
 
+#define DEBUG_FAIL_PRINT1(x)
+#define DEBUG_FAIL_PRINT2(x1, x2)
+#define DEBUG_FAIL_PRINT3(x1, x2, x3)
+#define DEBUG_FAIL_PRINT4(x1, x2, x3, x4)
+#define DEBUG_FAIL_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_FAIL_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
+#define DEBUG_MATCH_PRINT1(x)
+#define DEBUG_MATCH_PRINT2(x1, x2)
+#define DEBUG_MATCH_PRINT3(x1, x2, x3)
+#define DEBUG_MATCH_PRINT4(x1, x2, x3, x4)
+#define DEBUG_MATCH_PRINT_COMPILED_PATTERN(p, s, e)
+#define DEBUG_MATCH_PRINT_DOUBLE_STRING(w, s1, sz1, s2, sz2)
+
 #endif /* DEBUG */
 
 /* Set by `re_set_syntax' to the current regexp syntax to recognize.  Can
@@ -1523,14 +1569,14 @@
 									\
   DEBUG_STATEMENT (failure_id++);					\
   DEBUG_STATEMENT (nfailure_points_pushed++);				\
-  DEBUG_PRINT2 ("\nPUSH_FAILURE_POINT #%d:\n", failure_id);		\
-  DEBUG_PRINT2 ("  Before push, next avail: %ld\n",			\
+  DEBUG_FAIL_PRINT2 ("\nPUSH_FAILURE_POINT #%d:\n", failure_id);	\
+  DEBUG_FAIL_PRINT2 ("  Before push, next avail: %ld\n",		\
 		(long) (fail_stack).avail);				\
-  DEBUG_PRINT2 ("                     size: %ld\n",			\
+  DEBUG_FAIL_PRINT2 ("                     size: %ld\n",		\
 		(long) (fail_stack).size);				\
 									\
-  DEBUG_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);		\
-  DEBUG_PRINT2 ("     available: %ld\n",				\
+  DEBUG_FAIL_PRINT2 ("  slots needed: %d\n", NUM_FAILURE_ITEMS);	\
+  DEBUG_FAIL_PRINT2 ("     available: %ld\n",				\
 		(long) REMAINING_AVAIL_SLOTS);				\
 									\
   /* Ensure we have enough space allocated for what we will push.  */	\
@@ -1544,59 +1590,59 @@
 	  return failure_code;						\
 	}								\
       END_REGEX_MALLOC_OK ();						\
-      DEBUG_PRINT2 ("\n  Doubled stack; size now: %ld\n",		\
+      DEBUG_FAIL_PRINT2 ("\n  Doubled stack; size now: %ld\n",		\
 		    (long) (fail_stack).size);				\
-      DEBUG_PRINT2 ("  slots available: %ld\n",				\
+      DEBUG_FAIL_PRINT2 ("  slots available: %ld\n",			\
 		    (long) REMAINING_AVAIL_SLOTS);			\
 									\
       RE_MATCH_RELOCATE_MOVEABLE_DATA_POINTERS ();			\
     }									\
 									\
   /* Push the info, starting with the registers.  */			\
-  DEBUG_PRINT1 ("\n");							\
+  DEBUG_FAIL_PRINT1 ("\n");						\
 									\
   for (this_reg = lowest_active_reg; this_reg <= highest_active_reg;	\
        this_reg++)							\
     {									\
-      DEBUG_PRINT2 ("  Pushing reg: %d\n", this_reg);			\
+      DEBUG_FAIL_PRINT2 ("  Pushing reg: %d\n", this_reg);		\
       DEBUG_STATEMENT (num_regs_pushed++);				\
 									\
-      DEBUG_PRINT2 ("    start: 0x%lx\n", (long) regstart[this_reg]);	\
+      DEBUG_FAIL_PRINT2 ("    start: 0x%lx\n", (long) regstart[this_reg]); \
       PUSH_FAILURE_POINTER (regstart[this_reg]);			\
 									\
-      DEBUG_PRINT2 ("    end: 0x%lx\n", (long) regend[this_reg]);	\
+      DEBUG_FAIL_PRINT2 ("    end: 0x%lx\n", (long) regend[this_reg]);	\
       PUSH_FAILURE_POINTER (regend[this_reg]);				\
 									\
-      DEBUG_PRINT2 ("    info: 0x%lx\n      ",				\
+      DEBUG_FAIL_PRINT2 ("    info: 0x%lx\n      ",			\
 		    * (long *) (&reg_info[this_reg]));			\
-      DEBUG_PRINT2 (" match_null=%d",					\
+      DEBUG_FAIL_PRINT2 (" match_null=%d",				\
 		    REG_MATCH_NULL_STRING_P (reg_info[this_reg]));	\
-      DEBUG_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
-      DEBUG_PRINT2 (" matched_something=%d",				\
+      DEBUG_FAIL_PRINT2 (" active=%d", IS_ACTIVE (reg_info[this_reg]));	\
+      DEBUG_FAIL_PRINT2 (" matched_something=%d",			\
 		    MATCHED_SOMETHING (reg_info[this_reg]));		\
-      DEBUG_PRINT2 (" ever_matched_something=%d",			\
+      DEBUG_FAIL_PRINT2 (" ever_matched_something=%d",			\
 		    EVER_MATCHED_SOMETHING (reg_info[this_reg]));	\
-      DEBUG_PRINT1 ("\n");						\
+      DEBUG_FAIL_PRINT1 ("\n");						\
       PUSH_FAILURE_ELT (reg_info[this_reg].word);			\
     }									\
 									\
-  DEBUG_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg);	\
+  DEBUG_FAIL_PRINT2 ("  Pushing  low active reg: %d\n", lowest_active_reg); \
   PUSH_FAILURE_INT (lowest_active_reg);					\
 									\
-  DEBUG_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg);	\
+  DEBUG_FAIL_PRINT2 ("  Pushing high active reg: %d\n", highest_active_reg); \
   PUSH_FAILURE_INT (highest_active_reg);				\
 									\
-  DEBUG_PRINT2 ("  Pushing pattern 0x%lx: \n", (long) pattern_place);	\
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);		\
+  DEBUG_FAIL_PRINT2 ("  Pushing pattern 0x%lx: \n", (long) pattern_place); \
+  DEBUG_FAIL_PRINT_COMPILED_PATTERN (bufp, pattern_place, pend);	\
   PUSH_FAILURE_POINTER (pattern_place);					\
 									\
-  DEBUG_PRINT2 ("  Pushing string 0x%lx: `", (long) string_place);	\
-  DEBUG_PRINT_DOUBLE_STRING (string_place, string1, size1, string2,	\
+  DEBUG_FAIL_PRINT2 ("  Pushing string 0x%lx: `", (long) string_place);	\
+  DEBUG_FAIL_PRINT_DOUBLE_STRING (string_place, string1, size1, string2, \
 			     size2);					\
-  DEBUG_PRINT1 ("'\n");							\
+  DEBUG_FAIL_PRINT1 ("'\n");						\
   PUSH_FAILURE_POINTER (string_place);					\
 									\
-  DEBUG_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
+  DEBUG_FAIL_PRINT2 ("  Pushing failure id: %u\n", failure_id);		\
   DEBUG_PUSH (failure_id);						\
 } while (0)
 
@@ -1648,16 +1694,16 @@
   assert (!FAIL_STACK_EMPTY ());					\
 									\
   /* Remove failure points and point to how many regs pushed.  */	\
-  DEBUG_PRINT1 ("POP_FAILURE_POINT:\n");				\
-  DEBUG_PRINT2 ("  Before pop, next avail: %ld\n",			\
+  DEBUG_FAIL_PRINT1 ("POP_FAILURE_POINT:\n");				\
+  DEBUG_FAIL_PRINT2 ("  Before pop, next avail: %ld\n",			\
 		(long) fail_stack.avail);				\
-  DEBUG_PRINT2 ("                    size: %ld\n",			\
+  DEBUG_FAIL_PRINT2 ("                    size: %ld\n",			\
 		(long) fail_stack.size);				\
 									\
   assert (fail_stack.avail >= NUM_NONREG_ITEMS);			\
 									\
   DEBUG_POP (&ffailure_id.integer);					\
-  DEBUG_PRINT2 ("  Popping failure id: %d\n",				\
+  DEBUG_FAIL_PRINT2 ("  Popping failure id: %d\n",			\
 		* (int *) &ffailure_id);				\
 									\
   /* If the saved string location is NULL, it came from an		\
@@ -1667,34 +1713,34 @@
   if (string_temp != NULL)						\
     str = string_temp;							\
 									\
-  DEBUG_PRINT2 ("  Popping string 0x%lx: `",  (long) str);		\
-  DEBUG_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
-  DEBUG_PRINT1 ("'\n");							\
+  DEBUG_FAIL_PRINT2 ("  Popping string 0x%lx: `",  (long) str);		\
+  DEBUG_FAIL_PRINT_DOUBLE_STRING (str, string1, size1, string2, size2);	\
+  DEBUG_FAIL_PRINT1 ("'\n");						\
 									\
   pat = (unsigned char *) POP_FAILURE_POINTER ();			\
-  DEBUG_PRINT2 ("  Popping pattern 0x%lx: ", (long) pat);		\
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
+  DEBUG_FAIL_PRINT2 ("  Popping pattern 0x%lx: ", (long) pat);		\
+  DEBUG_FAIL_PRINT_COMPILED_PATTERN (bufp, pat, pend);			\
 									\
   /* Restore register info.  */						\
   high_reg = POP_FAILURE_INT ();					\
-  DEBUG_PRINT2 ("  Popping high active reg: %d\n", high_reg);		\
+  DEBUG_FAIL_PRINT2 ("  Popping high active reg: %d\n", high_reg);	\
 									\
   low_reg = POP_FAILURE_INT ();						\
-  DEBUG_PRINT2 ("  Popping  low active reg: %d\n", low_reg);		\
+  DEBUG_FAIL_PRINT2 ("  Popping  low active reg: %d\n", low_reg);	\
 									\
   for (this_reg = high_reg; this_reg >= low_reg; this_reg--)		\
     {									\
-      DEBUG_PRINT2 ("    Popping reg: %d\n", this_reg);			\
+      DEBUG_FAIL_PRINT2 ("    Popping reg: %d\n", this_reg);		\
 									\
       reg_info[this_reg].word = POP_FAILURE_ELT ();			\
-      DEBUG_PRINT2 ("      info: 0x%lx\n",				\
+      DEBUG_FAIL_PRINT2 ("      info: 0x%lx\n",				\
 		    * (long *) &reg_info[this_reg]);			\
 									\
       regend[this_reg] = POP_FAILURE_POINTER ();			\
-      DEBUG_PRINT2 ("      end: 0x%lx\n", (long) regend[this_reg]);	\
+      DEBUG_FAIL_PRINT2 ("      end: 0x%lx\n", (long) regend[this_reg]); \
 									\
       regstart[this_reg] = POP_FAILURE_POINTER ();			\
-      DEBUG_PRINT2 ("      start: 0x%lx\n", (long) regstart[this_reg]);	\
+      DEBUG_FAIL_PRINT2 ("      start: 0x%lx\n", (long) regstart[this_reg]); \
     }									\
 									\
   set_regs_matched_done = 0;						\
@@ -2157,11 +2203,11 @@
   regnum_t regnum = 0;
 
 #ifdef DEBUG
-  DEBUG_PRINT1 ("\nCompiling pattern: ");
-  if (debug)
+  if (debug_regexps & RE_DEBUG_COMPILATION)
     {
       int debug_count;
 
+      DEBUG_PRINT1 ("\nCompiling pattern: ");
       for (debug_count = 0; debug_count < size; debug_count++)
         putchar (pattern[debug_count]);
       putchar ('\n');
@@ -3405,7 +3451,7 @@
   bufp->used = buf_end - bufp->buffer;
 
 #ifdef DEBUG
-  if (debug)
+  if (debug_regexps & RE_DEBUG_COMPILATION)
     {
       DEBUG_PRINT1 ("\nCompiled pattern: \n");
       print_compiled_pattern (bufp);
@@ -4906,7 +4952,7 @@
 #endif
 #endif /* emacs */
 
-  DEBUG_PRINT1 ("\n\nEntering re_match_2.\n");
+  DEBUG_MATCH_PRINT1 ("\n\nEntering re_match_2.\n");
 
   BEGIN_REGEX_MALLOC_OK ();
   INIT_FAIL_STACK ();
@@ -5024,18 +5070,18 @@
       dend = end_match_2;
     }
 
-  DEBUG_PRINT1 ("The compiled pattern is: \n");
-  DEBUG_PRINT_COMPILED_PATTERN (bufp, p, pend);
-  DEBUG_PRINT1 ("The string to match is: `");
-  DEBUG_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
-  DEBUG_PRINT1 ("'\n");
+  DEBUG_MATCH_PRINT1 ("The compiled pattern is: \n");
+  DEBUG_MATCH_PRINT_COMPILED_PATTERN (bufp, p, pend);
+  DEBUG_MATCH_PRINT1 ("The string to match is: `");
+  DEBUG_MATCH_PRINT_DOUBLE_STRING (d, string1, size1, string2, size2);
+  DEBUG_MATCH_PRINT1 ("'\n");
 
   /* This loops over pattern commands.  It exits by returning from the
      function if the match is complete, or it drops through if the match
      fails at this starting point in the input data.  */
   for (;;)
     {
-      DEBUG_PRINT2 ("\n0x%lx: ", (long) p);
+      DEBUG_MATCH_PRINT2 ("\n0x%lx: ", (long) p);
 #ifdef emacs /* XEmacs added, w/removal of immediate_quit */
       if (!no_quit_in_re_search)
 	{
@@ -5048,7 +5094,7 @@
 
       if (p == pend)
 	{ /* End of pattern means we might have succeeded.  */
-          DEBUG_PRINT1 ("end of pattern ... ");
+          DEBUG_MATCH_PRINT1 ("end of pattern ... ");
 
 	  /* If we haven't matched the entire string, and we want the
              longest match, try backtracking.  */
@@ -5064,7 +5110,7 @@
 	      else
 		best_match_p = !MATCHING_IN_FIRST_STRING;
 
-              DEBUG_PRINT1 ("backtracking.\n");
+              DEBUG_MATCH_PRINT1 ("backtracking.\n");
 
               if (!FAIL_STACK_EMPTY ())
                 { /* More failure points to try.  */
@@ -5075,7 +5121,7 @@
                       best_regs_set = true;
                       match_end = d;
 
-                      DEBUG_PRINT1 ("\nSAVING match as best so far.\n");
+                      DEBUG_MATCH_PRINT1 ("\nSAVING match as best so far.\n");
 
                       for (mcnt = 1; mcnt < num_regs; mcnt++)
                         {
@@ -5097,7 +5143,7 @@
                      For example, the pattern `x.*y.*z' against the
                      strings `x-' and `y-z-', if the two strings are
                      not consecutive in memory.  */
-                  DEBUG_PRINT1 ("Restoring best registers.\n");
+                  DEBUG_MATCH_PRINT1 ("Restoring best registers.\n");
 
                   d = match_end;
                   dend = ((d >= string1 && d <= end1)
@@ -5112,7 +5158,7 @@
             } /* d != end_match_2 */
 
 	succeed_label:
-          DEBUG_PRINT1 ("Accepting match.\n");
+          DEBUG_MATCH_PRINT1 ("Accepting match.\n");
 
           /* If caller wants register contents data back, do it.  */
 	  {
@@ -5214,16 +5260,16 @@
 	      for (mcnt = num_nonshy_regs; mcnt < regs->num_regs; mcnt++)
 		regs->start[mcnt] = regs->end[mcnt] = -1;
 	  }
-          DEBUG_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
+          DEBUG_MATCH_PRINT4 ("%u failure points pushed, %u popped (%u remain).\n",
                         nfailure_points_pushed, nfailure_points_popped,
                         nfailure_points_pushed - nfailure_points_popped);
-          DEBUG_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
+          DEBUG_MATCH_PRINT2 ("%u registers pushed.\n", num_regs_pushed);
 
           mcnt = d - pos - (MATCHING_IN_FIRST_STRING
 			    ? string1
 			    : string2 - size1);
 
-          DEBUG_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("Returning %d from re_match_2.\n", mcnt);
 
           FREE_VARIABLES ();
           return mcnt;
@@ -5235,11 +5281,11 @@
         /* Ignore these.  Used to ignore the n of succeed_n's which
            currently have n == 0.  */
         case no_op:
-          DEBUG_PRINT1 ("EXECUTING no_op.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING no_op.\n");
           break;
 
 	case succeed:
-          DEBUG_PRINT1 ("EXECUTING succeed.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING succeed.\n");
 	  goto succeed_label;
 
         /* Match exactly a string of length n in the pattern.  The
@@ -5248,7 +5294,7 @@
            the default internal format.) */
 	case exactn:
 	  mcnt = *p++;
-          DEBUG_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING exactn %d.\n", mcnt);
 
           /* This is written out as an if-else so we don't waste time
              testing `translate' inside the loop.  */
@@ -5321,7 +5367,7 @@
 
         /* Match any character except possibly a newline or a null.  */
 	case anychar:
-          DEBUG_PRINT1 ("EXECUTING anychar.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING anychar.\n");
 
           REGEX_PREFETCH ();
 
@@ -5333,7 +5379,7 @@
 	    goto fail;
 
           SET_REGS_MATCHED ();
-          DEBUG_PRINT2 ("  Matched `%d'.\n", *d);
+          DEBUG_MATCH_PRINT2 ("  Matched `%d'.\n", *d);
 	  INC_IBYTEPTR_FMT (d, fmt); /* XEmacs change */
 	  break;
 
@@ -5344,7 +5390,7 @@
 	    REGISTER Ichar c;
 	    re_bool not_p = (re_opcode_t) *(p - 1) == charset_not;
 
-            DEBUG_PRINT2 ("EXECUTING charset%s.\n", not_p ? "_not" : "");
+            DEBUG_MATCH_PRINT2 ("EXECUTING charset%s.\n", not_p ? "_not" : "");
 
 	    REGEX_PREFETCH ();
 	    c = itext_ichar_fmt (d, fmt, lispobj);
@@ -5372,7 +5418,7 @@
 	    REGISTER Ichar c;
 	    re_bool not_p = (re_opcode_t) *(p - 1) == charset_mule_not;
 
-            DEBUG_PRINT2 ("EXECUTING charset_mule%s.\n", not_p ? "_not" : "");
+            DEBUG_MATCH_PRINT2 ("EXECUTING charset_mule%s.\n", not_p ? "_not" : "");
 
 	    REGEX_PREFETCH ();
 	    c = itext_ichar_fmt (d, fmt, lispobj);
@@ -5398,7 +5444,7 @@
            matched within the group is recorded (in the internal
            registers data structure) under the register number.  */
         case start_memory:
-	  DEBUG_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
+	  DEBUG_MATCH_PRINT3 ("EXECUTING start_memory %d (%d):\n", *p, p[1]);
 
           /* Find out if this group can match the empty string.  */
 	  p1 = p;		/* To send to group_match_null_string_p.  */
@@ -5407,7 +5453,7 @@
 	    REG_MATCH_NULL_STRING_P (reg_info[*p])
 	      = group_match_null_string_p (&p1, pend, reg_info);
 
-	  DEBUG_PRINT2 ("  group CAN%s match null string\n",
+	  DEBUG_MATCH_PRINT2 ("  group CAN%s match null string\n",
 			REG_MATCH_NULL_STRING_P (reg_info[*p]) ? "NOT" : "");
 
           /* Save the position in the string where we were the last time
@@ -5418,11 +5464,11 @@
           old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
                              ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
                              : regstart[*p];
-	  DEBUG_PRINT2 ("  old_regstart: %d\n",
+	  DEBUG_MATCH_PRINT2 ("  old_regstart: %d\n",
 			 POINTER_TO_OFFSET (old_regstart[*p]));
 
           regstart[*p] = d;
-	  DEBUG_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
+	  DEBUG_MATCH_PRINT2 ("  regstart: %d\n", POINTER_TO_OFFSET (regstart[*p]));
 
           IS_ACTIVE (reg_info[*p]) = 1;
           MATCHED_SOMETHING (reg_info[*p]) = 0;
@@ -5449,7 +5495,7 @@
            arguments are the same as start_memory's: the register
            number, and the number of inner groups.  */
 	case stop_memory:
-	  DEBUG_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
+	  DEBUG_MATCH_PRINT3 ("EXECUTING stop_memory %d (%d):\n", *p, p[1]);
 
           /* We need to save the string position the last time we were at
              this close-group operator in case the group is operated
@@ -5459,11 +5505,11 @@
           old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
                            ? REG_UNSET (regend[*p]) ? d : regend[*p]
 			   : regend[*p];
-	  DEBUG_PRINT2 ("      old_regend: %d\n",
+	  DEBUG_MATCH_PRINT2 ("      old_regend: %d\n",
 			 POINTER_TO_OFFSET (old_regend[*p]));
 
           regend[*p] = d;
-	  DEBUG_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
+	  DEBUG_MATCH_PRINT2 ("      regend: %d\n", POINTER_TO_OFFSET (regend[*p]));
 
           /* This register isn't active anymore.  */
           IS_ACTIVE (reg_info[*p]) = 0;
@@ -5599,7 +5645,7 @@
 	    REGISTER re_char *d2, *dend2;
 	    /* Get which register to match against.  */
 	    int regno = *p++;
-	    DEBUG_PRINT2 ("EXECUTING duplicate %d.\n", regno);
+	    DEBUG_MATCH_PRINT2 ("EXECUTING duplicate %d.\n", regno);
 
 	    /* Can't back reference a group which we've never matched.  */
             if (REG_UNSET (regstart[regno]) || REG_UNSET (regend[regno]))
@@ -5666,7 +5712,7 @@
            (unless `not_bol' is set in `bufp'), and, if
            `newline_anchor' is set, after newlines.  */
 	case begline:
-          DEBUG_PRINT1 ("EXECUTING begline.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING begline.\n");
 
           if (AT_STRINGS_BEG (d))
             {
@@ -5686,7 +5732,7 @@
 
         /* endline is the dual of begline.  */
 	case endline:
-          DEBUG_PRINT1 ("EXECUTING endline.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING endline.\n");
 
           if (AT_STRINGS_END (d))
             {
@@ -5706,7 +5752,7 @@
 
 	/* Match at the very beginning of the data.  */
         case begbuf:
-          DEBUG_PRINT1 ("EXECUTING begbuf.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING begbuf.\n");
           if (AT_STRINGS_BEG (d))
             break;
           goto fail;
@@ -5714,7 +5760,7 @@
 
 	/* Match at the very end of the data.  */
         case endbuf:
-          DEBUG_PRINT1 ("EXECUTING endbuf.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING endbuf.\n");
 	  if (AT_STRINGS_END (d))
 	    break;
           goto fail;
@@ -5737,10 +5783,10 @@
            `anychar's code to do something besides goto fail in this
            case; that seems worse than this.  */
         case on_failure_keep_string_jump:
-          DEBUG_PRINT1 ("EXECUTING on_failure_keep_string_jump");
+          DEBUG_MATCH_PRINT1 ("EXECUTING on_failure_keep_string_jump");
 
           EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT3 (" %d (to 0x%lx):\n", mcnt, (long) (p + mcnt));
+          DEBUG_MATCH_PRINT3 (" %d (to 0x%lx):\n", mcnt, (long) (p + mcnt));
 
           PUSH_FAILURE_POINT (p + mcnt, (unsigned char *) 0, -2);
           break;
@@ -5760,10 +5806,10 @@
            pop_failure_jump back to this on_failure_jump.  */
 	case on_failure_jump:
         on_failure:
-          DEBUG_PRINT1 ("EXECUTING on_failure_jump");
+          DEBUG_MATCH_PRINT1 ("EXECUTING on_failure_jump");
 
           EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT3 (" %d (to 0x%lx)", mcnt, (long) (p + mcnt));
+          DEBUG_MATCH_PRINT3 (" %d (to 0x%lx)", mcnt, (long) (p + mcnt));
 
           /* If this on_failure_jump comes right before a group (i.e.,
              the original * applied to a group), save the information
@@ -5794,7 +5840,7 @@
                 lowest_active_reg = *(p1 + 1);
             }
 
-          DEBUG_PRINT1 (":\n");
+          DEBUG_MATCH_PRINT1 (":\n");
           PUSH_FAILURE_POINT (p + mcnt, d, -2);
           break;
 
@@ -5803,7 +5849,7 @@
 	   We change it to either `pop_failure_jump' or `jump'.  */
         case maybe_pop_jump:
           EXTRACT_NUMBER_AND_INCR (mcnt, p);
-          DEBUG_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING maybe_pop_jump %d.\n", mcnt);
           {
 	    REGISTER unsigned char *p2 = p;
 
@@ -5849,7 +5895,7 @@
 		   against ":/".  I don't really understand this code
 		   yet.  */
   	        p[-3] = (unsigned char) pop_failure_jump;
-                DEBUG_PRINT1
+                DEBUG_MATCH_PRINT1
                   ("  End of pattern: change to `pop_failure_jump'.\n");
               }
 
@@ -5862,7 +5908,7 @@
                 if ((re_opcode_t) p1[3] == exactn && p1[5] != c)
                   {
   		    p[-3] = (unsigned char) pop_failure_jump;
-                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+                    DEBUG_MATCH_PRINT3 ("  %c != %c => pop_failure_jump.\n",
                                   c, p1[5]);
                   }
 
@@ -5880,7 +5926,7 @@
 		    if (!not_p)
                       {
   		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                        DEBUG_MATCH_PRINT1 ("  No match => pop_failure_jump.\n");
                       }
 		  }
 	      }
@@ -5897,7 +5943,7 @@
                               & (1 << (p1[5] % BYTEWIDTH)))))
                   {
   		    p[-3] = (unsigned char) pop_failure_jump;
-                    DEBUG_PRINT3 ("  %c != %c => pop_failure_jump.\n",
+                    DEBUG_MATCH_PRINT3 ("  %c != %c => pop_failure_jump.\n",
                                   c, p1[5]);
                   }
 
@@ -5915,7 +5961,7 @@
 		    if (idx == p2[1])
                       {
   		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                        DEBUG_MATCH_PRINT1 ("  No match => pop_failure_jump.\n");
                       }
 		  }
 		else if ((re_opcode_t) p1[3] == charset)
@@ -5932,7 +5978,7 @@
 		    if (idx == p2[1] || idx == p1[4])
                       {
   		        p[-3] = (unsigned char) pop_failure_jump;
-                        DEBUG_PRINT1 ("  No match => pop_failure_jump.\n");
+                        DEBUG_MATCH_PRINT1 ("  No match => pop_failure_jump.\n");
                       }
 		  }
 	      }
@@ -5941,7 +5987,7 @@
 	  if ((re_opcode_t) p[-1] != pop_failure_jump)
 	    {
 	      p[-1] = (unsigned char) jump;
-              DEBUG_PRINT1 ("  Match => jump.\n");
+              DEBUG_MATCH_PRINT1 ("  Match => jump.\n");
 	      goto unconditional_jump;
 	    }
         /* Note fall through.  */
@@ -5964,7 +6010,7 @@
             unsigned char *pdummy;
             re_char *sdummy = NULL;
 
-            DEBUG_PRINT1 ("EXECUTING pop_failure_jump.\n");
+            DEBUG_MATCH_PRINT1 ("EXECUTING pop_failure_jump.\n");
             POP_FAILURE_POINT (sdummy, pdummy,
                                dummy_low_reg, dummy_high_reg,
                                reg_dummy, reg_dummy, reg_info_dummy);
@@ -5976,16 +6022,16 @@
         case jump:
 	unconditional_jump:
 	  EXTRACT_NUMBER_AND_INCR (mcnt, p);	/* Get the amount to jump.  */
-          DEBUG_PRINT2 ("EXECUTING jump %d ", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING jump %d ", mcnt);
 	  p += mcnt;				/* Do the jump.  */
-          DEBUG_PRINT2 ("(to 0x%lx).\n", (long) p);
+          DEBUG_MATCH_PRINT2 ("(to 0x%lx).\n", (long) p);
 	  break;
 
 
         /* We need this opcode so we can detect where alternatives end
            in `group_match_null_string_p' et al.  */
         case jump_past_alt:
-          DEBUG_PRINT1 ("EXECUTING jump_past_alt.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING jump_past_alt.\n");
           goto unconditional_jump;
 
 
@@ -5995,7 +6041,7 @@
            are skipping over the on_failure_jump, so we have to push
            something meaningless for pop_failure_jump to pop.  */
         case dummy_failure_jump:
-          DEBUG_PRINT1 ("EXECUTING dummy_failure_jump.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING dummy_failure_jump.\n");
           /* It doesn't matter what we push for the string here.  What
              the code at `fail' tests is the value for the pattern.  */
           PUSH_FAILURE_POINT ((unsigned char *) 0, (unsigned char *) 0, -2);
@@ -6008,7 +6054,7 @@
            popped.  For example, matching `(a|ab)*' against `aab'
            requires that we match the `ab' alternative.  */
         case push_dummy_failure:
-          DEBUG_PRINT1 ("EXECUTING push_dummy_failure.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING push_dummy_failure.\n");
           /* See comments just above at `dummy_failure_jump' about the
              two zeroes.  */
           PUSH_FAILURE_POINT ((unsigned char *) 0, (unsigned char *) 0, -2);
@@ -6018,7 +6064,7 @@
            After that, handle like `on_failure_jump'.  */
         case succeed_n:
           EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING succeed_n %d.\n", mcnt);
 
           assert (mcnt >= 0);
           /* Originally, this is how many times we HAVE to succeed.  */
@@ -6027,11 +6073,11 @@
                mcnt--;
 	       p += 2;
                STORE_NUMBER_AND_INCR (p, mcnt);
-               DEBUG_PRINT3 ("  Setting 0x%lx to %d.\n", (long) p, mcnt);
+               DEBUG_MATCH_PRINT3 ("  Setting 0x%lx to %d.\n", (long) p, mcnt);
             }
 	  else if (mcnt == 0)
             {
-              DEBUG_PRINT2 ("  Setting two bytes from 0x%lx to no_op.\n",
+              DEBUG_MATCH_PRINT2 ("  Setting two bytes from 0x%lx to no_op.\n",
 			    (long) (p+2));
 	      p[2] = (unsigned char) no_op;
               p[3] = (unsigned char) no_op;
@@ -6041,7 +6087,7 @@
 
         case jump_n:
           EXTRACT_NUMBER (mcnt, p + 2);
-          DEBUG_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING jump_n %d.\n", mcnt);
 
           /* Originally, this is how many times we CAN jump.  */
           if (mcnt)
@@ -6057,18 +6103,18 @@
 
 	case set_number_at:
 	  {
-            DEBUG_PRINT1 ("EXECUTING set_number_at.\n");
+            DEBUG_MATCH_PRINT1 ("EXECUTING set_number_at.\n");
 
             EXTRACT_NUMBER_AND_INCR (mcnt, p);
             p1 = p + mcnt;
             EXTRACT_NUMBER_AND_INCR (mcnt, p);
-            DEBUG_PRINT3 ("  Setting 0x%lx to %d.\n", (long) p1, mcnt);
+            DEBUG_MATCH_PRINT3 ("  Setting 0x%lx to %d.\n", (long) p1, mcnt);
 	    STORE_NUMBER (p1, mcnt);
             break;
           }
 
         case wordbound:
-          DEBUG_PRINT1 ("EXECUTING wordbound.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING wordbound.\n");
 	  should_succeed = 1;
 	matchwordbound:
 	  {
@@ -6138,12 +6184,12 @@
 	  }
 
 	case notwordbound:
-          DEBUG_PRINT1 ("EXECUTING notwordbound.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING notwordbound.\n");
 	  should_succeed = 0;
 	  goto matchwordbound;
 
 	case wordbeg:
-          DEBUG_PRINT1 ("EXECUTING wordbeg.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING wordbeg.\n");
 	  if (AT_STRINGS_END (d))
 	    goto fail;
 	  {
@@ -6186,7 +6232,7 @@
 	  }
 
 	case wordend:
-          DEBUG_PRINT1 ("EXECUTING wordend.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING wordend.\n");
 	  if (AT_STRINGS_BEG (d))
 	    goto fail;
 	  {
@@ -6235,7 +6281,7 @@
 
 #ifdef emacs
   	case before_dot:
-          DEBUG_PRINT1 ("EXECUTING before_dot.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING before_dot.\n");
  	  if (!BUFFERP (lispobj)
 	      || (BUF_PTR_BYTE_POS (XBUFFER (lispobj), (unsigned char *) d)
 		  >= BUF_PT (XBUFFER (lispobj))))
@@ -6243,7 +6289,7 @@
   	  break;
 
   	case at_dot:
-          DEBUG_PRINT1 ("EXECUTING at_dot.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING at_dot.\n");
  	  if (!BUFFERP (lispobj)
 	      || (BUF_PTR_BYTE_POS (XBUFFER (lispobj), (unsigned char *) d)
 		  != BUF_PT (XBUFFER (lispobj))))
@@ -6251,7 +6297,7 @@
   	  break;
 
   	case after_dot:
-          DEBUG_PRINT1 ("EXECUTING after_dot.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING after_dot.\n");
  	  if (!BUFFERP (lispobj)
 	      || (BUF_PTR_BYTE_POS (XBUFFER (lispobj), (unsigned char *) d)
 		  <= BUF_PT (XBUFFER (lispobj))))
@@ -6259,12 +6305,12 @@
   	  break;
 
 	case syntaxspec:
-          DEBUG_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING syntaxspec %d.\n", mcnt);
 	  mcnt = *p++;
 	  goto matchsyntax;
 
         case wordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs wordchar.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING Emacs wordchar.\n");
 	  mcnt = (int) Sword;
         matchsyntax:
 	  should_succeed = 1;
@@ -6294,12 +6340,12 @@
 	  break;
 
 	case notsyntaxspec:
-          DEBUG_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
+          DEBUG_MATCH_PRINT2 ("EXECUTING notsyntaxspec %d.\n", mcnt);
 	  mcnt = *p++;
 	  goto matchnotsyntax;
 
         case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING Emacs notwordchar.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING Emacs notwordchar.\n");
 	  mcnt = (int) Sword;
         matchnotsyntax:
 	  should_succeed = 0;
@@ -6331,7 +6377,7 @@
 #endif /* MULE */
 #else /* not emacs */
 	case wordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING non-Emacs wordchar.\n");
 	  REGEX_PREFETCH ();
           if (!WORDCHAR_P ((int) (*d)))
             goto fail;
@@ -6340,7 +6386,7 @@
 	  break;
 
 	case notwordchar:
-          DEBUG_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
+          DEBUG_MATCH_PRINT1 ("EXECUTING non-Emacs notwordchar.\n");
 	  REGEX_PREFETCH ();
           if (!WORDCHAR_P ((int) (*d)))
             goto fail;
@@ -6359,7 +6405,7 @@
     fail:
       if (!FAIL_STACK_EMPTY ())
 	{ /* A restart point is known.  Restore to that state.  */
-          DEBUG_PRINT1 ("\nFAIL:\n");
+          DEBUG_MATCH_PRINT1 ("\nFAIL:\n");
           POP_FAILURE_POINT (d, p,
                              lowest_active_reg, highest_active_reg,
                              regstart, regend, reg_info);
--- a/src/regex.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/regex.h	Sat Feb 20 23:56:01 2010 -0600
@@ -2,7 +2,7 @@
    expression library, version 0.12.
 
    Copyright (C) 1985, 89, 90, 91, 92, 93, 95 Free Software Foundation, Inc.
-   Copyright (C) 2002 Ben Wing.
+   Copyright (C) 2002, 2010 Ben Wing.
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -526,4 +526,13 @@
 		 size_t errbuf_size);
 void regfree (regex_t *preg);
 
+enum regex_debug
+  {
+    RE_DEBUG_COMPILATION = 1 << 0,
+    RE_DEBUG_FAILURE_POINT = 1 << 1,
+    RE_DEBUG_MATCHING = 1 << 2,
+  };
+
+extern int debug_regexps;
+
 #endif /* INCLUDED_regex_h_ */
--- a/src/search.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/search.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* String search routines for XEmacs.
    Copyright (C) 1985, 1986, 1987, 1992-1995 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 2001, 2002 Ben Wing.
+   Copyright (C) 2001, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -50,10 +50,17 @@
 #ifdef DEBUG_XEMACS
 
 /* Used in tests/automated/case-tests.el if available. */
-Fixnum debug_xemacs_searches;
+Fixnum debug_searches;
+
+/* Declare as int rather than Bitflags because it's used by regex.c, which
+   may be used outside of XEmacs (e.g. etags.c). */
+int debug_regexps;
+Lisp_Object Vdebug_regexps;
 
 Lisp_Object Qsearch_algorithm_used, Qboyer_moore, Qsimple_search;
 
+Lisp_Object Qcompilation, Qfailure_point, Qmatching;
+
 #endif
 
 /* If the regexp is non-nil, then the buffer contains the compiled form
@@ -1461,7 +1468,7 @@
               if (!checked)
                 {
 #ifdef DEBUG_XEMACS
-                  if (debug_xemacs_searches)
+                  if (debug_searches)
                     {
                       Lisp_Symbol *sym = XSYMBOL (Qsearch_algorithm_used);
                       sym->value = Qnil;
@@ -1527,7 +1534,7 @@
       pat = base_pat = patbuf;
 
 #ifdef DEBUG_XEMACS
-      if (debug_xemacs_searches)
+      if (debug_searches)
         {
           Lisp_Symbol *sym = XSYMBOL (Qsearch_algorithm_used);
           sym->value = boyer_moore_ok ? Qboyer_moore : Qsimple_search;
@@ -3333,6 +3340,35 @@
 }
 
 
+#ifdef DEBUG_XEMACS
+
+static int
+debug_regexps_changed (Lisp_Object UNUSED (sym), Lisp_Object *val,
+		       Lisp_Object UNUSED (in_object),
+		       int UNUSED (flags))
+{
+  int newval = 0;
+
+  EXTERNAL_LIST_LOOP_2 (elt, *val)
+    {
+      CHECK_SYMBOL (elt);
+      if (EQ (elt, Qcompilation))
+	newval |= RE_DEBUG_COMPILATION;
+      else if (EQ (elt, Qfailure_point))
+	newval |= RE_DEBUG_FAILURE_POINT;
+      else if (EQ (elt, Qmatching))
+	newval |= RE_DEBUG_MATCHING;
+      else
+	invalid_argument
+	  ("Expected `compilation', `failure-point' or `matching'", elt);
+    }
+  debug_regexps = newval;
+  return 0;
+}
+
+#endif /* DEBUG_XEMACS */
+
+
 /************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
@@ -3421,10 +3457,26 @@
   DEFSYMBOL (Qboyer_moore);
   DEFSYMBOL (Qsimple_search);
 
-  DEFVAR_INT ("debug-xemacs-searches", &debug_xemacs_searches /*
+  DEFSYMBOL (Qcompilation);
+  DEFSYMBOL (Qfailure_point);
+  DEFSYMBOL (Qmatching);
+
+  DEFVAR_INT ("debug-searches", &debug_searches /*
 If non-zero, bind `search-algorithm-used' to `boyer-moore' or `simple-search',
 depending on the algorithm used for each search.  Used for testing.
 */ );
-  debug_xemacs_searches = 0;
-#endif 
+  debug_searches = 0;
+
+  DEFVAR_LISP_MAGIC ("debug-regexps", &Vdebug_regexps, /*
+List of areas to display debug info about during regexp operation.
+The following areas are recognized:
+
+`compilation'    Display the result of compiling a regexp.
+`failure-point'	 Display info about failure points reached.
+`matching'	 Display info about the process of matching a regex against
+                 text.
+*/ debug_regexps_changed);
+  Vdebug_regexps = Qnil;
+  debug_regexps = 0;
+#endif /* DEBUG_XEMACS */
 }
--- a/src/signal.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/signal.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,6 +1,6 @@
 /* Handling asynchronous signals.
    Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 1995, 1996, 2001, 2002, 2004 Ben Wing.
+   Copyright (C) 1995, 1996, 2001, 2002, 2004, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -727,7 +727,7 @@
 
 Backtrace given in
 
-  (Info-goto-node "(internals)Nasty Bugs due to Reentrancy in Redisplay Structures handling QUIT")
+  (Info-goto-node "(internals)Critical Redisplay Sections")
 
     */
       assert_with_message
--- a/src/syntax.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/syntax.c	Sat Feb 20 23:56:01 2010 -0600
@@ -31,12 +31,6 @@
 #include "syntax.h"
 #include "extents.h"
 
-#ifdef NEW_GC
-# define UNUSED_IF_NEW_GC(decl) UNUSED (decl)
-#else
-# define UNUSED_IF_NEW_GC(decl) decl
-#endif
-
 #define ST_COMMENT_STYLE 0x101
 #define ST_STRING_STYLE  0x102
 
--- a/src/sysdep.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/sysdep.c	Sat Feb 20 23:56:01 2010 -0600
@@ -108,12 +108,6 @@
 
 #endif
 
-#ifdef HAVE_TTY
-#define USED_IF_TTY(decl) decl
-#else
-#define USED_IF_TTY(decl) UNUSED (decl)
-#endif
-
 
 /************************************************************************/
 /*                         subprocess control                           */
--- a/src/syswindows.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/syswindows.h	Sat Feb 20 23:56:01 2010 -0600
@@ -130,6 +130,30 @@
     In fact, in general, it's possible to compile with support for all of
     these at the same time.
 
+
+
+   Here is a table mapping from GNU Emacs constants to XEmacs constants for
+   use in porting code.
+ 
+
+   Old Constant       New Constant
+   ---------------------------------------------------------------
+   `WINDOWSNT'        `WIN32_NATIVE'
+   `WIN32'            `WIN32_NATIVE'
+   `_WIN32'           `WIN32_NATIVE'
+   `HAVE_WIN32'       `WIN32_NATIVE'
+   `DOS_NT'           `WIN32_NATIVE'
+   `HAVE_NTGUI'       `WIN32_NATIVE', unless it ends up already bracketed
+                      by this
+   `HAVE_FACES'       always true
+   `MSDOS'            determine whether this code is really specific to
+                      MS-DOS (and not Windows - e.g. DJGPP code); if so,
+                      delete the code; otherwise, convert to `WIN32_NATIVE'
+                      (we do not support MS-DOS w/DOS Extender under XEmacs)
+   `__CYGWIN__'       `CYGWIN'
+   `__CYGWIN32__'     `CYGWIN'
+   `__MINGW32__'      `MINGW'
+
 */
 
 /* ------------------------- Basic includes ------------------------- */
--- a/src/tests.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/tests.c	Sat Feb 20 23:56:01 2010 -0600
@@ -682,7 +682,7 @@
   FROB (0XFFFFFFFFFFFFFFFE);
 #endif /* INT_VALBITS >= 63 */
 
-  return list3 (build_ascstring ("STORE_VOID_IN_LISP"), Qt, Qnil);
+  return list1 (list3 (build_ascstring ("STORE_VOID_IN_LISP"), Qt, Qnil));
 }
 
 
--- a/src/toolbar.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/toolbar.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,7 +1,7 @@
 /* Generic toolbar implementation.
    Copyright (C) 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 1995, 1996, 2003, 2004 Ben Wing.
+   Copyright (C) 1995, 1996, 2003, 2004, 2010 Ben Wing.
    Copyright (C) 1996 Chuck Thompson.
 
 This file is part of XEmacs.
@@ -780,15 +780,9 @@
       if (frame_size_changed)
 	{
 	  int width, height;
-	  if (!window_system_pixelated_geometry (wrap_frame (f)))
-	    pixel_to_char_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
-				&width, &height);
-	  else
-	    width = FRAME_PIXWIDTH (f), height = FRAME_PIXHEIGHT (f);
-	  if (!HAS_FRAMEMETH_P (f, set_frame_size))
-	    change_frame_size (f, height, width, 0);
-	  else
-	    FRAMEMETH (f, set_frame_size, (f, width, height));
+	  pixel_to_frame_unit_size (f, FRAME_PIXWIDTH (f), FRAME_PIXHEIGHT (f),
+				   &width, &height);
+	  internal_set_frame_size (f, width, height, 0);
 	  MARK_FRAME_LAYOUT_CHANGED (f);
 	}
       
--- a/src/vdb-win32.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/vdb-win32.c	Sat Feb 20 23:56:01 2010 -0600
@@ -29,7 +29,7 @@
 #include "syswindows.h"
 
 
-LONG WINAPI 
+static LONG WINAPI 
 win32_fault_handler (LPEXCEPTION_POINTERS e)
 {
 #define GET_FAULT_ADDRESS (void *) e->ExceptionRecord->ExceptionInformation[1]
--- a/src/vdb.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/vdb.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1,5 +1,6 @@
 /* Virtual diry bit implementation (platform independent) for XEmacs.
    Copyright (C) 2005 Marcus Crestani.
+   Copyright (C) 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -74,6 +75,8 @@
 
 /* For testing and debugging... */
 
+#ifdef DEBUG_XEMACS
+
 DEFUN ("test-vdb", Ftest_vdb, 0, 0, "", /*
 Test virtual dirty bit implementation. Prints results to stderr.
 */
@@ -148,9 +151,13 @@
   return Qnil;
 }
 
+#endif /* DEBUG_XEMACS */
+
 void
 syms_of_vdb (void)
 {
+#ifdef DEBUG_XEMACS
   DEFSUBR (Ftest_vdb);
   DEFSUBR (Ftest_segfault);
+#endif /* DEBUG_XEMACS */
 }
--- a/src/window.c	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/window.c	Sat Feb 20 23:56:01 2010 -0600
@@ -1175,7 +1175,7 @@
   margin_cwidth = (left_margin ? XINT (w->left_margin_width) :
 		   XINT (w->right_margin_width));
 
-  default_face_height_and_width (window, 0, &font_width);
+  default_face_width_and_height (window, &font_width, 0);
 
   /* The left margin takes precedence over the right margin so we
      subtract its width from the space available for the right
@@ -1658,7 +1658,7 @@
   hlimit = WINDOW_TEXT_HEIGHT (w);
   eobuf  = BUF_ZV (XBUFFER (w->buffer));
 
-  default_face_height_and_width (window, &defheight, NULL);
+  default_face_width_and_height (window, NULL, &defheight);
 
   /* guess lines needed in line start cache + a few extra */
   needed = (hlimit + defheight-1) / defheight + 3;
@@ -3477,8 +3477,8 @@
 
 /* Return non-zero if both frame sizes are less than or equal to
    minimal allowed values. ROWS and COLS are in characters */
-int
-frame_size_valid_p (struct frame *frame, int rows, int cols)
+static int
+frame_size_valid_p (struct frame *frame, int cols, int rows)
 {
   return (rows >= frame_min_height (frame)
 	  && cols >= MIN_SAFE_WINDOW_WIDTH);
@@ -3490,21 +3490,30 @@
 frame_pixsize_valid_p (struct frame *frame, int width, int height)
 {
   int rows, cols;
-  pixel_to_real_char_size (frame, width, height, &cols, &rows);
-  return frame_size_valid_p (frame, rows, cols);
+  pixel_to_char_size (frame, width, height, &cols, &rows);
+  return frame_size_valid_p (frame, cols, rows);
 }
 
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 void
-check_frame_size (struct frame *frame, int *rows, int *cols)
+check_frame_size (struct frame *frame, int *cols, int *rows)
 {
   int min_height = frame_min_height (frame);
-
-  if (*rows < min_height)
-    *rows = min_height;
-  if (*cols  < MIN_SAFE_WINDOW_WIDTH)
-    *cols = MIN_SAFE_WINDOW_WIDTH;
+  int min_pixwidth, min_pixheight;
+  int min_geomwidth, min_geomheight;
+
+  /* There is no char_to_frame_unit_size().  This can be done with
+     frame_conversion_internal(), but that's currently static, and we can
+     do it fine with two steps, as follows. */
+  char_to_pixel_size (frame, MIN_SAFE_WINDOW_WIDTH, min_height,
+		      &min_pixwidth, &min_pixheight);
+  pixel_to_frame_unit_size (frame, min_pixwidth, min_pixheight,
+			   &min_geomwidth, &min_geomheight);
+  if (*rows < min_geomheight)
+    *rows = min_geomheight;
+  if (*cols  < min_geomwidth)
+    *cols = min_geomwidth;
 }
 
 /* Normally the window is deleted if it gets too small.
@@ -3523,7 +3532,7 @@
   int line_size;
   int defheight, defwidth;
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
   line_size = (set_height ? defheight : defwidth);
 
   check_min_window_sizes ();
@@ -4127,7 +4136,7 @@
 		   window_top_window_gutter_height (w) +
 		   window_bottom_window_gutter_height (w)));
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   if (defheight)
     char_height = avail_height / defheight;
@@ -4151,7 +4160,7 @@
   Lisp_Object window = wrap_window (w);
 
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   avail_height = char_height * defheight;
   pixel_height = (avail_height +
@@ -4231,7 +4240,7 @@
 	    }
 	}
 
-      default_face_height_and_width (window, &defheight, &defwidth);
+      default_face_width_and_height (window, &defwidth, &defheight);
       /* #### This probably needs to know about the clipping area once a
          final definition is decided on. */
       if (defheight)
@@ -4274,7 +4283,7 @@
 		 (include_margins_p ? 0 : window_left_margin_width (w)) -
 		 (include_margins_p ? 0 : window_right_margin_width (w)));
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   if (defwidth) 
     char_width = (avail_width / defwidth);
@@ -4297,7 +4306,7 @@
   Lisp_Object window = wrap_window (w);
 
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   avail_width = char_width * defwidth;
   pixel_width = (avail_width +
@@ -4380,7 +4389,7 @@
   if (EQ (window, FRAME_ROOT_WINDOW (f)))
     invalid_operation ("Won't change only window", Qunbound);
 
-  default_face_height_and_width (window, &defheight, &defwidth);
+  default_face_width_and_height (window, &defwidth, &defheight);
 
   while (1)
     {
@@ -4609,7 +4618,7 @@
   if (INTP (Vwindow_pixel_scroll_increment))
     fheight = XINT (Vwindow_pixel_scroll_increment);
   else if (!NILP (Vwindow_pixel_scroll_increment))
-    default_face_height_and_width (window, &fheight, &fwidth);
+    default_face_width_and_height (window, &fwidth, &fheight);
 
   if (Dynarr_length (dla) >= 1)
     modeline = Dynarr_begin (dla)->modeline;
--- a/src/window.h	Sat Feb 20 18:57:55 2010 -0600
+++ b/src/window.h	Sat Feb 20 23:56:01 2010 -0600
@@ -2,7 +2,7 @@
    Copyright (C) 1985, 1986, 1992, 1993, 1994, 1995
    Free Software Foundation, Inc.
    Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
-   Copyright (C) 1995, 1996, 2002 Ben Wing.
+   Copyright (C) 1995, 1996, 2002, 2010 Ben Wing.
    Copyright (C) 1996 Chuck Thompson.
 
 This file is part of XEmacs.
@@ -148,9 +148,8 @@
 		    Error_Behavior errb);
 int buffer_window_count (struct buffer *b, struct frame *f);
 int buffer_window_mru (struct window *w);
-void check_frame_size (struct frame *frame, int *rows, int *cols);
+void check_frame_size (struct frame *frame, int *cols, int *rows);
 int frame_pixsize_valid_p (struct frame *frame, int width, int height);
-int frame_size_valid_p (struct frame *frame, int rows, int cols);
 struct window *decode_window (Lisp_Object window);
 struct window *find_window_by_pixel_pos (int pix_x, int pix_y, Lisp_Object win);
 
--- a/tests/ChangeLog	Sat Feb 20 18:57:55 2010 -0600
+++ b/tests/ChangeLog	Sat Feb 20 23:56:01 2010 -0600
@@ -1,3 +1,30 @@
+2010-02-15  Ben Wing  <ben@xemacs.org>
+
+	* automated/search-tests.el (let):
+	* automated/search-tests.el (boundp):
+	debug-xemacs-searches renamed to debug-searches.
+
+2010-02-20  Ben Wing  <ben@xemacs.org>
+
+	* automated/test-harness.el:
+	* automated/test-harness.el (test-harness-bug-expected): New.
+	* automated/test-harness.el (test-harness-unexpected-error-enter-debugger): New.
+	* automated/test-harness.el (test-harness-assertion-failure-enter-debugger): New.
+	* automated/test-harness.el (test-harness-unexpected-error-show-backtrace): New.
+	* automated/test-harness.el (test-harness-assertion-failure-show-backtrace): New.
+	* automated/test-harness.el (test-harness-assertion-failure-do-debug): New.
+	* automated/test-harness.el (test-harness-unexpected-error-do-debug): New.
+	* automated/test-harness.el (test-harness-unexpected-error-condition-handler): New.
+	* automated/test-harness.el (test-harness-error-wrap): New.
+	* automated/test-harness.el (test-harness-from-buffer):
+	New variables that allow a backtrace to be displayed and/or the
+	debugger to be entered when an assertion failure or unexpected error
+	occurs.  By default, debugging occurs when interactive and debug-on-error
+	is set, and backtrace-displaying occurs either
+	(a) when stack-trace-on-error is set, or (b) always, when an unexpected
+	error occurs. (However, no backtracing or debugging occurs when a bug
+	is expected.)
+
 2010-02-19  Aidan Kehoe  <kehoea@parhasard.net>
 
 	* automated/lisp-tests.el:
--- a/tests/automated/search-tests.el	Sat Feb 20 18:57:55 2010 -0600
+++ b/tests/automated/search-tests.el	Sat Feb 20 23:56:01 2010 -0600
@@ -166,7 +166,7 @@
 
 (with-temp-buffer
   (let ((target "M\xe9zard")
-        (debug-xemacs-searches 1))
+        (debug-searches 1))
     (Assert (not (search-forward target nil t)))
     (insert target)
     (goto-char (point-min))
@@ -180,10 +180,10 @@
     (Assert= (1+ (length target)) (search-forward target nil t))))
 
 (Skip-Test-Unless
- (boundp 'debug-xemacs-searches) ; normal when we have DEBUG_XEMACS
+ (boundp 'debug-searches) ; normal when we have DEBUG_XEMACS
  "not a DEBUG_XEMACS build"
  "checks that the algorithm chosen by #'search-forward is relatively sane"
- (let ((debug-xemacs-searches 1)
+ (let ((debug-searches 1)
        newcase)
    (with-temp-buffer
      (insert "\n\nDer beruehmte deutsche Fleiss\n\n")
--- a/tests/automated/test-harness.el	Sat Feb 20 18:57:55 2010 -0600
+++ b/tests/automated/test-harness.el	Sat Feb 20 23:56:01 2010 -0600
@@ -70,6 +70,9 @@
 ;; Declared for dynamic scope; _do not_ initialize here.
 (defvar unexpected-test-file-failures)
 
+(defvar test-harness-bug-expected nil
+  "Non-nil means a bug is expected; backtracing/debugging should not happen.")
+
 (defvar test-harness-test-compiled nil
   "Non-nil means the test code was compiled before execution.
 
@@ -87,6 +90,31 @@
   (and (not noninteractive) (> (device-baud-rate) search-slow-speed))
   "*Non-nil means print messages describing progress of emacs-tester.")
 
+(defvar test-harness-unexpected-error-enter-debugger debug-on-error
+  "*Non-nil means enter debugger when an unexpected error occurs.
+Only applies interactively.  Normally true if `debug-on-error' has been set.
+See also `test-harness-assertion-failure-enter-debugger' and
+`test-harness-unexpected-error-show-backtrace'.")
+
+(defvar test-harness-assertion-failure-enter-debugger debug-on-error
+  "*Non-nil means enter debugger when an assertion failure occurs.
+Only applies interactively.  Normally true if `debug-on-error' has been set.
+See also `test-harness-unexpected-error-enter-debugger' and
+`test-harness-assertion-failure-show-backtrace'.")
+
+(defvar test-harness-unexpected-error-show-backtrace t
+  "*Non-nil means show backtrace upon unexpected error.
+Only applies when debugger is not entered.  Normally true by default.  See also
+`test-harness-unexpected-error-enter-debugger' and
+`test-harness-assertion-failure-show-backtrace'.")
+
+(defvar test-harness-assertion-failure-show-backtrace stack-trace-on-error
+  "*Non-nil means show backtrace upon assertion failure.
+Only applies when debugger is not entered.  Normally true if
+`stack-trace-on-error' has been set.  See also
+`test-harness-assertion-failure-enter-debugger' and
+`test-harness-unexpected-error-show-backtrace'.")
+
 (defvar test-harness-file-results-alist nil
   "Each element is a list (FILE SUCCESSES TESTS).
 The order is the reverse of the order in which tests are run.
@@ -166,18 +194,88 @@
     (kill-buffer input-buffer)
     ))
 
+(defsubst test-harness-assertion-failure-do-debug (error-info)
+  "Maybe enter debugger or display a backtrace on assertion failure.
+ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'.
+The debugger will be entered if noninteractive and
+`test-harness-unexpected-error-enter-debugger' is non-nil; else, a
+backtrace will be displayed if `test-harness-unexpected-error-show-backtrace'
+is non-nil."
+  (when (not test-harness-bug-expected)
+    (cond ((and (not noninteractive)
+		test-harness-assertion-failure-enter-debugger)
+	   (funcall debugger 'error error-info))
+	  (test-harness-assertion-failure-show-backtrace
+	   (backtrace nil t)))))
+
+(defsubst test-harness-unexpected-error-do-debug (error-info)
+  "Maybe enter debugger or display a backtrace on unexpected error.
+ERROR-INFO is a cons of the args (SIG . DATA) that were passed to `signal'.
+The debugger will be entered if noninteractive and
+`test-harness-unexpected-error-enter-debugger' is non-nil; else, a
+backtrace will be displayed if `test-harness-unexpected-error-show-backtrace'
+is non-nil."
+  (when (not test-harness-bug-expected)
+    (cond ((and (not noninteractive)
+		test-harness-unexpected-error-enter-debugger)
+	   (funcall debugger 'error error-info))
+	  (test-harness-unexpected-error-show-backtrace
+	   (backtrace nil t)))))
+
+(defsubst test-harness-unexpected-error-condition-handler (error-info context-msg)
+  "Condition handler for when unexpected errors occur.
+Useful in conjunction with `call-with-condition-handler'.  ERROR-INFO is the
+value passed to the condition handler.  CONTEXT-MSG is a string indicating
+the context in which the unexpected error occurred.  A message is outputted
+including CONTEXT-MSG in it, `unexpected-test-file-failures' is incremented,
+and `test-harness-unexpected-error-do-debug' is called, which may enter the
+debugger or output a backtrace, depending on the settings of
+`test-harness-unexpected-error-enter-debugger' and
+`test-harness-unexpected-error-show-backtrace'.
+
+The function returns normally, which causes error-handling processing to
+continue; if you want to catch the error, you also need to wrap everything
+in `condition-case'.  See also `test-harness-error-wrap', which does this
+wrapping."
+  (incf unexpected-test-file-failures)
+  (princ (format "Unexpected error %S while %s\n"
+		 error-info context-msg))
+  (message "Unexpected error %S while %s." error-info context-msg)
+  (test-harness-unexpected-error-do-debug error-info))
+
+(defmacro test-harness-error-wrap (context-msg abort-msg &rest body)
+  "Wrap BODY so that unexpected errors are caught.
+The debugger will be entered if noninteractive and
+`test-harness-unexpected-error-enter-debugger' is non-nil; else, a backtrace
+will be displayed if `test-harness-unexpected-error-show-backtrace' is
+non-nil.  CONTEXT-MSG is displayed as part of a message shown before entering
+the debugger or showing a backtrace, and ABORT-MSG, if non-nil, is displayed
+afterwards.  See "
+  `(condition-case nil
+    (call-with-condition-handler
+	#'(lambda (error-info)
+	    (test-harness-unexpected-error-condition-handler
+	     error-info ,context-msg))
+	#'(lambda ()
+	    ,@body))
+    (error ,(if abort-msg `(message ,abort-msg) nil))))
+
 (defun test-harness-read-from-buffer (buffer)
   "Read forms from BUFFER, and turn it into a lambda test form."
   (let ((body nil))
     (goto-char (point-min) buffer)
-    (condition-case error-info
-	(while t
-	  (setq body (cons (read buffer) body)))
-      (end-of-file nil)
-      (error
-       (incf unexpected-test-file-failures)
-       (princ (format "Unexpected error %S reading forms from buffer\n"
-		      error-info))))
+    (condition-case nil
+	(call-with-condition-handler
+	    #'(lambda (error-info)
+		;; end-of-file is expected, so don't output error or backtrace
+		;; or enter debugger in this case.
+		(unless (eq 'end-of-file (car error-info))
+		  (test-harness-unexpected-error-condition-handler
+		   error-info "reading forms from buffer")))
+	    #'(lambda ()
+		(while t
+		  (setq body (cons (read buffer) body)))))
+      (error nil))
     `(lambda ()
        (defvar passes)
        (defvar assertion-failures)
@@ -221,7 +319,8 @@
 	"Wrap a BODY that consists of tests that are known to fail.
 This causes messages to be printed on failure indicating that this is expected,
 and on success indicating that this is unexpected."
-	`(let ((test-harness-failure-tag "KNOWN BUG")
+	`(let ((test-harness-bug-expected t)
+	       (test-harness-failure-tag "KNOWN BUG")
 	       (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
 	  ,@body))
 
@@ -231,7 +330,8 @@
 and on success indicating that this is unexpected."
 	(let ((quoted-body (if (= 1 (length body))
 			       `(quote ,(car body)) `(quote (progn ,@body)))))
-          `(let ((test-harness-failure-tag "KNOWN BUG")
+          `(let ((test-harness-bug-expected t)
+		 (test-harness-failure-tag "KNOWN BUG")
                  (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
             (condition-case error-info
                 (progn
@@ -255,7 +355,8 @@
 This causes messages to be printed on failure indicating that the
 implementation is incomplete (and hence the failure is expected); and on
 success indicating that this is unexpected."
-	`(let ((test-harness-failure-tag "IMPLEMENTATION INCOMPLETE")
+	`(let ((test-harness-bug-expected t)
+	       (test-harness-failure-tag "IMPLEMENTATION INCOMPLETE")
 	       (test-harness-success-tag "PASS (FAILURE EXPECTED)"))
 	  ,@body))
     
@@ -293,23 +394,30 @@
 is used in a loop."
 	(let ((description
 	       (or description `(quote ,assertion))))
-	  `(condition-case error-info
-	    (progn
-	      (assert ,assertion)
-	      (Print-Pass "%S" ,description)
-	      (incf passes))
-	    (cl-assertion-failed
-	     (Print-Failure (if ,failing-case
-				"Assertion failed: %S; failing case = %S"
-			      "Assertion failed: %S")
-			    ,description ,failing-case)
-	     (incf assertion-failures))
-	    (t (Print-Failure (if ,failing-case
-				  "%S ==> error: %S; failing case =  %S"
-				"%S ==> error: %S")
-			      ,description error-info ,failing-case)
-	       (incf other-failures)
-	       ))))
+	  `(condition-case nil
+	    (call-with-condition-handler
+		#'(lambda (error-info)
+		    (if (eq 'cl-assertion-failed (car error-info))
+			(progn
+			  (Print-Failure
+			   (if ,failing-case
+			       "Assertion failed: %S; failing case = %S"
+			     "Assertion failed: %S")
+			   ,description ,failing-case)
+			  (incf assertion-failures)
+			  (test-harness-assertion-failure-do-debug error-info))
+		      (Print-Failure
+		       (if ,failing-case
+			   "%S ==> error: %S; failing case =  %S"
+			 "%S ==> error: %S")
+		       ,description error-info ,failing-case)
+		      (incf other-failures)
+		      (test-harness-unexpected-error-do-debug error-info)))
+		#'(lambda ()
+		    (assert ,assertion)
+		    (Print-Pass "%S" ,description)
+		    (incf passes)))
+	    (cl-assertion-failed nil))))
 
 ;;;;; BEGIN DEFINITION OF SPECIFIC KINDS OF ASSERT MACROS
 
@@ -462,22 +570,27 @@
 		 (let ((msg-string (apply 'format (ad-get-args 0))))
 		   (setq messages (concat messages msg-string))
 		   msg-string))
-	       (condition-case error-info
-		   (progn
-		     (setq trick-optimizer (progn ,@body))
-		     (if (string-match ,expected-message-regexp messages)
-			 (progn
-			   (Print-Pass "%S ==> value %S, message %S, matching %S, as expected"
-				       ,quoted-body trick-optimizer messages ',expected-message-regexp)
-			   (incf passes))
-		       (Print-Failure "%S ==> value %S, message %S, NOT matching expected %S"
-				      ,quoted-body  trick-optimizer messages
-				      ',expected-message-regexp)
-		       (incf missing-message-failures)))
-		 (error
-		  (Print-Failure "%S ==> unexpected error %S"
-				 ,quoted-body error-info)
-		  (incf other-failures)))
+	       (ignore-errors
+		 (call-with-condition-handler
+		     #'(lambda (error-info)
+			 (Print-Failure "%S ==> unexpected error %S"
+					,quoted-body error-info)
+			 (incf other-failures)
+			 (test-harness-unexpected-error-do-debug error-info))
+		     #'(lambda ()
+			 (setq trick-optimizer (progn ,@body))
+			 (if (string-match ,expected-message-regexp messages)
+			     (progn
+			       (Print-Pass
+				"%S ==> value %S, message %S, matching %S, as expected"
+				,quoted-body trick-optimizer messages
+				',expected-message-regexp)
+			       (incf passes))
+			   (Print-Failure
+			    "%S ==> value %S, message %S, NOT matching expected %S"
+			    ,quoted-body  trick-optimizer messages
+			    ',expected-message-regexp)
+			   (incf missing-message-failures)))))
 	       (ad-unadvise 'message)))))
 
       ;; #### Perhaps this should override `message' itself, too?
@@ -497,36 +610,31 @@
 	    (point-marker))))
 
       (princ "Testing Interpreted Lisp\n\n")
-      (condition-case error-info
-	  (funcall (test-harness-read-from-buffer inbuffer))
-	(error
-	 (incf unexpected-test-file-failures)
-	 (princ (format "Unexpected error %S while executing interpreted code\n"
-		error-info))
-	 (message "Unexpected error %S while executing interpreted code." error-info)
-	 (message "Test suite execution aborted.")
-	 ))
+
+      (test-harness-error-wrap
+       "executing interpreted code"
+       "Test suite execution aborted."
+       (funcall (test-harness-read-from-buffer inbuffer)))
+
       (princ "\nTesting Compiled Lisp\n\n")
+
       (let (code
 	    (test-harness-test-compiled t))
-	(condition-case error-info
-	    (setq code
-		  ;; our lisp code is often intentionally dubious,
-		  ;; so throw away _all_ the byte compiler warnings.
-		  (letf (((symbol-function 'byte-compile-warn) 'ignore))
-		    (byte-compile (test-harness-read-from-buffer inbuffer))))
-	  (error
-	   (princ (format "Unexpected error %S while byte-compiling code\n"
-			  error-info))))
-	(condition-case error-info
-	    (if code (funcall code))
-	  (error
-	   (incf unexpected-test-file-failures)
-	   (princ (format "Unexpected error %S while executing byte-compiled code\n"
-			  error-info))
-	   (message "Unexpected error %S while executing byte-compiled code." error-info)
-	   (message "Test suite execution aborted.")
-	   )))
+	(test-harness-error-wrap
+	 "byte-compiling code" nil
+	 (setq code
+	       ;; our lisp code is often intentionally dubious,
+	       ;; so throw away _all_ the byte compiler warnings.
+	       (letf (((symbol-function 'byte-compile-warn)
+		       'ignore))
+		 (byte-compile (test-harness-read-from-buffer
+				inbuffer))))
+	 )
+
+	(test-harness-error-wrap "executing byte-compiled code"
+				 "Test suite execution aborted."
+				 (if code (funcall code)))
+	)
       (princ (format "\nSUMMARY for %s:\n" filename))
       (princ (format "\t%5d passes\n" passes))
       (princ (format "\t%5d assertion failures\n" assertion-failures))