emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r108632: Merge implmentation of wave-


From: Alp Aker
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r108632: Merge implmentation of wave-style underline face attribute (debbugs.gnu.org/10736).
Date: Sat, 16 Jun 2012 20:35:30 -0400
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108632 [merge]
committer: Alp Aker <address@hidden>
branch nick: trunk
timestamp: Sat 2012-06-16 20:35:30 -0400
message:
  Merge implmentation of wave-style underline face attribute 
(debbugs.gnu.org/10736).
modified:
  ChangeLog
  doc/lispref/display.texi
  lisp/ChangeLog
  lisp/cus-face.el
  lisp/faces.el
  src/ChangeLog
  src/dispextern.h
  src/nsterm.m
  src/w32term.c
  src/xfaces.c
  src/xterm.c
=== modified file 'ChangeLog'
--- a/ChangeLog 2012-06-13 13:40:48 +0000
+++ b/ChangeLog 2012-06-17 00:32:36 +0000
@@ -1,3 +1,8 @@
+2012-06-16  Aurelien Aptel  <address@hidden>
+
+       * doc/lispref/display.texi: Document wave-style underline
+       face attribute.
+
 2012-06-13  Andreas Schwab  <address@hidden>
 
        * configure.in: Rename --enable-use-lisp-union-type to

=== modified file 'doc/lispref/display.texi'
--- a/doc/lispref/display.texi  2012-06-11 14:42:55 +0000
+++ b/doc/lispref/display.texi  2012-06-17 00:32:36 +0000
@@ -2130,10 +2130,32 @@
 name, or a hexadecimal color specification.  @xref{Color Names}.
 
 @item :underline
-Whether or not characters should be underlined, and in what color.  If
-the value is @code{t}, underlining uses the foreground color of the
-face.  If the value is a string, underlining uses that color.  The
-value @code{nil} means do not underline.
+Whether or not characters should be underlined, and in what
+color. Here are the possible values of the @code{:underline}
+attribute, and what they mean:
+
address@hidden @asis
address@hidden @code{nil}
+Don't underline.
+
address@hidden @code{t}
+Underline with the foreground color of the face.
+
address@hidden @var{color}
+Underline in color @var{color}.
+
address@hidden @code{(:color @var{color} :style @var{style})}
+If @var{color} is a string, underline in it.
+If @var{color} is @code{foreground-color}, underline with the
+foreground color of the face.
+
+If @var{style} is @code{wave} underline with a wave.
+If @var{style} is @code{line} underline with a line. 
+
+If the attribute @code{:color} is omited, underline with the
+foreground color of the face.
+If the attribute @code{:style} is omited, underline with a line.
address@hidden table
 
 @item :overline
 Whether or not characters should be overlined, and in what color.

=== modified file 'lisp/ChangeLog'
--- a/lisp/ChangeLog    2012-06-16 17:45:09 +0000
+++ b/lisp/ChangeLog    2012-06-17 00:32:36 +0000
@@ -1,3 +1,10 @@
+2012-06-16  Aurelien Aptel  <address@hidden>
+
+       * cus-face.el (custom-face-attributes): Add wave-style underline
+       attribute.
+       * faces.el (set-face-attribute): Update docstring to describe
+       wave-style underline attribute.
+
 2012-06-16  Chong Yidong  <address@hidden>
 
        * term/xterm.el (terminal-init-xterm): Discard input before

