--- /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;