changeset 55244:c5bad07bbb95

(init_iterator): Handle line-spacing float value. Initialize override_ascent member. (append_space_for_newline): Reset override_ascent. Remove use_default_face. (calc_line_height_property): New function to calculate value of line-height and line-spacing properties. Look at overlays, too. Set override_ascent, override_descent, override_boff members when using another face than the current face. Float values are now relative to the frame default font, by default; accept a cons of ratio and face name to specify value relative to a specific face. (x_produce_glyphs): Use calc_line_height_property. Use override_ascent etc. when set to handle different face heights. A negative line-spacing property value is interpreted as a total line height, rather than inter-line spacing. (note_mouse_highlight): Allocate room for 40 overlays initially.
author Kim F. Storm <storm@cua.dk>
date Thu, 29 Apr 2004 22:37:52 +0000
parents fa2641411db1
children 902d9cd6cdb6
files src/xdisp.c
diffstat 1 files changed, 143 insertions(+), 47 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Thu Apr 29 22:36:34 2004 +0000
+++ b/src/xdisp.c	Thu Apr 29 22:37:52 2004 +0000
@@ -2073,6 +2073,9 @@
     {
       if (NATNUMP (current_buffer->extra_line_spacing))
 	it->extra_line_spacing = XFASTINT (current_buffer->extra_line_spacing);
+      else if (FLOATP (current_buffer->extra_line_spacing))
+	it->extra_line_spacing = (XFLOAT_DATA (current_buffer->extra_line_spacing)
+				  * FRAME_LINE_HEIGHT (it->f));
       else if (it->f->extra_line_spacing > 0)
 	it->extra_line_spacing = it->f->extra_line_spacing;
     }
@@ -2090,6 +2093,7 @@
   it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
   it->space_width = Qnil;
   it->font_height = Qnil;
+  it->override_ascent = -1;
 
   /* Are control characters displayed as `^C'?  */
   it->ctl_arrow_p = !NILP (current_buffer->ctl_arrow);
@@ -14202,7 +14206,7 @@
 
 	  PRODUCE_GLYPHS (it);
 
-	  it->use_default_face = 0;
+	  it->override_ascent = -1;
 	  it->constrain_row_ascent_descent_p = 0;
 	  it->current_x = saved_x;
 	  it->object = saved_object;
@@ -18510,6 +18514,97 @@
   take_vertical_position_into_account (it);
 }
 
+/* Calculate line-height and line-spacing properties.
+   An integer value specifies explicit pixel value.
+   A float value specifies relative value to current face height.
+   A cons (float . face-name) specifies relative value to
+   height of specified face font.
+
+   Returns height in pixels, or nil.  */
+
+static Lisp_Object
+calc_line_height_property (it, prop, font, boff)
+     struct it *it;
+     Lisp_Object prop;
+     XFontStruct *font;
+     int boff;
+{
+  Lisp_Object val;
+  Lisp_Object face_name = Qnil;
+  int ascent, descent, height, override;
+
+  val = Fget_char_property (make_number (IT_CHARPOS (*it)),
+			    prop, it->object);
+
+  if (NILP (val))
+    return val;
+
+  if (INTEGERP (val))
+    return val;
+
+  if (CONSP (val))
+    {
+      face_name = XCDR (val);
+      val = XCAR (val);
+    }
+  else if (SYMBOLP (val))
+    {
+      face_name = val;
+      val = Qnil;
+    }
+
+  override = EQ (prop, Qline_height);
+
+  if (NILP (face_name))
+    {
+      font = FRAME_FONT (it->f);
+      boff = FRAME_BASELINE_OFFSET (it->f);
+    }
+  else if (EQ (face_name, Qt))
+    {
+      override = 0;
+    }
+  else
+    {
+      int face_id;
+      struct face *face;
+      struct font_info *font_info;
+
+      face_id = lookup_named_face (it->f, face_name, ' ');
+      if (face_id < 0)
+	return -1;
+
+      face = FACE_FROM_ID (it->f, face_id);
+      font = face->font;
+      if (font == NULL)
+	return -1;
+
+      font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
+      boff = font_info->baseline_offset;
+      if (font_info->vertical_centering)
+	boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
+    }
+
+  ascent = FONT_BASE (font) + boff;
+  descent = FONT_DESCENT (font) - boff;
+
+  if (override)
+    {
+      it->override_ascent = ascent;
+      it->override_descent = descent;
+      it->override_boff = boff;
+    }
+
+  height = ascent + descent;
+  if (FLOATP (val))
+    height = (int)(XFLOAT_DATA (val) * height);
+  else if (INTEGERP (val))
+    height *= XINT (val);
+
+  return make_number (height);
+}
+
+
 /* RIF:
    Produce glyphs/get display metrics for the display element IT is
    loaded with.  See the description of struct display_iterator in
@@ -18596,17 +18691,20 @@
 
 	  it->nglyphs = 1;
 
-	  if (it->use_default_face)
-	    {
-	      font = FRAME_FONT (it->f);
-	      boff = FRAME_BASELINE_OFFSET (it->f);
-	    }
-
 	  pcm = rif->per_char_metric (font, &char2b,
 				      FONT_TYPE_FOR_UNIBYTE (font, it->char_to_display));
 
-	  it->ascent = FONT_BASE (font) + boff;
-	  it->descent = FONT_DESCENT (font) - boff;
+	  if (it->override_ascent >= 0)
+	    {
+	      it->ascent = it->override_ascent;
+	      it->descent = it->override_descent;
+	      boff = it->override_boff;
+	    }
+	  else
+	    {
+	      it->ascent = FONT_BASE (font) + boff;
+	      it->descent = FONT_DESCENT (font) - boff;
+	    }
 
 	  if (pcm)
 	    {
@@ -18709,26 +18807,27 @@
 	     But if previous part of the line set a height, don't
 	     increase that height */
 
