*** empty log message ***
[m17n/m17n-lib.git] / src / face.c
index 8d6fda3..5185d0f 100644 (file)
@@ -17,7 +17,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the m17n library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
    02111-1307, USA.  */
 
 /***en
@@ -243,7 +243,7 @@ serialize_face (void *val)
     MSymbol *key;
     MSymbol *type;
     MPlist *(*func) (MPlist *plist, void *val);
-  } serializer[MFACE_PROPERTY_MAX]
+  } serializer[MFACE_RATIO + 1]
       = { { &Mfoundry,         &Msymbol },
          { &Mfamily,           &Msymbol },
          { &Mweight,           &Msymbol },
@@ -257,11 +257,9 @@ serialize_face (void *val)
          { &Mhline,            NULL },
          { &Mbox,              NULL },
          { &Mvideomode,        &Msymbol },
-         { NULL,               NULL}, /* MFACE_HOOK_FUNC */
-         { NULL,               NULL}, /* MFACE_HOOK_ARG */
          { &Mratio,            &Minteger } };
   
-  for (i = 0; i < MFACE_PROPERTY_MAX; i++)
+  for (i = 0; i <= MFACE_RATIO; i++)
     if (face->property[i] && serializer[i].key)
       {
        pl = mplist_add (pl, Msymbol, *serializer[i].key);
@@ -363,7 +361,7 @@ deserialize_face (MPlist *plist)
       plist = MPLIST_NEXT (plist);
       if (MPLIST_TAIL_P (plist))
        break;
-      if (index < 0 || index >= MFACE_PROPERTY_MAX)
+      if (index < 0 || index > MFACE_RATIO)
        continue;
       if (key == Mfoundry || key == Mfamily || key == Mweight || key == Mstyle
          || key == Mstretch || key == Madstyle
@@ -419,8 +417,10 @@ mface__init ()
 
   M17N_OBJECT_ADD_ARRAY (face_table, "Face");
   Mface = msymbol_as_managing_key ("face");
-  msymbol_put (Mface, Mtext_prop_serializer, (void *) serialize_face);
-  msymbol_put (Mface, Mtext_prop_deserializer, (void *) deserialize_face);
+  msymbol_put_func (Mface, Mtext_prop_serializer,
+                   M17N_FUNC (serialize_face));
+  msymbol_put_func (Mface, Mtext_prop_deserializer,
+                   M17N_FUNC (deserialize_face));
 
   Mforeground = msymbol ("foreground");
   Mbackground = msymbol ("background");
@@ -442,7 +442,7 @@ mface__init ()
       MSymbol *key;
       /* Index (enum face_property) of the face property. */
       int index;
-    } mface_prop_data[MFACE_PROPERTY_MAX] =
+    } mface_prop_data[MFACE_HOOK_ARG + 1] =
        { { &Mfoundry,          MFACE_FOUNDRY },
          { &Mfamily,           MFACE_FAMILY },
          { &Mweight,           MFACE_WEIGHT },
@@ -456,10 +456,8 @@ mface__init ()
          { &Mhline,            MFACE_HLINE },
          { &Mbox,              MFACE_BOX },
          { &Mvideomode,        MFACE_VIDEOMODE },
-         { &Mhook_func,        MFACE_HOOK_FUNC },
-         { &Mhook_arg,         MFACE_HOOK_ARG },
          { &Mratio,            MFACE_RATIO },
-       };
+         { &Mhook_arg,         MFACE_HOOK_ARG } };
 
     for (i = 0; i < MFACE_PROPERTY_MAX; i++)
       /* We add one to distinguish it from no-property.  */
@@ -488,7 +486,7 @@ mface__init ()
   mface__default->property[MFACE_HLINE] = hline;
   mface__default->property[MFACE_BOX] = box;
   mface__default->property[MFACE_VIDEOMODE] = Mnormal;
-  mface__default->property[MFACE_HOOK_FUNC] = (void *) noop_hook;
+  mface__default->hook = noop_hook;
 
   mface_normal_video = mface ();
   mface_normal_video->property[MFACE_VIDEOMODE] = (void *) Mnormal;
@@ -634,9 +632,12 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font)
          merged_face.property[i] = FONT_PROPERTY (font, i);
       if (font->size)
        {
+         int font_size;
+
          if (font->size < 0)
            font->size = ((double) (- font->size)) * frame->dpi / 72.27 + 0.5;
-         merged_face.property[MFACE_SIZE] = (void *) font->size;
+         font_size = font->size;
+         merged_face.property[MFACE_SIZE] = (void *) font_size;
          merged_face.property[MFACE_RATIO] = (void *) 0;
        }
     }
