changeset 54429:5b0aa631db90

(Qcenter): Declare here. (syms_of_xdisp): intern and staticpro it. (handle_single_display_prop): Allow space display property on all platforms. (display_mode_line): Set mode_line_p before displaying line. (calc_pixel_width_or_height): Declare extern. Add separate :align-to handling. Remove complex cases for fringes and scroll-bars. Add left, right, and center alignment positions. Add text (area) width/height. Return width or height for image specs. (produce_stretch_glyph): Improve handling of :align-to. Is now relative to left of text area by default, but other base offsets can be specified -- also for text lines.
author Kim F. Storm <storm@cua.dk>
date Fri, 19 Mar 2004 00:43:16 +0000
parents 3a86bc69c0e3
children b521d24f538a
files src/xdisp.c
diffstat 1 files changed, 266 insertions(+), 219 deletions(-) [+]
line wrap: on
line diff
--- a/src/xdisp.c	Fri Mar 19 00:42:48 2004 +0000
+++ b/src/xdisp.c	Fri Mar 19 00:43:16 2004 +0000
@@ -301,6 +301,7 @@
 Lisp_Object Vdisplay_pixels_per_inch;
 Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height;
 Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise;
+Lisp_Object Qcenter;
 Lisp_Object Qmargin, Qpointer;
 extern Lisp_Object Qheight;
 extern Lisp_Object QCwidth, QCheight, QCascent;
@@ -3607,16 +3608,11 @@
 	  value = prop;
 	}
 