=== modified file 'lisp/cus-face.el'
--- a/lisp/cus-face.el  2012-01-19 07:21:25 +0000
+++ b/lisp/cus-face.el  2012-06-17 00:32:36 +0000
@@ -135,8 +135,13 @@
      (choice :tag "Underline"
             :help-echo "Control text underlining."
             (const :tag "Off" nil)
-            (const :tag "On" t)
-            (color :tag "Colored")))
+            (list :tag "On"
+                  (const :format "" :value :color)
+                  (choice :tag "Color" (const :tag "Foreground Color" 
foreground-color) color)
+                   (const :format "" :value :style)
+                   (choice :tag "Style"
+                           (const :tag "Line" line)
+                           (const :tag "Wave" wave)))))
 
     (:overline
      (choice :tag "Overline"

=== modified file 'lisp/faces.el'
--- a/lisp/faces.el     2012-06-08 16:39:49 +0000
+++ b/lisp/faces.el     2012-06-17 00:32:36 +0000
@@ -623,10 +623,21 @@
 
 `:underline'
 
-VALUE specifies whether characters in FACE should be underlined.  If
-VALUE is t, underline with foreground color of the face.  If VALUE is
-a string, underline with that color.  If VALUE is nil, explicitly
-don't underline.
+VALUE specifies whether characters in FACE should be underlined.
+If VALUE is t, underline with foreground color of the face.
+If VALUE is a string, underline with that color.
+If VALUE is nil, explicitly don't underline.
+
+Otherwise, VALUE must be a property list of the form:
+
+`(:color COLOR :style STYLE)'.
+
+COLOR can be a either a color name string or `foreground-color'.
+STYLE can be either `line' or `wave'.
+If a keyword/value pair is missing from the property list, a
+default value will be used for the value.
+The default value of COLOR is the foreground color of the face.
+The default value of STYLE is `line'.
 
 `:overline'
 

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-06-16 13:44:20 +0000
+++ b/src/ChangeLog     2012-06-17 00:32:36 +0000
@@ -1,3 +1,20 @@
+2012-06-16  Aurelien Aptel  <address@hidden>
+
+       Implement wave-style variant of underlining.
+       * dispextern.h (face_underline_type): New enum.
+       (face): Add field for underline type.
+       * nsterm.m (ns_draw_underwave): New function.
+       (ns_draw_text_decoration): Use it.
+       * w32term.c (w32_restore_glyph_string_clip, w32_draw_underwave):
+       New functions.
+       (x_draw_glyph_string): Use them.
+       * xfaces.c (Qline, Qwave): New Lisp objects.
+       (check_lface_attrs, merge_face_ref)
+       (Finternal_set_lisp_face_attribute, realize_x_face): Handle
+       wave-style underline face attributes.
+       * xterm.c (x_draw_underwave): New function.
+       (x_draw_glyph_string): Use it.
+
 2012-06-16  Juanma Barranquero  <address@hidden>
 
        * makefile.w32-in ($(BLD)/emacs.$(O), $(BLD)/fringe.$(O))

=== modified file 'src/dispextern.h'
--- a/src/dispextern.h  2012-06-10 13:20:58 +0000
+++ b/src/dispextern.h  2012-06-17 00:32:36 +0000
@@ -1510,6 +1510,13 @@
   FACE_SUNKEN_BOX
 };
 
+/* Underline type. */
+
+enum face_underline_type
+{
+  FACE_UNDER_LINE,
+  FACE_UNDER_WAVE
+};
 
 /* Structure describing a realized face.
 
@@ -1585,6 +1592,9 @@
      drawing shadows.  */
   unsigned use_box_color_for_shadows_p : 1;
 
+  /* Style of underlining. */
+  enum face_underline_type underline_type;
+
   /* Non-zero if text in this face should be underlined, overlined,
      strike-through or have a box drawn around it.  */
   unsigned underline_p : 1;

=== modified file 'src/nsterm.m'
--- a/src/nsterm.m      2012-05-26 21:23:28 +0000
+++ b/src/nsterm.m      2012-06-17 00:32:36 +0000
@@ -2595,6 +2595,60 @@
   return n;
 }
 
+/* --------------------------------------------------------------------
+   Draw a wavy line under glyph string s. The wave fills wave_height
+   pixels from y.
+
+                    x          wave_length = 3
+                                 --
+                y    *   *   *   *   *
+                     |* * * * * * * * *
+    wave_height = 3  | *   *   *   *
+  --------------------------------------------------------------------- */
+
+static void
+ns_draw_underwave (struct glyph_string *s, CGFloat width, CGFloat x)
+{
+  int wave_height = 3, wave_length = 3;
+  int y, dx, dy, odd, xmax;
+  NSPoint a, b;
+  NSRect waveClip;
+
+  dx = wave_length;
+  dy = wave_height - 1;
+  y =  s->ybase + 1;
+  xmax = x + width;
+
+  /* Find and set clipping rectangle */
+  waveClip = NSMakeRect (x, y, width, wave_height);
+  [[NSGraphicsContext currentContext] saveGraphicsState];
+  NSRectClip (waveClip);
+
+  /* Draw the waves */
+  a.x = x - ((int)(x) % dx);
+  b.x = a.x + dx;
+  odd = (int)(a.x/dx) % 2;
+  a.y = b.y = y;
+
+  if (odd)
+    a.y += dy;
+  else
+    b.y += dy;
+
+  while (a.x <= xmax)
+    {
+      [NSBezierPath strokeLineFromPoint:a toPoint:b];
+      a.x = b.x, a.y = b.y;
+      b.x += dx, b.y = y + odd*dy;
+      odd = !odd;
+    }
+
+  /* Restore previous clipping rectangle(s) */
+  [[NSGraphicsContext currentContext] restoreGraphicsState];
+}
+
+
+
 void
 ns_draw_text_decoration (struct glyph_string *s, struct face *face,
                          NSColor *defaultCol, CGFloat width, CGFloat x)