@@ -726,6 +727,7 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font)
     {
       rface->rfont = rfont;
       rface->layouter = rfont->layouter;
+      rfont->layouter = Mnil;
       work_gstring.glyphs[0].rface = rface;
       work_gstring.glyphs[0].code = MCHAR_INVALID_CODE;
       mfont__get_metric (&work_gstring, 0, 1);
@@ -770,7 +772,7 @@ mface__realize (MFrame *frame, MFace **faces, int num, int size, MFont *font)
   rface->ascii_rface = rface;
   (*frame->driver->realize_face) (rface);
 
-  func = (MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC];
+  func = rface->face.hook;
   if (func && func != noop_hook)
     (func) (&(rface->face), rface->info, rface->face.property[MFACE_HOOK_ARG]);
 
@@ -829,6 +831,7 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset,
              *new = *rface;
              new->rfont = rfont;
              new->layouter = rfont->layouter;
+             rfont->layouter = Mnil;
              new->non_ascii_list = NULL;
              new->ascent = rfont->ascent;
              new->descent = rfont->descent;
@@ -836,11 +839,22 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset,
          for (; from_g < to_g && from_g->rface->font; from_g++)
            {
              from_g->rface = new;
-             from_g->code
-               = (rfont->layouter
-                  ? mfont__flt_encode_char (rfont->layouter, from_g->c)
-                  : mfont__encode_char (rfont->frame, (MFont *) rfont, NULL,
-                                        from_g->c));
+             if (new->layouter)
+               {
+                 from_g->code = mfont__flt_encode_char (new->layouter, 
+                                                        from_g->c);
+                 if (from_g->code == MCHAR_INVALID_CODE)
+                   {
+                     from_g->rface = rface;
+                     from_g->code = mfont__encode_char (rfont->frame, 
+                                                        (MFont *) rfont,
+                                                        NULL, from_g->c);
+                   }
+               }
+             else
+               from_g->code = mfont__encode_char (rfont->frame, 
+                                                  (MFont *) rfont,
+                                                  NULL, from_g->c);
            }
        }
       return from_g;
@@ -863,7 +877,10 @@ mface__for_chars (MSymbol script, MSymbol language, MSymbol charset,
   rfont = mfont__lookup_fontset (from_g->rface->rfontset, from_g, &num,
                                 script, language, charset, size, 0);
   if (rfont)
-    layouter = rfont->layouter;
+    {
+      layouter = rfont->layouter;
+      rfont->layouter = Mnil;
+    }
   else
     {
       from_g->code = MCHAR_INVALID_CODE;
@@ -922,7 +939,7 @@ mface__free_realized (MRealizedFace *rface)
   MPLIST_DO (plist, rface->non_ascii_list)
     free (MPLIST_VAL (plist));
   M17N_OBJECT_UNREF (rface->non_ascii_list);
-  if (rface->font)
+  if (rface->font && rface->font->type != MFONT_TYPE_REALIZED)
     free (rface->font);
   free (rface);
 }
@@ -1804,7 +1821,7 @@ mface_from_font (MFont *font)
 
         #Mforeground, #Mbackground, #Mvideomode, #Mhline, #Mbox,
         #Mfoundry, #Mfamily, #Mweight, #Mstyle, #Mstretch, #Madstyle,
-        #Msize, #Mfontset, #Mratio, #Mhook_func, #Mhook_arg
+        #Msize, #Mfontset, #Mratio, #Mhook_arg
 
     @return 
     Ìá¤êÃͤη¿¤Ï $KEY ¤Ë°Í¸¤¹¤ë¡£¾åµ­¤Î¥­¡¼¤ÎÀâÌÀ¤ò»²¾È¤¹¤ë¤³¤È¡£
@@ -1813,7 +1830,7 @@ mface_from_font (MFont *font)
 
 /***
     @seealso
-    mface_put_prop ()
+    mface_put_prop (), mface_put_hook ()
 
     @errors
     @c MERROR_FACE  */
@@ -1824,13 +1841,37 @@ mface_get_prop (MFace *face, MSymbol key)
   int index = (int) msymbol_get (key, M_face_prop_index) - 1;
 
   if (index < 0)
-    MERROR (MERROR_FACE, NULL);
+    {
+      if (key == Mhook_func)
+       /* This unsafe code is for backward compatiblity.  */
+       return *(void **) &face->hook;
+      MERROR (MERROR_FACE, NULL);
+    }
   return face->property[index];
 }
 
 /*=*/
 
 /***en
+    @brief Get the hook function of a face.
+
+    The mface_get_hook () function returns the hook function of face
+    $FACE.  */
+
+/***ja
+    @brief ¥Õ¥§¡¼¥¹¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÆÀ¤ë.
+
+    ´Ø¿ô mface_get_hook () ¤Ï¥Õ¥§¡¼¥¹ $FACE ¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÊÖ¤¹¡£ */
+
+MFaceHookFunc
+mface_get_hook (MFace *face)
+{
+  return face->hook;
+}
+
+/*=*/
+
+/***en
     @brief Set a value of a face property.
 
     The mface_put_prop () function assigns $VAL to the property whose
@@ -1885,22 +1926,32 @@ mface_put_prop (MFace *face, MSymbol key, void *val)
   int index = (int) msymbol_get (key, M_face_prop_index) - 1;
   MPlist *plist;
 
-  if (index < 0)
-    MERROR (MERROR_FACE, -1);
-  if (key == Mfontset)
+  if (key == Mhook_func)
     {
-      if (face->property[index])
-       M17N_OBJECT_UNREF (face->property[index]);
-      M17N_OBJECT_REF (val);
+      /* This unsafe code is for backward compatiblity.  */
+      if (*(void **) &face->hook == val)
+       return 0;
+      *(void **) &face->hook = val;
     }