+      valid_p = (STRINGP (value)
 #ifdef HAVE_WINDOW_SYSTEM
-      if (FRAME_TERMCAP_P (it->f))
-	valid_p = STRINGP (value);
-      else
-	valid_p = (STRINGP (value)
-		   || (CONSP (value) && EQ (XCAR (value), Qspace))
-		   || valid_image_p (value));
-#else /* not HAVE_WINDOW_SYSTEM */
-      valid_p = STRINGP (value);
+		 || (!FRAME_TERMCAP_P (it->f) && valid_image_p (value))
 #endif /* not HAVE_WINDOW_SYSTEM */
+		 || (CONSP (value) && EQ (XCAR (value), Qspace)));
 
       if ((EQ (location, Qleft_margin)
 	   || EQ (location, Qright_margin)
@@ -15065,6 +15061,8 @@
   init_iterator (&it, w, -1, -1, NULL, face_id);
   prepare_desired_row (it.glyph_row);
 
+  it.glyph_row->mode_line_p = 1;
+
   if (! mode_line_inverse_video)
     /* Force the mode-line to be displayed in the default face.  */
     it.base_face_id = it.face_id = DEFAULT_FACE_ID;
@@ -15081,7 +15079,6 @@
 
   compute_line_metrics (&it);
   it.glyph_row->full_width_p = 1;
-  it.glyph_row->mode_line_p = 1;
   it.glyph_row->continued_p = 0;
   it.glyph_row->truncated_on_left_p = 0;
   it.glyph_row->truncated_on_right_p = 0;
@@ -16695,6 +16692,251 @@
   return 0;
 }
 
+/* Calculate a width or height in pixels from a specification using
+   the following elements:
+
+   SPEC ::= 
+     NUM      - a (fractional) multiple of the default font width/height
+     (NUM)    - specifies exactly NUM pixels
+     UNIT     - a fixed number of pixels, see below.
+     ELEMENT  - size of a display element in pixels, see below.
+     (NUM . SPEC) - equals NUM * SPEC
+     (+ SPEC SPEC ...)  - add pixel values
+     (- SPEC SPEC ...)  - subtract pixel values
+     (- SPEC)           - negate pixel value
+
+   NUM ::= 
+     INT or FLOAT   - a number constant
+     SYMBOL         - use symbol's (buffer local) variable binding.
+
+   UNIT ::=
+     in       - pixels per inch  *)
+     mm       - pixels per 1/1000 meter  *)
+     cm       - pixels per 1/100 meter   *)
+     width    - width of current font in pixels.
+     height   - height of current font in pixels.
+
+     *) using the ratio(s) defined in display-pixels-per-inch.
+
+   ELEMENT ::=
+
+     left-fringe          - left fringe width in pixels
+     right-fringe         - right fringe width in pixels
+
+     left-margin          - left margin width in pixels
+     right-margin         - right margin width in pixels
+
+     scroll-bar           - scroll-bar area width in pixels
+
+   Examples:
+
+   Pixels corresponding to 5 inches:
+     (5 . in)     
+		
+   Total width of non-text areas on left side of window (if scroll-bar is on left):
+     '(space :width (+ left-fringe left-margin scroll-bar))
+
+   Align to first text column (in header line):
+     '(space :align-to 0)
+
+   Align to middle of text area minus half the width of variable `my-image' 
+   containing a loaded image:
+     '(space :align-to (0.5 . (- text my-image)))
+
+   Width of left margin minus width of 1 character in the default font:
+     '(space :width (- left-margin 1))
+
+   Width of left margin minus width of 2 characters in the current font:
+     '(space :width (- left-margin (2 . width)))
+
+   Center 1 character over left-margin (in header line):
+     '(space :align-to (+ left-margin (0.5 . left-margin) -0.5))
+
+   Different ways to express width of left fringe plus left margin minus one pixel:
+     '(space :width (- (+ left-fringe left-margin) (1)))
+     '(space :width (+ left-fringe left-margin (- (1))))
+     '(space :width (+ left-fringe left-margin (-1)))
+
+*/
+
+#define NUMVAL(X)				\
+     ((INTEGERP (X) || FLOATP (X))		\
+      ? XFLOATINT (X)				\
+      : - 1)
+
+int
+calc_pixel_width_or_height (res, it, prop, font, width_p, align_to)
+     double *res;
+     struct it *it;
+     Lisp_Object prop;
+     void *font;
+     int width_p, *align_to;
+{
+  double pixels;
+
+#define OK_PIXELS(val) ((*res = (double)(val)), 1)
+#define OK_ALIGN_TO(val) ((*align_to = (int)(val)), 1)
+
+  if (NILP (prop))
+    return OK_PIXELS (0);
+
+  if (SYMBOLP (prop))
+    {
+      if (SCHARS (SYMBOL_NAME (prop)) == 2)
+	{
+	  char *unit =  SDATA (SYMBOL_NAME (prop));
+
+	  if (unit[0] == 'i' && unit[1] == 'n')
+	    pixels = 1.0;
+	  else if (unit[0] == 'm' && unit[1] == 'm')
+	    pixels = 25.4;
+	  else if (unit[0] == 'c' && unit[1] == 'm')
+	    pixels = 2.54;
+	  else
+	    pixels = 0;
+	  if (pixels > 0)
+	    {
+	      double ppi;
+	      if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
+		  || (CONSP (Vdisplay_pixels_per_inch)
+		      && (ppi = (width_p
+				 ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
+				 : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
+			  ppi > 0)))
+		return OK_PIXELS (ppi / pixels);
+
+	      return 0;
+	    }
+	}
+
+#ifdef HAVE_WINDOW_SYSTEM
+      if (EQ (prop, Qheight))
+	return OK_PIXELS (font ? FONT_HEIGHT ((XFontStruct *)font) : FRAME_LINE_HEIGHT (it->f));
+      if (EQ (prop, Qwidth))
+	return OK_PIXELS (font ? FONT_WIDTH ((XFontStruct *)font) : FRAME_COLUMN_WIDTH (it->f));
+#else
+      if (EQ (prop, Qheight) || EQ (prop, Qwidth))
+	return OK_PIXELS (1);
+#endif
+
+      if (EQ (prop, Qtext))
+	  return OK_PIXELS (width_p
+			    ? window_box_width (it->w, TEXT_AREA)
+			    : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
+
+      if (align_to && *align_to < 0)
+	{
+	  *res = 0;
+	  if (EQ (prop, Qleft))
+	    return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA));
+	  if (EQ (prop, Qright))
+	    return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
+	  if (EQ (prop, Qcenter))
+	    return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
+				+ window_box_width (it->w, TEXT_AREA) / 2);
+	  if (EQ (prop, Qleft_fringe))
+	    return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+				? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
+				: window_box_right_offset (it->w, LEFT_MARGIN_AREA));
+	  if (EQ (prop, Qright_fringe))
+	    return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+				? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+				: window_box_right_offset (it->w, TEXT_AREA));
+	  if (EQ (prop, Qleft_margin))
+	    return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
+	  if (EQ (prop, Qright_margin))
+	    return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
+	  if (EQ (prop, Qscroll_bar))
+	    return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
+				? 0
+				: (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
+				   + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
+				      ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
+				      : 0)));
+	}
+      else
+	{
+	  if (EQ (prop, Qleft_fringe))
+	    return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
+	  if (EQ (prop, Qright_fringe))
+	    return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
+	  if (EQ (prop, Qleft_margin))
+	    return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
+	  if (EQ (prop, Qright_margin))
+	    return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
+	  if (EQ (prop, Qscroll_bar))
+	    return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
+	}
+
+      prop = Fbuffer_local_value (prop, it->w->buffer);
+    }
+
+  if (INTEGERP (prop) || FLOATP (prop))
+    {
+      int base_unit = (width_p
+		       ? FRAME_COLUMN_WIDTH (it->f)
+		       : FRAME_LINE_HEIGHT (it->f));
+      return OK_PIXELS (XFLOATINT (prop) * base_unit);
+    }
+
+  if (CONSP (prop))
+    {
+      Lisp_Object car = XCAR (prop);
+      Lisp_Object cdr = XCDR (prop);
+
+      if (SYMBOLP (car))
+	{
+	  if (valid_image_p (prop))
+	    {
+	      int id = lookup_image (it->f, prop);
+	      struct image *img = IMAGE_FROM_ID (it->f, id);
+
+	      return OK_PIXELS (width_p ? img->width : img->height);
+	    }
+
+	  if (EQ (car, Qplus) || EQ (car, Qminus))
+	    {
+	      int first = 1;
+	      double px;
+
+	      pixels = 0;
+	      while (CONSP (cdr))
+		{
+		  if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
+						   font, width_p, align_to))
+		    return 0;
+		  if (first)
+		    pixels = (EQ (car, Qplus) ? px : -px), first = 0;
+		  else
+		    pixels += px;
+		  cdr = XCDR (cdr);
+		}
+	      if (EQ (car, Qminus))
+		pixels = -pixels;
+	      return OK_PIXELS (pixels);
+	    }
+
+	  car = Fbuffer_local_value (car, it->w->buffer);
+	}
+
+      if (INTEGERP (car) || FLOATP (car))
+	{
+	  double fact;
+	  pixels = XFLOATINT (car);
+	  if (NILP (cdr))
+	    return OK_PIXELS (pixels);
+	  if (calc_pixel_width_or_height (&fact, it, cdr,
+					  font, width_p, align_to))
+	    return OK_PIXELS (pixels * fact);
+	  return 0;
+	}
+
+      return 0;
+    }
+
+  return 0;
+}
+
 
 /***********************************************************************
 			     Glyph Display
@@ -17978,209 +18220,6 @@
 }
 
 
-/* Calculate a width or height in pixels from a specification using
-   the following elements:
-
-   SPEC ::= 
-     NUM      - a (fractional) multiple of the default font width/height
-     (NUM)    - specifies exactly NUM pixels
-     UNIT     - a fixed number of pixels, see below.
-     ELEMENT  - size of a display element in pixels, see below.
-     (NUM . SPEC) - equals NUM * SPEC
-     (+ SPEC SPEC ...)  - add pixel values
-     (- SPEC SPEC ...)  - subtract pixel values
-     (- SPEC)           - negate pixel value
-
-   NUM ::= 
-     INT or FLOAT   - a number constant
-     SYMBOL         - use symbol's (buffer local) variable binding.
-
-   UNIT ::=
-     in       - pixels per inch  *)
-     mm       - pixels per 1/1000 meter  *)
-     cm       - pixels per 1/100 meter   *)
-     width    - width of current font in pixels.
-     height   - height of current font in pixels.
-
-     *) using the ratio(s) defined in display-pixels-per-inch.
-
-   ELEMENT ::=
-
-     left-fringe         - left fringe width in pixels
-     (left-fringe . nil) - left fringe width if inside margins, else 0
-     (left-fringe . t)   - left fringe width if outside margins, else 0
-
-     right-fringe         - right fringe width in pixels
-     (right-fringe . nil) - right fringe width if inside margins, else 0
-     (right-fringe . t)   - right fringe width if outside margins, else 0
-
-     left-margin          - left margin width in pixels
-     right-margin         - right margin width in pixels
-
-     scroll-bar           - scroll-bar area width in pixels
-     (scroll-bar . left)  - scroll-bar width if on left, else 0
-     (scroll-bar . right) - scroll-bar width if on right, else 0
-
-   Examples:
-
-   Pixels corresponding to 5 inches:
-     (5 . in)     
-		
-   Total width of non-text areas on left side of window:
-     (+ left-fringe left-margin (scroll-bar . left))
-
-   Total width of fringes if inside display margins:
-     (+ (left-fringe) (right-fringe))
-
-   Width of left margin minus width of 1 character in the default font:
-     (- left-margin 1)
-
-   Width of left margin minus width of 2 characters in the current font:
-     (- left-margin (2 . width))
-
-   Width of left fringe plus left margin minus one pixel:
-     (- (+ left-fringe left-margin) (1))
-     (+ left-fringe left-margin (- (1)))
-     (+ left-fringe left-margin (-1))
-
-*/
-
-#define NUMVAL(X)				\
-     ((INTEGERP (X) || FLOATP (X))		\
-      ? XFLOATINT (X)				\
-      : - 1)
-
-static int
-calc_pixel_width_or_height (res, it, prop, font, width_p)
-     double *res;
-     struct it *it;
-     Lisp_Object prop;
-     XFontStruct *font;
-     int width_p;
-{
-  double pixels;
-
-#define OK_PIXELS(val) ((*res = (val)), 1)
-
-  if (SYMBOLP (prop))
-    {
-      if (SCHARS (SYMBOL_NAME (prop)) == 2)
-	{
-	  char *unit =  SDATA (SYMBOL_NAME (prop));
-
-	  if (unit[0] == 'i' && unit[1] == 'n')
-	    pixels = 1.0;
-	  else if (unit[0] == 'm' && unit[1] == 'm')
-	    pixels = 25.4;
-	  else if (unit[0] == 'c' && unit[1] == 'm')
-	    pixels = 2.54;
-	  else
-	    pixels = 0;
-	  if (pixels > 0)
-	    {
-	      double ppi;
-	      if ((ppi = NUMVAL (Vdisplay_pixels_per_inch), ppi > 0)
-		  || (CONSP (Vdisplay_pixels_per_inch)
-		      && (ppi = (width_p
-				 ? NUMVAL (XCAR (Vdisplay_pixels_per_inch))
-				 : NUMVAL (XCDR (Vdisplay_pixels_per_inch))),
-			  ppi > 0)))
-		return OK_PIXELS (ppi / pixels);
-
-	      return 0;
-	    }
-	}
-
-      if (EQ (prop, Qheight))
-	return OK_PIXELS (font ? FONT_HEIGHT (font) : FRAME_LINE_HEIGHT (it->f));
-      if (EQ (prop, Qwidth))
-	return OK_PIXELS (font ? FONT_WIDTH (font) : FRAME_COLUMN_WIDTH (it->f));
-      if (EQ (prop, Qleft_fringe))
-	return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
-      if (EQ (prop, Qright_fringe))
-	return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
-      if (EQ (prop, Qleft_margin))
-	return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
-      if (EQ (prop, Qright_margin))
-	return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
-      if (EQ (prop, Qscroll_bar))
-	return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
-
-      prop = Fbuffer_local_value (prop, it->w->buffer);
-    }
-
-  if (INTEGERP (prop) || FLOATP (prop))
-    {
-      int base_unit = (width_p
-		       ? FRAME_COLUMN_WIDTH (it->f)
-		       : FRAME_LINE_HEIGHT (it->f));
-      return OK_PIXELS (XFLOATINT (prop) * base_unit);
-    }
-
-  if (CONSP (prop))
-    {
-      Lisp_Object car = XCAR (prop);
-      Lisp_Object cdr = XCDR (prop);
-
-      if (SYMBOLP (car))
-	{
-	  if (EQ (car, Qplus) || EQ (car, Qminus))
-	    {
-	      int first = 1;
-	      double px;
-
-	      pixels = 0;
-	      while (CONSP (cdr))
-		{
-		  if (!calc_pixel_width_or_height (&px, it, XCAR (cdr), font, width_p))
-		    return 0;
-		  if (first)
-		    pixels = (EQ (car, Qplus) ? px : -px), first = 0;
-		  else
-		    pixels += px;
-		  cdr = XCDR (cdr);
-		}
-	      if (EQ (car, Qminus))
-		pixels = -pixels;
-	      return OK_PIXELS (pixels);
-	    }
-
-	  if (EQ (car, Qleft_fringe))
-	    return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
-			       == !NILP (cdr))
-			      ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
-			      : 0);
-	  if (EQ (car, Qright_fringe))
-	    return OK_PIXELS ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
-			       == !NILP (cdr))
-			      ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
-			      : 0);
-	  if (EQ (car, Qscroll_bar))
-	    return OK_PIXELS ((WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
-				== EQ (cdr, Qleft))
-			       ? WINDOW_SCROLL_BAR_AREA_WIDTH (it->w)
-			       : 0);
-
-	  car = Fbuffer_local_value (car, it->w->buffer);
-	}
-
-      if (INTEGERP (car) || FLOATP (car))
-	{
-	  double fact;
-	  pixels = XFLOATINT (car);
-	  if (NILP (cdr))
-	    return OK_PIXELS (pixels);
-	  if (calc_pixel_width_or_height (&fact, it, cdr, font, width_p))
-	    return OK_PIXELS (pixels * fact);
-	  return 0;
-	}
-
-      return 0;
-    }
-
-  return 0;
-}
-
 /* Produce a stretch glyph for iterator IT.  IT->object is the value
    of the glyph property displayed.  The value must be a list
    `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
@@ -18218,7 +18257,7 @@
 {
   /* (space :width WIDTH :height HEIGHT ...)  */
   Lisp_Object prop, plist;