@@ -2608,63 +2662,75 @@
   /* Do underline. */
   if (face->underline_p)
     {
-      NSRect r;
-      unsigned long thickness, position;
-
-      /* If the prev was underlined, match its appearance. */
-      if (s->prev && s->prev->face->underline_p
-          && s->prev->underline_thickness > 0)
-        {
-          thickness = s->prev->underline_thickness;
-          position = s->prev->underline_position;
-        }
-      else
-        {
-          struct font *font;
-          unsigned long descent;
-
-          font=s->font;
-          descent = s->y + s->height - s->ybase;
-
-          /* Use underline thickness of font, defaulting to 1. */
-          thickness = (font && font->underline_thickness > 0)
-            ? font->underline_thickness : 1;
-
-          /* Determine the offset of underlining from the baseline. */
-          if (x_underline_at_descent_line)
-            position = descent - thickness;
-          else if (x_use_underline_position_properties
-                   && font && font->underline_position >= 0)
-            position = font->underline_position;
-          else if (font)
-            position = lround (font->descent / 2);
-          else
-            position = underline_minimum_offset;
-
-          position = max (position, underline_minimum_offset);
-
-          /* Ensure underlining is not cropped. */
-          if (descent <= position)
-            {
-              position = descent - 1;
-              thickness = 1;
-            }
-          else if (descent < position + thickness)
-            thickness = 1;
-        }
-
-      s->underline_thickness = thickness;
-      s->underline_position = position;
-
-      r = NSMakeRect (x, s->ybase + position, width, thickness);
-
-      if (face->underline_defaulted_p)
-        [defaultCol set];
-      else
-        [ns_lookup_indexed_color (face->underline_color, s->f) set];
-      NSRectFill (r);
+      if (s->face->underline_type == FACE_UNDER_WAVE)
+        {
+          if (face->underline_defaulted_p)
+            [defaultCol set];
+          else
+            [ns_lookup_indexed_color (face->underline_color, s->f) set];
+
+          ns_draw_underwave (s, width, x);
+        }
+      else if (s->face->underline_type == FACE_UNDER_LINE)
+        {
+
+          NSRect r;
+          unsigned long thickness, position;
+
+          /* If the prev was underlined, match its appearance. */
+          if (s->prev && s->prev->face->underline_p
+              && s->prev->underline_thickness > 0)
+            {
+              thickness = s->prev->underline_thickness;
+              position = s->prev->underline_position;
+            }
+          else
+            {
+              struct font *font;
+              unsigned long descent;
+
+              font=s->font;
+              descent = s->y + s->height - s->ybase;
+
+              /* Use underline thickness of font, defaulting to 1. */
+              thickness = (font && font->underline_thickness > 0)
+                ? font->underline_thickness : 1;
+
+              /* Determine the offset of underlining from the baseline. */
+              if (x_underline_at_descent_line)
+                position = descent - thickness;
+              else if (x_use_underline_position_properties
+                       && font && font->underline_position >= 0)
+                position = font->underline_position;
+              else if (font)
+                position = lround (font->descent / 2);
+              else
+                position = underline_minimum_offset;
+
+              position = max (position, underline_minimum_offset);
+
+              /* Ensure underlining is not cropped. */
+              if (descent <= position)
+                {
+                  position = descent - 1;
+                  thickness = 1;
+                }
+              else if (descent < position + thickness)
+                thickness = 1;
+            }
+
+          s->underline_thickness = thickness;
+          s->underline_position = position;
+
+          r = NSMakeRect (x, s->ybase + position, width, thickness);
+
+          if (face->underline_defaulted_p)
+            [defaultCol set];
+          else
+            [ns_lookup_indexed_color (face->underline_color, s->f) set];
+          NSRectFill (r);
+        }
     }
-
   /* Do overline. We follow other terms in using a thickness of 1
      and ignoring overline_margin. */
   if (face->overline_p)

