Support resizing frames and windows pixelwise.
authorMartin Rudalics <rudalics@gmx.at>
Sat, 30 Nov 2013 09:25:31 +0000 (10:25 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Sat, 30 Nov 2013 09:25:31 +0000 (10:25 +0100)
* dispextern.h (enum window_part): Add ON_SCROLL_BAR,
ON_RIGHT_DIVIDER and ON_BOTTOM_DIVIDER.
(struct glyph_matrix): Replace window_left_col and
window_top_line by window_pixel_left and window_pixel_top.
(WINDOW_WANTS_MODELINE_P, WINDOW_WANTS_HEADER_LINE_P): Minor
rewrite.
(enum face_id): Add WINDOW_DIVIDER_FACE_ID.
(draw_window_divider, move_it_to, x_draw_right_divider)
(x_draw_bottom_divider, change_frame_size): Add or fix
declarations.
* dispnew.c (change_frame_size_1): Change prototype.
(adjust_glyph_matrix, required_matrix_width)
(adjust_frame_glyphs_for_window_redisplay): Use pixel
values instead of lines and columns.
(marginal_area_string): Use WINDOW_FRINGES_WIDTH instead of
WINDOW_TOTAL_FRINGE_WIDTH.
(handle_window_change_signal, do_pending_window_change)
(init_display): Adjusts calls of change_frame_size.
(change_frame_size, change_frame_size_1): Handle pixelwise
changes.
* frame.c (Qright_divider_width, Qbottom_divider_width): New
Lisp objects.
(set_menu_bar_lines_1, set_menu_bar_lines, make_frame)
(make_terminal_frame, Fmake_terminal_frame, Fframe_parameters)
(x_set_internal_border_width, x_set_vertical_scroll_bars)
(x_set_scroll_bar_width, x_figure_window_size): Handle pixel
values.
(set_frame_param): New function.
(Fframe_text_cols, Fframe_text_lines, Fframe_total_cols)
(Fframe_text_width, Fframe_text_height, Fscroll_bar_width)
(Ffringe_width, Fborder_width, Fright_divider_width)
(Fbottom_divider_width): New functions, defsubr them.
(Fset_frame_height, Fset_frame_width, Fset_frame_size): New
argument pixelwise.
(struct frame_parm_table): New members Qright_divider_width and
Qbottom_divider_width.
(x_set_frame_parameters): Handle parameters for pixelwise sizes.
(x_report_frame_params): Handle Qright_divider_width and
Qbottom_divider_width.
(x_set_right_divider_width, x_set_bottom_divider_width): New
functions.
(frame_resize_pixelwise): New option.
* frame.h (struct frame): Add tool_bar_height, menu_bar_height,
new_pixelwise, right_divider_width and bottom_divider_width;
remove total_lines; rename text_lines, text_cols, new_text_lines
and new_text_cols to text_height, text_width, new_height and
new_width respectively.
(FRAME_LINES, FRAME_COLS): Rename to FRAME_TEXT_HEIGHT and
FRAME_TEXT_WIDTH respectively.
(FRAME_MENU_BAR_HEIGHT, FRAME_TOOL_BAR_HEIGHT)
(FRAME_RIGHT_DIVIDER_WIDTH, FRAME_BOTTOM_DIVIDER_WIDTH)
(FRAME_TEXT_TO_PIXEL_WIDTH, FRAME_PIXEL_TO_TEXT_WIDTH): New
macros.
(FRAME_TOP_MARGIN_HEIGHT, FRAME_LEFT_SCROLL_BAR_AREA_WIDTH)
(FRAME_RIGHT_SCROLL_BAR_AREA_WIDTH, FRAME_SCROLL_BAR_AREA_WIDTH)
(SET_FRAME_COLS, SET_FRAME_WIDTH, SET_FRAME_HEIGHT)
(FRAME_TEXT_COLS_TO_PIXEL_WIDTH, FRAME_PIXEL_WIDTH_TO_TEXT_COLS)
(FRAME_TEXT_COLS_TO_PIXEL_WIDTH): Rewrite macros.
(FRAME_TOTAL_COLS_ARG): Remove macro.
* fringe.c (draw_fringe_bitmap_1): Handle right divder.
* gtkutil.c (xg_frame_resized, xg_frame_set_char_size)
(x_wm_set_size_hint): Handle frame pixel sizes.
* indent.c (compute_motion, Fcompute_motion): Call
window_body_width instead of window_body_cols.
* keyboard.c (Qright_divider, Qbottom_divider): New symbols.
(make_lispy_position): Handle right and bottom dividers.
(Fsuspend_emacs): Pixelize call of change_frame_size.
* keyboard.h: Extern Qright_divider, Qbottom_divider.
* lisp.h: Extern set_frame_param.
* nsfns.m (x_set_tool_bar_lines): Pixelize call of
x_set_window_size.
(Fx_create_frame): Add entry for vertical_drag_cursor.  Pixelize
call of change_frame_size.
* nsterm.h (struct ns_output): Add vertical_drag_cursor.
* nsterm.m (ns_update_window_end): Optionally draw right
divider.
(x_set_window_size): Add argument pixelwise.  Call
check_frame_size and change_frame_size with pixelwise zero.
(ns_draw_window_divider): New function.
(ns_redisplay_interface): Add ns_draw_window_divider.
(updateFrameSize:): Call change_frame_size with pixelwise zero.
(x_new_font): Call x_set_window_size with pixelwise zero.
* print.c (print_object): For a window print its sequence
number again.
* term.c (Fresume_tty): Pixelize call of change_frame_size.
* w32fns.c (x_set_mouse_color): Handle vertical drag cursor.
(x_set_menu_bar_lines, x_set_tool_bar_lines): Calculate pixelwise.
(w32_createwindow): Use scroll bar area width.
(w32_wnd_proc): Handle bottom divider width.  For
WM_WINDOWPOSCHANGING return zero if we resize pixelwise.
(Fx_create_frame): Default divider width parameters.  Caclulate
sizes pixelwise.  Add vertical drag cursor support.
(x_create_tip_frame): Default divider widths to zero.  Pixelize
call to change_frame_size.
(Fx_show_tip): Add handling of divider widths.  Pixelize window
position and sizes.
(Fw32_frame_rect): New function.
(frame_parm_handler w32_frame_parm_handlers): Add divider
widths.
(Vx_window_vertical_drag_shape): Add variable.
* w32inevt.c (resize_event, maybe_generate_resize_event):
Pixelize change_frame_size calls.
* w32menu.c (set_frame_menubar): Pixelize x_set_window_size
call.
* w32term.c (w32_draw_window_divider): New function.
(x_update_window_end): Handle right divider.
(w32_draw_fringe_bitmap, x_scroll_run)
(w32_set_vertical_scroll_bar): Pixelize scrollbar widths.
(w32_read_socket): Handle SIZE_MAXIMIZED separately.  Calculate
new frame sizes pixelwise.
(x_new_font): Pixelize call to x_set_window_size.
(x_check_fullscreen): Pixelize call to change_frame_size.
(x_set_window_size_1, x_set_window_size): New argument
pixelwise.  Calculate pixelwise.
(x_wm_set_size_hint): Use scroll bar area width.
(w32_redisplay_interface): Add w32_draw_window_divider.
* w32term.h (struct w32_output): Add vertical drag cursor.
* widget.c (set_frame_size, update_wm_hints)
(EmacsFrameResize, EmacsFrameSetValues): Pixelize calls of
change_frame_size.
(EmacsFrameSetCharSize): Pixelize call of x_set_window_size.
* window.c (sequence_number): Restore.
(Fwindow_pixel_width, Fwindow_pixel_height)
(Fwindow_mode_line_height, Fwindow_header_line_height)
(window_pixel_to_total, Frun_window_scroll_functions)
(Fset_window_new_pixel, window_resize_apply_total)
(Fwindow_resize_apply_total): New functions.
(window_body_height, window_body_width): Rename from
window_body_lines.  New argument PIXELWISE.  Calculate
pixelwise.
(Fwindow_body_height, Fwindow_body_width): New argument
PIXELWISE.
(coordinates_in_window, window_relative_x_coord): Use window's
pixel width instead of total width.
(replace_window, recombine_windows): Initialize pixel values.
(resize_root_window, resize_frame_windows, grow_mini_window)
(shrink_mini_window): New argument PIXELWISE.  Calculate
pixelwise.
(Fdelete_other_windows_internal, adjust_window_margins)
(window_resize_check, window_resize_apply)
(Fdelete_window_internal, Fresize_mini_window_internal)
(Fwindow_text_width, Fwindow_text_height): Calculate pixelwise.
(check_frame_size): Rename arguments.  New argument PIXELWISE.
Calculate pixelwise.
(set_window_buffer): Make samebuf bool.  Run configuration change
hook only if buffer changed.
(Fset_window_buffer): Rewrite doc-string.
(make_window): Initialize new_pixel slot.
(Fwindow_resize_apply): Check pixel size of root window.
(Fsplit_window_internal): Call 2nd argument pixel_size.
Calculate pixelwise.
(Fscroll_left, Fscroll_right): Call window_body_width instead of
window_body_cols.
(save_window_data): New slots frame_text_width,
frame_text_height, frame_menu_bar_height, frame_tool_bar_height.
(saved_window): New slots pixel_left, pixel_top, pixel_height,
pixel_width.
(Fcurrent_window_configuration, Fset_window_configuration)
(save_window_save, compare_window_configurations): Handle new
slots in save_window_data and saved_window.
(Fset_window_scroll_bars): Fix doc-string.
(window_resize_pixelwise): New variable.
(coordinates_in_window, Fcoordinates_in_window_p): Handle
dividers.
(make_parent_window): Adjust sequence_number.
(Fwindow_right_divider_width, Fwindow_bottom_divider_width): New
functions.
* window.h (struct window): New members new_pixel, pixel_left,
pixel_top, pixel_width, pixel_height.  Restore sequence_number.
(wset_new_pixel): New function.
(WINDOW_PIXEL_WIDTH, WINDOW_PIXEL_HEIGHT)
(MIN_SAFE_WINDOW_PIXEL_WIDTH, MIN_SAFE_WINDOW_PIXEL_HEIGHT)
(WINDOW_LEFT_PIXEL_EDGE, WINDOW_RIGHT_PIXEL_EDGE)
(WINDOW_TOP_PIXEL_EDGE, WINDOW_BOTTOM_PIXEL_EDGE)
(WINDOW_BOTTOMMOST_P, WINDOW_BOX_LEFT_PIXEL_EDGE)
(WINDOW_BOX_RIGHT_PIXEL_EDGE, WINDOW_MARGINS_COLS)
(WINDOW_MARGINS_WIDTH, WINDOW_RIGHT_DIVIDER_WIDTH)
(WINDOW_BOTTOM_DIVIDER_WIDTH): New macros.
(WINDOW_TOTAL_FRINGE_WIDTH): Rename to WINDOW_FRINGES_WIDTH.
(WINDOW_TOTAL_WIDTH, WINDOW_TOTAL_HEIGHT): Remove macros.
(WINDOW_RIGHT_EDGE_X, WINDOW_LEFT_EDGE_X, WINDOW_TOP_EDGE_Y)
(WINDOW_BOTTOM_EDGE_Y, WINDOW_FULL_WIDTH_P, WINDOW_LEFTMOST_P)
(WINDOW_RIGHTMOST_P, WINDOW_BOX_LEFT_EDGE_X)
(WINDOW_BOX_RIGHT_EDGE_X, WINDOW_FRINGE_COLS)
(WINDOW_BOX_HEIGHT_NO_MODE_LINE, WINDOW_BOX_TEXT_HEIGHT):
Rewrite.
(resize_frame_windows, grow_mini_window, shrink_mini_window)
(window_body_width, check_frame_size): Adapt external declarations.
* xdisp.c (last_max_ascent): New integer.
(window_text_bottom_y): Handle bottom divider.
(window_box_width, window_box_height): Calculate pixelwise.
(get_glyph_string_clip_rects): Handle right divider.
(remember_mouse_glyph): When windows are resized pixelwise
proceed with width and height set to 1.
(init_iterator): Use WINDOW_PIXEL_WIDTH instead of
WINDOW_TOTAL_WIDTH.
(move_it_to): Calculate and return maximum x position
encountered.
(Fwindow_text_pixel_size): New function.
(resize_mini_window, update_tool_bar): Calculate pixelwise.
(tool_bar_lines_needed): Rename to tool_bar_height.  Calculate
pixelwise.
(Ftool_bar_lines_needed): Rename to Ftool_bar_height.  Calculate
pixelwise.
(redisplay_tool_bar): Calculate pixelwise.
(redisplay_window): Calculate pixelwise.  Handle dividers.
(draw_glyphs, x_clear_end_of_line, note_mouse_highlight)
(x_draw_vertical_border): Handle dividers.
(define_frame_cursor1): Handle vertical drag cursor.
(x_draw_right_divider, x_draw_bottom_divider): New functions.
(expose_window): Calculate pixelwise.  Handle dividers.
(init_xdisp): Initialize pixel values.
* xfaces.c (Qwindow_divider): New face.
(realize_basic_faces): Realize it.
* xfns.c (x_set_mouse_color): Handle vertical_drag_cursor.
(x_set_menu_bar_lines, x_set_tool_bar_lines): Calculate pixelwise.
(x_set_scroll_bar_default_width): Default actual width to 16.
(Fx_create_frame): Set sizes pixelwise.
(x_create_tip_frame): Default divider widths to zero.  Pixelize
call of change_frame_size.
(Fx_show_tip): Handle divider widths.  Initial pixel position
and sizes.
(frame_parm_handler x_frame_parm_handlers): Add divider widths.
(Vx_window_vertical_drag_shape): New option.
* xmenu.c (free_frame_menubar): Pixelize call of
x_set_window_size.
* xterm.c (x_draw_window_divider): New function.
(x_update_window_end): Optionally draw right divider.
(x_draw_fringe_bitmap, x_scroll_run, x_scroll_bar_create)
(XTset_vertical_scroll_bar): Use scroll bar pixel width.
(handle_one_xevent, x_new_font): Calculate pixelwise.
(x_set_window_size_1, x_set_window_size): New argument
pixelwise.  Calculate pixelwise.
(x_wm_set_size_hint): Pixelize call of check_frame_size.
(struct x_redisplay_interface): Add x_draw_window_divider.
* xterm.h (struct x_output): Add vertical_drag_cursor.

* cus-start.el (frame-resize-pixelwise)
(window-resize-pixelwise): New entries.
* emacs-lisp/debug.el (debug): Use window-total-height instead
of window-total-size.
* frame.el (tool-bar-lines-needed): Defalias to tool-bar-height.
* help.el (describe-bindings-internal): Call help-buffer
(temp-buffer-max-width): New option.
(resize-temp-buffer-window, help-window-setup)
(with-help-window): Rewrite.
* mouse.el (mouse-drag-line): Rewrite.  Add key bindings for
dragging dividers.
* window.el (frame-char-size, window-min-pixel-height)
(window-safe-min-pixel-height, window-safe-min-pixel-width)
(window-min-pixel-width, window-safe-min-pixel-size)
(window-combination-p, window-safe-min-size)
(window-resizable-p, window--size-to-pixel)
(window--pixel-to-size, window--resize-apply-p): New functions.
(window-safe-min-height): Fix doc-string.
(window-size, window-min-size, window--min-size-1)
(window-sizable, window-sizable-p, window--min-delta-1)
(window-min-delta, window--max-delta-1, window-max-delta)
(window--resizable, window--resizable-p, window-resizable)
(window-full-height-p, window-full-width-p, window-at-side-p)
(window--in-direction-2, window-in-direction)
(window--resize-reset-1, window--resize-mini-window)
(window-resize, window-resize-no-error)
(window--resize-child-windows-normal)
(window--resize-child-windows, window--resize-siblings)
(window--resize-this-window, window--resize-root-window)
(window--resize-root-window-vertically)
(adjust-window-trailing-edge, enlarge-window, shrink-window)
(maximize-window, minimize-window, delete-window)
(quit-restore-window, window-split-min-size, split-window)
(balance-windows-2, balance-windows)
(balance-windows-area-adjust, balance-windows-area)
(window--state-get-1, window-state-get, window--state-put-1)
(window--state-put-2, window-state-put)
(display-buffer-record-window, window--display-buffer): Make
functions handle pixelwise sizing of windows.
(display-buffer--action-function-custom-type)
(display-buffer-fallback-action): Add
display-buffer-in-previous-window.
(display-buffer-use-some-window): Resize window to height it had
before.
(fit-window-to-buffer-horizontally): New option.
(fit-frame-to-buffer): Describe new values.
(fit-frame-to-buffer-bottom-margin): Replace with
fit-frame-to-buffer-margins.
(window--sanitize-margin): New function.
(fit-frame-to-buffer, fit-window-to-buffer): Rewrite completely
using window-text-pixel-size.

37 files changed:
lisp/ChangeLog
lisp/cus-start.el
lisp/emacs-lisp/debug.el
lisp/frame.el
lisp/help.el
lisp/mouse.el
lisp/window.el
src/ChangeLog
src/dispextern.h
src/dispnew.c
src/frame.c
src/frame.h
src/fringe.c
src/gtkutil.c
src/indent.c
src/keyboard.c
src/keyboard.h
src/lisp.h
src/nsfns.m
src/nsterm.h
src/nsterm.m
src/print.c
src/term.c
src/w32fns.c
src/w32inevt.c
src/w32menu.c
src/w32term.c
src/w32term.h
src/widget.c
src/window.c
src/window.h
src/xdisp.c
src/xfaces.c
src/xfns.c
src/xmenu.c
src/xterm.c
src/xterm.h

index 4495d72..d509923 100644 (file)
@@ -1,3 +1,58 @@
+2013-12-01  Martin Rudalics  <rudalics@gmx.at>
+
+       Support resizing frames and windows pixelwise.
+       * cus-start.el (frame-resize-pixelwise)
+       (window-resize-pixelwise): New entries.
+       * emacs-lisp/debug.el (debug): Use window-total-height instead
+       of window-total-size.
+       * frame.el (tool-bar-lines-needed): Defalias to tool-bar-height.
+       * help.el (describe-bindings-internal): Call help-buffer
+       (temp-buffer-max-width): New option.
+       (resize-temp-buffer-window, help-window-setup)
+       (with-help-window): Rewrite.
+       * mouse.el (mouse-drag-line): Rewrite.  Add key bindings for
+       dragging dividers.
+       * window.el (frame-char-size, window-min-pixel-height)
+       (window-safe-min-pixel-height, window-safe-min-pixel-width)
+       (window-min-pixel-width, window-safe-min-pixel-size)
+       (window-combination-p, window-safe-min-size)
+       (window-resizable-p, window--size-to-pixel)
+       (window--pixel-to-size, window--resize-apply-p): New functions.
+       (window-safe-min-height): Fix doc-string.
+       (window-size, window-min-size, window--min-size-1)
+       (window-sizable, window-sizable-p, window--min-delta-1)
+       (window-min-delta, window--max-delta-1, window-max-delta)
+       (window--resizable, window--resizable-p, window-resizable)
+       (window-full-height-p, window-full-width-p, window-at-side-p)
+       (window--in-direction-2, window-in-direction)
+       (window--resize-reset-1, window--resize-mini-window)
+       (window-resize, window-resize-no-error)
+       (window--resize-child-windows-normal)
+       (window--resize-child-windows, window--resize-siblings)
+       (window--resize-this-window, window--resize-root-window)
+       (window--resize-root-window-vertically)
+       (adjust-window-trailing-edge, enlarge-window, shrink-window)
+       (maximize-window, minimize-window, delete-window)
+       (quit-restore-window, window-split-min-size, split-window)
+       (balance-windows-2, balance-windows)
+       (balance-windows-area-adjust, balance-windows-area)
+       (window--state-get-1, window-state-get, window--state-put-1)
+       (window--state-put-2, window-state-put)
+       (display-buffer-record-window, window--display-buffer): Make
+       functions handle pixelwise sizing of windows.
+       (display-buffer--action-function-custom-type)
+       (display-buffer-fallback-action): Add
+       display-buffer-in-previous-window.
+       (display-buffer-use-some-window): Resize window to height it had
+       before.
+       (fit-window-to-buffer-horizontally): New option.
+       (fit-frame-to-buffer): Describe new values.
+       (fit-frame-to-buffer-bottom-margin): Replace with
+       fit-frame-to-buffer-margins.
+       (window--sanitize-margin): New function.
+       (fit-frame-to-buffer, fit-window-to-buffer): Rewrite completely
+       using window-text-pixel-size.
+
 2013-11-30  Glenn Morris  <rgm@gnu.org>
 
        * emacs-lisp/bytecomp.el (byte-compile-form):
index 24f8ac3..8e94e85 100644 (file)
@@ -272,6 +272,7 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
             (tool-bar-mode (frames mouse) boolean nil
 ;                          :initialize custom-initialize-default
                            :set custom-set-minor-mode)
+            (frame-resize-pixelwise windows boolean "24.4")
             ;; fringe.c
             (overflow-newline-into-fringe fringe boolean)
             ;; image.c
@@ -448,6 +449,7 @@ since it could result in memory overflow and make Emacs crash."
                              :value display-buffer)
                       (other :tag "Always (t)" :value t))
              "24.3")
+            (window-resize-pixelwise windows boolean "24.4")
             ;; xdisp.c
             ;; The whitespace group is for whitespace.el.
             (show-trailing-whitespace editing-basics boolean nil
index 6c7a0d2..aa5b25b 100644 (file)
@@ -204,7 +204,7 @@ first will be printed into the backtrace buffer."
                        (window-resize
                         debugger-window
                         (- debugger-previous-window-height
-                           (window-total-size debugger-window)))
+                           (window-total-height debugger-window)))
                      (error nil)))
                (setq debugger-previous-window debugger-window))
              (debugger-mode)
@@ -236,7 +236,7 @@ first will be printed into the backtrace buffer."
                     (eq (window-buffer debugger-window) debugger-buffer))
            ;; Record height of debugger window.
            (setq debugger-previous-window-height
-                 (window-total-size debugger-window)))
+                 (window-total-height debugger-window)))
          (if debugger-will-be-back
              ;; Restore previous window configuration (Bug#12623).
              (set-window-configuration window-configuration)
index a639d89..6105c88 100644 (file)
@@ -210,6 +210,8 @@ This function runs the hook `focus-out-hook'."
 
 (declare-function tool-bar-mode "tool-bar" (&optional arg))
 
+(defalias 'tool-bar-lines-needed 'tool-bar-height)
+
 ;; startup.el calls this function after loading the user's init
 ;; file.  Now default-frame-alist and initial-frame-alist contain
 ;; information to which we must react; do what needs to be done.
index c21d5b8..905c875 100644 (file)
@@ -493,9 +493,8 @@ The optional argument MENUS, if non-nil, says to mention menu bindings.
 The optional argument PREFIX, if non-nil, should be a key sequence;
 then we display only bindings that start with that prefix."
   (let ((buf (current-buffer)))
-    (with-help-window "*Help*"
-      (with-current-buffer standard-output
-       (describe-buffer-bindings buf prefix menus)))))
+    (with-help-window (help-buffer)
+      (describe-buffer-bindings buf prefix menus))))
 
 (defun where-is (definition &optional insert)
   "Print message listing key sequences that invoke the command DEFINITION.
@@ -983,6 +982,23 @@ function is called, the window to be resized is selected."
   :group 'help
   :version "24.3")
 
+(defcustom temp-buffer-max-width
+  (lambda (buffer)
+    (if (eq (selected-window) (frame-root-window))
+       (/ (x-display-pixel-width) (frame-char-width) 2)
+      (/ (- (frame-width) 2) 2)))
+  "Maximum width of a window displaying a temporary buffer.
+This is effective only when Temp Buffer Resize mode is enabled.
+The value is the maximum width (in columns) which
+`resize-temp-buffer-window' will give to a window displaying a
+temporary buffer.  It can also be a function to be called to
+choose the width for such a buffer.  It gets one argument, the
+buffer, and should return a positive integer.  At the time the
+function is called, the window to be resized is selected."
+  :type '(choice integer function)
+  :group 'help
+  :version "24.4")
+
 (define-minor-mode temp-buffer-resize-mode
   "Toggle auto-resizing temporary buffer windows (Temp Buffer Resize Mode).
 With a prefix argument ARG, enable Temp Buffer Resize mode if ARG
@@ -1010,33 +1026,40 @@ and some others."
 
 (defun resize-temp-buffer-window (&optional window)
   "Resize WINDOW to fit its contents.
-WINDOW can be any live window and defaults to the selected one.
-
-Do not make WINDOW higher than `temp-buffer-max-height' nor
-smaller than `window-min-height'.  Do nothing if WINDOW is not
-vertically combined, some of its contents are scrolled out of
-view, or WINDOW was not created by `display-buffer'."
+WINDOW must be a live window and defaults to the selected one.
+Do not resize if WINDOW was not created by `display-buffer'.
+
+If WINDOW is part of a vertical combination, restrain its new
+size by `temp-buffer-max-height' and do not resize if its minimum
+accessible position is scrolled out of view.  If WINDOW is part
+of a horizontal combination, restrain its new size by
+`temp-buffer-max-width'.  In both cases, the value of the option
+`fit-window-to-buffer-horizontally' can inhibit resizing.
+
+If WINDOW is the root window of its frame, resize the frame
+provided `fit-frame-to-buffer' is non-nil."
   (setq window (window-normalize-window window t))
   (let ((height (if (functionp temp-buffer-max-height)
                    (with-selected-window window
                      (funcall temp-buffer-max-height (window-buffer)))
                  temp-buffer-max-height))
+       (width (if (functionp temp-buffer-max-width)
+                  (with-selected-window window
+                    (funcall temp-buffer-max-width (window-buffer)))
+                temp-buffer-max-width))
        (quit-cadr (cadr (window-parameter window 'quit-restore))))
-    (cond
-     ;; Resize WINDOW iff it was split off by `display-buffer'.
-     ((and (eq quit-cadr 'window)
-          (pos-visible-in-window-p (point-min) window)
-          (window-combined-p window))
-      (fit-window-to-buffer window height))
-     ;; Resize FRAME iff it was created by `display-buffer'.
-     ((and fit-frame-to-buffer
-          (eq quit-cadr 'frame)
-          (eq window (frame-root-window window)))
-      (let ((frame (window-frame window)))
-       (fit-frame-to-buffer
-        frame (+ (frame-height frame)
-                 (- (window-total-size window))
-                 height)))))))
+    ;; Resize WINDOW iff it was made by `display-buffer'.
+    (when (or (and (eq quit-cadr 'window)
+                  (or (and (window-combined-p window)
+                           (not (eq fit-window-to-buffer-horizontally
+                                    'only))
+                           (pos-visible-in-window-p (point-min) window))
+                      (and (window-combined-p window t)
+                           fit-window-to-buffer-horizontally)))
+             (and (eq quit-cadr 'frame)
+                    fit-frame-to-buffer
+                    (eq window (frame-root-window window))))
+       (fit-window-to-buffer window height nil width))))
 
 ;;; Help windows.
 (defcustom help-window-select 'other
@@ -1089,28 +1112,29 @@ window."
     (message "%s"
      (substitute-command-keys (concat quit-part scroll-part)))))
 
-(defun help-window-setup (help-window)
-  "Set up help window for `with-help-window'.
-HELP-WINDOW is the window used for displaying the help buffer."
-  (let* ((help-buffer (when (window-live-p help-window)
-                       (window-buffer help-window)))
-        (help-setup (when (window-live-p help-window)
-                      (car (window-parameter help-window 'quit-restore)))))
+(defun help-window-setup (window &optional value)
+  "Set up help window WINDOW for `with-help-window'.
+WINDOW is the window used for displaying the help buffer.
+Return VALUE."
+  (let* ((help-buffer (when (window-live-p window)
+                       (window-buffer window)))
+        (help-setup (when (window-live-p window)
+                      (car (window-parameter window 'quit-restore)))))
     (when help-buffer
       ;; Handle `help-window-point-marker'.
       (when (eq (marker-buffer help-window-point-marker) help-buffer)
-       (set-window-point help-window help-window-point-marker)
+       (set-window-point window help-window-point-marker)
        ;; Reset `help-window-point-marker'.
        (set-marker help-window-point-marker nil))
 
       (cond
-       ((or (eq help-window (selected-window))
+       ((or (eq window (selected-window))
            (and (or (eq help-window-select t)
                     (eq help-setup 'frame)
                     (and (eq help-window-select 'other)
-                         (eq (window-frame help-window) (selected-frame))
+                         (eq (window-frame window) (selected-frame))
                          (> (length (window-list nil 'no-mini)) 2)))
-                (select-window help-window)))
+                (select-window window)))
        ;; The help window is or gets selected ...
        (help-window-display-message
         (cond
@@ -1118,12 +1142,12 @@ HELP-WINDOW is the window used for displaying the help buffer."
           ;; ... and is new, ...
           "Type \"q\" to delete help window")
          ((eq help-setup 'frame)
-          "Type \"q\" to delete help frame")
+          "Type \"q\" to quit the help frame")
          ((eq help-setup 'other)
           ;; ... or displayed some other buffer before.
           "Type \"q\" to restore previous buffer"))
-        help-window t))
-       ((and (eq (window-frame help-window) (selected-frame))
+        window t))
+       ((and (eq (window-frame window) (selected-frame))
             (= (length (window-list nil 'no-mini)) 2))
        ;; There are two windows on the help window's frame and the
        ;; other one is the selected one.
@@ -1133,7 +1157,7 @@ HELP-WINDOW is the window used for displaying the help buffer."
           "Type \\[delete-other-windows] to delete the help window")
          ((eq help-setup 'other)
           "Type \"q\" in help window to restore its previous buffer"))
-        help-window 'other))
+        window 'other))
        (t
        ;; The help window is not selected ...
        (help-window-display-message
@@ -1144,40 +1168,42 @@ HELP-WINDOW is the window used for displaying the help buffer."
          ((eq help-setup 'other)
           ;; ... or displayed some other buffer before.
           "Type \"q\" in help window to restore previous buffer"))
-        help-window))))))
+        window))))
+    ;; Return VALUE.
+    value))
 
-;; `with-help-window' is a wrapper for `with-output-to-temp-buffer'
+;; `with-help-window' is a wrapper for `with-temp-buffer-window'
 ;; providing the following additional twists:
 
-;; (1) Issue more accurate messages telling how to scroll and quit the
-;; help window.
+;; (1) It puts the buffer in `help-mode' (via `help-mode-setup') and
+;; adds cross references (via `help-mode-finish').
+
+;; (2) It issues a message telling how to scroll and quit the help
+;; window (via `help-window-setup').
 
-;; (2) An option (customizable via `help-window-select') to select the
+;; (3) An option (customizable via `help-window-select') to select the
 ;; help window automatically.
 
-;; (3) A marker (`help-window-point-marker') to move point in the help
+;; (4) A marker (`help-window-point-marker') to move point in the help
 ;; window to an arbitrary buffer position.
 
 ;; Note: It's usually always wrong to use `help-print-return-message' in
 ;; the body of `with-help-window'.
 (defmacro with-help-window (buffer-name &rest body)
   "Display buffer with name BUFFER-NAME in a help window evaluating BODY.
-Select help window if the actual value of the user option
+Select help window if the current value of the user option
 `help-window-select' says so.  Return last value in BODY."
   (declare (indent 1) (debug t))
   `(progn
      ;; Make `help-window-point-marker' point nowhere.  The only place
      ;; where this should be set to a buffer position is within BODY.
      (set-marker help-window-point-marker nil)
-     (let* (help-window
-            (temp-buffer-show-hook
-             (cons (lambda () (setq help-window (selected-window)))
-                   temp-buffer-show-hook)))
-       ;; Return value returned by `with-output-to-temp-buffer'.
-       (prog1
-          (with-output-to-temp-buffer ,buffer-name
-            (progn ,@body))
-        (help-window-setup help-window)))))
+     (let ((temp-buffer-window-setup-hook
+           (cons 'help-mode-setup temp-buffer-window-setup-hook))
+          (temp-buffer-window-show-hook
+           (cons 'help-mode-finish temp-buffer-window-show-hook)))
+       (with-temp-buffer-window
+       ,buffer-name nil 'help-window-setup (progn ,@body)))))
 
 ;; Called from C, on encountering `help-char' when reading a char.
 ;; Don't print to *Help*; that would clobber Help history.
index 91a17f0..ec38f46 100644 (file)
@@ -392,93 +392,111 @@ must be one of the symbols `header', `mode', or `vertical'."
         (window (posn-window start))
         (frame (window-frame window))
         (minibuffer-window (minibuffer-window frame))
+         (on-link (and mouse-1-click-follows-link
+                      (mouse-on-link-p start)))
         (side (and (eq line 'vertical)
                    (or (cdr (assq 'vertical-scroll-bars
                                   (frame-parameters frame)))
                        'right)))
         (draggable t)
-        event position growth dragged)
+        height finished event position growth dragged)
     (cond
      ((eq line 'header)
       ;; Check whether header-line can be dragged at all.
       (if (window-at-side-p window 'top)
          (setq draggable nil)
+       (setq height (/ (window-header-line-height window) 2))
        (setq window (window-in-direction 'above window t))))
      ((eq line 'mode)
       ;; Check whether mode-line can be dragged at all.
-      (and (window-at-side-p window 'bottom)
-          ;; Allow resizing the minibuffer window if it's on the same
-          ;; frame as and immediately below the clicked window, and
-          ;; it's active or `resize-mini-windows' is nil.
-          (not (and (eq (window-frame minibuffer-window) frame)
-                    (= (nth 1 (window-edges minibuffer-window))
-                       (nth 3 (window-edges window)))
-                    (or (not resize-mini-windows)
-                        (eq minibuffer-window
-                            (active-minibuffer-window)))))
-          (setq draggable nil)))
+      (if (and (window-at-side-p window 'bottom)
+              ;; Allow resizing the minibuffer window if it's on the same
+              ;; frame as and immediately below the clicked window, and
+              ;; it's active or `resize-mini-windows' is nil.
+              (not (and (eq (window-frame minibuffer-window) frame)
+                        (= (nth 1 (window-pixel-edges minibuffer-window))
+                           (nth 3 (window-pixel-edges window)))
+                        (or (not resize-mini-windows)
+                            (eq minibuffer-window
+                                (active-minibuffer-window))))))
+         (setq draggable nil)
+       (setq height (/ (window-mode-line-height window) 2))))
      ((eq line 'vertical)
-      ;; Get the window to adjust for the vertical case.  If the
-      ;; scroll bar is on the window's right or there's no scroll bar
-      ;; at all, adjust the window where the start-event occurred.  If
-      ;; the scroll bar is on the start-event window's left, adjust
-      ;; the window on the left of it.
-      (unless (eq side 'right)
+      ;; Get the window to adjust for the vertical case.  If the scroll
+      ;; bar is on the window's right or we drag a vertical divider,
+      ;; adjust the window where the start-event occurred.  If the
+      ;; scroll bar is on the start-event window's left or there are no
+      ;; scrollbars, adjust the window on the left of it.
+      (unless (or (eq side 'right)
+                 (not (zerop (window-right-divider-width window))))
        (setq window (window-in-direction 'left window t)))))
 
     ;; Start tracking.
     (track-mouse
-      ;; Loop reading events and sampling the position of the mouse,
-      ;; until there is a non-mouse-movement event.  Also,
-      ;; scroll-bar-movement events are the same as mouse movement for
-      ;; our purposes.  (Why? -- cyd)
-      ;; If you change this, check that all of the following still work:
-      ;; Resizing windows by dragging mode-lines and header lines,
-      ;; and vertical lines (in windows without scroll bars).
-      ;;   Doing this should not select another window, even if
-      ;;   mouse-autoselect-window is non-nil.
-      ;; Mouse-1 clicks in Info header lines should advance position
-      ;; by one node at a time if mouse-1-click-follows-link is non-nil,
-      ;; otherwise they should just select the window.
-      (while (progn
-              (setq event (read-event))
-              (memq (car-safe event)
-                     '(mouse-movement scroll-bar-movement
-                                      switch-frame select-window)))
-       (setq position (mouse-position))
+      ;; Loop reading events and sampling the position of the mouse.
+      (while (not finished)
+       (setq event (read-event))
+       (setq position (mouse-pixel-position))
        ;; Do nothing if
        ;;   - there is a switch-frame event.
        ;;   - the mouse isn't in the frame that we started in
        ;;   - the mouse isn't in any Emacs frame
+       ;; Drag if
+       ;;   - there is a mouse-movement event
+       ;;   - there is a scroll-bar-movement event (Why? -- cyd)
+       ;;     (same as mouse movement for our purposes)
+       ;; Quit if
+       ;;   - there is a keyboard event or some other unknown event.
        (cond
+        ((not (consp event))
+         (setq finished t))
         ((memq (car event) '(switch-frame select-window))
          nil)
-        ((not (and (eq (car position) frame)
-                   (cadr position)))
+        ((not (memq (car event) '(mouse-movement scroll-bar-movement)))
+         (when (consp event)
+           ;; Do not unread a drag-mouse-1 event to avoid selecting
+           ;; some other window.  For vertical line dragging do not
+           ;; unread mouse-1 events either (but only if we dragged at
+           ;; least once to allow mouse-1 clicks get through).
+           (unless (and dragged
+                        (if (eq line 'vertical)
+                            (memq (car event) '(drag-mouse-1 mouse-1))
+                          (eq (car event) 'drag-mouse-1)))
+             (push event unread-command-events)))
+         (setq finished t))
+        ((not (and (eq (car position) frame)
+                   (cadr position)))
          nil)
         ((eq line 'vertical)
-         ;; Drag vertical divider.
+         ;; Drag vertical divider.  This must be probably fixed like
+         ;; for the mode-line.
          (setq growth (- (cadr position)
                          (if (eq side 'right) 0 2)
-                         (nth 2 (window-edges window))
+                         (nth 2 (window-pixel-edges window))
                          -1))
          (unless (zerop growth)
-           (setq dragged t))
-         (adjust-window-trailing-edge window growth t))
+           (setq dragged t)
+           (adjust-window-trailing-edge window growth t t)))
         (draggable
          ;; Drag horizontal divider.
          (setq growth
                (if (eq line 'mode)
-                   (- (cddr position) (nth 3 (window-edges window)) -1)
+                   (- (+ (cddr position) height)
+                      (nth 3 (window-pixel-edges window)))
                  ;; The window's top includes the header line!
-                 (- (nth 3 (window-edges window)) (cddr position))))
+                 (- (+ (nth 3 (window-pixel-edges window)) height)
+                    (cddr position))))
          (unless (zerop growth)
-           (setq dragged t))
-         (adjust-window-trailing-edge window (if (eq line 'mode)
-                                                 growth
-                                               (- growth)))))))
+           (setq dragged t)
+           (adjust-window-trailing-edge
+            window (if (eq line 'mode) growth (- growth)) nil t))))))
     ;; Process the terminating event.
-    (unless dragged
+    (when (and (mouse-event-p event) on-link (not dragged)
+              (mouse--remap-link-click-p start-event event))
+      ;; If mouse-2 has never been done by the user, it doesn't have
+      ;; the necessary property to be interpreted correctly.
+      (put 'mouse-2 'event-kind 'mouse-click)
+      (setcar event 'mouse-2)
       (push event unread-command-events))))
 
 (defun mouse-drag-mode-line (start-event)
@@ -1936,6 +1954,8 @@ choose a font."
 (global-set-key [vertical-scroll-bar C-mouse-2] 'mouse-split-window-vertically)
 (global-set-key [vertical-line C-mouse-2] 'mouse-split-window-vertically)
 (global-set-key [vertical-line down-mouse-1] 'mouse-drag-vertical-line)
+(global-set-key [right-divider down-mouse-1] 'mouse-drag-vertical-line)
+(global-set-key [bottom-divider down-mouse-1] 'mouse-drag-mode-line)
 (global-set-key [vertical-line mouse-1] 'mouse-select-window)
 
 (provide 'mouse)
index f997d8b..d35d898 100644 (file)
@@ -278,6 +278,28 @@ Otherwise, signal an error."
    (t
     (error "%s is not a valid window" window))))
 
+;; Maybe this should go to frame.el.
+(defun frame-char-size (&optional window-or-frame horizontal)
+  "Return the value of `frame-char-height' for WINDOW-OR-FRAME.
+If WINDOW-OR-FRAME is a live frame, return the value of
+`frame-char-height' for that frame.  If WINDOW-OR-FRAME is a
+valid window, return the value of `frame-char-height' for that
+window's frame.  In any other case, return the value of
+`frame-char-height' for the selected frame.
+
+Optional argument HORIZONTAL non-nil means to return the value of
+`frame-char-width' for WINDOW-OR-FRAME."
+  (let ((frame
+        (cond
+         ((window-valid-p window-or-frame)
+          (window-frame window-or-frame))
+         ((frame-live-p window-or-frame)
+          window-or-frame)
+         (t (selected-frame)))))
+    (if horizontal
+       (frame-char-width frame)
+      (frame-char-height frame))))
+
 (defvar ignore-window-parameters nil
   "If non-nil, standard functions ignore window parameters.
 The functions currently affected by this are `split-window',
@@ -286,10 +308,16 @@ The functions currently affected by this are `split-window',
 An application may bind this to a non-nil value around calls to
 these functions to inhibit processing of window parameters.")
 
+;; This must go to C, finally (or get removed).
 (defconst window-safe-min-height 1
-  "The absolute minimum number of lines of a window.
+  "The absolute minimum number of lines of any window.
 Anything less might crash Emacs.")
 
+(defun window-safe-min-pixel-height (&optional window)
+  "Return the absolute minimum pixel height of WINDOW."
+  (* window-safe-min-height
+     (frame-char-size (window-normalize-window window))))
+
 (defcustom window-min-height 4
   "The minimum number of lines of any window.
 The value has to accommodate a mode- or header-line if present.
@@ -305,10 +333,21 @@ shorter, explicitly specify the SIZE argument of that function."
   :version "24.1"
   :group 'windows)
 
+(defun window-min-pixel-height (&optional window)
+  "Return the minimum pixel height of window WINDOW."
+  (* (max window-min-height window-safe-min-height)
+     (frame-char-size window)))
+
+;; This must go to C, finally (or get removed).
 (defconst window-safe-min-width 2
   "The absolute minimum number of columns of a window.
 Anything less might crash Emacs.")
 
+(defun window-safe-min-pixel-width (&optional window)
+  "Return the absolute minimum pixel width of WINDOW."
+  (* window-safe-min-width
+     (frame-char-size (window-normalize-window window) t)))
+
 (defcustom window-min-width 10
   "The minimum number of columns of any window.
 The value has to accommodate margins, fringes, or scrollbars if
@@ -325,15 +364,27 @@ narrower, explicitly specify the SIZE argument of that function."
   :version "24.1"
   :group 'windows)
 
+(defun window-min-pixel-width (&optional window)
+  "Return the minimum pixel width of window WINDOW."
+  (* (max window-min-width window-safe-min-width)
+     (frame-char-size window t)))
+
+(defun window-safe-min-pixel-size (&optional window horizontal)
+  "Return the absolute minimum pixel height of WINDOW.
+Optional argument HORIZONTAL non-nil means return the absolute
+minimum pixel width of WINDOW."
+  (if horizontal
+      (window-safe-min-pixel-width window)
+    (window-safe-min-pixel-height window)))
+
 (defun window-combined-p (&optional window horizontal)
   "Return non-nil if WINDOW has siblings in a given direction.
 WINDOW must be a valid window and defaults to the selected one.
 
-HORIZONTAL determines a direction for the window combination.
-If HORIZONTAL is omitted or nil, return non-nil if WINDOW is part
-of a vertical window combination.
-If HORIZONTAL is non-nil, return non-nil if WINDOW is part of a
-horizontal window combination."
+HORIZONTAL determines a direction for the window combination.  If
+HORIZONTAL is omitted or nil, return non-nil if WINDOW is part of
+a vertical window combination.  If HORIZONTAL is non-nil, return
+non-nil if WINDOW is part of a horizontal window combination."
   (setq window (window-normalize-window window))
   (let ((parent (window-parent window)))
     (and parent
@@ -341,6 +392,16 @@ horizontal window combination."
             (window-left-child parent)
           (window-top-child parent)))))
 
+(defun window-combination-p (&optional window horizontal)
+  "Return WINDOW's first child if WINDOW is a vertical combination.
+WINDOW can be any window and defaults to the selected one.
+Optional argument HORIZONTAL non-nil means return WINDOW's first
+child if WINDOW is a horizontal combination."
+  (setq window (window-normalize-window window))
+  (if horizontal
+      (window-left-child window)
+    (window-top-child window)))
+
 (defun window-combinations (window &optional horizontal)
   "Return largest number of windows vertically arranged within WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
@@ -731,8 +792,8 @@ SIDE.  Return the new window, nil if its creation window failed."
               (cons
                (if left-or-right 'window-width 'window-height)
                (/ (window-total-size (frame-root-window) left-or-right)
-                  ;; By default use a fourth of the size of the
-                  ;; frame's root window.
+                  ;; By default use a fourth of the size of the frame's
+                  ;; root window.
                   4))
               alist)))
       ;; Install BUFFER in new window and return NEW.
@@ -951,6 +1012,35 @@ FRAME defaults to the selected frame."
   (window--atom-check frame))
 
 ;;; Window sizes.
+(defun window-total-size (&optional window horizontal)
+  "Return the total height or width of WINDOW.
+WINDOW must be a valid window and defaults to the selected one.
+
+If HORIZONTAL is omitted or nil, return the total height of
+WINDOW, in lines, like `window-total-height'.  Otherwise return
+the total width, in columns, like `window-total-width'."
+  (if horizontal
+      (window-total-width window)
+    (window-total-height window)))
+
+(defun window-size (&optional window horizontal pixelwise)
+  "Return the height or width of WINDOW.
+WINDOW must be a valid window and defaults to the selected one.
+
+If HORIZONTAL is omitted or nil, return the total height of
+WINDOW, in lines, like `window-total-height'.  Otherwise return
+the total width, in columns, like `window-total-width'.
+
+Optional argument PIXELWISE means return the pixel size of WINDOW
+like `window-pixel-height' and `window-pixel-width'."
+  (if horizontal
+      (if pixelwise
+         (window-pixel-width window)
+       (window-total-width window))
+    (if pixelwise
+       (window-pixel-height window)
+      (window-total-height window))))
+
 (defvar window-size-fixed nil
   "Non-nil in a buffer means windows displaying the buffer are fixed-size.
 If the value is `height', then only the window's height is fixed.
@@ -966,7 +1056,25 @@ window).")
   "Return non-nil if IGNORE says to ignore size restrictions for WINDOW."
   (if (window-valid-p ignore) (eq window ignore) ignore))
 
-(defun window-min-size (&optional window horizontal ignore)
+(defun window-safe-min-size (&optional window horizontal pixelwise)
+  "Return safe minimum size of WINDOW.
+WINDOW must be a valid window and defaults to the selected one.
+Optional argument HORIZONTAL non-nil means return the minimum
+number of columns of WINDOW; otherwise return the minimum number
+of WINDOW's lines.
+
+Optional argument PIXELWISE non-nil means return the minimum pixel-size
+of WINDOW."
+  (setq window (window-normalize-window window))
+  (if pixelwise
+      (if horizontal
+         (* window-safe-min-width
+            (frame-char-width (window-frame window)))
+       (* window-safe-min-height
+          (frame-char-height (window-frame window))))
+    (if horizontal window-safe-min-width window-safe-min-height)))
+
+(defun window-min-size (&optional window horizontal ignore pixelwise)
   "Return the minimum size of WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
 Optional argument HORIZONTAL non-nil means return the minimum
@@ -979,11 +1087,14 @@ imposed by fixed size windows, `window-min-height' or
 windows may get as small as `window-safe-min-height' lines and
 `window-safe-min-width' columns.  If IGNORE is a window, ignore
 restrictions for that window only.  Any other non-nil value
-means ignore all of the above restrictions for all windows."
+means ignore all of the above restrictions for all windows.
+
+Optional argument PIXELWISE non-nil means return the minimum pixel-size
+of WINDOW."
   (window--min-size-1
-   (window-normalize-window window) horizontal ignore))
+   (window-normalize-window window) horizontal ignore pixelwise))
 
-(defun window--min-size-1 (window horizontal ignore)
+(defun window--min-size-1 (window horizontal ignore pixelwise)
   "Internal function of `window-min-size'."
   (let ((sub (window-child window)))
     (if sub
@@ -994,13 +1105,15 @@ means ignore all of the above restrictions for all windows."
              ;; the minimum sizes of its child windows.
              (while sub
                (setq value (+ value
-                              (window--min-size-1 sub horizontal ignore)))
+                              (window--min-size-1
+                               sub horizontal ignore pixelwise)))
                (setq sub (window-right sub)))
            ;; The minimum size of an ortho-combination is the maximum
            ;; of the minimum sizes of its child windows.
            (while sub
              (setq value (max value
-                              (window--min-size-1 sub horizontal ignore)))
+                              (window--min-size-1
+                               sub horizontal ignore pixelwise)))
              (setq sub (window-right sub))))
          value)
       (with-current-buffer (window-buffer window)
@@ -1008,10 +1121,10 @@ means ignore all of the above restrictions for all windows."
         ((and (not (window--size-ignore-p window ignore))
               (window-size-fixed-p window horizontal))
          ;; The minimum size of a fixed size window is its size.
-         (window-total-size window horizontal))
+         (window-size window horizontal pixelwise))
         ((or (eq ignore 'safe) (eq ignore window))
          ;; If IGNORE equals `safe' or WINDOW return the safe values.
-         (if horizontal window-safe-min-width window-safe-min-height))
+         (window-safe-min-size window horizontal pixelwise))
         (horizontal
          ;; For the minimum width of a window take fringes and
          ;; scroll-bars into account.  This is questionable and should
@@ -1022,34 +1135,54 @@ means ignore all of the above restrictions for all windows."
          (let ((frame (window-frame window))
                (fringes (window-fringes window))
                (scroll-bars (window-scroll-bars window)))
-           (max
-            (+ window-safe-min-width
-               (ceiling (car fringes) (frame-char-width frame))
-               (ceiling (cadr fringes) (frame-char-width frame))
-               (cond
-                ((memq (nth 2 scroll-bars) '(left right))
-                 (nth 1 scroll-bars))
+           (if pixelwise
+               (max
+                (+ (window-safe-min-size window t t)
+                   (car fringes) (cadr fringes)
+                   (cond
+                    ((memq (nth 2 scroll-bars) '(left right))
+                     (nth 1 scroll-bars))
+                    ((memq (frame-parameter frame 'vertical-scroll-bars)
+                           '(left right))
+                     (frame-parameter frame 'scroll-bar-width))
+                    (t 0)))
+                (if (window--size-ignore-p window ignore)
+                    0
+                  (window-min-pixel-width)))
+             (max
+              (+ window-safe-min-width
+                 (ceiling (car fringes) (frame-char-width frame))
+                 (ceiling (cadr fringes) (frame-char-width frame))
+                 (cond
+                  ((memq (nth 2 scroll-bars) '(left right))
+                   (nth 1 scroll-bars))
                 ((memq (frame-parameter frame 'vertical-scroll-bars)
                        '(left right))
                  (ceiling (or (frame-parameter frame 'scroll-bar-width) 14)
                           (frame-char-width)))
                 (t 0)))
-            (if (and (not (window--size-ignore-p window ignore))
-                     (numberp window-min-width))
-                window-min-width
-              0))))
+              (if (window--size-ignore-p window ignore)
+                  0
+                window-min-width)))))
+        (pixelwise
+         (max 
+          (+ (window-safe-min-size window nil t)
+             (window-header-line-height window)
+             (window-mode-line-height window))
+          (if (window--size-ignore-p window ignore)
+              0
+            (window-min-pixel-height))))
         (t
          ;; For the minimum height of a window take any mode- or
          ;; header-line into account.
          (max (+ window-safe-min-height
                  (if header-line-format 1 0)
                  (if mode-line-format 1 0))
-              (if (and (not (window--size-ignore-p window ignore))
-                       (numberp window-min-height))
-                  window-min-height
-                0))))))))
+              (if (window--size-ignore-p window ignore)
+                  0
+                window-min-height))))))))
 
-(defun window-sizable (window delta &optional horizontal ignore)
+(defun window-sizable (window delta &optional horizontal ignore pixelwise)
   "Return DELTA if DELTA lines can be added to WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
 Optional argument HORIZONTAL non-nil means return DELTA if DELTA
@@ -1076,12 +1209,15 @@ imposed by fixed size windows, `window-min-height' or
 windows may get as small as `window-safe-min-height' lines and
 `window-safe-min-width' columns.  If IGNORE is a window, ignore
 restrictions for that window only.  Any other non-nil value means
-ignore all of the above restrictions for all windows."
+ignore all of the above restrictions for all windows.
+
+Optional argument PIXELWISE non-nil means interpret DELTA as
+pixels."
   (setq window (window-normalize-window window))
   (cond
    ((< delta 0)
-    (max (- (window-min-size window horizontal ignore)
-           (window-total-size window horizontal))
+    (max (- (window-min-size window horizontal ignore pixelwise)
+           (window-size window horizontal pixelwise))
         delta))
    ((window--size-ignore-p window ignore)
     delta)
@@ -1091,15 +1227,17 @@ ignore all of the above restrictions for all windows."
       delta))
    (t 0)))
 
-(defun window-sizable-p (window delta &optional horizontal ignore)
+(defun window-sizable-p (window delta &optional horizontal ignore pixelwise)
   "Return t if WINDOW can be resized by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
 For the meaning of the arguments of this function see the
 doc-string of `window-sizable'."
   (setq window (window-normalize-window window))
   (if (> delta 0)
-      (>= (window-sizable window delta horizontal ignore) delta)
-    (<= (window-sizable window delta horizontal ignore) delta)))
+      (>= (window-sizable window delta horizontal ignore pixelwise)
+         delta)
+    (<= (window-sizable window delta horizontal ignore pixelwise)
+       delta)))
 
 (defun window--size-fixed-1 (window horizontal)
   "Internal function for `window-size-fixed-p'."
@@ -1146,7 +1284,7 @@ WINDOW can be resized in the desired direction.  The function
   (window--size-fixed-1
    (window-normalize-window window) horizontal))
 
-(defun window--min-delta-1 (window delta &optional horizontal ignore trail noup)
+(defun window--min-delta-1 (window delta &optional horizontal ignore trail noup pixelwise)
   "Internal function for `window-min-delta'."
   (if (not (window-parent window))
       ;; If we can't go up, return zero.
@@ -1177,14 +1315,16 @@ WINDOW can be resized in the desired direction.  The function
            (unless (eq sub window)
              (setq delta
                    (min delta
-                        (- (window-total-size sub horizontal)
-                           (window-min-size sub horizontal ignore)))))
+                        (- (window-size sub horizontal pixelwise)
+                           (window-min-size
+                            sub horizontal ignore pixelwise)))))
            (setq sub (window-right sub))))
        (if noup
            delta
-         (window--min-delta-1 parent delta horizontal ignore trail))))))
+         (window--min-delta-1
+          parent delta horizontal ignore trail nil pixelwise))))))
 
-(defun window-min-delta (&optional window horizontal ignore trail noup nodown)
+(defun window-min-delta (&optional window horizontal ignore trail noup nodown pixelwise)
   "Return number of lines by which WINDOW can be shrunk.
 WINDOW must be a valid window and defaults to the selected one.
 Return zero if WINDOW cannot be shrunk.
@@ -1210,15 +1350,19 @@ tree, but try to enlarge windows within WINDOW's combination only.
 
 Optional argument NODOWN non-nil means don't check whether WINDOW
 itself (and its child windows) can be shrunk; check only whether
-at least one other window can be enlarged appropriately."
+at least one other window can be enlarged appropriately.
+
+Optional argument PIXELWISE non-nil means return number of pixels
+by which WINDOW can be shrunk."
   (setq window (window-normalize-window window))
-  (let ((size (window-total-size window horizontal))
-       (minimum (window-min-size window horizontal ignore)))
+  (let ((size (window-size window horizontal pixelwise))
+       (minimum (window-min-size window horizontal ignore pixelwise)))
     (cond
      (nodown
       ;; If NODOWN is t, try to recover the entire size of WINDOW.
-      (window--min-delta-1 window size horizontal ignore trail noup))
-     ((= size minimum)
+      (window--min-delta-1
+       window size horizontal ignore trail noup pixelwise))
+     ((<= size minimum)
       ;; If NODOWN is nil and WINDOW's size is already at its minimum,
       ;; there's nothing to recover.
       0)
@@ -1226,9 +1370,9 @@ at least one other window can be enlarged appropriately."
       ;; Otherwise, try to recover whatever WINDOW is larger than its
       ;; minimum size.
       (window--min-delta-1
-       window (- size minimum) horizontal ignore trail noup)))))
+       window (- size minimum) horizontal ignore trail noup pixelwise)))))
 
-(defun window--max-delta-1 (window delta &optional horizontal ignore trail noup)
+(defun window--max-delta-1 (window delta &optional horizontal ignore trail noup pixelwise)
   "Internal function of `window-max-delta'."
   (if (not (window-parent window))
       ;; Can't go up.  Return DELTA.
@@ -1248,8 +1392,9 @@ at least one other window can be enlarged appropriately."
                 (t
                  (setq delta
                        (+ delta
-                          (- (window-total-size sub horizontal)
-                             (window-min-size sub horizontal ignore))))))
+                          (- (window-size sub horizontal pixelwise)
+                             (window-min-size
+                              sub horizontal ignore pixelwise))))))
                (setq sub (window-right sub))))
          ;; For an ortho-combination throw DELTA when at least one
          ;; child window is fixed-size.
@@ -1264,9 +1409,10 @@ at least one other window can be enlarged appropriately."
            delta
          ;; Else try with parent of WINDOW, passing the DELTA we
          ;; recovered so far.
-         (window--max-delta-1 parent delta horizontal ignore trail))))))
+         (window--max-delta-1
+          parent delta horizontal ignore trail nil pixelwise))))))
 
-(defun window-max-delta (&optional window horizontal ignore trail noup nodown)
+(defun window-max-delta (&optional window horizontal ignore trail noup nodown pixelwise)
   "Return maximum number of lines by which WINDOW can be enlarged.
 WINDOW must be a valid window and defaults to the selected one.
 The return value is zero if WINDOW cannot be enlarged.
@@ -1293,7 +1439,10 @@ WINDOW's combination.
 
 Optional argument NODOWN non-nil means do not check whether
 WINDOW itself (and its child windows) can be enlarged; check
-only whether other windows can be shrunk appropriately."
+only whether other windows can be shrunk appropriately.
+
+Optional argument PIXELWISE non-nil means return number of
+pixels by which WINDOW can be enlarged."
   (setq window (window-normalize-window window))
   (if (and (not (window--size-ignore-p window ignore))
           (not nodown) (window-size-fixed-p window horizontal))
@@ -1301,10 +1450,10 @@ only whether other windows can be shrunk appropriately."
       ;; size.
       0
     ;; WINDOW has no fixed size.
-    (window--max-delta-1 window 0 horizontal ignore trail noup)))
+    (window--max-delta-1 window 0 horizontal ignore trail noup pixelwise)))
 
 ;; Make NOUP also inhibit the min-size check.
-(defun window--resizable (window delta &optional horizontal ignore trail noup nodown)
+(defun window--resizable (window delta &optional horizontal ignore trail noup nodown pixelwise)
   "Return DELTA if WINDOW can be resized vertically by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
 Optional argument HORIZONTAL non-nil means return DELTA if WINDOW
@@ -1340,30 +1489,40 @@ to) WINDOW's siblings.
 
 Optional argument NODOWN non-nil means don't go down in the
 window tree.  This means do not check whether resizing would
-violate size restrictions of WINDOW or its child windows."
+violate size restrictions of WINDOW or its child windows.
+
+Optional argument PIXELWISE non-nil means interpret DELTA as
+number of pixels."
   (setq window (window-normalize-window window))
   (cond
    ((< delta 0)
-    (max (- (window-min-delta window horizontal ignore trail noup nodown))
+    (max (- (window-min-delta
+            window horizontal ignore trail noup nodown pixelwise))
         delta))
    ((> delta 0)
-    (min (window-max-delta window horizontal ignore trail noup nodown)
+    (min (window-max-delta
+         window horizontal ignore trail noup nodown pixelwise)
         delta))
    (t 0)))
 
-(defun window-resizable-p (window delta &optional horizontal ignore trail noup nodown)
+(defun window--resizable-p (window delta &optional horizontal ignore trail noup nodown pixelwise)
   "Return t if WINDOW can be resized vertically by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
 For the meaning of the arguments of this function see the
-doc-string of `window--resizable'."
+doc-string of `window--resizable'.
+
+Optional argument PIXELWISE non-nil means interpret DELTA as
+pixels."
   (setq window (window-normalize-window window))
   (if (> delta 0)
-      (>= (window--resizable window delta horizontal ignore trail noup nodown)
+      (>= (window--resizable
+          window delta horizontal ignore trail noup nodown pixelwise)
          delta)
-    (<= (window--resizable window delta horizontal ignore trail noup nodown)
+    (<= (window--resizable
+        window delta horizontal ignore trail noup nodown pixelwise)
        delta)))
 
-(defun window-resizable (window delta &optional horizontal ignore)
+(defun window-resizable (window delta &optional horizontal ignore pixelwise)
   "Return DELTA if WINDOW can be resized vertically by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
 Optional argument HORIZONTAL non-nil means return DELTA if WINDOW
@@ -1386,23 +1545,32 @@ imposed by fixed size windows, `window-min-height' or
 restrictions for that window only.  If IGNORE equals `safe',
 live windows may get as small as `window-safe-min-height' lines
 and `window-safe-min-width' columns.  Any other non-nil value
-means ignore all of the above restrictions for all windows."
+means ignore all of the above restrictions for all windows.
+
+Optional argument PIXELWISE non-nil means interpret DELTA as
+pixels."
   (setq window (window-normalize-window window))
-  (window--resizable window delta horizontal ignore))
+  (window--resizable window delta horizontal ignore nil nil nil pixelwise))
 
-(defun window-total-size (&optional window horizontal)
-  "Return the total height or width of WINDOW.
+(defun window-resizable-p (window delta &optional horizontal ignore pixelwise)
+  "Return t if WINDOW can be resized vertically by DELTA lines.
 WINDOW must be a valid window and defaults to the selected one.
+For the meaning of the arguments of this function see the
+doc-string of `window-resizable'."
+  (setq window (window-normalize-window window))
+  (if (> delta 0)
+      (>= (window--resizable
+          window delta horizontal ignore nil nil nil pixelwise)
+         delta)
+    (<= (window--resizable
+        window delta horizontal ignore nil nil nil pixelwise)
+       delta)))
 
-If HORIZONTAL is omitted or nil, return the total height of
-WINDOW, in lines, like `window-total-height'.  Otherwise return
-the total width, in columns, like `window-total-width'."
-  (if horizontal
-      (window-total-width window)
-    (window-total-height window)))
-
-;; Eventually we should make `window-height' obsolete.
+;; Aliases of functions defined in window.c.
 (defalias 'window-height 'window-total-height)
+(defalias 'window-width 'window-body-width)
+
+;; Eventually the following two should work pixelwise.
 
 ;; See discussion in bug#4543.
 (defun window-full-height-p (&optional window)
@@ -1412,8 +1580,8 @@ WINDOW equals the total height of the root window of WINDOW's
 frame.  WINDOW must be a valid window and defaults to the
 selected one."
   (setq window (window-normalize-window window))
-  (= (window-total-size window)
-     (window-total-size (frame-root-window window))))
+  (= (window-pixel-height window)
+     (window-pixel-height (frame-root-window window))))
 
 (defun window-full-width-p (&optional window)
   "Return t if WINDOW is as wide as its containing frame.
@@ -1421,8 +1589,8 @@ More precisely, return t if and only if the total width of WINDOW
 equals the total width of the root window of WINDOW's frame.
 WINDOW must be a valid window and defaults to the selected one."
   (setq window (window-normalize-window window))
-  (= (window-total-size window t)
-     (window-total-size (frame-root-window window) t)))
+  (= (window-pixel-width window)
+     (window-pixel-width (frame-root-window window))))
 
 (defun window-body-size (&optional window horizontal)
   "Return the height or width of WINDOW's text area.
@@ -1435,9 +1603,6 @@ the text area, like `window-body-width'."
       (window-body-width window)
     (window-body-height window)))
 
-;; Eventually we should make `window-height' obsolete.
-(defalias 'window-width 'window-body-width)
-
 (defun window-current-scroll-bars (&optional window)
   "Return the current scroll bar settings for WINDOW.
 WINDOW must be a live window and defaults to the selected one.
@@ -1520,8 +1685,8 @@ SIDE can be any of the symbols `left', `top', `right' or
          ((eq side 'top) 1)
          ((eq side 'right) 2)
          ((memq side '(bottom nil)) 3))))
-    (= (nth edge (window-edges window))
-       (nth edge (window-edges (frame-root-window window))))))
+    (= (nth edge (window-pixel-edges window))
+       (nth edge (window-pixel-edges (frame-root-window window))))))
 
 (defun window-at-side-list (&optional frame side)
   "Return list of all windows on SIDE of FRAME.
@@ -1540,14 +1705,14 @@ SIDE can be any of the symbols `left', `top', `right' or
 (defun window--in-direction-2 (window posn &optional horizontal)
   "Support function for `window-in-direction'."
   (if horizontal
-      (let ((top (window-top-line window)))
+      (let ((top (window-pixel-top window)))
        (if (> top posn)
            (- top posn)
-         (- posn top (window-total-height window))))
-    (let ((left (window-left-column window)))
+         (- posn top (window-pixel-height window))))
+    (let ((left (window-pixel-left window)))
       (if (> left posn)
          (- left posn)
-       (- posn left (window-total-width window))))))
+       (- posn left (window-pixel-width window))))))
 
 ;; Predecessors to the below have been devised by Julian Assange in
 ;; change-windows-intuitively.el and Hovav Shacham in windmove.el.
@@ -1574,29 +1739,27 @@ Return nil if no suitable window can be found."
   (let* ((frame (window-frame window))
         (hor (memq direction '(left right)))
         (first (if hor
-                   (window-left-column window)
-                 (window-top-line window)))
-        (last (+ first (if hor
-                           (window-total-width window)
-                         (window-total-height window))))
-        (posn-cons (nth 6 (posn-at-point (window-point window) window)))
+                   (window-pixel-left window)
+                 (window-pixel-top window)))
+        (last (+ first (window-size window hor t)))
+        (posn-cons (nth 2 (posn-at-point (window-point window) window)))
         ;; The column / row value of `posn-at-point' can be nil for the
         ;; mini-window, guard against that.
         (posn (if hor
-                  (+ (or (cdr posn-cons) 1) (window-top-line window))
-                (+ (or (car posn-cons) 1) (window-left-column window))))
+                  (+ (or (cdr posn-cons) 1) (window-pixel-top window))
+                (+ (or (car posn-cons) 1) (window-pixel-left window))))
         (best-edge
          (cond
-          ((eq direction 'below) (frame-height frame))
-          ((eq direction 'right) (frame-width frame))
+          ((eq direction 'below) (frame-pixel-height frame))
+          ((eq direction 'right) (frame-pixel-width frame))
           (t -1)))
         (best-edge-2 best-edge)
-        (best-diff-2 (if hor (frame-height frame) (frame-width frame)))
+        (best-diff-2 (if hor (frame-pixel-height frame) (frame-pixel-width frame)))
         best best-2 best-diff-2-new)
     (walk-window-tree
      (lambda (w)
-       (let* ((w-top (window-top-line w))
-             (w-left (window-left-column w)))
+       (let* ((w-top (window-pixel-top w))
+             (w-left (window-pixel-left w)))
         (cond
          ((or (eq window w)
               ;; Ignore ourselves.
@@ -1606,7 +1769,7 @@ Return nil if no suitable window can be found."
          (hor
           (cond
            ((and (<= w-top posn)
-                 (< posn (+ w-top (window-total-height w))))
+                 (< posn (+ w-top (window-pixel-height w))))
             ;; W is to the left or right of WINDOW and covers POSN.
             (when (or (and (eq direction 'left)
                            (<= w-left first) (> w-left best-edge))
@@ -1615,7 +1778,7 @@ Return nil if no suitable window can be found."
               (setq best-edge w-left)
               (setq best w)))
            ((and (or (and (eq direction 'left)
-                          (<= (+ w-left (window-total-width w)) first))
+                          (<= (+ w-left (window-pixel-width w)) first))
                      (and (eq direction 'right) (<= last w-left)))
                  ;; W is to the left or right of WINDOW but does not
                  ;; cover POSN.
@@ -1632,7 +1795,7 @@ Return nil if no suitable window can be found."
          (t
           (cond
            ((and (<= w-left posn)
-                 (< posn (+ w-left (window-total-width w))))
+                 (< posn (+ w-left (window-pixel-width w))))
             ;; W is above or below WINDOW and covers POSN.
             (when (or (and (eq direction 'above)
                            (<= w-top first) (> w-top best-edge))
@@ -1641,7 +1804,7 @@ Return nil if no suitable window can be found."
               (setq best-edge w-top)
               (setq best w)))
            ((and (or (and (eq direction 'above)
-                          (<= (+ w-top (window-total-height w)) first))
+                          (<= (+ w-top (window-pixel-height w)) first))
                      (and (eq direction 'below) (<= last w-top)))
                  ;; W is above or below WINDOW but does not cover POSN.
                  (setq best-diff-2-new
@@ -1798,8 +1961,8 @@ selected frame and no others."
     (dolist (window (window-list-1 nil 'nomini all-frames))
       (when (and (or dedicated (not (window-dedicated-p window)))
                 (or (not not-selected) (not (eq window (selected-window)))))
-       (setq size (* (window-total-size window)
-                     (window-total-size window t)))
+       (setq size (* (window-pixel-height window)
+                     (window-pixel-width window)))
        (when (> size best-size)
          (setq best-size size)
          (setq best-window window))))
@@ -1854,11 +2017,106 @@ meaning of this argument."
    (length (window-list-1 nil minibuf)))
 \f
 ;;; Resizing windows.
+(defun window--size-to-pixel (window size &optional horizontal pixelwise round-maybe)
+  "For WINDOW convert SIZE lines to pixels.
+SIZE is supposed to specify a height of WINDOW in terms of text
+lines.  The return value is the number of pixels specifying that
+height.
+
+WINDOW must be a valid window.  Optional argument HORIZONTAL
+non-nil means convert SIZE columns to pixels.
+
+Optional argument PIXELWISE non-nil means SIZE already specifies
+pixels but may have to be adjusted to a multiple of the character
+size of WINDOW's frame.  Optional argument ROUND-MAYBE non-nil
+means round to the nearest multiple of the character size of
+WINDOW's frame if the option `window-resize-pixelwise' is nil."
+  (setq window (window-normalize-window window))
+  (let ((char-size (frame-char-size window horizontal)))
+    (if pixelwise
+       (if (and round-maybe (not window-resize-pixelwise))
+           (* (round size char-size) char-size)
+         size)
+      (* size char-size))))
+
+(defun window--pixel-to-size (window size &optional horizontal round-up)
+  "For WINDOW convert SIZE pixels to lines.
+WINDOW must be a valid window and defaults to the selected one.
+Optional argument HORIZONTAL non-nil means convert SIZE pixels to
+columns.  Optional argument ROUND-UP means to round up the return
+value."
+  (let ((char-size (frame-char-size
+                   (window-normalize-window window) horizontal)))
+    (if round-up
+       (/ (+ size char-size -1) char-size)
+      (/ size char-size))))
+
+(defun window--pixel-to-total-1 (window horizontal char-size)
+  "Subroutine of `window--pixel-to-total'."
+  (let ((child (window-child window)))
+    (if (window-combination-p window horizontal)
+       ;; In an iso-combination distribute sizes proportionally.
+       (let ((remainder (window-new-total window))
+             size best-child best-size)
+         ;; Initialize total sizes to each child's floor.
+         (while child
+           (setq size (window--pixel-to-size
+                       child (window-size child horizontal t)
+                       horizontal))
+           (set-window-new-total child size)
+           (setq remainder (- remainder size))
+           (setq child (window-next-sibling child)))
+         ;; Distribute remainder.
+         (while (> remainder 0)
+           (setq child (window-last-child window))
+           (setq best-child nil)
+           (setq best-size 0)
+           ;; We want those auxiliary fields in the window structure to
+           ;; avoid this.
+           (while child
+             (setq size (- (/ (window-size child horizontal t) char-size)
+                           (window-new-total child)))
+             (when (> size best-size)
+               (setq best-child child)
+               (setq best-size size))
+             (setq child (window-prev-sibling child)))
+           ;; We MUST have a best-child here.
+           (set-window-new-total best-child 1 t)
+           (setq remainder (1- remainder)))
+         ;; Recurse.
+         (setq child (window-child window))
+         (while child
+           (window--pixel-to-total-1 child horizontal char-size)
+           (setq child (window-next-sibling child))))
+      ;; In an ortho-combination assign new sizes directly.
+      (let ((size (window-new-total window)))
+       (while child
+         (set-window-new-total child size)
+         (window--pixel-to-total-1 child horizontal char-size)
+         (setq child (window-next-sibling child)))))))
+
+(defun window--pixel-to-total (&optional frame horizontal)
+  "On FRAME assign new total window heights from pixel heights.
+FRAME must be a live frame and defaults to the selected frame.
+
+Optional argument HORIZONTAL non-nil means assign new total
+window widths from pixel widths."
+  (setq frame (window-normalize-frame frame))
+  (let ((root (frame-root-window))
+       (char-size (frame-char-size frame horizontal))
+       (mini (minibuffer-window frame)))
+    (set-window-new-total
+     root (window--pixel-to-size
+          root (window-size root horizontal t) horizontal))
+    (unless (window-buffer root)
+      (window--pixel-to-total-1 root horizontal char-size)))
+  (window-resize-apply-total frame horizontal))
+
 (defun window--resize-reset (&optional frame horizontal)
   "Reset resize values for all windows on FRAME.
 FRAME defaults to the selected frame.
 
-This function stores the current value of `window-total-size' applied
+This function stores the current value of `window-size' applied
 with argument HORIZONTAL in the new total size of all windows on
 FRAME.  It also resets the new normal size of each of these
 windows."
@@ -1868,7 +2126,8 @@ windows."
 (defun window--resize-reset-1 (window horizontal)
   "Internal function of `window--resize-reset'."
   ;; Register old size in the new total size.
-  (set-window-new-total window (window-total-size window horizontal))
+  (set-window-new-pixel window (window-size window horizontal t))
+  (set-window-new-total window (window-size window horizontal))
   ;; Reset new normal size.
   (set-window-new-normal window)
   (when (window-child window)
@@ -1879,35 +2138,51 @@ windows."
 ;; The following routine is used to manually resize the minibuffer
 ;; window and is currently used, for example, by ispell.el.
 (defun window--resize-mini-window (window delta)
-  "Resize minibuffer window WINDOW by DELTA lines.
-If WINDOW cannot be resized by DELTA lines make it as large (or
+  "Resize minibuffer window WINDOW by DELTA pixels.
+If WINDOW cannot be resized by DELTA pixels make it as large (or
 as small) as possible, but don't signal an error."
   (when (window-minibuffer-p window)
     (let* ((frame (window-frame window))
           (root (frame-root-window frame))
-          (height (window-total-size window))
+          (height (window-pixel-height window))
           (min-delta
-           (- (window-total-size root)
-              (window-min-size root))))
+           (- (window-pixel-height root)
+              (window-min-size root nil nil t))))
       ;; Sanitize DELTA.
       (cond
        ((<= (+ height delta) 0)
-       (setq delta (- (- height 1))))
+       (setq delta (- (frame-char-height (window-frame window)) height)))
        ((> delta min-delta)
        (setq delta min-delta)))
 
-      ;; Resize now.
-      (window--resize-reset frame)
-      ;; Ideally we should be able to resize just the last child of root
-      ;; here.  See the comment in `resize-root-window-vertically' for
-      ;; why we do not do that.
-      (window--resize-this-window root (- delta) nil nil t)
-      (set-window-new-total window (+ height delta))
-      ;; The following routine catches the case where we want to resize
-      ;; a minibuffer-only frame.
-      (resize-mini-window-internal window))))
-
-(defun window-resize (window delta &optional horizontal ignore)
+      (unless (zerop delta)
+       ;; Resize now.
+       (window--resize-reset frame)
+       ;; Ideally we should be able to resize just the last child of root
+       ;; here.  See the comment in `resize-root-window-vertically' for
+       ;; why we do not do that.
+       (window--resize-this-window root (- delta) nil nil t)
+       (set-window-new-pixel window (+ height delta))
+       ;; The following routine catches the case where we want to resize
+       ;; a minibuffer-only frame.
+       (when (resize-mini-window-internal window)
+         (window--pixel-to-total frame)
+         (run-window-configuration-change-hook frame))))))
+
+(defun window--resize-apply-p (frame &optional horizontal)
+  "Return t when a window on FRAME shall be resized vertically.
+Optional argument HORIZONTAL non-nil means return t when a window
+shall be resized horizontally."
+(catch 'apply
+    (walk-window-tree
+     (lambda (window)
+       (unless (= (window-new-pixel window)
+                 (window-size window horizontal t))
+        (throw 'apply t)))
+     frame t)
+    nil))
+
+(defun window-resize (window delta &optional horizontal ignore pixelwise)
   "Resize WINDOW vertically by DELTA lines.
 WINDOW can be an arbitrary window and defaults to the selected
 one.  An attempt to resize the root window of a frame will raise
@@ -1930,6 +2205,9 @@ live windows may get as small as `window-safe-min-height' lines
 and `window-safe-min-width' columns.  Any other non-nil value
 means ignore all of the above restrictions for all windows.
 
+Optional argument PIXELWISE non-nil means resize WINDOW by DELTA
+pixels.
+
 This function resizes other windows proportionally and never
 deletes any windows.  If you want to move only the low (right)
 edge of WINDOW consider using `adjust-window-trailing-edge'
@@ -1938,6 +2216,8 @@ instead."
   (let* ((frame (window-frame window))
         (minibuffer-window (minibuffer-window frame))
         sibling)
+    (setq delta (window--size-to-pixel
+                window delta horizontal pixelwise t))
     (cond
      ((eq window (frame-root-window frame))
       (error "Cannot resize the root window of a frame"))
@@ -1954,19 +2234,21 @@ instead."
       ;; nil or the minibuffer window is active, resize the minibuffer
       ;; window.
       (window--resize-mini-window minibuffer-window (- delta)))
-     ((window-resizable-p window delta horizontal ignore)
+     ((window--resizable-p
+       window delta horizontal ignore nil nil nil t)
       (window--resize-reset frame horizontal)
       (window--resize-this-window window delta horizontal ignore t)
       (if (and (not window-combination-resize)
               (window-combined-p window horizontal)
               (setq sibling (or (window-right window) (window-left window)))
-              (window-sizable-p sibling (- delta) horizontal ignore))
+              (window-sizable-p
+               sibling (- delta) horizontal ignore t))
          ;; If window-combination-resize is nil, WINDOW is part of an
          ;; iso-combination, and WINDOW's neighboring right or left
          ;; sibling can be resized as requested, resize that sibling.
          (let ((normal-delta
                 (/ (float delta)
-                   (window-total-size (window-parent window) horizontal))))
+                   (window-size (window-parent window) horizontal t))))
            (window--resize-this-window sibling (- delta) horizontal nil t)
            (set-window-new-normal
             window (+ (window-normal-size window horizontal)
@@ -1976,17 +2258,24 @@ instead."
                        normal-delta)))
        ;; Otherwise, resize all other windows in the same combination.
        (window--resize-siblings window delta horizontal ignore))
-      (window-resize-apply frame horizontal))
+      (when (window--resize-apply-p frame horizontal)
+       (window-resize-apply frame horizontal)
+       (window--pixel-to-total frame horizontal)
+       (run-window-configuration-change-hook frame)))
      (t
       (error "Cannot resize window %s" window)))))
 
-(defun window-resize-no-error (window delta &optional horizontal ignore)
+(defun window-resize-no-error (window delta &optional horizontal ignore pixelwise)
   "Resize WINDOW vertically if it is resizable by DELTA lines.
 This function is like `window-resize' but does not signal an
 error when WINDOW cannot be resized.  For the meaning of the
-optional arguments see the documentation of `window-resize'."
-  (when (window-resizable-p window delta horizontal ignore)
-    (window-resize window delta horizontal ignore)))
+optional arguments see the documentation of `window-resize'.
+
+Optional argument PIXELWISE non-nil means interpret DELTA as
+pixels."
+  (when (window--resizable-p
+        window delta horizontal ignore nil nil nil pixelwise)
+    (window-resize window delta horizontal ignore pixelwise)))
 
 (defun window--resize-child-windows-skip-p (window)
   "Return non-nil if WINDOW shall be skipped by resizing routines."
@@ -2004,7 +2293,8 @@ OTHER-DELTA, a number, specifies that this many lines (columns)
 have been obtained from (or returned to) an ancestor window of
 PARENT in order to resize WINDOW."
   (let* ((delta-normal
-         (if (and (= (- this-delta) (window-total-size window horizontal))
+         (if (and (= (- this-delta)
+                     (window-size window horizontal t))
                   (zerop other-delta))
              ;; When WINDOW gets deleted and we can return its entire
              ;; space to its siblings, use WINDOW's normal size as the
@@ -2012,7 +2302,8 @@ PARENT in order to resize WINDOW."
              (- (window-normal-size window horizontal))
            ;; In any other case calculate the normal delta from the
            ;; relation of THIS-DELTA to the total size of PARENT.
-           (/ (float this-delta) (window-total-size parent horizontal))))
+           (/ (float this-delta)
+              (window-size parent horizontal t))))
         (sub (window-child parent))
         (parent-normal 0.0)
         (skip (eq trail 'after)))
@@ -2054,8 +2345,8 @@ PARENT in order to resize WINDOW."
     (when (numberp other-delta)
       ;; Set the new normal size of windows from what they should have
       ;; contributed for recovering OTHER-DELTA lines (columns).
-      (setq delta-normal (/ (float (window-total-size parent horizontal))
-                           (+ (window-total-size parent horizontal)
+      (setq delta-normal (/ (float (window-size parent horizontal t))
+                           (+ (window-size parent horizontal t)
                               other-delta)))
       (setq sub (window-child parent))
       (setq skip (eq trail 'after))
@@ -2089,16 +2380,16 @@ PARENT in order to resize WINDOW."
        ;; Don't get larger than 1 or smaller than 0.
        (min 1.0 (max (- 1.0 sum) 0.0))))))
 
-(defun window--resize-child-windows (parent delta &optional horizontal window ignore trail edge)
-  "Resize child windows of window PARENT vertically by DELTA lines.
+(defun window--resize-child-windows (parent delta &optional horizontal window ignore trail edge char-size)
+  "Resize child windows of window PARENT vertically by DELTA pixels.
 PARENT must be a vertically combined internal window.
 
-Optional argument HORIZONTAL non-nil means resize child windows of
-PARENT horizontally by DELTA columns.  In this case PARENT must
+Optional argument HORIZONTAL non-nil means resize child windows
+of PARENT horizontally by DELTA pixels.  In this case PARENT must
 be a horizontally combined internal window.
 
 WINDOW, if specified, must denote a child window of PARENT that
-is resized by DELTA lines.
+is resized by DELTA pixels.
 
 Optional argument IGNORE non-nil means ignore restrictions
 imposed by fixed size windows, `window-min-height' or
@@ -2114,12 +2405,21 @@ resize only windows on the left or above EDGE.  If TRAIL equals
 `after', resize only windows on the right or below EDGE.  Also,
 preferably only resize windows adjacent to EDGE.
 
+If the optional argument CHAR-SIZE is a positive integer, it specifies
+the number of pixels by which windows are incrementally resized.
+If CHAR-SIZE is nil, this means to use the value of
+`frame-char-height' or `frame-char-width' of WINDOW's frame.
+
 Return the symbol `normalized' if new normal sizes have been
 already set by this routine."
   (let* ((first (window-child parent))
         (last (window-last-child parent))
-        (parent-total (+ (window-total-size parent horizontal) delta))
-        sub best-window best-value)
+        (parent-total (+ (window-size parent horizontal t)
+                         delta))
+        (char-size (or char-size
+                       (and window-resize-pixelwise 1)
+                       (frame-char-size window horizontal)))
+        sub best-window best-value best-delta)
 
     (if (and edge (memq trail '(before after))
             (progn
@@ -2134,16 +2434,14 @@ already set by this routine."
               sub)
             (if horizontal
                 (if (eq trail 'before)
-                    (= (+ (window-left-column sub)
-                          (window-total-size sub t))
+                    (= (+ (window-pixel-left sub) (window-pixel-width sub))
                        edge)
-                  (= (window-left-column sub) edge))
+                  (= (window-pixel-left sub) edge))
               (if (eq trail 'before)
-                  (= (+ (window-top-line sub)
-                        (window-total-size sub))
+                  (= (+ (window-pixel-top sub) (window-pixel-height sub))
                      edge)
-                (= (window-top-line sub) edge)))
-            (window-sizable-p sub delta horizontal ignore))
+                (= (window-pixel-top sub) edge)))
+            (window-sizable-p sub delta horizontal ignore t))
        ;; Resize only windows adjacent to EDGE.
        (progn
          (window--resize-this-window
@@ -2152,7 +2450,7 @@ already set by this routine."
              (progn
                ;; Assign new normal sizes.
                (set-window-new-normal
-                sub (/ (float (window-new-total sub)) parent-total))
+                sub (/ (float (window-new-pixel sub)) parent-total))
                (set-window-new-normal
                 window (- (window-normal-size window horizontal)
                           (- (window-new-normal sub)
@@ -2180,15 +2478,15 @@ already set by this routine."
           sub
           (cons
            ;; We used to call this with NODOWN t, "fixed" 2011-05-11.
-           (window-min-delta sub horizontal ignore trail t) ; t)
-           (- (/ (float (window-total-size sub horizontal))
+           (window-min-delta sub horizontal ignore trail t nil t)
+           (- (/ (float (window-size sub horizontal t))
                  parent-total)
               (window-normal-size sub horizontal)))))
         ((> delta 0)
          ;; When enlarging store the total/normal size factor only
          (set-window-new-normal
           sub
-          (- (/ (float (window-total-size sub horizontal))
+          (- (/ (float (window-size sub horizontal t))
                 parent-total)
              (window-normal-size sub horizontal)))))
 
@@ -2212,16 +2510,18 @@ already set by this routine."
            (setq sub (window-left sub)))
 
          (when best-window
-           (setq delta (1+ delta)))
-         (set-window-new-total best-window -1 t)
-         (set-window-new-normal
-          best-window
-          (if (= (car (window-new-normal best-window)) 1)
-              'skip ; We can't shrink best-window any further.
-            (cons (1- (car (window-new-normal best-window)))
-                  (- (/ (float (window-new-total best-window))
-                        parent-total)
-                     (window-normal-size best-window horizontal)))))))
+           (setq best-delta (min (car (window-new-normal best-window))
+                                 char-size (- delta)))
+           (setq delta (+ delta best-delta))
+           (set-window-new-pixel best-window (- best-delta) t)
+           (set-window-new-normal
+            best-window
+            (if (= (car (window-new-normal best-window)) best-delta)
+                'skip      ; We can't shrink best-window any further.
+              (cons (1- (car (window-new-normal best-window)))
+                    (- (/ (float (window-new-pixel best-window))
+                          parent-total)
+                       (window-normal-size best-window horizontal))))))))
        ((> delta 0)
        ;; Enlarge windows by delta.
        (setq best-window t)
@@ -2238,13 +2538,14 @@ already set by this routine."
            (setq sub (window-left sub)))
 
          (when best-window
-           (setq delta (1- delta)))
-         (set-window-new-total best-window 1 t)
-         (set-window-new-normal
-          best-window
-          (- (/ (float (window-new-total best-window))
-                parent-total)
-             (window-normal-size best-window horizontal))))))
+           (setq best-delta (min delta char-size))
+           (setq delta (- delta best-delta))
+           (set-window-new-pixel best-window best-delta t)
+           (set-window-new-normal
+            best-window
+            (- (/ (float (window-new-pixel best-window))
+                  parent-total)
+               (window-normal-size best-window horizontal)))))))
 
       (when best-window
        (setq sub last)
@@ -2258,8 +2559,8 @@ already set by this routine."
          (unless (eq (window-new-normal sub) 'ignore)
            ;; Resize this window's child windows (back-engineering
            ;; delta from sub's old and new total sizes).
-           (let ((delta (- (window-new-total sub)
-                           (window-total-size sub horizontal))))
+           (let ((delta (- (window-new-pixel sub)
+                           (window-size sub horizontal t))))
              (unless (and (zerop delta) (not trail))
                ;; For the TRAIL non-nil case we have to resize SUB
                ;; recursively even if it's size does not change.
@@ -2267,10 +2568,10 @@ already set by this routine."
                 sub delta horizontal ignore nil trail edge))))
          (setq sub (window-left sub)))))))
 
-(defun window--resize-siblings (window delta &optional horizontal ignore trail edge)
-  "Resize other windows when WINDOW is resized vertically by DELTA lines.
+(defun window--resize-siblings (window delta &optional horizontal ignore trail edge char-size)
+  "Resize other windows when WINDOW is resized vertically by DELTA pixels.
 Optional argument HORIZONTAL non-nil means resize other windows
-when WINDOW is resized horizontally by DELTA columns.  WINDOW
+when WINDOW is resized horizontally by DELTA pixels.  WINDOW
 itself is not resized by this function.
 
 Optional argument IGNORE non-nil means ignore restrictions
@@ -2315,7 +2616,7 @@ preferably only resize windows adjacent to EDGE."
              (setq sub (window-right sub)))
 
            ;; Set this-delta to what we can get from WINDOW's siblings.
-           (if (= (- delta) (window-total-size window horizontal))
+           (if (= (- delta) (window-size window horizontal t))
                ;; A deletion, presumably.  We must handle this case
                ;; specially since `window--resizable' can't be used.
                (if this-delta
@@ -2326,7 +2627,8 @@ preferably only resize windows adjacent to EDGE."
                  (setq this-delta 0))
              ;; Any other form of resizing.
              (setq this-delta
-                   (window--resizable window delta horizontal ignore trail t)))
+                   (window--resizable
+                    window delta horizontal ignore trail t nil t)))
 
            ;; Set other-delta to what we still have to get from
            ;; ancestor windows of parent.
@@ -2334,7 +2636,7 @@ preferably only resize windows adjacent to EDGE."
            (unless (zerop other-delta)
              ;; Unless we got everything from WINDOW's siblings, PARENT
              ;; must be resized by other-delta lines or columns.
-             (set-window-new-total parent other-delta 'add))
+             (set-window-new-pixel parent other-delta 'add))
 
            (if (zerop this-delta)
                ;; We haven't got anything from WINDOW's siblings but we
@@ -2345,7 +2647,7 @@ preferably only resize windows adjacent to EDGE."
              ;; we have to resize their child windows.
              (unless (eq (window--resize-child-windows
                           parent (- this-delta) horizontal
-                          window ignore trail edge)
+                          window ignore trail edge char-size)
                          ;; If `window--resize-child-windows' returns
                          ;; 'normalized, this means it has set the
                          ;; normal sizes already.
@@ -2359,21 +2661,22 @@ preferably only resize windows adjacent to EDGE."
 
        ;; In an ortho-combination all siblings of WINDOW must be
        ;; resized by DELTA.
-       (set-window-new-total parent delta 'add)
+       (set-window-new-pixel parent delta 'add)
        (while sub
          (unless (eq sub window)
-           (window--resize-this-window sub delta horizontal ignore t))
+           (window--resize-this-window
+            sub delta horizontal ignore t))
          (setq sub (window-right sub))))
 
       (unless (zerop delta)
        ;; "Go up."
        (window--resize-siblings
-        parent delta horizontal ignore trail edge)))))
+        parent delta horizontal ignore trail edge char-size)))))
 
-(defun window--resize-this-window (window delta &optional horizontal ignore add trail edge)
-  "Resize WINDOW vertically by DELTA lines.
+(defun window--resize-this-window (window delta &optional horizontal ignore add trail edge char-size)
+  "Resize WINDOW vertically by DELTA pixels.
 Optional argument HORIZONTAL non-nil means resize WINDOW
-horizontally by DELTA columns.
+horizontally by DELTA pixels.
 
 Optional argument IGNORE non-nil means ignore restrictions
 imposed by fixed size windows, `window-min-height' or
@@ -2392,6 +2695,11 @@ resize only windows on the left or above EDGE.  If TRAIL equals
 `after', resize only windows on the right or below EDGE.  Also,
 preferably only resize windows adjacent to EDGE.
 
+If the optional argument CHAR-SIZE is a positive integer, it specifies
+the number of pixels by which windows are incrementally resized.
+If CHAR-SIZE is nil, this means to use the value of
+`frame-char-height' or `frame-char-width' of WINDOW's frame.
+
 This function recursively resizes WINDOW's child windows to fit the
 new size.  Make sure that WINDOW is `window--resizable' before
 calling this function.  Note that this function does not resize
@@ -2400,7 +2708,7 @@ eventually call `window-resize-apply' in order to make resizing
 actually take effect."
   (when add
     ;; Add DELTA to the new total size of WINDOW.
-    (set-window-new-total window delta t))
+    (set-window-new-pixel window delta t))
 
   (let ((sub (window-child window)))
     (cond
@@ -2409,15 +2717,15 @@ actually take effect."
       ;; In an iso-combination resize child windows according to their
       ;; normal sizes.
       (window--resize-child-windows
-       window delta horizontal nil ignore trail edge))
+       window delta horizontal nil ignore trail edge char-size))
      ;; In an ortho-combination resize each child window by DELTA.
      (t
       (while sub
        (window--resize-this-window
-        sub delta horizontal ignore t trail edge)
+        sub delta horizontal ignore t trail edge char-size)
        (setq sub (window-right sub)))))))
 
-(defun window--resize-root-window (window delta horizontal ignore)
+(defun window--resize-root-window (window delta horizontal ignore pixelwise)
   "Resize root window WINDOW vertically by DELTA lines.
 HORIZONTAL non-nil means resize root window WINDOW horizontally
 by DELTA columns.
@@ -2427,57 +2735,74 @@ size windows, `window-min-height' or `window-min-width' settings.
 
 This function is only called by the frame resizing routines.  It
 resizes windows proportionally and never deletes any windows."
-  (when (and (windowp window) (numberp delta)
-            (window-sizable-p window delta horizontal ignore))
-    (window--resize-reset (window-frame window) horizontal)
-    (window--resize-this-window window delta horizontal ignore t)))
+  (when (and (windowp window) (numberp delta))
+    (let ((pixel-delta
+          (if pixelwise
+              delta
+            (window--size-to-pixel window delta horizontal))))
+      (when (window-sizable-p window pixel-delta horizontal ignore t)
+       (window--resize-reset (window-frame window) horizontal)
+       (window--resize-this-window
+        window pixel-delta horizontal ignore t)))))
 
-(defun window--resize-root-window-vertically (window delta)
+(defun window--resize-root-window-vertically (window delta pixelwise)
   "Resize root window WINDOW vertically by DELTA lines.
 If DELTA is less than zero and we can't shrink WINDOW by DELTA
 lines, shrink it as much as possible.  If DELTA is greater than
 zero, this function can resize fixed-size windows in order to
-recover the necessary lines.
+recover the necessary lines.  Return the number of lines that
+were recovered.
 
-Return the number of lines that were recovered.
+Third argument PIXELWISE non-nil means to intepret DELTA as
+pixels and return the number of pixels that were recovered.
 
-This function is only called by the minibuffer window resizing
-routines.  It resizes windows proportionally and never deletes
-any windows."
-  (let ((frame (window-frame window))
-       ignore)
+This function is called by the minibuffer window resizing
+routines."
+  (let* ((frame (window-frame window))
+        (pixel-delta
+         (cond
+          (pixelwise
+           delta)
+          ((numberp delta)
+           (* (frame-char-height frame) delta))
+          (t 0)))
+        ignore)
     (cond
-     ((not (numberp delta))
-      (setq delta 0))
-     ((zerop delta))
-     ((< delta 0)
-      (setq delta (window-sizable window delta))
+     ((zerop pixel-delta))
+     ((< pixel-delta 0)
+      (setq pixel-delta (window-sizable window pixel-delta nil nil pixelwise))
       (window--resize-reset frame)
       ;; When shrinking the root window, emulate an edge drag in order
       ;; to not resize other windows if we can avoid it (Bug#12419).
       (window--resize-this-window
-       window delta nil ignore t 'before
-       (+ (window-top-line window) (window-total-size window)))
+       window pixel-delta nil ignore t 'before
+       (+ (window-pixel-top window) (window-pixel-height window)))
       ;; Don't record new normal sizes to make sure that shrinking back
       ;; proportionally works as intended.
       (walk-window-tree
        (lambda (window) (set-window-new-normal window 'ignore)) frame t))
-     ((> delta 0)
+     ((> pixel-delta 0)
       (window--resize-reset frame)
-      (unless (window-sizable window delta)
+      (unless (window-sizable window pixel-delta nil nil pixelwise)
        (setq ignore t))
       ;; When growing the root window, resize proportionally.  This
       ;; should give windows back their original sizes (hopefully).
-      (window--resize-this-window window delta nil ignore t)))
+      (window--resize-this-window
+       window pixel-delta nil ignore t)))
      ;; Return the possibly adjusted DELTA.
-     delta))
+     (if pixelwise
+        pixel-delta
+       (/ pixel-delta (frame-char-height frame)))))
 
-(defun adjust-window-trailing-edge (window delta &optional horizontal)
+(defun adjust-window-trailing-edge (window delta &optional horizontal pixelwise)
   "Move WINDOW's bottom edge by DELTA lines.
 Optional argument HORIZONTAL non-nil means move WINDOW's right
 edge by DELTA columns.  WINDOW must be a valid window and
 defaults to the selected one.
 
+Optional argument PIXELWISE non-nil means interpret DELTA as
+number of pixels.
+
 If DELTA is greater than zero, move the edge downwards or to the
 right.  If DELTA is less than zero, move the edge upwards or to
 the left.  If the edge can't be moved by DELTA lines or columns,
@@ -2487,6 +2812,11 @@ move it as far as possible in the desired direction."
         (minibuffer-window (minibuffer-window frame))
         (right window)
         left this-delta min-delta max-delta)
+
+    (unless pixelwise
+      (setq pixelwise t)
+      (setq delta (* delta (frame-char-size window horizontal))))
+
     ;; Find the edge we want to move.
     (while (and (or (not (window-combined-p right horizontal))
                    (not (window-right right)))
@@ -2497,8 +2827,8 @@ move it as far as possible in the desired direction."
           ;; and immediately below WINDOW and it's either active or
           ;; `resize-mini-windows' is nil.
           (eq (window-frame minibuffer-window) frame)
-          (= (nth 1 (window-edges minibuffer-window))
-             (nth 3 (window-edges window)))
+          (= (nth 1 (window-pixel-edges minibuffer-window))
+             (nth 3 (window-pixel-edges window)))
           (or (not resize-mini-windows)
               (eq minibuffer-window (active-minibuffer-window))))
       (window--resize-mini-window minibuffer-window (- delta)))
@@ -2539,8 +2869,12 @@ move it as far as possible in the desired direction."
       ;; two windows we want to resize.
       (cond
        ((> delta 0)
-       (setq max-delta (window--max-delta-1 left 0 horizontal nil 'after))
-       (setq min-delta (window--min-delta-1 right (- delta) horizontal nil 'before))
+       (setq max-delta
+             (window--max-delta-1
+              left 0 horizontal nil 'after nil pixelwise))
+       (setq min-delta
+             (window--min-delta-1
+              right (- delta) horizontal nil 'before nil pixelwise))
        (when (or (< max-delta delta) (> min-delta (- delta)))
          ;; We can't get the whole DELTA - move as far as possible.
          (setq delta (min max-delta (- min-delta))))
@@ -2548,22 +2882,27 @@ move it as far as possible in the desired direction."
          ;; Start resizing.
          (window--resize-reset frame horizontal)
          ;; Try to enlarge LEFT first.
-         (setq this-delta (window--resizable left delta horizontal))
+         (setq this-delta (window--resizable
+                           left delta horizontal nil nil nil nil pixelwise))
          (unless (zerop this-delta)
            (window--resize-this-window
             left this-delta horizontal nil t 'before
             (if horizontal
-                (+ (window-left-column left) (window-total-size left t))
-              (+ (window-top-line left) (window-total-size left)))))
+                (+ (window-pixel-left left) (window-pixel-width left))
+              (+ (window-pixel-top left) (window-pixel-height left)))))
          ;; Shrink windows on right of LEFT.
          (window--resize-siblings
           left delta horizontal nil 'after
           (if horizontal
-              (window-left-column right)
-            (window-top-line right)))))
+              (window-pixel-left right)
+            (window-pixel-top right)))))
        ((< delta 0)
-       (setq max-delta (window--max-delta-1 right 0 horizontal nil 'before))
-       (setq min-delta (window--min-delta-1 left delta horizontal nil 'after))
+       (setq max-delta
+             (window--max-delta-1
+              right 0 horizontal nil 'before nil pixelwise))
+       (setq min-delta
+             (window--min-delta-1
+              left delta horizontal nil 'after nil pixelwise))
        (when (or (< max-delta (- delta)) (> min-delta delta))
          ;; We can't get the whole DELTA - move as far as possible.
          (setq delta (max (- max-delta) min-delta)))
@@ -2571,24 +2910,30 @@ move it as far as possible in the desired direction."
          ;; Start resizing.
          (window--resize-reset frame horizontal)
          ;; Try to enlarge RIGHT.
-         (setq this-delta (window--resizable right (- delta) horizontal))
+         (setq this-delta
+               (window--resizable
+                right (- delta) horizontal nil nil nil nil pixelwise))
          (unless (zerop this-delta)
            (window--resize-this-window
             right this-delta horizontal nil t 'after
             (if horizontal
-                (window-left-column right)
-              (window-top-line right))))
+                (window-pixel-left right)
+              (window-pixel-top right))))
          ;; Shrink windows on left of RIGHT.
          (window--resize-siblings
           right (- delta) horizontal nil 'before
           (if horizontal
-              (+ (window-left-column left) (window-total-size left t))
-            (+ (window-top-line left) (window-total-size left)))))))
+              (+ (window-pixel-left left) (window-pixel-width left))
+            (+ (window-pixel-top left) (window-pixel-height left)))))))
       (unless (zerop delta)
        ;; Don't report an error in the standard case.
-       (unless (window-resize-apply frame horizontal)
-         ;; But do report an error if applying the changes fails.
-         (error "Failed adjusting window %s" window)))))))
+       (when (window--resize-apply-p frame horizontal)
+         (if (window-resize-apply frame horizontal)
+             (progn
+               (window--pixel-to-total frame horizontal)
+               (run-window-configuration-change-hook frame))
+           ;; But do report an error if applying the changes fails.
+           (error "Failed adjusting window %s" window))))))))
 
 (defun enlarge-window (delta &optional horizontal)
   "Make the selected window DELTA lines taller.
@@ -2613,7 +2958,7 @@ negative, shrink selected window by -DELTA lines or columns."
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
       (window--resize-mini-window minibuffer-window (- delta)))
-     ((window-resizable-p nil delta horizontal)
+     ((window--resizable-p nil delta horizontal)
       (window-resize nil delta horizontal))
      (t
       (window-resize
@@ -2646,7 +2991,7 @@ Also see the `window-min-height' variable."
       ;; If the selected window is full height and `resize-mini-windows'
       ;; is nil, resize the minibuffer window.
       (window--resize-mini-window minibuffer-window delta))
-     ((window-resizable-p nil (- delta) horizontal)
+     ((window--resizable-p nil (- delta) horizontal)
       (window-resize nil (- delta) horizontal))
      (t
       (window-resize
@@ -2655,23 +3000,39 @@ Also see the `window-min-height' variable."
             (window-max-delta nil horizontal))
        horizontal)))))
 
-(defun maximize-window (&optional window)
+(defun maximize-window (&optional window pixelwise)
   "Maximize WINDOW.
 Make WINDOW as large as possible without deleting any windows.
-WINDOW must be a valid window and defaults to the selected one."
+WINDOW must be a valid window and defaults to the selected one.
+
+If the option `window-resize-pixelwise' is non-nil maximize
+WINDOW pixelwise."
   (interactive)
   (setq window (window-normalize-window window))
-  (window-resize window (window-max-delta window))
-  (window-resize window (window-max-delta window t) t))
-
-(defun minimize-window (&optional window)
+  (window-resize
+   window (window-max-delta window nil nil nil nil nil window-resize-pixelwise)
+   nil nil window-resize-pixelwise)
+  (window-resize
+   window (window-max-delta window t nil nil nil nil window-resize-pixelwise)
+   t nil window-resize-pixelwise))
+
+(defun minimize-window (&optional window pixelwise)
   "Minimize WINDOW.
 Make WINDOW as small as possible without deleting any windows.
-WINDOW must be a valid window and defaults to the selected one."
+WINDOW must be a valid window and defaults to the selected one.
+
+If the option `window-resize-pixelwise' is non-nil minimize
+WINDOW pixelwise."
   (interactive)
   (setq window (window-normalize-window window))
-  (window-resize window (- (window-min-delta window)))
-  (window-resize window (- (window-min-delta window t)) t))
+  (window-resize
+   window
+   (- (window-min-delta window nil nil nil nil nil window-resize-pixelwise))
+   nil nil window-resize-pixelwise)
+  (window-resize
+   window
+   (- (window-min-delta window t nil nil nil nil window-resize-pixelwise))
+   t nil window-resize-pixelwise))
 \f
 (defun frame-root-window-p (window)
   "Return non-nil if WINDOW is the root window of its frame."
@@ -2914,7 +3275,7 @@ that is its frame's root window."
        (error "Attempt to delete last non-side window")))
 
       (let* ((horizontal (window-left-child parent))
-            (size (window-total-size window horizontal))
+            (size (window-size window horizontal t))
             (frame-selected
              (window--in-subtree-p (frame-selected-window frame) window))
             ;; Emacs 23 preferably gives WINDOW's space to its left
@@ -2923,13 +3284,13 @@ that is its frame's root window."
        (window--resize-reset frame horizontal)
        (cond
         ((and (not window-combination-resize)
-              sibling (window-sizable-p sibling size))
+              sibling (window-sizable-p sibling size horizontal nil t))
          ;; Resize WINDOW's sibling.
          (window--resize-this-window sibling size horizontal nil t)
          (set-window-new-normal
           sibling (+ (window-normal-size sibling horizontal)
                      (window-normal-size window horizontal))))
-        ((window-resizable-p window (- size) horizontal nil nil nil t)
+        ((window--resizable-p window (- size) horizontal nil nil nil t t)
          ;; Can do without resizing fixed-size windows.
          (window--resize-siblings window (- size) horizontal))
         (t
@@ -2937,6 +3298,7 @@ that is its frame's root window."
          (window--resize-siblings window (- size) horizontal t)))
        ;; Actually delete WINDOW.
        (delete-window-internal window)
+       (window--pixel-to-total frame horizontal)
        (when (and frame-selected
                   (window-parameter
                    (frame-selected-window frame) 'no-other-window))
@@ -3608,11 +3970,11 @@ the buffer of WINDOW.  The following values are handled:
           (eq (nth 3 quit-restore) buffer))
       ;; Show another buffer stored in quit-restore parameter.
       (when (and (integerp (nth 3 quad))
-                (/= (nth 3 quad) (window-total-size window)))
+                (/= (nth 3 quad) (window-total-height window)))
        ;; Try to resize WINDOW to its old height but don't signal an
        ;; error.
        (condition-case nil
-           (window-resize window (- (nth 3 quad) (window-total-size window)))
+           (window-resize window (- (nth 3 quad) (window-total-height window)))
          (error nil)))
       (set-window-dedicated-p window nil)
       ;; Restore WINDOW's previous buffer, start and point position.
@@ -3690,14 +4052,20 @@ showing BUFFER-OR-NAME."
        (unrecord-window-buffer window buffer)))))
 \f
 ;;; Splitting windows.
-(defun window-split-min-size (&optional horizontal)
+(defun window-split-min-size (&optional horizontal pixelwise)
   "Return minimum height of any window when splitting windows.
 Optional argument HORIZONTAL non-nil means return minimum width."
-  (if horizontal
-      (max window-min-width window-safe-min-width)
-    (max window-min-height window-safe-min-height)))
+  (cond
+   (pixelwise
+    (if horizontal
+       (window-min-pixel-width)
+      (window-min-pixel-height)))
+   (horizontal
+    (max window-min-width window-safe-min-width))
+   (t
+    (max window-min-height window-safe-min-height))))
 
-(defun split-window (&optional window size side)
+(defun split-window (&optional window size side pixelwise)
   "Make a new window adjacent to WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
 Return the new window which is always a live window.
@@ -3725,6 +4093,8 @@ window provided SIZE is negative) including space reserved for
 fringes and the scrollbar or a divider column.  Any other non-nil
 value for SIDE is currently handled like t (or `right').
 
+PIXELWISE, if non-nil, means to intepret SIZE pixelwise.
+
 If the variable `ignore-window-parameters' is non-nil or the
 `split-window' parameter of WINDOW equals t, do not process any
 parameters of WINDOW.  Otherwise, if the `split-window' parameter
@@ -3754,8 +4124,11 @@ frame.  The selected window is not changed by this function."
         ;; have to override their value.
         (window-combination-limit window-combination-limit)
         (window-combination-resize window-combination-resize)
+        (char-size (frame-char-size window horizontal))
+        (pixel-size
+         (when (numberp size)
+           (window--size-to-pixel window size horizontal pixelwise t)))
         atom-root)
-
     (window--check frame)
     (catch 'done
       (cond
@@ -3771,7 +4144,7 @@ frame.  The selected window is not changed by this function."
        ((and (window-parameter window 'window-atom)
             (setq atom-root (window-atom-root window))
             (not (eq atom-root window)))
-       (throw 'done (split-window atom-root size side)))
+       (throw 'done (split-window atom-root size side pixelwise)))
        ;; If WINDOW is a side window or its first or last child is a
        ;; side window, throw an error unless `window-combination-resize'
        ;; equals 'side.
@@ -3796,13 +4169,14 @@ frame.  The selected window is not changed by this function."
 
       ;; If `window-combination-resize' is t and SIZE is non-negative,
       ;; bind `window-combination-limit' to t.
-      (when (and (eq window-combination-resize t) size (> size 0))
+      (when (and (eq window-combination-resize t)
+                pixel-size (> pixel-size 0))
        (setq window-combination-limit t))
 
-      (let* ((parent-size
-             ;; `parent-size' is the size of WINDOW's parent, provided
-             ;; it has one.
-             (when parent (window-total-size parent horizontal)))
+      (let* ((parent-pixel-size
+             ;; `parent-pixel-size' is the pixel size of WINDOW's
+             ;; parent, provided it has one.
+             (when parent (window-size parent horizontal t)))
             ;; `resize' non-nil means we are supposed to resize other
             ;; windows in WINDOW's combination.
             (resize
@@ -3812,76 +4186,82 @@ frame.  The selected window is not changed by this function."
                   (not (eq window-combination-limit t))
                   ;; Resize makes sense in iso-combinations only.
                   (window-combined-p window horizontal)))
-            ;; `old-size' is the current size of WINDOW.
-            (old-size (window-total-size window horizontal))
+            ;; `old-pixel-size' is the current pixel size of WINDOW.
+            (old-pixel-size (window-size window horizontal t))
             ;; `new-size' is the specified or calculated size of the
             ;; new window.
-            (new-size
-             (cond
-              ((not size)
-               (max (window-split-min-size horizontal)
-                    (if resize
-                        ;; When resizing try to give the new window the
-                        ;; average size of a window in its combination.
-                        (min (- parent-size
-                                (window-min-size parent horizontal))
-                             (/ parent-size
-                                (1+ (window-combinations
-                                     parent horizontal))))
-                      ;; Else try to give the new window half the size
-                      ;; of WINDOW (plus an eventual odd line).
-                      (+ (/ old-size 2) (% old-size 2)))))
-              ((>= size 0)
-               ;; SIZE non-negative specifies the new size of WINDOW.
-
-               ;; Note: Specifying a non-negative SIZE is practically
-               ;; always done as workaround for making the new window
-               ;; appear above or on the left of the new window (the
-               ;; ispell window is a typical example of that).  In all
-               ;; these cases the SIDE argument should be set to 'above
-               ;; or 'left in order to support the 'resize option.
-               ;; Here we have to nest the windows instead, see above.
-               (- old-size size))
-              (t
-               ;; SIZE negative specifies the size of the new window.
-               (- size))))
-            new-parent new-normal)
+            new-pixel-size new new-parent new-normal)
+       (cond
+        ((not pixel-size)
+         (setq new-pixel-size
+               (if resize
+                   ;; When resizing try to give the new window the
+                   ;; average size of a window in its combination.
+                   (min (- parent-pixel-size
+                           (window-min-size parent horizontal nil t))
+                        (/ parent-pixel-size
+                           (1+ (window-combinations parent horizontal))))
+                 ;; Else try to give the new window half the size
+                 ;; of WINDOW (plus an eventual odd pixel).
+                 (/ old-pixel-size 2)))
+         (unless window-resize-pixelwise
+           ;; Round to nearest char-size multiple.
+           (setq new-pixel-size
+                 (* char-size (round new-pixel-size char-size)))))
+        ((>= pixel-size 0)
+         ;; SIZE non-negative specifies the new size of WINDOW.
+
+         ;; Note: Specifying a non-negative SIZE is practically
+         ;; always done as workaround for making the new window
+         ;; appear above or on the left of the new window (the
+         ;; ispell window is a typical example of that).  In all
+         ;; these cases the SIDE argument should be set to 'above
+         ;; or 'left in order to support the 'resize option.
+         ;; Here we have to nest the windows instead, see above.
+         (setq new-pixel-size (- old-pixel-size pixel-size)))
+        (t
+         ;; SIZE negative specifies the size of the new window.
+         (setq new-pixel-size (- pixel-size))))
 
        ;; Check SIZE.
        (cond
-        ((not size)
+        ((not pixel-size)
          (cond
           (resize
            ;; SIZE unspecified, resizing.
-           (when (and (not (window-sizable-p parent (- new-size) horizontal))
+           (when (and (not (window-sizable-p
+                            parent (- new-pixel-size) horizontal nil t))
                       ;; Try again with minimum split size.
-                      (setq new-size
-                            (max new-size (window-split-min-size horizontal)))
-                      (not (window-sizable-p parent (- new-size) horizontal)))
-             (error "Window %s too small for splitting" parent)))
-          ((> (+ new-size (window-min-size window horizontal)) old-size)
+                      (setq new-pixel-size
+                            (max new-pixel-size
+                                 (window-split-min-size horizontal t)))
+                      (not (window-sizable-p
+                            parent (- new-pixel-size) horizontal nil t)))
+             (error "Window %s too small for splitting 1" parent)))
+          ((> (+ new-pixel-size (window-min-size window horizontal nil t))
+              old-pixel-size)
            ;; SIZE unspecified, no resizing.
-           (error "Window %s too small for splitting" window))))
-        ((and (>= size 0)
-              (or (>= size old-size)
-                  (< new-size (if horizontal
-                                  window-safe-min-width
-                                window-safe-min-width))))
+           (error "Window %s too small for splitting 2" window))))
+        ((and (>= pixel-size 0)
+              (or (>= pixel-size old-pixel-size)
+                  (< new-pixel-size
+                     (window-safe-min-pixel-size window horizontal))))
          ;; SIZE specified as new size of old window.  If the new size
          ;; is larger than the old size or the size of the new window
          ;; would be less than the safe minimum, signal an error.
-         (error "Window %s too small for splitting" window))
+         (error "Window %s too small for splitting 3" window))
         (resize
          ;; SIZE specified, resizing.
-         (unless (window-sizable-p parent (- new-size) horizontal)
+         (unless (window-sizable-p
+                  parent (- new-pixel-size) horizontal nil t)
            ;; If we cannot resize the parent give up.
-           (error "Window %s too small for splitting" parent)))
-        ((or (< new-size
-                (if horizontal window-safe-min-width window-safe-min-height))
-             (< (- old-size new-size)
-                (if horizontal window-safe-min-width window-safe-min-height)))
+           (error "Window %s too small for splitting 4" parent)))
+        ((or (< new-pixel-size
+                (window-safe-min-pixel-size window horizontal))
+             (< (- old-pixel-size new-pixel-size)
+                (window-safe-min-pixel-size window horizontal)))
          ;; SIZE specification violates minimum size restrictions.
-         (error "Window %s too small for splitting" window)))
+         (error "Window %s too small for splitting 5" window)))
 
        (window--resize-reset frame horizontal)
 
@@ -3894,7 +4274,8 @@ frame.  The selected window is not changed by this function."
        (setq new-normal
              ;; Make new-normal the normal size of the new window.
              (cond
-              (size (/ (float new-size) (if new-parent old-size parent-size)))
+              (pixel-size (/ (float new-pixel-size)
+                             (if new-parent old-pixel-size parent-pixel-size)))
               (new-parent 0.5)
               (resize (/ 1.0 (1+ (window-combinations parent horizontal))))
               (t (/ (window-normal-size window horizontal) 2.0))))
@@ -3905,7 +4286,8 @@ frame.  The selected window is not changed by this function."
            ;; we won't be able to return space to those windows when we
            ;; delete the one we create here.  Hence we do not go up.
            (progn
-             (window--resize-child-windows parent (- new-size) horizontal)
+             (window--resize-child-windows
+              parent (- new-pixel-size) horizontal)
              (let* ((normal (- 1.0 new-normal))
                     (sub (window-child parent)))
                (while sub
@@ -3913,13 +4295,18 @@ frame.  The selected window is not changed by this function."
                   sub (* (window-normal-size sub horizontal) normal))
                  (setq sub (window-right sub)))))
          ;; Get entire space from WINDOW.
-         (set-window-new-total window (- old-size new-size))
-         (window--resize-this-window window (- new-size) horizontal)
+         (set-window-new-pixel
+          window (- old-pixel-size new-pixel-size))
+;;       (set-window-new-pixel window (- old-pixel-size new-pixel-size))
+;;       (set-window-new-total
+;;        window (- old-size new-size))
+         (window--resize-this-window window (- new-pixel-size) horizontal)
          (set-window-new-normal
           window (- (if new-parent 1.0 (window-normal-size window horizontal))
                     new-normal)))
 
-       (let* ((new (split-window-internal window new-size side new-normal)))
+       (let* ((new (split-window-internal window new-pixel-size side new-normal)))
+         (window--pixel-to-total frame horizontal)
          ;; Assign window-side parameters, if any.
          (cond
           ((eq window-combination-resize 'side)
@@ -3946,6 +4333,7 @@ frame.  The selected window is not changed by this function."
            (set-window-parameter new 'window-atom t)))
 
          (run-window-configuration-change-hook frame)
+         (run-window-scroll-functions new)
          (window--check frame)
          ;; Always return the new window.
          new)))))
@@ -4056,17 +4444,20 @@ right, if any."
   "Subroutine of `balance-windows-1'.
 WINDOW must be a vertical combination (horizontal if HORIZONTAL
 is non-nil)."
-  (let* ((first (window-child window))
+  (let* ((char-size (if window-resize-pixelwise
+                       1
+                     (frame-char-size window horizontal)))
+        (first (window-child window))
         (sub first)
         (number-of-children 0)
-        (parent-size (window-new-total window))
+        (parent-size (window-new-pixel window))
         (total-sum parent-size)
         failed size sub-total sub-delta sub-amount rest)
     (while sub
       (setq number-of-children (1+ number-of-children))
       (when (window-size-fixed-p sub horizontal)
        (setq total-sum
-             (- total-sum (window-total-size sub horizontal)))
+             (- total-sum (window-size sub horizontal t)))
        (set-window-new-normal sub 'ignore))
       (setq sub (window-right sub)))
 
@@ -4078,12 +4469,12 @@ is non-nil)."
       (while (and sub (not failed))
        ;; Ignore child windows that should be ignored or are stuck.
        (unless (window--resize-child-windows-skip-p sub)
-         (setq sub-total (window-total-size sub horizontal))
+         (setq sub-total (window-size sub horizontal t))
          (setq sub-delta (- size sub-total))
          (setq sub-amount
-               (window-sizable sub sub-delta horizontal))
+               (window-sizable sub sub-delta horizontal nil t))
          ;; Register the new total size for this child window.
-         (set-window-new-total sub (+ sub-total sub-amount))
+         (set-window-new-pixel sub (+ sub-total sub-amount))
          (unless (= sub-amount sub-delta)
            (setq total-sum (- total-sum sub-total sub-amount))
            (setq number-of-children (1- number-of-children))
@@ -4092,14 +4483,15 @@ is non-nil)."
            (set-window-new-normal sub 'skip)))
        (setq sub (window-right sub))))
 
+    ;; How can we be sure that `number-of-children' is NOT zero here ?
     (setq rest (% total-sum number-of-children))
     ;; Fix rounding by trying to enlarge non-stuck windows by one line
     ;; (column) until `rest' is zero.
     (setq sub first)
     (while (and sub (> rest 0))
       (unless (window--resize-child-windows-skip-p window)
-       (set-window-new-total sub 1 t)
-       (setq rest (1- rest)))
+       (set-window-new-pixel sub char-size t)
+       (setq rest (- rest char-size)))
       (setq sub (window-right sub)))
 
     ;; Fix rounding by trying to enlarge stuck windows by one line
@@ -4107,8 +4499,8 @@ is non-nil)."
     (setq sub first)
     (while (and sub (> rest 0))
       (unless (eq (window-new-normal sub) 'ignore)
-       (set-window-new-total sub 1 t)
-       (setq rest (1- rest)))
+       (set-window-new-pixel sub char-size t)
+       (setq rest (- rest char-size)))
       (setq sub (window-right sub)))
 
     (setq sub first)
@@ -4116,8 +4508,8 @@ is non-nil)."
       ;; Record new normal sizes.
       (set-window-new-normal
        sub (/ (if (eq (window-new-normal sub) 'ignore)
-                 (window-total-size sub horizontal)
-               (window-new-total sub))
+                 (window-size sub horizontal t)
+               (window-new-pixel sub))
              (float parent-size)))
       ;; Recursively balance each window's child windows.
       (balance-windows-1 sub horizontal)
@@ -4129,9 +4521,9 @@ is non-nil)."
       (let ((sub (window-child window)))
        (if (window-combined-p sub horizontal)
            (balance-windows-2 window horizontal)
-         (let ((size (window-new-total window)))
+         (let ((size (window-new-pixel window)))
            (while sub
-             (set-window-new-total sub size)
+             (set-window-new-pixel sub size)
              (balance-windows-1 sub horizontal)
              (setq sub (window-right sub))))))))
 
@@ -4157,11 +4549,17 @@ window."
     ;; Balance vertically.
     (window--resize-reset (window-frame window))
     (balance-windows-1 window)
-    (window-resize-apply frame)
+    (when (window--resize-apply-p frame)
+      (window-resize-apply frame)
+      (window--pixel-to-total frame)
+      (run-window-configuration-change-hook frame))
     ;; Balance horizontally.
     (window--resize-reset (window-frame window) t)
     (balance-windows-1 window t)
-    (window-resize-apply frame t)))
+    (when (window--resize-apply-p frame t)
+      (window-resize-apply frame)
+      (window--pixel-to-total frame t)
+      (run-window-configuration-change-hook frame))))
 
 (defun window-fixed-size-p (&optional window direction)
   "Return t if WINDOW cannot be resized in DIRECTION.
@@ -4180,14 +4578,17 @@ This is used by `balance-windows-area'.
 Changing this globally has no effect.")
 (make-variable-buffer-local 'window-area-factor)
 
-(defun balance-windows-area-adjust (window delta horizontal)
+(defun balance-windows-area-adjust (window delta horizontal pixelwise)
   "Wrapper around `window-resize' with error checking.
 Arguments WINDOW, DELTA and HORIZONTAL are passed on to that function."
   ;; `window-resize' may fail if delta is too large.
   (while (>= (abs delta) 1)
     (condition-case nil
         (progn
-          (window-resize window delta horizontal)
+         ;; It was wrong to use `window-resize' here.  Somehow
+         ;; `balance-windows-area' depends on resizing windows
+         ;; asymmetrically.
+         (adjust-window-trailing-edge window delta horizontal pixelwise)
           (setq delta 0))
       (error
        ;;(message "adjust: %s" (error-message-string err))
@@ -4204,7 +4605,8 @@ specific buffers."
                                    (if (not (window-fixed-size-p win)) win))
                                  (window-list nil 'nomini))))
          (changelog nil)
-         next)
+        (pixelwise window-resize-pixelwise)
+        next)
     ;; Resizing a window changes the size of surrounding windows in complex
     ;; ways, so it's difficult to balance them all.  The introduction of
     ;; `adjust-window-trailing-edge' made it a bit easier, but it is still
@@ -4228,11 +4630,13 @@ specific buffers."
                       (window-fixed-size-p next)))
         ;; (assert (eq next (or (cadr (member win wins)) (car wins))))
         (let* ((horiz
-                (< (car (window-edges win)) (car (window-edges next))))
-               (areadiff (/ (- (* (window-height next) (window-width next)
+                (< (car (window-pixel-edges win)) (car (window-pixel-edges next))))
+               (areadiff (/ (- (* (window-height next pixelwise)
+                                 (window-width next pixelwise)
                                   (buffer-local-value 'window-area-factor
                                                       (window-buffer next)))
-                               (* (window-height win) (window-width win)
+                               (* (window-height win pixelwise)
+                                 (window-width win pixelwise)
                                   (buffer-local-value 'window-area-factor
                                                       (window-buffer win))))
                             (max (buffer-local-value 'window-area-factor
@@ -4240,8 +4644,10 @@ specific buffers."
                                  (buffer-local-value 'window-area-factor
                                                      (window-buffer next)))))
                (edgesize (if horiz
-                             (+ (window-height win) (window-height next))
-                           (+ (window-width win) (window-width next))))
+                             (+ (window-height win pixelwise)
+                               (window-height next pixelwise))
+                           (+ (window-width win pixelwise)
+                             (window-width next pixelwise))))
                (diff (/ areadiff edgesize)))
           (when (zerop diff)
             ;; Maybe diff is actually closer to 1 than to 0.
@@ -4256,9 +4662,9 @@ specific buffers."
               (setq carry (+ carry areadiff))
            ;; This used `adjust-window-trailing-edge' before and uses
            ;; `window-resize' now.  Error wrapping is still needed.
-           (balance-windows-area-adjust win diff horiz)
+           (balance-windows-area-adjust win diff horiz pixelwise)
             ;; (sit-for 0.5)
-            (let ((change (cons win (window-edges win))))
+            (let ((change (cons win (window-pixel-edges win))))
               ;; If the same change has been seen already for this window,
               ;; we're most likely in an endless loop, so don't count it as
               ;; a change.
@@ -4285,8 +4691,10 @@ specific buffers."
         (head
          `(,type
             ,@(unless (window-next-sibling window) `((last . t)))
-            (total-height . ,(window-total-size window))
-            (total-width . ,(window-total-size window t))
+            (pixel-width . ,(window-pixel-width window))
+            (pixel-height . ,(window-pixel-height window))
+            (total-width . ,(window-total-width window))
+            (total-height . ,(window-total-height window))
             (normal-height . ,(window-normal-size window))
             (normal-width . ,(window-normal-size window t))
             ,@(unless (window-live-p window)
@@ -4372,7 +4780,13 @@ value can be also stored on disk and read back in a new session."
      (min-height-ignore . ,(window-min-size window nil t))
      (min-width-ignore  . ,(window-min-size window t t))
      (min-height-safe   . ,(window-min-size window nil 'safe))
-     (min-width-safe    . ,(window-min-size window t 'safe)))
+     (min-width-safe    . ,(window-min-size window t 'safe))
+     (min-pixel-height  . ,(window-min-size window nil nil t))
+     (min-pixel-width   . ,(window-min-size window t nil t))
+     (min-pixel-height-ignore . ,(window-min-size window nil t t))
+     (min-pixel-width-ignore  . ,(window-min-size window t t t))
+     (min-pixel-height-safe   . ,(window-min-size window nil 'safe t))
+     (min-pixel-width-safe    . ,(window-min-size window t 'safe t)))
    (window--state-get-1 window writable)))
 
 (defvar window-state-put-list nil
@@ -4381,7 +4795,7 @@ value can be also stored on disk and read back in a new session."
 (defvar window-state-put-stale-windows nil
   "Helper variable for `window-state-put'.")
 
-(defun window--state-put-1 (state &optional window ignore totals)
+(defun window--state-put-1 (state &optional window ignore totals pixelwise)
   "Helper function for `window-state-put'."
   (let ((type (car state)))
     (setq state (cdr state))
@@ -4392,7 +4806,7 @@ value can be also stored on disk and read back in a new session."
       (push (cons window state) window-state-put-list))
      ((memq type '(vc hc))
       (let* ((horizontal (eq type 'hc))
-            (total (window-total-size window horizontal))
+            (total (window-size window horizontal pixelwise))
             (first t)
             size new)
        (dolist (item state)
@@ -4409,25 +4823,39 @@ value can be also stored on disk and read back in a new session."
              (setq size
                    (if totals
                        ;; Use total size.
-                       (cdr (assq (if horizontal 'total-width 'total-height) item))
+                       (if pixelwise
+                           (cdr (assq (if horizontal
+                                          'pixel-width
+                                        'pixel-height)
+                                      item))
+                         (cdr (assq (if horizontal
+                                        'total-width
+                                      'total-height)
+                                    item)))
                      ;; Use normalized size and round.
-                     (round (* total
-                               (cdr (assq
-                                     (if horizontal 'normal-width 'normal-height)
-                                     item))))))
+                     (round
+                      (* total
+                         (cdr (assq (if horizontal 'normal-width 'normal-height)
+                                    item))))))
 
              ;; Use safe sizes, we try to resize later.
-             (setq size (max size (if horizontal
-                                      window-safe-min-height
-                                    window-safe-min-width)))
-
-             (if (window-sizable-p window (- size) horizontal 'safe)
+             (setq size (max size
+                             (if horizontal
+                                 (* window-safe-min-width
+                                    (if pixelwise
+                                        (frame-char-width (window-frame window))
+                                      1))
+                               (* window-safe-min-height
+                                  (if pixelwise
+                                      (frame-char-height (window-frame window))
+                                    1)))))
+             (if (window-sizable-p window (- size) horizontal 'safe pixelwise)
                  (let* ((window-combination-limit
                          (assq 'combination-limit item)))
                    ;; We must inherit the combination limit, otherwise
                    ;; we might mess up handling of atomic and side
                    ;; window.
-                   (setq new (split-window window size horizontal)))
+                   (setq new (split-window window size horizontal pixelwise)))
                ;; Give up if we can't resize window down to safe sizes.
                (error "Cannot resize window %s" window))
 
@@ -4445,7 +4873,7 @@ value can be also stored on disk and read back in a new session."
            ;; Continue with the last window split off.
            (setq window new))))))))
 
-(defun window--state-put-2 (ignore)
+(defun window--state-put-2 (ignore pixelwise)
   "Helper function for `window-state-put'."
   (dolist (item window-state-put-list)
     (let ((window (car item))
@@ -4481,32 +4909,44 @@ value can be also stored on disk and read back in a new session."
                (if (memq window-size-fixed '(t height))
                    ;; A fixed height window, try to restore the
                    ;; original size.
-                   (let ((delta (- (cdr (assq 'total-height item))
-                                   (window-total-height window)))
+                   (let ((delta
+                          (- (cdr (assq
+                                   (if pixelwise 'pixel-height 'total-height)
+                                   item))
+                             (window-size window nil pixelwise)))
                          window-size-fixed)
-                     (when (window-resizable-p window delta)
-                       (window-resize window delta)))
+                     (when (window--resizable-p
+                            window delta nil nil nil nil nil pixelwise)
+                       (window-resize window delta nil nil pixelwise)))
                  ;; Else check whether the window is not high enough.
-                 (let* ((min-size (window-min-size window nil ignore))
-                        (delta (- min-size (window-total-size window))))
+                 (let* ((min-size
+                         (window-min-size window nil ignore pixelwise))
+                        (delta
+                         (- min-size (window-size window nil pixelwise))))
                    (when (and (> delta 0)
-                              (window-resizable-p window delta nil ignore))
-                     (window-resize window delta nil ignore))))
+                              (window--resizable-p
+                               window delta nil ignore nil nil nil pixelwise))
+                     (window-resize window delta nil ignore pixelwise))))
                ;; Adjust horizontally.
                (if (memq window-size-fixed '(t width))
                    ;; A fixed width window, try to restore the original
                    ;; size.
-                   (let ((delta (- (cdr (assq 'total-width item))
-                                   (window-total-width window)))
+                   (let ((delta
+                          (- (cdr (assq
+                                   (if pixelwise 'pixel-width 'total-width)
+                                   item))
+                             (window-size window t pixelwise)))
                          window-size-fixed)
-                     (when (window-resizable-p window delta)
-                       (window-resize window delta)))
+                     (when (window--resizable-p
+                            window delta nil nil nil nil nil pixelwise)
+                       (window-resize window delta nil nil pixelwise)))
                  ;; Else check whether the window is not wide enough.
-                 (let* ((min-size (window-min-size window t ignore))
-                        (delta (- min-size (window-total-size window t))))
+                 (let* ((min-size (window-min-size window t ignore pixelwise))
+                        (delta (- min-size (window-size window t pixelwise))))
                    (when (and (> delta 0)
-                              (window-resizable-p window delta t ignore))
-                     (window-resize window delta t ignore))))
+                              (window--resizable-p
+                               window delta t ignore nil nil nil pixelwise))
+                     (window-resize window delta t ignore pixelwise))))
                ;; Set dedicated status.
                (set-window-dedicated-p window (cdr (assq 'dedicated state)))
                ;; Install positions (maybe we should do this after all
@@ -4542,32 +4982,60 @@ windows can get as small as `window-safe-min-height' and
         ;; STATE and that of WINDOW are equal so we can avoid
         ;; calculating new sizes, and (2) if we do have to resize
         ;; whether we can do so without violating size restrictions.
-        (totals
-         (and (= (window-total-size window)
-                 (cdr (assq 'total-height state)))
-              (= (window-total-size window t)
-                 (cdr (assq 'total-width state)))))
-        (min-height (cdr (assq 'min-height head)))
-        (min-width (cdr (assq 'min-width head))))
+        (pixelwise (and (cdr (assq 'pixel-width state))
+                        (cdr (assq 'pixel-height state))))
+        (totals (or (and pixelwise
+                         (= (window-pixel-width window)
+                            (cdr (assq 'pixel-width state)))
+                         (= (window-pixel-height window)
+                            (cdr (assq 'pixel-height state))))
+                    (and (= (window-total-width window)
+                            (cdr (assq 'total-width state)))
+                         (= (window-total-height window)
+                            (cdr (assq 'total-height state))))))
+        (min-height (cdr (assq
+                          (if pixelwise 'min-pixel-height 'min-height)
+                          head)))
+        (min-width (cdr (assq
+                         (if pixelwise 'min-pixel-width 'min-weight)
+                         head))))
     (if (and (not totals)
-            (or (> min-height (window-total-size window))
-                (> min-width (window-total-size window t)))
+            (or (> min-height (window-size window nil pixelwise))
+                (> min-width (window-size window t pixelwise)))
             (or (not ignore)
                 (and (setq min-height
-                           (cdr (assq 'min-height-ignore head)))
+                           (cdr (assq
+                                 (if pixelwise
+                                     'min-pixel-height-ignore
+                                   'min-height-ignore)
+                                 head)))
                      (setq min-width
-                           (cdr (assq 'min-width-ignore head)))
-                     (or (> min-height (window-total-size window))
-                         (> min-width (window-total-size window t)))
+                           (cdr (assq
+                                 (if pixelwise
+                                     'min-pixel-width-ignore
+                                   'min-width-ignore)
+                                 head)))
+                     (or (> min-height
+                            (window-size window nil pixelwise))
+                         (> min-width
+                            (window-size window t pixelwise)))
                      (or (not (eq ignore 'safe))
                          (and (setq min-height
-                                    (cdr (assq 'min-height-safe head)))
+                                    (cdr (assq
+                                          (if pixelwise
+                                              'min-pixel-height-safe
+                                            'min-height-safe)
+                                          head)))
                               (setq min-width
-                                    (cdr (assq 'min-width-safe head)))
+                                    (cdr (assq
+                                          (if pixelwise
+                                              'min-pixel-width-safe
+                                            'min-width-safe)
+                                          head)))
                               (or (> min-height
-                                     (window-total-size window))
+                                     (window-size window nil pixelwise))
                                   (> min-width
-                                     (window-total-size window t))))))))
+                                     (window-size window t pixelwise))))))))
        ;; The check above might not catch all errors due to rounding
        ;; issues - so IGNORE equal 'safe might not always produce the
        ;; minimum possible state.  But such configurations hardly make
@@ -4581,8 +5049,8 @@ windows can get as small as `window-safe-min-height' and
       ;; all live windows have been set by `window--state-put-2'.
       (with-temp-buffer
        (set-window-buffer window (current-buffer))
-       (window--state-put-1 state window nil totals)
-       (window--state-put-2 ignore))
+       (window--state-put-1 state window nil totals pixelwise)
+       (window--state-put-2 ignore pixelwise))
       (while window-state-put-stale-windows
        (let ((window (pop window-state-put-stale-windows)))
          (when (eq (window-deletable-p window) t)
@@ -4625,7 +5093,7 @@ element is BUFFER."
                     ;; Preserve window-point-insertion-type (Bug#12588).
                     (copy-marker
                      (window-point window) window-point-insertion-type)
-                    (window-total-size window))
+                    (window-total-height window))
               (selected-window) buffer)))))
    ((eq type 'window)
     ;; WINDOW has been created on an existing frame.
@@ -5250,12 +5718,35 @@ live."
        (set-window-dedicated-p window dedicated))
       (when (memq type '(window frame))
        (set-window-prev-buffers window nil)))
-    (let ((parameter (window-parameter window 'quit-restore))
+    (let ((frame (window-frame window))
+         (parameter (window-parameter window 'quit-restore))
          (height (cdr (assq 'window-height alist)))
-         (width (cdr (assq 'window-width alist))))
-      (when (or (eq type 'window)
-               (and (eq (car parameter) 'same)
-                    (eq (nth 1 parameter) 'window)))
+         (width (cdr (assq 'window-width alist)))
+         (size (cdr (assq 'window-size alist))))
+      (cond
+       ((or (eq type 'frame)
+           (and (eq (car parameter) 'same)
+                (eq (nth 1 parameter) 'frame)))
+       ;; Adjust size of frame if asked for.
+       (cond
+        ((not size))
+        ((consp size)
+         (let ((width (car size))
+               (height (cdr size))
+               (frame (window-frame window))
+               delta)
+           (when (and (numberp width) (numberp height))
+             (set-frame-height
+              frame (+ (frame-height frame)
+                       (- height (window-total-height window))))
+             (set-frame-width
+              frame (+ (frame-width frame)
+                       (- width (window-total-width window)))))))
+        ((functionp size)
+         (ignore-errors (funcall size window)))))
+       ((or (eq type 'window)
+           (and (eq (car parameter) 'same)
+                (eq (nth 1 parameter) 'window)))
        ;; Adjust height of window if asked for.
        (cond
         ((not height))
@@ -5264,10 +5755,10 @@ live."
                  (if (integerp height)
                      height
                    (round
-                    (* (window-total-size (frame-root-window window))
+                    (* (window-total-height (frame-root-window window))
                        height))))
-                (delta (- new-height (window-total-size window))))
-           (when (and (window-resizable-p window delta nil 'safe)
+                (delta (- new-height (window-total-height window))))
+           (when (and (window--resizable-p window delta nil 'safe)
                       (window-combined-p window))
              (window-resize window delta nil 'safe))))
         ((functionp height)
@@ -5280,14 +5771,14 @@ live."
                  (if (integerp width)
                      width
                    (round
-                    (* (window-total-size (frame-root-window window) t)
+                    (* (window-total-width (frame-root-window window))
                        width))))
-                (delta (- new-width (window-total-size window t))))
-           (when (and (window-resizable-p window delta t 'safe)
+                (delta (- new-width (window-total-width window))))
+           (when (and (window--resizable-p window delta t 'safe)
                       (window-combined-p window t))
              (window-resize window delta t 'safe))))
         ((functionp width)
-         (ignore-errors (funcall width window))))))
+         (ignore-errors (funcall width window)))))))
 
     window))
 
@@ -5320,6 +5811,7 @@ The actual non-nil value of this variable will be copied to the
           (const display-buffer-pop-up-window)
           (const display-buffer-same-window)
           (const display-buffer-pop-up-frame)
+          (const display-buffer-in-previous-window)
           (const display-buffer-use-some-window)
           (function :tag "Other function"))
   "Custom type for `display-buffer' action functions.")
@@ -5390,6 +5882,7 @@ See `display-buffer' for details."
   '((display-buffer--maybe-same-window  ;FIXME: why isn't this redundant?
      display-buffer-reuse-window
      display-buffer--maybe-pop-up-frame-or-window
+     display-buffer-in-previous-window
      display-buffer-use-some-window
      ;; If all else fails, pop up a new frame.
      display-buffer-pop-up-frame))
@@ -5466,6 +5959,7 @@ Available action functions include:
  `display-buffer-reuse-window'
  `display-buffer-pop-up-frame'
  `display-buffer-pop-up-window'
+ `display-buffer-in-previous-window'
  `display-buffer-use-some-window'
 
 Recognized alist entries include:
@@ -5823,8 +6317,20 @@ that frame."
                (unless (and not-this-window
                             (eq window (selected-window)))
                  window))
-             (get-largest-window 0 nil not-this-window))))
+             (get-largest-window 0 nil not-this-window)))
+        (quit-restore (and (window-live-p window)
+                           (window-parameter window 'quit-restore)))
+        (quad (nth 1 quit-restore)))
     (when (window-live-p window)
+      ;; If the window was used by `display-buffer' before, try to
+      ;; resize it to its old height but don't signal an error.
+      (when (and (listp quad)
+                (integerp (nth 3 quad))
+                (/= (nth 3 quad) (window-total-height window)))
+       (condition-case nil
+           (window-resize window (- (nth 3 quad) (window-total-height window)))
+         (error nil)))
+
       (prog1
          (window--display-buffer buffer window 'reuse alist)
        (window--even-window-heights window)
@@ -6133,216 +6639,496 @@ WINDOW must be a live window and defaults to the selected one."
                             (eobp)
                             window))))
 
-;;; Resizing buffers to fit their contents exactly.
+;;; Resizing windows and frames to fit their contents exactly.
+(defcustom fit-window-to-buffer-horizontally nil
+  "Non-nil means `fit-window-to-buffer' can resize windows horizontally.
+If this is nil, `fit-window-to-buffer' never resizes windows
+horizontally.  If this is `only', it can resize windows
+horizontally only.  Any other value means `fit-window-to-buffer'
+can resize windows in both dimensions."
+  :type 'boolean
+  :version "24.4"
+  :group 'help)
+
+;; `fit-frame-to-buffer' eventually wants to know the real frame sizes
+;; counting title bar and outer borders.
 (defcustom fit-frame-to-buffer nil
-  "Non-nil means `fit-window-to-buffer' can resize frames.
-A frame can be resized if and only if its root window is a live
-window.  The height of the root window is subject to the values
-of `fit-frame-to-buffer-max-height' and `window-min-height'."
+  "Non-nil means `fit-frame-to-buffer' can fit a frame to its buffer.
+A frame is fit if and only if its root window is a live window
+and this option is non-nil.  If this is `horizontally', frames
+are resized horizontally only.  If this is `vertically', frames
+are resized vertically only.  Any other non-nil value means
+frames can be resized in both dimensions.  See also
+`fit-frame-to-buffer-margins' and `fit-frame-to-buffer-sizes'.
+
+If this is non-nil and a window is the only window of its frame,
+`fit-window-to-buffer' will invoke `fit-frame-to-buffer' to fit
+the frame to its buffer."
   :type 'boolean
-  :version "24.3"
+  :version "24.4"
   :group 'help)
 
-(defcustom fit-frame-to-buffer-bottom-margin 4
-  "Bottom margin for the command `fit-frame-to-buffer'.
-This is the number of lines that function leaves free at the bottom of
-the display, in order to not obscure any system task bar or panel.
-If you do not have one (or if it is vertical) you might want to
-reduce this.  If it is thicker, you might want to increase this."
-  ;; If you set this too small, fit-frame-to-buffer can shift the
-  ;; frame up to avoid the panel.
-  :type 'integer
-  :version "24.3"
-  :group 'windows)
+(defcustom fit-frame-to-buffer-margins '(nil nil nil nil)
+  "Margins around frame for `fit-frame-to-buffer'.
+This list specifies the numbers of pixels to be left free on the
+left, above, the right, and below a frame that shall be fit to
+its buffer.  The value specified here can be overridden for a
+specific frame by that frame's `fit-frame-to-buffer-margins'
+parameter, if present.
+
+This variable controls how fitting a frame to the size of its
+buffer coordinates with the size of your display.  If you don't
+specify a value here, the size of the display's workarea is used.
+
+See also `fit-frame-to-buffer-sizes'."
+  :version "24.4"
+  :type '(list
+         (choice
+          :tag "Left"
+          :value nil
+          :format "%[LeftMargin%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Pixels" :size 5))
+         (choice
+          :tag "Top"
+          :value nil
+          :format "%[TopMargin%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Pixels" :size 5))
+         (choice
+          :tag "Right"
+          :value nil
+          :format "%[RightMargin%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Pixels" :size 5))
+         (choice
+          :tag "Bottom"
+          :value nil
+          :format "%[BottomMargin%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Pixels" :size 5)))
+  :group 'help)
+
+(defcustom fit-frame-to-buffer-sizes '(nil nil nil nil)
+  "Size boundaries of frame for `fit-frame-to-buffer'.
+This list specifies the total maximum and minimum lines and
+maximum and minimum columns of the root window of any frame that
+shall be fit to its buffer.  If any of these values is non-nil,
+it overrides the corresponding argument of `fit-frame-to-buffer'.
+
+On window systems where the menubar can wrap, fitting a frame to
+its buffer may swallow the last line(s).  Specifying an
+appropriate minimum width value here can avoid such wrapping.
+
+See also `fit-frame-to-buffer-margins'."
+  :version "24.4"
+  :type '(list
+         (choice
+          :tag "Maximum Height"
+          :value nil
+          :format "%[MaxHeight%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Lines" :size 5))
+         (choice
+          :tag "Minimum Height"
+          :value nil
+          :format "%[MinHeight%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Lines" :size 5))
+         (choice
+          :tag "Maximum Width"
+          :value nil
+          :format "%[MaxWidth%] %v  "
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Columns" :size 5))
+         (choice
+          :tag "Minimum Width"
+          :value nil
+          :format "%[MinWidth%] %v\n"
+          (const :tag "None" :format "%t" nil)
+          (integer :tag "Columns" :size 5)))
+  :group 'help)
 
 (declare-function x-display-pixel-height "xfns.c" (&optional terminal))
 (declare-function tool-bar-lines-needed "xdisp.c" (&optional frame))
 
-(defun fit-frame-to-buffer (&optional frame max-height min-height)
-  "Adjust height of FRAME to display its buffer contents exactly.
-FRAME can be any live frame and defaults to the selected one.
+(defun window--sanitize-margin (margin left right)
+  "Return MARGIN if it's a number between LEFT and RIGHT."
+  (when (and (numberp margin)
+            (<= left (- right margin)) (<= margin right))
+    margin))
 
-Optional argument MAX-HEIGHT specifies the maximum height of FRAME.
-It defaults to the height of the display below the current
-top line of FRAME, minus `fit-frame-to-buffer-bottom-margin'.
-Optional argument MIN-HEIGHT specifies the minimum height of FRAME.
-The default corresponds to `window-min-height'."
+(defun fit-frame-to-buffer (&optional frame max-height min-height max-width min-width)
+  "Adjust size of FRAME to display the contents of its buffer exactly.
+FRAME can be any live frame and defaults to the selected one.
+Fit only if FRAME's root window is live.  MAX-HEIGHT, MIN-HEIGHT,
+MAX-WIDTH and MIN-WIDTH specify bounds on the new total size of
+FRAME's root window.
+
+The option `fit-frame-to-buffer' controls whether this function
+has any effect.  New position and size of FRAME are additionally
+determined by the options `fit-frame-to-buffer-sizes' and
+`fit-frame-to-buffer-margins' or the corresponding parameters of
+FRAME."
   (interactive)
   (or (fboundp 'x-display-pixel-height)
       (user-error "Cannot resize frame in non-graphic Emacs"))
   (setq frame (window-normalize-frame frame))
-  (let* ((root (frame-root-window frame))
-        (frame-min-height
-         (+ (- (frame-height frame) (window-total-size root))
-            window-min-height))
-        (frame-top (frame-parameter frame 'top))
-        (top (if (consp frame-top)
-                 (funcall (car frame-top) (cadr frame-top))
-               frame-top))
-        (frame-max-height
-         (- (/ (- (x-display-pixel-height frame) top)
-               (frame-char-height frame))
-            fit-frame-to-buffer-bottom-margin))
-        (compensate 0)
-        delta)
-    (when (and (window-live-p root) (not (window-size-fixed-p root)))
-      (with-selected-window root
-       (cond
-        ((not max-height)
-         (setq max-height frame-max-height))
-        ((numberp max-height)
-         (setq max-height (min max-height frame-max-height)))
-        (t
-         (error "%s is an invalid maximum height" max-height)))
+  (when (and (window-live-p (frame-root-window frame))
+            fit-frame-to-buffer
+            (or (not window-size-fixed)
+                (and (eq window-size-fixed 'height)
+                     (not (eq fit-frame-to-buffer 'vertically)))
+                (and (eq window-size-fixed 'width)
+                     (not (eq fit-frame-to-buffer 'horizontally)))))
+    (with-selected-window (frame-root-window frame)
+      (let* ((window (frame-root-window frame))
+            (char-width (frame-char-width))
+            (char-height (frame-char-height))
+            (monitor-attributes (car (display-monitor-attributes-list
+                                      (frame-parameter frame 'display))))
+            (geometry (cdr (assq 'geometry monitor-attributes)))
+            (display-width (- (nth 2 geometry) (nth 0 geometry)))
+            (display-height (- (nth 3 geometry) (nth 1 geometry)))
+            (workarea (cdr (assq 'workarea monitor-attributes)))
+            ;; Handle margins.
+            (margins (or (frame-parameter frame 'fit-frame-to-buffer-margins)
+                         fit-frame-to-buffer-margins))
+            (left-margin (or (window--sanitize-margin
+                              (nth 0 margins) 0 display-width)
+                             (nth 0 workarea)))
+            (top-margin (or (window--sanitize-margin
+                             (nth 1 margins) 0 display-height)
+                            (nth 1 workarea)))
+            (workarea-width (nth 2 workarea))
+            (right-margin (or (window--sanitize-margin
+                               (nth 2 margins) left-margin display-width)
+                              (+ left-margin workarea-width)))
+            (workarea-height (nth 3 workarea))
+            (bottom-margin (or (window--sanitize-margin
+                                (nth 3 margins) top-margin display-height)
+                               (+ top-margin workarea-height)))
+            ;; The pixel width of FRAME (which does not include the
+            ;; window manager's decorations).
+            (frame-width (frame-pixel-width))
+            ;; The pixel width of the body of FRAME's root window.
+            (window-body-width (window-body-width nil t))
+            ;; The difference in pixels between total and body width of
+            ;; FRAME's window.
+            (window-extra-width (- (window-pixel-width) window-body-width))
+            ;; The difference in pixels between the frame's pixel width
+            ;; and the window's body width.  This is the space we can't
+            ;; use for fitting.
+            (extra-width (- frame-width window-body-width))
+            ;; The maximum width we can use for fitting.
+            (fit-width (- workarea-width extra-width))
+            ;; The pixel position of FRAME's left border.  We usually
+            ;; try to leave this alone.
+            (left
+             (let ((left (frame-parameter nil 'left)))
+               (if (consp left)
+                   (funcall (car left) (cadr left))
+                 left)))
+            ;; The pixel height of FRAME (which does not include title
+            ;; line, decorations, and sometimes neither the menu nor
+            ;; the toolbar).
+            (frame-height (frame-pixel-height))
+            ;; The pixel height of FRAME's root window (we don't care
+            ;; about the window's body height since the return value of
+            ;; `window-text-pixel-size' includes header and mode line).
+            (window-height (window-pixel-height))
+            ;; The difference in pixels between the frame's pixel
+            ;; height and the window's height.
+            (extra-height (- frame-height window-height))
+            ;; When tool-bar-mode is enabled and we just created a new
+            ;; frame, reserve lines for toolbar resizing.  Needed
+            ;; because for reasons unknown to me Emacs (1) reserves one
+            ;; line for the toolbar when making the initial frame and
+            ;; toolbars are enabled, and (2) later adds the remaining
+            ;; lines needed.  Our code runs IN BETWEEN (1) and (2).
+            ;; YMMV when you're on a system that behaves differently.
+            (toolbar-extra-height
+             (let ((quit-restore (window-parameter window 'quit-restore))
+                   ;; This may have to change when we allow arbitrary
+                   ;; pixel height toolbars.
+                   (lines (tool-bar-height)))
+               (* char-height
+                  (if (and quit-restore (eq (car quit-restore) 'frame)
+                           (not (zerop lines)))
+                      (1- lines)
+                    0))))
+            ;; The maximum height we can use for fitting.
+            (fit-height
+             (- workarea-height extra-height toolbar-extra-height))
+            ;; The pixel position of FRAME's top border.  We usually
+            ;; try to leave this alone.
+            (top
+             (let ((top (frame-parameter nil 'top)))
+               (if (consp top)
+                   (funcall (car top) (cadr top))
+                 top)))
+            ;; Sanitize minimum and maximum sizes.
+            (sizes (or (frame-parameter frame 'fit-frame-to-buffer-sizes)
+                       fit-frame-to-buffer-sizes))
+            (max-height
+             (cond
+              ((numberp (nth 0 sizes)) (* (nth 0 sizes) char-height))
+              ((numberp max-height) (* max-height char-height))))
+            (min-height
+             (cond
+              ((numberp (nth 1 sizes)) (* (nth 1 sizes) char-height))
+              ((numberp min-height) (* min-height char-height))))
+            (max-width
+             (cond
+              ((numberp (nth 2 sizes))
+               (- (* (nth 2 sizes) char-width) window-extra-width))
+              ((numberp max-width)
+               (- (* max-width char-width) window-extra-width))))
+            (min-width
+             (cond
+              ((numberp (nth 3 sizes))
+               (- (* (nth 3 sizes) char-width) window-extra-width))
+              ((numberp min-width)
+               (- (* min-width char-width) window-extra-width))))
+            ;; Note: Currently, for a new frame the sizes of the header
+            ;; and mode line may be estimated incorrectly
+            (value (window-text-pixel-size
+                    nil t t workarea-width workarea-height t))
+            (width (+ (car value) (window-right-divider-width)))
+            (height (+ (cdr value) (window-bottom-divider-width)))
+            remainder)
+       (unless window-resize-pixelwise
+         ;; Round sizes to character sizes.
+         (setq remainder (% width char-width))
+         (unless (zerop remainder)
+           (setq width (+ width (- char-width remainder))))
+         (setq remainder (% height char-height))
+         (setq height (+ height (- char-height remainder))))
+       ;; Now make sure that we don't get larger than our rounded
+       ;; maximum lines and columns.
+       (when (> width fit-width)
+         (setq width (- fit-width (% fit-width char-width))))
+       (when (> height fit-height)
+         (setq height (- fit-height (% fit-height char-height))))
+       ;; Don't change height or width when the window's size is fixed
+       ;; in either direction.
        (cond
-        ((not min-height)
-         (setq min-height frame-min-height))
-        ((numberp min-height)
-         (setq min-height (min min-height frame-min-height)))
-        (t
-         (error "%s is an invalid minimum height" min-height)))
-       ;; When tool-bar-mode is enabled and we have just created a new
-       ;; frame, reserve lines for toolbar resizing.  This is needed
-       ;; because for reasons unknown to me Emacs (1) reserves one line
-       ;; for the toolbar when making the initial frame and toolbars
-       ;; are enabled, and (2) later adds the remaining lines needed.
-       ;; Our code runs IN BETWEEN (1) and (2).  YMMV when you're on a
-       ;; system that behaves differently.
-       (let ((quit-restore (window-parameter root 'quit-restore))
-             (lines (tool-bar-lines-needed frame)))
-         (when (and quit-restore (eq (car quit-restore) 'frame)
-                    (not (zerop lines)))
-           (setq compensate (1- lines))))
-       (message "%s" compensate)
-       (setq delta
-             ;; Always count a final newline - we don't do any
-             ;; post-processing, so let's play safe.
-             (+ (count-screen-lines nil nil t)
-                (- (window-body-size))
-                compensate)))
-      ;; Move away from final newline.
-      (when (and (eobp) (bolp) (not (bobp)))
-       (set-window-point root (line-beginning-position 0)))
-      (set-window-start root (point-min))
-      (set-window-vscroll root 0)
-      (condition-case nil
-         (set-frame-height
-          frame
-          (min (max (+ (frame-height frame) delta)
-                    min-height)
-               max-height))
-       (error (setq delta nil))))
-    delta))
-
-(defun fit-window-to-buffer (&optional window max-height min-height)
-  "Adjust height of WINDOW to display its buffer's contents exactly.
+        ((eq window-size-fixed 'height)
+         (setq height nil))
+        ((eq window-size-fixed 'width)
+         (setq height nil)))
+       (when width
+         ;; Fit to maximum and minimum widths.
+         (when max-width
+           (setq width (min width max-width)))
+         (when min-width
+           (setq width (max width min-width)))
+         ;; Add extra width.
+         (setq width (+ width extra-width))
+         ;; Preserve right margin.
+         (let ((right (+ left width extra-width))
+               (max-right (- workarea-width right-margin)))
+           (cond
+            ((> right max-right)
+             ;; Move FRAME to left.
+             (setq left (max 0 (- left (- right max-right)))))
+            ((< left left-margin)
+             ;; Move frame to right.
+             (setq left left-margin)))))
+       (when height
+         ;; Fit to maximum and minimum heights.
+         (when max-height
+           (setq height (min height max-height)))
+         (when min-height
+           (setq height (max height min-height)))
+         ;; Add extra height.
+         (setq height (+ height extra-height))
+         ;; Preserve bottom and top margins.
+         (let ((bottom (+ top height extra-height))
+               (max-bottom (- workarea-height bottom-margin)))
+           (cond
+            ((> bottom max-bottom)
+             ;; Move FRAME to left.
+             (setq top (max 0 (- top (- bottom max-bottom)))))
+            ((< top top-margin)
+             ;; Move frame down.
+             (setq top top-margin)))))
+       ;; Apply changes.
+       (set-frame-position frame left top)
+       ;; Clumsily try to translate our calculations to what
+       ;; `set-frame-size' wants.
+       (when width
+         (setq width (- (+ (frame-text-width) width)
+                        extra-width window-body-width)))
+       (when height
+         (setq height (- (+ (frame-text-height) height)
+                         extra-height window-height)))
+       (set-frame-size
+        frame
+        (if width
+            (if window-resize-pixelwise
+                width
+              (/ width char-width))
+          (frame-text-width))
+        (if height
+            (if window-resize-pixelwise
+                height
+              (/ height char-height))
+          (frame-text-height))
+        window-resize-pixelwise)))))
+
+(defun fit-window-to-buffer (&optional window max-height min-height max-width min-width)
+  "Adjust size of WINDOW to display its buffer's contents exactly.
 WINDOW must be a live window and defaults to the selected one.
 
-Optional argument MAX-HEIGHT specifies the maximum height of
-WINDOW and defaults to the height of WINDOW's frame.  Optional
-argument MIN-HEIGHT specifies the minimum height of WINDOW and
-defaults to `window-min-height'.  Both MAX-HEIGHT and MIN-HEIGHT
-are specified in lines and include the mode line and header line,
-if any.
-
-If WINDOW is a full height window, then if the option
-`fit-frame-to-buffer' is non-nil, this calls the function
-`fit-frame-to-buffer' to adjust the frame height.
-
-Return the number of lines by which WINDOW was enlarged or
-shrunk.  If an error occurs during resizing, return nil but don't
-signal an error.
+If WINDOW is part of a vertical combination, adjust WINDOW's
+height.  The new height is calculated from the number of lines of
+the accessible portion of its buffer.  The optional argument
+MAX-HEIGHT specifies a maximum height and defaults to the height
+of WINDOW's frame.  The optional argument MIN-HEIGHT specifies a
+minimum height and defaults to `window-min-height'.  Both
+MAX-HEIGHT and MIN-HEIGHT are specified in lines and include the
+mode line and header line, if any.
+
+If WINDOW is part of a horizontal combination and the value of
+the option `fit-window-to-buffer-horizontally' is non-nil, adjust
+WINDOW's height.  The new width of WINDOW is calculated from the
+maximum length of its buffer's lines that follow the current
+start position of WINDOW.  The optional argument MAX-WIDTH
+specifies a maximum width and defaults to the width of WINDOW's
+frame.  The optional argument MIN-WIDTH specifies a minimum width
+and defaults to `window-min-width'.  Both MAX-WIDTH and MIN-WIDTH
+are specified in columns and include fringes, margins and
+scrollbars, if any.
+
+Fit pixelwise if the option `window-resize-pixelwise' is non-nil.
+If WINDOW is its frame's root window, then if the option
+`fit-frame-to-buffer' is non-nil, call `fit-frame-to-buffer' to
+adjust the frame's size.
 
 Note that even if this function makes WINDOW large enough to show
-_all_ lines of its buffer you might not see the first lines when
-WINDOW was scrolled."
+_all_ parts of its buffer you might not see the first part when
+WINDOW was scrolled.  If WINDOW is resized horizontally, you will
+not see the top of its buffer unless WINDOW starts at its minimum
+accessible position."
   (interactive)
   (setq window (window-normalize-window window t))
-  (cond
-   ((window-size-fixed-p window))
-   ((window-full-height-p window)
-    (when fit-frame-to-buffer
-      (fit-frame-to-buffer (window-frame window))))
-   (t
+  (if (eq window (frame-root-window window))
+      (when fit-frame-to-buffer
+       ;; Fit WINDOW's frame to buffer.
+       (fit-frame-to-buffer
+        (window-frame window)
+        max-height min-height max-width min-width))
     (with-selected-window window
-      (let* ((height (window-total-size))
+      (let* ((pixelwise window-resize-pixelwise)
+            (frame (window-frame))
+            (char-height (frame-char-height))
+            (char-width (frame-char-width))
+            (display-height (display-pixel-height))
+            (total-height (window-size window nil pixelwise))
+            (body-height (window-body-height window pixelwise))
+            (body-width (window-body-width window pixelwise))
             (min-height
-             ;; Adjust MIN-HEIGHT.
+             ;; Sanitize MIN-HEIGHT.
              (if (numberp min-height)
                  ;; Can't get smaller than `window-safe-min-height'.
-                 (max min-height window-safe-min-height)
+                 (max (if pixelwise
+                          (* char-height min-height)
+                        min-height)
+                      (if pixelwise
+                          (window-safe-min-pixel-height window)
+                        window-safe-min-height))
                ;; Preserve header and mode line if present.
-               (window-min-size nil nil t)))
+               (window-min-size nil nil t pixelwise)))
             (max-height
-             ;; Adjust MAX-HEIGHT.
+             ;; Sanitize MAX-HEIGHT.
              (if (numberp max-height)
-                 ;; Can't get larger than height of frame.
-                 (min max-height
-                      (window-total-size (frame-root-window window)))
-               ;; Don't delete other windows.
-               (+ height (window-max-delta nil nil window))))
-            ;; Make `desired-height' the height necessary to show
-            ;; all of WINDOW's buffer, constrained by MIN-HEIGHT
-            ;; and MAX-HEIGHT.
-            (desired-height
-             (max
-              (min
-               (+ (count-screen-lines)
-                  ;; For non-minibuffers count the mode line, if any.
-                  (if (and (not (window-minibuffer-p window))
-                           mode-line-format)
-                      1
-                    0)
-                  ;; Count the header line, if any.
-                  (if header-line-format 1 0))
-               max-height)
-              min-height))
-            (desired-delta
-             (- desired-height (window-total-size window)))
-            (delta
-             (if (> desired-delta 0)
-                 (min desired-delta
-                      (window-max-delta window nil window))
-               (max desired-delta
-                    (- (window-min-delta window nil window))))))
-       (condition-case nil
-           (if (zerop delta)
-               ;; Return zero if DELTA became zero in the process.
-               0
-             ;; Don't try to redisplay with the cursor at the end on its
-             ;; own line--that would force a scroll and spoil things.
-             (when (and (eobp) (bolp) (not (bobp)))
-               ;; It's silly to put `point' at the end of the previous
-               ;; line and so maybe force horizontal scrolling.
-               (set-window-point window (line-beginning-position 0)))
-             ;; Call `window-resize' with OVERRIDE argument equal WINDOW.
-             (window-resize window delta nil window)
-             ;; Check if the last line is surely fully visible.  If
-             ;; not, enlarge the window.
-             (let ((end (save-excursion
-                          (goto-char (point-max))
-                          (when (and (bolp) (not (bobp)))
-                            ;; Don't include final newline.
-                            (backward-char 1))
-                          (when truncate-lines
-                            ;; If line-wrapping is turned off, test the
-                            ;; beginning of the last line for
-                            ;; visibility instead of the end, as the
-                            ;; end of the line could be invisible by
-                            ;; virtue of extending past the edge of the
-                            ;; window.
-                            (forward-line 0))
-                          (point))))
-               (set-window-vscroll window 0)
-               ;; This loop might in some rare pathological cases raise
-               ;; an error - another reason for the `condition-case'.
-               (while (and (< desired-height max-height)
-                           (= desired-height (window-total-size))
-                           (not (pos-visible-in-window-p end)))
-                 (window-resize window 1 nil window)
-                 (setq desired-height (1+ desired-height)))))
-         (error (setq delta nil)))
-       delta)))))
+                 (min
+                  (+ total-height
+                     (window-max-delta
+                      window nil nil nil nil nil pixelwise))
+                  (if pixelwise
+                      (* char-height max-height)
+                    max-height))
+               (+ total-height (window-max-delta
+                                window nil nil nil nil nil pixelwise))))
+            height)
+       (cond
+        ;; If WINDOW is vertically combined, try to resize it
+        ;; vertically.
+        ((and (not (eq fit-window-to-buffer-horizontally 'only))
+              (not (window-size-fixed-p window))
+              (window-combined-p))
+         ;; Vertically we always want to fit the entire buffer.
+         ;; WINDOW'S height can't get larger than its frame's pixel
+         ;; height.  Its width remains fixed.
+         (setq height (+ (cdr (window-text-pixel-size
+                               nil nil t nil (frame-pixel-height) t))
+                         (window-bottom-divider-width)))
+         ;; Round height.
+         (unless pixelwise
+           (setq height (+ (/ height char-height)
+                           (if (zerop (% height char-height)) 0 1))))
+         (unless (= height total-height)
+           (window-resize-no-error
+            window
+            (- (max min-height (min max-height height)) total-height)
+            nil window pixelwise)))
+        ;; If WINDOW is horizontally combined, try to resize it
+        ;; horizontally.
+        ((and fit-window-to-buffer-horizontally
+              (not (window-size-fixed-p window t))
+              (window-combined-p nil t))
+         (let* ((display-width (display-pixel-width))
+                (total-width (window-size window nil pixelwise))
+                (min-width
+                 ;; Sanitize MIN-WIDTH.
+                 (if (numberp min-width)
+                     ;; Can't get smaller than `window-safe-min-width'.
+                     (max (if pixelwise
+                              (* char-width min-width)
+                            min-width)
+                          (if pixelwise
+                              (window-safe-min-pixel-width)
+                            window-safe-min-width))
+                   ;; Preserve fringes, margines, scrollbars if present.
+                   (window-min-size nil nil t pixelwise)))
+                (max-width
+                 ;; Sanitize MAX-WIDTH.
+                 (if (numberp max-width)
+                     (min (+ total-width
+                             (window-max-delta
+                              nil t nil nil nil nil pixelwise))
+                          (if pixelwise
+                              (* char-width max-width)
+                            max-width))
+                   (+ total-width (window-max-delta
+                                   nil t nil nil nil nil pixelwise))))
+                ;; When fitting vertically, assume that WINDOW's start
+                ;; position remains unaltered.  WINDOW can't get wider
+                ;; than its frame's pixel width, its height remains
+                ;; unaltered.
+                (width (+ (car (window-text-pixel-size
+                                nil (window-start) (point-max)
+                                (frame-pixel-width)
+                                ;; Add one char-height to assure that
+                                ;; we're on the safe side.  This
+                                ;; overshoots when the first line below
+                                ;; the bottom is wider than the window.
+                                (* body-height
+                                   (if pixelwise char-height 1))))
+                          (window-right-divider-width))))
+           (unless pixelwise
+             (setq width (+ (/ width char-width)
+                            (if (zerop (% width char-width)) 0 1))))
+           (unless (= width body-width)
+             (window-resize-no-error
+              window
+              (- (max min-width
+                      (min max-width
+                           (+ total-width (- width body-width))))
+                 total-width)
+              t window pixelwise)))))))))
 
 (defun window-safely-shrinkable-p (&optional window)
   "Return t if WINDOW can be shrunk without shrinking other windows.
@@ -6372,7 +7158,7 @@ Return non-nil if the window was shrunk, nil otherwise."
   ;; should be taken care of by `fit-window-to-buffer'.
   (when (and (window-combined-p window)
             (pos-visible-in-window-p (point-min) window))
-    (fit-window-to-buffer window (window-total-size window))))
+    (fit-window-to-buffer window (window-total-height window))))
 \f
 (defun kill-buffer-and-window ()
   "Kill the current buffer and delete the selected window."
index 0585975..addfb83 100644 (file)
@@ -1,3 +1,243 @@
+2013-12-01  Martin Rudalics  <rudalics@gmx.at>
+
+       Support resizing frames and windows pixelwise.
+       * dispextern.h (enum window_part): Add ON_SCROLL_BAR,
+       ON_RIGHT_DIVIDER and ON_BOTTOM_DIVIDER.
+       (struct glyph_matrix): Replace window_left_col and
+       window_top_line by window_pixel_left and window_pixel_top.
+       (WINDOW_WANTS_MODELINE_P, WINDOW_WANTS_HEADER_LINE_P): Minor
+       rewrite.
+       (enum face_id): Add WINDOW_DIVIDER_FACE_ID.
+       (draw_window_divider, move_it_to, x_draw_right_divider)
+       (x_draw_bottom_divider, change_frame_size): Add or fix
+       declarations.
+       * dispnew.c (change_frame_size_1): Change prototype.
+       (adjust_glyph_matrix, required_matrix_width)
+       (adjust_frame_glyphs_for_window_redisplay): Use pixel
+       values instead of lines and columns.
+       (marginal_area_string): Use WINDOW_FRINGES_WIDTH instead of
+       WINDOW_TOTAL_FRINGE_WIDTH.
+       (handle_window_change_signal, do_pending_window_change)
+       (init_display): Adjusts calls of change_frame_size.
+       (change_frame_size, change_frame_size_1): Handle pixelwise
+       changes.
+       * frame.c (Qright_divider_width, Qbottom_divider_width): New
+       Lisp objects.
+       (set_menu_bar_lines_1, set_menu_bar_lines, make_frame)
+       (make_terminal_frame, Fmake_terminal_frame, Fframe_parameters)
+       (x_set_internal_border_width, x_set_vertical_scroll_bars)
+       (x_set_scroll_bar_width, x_figure_window_size): Handle pixel
+       values.
+       (set_frame_param): New function.
+       (Fframe_text_cols, Fframe_text_lines, Fframe_total_cols)
+       (Fframe_text_width, Fframe_text_height, Fscroll_bar_width)
+       (Ffringe_width, Fborder_width, Fright_divider_width)
+       (Fbottom_divider_width): New functions, defsubr them.
+       (Fset_frame_height, Fset_frame_width, Fset_frame_size): New
+       argument pixelwise.
+       (struct frame_parm_table): New members Qright_divider_width and
+       Qbottom_divider_width.
+       (x_set_frame_parameters): Handle parameters for pixelwise sizes.
+       (x_report_frame_params): Handle Qright_divider_width and
+       Qbottom_divider_width.
+       (x_set_right_divider_width, x_set_bottom_divider_width): New
+       functions.
+       (frame_resize_pixelwise): New option.
+       * frame.h (struct frame): Add tool_bar_height, menu_bar_height,
+       new_pixelwise, right_divider_width and bottom_divider_width;
+       remove total_lines; rename text_lines, text_cols, new_text_lines
+       and new_text_cols to text_height, text_width, new_height and
+       new_width respectively.
+       (FRAME_LINES, FRAME_COLS): Rename to FRAME_TEXT_HEIGHT and
+       FRAME_TEXT_WIDTH respectively.
+       (FRAME_MENU_BAR_HEIGHT, FRAME_TOOL_BAR_HEIGHT)
+       (FRAME_RIGHT_DIVIDER_WIDTH, FRAME_BOTTOM_DIVIDER_WIDTH)
+       (FRAME_TEXT_TO_PIXEL_WIDTH, FRAME_PIXEL_TO_TEXT_WIDTH): New
+       macros.
+       (FRAME_TOP_MARGIN_HEIGHT, FRAME_LEFT_SCROLL_BAR_AREA_WIDTH)
+       (FRAME_RIGHT_SCROLL_BAR_AREA_WIDTH, FRAME_SCROLL_BAR_AREA_WIDTH)
+       (SET_FRAME_COLS, SET_FRAME_WIDTH, SET_FRAME_HEIGHT)
+       (FRAME_TEXT_COLS_TO_PIXEL_WIDTH, FRAME_PIXEL_WIDTH_TO_TEXT_COLS)
+       (FRAME_TEXT_COLS_TO_PIXEL_WIDTH): Rewrite macros.
+       (FRAME_TOTAL_COLS_ARG): Remove macro.
+       * fringe.c (draw_fringe_bitmap_1): Handle right divder.
+       * gtkutil.c (xg_frame_resized, xg_frame_set_char_size)
+       (x_wm_set_size_hint): Handle frame pixel sizes.
+       * indent.c (compute_motion, Fcompute_motion): Call
+       window_body_width instead of window_body_cols.
+       * keyboard.c (Qright_divider, Qbottom_divider): New symbols.
+       (make_lispy_position): Handle right and bottom dividers.
+       (Fsuspend_emacs): Pixelize call of change_frame_size.
+       * keyboard.h: Extern Qright_divider, Qbottom_divider.
+       * lisp.h: Extern set_frame_param.
+       * nsfns.m (x_set_tool_bar_lines): Pixelize call of
+       x_set_window_size.
+       (Fx_create_frame): Add entry for vertical_drag_cursor.  Pixelize
+       call of change_frame_size.
+       * nsterm.h (struct ns_output): Add vertical_drag_cursor.
+       * nsterm.m (ns_update_window_end): Optionally draw right
+       divider.
+       (x_set_window_size): Add argument pixelwise.  Call
+       check_frame_size and change_frame_size with pixelwise zero.
+       (ns_draw_window_divider): New function.
+       (ns_redisplay_interface): Add ns_draw_window_divider.
+       (updateFrameSize:): Call change_frame_size with pixelwise zero.
+       (x_new_font): Call x_set_window_size with pixelwise zero.
+       * print.c (print_object): For a window print its sequence
+       number again.
+       * term.c (Fresume_tty): Pixelize call of change_frame_size.
+       * w32fns.c (x_set_mouse_color): Handle vertical drag cursor.
+       (x_set_menu_bar_lines, x_set_tool_bar_lines): Calculate pixelwise.
+       (w32_createwindow): Use scroll bar area width.
+       (w32_wnd_proc): Handle bottom divider width.  For
+       WM_WINDOWPOSCHANGING return zero if we resize pixelwise.
+       (Fx_create_frame): Default divider width parameters.  Caclulate
+       sizes pixelwise.  Add vertical drag cursor support.
+       (x_create_tip_frame): Default divider widths to zero.  Pixelize
+       call to change_frame_size.
+       (Fx_show_tip): Add handling of divider widths.  Pixelize window
+       position and sizes.
+       (Fw32_frame_rect): New function.
+       (frame_parm_handler w32_frame_parm_handlers): Add divider
+       widths.
+       (Vx_window_vertical_drag_shape): Add variable.
+       * w32inevt.c (resize_event, maybe_generate_resize_event):
+       Pixelize change_frame_size calls.
+       * w32menu.c (set_frame_menubar): Pixelize x_set_window_size
+       call.
+       * w32term.c (w32_draw_window_divider): New function.
+       (x_update_window_end): Handle right divider.
+       (w32_draw_fringe_bitmap, x_scroll_run)
+       (w32_set_vertical_scroll_bar): Pixelize scrollbar widths.
+       (w32_read_socket): Handle SIZE_MAXIMIZED separately.  Calculate
+       new frame sizes pixelwise.
+       (x_new_font): Pixelize call to x_set_window_size.
+       (x_check_fullscreen): Pixelize call to change_frame_size.
+       (x_set_window_size_1, x_set_window_size): New argument
+       pixelwise.  Calculate pixelwise.
+       (x_wm_set_size_hint): Use scroll bar area width.
+       (w32_redisplay_interface): Add w32_draw_window_divider.
+       * w32term.h (struct w32_output): Add vertical drag cursor.
+       * widget.c (set_frame_size, update_wm_hints)
+       (EmacsFrameResize, EmacsFrameSetValues): Pixelize calls of
+       change_frame_size.
+       (EmacsFrameSetCharSize): Pixelize call of x_set_window_size.
+       * window.c (sequence_number): Restore.
+       (Fwindow_pixel_width, Fwindow_pixel_height)
+       (Fwindow_mode_line_height, Fwindow_header_line_height)
+       (window_pixel_to_total, Frun_window_scroll_functions)
+       (Fset_window_new_pixel, window_resize_apply_total)
+       (Fwindow_resize_apply_total): New functions.
+       (window_body_height, window_body_width): Rename from
+       window_body_lines.  New argument PIXELWISE.  Calculate
+       pixelwise.
+       (Fwindow_body_height, Fwindow_body_width): New argument
+       PIXELWISE.
+       (coordinates_in_window, window_relative_x_coord): Use window's
+       pixel width instead of total width.
+       (replace_window, recombine_windows): Initialize pixel values.
+       (resize_root_window, resize_frame_windows, grow_mini_window)
+       (shrink_mini_window): New argument PIXELWISE.  Calculate
+       pixelwise.
+       (Fdelete_other_windows_internal, adjust_window_margins)
+       (window_resize_check, window_resize_apply)
+       (Fdelete_window_internal, Fresize_mini_window_internal)
+       (Fwindow_text_width, Fwindow_text_height): Calculate pixelwise.
+       (check_frame_size): Rename arguments.  New argument PIXELWISE.
+       Calculate pixelwise.
+       (set_window_buffer): Make samebuf bool.  Run configuration change
+       hook only if buffer changed.
+       (Fset_window_buffer): Rewrite doc-string.
+       (make_window): Initialize new_pixel slot.
+       (Fwindow_resize_apply): Check pixel size of root window.
+       (Fsplit_window_internal): Call 2nd argument pixel_size.
+       Calculate pixelwise.
+       (Fscroll_left, Fscroll_right): Call window_body_width instead of
+       window_body_cols.
+       (save_window_data): New slots frame_text_width,
+       frame_text_height, frame_menu_bar_height, frame_tool_bar_height.
+       (saved_window): New slots pixel_left, pixel_top, pixel_height,
+       pixel_width.
+       (Fcurrent_window_configuration, Fset_window_configuration)
+       (save_window_save, compare_window_configurations): Handle new
+       slots in save_window_data and saved_window.
+       (Fset_window_scroll_bars): Fix doc-string.
+       (window_resize_pixelwise): New variable.
+       (coordinates_in_window, Fcoordinates_in_window_p): Handle
+       dividers.
+       (make_parent_window): Adjust sequence_number.
+       (Fwindow_right_divider_width, Fwindow_bottom_divider_width): New
+       functions.
+       * window.h (struct window): New members new_pixel, pixel_left,
+       pixel_top, pixel_width, pixel_height.  Restore sequence_number.
+       (wset_new_pixel): New function.
+       (WINDOW_PIXEL_WIDTH, WINDOW_PIXEL_HEIGHT)
+       (MIN_SAFE_WINDOW_PIXEL_WIDTH, MIN_SAFE_WINDOW_PIXEL_HEIGHT)
+       (WINDOW_LEFT_PIXEL_EDGE, WINDOW_RIGHT_PIXEL_EDGE)
+       (WINDOW_TOP_PIXEL_EDGE, WINDOW_BOTTOM_PIXEL_EDGE)
+       (WINDOW_BOTTOMMOST_P, WINDOW_BOX_LEFT_PIXEL_EDGE)
+       (WINDOW_BOX_RIGHT_PIXEL_EDGE, WINDOW_MARGINS_COLS)
+       (WINDOW_MARGINS_WIDTH, WINDOW_RIGHT_DIVIDER_WIDTH)
+       (WINDOW_BOTTOM_DIVIDER_WIDTH): New macros.
+       (WINDOW_TOTAL_FRINGE_WIDTH): Rename to WINDOW_FRINGES_WIDTH.
+       (WINDOW_TOTAL_WIDTH, WINDOW_TOTAL_HEIGHT): Remove macros.
+       (WINDOW_RIGHT_EDGE_X, WINDOW_LEFT_EDGE_X, WINDOW_TOP_EDGE_Y)
+       (WINDOW_BOTTOM_EDGE_Y, WINDOW_FULL_WIDTH_P, WINDOW_LEFTMOST_P)
+       (WINDOW_RIGHTMOST_P, WINDOW_BOX_LEFT_EDGE_X)
+       (WINDOW_BOX_RIGHT_EDGE_X, WINDOW_FRINGE_COLS)
+       (WINDOW_BOX_HEIGHT_NO_MODE_LINE, WINDOW_BOX_TEXT_HEIGHT):
+       Rewrite.
+       (resize_frame_windows, grow_mini_window, shrink_mini_window)
+       (window_body_width, check_frame_size): Adapt external declarations.
+       * xdisp.c (last_max_ascent): New integer.
+       (window_text_bottom_y): Handle bottom divider.
+       (window_box_width, window_box_height): Calculate pixelwise.
+       (get_glyph_string_clip_rects): Handle right divider.
+       (remember_mouse_glyph): When windows are resized pixelwise
+       proceed with width and height set to 1.
+       (init_iterator): Use WINDOW_PIXEL_WIDTH instead of
+       WINDOW_TOTAL_WIDTH.
+       (move_it_to): Calculate and return maximum x position
+       encountered.
+       (Fwindow_text_pixel_size): New function.
+       (resize_mini_window, update_tool_bar): Calculate pixelwise.
+       (tool_bar_lines_needed): Rename to tool_bar_height.  Calculate
+       pixelwise.
+       (Ftool_bar_lines_needed): Rename to Ftool_bar_height.  Calculate
+       pixelwise.
+       (redisplay_tool_bar): Calculate pixelwise.
+       (redisplay_window): Calculate pixelwise.  Handle dividers.
+       (draw_glyphs, x_clear_end_of_line, note_mouse_highlight)
+       (x_draw_vertical_border): Handle dividers.
+       (define_frame_cursor1): Handle vertical drag cursor.
+       (x_draw_right_divider, x_draw_bottom_divider): New functions.
+       (expose_window): Calculate pixelwise.  Handle dividers.
+       (init_xdisp): Initialize pixel values.
+       * xfaces.c (Qwindow_divider): New face.
+       (realize_basic_faces): Realize it.
+       * xfns.c (x_set_mouse_color): Handle vertical_drag_cursor.
+       (x_set_menu_bar_lines, x_set_tool_bar_lines): Calculate pixelwise.
+       (x_set_scroll_bar_default_width): Default actual width to 16.
+       (Fx_create_frame): Set sizes pixelwise.
+       (x_create_tip_frame): Default divider widths to zero.  Pixelize
+       call of change_frame_size.
+       (Fx_show_tip): Handle divider widths.  Initial pixel position
+       and sizes.
+       (frame_parm_handler x_frame_parm_handlers): Add divider widths.
+       (Vx_window_vertical_drag_shape): New option.
+       * xmenu.c (free_frame_menubar): Pixelize call of
+       x_set_window_size.
+       * xterm.c (x_draw_window_divider): New function.
+       (x_update_window_end): Optionally draw right divider.
+       (x_draw_fringe_bitmap, x_scroll_run, x_scroll_bar_create)
+       (XTset_vertical_scroll_bar): Use scroll bar pixel width.
+       (handle_one_xevent, x_new_font): Calculate pixelwise.
+       (x_set_window_size_1, x_set_window_size): New argument
+       pixelwise.  Calculate pixelwise.
+       (x_wm_set_size_hint): Pixelize call of check_frame_size.
+       (struct x_redisplay_interface): Add x_draw_window_divider.
+       * xterm.h (struct x_output): Add vertical_drag_cursor.
+
 2013-11-30  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * xdisp.c (redisplay_internal): Don't call set_window_update_flags.
index 6f16231..fb20534 100644 (file)
@@ -118,7 +118,9 @@ enum window_part
   ON_RIGHT_FRINGE,
   ON_LEFT_MARGIN,
   ON_RIGHT_MARGIN,
-  ON_SCROLL_BAR
+  ON_SCROLL_BAR,
+  ON_RIGHT_DIVIDER,
+  ON_BOTTOM_DIVIDER
 };
 
 /* Number of bits allocated to store fringe bitmap numbers.  */
@@ -667,7 +669,7 @@ struct glyph_pool
    glyph memory, which is allocated in the form of a glyph_pool structure.
    Glyph rows in such a window matrix are slices of frame matrix rows.
 
-   2. Free-standing window glyph matrices managing their own glyph
+   3. Free-standing window glyph matrices managing their own glyph
    storage.  This form is used in window-based redisplay which
    includes variable width and height fonts etc.
 
@@ -704,12 +706,12 @@ struct glyph_matrix
   int matrix_w, matrix_h;
 
   /* If this structure describes a window matrix of window W,
-     window_left_col is the value of W->left_col, window_top_line the
-     value of W->top_line, window_height and window_width are width and
-     height of W, as returned by window_box, and window_vscroll is the
-     value of W->vscroll at the time the matrix was last adjusted.
+     window_pixel_left is the value of W->pixel_left, window_pixel_top
+     the value of W->pixel_top, window_height and window_width are width
+     and height of W, as returned by window_box, and window_vscroll is
+     the value of W->vscroll at the time the matrix was last adjusted.
      Only set for window-based redisplay.  */
-  int window_left_col, window_top_line;
+  int window_pixel_left, window_pixel_top;
   int window_height, window_width;
   int window_vscroll;
 
@@ -722,7 +724,7 @@ struct glyph_matrix
      which do their own scrolling.  */
   unsigned no_scrolling_p : 1;
 
-  /* Non-zero means window displayed in this matrix has a top mode
+  /* Non-zero means window displayed in this matrix has a header
      line.  */
   unsigned header_line_p : 1;
 
@@ -1460,28 +1462,40 @@ struct glyph_string
 #define DESIRED_HEADER_LINE_HEIGHT(W) \
      MATRIX_HEADER_LINE_HEIGHT ((W)->desired_matrix)
 
-/* Value is non-zero if window W wants a mode line.  */
+/* PXW: The height checks below serve to show at least one text line
+   instead of a mode- and/or header line when a window gets very small.
+   But (1) the check fails when the mode- or header-line is taller than
+   the associated frame's line height and (2) we don't care much about
+   text visibility anyway when shrinking a frame containing a toolbar.
 
-#define WINDOW_WANTS_MODELINE_P(W)                             \
-  (!MINI_WINDOW_P ((W))                                                \
-   && !(W)->pseudo_window_p                                    \
-   && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))     \
-   && BUFFERP ((W)->contents)                                  \
-   && !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format)) \
-   && WINDOW_TOTAL_LINES (W) > 1)
+   So maybe these checks should be removed and any clipping left to the
+   window manager.  */
 
-/* Value is true if window W wants a header line.  */
-
-#define WINDOW_WANTS_HEADER_LINE_P(W)                                  \
+/* Value is non-zero if window W wants a mode line and is large enough
+   to accomodate it.  */
+#define WINDOW_WANTS_MODELINE_P(W)                                     \
   (BUFFERP ((W)->contents)                                             \
-   ? (!MINI_WINDOW_P ((W))                                             \
+   ? (!MINI_WINDOW_P (W)                                               \
       && !(W)->pseudo_window_p                                         \
-      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME ((W))))          \
-      && !NILP (BVAR (XBUFFER ((W)->contents), header_line_format))    \
-      && WINDOW_TOTAL_LINES (W) >                                      \
-          (1 + !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format)))) \
+      && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W)))            \
+      && !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format))      \
+      && WINDOW_PIXEL_HEIGHT (W) > WINDOW_FRAME_LINE_HEIGHT (W))       \
    : 0)
 
+/* Value is non-zero if window W wants a header line and is large enough
+   to accomodate it.  */
+#define WINDOW_WANTS_HEADER_LINE_P(W)                                  \
+     (BUFFERP ((W)->contents)                                          \
+      ? (!MINI_WINDOW_P (W)                                            \
+        && !(W)->pseudo_window_p                                       \
+        && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W)))          \
+        && !NILP (BVAR (XBUFFER ((W)->contents), header_line_format))  \
+        && (WINDOW_PIXEL_HEIGHT (W)                                    \
+            > (WINDOW_WANTS_MODELINE_P (W)                             \
+               ? (2 * WINDOW_FRAME_LINE_HEIGHT (W))                    \
+               : WINDOW_FRAME_LINE_HEIGHT (W))))                       \
+      : 0)
+
 /* Return proper value to be used as baseline offset of font that has
    ASCENT and DESCENT to draw characters by the font at the vertical
    center of the line of frame F.
@@ -1751,6 +1765,7 @@ enum face_id
   MOUSE_FACE_ID,
   MENU_FACE_ID,
   VERTICAL_BORDER_FACE_ID,
+  WINDOW_DIVIDER_FACE_ID,
   BASIC_FACE_ID_SENTINEL
 };
 
@@ -2850,6 +2865,10 @@ struct redisplay_interface
   void (*draw_vertical_window_border) (struct window *w,
                                        int x, int y_0, int y_1);
 
+/* Draw window divider for window W from (X_0, Y_0) to (X_1, ,Y_1).  */
+  void (*draw_window_divider) (struct window *w,
+                              int x_0, int x_1, int y_0, int y_1);
+
 /* Shift display of frame F to make room for inserted glyphs.
    The area at pixel (X,Y) of width WIDTH and height HEIGHT is
    shifted right by SHIFT_BY pixels.  */
@@ -3167,6 +3186,7 @@ int window_box_left_offset (struct window *, enum glyph_row_area);
 int window_box_right (struct window *, enum glyph_row_area);
 int window_box_right_offset (struct window *, enum glyph_row_area);
 int estimate_mode_line_height (struct frame *, enum face_id);
+int move_it_to (struct it *, ptrdiff_t, int, int, int, int);
 void pixel_to_glyph_coords (struct frame *, int, int, int *, int *,
                             NativeRectangle *, int);
 void remember_mouse_glyph (struct frame *, int, int, NativeRectangle *);
@@ -3178,7 +3198,6 @@ void init_iterator (struct it *, struct window *, ptrdiff_t,
 void init_iterator_to_row_start (struct it *, struct window *,
                                  struct glyph_row *);
 void start_display (struct it *, struct window *, struct text_pos);
-void move_it_to (struct it *, ptrdiff_t, int, int, int, int);
 void move_it_vertically (struct it *, int);
 void move_it_vertically_backward (struct it *, int);
 void move_it_by_lines (struct it *, ptrdiff_t);
@@ -3235,6 +3254,8 @@ extern void display_and_set_cursor (struct window *, bool, int, int, int, int);
 extern void x_update_cursor (struct frame *, bool);
 extern void x_clear_cursor (struct window *);
 extern void x_draw_vertical_border (struct window *w);
+extern void x_draw_right_divider (struct window *w);
+extern void x_draw_bottom_divider (struct window *w);
 
 extern int get_glyph_string_clip_rects (struct glyph_string *,
                                         NativeRectangle *, int);
@@ -3464,7 +3485,7 @@ void clear_glyph_row (struct glyph_row *);
 void prepare_desired_row (struct glyph_row *);
 void update_single_window (struct window *, bool);
 void do_pending_window_change (bool);
-void change_frame_size (struct frame *, int, int, bool, bool, bool);
+void change_frame_size (struct frame *, int, int, bool, bool, bool, bool);
 void init_display (void);
 void syms_of_display (void);
 extern Lisp_Object Qredisplay_dont_pause;
index b68cc2e..9492960 100644 (file)
@@ -72,7 +72,7 @@ struct dim
 static void update_frame_line (struct frame *, int);
 static int required_matrix_height (struct window *);
 static int required_matrix_width (struct window *);
-static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool);
+static void change_frame_size_1 (struct frame *, int, int, bool, bool, bool, bool);
 static void increment_row_positions (struct glyph_row *, ptrdiff_t, ptrdiff_t);
 static void build_frame_matrix_from_window_tree (struct glyph_matrix *,
                                                  struct window *);
@@ -401,8 +401,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
       if (!marginal_areas_changed_p
          && !XFRAME (w->frame)->fonts_changed
          && !header_line_changed_p
-         && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-         && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+         && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+         && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
          && matrix->window_height == window_height
          && matrix->window_vscroll == w->vscroll
          && matrix->window_width == window_width)
@@ -543,8 +543,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
              && !header_line_changed_p
              && new_rows == 0
              && dim.width == matrix->matrix_w
-             && matrix->window_left_col == WINDOW_LEFT_EDGE_COL (w)
-             && matrix->window_top_line == WINDOW_TOP_EDGE_LINE (w)
+             && matrix->window_pixel_left == WINDOW_LEFT_PIXEL_EDGE (w)
+             && matrix->window_pixel_top == WINDOW_TOP_PIXEL_EDGE (w)
              && matrix->window_width == window_width)
            {
              /* Find the last row in the window.  */
@@ -591,8 +591,8 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
      was last adjusted.  This is used to optimize redisplay above.  */
   if (w)
     {
-      matrix->window_left_col = WINDOW_LEFT_EDGE_COL (w);
-      matrix->window_top_line = WINDOW_TOP_EDGE_LINE (w);
+      matrix->window_pixel_left = WINDOW_LEFT_PIXEL_EDGE (w);
+      matrix->window_pixel_top = WINDOW_TOP_PIXEL_EDGE (w);
       matrix->window_height = window_height;
       matrix->window_width = window_width;
       matrix->window_vscroll = w->vscroll;
@@ -1661,6 +1661,7 @@ required_matrix_height (struct window *w)
     {
       int ch_height = FRAME_SMALLEST_FONT_HEIGHT (f);
       int window_pixel_height = window_box_height (w) + eabs (w->vscroll);
+
       return (((window_pixel_height + ch_height - 1)
               / ch_height) * w->nrows_scale_factor
              /* One partially visible line at the top and
@@ -1685,10 +1686,9 @@ required_matrix_width (struct window *w)
   if (FRAME_WINDOW_P (f))
     {
       int ch_width = FRAME_SMALLEST_CHAR_WIDTH (f);
-      int window_pixel_width = WINDOW_TOTAL_WIDTH (w);
 
       /* Compute number of glyphs needed in a glyph row.  */
-      return (((window_pixel_width + ch_width - 1)
+      return (((WINDOW_PIXEL_WIDTH (w) + ch_width - 1)
               / ch_width) * w->ncols_scale_factor
              /* 2 partially visible columns in the text area.  */
              + 2
@@ -1978,6 +1978,10 @@ adjust_frame_glyphs_for_frame_redisplay (struct frame *f)
       /* Size of frame matrices must equal size of frame.  Note
         that we are called for X frames with window widths NOT equal
         to the frame width (from CHANGE_FRAME_SIZE_1).  */
+      if (matrix_dim.width != FRAME_COLS (f)
+         || matrix_dim.height != FRAME_LINES (f))
+       return;
+
       eassert (matrix_dim.width == FRAME_COLS (f)
               && matrix_dim.height == FRAME_LINES (f));
 
@@ -2047,10 +2051,14 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
 
     /* Set window dimensions to frame dimensions and allocate or
        adjust glyph matrices of W.  */
-    w->top_line = 0;
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_MENU_BAR_LINES (f);
+    w->pixel_top = 0;
+    w->top_line = 0;
+    w->pixel_width = FRAME_PIXEL_WIDTH (f);
     w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_MENU_BAR_HEIGHT (f);
+    w->total_lines = FRAME_MENU_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
 #endif
@@ -2072,10 +2080,15 @@ adjust_frame_glyphs_for_window_redisplay (struct frame *f)
     else
       w = XWINDOW (f->tool_bar_window);
 
-    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_left = 0;
     w->left_col = 0;
-    w->total_lines = FRAME_TOOL_BAR_LINES (f);
+    w->pixel_top = FRAME_MENU_BAR_HEIGHT (f);
+    w->top_line = FRAME_MENU_BAR_LINES (f);
+    w->pixel_width = (FRAME_PIXEL_WIDTH (f)
+                      - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
     w->total_cols = FRAME_TOTAL_COLS (f);
+    w->pixel_height = FRAME_TOOL_BAR_HEIGHT (f);
+    w->total_lines = FRAME_TOOL_BAR_LINES (f);
     allocate_matrices_for_window_redisplay (w);
   }
 #endif
@@ -5275,7 +5288,7 @@ marginal_area_string (struct window *w, enum window_part part,
       if (area == RIGHT_MARGIN_AREA)
        x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
               ? WINDOW_LEFT_FRINGE_WIDTH (w)
-              : WINDOW_TOTAL_FRINGE_WIDTH (w))
+              : WINDOW_FRINGES_WIDTH (w))
              + window_box_width (w, LEFT_MARGIN_AREA)
              + window_box_width (w, TEXT_AREA));
       else
@@ -5367,7 +5380,7 @@ handle_window_change_signal (int sig)
           /* Record the new sizes, but don't reallocate the data
              structures now.  Let that be done later outside of the
              signal handler.  */
-          change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+          change_frame_size (XFRAME (frame), width, height, 0, 1, 0, 0);
     }
   }
 }
@@ -5401,17 +5414,21 @@ do_pending_window_change (bool safe)
        {
          struct frame *f = XFRAME (frame);
 
-         if (f->new_text_lines != 0 || f->new_text_cols != 0)
-           change_frame_size (f, f->new_text_lines, f->new_text_cols,
-                              0, 0, safe);
+         if (f->new_height != 0 || f->new_width != 0)
+           change_frame_size (f, f->new_width, f->new_height,
+                              0, 0, safe, f->new_pixelwise);
        }
     }
 }
 
-
 /* Change the frame height and/or width.  Values may be given as zero to
    indicate no change is to take place.
 
+   new_height and new_width refer to the text portion of the frame.  It
+   doesn't matter for new_height, since text and total portion are the
+   same in that case.  But new_width must be enlarged to get the total
+   width of the frame.
+
    If DELAY, assume we're being called from a signal handler, and
    queue the change for later - perhaps the next redisplay.
    Since this tries to resize windows, we can't call it
@@ -5421,8 +5438,8 @@ do_pending_window_change (bool safe)
    safe to change frame sizes while a redisplay is in progress.  */
 
 void
-change_frame_size (struct frame *f, int newheight, int newwidth,
-                  bool pretend, bool delay, bool safe)
+change_frame_size (struct frame *f, int new_width, int new_height,
+                  bool pretend, bool delay, bool safe, bool pixelwise)
 {
   Lisp_Object tail, frame;
 
@@ -5433,55 +5450,72 @@ change_frame_size (struct frame *f, int newheight, int newwidth,
          ttys. */
       FOR_EACH_FRAME (tail, frame)
        if (! FRAME_WINDOW_P (XFRAME (frame)))
-         change_frame_size_1 (XFRAME (frame), newheight, newwidth,
-                              pretend, delay, safe);
+         change_frame_size_1 (XFRAME (frame), new_width, new_height,
+                              pretend, delay, safe, pixelwise);
     }
   else
-    change_frame_size_1 (f, newheight, newwidth, pretend, delay, safe);
+    change_frame_size_1 (f, new_width, new_height, pretend, delay, safe,
+                        pixelwise);
 }
 
 static void
-change_frame_size_1 (struct frame *f, int newheight, int newwidth,
-                    bool pretend, bool delay, bool safe)
+change_frame_size_1 (struct frame *f, int new_width, int new_height,
+                    bool pretend, bool delay, bool safe, bool pixelwise)
 {
-  int new_frame_total_cols;
+  int new_text_width, new_text_height, new_root_width;
+  int old_root_width = (FRAME_PIXEL_WIDTH (f)
+                       - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
+  int new_cols, new_lines;
   ptrdiff_t count = SPECPDL_INDEX ();
 
   /* If we can't deal with the change now, queue it for later.  */
   if (delay || (redisplaying_p && !safe))
     {
-      f->new_text_lines = newheight;
-      f->new_text_cols = newwidth;
+      f->new_width = new_width;
+      f->new_height = new_height;
+      f->new_pixelwise = pixelwise;
       delayed_size_change = 1;
       return;
     }
 
   /* This size-change overrides any pending one for this frame.  */
-  f->new_text_lines = 0;
-  f->new_text_cols = 0;
+  f->new_height = 0;
+  f->new_width = 0;
+  f->new_pixelwise = 0;
 
   /* If an argument is zero, set it to the current value.  */
-  if (newheight == 0)
-    newheight = FRAME_LINES (f);
-  if (newwidth == 0)
-    newwidth  = FRAME_COLS  (f);
+  if (pixelwise)
+    {
+      new_text_width = (new_width == 0) ? FRAME_TEXT_WIDTH (f) : new_width;
+      new_text_height = (new_height == 0) ? FRAME_TEXT_HEIGHT (f) : new_height;
+      new_cols = new_text_width / FRAME_COLUMN_WIDTH (f);
+      new_lines = new_text_height / FRAME_LINE_HEIGHT (f);
+    }
+  else
+    {
+      new_cols = (new_width == 0) ? FRAME_COLS (f) : new_width;
+      new_lines = (new_height == 0) ? FRAME_LINES (f) : new_height;
+      new_text_width = new_cols * FRAME_COLUMN_WIDTH (f);
+      new_text_height = new_lines * FRAME_LINE_HEIGHT (f);
+    }
 
   /* Compute width of windows in F.  */
   /* Round up to the smallest acceptable size.  */
-  check_frame_size (f, &newheight, &newwidth);
-
-  /* This is the width of the frame with vertical scroll bars and fringe
-     columns.  Do this after rounding - see discussion of bug#9723.  */
-  new_frame_total_cols = FRAME_TOTAL_COLS_ARG (f, newwidth);
-
+  check_frame_size (f, &new_text_width, &new_text_height, 1);
+
+  /* This is the width of the frame without vertical scroll bars and
+     fringe columns.  Do this after rounding - see discussion of
+     bug#9723.  */
+  new_root_width = (new_text_width
+                   /* PXM: Use the configured scrollbar width !??  */
+                   + FRAME_SCROLL_BAR_AREA_WIDTH (f)
+                   + FRAME_TOTAL_FRINGE_WIDTH (f));
   /* If we're not changing the frame size, quit now.  */
   /* Frame width may be unchanged but the text portion may change, for
      example, fullscreen and remove/add scroll bar.  */
-  if (newheight == FRAME_LINES (f)
-      /* Text portion unchanged?  */
-      && newwidth == FRAME_COLS  (f)
-      /* Frame width unchanged?  */
-      && new_frame_total_cols == FRAME_TOTAL_COLS (f))
+  if (new_text_height == FRAME_TEXT_HEIGHT (f)
+      && new_text_width == FRAME_TEXT_WIDTH (f)
+      && new_root_width == old_root_width)
     return;
 
   block_input ();
@@ -5490,36 +5524,44 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
   /* We only can set screen dimensions to certain values supported
      by our video hardware.  Try to find the smallest size greater
      or equal to the requested dimensions.  */
-  dos_set_window_size (&newheight, &newwidth);
+  dos_set_window_size (&new_lines, &new_cols);
 #endif
 
-  if (newheight != FRAME_LINES (f))
+  if (new_text_height != FRAME_TEXT_HEIGHT (f))
     {
-      resize_frame_windows (f, newheight, 0);
+      resize_frame_windows (f, new_text_height, 0, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameRows (FRAME_TTY (f)) = newheight;
+       FrameRows (FRAME_TTY (f)) = new_height;
     }
 
-  if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
+  if (new_text_width != FRAME_TEXT_WIDTH (f)
+      || new_root_width != old_root_width)
     {
-      resize_frame_windows (f, new_frame_total_cols, 1);
+      resize_frame_windows (f, new_root_width, 1, 1);
 
       /* MSDOS frames cannot PRETEND, as they change frame size by
         manipulating video hardware.  */
       if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
-       FrameCols (FRAME_TTY (f)) = newwidth;
+       FrameCols (FRAME_TTY (f)) = new_cols;
 
 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
       if (WINDOWP (f->tool_bar_window))
-       XWINDOW (f->tool_bar_window)->total_cols = newwidth;
+       {
+         XWINDOW (f->tool_bar_window)->total_cols = new_cols;
+         XWINDOW (f->tool_bar_window)->pixel_width = new_root_width;
+       }
 #endif
     }
 
-  FRAME_LINES (f) = newheight;
-  SET_FRAME_COLS (f, newwidth);
+  SET_FRAME_COLS (f, new_cols);
+  FRAME_LINES (f) = new_lines;
+  FRAME_TEXT_WIDTH (f) = new_text_width;
+  FRAME_TEXT_HEIGHT (f) = new_text_height;
+  FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width);
+  FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height);
 
   {
     struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
@@ -5546,8 +5588,6 @@ change_frame_size_1 (struct frame *f, int newheight, int newwidth,
 
   unbind_to (count, Qnil);
 }
-
-
 \f
 /***********************************************************************
                   Terminal Related Lisp Functions
@@ -6076,8 +6116,8 @@ init_display (void)
 #endif
     t->display_info.tty->top_frame = selected_frame;
     change_frame_size (XFRAME (selected_frame),
-                       FrameRows (t->display_info.tty),
-                       FrameCols (t->display_info.tty), 0, 0, 1);
+                       FrameCols (t->display_info.tty),
+                       FrameRows (t->display_info.tty), 0, 0, 1, 0);
 
     /* Delete the initial terminal. */
     if (--initial_terminal->reference_count == 0
index 35e7ff1..df41822 100644 (file)
@@ -78,6 +78,7 @@ Lisp_Object Qleft, Qright;
 Lisp_Object Qicon_left, Qicon_top, Qicon_type, Qicon_name;
 Lisp_Object Qtooltip;
 Lisp_Object Qinternal_border_width;
+Lisp_Object Qright_divider_width, Qbottom_divider_width;
 Lisp_Object Qmouse_color;
 Lisp_Object Qminibuffer;
 Lisp_Object Qscroll_bar_width, Qvertical_scroll_bars;
@@ -197,9 +198,12 @@ static void
 set_menu_bar_lines_1 (Lisp_Object window, int n)
 {
   struct window *w = XWINDOW (window);
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
 
   w->top_line += n;
+  w->pixel_top += n * FRAME_LINE_HEIGHT (f);
   w->total_lines -= n;
+  w->pixel_height -= n * FRAME_LINE_HEIGHT (f);
 
   /* Handle just the top child in a vertical split.  */
   if (WINDOW_VERTICAL_COMBINATION_P (w))
@@ -236,6 +240,7 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       windows_or_buffers_changed = 14;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
       FRAME_MENU_BAR_LINES (f) = nlines;
+      FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
       set_menu_bar_lines_1 (f->root_window, nlines - olines);
       adjust_frame_glyphs (f);
     }
@@ -325,6 +330,7 @@ make_frame (bool mini_p)
 {
   Lisp_Object frame;
   register struct frame *f;
+  register struct window *rw, *mw;
   register Lisp_Object root_window;
   register Lisp_Object mini_window;
 
@@ -350,23 +356,25 @@ make_frame (bool mini_p)
 #endif
 
   root_window = make_window ();
+  rw = XWINDOW (root_window);
   if (mini_p)
     {
       mini_window = make_window ();
-      wset_next (XWINDOW (root_window), mini_window);
-      wset_prev (XWINDOW (mini_window), root_window);
-      XWINDOW (mini_window)->mini = 1;
-      wset_frame (XWINDOW (mini_window), frame);
+      mw = XWINDOW (mini_window);
+      wset_next (rw, mini_window);
+      wset_prev (mw, root_window);
+      mw->mini = 1;
+      wset_frame (mw, frame);
       fset_minibuffer_window (f, mini_window);
     }
   else
     {
       mini_window = Qnil;
-      wset_next (XWINDOW (root_window), Qnil);
+      wset_next (rw, Qnil);
       fset_minibuffer_window (f, Qnil);
     }
 
-  wset_frame (XWINDOW (root_window), frame);
+  wset_frame (rw, frame);
 
   /* 10 is arbitrary,
      just so that there is "something there."
@@ -374,15 +382,22 @@ make_frame (bool mini_p)
 
   SET_FRAME_COLS (f, 10);
   FRAME_LINES (f) = 10;
+  SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
+  SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
 
-  XWINDOW (root_window)->total_cols = 10;
-  XWINDOW (root_window)->total_lines = mini_p ? 9 : 10;
+  rw->total_cols = 10;
+  rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
+  rw->total_lines = mini_p ? 9 : 10;
+  rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
 
   if (mini_p)
     {
-      XWINDOW (mini_window)->total_cols = 10;
-      XWINDOW (mini_window)->top_line = 9;
-      XWINDOW (mini_window)->total_lines = 1;
+      mw->top_line = rw->total_lines;
+      mw->pixel_top = rw->pixel_height;
+      mw->total_cols = rw->total_cols;
+      mw->pixel_width = rw->pixel_width;
+      mw->total_lines = 1;
+      mw->pixel_height = FRAME_LINE_HEIGHT (f);
     }
 
   /* Choose a buffer for the frame's root window.  */
@@ -603,7 +618,8 @@ make_terminal_frame (struct terminal *terminal)
 #endif /* not MSDOS */
 
   FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
-  FRAME_MENU_BAR_LINES(f) = NILP (Vmenu_bar_mode) ? 0 : 1;
+  FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
+  FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
 
   /* Set the top frame to the newly created frame. */
   if (FRAMEP (FRAME_TTY (f)->top_frame)
@@ -723,7 +739,7 @@ affects all frames on the same terminal device.  */)
   {
     int width, height;
     get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
-    change_frame_size (f, height, width, 0, 0, 0);
+    change_frame_size (f, width, height, 0, 0, 0, 0);
   }
 
   adjust_frame_glyphs (f);
@@ -2011,6 +2027,18 @@ set_term_frame_name (struct frame *f, Lisp_Object name)
   update_mode_lines = 16;
 }
 
+void
+set_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
+{
+  register Lisp_Object old_alist_elt;
+
+  old_alist_elt = Fassq (prop, f->param_alist);
+  if (EQ (old_alist_elt, Qnil))
+    fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
+  else
+    Fsetcdr (old_alist_elt, val);
+}
+
 void
 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
 {
@@ -2164,9 +2192,17 @@ If FRAME is omitted or nil, return information on the currently selected frame.
                                    :"tty"));
     }
   store_in_alist (&alist, Qname, f->name);
-  height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
+  height = (f->new_height
+           ? (f->new_pixelwise
+              ? (f->new_height / FRAME_LINE_HEIGHT (f))
+              : f->new_height)
+           : FRAME_LINES (f));
   store_in_alist (&alist, Qheight, make_number (height));
-  width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
+  width = (f->new_width
+          ? (f->new_pixelwise
+             ? (f->new_width / FRAME_COLUMN_WIDTH (f))
+             : f->new_width)
+          : FRAME_COLS (f));
   store_in_alist (&alist, Qwidth, make_number (width));
   store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
   store_in_alist (&alist, Qminibuffer,
@@ -2437,80 +2473,180 @@ is used.  */)
 #endif
   return make_number (0);
 }
+
+DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
+       doc: /* Return width in columns of FRAME's text area.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_COLS (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
+       doc: /* Return height in lines of FRAME's text area.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_LINES (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
+       doc: /* Return total columns of FRAME.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
+       doc: /* Return text area width of FRAME in pixels.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
+       doc: /* Return text area height of FRAME in pixels.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
+       doc: /* Return scroll bar width of FRAME in pixels.  */)
+  (Lisp_Object frame)
+{
+  return make_number (decode_any_frame (frame)->scroll_bar_actual_width);
+}
+
+DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
+       doc: /* Return fringe width of FRAME in pixels.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0,
+       doc: /* Return border width of FRAME in pixels.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
+       doc: /* Return width (in pixels) of vertical window dividers on FRAME.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
+}
+
+DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
+       doc: /* Return width (in pixels) of horizontal window dividers on FRAME.  */)
+  (Lisp_Object frame)
+{
+  return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
+}
 \f
-DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 3, 0,
-       doc: /* Specify that the frame FRAME has LINES lines.
-If FRAME is nil, the selected frame is used.  Optional third arg
-non-nil means that redisplay should use LINES lines but that the
-idea of the actual height of the frame should not be changed.  */)
-  (Lisp_Object frame, Lisp_Object lines, Lisp_Object pretend)
+DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
+       doc: /* Specify that the frame FRAME has HEIGHT text lines.
+Optional third arg PRETEND non-nil means that redisplay should use
+HEIGHT lines but that the idea of the actual height of the frame should
+not be changed.  Optional fourth argument PIXELWISE non-nil means that
+FRAME should be HEIGHT pixels high.  */)
+  (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
 {
   register struct frame *f = decode_live_frame (frame);
 
-  CHECK_TYPE_RANGED_INTEGER (int, lines);
+  CHECK_TYPE_RANGED_INTEGER (int, height);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
-      if (XINT (lines) != FRAME_LINES (f))
-       x_set_window_size (f, 1, FRAME_COLS (f), XINT (lines));
-      do_pending_window_change (0);
+      if (NILP (pixelwise))
+       {
+         if (XINT (height) != FRAME_LINES (f))
+           x_set_window_size (f, 1, FRAME_COLS (f), XINT (height), 0);
+
+         do_pending_window_change (0);
+       }
+      else if (XINT (height) != FRAME_TEXT_HEIGHT (f))
+       {
+         x_set_window_size (f, 1, FRAME_TEXT_WIDTH (f), XINT (height), 1);
+         do_pending_window_change (0);
+       }
     }
   else
 #endif
-    change_frame_size (f, XINT (lines), 0, !NILP (pretend), 0, 0);
+    change_frame_size (f, 0, XINT (height), !NILP (pretend), 0, 0,
+                      NILP (pixelwise) ? 0 : 1);
   return Qnil;
 }
 
-DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 3, 0,
-       doc: /* Specify that the frame FRAME has COLS columns.
-If FRAME is nil, the selected frame is used.  Optional third arg
-non-nil means that redisplay should use COLS columns but that the
-idea of the actual width of the frame should not be changed.  */)
-  (Lisp_Object frame, Lisp_Object cols, Lisp_Object pretend)
+DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
+       doc: /* Specify that the frame FRAME has WIDTH columns.
+Optional third arg PRETEND non-nil means that redisplay should use WIDTH
+columns but that the idea of the actual width of the frame should not
+be changed.  Optional fourth argument PIXELWISE non-nil means that FRAME
+should be WIDTH pixels wide.  */)
+  (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
 {
   register struct frame *f = decode_live_frame (frame);
 
-  CHECK_TYPE_RANGED_INTEGER (int, cols);
+  CHECK_TYPE_RANGED_INTEGER (int, width);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
-      if (XINT (cols) != FRAME_COLS (f))
-       x_set_window_size (f, 1, XINT (cols), FRAME_LINES (f));
-      do_pending_window_change (0);
+      if (NILP (pixelwise))
+       {
+         if (XINT (width) != FRAME_COLS (f))
+           x_set_window_size (f, 1, XINT (width), FRAME_LINES (f), 0);
+
+         do_pending_window_change (0);
+       }
+      else if (XINT (width) != FRAME_TEXT_WIDTH (f))
+       {
+         x_set_window_size (f, 1, XINT (width), FRAME_TEXT_HEIGHT (f), 1);
+         do_pending_window_change (0);
+       }
     }
   else
 #endif
-    change_frame_size (f, 0, XINT (cols), !NILP (pretend), 0, 0);
+    change_frame_size (f, XINT (width), 0, !NILP (pretend), 0, 0,
+                      NILP (pixelwise) ? 0 : 1);
   return Qnil;
 }
 
-DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 3, 0,
-       doc: /* Sets size of FRAME to COLS by ROWS, measured in characters.
-If FRAME is nil, the selected frame is used.  */)
-  (Lisp_Object frame, Lisp_Object cols, Lisp_Object rows)
+DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
+       doc: /* Sets size of FRAME to WIDTH by HEIGHT, measured in characters.
+Optional argument PIXELWISE non-nil means to measure in pixels.  */)
+  (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
 {
   register struct frame *f = decode_live_frame (frame);
 
-  CHECK_TYPE_RANGED_INTEGER (int, cols);
-  CHECK_TYPE_RANGED_INTEGER (int, rows);
+  CHECK_TYPE_RANGED_INTEGER (int, width);
+  CHECK_TYPE_RANGED_INTEGER (int, height);
 
   /* I think this should be done with a hook.  */
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
-      if (XINT (rows) != FRAME_LINES (f)
-         || XINT (cols) != FRAME_COLS (f)
-         || f->new_text_lines || f->new_text_cols)
-       x_set_window_size (f, 1, XINT (cols), XINT (rows));
-      do_pending_window_change (0);
+      if (!NILP (pixelwise)
+         ? (XINT (width) != FRAME_TEXT_WIDTH (f)
+            || XINT (height) != FRAME_TEXT_HEIGHT (f)
+            || f->new_height || f->new_width)
+         : (XINT (width) != FRAME_COLS (f)
+            || XINT (height) != FRAME_LINES (f)
+            || f->new_height || f->new_width))
+       {
+         x_set_window_size (f, 1, XINT (width), XINT (height),
+                            NILP (pixelwise) ? 0 : 1);
+         do_pending_window_change (0);
+       }
     }
   else
 #endif
-    change_frame_size (f, XINT (rows), XINT (cols), 0, 0, 0);
+    change_frame_size (f, XINT (width), XINT (height), 0, 0, 0,
+                      NILP (pixelwise) ? 0 : 1);
 
   return Qnil;
 }
@@ -2569,6 +2705,8 @@ static const struct frame_parm_table frame_parms[] =
   {"icon-name",                        &Qicon_name},
   {"icon-type",                        &Qicon_type},
   {"internal-border-width",    &Qinternal_border_width},
+  {"right-divider-width",      &Qright_divider_width},
+  {"bottom-divider-width",     &Qbottom_divider_width},
   {"menu-bar-lines",           &Qmenu_bar_lines},
   {"mouse-color",              &Qmouse_color},
   {"name",                     &Qname},
@@ -2703,8 +2841,16 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
   icon_left = icon_top = Qunbound;
 
   /* Provide default values for HEIGHT and WIDTH.  */
-  width = (f->new_text_cols ? f->new_text_cols : FRAME_COLS (f));
-  height = (f->new_text_lines ? f->new_text_lines : FRAME_LINES (f));
+  width = (f->new_width
+          ? (f->new_pixelwise
+             ? (f->new_width / FRAME_COLUMN_WIDTH (f))
+             : f->new_width)
+          : FRAME_COLS (f));
+  height = (f->new_height
+           ? (f->new_pixelwise
+              ? (f->new_height / FRAME_LINE_HEIGHT (f))
+              : f->new_height)
+           : FRAME_LINES (f));
 
   /* Process foreground_color and background_color before anything else.
      They are independent of other properties, but other properties (e.g.,
@@ -2830,15 +2976,16 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
   {
     Lisp_Object frame;
 
-    check_frame_size (f, &height, &width);
+    /* Make this 1, eventually.  */
+    check_frame_size (f, &width, &height, 0);
 
     XSETFRAME (frame, f);
 
     if (size_changed
         && (width != FRAME_COLS (f)
             || height != FRAME_LINES (f)
-            || f->new_text_lines || f->new_text_cols))
-        Fset_frame_size (frame, make_number (width), make_number (height));
+            || f->new_height || f->new_width))
+      Fset_frame_size (frame, make_number (width), make_number (height), Qnil);
 
     if ((!NILP (left) || !NILP (top))
        && ! (left_no_change && top_no_change)
@@ -2946,6 +3093,10 @@ x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
                  make_number (f->border_width));
   store_in_alist (alistptr, Qinternal_border_width,
                  make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
+  store_in_alist (alistptr, Qright_divider_width,
+                 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
+  store_in_alist (alistptr, Qbottom_divider_width,
+                 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
   store_in_alist (alistptr, Qleft_fringe,
                  make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
   store_in_alist (alistptr, Qright_fringe,
@@ -3278,7 +3429,53 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
 
   if (FRAME_X_WINDOW (f) != 0)
     {
-      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+      SET_FRAME_GARBAGED (f);
+      do_pending_window_change (0);
+    }
+  else
+    SET_FRAME_GARBAGED (f);
+}
+
+void
+x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+  int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
+
+  CHECK_TYPE_RANGED_INTEGER (int, arg);
+  FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
+  if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
+    FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
+
+  if (FRAME_RIGHT_DIVIDER_WIDTH (f) == old)
+    return;
+
+  if (FRAME_X_WINDOW (f) != 0)
+    {
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
+      SET_FRAME_GARBAGED (f);
+      do_pending_window_change (0);
+    }
+  else
+    SET_FRAME_GARBAGED (f);
+}
+
+void
+x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
+{
+  int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
+
+  CHECK_TYPE_RANGED_INTEGER (int, arg);
+  FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
+  if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
+    FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
+
+  if (FRAME_BOTTOM_DIVIDER_WIDTH (f) == old)
+    return;
+
+  if (FRAME_X_WINDOW (f) != 0)
+    {
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
       SET_FRAME_GARBAGED (f);
       do_pending_window_change (0);
     }
@@ -3344,7 +3541,8 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
         However, if the window hasn't been created yet, we shouldn't
         call x_set_window_size.  */
       if (FRAME_X_WINDOW (f))
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
+                          FRAME_TEXT_HEIGHT (f), 1);
       do_pending_window_change (0);
     }
 }
@@ -3352,27 +3550,29 @@ x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval
 void
 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
-  int wid = FRAME_COLUMN_WIDTH (f);
+  int unit = FRAME_COLUMN_WIDTH (f);
 
   if (NILP (arg))
     {
       x_set_scroll_bar_default_width (f);
 
       if (FRAME_X_WINDOW (f))
-        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+        x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
+                          FRAME_TEXT_HEIGHT (f), 1);
       do_pending_window_change (0);
     }
   else if (RANGED_INTEGERP (1, arg, INT_MAX)
           && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
     {
       FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
-      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + wid-1) / wid;
+      FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
       if (FRAME_X_WINDOW (f))
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
+                          FRAME_TEXT_HEIGHT (f), 1);
       do_pending_window_change (0);
     }
 
-  change_frame_size (f, 0, FRAME_COLS (f), 0, 0, 0);
+  change_frame_size (f, 0, 0, 0, 0, 0, 1);
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
   XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
 }
@@ -3985,17 +4185,20 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
   /* Default values if we fall through.
      Actually, if that happens we should get
      window manager prompting.  */
+  SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
   SET_FRAME_COLS (f, DEFAULT_COLS);
+  SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
   FRAME_LINES (f) = DEFAULT_ROWS;
+
   /* Window managers expect that if program-specified
      positions are not (0,0), they're intentional, not defaults.  */
   f->top_pos = 0;
   f->left_pos = 0;
 
-  /* Ensure that old new_text_cols and new_text_lines will not override the
+  /* Ensure that old new_width and new_height will not override the
      values set here.  */
   /* ++KFS: This was specific to W32, but seems ok for all platforms */
-  f->new_text_cols = f->new_text_lines = 0;
+  f->new_width = f->new_height = f->new_pixelwise = 0;
 
   tem0 = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
   tem1 = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
@@ -4036,7 +4239,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
      change the frame size.  This is done so that users can create
      tall Emacs frames without having to guess how tall the tool-bar
      will get.  */
-  if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
+  if (toolbar_p && FRAME_TOOL_BAR_HEIGHT (f))
     {
       int margin, relief, bar_height;
 
@@ -4052,14 +4255,15 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
       else
        margin = 0;
 
+      /* PXW: We should be able to not round here.  */
       bar_height = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
       FRAME_LINES (f) += (bar_height + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
     }
 
   compute_fringe_widths (f, 0);
 
-  FRAME_PIXEL_WIDTH (f) = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, FRAME_COLS (f));
-  FRAME_PIXEL_HEIGHT (f) = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f));
+  SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
+  SET_FRAME_HEIGHT(f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
 
   tem0 = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
   tem1 = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
@@ -4512,6 +4716,12 @@ handles focus, since there is no way in general for Emacs to find out
 automatically.  See also `mouse-autoselect-window'.  */);
   focus_follows_mouse = 0;
 
+  DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
+              doc: /* Non-nil means frames are resized pixelwise.
+If this is nil, resizing a frame will round sizes to the frame's
+current values of `frame-char-height' and `frame-char-width'.  */);
+  frame_resize_pixelwise = 0;
+
   staticpro (&Vframe_list);
 
   defsubr (&Sframep);
@@ -4551,6 +4761,16 @@ automatically.  See also `mouse-autoselect-window'.  */);
   defsubr (&Sframe_char_width);
   defsubr (&Sframe_pixel_height);
   defsubr (&Sframe_pixel_width);
+  defsubr (&Sframe_text_cols);
+  defsubr (&Sframe_text_lines);
+  defsubr (&Sframe_total_cols);
+  defsubr (&Sframe_text_width);
+  defsubr (&Sframe_text_height);
+  defsubr (&Sscroll_bar_width);
+  defsubr (&Sfringe_width);
+  defsubr (&Sborder_width);
+  defsubr (&Sright_divider_width);
+  defsubr (&Sbottom_divider_width);
   defsubr (&Stool_bar_pixel_width);
   defsubr (&Sset_frame_height);
   defsubr (&Sset_frame_width);
index 657ef48..4a0ff46 100644 (file)
@@ -220,6 +220,9 @@ struct frame
   /* Margin at the top of the frame.  Used to display the tool-bar.  */
   int tool_bar_lines;
 
+  /* Pixel height of tool bar.  */
+  int tool_bar_height;
+
   int n_tool_bar_rows;
   int n_tool_bar_items;
 
@@ -236,23 +239,36 @@ struct frame
   /* Cost of deleting n lines on this frame.  */
   int *delete_n_lines_cost;
 
-  /* Size of this frame, excluding fringes, scroll bars etc.,
-     in units of canonical characters.  */
-  int text_lines, text_cols;
+  /* Text width of this frame (excluding fringes, scroll bars and
+     internal border width) and text height (excluding internal border
+     width) in units of canonical characters.  */
+  int text_cols, text_lines;
+
+  /* Total width of this frame (including fringes and scroll bars) in
+     units of canonical characters.  */
+  int total_cols;
+
+  /* Text width of this frame (excluding fringes, scroll bars and
+     internal border width) and text height (excluding internal border
+     width) in pixels.  */
+  int text_width, text_height;
 
-  /* Total size of this frame (i.e. its native window), in units of
-     canonical characters.  */
-  int total_lines, total_cols;
+  /* New text height and width for pending size change.  0 if no change
+     pending.  These value represent pixels or canoncial character units
+     according to the value of new_pixelwise and correlate to the the
+     text width/height of the frame.  */
+  int new_width, new_height;
 
-  /* New text height and width for pending size change.
-     0 if no change pending.  */
-  int new_text_lines, new_text_cols;
+  /* Whether new_height and new_width shall be interpreted
+     in pixels.  */
+  bool new_pixelwise;
 
   /* Pixel position of the frame window (x and y offsets in root window).  */
   int left_pos, top_pos;
 
-  /* Size of the frame window in pixels.  */
-  int pixel_height, pixel_width;
+  /* Size of the frame window (including internal border widths) in
+     pixels.  */
+  int pixel_width, pixel_height;
 
   /* These many pixels are the difference between the outer window (i.e. the
      left and top of the window manager decoration) and FRAME_X_WINDOW.  */
@@ -272,6 +288,10 @@ struct frame
      a highlighting is displayed inside the internal border.  */
   int internal_border_width;
 
+  /* Width of borders between this frame's windows.  */
+  int right_divider_width;
+  int bottom_divider_width;
+
   /* Canonical X unit.  Width of default font, in pixels.  */
   int column_width;
 
@@ -322,6 +342,9 @@ struct frame
   /* Number of lines of menu bar.  */
   int menu_bar_lines;
 
+  /* Pixel height of menubar.  */
+  int menu_bar_height;
+
 #if defined (HAVE_X_WINDOWS)
   /* Used by x_wait_for_event when watching for an X event on this frame.  */
   int wait_event_type;
@@ -658,20 +681,28 @@ default_pixels_per_inch_y (void)
   (WINDOWP (f->minibuffer_window)                              \
    && XFRAME (XWINDOW (f->minibuffer_window)->frame) == f)
 
+/* Pixel width of frame F.  */
+#define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width)
+
 /* Pixel height of frame F, including non-toolkit menu bar and
    non-toolkit tool bar lines.  */
 #define FRAME_PIXEL_HEIGHT(f) ((f)->pixel_height)
 
-/* Pixel width of frame F.  */
-#define FRAME_PIXEL_WIDTH(f) ((f)->pixel_width)
+/* Width of frame F, measured in canonical character columns,
+   not including scroll bars if any.  */
+#define FRAME_COLS(f) (f)->text_cols
 
 /* Height of frame F, measured in canonical lines, including
    non-toolkit menu bar and non-toolkit tool bar lines.  */
 #define FRAME_LINES(f) (f)->text_lines
 
-/* Width of frame F, measured in canonical character columns,
-   not including scroll bars if any.  */
-#define FRAME_COLS(f) (f)->text_cols
+/* Width of frame F, measured in pixels not including the width for
+   fringes, scroll bar, and internal borders.  */
+#define FRAME_TEXT_WIDTH(f) (f)->text_width
+
+/* Height of frame F, measured in pixels not including the height
+   for internal borders.  */
+#define FRAME_TEXT_HEIGHT(f) (f)->text_height
 
 /* Number of lines of frame F used for menu bar.
    This is relevant on terminal frames and on
@@ -679,6 +710,9 @@ default_pixels_per_inch_y (void)
    These lines are counted in FRAME_LINES.  */
 #define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines
 
+/* Pixel height of frame F's menu bar.  */
+#define FRAME_MENU_BAR_HEIGHT(f) (f)->menu_bar_height
+
 /* Nonzero if this frame should display a tool bar
    in a way that does not use any text lines.  */
 #if defined (USE_GTK) || defined (HAVE_NS)
@@ -688,19 +722,18 @@ default_pixels_per_inch_y (void)
 #endif
 
 /* Number of lines of frame F used for the tool-bar.  */
-
 #define FRAME_TOOL_BAR_LINES(f) (f)->tool_bar_lines
 
+/* Pixel height of frame F's tool-bar.  */
+#define FRAME_TOOL_BAR_HEIGHT(f) (f)->tool_bar_height
 
 /* Lines above the top-most window in frame F.  */
-
 #define FRAME_TOP_MARGIN(F) \
   (FRAME_MENU_BAR_LINES (F) + FRAME_TOOL_BAR_LINES (F))
 
-/* Pixel height of the top margin above.  */
-
-#define FRAME_TOP_MARGIN_HEIGHT(f) \
-  (FRAME_TOP_MARGIN (f) * FRAME_LINE_HEIGHT (f))
+/* Pixel height of frame F's top margin.  */
+#define FRAME_TOP_MARGIN_HEIGHT(F)                             \
+  (FRAME_MENU_BAR_HEIGHT (F) + FRAME_TOOL_BAR_HEIGHT (F))
 
 /* Nonzero if this frame should display a menu bar
    in a way that does not use any text lines.  */
@@ -788,7 +821,7 @@ default_pixels_per_inch_y (void)
 
 #define FRAME_LEFT_SCROLL_BAR_AREA_WIDTH(f)                            \
   (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)                          \
-   ? (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))       \
+   ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)                                 \
    : 0)
 
 /* Width of a scroll bar in frame F, measured in columns (characters),
@@ -804,7 +837,7 @@ default_pixels_per_inch_y (void)
 
 #define FRAME_RIGHT_SCROLL_BAR_AREA_WIDTH(f)                           \
   (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f)                         \
-   ? (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))       \
+   ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)                                 \
    : 0)
 
 /* Actual width of a scroll bar in frame F, measured in columns.  */
@@ -818,29 +851,36 @@ default_pixels_per_inch_y (void)
 
 #define FRAME_SCROLL_BAR_AREA_WIDTH(f)                                 \
   (FRAME_HAS_VERTICAL_SCROLL_BARS (f)                                  \
-   ? (FRAME_CONFIG_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))       \
+   ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f)                                 \
    : 0)
 
 /* Total width of frame F, in columns (characters),
    including the width used by scroll bars if any.  */
-
 #define FRAME_TOTAL_COLS(f) ((f)->total_cols)
 
-/* Set the width of frame F to VAL.
-   VAL is the width of a full-frame window,
-   not including scroll bars and fringes.  */
-
-#define SET_FRAME_COLS(f, val)                                         \
-  (FRAME_COLS (f) = (val),                                             \
-   (f)->total_cols = FRAME_TOTAL_COLS_ARG (f, FRAME_COLS (f)))
-
-/* Given a value WIDTH for frame F's nominal width,
-   return the value that FRAME_TOTAL_COLS should have.  */
-
-#define FRAME_TOTAL_COLS_ARG(f, width)         \
-  ((width)                                     \
-   + FRAME_SCROLL_BAR_COLS (f)                 \
-   + FRAME_FRINGE_COLS (f))
+/* Set the character widths of frame F.  WIDTH specifies a nominal
+   character text width.  */
+#define SET_FRAME_COLS(f, width)                                       \
+  ((f)->text_cols = (width),                                           \
+   (f)->total_cols = ((width)                                          \
+                     + FRAME_SCROLL_BAR_COLS (f)                       \
+                     + FRAME_FRINGE_COLS (f)))
+
+/* Set the pixel widths of frame F.  WIDTH specifies a nominal pixel
+   text width.  */
+#define SET_FRAME_WIDTH(f, width)                                      \
+  ((f)->text_width = (width),                                          \
+   (f)->pixel_width = ((width)                                         \
+                      + FRAME_SCROLL_BAR_AREA_WIDTH (f)                \
+                      + FRAME_TOTAL_FRINGE_WIDTH (f)                   \
+                      + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)))
+
+/* Set the pixel heights of frame F.  HEIGHT specifies a nominal pixel
+   text width.  */
+#define SET_FRAME_HEIGHT(f, height)                                    \
+  ((f)->text_height = (height),                                                \
+   (f)->pixel_height = ((height)                                       \
+                      + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)))
 
 /* Maximum + 1 legitimate value for FRAME_CURSOR_X.  */
 
@@ -1004,11 +1044,13 @@ extern Lisp_Object Vframe_list;
 #define FRAME_TOTAL_FRINGE_WIDTH(F) \
   (FRAME_LEFT_FRINGE_WIDTH (F) + FRAME_RIGHT_FRINGE_WIDTH (F))
 
-
 /* Pixel-width of internal border lines */
-
 #define FRAME_INTERNAL_BORDER_WIDTH(F) ((F)->internal_border_width)
 
+/* Pixel-size of window border lines */
+#define FRAME_RIGHT_DIVIDER_WIDTH(F) ((F)->right_divider_width)
+#define FRAME_BOTTOM_DIVIDER_WIDTH(F) ((F)->bottom_divider_width)
+
 #else /* not HAVE_WINDOW_SYSTEM */
 
 #define FRAME_FRINGE_COLS(F)   0
@@ -1016,11 +1058,10 @@ extern Lisp_Object Vframe_list;
 #define FRAME_LEFT_FRINGE_WIDTH(F)  0
 #define FRAME_RIGHT_FRINGE_WIDTH(F) 0
 #define FRAME_INTERNAL_BORDER_WIDTH(F) 0
+#define FRAME_RIGHT_DIVIDER_WIDTH(F) 0
+#define FRAME_BOTTOM_DIVIDER_WIDTH(F) 0
 
 #endif /* not HAVE_WINDOW_SYSTEM */
-
-
-
 \f
 /***********************************************************************
            Conversion between canonical units and pixels
@@ -1077,58 +1118,81 @@ extern Lisp_Object Vframe_list;
    Return the upper/left pixel position of the character cell on frame F
    at ROW/COL.  */
 
-#define FRAME_LINE_TO_PIXEL_Y(f, row) \
+#define FRAME_LINE_TO_PIXEL_Y(f, row)                                  \
   (((row) < FRAME_TOP_MARGIN (f) ? 0 : FRAME_INTERNAL_BORDER_WIDTH (f))        \
    + (row) * FRAME_LINE_HEIGHT (f))
 
-#define FRAME_COL_TO_PIXEL_X(f, col) \
-  (FRAME_INTERNAL_BORDER_WIDTH (f) \
+#define FRAME_COL_TO_PIXEL_X(f, col)           \
+  (FRAME_INTERNAL_BORDER_WIDTH (f)             \
    + (col) * FRAME_COLUMN_WIDTH (f))
 
 /* Return the pixel width/height of frame F if it has
    COLS columns/LINES rows.  */
 
 #define FRAME_TEXT_COLS_TO_PIXEL_WIDTH(f, cols) \
-  (FRAME_COL_TO_PIXEL_X (f, cols) \
-   + (f)->scroll_bar_actual_width \
-   + FRAME_TOTAL_FRINGE_WIDTH (f)      \
+  (FRAME_COL_TO_PIXEL_X (f, cols)              \
+   + FRAME_SCROLL_BAR_AREA_WIDTH (f)           \
+   + FRAME_TOTAL_FRINGE_WIDTH (f)              \
    + FRAME_INTERNAL_BORDER_WIDTH (f))
 
 #define FRAME_TEXT_LINES_TO_PIXEL_HEIGHT(f, lines) \
-  ((lines) * FRAME_LINE_HEIGHT (f) \
+  ((lines) * FRAME_LINE_HEIGHT (f)                \
    + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
 
-
 /* Return the row/column (zero-based) of the character cell containing
    the pixel on FRAME at Y/X.  */
 
-#define FRAME_PIXEL_Y_TO_LINE(f, y) \
-  (((y) < FRAME_TOP_MARGIN_HEIGHT (f)  \
-    ? (y)      \
+#define FRAME_PIXEL_Y_TO_LINE(f, y)                                    \
+  (((y) < FRAME_TOP_MARGIN_HEIGHT (f)                                  \
+    ? (y)                                                              \
     : ((y) < FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \
        ? (y) - (FRAME_TOP_MARGIN_HEIGHT (f) + FRAME_INTERNAL_BORDER_WIDTH (f) \
-               /* Arrange for the division to round down.  */  \
-               + FRAME_LINE_HEIGHT (f) - 1)    \
-       : (y) - FRAME_INTERNAL_BORDER_WIDTH (f)))       \
+               /* Arrange for the division to round down.  */          \
+               + FRAME_LINE_HEIGHT (f) - 1)                            \
+       : (y) - FRAME_INTERNAL_BORDER_WIDTH (f)))                       \
    / FRAME_LINE_HEIGHT (f))
 
-#define FRAME_PIXEL_X_TO_COL(f, x) \
+#define FRAME_PIXEL_X_TO_COL(f, x)             \
   (((x) - FRAME_INTERNAL_BORDER_WIDTH (f))     \
    / FRAME_COLUMN_WIDTH (f))
 
 /* How many columns/rows of text can we fit in WIDTH/HEIGHT pixels on
    frame F?  */
 
-#define FRAME_PIXEL_WIDTH_TO_TEXT_COLS(f, width)               \
-  (FRAME_PIXEL_X_TO_COL (f, ((width)                           \
-                            - FRAME_INTERNAL_BORDER_WIDTH (f)  \
-                            - FRAME_TOTAL_FRINGE_WIDTH (f)     \
-                            - (f)->scroll_bar_actual_width)))
+#define FRAME_PIXEL_WIDTH_TO_TEXT_COLS(f, width)                       \
+  (FRAME_PIXEL_X_TO_COL (f, ((width)                                   \
+                            - FRAME_INTERNAL_BORDER_WIDTH (f)          \
+                            - FRAME_TOTAL_FRINGE_WIDTH (f)             \
+                            - FRAME_SCROLL_BAR_AREA_WIDTH (f))))       \
 
-#define FRAME_PIXEL_HEIGHT_TO_TEXT_LINES(f, height) \
-  (FRAME_PIXEL_Y_TO_LINE (f, ((height) \
+#define FRAME_PIXEL_HEIGHT_TO_TEXT_LINES(f, height)                    \
+  (FRAME_PIXEL_Y_TO_LINE (f, ((height)                                 \
                              - FRAME_INTERNAL_BORDER_WIDTH (f))))
 
+/* Return the pixel width/height of frame F with a text size of
+   width/heigh.  */
+
+#define FRAME_TEXT_TO_PIXEL_WIDTH(f, width)      \
+  ((width)                                       \
+   + FRAME_SCROLL_BAR_AREA_WIDTH (f)             \
+   + FRAME_TOTAL_FRINGE_WIDTH (f)                \
+   + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+
+#define FRAME_TEXT_TO_PIXEL_HEIGHT(f, height)       \
+  ((height) + 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+
+/* Return the text width/height of frame F with a pixel size of
+   width/heigh.  */
+
+#define FRAME_PIXEL_TO_TEXT_WIDTH(f, width)      \
+  ((width)                                       \
+   - FRAME_SCROLL_BAR_AREA_WIDTH (f)             \
+   - FRAME_TOTAL_FRINGE_WIDTH (f)                \
+   - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+
+#define FRAME_PIXEL_TO_TEXT_HEIGHT(f, height)          \
+  ((height) - 2 * FRAME_INTERNAL_BORDER_WIDTH (f))
+
 /* Value is the smallest width of any character in any font on frame F.  */
 
 #define FRAME_SMALLEST_CHAR_WIDTH(f)           \
@@ -1151,6 +1215,7 @@ extern Lisp_Object Qfont;
 extern Lisp_Object Qbackground_color, Qforeground_color;
 extern Lisp_Object Qicon, Qicon_name, Qicon_type, Qicon_left, Qicon_top;
 extern Lisp_Object Qinternal_border_width;
+extern Lisp_Object Qright_divider_width, Qbottom_divider_width;
 extern Lisp_Object Qtooltip;
 extern Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position;
 extern Lisp_Object Qmouse_color;
@@ -1214,6 +1279,10 @@ extern void x_set_fringe_width (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_set_border_width (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_set_internal_border_width (struct frame *, Lisp_Object,
                                          Lisp_Object);
+extern void x_set_right_divider_width (struct frame *, Lisp_Object,
+                                      Lisp_Object);
+extern void x_set_bottom_divider_width (struct frame *, Lisp_Object,
+                                       Lisp_Object);
 extern void x_set_visibility (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_set_autoraise (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_set_autolower (struct frame *, Lisp_Object, Lisp_Object);
@@ -1237,7 +1306,7 @@ extern Lisp_Object display_x_get_resource (Display_Info *,
 
 extern void set_frame_menubar (struct frame *f, bool first_time, bool deep_p);
 extern void x_set_window_size (struct frame *f, int change_grav,
-                              int cols, int rows);
+                              int width, int height, bool pixelwise);
 extern Lisp_Object x_get_focus_frame (struct frame *);
 extern void x_set_mouse_position (struct frame *f, int h, int v);
 extern void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
@@ -1246,9 +1315,7 @@ extern void x_make_frame_invisible (struct frame *f);
 extern void x_iconify_frame (struct frame *f);
 extern void x_set_frame_alpha (struct frame *f);
 extern void x_set_menu_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
-extern void x_set_tool_bar_lines (struct frame *f,
-                                  Lisp_Object value,
-                                  Lisp_Object oldval);
+extern void x_set_tool_bar_lines (struct frame *, Lisp_Object, Lisp_Object);
 extern void x_activate_menubar (struct frame *);
 extern void x_real_positions (struct frame *, int *, int *);
 extern void free_frame_menubar (struct frame *);
index 9c77e65..db4f92d 100644 (file)
@@ -659,6 +659,10 @@ draw_fringe_bitmap_1 (struct window *w, struct glyph_row *row, int left_p, int o
        {
          /* If W has a vertical border to its left, don't draw over it.  */
          wd -= ((!WINDOW_LEFTMOST_P (w)
+                 /* This could be wrong when we allow window local
+                    right dividers - but the window on the left is hard
+                    to get.  */
+                 && !FRAME_RIGHT_DIVIDER_WIDTH (f)
                  && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
                  /* But don't reduce the fringe width if the window
                     has a left margin, because that means we are not
index 192b64a..d30a68a 100644 (file)
@@ -904,7 +904,7 @@ xg_clear_under_internal_border (struct frame *f)
 void
 xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
 {
-  int rows, columns;
+  int width, height;
 
   if (pixelwidth == -1 && pixelheight == -1)
     {
@@ -916,11 +916,11 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
     }
 
 
-  rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
-  columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
+  width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixelwidth);
+  height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelheight);
 
-  if (columns != FRAME_COLS (f)
-      || rows != FRAME_LINES (f)
+  if (width != FRAME_TEXT_WIDTH (f)
+      || height != FRAME_TEXT_HEIGHT (f)
       || pixelwidth != FRAME_PIXEL_WIDTH (f)
       || pixelheight != FRAME_PIXEL_HEIGHT (f))
     {
@@ -928,7 +928,7 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
       FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
       xg_clear_under_internal_border (f);
-      change_frame_size (f, rows, columns, 0, 1, 0);
+      change_frame_size (f, width, height, 0, 1, 0, 1);
       SET_FRAME_GARBAGED (f);
       cancel_mouse_face (f);
     }
@@ -938,11 +938,10 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
    COLUMNS/ROWS is the size the edit area shall have after the resize.  */
 
 void
-xg_frame_set_char_size (struct frame *f, int cols, int rows)
+xg_frame_set_char_size (struct frame *f, int width, int height)
 {
-  int pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
-    + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
   int pixelwidth;
+  int pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
 
   if (FRAME_PIXEL_HEIGHT (f) == 0)
     return;
@@ -959,9 +958,7 @@ xg_frame_set_char_size (struct frame *f, int cols, int rows)
 
   /* FRAME_TEXT_COLS_TO_PIXEL_WIDTH uses scroll_bar_actual_width, so call it
      after calculating that value.  */
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
-    + FRAME_TOOLBAR_WIDTH (f);
-
+  pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
 
   /* Do this before resize, as we don't know yet if we will be resized.  */
   xg_clear_under_internal_border (f);
@@ -991,7 +988,7 @@ xg_frame_set_char_size (struct frame *f, int cols, int rows)
     }
   else
     {
-      change_frame_size (f, rows, cols, 0, 1, 0);
+      change_frame_size (f, width, height, 0, 1, 0, 1);
       FRAME_PIXEL_WIDTH (f) = pixelwidth;
       FRAME_PIXEL_HEIGHT (f) = pixelheight;
      }
@@ -1381,7 +1378,7 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
   base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 1)
     + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
 
-  check_frame_size (f, &min_rows, &min_cols);
+  check_frame_size (f, &min_cols, &min_rows, 0);
   if (min_cols > 0) --min_cols; /* We used one col in base_width = ... 1); */
   if (min_rows > 0) --min_rows; /* We used one row in base_height = ... 1); */
 
index 891b427..502611b 100644 (file)
@@ -1146,7 +1146,7 @@ compute_motion (ptrdiff_t from, ptrdiff_t frombyte, EMACS_INT fromvpos,
   /* Negative width means use all available text columns.  */
   if (width < 0)
     {
-      width = window_body_cols (win);
+      width = window_body_width (win, 0);
       /* We must make room for continuation marks if we don't have fringes.  */
 #ifdef HAVE_WINDOW_SYSTEM
       if (!FRAME_WINDOW_P (XFRAME (win->frame)))
@@ -1756,7 +1756,7 @@ visible section of the buffer, and pass LINE and COL as TOPOS.  */)
                         ? window_internal_height (w)
                         : XINT (XCDR (topos))),
                        (NILP (topos)
-                        ? (window_body_cols (w)
+                        ? (window_body_width (w, 0)
                            - (
 #ifdef HAVE_WINDOW_SYSTEM
                               FRAME_WINDOW_P (XFRAME (w->frame)) ? 0 :
index 2e16a87..b50c06b 100644 (file)
@@ -347,6 +347,7 @@ static Lisp_Object Qmodifier_cache;
 /* Symbols to use for parts of windows.  */
 Lisp_Object Qmode_line;
 Lisp_Object Qvertical_line;
+Lisp_Object Qright_divider, Qbottom_divider;
 static Lisp_Object Qvertical_scroll_bar;
 Lisp_Object Qmenu_bar;
 
@@ -5302,6 +5303,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
          dy = yret = wy;
        }
       /* Nothing special for part == ON_SCROLL_BAR.  */
+      else if (part == ON_RIGHT_DIVIDER)
+       {
+         posn = Qright_divider;
+         width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
+         dx = xret = wx;
+         dy = yret = wy;
+       }
+      else if (part == ON_BOTTOM_DIVIDER)
+       {
+         posn = Qbottom_divider;
+         width = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+         dx = xret = wx;
+         dy = yret = wy;
+       }
 
       /* For clicks in the text area, fringes, or margins, call
         buffer_posn_from_coords to extract TEXTPOS, the buffer
@@ -10142,7 +10157,7 @@ On such systems, Emacs starts a subshell instead of suspending.  */)
      with a window system; but suspend should be disabled in that case.  */
   get_tty_size (fileno (CURTTY ()->input), &width, &height);
   if (width != old_width || height != old_height)
-    change_frame_size (SELECTED_FRAME (), height, width, 0, 0, 0);
+    change_frame_size (SELECTED_FRAME (), width, height, 0, 0, 0, 0);
 
   /* Run suspend-resume-hook.  */
   hook = intern ("suspend-resume-hook");
@@ -10978,6 +10993,8 @@ syms_of_keyboard (void)
   DEFSYM (Qvertical_line, "vertical-line");
   DEFSYM (Qvertical_scroll_bar, "vertical-scroll-bar");
   DEFSYM (Qmenu_bar, "menu-bar");
+  DEFSYM (Qright_divider, "right-divider");
+  DEFSYM (Qbottom_divider, "bottom-divider");
 
   DEFSYM (Qmouse_fixup_help_message, "mouse-fixup-help-message");
 
index b8aad95..a1aa59f 100644 (file)
@@ -457,6 +457,7 @@ extern Lisp_Object Qhelp_echo;
 
 /* Symbols to use for non-text mouse positions.  */
 extern Lisp_Object Qmode_line, Qvertical_line, Qheader_line;
+extern Lisp_Object Qright_divider, Qbottom_divider;
 
 /* True while doing kbd input.  */
 extern bool waiting_for_input;
index 52b20b7..60cbc98 100644 (file)
@@ -4042,6 +4042,7 @@ extern void syms_of_indent (void);
 /* Defined in frame.c.  */
 extern Lisp_Object Qonly, Qnone;
 extern Lisp_Object Qvisible;
+extern void set_frame_param (struct frame *, Lisp_Object, Lisp_Object);
 extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
 extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
 extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
index ee6020f..550e625 100644 (file)
@@ -703,7 +703,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
         }
     }
 
-  x_set_window_size (f, 0, f->text_cols, f->text_lines);
+  x_set_window_size (f, 0, f->text_cols, f->text_lines, 0);
 }
 
 
@@ -1266,6 +1266,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
+  f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
      = [NSCursor arrowCursor];
   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
@@ -1303,7 +1304,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   SET_FRAME_COLS (f, 0);
   FRAME_LINES (f) = 0;
-  change_frame_size (f, height, width, 1, 0, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 0);
 
   if (! f->output_data.ns->explicit_parent)
     {
index 22a8aec..0f22350 100644 (file)
@@ -654,6 +654,7 @@ struct ns_output
   Cursor hand_cursor;
   Cursor hourglass_cursor;
   Cursor horizontal_drag_cursor;
+  Cursor vertical_drag_cursor;
 
   /* NS-specific */
   Cursor current_pointer;
index d995bfa..7121366 100644 (file)
@@ -771,7 +771,12 @@ ns_update_window_end (struct window *w, bool cursor_on_p,
                                w->output_cursor.x, w->output_cursor.y);
 
       if (draw_window_fringes (w, 1))
-       x_draw_vertical_border (w);
+       {
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+       }
 
       unblock_input ();
     }
@@ -1235,7 +1240,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
 
 
 void
-x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
+x_set_window_size (struct frame *f, int change_grav, int cols, int rows, bool pixelwise)
 /* --------------------------------------------------------------------------
      Adjust window pixel size based on given character grid size
      Impl is a bit more complex than other terms, need to do some
@@ -1257,7 +1262,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
 
   block_input ();
 
-  check_frame_size (f, &rows, &cols);
+  check_frame_size (f, &cols, &rows, 0);
 
   f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
   compute_fringe_widths (f, 0);
@@ -1316,7 +1321,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
     [view setBoundsOrigin: origin];
   }
 
-  change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
+  change_frame_size (f, cols, rows, 0, 1, 0, 0); /* pretend, delay, safe */
   FRAME_PIXEL_WIDTH (f) = pixelwidth;
   FRAME_PIXEL_HEIGHT (f) = pixelheight;
 /*  SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
@@ -2504,6 +2509,28 @@ ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
 }
 
 
+static void
+ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+/* --------------------------------------------------------------------------
+     External (RIF): Draw a window divider.
+   -------------------------------------------------------------------------- */
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+  NSRect r = NSMakeRect (x0, y0, x1-x0, y1-y0);
+
+  NSTRACE (ns_draw_window_divider);
+
+  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  if (face)
+      [ns_lookup_indexed_color(face->foreground, f) set];
+
+  ns_focus (f, &r, 1);
+  NSRectFill(r);
+  ns_unfocus (f);
+}
+
+
 void
 show_hourglass (struct atimer *timer)
 {
@@ -4017,6 +4044,7 @@ static struct redisplay_interface ns_redisplay_interface =
   ns_clear_frame_area,
   ns_draw_window_cursor,
   ns_draw_vertical_window_border,
+  ns_draw_window_divider,
   ns_shift_glyphs_for_insert
 };
 
@@ -5657,7 +5685,7 @@ not_in_argv (NSString *arg)
 
       FRAME_PIXEL_WIDTH (emacsframe) = neww;
       FRAME_PIXEL_HEIGHT (emacsframe) = newh;
-      change_frame_size (emacsframe, rows, cols, 0, delay, 0);
+      change_frame_size (emacsframe, cols, rows, 0, delay, 0, 0);
       SET_FRAME_GARBAGED (emacsframe);
       cancel_mouse_face (emacsframe);
 
@@ -7330,7 +7358,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
 
   /* Now make the frame display the given font.  */
   if (FRAME_NS_WINDOW (f) != 0)
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+    x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f), 0);
 
   return font_object;
 }
index e3c56a6..80e010e 100644 (file)
@@ -1766,8 +1766,9 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
        }
       else if (WINDOWP (obj))
        {
-         void *ptr = XWINDOW (obj);
-         int len = sprintf (buf, "#<window %p", ptr);
+         int len;
+         strout ("#<window ", -1, -1, printcharfun);
+         len = sprintf (buf, "%d", XWINDOW (obj)->sequence_number);
          strout (buf, len, len, printcharfun);
          if (BUFFERP (XWINDOW (obj)->contents))
            {
index 877d43b..4d90002 100644 (file)
@@ -2407,7 +2407,7 @@ frame's terminal). */)
             was suspended.  */
          get_tty_size (fileno (t->display_info.tty->input), &width, &height);
          if (width != old_width || height != old_height)
-           change_frame_size (f, height, width, 0, 0, 0);
+           change_frame_size (f, width, height, 0, 0, 0, 0);
          SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
        }
 
index 403a7ba..975d3f9 100644 (file)
@@ -1383,6 +1383,17 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     horizontal_drag_cursor
       = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_h_double_arrow);
 
+  if (!NILP (Vx_window_vertical_drag_shape))
+    {
+      CHECK_NUMBER (Vx_window_vertical_drag_shape);
+      vertical_drag_cursor
+       = XCreateFontCursor (FRAME_X_DISPLAY (f),
+                            XINT (Vx_window_vertical_drag_shape));
+    }
+  else
+    vertical_drag_cursor
+      = XCreateFontCursor (FRAME_X_DISPLAY (f), XC_sb_v_double_arrow);
+
   /* Check and report errors with the above calls.  */
   x_check_errors (FRAME_W32_DISPLAY (f), "can't set cursor shape: %s");
   x_uncatch_errors (FRAME_W32_DISPLAY (f), count);
@@ -1623,6 +1634,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     nlines = 0;
 
   FRAME_MENU_BAR_LINES (f) = 0;
+  FRAME_MENU_BAR_HEIGHT (f) = 0;
   if (nlines)
     FRAME_EXTERNAL_MENU_BAR (f) = 1;
   else
@@ -1634,7 +1646,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       /* Adjust the frame size so that the client (text) dimensions
         remain the same.  This depends on FRAME_EXTERNAL_MENU_BAR being
         set correctly.  */
-      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
       do_pending_window_change (0);
     }
   adjust_frame_glyphs (f);
@@ -1642,16 +1654,17 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 
 
 /* Set the number of lines used for the tool bar of frame F to VALUE.
-   VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL
-   is the old number of tool bar lines.  This function changes the
-   height of all windows on frame F to match the new tool bar height.
-   The frame's height doesn't change.  */
+   VALUE not an integer, or < 0 means set the lines to zero.  OLDVAL is
+   the old number of tool bar lines (and is unused).  This function may
+   change the height of all windows on frame F to match the new tool bar
+   height.  By design, the frame's height doesn't change (but maybe it
+   should if we don't get enough space otherwise).  */
 
 void
 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 {
   int delta, nlines, root_height;
-  Lisp_Object root_window;
+  int unit = FRAME_LINE_HEIGHT (f);
 
   /* Treat tool bars like menu bars.  */
   if (FRAME_MINIBUF_ONLY_P (f))
@@ -1666,19 +1679,25 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
   /* Make sure we redisplay all windows in this frame.  */
   windows_or_buffers_changed = 23;
 
-  delta = nlines - FRAME_TOOL_BAR_LINES (f);
+  /* DELTA is in pixels now.  */
+  delta = (nlines - FRAME_TOOL_BAR_LINES (f)) * unit;
 
-  /* Don't resize the tool-bar to more than we have room for.  */
-  root_window = FRAME_ROOT_WINDOW (f);
-  root_height = WINDOW_TOTAL_LINES (XWINDOW (root_window));
-  if (root_height - delta < 1)
+  /* Don't resize the tool-bar to more than we have room for.  FIXME:
+     This must use window_sizable eventually !!!!!!!!!!!!  */
+  if (delta > 0)
     {
-      delta = root_height - 1;
-      nlines = FRAME_TOOL_BAR_LINES (f) + delta;
+      root_height = WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)));
+      if (root_height - delta < unit)
+       {
+         delta = root_height - unit;
+         nlines = (root_height / unit) + min (1, (root_height % unit));
+       }
     }
 
   FRAME_TOOL_BAR_LINES (f) = nlines;
-  resize_frame_windows (f, FRAME_LINES (f), 0);
+  FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
+  ++windows_or_buffers_changed;
+  resize_frame_windows (f, FRAME_TEXT_HEIGHT (f), 0, 1);
   adjust_frame_glyphs (f);
 
   /* We also have to make sure that the internal border at the top of
@@ -1687,7 +1706,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
      below the tool bar if one is displayed, but is below the menu bar
      if there isn't a tool bar.  The tool bar draws into the area
      below the menu bar.  */
-  if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
+  if (FRAME_W32_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
     {
       clear_frame (f);
       clear_current_matrices (f);
@@ -1700,7 +1719,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     {
       int height = FRAME_INTERNAL_BORDER_WIDTH (f);
       int width = FRAME_PIXEL_WIDTH (f);
-      int y = nlines * FRAME_LINE_HEIGHT (f);
+      int y = nlines * unit;
 
       block_input ();
       {
@@ -1948,7 +1967,7 @@ w32_createwindow (struct frame *f)
       SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
       SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
       SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
-      SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
+      SetWindowLong (hwnd, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
       SetWindowLong (hwnd, WND_BACKGROUND_INDEX, FRAME_BACKGROUND_PIXEL (f));
 
       /* Enable drag-n-drop.  */
@@ -3224,6 +3243,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
                               - WINDOW_RIGHT_MARGIN_WIDTH (w)
                               - WINDOW_RIGHT_FRINGE_WIDTH (w));
          form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
+                               - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
                                - w32_system_caret_mode_height);
 
          /* Punt if the window was deleted behind our back.  */
@@ -3773,7 +3793,7 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
     case WM_WINDOWPOSCHANGING:
       /* Don't restrict the sizing of tip frames.  */
-      if (hwnd == tip_window)
+      if (frame_resize_pixelwise || hwnd == tip_window)
        return 0;
 
       /* Don't restrict the sizing of fullscreened frames, allowing them to be
@@ -4452,6 +4472,10 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Default internalBorderWidth to 0 on Windows to match other programs.  */
   x_default_parameter (f, parameters, Qinternal_border_width, make_number (0),
                       "internalBorderWidth", "InternalBorder", RES_TYPE_NUMBER);
+  x_default_parameter (f, parameters, Qright_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
+  x_default_parameter (f, parameters, Qbottom_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
   x_default_parameter (f, parameters, Qvertical_scroll_bars, Qright,
                       "verticalScrollBars", "ScrollBars", RES_TYPE_SYMBOL);
 
@@ -4481,6 +4505,20 @@ This function is an internal primitive--use `make-frame' instead.  */)
      happen.  */
   init_frame_faces (f);
 
+  /* PXW: This is a duplicate from below.  We have to do it here since
+     otherwise x_set_tool_bar_lines will work with the character sizes
+     installed by init_frame_faces while the frame's pixel size is still
+     calculated from a character size of 1 and we subsequently hit the
+     eassert (height >= 0) assertion in window_box_height.  The
+     non-pixelwise code apparently worked around this because it had one
+     frame line vs one toolbar line which left us with a zero root
+     window height which was obviously wrong as well ...  */
+  width = FRAME_TEXT_WIDTH (f);
+  height = FRAME_TEXT_HEIGHT (f);
+  FRAME_TEXT_HEIGHT (f) = 0;
+  SET_FRAME_WIDTH (f, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 1);
+
   /* The X resources controlling the menu-bar and tool-bar are
      processed specially at startup, and reflected in the mode
      variables; ignore them here.  */
@@ -4509,6 +4547,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.w32->hand_cursor = w32_load_cursor (IDC_HAND);
   f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
   f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
+  f->output_data.w32->vertical_drag_cursor = w32_load_cursor (IDC_SIZENS);
 
   f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
 
@@ -4546,12 +4585,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
      Change will not be effected unless different from the current
      FRAME_LINES (f).  */
-  width = FRAME_COLS (f);
-  height = FRAME_LINES (f);
-
-  FRAME_LINES (f) = 0;
-  SET_FRAME_COLS (f, 0);
-  change_frame_size (f, height, width, 1, 0, 0);
+  width = FRAME_TEXT_WIDTH (f);
+  height = FRAME_TEXT_HEIGHT (f);
+  FRAME_TEXT_HEIGHT (f) = 0;
+  SET_FRAME_WIDTH (f, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 1);
 
   /* Tell the server what size and position, etc, we want, and how
      badly we want them.  This should be done after we have the menu
@@ -5689,6 +5727,10 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
                       "internalBorderWidth", "internalBorderWidth",
                       RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qright_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
 
   /* Also do the stuff which must be set before the window exists.  */
   x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
@@ -5733,14 +5775,14 @@ x_create_tip_frame (struct w32_display_info *dpyinfo,
   x_default_parameter (f, parms, Qcursor_type, Qbox,
                       "cursorType", "CursorType", RES_TYPE_SYMBOL);
 
-  /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
-     Change will not be effected unless different from the current
-     FRAME_LINES (f).  */
+  /* Dimensions, especially FRAME_LINES (f), must be done via
+     change_frame_size.  Change will not be effected unless different
+     from the current FRAME_LINES (f).  */
   width = FRAME_COLS (f);
   height = FRAME_LINES (f);
   FRAME_LINES (f) = 0;
   SET_FRAME_COLS (f, 0);
-  change_frame_size (f, height, width, 1, 0, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 0);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -5998,6 +6040,10 @@ Text larger than the specified size is clipped.  */)
     parms = Fcons (Fcons (Qname, build_string ("tooltip")), parms);
   if (NILP (Fassq (Qinternal_border_width, parms)))
     parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
+  if (NILP (Fassq (Qright_divider_width, parms)))
+    parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms);
+  if (NILP (Fassq (Qbottom_divider_width, parms)))
+    parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms);
   if (NILP (Fassq (Qborder_width, parms)))
     parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
   if (NILP (Fassq (Qborder_color, parms)))
@@ -6019,6 +6065,8 @@ Text larger than the specified size is clipped.  */)
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left_col = 0;
   w->top_line = 0;
+  w->pixel_left = 0;
+  w->pixel_top = 0;
 
   if (CONSP (Vx_max_tooltip_size)
       && INTEGERP (XCAR (Vx_max_tooltip_size))
@@ -6035,6 +6083,9 @@ Text larger than the specified size is clipped.  */)
       w->total_lines = 40;
     }
 
+  w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f);
+  w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f);
+
   FRAME_TOTAL_COLS (f) = WINDOW_TOTAL_COLS (w);
   adjust_frame_glyphs (f);
   w->pseudo_window_p = 1;
@@ -6100,11 +6151,17 @@ Text larger than the specified size is clipped.  */)
      width of the frame.  */
   if (seen_reversed_p)
     {
-      /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
+      /* PXW: Why do we do the pixel-to-cols conversion only if
+        seen_reversed_p holds?  Don't we have to set other fields of
+        the window/frame stucture ?
+
+        w->total_cols and FRAME_TOTAL_COLS want the width in columns,
         not in pixels.  */
+      w->pixel_width = width;
       width /= WINDOW_FRAME_COLUMN_WIDTH (w);
       w->total_cols = width;
       FRAME_TOTAL_COLS (f) = width;
+      SET_FRAME_WIDTH (f, width);
       adjust_frame_glyphs (f);
       w->pseudo_window_p = 1;
       clear_glyph_matrix (w->desired_matrix);
@@ -6134,16 +6191,15 @@ Text larger than the specified size is clipped.  */)
        }
     }
 
-  /* Round up the height to an integral multiple of FRAME_LINE_HEIGHT.  */
-  if (height % FRAME_LINE_HEIGHT (f) != 0)
-    height += FRAME_LINE_HEIGHT (f) - height % FRAME_LINE_HEIGHT (f);
   /* Add the frame's internal border to the width and height the w32
      window should have.  */
   height += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
   width += 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
 
   /* Move the tooltip window where the mouse pointer is.  Resize and
-     show it.  */
+     show it.
+
+     PXW: This should use the frame's pixel coordinates.  */
   compute_tip_xy (f, parms, dx, dy, width, height, &root_x, &root_y);
 
   {
@@ -6919,6 +6975,29 @@ This is a direct interface to the Windows API FindWindow function.  */)
   return Qt;
 }
 
+DEFUN ("w32-frame-rect", Fw32_frame_rect, Sw32_frame_rect, 0, 2, 0,
+       doc: /* Return boundary rectangle of FRAME in screen coordinates.
+FRAME must be a live frame and defaults to the selected one.
+
+The boundary rectangle is a list of four elements, specifying the left,
+top, right and bottom screen coordinates of FRAME including menu and
+title bar and decorations.  Optional argument CLIENT non-nil means to
+return the boundaries of the client rectangle which excludes menu and
+title bar and decorations.  */)
+  (Lisp_Object frame, Lisp_Object client)
+{
+  struct frame *f = decode_live_frame (frame);
+  RECT rect;
+
+  if (!NILP (client))
+    GetClientRect (FRAME_W32_WINDOW (f), &rect);
+  else
+    GetWindowRect (FRAME_W32_WINDOW (f), &rect);
+
+  return list4 (make_number (rect.left), make_number (rect.top),
+               make_number (rect.right), make_number (rect.bottom));
+}
+
 DEFUN ("w32-battery-status", Fw32_battery_status, Sw32_battery_status, 0, 0, 0,
        doc: /* Get power status information from Windows system.
 
@@ -7510,6 +7589,8 @@ frame_parm_handler w32_frame_parm_handlers[] =
   x_set_icon_name,
   x_set_icon_type,
   x_set_internal_border_width,
+  x_set_right_divider_width,
+  x_set_bottom_divider_width,
   x_set_menu_bar_lines,
   x_set_mouse_color,
   x_explicitly_set_name,
@@ -7761,6 +7842,13 @@ or when you set the mouse color.  */);
 This variable takes effect when you create a new frame
 or when you set the mouse color.  */);
   Vx_window_horizontal_drag_shape = Qnil;
+
+  DEFVAR_LISP ("x-window-vertical-drag-cursor",
+              Vx_window_vertical_drag_shape,
+              doc: /* Pointer shape to use for indicating a window can be dragged vertically.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
+  Vx_window_vertical_drag_shape = Qnil;
 #endif
 
   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
@@ -7853,6 +7941,7 @@ only be necessary if the default setting causes problems.  */);
   defsubr (&Sw32_reconstruct_hot_key);
   defsubr (&Sw32_toggle_lock_key);
   defsubr (&Sw32_window_exists_p);
+  defsubr (&Sw32_frame_rect);
   defsubr (&Sw32_battery_status);
 
 #ifdef WINDOWSNT
index a157cb5..d4c96bd 100644 (file)
@@ -587,7 +587,7 @@ resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
 {
   struct frame *f = get_frame ();
 
-  change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
+  change_frame_size (f, event->dwSize.X, event->dwSize.Y, 0, 1, 0, 0);
   SET_FRAME_GARBAGED (f);
 }
 
@@ -602,9 +602,9 @@ maybe_generate_resize_event (void)
   /* It is okay to call this unconditionally, since it will do nothing
      if the size hasn't actually changed.  */
   change_frame_size (f,
-                    1 + info.srWindow.Bottom - info.srWindow.Top,
                     1 + info.srWindow.Right - info.srWindow.Left,
-                    0, 0, 0);
+                    1 + info.srWindow.Bottom - info.srWindow.Top,
+                    0, 0, 0, 0);
 }
 
 #if HAVE_W32NOTIFY
index b846a3f..4f8e8db 100644 (file)
@@ -505,7 +505,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
     /* Force the window size to be recomputed so that the frame's text
        area remains the same, if menubar has just been created.  */
     if (old_widget == NULL)
-      x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+      x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
   }
 
   unblock_input ();
index 90cc204..38b2978 100644 (file)
@@ -180,7 +180,7 @@ void x_lower_frame (struct frame *);
 void x_scroll_bar_clear (struct frame *);
 void x_wm_set_size_hint (struct frame *, long, bool);
 void x_raise_frame (struct frame *);
-void x_set_window_size (struct frame *, int, int, int);
+void x_set_window_size (struct frame *, int, int, int, bool);
 void x_wm_set_window_state (struct frame *, int);
 void x_wm_set_icon_pixmap (struct frame *, int);
 static void w32_initialize (void);
@@ -621,6 +621,32 @@ w32_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
 }
 
 
+/* Draw a window divider from (x0, y0) to (x1, y1)  */
+
+static void
+w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  RECT r;
+  HDC hdc;
+  struct face *face;
+
+  r.left = x0;
+  r.right = x1;
+  r.top = y0;
+  r.bottom = y1;
+
+  hdc = get_frame_dc (f);
+  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  if (face)
+    w32_fill_rect (f, hdc, face->foreground, &r);
+  else
+    w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+
+  release_frame_dc (f, hdc);
+}
+
+
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -648,7 +674,12 @@ x_update_window_end (struct window *w, bool cursor_on_p,
                                w->output_cursor.x, w->output_cursor.y);
 
       if (draw_window_fringes (w, 1))
-       x_draw_vertical_border (w);
+       {
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+       }
 
       unblock_input ();
     }
@@ -777,8 +808,7 @@ w32_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
          if (sb_width > 0)
            {
              int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-             int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                                   * FRAME_COLUMN_WIDTH (f));
+             int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
 
              if (bx < 0)
                {
@@ -2675,8 +2705,7 @@ x_scroll_run (struct window *w, struct run *run)
       if (sb_width > 0)
        {
          int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-         int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                               * FRAME_COLUMN_WIDTH (f));
+         int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
 
          if (bar_area_x + bar_area_width == x)
            {
@@ -3740,7 +3769,7 @@ w32_set_vertical_scroll_bar (struct window *w,
   /* Get window dimensions.  */
   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
   top  = window_y;
-  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
+  width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
@@ -4681,6 +4710,47 @@ w32_read_socket (struct terminal *terminal,
                  break;
 
                case SIZE_MAXIMIZED:
+                 {
+                   bool iconified = FRAME_ICONIFIED_P (f);
+
+                   SET_FRAME_VISIBLE (f, 1);
+                   SET_FRAME_ICONIFIED (f, 0);
+
+                   /* wait_reading_process_output will notice this
+                      and update the frame's display structures.  */
+                   SET_FRAME_GARBAGED (f);
+
+                   if (iconified)
+                     {
+                       int x, y;
+
+                       /* Reset top and left positions of the Window
+                          here since Windows sends a WM_MOVE message
+                          BEFORE telling us the Window is minimized
+                          when the Window is iconified, with 3000,3000
+                          as the co-ords. */
+                       x_real_positions (f, &x, &y);
+                       f->left_pos = x;
+                       f->top_pos = y;
+
+                       inev.kind = DEICONIFY_EVENT;
+                       XSETFRAME (inev.frame_or_window, f);
+                     }
+                   else if (! NILP (Vframe_list)
+                            && ! NILP (XCDR (Vframe_list)))
+                     /* Force a redisplay sooner or later
+                        to update the frame titles
+                        in case this is the second frame.  */
+                     record_asynch_buffer_change ();
+                 }
+
+                 if (get_frame_param (f, Qfullscreen) == Qnil)
+                   set_frame_param (f, Qfullscreen, Qmaximized);
+                 else if (get_frame_param (f, Qfullscreen) != Qmaximized)
+                   set_frame_param (f, Qmaximized, Qmaximized);
+
+                 break;
+
                case SIZE_RESTORED:
                  {
                    bool iconified = FRAME_ICONIFIED_P (f);
@@ -4712,6 +4782,12 @@ w32_read_socket (struct terminal *terminal,
                         in case this is the second frame.  */
                      record_asynch_buffer_change ();
                  }
+
+                 if (get_frame_param (f, Qfullscreen) == Qmaximized)
+                   set_frame_param (f, Qfullscreen, Qnil);
+                 else if (get_frame_param (f, Qmaximized) != Qnil)
+                   set_frame_param (f, Qmaximized, Qnil);
+
                  break;
                }
            }
@@ -4719,16 +4795,14 @@ w32_read_socket (struct terminal *terminal,
          if (f && !FRAME_ICONIFIED_P (f) && msg.msg.wParam != SIZE_MINIMIZED)
            {
              RECT rect;
-             int rows;
-             int columns;
-             int width;
-             int height;
+             int rows, columns, width, height, text_width, text_height;
 
              GetClientRect (msg.msg.hwnd, &rect);
 
              height = rect.bottom - rect.top;
              width = rect.right - rect.left;
-
+             text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width);
+             text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height);
              rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
              columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
 
@@ -4738,16 +4812,18 @@ w32_read_socket (struct terminal *terminal,
                 not changed, the font size may have changed, so we need
                 to check the pixel dimensions as well.  */
 
-             if (columns != FRAME_COLS (f)
-                 || rows != FRAME_LINES (f)
-                 || width != FRAME_PIXEL_WIDTH (f)
-                 || height != FRAME_PIXEL_HEIGHT (f))
+             if (width != FRAME_PIXEL_WIDTH (f)
+                 || height != FRAME_PIXEL_HEIGHT (f)
+                 || text_width != FRAME_TEXT_WIDTH (f)
+                 || text_height != FRAME_TEXT_HEIGHT (f))
                {
-                 change_frame_size (f, rows, columns, 0, 1, 0);
+                 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
                  SET_FRAME_GARBAGED (f);
                  cancel_mouse_face (f);
-                 FRAME_PIXEL_WIDTH (f) = width;
-                 FRAME_PIXEL_HEIGHT (f) = height;
+                 /* Do we want to set these here ????  */
+/**              FRAME_PIXEL_WIDTH (f) = width; **/
+/**              FRAME_TEXT_WIDTH (f) = text_width; **/
+/**              FRAME_PIXEL_HEIGHT (f) = height; **/
                  f->win_gravity = NorthWestGravity;
                }
            }
@@ -5404,7 +5480,8 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-       x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f),
+                          FRAME_TEXT_HEIGHT (f), 1);
     }
 
   /* X version sets font of input methods here also.  */
@@ -5542,7 +5619,7 @@ x_check_fullscreen (struct frame *f)
          when setting WM manager hints.  */
       if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
         {
-          change_frame_size (f, height, width, 0, 1, 0);
+          change_frame_size (f, width, height, 0, 1, 0, 0);
           SET_FRAME_GARBAGED (f);
           cancel_mouse_face (f);
 
@@ -5606,20 +5683,28 @@ w32fullscreen_hook (struct frame *f)
    Otherwise we leave the window gravity unchanged.  */
 
 void
-x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
 {
   int pixelwidth, pixelheight;
 
   block_input ();
 
-  check_frame_size (f, &rows, &cols);
+  check_frame_size (f, &width, &height, pixelwise);
   f->scroll_bar_actual_width
     = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
-  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+  if (pixelwise)
+    {
+      pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
+      pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
+    }
+  else
+    {
+      pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
+      pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
+    }
 
   f->win_gravity = NorthWestGravity;
   x_wm_set_size_hint (f, (long) 0, 0);
@@ -5670,7 +5755,7 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
 
      We pass 1 for DELAY since we can't run Lisp code inside of
      a BLOCK_INPUT.  */
-  change_frame_size (f, rows, cols, 0, 1, 0);
+  change_frame_size (f, width, height, 0, 1, 0, 0);
   FRAME_PIXEL_WIDTH (f) = pixelwidth;
   FRAME_PIXEL_HEIGHT (f) = pixelheight;
 
@@ -6051,7 +6136,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
   SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
   SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
   SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
-  SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
+  SetWindowLong (window, WND_SCROLLBAR_INDEX, FRAME_SCROLL_BAR_AREA_WIDTH (f));
 
   leave_crit ();
 }
@@ -6191,6 +6276,7 @@ static struct redisplay_interface w32_redisplay_interface =
   w32_clear_frame_area,
   w32_draw_window_cursor,
   w32_draw_vertical_window_border,
+  w32_draw_window_divider,
   w32_shift_glyphs_for_insert
 };
 
index 6825e3c..779b37e 100644 (file)
@@ -230,7 +230,7 @@ extern struct w32_display_info *w32_term_init (Lisp_Object,
 extern int w32_defined_color (struct frame *f, const char *color,
                               XColor *color_def, int alloc);
 extern void x_set_window_size (struct frame *f, int change_grav,
-                              int cols, int rows);
+                              int width, int height, bool pixelwise);
 extern int x_display_pixel_height (struct w32_display_info *);
 extern int x_display_pixel_width (struct w32_display_info *);
 extern Lisp_Object x_get_focus_frame (struct frame *);
@@ -349,6 +349,7 @@ struct w32_output
   Cursor hand_cursor;
   Cursor hourglass_cursor;
   Cursor horizontal_drag_cursor;
+  Cursor vertical_drag_cursor;
 
   /* Non-zero means hourglass cursor is currently displayed.  */
   unsigned hourglass_p : 1;
index d6469d7..89b43fd 100644 (file)
@@ -412,7 +412,7 @@ set_frame_size (EmacsFrame ew)
 #if 0 /* This can run Lisp code, and it is dangerous to give
         out the frame to Lisp code before it officially exists.
         This is handled in Fx_create_frame so not needed here.  */
-    change_frame_size (f, h, w, 1, 0, 0);
+    change_frame_size (f, w, h, 1, 0, 0, 0);
 #endif
     char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
     ew->core.width = pixel_width;
@@ -467,7 +467,7 @@ update_wm_hints (EmacsFrame ew)
   if (! wmshell) return;
 
 #if 0
-  check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
+  check_frame_size (ew->emacs_frame.frame, &min_cols, &min_rows, 0);
 #endif
 
   pixel_to_char_size (ew, ew->core.width, ew->core.height,
@@ -681,7 +681,7 @@ EmacsFrameResize (Widget widget)
       || ew->core.width != FRAME_PIXEL_WIDTH (f)
       || ew->core.height + x->menubar_height != FRAME_PIXEL_HEIGHT (f))
     {
-      change_frame_size (f, rows, columns, 0, 1, 0);
+      change_frame_size (f, columns, rows, 0, 1, 0, 0);
       update_wm_hints (ew);
       update_various_frame_slots (ew);
 
@@ -735,8 +735,8 @@ EmacsFrameSetValues (Widget cur_widget, Widget req_widget, Widget new_widget, Ar
       new->core.width = pixel_width;
       new->core.height = pixel_height;
 
-      change_frame_size (new->emacs_frame.frame, char_height, char_width,
-                         1, 0, 0);
+      change_frame_size (new->emacs_frame.frame, char_width, char_height,
+                        1, 0, 0, 0);
       needs_a_refresh = True;
     }
 
@@ -798,7 +798,7 @@ EmacsFrameSetCharSize (Widget widget, int columns, int rows)
   EmacsFrame ew = (EmacsFrame) widget;
   struct frame *f = ew->emacs_frame.frame;
 
-  x_set_window_size (f, 0, columns, rows);
+  x_set_window_size (f, 0, columns, rows, 0);
 }
 
 \f
index 89fcb49..e73c50f 100644 (file)
@@ -51,6 +51,7 @@ static Lisp_Object Qrecord_window_buffer;
 static Lisp_Object Qwindow_deletable_p, Qdelete_window, Qdisplay_buffer;
 static Lisp_Object Qreplace_buffer_in_windows, Qget_mru_window;
 static Lisp_Object Qwindow_resize_root_window, Qwindow_resize_root_window_vertically;
+static Lisp_Object Qwindow_pixel_to_total;
 static Lisp_Object Qscroll_up, Qscroll_down, Qscroll_command;
 static Lisp_Object Qsafe, Qabove, Qbelow, Qwindow_size, Qclone_of;
 
@@ -74,6 +75,7 @@ static int foreach_window_1 (struct window *,
 static Lisp_Object window_list_1 (Lisp_Object, Lisp_Object, Lisp_Object);
 static int window_resize_check (struct window *, bool);
 static void window_resize_apply (struct window *, bool);
+static void window_resize_apply_total (struct window *, bool);
 static Lisp_Object select_window (Lisp_Object, Lisp_Object, int);
 static void select_window_1 (Lisp_Object, bool);
 
@@ -112,6 +114,9 @@ Lisp_Object minibuf_selected_window;
 /* Hook run at end of temp_output_buffer_show.  */
 static Lisp_Object Qtemp_buffer_show_hook;
 
+/* Incremented for each window created.  */
+static int sequence_number;
+
 /* Nonzero after init_window_once has finished.  */
 static int window_initialized;
 
@@ -675,6 +680,31 @@ selected one.  */)
   return make_number (decode_live_window (window)->use_time);
 }
 \f
+DEFUN ("window-pixel-width", Fwindow_pixel_width, Swindow_pixel_width, 0, 1, 0,
+       doc: /* Return the pixel width of window WINDOW.
+WINDOW must be a valid window and defaults to the selected one.
+
+The return value includes the fringes and margins of WINDOW as well as
+any vertical dividers or scroll bars belonging to WINDOW.  If WINDOW is
+an internal window, its pixel width is the width of the screen areas
+spanned by its children.  */)
+     (Lisp_Object window)
+{
+  return make_number (decode_valid_window (window)->pixel_width);
+}
+
+DEFUN ("window-pixel-height", Fwindow_pixel_height, Swindow_pixel_height, 0, 1, 0,
+       doc: /* Return the pixel height of window WINDOW.
+WINDOW must be a valid window and defaults to the selected one.
+
+The return value includes the mode line and header line, if any.  If
+WINDOW is an internal window, its pixel height is the height of the
+screen areas spanned by its children.  */)
+  (Lisp_Object window)
+{
+  return make_number (decode_valid_window (window)->pixel_height);
+}
+
 DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 1, 0,
        doc: /* Return the total height, in lines, of window WINDOW.
 WINDOW must be a valid window and defaults to the selected one.
@@ -732,6 +762,30 @@ WINDOW must be a valid window and defaults to the selected one.  */)
   return decode_valid_window (window)->new_normal;
 }
 
+DEFUN ("window-new-pixel", Fwindow_new_pixel, Swindow_new_pixel, 0, 1, 0,
+       doc: /* Return new pixel size of window WINDOW.
+WINDOW must be a valid window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return decode_valid_window (window)->new_pixel;
+}
+
+DEFUN ("window-pixel-left", Fwindow_pixel_left, Swindow_pixel_left, 0, 1, 0,
+       doc: /* Return left pixel edge of window WINDOW.
+WINDOW must be a valid window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return make_number (decode_valid_window (window)->pixel_left);
+}
+
+DEFUN ("window-pixel-top", Fwindow_pixel_top, Swindow_pixel_top, 0, 1, 0,
+       doc: /* Return top pixel edge of window WINDOW.
+WINDOW must be a valid window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return make_number (decode_valid_window (window)->pixel_top);
+}
+
 DEFUN ("window-left-column", Fwindow_left_column, Swindow_left_column, 0, 1, 0,
        doc: /* Return left column of window WINDOW.
 This is the distance, in columns, between the left edge of WINDOW and
@@ -760,75 +814,118 @@ WINDOW must be a valid window and defaults to the selected one.  */)
    header line of W.  */
 
 static int
-window_body_lines (struct window *w)
+window_body_height (struct window *w, bool pixelwise)
 {
-  int height = w->total_lines;
-
-  if (!MINI_WINDOW_P (w))
-    {
-      if (WINDOW_WANTS_MODELINE_P (w))
-       --height;
-      if (WINDOW_WANTS_HEADER_LINE_P (w))
-       --height;
-    }
+  int pixels = (w->pixel_height
+               - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
+               - WINDOW_HEADER_LINE_HEIGHT (w)
+               - WINDOW_MODE_LINE_HEIGHT (w));
+  int unit = FRAME_LINE_HEIGHT (WINDOW_XFRAME (w));
 
-  return height;
+  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
 }
 
 /* Return the number of columns of W's body.  Don't count columns
    occupied by the scroll bar or the vertical bar separating W from its
    right sibling.  On window-systems don't count fringes or display
    margins either.  */
-
 int
-window_body_cols (struct window *w)
+window_body_width (struct window *w, bool pixelwise)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  int width = w->total_cols;
 
-  if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
-    /* Scroll bars occupy a few columns.  */
-    width -= WINDOW_CONFIG_SCROLL_BAR_COLS (w);
-  else if (!FRAME_WINDOW_P (f)
-          && !WINDOW_RIGHTMOST_P (w) && !WINDOW_FULL_WIDTH_P (w))
-    /* The column of `|' characters separating side-by-side windows
-       occupies one column only.  */
-    width -= 1;
+  int pixels = (w->pixel_width
+               - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+               - (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
+                  ? WINDOW_SCROLL_BAR_AREA_WIDTH (w)
+                  : ((!FRAME_WINDOW_P (f)
+                      && !WINDOW_RIGHTMOST_P (w)
+                      && !WINDOW_RIGHT_DIVIDER_WIDTH (w)
+                      && !WINDOW_FULL_WIDTH_P (w))
+                     /* According to Eli this is either 1 or 0.  */
+                     ? 1 : 0))
+               - WINDOW_MARGINS_WIDTH (w)
+               - (FRAME_WINDOW_P (f)
+                  ? WINDOW_FRINGES_WIDTH (w)
+                  : 0));
+  int unit = FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+
+  return pixelwise ? pixels : ((pixels + unit - 1) / unit);
+}
+
+DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
+       doc: /* Return the height, in lines, of WINDOW's text area.
+WINDOW must be a live window and defaults to the selected one.
 
-  /* Display margins cannot be used for normal text.  */
-  width -= WINDOW_LEFT_MARGIN_COLS (w) + WINDOW_RIGHT_MARGIN_COLS (w);
+Optional argument PIXELWISE non-nil means return the height in pixels.
 
-  if (FRAME_WINDOW_P (f))
-    /* On window-systems, fringes cannot be used for normal text.  */
-    width -= WINDOW_FRINGE_COLS (w);
+The returned height does not include the mode line or header line.  On a
+graphical display, the height is expressed as an integer multiple of the
+default character height if PIXELWISE is nil.
 
-  return width;
+If PIXELWISE is nil and a line at the bottom of the text area is only
+partially visible, that counts as a whole line; to exclude
+partially-visible lines, use `window-text-height'.  */)
+  (Lisp_Object window, Lisp_Object pixelwise)
+{
+  return make_number (window_body_height (decode_live_window (window),
+                                         NILP (pixelwise) ? 0 : 1));
 }
 
-DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 1, 0,
-       doc: /* Return the height, in lines, of WINDOW's text area.
+DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
+       doc: /* Return the width, in columns, of WINDOW's text area.
 WINDOW must be a live window and defaults to the selected one.
 
-The returned height does not include the mode line or header line.
-On a graphical display, the height is expressed as an integer multiple
-of the default character height.  If a line at the bottom of the text
-area is only partially visible, that counts as a whole line; to
-exclude partially-visible lines, use `window-text-height'.  */)
+Optional argument PIXELWISE non-nil means return the width in pixels.
+
+The return value does not include any vertical dividers, fringe or
+marginal areas, or scroll bars.  On a graphical display, the width is
+expressed as an integer multiple of the default character width if
+PIXELWISE is nil.
+
+If PIXELWISE is nil and a column at the right of the text area is only
+partially visible, that counts as a whole column; to exclude
+partially-visible columns, use `window-text-width'.  */)
+  (Lisp_Object window, Lisp_Object pixelwise)
+{
+  return make_number (window_body_width (decode_live_window (window),
+                                        NILP (pixelwise) ? 0 : 1));
+}
+
+DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
+       Swindow_mode_line_height, 0, 1, 0,
+       doc: /* Return the height in pixel of WINDOW's mode-line.
+WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
-  return make_number (window_body_lines (decode_live_window (window)));
+  return (make_number (WINDOW_MODE_LINE_HEIGHT (decode_live_window (window))));
 }
 
-DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 1, 0,
-       doc: /* Return the width, in columns, of WINDOW's text area.
-WINDOW must be a live window and defaults to the selected one.
+DEFUN ("window-header-line-height", Fwindow_header_line_height,
+       Swindow_header_line_height, 0, 1, 0,
+       doc: /* Return the height in pixel of WINDOW's header-line.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return (make_number (WINDOW_HEADER_LINE_HEIGHT (decode_live_window (window))));
+}
 
-The return value does not include any vertical dividers, fringe or
-marginal areas, or scroll bars.  On a graphical display, the width is
-expressed as an integer multiple of the default character width.  */)
+DEFUN ("window-right-divider-width", Fwindow_right_divider_width,
+       Swindow_right_divider_width, 0, 1, 0,
+       doc: /* Return the width of WINDOW's right divider.
+WINDOW must be a live window and defaults to the selected one.  */)
   (Lisp_Object window)
 {
-  return make_number (window_body_cols (decode_live_window (window)));
+  return (make_number (WINDOW_RIGHT_DIVIDER_WIDTH (decode_live_window (window))));
+}
+
+DEFUN ("window-bottom-divider-width", Fwindow_bottom_divider_width,
+       Swindow_bottom_divider_width, 0, 1, 0,
+       doc: /* Return the width of WINDOW's bottom divider.
+WINDOW must be a live window and defaults to the selected one.  */)
+  (Lisp_Object window)
+{
+  return (make_number (WINDOW_BOTTOM_DIVIDER_WIDTH (decode_live_window (window))));
 }
 
 DEFUN ("window-hscroll", Fwindow_hscroll, Swindow_hscroll, 0, 1, 0,
@@ -1078,11 +1175,15 @@ display margins, fringes, header line, and/or mode line.  */)
 
 /* Test if the character at column X, row Y is within window W.
    If it is not, return ON_NOTHING;
+   if it is on the window's vertical divider, return
+      ON_RIGHT_DIVIDER;
+   if it is on the window's horizontal divider, return
+      ON_BOTTOM_DIVIDER;
    if it is in the window's text area, return ON_TEXT;
    if it is on the window's modeline, return ON_MODE_LINE;
    if it is on the border between the window and its right sibling,
-      return ON_VERTICAL_BORDER.
-   if it is on a scroll bar, return ON_SCROLL_BAR.
+      return ON_VERTICAL_BORDER;
+   if it is on a scroll bar, return ON_SCROLL_BAR;
    if it is on the window's top line, return ON_HEADER_LINE;
    if it is in left or right fringe of the window,
       return ON_LEFT_FRINGE or ON_RIGHT_FRINGE;
@@ -1110,13 +1211,28 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (y < top_y || y >= bottom_y || x < left_x || x >= right_x)
     return ON_NOTHING;
 
-  /* On the mode line or header line?   */
-  if ((WINDOW_WANTS_MODELINE_P (w)
-       && y >= bottom_y - CURRENT_MODE_LINE_HEIGHT (w)
-       && (part = ON_MODE_LINE))
-      || (WINDOW_WANTS_HEADER_LINE_P (w)
-         && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
-         && (part = ON_HEADER_LINE)))
+  /* On vertical window divider (which prevails horizontal
+     dividers) ?  */
+  if (!WINDOW_RIGHTMOST_P (w)
+      && WINDOW_RIGHT_DIVIDER_WIDTH (w)
+      && x >= right_x - WINDOW_RIGHT_DIVIDER_WIDTH (w)
+      && x <= right_x)
+    return ON_RIGHT_DIVIDER;
+  /* On the horizontal window divider?  */
+  else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
+          && y >= (bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+          && y <= bottom_y)
+    return ON_BOTTOM_DIVIDER;
+  /* On the mode or header line?   */
+  else if ((WINDOW_WANTS_MODELINE_P (w)
+           && y >= (bottom_y
+                    - CURRENT_MODE_LINE_HEIGHT (w)
+                    - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+           && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
+           && (part = ON_MODE_LINE))
+          || (WINDOW_WANTS_HEADER_LINE_P (w)
+              && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
+              && (part = ON_HEADER_LINE)))
     {
       /* If it's under/over the scroll bar portion of the mode/header
         line, say it's on the vertical line.  That's to be able to
@@ -1139,7 +1255,7 @@ coordinates_in_window (register struct window *w, int x, int y)
   if (w->pseudo_window_p)
     {
       left_x = 0;
-      right_x = WINDOW_TOTAL_WIDTH (w) - 1;
+      right_x = WINDOW_PIXEL_WIDTH (w) - 1;
     }
   else
     {
@@ -1169,6 +1285,8 @@ coordinates_in_window (register struct window *w, int x, int y)
      terminals, the vertical line's x coordinate is right_x.  */
   else if (!w->pseudo_window_p
           && !WINDOW_RIGHTMOST_P (w)
+          /* Why check ux if we are not the rightmost window ?  Also
+             shouldn't a pseudo window always be rightmost ?  */
           && x > right_x - ux)
     return ON_VERTICAL_BORDER;
 
@@ -1224,7 +1342,7 @@ window_relative_x_coord (struct window *w, enum window_part part, int x)
     case ON_RIGHT_MARGIN:
       return (x + 1
              - ((w->pseudo_window_p)
-                ? WINDOW_TOTAL_WIDTH (w)
+                ? WINDOW_PIXEL_WIDTH (w)
                 : WINDOW_BOX_RIGHT_EDGE_X (w))
              + window_box_width (w, RIGHT_MARGIN_AREA)
              + ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
@@ -1309,6 +1427,12 @@ If they are in the windows's left or right marginal areas, `left-margin'\n\
       /* Historically we are supposed to return nil in this case.  */
       return Qnil;
 
+    case ON_RIGHT_DIVIDER:
+      return Qright_divider;
+
+    case ON_BOTTOM_DIVIDER:
+      return Qbottom_divider;
+
     default:
       emacs_abort ();
     }
@@ -2002,6 +2126,10 @@ replace_window (Lisp_Object old, Lisp_Object new, int setflag)
 
   if (setflag)
     {
+      n->pixel_left = o->pixel_left;
+      n->pixel_top = o->pixel_top;
+      n->pixel_width = o->pixel_width;
+      n->pixel_height = o->pixel_height;
       n->left_col = o->left_col;
       n->top_line = o->top_line;
       n->total_cols = o->total_cols;
@@ -2082,13 +2210,13 @@ recombine_windows (Lisp_Object window)
              wset_parent (c, parent);
 
              if (horflag)
-               wset_normal_cols (c,
-                                 make_float ((double) c->total_cols
-                                             / (double) p->total_cols));
+               wset_normal_cols
+                 (c, make_float ((double) c->pixel_width
+                                 / (double) p->pixel_width));
              else
-               wset_normal_lines (c,
-                                  make_float ((double) c->total_lines
-                                              / (double) p->total_lines));
+               wset_normal_lines
+                 (c, make_float ((double) c->pixel_height
+                                 / (double) p->pixel_height));
 
              if (NILP (c->next))
                {
@@ -2719,9 +2847,16 @@ selected frame and no others.  */)
 }
 
 static Lisp_Object
-resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore)
+resize_root_window (Lisp_Object window, Lisp_Object delta, Lisp_Object horizontal, Lisp_Object ignore, Lisp_Object pixelwise)
+{
+  return call5 (Qwindow_resize_root_window, window, delta, horizontal, ignore, pixelwise);
+}
+
+
+static Lisp_Object
+window_pixel_to_total (Lisp_Object frame, Lisp_Object horizontal)
 {
-  return call4 (Qwindow_resize_root_window, window, delta, horizontal, ignore);
+  return call2(Qwindow_pixel_to_total, frame, horizontal);
 }
 
 
@@ -2785,8 +2920,8 @@ window-start value is reasonable when this function is called.  */)
     {
       startpos = marker_position (w->start);
       startbyte = marker_byte_position (w->start);
-      top = WINDOW_TOP_EDGE_LINE (w)
-       - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w)));
+      top = (WINDOW_TOP_EDGE_LINE (w)
+            - FRAME_TOP_MARGIN (XFRAME (WINDOW_FRAME (w))));
       /* Make sure WINDOW is the frame's selected window.  */
       if (!EQ (window, FRAME_SELECTED_WINDOW (f)))
        {
@@ -2852,16 +2987,23 @@ window-start value is reasonable when this function is called.  */)
   if (!WINDOW_LEAF_P (w))
     {
       /* Resize child windows vertically.  */
-      XSETINT (delta, r->total_lines - w->total_lines);
+      XSETINT (delta, r->pixel_height - w->pixel_height);
+      w->pixel_top = r->pixel_top;
       w->top_line = r->top_line;
-      resize_root_window (window, delta, Qnil, Qnil);
+      resize_root_window (window, delta, Qnil, Qnil, Qt);
       if (window_resize_check (w, 0))
-       window_resize_apply (w, 0);
+       {
+         window_resize_apply (w, 0);
+         window_pixel_to_total (w->frame, Qnil);
+       }
       else
        {
-         resize_root_window (window, delta, Qnil, Qt);
+         resize_root_window (window, delta, Qnil, Qt, Qt);
          if (window_resize_check (w, 0))
-           window_resize_apply (w, 0);
+           {
+             window_resize_apply (w, 0);
+             window_pixel_to_total (w->frame, Qnil);
+           }
          else
            resize_failed = 1;
        }
@@ -2870,15 +3012,22 @@ window-start value is reasonable when this function is called.  */)
       if (!resize_failed)
        {
          w->left_col = r->left_col;
-         XSETINT (delta, r->total_cols - w->total_cols);
-         resize_root_window (window, delta, Qt, Qnil);
+         w->pixel_left = r->pixel_left;
+         XSETINT (delta, r->pixel_width - w->pixel_width);
+         resize_root_window (window, delta, Qt, Qnil, Qt);
          if (window_resize_check (w, 1))
-           window_resize_apply (w, 1);
+           {
+             window_resize_apply (w, 1);
+             window_pixel_to_total (w->frame, Qt);
+           }
          else
            {
-             resize_root_window (window, delta, Qt, Qt);
+             resize_root_window (window, delta, Qt, Qt, Qt);
              if (window_resize_check (w, 1))
-               window_resize_apply (w, 1);
+               {
+                 window_resize_apply (w, 1);
+                 window_pixel_to_total (w->frame, Qt);
+               }
              else
                resize_failed = 1;
            }
@@ -2987,27 +3136,46 @@ replace_buffer_in_windows_safely (Lisp_Object buffer)
     }
 }
 
-/* If *ROWS or *COLS are too small a size for FRAME, set them to the
-   minimum allowable size.  */
+/* If *HEIGHT or *WIDTH are too small a size for FRAME, set them to the
+   minimum allowable size.  PIXELWISE means interpret these as pixel
+   sizes.  */
 
 void
-check_frame_size (struct frame *frame, int *rows, int *cols)
+check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise)
 {
   /* For height, we have to see:
      how many windows the frame has at minimum (one or two),
      and whether it has a menu bar or other special stuff at the top.  */
-  int min_height
-    = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
-       ? MIN_SAFE_WINDOW_HEIGHT
-       : 2 * MIN_SAFE_WINDOW_HEIGHT);
+  if (pixelwise)
+    {
+      int min_height = MIN_SAFE_WINDOW_HEIGHT * FRAME_LINE_HEIGHT (frame);
+      int min_width = MIN_SAFE_WINDOW_WIDTH * FRAME_COLUMN_WIDTH (frame);
 
-  if (FRAME_TOP_MARGIN (frame) > 0)
-    min_height += FRAME_TOP_MARGIN (frame);
+      if (!FRAME_MINIBUF_ONLY_P (frame) && FRAME_HAS_MINIBUF_P (frame))
+       min_height = 2 * min_height;
 
-  if (*rows < min_height)
-    *rows = min_height;
-  if (*cols  < MIN_SAFE_WINDOW_WIDTH)
-    *cols = MIN_SAFE_WINDOW_WIDTH;
+      min_height += FRAME_TOP_MARGIN_HEIGHT (frame);
+
+      if (*height < min_height)
+       *height = min_height;
+      if (*width < min_width)
+       *width = min_width;
+    }
+  else
+    {
+      int min_height
+       = ((FRAME_MINIBUF_ONLY_P (frame) || ! FRAME_HAS_MINIBUF_P (frame))
+          ? MIN_SAFE_WINDOW_HEIGHT
+          : 2 * MIN_SAFE_WINDOW_HEIGHT);
+
+      if (FRAME_TOP_MARGIN (frame) > 0)
+       min_height += FRAME_TOP_MARGIN (frame);
+
+      if (*height < min_height)
+       *height = min_height;
+      if (*width  < MIN_SAFE_WINDOW_WIDTH)
+       *width = MIN_SAFE_WINDOW_WIDTH;
+    }
 }
 
 /* Adjust the margins of window W if text area is too small.
@@ -3017,31 +3185,37 @@ check_frame_size (struct frame *frame, int *rows, int *cols)
 static int
 adjust_window_margins (struct window *w)
 {
-  int box_cols = (WINDOW_TOTAL_COLS (w)
-                 - WINDOW_FRINGE_COLS (w)
-                 - WINDOW_SCROLL_BAR_COLS (w));
-  int margin_cols = (WINDOW_LEFT_MARGIN_COLS (w)
-                    + WINDOW_RIGHT_MARGIN_COLS (w));
+  int box_width = (WINDOW_PIXEL_WIDTH (w)
+                  - WINDOW_FRINGES_WIDTH (w)
+                  - WINDOW_SCROLL_BAR_AREA_WIDTH (w));
+  int margin_width = WINDOW_MARGINS_WIDTH (w);
 
-  if (box_cols - margin_cols >= MIN_SAFE_WINDOW_WIDTH)
+  if (box_width - margin_width >= MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
     return 1;
 
-  if (margin_cols < 0 || box_cols < MIN_SAFE_WINDOW_WIDTH)
+  if (margin_width < 0 || box_width < MIN_SAFE_WINDOW_PIXEL_WIDTH (w))
     return 0;
-
-  /* Window's text area is too narrow, but reducing the window
-     margins will fix that.  */
-  margin_cols = box_cols - MIN_SAFE_WINDOW_WIDTH;
-  if (WINDOW_RIGHT_MARGIN_COLS (w) > 0)
+  else
+    /* Window's text area is too narrow, but reducing the window
+       margins will fix that.  */
     {
-      if (WINDOW_LEFT_MARGIN_COLS (w) > 0)
-       w->left_margin_cols = w->right_margin_cols = margin_cols / 2;
+      int unit = WINDOW_FRAME_COLUMN_WIDTH (w);
+
+      margin_width = box_width - MIN_SAFE_WINDOW_PIXEL_WIDTH (w);
+
+      if (WINDOW_RIGHT_MARGIN_WIDTH (w) > 0)
+       {
+         if (WINDOW_LEFT_MARGIN_WIDTH (w) > 0)
+           w->left_margin_cols = w->right_margin_cols =
+             margin_width / (2 * unit);
+         else
+           w->right_margin_cols = margin_width / unit;
+       }
       else
-       w->right_margin_cols = margin_cols;
+       w->left_margin_cols = margin_width / unit;
+
+      return 1;
     }
-  else
-    w->left_margin_cols = margin_cols;
-  return 1;
 }
 \f
 /* The following three routines are needed for running a window's
@@ -3126,11 +3300,23 @@ If FRAME is omitted or nil, it defaults to the selected frame.  */)
   return Qnil;
 }
 
-/* Make WINDOW display BUFFER as its contents.  RUN_HOOKS_P non-zero
-   means it's allowed to run hooks.  See make_frame for a case where
-   it's not allowed.  KEEP_MARGINS_P non-zero means that the current
-   margins, fringes, and scroll-bar settings of the window are not
-   reset from the buffer's local settings.  */
+DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
+       Srun_window_scroll_functions, 0, 1, 0,
+       doc: /* Run `window-scroll-functions' for WINDOW.
+If WINDOW is omitted or nil, it defaults to the selected window.  */)
+  (Lisp_Object window)
+{
+  if (! NILP (Vwindow_scroll_functions))
+    run_hook_with_args_2 (Qwindow_scroll_functions, window,
+                         Fmarker_position (decode_live_window (window)->start));
+  return Qnil;
+}
+
+/* Make WINDOW display BUFFER.  RUN_HOOKS_P non-zero means it's allowed
+   to run hooks.  See make_frame for a case where it's not allowed.
+   KEEP_MARGINS_P non-zero means that the current margins, fringes, and
+   scroll-bar settings of the window are not reset from the buffer's
+   local settings.  */
 
 void
 set_window_buffer (Lisp_Object window, Lisp_Object buffer,
@@ -3139,7 +3325,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
   struct window *w = XWINDOW (window);
   struct buffer *b = XBUFFER (buffer);
   ptrdiff_t count = SPECPDL_INDEX ();
-  int samebuf = EQ (buffer, w->contents);
+  bool samebuf = EQ (buffer, w->contents);
 
   wset_buffer (w, buffer);
 
@@ -3209,14 +3395,15 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
       if (! NILP (Vwindow_scroll_functions))
        run_hook_with_args_2 (Qwindow_scroll_functions, window,
                              Fmarker_position (w->start));
-      run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
+      if (!samebuf)
+       run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w)));
     }
 
   unbind_to (count, Qnil);
 }
 
 DEFUN ("set-window-buffer", Fset_window_buffer, Sset_window_buffer, 2, 3, 0,
-       doc: /* Make WINDOW display BUFFER-OR-NAME as its contents.
+       doc: /* Make WINDOW display BUFFER-OR-NAME.
 WINDOW must be a live window and defaults to the selected one.
 BUFFER-OR-NAME must be a buffer or the name of an existing buffer.
 
@@ -3388,6 +3575,8 @@ make_parent_window (Lisp_Object window, bool horflag)
   adjust_window_count (p, 1);
   XSETWINDOW (parent, p);
 
+  p->sequence_number = ++sequence_number;
+
   replace_window (window, parent, 1);
 
   wset_next (o, Qnil);
@@ -3416,6 +3605,7 @@ make_window (void)
   wset_normal_cols (w, make_float (1.0));
   wset_new_total (w, make_number (0));
   wset_new_normal (w, make_number (0));
+  wset_new_pixel (w, make_number (0));
   wset_start (w, Fmake_marker ());
   wset_pointm (w, Fmake_marker ());
   wset_vertical_scroll_bar_type (w, Qt);
@@ -3433,6 +3623,7 @@ make_window (void)
   w->phys_cursor_type = NO_CURSOR;
   w->phys_cursor_width = -1;
 #endif
+  w->sequence_number = ++sequence_number;
   w->scroll_bar_width = -1;
   w->column_number_displayed = -1;
 
@@ -3443,6 +3634,28 @@ make_window (void)
   return window;
 }
 \f
+DEFUN ("set-window-new-pixel", Fset_window_new_pixel, Sset_window_new_pixel, 2, 3, 0,
+       doc: /* Set new pixel size of WINDOW to SIZE.
+WINDOW must be a valid window and defaults to the selected one.
+Return SIZE.
+
+Optional argument ADD non-nil means add SIZE to the new pixel size of
+WINDOW and return the sum.
+
+Note: This function does not operate on any child windows of WINDOW.  */)
+  (Lisp_Object window, Lisp_Object size, Lisp_Object add)
+{
+  struct window *w = decode_valid_window (window);
+
+  CHECK_NUMBER (size);
+  if (NILP (add))
+    wset_new_pixel (w, size);
+  else
+    wset_new_pixel (w, make_number (XINT (w->new_pixel) + XINT (size)));
+
+  return w->new_pixel;
+}
+
 DEFUN ("set-window-new-total", Fset_window_new_total, Sset_window_new_total, 2, 3, 0,
        doc: /* Set new total size of WINDOW to SIZE.
 WINDOW must be a valid window and defaults to the selected one.
@@ -3477,8 +3690,8 @@ Note: This function does not operate on any child windows of WINDOW.  */)
   return size;
 }
 
-/* Return 1 if setting w->total_lines (w->total_cols if HORFLAG is
-   non-zero) to w->new_total would result in correct heights (widths)
+/* Return 1 if setting w->pixel_height (w->pixel_width if HORFLAG is
+   non-zero) to w->new_pixel would result in correct heights (widths)
    for window W and recursively all child windows of W.
 
    Note: This function does not check any of `window-fixed-size-p',
@@ -3487,6 +3700,7 @@ Note: This function does not operate on any child windows of WINDOW.  */)
 static int
 window_resize_check (struct window *w, bool horflag)
 {
+  struct frame *f = XFRAME (w->frame);
   struct window *c;
 
   if (WINDOW_VERTICAL_COMBINATION_P (w))
@@ -3498,26 +3712,31 @@ window_resize_check (struct window *w, bool horflag)
        {
          while (c)
            {
-             if ((XINT (c->new_total) != XINT (w->new_total))
+             if (XINT (c->new_pixel) != XINT (w->new_pixel)
                  || !window_resize_check (c, horflag))
                return 0;
+
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
+
          return 1;
        }
       else
        /* The sum of the heights of the child windows of W must equal
           W's height.  */
        {
-         int sum_of_sizes = 0;
+         int sum_of_pixels = 0;
+
          while (c)
            {
              if (!window_resize_check (c, horflag))
                return 0;
-             sum_of_sizes = sum_of_sizes + XINT (c->new_total);
+
+             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
-         return (sum_of_sizes == XINT (w->new_total));
+
+         return (sum_of_pixels == XINT (w->new_pixel));
        }
     }
   else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
@@ -3528,26 +3747,31 @@ window_resize_check (struct window *w, bool horflag)
        /* The sum of the widths of the child windows of W must equal W's
           width.  */
        {
-         int sum_of_sizes = 0;
+         int sum_of_pixels = 0;
+
          while (c)
            {
              if (!window_resize_check (c, horflag))
                return 0;
-             sum_of_sizes = sum_of_sizes + XINT (c->new_total);
+
+             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
-         return (sum_of_sizes == XINT (w->new_total));
+
+         return (sum_of_pixels == XINT (w->new_pixel));
        }
       else
        /* All child windows of W must have the same height as W.  */
        {
          while (c)
            {
-             if ((XINT (c->new_total) != XINT (w->new_total))
+             if (XINT (c->new_pixel) != XINT (w->new_pixel)
                  || !window_resize_check (c, horflag))
                return 0;
+
              c = NILP (c->next) ? 0 : XWINDOW (c->next);
            }
+
          return 1;
        }
     }
@@ -3555,12 +3779,111 @@ window_resize_check (struct window *w, bool horflag)
     /* A leaf window.  Make sure it's not too small.  The following
        hardcodes the values of `window-safe-min-width' (2) and
        `window-safe-min-height' (1) which are defined in window.el.  */
-    return XINT (w->new_total) >= (horflag ? 2 : 1);
+    return (XINT (w->new_pixel) >= (horflag
+                                   ? (2 * FRAME_COLUMN_WIDTH (f))
+                                   : FRAME_LINE_HEIGHT (f)));
 }
 
-/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
-   w->new_total for window W and recursively all child windows of W.
-   Also calculate and assign the new vertical (horizontal) start
+static int
+window_resize_total_check (struct window *w, int horflag)
+{
+  struct frame *f = XFRAME (w->frame);
+  struct window *c;
+
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
+    /* W is a vertical combination.  */
+    {
+      c = XWINDOW (w->contents);
+      if (horflag)
+       /* All child windows of W must have the same width as W.  */
+       {
+         while (c)
+           {
+             if (XINT (c->new_pixel) != XINT (w->new_pixel)
+/**              || XINT (c->new_total != XINT (w->new_total)) **/
+                 || !window_resize_check (c, horflag))
+               return 0;
+
+             c = NILP (c->next) ? 0 : XWINDOW (c->next);
+           }
+
+         return 1;
+       }
+      else
+       /* The sum of the heights of the child windows of W must equal
+          W's height.  */
+       {
+         int sum_of_pixels = 0, sum_of_totals = 0;
+
+         while (c)
+           {
+             if (!window_resize_check (c, horflag))
+               return 0;
+
+             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
+/**          sum_of_totals = sum_of_totals + XINT (c->new_total); **/
+             c = NILP (c->next) ? 0 : XWINDOW (c->next);
+           }
+
+         return (sum_of_pixels == XINT (w->new_pixel)
+/**              && sum_of_totals == XINT (w->new_total) **/
+                 );
+       }
+    }
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
+    /* W is a horizontal combination.  */
+    {
+      c = XWINDOW (w->contents);
+      if (horflag)
+       /* The sum of the widths of the child windows of W must equal W's
+          width.  */
+       {
+         int sum_of_pixels = 0, sum_of_totals = 0;
+
+         while (c)
+           {
+             if (!window_resize_check (c, horflag))
+               return 0;
+
+             sum_of_pixels = sum_of_pixels + XINT (c->new_pixel);
+             sum_of_totals = sum_of_totals + XINT (c->new_total);
+             c = NILP (c->next) ? 0 : XWINDOW (c->next);
+           }
+
+         return (sum_of_pixels == XINT (w->new_pixel)
+/**              && sum_of_totals == XINT (w->new_total) **/
+                 );
+       }
+      else
+       /* All child windows of W must have the same height as W.  */
+       {
+         while (c)
+           {
+             if (XINT (c->new_pixel) != XINT (w->new_pixel)
+/**              || XINT (c->new_total) != XINT (w->new_total) **/
+                 || !window_resize_check (c, horflag))
+               return 0;
+
+             c = NILP (c->next) ? 0 : XWINDOW (c->next);
+           }
+
+         return 1;
+       }
+    }
+  else
+    /* A leaf window.  Make sure it's not too small.  The following
+       hardcodes the values of `window-safe-min-width' (2) and
+       `window-safe-min-height' (1) which are defined in window.el.  */
+    return (XINT (w->new_pixel) >= (horflag
+                                   ? (2 * FRAME_COLUMN_WIDTH (f))
+                                   : FRAME_LINE_HEIGHT (f))
+/**        && XINT (w->new_total) >= (horflag ? 2 : 1) **/
+           );
+}
+
+/* Set w->pixel_height (w->pixel_height if HORIZONTAL is non-zero) to
+   w->new_pixel for window W and recursively all child windows of W.
+   Also calculate and assign the new vertical (horizontal) pixel start
    positions of each of these windows.
 
    This function does not perform any error checks.  Make sure you have
@@ -3569,25 +3892,30 @@ static void
 window_resize_apply (struct window *w, bool horflag)
 {
   struct window *c;
-  int pos;
+  int edge;
+  int unit = (horflag
+             ? FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w))
+             : FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
 
   /* Note: Assigning new_normal requires that the new total size of the
      parent window has been set *before*.  */
   if (horflag)
     {
-      w->total_cols = XFASTINT (w->new_total);
+      w->pixel_width = XFASTINT (w->new_pixel);
+      w->total_cols = w->pixel_width / unit;
       if (NUMBERP (w->new_normal))
        wset_normal_cols (w, w->new_normal);
 
-      pos = w->left_col;
+      edge = w->pixel_left;
     }
   else
     {
-      w->total_lines = XFASTINT (w->new_total);
+      w->pixel_height = XFASTINT (w->new_pixel);
+      w->total_lines = w->pixel_height / unit;
       if (NUMBERP (w->new_normal))
        wset_normal_lines (w, w->new_normal);
 
-      pos = w->top_line;
+      edge = w->pixel_top;
     }
 
   if (WINDOW_VERTICAL_COMBINATION_P (w))
@@ -3597,12 +3925,19 @@ window_resize_apply (struct window *w, bool horflag)
       while (c)
        {
          if (horflag)
-           c->left_col = pos;
+           {
+             c->pixel_left = edge;
+             c->left_col = edge / unit;
+           }
          else
-           c->top_line = pos;
+           {
+             c->pixel_top = edge;
+             c->top_line = edge / unit;
+           }
          window_resize_apply (c, horflag);
          if (!horflag)
-           pos = pos + c->total_lines;
+           edge = edge + c->pixel_height;
+
          c = NILP (c->next) ? 0 : XWINDOW (c->next);
        }
     }
@@ -3613,12 +3948,20 @@ window_resize_apply (struct window *w, bool horflag)
       while (c)
        {
          if (horflag)
-           c->left_col = pos;
+           {
+             c->pixel_left = edge;
+             c->left_col = edge / unit;
+           }
          else
-           c->top_line = pos;
+           {
+             c->pixel_top = edge;
+             c->top_line = edge / unit;
+           }
+
          window_resize_apply (c, horflag);
          if (horflag)
-           pos = pos + c->total_cols;
+           edge = edge + c->pixel_width;
+
          c = NILP (c->next) ? 0 : XWINDOW (c->next);
        }
     }
@@ -3628,6 +3971,67 @@ window_resize_apply (struct window *w, bool horflag)
 }
 
 
+/* Set w->total_lines (w->total_cols if HORIZONTAL is non-zero) to
+   w->new_total for window W and recursively all child windows of W.
+   Also calculate and assign the new vertical (horizontal) start
+   positions of each of these windows.  */
+static void
+window_resize_apply_total (struct window *w, bool horflag)
+{
+  struct window *c;
+  int edge;
+
+  /* Note: Assigning new_normal requires that the new total size of the
+     parent window has been set *before*.  */
+  if (horflag)
+    {
+      w->total_cols = XFASTINT (w->new_total);
+      edge = w->left_col;
+    }
+  else
+    {
+      w->total_lines = XFASTINT (w->new_total);
+      edge = w->top_line;
+    }
+
+  if (WINDOW_VERTICAL_COMBINATION_P (w))
+    /* W is a vertical combination.  */
+    {
+      c = XWINDOW (w->contents);
+      while (c)
+       {
+         if (horflag)
+           c->left_col = edge;
+         else
+           c->top_line = edge;
+
+         window_resize_apply_total (c, horflag);
+         if (!horflag)
+           edge = edge + c->total_lines;
+
+         c = NILP (c->next) ? 0 : XWINDOW (c->next);
+       }
+    }
+  else if (WINDOW_HORIZONTAL_COMBINATION_P (w))
+    /* W is a horizontal combination.  */
+    {
+      c = XWINDOW (w->contents);
+      while (c)
+       {
+         if (horflag)
+           c->left_col = edge;
+         else
+           c->top_line = edge;
+
+         window_resize_apply_total (c, horflag);
+         if (horflag)
+           edge = edge + c->total_cols;
+
+         c = NILP (c->next) ? 0 : XWINDOW (c->next);
+       }
+    }
+}
+
 DEFUN ("window-resize-apply", Fwindow_resize_apply, Swindow_resize_apply, 0, 2, 0,
        doc: /* Apply requested size values for window-tree of FRAME.
 If FRAME is omitted or nil, it defaults to the selected frame.
@@ -3649,8 +4053,8 @@ be applied on the Elisp level.  */)
   bool horflag = !NILP (horizontal);
 
   if (!window_resize_check (r, horflag)
-      || (XINT (r->new_total)
-         != (horflag ? r->total_cols : r->total_lines)))
+      || (XINT (r->new_pixel)
+         != (horflag ? r->pixel_width : r->pixel_height)))
     return Qnil;
 
   block_input ();
@@ -3662,7 +4066,31 @@ be applied on the Elisp level.  */)
   adjust_frame_glyphs (f);
   unblock_input ();
 
-  run_window_configuration_change_hook (f);
+  return Qt;
+}
+
+
+DEFUN ("window-resize-apply-total", Fwindow_resize_apply_total, Swindow_resize_apply_total, 0, 2, 0,
+       doc: /* Apply requested total size values for window-tree of FRAME.
+If FRAME is omitted or nil, it defaults to the selected frame.
+
+This function does not assign pixel or normal size values.  You should
+have run `window-resize-apply' before running this.
+
+Optional argument HORIZONTAL omitted or nil means apply requested
+height values.  HORIZONTAL non-nil means apply requested width
+values.  */)
+     (Lisp_Object frame, Lisp_Object horizontal)
+{
+  struct frame *f = decode_live_frame (frame);
+  struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
+
+  block_input ();
+  /* Necessary when deleting the top-/or leftmost window.  */
+  r->left_col = 0;
+  r->top_line = FRAME_TOP_MARGIN (f);
+  window_resize_apply_total (r, !NILP (horizontal));
+  unblock_input ();
 
   return Qt;
 }
@@ -3670,59 +4098,107 @@ be applied on the Elisp level.  */)
 
 /* Resize frame F's windows when number of lines of F is set to SIZE.
    HORFLAG 1 means resize windows when number of columns of F is set to
-   SIZE.
+   SIZE.  PIXELWISE 1 means to interpret SIZE as pixels.
 
    This function can delete all windows but the selected one in order to
    satisfy the request.  The result will be meaningful if and only if
    F's windows have meaningful sizes when you call this.  */
 void
-resize_frame_windows (struct frame *f, int size, bool horflag)
+resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
 {
   Lisp_Object root = f->root_window;
   struct window *r = XWINDOW (root);
   Lisp_Object mini = f->minibuffer_window;
   struct window *m;
+  /* old_size is the old size of the frame's root window.  */
+  int old_size = horflag ? r->total_cols : r->total_lines;
+  int old_pixel_size = horflag ? r->pixel_width : r->pixel_height;
   /* new_size is the new size of the frame's root window.  */
-  int new_size = (horflag
-                 ? size
-                 : (size
-                    - FRAME_TOP_MARGIN (f)
-                    - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
-                       ? 1 : 0)));
+  int new_size, new_pixel_size;
+
+  if (pixelwise)
+    {
+      new_pixel_size
+       = (horflag
+          ? size
+          : (size
+             - FRAME_TOP_MARGIN_HEIGHT (f)
+             - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
+                ? FRAME_LINE_HEIGHT (f) : 0)));
+      new_size = new_pixel_size / (horflag
+                                  ? FRAME_COLUMN_WIDTH (f)
+                                  : FRAME_LINE_HEIGHT (f));
+    }
+  else    
+    {
+      new_size= (horflag
+                ? size
+                : (size
+                   - FRAME_TOP_MARGIN (f)
+                   - ((FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
+                      ? 1 : 0)));
+      new_pixel_size = new_size * (horflag
+                                  ? FRAME_COLUMN_WIDTH (f)
+                                  : FRAME_LINE_HEIGHT (f));
+    }
 
   r->top_line = FRAME_TOP_MARGIN (f);
-  if (WINDOW_LEAF_P (r))
+  r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
+
+  if (new_pixel_size == old_pixel_size)
+    return;
+  else if (WINDOW_LEAF_P (r))
     /* For a leaf root window just set the size.  */
     if (horflag)
-      r->total_cols = new_size;
+      {
+       r->total_cols = new_size;
+       r->pixel_width = new_pixel_size;
+      }
     else
-      r->total_lines = new_size;
+      {
+       r->total_lines = new_size;
+       r->pixel_height = new_pixel_size;
+      }
   else
     {
-      /* old_size is the old size of the frame's root window.  */
-      int old_size = horflag ? r->total_cols : r->total_lines;
       Lisp_Object delta;
 
-      XSETINT (delta, new_size - old_size);
+      if (pixelwise)
+       XSETINT (delta, new_pixel_size - old_pixel_size);
+      else
+       XSETINT (delta, new_size - old_size);
+
       /* Try a "normal" resize first.  */
-      resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil);
+      resize_root_window (root, delta, horflag ? Qt : Qnil, Qnil,
+                         pixelwise ? Qt : Qnil);
       if (window_resize_check (r, horflag)
-         && new_size == XINT (r->new_total))
-       window_resize_apply (r, horflag);
+         && new_pixel_size == XINT (r->new_pixel))
+       {
+         window_resize_apply (r, horflag);
+         window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+       }
       else
        {
          /* Try with "reasonable" minimum sizes next.  */
-         resize_root_window (root, delta, horflag ? Qt : Qnil, Qt);
+         resize_root_window (root, delta, horflag ? Qt : Qnil, Qt,
+                             pixelwise ? Qt : Qnil);
          if (window_resize_check (r, horflag)
-             && new_size == XINT (r->new_total))
-           window_resize_apply (r, horflag);
+             && new_pixel_size == XINT (r->new_pixel))
+           {
+             window_resize_apply (r, horflag);
+             window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+           }
          else
            {
              /* Finally, try with "safe" minimum sizes.  */
-             resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe);
+             resize_root_window (root, delta, horflag ? Qt : Qnil, Qsafe,
+                                 pixelwise ? Qt : Qnil);
              if (window_resize_check (r, horflag)
-                 && new_size == XINT (r->new_total))
-               window_resize_apply (r, horflag);
+                 && new_pixel_size == XINT (r->new_pixel))
+               {
+                 window_resize_apply (r, horflag);
+                 window_pixel_to_total (r->frame, horflag ? Qt : Qnil);
+               }
              else
                {
                  /* We lost.  Delete all windows but the frame's
@@ -3730,9 +4206,15 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
                  root = f->selected_window;
                  Fdelete_other_windows_internal (root, Qnil);
                  if (horflag)
-                   XWINDOW (root)->total_cols = new_size;
+                   {
+                     XWINDOW (root)->total_cols = new_size;
+                     XWINDOW (root)->pixel_width = new_pixel_size;
+                   }
                  else
-                   XWINDOW (root)->total_lines = new_size;
+                   {
+                     XWINDOW (root)->total_lines = new_size;
+                     XWINDOW (root)->pixel_height = new_pixel_size;
+                   }
                }
            }
        }
@@ -3742,12 +4224,17 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
     {
       m = XWINDOW (mini);
       if (horflag)
-       m->total_cols = size;
+       {
+         m->total_cols = size;
+         m->pixel_width = new_pixel_size;
+       }
       else
        {
          /* Are we sure we always want 1 line here?  */
          m->total_lines = 1;
+         m->pixel_height = FRAME_LINE_HEIGHT (f);
          m->top_line = r->top_line + r->total_lines;
+         m->pixel_top = r->pixel_top + r->pixel_height;
        }
     }
 
@@ -3757,27 +4244,27 @@ resize_frame_windows (struct frame *f, int size, bool horflag)
 
 DEFUN ("split-window-internal", Fsplit_window_internal, Ssplit_window_internal, 4, 4, 0,
        doc: /* Split window OLD.
-Second argument TOTAL-SIZE specifies the number of lines or columns of the
+Second argument PIXEL-SIZE specifies the number of pixels of the
 new window.  In any case TOTAL-SIZE must be a positive integer.
 
 Third argument SIDE nil (or `below') specifies that the new window shall
 be located below WINDOW.  SIDE `above' means the new window shall be
-located above WINDOW.  In both cases TOTAL-SIZE specifies the number of
-lines of the new window including space reserved for the mode and/or
+located above WINDOW.  In both cases PIXEL-SIZE specifies the pixel
+height of the new window including space reserved for the mode and/or
 header line.
 
 SIDE t (or `right') specifies that the new window shall be located on
 the right side of WINDOW.  SIDE `left' means the new window shall be
-located on the left of WINDOW.  In both cases TOTAL-SIZE specifies the
-number of columns of the new window including space reserved for fringes
-and the scrollbar or a divider column.
+located on the left of WINDOW.  In both cases PIXEL-SIZE specifies the
+width of the new window including space reserved for fringes and the
+scrollbar or a divider column.
 
 Fourth argument NORMAL-SIZE specifies the normal size of the new window
 according to the SIDE argument.
 
-The new total and normal sizes of all involved windows must have been
+The new pixel and normal sizes of all involved windows must have been
 set correctly.  See the code of `split-window' for how this is done.  */)
-  (Lisp_Object old, Lisp_Object total_size, Lisp_Object side, Lisp_Object normal_size)
+  (Lisp_Object old, Lisp_Object pixel_size, Lisp_Object side, Lisp_Object normal_size)
 {
   /* OLD (*o) is the window we have to split.  (*p) is either OLD's
      parent window or an internal window we have to install as OLD's new
@@ -3786,19 +4273,24 @@ set correctly.  See the code of `split-window' for how this is done.  */)
      NEW (*n) is the new window created with some parameters taken from
      REFERENCE (*r).  */
   register Lisp_Object new, frame, reference;
-  register struct window *o, *p, *n, *r;
+  register struct window *o, *p, *n, *r, *c;
   struct frame *f;
   bool horflag
     /* HORFLAG is 1 when we split side-by-side, 0 otherwise.  */
     = EQ (side, Qt) || EQ (side, Qleft) || EQ (side, Qright);
-  int combination_limit = 0;
+  int combination_limit = 0, sum = 0;
+  int total_size;
 
   CHECK_WINDOW (old);
   o = XWINDOW (old);
   frame = WINDOW_FRAME (o);
   f = XFRAME (frame);
 
-  CHECK_NUMBER (total_size);
+  CHECK_NUMBER (pixel_size);
+  total_size
+    = XINT (pixel_size) / (horflag
+                          ? FRAME_COLUMN_WIDTH (f)
+                          : FRAME_LINE_HEIGHT (f));
 
   /* Set combination_limit to 1 if we have to make a new parent window.
      We do that if either `window-combination-limit' is t, or OLD has no
@@ -3822,7 +4314,7 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   /* The following bugs are caught by `split-window'.  */
   if (MINI_WINDOW_P (o))
     error ("Attempt to split minibuffer window");
-  else if (XINT (total_size) < (horflag ? 2 : 1))
+  else if (total_size < (horflag ? 2 : 1))
     error ("Size of new window too small (after split)");
   else if (!combination_limit && !NILP (Vwindow_combination_resize))
     /* `window-combination-resize' non-nil means try to resize OLD's siblings
@@ -3830,22 +4322,21 @@ set correctly.  See the code of `split-window' for how this is done.  */)
     {
       p = XWINDOW (o->parent);
       /* Temporarily pretend we split the parent window.  */
-      wset_new_total
-       (p, make_number ((horflag ? p->total_cols : p->total_lines)
-                        - XINT (total_size)));
+      wset_new_pixel
+       (p, make_number ((horflag ? p->pixel_width : p->pixel_height)
+                        - XINT (pixel_size)));
       if (!window_resize_check (p, horflag))
        error ("Window sizes don't fit");
       else
        /* Undo the temporary pretension.  */
-       wset_new_total (p, make_number
-                       (horflag ? p->total_cols : p->total_lines));
+       wset_new_pixel (p, make_number (horflag ? p->pixel_width : p->pixel_height));
     }
   else
     {
       if (!window_resize_check (o, horflag))
        error ("Resizing old window failed");
-      else if (XINT (total_size) + XINT (o->new_total)
-              != (horflag ? o->total_cols : o->total_lines))
+      else if (XINT (pixel_size) + XINT (o->new_pixel)
+              != (horflag ? o->pixel_width : o->pixel_height))
        error ("Sum of sizes of old and new window don't fit");
     }
 
@@ -3865,8 +4356,10 @@ set correctly.  See the code of `split-window' for how this is done.  */)
           that its children get merged into another window.  */
        wset_combination_limit (p, Qt);
       /* These get applied below.  */
-      wset_new_total (p, make_number
-                     (horflag ? o->total_cols : o->total_lines));
+      wset_new_pixel
+       (p, make_number (horflag ? o->pixel_width : o->pixel_height));
+      wset_new_total
+       (p, make_number (horflag ? o->total_cols : o->total_lines));
       wset_new_normal (p, new_normal);
     }
   else
@@ -3913,18 +4406,33 @@ set correctly.  See the code of `split-window' for how this is done.  */)
   /* Directly assign orthogonal coordinates and sizes.  */
   if (horflag)
     {
+      n->pixel_top = o->pixel_top;
       n->top_line = o->top_line;
+      n->pixel_height = o->pixel_height;
       n->total_lines = o->total_lines;
     }
   else
     {
+      n->pixel_left = o->pixel_left;
       n->left_col = o->left_col;
+      n->pixel_width = o->pixel_width;
       n->total_cols = o->total_cols;
     }
 
   /* Iso-coordinates and sizes are assigned by window_resize_apply,
      get them ready here.  */
-  wset_new_total (n, total_size);
+  wset_new_pixel (n, pixel_size);
+  c = XWINDOW (p->contents);
+  while (c)
+    {
+      if (c != n)
+       sum = sum + XINT (c->new_total);
+      c = NILP (c->next) ? 0 : XWINDOW (c->next);
+    }
+  wset_new_total (n, make_number ((horflag
+                                  ? p->total_cols
+                                  : p->total_lines)
+                                 - sum));
   wset_new_normal (n, normal_size);
 
   block_input ();
@@ -4003,15 +4511,14 @@ Signal an error when WINDOW is the only window on its frame.  */)
     }
 
   if (window_resize_check (r, horflag)
-      && (XINT (r->new_total)
-         == (horflag ? r->total_cols : r->total_lines)))
+      && (XINT (r->new_pixel)
+         == (horflag ? r->pixel_width : r->pixel_height)))
     /* We can delete WINDOW now.  */
     {
 
       /* Block input.  */
       block_input ();
       window_resize_apply (p, horflag);
-
       /* If this window is referred to by the dpyinfo's mouse
         highlight, invalidate that slot to be safe (Bug#9904).  */
       if (!FRAME_INITIAL_P (f))
@@ -4122,55 +4629,74 @@ Signal an error when WINDOW is the only window on its frame.  */)
 /* Grow mini-window W by DELTA lines, DELTA >= 0, or as much as we
    can.  */
 void
-grow_mini_window (struct window *w, int delta)
+grow_mini_window (struct window *w, int delta, bool pixelwise)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *r;
-  Lisp_Object root, value;
+  Lisp_Object root, height;
+  int line_height, pixel_height;
 
   eassert (MINI_WINDOW_P (w));
   eassert (delta >= 0);
 
-  root = FRAME_ROOT_WINDOW (f);
-  r = XWINDOW (root);
-  value = call2 (Qwindow_resize_root_window_vertically,
-                root, make_number (- delta));
-  if (INTEGERP (value) && window_resize_check (r, 0))
+  if (delta > 0)
     {
-      block_input ();
-      window_resize_apply (r, 0);
+      root = FRAME_ROOT_WINDOW (f);
+      r = XWINDOW (root);
+      height = call3 (Qwindow_resize_root_window_vertically,
+                     root, make_number (- delta), pixelwise ? Qt : Qnil);
+      if (INTEGERP (height) && window_resize_check (r, 0))
+       {
+         block_input ();
+         window_resize_apply (r, 0);
 
-      /* Grow the mini-window.  */
-      w->top_line = r->top_line + r->total_lines;
-      w->total_lines -= XINT (value);
-      /* Enforce full redisplay of the frame.  */
-      /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
-      fset_redisplay (f);
-      adjust_frame_glyphs (f);
-      unblock_input ();
+         if (pixelwise)
+           {
+             pixel_height = -XINT (height);
+             line_height = pixel_height / FRAME_LINE_HEIGHT (f);
+           }
+         else
+           {
+             line_height = -XINT (height); 
+             pixel_height = line_height * FRAME_LINE_HEIGHT (f);
+           }
+
+         /* Grow the mini-window.  */
+         w->pixel_top = r->pixel_top + r->pixel_height;
+         w->top_line = r->top_line + r->total_lines;
+         w->pixel_height += pixel_height;
+         w->total_lines += line_height;
+
+         /* Enforce full redisplay of the frame.  */
+         /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
+         fset_redisplay (f);
+         adjust_frame_glyphs (f);
+         unblock_input ();
+       }
     }
 }
 
-
-/* Shrink mini-window W.  */
+/* Shrink mini-window W to one line.  */
 void
-shrink_mini_window (struct window *w)
+shrink_mini_window (struct window *w, bool pixelwise)
 {
   struct frame *f = XFRAME (w->frame);
   struct window *r;
-  Lisp_Object root, value;
-  EMACS_INT size;
+  Lisp_Object root, delta;
+  EMACS_INT height, unit;
 
   eassert (MINI_WINDOW_P (w));
 
-  size = w->total_lines;
-  if (size > 1)
+  height = pixelwise ? w->pixel_height : w->total_lines; 
+  unit = pixelwise ? FRAME_LINE_HEIGHT (f) : 1;
+  if (height > unit)
     {
       root = FRAME_ROOT_WINDOW (f);
       r = XWINDOW (root);
-      value = call2 (Qwindow_resize_root_window_vertically,
-                    root, make_number (size - 1));
-      if (INTEGERP (value) && window_resize_check (r, 0))
+      delta = call3 (Qwindow_resize_root_window_vertically,
+                    root, make_number (height - unit),
+                    pixelwise ? Qt : Qnil);
+      if (INTEGERP (delta) && window_resize_check (r, 0))
        {
          block_input ();
          window_resize_apply (r, 0);
@@ -4178,6 +4704,8 @@ shrink_mini_window (struct window *w)
          /* Shrink the mini-window.  */
          w->top_line = r->top_line + r->total_lines;
          w->total_lines = 1;
+         w->pixel_top = r->pixel_top + r->pixel_height;
+         w->pixel_height = FRAME_LINE_HEIGHT (f);
          /* Enforce full redisplay of the frame.  */
          /* FIXME: Shouldn't window--resize-root-window-vertically do it?  */
          fset_redisplay (f);
@@ -4209,26 +4737,27 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini
     error ("Cannot resize a minibuffer-only frame");
 
   r = XWINDOW (FRAME_ROOT_WINDOW (f));
-  height = r->total_lines + w->total_lines;
+  height = r->pixel_height + w->pixel_height;
   if (window_resize_check (r, 0)
-      && XINT (w->new_total) > 0
-      && height == XINT (r->new_total) + XINT (w->new_total))
+      && XINT (w->new_pixel) > 0
+      && height == XINT (r->new_pixel) + XINT (w->new_pixel))
     {
       block_input ();
       window_resize_apply (r, 0);
 
       w->total_lines = XFASTINT (w->new_total);
       w->top_line = r->top_line + r->total_lines;
+      w->pixel_height = XFASTINT (w->new_pixel);
+      w->pixel_top = r->pixel_top + r->pixel_height;
 
       windows_or_buffers_changed = 36;
       FRAME_WINDOW_SIZES_CHANGED (f) = 1;
       adjust_frame_glyphs (f);
       unblock_input ();
-
-      run_window_configuration_change_hook (f);
       return Qt;
     }
-  else error ("Failed to resize minibuffer window");
+  else
+    error ("Failed to resize minibuffer window");
 }
 \f
 /* Mark window cursors off for all windows in the window tree rooted
@@ -4990,7 +5519,7 @@ by this function.  This happens in an interactive call.  */)
 {
   struct window *w = XWINDOW (selected_window);
   EMACS_INT requested_arg = (NILP (arg)
-                            ? window_body_cols (w) - 2
+                            ? window_body_width (w, 0) - 2
                             : XINT (Fprefix_numeric_value (arg)));
   Lisp_Object result = set_window_hscroll (w, w->hscroll + requested_arg);
 
@@ -5013,7 +5542,7 @@ by this function.  This happens in an interactive call.  */)
 {
   struct window *w = XWINDOW (selected_window);
   EMACS_INT requested_arg = (NILP (arg)
-                            ? window_body_cols (w) - 2
+                            ? window_body_width (w, 0) - 2
                             : XINT (Fprefix_numeric_value (arg)));
   Lisp_Object result = set_window_hscroll (w, w->hscroll - requested_arg);
 
@@ -5287,22 +5816,36 @@ and redisplay normally--don't erase and redraw the frame.  */)
   return Qnil;
 }
 
-DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
+DEFUN ("window-text-width", Fwindow_text_width, Swindow_text_width,
        0, 1, 0,
-       doc: /* Return the height in lines of the text display area of WINDOW.
+       doc: /* Return the width in columns of the text display area of WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
-The returned height does not include the mode line, any header line,
-nor any partial-height lines at the bottom of the text area.  */)
+The returned width does not include dividers, scrollbars, margins,
+fringes, nor any partial-width columns at the right of the text
+area.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
-  int pixel_height = window_box_height (w);
-  int line_height = pixel_height / FRAME_LINE_HEIGHT (XFRAME (w->frame));
-  return make_number (line_height);
+
+  return make_number (window_box_width (w, TEXT_AREA)
+                     / FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w)));
 }
 
+DEFUN ("window-text-height", Fwindow_text_height, Swindow_text_height,
+       0, 1, 0,
+       doc: /* Return the height in lines of the text display area of WINDOW.
+WINDOW must be a live window and defaults to the selected one.
 
+The returned height does not include dividers, the mode line, any header
+line, nor any partial-height lines at the bottom of the text area.  */)
+  (Lisp_Object window)
+{
+  struct window *w = decode_live_window (window);
+
+  return make_number (window_box_height (w)
+                     / FRAME_LINE_HEIGHT (WINDOW_XFRAME (w)));
+}
 \f
 DEFUN ("move-to-window-line", Fmove_to_window_line, Smove_to_window_line,
        1, 1, "P",
@@ -5395,9 +5938,15 @@ struct save_window_data
 
     /* All fields above are traced by the GC.
        From `frame-cols' down, the fields are ignored by the GC.  */
-
-    int frame_cols, frame_lines, frame_menu_bar_lines;
-    int frame_tool_bar_lines;
+    /* We should be able to do without the following two.  */
+    int frame_cols, frame_lines;
+    /* These two should get eventually replaced by their pixelized
+       counterparts.  */
+    int frame_menu_bar_lines, frame_tool_bar_lines;
+    int frame_text_width, frame_text_height;
+    /* These are currently unused.  We need them as soon as we pixelize
+       them.  */
+    int frame_menu_bar_height, frame_tool_bar_height;
   };
 
 /* This is saved as a Lisp_Vector  */
@@ -5406,6 +5955,7 @@ struct saved_window
   struct vectorlike_header header;
 
   Lisp_Object window, buffer, start, pointm, mark;
+  Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
   Lisp_Object left_col, top_line, total_cols, total_lines;
   Lisp_Object normal_cols, normal_lines;
   Lisp_Object hscroll, min_hscroll;
@@ -5526,6 +6076,10 @@ the return value is nil.  Otherwise the value is t.  */)
         made, we change the frame to the size specified in the
         configuration, restore the configuration, and then resize it
         back.  We keep track of the prevailing height in these variables.  */
+      int previous_frame_text_height = FRAME_TEXT_HEIGHT (f);
+      int previous_frame_text_width =  FRAME_TEXT_WIDTH  (f);
+      int previous_frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+      int previous_frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
       int previous_frame_lines = FRAME_LINES (f);
       int previous_frame_cols =  FRAME_COLS  (f);
       int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
@@ -5550,12 +6104,12 @@ the return value is nil.  Otherwise the value is t.  */)
         if it runs during this.  */
       block_input ();
 
-      if (data->frame_lines != previous_frame_lines
-         || data->frame_cols != previous_frame_cols)
-       change_frame_size (f, data->frame_lines,
-                          data->frame_cols, 0, 0, 0);
-      if (data->frame_menu_bar_lines
-         != previous_frame_menu_bar_lines)
+      if (data->frame_text_width != previous_frame_text_width
+         || data->frame_text_height != previous_frame_text_height)
+       change_frame_size (f, data->frame_text_width,
+                          data->frame_text_height, 0, 0, 0, 1);
+
+      if (data->frame_menu_bar_lines != previous_frame_menu_bar_lines)
        {
 #ifdef HAVE_WINDOW_SYSTEM
          if (FRAME_WINDOW_P (f))
@@ -5567,8 +6121,7 @@ the return value is nil.  Otherwise the value is t.  */)
                                make_number (0));
        }
 #ifdef HAVE_WINDOW_SYSTEM
-      if (data->frame_tool_bar_lines
-         != previous_frame_tool_bar_lines)
+      if (data->frame_tool_bar_lines != previous_frame_tool_bar_lines)
        x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
                              make_number (0));
 #endif
@@ -5640,6 +6193,10 @@ the return value is nil.  Otherwise the value is t.  */)
          /* If we squirreled away the buffer, restore it now.  */
          if (BUFFERP (w->combination_limit))
            wset_buffer (w, w->combination_limit);
+         w->pixel_left = XFASTINT (p->pixel_left);
+         w->pixel_top = XFASTINT (p->pixel_top);
+         w->pixel_width = XFASTINT (p->pixel_width);
+         w->pixel_height = XFASTINT (p->pixel_height);
          w->left_col = XFASTINT (p->left_col);
          w->top_line = XFASTINT (p->top_line);
          w->total_cols = XFASTINT (p->total_cols);
@@ -5745,11 +6302,12 @@ the return value is nil.  Otherwise the value is t.  */)
              && FRAME_LIVE_P (XFRAME (data->focus_frame))))
        Fredirect_frame_focus (frame, data->focus_frame);
 
-      /* Set the screen height to the value it had before this function.  */
-      if (previous_frame_lines != FRAME_LINES (f)
-         || previous_frame_cols != FRAME_COLS (f))
-       change_frame_size (f, previous_frame_lines, previous_frame_cols,
-                          0, 0, 0);
+      /* Set the frame size to the value it had before this function.  */
+      if (previous_frame_text_width != FRAME_TEXT_WIDTH (f)
+         || previous_frame_text_height != FRAME_TEXT_HEIGHT (f))
+       change_frame_size (f, previous_frame_text_width,
+                          previous_frame_text_height, 0, 0, 0, 1);
+
       if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
        {
 #ifdef HAVE_WINDOW_SYSTEM
@@ -5954,6 +6512,10 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, int i)
       wset_temslot (w, make_number (i)); i++;
       p->window = window;
       p->buffer = (WINDOW_LEAF_P (w) ? w->contents : Qnil);
+      p->pixel_left = make_number (w->pixel_left);
+      p->pixel_top = make_number (w->pixel_top);
+      p->pixel_width = make_number (w->pixel_width);
+      p->pixel_height = make_number (w->pixel_height);
       p->left_col = make_number (w->left_col);
       p->top_line = make_number (w->top_line);
       p->total_cols = make_number (w->total_cols);
@@ -6093,6 +6655,10 @@ saved by this function.  */)
   data->frame_lines = FRAME_LINES (f);
   data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f);
   data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f);
+  data->frame_text_width = FRAME_TEXT_WIDTH (f);
+  data->frame_text_height = FRAME_TEXT_HEIGHT (f);
+  data->frame_menu_bar_height = FRAME_MENU_BAR_HEIGHT (f);
+  data->frame_tool_bar_height = FRAME_TOOL_BAR_HEIGHT (f);
   data->selected_frame = selected_frame;
   data->current_window = FRAME_SELECTED_WINDOW (f);
   XSETBUFFER (data->current_buffer, current_buffer);
@@ -6179,8 +6745,10 @@ as nil.  */)
   (Lisp_Object window)
 {
   struct window *w = decode_live_window (window);
-  return Fcons (w->left_margin_cols ? make_number (w->left_margin_cols) : Qnil,
-               w->right_margin_cols ? make_number (w->right_margin_cols) : Qnil);
+  return Fcons (w->left_margin_cols
+               ? make_number (w->left_margin_cols) : Qnil,
+               w->right_margin_cols
+               ? make_number (w->right_margin_cols) : Qnil);
 }
 
 
@@ -6290,15 +6858,14 @@ DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
        doc: /* Set width and type of scroll bars of window WINDOW.
 WINDOW must be a live window and defaults to the selected one.
 
-Second parameter WIDTH specifies the pixel width for the scroll bar;
-this is automatically adjusted to a multiple of the frame column width.
+Second parameter WIDTH specifies the pixel width for the scroll bar.
 Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
 bar: left, right, or nil.
 If WIDTH is nil, use the frame's scroll-bar width.
 If VERTICAL-TYPE is t, use the frame's scroll-bar type.
 Fourth parameter HORIZONTAL-TYPE is currently unused.
 
-Return t if scroll bars was actually changed and nil otherwise.  */)
+Return t if scroll bars were actually changed and nil otherwise.  */)
   (Lisp_Object window, Lisp_Object width,
    Lisp_Object vertical_type, Lisp_Object horizontal_type)
 {
@@ -6493,6 +7060,10 @@ compare_window_configurations (Lisp_Object configuration1,
          != EQ (d2->current_window, sw2->window)
          /* Windows' buffers must match.  */
          || !EQ (sw1->buffer, sw2->buffer)
+         || !EQ (sw1->pixel_left, sw2->pixel_left)
+         || !EQ (sw1->pixel_top, sw2->pixel_top)
+         || !EQ (sw1->pixel_height, sw2->pixel_height)
+         || !EQ (sw1->pixel_width, sw2->pixel_width)
          || !EQ (sw1->left_col, sw2->left_col)
          || !EQ (sw1->top_line, sw2->top_line)
          || !EQ (sw1->total_cols, sw2->total_cols)
@@ -6571,6 +7142,7 @@ syms_of_window (void)
   DEFSYM (Qdelete_window, "delete-window");
   DEFSYM (Qwindow_resize_root_window, "window--resize-root-window");
   DEFSYM (Qwindow_resize_root_window_vertically, "window--resize-root-window-vertically");
+  DEFSYM (Qwindow_pixel_to_total, "window--pixel-to-total");
   DEFSYM (Qsafe, "safe");
   DEFSYM (Qdisplay_buffer, "display-buffer");
   DEFSYM (Qreplace_buffer_in_windows, "replace-buffer-in-windows");
@@ -6729,6 +7301,18 @@ Parameters not saved by `current-window-configuration' or
 respectively are not installed by `window-state-put'.  */);
   Vwindow_persistent_parameters = list1 (Fcons (Qclone_of, Qt));
 
+  DEFVAR_BOOL ("window-resize-pixelwise", window_resize_pixelwise,
+              doc: /*  Non-nil means resizing windows works pixelwise.
+Functions currently affected by this option are `split-window',
+`maximize-window', `minimize-window', `fit-window-to-buffer' and
+`fit-frame-to-buffer' and all functions symmetrically resizing a
+parent window.
+
+Note that when a frame's pixel size is not a multiple of the
+frame's character size, at least one window may get resized
+pixelwise even if this option is nil.  */);
+  window_resize_pixelwise = 0;
+
   defsubr (&Sselected_window);
   defsubr (&Sminibuffer_window);
   defsubr (&Swindow_minibuffer_p);
@@ -6751,16 +7335,23 @@ respectively are not installed by `window-state-put'.  */);
   defsubr (&Swindow_combination_limit);
   defsubr (&Sset_window_combination_limit);
   defsubr (&Swindow_use_time);
-  defsubr (&Swindow_top_line);
-  defsubr (&Swindow_left_column);
-  defsubr (&Swindow_total_height);
+  defsubr (&Swindow_pixel_width);
+  defsubr (&Swindow_pixel_height);
   defsubr (&Swindow_total_width);
+  defsubr (&Swindow_total_height);
   defsubr (&Swindow_normal_size);
+  defsubr (&Swindow_new_pixel);
   defsubr (&Swindow_new_total);
   defsubr (&Swindow_new_normal);
+  defsubr (&Swindow_pixel_left);
+  defsubr (&Swindow_pixel_top);
+  defsubr (&Swindow_left_column);
+  defsubr (&Swindow_top_line);
+  defsubr (&Sset_window_new_pixel);
   defsubr (&Sset_window_new_total);
   defsubr (&Sset_window_new_normal);
   defsubr (&Swindow_resize_apply);
+  defsubr (&Swindow_resize_apply_total);
   defsubr (&Swindow_body_height);
   defsubr (&Swindow_body_width);
   defsubr (&Swindow_hscroll);
@@ -6770,6 +7361,10 @@ respectively are not installed by `window-state-put'.  */);
   defsubr (&Swindow_edges);
   defsubr (&Swindow_pixel_edges);
   defsubr (&Swindow_absolute_pixel_edges);
+  defsubr (&Swindow_mode_line_height);
+  defsubr (&Swindow_header_line_height);
+  defsubr (&Swindow_right_divider_width);
+  defsubr (&Swindow_bottom_divider_width);
   defsubr (&Swindow_inside_edges);
   defsubr (&Swindow_inside_pixel_edges);
   defsubr (&Swindow_inside_absolute_pixel_edges);
@@ -6792,6 +7387,7 @@ respectively are not installed by `window-state-put'.  */);
   defsubr (&Sresize_mini_window_internal);
   defsubr (&Sset_window_buffer);
   defsubr (&Srun_window_configuration_change_hook);
+  defsubr (&Srun_window_scroll_functions);
   defsubr (&Sselect_window);
   defsubr (&Sforce_window_update);
   defsubr (&Ssplit_window_internal);
@@ -6803,6 +7399,7 @@ respectively are not installed by `window-state-put'.  */);
   defsubr (&Sscroll_other_window);
   defsubr (&Sminibuffer_selected_window);
   defsubr (&Srecenter);
+  defsubr (&Swindow_text_width);
   defsubr (&Swindow_text_height);
   defsubr (&Smove_to_window_line);
   defsubr (&Swindow_configuration_p);
index 555c386..b91161f 100644 (file)
@@ -111,6 +111,7 @@ struct window
        to something beyond an integer, so C int can't be used here.  */
     Lisp_Object new_total;
     Lisp_Object new_normal;
+    Lisp_Object new_pixel;
 
     /* May be buffer, window, or nil.  */
     Lisp_Object contents;
@@ -180,14 +181,26 @@ struct window
     /* Number saying how recently window was selected.  */
     int use_time;
 
+    /* Unique number of window assigned when it was created.  */
+    int sequence_number;
+
+    /* The upper left corner pixel coordinates of this window, as
+       integers relative to upper left corner of frame = 0, 0.  */
+    int pixel_left;
+    int pixel_top;
+
     /* The upper left corner coordinates of this window,
        relative to upper left corner of frame = 0, 0.  */
     int left_col;
     int top_line;
 
+    /* The pixel size of the window.  */
+    int pixel_width;
+    int pixel_height;
+
     /* The size of the window.  */
-    int total_lines;
     int total_cols;
+    int total_lines;
 
     /* Number of columns display within the window is scrolled to the left.  */
     ptrdiff_t hscroll;
@@ -356,31 +369,43 @@ wset_frame (struct window *w, Lisp_Object val)
 {
   w->frame = val;
 }
+
 INLINE void
 wset_next (struct window *w, Lisp_Object val)
 {
   w->next = val;
 }
+
 INLINE void
 wset_prev (struct window *w, Lisp_Object val)
 {
   w->prev = val;
 }
+
 INLINE void
 wset_redisplay_end_trigger (struct window *w, Lisp_Object val)
 {
   w->redisplay_end_trigger = val;
 }
+
+INLINE void
+wset_new_pixel (struct window *w, Lisp_Object val)
+{
+  w->new_pixel = val;
+}
+
 INLINE void
 wset_vertical_scroll_bar (struct window *w, Lisp_Object val)
 {
   w->vertical_scroll_bar = val;
 }
+
 INLINE void
 wset_prev_buffers (struct window *w, Lisp_Object val)
 {
   w->prev_buffers = val;
 }
+
 INLINE void
 wset_next_buffers (struct window *w, Lisp_Object val)
 {
@@ -446,38 +471,44 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 #define WINDOW_FRAME_LINE_HEIGHT(W) \
   (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W))))
 
-/* Return the width of window W in canonical column units.
+/* Return the pixel width of window W.
    This includes scroll bars and fringes.  */
+#define WINDOW_PIXEL_WIDTH(W) (W)->pixel_width
 
+/* Return the pixel height of window W.
+   This includes header and mode lines, if any.  */
+#define WINDOW_PIXEL_HEIGHT(W) (W)->pixel_height
+
+/* Return the width of window W in canonical column units.
+   This includes scroll bars and fringes.
+   This value is adjusted such that the sum of the widths of all child
+   windows equals the width of their parent window.  */
 #define WINDOW_TOTAL_COLS(W) (W)->total_cols
 
 /* Return the height of window W in canonical line units.
-   This includes header and mode lines, if any.  */
-
+   This includes header and mode lines, if any.
+   This value is adjusted such that the sum of the heights of all child
+   windows equals the height of their parent window.  */
 #define WINDOW_TOTAL_LINES(W) (W)->total_lines
 
-/* Return the total pixel width of window W.  */
-
-#define WINDOW_TOTAL_WIDTH(W) \
-  (WINDOW_TOTAL_COLS (W) * WINDOW_FRAME_COLUMN_WIDTH (W))
-
-/* Return the total pixel height of window W.  */
-
-#define WINDOW_TOTAL_HEIGHT(W) \
-  (WINDOW_TOTAL_LINES (W) * WINDOW_FRAME_LINE_HEIGHT (W))
-
-/* For HORFLAG non-zero the total number of columns of window W.  Otherwise
-   the total number of lines of W.  */
-
-#define WINDOW_TOTAL_SIZE(w, horflag) \
-  (horflag ? WINDOW_TOTAL_COLS (w) : WINDOW_TOTAL_LINES (w))
-
 /* The smallest acceptable dimensions for a window.  Anything smaller
    might crash Emacs.  */
+#define MIN_SAFE_WINDOW_WIDTH (2)
+
+#define MIN_SAFE_WINDOW_PIXEL_WIDTH(W) \
+  (2 * WINDOW_FRAME_COLUMN_WIDTH (W))
 
-#define MIN_SAFE_WINDOW_WIDTH  (2)
 #define MIN_SAFE_WINDOW_HEIGHT (1)
 
+#define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \
+  (WINDOW_FRAME_LINE_HEIGHT (W))
+
+/* Width of right divider of window W.  */
+#define WINDOW_RIGHT_DIVIDER_WIDTH(W)                          \
+  ((WINDOW_RIGHTMOST_P (W) || MINI_WINDOW_P (W))               \
+   ? 0                                                         \
+   : FRAME_RIGHT_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
+
 /* Return the canonical frame column at which window W starts.
    This includes a left-hand scroll bar, if any.  */
 
@@ -500,20 +531,37 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 #define WINDOW_BOTTOM_EDGE_LINE(W) \
   (WINDOW_TOP_EDGE_LINE (W) + WINDOW_TOTAL_LINES (W))
 
+/* Return the left pixel edge at which window W starts.
+   This includes a left-hand scroll bar, if any.  */
+#define WINDOW_LEFT_PIXEL_EDGE(W) (W)->pixel_left
+
+/* Return the right pixel edge before which window W ends.
+   This includes a right-hand scroll bar, if any.  */
+#define WINDOW_RIGHT_PIXEL_EDGE(W) \
+  (WINDOW_LEFT_PIXEL_EDGE (W) + WINDOW_PIXEL_WIDTH (W))
+
+/* Return the top pixel edge at which window W starts.
+   This includes a header line, if any.  */
+#define WINDOW_TOP_PIXEL_EDGE(W) (W)->pixel_top
+
+/* Return the bottom pixel edge before which window W ends.
+   This includes a mode line, if any.  */
+#define WINDOW_BOTTOM_PIXEL_EDGE(W) \
+  (WINDOW_TOP_PIXEL_EDGE (W) + WINDOW_PIXEL_HEIGHT (W))
 
 /* Return the frame x-position at which window W starts.
    This includes a left-hand scroll bar, if any.  */
 
 #define WINDOW_LEFT_EDGE_X(W) \
   (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
-   + WINDOW_LEFT_EDGE_COL (W) * WINDOW_FRAME_COLUMN_WIDTH (W))
+   + WINDOW_LEFT_PIXEL_EDGE (W))
 
 /* Return the frame x- position before which window W ends.
    This includes a right-hand scroll bar, if any.  */
 
 #define WINDOW_RIGHT_EDGE_X(W) \
   (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
-   + WINDOW_RIGHT_EDGE_COL (W) * WINDOW_FRAME_COLUMN_WIDTH (W))
+   + WINDOW_RIGHT_PIXEL_EDGE (W))
 
 /* 1 if W is a menu bar window.  */
 
@@ -536,37 +584,45 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 #endif
 
 /* Return the frame y-position at which window W starts.
-   This includes a header line, if any.  */
+   This includes a header line, if any.
 
+   PXW: With a menu or tool bar this is not symmetric to the _X values
+   since it _does_ include the internal border width.  */
 #define WINDOW_TOP_EDGE_Y(W) \
   (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
     ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
-   + WINDOW_TOP_EDGE_LINE (W) * WINDOW_FRAME_LINE_HEIGHT (W))
+   + WINDOW_TOP_PIXEL_EDGE (W))
 
 /* Return the frame y-position before which window W ends.
    This includes a mode line, if any.  */
-
-#define WINDOW_BOTTOM_EDGE_Y(W) \
-  (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
+#define WINDOW_BOTTOM_EDGE_Y(W)                                   \
+  (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W))      \
     ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
-   + WINDOW_BOTTOM_EDGE_LINE (W) * WINDOW_FRAME_LINE_HEIGHT (W))
-
+   + WINDOW_BOTTOM_PIXEL_EDGE (W))
 
 /* 1 if window W takes up the full width of its frame.  */
-
-#define WINDOW_FULL_WIDTH_P(W) \
-  (WINDOW_TOTAL_COLS (W) == FRAME_TOTAL_COLS (WINDOW_XFRAME (W)))
+#define WINDOW_FULL_WIDTH_P(W)                                 \
+  (WINDOW_PIXEL_WIDTH (W)                                      \
+   == (WINDOW_PIXEL_WIDTH                                      \
+       (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))))))     \
 
 /* 1 if window W's has no other windows to its left in its frame.  */
 
 #define WINDOW_LEFTMOST_P(W) \
-  (WINDOW_LEFT_EDGE_COL (W) == 0)
+  (WINDOW_LEFT_PIXEL_EDGE (W) == 0)
 
 /* 1 if window W's has no other windows to its right in its frame.  */
-
-#define WINDOW_RIGHTMOST_P(W) \
-  (WINDOW_RIGHT_EDGE_COL (W) == FRAME_TOTAL_COLS (WINDOW_XFRAME (W)))
-
+#define WINDOW_RIGHTMOST_P(W)                                  \
+  (WINDOW_RIGHT_PIXEL_EDGE (W)                                 \
+   == (WINDOW_RIGHT_PIXEL_EDGE                                 \
+       (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))))))     \
+
+/* 1 if window W's has no other windows below it in its frame
+   (the minibuffer window is not counted in this respect).  */
+#define WINDOW_BOTTOMMOST_P(W)                                 \
+  (WINDOW_BOTTOM_PIXEL_EDGE (W)                                        \
+   == (WINDOW_BOTTOM_PIXEL_EDGE                                        \
+       (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))))))     \
 
 /* Return the frame column at which the text (or left fringe) in
    window W starts.  This is different from the `LEFT_EDGE' because it
@@ -576,6 +632,13 @@ wset_next_buffers (struct window *w, Lisp_Object val)
   (WINDOW_LEFT_EDGE_COL (W) \
    + WINDOW_LEFT_SCROLL_BAR_COLS (W))
 
+/* Return the pixel value where the text (or left fringe) in
+   window W starts.  This is different from the `LEFT_EDGE' because it
+   does not include a left-hand scroll bar if any.  */
+#define WINDOW_BOX_LEFT_PIXEL_EDGE(W)          \
+  (WINDOW_LEFT_PIXEL_EDGE (W)                  \
+   + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (W))
+
 /* Return the window column before which the text in window W ends.
    This is different from WINDOW_RIGHT_EDGE_COL because it does not
    include a scroll bar or window-separating line on the right edge.  */
@@ -584,59 +647,72 @@ wset_next_buffers (struct window *w, Lisp_Object val)
   (WINDOW_RIGHT_EDGE_COL (W) \
    - WINDOW_RIGHT_SCROLL_BAR_COLS (W))
 
+/* Return the pixel value before which the text in window W ends.  This
+   is different from the `RIGHT_EDGE' because it does not include a
+   right-hand scroll bar or window-separating line on the right
+   edge.  */
+#define WINDOW_BOX_RIGHT_PIXEL_EDGE(W)         \
+  (WINDOW_RIGHT_PIXEL_EDGE (W)                 \
+   - WINDOW_RIGHT_DIVIDER_WIDTH (W)            \
+   - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (W))
 
 /* Return the frame position at which the text (or left fringe) in
    window W starts.  This is different from the `LEFT_EDGE' because it
    does not include a left-hand scroll bar if any.  */
-
-#define WINDOW_BOX_LEFT_EDGE_X(W) \
+#define WINDOW_BOX_LEFT_EDGE_X(W)                 \
   (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
-   + WINDOW_BOX_LEFT_EDGE_COL (W) * WINDOW_FRAME_COLUMN_WIDTH (W))
+   + WINDOW_BOX_LEFT_PIXEL_EDGE (W))
 
 /* Return the window column before which the text in window W ends.
    This is different from WINDOW_RIGHT_EDGE_COL because it does not
    include a scroll bar or window-separating line on the right edge.  */
-
-#define WINDOW_BOX_RIGHT_EDGE_X(W) \
+#define WINDOW_BOX_RIGHT_EDGE_X(W)                \
   (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
-   + WINDOW_BOX_RIGHT_EDGE_COL (W) * WINDOW_FRAME_COLUMN_WIDTH (W))
-
-
-/* Width of left margin area in columns.  */
+   + WINDOW_BOX_RIGHT_PIXEL_EDGE (W))
 
+/* Widths of marginal areas in columns.  */
 #define WINDOW_LEFT_MARGIN_COLS(W) (W->left_margin_cols)
 
-/* Width of right marginal area in columns.  */
-
 #define WINDOW_RIGHT_MARGIN_COLS(W) (W->right_margin_cols)
 
-/* Width of left margin area in pixels.  */
+#define WINDOW_MARGINS_COLS(W)                 \
+  (WINDOW_LEFT_MARGIN_COLS (W)                 \
+   + WINDOW_RIGHT_MARGIN_COLS (W))
 
+/* Widths of marginal areas in pixels.  */
 #define WINDOW_LEFT_MARGIN_WIDTH(W)                    \
   (W->left_margin_cols * WINDOW_FRAME_COLUMN_WIDTH (W))
 
-/* Width of right marginal area in pixels.  */
-
-#define WINDOW_RIGHT_MARGIN_WIDTH(W)                   \
+#define WINDOW_RIGHT_MARGIN_WIDTH(W)                           \
   (W->right_margin_cols * WINDOW_FRAME_COLUMN_WIDTH (W))
 
-/* Total width of fringes reserved for drawing truncation bitmaps,
-   continuation bitmaps and alike.  The width is in canonical char
-   units of the frame.  This must currently be the case because window
-   sizes aren't pixel values.  If it weren't the case, we wouldn't be
-   able to split windows horizontally nicely.  */
+#define WINDOW_MARGINS_WIDTH(W)                        \
+  (WINDOW_LEFT_MARGIN_WIDTH (W)                        \
+   + WINDOW_RIGHT_MARGIN_WIDTH (W))
 
+/* Pixel-widths of fringes.  */
+#define WINDOW_LEFT_FRINGE_WIDTH(W)                    \
+  (W->left_fringe_width >= 0                           \
+   ? W->left_fringe_width                              \
+   : FRAME_LEFT_FRINGE_WIDTH (WINDOW_XFRAME (W)))
+
+#define WINDOW_RIGHT_FRINGE_WIDTH(W)                   \
+  (W->right_fringe_width >= 0                          \
+   ? W->right_fringe_width                             \
+   : FRAME_RIGHT_FRINGE_WIDTH (WINDOW_XFRAME (W)))
+
+#define WINDOW_FRINGES_WIDTH(W)                \
+  (WINDOW_LEFT_FRINGE_WIDTH (W) + WINDOW_RIGHT_FRINGE_WIDTH (W))
+
+/* Widths of fringes in columns.  */
 #define WINDOW_FRINGE_COLS(W)                  \
   ((W->left_fringe_width >= 0                  \
     && W->right_fringe_width >= 0)             \
-   ? ((W->left_fringe_width                    \
-       + W->right_fringe_width                 \
+   ? ((WINDOW_FRINGES_WIDTH (W)                        \
        + WINDOW_FRAME_COLUMN_WIDTH (W) - 1)    \
       / WINDOW_FRAME_COLUMN_WIDTH (W))         \
    : FRAME_FRINGE_COLS (WINDOW_XFRAME (W)))
 
-/* Column-width of the left and right fringe.  */
-
 #define WINDOW_LEFT_FRINGE_COLS(W)             \
   ((WINDOW_LEFT_FRINGE_WIDTH ((W))             \
     + WINDOW_FRAME_COLUMN_WIDTH (W) - 1)       \
@@ -647,29 +723,12 @@ wset_next_buffers (struct window *w, Lisp_Object val)
     + WINDOW_FRAME_COLUMN_WIDTH (W) - 1)       \
    / WINDOW_FRAME_COLUMN_WIDTH (W))
 
-/* Pixel-width of the left and right fringe.  */
-
-#define WINDOW_LEFT_FRINGE_WIDTH(W)                    \
-  (W->left_fringe_width >= 0 ? W->left_fringe_width    \
-   : FRAME_LEFT_FRINGE_WIDTH (WINDOW_XFRAME (W)))
-
-#define WINDOW_RIGHT_FRINGE_WIDTH(W)                   \
-  (W->right_fringe_width >= 0 ? W->right_fringe_width  \
-   : FRAME_RIGHT_FRINGE_WIDTH (WINDOW_XFRAME (W)))
-
-/* Total width of fringes in pixels.  */
-
-#define WINDOW_TOTAL_FRINGE_WIDTH(W)           \
-  (WINDOW_LEFT_FRINGE_WIDTH (W) + WINDOW_RIGHT_FRINGE_WIDTH (W))
-
 /* Are fringes outside display margins in window W.  */
-
 #define WINDOW_HAS_FRINGES_OUTSIDE_MARGINS(W)  \
   ((W)->fringes_outside_margins)
 
 /* Say whether scroll bars are currently enabled for window W,
    and which side they are on.  */
-
 #define WINDOW_VERTICAL_SCROLL_BAR_TYPE(w)             \
   (EQ (w->vertical_scroll_bar_type, Qt)                        \
    ? FRAME_VERTICAL_SCROLL_BAR_TYPE (WINDOW_XFRAME (w))        \
@@ -697,15 +756,14 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 /* Width that a scroll bar in window W should have, if there is one.
    Measured in pixels.  If scroll bars are turned off, this is still
    nonzero.  */
-
 #define WINDOW_CONFIG_SCROLL_BAR_WIDTH(w)              \
-  (w->scroll_bar_width >= 0 ? w->scroll_bar_width      \
+  (w->scroll_bar_width >= 0                            \
+   ? w->scroll_bar_width                               \
    : FRAME_CONFIG_SCROLL_BAR_WIDTH (WINDOW_XFRAME (w)))
 
 /* Width that a scroll bar in window W should have, if there is one.
    Measured in columns (characters).  If scroll bars are turned off,
    this is still nonzero.  */
-
 #define WINDOW_CONFIG_SCROLL_BAR_COLS(w)               \
   (w->scroll_bar_width >= 0                            \
    ? ((w->scroll_bar_width                             \
@@ -713,65 +771,64 @@ wset_next_buffers (struct window *w, Lisp_Object val)
       / WINDOW_FRAME_COLUMN_WIDTH (w))                 \
    : FRAME_CONFIG_SCROLL_BAR_COLS (WINDOW_XFRAME (w)))
 
-/* Width of a scroll bar in window W, measured in columns (characters),
-   but only if scroll bars are on the left.  If scroll bars are on
-   the right in this frame, or there are no scroll bars, value is 0.  */
-
+/* Width of left scroll bar in window W, measured in columns
+   (characters).  If scroll bars are on the right in this frame, or
+   there are no scroll bars, value is 0.  */
 #define WINDOW_LEFT_SCROLL_BAR_COLS(w)        \
   (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)  \
    ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w))       \
    : 0)
 
-/* Width of a left scroll bar area in window W , measured in pixels.  */
-
-#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(w)                            \
-  (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)                           \
-   ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)) \
-   : 0)
-
-/* Width of a scroll bar in window W, measured in columns (characters),
-   but only if scroll bars are on the right.  If scroll bars are on
-   the left in this frame, or there are no scroll bars, value is 0.  */
-
+/* Width of right scroll bar in window W, measured in columns
+   (characters).  If scroll bars are on the left in this frame, or there
+   are no scroll bars, value is 0.  */
 #define WINDOW_RIGHT_SCROLL_BAR_COLS(w)                \
   (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w) \
    ? WINDOW_CONFIG_SCROLL_BAR_COLS (w)         \
    : 0)
 
-/* Width of a left scroll bar area in window W , measured in pixels.  */
-
-#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(w)                           \
-  (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)                          \
-   ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)) \
-   : 0)
-
-
-/* Actual width of a scroll bar in window W, measured in columns.  */
-
+/* Width of a scroll bar in window W, measured in columns.  */
 #define WINDOW_SCROLL_BAR_COLS(w)             \
   (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)         \
    ? WINDOW_CONFIG_SCROLL_BAR_COLS (w)        \
    : 0)
 
-/* Width of a left scroll bar area in window W , measured in pixels.  */
+/* Width of a left scroll bar area in window W, measured in pixels.  */
+#define WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH(w)                           \
+  (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)                          \
+   ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)                                        \
+   : 0)
 
-#define WINDOW_SCROLL_BAR_AREA_WIDTH(w)                                         \
-  (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)                                   \
-   ? (WINDOW_CONFIG_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)) \
+/* Width of a right scroll bar area in window W, measured in pixels.  */
+#define WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH(w)                          \
+  (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)                         \
+   ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)                                        \
    : 0)
 
+/* Width of scroll bar area in window W, measured in pixels.  */
+#define WINDOW_SCROLL_BAR_AREA_WIDTH(w)                                        \
+  (WINDOW_HAS_VERTICAL_SCROLL_BAR (w)                                  \
+   ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (w)                                        \
+   : 0)
 
 /* Return the frame position where the scroll bar of window W starts.  */
-
 #define WINDOW_SCROLL_BAR_AREA_X(W)            \
   (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (W) \
    ? WINDOW_BOX_RIGHT_EDGE_X (W)               \
    : WINDOW_LEFT_EDGE_X (W))
 
+/* Width of bottom divider of window W.  */
+#define WINDOW_BOTTOM_DIVIDER_WIDTH(W)                                 \
+  (((WINDOW_BOTTOMMOST_P (W)                                           \
+     && NILP ((XWINDOW (FRAME_ROOT_WINDOW                              \
+                       (WINDOW_XFRAME (W))))->next))                   \
+    || EQ ((W)->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))           \
+    || (W)->pseudo_window_p)                                           \
+   ? 0                                                                 \
+   : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
 
 /* Height in pixels, and in lines, of the mode line.
    May be zero if W doesn't have a mode line.  */
-
 #define WINDOW_MODE_LINE_HEIGHT(W)     \
   (WINDOW_WANTS_MODELINE_P ((W))       \
    ? CURRENT_MODE_LINE_HEIGHT (W)      \
@@ -782,7 +839,6 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 
 /* Height in pixels, and in lines, of the header line.
    Zero if W doesn't have a header line.  */
-
 #define WINDOW_HEADER_LINE_HEIGHT(W)   \
   (WINDOW_WANTS_HEADER_LINE_P ((W))    \
    ? CURRENT_HEADER_LINE_HEIGHT (W)    \
@@ -791,43 +847,38 @@ wset_next_buffers (struct window *w, Lisp_Object val)
 #define WINDOW_HEADER_LINE_LINES(W)    \
   (!! WINDOW_WANTS_HEADER_LINE_P ((W)))
 
-/* Pixel height of window W without mode line.  */
-
+/* Pixel height of window W without mode line and bottom divider.  */
 #define WINDOW_BOX_HEIGHT_NO_MODE_LINE(W)      \
-  (WINDOW_TOTAL_HEIGHT ((W))                   \
+  (WINDOW_PIXEL_HEIGHT ((W))                   \
+   - WINDOW_BOTTOM_DIVIDER_WIDTH (W)           \
    - WINDOW_MODE_LINE_HEIGHT ((W)))
 
-/* Pixel height of window W without mode and header line.  */
-
+/* Pixel height of window W without mode and header line and bottom
+   divider.  */
 #define WINDOW_BOX_TEXT_HEIGHT(W)      \
-  (WINDOW_TOTAL_HEIGHT ((W))           \
+  (WINDOW_PIXEL_HEIGHT ((W))           \
+   - WINDOW_BOTTOM_DIVIDER_WIDTH (W)   \
    - WINDOW_MODE_LINE_HEIGHT ((W))     \
    - WINDOW_HEADER_LINE_HEIGHT ((W)))
 
-
 /* Convert window W relative pixel X to frame pixel coordinates.  */
-
 #define WINDOW_TO_FRAME_PIXEL_X(W, X)  \
   ((X) + WINDOW_BOX_LEFT_EDGE_X ((W)))
 
 /* Convert window W relative pixel Y to frame pixel coordinates.  */
-
 #define WINDOW_TO_FRAME_PIXEL_Y(W, Y)  \
   ((Y) + WINDOW_TOP_EDGE_Y ((W)))
 
 /* Convert frame relative pixel X to window relative pixel X.  */
-
 #define FRAME_TO_WINDOW_PIXEL_X(W, X)  \
   ((X) - WINDOW_BOX_LEFT_EDGE_X ((W)))
 
 /* Convert frame relative pixel Y to window relative pixel Y.  */
-
 #define FRAME_TO_WINDOW_PIXEL_Y(W, Y)  \
   ((Y) - WINDOW_TOP_EDGE_Y ((W)))
 
 /* Convert a text area relative x-position in window W to frame X
    pixel coordinates.  */
-
 #define WINDOW_TEXT_TO_FRAME_PIXEL_X(W, X)     \
   (window_box_left ((W), TEXT_AREA) + (X))
 
@@ -873,18 +924,17 @@ extern Lisp_Object minibuf_selected_window;
 extern Lisp_Object make_window (void);
 extern Lisp_Object window_from_coordinates (struct frame *, int, int,
                                             enum window_part *, bool);
-extern void resize_frame_windows (struct frame *, int, bool);
+extern void resize_frame_windows (struct frame *, int, bool, bool);
 extern void restore_window_configuration (Lisp_Object);
 extern void delete_all_child_windows (Lisp_Object);
-extern void grow_mini_window (struct window *, int);
-extern void shrink_mini_window (struct window *);
+extern void grow_mini_window (struct window *, int, bool);
+extern void shrink_mini_window (struct window *, bool);
 extern int window_relative_x_coord (struct window *, enum window_part, int);
 
 void run_window_configuration_change_hook (struct frame *f);
 
-/* Make WINDOW display BUFFER as its contents.  RUN_HOOKS_P non-zero
-   means it's allowed to run hooks.  See make_frame for a case where
-   it's not allowed.  */
+/* Make WINDOW display BUFFER.  RUN_HOOKS_P non-zero means it's allowed
+   to run hooks.  See make_frame for a case where it's not allowed.  */
 
 void set_window_buffer (Lisp_Object window, Lisp_Object buffer,
                         bool run_hooks_p, bool keep_margins_p);
@@ -932,7 +982,7 @@ extern void redisplay_other_windows (void);
 /* If *ROWS or *COLS are too small a size for FRAME, set them to the
    minimum allowable size.  */
 
-extern void check_frame_size (struct frame *frame, int *rows, int *cols);
+extern void check_frame_size (struct frame *frame, int *width, int *height, bool pixelwise);
 
 /* Return a pointer to the glyph W's physical cursor is on.  Value is
    null if W's current matrix is invalid, so that no meaningful glyph
@@ -968,7 +1018,7 @@ extern struct window *decode_any_window (Lisp_Object);
 extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
 extern void mark_window_cursors_off (struct window *);
 extern int window_internal_height (struct window *);
-extern int window_body_cols (struct window *w);
+extern int window_body_width (struct window *w, bool);
 extern void temp_output_buffer_show (Lisp_Object);
 extern void replace_buffer_in_windows (Lisp_Object);
 extern void replace_buffer_in_windows_safely (Lisp_Object);
index 28da6bf..8e2c18f 100644 (file)
@@ -570,7 +570,7 @@ static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
 
 /* Ascent and height of the last line processed by move_it_to.  */
 
-static int last_height;
+static int last_max_ascent, last_height;
 
 /* Non-zero if there's a help-echo in the echo area.  */
 
@@ -998,10 +998,13 @@ static int coords_in_mouse_face_p (struct window *, int, int);
 int
 window_text_bottom_y (struct window *w)
 {
-  int height = WINDOW_TOTAL_HEIGHT (w);
+  int height = WINDOW_PIXEL_HEIGHT (w);
+
+  height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
 
   if (WINDOW_WANTS_MODELINE_P (w))
     height -= CURRENT_MODE_LINE_HEIGHT (w);
+
   return height;
 }
 
@@ -1012,32 +1015,23 @@ window_text_bottom_y (struct window *w)
 int
 window_box_width (struct window *w, enum glyph_row_area area)
 {
-  int cols = w->total_cols;
-  int pixels = 0;
+  int pixels = w->pixel_width;
 
   if (!w->pseudo_window_p)
     {
-      cols -= WINDOW_SCROLL_BAR_COLS (w);
+      pixels -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
+      pixels -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
 
       if (area == TEXT_AREA)
-       {
-         cols -= max (0, w->left_margin_cols);
-         cols -= max (0, w->right_margin_cols);
-         pixels = -WINDOW_TOTAL_FRINGE_WIDTH (w);
-       }
+       pixels -= (WINDOW_MARGINS_WIDTH (w)
+                  + WINDOW_FRINGES_WIDTH (w));
       else if (area == LEFT_MARGIN_AREA)
-       {
-         cols = max (0, w->left_margin_cols);
-         pixels = 0;
-       }
+       pixels = WINDOW_LEFT_MARGIN_WIDTH (w);
       else if (area == RIGHT_MARGIN_AREA)
-       {
-         cols = max (0, w->right_margin_cols);
-         pixels = 0;
-       }
+       pixels = WINDOW_RIGHT_MARGIN_WIDTH (w);
     }
 
-  return cols * WINDOW_FRAME_COLUMN_WIDTH (w) + pixels;
+  return pixels;
 }
 
 
@@ -1048,10 +1042,12 @@ int
 window_box_height (struct window *w)
 {
   struct frame *f = XFRAME (w->frame);
-  int height = WINDOW_TOTAL_HEIGHT (w);
+  int height = WINDOW_PIXEL_HEIGHT (w);
 
   eassert (height >= 0);
 
+  height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+
   /* Note: the code below that determines the mode-line/header-line
      height is essentially the same as that contained in the macro
      CURRENT_{MODE,HEADER}_LINE_HEIGHT, except that it checks whether
@@ -1910,6 +1906,8 @@ pixel_to_glyph_coords (struct frame *f, register int pix_x, register int pix_y,
                           FRAME_COLUMN_WIDTH (f) - 1,
                           FRAME_LINE_HEIGHT (f) - 1);
 
+      /* PXW: Should we clip pixelized before converting to
+        columns/lines ?  */
       if (!noclip)
        {
          if (pix_x < 0)
@@ -2050,7 +2048,10 @@ get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int
     {
       /* Draw full-width.  X coordinates are relative to S->w->left_col.  */
       r.x = WINDOW_LEFT_EDGE_X (s->w);
-      r.width = WINDOW_TOTAL_WIDTH (s->w);
+      if (s->row->mode_line_p)
+       r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
+      else
+       r.width = WINDOW_PIXEL_WIDTH (s->w);
 
       /* Unless displaying a mode or menu bar line, which are always
         fully visible, clip to the visible part of the row.  */
@@ -2318,9 +2319,14 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
   /* Try to determine frame pixel position and size of the glyph under
      frame pixel coordinates X/Y on frame F.  */
 
-  if (!f->glyphs_initialized_p
-      || (window = window_from_coordinates (f, gx, gy, &part, 0),
-         NILP (window)))
+  if (window_resize_pixelwise)
+    {
+      width = height = 1;
+      goto virtual_glyph;
+    }
+  else if (!f->glyphs_initialized_p
+          || (window = window_from_coordinates (f, gx, gy, &part, 0),
+              NILP (window)))
     {
       width = FRAME_SMALLEST_CHAR_WIDTH (f);
       height = FRAME_SMALLEST_FONT_HEIGHT (f);
@@ -2478,6 +2484,7 @@ remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
       goto store_rect;
     }
 
+ pixelwise:
   gx += WINDOW_LEFT_EDGE_X (w);
   gy += WINDOW_TOP_EDGE_Y (w);
 
@@ -2807,6 +2814,7 @@ init_iterator (struct it *it, struct window *w,
          && ((!NILP (Vtruncate_partial_width_windows)
               && !INTEGERP (Vtruncate_partial_width_windows))
              || (INTEGERP (Vtruncate_partial_width_windows)
+                 /* PXW: Shall we do something about this ?  */
                  && (WINDOW_TOTAL_COLS (it->w)
                      < XINT (Vtruncate_partial_width_windows))))))
     it->line_wrap = TRUNCATE;
@@ -2866,7 +2874,7 @@ init_iterator (struct it *it, struct window *w,
     {
       /* Mode lines, menu bar in terminal frames.  */
       it->first_visible_x = 0;
-      it->last_visible_x = WINDOW_TOTAL_WIDTH (w);
+      it->last_visible_x = WINDOW_PIXEL_WIDTH (w);
     }
   else
     {
@@ -8843,13 +8851,17 @@ move_it_in_display_line (struct it *it,
 
    If TO_CHARPOS is in invisible text, e.g. a truncated part of a
    screen line, this function will set IT to the next position that is
-   displayed to the right of TO_CHARPOS on the screen.  */
+   displayed to the right of TO_CHARPOS on the screen.
 
-void
+   Return the maximum pixel length of any line scanned but never more
+   than it.last_visible_x.  */
+
+int
 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
 {
   enum move_it_result skip, skip2 = MOVE_X_REACHED;
   int line_height, line_start_x = 0, reached = 0;
+  int max_current_x = 0;
   void *backup_data = NULL;
 
   for (;;)
@@ -8980,6 +8992,9 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
              if (to_y >= it->current_y
                  && to_y < it->current_y + line_height)
                {
+                 if (to_y > it->current_y)
+                   max_current_x = max (it->current_x, max_current_x);
+
                  /* When word-wrap is on, TO_X may lie past the end
                     of a wrapped line.  Then it->current is the
                     character on the next line, so backtrack to the
@@ -8992,12 +9007,16 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
                      skip = move_it_in_display_line_to
                        (it, -1, prev_x, MOVE_TO_X);
                    }
+
                  reached = 6;
                }
            }
 
          if (reached)
-           break;
+           {
+             max_current_x = max (it->current_x, max_current_x);
+             break;
+           }
        }
       else if (BUFFERP (it->object)
               && (it->method == GET_FROM_BUFFER
@@ -9017,15 +9036,18 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       switch (skip)
        {
        case MOVE_POS_MATCH_OR_ZV:
+         max_current_x = max (it->current_x, max_current_x);
          reached = 8;
          goto out;
 
        case MOVE_NEWLINE_OR_CR:
+         max_current_x = max (it->current_x, max_current_x);
          set_iterator_to_next (it, 1);
          it->continuation_lines_width = 0;
          break;
 
        case MOVE_LINE_TRUNCATED:
+         max_current_x = it->last_visible_x;
          it->continuation_lines_width = 0;
          reseat_at_next_visible_line_start (it, 0);
          if ((op & MOVE_TO_POS) != 0
@@ -9037,6 +9059,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
          break;
 
        case MOVE_LINE_CONTINUED:
+         max_current_x = it->last_visible_x;
          /* For continued lines ending in a tab, some of the glyphs
             associated with the tab are displayed on the current
             line.  Since it->current_x does not include these glyphs,
@@ -9072,6 +9095,7 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
+      last_max_ascent = it->max_ascent;
       it->max_ascent = it->max_descent = 0;
     }
 
@@ -9098,12 +9122,15 @@ move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos
       it->current_y += it->max_ascent + it->max_descent;
       ++it->vpos;
       last_height = it->max_ascent + it->max_descent;
+      last_max_ascent = it->max_ascent;
     }
 
   if (backup_data)
     bidi_unshelve_cache (backup_data, 1);
 
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
+
+  return max_current_x;
 }
 
 
@@ -9451,6 +9478,145 @@ in_display_vector_p (struct it *it)
          && it->dpvec + it->current.dpvec_index != it->dpend);
 }
 
+DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0,
+       doc: /* Return the size of the text of WINDOW's buffer in pixels.
+WINDOW must be a live window and defaults to the selected one.  The
+return value is a cons of the maximum pixel-width of any text line and
+the maximum pixel-height of all text lines.
+
+The optional argument FROM, if non-nil, specifies the first text
+position and defaults to the minimum accessible position of the buffer.
+If FROM is t, use the minimum accessible position that is not a newline
+character.  TO, if non-nil, specifies the last text position and
+defaults to the maximum accessible position of the buffer.  If TO is t,
+use the maximum accessible position that is not a newline character.
+
+The optional argument X_LIMIT, if non-nil, specifies the maximum text
+width that can be returned.  X_LIMIT nil or omitted, means to use the
+pixel-width of WINDOW's body; use this if you do not intend to change
+the width of WINDOW.  Use the maximum width WINDOW may assume if you
+intend to change WINDOW's width.
+
+The optional argument Y_LIMIT, if non-nil, specifies the maximum text
+height that can be returned.  Text lines whose y-coordinate is beyond
+Y_LIMIT are ignored.  Since calculating the text height of a large
+buffer can take some time, it makes sense to specify this argument if
+the size of the buffer is unknown.
+
+Optional argument MODE_AND_HEADER_LINE nil or omitted means do not
+include the height of the mode- or header-line of WINDOW in the return
+value.  If it is either the symbol `mode-line' or `header-line', include
+only the height of that line, if present, in the return value.  If t,
+include the height of any of these lines in the return value.  */)
+  (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
+   Lisp_Object mode_and_header_line)
+{
+  struct window *w = decode_live_window (window);
+  Lisp_Object buf, value;
+  struct buffer *b;
+  struct it it;
+  struct buffer *old_buffer = NULL;
+  ptrdiff_t start, end, pos;
+  struct text_pos startp, endp;
+  void *itdata = NULL;
+  int c, max_y = -1, x = 0, y = 0;
+
+  buf = w->contents;
+  CHECK_BUFFER (buf);
+  b = XBUFFER (buf);
+
+  if (b != current_buffer)
+    {
+      old_buffer = current_buffer;
+      set_buffer_internal (b);
+    }
+
+  if (NILP (from))
+    start = BEGV;
+  else if (EQ (from, Qt))
+    {
+      start = pos = BEGV;
+      while ((pos++ < ZV) && (c = FETCH_CHAR (pos))
+            && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+       start = pos;
+      while ((pos-- > BEGV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+       start = pos;
+    }
+  else
+    {
+      CHECK_NUMBER_COERCE_MARKER (from);
+      start = min (max (XINT (from), BEGV), ZV);
+    }
+
+  if (NILP (to))
+    end = ZV;
+  else if (EQ (to, Qt))
+    {
+      end = pos = ZV;
+      while ((pos-- > BEGV) && (c = FETCH_CHAR (pos))
+            && (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
+       end = pos;
+      while ((pos++ < ZV) && (c = FETCH_CHAR (pos)) && (c == ' ' || c == '\t'))
+       end = pos;
+    }
+  else
+    {
+      CHECK_NUMBER_COERCE_MARKER (to);
+      end = max (start, min (XINT (to), ZV));
+    }
+
+  if (!NILP (y_limit))
+    {
+      CHECK_NUMBER (y_limit);
+      max_y = XINT (y_limit);
+    }
+
+  itdata = bidi_shelve_cache ();
+  SET_TEXT_POS (startp, start, CHAR_TO_BYTE (start));
+  start_display (&it, w, startp);
+
+  /**   move_it_vertically_backward (&it, 0); **/
+  if (NILP (x_limit))
+    x = move_it_to (&it, end, -1, max_y, -1, MOVE_TO_POS | MOVE_TO_Y);
+  else
+    {
+      CHECK_NUMBER (x_limit);
+      it.last_visible_x = XINT (x_limit);
+      /* Actually, we never want move_it_to stop at to_x.  But to make
+        sure that move_it_in_display_line_to always moves far enough,
+        we set it to INT_MAX and specify MOVE_TO_X.  */
+      x = move_it_to (&it, end, INT_MAX, max_y, -1,
+                     MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
+    }
+
+  if (start == end)
+    y = it.current_y;
+  else
+    {
+      /* Count last line.  */
+      last_height = 0;
+      y = line_bottom_y (&it); /* - y; */
+    }
+
+  if (!EQ (mode_and_header_line, Qheader_line)
+      && !EQ (mode_and_header_line, Qt))
+    /* Do not count the header-line which was counted automatically by
+       start_display.  */
+    y = y - WINDOW_HEADER_LINE_HEIGHT (w);
+
+  if (EQ (mode_and_header_line, Qmode_line)
+      || EQ (mode_and_header_line, Qt))
+    /* Do count the mode-line which is not included automatically by
+       start_display.  */
+    y = y + WINDOW_MODE_LINE_HEIGHT (w);
+
+  bidi_unshelve_cache (itdata, 0);
+
+  if (old_buffer)
+    set_buffer_internal (old_buffer);
+
+  return Fcons (make_number (x), make_number (y));
+}
 \f
 /***********************************************************************
                               Messages
@@ -10447,11 +10613,10 @@ resize_mini_window (struct window *w, int exact_p)
   if (!FRAME_MINIBUF_ONLY_P (f))
     {
       struct it it;
-      struct window *root = XWINDOW (FRAME_ROOT_WINDOW (f));
-      int total_height = WINDOW_TOTAL_LINES (root) + WINDOW_TOTAL_LINES (w);
-      int height;
-      EMACS_INT max_height;
+      int total_height = (WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_ROOT_WINDOW (f)))
+                         + WINDOW_PIXEL_HEIGHT (w));
       int unit = FRAME_LINE_HEIGHT (f);
+      int height, max_height;
       struct text_pos start;
       struct buffer *old_current_buffer = NULL;
 
@@ -10465,18 +10630,18 @@ resize_mini_window (struct window *w, int exact_p)
 
       /* Compute the max. number of lines specified by the user.  */
       if (FLOATP (Vmax_mini_window_height))
-       max_height = XFLOATINT (Vmax_mini_window_height) * FRAME_LINES (f);
+       max_height = XFLOATINT (Vmax_mini_window_height) * total_height;
       else if (INTEGERP (Vmax_mini_window_height))
-       max_height = XINT (Vmax_mini_window_height);
+       max_height = XINT (Vmax_mini_window_height) * unit;
       else
        max_height = total_height / 4;
 
       /* Correct that max. height if it's bogus.  */
-      max_height = clip_to_bounds (1, max_height, total_height);
+      max_height = clip_to_bounds (unit, max_height, total_height);
 
       /* Find out the height of the text in the window.  */
       if (it.line_wrap == TRUNCATE)
-       height = 1;
+       height = unit;
       else
        {
          last_height = 0;
@@ -10486,7 +10651,6 @@ resize_mini_window (struct window *w, int exact_p)
          else
            height = it.current_y + it.max_ascent + it.max_descent;
          height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
-         height = (height + unit - 1) / unit;
        }
 
       /* Compute a suitable window start.  */
@@ -10494,7 +10658,7 @@ resize_mini_window (struct window *w, int exact_p)
        {
          height = max_height;
          init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
-         move_it_vertically_backward (&it, (height - 1) * unit);
+         move_it_vertically_backward (&it, height);
          start = it.current.pos;
        }
       else
@@ -10505,49 +10669,49 @@ resize_mini_window (struct window *w, int exact_p)
        {
          /* Let it grow only, until we display an empty message, in which
             case the window shrinks again.  */
-         if (height > WINDOW_TOTAL_LINES (w))
+         if (height > WINDOW_PIXEL_HEIGHT (w))
            {
-             int old_height = WINDOW_TOTAL_LINES (w);
+             int old_height = WINDOW_PIXEL_HEIGHT (w);
 
              FRAME_WINDOWS_FROZEN (f) = 1;
-             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
-             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+             grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+             window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
            }
-         else if (height < WINDOW_TOTAL_LINES (w)
+         else if (height < WINDOW_PIXEL_HEIGHT (w)
                   && (exact_p || BEGV == ZV))
            {
-             int old_height = WINDOW_TOTAL_LINES (w);
+             int old_height = WINDOW_PIXEL_HEIGHT (w);
 
              FRAME_WINDOWS_FROZEN (f) = 0;
-             shrink_mini_window (w);
-             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+             shrink_mini_window (w, 1);
+             window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
            }
        }
       else
        {
          /* Always resize to exact size needed.  */
-         if (height > WINDOW_TOTAL_LINES (w))
+         if (height > WINDOW_PIXEL_HEIGHT (w))
            {
-             int old_height = WINDOW_TOTAL_LINES (w);
+             int old_height = WINDOW_PIXEL_HEIGHT (w);
 
              FRAME_WINDOWS_FROZEN (f) = 1;
-             grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
-             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+             grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
+             window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
            }
-         else if (height < WINDOW_TOTAL_LINES (w))
+         else if (height < WINDOW_PIXEL_HEIGHT (w))
            {
-             int old_height = WINDOW_TOTAL_LINES (w);
+             int old_height = WINDOW_PIXEL_HEIGHT (w);
 
              FRAME_WINDOWS_FROZEN (f) = 0;
-             shrink_mini_window (w);
+             shrink_mini_window (w, 1);
 
              if (height)
                {
                  FRAME_WINDOWS_FROZEN (f) = 1;
-                 grow_mini_window (w, height - WINDOW_TOTAL_LINES (w));
+                 grow_mini_window (w, height - WINDOW_PIXEL_HEIGHT (w), 1);
                }
 
-             window_height_changed_p = WINDOW_TOTAL_LINES (w) != old_height;
+             window_height_changed_p = WINDOW_PIXEL_HEIGHT (w) != old_height;
            }
        }
 
@@ -11501,8 +11665,8 @@ update_tool_bar (struct frame *f, int save_match_data)
 #if defined (USE_GTK) || defined (HAVE_NS)
   int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
 #else
-  int do_update = WINDOWP (f->tool_bar_window)
-    && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0;
+  int do_update = (WINDOWP (f->tool_bar_window)
+                  && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0);
 #endif
 
   if (do_update)
@@ -11884,7 +12048,8 @@ display_tool_bar_line (struct it *it, int height)
 }
 
 
-/* Max tool-bar height.  */
+/* Max tool-bar height.  Basically, this is what makes all other windows
+   disappear when the frame gets too small.  Rethink this!  */
 
 #define MAX_FRAME_TOOL_BAR_HEIGHT(f) \
   ((FRAME_LINE_HEIGHT (f) * FRAME_LINES (f)))
@@ -11894,11 +12059,11 @@ display_tool_bar_line (struct it *it, int height)
    returned in *N_ROWS if non-NULL.  */
 
 static int
-tool_bar_lines_needed (struct frame *f, int *n_rows)
+tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
 {
   struct window *w = XWINDOW (f->tool_bar_window);
   struct it it;
-  /* tool_bar_lines_needed is called from redisplay_tool_bar after building
+  /* tool_bar_height is called from redisplay_tool_bar after building
      the desired matrix, so use (unused) mode-line row as temporary row to
      avoid destroying the first tool-bar row.  */
   struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
@@ -11907,6 +12072,7 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
      F->desired_tool_bar_string in the tool-bar window of frame F.  */
   init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
+  /* PXW: Use FRAME_PIXEL_WIDTH (f) here ?  */
   it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
   reseat_to_string (&it, NULL, f->desired_tool_bar_string, 0, 0, 0, -1);
   it.paragraph_embedding = L2R;
@@ -11923,7 +12089,10 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
   if (n_rows)
     *n_rows = it.vpos > 0 ? it.vpos : -1;
 
-  return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
+  if (pixelwise)
+    return it.current_y;
+  else
+    return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
 }
 
 #endif /* !USE_GTK && !HAVE_NS */
@@ -11932,30 +12101,30 @@ tool_bar_lines_needed (struct frame *f, int *n_rows)
 EXFUN (Ftool_bar_lines_needed, 1) ATTRIBUTE_CONST;
 #endif
 
-DEFUN ("tool-bar-lines-needed", Ftool_bar_lines_needed, Stool_bar_lines_needed,
-       0, 1, 0,
+DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
+       0, 2, 0,
        doc: /* Return the number of lines occupied by the tool bar of FRAME.
-If FRAME is nil or omitted, use the selected frame.  */)
-  (Lisp_Object frame)
+If FRAME is nil or omitted, use the selected frame.  Optional argument
+PIXELWISE non-nil means return the height of the tool bar inpixels.  */)
+  (Lisp_Object frame, Lisp_Object pixelwise)
 {
-  int nlines = 0;
-#if ! defined (USE_GTK) && ! defined (HAVE_NS)
   struct frame *f = decode_any_frame (frame);
-  struct window *w;
+  int height = 0;
 
+#if ! defined (USE_GTK) && ! defined (HAVE_NS)
   if (WINDOWP (f->tool_bar_window)
-      && (w = XWINDOW (f->tool_bar_window),
-         WINDOW_TOTAL_LINES (w) > 0))
+      && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
     {
       update_tool_bar (f, 1);
       if (f->n_tool_bar_items)
        {
          build_desired_tool_bar_string (f);
-         nlines = tool_bar_lines_needed (f, NULL);
+         height = tool_bar_height (f, NULL, NILP (pixelwise) ? 0 : 1);
        }
     }
 #endif
-  return make_number (nlines);
+
+  return make_number (height);
 }
 
 
@@ -11983,13 +12152,13 @@ redisplay_tool_bar (struct frame *f)
      can turn off tool-bars by specifying tool-bar-lines zero.  */
   if (!WINDOWP (f->tool_bar_window)
       || (w = XWINDOW (f->tool_bar_window),
-          WINDOW_TOTAL_LINES (w) == 0))
+          WINDOW_PIXEL_HEIGHT (w) == 0))
     return 0;
 
   /* Set up an iterator for the tool-bar window.  */
   init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
   it.first_visible_x = 0;
-  it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
+  it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
   row = it.glyph_row;
 
   /* Build a string that represents the contents of the tool-bar.  */
@@ -12006,24 +12175,22 @@ redisplay_tool_bar (struct frame *f)
 
   if (f->n_tool_bar_rows == 0)
     {
-      int nlines;
+      int new_height = tool_bar_height (f, &f->n_tool_bar_rows, 1);
 
-      if ((nlines = tool_bar_lines_needed (f, &f->n_tool_bar_rows),
-          nlines != WINDOW_TOTAL_LINES (w)))
+      if (new_height != WINDOW_PIXEL_HEIGHT (w))
        {
          Lisp_Object frame;
-         int old_height = WINDOW_TOTAL_LINES (w);
+         int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+                          / FRAME_LINE_HEIGHT (f));
 
          XSETFRAME (frame, f);
          Fmodify_frame_parameters (frame,
                                    list1 (Fcons (Qtool_bar_lines,
-                                                 make_number (nlines))));
-         if (WINDOW_TOTAL_LINES (w) != old_height)
-           {
-             clear_glyph_matrix (w->desired_matrix);
-             f->fonts_changed = 1;
-             return 1;
-           }
+                                                 make_number (new_lines))));
+         /* Always do that now.  */
+         clear_glyph_matrix (w->desired_matrix);
+         f->fonts_changed = 1;
+         return 1;
        }
     }
 
@@ -12072,6 +12239,7 @@ redisplay_tool_bar (struct frame *f)
 
   if (!NILP (Vauto_resize_tool_bars))
     {
+      /* Do we really allow the toolbar to occupy the whole frame?  */
       int max_tool_bar_height = MAX_FRAME_TOOL_BAR_HEIGHT (f);
       int change_height_p = 0;
 
@@ -12102,29 +12270,29 @@ redisplay_tool_bar (struct frame *f)
       if (change_height_p)
        {
          Lisp_Object frame;
-         int old_height = WINDOW_TOTAL_LINES (w);
          int nrows;
-         int nlines = tool_bar_lines_needed (f, &nrows);
+         int new_height = tool_bar_height (f, &nrows, 1);
 
          change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
                              && !f->minimize_tool_bar_window_p)
-                            ? (nlines > old_height)
-                            : (nlines != old_height));
+                            ? (new_height > WINDOW_PIXEL_HEIGHT (w))
+                            : (new_height != WINDOW_PIXEL_HEIGHT (w)));
          f->minimize_tool_bar_window_p = 0;
 
          if (change_height_p)
            {
+             int new_lines = ((new_height + FRAME_LINE_HEIGHT (f) - 1)
+                              / FRAME_LINE_HEIGHT (f));
+
              XSETFRAME (frame, f);
              Fmodify_frame_parameters (frame,
                                        list1 (Fcons (Qtool_bar_lines,
-                                                     make_number (nlines))));
-             if (WINDOW_TOTAL_LINES (w) != old_height)
-               {
-                 clear_glyph_matrix (w->desired_matrix);
-                 f->n_tool_bar_rows = nrows;
-                 f->fonts_changed = 1;
-                 return 1;
-               }
+                                                     make_number (new_lines))));
+             /* Always do that now.  */
+             clear_glyph_matrix (w->desired_matrix);
+             f->n_tool_bar_rows = nrows;
+             f->fonts_changed = 1;
+             return 1;
            }
        }
     }
@@ -13323,6 +13491,8 @@ redisplay_internal (void)
               PT == w->last_point
               /* Make sure the cursor was last displayed
                  in this window.  Otherwise we have to reposition it.  */
+
+              /* PXW: Must be pixelized, probably.  */
               && 0 <= w->cursor.vpos
               && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
        {
@@ -14926,6 +15096,7 @@ compute_window_start_on_continuation_line (struct window *w)
       /* If the line start is "too far" away from the window start,
          say it takes too much time to compute a new window start.  */
       if (CHARPOS (start_pos) - IT_CHARPOS (it)
+         /* PXW: Do we need upper bounds here ?  */
          < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w))
        {
          int min_distance, distance;
@@ -16220,7 +16391,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
            redisplay_tool_bar (f);
 #else
          if (WINDOWP (f->tool_bar_window)
-             && (FRAME_TOOL_BAR_LINES (f) > 0
+             && (FRAME_TOOL_BAR_HEIGHT (f) > 0
                  || !NILP (Vauto_resize_tool_bars))
              && redisplay_tool_bar (f))
            ignore_mouse_drag_p = 1;
@@ -16238,10 +16409,18 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
       update_begin (f);
       block_input ();
       if (draw_window_fringes (w, 1))
-       x_draw_vertical_border (w);
+       {
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+       }
       unblock_input ();
       update_end (f);
     }
+
+  if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+    x_draw_bottom_divider (w);
 #endif /* HAVE_WINDOW_SYSTEM */
 
   /* We go to this label, with fonts_changed set, if it is
@@ -20544,6 +20723,7 @@ display_menu_bar (struct window *w)
   eassert (!FRAME_WINDOW_P (f));
   init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
   it.first_visible_x = 0;
+  /* PXW: Use FRAME_PIXEL_WIDTH (f) here ?  */
   it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
 #elif defined (HAVE_X_WINDOWS) /* X without toolkit.  */
   if (FRAME_WINDOW_P (f))
@@ -20555,6 +20735,7 @@ display_menu_bar (struct window *w)
       init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
                     MENU_FACE_ID);
       it.first_visible_x = 0;
+      /* PXW: Use FRAME_PIXEL_WIDTH (f) here ?  */
       it.last_visible_x = FRAME_TOTAL_COLS (f) * FRAME_COLUMN_WIDTH (f);
     }
   else
@@ -23929,7 +24110,8 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
       /* X is relative to the left edge of W, without scroll bars
         or fringes.  */
       area_left = WINDOW_LEFT_EDGE_X (w);
-      last_x = WINDOW_LEFT_EDGE_X (w) + WINDOW_TOTAL_WIDTH (w);
+      last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
+               - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
     }
   else
     {
@@ -25967,7 +26149,8 @@ x_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
   f = XFRAME (w->frame);
 
   if (updated_row->full_width_p)
-    max_x = WINDOW_TOTAL_WIDTH (w);
+    max_x = (WINDOW_PIXEL_WIDTH (w)
+            - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
   else
     max_x = window_box_width (w, updated_area);
   max_y = window_text_bottom_y (w);
@@ -27811,6 +27994,8 @@ define_frame_cursor1 (struct frame *f, Cursor cursor, Lisp_Object pointer)
        cursor = FRAME_X_OUTPUT (f)->text_cursor;
       else if (EQ (pointer, intern ("hdrag")))
        cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+      else if (EQ (pointer, intern ("nhdrag")))
+       cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
 #ifdef HAVE_X_WINDOWS
       else if (EQ (pointer, intern ("vdrag")))
        cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
@@ -28224,6 +28409,16 @@ note_mouse_highlight (struct frame *f, int x, int y)
       cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
       help_echo_string = build_string ("drag-mouse-1: resize");
     }
+  else if (part == ON_RIGHT_DIVIDER)
+    {
+      cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
+      help_echo_string = build_string ("drag-mouse-1: resize");
+    }
+  else if (part == ON_BOTTOM_DIVIDER)
+    {
+      cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
+      help_echo_string = build_string ("drag-mouse-1: resize");
+    }
   else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
           || part == ON_SCROLL_BAR)
     cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -28864,7 +29059,7 @@ x_draw_vertical_border (struct window *w)
      do it for frames with vertical scroll bars because either the
      right scroll bar of a window, or the left scroll bar of its
      neighbor will suffice as a border.  */
-  if (FRAME_HAS_VERTICAL_SCROLL_BARS (XFRAME (w->frame)))
+  if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
     return;
 
   /* Note: It is necessary to redraw both the left and the right
@@ -28883,6 +29078,7 @@ x_draw_vertical_border (struct window *w)
 
       FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
     }
+
   if (!WINDOW_LEFTMOST_P (w)
       && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
     {
@@ -28899,6 +29095,44 @@ x_draw_vertical_border (struct window *w)
 }
 
 
+/* Draw window dividers for window W.  */
+
+void
+x_draw_right_divider (struct window *w)
+{
+  struct frame *f = WINDOW_XFRAME (w);
+
+  if (w->mini || w->pseudo_window_p)
+    return;
+  else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+    {
+      int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
+      int x1 = WINDOW_RIGHT_EDGE_X (w);
+      int y0 = WINDOW_TOP_EDGE_Y (w);
+      int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+
+      FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+    }
+}
+
+void
+x_draw_bottom_divider (struct window *w)
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+
+  if (w->mini || w->pseudo_window_p)
+    return;
+  else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+    {
+      int x0 = WINDOW_LEFT_EDGE_X (w);
+      int x1 = WINDOW_RIGHT_EDGE_X (w);
+      int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
+      int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+
+      FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
+    }
+}
+
 /* Redraw the part of window W intersection rectangle FR.  Pixel
    coordinates in FR are frame-relative.  Call this function with
    input blocked.  Value is non-zero if the exposure overwrites
@@ -28930,8 +29164,8 @@ expose_window (struct window *w, XRectangle *fr)
   /* Frame-relative pixel rectangle of W.  */
   wr.x = WINDOW_LEFT_EDGE_X (w);
   wr.y = WINDOW_TOP_EDGE_Y (w);
-  wr.width = WINDOW_TOTAL_WIDTH (w);
-  wr.height = WINDOW_TOTAL_HEIGHT (w);
+  wr.width = WINDOW_PIXEL_WIDTH (w);
+  wr.height = WINDOW_PIXEL_HEIGHT (w);
 
   if (x_intersect_rectangles (fr, &wr, &r))
     {
@@ -29027,7 +29261,13 @@ expose_window (struct window *w, XRectangle *fr)
                             fr);
 
          /* Draw border between windows.  */
-         x_draw_vertical_border (w);
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+
+         if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
+           x_draw_bottom_divider (w);
 
          /* Turn the cursor on again.  */
          if (cursor_cleared_p
@@ -29245,13 +29485,14 @@ syms_of_xdisp (void)
   defsubr (&Strace_to_stderr);
 #endif
 #ifdef HAVE_WINDOW_SYSTEM
-  defsubr (&Stool_bar_lines_needed);
+  defsubr (&Stool_bar_height);
   defsubr (&Slookup_image_map);
 #endif
   defsubr (&Sline_pixel_height);
   defsubr (&Sformat_mode_line);
   defsubr (&Sinvisible_p);
   defsubr (&Scurrent_bidi_paragraph_direction);
+  defsubr (&Swindow_text_pixel_size);
   defsubr (&Smove_point_visually);
 
   DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
@@ -29879,12 +30120,18 @@ init_xdisp (void)
       echo_area_window = minibuf_window;
 
       r->top_line = FRAME_TOP_MARGIN (f);
-      r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+      r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
       r->total_cols = FRAME_COLS (f);
+      r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
+      r->total_lines = FRAME_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
+      r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
 
       m->top_line = FRAME_LINES (f) - 1;
-      m->total_lines = 1;
+      m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
       m->total_cols = FRAME_COLS (f);
+      m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
+      m->total_lines = 1;
+      m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
 
       scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
       scratch_glyph_row.glyphs[TEXT_AREA + 1]
index b9ddddf..b6e0abc 100644 (file)
@@ -323,6 +323,7 @@ Lisp_Object Qheader_line, Qscroll_bar, Qcursor;
 static Lisp_Object Qborder, Qmouse, Qmenu;
 Lisp_Object Qmode_line_inactive;
 static Lisp_Object Qvertical_border;
+static Lisp_Object Qwindow_divider;
 
 /* The symbol `face-alias'.  A symbols having that property is an
    alias for another face.  Value of the property is the name of
@@ -5246,6 +5247,7 @@ realize_basic_faces (struct frame *f)
       realize_named_face (f, Qmouse, MOUSE_FACE_ID);
       realize_named_face (f, Qmenu, MENU_FACE_ID);
       realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
+      realize_named_face (f, Qwindow_divider, WINDOW_DIVIDER_FACE_ID);
 
       /* Reflect changes in the `menu' face in menu bars.  */
       if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
@@ -6448,6 +6450,7 @@ syms_of_xfaces (void)
   DEFSYM (Qmouse, "mouse");
   DEFSYM (Qmode_line_inactive, "mode-line-inactive");
   DEFSYM (Qvertical_border, "vertical-border");
+  DEFSYM (Qwindow_divider, "window-divider");
   DEFSYM (Qtty_color_desc, "tty-color-desc");
   DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
   DEFSYM (Qtty_color_by_index, "tty-color-by-index");
index 46f3770..bd4a6a6 100644 (file)
@@ -612,7 +612,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
   struct x_output *x = f->output_data.x;
   Display *dpy = FRAME_X_DISPLAY (f);
   Cursor cursor, nontext_cursor, mode_cursor, hand_cursor;
-  Cursor hourglass_cursor, horizontal_drag_cursor;
+  Cursor hourglass_cursor, horizontal_drag_cursor, vertical_drag_cursor;
   unsigned long pixel = x_decode_color (f, arg, BLACK_PIX_DEFAULT (f));
   unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f);
 
@@ -688,6 +688,16 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     horizontal_drag_cursor
       = XCreateFontCursor (dpy, XC_sb_h_double_arrow);
 
+  if (!NILP (Vx_window_vertical_drag_shape))
+    {
+      CHECK_NUMBER (Vx_window_vertical_drag_shape);
+      vertical_drag_cursor
+       = XCreateFontCursor (dpy, XINT (Vx_window_vertical_drag_shape));
+    }
+  else
+    vertical_drag_cursor
+      = XCreateFontCursor (dpy, XC_sb_v_double_arrow);
+
   /* Check and report errors with the above calls.  */
   x_check_errors (dpy, "can't set cursor shape: %s");
   x_uncatch_errors ();
@@ -745,6 +755,11 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
     XFreeCursor (dpy, x->horizontal_drag_cursor);
   x->horizontal_drag_cursor = horizontal_drag_cursor;
 
+  if (vertical_drag_cursor != x->vertical_drag_cursor
+      && x->vertical_drag_cursor != 0)
+    XFreeCursor (dpy, x->vertical_drag_cursor);
+  x->vertical_drag_cursor = vertical_drag_cursor;
+
   XFlush (dpy);
   unblock_input ();
 
@@ -963,6 +978,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   FRAME_MENU_BAR_LINES (f) = 0;
+  FRAME_MENU_BAR_HEIGHT (f) = 0;
   if (nlines)
     {
       FRAME_EXTERNAL_MENU_BAR (f) = 1;
@@ -980,7 +996,8 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 #else /* not USE_X_TOOLKIT && not USE_GTK */
   FRAME_MENU_BAR_LINES (f) = nlines;
-  resize_frame_windows (f, FRAME_LINES (f), 0);
+  FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
+  resize_frame_windows (f, FRAME_LINES (f), 0, 0);
 
   /* If the menu bar height gets changed, the internal border below
      the top margin has to be cleared.  Also, if the menu bar gets
@@ -993,7 +1010,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
       int y;
 
       /* height can be zero here. */
-      if (height > 0 && width > 0)
+      if (FRAME_X_WINDOW (f) && height > 0 && width > 0)
        {
          y = FRAME_TOP_MARGIN_HEIGHT (f);
 
@@ -1051,6 +1068,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
 #ifdef USE_GTK
 
   FRAME_TOOL_BAR_LINES (f) = 0;
+  FRAME_TOOL_BAR_HEIGHT (f) = 0;
   if (nlines)
     {
       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
@@ -1083,7 +1101,8 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
     }
 
   FRAME_TOOL_BAR_LINES (f) = nlines;
-  resize_frame_windows (f, FRAME_LINES (f), 0);
+  FRAME_TOOL_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
+  resize_frame_windows (f, FRAME_LINES (f), 0, 0);
   adjust_frame_glyphs (f);
 
   /* We also have to make sure that the internal border at the top of
@@ -1092,7 +1111,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
      below the tool bar if one is displayed, but is below the menu bar
      if there isn't a tool bar.  The tool bar draws into the area
      below the menu bar.  */
-  if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_LINES (f) == 0)
+  if (FRAME_X_WINDOW (f) && FRAME_TOOL_BAR_HEIGHT (f) == 0)
     {
       clear_frame (f);
       clear_current_matrices (f);
@@ -1471,13 +1490,13 @@ x_set_scroll_bar_default_width (struct frame *f)
   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (minw + wid - 1) / wid;
   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = minw;
 #else
-  /* Make the actual width at least 14 pixels and a multiple of a
+  /* Make the actual width 16 pixels and a multiple of a
      character width.  */
-  FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
+  FRAME_CONFIG_SCROLL_BAR_COLS (f) = (16 + wid - 1) / wid;
 
   /* Use all of that space (aside from required margins) for the
      scroll bar.  */
-  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 0;
+  FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 16;
 #endif
 }
 
@@ -3130,12 +3149,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
   /* Dimensions, especially FRAME_LINES (f), must be done via change_frame_size.
      Change will not be effected unless different from the current
      FRAME_LINES (f).  */
-  width = FRAME_COLS (f);
-  height = FRAME_LINES (f);
-
-  SET_FRAME_COLS (f, 0);
-  FRAME_LINES (f) = 0;
-  change_frame_size (f, height, width, 1, 0, 0);
+  width = FRAME_TEXT_WIDTH (f);
+  height = FRAME_TEXT_HEIGHT (f);
+  FRAME_TEXT_HEIGHT (f) = 0;
+  SET_FRAME_WIDTH (f, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 1);
 
 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
   /* Create the menu bar.  */
@@ -4918,6 +4936,10 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   x_default_parameter (f, parms, Qinternal_border_width, make_number (1),
                       "internalBorderWidth", "internalBorderWidth",
                       RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qright_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
 
   /* Also do the stuff which must be set before the window exists.  */
   x_default_parameter (f, parms, Qforeground_color, build_string ("black"),
@@ -5000,7 +5022,7 @@ x_create_tip_frame (struct x_display_info *dpyinfo,
   height = FRAME_LINES (f);
   SET_FRAME_COLS (f, 0);
   FRAME_LINES (f) = 0;
-  change_frame_size (f, height, width, 1, 0, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 0);
 
   /* Add `tooltip' frame parameter's default value. */
   if (NILP (Fframe_parameter (frame, Qtooltip)))
@@ -5260,6 +5282,10 @@ Text larger than the specified size is clipped.  */)
     parms = Fcons (Fcons (Qinternal_border_width, make_number (3)), parms);
   if (NILP (Fassq (Qborder_width, parms)))
     parms = Fcons (Fcons (Qborder_width, make_number (1)), parms);
+  if (NILP (Fassq (Qbottom_divider_width, parms)))
+    parms = Fcons (Fcons (Qbottom_divider_width, make_number (0)), parms);
+  if (NILP (Fassq (Qright_divider_width, parms)))
+    parms = Fcons (Fcons (Qright_divider_width, make_number (0)), parms);
   if (NILP (Fassq (Qborder_color, parms)))
     parms = Fcons (Fcons (Qborder_color, build_string ("lightyellow")), parms);
   if (NILP (Fassq (Qbackground_color, parms)))
@@ -5275,6 +5301,8 @@ Text larger than the specified size is clipped.  */)
   w = XWINDOW (FRAME_ROOT_WINDOW (f));
   w->left_col = 0;
   w->top_line = 0;
+  w->pixel_left = 0;
+  w->pixel_top = 0;
 
   if (CONSP (Vx_max_tooltip_size)
       && RANGED_INTEGERP (1, XCAR (Vx_max_tooltip_size), INT_MAX)
@@ -5289,6 +5317,9 @@ Text larger than the specified size is clipped.  */)
       w->total_lines = 40;
     }
 
+  w->pixel_width = w->total_cols * FRAME_COLUMN_WIDTH (f);
+  w->pixel_height = w->total_lines * FRAME_LINE_HEIGHT (f);
+
   FRAME_TOTAL_COLS (f) = w->total_cols;
   adjust_frame_glyphs (f);
   w->pseudo_window_p = 1;
@@ -5355,9 +5386,11 @@ Text larger than the specified size is clipped.  */)
     {
       /* w->total_cols and FRAME_TOTAL_COLS want the width in columns,
         not in pixels.  */
+      w->pixel_width = width;
       width /= WINDOW_FRAME_COLUMN_WIDTH (w);
       w->total_cols = width;
       FRAME_TOTAL_COLS (f) = width;
+      SET_FRAME_WIDTH (f, width);
       adjust_frame_glyphs (f);
       clear_glyph_matrix (w->desired_matrix);
       clear_glyph_matrix (w->current_matrix);
@@ -5958,6 +5991,8 @@ frame_parm_handler x_frame_parm_handlers[] =
   x_set_icon_name,
   x_set_icon_type,
   x_set_internal_border_width,
+  x_set_right_divider_width,
+  x_set_bottom_divider_width,
   x_set_menu_bar_lines,
   x_set_mouse_color,
   x_explicitly_set_name,
@@ -6041,6 +6076,13 @@ This variable takes effect when you create a new frame
 or when you set the mouse color.  */);
   Vx_window_horizontal_drag_shape = Qnil;
 
+  DEFVAR_LISP ("x-window-vertical-drag-cursor",
+             Vx_window_vertical_drag_shape,
+  doc: /* Pointer shape to use for indicating a window can be dragged vertically.
+This variable takes effect when you create a new frame
+or when you set the mouse color.  */);
+  Vx_window_vertical_drag_shape = Qnil;
+
   DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
     doc: /* A string indicating the foreground color of the cursor box.  */);
   Vx_cursor_fore_pixel = Qnil;
index cdc63cb..d587610 100644 (file)
@@ -1168,7 +1168,7 @@ free_frame_menubar (struct frame *f)
          if (x1 == 0 && y1 == 0)
            XtVaSetValues (f->output_data.x->widget, XtNx, x0, XtNy, y0, NULL);
 #endif
-          x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+         x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
        }
       unblock_input ();
     }
index e80212a..46419ae 100644 (file)
@@ -214,7 +214,7 @@ enum xembed_message
   };
 
 static bool x_alloc_nearest_color_1 (Display *, Colormap, XColor *);
-static void x_set_window_size_1 (struct frame *, int, int, int);
+static void x_set_window_size_1 (struct frame *, int, int, int, bool);
 static void x_raise_frame (struct frame *);
 static void x_lower_frame (struct frame *);
 static const XColor *x_color_cells (Display *, int *);
@@ -509,6 +509,23 @@ x_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
             f->output_data.x->normal_gc, x, y0, x, y1);
 }
 
+/* Draw a window divider from (x0,y0) to (x1,y1)  */
+
+static void
+x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+{
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct face *face;
+
+  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  if (face)
+    XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
+                   face->foreground);
+
+  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
+                 f->output_data.x->normal_gc, x0, y0, x1 - x0, y1 - y0);
+}
+
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
@@ -536,7 +553,12 @@ x_update_window_end (struct window *w, bool cursor_on_p,
                                w->output_cursor.x, w->output_cursor.y);
 
       if (draw_window_fringes (w, 1))
-       x_draw_vertical_border (w);
+       {
+         if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+           x_draw_right_divider (w);
+         else
+           x_draw_vertical_border (w);
+       }
 
       unblock_input ();
     }
@@ -658,8 +680,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fring
          if (sb_width > 0)
            {
              int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-             int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                                   * FRAME_COLUMN_WIDTH (f));
+             int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
 
              if (bx < 0)
                {
@@ -3121,8 +3142,7 @@ x_scroll_run (struct window *w, struct run *run)
       if (sb_width > 0)
        {
          int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w);
-         int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w)
-                               * FRAME_COLUMN_WIDTH (f));
+         int bar_area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
 
          if (bar_area_x + bar_area_width == x)
            {
@@ -4945,7 +4965,7 @@ x_scroll_bar_create (struct window *w, int top, int left, int width, int height)
     /* Clear the area of W that will serve as a scroll bar.  This is
        for the case that a window has been split horizontally.  In
        this case, no clear_frame is generated to reduce flickering.  */
-    if (width > 0 && height > 0)
+    if (width > 0 && window_box_height (w) > 0)
       x_clear_area (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
                    left, top, width, window_box_height (w));
 
@@ -5156,7 +5176,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
   /* Get window dimensions.  */
   window_box (w, ANY_AREA, 0, &window_y, 0, &window_height);
   top = window_y;
-  width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
+  width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
   height = window_height;
 
   /* Compute the left edge of the scroll bar area.  */
@@ -5203,7 +5223,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
          unblock_input ();
        }
 
-      bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
+      bar = x_scroll_bar_create (w, top, sb_left, sb_width, max (height, 1));
     }
   else
     {
@@ -5254,7 +5274,7 @@ XTset_vertical_scroll_bar (struct window *w, int portion, int whole, int positio
         previous mode line display is cleared after C-x 2 C-x 1, for
         example.  */
       {
-       int area_width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
+       int area_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
        int rest = area_width - sb_width;
        if (rest > 0 && height > 0)
          {
@@ -6722,8 +6742,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
         {
 #ifndef USE_X_TOOLKIT
 #ifndef USE_GTK
-          int rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, event->xconfigure.height);
-          int columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, event->xconfigure.width);
+          int width = FRAME_PIXEL_TO_TEXT_WIDTH (f, event->xconfigure.width);
+          int height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, event->xconfigure.height);
 
           /* In the toolkit version, change_frame_size
              is called by the code that handles resizing
@@ -6732,12 +6752,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
           /* Even if the number of character rows and columns has
              not changed, the font size may have changed, so we need
              to check the pixel dimensions as well.  */
-          if (columns != FRAME_COLS (f)
-              || rows != FRAME_LINES (f)
+          if (width != FRAME_TEXT_WIDTH (f)
+              || height != FRAME_TEXT_HEIGHT (f)
               || event->xconfigure.width != FRAME_PIXEL_WIDTH (f)
               || event->xconfigure.height != FRAME_PIXEL_HEIGHT (f))
             {
-              change_frame_size (f, rows, columns, 0, 1, 0);
+              change_frame_size (f, width, height, 0, 1, 0, 1);
               SET_FRAME_GARBAGED (f);
               cancel_mouse_face (f);
             }
@@ -7822,12 +7842,15 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
   if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
     {
       int wid = FRAME_COLUMN_WIDTH (f);
+
       FRAME_CONFIG_SCROLL_BAR_COLS (f)
        = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
     }
   else
     {
       int wid = FRAME_COLUMN_WIDTH (f);
+
+      FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = 14;
       FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
     }
 
@@ -7837,7 +7860,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
         doing it because it's done in Fx_show_tip, and it leads to
         problems because the tip frame has no widget.  */
       if (NILP (tip_frame) || XFRAME (tip_frame) != f)
-        x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+       x_set_window_size (f, 0, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 1);
     }
 
 #ifdef HAVE_X_I18N
@@ -8652,11 +8675,11 @@ x_wait_for_event (struct frame *f, int eventtype)
    size changes.  Otherwise we leave the window gravity unchanged.  */
 
 static void
-x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size_1 (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
 {
   int pixelwidth, pixelheight;
 
-  check_frame_size (f, &rows, &cols);
+  check_frame_size (f, &width, &height, pixelwise);
   f->scroll_bar_actual_width
     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
        ? 0
@@ -8664,9 +8687,11 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
 
   compute_fringe_widths (f, 0);
 
-  pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols)
+  pixelwidth =
+    (pixelwise ? width : FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width))
     + FRAME_TOOLBAR_WIDTH (f);
-  pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows)
+  pixelheight =
+    (pixelwise ? height : FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height))
     + FRAME_MENUBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f);
 
   if (change_gravity) f->win_gravity = NorthWestGravity;
@@ -8702,7 +8727,7 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
     x_wait_for_event (f, ConfigureNotify);
   else
     {
-      change_frame_size (f, rows, cols, 0, 1, 0);
+      change_frame_size (f, width, height, 0, 1, 0, 1);
       FRAME_PIXEL_WIDTH (f) = pixelwidth;
       FRAME_PIXEL_HEIGHT (f) = pixelheight;
       x_sync (f);
@@ -8716,17 +8741,17 @@ x_set_window_size_1 (struct frame *f, int change_gravity, int cols, int rows)
    Otherwise we leave the window gravity unchanged.  */
 
 void
-x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
+x_set_window_size (struct frame *f, int change_gravity, int width, int height, bool pixelwise)
 {
   block_input ();
 
   if (NILP (tip_frame) || XFRAME (tip_frame) != f)
     {
-      int r, c;
+      int r, c, text_width, text_height;
 
       /* When the frame is maximized/fullscreen or running under for
          example Xmonad, x_set_window_size_1 will be a no-op.
-         In that case, the right thing to do is extend rows/cols to
+         In that case, the right thing to do is extend rows/width to
          the current frame size.  We do that first if x_set_window_size_1
          turns out to not be a no-op (there is no way to know).
          The size will be adjusted again if the frame gets a
@@ -8737,23 +8762,25 @@ x_set_window_size (struct frame *f, int change_gravity, int cols, int rows)
          is however.  */
       pixelh -= FRAME_MENUBAR_HEIGHT (f);
 #endif
+      text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, FRAME_PIXEL_WIDTH (f));
+      text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixelh);
       r = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelh);
       /* Update f->scroll_bar_actual_width because it is used in
          FRAME_PIXEL_WIDTH_TO_TEXT_COLS.  */
       f->scroll_bar_actual_width
         = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
       c = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, FRAME_PIXEL_WIDTH (f));
-      change_frame_size (f, r, c, 0, 1, 0);
+      change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
     }
 
 #ifdef USE_GTK
   if (FRAME_GTK_WIDGET (f))
-    xg_frame_set_char_size (f, cols, rows);
+    xg_frame_set_char_size (f, width, height);
   else
-    x_set_window_size_1 (f, change_gravity, cols, rows);
+    x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
 #else /* not USE_GTK */
 
-  x_set_window_size_1 (f, change_gravity, cols, rows);
+  x_set_window_size_1 (f, change_gravity, width, height, pixelwise);
 
 #endif /* not USE_GTK */
 
@@ -9439,7 +9466,7 @@ x_wm_set_size_hint (struct frame *f, long flags, bool user_position)
     base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
     base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
-    check_frame_size (f, &min_rows, &min_cols);
+    check_frame_size (f, &min_cols, &min_rows, 0);
 
     /* The window manager uses the base width hints to calculate the
        current number of rows and columns in the frame while
@@ -10352,6 +10379,7 @@ static struct redisplay_interface x_redisplay_interface =
     x_clear_frame_area,
     x_draw_window_cursor,
     x_draw_vertical_window_border,
+    x_draw_window_divider,
     x_shift_glyphs_for_insert
   };
 
index 89676e8..88a0ae7 100644 (file)
@@ -549,6 +549,7 @@ struct x_output
   Cursor hand_cursor;
   Cursor hourglass_cursor;
   Cursor horizontal_drag_cursor;
+  Cursor vertical_drag_cursor;
   Cursor current_cursor;
 
   /* Window whose cursor is hourglass_cursor.  This window is temporarily
@@ -930,7 +931,7 @@ extern void x_check_errors (Display *, const char *)
 extern bool x_had_errors_p (Display *);
 extern void x_uncatch_errors (void);
 extern void x_clear_errors (Display *);
-extern void x_set_window_size (struct frame *, int, int, int);
+extern void x_set_window_size (struct frame *, int, int, int, bool);
 extern void x_set_mouse_position (struct frame *, int, int);
 extern void x_set_mouse_pixel_position (struct frame *, int, int);
 extern void xembed_request_focus (struct frame *);