-  int width = 0, height = 0;
+  int width = 0, height = 0, align_to = -1;
   int zero_width_ok_p = 0, zero_height_ok_p = 0;
   int ascent = 0;
   double tem;
@@ -18233,7 +18272,7 @@
 
   /* Compute the width of the stretch.  */
   if ((prop = Fplist_get (plist, QCwidth), !NILP (prop))
-      && calc_pixel_width_or_height (&tem, it, prop, font, 1))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 1, 0))
     {
       /* Absolute width `:width WIDTH' specified and valid.  */
       zero_width_ok_p = 1;
@@ -18264,9 +18303,15 @@
       width = NUMVAL (prop) * it2.pixel_width;
     }
   else if ((prop = Fplist_get (plist, QCalign_to), !NILP (prop))
-	   && calc_pixel_width_or_height (&tem, it, prop, font, 1))
-    {
-      width = max (0, (int)tem - it->current_x);
+	   && calc_pixel_width_or_height (&tem, it, prop, font, 1, &align_to))
+    {
+      if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
+	align_to = (align_to < 0 
+		    ? 0
+		    : align_to - window_box_left_offset (it->w, TEXT_AREA));
+      else if (align_to < 0)
+	align_to = window_box_left_offset (it->w, TEXT_AREA);
+      width = max (0, (int)tem + align_to - it->current_x);
       zero_width_ok_p = 1;
     }
   else
@@ -18278,7 +18323,7 @@
 
   /* Compute height.  */
   if ((prop = Fplist_get (plist, QCheight), !NILP (prop))
-      && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+      && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     {
       height = (int)tem;
       zero_height_ok_p = 1;
@@ -18299,7 +18344,7 @@
       NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
     ascent = height * NUMVAL (prop) / 100.0;
   else if (!NILP (prop)
-	   && calc_pixel_width_or_height (&tem, it, prop, font, 0))
+	   && calc_pixel_width_or_height (&tem, it, prop, font, 0, 0))
     ascent = min (max (0, (int)tem), height);
   else
     ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
@@ -21523,6 +21568,8 @@
   staticpro (&Qleft_margin);
   Qright_margin = intern ("right-margin");
   staticpro (&Qright_margin);
+  Qcenter = intern ("center");
+  staticpro (&Qcenter);
   QCalign_to = intern (":align-to");
   staticpro (&QCalign_to);
   QCrelative_width = intern (":relative-width");