(code_convert_region): Fix previous change. Adjusted
[bpt/emacs.git] / src / fontset.c
index 141ba4b..fe35268 100644 (file)
@@ -1,7 +1,6 @@
 /* Fontset handler.
-   Ver.1.0
-   Copyright (C) 1995 Free Software Foundation, Inc.
-   Copyright (C) 1995 Electrotechnical Laboratory, JAPAN.
+   Copyright (C) 1995, 1997 Electrotechnical Laboratory, JAPAN.
+   Licensed to the Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -31,8 +30,16 @@ Boston, MA 02111-1307, USA.  */
 #include "frame.h"
 
 Lisp_Object Vglobal_fontset_alist;
-
 Lisp_Object Vfont_encoding_alist;
+Lisp_Object Vuse_default_ascent;
+Lisp_Object Vignore_relative_composition;
+Lisp_Object Valternate_fontname_alist;
+Lisp_Object Vfontset_alias_alist;
+Lisp_Object Vhighlight_wrong_size_font;
+Lisp_Object Vclip_large_size_font;
+
+/* Used as a temporary in macro FS_LOAD_FONT.  */
+int font_idx_temp;
 
 /* We had better have our own strcasecmp function because some system
    doesn't have it.  */
@@ -53,25 +60,27 @@ my_strcasecmp (s0, s1)
    the comments in src/fontset.h for more detail.  */
 
 /* Return a pointer to struct font_info of font FONT_IDX of frame F.  */
-struct font_info *(*get_font_info_func) (/* FRAME_PTR f; int font_idx */);
+struct font_info *(*get_font_info_func) P_ ((FRAME_PTR f, int font_idx));
 
 /* Return a list of font names which matches PATTERN.  See the document of
    `x-list-fonts' for more detail.  */
-Lisp_Object (*list_fonts_func) (/* Lisp_Object pattern, face, frame, width */);
+Lisp_Object (*list_fonts_func) P_ ((Lisp_Object pattern, Lisp_Object face,
+                                   Lisp_Object frame, Lisp_Object width));
 
 /* Load a font named NAME for frame F and return a pointer to the
    information of the loaded font.  If loading is failed, return 0.  */
-struct font_info *(*load_font_func) (/* FRAME_PTR f; char *name */);
+struct font_info *(*load_font_func) P_ ((FRAME_PTR f, char *name, int));
 
 /* Return a pointer to struct font_info of a font named NAME for frame F.  */
-struct font_info *(*query_font_func) (/* FRAME_PTR f; char *name */);
+struct font_info *(*query_font_func) P_ ((FRAME_PTR f, char *name));
 
 /* Additional function for setting fontset or changing fontset
    contents of frame F.  */
-void (*set_frame_fontset_func) (/* FRAME_PTR f; Lisp_Object arg, oldval */);
+void (*set_frame_fontset_func) P_ ((FRAME_PTR f, Lisp_Object arg,
+                                   Lisp_Object oldval));
 
 /* Check if any window system is used now.  */
-void (*check_window_system_func) ();
+void (*check_window_system_func) P_ ((void));
 
 struct fontset_data *
 alloc_fontset_data ()
@@ -88,19 +97,22 @@ void
 free_fontset_data (fontset_data)
      struct fontset_data *fontset_data;
 {
-  int i;
-
-  for (i = 0; i < fontset_data->n_fontsets; i++)
+  if (fontset_data->fontset_table)
     {
-      int j;
+      int i;
 
-      xfree (fontset_data->fontset_table[i]->name);
-      for (j = 0; j < MAX_CHARSET; j++)
-       if (fontset_data->fontset_table[i]->fontname[j])
-         xfree (fontset_data->fontset_table[i]->fontname[j]);
-      xfree (fontset_data->fontset_table[i]);
+      for (i = 0; i < fontset_data->n_fontsets; i++)
+       {
+         int j;
+         
+         xfree (fontset_data->fontset_table[i]->name);
+         for (j = 0; j <= MAX_CHARSET; j++)
+           if (fontset_data->fontset_table[i]->fontname[j])
+             xfree (fontset_data->fontset_table[i]->fontname[j]);
+         xfree (fontset_data->fontset_table[i]);
+       }
+      xfree (fontset_data->fontset_table);
     }
-  xfree (fontset_data->fontset_table);
 
   xfree (fontset_data);
 }
