Subject: Re: bug#18357: 24.3.93; Calendar not fully displayed

From: martin rudalics <[email-masked]>
Date: Mon, 01 Sep 2014 11:18:52 +0200

The following is based on my scenario.  With emacs -Q evaluate the
following form

(progn
   (custom-set-faces
    '(mode-line ((t (:background "#000040" :foreground "wheat" :box (:line-width 2 :color "#000040") :weight bold :family "Verdana"))))
    '(mode-line-inactive ((t (:inherit mode-line :background "grey48" :foreground "wheat" :box (:line-width 2 :color "#000040"))))))
   (setq calendar-week-start-day 1)
   (calendar))

In `calendar' two interesting things happen.  The first one is a
`split-window-sensibly' call to set up the calendar window.  I've put a
breakpoint in estimate_mode_line_height giving the following backtrace
(the function estimate_window_mode_line_height works around the problem
to set a breakpoint exclusively for calls from CURRENT_MODE_LINE_HEIGHT,
the redefinitions appear below for anyone interested).

#0  estimate_mode_line_height (f=0x17ca658, face_id=MODE_LINE_INACTIVE_FACE_ID) at xdisp.c:1908
#1  0x0102406d in estimate_window_mode_line_height (w=0x4988718) at xdisp.c:1928
#2  0x010860f0 in Fwindow_mode_line_height (window=...) at window.c:1010
[...]
#87 0x010fa4f7 in main (argc=2, argv=0xa32808) at emacs.c:1645

Lisp Backtrace:
"window-mode-line-height" (0x82ae8c)
"window--min-size-1" (0x82b1b8)
"window-min-size" (0x82b4e8)
0x12a2bb8 PVEC_COMPILED
"walk-window-tree-1" (0x82bb48)
"walk-window-tree-1" (0x82be78)
"walk-window-tree" (0x82c1a8)
"window--sanitize-window-sizes" (0x82c4c8)
"byte-code" (0x82c760)
"split-window" (0x82cb68)
"split-window-below" (0x82cea8)
"split-window-sensibly" (0x82d1e4)
"funcall" (0x82d1e0)
"window--try-to-split-window" (0x82d668)
"display-buffer-pop-up-window" (0x82d998)
"display-buffer--maybe-pop-up-frame-or-window" (0x82dcb8)
"display-buffer" (0x82dff8)
"pop-to-buffer" (0x82e328)
"calendar-basic-setup" (0x82e658)
"calendar" (0x82e8f0)
"progn" (0x82eadc)
"eval" (0x82ebe0)
"eval-last-sexp-1" (0x82ef0c)
"eval-last-sexp" (0x82f338)
"funcall-interactively" (0x82f334)
"call-interactively" (0x82f550)
"command-execute" (0x82f890)
(gdb)

If I here print the value of the box_line_width of the
MODE_LINE_INACTIVE_FACE_ID I get:

(gdb) p face->box_line_width
$24 = -1

which is obviously not up to date given the specification I requested.
It's only during the next redisplay that the value of 2 is recognized
and applied:

#0  realize_x_face (cache=0xf94eb0, attrs=0x82d91c) at xfaces.c:5617
#1  0x010f1d25 in realize_face (cache=0xf94eb0, attrs=0x82d91c, former_face_id=1) at xfaces.c:5443
#2  0x010f1c4c in realize_named_face (f=0x17ca658, symbol=..., id=1) at xfaces.c:5414
#3  0x010f11b7 in realize_basic_faces (f=0x17ca658) at xfaces.c:5225
#4  0x010e7259 in recompute_basic_faces (f=0x17ca658) at xfaces.c:725
#5  0x0102ae1a in init_iterator (it=0x82da44, w=0x4988718, charpos=-1, bytepos=-1, row=0x0, base_face_id=DEFAULT_FACE_ID) at xdisp.c:2890
#6  0x010424de in x_consider_frame_title (frame=...) at xdisp.c:11623
#7  0x010428dd in prepare_menu_bars () at xdisp.c:11725
#8  0x01046b0b in redisplay_internal () at xdisp.c:13549
#9  0x0104590e in redisplay () at xdisp.c:13168
#10 0x010ff5e1 in read_char (commandflag=1, map=..., prev_event=..., used_mouse_menu=0x82f7ef, end_time=0x0) at keyboard.c:2590
#11 0x0110cf87 in read_key_sequence (keybuf=0x82f8e4, bufsize=30, prompt=..., dont_downcase_last=false, can_return_switch_frame=true, fix_current_buffer=true, prevent_redisplay=false) at keyboard.c:9152
#12 0x010fd149 in command_loop_1 () at keyboard.c:1462
#13 0x011891ce in internal_condition_case (bfun=0x10fcdc4 <command_loop_1>, handlers=..., hfun=0x10fc62f <cmd_error>) at eval.c:1347
#14 0x010fca7a in command_loop_2 (ignore=...) at keyboard.c:1193
#15 0x01188782 in internal_catch (tag=..., func=0x10fca56 <command_loop_2>, arg=...) at eval.c:1111
#16 0x010fca34 in command_loop () at keyboard.c:1172
#17 0x010fc1cb in recursive_edit_1 () at keyboard.c:782
#18 0x010fc388 in Frecursive_edit () at keyboard.c:853
#19 0x010fa4f7 in main (argc=2, argv=0xa32808) at emacs.c:1645

Lisp Backtrace:
"redisplay_internal (C function)" (0x205e398)
(gdb) p XINT (value)
$25 = 2
(gdb)

The second interesting thing happening in `calendar' is the call to
`fit-window-to-buffer'.  Since this call happens _between_ the two
backtraces reproduced above, it does not add the line-widths of the box
to the height of the mode line.  In the present case, the missing 4
pixels are responsible for (1) not making the calendar window high
enough and (2) scrolling the calendar window to move `point' out of the
scroll margin.

Obviously, putting in a `sit-for' before calling `calendar' realizes the
mode line face and the subsequential calls use the correct value.

I suppose that we should realize the mode line face whenever we call
estimate_mode_line_height but have no idea whether and how this can be
done.

martin

CURRENT_MODE_LINE_HEIGHT redefinitions.

#define CURRENT_MODE_LINE_HEIGHT(W)					\
   (W->mode_line_height >= 0						\
     ? W->mode_line_height						\
     : (W->mode_line_height						\
        = estimate_window_mode_line_height (W)))				\

int
estimate_window_mode_line_height (struct window *w)
{
   int x;

   if (MATRIX_MODE_LINE_HEIGHT (w->current_matrix))
     x = MATRIX_MODE_LINE_HEIGHT (w->current_matrix);
   else
     x = estimate_mode_line_height (XFRAME (w->frame), CURRENT_MODE_LINE_FACE_ID (w));

   return x;
}