=== modified file 'src/w32term.c'
--- a/src/w32term.c     2012-06-13 13:40:48 +0000
+++ b/src/w32term.c     2012-06-17 00:32:36 +0000
@@ -313,6 +313,94 @@
     SelectClipRgn (hdc, NULL);
 }
 
+/* Restore clipping rectangle in S */
+static void
+w32_restore_glyph_string_clip (struct glyph_string *s)
+{
+  RECT *r = s->clip;
+  int n = s->num_clips;
+
+  if (n == 1)
+    w32_set_clip_rectangle (s->hdc, r);
+  else if (n > 1)
+    {
+      HRGN clip1 = CreateRectRgnIndirect (r);
+      HRGN clip2 = CreateRectRgnIndirect (r + 1);
+      if (CombineRgn (clip1, clip1, clip2, RGN_OR) != ERROR)
+        SelectClipRgn (s->hdc, clip1);
+      DeleteObject (clip1);
+      DeleteObject (clip2);
+    }
+}
+
+/*
+   Draw a wavy line under S. The wave fills wave_height pixels from y0.
+
+                    x0         wave_length = 2
+                                 --
+                y0   *   *   *   *   *
+                     |* * * * * * * * *
+    wave_height = 3  | *   *   *   *
+
+*/
+
+void
+w32_draw_underwave (struct glyph_string *s, COLORREF color)
+{
+  int wave_height = 2, wave_length = 3;
+  int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+  XRectangle wave_clip, string_clip, final_clip;
+  RECT w32_final_clip, w32_string_clip;
+  HPEN hp, oldhp;
+
+  dx = wave_length;
+  dy = wave_height - 1;
+  x0 = s->x;
+  y0 = s->ybase + 1;
+  width = s->width;
+  xmax = x0 + width;
+
+  /* Find and set clipping rectangle */
+
+  wave_clip = (XRectangle){ x0, y0, width, wave_height };
+  get_glyph_string_clip_rect (s, &w32_string_clip);
+  CONVERT_TO_XRECT (string_clip, w32_string_clip);
+
+  if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
+    return;
+
+  hp = CreatePen (PS_SOLID, 0, color);
+  oldhp = SelectObject (s->hdc, hp);
+  CONVERT_FROM_XRECT (final_clip, w32_final_clip);
+  w32_set_clip_rectangle (s->hdc, &w32_final_clip);
+
+  /* Draw the waves */
+
+  x1 = x0 - (x0 % dx);
+  x2 = x1 + dx;
+  odd = (x1/dx) % 2;
+  y1 = y2 = y0;
+
+  if (odd)
+    y1 += dy;
+  else
+    y2 += dy;
+
+  MoveToEx (s->hdc, x1, y1, NULL);
+
+  while (x1 <= xmax)
+    {
+      LineTo (s->hdc, x2, y2);
+      x1  = x2, y1 = y2;
+      x2 += dx, y2 = y0 + odd*dy;
+      odd = !odd;
+    }
+
+  /* Restore previous pen and clipping rectangle(s) */
+  w32_restore_glyph_string_clip (s);
+  SelectObject (s->hdc, oldhp);
+  DeleteObject (hp);
+}
 
 /* Draw a hollow rectangle at the specified position.  */
 void
