use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / composite.c
index ddd9238..b75ac99 100644 (file)
@@ -1,5 +1,5 @@
 /* Composite sequence support.
-   Copyright (C) 2001-2013 Free Software Foundation, Inc.
+   Copyright (C) 2001-2014 Free Software Foundation, Inc.
    Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H14PRO021
@@ -24,8 +24,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#define COMPOSITE_INLINE EXTERN_INLINE
-
 #include "lisp.h"
 #include "character.h"
 #include "buffer.h"
@@ -160,10 +158,6 @@ static Lisp_Object Qauto_composition_function;
    auto-compositions.  */
 #define MAX_AUTO_COMPOSITION_LOOKBACK 3
 
-/* Temporary variable used in macros COMPOSITION_XXX.  */
-Lisp_Object composition_temp;
-
-\f
 /* Return COMPOSITION-ID of a composition at buffer position
    CHARPOS/BYTEPOS and length NCHARS.  The `composition' property of
    the sequence is PROP.  STRING, if non-nil, is a string that
@@ -234,7 +228,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars,
     key = components;
   else if (NILP (components))
     {
-      key = Fmake_vector (make_number (nchars), Qnil);
+      key = make_uninit_vector (nchars);
       if (STRINGP (string))
        for (i = 0; i < nchars; i++)
          {
@@ -333,7 +327,7 @@ get_composition_id (ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t nchars,
   cmp->method = method;
   cmp->hash_index = hash_index;
   cmp->glyph_len = glyph_len;
-  cmp->offsets = xnmalloc (glyph_len, 2 * sizeof *cmp->offsets);
+  cmp->offsets = xnmalloc_atomic (glyph_len, 2 * sizeof *cmp->offsets);
   cmp->font = NULL;
 
   if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
@@ -478,11 +472,11 @@ run_composition_function (ptrdiff_t from, ptrdiff_t to, Lisp_Object prop)
      valid too.  */
   if (from > BEGV
       && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
-      && !COMPOSITION_VALID_P (start, end, prop))
+      && !composition_valid_p (start, end, prop))
     from = start;
   if (to < ZV
       && find_composition (to, -1, &start, &end, &prop, Qnil)
-      && !COMPOSITION_VALID_P (start, end, prop))
+      && !composition_valid_p (start, end, prop))
     to = end;
   if (!NILP (Ffboundp (func)))
     call2 (func, make_number (from), make_number (to));
@@ -524,7 +518,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
         latter to the copy of it.  */
       if (from > BEGV
          && find_composition (from - 1, -1, &start, &end, &prop, Qnil)
-         && COMPOSITION_VALID_P (start, end, prop))
+         && composition_valid_p (start, end, prop))
        {
          min_pos = start;
          if (end > to)
@@ -538,7 +532,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
        }
       else if (from < ZV
               && find_composition (from, -1, &start, &from, &prop, Qnil)
-              && COMPOSITION_VALID_P (start, from, prop))
+              && composition_valid_p (start, from, prop))
        {
          if (from > to)
            max_pos = from;
@@ -553,7 +547,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
          (to - 1).  */
       while (from < to - 1
             && find_composition (from, to, &start, &from, &prop, Qnil)
-            && COMPOSITION_VALID_P (start, from, prop)
+            && composition_valid_p (start, from, prop)
             && from < to - 1)
        run_composition_function (start, from, prop);
     }
