]> code.delx.au - gnu-emacs/blobdiff - src/xdisp.c
Fix cursor movement in R2L text within L2R paragraphs.
[gnu-emacs] / src / xdisp.c
index fa4b3c4f9ab10925976b85eeb13de2d22ce85f52..4ed08e72e19e4d19573f1d0e20c87146fdd38800 100644 (file)
@@ -604,7 +604,7 @@ int current_mode_line_height, current_header_line_height;
 #define SAVE_IT(ITCOPY,ITORIG,CACHE)           \
   do {                                         \
     if (CACHE)                                 \
-      xfree (CACHE);                           \
+      bidi_unshelve_cache (CACHE, 1);          \
     ITCOPY = ITORIG;                           \
     CACHE = bidi_shelve_cache();               \
   } while (0)
@@ -613,7 +613,7 @@ int current_mode_line_height, current_header_line_height;
   do {                                         \
     if (pITORIG != pITCOPY)                    \
       *(pITORIG) = *(pITCOPY);                 \
-    bidi_unshelve_cache (CACHE);               \
+    bidi_unshelve_cache (CACHE, 0);            \
     CACHE = NULL;                              \
   } while (0)
 
@@ -1341,9 +1341,9 @@ pos_visible_p (struct window *w, EMACS_INT charpos, int *x, int *y,
          *vpos = it2.vpos;
        }
       else
-       xfree (it2data);
+       bidi_unshelve_cache (it2data, 1);
     }
-  bidi_unshelve_cache (itdata);
+  bidi_unshelve_cache (itdata, 0);
 
   if (old_buffer)
     set_buffer_internal_1 (old_buffer);
@@ -2627,7 +2627,7 @@ init_iterator (struct it *it, struct window *w,
            it->paragraph_embedding = R2L;
          else
            it->paragraph_embedding = NEUTRAL_DIR;
-         bidi_unshelve_cache (NULL);
+         bidi_unshelve_cache (NULL, 0);
          bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
                        &it->bidi_it);
        }