@@ -2347,60 +2435,74 @@
       /* Draw underline.  */
       if (s->face->underline_p)
         {
-          unsigned long thickness, position;
-          int y;
-
-          if (s->prev && s->prev->face->underline_p)
-            {
-              /* We use the same underline style as the previous one.  */
-              thickness = s->prev->underline_thickness;
-              position = s->prev->underline_position;
-            }
-          else
-            {
-              /* Get the underline thickness.  Default is 1 pixel.  */
-              if (s->font && s->font->underline_thickness > 0)
-                thickness = s->font->underline_thickness;
-              else
-                thickness = 1;
-              if (x_underline_at_descent_line)
-                position = (s->height - thickness) - (s->ybase - s->y);
-              else
-                {
-                /* Get the underline position.  This is the recommended
-                   vertical offset in pixels from the baseline to the top of
-                   the underline.  This is a signed value according to the
-                   specs, and its default is
-
-                   ROUND ((maximum_descent) / 2), with
-                   ROUND (x) = floor (x + 0.5)  */
-
-                if (x_use_underline_position_properties
-                    && s->font && s->font->underline_position >= 0)
-                  position = s->font->underline_position;
-                else if (s->font)
-                  position = (s->font->descent + 1) / 2;
-                }
-             position = max (position, underline_minimum_offset);
-            }
-         /* Check the sanity of thickness and position.  We should
-            avoid drawing underline out of the current line area.  */
-         if (s->y + s->height <= s->ybase + position)
-           position = (s->height - 1) - (s->ybase - s->y);
-         if (s->y + s->height < s->ybase + position + thickness)
-           thickness = (s->y + s->height) - (s->ybase + position);
-         s->underline_thickness = thickness;
-         s->underline_position =position;
-          y = s->ybase + position;
-          if (s->face->underline_defaulted_p)
-            {
-              w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
-                             y, s->width, 1);
-            }
-          else
-            {
-              w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
-                             y, s->width, 1);
+          if (s->face->underline_type == FACE_UNDER_WAVE)
+            {
+              COLORREF color;
+
+              if (s->face->underline_defaulted_p)
+                color = s->gc->foreground;
+              else
+                color = s->face->underline_color;
+
+              w32_draw_underwave (s, color);
+            }
+          else if (s->face->underline_type == FACE_UNDER_LINE)
+            {
+              unsigned long thickness, position;
+              int y;
+
+              if (s->prev && s->prev->face->underline_p)
+                {
+                  /* We use the same underline style as the previous one.  */
+                  thickness = s->prev->underline_thickness;
+                  position = s->prev->underline_position;
+                }
+              else
+                {
+                  /* Get the underline thickness.  Default is 1 pixel.  */
+                  if (s->font && s->font->underline_thickness > 0)
+                    thickness = s->font->underline_thickness;
+                  else
+                    thickness = 1;
+                  if (x_underline_at_descent_line)
+                    position = (s->height - thickness) - (s->ybase - s->y);
+                  else
+                    {
+                      /* Get the underline position.  This is the recommended
+                         vertical offset in pixels from the baseline to the 
top of
+                         the underline.  This is a signed value according to 
the
+                         specs, and its default is
+
+                         ROUND ((maximum_descent) / 2), with
+                         ROUND (x) = floor (x + 0.5)  */
+
+                      if (x_use_underline_position_properties
+                          && s->font && s->font->underline_position >= 0)
+                        position = s->font->underline_position;
+                      else if (s->font)
+                        position = (s->font->descent + 1) / 2;
+                    }
+                  position = max (position, underline_minimum_offset);
+                }
+              /* Check the sanity of thickness and position.  We should
+                 avoid drawing underline out of the current line area.  */
+              if (s->y + s->height <= s->ybase + position)
+                position = (s->height - 1) - (s->ybase - s->y);
+              if (s->y + s->height < s->ybase + position + thickness)
+                thickness = (s->y + s->height) - (s->ybase + position);
+              s->underline_thickness = thickness;
+              s->underline_position =position;
+              y = s->ybase + position;
+              if (s->face->underline_defaulted_p)
+                {
+                  w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
+                                 y, s->width, 1);
+                }
+              else
+                {
+                  w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
+                                 y, s->width, 1);
+                }
             }
         }
       /* Draw overline.  */

=== modified file 'src/xfaces.c'
--- a/src/xfaces.c      2012-06-09 16:44:44 +0000
+++ b/src/xfaces.c      2012-06-17 00:32:36 +0000
@@ -320,6 +320,7 @@
 
 Lisp_Object Qnormal;
 Lisp_Object Qbold;
+static Lisp_Object Qline, Qwave;
 static Lisp_Object Qultra_light, Qextra_light, Qlight;
 static Lisp_Object Qsemi_light, Qsemi_bold, Qextra_bold, Qultra_bold;
 static Lisp_Object Qoblique, Qreverse_oblique, Qreverse_italic;