@@ -111,7 +123,10 @@ free_fontset_data (fontset_data)
    If loading fails, return 0;
    If FONTNAME is NULL, the name is taken from the information of FONTSET.
    If FONTSET is given, try to load a font whose size matches that of
-   FONTSET, and, the font index is stored in the table for FONTSET.  */
+   FONTSET, and, the font index is stored in the table for FONTSET.
+
+   If you give FONTSET argument, don't call this function directry,
+   instead call macro FS_LOAD_FONT with the same argument.  */
 
 struct font_info *
 fs_load_font (f, font_table, charset, fontname, fontset)
@@ -145,11 +160,23 @@ fs_load_font (f, font_table, charset, fontname, fontset)
     /* No way to get fontname.  */
     return 0;
 
-  /* If a fontset is specified and we have already loaded some fonts
-     in the fontset, we need a font of appropriate size to be used
-     with the fonts.  */
-  if (fontsetp && fontsetp->size)
-    size = fontsetp->size * CHARSET_WIDTH (charset);
+  /* If CHARSET is not ASCII and FONTSET is specified, we must load a
+     font of appropriate size to be used with other fonts in this
+     fontset.  */
+  if (charset != CHARSET_ASCII && fontsetp)
+    {
+      /* If we have not yet loaded ASCII font of FONTSET, we must load
+        it now to decided the size and height of this fontset.  */
+      if (fontsetp->size == 0)
+       {
+         fontp = fs_load_font (f, font_table, CHARSET_ASCII, 0, fontset);
+         if (!fontp)
+           /* Any fontset should contain avairable ASCII.  */
+           return 0;
+       }
+      /* Now we have surely decided the size of this fontset.  */
+      size = fontsetp->size * CHARSET_WIDTH (charset);
+    }
 
   fontp = (*load_font_func) (f, fontname, size);
 
@@ -164,14 +191,14 @@ fs_load_font (f, font_table, charset, fontname, fontset)
      not set by (*load_font_func).  */
   fontp->charset = charset;
 
-  if (fontp->encoding[1] >= 0)
+  if (fontp->encoding[1] != FONT_ENCODING_NOT_DECIDED)
     {
       /* The font itself tells which code points to be used.  Use this
         encoding for all other charsets.  */
       int i;
 
       fontp->encoding[0] = fontp->encoding[1];
-      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i < MAX_CHARSET; i++)
+      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
        fontp->encoding[i] = fontp->encoding[1];
     }
   else
@@ -181,7 +208,7 @@ fs_load_font (f, font_table, charset, fontname, fontset)
 
       /* At first, set 1 (means 0xA0..0xFF) as the default.  */
       fontp->encoding[0] = 1;
-      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i < MAX_CHARSET; i++)
+      for (i = MIN_CHARSET_OFFICIAL_DIMENSION1; i <= MAX_CHARSET; i++)
        fontp->encoding[i] = 1;
       /* Then override them by a specification in Vfont_encoding_alist.  */
       for (list = Vfont_encoding_alist; CONSP (list); list = XCONS (list)->cdr)