@@ -562,7 +556,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
     {
       if (from < to
          && find_composition (to - 1, -1, &start, &end, &prop, Qnil)
-         && COMPOSITION_VALID_P (start, end, prop))
+         && composition_valid_p (start, end, prop))
        {
          /* TO should be also at composition boundary.  But,
             insertion or deletion will make two compositions adjacent
@@ -580,7 +574,7 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
        }
       else if (to < ZV
               && find_composition (to, -1, &start, &end, &prop, Qnil)
-              && COMPOSITION_VALID_P (start, end, prop))
+              && composition_valid_p (start, end, prop))
        {
          run_composition_function (start, end, prop);
          max_pos = end;
@@ -588,15 +582,15 @@ update_compositions (ptrdiff_t from, ptrdiff_t to, int check_mask)
     }
   if (min_pos < max_pos)
     {
-      ptrdiff_t count = SPECPDL_INDEX ();
+      dynwind_begin ();
 
       specbind (Qinhibit_read_only, Qt);
       specbind (Qinhibit_modification_hooks, Qt);
       specbind (Qinhibit_point_motion_hooks, Qt);
       Fremove_list_of_text_properties (make_number (min_pos),
                                       make_number (max_pos),
-                                      Fcons (Qauto_composed, Qnil), Qnil);
-      unbind_to (count, Qnil);
+                                      list1 (Qauto_composed), Qnil);
+      dynwind_end ();
     }
 }
 
@@ -642,13 +636,7 @@ compose_text (ptrdiff_t start, ptrdiff_t end, Lisp_Object components,
                       Qcomposition, prop, string);
 }
 
-
-static Lisp_Object autocmp_chars (Lisp_Object, ptrdiff_t, ptrdiff_t,
-                                  ptrdiff_t, struct window *,
-                                  struct face *, Lisp_Object);
-
-\f
-/* Lisp glyph-string handlers */
+/* Lisp glyph-string handlers.  */
 
 /* Hash table for automatic composition.  The key is a header of a
    lgstring (Lispy glyph-string), and the value is a body of a
@@ -686,7 +674,6 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
       len = j;
     }
 
-  lint_assume (len <= TYPE_MAXIMUM (ptrdiff_t) - 2);
   copy = Fmake_vector (make_number (len + 2), Qnil);
   LGSTRING_SET_HEADER (copy, Fcopy_sequence (header));
   for (i = 0; i < len; i++)
@@ -704,10 +691,6 @@ composition_gstring_from_id (ptrdiff_t id)
   return HASH_VALUE (h, id);
 }
 
-static Lisp_Object fill_gstring_header (Lisp_Object, Lisp_Object,
-                                        Lisp_Object, Lisp_Object,
-                                        Lisp_Object);
-
 bool
 composition_gstring_p (Lisp_Object gstring)
 {
@@ -797,34 +780,11 @@ static Lisp_Object gstring_work;
 static Lisp_Object gstring_work_headers;
 
 static Lisp_Object
-fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lisp_Object font_object, Lisp_Object string)
+fill_gstring_header (Lisp_Object header, ptrdiff_t from, ptrdiff_t from_byte,
+                    ptrdiff_t to, Lisp_Object font_object, Lisp_Object string)
 {
-  ptrdiff_t from, to, from_byte;
-  ptrdiff_t len, i;
+  ptrdiff_t len = to - from, i;
 
-  if (NILP (string))
-    {
-      if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
-       error ("Attempt to shape unibyte text");
-      validate_region (&start, &end);
-      from = XFASTINT (start);
-      to = XFASTINT (end);
-      from_byte = CHAR_TO_BYTE (from);
-    }
-  else
-    {
-      CHECK_STRING (string);
-      if (! STRING_MULTIBYTE (string))
-       error ("Attempt to shape unibyte text");
-      /* The caller checks that START and END are nonnegative integers.  */
-      if (! (XINT (start) <= XINT (end) && XINT (end) <= SCHARS (string)))
-       args_out_of_range_3 (string, start, end);
-      from = XINT (start);
-      to = XINT (end);
-      from_byte = string_char_to_byte (string, from);
-    }
-
-  len = to - from;
   if (len == 0)
     error ("Attempt to shape zero-length text");
   if (VECTORP (header))
@@ -837,7 +797,7 @@ fill_gstring_header (Lisp_Object header, Lisp_Object start, Lisp_Object end, Lis
       if (len <= 8)
        header = AREF (gstring_work_headers, len - 1);
       else
-       header = Fmake_vector (make_number (len + 1), Qnil);
+       header = make_uninit_vector (len + 1);
     }
 
   ASET (header, 0, font_object);
@@ -905,10 +865,12 @@ fill_gstring_body (Lisp_Object gstring)
    object.  Otherwise return nil.  */
 
 static Lisp_Object
-autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t limit, struct window *win, struct face *face, Lisp_Object string)
+autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
+              ptrdiff_t limit, struct window *win, struct face *face,
+              Lisp_Object string)
 {
-  ptrdiff_t count = SPECPDL_INDEX ();
-  FRAME_PTR f = XFRAME (win->frame);
+  dynwind_begin ();
+  struct frame *f = XFRAME (win->frame);
   Lisp_Object pos = make_number (charpos);
   ptrdiff_t to;
   ptrdiff_t pt = PT, pt_byte = PT_BYTE;
@@ -919,8 +881,11 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t
   re = AREF (rule, 0);
   if (NILP (re))
     len = 1;
-  else if (! STRINGP (re))
-    return unbind_to (count, Qnil);
+  else if (! STRINGP (re)){
+    
+      dynwind_end ();
+      return Qnil;
+    }
   else if ((len = fast_looking_at (re, charpos, bytepos, limit, -1, string))
           > 0)
     {
@@ -929,18 +894,24 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t
       else
        len = string_byte_to_char (string, bytepos + len) - charpos;
     }
-  if (len <= 0)
-    return unbind_to (count, Qnil);
+  if (len <= 0){
+    
+      dynwind_end ();
+      return Qnil;
+    }
   to = limit = charpos + len;
 #ifdef HAVE_WINDOW_SYSTEM
   if (FRAME_WINDOW_P (f))
     {
-      font_object = font_range (charpos, &to, win, face, string);
+      font_object = font_range (charpos, bytepos, &to, win, face, string);
       if (! FONT_OBJECT_P (font_object)
          || (! NILP (re)
              && to < limit
-             && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0)))
-       return unbind_to (count, Qnil);
+             && (fast_looking_at (re, charpos, bytepos, to, -1, string) <= 0))){
+       
+         dynwind_end ();
+       return Qnil;
+       }
     }
   else
 #endif /* not HAVE_WINDOW_SYSTEM */
@@ -956,20 +927,22 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos, ptrdiff_t
       lgstring = safe_call (6, Vauto_composition_function, AREF (rule, 2),
                            pos, make_number (to), font_object, string);
     }
-  return unbind_to (count, lgstring);
+  dynwind_end ();
+  return lgstring;
 }
 
-static Lisp_Object _work_val;
-
 /* 1 iff the character C is composable.  Characters of general
    category Z? or C? are not composable except for ZWNJ and ZWJ. */
 