-  else if (key == Mhline)
-    val = get_hline_create (val);
-  else if (key == Mbox)
-    val = get_box_create (val);
+  else
+    {
+      if (index < 0)
+       MERROR (MERROR_FACE, -1);
+      if (key == Mfontset)
+       {
+         if (face->property[index])
+           M17N_OBJECT_UNREF (face->property[index]);
+         M17N_OBJECT_REF (val);
+       }
+      else if (key == Mhline)
+       val = get_hline_create (val);
+      else if (key == Mbox)
+       val = get_box_create (val);
 
-  if (face->property[index] == val)
-    return 0;
-  face->property[index] = val;
+      if (face->property[index] == val)
+       return 0;
+      face->property[index] = val;
+    }
 
   MPLIST_DO (plist, face->frame_list)
     {
@@ -1917,6 +1968,40 @@ mface_put_prop (MFace *face, MSymbol key, void *val)
 /*=*/
 
 /***en
+    @brief Set a hook function to a face.
+
+    The mface_set_hook () function sets the hook function of face
+    $FACE to $FUNC.  */
+
+/***ja
+    @brief ¥Õ¥§¡¼¥¹¤Î¥Õ¥Ã¥¯´Ø¿ô¤òÀßÄꤹ¤ë.
+
+    ´Ø¿ô mface_set_hook () ¤Ï¡¢¥Õ¥§¡¼¥¹ $FACE ¤Î¥Õ¥Ã¥¯´Ø¿ô¤ò$FUNC ¤ËÀß
+    Äꤹ¤ë¡£  */
+
+int
+mface_put_hook (MFace *face, MFaceHookFunc func)
+{
+  if (face->hook != func)
+    {
+      MPlist *plist;
+      face->hook = func;
+
+      MPLIST_DO (plist, face->frame_list)
+       {
+         MFrame *frame = MPLIST_VAL (plist);
+
+         frame->tick++;
+         if (face == frame->face)
+           mface__update_frame_face (frame);
+       }
+    }
+  return 0;
+}
+
+/*=*/
+
+/***en
     @brief Update a face.
 
     The mface_update () function update face $FACE on frame $FRAME by
@@ -1931,7 +2016,7 @@ mface_put_prop (MFace *face, MSymbol key, void *val)
 void
 mface_update (MFrame *frame, MFace *face)
 {
-  MFaceHookFunc func = (MFaceHookFunc) face->property[MFACE_HOOK_FUNC];
+  MFaceHookFunc func = face->hook;
   MPlist *rface_list;
   MRealizedFace *rface;
 
@@ -1940,7 +2025,7 @@ mface_update (MFrame *frame, MFace *face)
       MPLIST_DO (rface_list, frame->realized_face_list)
        {
          rface = MPLIST_VAL (rface_list);
-         if ((MFaceHookFunc) rface->face.property[MFACE_HOOK_FUNC] == func)
+         if (rface->face.hook == func)
            (func) (&(rface->face), rface->face.property[MFACE_HOOK_ARG],
                    rface->info);
        }