@@ -189,14 +216,13 @@ fs_load_font (f, font_table, charset, fontname, fontset)
          elt = XCONS (list)->car;
          if (CONSP (elt)
              && STRINGP (XCONS (elt)->car) && CONSP (XCONS (elt)->cdr)
-             && (fast_string_match_ignore_case (XCONS (elt)->car, fontname)
+             && (fast_c_string_match_ignore_case (XCONS (elt)->car, fontname)
                  >= 0))
            {
              Lisp_Object tmp;
 
              for (tmp = XCONS (elt)->cdr; CONSP (tmp); tmp = XCONS (tmp)->cdr)
                if (CONSP (XCONS (tmp)->car)
-                   && INTEGERP (XCONS (XCONS (tmp)->car)->car)
                    && ((i = get_charset_id (XCONS (XCONS (tmp)->car)->car))
                        >= 0)
                    && INTEGERP (XCONS (XCONS (tmp)->car)->cdr)
@@ -213,7 +239,7 @@ fs_load_font (f, font_table, charset, fontname, fontset)
       elt = XCONS (list)->car;
       if (CONSP (elt)
          && STRINGP (XCONS (elt)->car) && VECTORP (XCONS (elt)->cdr)
-         && fast_string_match_ignore_case (XCONS (elt)->car, fontname) >= 0)
+         && fast_c_string_match_ignore_case (XCONS (elt)->car, fontname) >= 0)
        {
          fontp->font_encoder
            = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
@@ -222,42 +248,51 @@ fs_load_font (f, font_table, charset, fontname, fontset)
        }
     }
 
+  /* If FONTSET is specified, setup various fields of it.  */
   if (fontsetp)
     {
       fontsetp->font_indexes[charset] = fontp->font_idx;
-      if (fontsetp->size == 0)
-       fontsetp->size = fontp->size / CHARSET_WIDTH (charset);
-
-      if (charset == CHARSET_ASCII
-         && fontsetp->size != fontp->size)
+      if (charset == CHARSET_ASCII)
        {
-         /* When loading ASCII font of the different size from the
-            size of FONTSET, we have to update the size of FONTSET.
-            Since changing the size of FONTSET may make some fonts
-            already loaded inappropriate to be used in FONTSET, we
-            must delete the record of such fonts.  In that case, we
-            also have to calculate the height of FONTSET from the
-            remaining fonts.  */
-         int i;
-
-         fontsetp->size = fontp->size;
-         fontsetp->height = fontp->height;
-         for (i = CHARSET_ASCII + 1; i < MAX_CHARSET; i++)
+         /* Decide or change the size and height of this fontset.  */
+         if (fontsetp->size == 0)
            {
-             font_idx = fontsetp->font_indexes[i];
-             if (font_idx >= 0)
+             fontsetp->size = fontp->size;
+             fontsetp->height = fontp->height;
+           }
+         else if (fontsetp->size != fontp->size
+                  || fontsetp->height != fontp->height)
+           {
+             /* When loading ASCII font of the different size from
+                the size of FONTSET, we have to update the size of
+                FONTSET.  Since changing the size of FONTSET may make
+                some fonts already loaded inappropriate to be used in
+                FONTSET, we must delete the record of such fonts.  In
+                that case, we also have to calculate the height of
+                FONTSET from the remaining fonts.  */
+             int i;
+
+             fontsetp->size = fontp->size;
+             fontsetp->height = fontp->height;
+             for (i = CHARSET_ASCII + 1; i <= MAX_CHARSET; i++)
                {
-                 struct font_info *fontp2 = font_table + font_idx;
-
-                 if (fontp2->size != fontp->size * CHARSET_WIDTH (i))
-                   fontsetp->font_indexes[i] = FONT_NOT_OPENED;
-                 else if (fontsetp->height < fontp->height)
-                   fontsetp->height = fontp->height;
+                 font_idx = fontsetp->font_indexes[i];
+                 if (font_idx >= 0)
+                   {
+                     struct font_info *fontp2 = font_table + font_idx;
+
+                     if (fontp2->size != fontp->size * CHARSET_WIDTH (i))
+                       fontsetp->font_indexes[i] = FONT_NOT_OPENED;
+                     /* The following code should be disabled until
+                        Emacs supports variable height lines.  */
+#if 0
+                     else if (fontsetp->height < fontp->height)
+                       fontsetp->height = fontp->height;
+#endif
+                   }
                }
            }
        }
-      else if (fontsetp->height < fontp->height)
-       fontsetp->height = fontp->height;
     }
 
   return fontp;
@@ -313,7 +348,7 @@ fs_register_fontset (f, fontset_info)
 
   fontsetp->size = fontsetp->height = 0;
 
-  for (i = 0; i < MAX_CHARSET; i++)
+  for (i = 0; i <= MAX_CHARSET; i++)
     {
       fontsetp->fontname[i] = (char *) 0;
       fontsetp->font_indexes[i] = FONT_NOT_OPENED;
@@ -378,50 +413,31 @@ Lisp_Object
 fontset_pattern_regexp (pattern)
      Lisp_Object pattern;
 {
-  int nickname = 0;
-
   if (!index (XSTRING (pattern)->data, '*')
       && !index (XSTRING (pattern)->data, '?'))
     /* PATTERN does not contain any wild cards.  */
-    {
-      if (XSTRING (pattern)->size > 8
-         && ! bcmp (XSTRING (pattern)->data, "fontset-", 8))
-       /* Just a nickname of a fontset is specified.  */
-       nickname = 1;
-      else
-       return Qnil;
-    }
+    return Qnil;
 
   if (!CONSP (Vcached_fontset_data)
       || strcmp (XSTRING (pattern)->data, CACHED_FONTSET_NAME))
     {
       /* We must at first update the cached data.  */
-      char *regex = (char *) alloca (XSTRING (pattern)->size * 2 + 3);
+      char *regex = (char *) alloca (XSTRING (pattern)->size * 2);
       char *p0, *p1 = regex;
 
-      if (nickname)
+      /* Convert "*" to ".*", "?" to ".".  */
+      *p1++ = '^';
+      for (p0 = (char *) XSTRING (pattern)->data; *p0; p0++)
        {
-         /* Just prepend ".*-" to PATTERN.  */
-         *p1++= '.'; *p1++= '*', *p1++= '-';
-         bcopy (XSTRING (pattern)->data, p1, XSTRING (pattern)->size);
-         p1 += XSTRING (pattern)->size;
-       }
-      else
-       {
-         /* Convert "*" to ".*", "?" to ".".  */
-         *p1++ = '^';
-         for (p0 = XSTRING (pattern)->data; *p0; p0++)
+         if (*p0 == '*')
            {
-             if (*p0 == '*')
-               {
-                 *p1++ = '.';
-                 *p1++ = '*';
-               }
-             else if (*p0 == '?')
-               *p1++ == '.';
-             else
-               *p1++ = *p0;
+             *p1++ = '.';
+             *p1++ = '*';
            }
+         else if (*p0 == '?')
+           *p1++ = '.';
+         else
+           *p1++ = *p0;
        }
       *p1++ = '$';
       *p1++ = 0;
@@ -449,6 +465,10 @@ just like X's font name matching algorithm allows.")
   if (XSTRING (pattern)->size == 0)
     return Qnil;
 
+  tem = Frassoc (pattern, Vfontset_alias_alist);
+  if (!NILP (tem))
+    return Fcar (tem);
+
   regexp = fontset_pattern_regexp (pattern);
 
   for (tem = Vglobal_fontset_alist; CONSP (tem); tem = XCONS (tem)->cdr)
@@ -456,8 +476,8 @@ just like X's font name matching algorithm allows.")
       Lisp_Object fontset_name = XCONS (XCONS (tem)->car)->car;
       if (!NILP (regexp))
        {
-         if (fast_string_match_ignore_case (regexp,
-                                            XSTRING (fontset_name)->data)
+         if (fast_c_string_match_ignore_case (regexp,
+                                              XSTRING (fontset_name)->data)
              >= 0)
            return fontset_name;
        }
@@ -498,7 +518,7 @@ list_fontsets (f, pattern, size)
 
       if (!NILP (regexp))
        {
-         if (fast_string_match_ignore_case (regexp, fontsetp->name) >= 0)
+         if (fast_c_string_match_ignore_case (regexp, fontsetp->name) >= 0)
            name_matched = 1;
        }
       else
@@ -517,7 +537,7 @@ list_fontsets (f, pattern, size)
                 one with SIZE.  */
              int j;
 
-             for (j = 0; j < MAX_CHARSET; j++)
+             for (j = 0; j <= MAX_CHARSET; j++)
                if (fontsetp->fontname[j])
                  {
                    if ((*load_font_func) (f, fontsetp->fontname[j], size))
@@ -613,11 +633,12 @@ If FRAME is omitted or nil, all frames are affected.")
   if (NILP (frame))
     {
       Lisp_Object fontset_info = Fassoc (fullname, Vglobal_fontset_alist);
-      Lisp_Object tem = Fassq (charset, XCONS (fontset_info)->cdr);
+      Lisp_Object tem = Fassq (charset_symbol, XCONS (fontset_info)->cdr);
 
       if (NILP (tem))
        XCONS (fontset_info)->cdr
-         = Fcons (Fcons (charset, fontname), XCONS (fontset_info)->cdr);
+         = Fcons (Fcons (charset_symbol, fontname),
+                  XCONS (fontset_info)->cdr);
       else
        XCONS (tem)->cdr = fontname;
     }
@@ -636,13 +657,13 @@ If FRAME is omitted or nil, all frames are affected.")
          struct fontset_info *fontsetp
            = FRAME_FONTSET_DATA (f)->fontset_table[fontset];
 
-         if (fontsetp->fontname[XINT (charset)])
-           xfree (fontsetp->fontname[XINT (charset)]);
-         fontsetp->fontname[XINT (charset)]
+         if (fontsetp->fontname[charset])
+           xfree (fontsetp->fontname[charset]);
+         fontsetp->fontname[charset]
            = (char *) xmalloc (XSTRING (fontname)->size + 1);
-         bcopy (XSTRING (fontname)->data, fontsetp->fontname[XINT (charset)],
+         bcopy (XSTRING (fontname)->data, fontsetp->fontname[charset],
                 XSTRING (fontname)->size + 1);
-         fontsetp->font_indexes[XINT (charset)] = FONT_NOT_OPENED;
+         fontsetp->font_indexes[charset] = FONT_NOT_OPENED;
 
          if (charset == CHARSET_ASCII)
            {
@@ -667,7 +688,7 @@ DEFUN ("font-info", Ffont_info, Sfont_info, 1, 2, 0,
   "Return information about a font named NAME on frame FRAME.\n\
 If FRAME is omitted or nil, use the selected frame.\n\
 The returned value is a vector of OPENED-NAME, FULL-NAME, CHARSET, SIZE,\n\
-  HEIGHT, BASELINE-OFFSET, and RELATIVE-COMPOSE,\n\
+  HEIGHT, BASELINE-OFFSET, RELATIVE-COMPOSE, and DEFAULT-ASCENT,\n\
 where\n\
   OPENED-NAME is the name used for opening the font,\n\
   FULL-NAME is the full name of the font,\n\
@@ -675,7 +696,8 @@ where\n\
   SIZE is the minimum bound width of the font,\n\
   HEIGHT is the height of the font,\n\
   BASELINE-OFFSET is the upward offset pixels from ASCII baseline,\n\
-  RELATIVE-COMPOSE is the number controlling how to compose characters.\n\
+  RELATIVE-COMPOSE and DEFAULT-ASCENT are the numbers controlling\n\
+    how to compose characters.\n\
 If the named font is not yet loaded, return nil.")
   (name, frame)
      Lisp_Object name, frame;
@@ -702,7 +724,7 @@ If the named font is not yet loaded, return nil.")
   if (!fontp)
     return Qnil;
 
-  info = Fmake_vector (make_number (6), Qnil);
+  info = Fmake_vector (make_number (8), Qnil);
 
   XVECTOR (info)->contents[0] = build_string (fontp->name);
   XVECTOR (info)->contents[1] = build_string (fontp->full_name);
@@ -711,6 +733,7 @@ If the named font is not yet loaded, return nil.")
   XVECTOR (info)->contents[4] = make_number (fontp->height);
   XVECTOR (info)->contents[5] = make_number (fontp->baseline_offset);
   XVECTOR (info)->contents[6] = make_number (fontp->relative_compose);
+  XVECTOR (info)->contents[7] = make_number (fontp->default_ascent);
 
   return info;
 }
@@ -757,7 +780,7 @@ loading failed.")
   XVECTOR (info)->contents[0] = make_number (fontsetp->size);
   XVECTOR (info)->contents[1] = make_number (fontsetp->height);
   val = Qnil;
-  for (i = 0; i < MAX_CHARSET; i++)
+  for (i = 0; i <= MAX_CHARSET; i++)
     if (fontsetp->fontname[i])
       {
        int font_idx = fontsetp->font_indexes[i];
@@ -790,6 +813,7 @@ syms_of_fontset ()
     /* Window system initializer should have set proper functions.  */
     abort ();
 
+  Qfontset = intern ("fontset");
   staticpro (&Qfontset);
 
   Vcached_fontset_data = Qnil;
@@ -813,6 +837,51 @@ ENCODING is one of the following integer values:\n\
        3: code points 0xA020..0xFF7F are used.");
   Vfont_encoding_alist = Qnil;
 
+  DEFVAR_LISP ("use-default-ascent", &Vuse_default_ascent,
+     "Char table of characters whose ascent values should be ignored.\n\
+If an entry for a character is non-nil, the ascent value of the glyph\n\
+is assumed to be what specified by _MULE_DEFAULT_ASCENT property of a font.\n\
+\n\
+This affects how a composite character which contains\n\
+such a character is displayed on screen.");
+  Vuse_default_ascent = Qnil;
+
+  DEFVAR_LISP ("ignore-relative-composition", &Vignore_relative_composition,
+     "Char table of characters which is not composed relatively.\n\
+If an entry for a character is non-nil, a composite character\n\
+which contains that character is displayed so that\n\
+the glyph of that character is put without considering\n\
+an ascent and descent value of a previous character.");
+  Vuse_default_ascent = Qnil;
+
+  DEFVAR_LISP ("alternate-fontname-alist", &Valternate_fontname_alist,
+     "Alist of fontname vs list of the alternate fontnames.\n\
+When a specified font name is not found, the corresponding\n\
+alternate fontnames (if any) are tried instead.");
+  Valternate_fontname_alist = Qnil;
+
+  DEFVAR_LISP ("fontset-alias-alist", &Vfontset_alias_alist,
+     "Alist of fontset names vs the aliases.");
+  Vfontset_alias_alist = Qnil;
+
+  DEFVAR_LISP ("highlight-wrong-size-font", &Vhighlight_wrong_size_font,
+     "*Non-nil means highlight characters shown in wrong size fonts somehow.\n\
+The way to highlight them depends on window system on which Emacs runs.\n\
+On X11, a rectangle is shown around each such character.");
+  Vhighlight_wrong_size_font = Qnil;
+
+  DEFVAR_LISP ("clip-large-size-font", &Vclip_large_size_font,
+     "*Non-nil means characters shown in overlarge fonts are clipped.\n\
+The height of clipping area is the same as that of an ASCII character.\n\
+The width of the area is the same as that of an ASCII character,\n\
+or twice as wide, depending on the character set's column-width.\n\
+\n\
+If the only font you have for a specific character set is too large,\n\
+and clipping these characters makes them hard to read,\n\
+you can set this variable to nil to display the characters without clipping.\n\
+The drawback is that you will get some garbage left on your screen.");
+  Vclip_large_size_font = Qt;
+
   defsubr (&Squery_fontset);
   defsubr (&Snew_fontset);
   defsubr (&Sset_fontset_font);