6405629: Monospace arabic fonts fail to display correctly nv_48
authorJay Hobson <Jay.Hobson@Sun.COM>
Tue, 29 Aug 2006 10:18:32 -0700
changeset 54 43f2cc726f52
parent 53 beedb1b8ff17
child 55 8c2c2e020650
6405629: Monospace arabic fonts fail to display correctly
open-src/lib/fontconfig/Makefile
open-src/lib/fontconfig/fontconfig-2.3.2.patch.hide
open-src/lib/fontconfig/fonts.conf.append
--- a/open-src/lib/fontconfig/Makefile	Fri Aug 25 15:08:19 2006 -0700
+++ b/open-src/lib/fontconfig/Makefile	Tue Aug 29 10:18:32 2006 -0700
@@ -30,7 +30,7 @@
 # or other dealings in this Software without prior written authorization
 # of the copyright holder.
 #
-# @(#)Makefile	1.61	05/11/30
+# @(#)Makefile	1.62	06/08/29
 #
 
 PWD:sh=pwd
@@ -49,7 +49,8 @@
 SOURCE_UNCOMPRESS=gzcat
 
 # Patches to apply to source after unpacking, in order
-SOURCE_PATCHES=fontconfig-$(FONTCONFIG_VERS).patch
+SOURCE_PATCHES=fontconfig-$(FONTCONFIG_VERS).patch \
+	       fontconfig-$(FONTCONFIG_VERS).patch.hide
 
 include $(TOP)/common/Makefile.inc
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/lib/fontconfig/fontconfig-2.3.2.patch.hide	Tue Aug 29 10:18:32 2006 -0700
@@ -0,0 +1,926 @@
+--- src/fcint.h	Mon Jun 12 09:58:54 2006
++++ new/src/fcint.h	Wed Aug  9 16:20:57 2006
+@@ -327,6 +327,21 @@
+     FcChar32	*blanks;
+ };
+ 
++typedef struct _FcFontLang {
++    FcChar8             *family;        /* Name of font family */
++    FcStrSet            *hides;		/* list of hidden languages */
++    FcStrSet            *only;          /* list of only allowed languages */
++    FcStrSet            *poor;          /* list of only allowed languages */
++    struct _FcFontLang  *next;          /* Next font family */
++} FcFontLang;
++
++typedef struct _FcHide {
++    FcChar8             *alias;         /* Name of alias Sans/Serif */
++    FcFontLang          *family;        /* Hidden languages struct */
++    FcFontLang          *az[26];        /* Quick pointers */
++    struct _FcHide      *next;          /* Next alias */
++} FcHide;
++
+ struct _FcConfig {
+     /*
+      * File names loaded from the configuration -- saved here as the
+@@ -381,6 +396,14 @@
+      */
+     time_t	rescanTime;	    /* last time information was scanned */
+     int		rescanInterval;	    /* interval between scans */
++    /*
++     * Languages can be selectively turned off for some fonts to allow
++     * fonts to be used for specific languages only even if the font
++     * supports the language. This allows best fonts to be used per
++     * language where two fonts that both support the same language
++     * cannot be placed in the preference list appropriately.
++     */
++    FcHide *hideFont;
+ };
+  
+ extern FcConfig	*_fcConfig;
+@@ -645,6 +668,9 @@
+ void
+ FcEditDestroy (FcEdit *e);
+ 
++void
++FcHideDestroy ( FcHide *r );
++
+ /* fcinit.c */
+ 
+ void
+@@ -676,6 +702,12 @@
+ FcBool
+ FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
+ 
++FcBool
++FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang);
++
++FcBool
++FcLangSetRemoveLangs (FcLangSet *ls, FcStrSet *langs);
++
+ /* fclist.c */
+ 
+ FcBool
+--- src/fccfg.c	Mon Jun 12 09:44:21 2006
++++ new/src/fccfg.c	Wed Aug  9 16:21:39 2006
+@@ -115,6 +115,7 @@
+ 
+     config->rescanTime = time(0);
+     config->rescanInterval = 30;    
++    config->hideFont = NULL;
+     
+     return config;
+ 
+@@ -233,6 +234,7 @@
+     for (set = FcSetSystem; set <= FcSetApplication; set++)
+ 	if (config->fonts[set])
+ 	    FcFontSetDestroy (config->fonts[set]);
++    FcHideDestroy (config->hideFont);
+ 
+     free (config);
+     FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
+--- src/fclang.c	Mon Jun 12 09:46:05 2006
++++ new/src/fclang.c	Wed Aug  9 16:21:39 2006
+@@ -43,6 +43,7 @@
+ 
+ #define FcLangSetBitSet(ls, id)	((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
+ #define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
++#define FcLangSetBitUnset(ls, id)       ((ls)->map[(id)>>5] &= ~((FcChar32) 1 << ((id) & 0x1f)))
+ 
+ FcLangSet *
+ FcFreeTypeLangSet (const FcCharSet  *charset, 
+@@ -336,6 +337,34 @@
+     return FcStrSetAdd (ls->extra, lang);
+ }
+ 
++FcBool
++FcLangSetRemove (FcLangSet *ls, const FcChar8 *lang)
++{
++    int id;
++
++    id = FcLangSetIndex (lang);
++    if (id >= 0)
++    {
++        FcLangSetBitUnset (ls, id);
++        return FcTrue;
++    }
++    if (ls->extra)
++        return FcStrSetDel (ls->extra, lang);
++    return FcFalse;
++}
++
++FcBool
++FcLangSetRemoveLangs (FcLangSet *ls, FcStrSet *langs)
++{
++    int i;
++
++    for ( i = 0; i < langs->num; i++ )
++    {
++        FcLangSetRemove ( ls, langs->strs[i] );
++    }
++    return FcTrue;
++}
++
+ FcLangResult
+ FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
+ {
+--- src/fcmatch.c	Mon Jun 12 09:47:34 2006
++++ new/src/fcmatch.c	Thu Aug 10 05:46:03 2006
+@@ -491,6 +491,152 @@
+     return new;
+ }
+ 
++static FcHide *
++FcHideGetList (FcConfig *config, FcPattern *p)
++{
++    FcHide *r = NULL;
++
++    if ( config->hideFont )
++    {
++        FcPatternElt *pe    = FcPatternFindElt (p, "family");
++
++        r = config->hideFont;
++
++        /*
++         * Find the base family (alias) and see if it is in the
++         * hidden list
++         */
++        if ( pe )
++        {
++            FcValueList *vlist = pe->values;
++
++            while ( vlist->next )
++                vlist = vlist->next;
++
++            while ( r )
++            {
++                if ( !strcasecmp ( (char *)r->alias, (char *)vlist->value.u.s ))                    break;
++                else
++                    r = r->next;
++            }
++        }
++
++        /*
++         * At this point, we have the list of hidden/only/poor fonts
++         * for the alias. We now need to check and see if the
++         * font we are comparing is on the list.
++         */
++    }
++
++    return r;
++}
++
++static FcPattern *
++FcHideFont ( FcHide       *r, 
++	     FcPatternElt *pe, 
++	     FcPattern    *fnt, 
++	     FcLangSet   **pls )
++{
++    FcPattern  *new = fnt;
++    FcFontLang *fl;
++
++    if ( r && pe )
++    {
++        int pos = (int)(FcToLower(pe->values->value.u.s[0])) - 'a';
++
++        fl = r->az[pos];
++
++	/*
++	 * Check to see if the family is in the hide list for this alias
++	 */
++        while ( fl )
++        {
++            FcValueList *vlist = pe->values;
++            int          cmp   = strcasecmp ( (char *)fl->family,
++                                              (char *)vlist->value.u.s );
++
++            if ( !cmp )
++                break;
++            else if ( cmp > 0 )
++                fl = NULL;
++            else
++                fl = fl->next;
++        }
++
++	/*
++	 * If the family is to be language hidden, then copy the pattern
++	 * and modify the language support list
++	 */
++        if ( fl )
++        {
++            FcPatternElt *ppe;
++
++	    new = FcPatternDuplicate (fnt);
++	    if ( new )
++	    {
++	        ppe = FcPatternFindElt (new, "lang");
++		if ( ppe )
++		{
++		    if ( ppe->values->value.type == FcTypeLangSet )
++		    {
++			int i;
++			if ( fl->hides )
++			{
++			    FcLangSetRemoveLangs ( 
++					(FcLangSet *)ppe->values->value.u.l, 
++					fl->hides );
++			}
++			if ( fl->only )
++			{
++			    FcLangSetDestroy ( (FcLangSet *)ppe->values->value.u.l );
++			    ppe->values->value.u.l = FcLangSetCreate ();
++			    for ( i = 0; i < fl->only->num; i++ )
++				FcLangSetAdd ( 
++					(FcLangSet *)ppe->values->value.u.l, 
++					fl->only->strs[i] );
++			}
++			if ( fl->poor )
++			{
++			    *pls = FcLangSetCreate ();
++			    for ( i = 0; i < fl->poor->num; i++ )
++				FcLangSetAdd ( (FcLangSet *)*pls,
++					fl->poor->strs[i] );
++			}
++		    }
++		    else
++		    {
++			/*
++			 * Don't know what to do with this yet
++			 */
++		    }
++		}
++		else
++		{
++		    FcPatternDestroy ( new );
++		    new = fnt;
++		}
++	    }
++        }
++    }
++
++    return new;
++}
++
++static double
++FcHidePoorLangs ( FcValue *value, FcLangSet *ls )
++{
++    double v = 0;
++    switch (value->type) {
++    case FcTypeLangSet:
++        v = FcLangSetCompare (ls, value->u.l);
++        break;
++    case FcTypeString:
++        v = FcLangSetHasLang (ls, value->u.s);
++        break;
++    }
++    return ( v != 2.0 ) * 1.5 * 100;
++}
++
+ static void
+ FcChangeFormat ( FcPattern *p )
+ {
+@@ -543,6 +689,7 @@
+     FcPattern	    *best;
+     int		    i;
+     int		    set;
++    FcHide          *r = NULL;
+ 
+     FcChangeFormat ( p );
+ 
+@@ -563,6 +710,9 @@
+ 	    return 0;
+ 	}
+     }
++
++    r = FcHideGetList ( config, p );
++
+     for (set = 0; set < nsets; set++)
+     {
+ 	s = sets[set];
+@@ -570,13 +720,39 @@
+ 	    continue;
+ 	for (f = 0; f < s->nfont; f++)
+ 	{
++            FcPatternElt *pe = FcPatternFindElt (s->fonts[f], "family");
++            FcLangSet    *ls = NULL;
++            FcPattern    *hideFont = FcHideFont ( r, pe, s->fonts[f], &ls );
++            int           res = 1;
+ 	    if (FcDebug () & FC_DBG_MATCHV)
+ 	    {
+ 		printf ("Font %d ", f);
+-		FcPatternPrint (s->fonts[f]);
++		FcPatternPrint (hideFont);
+ 	    }
+-	    if (!FcCompare (p, s->fonts[f], score, result))
+-		return 0;
++	    if (!FcCompare (p, hideFont, score, result))
++		res = 0;
++
++            if ( hideFont )
++            {
++		FcPatternDestroy ( hideFont );
++            }
++
++	    if ( ls )
++	    {
++		FcValue patLang;
++
++    		for (i = 0;
++		     FcPatternGet (p, FC_LANG, i, &patLang) == FcResultMatch;
++		     i++)
++			;
++		if ( FcPatternGet ( p, FC_LANG, i-1, &patLang) == FcResultMatch )
++		    score[MATCH_LANG_INDEX] = FcHidePoorLangs ( &patLang, ls );
++		FcLangSetDestroy ( ls );
++	    }
++
++            if ( !res )
++                return 0;
++
+ 	    if (FcDebug () & FC_DBG_MATCHV)
+ 	    {
+ 		printf ("Score");
+@@ -731,7 +907,9 @@
+     int		    nPatternLang;
+     int    	    *patternLangSat;
+     FcValue	    patternLang;
++    FcHide          *r = NULL;
+ 
++
+     FcChangeFormat ( p );
+ 
+     if (FcDebug () & FC_DBG_MATCH)
+@@ -766,6 +944,9 @@
+     
+     new = nodes;
+     nodep = nodeps;
++
++    r = FcHideGetList ( config, p );
++
+     for (set = 0; set < nsets; set++)
+     {
+ 	s = sets[set];
+@@ -773,14 +954,34 @@
+ 	    continue;
+ 	for (f = 0; f < s->nfont; f++)
+ 	{
++            FcLangSet    *ls = NULL;
++            FcPatternElt *pe = FcPatternFindElt (s->fonts[f], "family");
++            FcPattern    *hideFont = FcHideFont ( r, pe, s->fonts[f], &ls);
++            int           res = 1;
+ 	    if (FcDebug () & FC_DBG_MATCHV)
+ 	    {
+ 		printf ("Font %d ", f);
+-		FcPatternPrint (s->fonts[f]);
++		FcPatternPrint (hideFont);
+ 	    }
+ 	    new->pattern = s->fonts[f];
+-	    if (!FcCompare (p, new->pattern, new->score, result))
+-		goto bail1;
++	    if (!FcCompare (p, hideFont, new->score, result))
++		res = 0;
++
++            if ( hideFont )
++            {
++		FcPatternDestroy ( hideFont );
++            }
++
++	    if ( ls )
++	    {
++		if ( FcPatternGet ( p, FC_LANG, i, &patternLang ) == FcResultMatch )
++		    new->score[MATCH_LANG_INDEX] = FcHidePoorLangs ( &patternLang, ls );
++		FcLangSetDestroy ( ls );
++	    }
++
++            if ( !res )
++                goto bail1;
++
+ 	    if (FcDebug () & FC_DBG_MATCHV)
+ 	    {
+ 		printf ("Score");
+--- src/fcxml.c	Mon Jun 12 09:53:00 2006
++++ new/src/fcxml.c	Wed Aug  9 16:21:39 2006
+@@ -284,6 +284,11 @@
+     FcElementDefault,
+     FcElementFamily,
+ 
++    FcElementPoor,
++    FcElementOnly,
++    FcElementHide,
++    FcElementLang,
++
+     FcElementSelectfont,
+     FcElementAcceptfont,
+     FcElementRejectfont,
+@@ -347,6 +352,11 @@
+ 	{ "default",	FcElementDefault },
+ 	{ "family",	FcElementFamily },
+ 
++        { "poor",       FcElementPoor },
++        { "only",       FcElementOnly },
++        { "hide",       FcElementHide },
++        { "lang",       FcElementLang },
++
+ 	{ "selectfont",	FcElementSelectfont },
+ 	{ "acceptfont",	FcElementAcceptfont },
+ 	{ "rejectfont",	FcElementRejectfont },
+@@ -415,6 +425,11 @@
+     FcVStackPrefer,
+     FcVStackAccept,
+     FcVStackDefault,
++
++    FcVStackPoor,
++    FcVStackOnly,
++    FcVStackHide,
++    FcVStackLang,
+     
+     FcVStackInteger,
+     FcVStackDouble,
+@@ -711,6 +726,7 @@
+ 	case FcVStackField:
+ 	case FcVStackConstant:
+ 	case FcVStackGlob:
++        case FcVStackLang:
+ 	    FcStrFree (vstack->u.string);
+ 	    break;
+ 	case FcVStackPattern:
+@@ -718,6 +734,9 @@
+ 	    break;
+ 	case FcVStackInteger:
+ 	case FcVStackDouble:
++        case FcVStackPoor:
++        case FcVStackOnly:
++        case FcVStackHide:
+ 	    break;
+ 	case FcVStackMatrix:
+ 	    FcMatrixFree (vstack->u.matrix);
+@@ -1327,6 +1346,405 @@
+ }
+ 
+ static void
++FcParseLang (FcConfigParse *parse)
++{
++    FcChar8 *s;
++    FcExpr  *expr;
++
++    if (!parse->pstack)
++        return;
++    s = FcStrBufDone (&parse->pstack->str);
++    if (!s)
++    {
++        FcConfigMessage (parse, FcSevereError, "out of memory");
++        return;
++    }
++    expr = FcExprCreateString (s);
++    FcStrFree (s);
++    if (expr)
++        FcVStackPushExpr (parse, FcVStackLang, expr);
++}
++
++static void
++FcParseOnly (FcConfigParse *parse, FcVStackTag tag)
++{
++    FcExpr      *family = 0;
++    FcStrSet    *lang = 0;
++    FcVStack    *vstack;
++    FcFontLang  *fl = NULL;
++    FcExpr      *expr;
++
++    while ((vstack = FcVStackPop (parse)))
++    {
++        switch (vstack->tag) {
++        case FcVStackFamily:
++            if (family)
++                FcExprDestroy (family);
++            family = vstack->u.expr;
++            vstack->tag = FcVStackNone;
++            break;
++        case FcVStackLang:
++            if (!lang)
++                lang = FcStrSetCreate ();
++            FcStrSetAdd (lang, vstack->u.expr->u.sval);
++            break;
++        default:
++            FcConfigMessage (parse, FcSevereWarning, "bad alias");
++            break;
++        }
++        FcVStackDestroy (vstack);
++    }
++    if (!family)
++    {
++        FcConfigMessage (parse, FcSevereError, "missing family in only");
++    }
++    if ( lang )
++    {
++        fl = (FcFontLang *)malloc (sizeof (FcFontLang));
++
++        if ( fl )
++        {
++            int len = strlen ( (char *)family->u.sval );
++            fl->family = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 ));
++            strncpy ( (char *)fl->family, (char *)family->u.sval, len );
++            fl->family[len] = '\0';
++            fl->hides       = NULL;
++            fl->only        = lang;
++            fl->poor        = NULL;
++            fl->next        = NULL;
++        }
++    }
++    if ( fl )
++    {
++        expr = FcExprCreateNil ();
++        if (expr)
++	{
++	    expr->u.sval = (FcChar8 *)fl;
++            FcVStackPushExpr (parse, FcVStackOnly, expr);
++	}
++    }
++}
++
++static void
++FcParsePoor (FcConfigParse *parse, FcVStackTag tag)
++{
++    FcExpr      *family = 0;
++    FcStrSet    *lang = 0;
++    FcVStack    *vstack;
++    FcFontLang  *fl = NULL;
++    FcExpr      *expr;
++
++    while ((vstack = FcVStackPop (parse)))
++    {
++        switch (vstack->tag) {
++        case FcVStackFamily:
++            if (family)
++                FcExprDestroy (family);
++            family = vstack->u.expr;
++            vstack->tag = FcVStackNone;
++            break;
++        case FcVStackLang:
++            if (!lang)
++                lang = FcStrSetCreate ();
++            FcStrSetAdd (lang, vstack->u.expr->u.sval);
++            break;
++        default:
++            FcConfigMessage (parse, FcSevereWarning, "bad alias");
++            break;
++        }
++        FcVStackDestroy (vstack);
++    }
++    if (!family)
++    {
++        FcConfigMessage (parse, FcSevereError, "missing family in poor");
++    }
++    if ( lang )
++    {
++        fl = (FcFontLang *)malloc (sizeof (FcFontLang));
++
++        if ( fl )
++        {
++            int len = strlen ( (char *)family->u.sval );
++            fl->family = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 ));
++            strncpy ( (char *)fl->family, (char *)family->u.sval, len );
++            fl->family[len] = '\0';
++            fl->hides       = NULL;
++            fl->only        = NULL;
++            fl->poor        = lang;
++            fl->next        = NULL;
++        }
++    }
++    if ( fl )
++    {
++        expr = FcExprCreateNil ();
++        if (expr)
++	{
++	    expr->u.sval = (FcChar8 *)fl;
++            FcVStackPushExpr (parse, FcVStackPoor, expr);
++	}
++    }
++}
++static void
++FcParseHide (FcConfigParse *parse, FcVStackTag tag)
++{
++    FcExpr      *family = 0;
++    FcStrSet    *lang = 0;
++    FcVStack    *vstack;
++    FcFontLang  *fl = NULL;
++    FcExpr      *expr;
++
++    while ((vstack = FcVStackPop (parse)))
++    {
++        switch (vstack->tag) {
++        case FcVStackFamily:
++            if (family)
++                FcExprDestroy (family);
++            family = vstack->u.expr;
++            vstack->tag = FcVStackNone;
++            break;
++        case FcVStackLang:
++            if (!lang)
++                lang = FcStrSetCreate ();
++            FcStrSetAdd (lang, vstack->u.expr->u.sval);
++            break;
++        default:
++            FcConfigMessage (parse, FcSevereWarning, "bad alias");
++            break;
++        }
++        FcVStackDestroy (vstack);
++    }
++    if (!family)
++    {
++        FcConfigMessage (parse, FcSevereError, "missing family in hide");
++    }
++    if ( lang )
++    {
++        fl = (FcFontLang *)malloc (sizeof (FcFontLang));
++
++        if ( fl )
++        {
++            int len = strlen ( (char *)family->u.sval );
++            fl->family = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 ));
++            strncpy ( (char *)fl->family, (char *)family->u.sval, len );
++            fl->family[len] = '\0';
++            fl->hides       = lang;
++            fl->only        = NULL;
++            fl->poor        = NULL;
++            fl->next        = NULL;
++        }
++    }
++    if ( fl )
++    {
++        expr = FcExprCreateNil ();
++        if (expr)
++	{
++	    expr->u.sval = (FcChar8 *)fl;
++            FcVStackPushExpr (parse, FcVStackHide, expr);
++	}
++    }
++}
++
++static void
++FcFontLangDestroy(FcFontLang *fl)
++{
++    FcFontLang *cur = fl;
++
++    while (fl)
++    {
++        cur = fl;
++        fl  = fl->next;
++
++        free (cur->family);
++	if ( cur->hides )
++            FcStrSetDestroy ( cur->hides );
++	if ( cur->only )
++            FcStrSetDestroy ( cur->only );
++	if ( cur->poor )
++            FcStrSetDestroy ( cur->poor );
++        free (cur);
++    }
++}
++
++void
++FcHideDestroy ( FcHide *r )
++{
++    if ( r )
++    {
++        if ( r->alias )
++            free ( r->alias );
++        FcFontLangDestroy ( r->family );
++        FcHideDestroy ( r->next );
++        free ( r );
++    }
++}
++
++static int
++FcHideCreate(FcConfigParse *parse, FcFontLang *fl, FcExpr *family)
++{
++    FcHide *new = parse->config->hideFont;
++    int     i;
++
++    /*
++     * Check to see if user has already hidden something in this alias
++     */
++    while ( new != NULL )
++    {
++        if ( !strcasecmp ( (char *)new->alias, (char *)family->u.sval ))
++            break;
++        else
++            new = new->next;
++    }
++
++    /*
++     * If no alias hides exist, then create an FcHide structure and
++     * fill in the base values.
++     */
++    if ( !new )
++    {
++        new = (FcHide *)malloc ( sizeof ( FcHide ));
++
++	if ( new )
++	{
++            int len = strlen ( (char *)family->u.sval );
++            new->alias  = (FcChar8 *)malloc ( sizeof ( char ) * ( len + 1 ));
++            if ( new->alias )
++            {
++                strncpy ((char *)new->alias, (char *)family->u.sval, len);
++                new->alias[len] = '\0';
++            }
++            else
++            {
++                free (new);
++                return 0;
++            }
++            new->family = NULL;
++            new->next   = parse->config->hideFont;
++            parse->config->hideFont = new;
++	}
++	else
++	    return 0;
++    }
++
++    /*
++     * Add FontLang structure in alphabetical order based on family
++     * to the restrict list
++     */
++    while ( fl )
++    {
++        FcFontLang *next = fl->next;
++
++        fl->next = NULL;
++
++        /*
++         * If no hidden families exist, then just add this one
++         */
++        if ( !new->family )
++            new->family = fl;
++        else
++        {
++            FcFontLang *ptr  = new->family;
++            FcFontLang *last = NULL;
++
++            /*
++             * Check to see where to enter hidden family, or if it already
++             * exists
++             */
++            while ( ptr )
++            {
++		int cmp = strcasecmp ( (char *)fl->family, (char *)ptr->family);
++                /*
++                 * Find out if new family is before current alphabetically
++                 */
++                if ( cmp < 0 )
++                {
++                    fl->next = ptr;
++                    if ( !last )
++                        new->family = fl;
++                    else
++                        last->next = fl;
++                    break;
++                }
++                /*
++                 * If it already exists, then just add new lang(s)
++                 */
++                else if ( cmp == 0 )
++                {
++                    /*
++                     * Check to see if we have a family with only langs and
++                     * hidden langs. Return error. Otherwise, add langs to list
++                     */
++                    if (( fl->hides && ptr->only ) ||
++                        ( fl->only && ptr->hides ))
++                        return 1;
++                    if ( fl->hides )
++                    {
++                        if ( !ptr->hides )
++                            ptr->hides = FcStrSetCreate ();
++                        for ( i = 0; i < fl->hides->num; i++ )
++                        {
++                            if ( !FcStrSetMember ( ptr->hides, fl->hides->strs[i] ))
++                                FcStrSetAdd ( ptr->hides, fl->hides->strs[i] );
++                        }
++                    }
++                    if ( fl->only )
++                    {
++                        if ( !ptr->only )
++                            ptr->only = FcStrSetCreate ();
++                        for ( i = 0; i < fl->only->num; i++ )
++                        {
++                            if ( !FcStrSetMember ( ptr->only, fl->only->strs[i] ))
++                                FcStrSetAdd ( ptr->only, fl->only->strs[i] );
++                        }
++                    }
++                    if ( fl->poor )
++                    {
++                        if ( !ptr->only )
++                            ptr->poor = FcStrSetCreate ();
++                        for ( i = 0; i < fl->poor->num; i++ )
++                        {
++                            if ( !FcStrSetMember ( ptr->poor, fl->poor->strs[i] ))
++                                FcStrSetAdd ( ptr->poor, fl->poor->strs[i] );
++                        }
++                    }
++                    FcFontLangDestroy ( fl );
++                    break;
++                }
++                /*
++                 * If it is after, then continue moving down the list
++                 */
++                else
++		{
++                    last = ptr;
++                    ptr = ptr->next;
++
++                    if ( !ptr )
++		    {
++                        last->next = fl;
++                    }
++                }
++            }
++	}
++        fl = next;
++    }
++
++    for ( i = 0; i < 26; i++ )
++        new->az[i] = NULL;
++
++    fl = new->family;
++    while ( fl )
++    {
++        int pos = (int)(fl->family[0]) - (int)'A';
++        if ( !new->az[pos] )
++        {
++            new->az[pos] = fl;
++        }
++        fl = fl->next;
++    }
++
++    return 0;
++}
++
++static void
+ FcParseAlias (FcConfigParse *parse)
+ {
+     FcExpr	*family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
+@@ -1333,6 +1751,8 @@
+     FcEdit	*edit = 0, *next;
+     FcVStack	*vstack;
+     FcTest	*test;
++    FcFontLang  *langs = NULL;
++    FcFontLang  *tmp;
+ 
+     while ((vstack = FcVStackPop (parse))) 
+     {
+@@ -1354,6 +1774,15 @@
+ 		vstack->tag = FcVStackNone;
+ 	    }
+ 	    break;
++        case FcVStackPoor:
++        case FcVStackOnly:
++        case FcVStackHide:
++            tmp = (FcFontLang *)(vstack->u.expr->u.sval);
++            FcExprDestroy (vstack->u.expr);
++            tmp->next = langs;
++            langs = tmp;
++            vstack->tag = FcVStackNone;
++            break;
+ 	case FcVStackPrefer:
+ 	    if (prefer)
+ 		FcExprDestroy (prefer);
+@@ -1427,6 +1856,11 @@
+ 	else
+ 	    FcExprDestroy (def);
+     }
++    if (langs)
++    {
++        if ( FcHideCreate(parse, langs, family))
++	    FcConfigMessage ( parse, FcSevereError, "Cannot include hide and only for same family" );
++    }
+     if (edit)
+     {
+ 	test = FcTestCreate (parse, FcMatchPattern,
+@@ -1454,6 +1888,7 @@
+ 	break;
+     case FcVStackString:
+     case FcVStackFamily:
++    case FcVStackLang:
+ 	expr = FcExprCreateString (vstack->u.string);
+ 	break;
+     case FcVStackField:
+@@ -2078,6 +2513,19 @@
+ 	FcParseFamily (parse);
+ 	break;
+ 
++    case FcElementPoor:
++        FcParsePoor (parse, FcVStackLang);
++        break;
++    case FcElementOnly:
++        FcParseOnly (parse, FcVStackLang);
++        break;
++    case FcElementHide:
++        FcParseHide (parse, FcVStackLang);
++        break;
++    case FcElementLang:
++        FcParseLang (parse);
++        break;
++
+     case FcElementTest:
+ 	FcParseTest (parse);
+ 	break;
--- a/open-src/lib/fontconfig/fonts.conf.append	Fri Aug 25 15:08:19 2006 -0700
+++ b/open-src/lib/fontconfig/fonts.conf.append	Tue Aug 29 10:18:32 2006 -0700
@@ -97,3 +97,14 @@
 	</edit>
 </match>
 
+<!--
+ Mark Lucida Sans Typewriter as poor support for AR locale
+ Use KacstQurn instead.
+-->
+<alias>
+	<family>Monospace</family>
+	<poor>
+		<family>Lucida Sans Typewriter</family>
+		<lang>ar</lang>
+	</poor>
+</alias>