@@ -1894,7 +1895,8 @@
   xassert (UNSPECIFIEDP (attrs[LFACE_UNDERLINE_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_UNDERLINE_INDEX])
           || SYMBOLP (attrs[LFACE_UNDERLINE_INDEX])
-          || STRINGP (attrs[LFACE_UNDERLINE_INDEX]));
+          || STRINGP (attrs[LFACE_UNDERLINE_INDEX])
+          || CONSP (attrs[LFACE_UNDERLINE_INDEX]));
   xassert (UNSPECIFIEDP (attrs[LFACE_OVERLINE_INDEX])
           || IGNORE_DEFFACE_P (attrs[LFACE_OVERLINE_INDEX])
           || SYMBOLP (attrs[LFACE_OVERLINE_INDEX])
@@ -2525,7 +2527,8 @@
                {
                  if (EQ (value, Qt)
                      || NILP (value)
-                     || STRINGP (value))
+                     || STRINGP (value)
+                     || CONSP (value))
                    to[LFACE_UNDERLINE_INDEX] = value;
                  else
                    err = 1;
@@ -2948,15 +2951,54 @@
     }
   else if (EQ (attr, QCunderline))
     {
-      if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value))
-       if ((SYMBOLP (value)
-            && !EQ (value, Qt)
-            && !EQ (value, Qnil))
-           /* Underline color.  */
-           || (STRINGP (value)
-               && SCHARS (value) == 0))
-         signal_error ("Invalid face underline", value);
-
+      int valid_p = 0;
+      
+      if (UNSPECIFIEDP (value) || IGNORE_DEFFACE_P (value))
+       valid_p = 1;
+      else if (NILP (value) || EQ (value, Qt))
+        valid_p = 1;
+      else if (STRINGP (value) && SCHARS (value) > 0)
+        valid_p = 1;
+      else if (CONSP (value))
+        {
+          Lisp_Object key, val, list;
+
+          list = value;
+          valid_p = 1;
+
+          while (!NILP (CAR_SAFE(list)))
+            {
+              key = CAR_SAFE (list);
+              list = CDR_SAFE (list);
+              val = CAR_SAFE (list);
+              list = CDR_SAFE (list);
+            
+              if(NILP (key) || NILP (val)) 
+                {
+                  valid_p = 0;
+                  break;
+                }
+
+              else if (EQ (key, QCcolor)
+                       && !(EQ (val, Qforeground_color)
+                            || (STRINGP (val) && SCHARS (val) > 0)))
+                {
+                  valid_p = 0;
+                  break;
+                }
+              
+              else if (EQ (key, QCstyle) 
+                       && !(EQ (val, Qline) || EQ (val, Qwave)))
+                {
+                  valid_p = 0;
+                  break;
+                }
+            }
+        }
+      
+      if (!valid_p)
+        signal_error ("Invalid face underline", value);
+      
       old_value = LFACE_UNDERLINE (lface);
       LFACE_UNDERLINE (lface) = value;
     }
@@ -5576,7 +5618,7 @@
 #ifdef HAVE_WINDOW_SYSTEM
   struct face *default_face;
   struct frame *f;
-  Lisp_Object stipple, overline, strike_through, box;
+  Lisp_Object stipple, underline, overline, strike_through, box;
 
   xassert (FRAME_WINDOW_P (cache->f));
 
@@ -5709,29 +5751,76 @@
 
   /* Text underline, overline, strike-through.  */
 
-  if (EQ (attrs[LFACE_UNDERLINE_INDEX], Qt))
+  underline = attrs[LFACE_UNDERLINE_INDEX];
+  if (EQ (underline, Qt))
     {
       /* Use default color (same as foreground color).  */
       face->underline_p = 1;
+      face->underline_type = FACE_UNDER_LINE;
       face->underline_defaulted_p = 1;
       face->underline_color = 0;
     }