@@ -3163,7 +3163,6 @@ compute_display_string_pos (struct text_pos *position,
   EMACS_INT lim =
     (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
   struct text_pos tpos;
-  struct buffer *b;
 
   *disp_prop_p = 1;
 
@@ -5327,6 +5326,8 @@ iterate_out_of_display_property (struct it *it)
   EMACS_INT eob = (buffer_p ? ZV : it->end_charpos);
   EMACS_INT bob = (buffer_p ? BEGV : 0);
 
+  xassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
+
   /* Maybe initialize paragraph direction.  If we are at the beginning
      of a new paragraph, next_element_from_buffer may not have a
      chance to do that.  */
@@ -5335,7 +5336,8 @@ iterate_out_of_display_property (struct it *it)
   /* prev_stop can be zero, so check against BEGV as well.  */
   while (it->bidi_it.charpos >= bob
         && it->prev_stop <= it->bidi_it.charpos
-        && it->bidi_it.charpos < CHARPOS (it->position))
+        && it->bidi_it.charpos < CHARPOS (it->position)
+        && it->bidi_it.charpos < eob)
     bidi_move_to_visually_next (&it->bidi_it);
   /* Record the stop_pos we just crossed, for when we cross it
      back, maybe.  */
@@ -5344,14 +5346,11 @@ iterate_out_of_display_property (struct it *it)
   /* If we ended up not where pop_it put us, resync IT's
      positional members with the bidi iterator. */
   if (it->bidi_it.charpos != CHARPOS (it->position))
-    {
-      SET_TEXT_POS (it->position,
-                   it->bidi_it.charpos, it->bidi_it.bytepos);
-      if (buffer_p)
-       it->current.pos = it->position;
-      else
-       it->current.string_pos = it->position;
-    }
+    SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
+  if (buffer_p)
+    it->current.pos = it->position;
+  else
+    it->current.string_pos = it->position;
 }
 
 /* Restore IT's settings from IT->stack.  Called, for example, when no
@@ -5533,19 +5532,42 @@ forward_to_next_line_start (struct it *it, int *skipped_p,
 
       xassert (!STRINGP (it->string));
 
-      /* If we are not bidi-reordering, and there isn't any `display'
-        property in sight, and no overlays, we can just use the
-        position of the newline in buffer text.  */
-      if (!it->bidi_p
-         && (it->stop_charpos >= limit
-             || ((pos = Fnext_single_property_change (make_number (start),
-                                                      Qdisplay, Qnil,
-                                                      make_number (limit)),
-                  NILP (pos))
-                 && next_overlay_change (start) == ZV)))
-       {
-         IT_CHARPOS (*it) = limit;
-         IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
+      /* If there isn't any `display' property in sight, and no
+        overlays, we can just use the position of the newline in
+        buffer text.  */
+      if (it->stop_charpos >= limit
+         || ((pos = Fnext_single_property_change (make_number (start),
+                                                  Qdisplay, Qnil,
+                                                  make_number (limit)),
+              NILP (pos))
+             && next_overlay_change (start) == ZV))
+       {
+         if (!it->bidi_p)
+           {
+             IT_CHARPOS (*it) = limit;
+             IT_BYTEPOS (*it) = CHAR_TO_BYTE (limit);
+           }
+         else
+           {
+             struct bidi_it bprev;
+
+             /* Help bidi.c avoid expensive searches for display
+                properties and overlays, by telling it that there are
+                none up to `limit'.  */
+             if (it->bidi_it.disp_pos < limit)
+               {
+                 it->bidi_it.disp_pos = limit;
+                 it->bidi_it.disp_prop_p = 0;
+               }
+             do {
+               bprev = it->bidi_it;
+               bidi_move_to_visually_next (&it->bidi_it);
+             } while (it->bidi_it.charpos != limit);
+             IT_CHARPOS (*it) = limit;
+             IT_BYTEPOS (*it) = it->bidi_it.bytepos;
+             if (bidi_it_prev)
+               *bidi_it_prev = bprev;
+           }
          *skipped_p = newline_found_p = 1;
        }
       else
@@ -5619,7 +5641,7 @@ back_to_previous_visible_line_start (struct it *it)
        pos = --IT_CHARPOS (it2);
        --IT_BYTEPOS (it2);
        it2.sp = 0;
-       bidi_unshelve_cache (NULL);
+       bidi_unshelve_cache (NULL, 0);
        it2.string_from_display_prop_p = 0;
        it2.from_disp_prop_p = 0;
        if (handle_display_prop (&it2) == HANDLED_RETURN
@@ -5829,7 +5851,7 @@ reseat_1 (struct it *it, struct text_pos pos, int set_stop_p)
     {
       bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
                    &it->bidi_it);
-      bidi_unshelve_cache (NULL);
+      bidi_unshelve_cache (NULL, 0);
       it->bidi_it.paragraph_dir = NEUTRAL_DIR;
       it->bidi_it.string.s = NULL;
       it->bidi_it.string.lstring = Qnil;
@@ -7677,7 +7699,12 @@ move_it_in_display_line_to (struct it *it,
   ((op & MOVE_TO_POS) != 0                                     \
    && BUFFERP (it->object)                                     \
    && (IT_CHARPOS (*it) == to_charpos                          \
-       || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos))      \
+       || (!it->bidi_p && IT_CHARPOS (*it) > to_charpos)       \
+       || (it->what == IT_COMPOSITION                          \
+          && ((IT_CHARPOS (*it) > to_charpos                   \
+               && to_charpos >= it->cmp_it.charpos)            \
+              || (IT_CHARPOS (*it) < to_charpos                \
+                  && to_charpos <= it->cmp_it.charpos))))      \
    && (it->method == GET_FROM_BUFFER                           \
        || (it->method == GET_FROM_DISPLAY_VECTOR               \
           && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
@@ -8010,13 +8037,23 @@ move_it_in_display_line_to (struct it *it,
             positions smaller than TO_CHARPOS, return
             MOVE_POS_MATCH_OR_ZV, like the unidirectional display
             did.  */
-         if ((op & MOVE_TO_POS) != 0
-             && !saw_smaller_pos
-             && IT_CHARPOS (*it) > to_charpos)
+         if (it->bidi_p && (op & MOVE_TO_POS) != 0)
            {
-             result = MOVE_POS_MATCH_OR_ZV;
-             if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
-               RESTORE_IT (it, &ppos_it, ppos_data);
+             if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
+               {
+                 if (IT_CHARPOS (ppos_it) < ZV)
+                   {
+                     RESTORE_IT (it, &ppos_it, ppos_data);
+                     result = MOVE_POS_MATCH_OR_ZV;
+                   }
+                 else
+                   goto buffer_pos_reached;
+               }
+             else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
+                      && IT_CHARPOS (*it) > to_charpos)
+               goto buffer_pos_reached;
+             else
+               result = MOVE_NEWLINE_OR_CR;
            }
          else
            result = MOVE_NEWLINE_OR_CR;
@@ -8055,13 +8092,13 @@ move_it_in_display_line_to (struct it *it,
                     character positions smaller than TO_CHARPOS,
                     return MOVE_POS_MATCH_OR_ZV, like the
                     unidirectional display did.  */
-                 || ((op & MOVE_TO_POS) != 0
+                 || (it->bidi_p && (op & MOVE_TO_POS) != 0
                      && !saw_smaller_pos
                      && IT_CHARPOS (*it) > to_charpos))
                {
-                 result = MOVE_POS_MATCH_OR_ZV;
-                 if (it->bidi_p && !at_eob_p && IT_CHARPOS (ppos_it) < ZV)
+                 if (!at_eob_p && IT_CHARPOS (ppos_it) < ZV)
                    RESTORE_IT (it, &ppos_it, ppos_data);
+                 result = MOVE_POS_MATCH_OR_ZV;
                  break;
                }
              if (ITERATOR_AT_END_OF_LINE_P (it))
@@ -8070,13 +8107,13 @@ move_it_in_display_line_to (struct it *it,
                  break;
                }
            }
-         else if ((op & MOVE_TO_POS) != 0
+         else if (it->bidi_p && (op & MOVE_TO_POS) != 0
                   && !saw_smaller_pos
                   && IT_CHARPOS (*it) > to_charpos)
            {
-             result = MOVE_POS_MATCH_OR_ZV;
-             if (it->bidi_p && IT_CHARPOS (ppos_it) < ZV)
+             if (IT_CHARPOS (ppos_it) < ZV)
                RESTORE_IT (it, &ppos_it, ppos_data);
+             result = MOVE_POS_MATCH_OR_ZV;
              break;
            }
          result = MOVE_LINE_TRUNCATED;
@@ -8097,13 +8134,13 @@ move_it_in_display_line_to (struct it *it,
  done:
 
   if (atpos_data)
-    xfree (atpos_data);
+    bidi_unshelve_cache (atpos_data, 1);
   if (atx_data)
-    xfree (atx_data);
+    bidi_unshelve_cache (atx_data, 1);
   if (wrap_data)
-    xfree (wrap_data);
+    bidi_unshelve_cache (wrap_data, 1);
   if (ppos_data)
-    xfree (ppos_data);
+    bidi_unshelve_cache (ppos_data, 1);
 
   /* Restore the iterator settings altered at the beginning of this
      function.  */
@@ -8138,7 +8175,7 @@ move_it_in_display_line (struct it *it,
            (it, -1, prev_x, MOVE_TO_X);
        }
       else
-       xfree (save_data);
+       bidi_unshelve_cache (save_data, 1);
     }
   else
     move_it_in_display_line_to (it, to_charpos, to_x, op);
@@ -8397,7 +8434,7 @@ move_it_to (struct it *it, EMACS_INT to_charpos, int to_x, int to_y, int to_vpos
     }
 
   if (backup_data)
-    xfree (backup_data);
+    bidi_unshelve_cache (backup_data, 1);
 
   TRACE_MOVE ((stderr, "move_it_to: reached %d\n", reached));
 }
@@ -8476,7 +8513,7 @@ move_it_vertically_backward (struct it *it, int dy)
       RESTORE_IT (it, it, it2data);
       if (nlines > 0)
        move_it_by_lines (it, nlines);
-      xfree (it3data);
+      bidi_unshelve_cache (it3data, 1);
     }
   else
     {
@@ -8672,7 +8709,7 @@ move_it_by_lines (struct it *it, int dvpos)
          if (IT_CHARPOS (*it) >= start_charpos)
            RESTORE_IT (it, &it2, it2data);
          else
-           xfree (it2data);
+           bidi_unshelve_cache (it2data, 1);
        }
       else
        RESTORE_IT (it, it, it2data);
@@ -13288,6 +13325,9 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
   /* Last buffer position covered by an overlay string with an integer
      `cursor' property.  */
   EMACS_INT bpos_covered = 0;
+  /* Non-zero means the display string on which to display the cursor
+     comes from a text property, not from an overlay.  */
+  int string_from_text_prop = 0;
 
   /* Skip over glyphs not having an object at the start and the end of
      the row.  These are special glyphs like truncation marks on
@@ -13606,9 +13646,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                {
                  Lisp_Object str;
                  EMACS_INT tem;
+                 /* If the display property covers the newline, we
+                    need to search for it one position farther.  */
+                 EMACS_INT lim = pos_after
+                   + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
 
+                 string_from_text_prop = 0;
                  str = glyph->object;
-                 tem = string_buffer_position_lim (str, pos, pos_after, 0);
+                 tem = string_buffer_position_lim (str, pos, lim, 0);
                  if (tem == 0  /* from overlay */
                      || pos <= tem)
                    {
@@ -13632,7 +13677,10 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
                          EMACS_INT strpos = glyph->charpos;
 
                          if (tem)
-                           cursor = glyph;
+                           {
+                             cursor = glyph;
+                             string_from_text_prop = 1;
+                           }
                          for ( ;
                               (row->reversed_p ? glyph > stop : glyph < stop)
                                 && EQ (glyph->object, str);
@@ -13707,14 +13755,14 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
       w->cursor.vpos >= 0
       /* that candidate is not the row we are processing */
       && MATRIX_ROW (matrix, w->cursor.vpos) != row
-      /* the row we are processing is part of a continued line */
-      && (row->continued_p || MATRIX_ROW_CONTINUATION_LINE_P (row))
       /* Make sure cursor.vpos specifies a row whose start and end
-        charpos occlude point.  This is because some callers of this
-        function leave cursor.vpos at the row where the cursor was
-        displayed during the last redisplay cycle.  */
+        charpos occlude point, and it is valid candidate for being a
+        cursor-row.  This is because some callers of this function
+        leave cursor.vpos at the row where the cursor was displayed
+        during the last redisplay cycle.  */
       && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
-      && pt_old < MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)))
+      && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
+      && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
     {
       struct glyph *g1 =
        MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
@@ -13723,18 +13771,39 @@ set_cursor_from_row (struct window *w, struct glyph_row *row,
       if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
        return 0;
       /* Keep the candidate whose buffer position is the closest to
-        point.  */
+        point or has the `cursor' property.  */
       if (/* previous candidate is a glyph in TEXT_AREA of that row */
          w->cursor.hpos >= 0
          && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
-         && BUFFERP (g1->object)
-         && (g1->charpos == pt_old /* an exact match always wins */
-             || (BUFFERP (glyph->object)
-                 && eabs (g1->charpos - pt_old)
-                  < eabs (glyph->charpos - pt_old))))
+         && ((BUFFERP (g1->object)
+              && (g1->charpos == pt_old /* an exact match always wins */
+                  || (BUFFERP (glyph->object)
+                      && eabs (g1->charpos - pt_old)
+                      < eabs (glyph->charpos - pt_old))))
+             /* previous candidate is a glyph from a string that has
+                a non-nil `cursor' property */
+             || (STRINGP (g1->object)
+                 && (!NILP (Fget_char_property (make_number (g1->charpos),
+                                               Qcursor, g1->object))
+                     /* pevious candidate is from the same display
+                        string as this one, and the display string
+                        came from a text property */
+                     || (EQ (g1->object, glyph->object)
+                         && string_from_text_prop)
+                     /* this candidate is from newline and its
+                        position is not an exact match */
+                     || (INTEGERP (glyph->object)
+                         && glyph->charpos != pt_old)))))
        return 0;
       /* If this candidate gives an exact match, use that.  */
-      if (!(BUFFERP (glyph->object) && glyph->charpos == pt_old)
+      if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
+           /* If this candidate is a glyph created for the
+              terminating newline of a line, and point is on that
+              newline, it wins because it's an exact match.  */
+           || (!row->continued_p
+               && INTEGERP (glyph->object)
+               && glyph->charpos == 0
+               && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
          /* Otherwise, keep the candidate that comes from a row
             spanning less buffer positions.  This may win when one or
             both candidate positions are on glyphs that came from
@@ -14516,7 +14585,8 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp, int *scroll_ste
                    }
                  ++row;
                }
-             while ((MATRIX_ROW_CONTINUATION_LINE_P (row)
+             while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
+                      || row->continued_p)
                      && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
                     || (MATRIX_ROW_START_CHARPOS (row) == PT
                         && MATRIX_ROW_BOTTOM_Y (row) < last_y));
@@ -15182,7 +15252,8 @@ redisplay_window (Lisp_Object window, int just_this_one_p)
              if (pt_offset)
                centering_position -= pt_offset;
              centering_position -=
-               FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0));
+               FRAME_LINE_HEIGHT (f) * (1 + margin + (last_line_misfit != 0))
+               + WINDOW_HEADER_LINE_HEIGHT (w);
              /* Don't let point enter the scroll margin near top of
                 the window.  */
              if (centering_position < margin * FRAME_LINE_HEIGHT (f))
@@ -17946,7 +18017,8 @@ cursor_row_p (struct glyph_row *row)
 {
   int result = 1;
 
-  if (PT == CHARPOS (row->end.pos))
+  if (PT == CHARPOS (row->end.pos)
+      || PT == MATRIX_ROW_END_CHARPOS (row))
     {
       /* Suppose the row ends on a string.
         Unless the row is continued, that means it ends on a newline
@@ -18007,16 +18079,25 @@ cursor_row_p (struct glyph_row *row)
 
 \f
 
-/* Push the display property PROP so that it will be rendered at the
-   current position in IT.  Return 1 if PROP was successfully pushed,
-   0 otherwise.  */
+/* Push the property PROP so that it will be rendered at the current
+   position in IT.  Return 1 if PROP was successfully pushed, 0
+   otherwise.  Called from handle_line_prefix to handle the
+   `line-prefix' and `wrap-prefix' properties.  */
 
 static int
 push_display_prop (struct it *it, Lisp_Object prop)
 {
-  xassert (it->method == GET_FROM_BUFFER);
+  struct text_pos pos =
+    (it->method == GET_FROM_STRING) ? it->current.string_pos : it->current.pos;
 
-  push_it (it, NULL);
+  xassert (it->method == GET_FROM_BUFFER
+          || it->method == GET_FROM_STRING);
+
+  /* We need to save the current buffer/string position, so it will be
+     restored by pop_it, because iterate_out_of_display_property
+     depends on that being set correctly, but some situations leave
+     it->position not yet set when this function is called.  */
+  push_it (it, &pos);
 
   if (STRINGP (prop))
     {
@@ -18035,11 +18116,9 @@ push_display_prop (struct it *it, Lisp_Object prop)
       it->stop_charpos = 0;
       it->prev_stop = 0;
       it->base_level_stop = 0;
-      it->string_from_display_prop_p = 1;
-      it->from_disp_prop_p = 1;
 
       /* Force paragraph direction to be that of the parent
-        buffer.  */
+        buffer/string.  */
       if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
        it->paragraph_embedding = it->bidi_it.paragraph_dir;
       else
@@ -18052,7 +18131,7 @@ push_display_prop (struct it *it, Lisp_Object prop)
          it->bidi_it.string.s = NULL;
          it->bidi_it.string.schars = it->end_charpos;
          it->bidi_it.string.bufpos = IT_CHARPOS (*it);
-         it->bidi_it.string.from_disp_str = 1;
+         it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
          it->bidi_it.string.unibyte = !it->multibyte_p;
          bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
        }
@@ -18322,15 +18401,22 @@ display_line (struct it *it)
 #define RECORD_MAX_MIN_POS(IT)                                 \
   do                                                           \
     {                                                          \
-      if (IT_CHARPOS (*(IT)) < min_pos)                                \
+      int composition_p = (IT)->what == IT_COMPOSITION;                \
+      EMACS_INT current_pos =                                  \
+       composition_p ? (IT)->cmp_it.charpos                    \
+                     : IT_CHARPOS (*(IT));                     \
+      EMACS_INT current_bpos =                                 \
+       composition_p ? CHAR_TO_BYTE (current_pos)              \
+                     : IT_BYTEPOS (*(IT));                     \
+      if (current_pos < min_pos)                               \
        {                                                       \
-         min_pos = IT_CHARPOS (*(IT));                         \
-         min_bpos = IT_BYTEPOS (*(IT));                        \
+         min_pos = current_pos;                                \
+         min_bpos = current_bpos;                              \
        }                                                       \
-      if (IT_CHARPOS (*(IT)) > max_pos)                                \
+      if (IT_CHARPOS (*it) > max_pos)                          \
        {                                                       \
-         max_pos = IT_CHARPOS (*(IT));                         \
-         max_bpos = IT_BYTEPOS (*(IT));                        \
+         max_pos = IT_CHARPOS (*it);                           \
+         max_bpos = IT_BYTEPOS (*it);                          \
        }                                                       \
     }                                                          \
   while (0)
@@ -18777,6 +18863,9 @@ display_line (struct it *it)
        }
     }
 
+  if (wrap_data)
+    bidi_unshelve_cache (wrap_data, 1);
+
   /* If line is not empty and hscrolled, maybe insert truncation glyphs
      at the left window margin.  */
   if (it->first_visible_x
@@ -18934,7 +19023,8 @@ See also `bidi-paragraph-direction'.  */)
       buf = XBUFFER (buffer);
     }
 
-  if (NILP (BVAR (buf, bidi_display_reordering)))
+  if (NILP (BVAR (buf, bidi_display_reordering))
+      || NILP (BVAR (buf, enable_multibyte_characters)))
     return Qleft_to_right;
   else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
     return BVAR (buf, bidi_paragraph_direction);
@@ -23985,6 +24075,8 @@ x_produce_glyphs (struct it *it)
       Lisp_Object gstring;
       struct font_metrics metrics;
 
+      it->nglyphs = 1;
+
       gstring = composition_gstring_from_id (it->cmp_it.id);
       it->pixel_width
        = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,