Subject: Re: bug#18195: 24.3.92; window-screen-lines is not accurate

From: martin rudalics <[email-masked]>
Date: Tue, 05 Aug 2014 17:45:25 +0200

> You'll need to designate a window anyway, since layout is impossible
 > without knowing in which window it will be done.

`window-text-pixel-size' works on any life window, by default the
selected.

 > There's also the issue of the buffer text on which the text will be
 > overlaid: the dimensions of the screen lines to be (partially)
 > overlaid affect the pixel dimensions of the overlaying text.  So if
 > the buffer text uses different fonts, the text overlaid on it will
 > have different dimensions than the same text when displayed in its own
 > buffer.

This would have to be done on the Lisp level by selecting some font
before calculating the size of the overlay.  But I have problems with
the attached patch.  If I invoke `window-text-pixel-size' with a
different buffer than that displayed in the window I get an arguments
out of range error.  Any ideas?

martin

A backtrace goes as follows:

#0  args_out_of_range (a1=..., a2=...) at data.c:217
#1  0x011eadda in validate_interval_range (object=..., begin=0x82b310, end=0x82b310, force=false) at textprop.c:182
#2  0x011ec8a4 in Ftext_properties_at (position=..., object=...) at textprop.c:601
#3  0x011ec931 in Fget_text_property (position=..., prop=..., object=...) at textprop.c:621
#4  0x010f5806 in face_at_buffer_position (w=0x17b8bf8, pos=82, endptr=0x82b438, limit=182, mouse=0, base_face_id=0) at xfaces.c:5976
#5  0x0102eb20 in handle_face_prop (it=0x82e180) at xdisp.c:3923
#6  0x0102db70 in handle_stop (it=0x82e180) at xdisp.c:3427
#7  0x0103a40c in next_element_from_buffer (it=0x82e180) at xdisp.c:8242
#8  0x01036f16 in get_next_display_element (it=0x82e180) at xdisp.c:6874
#9  0x0103aec6 in move_it_in_display_line_to (it=0x82e180, to_charpos=311, to_x=-1, op=MOVE_TO_POS) at xdisp.c:8582
#10 0x0103d080 in move_it_to (it=0x82e180, to_charpos=311, to_x=-1, to_y=-1, to_vpos=-1, op=10) at xdisp.c:9149
#11 0x0103ec0d in Fwindow_text_pixel_size (window=..., from=..., to=..., x_limit=..., y_limit=..., mode_and_header_line=..., buffer=...) at xdisp.c:9833
#12 0x0118d7f5 in eval_sub (form=...) at eval.c:2202
#13 0x0118cf36 in Feval (form=..., lexical=...) at eval.c:1996
#14 0x0118e9e6 in Ffuncall (nargs=3, args=0x82ebdc) at eval.c:2811
#15 0x011d01d6 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=1, args=0x82ef10) at bytecode.c:918
#16 0x0118f18c in funcall_lambda (fun=..., nargs=1, arg_vector=0x82ef0c) at eval.c:2976
#17 0x0118ebde in Ffuncall (nargs=2, args=0x82ef08) at eval.c:2857
#18 0x011d01d6 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=1, args=0x82f33c) at bytecode.c:918
#19 0x0118f18c in funcall_lambda (fun=..., nargs=1, arg_vector=0x82f338) at eval.c:2976
#20 0x0118ebde in Ffuncall (nargs=2, args=0x82f334) at eval.c:2857
#21 0x01186548 in Ffuncall_interactively (nargs=2, args=0x82f334) at callint.c:270
#22 0x0118e8ac in Ffuncall (nargs=3, args=0x82f330) at eval.c:2789
#23 0x01188170 in Fcall_interactively (function=..., record_flag=..., keys=...) at callint.c:872
#24 0x0118ea15 in Ffuncall (nargs=4, args=0x82f54c) at eval.c:2815
#25 0x011d01d6 in exec_byte_code (bytestr=..., vector=..., maxdepth=..., args_template=..., nargs=1, args=0x82f894) at bytecode.c:918
#26 0x0118f18c in funcall_lambda (fun=..., nargs=1, arg_vector=0x82f890) at eval.c:2976
#27 0x0118ebde in Ffuncall (nargs=2, args=0x82f88c) at eval.c:2857
#28 0x0118e4a5 in call1 (fn=..., arg1=...) at eval.c:2607
#29 0x010ffcee in command_loop_1 () at keyboard.c:1545
#30 0x0118b92a in internal_condition_case (bfun=0x10ff67c <command_loop_1>, handlers=..., hfun=0x10feee7 <cmd_error>) at eval.c:1347
#31 0x010ff332 in command_loop_2 (ignore=...) at keyboard.c:1169
#32 0x0118aede in internal_catch (tag=..., func=0x10ff30e <command_loop_2>, arg=...) at eval.c:1111
#33 0x010ff2ec in command_loop () at keyboard.c:1148
#34 0x010fea83 in recursive_edit_1 () at keyboard.c:769
#35 0x010fec40 in Frecursive_edit () at keyboard.c:840
#36 0x010fcdaf in main (argc=1, argv=0xa327e8) at emacs.c:1650

Lisp Backtrace:
"window-text-pixel-size" (0x82ea80)
"eval" (0x82ebe0)
"eval-last-sexp-1" (0x82ef0c)
"eval-last-sexp" (0x82f338)
"funcall-interactively" (0x82f334)
"call-interactively" (0x82f550)
"command-execute" (0x82f890)
=== modified file 'src/xdisp.c'
--- src/xdisp.c	2014-08-01 13:10:07 +0000
+++ src/xdisp.c	2014-08-05 15:28:23 +0000
@@ -9713,7 +9713,7 @@
 	  && it->dpvec + it->current.dpvec_index != it->dpend);
 }

-DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 6, 0,
+DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 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
@@ -9746,9 +9746,13 @@
 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 both, if present, in the return value.  */)
+include the height of both, if present, in the return value.
+
+Optional argument BUFFER, if non-nil, means to work on another buffer
+than that displayed in WINDOW.  If BUFFER denotes a live buffer, use
+that buffer.  If BUFFER equals t, use the current buffer.  */)
   (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit, Lisp_Object y_limit,
-   Lisp_Object mode_and_header_line)
+   Lisp_Object mode_and_header_line, Lisp_Object buffer)
 {
   struct window *w = decode_live_window (window);
   Lisp_Object buf;
@@ -9760,14 +9764,25 @@
   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)
+  if (!EQ (buffer, Qt))
     {
-      old_buffer = current_buffer;
-      set_buffer_internal (b);
+      if (NILP (buffer))
+	{
+	  buf = w->contents;
+	  CHECK_BUFFER (buf);
+	  b = XBUFFER (buf);
+	}
+      else
+	{
+	  CHECK_BUFFER (buffer);
+	  b = XBUFFER (buffer);
+	}
+
+      if (b != current_buffer)
+	{
+	  old_buffer = current_buffer;
+	  set_buffer_internal (b);
+	}
     }

   if (NILP (from))
@@ -15814,6 +15829,17 @@
 	 left.  */
       whole = max (whole, w->hscroll + box_width);
       whole = max (whole, end - start);
+      if (it.bidi_p)
+	{
+	  Lisp_Object pdir;
+
+	  pdir = Fcurrent_bidi_paragraph_direction (Qnil);
+	  if (EQ (pdir, Qright_to_left))
+	    {
+	      end = whole - w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
+	      start = end - box_width;
+	    }
+	}

       if (old_buffer)
 	set_buffer_internal (old_buffer);