-  else if (STRINGP (attrs[LFACE_UNDERLINE_INDEX]))
+  else if (STRINGP (underline))
     {
       /* Use specified color.  */
       face->underline_p = 1;
+      face->underline_type = FACE_UNDER_LINE;
       face->underline_defaulted_p = 0;
       face->underline_color
-       = load_color (f, face, attrs[LFACE_UNDERLINE_INDEX],
+       = load_color (f, face, underline,
                      LFACE_UNDERLINE_INDEX);
     }
-  else if (NILP (attrs[LFACE_UNDERLINE_INDEX]))
+  else if (NILP (underline))
     {
       face->underline_p = 0;
       face->underline_defaulted_p = 0;
       face->underline_color = 0;
     }
-
+  else if (CONSP (underline))
+    {
+      /* `(:color COLOR :style STYLE)'.  
+         STYLE being one of `line' or `wave'. */
+      face->underline_p = 1;
+      face->underline_color = 0;
+      face->underline_defaulted_p = 1;
+      face->underline_type = FACE_UNDER_LINE;
+
+      while (CONSP (underline))
+        {
+          Lisp_Object keyword, value;
+
+          keyword = XCAR (underline);
+          underline = XCDR (underline);
+
+          if (!CONSP (underline))
+            break;
+          value = XCAR (underline);
+          underline = XCDR (underline);
+
+          if (EQ (keyword, QCcolor))
+            {
+              if (EQ (value, Qforeground_color))
+                {
+                  face->underline_defaulted_p = 1;
+                  face->underline_color = 0;
+                }
+              else if (STRINGP (value))
+                {
+                  face->underline_defaulted_p = 0;
+                  face->underline_color = load_color (f, face, value,
+                                                      LFACE_UNDERLINE_INDEX);
+                }
+            }
+          else if (EQ (keyword, QCstyle))
+            {
+              if (EQ (value, Qline))
+                face->underline_type = FACE_UNDER_LINE;
+              else if (EQ (value, Qwave))
+                face->underline_type = FACE_UNDER_WAVE;
+            }
+        }
+    }
+  
   overline = attrs[LFACE_OVERLINE_INDEX];
   if (STRINGP (overline))
     {
@@ -6476,6 +6565,8 @@
   DEFSYM (QCcolor, ":color");
   DEFSYM (QCline_width, ":line-width");
   DEFSYM (QCstyle, ":style");
+  DEFSYM (Qline, "line");
+  DEFSYM (Qwave, "wave");
   DEFSYM (Qreleased_button, "released-button");
   DEFSYM (Qpressed_button, "pressed-button");
   DEFSYM (Qnormal, "normal");

=== modified file 'src/xterm.c'
--- a/src/xterm.c       2012-05-31 06:51:43 +0000
+++ b/src/xterm.c       2012-06-17 00:32:36 +0000
@@ -2663,6 +2663,65 @@
   s->background_filled_p = 1;
 }
 
+/*
+   Draw a wavy line under S. The wave fills wave_height pixels from y0.
+
+                    x0         wave_length = 2
+                                 --
+                y0   *   *   *   *   *
+                     |* * * * * * * * *
+    wave_height = 3  | *   *   *   *
+
+*/
+
+static void
+x_draw_underwave (struct glyph_string *s)
+{
+  int wave_height = 2, wave_length = 3;
+  int dx, dy, x0, y0, width, x1, y1, x2, y2, odd, xmax;
+  XRectangle wave_clip, string_clip, final_clip;
+
+  dx = wave_length;
+  dy = wave_height - 1;
+  x0 = s->x;
+  y0 = s->ybase + 1;
+  width = s->width;
+  xmax = x0 + width;
+
+  /* Find and set clipping rectangle */
+
+  wave_clip = (XRectangle){ x0, y0, width, wave_height };
+  get_glyph_string_clip_rect (s, &string_clip);
+
+  if (!x_intersect_rectangles (&wave_clip, &string_clip, &final_clip))
+    return;
+
+  XSetClipRectangles (s->display, s->gc, 0, 0, &final_clip, 1, Unsorted);
+
+  /* Draw the waves */
+
+  x1 = x0 - (x0 % dx);
+  x2 = x1 + dx;
+  odd = (x1/dx) % 2;
+  y1 = y2 = y0;
+
+  if (odd)
+    y1 += dy;
+  else
+    y2 += dy;
+
+  while (x1 <= xmax)
+    {
+      XDrawLine (s->display, s->window, s->gc, x1, y1, x2, y2);
+      x1  = x2, y1 = y2;
+      x2 += dx, y2 = y0 + odd*dy;
+      odd = !odd;
+    }
+
+  /* Restore previous clipping rectangle(s) */
+  XSetClipRectangles (s->display, s->gc, 0, 0, s->clip, s->num_clips, 
Unsorted);
+}
+
 
 /* Draw glyph string S.  */
 
@@ -2765,68 +2824,83 @@
     {
       /* Draw underline.  */
       if (s->face->underline_p)
-       {
-         unsigned long thickness, position;
-         int y;
-
-         if (s->prev && s->prev->face->underline_p)
-           {
-             /* We use the same underline style as the previous one.  */
-             thickness = s->prev->underline_thickness;
-             position = s->prev->underline_position;
-           }
-         else
-           {
-             /* Get the underline thickness.  Default is 1 pixel.  */
-             if (s->font && s->font->underline_thickness > 0)
-               thickness = s->font->underline_thickness;
-             else
-               thickness = 1;
-             if (x_underline_at_descent_line)
-               position = (s->height - thickness) - (s->ybase - s->y);
-             else
-               {
-                 /* Get the underline position.  This is the recommended
-                    vertical offset in pixels from the baseline to the top of
-                    the underline.  This is a signed value according to the
-                    specs, and its default is
-
-                    ROUND ((maximum descent) / 2), with
-                    ROUND(x) = floor (x + 0.5)  */
-
-                 if (x_use_underline_position_properties
-                     && s->font && s->font->underline_position >= 0)
-                   position = s->font->underline_position;
-                 else if (s->font)
-                   position = (s->font->descent + 1) / 2;
-                 else
-                   position = underline_minimum_offset;
-               }
-             position = max (position, underline_minimum_offset);
-           }
-         /* Check the sanity of thickness and position.  We should
-            avoid drawing underline out of the current line area.  */
-         if (s->y + s->height <= s->ybase + position)
-           position = (s->height - 1) - (s->ybase - s->y);
-         if (s->y + s->height < s->ybase + position + thickness)
-           thickness = (s->y + s->height) - (s->ybase + position);
-         s->underline_thickness = thickness;
-         s->underline_position = position;
-         y = s->ybase + position;
-         if (s->face->underline_defaulted_p)
-           XFillRectangle (s->display, s->window, s->gc,
-                           s->x, y, s->width, thickness);
-         else
-           {
-             XGCValues xgcv;
-             XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
-             XSetForeground (s->display, s->gc, s->face->underline_color);
-             XFillRectangle (s->display, s->window, s->gc,
-                             s->x, y, s->width, thickness);
-             XSetForeground (s->display, s->gc, xgcv.foreground);
-           }
-       }
-
+        {
+          if (s->face->underline_type == FACE_UNDER_WAVE)
+            {
+              if (s->face->underline_defaulted_p)
+                x_draw_underwave (s);
+              else
+                {
+                  XGCValues xgcv;
+                  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+                  XSetForeground (s->display, s->gc, s->face->underline_color);
+                  x_draw_underwave (s);
+                  XSetForeground (s->display, s->gc, xgcv.foreground);
+                }
+            }
+          else if (s->face->underline_type == FACE_UNDER_LINE)
+            {
+              unsigned long thickness, position;
+              int y;
+
+              if (s->prev && s->prev->face->underline_p)
+                {
+                  /* We use the same underline style as the previous one.  */
+                  thickness = s->prev->underline_thickness;
+                  position = s->prev->underline_position;
+                }
+              else
+                {
+                  /* Get the underline thickness.  Default is 1 pixel.  */
+                  if (s->font && s->font->underline_thickness > 0)
+                    thickness = s->font->underline_thickness;
+                  else
+                    thickness = 1;
+                  if (x_underline_at_descent_line)
+                    position = (s->height - thickness) - (s->ybase - s->y);
+                  else
+                    {
+                      /* Get the underline position.  This is the recommended
+                         vertical offset in pixels from the baseline to the 
top of
+                         the underline.  This is a signed value according to 
the
+                         specs, and its default is
+
+                         ROUND ((maximum descent) / 2), with
+                         ROUND(x) = floor (x + 0.5)  */
+
+                      if (x_use_underline_position_properties
+                          && s->font && s->font->underline_position >= 0)
+                        position = s->font->underline_position;
+                      else if (s->font)
+                        position = (s->font->descent + 1) / 2;
+                      else
+                        position = underline_minimum_offset;
+                    }
+                  position = max (position, underline_minimum_offset);
+                }
+              /* Check the sanity of thickness and position.  We should
+                 avoid drawing underline out of the current line area.  */
+              if (s->y + s->height <= s->ybase + position)
+                position = (s->height - 1) - (s->ybase - s->y);
+              if (s->y + s->height < s->ybase + position + thickness)
+                thickness = (s->y + s->height) - (s->ybase + position);
+              s->underline_thickness = thickness;
+              s->underline_position = position;
+              y = s->ybase + position;
+              if (s->face->underline_defaulted_p)
+                XFillRectangle (s->display, s->window, s->gc,
+                                s->x, y, s->width, thickness);
+              else
+                {
+                  XGCValues xgcv;
+                  XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
+                  XSetForeground (s->display, s->gc, s->face->underline_color);
+                  XFillRectangle (s->display, s->window, s->gc,
+                                  s->x, y, s->width, thickness);
+                  XSetForeground (s->display, s->gc, xgcv.foreground);
+                }
+            }
+        }
       /* Draw overline.  */
       if (s->face->overline_p)
        {


reply via email to

[Prev in Thread] Current Thread [Next in Thread]