-#define CHAR_COMPOSABLE_P(C)                                           \
-  ((C) > ' '                                                           \
-   && ((C) == 0x200C || (C) == 0x200D                                  \
-       || (_work_val = CHAR_TABLE_REF (Vunicode_category_table, (C)),  \
-          (INTEGERP (_work_val)                                        \
-           && (XINT (_work_val) <= UNICODE_CATEGORY_So)))))
+static bool
+char_composable_p (int c)
+{
+  Lisp_Object val;
+  return (c > ' '                      
+         && (c == 0x200C || c == 0x200D
+             || (val = CHAR_TABLE_REF (Vunicode_category_table, c),
+                 (INTEGERP (val) && (XINT (val) <= UNICODE_CATEGORY_So)))));
+}
 
 /* Update cmp_it->stop_pos to the next position after CHARPOS (and
    BYTEPOS) where character composition may happen.  If BYTEPOS is
@@ -1019,7 +992,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
   if (charpos < endpos
       && find_composition (charpos, endpos, &start, &end, &prop, string)
       && start >= charpos
-      && COMPOSITION_VALID_P (start, end, prop))
+      && composition_valid_p (start, end, prop))
     {
       cmp_it->stop_pos = endpos = start;
       cmp_it->ch = -1;
@@ -1105,7 +1078,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
        p = SDATA (string) + bytepos;
       c = STRING_CHAR_AND_LENGTH (p, len);
       limit = bytepos + len;
-      while (CHAR_COMPOSABLE_P (c))
+      while (char_composable_p (c))
        {
          val = CHAR_TABLE_REF (Vcomposition_function_table, c);
          if (! NILP (val))
@@ -1182,7 +1155,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
       /* Skip all uncomposable characters.  */
       if (NILP (string))
        {
-         while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
+         while (charpos - 1 > endpos && ! char_composable_p (c))
            {
              DEC_BOTH (charpos, bytepos);
              c = FETCH_MULTIBYTE_CHAR (bytepos);
@@ -1190,7 +1163,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
        }
       else
        {
-         while (charpos - 1 > endpos && ! CHAR_COMPOSABLE_P (c))
+         while (charpos - 1 > endpos && ! char_composable_p (c))
            {
              p--;
              while (! CHAR_HEAD_P (*p))
@@ -1205,7 +1178,7 @@ composition_compute_stop_pos (struct composition_it *cmp_it, ptrdiff_t charpos,
 
 /* Check if the character at CHARPOS (and BYTEPOS) is composed
    (possibly with the following characters) on window W.  ENDPOS limits
-   characters to be composed.  FACE, in non-NULL, is a base face of
+   characters to be composed.  FACE, if non-NULL, is a base face of
    the character.  If STRING is not nil, it is a string containing the
    character to check, and CHARPOS and BYTEPOS are indices in the
    string.  In that case, FACE must not be NULL.
@@ -1426,7 +1399,7 @@ composition_update_it (struct composition_it *cmp_it, ptrdiff_t charpos, ptrdiff
       cmp_it->width = 0;
       for (i = cmp_it->nchars - 1; i >= 0; i--)
        {
-         c = XINT (LGSTRING_CHAR (gstring, i));
+         c = XINT (LGSTRING_CHAR (gstring, from + i));
          cmp_it->nbytes += CHAR_BYTES (c);
          cmp_it->width += CHAR_WIDTH (c);
        }
@@ -1524,7 +1497,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
                  |-B-|-C-|--D--|
 
      Here, it is known that characters after positions 1 and 9 can
-     never be composed (i.e. ! CHAR_COMPOSABLE_P (CH)), and
+     never be composed (i.e. ! char_composable_p (CH)), and
      composition A is an invalid one because it's partially covered by
      the valid composition C.  And to know whether a composition is
      valid or not, the only way is to start searching forward from a
@@ -1548,7 +1521,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
   while (1)
     {
       c = STRING_CHAR (cur.p);
-      if (! CHAR_COMPOSABLE_P (c))
+      if (! char_composable_p (c))
        {
          if (limit <= pos)     /* case (1)  */
            {
@@ -1557,7 +1530,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
                  return 0;
                BACKWARD_CHAR (cur, stop);
                c = STRING_CHAR (cur.p);
-             } while (! CHAR_COMPOSABLE_P (c));
+             } while (! char_composable_p (c));
              fore_check_limit = cur.pos + 1;
            }
          else                  /* case (2) */
@@ -1573,7 +1546,7 @@ find_automatic_composition (ptrdiff_t pos, ptrdiff_t limit,
          prev = cur;
          BACKWARD_CHAR (cur, stop);
          c = STRING_CHAR (cur.p);
-         if (! CHAR_COMPOSABLE_P (c))
+         if (! char_composable_p (c))
            {
              cur = prev;
              break;
@@ -1679,7 +1652,7 @@ composition_adjust_point (ptrdiff_t last_pt, ptrdiff_t new_pt)
 
   /* At first check the static composition. */
   if (get_property_and_range (new_pt, Qcomposition, &val, &beg, &end, Qnil)
-      && COMPOSITION_VALID_P (beg, end, val))
+      && composition_valid_p (beg, end, val))
     {
       if (beg < new_pt /* && end > new_pt   <- It's always the case.  */
          && (last_pt <= beg || last_pt >= end))
@@ -1721,7 +1694,10 @@ Otherwise (for terminal display), FONT-OBJECT must be a terminal ID, a
 frame, or nil for the selected frame's terminal device.
 
 If the optional 4th argument STRING is not nil, it is a string
-containing the target characters between indices FROM and TO.
+containing the target characters between indices FROM and TO,
+which are treated as in `substring'.  Otherwise FROM and TO are
+character positions in current buffer; they can be in either order,
+and can be integers or markers.
 
 A glyph-string is a vector containing information about how to display
 a specific character sequence.  The format is:
@@ -1753,10 +1729,8 @@ should be ignored.  */)
   (Lisp_Object from, Lisp_Object to, Lisp_Object font_object, Lisp_Object string)
 {
   Lisp_Object gstring, header;
-  ptrdiff_t frompos, topos;
+  ptrdiff_t frompos, frombyte, topos;
 
-  CHECK_NATNUM (from);
-  CHECK_NATNUM (to);
   if (! FONT_OBJECT_P (font_object))
     {
       struct coding_system *coding;
@@ -1768,13 +1742,30 @@ should be ignored.  */)
       font_object = CODING_ID_NAME (coding->id);
     }
 
-  header = fill_gstring_header (Qnil, from, to, font_object, string);
+  if (NILP (string))
+    {
+      if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
+       error ("Attempt to shape unibyte text");
+      validate_region (&from, &to);
+      frompos = XFASTINT (from);
+      topos = XFASTINT (to);
+      frombyte = CHAR_TO_BYTE (frompos);
+    }
+  else
+    {
+      CHECK_STRING (string);
+      validate_subarray (string, from, to, SCHARS (string), &frompos, &topos);
+      if (! STRING_MULTIBYTE (string))
+       error ("Attempt to shape unibyte text");
+      frombyte = string_char_to_byte (string, frompos);
+    }
+
+  header = fill_gstring_header (Qnil, frompos, frombyte,
+                               topos, font_object, string);
   gstring = gstring_lookup_cache (header);
   if (! NILP (gstring))
     return gstring;
 
-  frompos = XINT (from);
-  topos = XINT (to);
   if (LGSTRING_GLYPH_LEN (gstring_work) < topos - frompos)
     gstring_work = Fmake_vector (make_number (topos - frompos + 2), Qnil);
   LGSTRING_SET_HEADER (gstring_work, header);
@@ -1810,21 +1801,18 @@ DEFUN ("compose-string-internal", Fcompose_string_internal,
        Scompose_string_internal, 3, 5, 0,
        doc: /* Internal use only.
 
-Compose text between indices START and END of STRING.
-Optional 4th and 5th arguments are COMPONENTS and MODIFICATION-FUNC
+Compose text between indices START and END of STRING, where
+START and END are treated as in `substring'.  Optional 4th
+and 5th arguments are COMPONENTS and MODIFICATION-FUNC
 for the composition.  See `compose-string' for more details.  */)
-  (Lisp_Object string, Lisp_Object start, Lisp_Object end, Lisp_Object components, Lisp_Object modification_func)
+  (Lisp_Object string, Lisp_Object start, Lisp_Object end,
+   Lisp_Object components, Lisp_Object modification_func)
 {
-  CHECK_STRING (string);
-  CHECK_NUMBER (start);
-  CHECK_NUMBER (end);
-
-  if (XINT (start) < 0 ||
-      XINT (start) > XINT (end)
-      || XINT (end) > SCHARS (string))
-    args_out_of_range (start, end);
+  ptrdiff_t from, to;
 
-  compose_text (XINT (start), XINT (end), components, modification_func, string);
+  CHECK_STRING (string);
+  validate_subarray (string, start, end, SCHARS (string), &from, &to);
+  compose_text (from, to, components, modification_func, string);
   return string;
 }
 
@@ -1879,14 +1867,12 @@ See `find-composition' for more details.  */)
          && (e <= XINT (pos) ? e > end : s < start))
        return list3 (make_number (s), make_number (e), gstring);
     }
-  if (!COMPOSITION_VALID_P (start, end, prop))
-    return Fcons (make_number (start), Fcons (make_number (end),
-                                             Fcons (Qnil, Qnil)));
+  if (!composition_valid_p (start, end, prop))
+    return list3 (make_number (start), make_number (end), Qnil);
   if (NILP (detail_p))
-    return Fcons (make_number (start), Fcons (make_number (end),
-                                             Fcons (Qt, Qnil)));
+    return list3 (make_number (start), make_number (end), Qt);
 
-  if (COMPOSITION_REGISTERD_P (prop))
+  if (composition_registered_p (prop))
     id = COMPOSITION_ID (prop);
   else
     {
@@ -1899,17 +1885,14 @@ See `find-composition' for more details.  */)
   if (id >= 0)
     {
       Lisp_Object components, relative_p, mod_func;
-      enum composition_method method = COMPOSITION_METHOD (prop);
+      enum composition_method method = composition_method (prop);
       int width = composition_table[id]->width;
 
       components = Fcopy_sequence (COMPOSITION_COMPONENTS (prop));
       relative_p = (method == COMPOSITION_WITH_RULE_ALTCHARS
                    ? Qnil : Qt);
       mod_func = COMPOSITION_MODIFICATION_FUNC (prop);
-      tail = Fcons (components,
-                   Fcons (relative_p,
-                          Fcons (mod_func,
-                                 Fcons (make_number (width), Qnil))));
+      tail = list4 (components, relative_p, mod_func, make_number (width));
     }
   else
     tail = Qnil;
@@ -1923,6 +1906,8 @@ syms_of_composite (void)
 {
   int i;
 
+#include "composite.x"
+
   DEFSYM (Qcomposition, "composition");
 
   /* Make a hash table for static composition.  */
@@ -1958,7 +1943,7 @@ syms_of_composite (void)
   }
 
   staticpro (&gstring_work_headers);
-  gstring_work_headers = Fmake_vector (make_number (8), Qnil);
+  gstring_work_headers = make_uninit_vector (8);
   for (i = 0; i < 8; i++)
     ASET (gstring_work_headers, i, Fmake_vector (make_number (i + 2), Qnil));
   staticpro (&gstring_work);
@@ -2035,9 +2020,4 @@ GSTRING, or modify GSTRING itself and return it.
 
 See also the documentation of `auto-composition-mode'.  */);
   Vcomposition_function_table = Fmake_char_table (Qnil, Qnil);
-
-  defsubr (&Scompose_region_internal);
-  defsubr (&Scompose_string_internal);
-  defsubr (&Sfind_composition_internal);
-  defsubr (&Scomposition_get_gstring);
 }