emacs-devel
[Top][All Lists]
Advanced

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

Re: Tick Reduction


From: Lars Ingebrigtsen
Subject: Re: Tick Reduction
Date: Mon, 22 Nov 2021 09:19:59 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/29.0.50 (gnu/linux)

I wondered whether it'd be much work to implement a min-width thing for
a sequence of characters.  So with this

(insert "||" (propertize "foo" 'min-width '(10.0)) "||")

and the proof of concept patch (it needs some more sanity checking)
below I get:

PNG image

which seems promising.  However, point movement over the stretch glyph
is very wonky -- Emacs basically refuses to put point after that
stretch glyph.

Anybody got any tips on what I need to do to get point movement working
here?

diff --git a/src/dispextern.h b/src/dispextern.h
index a698f6546b..a78be900db 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2185,6 +2185,8 @@ #define MAX_FRINGE_BITMAPS (1<<FRINGE_ID_BITS)
   /* Not a property.  Used to indicate changes in overlays.  */
   OVERLAY_PROP_IDX,
 
+  MIN_WIDTH_PROP_IDX,
+
   /* Sentinel.  */
   LAST_PROP_IDX
 };
@@ -2746,6 +2748,12 @@ #define OVERLAY_STRING_CHUNK_SIZE 16
   /* For iterating over bidirectional text.  */
   struct bidi_it bidi_it;
   bidi_dir_t paragraph_embedding;
+
+  /* For handling the :min-width property.  The object is the text
+     property we're testing the `eq' of (nil if none), and the integer
+     is the x position of the start of the run of glyphs. */
+  Lisp_Object min_width_property;
+  int min_width_start;
 };
 
 
diff --git a/src/xdisp.c b/src/xdisp.c
index 8d34b7c4c3..83f1f64fec 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -822,6 +822,10 @@ #define RESTORE_IT(pITORIG, pITCOPY, CACHE)        \
 /* Functions to mark elements as needing redisplay.  */
 enum { REDISPLAY_SOME = 2};    /* Arbitrary choice.  */
 
+static bool
+calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
+                           struct font *, bool, int *);
+
 void
 redisplay_other_windows (void)
 {
@@ -969,6 +973,7 @@ move_trace (char const *fmt, ...)
 static enum prop_handled handle_composition_prop (struct it *);
 static enum prop_handled handle_overlay_change (struct it *);
 static enum prop_handled handle_fontified_prop (struct it *);
+static enum prop_handled handle_min_width_prop (struct it *);
 
 /* Properties handled by iterators.  */
 
@@ -981,6 +986,7 @@ move_trace (char const *fmt, ...)
   {SYMBOL_INDEX (Qdisplay),    DISPLAY_PROP_IDX,       handle_display_prop},
   {SYMBOL_INDEX (Qinvisible),  INVISIBLE_PROP_IDX,     handle_invisible_prop},
   {SYMBOL_INDEX (Qcomposition),        COMPOSITION_PROP_IDX, 
handle_composition_prop},
+  {SYMBOL_INDEX (Qmin_width),  MIN_WIDTH_PROP_IDX,     handle_min_width_prop},
   {0,                          0,                      NULL}
 };
 
@@ -5141,6 +5147,81 @@ setup_for_ellipsis (struct it *it, int len)
   it->ellipsis_p = true;
 }
 
+
+/***********************************************************************
+                           `min-width' property
+ ***********************************************************************/
+
+/* Set up iterator IT from `min-width' property at its current position.
+   Called from handle_stop.  */
+
+static enum prop_handled
+handle_min_width_prop (struct it *it)
+{
+  if (STRINGP (it->string) || !it->glyph_row)
+    return HANDLED_NORMALLY;
+
+  Lisp_Object buffer = it->w->contents;
+  struct text_pos *position = &it->current.pos;
+  ptrdiff_t bufpos = CHARPOS (*position);
+
+  Lisp_Object propval = Fget_text_property (make_fixnum (bufpos),
+                                           Qmin_width, buffer);
+  /* We're being called at the end of the `min-width' sequence,
+     probably. */
+  if (NILP (propval))
+    {
+      /* Check that we're really right after the sequence of
+        characters covered by this `min-width'.  */
+      if (!NILP (it->min_width_property)
+         && bufpos > BEGV
+         && EQ (it->min_width_property,
+                Fget_text_property (make_fixnum (bufpos - 1),
+                                    Qmin_width, buffer)))
+       {
+         struct font *font = NULL;
+         double width;
+         if (FRAME_WINDOW_P (it->f))
+           {
+#ifdef HAVE_WINDOW_SYSTEM
+             struct face *face = FACE_FROM_ID (it->f, it->face_id);
+             font = face->font ? face->font : FRAME_FONT (it->f);
+             const int stretch_ascent =
+               (((it->ascent + it->descent)
+                 * FONT_BASE (font)) / FONT_HEIGHT (font));
+             prepare_face_for_display (it->f, face);
+#else
+             struct face *face = NULL;
+#endif
+             calc_pixel_width_or_height (&width, it,
+                                         XCAR (it->min_width_property),
+                                         font, true, NULL);
+             width -= it->current_x - it->min_width_start;
+             append_stretch_glyph (it, Qnil,
+                                   (int)width,
+                                   it->ascent + it->descent,
+                                   stretch_ascent);
+             it->min_width_property = Qnil;
+           }
+       }
+    }
+  /* We're at the start of a `min-width' sequence -- record the
+     position and the property, so that we can later see if we're at
+     the end.  */
+  else if (CONSP (propval) && NUMBERP (XCAR (propval)))
+    {
+      if (bufpos == BEGV
+         || (bufpos > BEGV
+             && !EQ (propval, Fget_text_property (make_fixnum (bufpos - 1),
+                                                  Qmin_width, buffer))))
+       {
+         it->min_width_property = propval;
+         it->min_width_start = it->current_x;
+       }
+    }
+  return HANDLED_NORMALLY;
+}
+
 
 
 /***********************************************************************
@@ -7186,6 +7267,7 @@ reseat_1 (struct it *it, struct text_pos pos, bool 
set_stop_p)
     }
   /* This make the information stored in it->cmp_it invalidate.  */
   it->cmp_it.id = -1;
+  it->min_width_property = Qnil;
 }
 
 

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no


reply via email to

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