-	  Lisp_Object lsp, lh;
-
+	  Lisp_Object height, spacing;
+
+	  it->override_ascent = -1;
 	  it->pixel_width = 0;
 	  it->nglyphs = 0;
 
-	  lh = Fget_text_property (make_number (IT_CHARPOS (*it)),
-				   Qline_height, it->object);
-
-	  if (EQ (lh, Qt))
-	    {
-	      it->use_default_face = 1;
-	      font = FRAME_FONT (it->f);
-	      boff = FRAME_BASELINE_OFFSET (it->f);
-	      font_info = NULL;
-	    }
-
-	  it->ascent = FONT_BASE (font) + boff;
-	  it->descent = FONT_DESCENT (font) - boff;
-
-	  if (EQ (lh, make_number (0)))
+	  height = calc_line_height_property(it, Qline_height, font, boff);
+
+	  if (it->override_ascent >= 0)
+	    {
+	      it->ascent = it->override_ascent;
+	      it->descent = it->override_descent;
+	      boff = it->override_boff;
+	    }
+	  else
+	    {
+	      it->ascent = FONT_BASE (font) + boff;
+	      it->descent = FONT_DESCENT (font) - boff;
+	    }
+
+	  if (EQ (height, make_number(0)))
 	    {
 	      if (it->descent > it->max_descent)
 		{
@@ -18747,7 +18846,6 @@
 	    }
 	  else
 	    {
-	      int explicit_height = -1;
 	      it->phys_ascent = it->ascent;
 	      it->phys_descent = it->descent;
 
@@ -18758,23 +18856,20 @@
 		  it->ascent += face->box_line_width;
 		  it->descent += face->box_line_width;
 		}
-	      if (INTEGERP (lh))
-		explicit_height = XINT (lh);
-	      else if (FLOATP (lh))
-		explicit_height = (it->phys_ascent + it->phys_descent)
-		  * XFLOAT_DATA (lh);
-
-	      if (explicit_height > it->ascent + it->descent)
-		it->ascent = explicit_height - it->descent;
-	    }
-
-	  lsp = Fget_text_property (make_number (IT_CHARPOS (*it)),
-				    Qline_spacing, it->object);
-	  if (INTEGERP (lsp))
-	    extra_line_spacing = XINT (lsp);
-	  else if (FLOATP (lsp))
-	    extra_line_spacing = (it->phys_ascent + it->phys_descent)
-	      * XFLOAT_DATA (lsp);
+	      if (!NILP (height)
+		  && XINT (height) > it->ascent + it->descent)
+		it->ascent = XINT (height) - it->descent;
+	    }
+
+	  spacing = calc_line_height_property(it, Qline_spacing, font, boff);
+	  if (!NILP (spacing))
+	    {
+	      int sp = XINT (spacing);
+	      if (sp < 0)
+		extra_line_spacing = (-sp) - (it->phys_ascent + it->phys_descent);
+	      else
+		extra_line_spacing = sp;
+	    }
 	}
       else if (it->char_to_display == '\t')
 	{
@@ -19151,7 +19246,8 @@
   if (it->area == TEXT_AREA)
     it->current_x += it->pixel_width;
 
-  it->descent += extra_line_spacing;
+  if (extra_line_spacing > 0)
+    it->descent += extra_line_spacing;
 
   it->max_ascent = max (it->max_ascent, it->ascent);
   it->max_descent = max (it->max_descent, it->descent);
@@ -20815,9 +20911,9 @@
       if (BUFFERP (object))
 	{
 	  /* Put all the overlays we want in a vector in overlay_vec.
-	     Store the length in len.  If there are more than 10, make
+	     Store the length in len.  If there are more than 40, make
 	     enough space for all, and try again.  */
-	  len = 10;
+	  len = 40;
 	  overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
 	  noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
 	  if (noverlays > len)