2002-02-15 00:34:13 +01:00
|
|
|
/*
|
2008-08-12 22:34:24 +02:00
|
|
|
* fontconfig/src/fcstr.c
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
2004-12-07 02:14:46 +01:00
|
|
|
* Copyright © 2000 Keith Packard
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
|
|
|
* documentation for any purpose is hereby granted without fee, provided that
|
|
|
|
* the above copyright notice appear in all copies and that both that
|
|
|
|
* copyright notice and this permission notice appear in supporting
|
2010-11-10 22:45:42 +01:00
|
|
|
* documentation, and that the name of the author(s) not be used in
|
2002-02-15 00:34:13 +01:00
|
|
|
* advertising or publicity pertaining to distribution of the software without
|
2010-11-10 22:45:42 +01:00
|
|
|
* specific, written prior permission. The authors make no
|
2002-02-15 00:34:13 +01:00
|
|
|
* representations about the suitability of this software for any purpose. It
|
|
|
|
* is provided "as is" without express or implied warranty.
|
|
|
|
*
|
2009-03-12 21:00:08 +01:00
|
|
|
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
2002-02-15 00:34:13 +01:00
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
2009-03-12 21:00:08 +01:00
|
|
|
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
2002-02-15 00:34:13 +01:00
|
|
|
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
|
|
|
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
|
|
|
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
2006-04-25 07:57:41 +02:00
|
|
|
#include "fcint.h"
|
2002-02-15 00:34:13 +01:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <ctype.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-02-06 11:35:30 +01:00
|
|
|
|
2012-10-07 20:41:38 +02:00
|
|
|
/* Objects MT-safe for readonly access. */
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrCopy (const FcChar8 *s)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2013-01-02 09:06:15 +01:00
|
|
|
return FcStrdup (s);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
static FcChar8 *
|
2019-01-31 11:17:47 +01:00
|
|
|
FcStrMakeTriple (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *s3)
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
{
|
|
|
|
int s1l = s1 ? strlen ((char *) s1) : 0;
|
|
|
|
int s2l = s2 ? strlen ((char *) s2) : 0;
|
2019-01-31 11:17:47 +01:00
|
|
|
int s3l = s3 ? strlen ((char *) s3) : 0;
|
|
|
|
int l = s1l + 1 + s2l + 1 + s3l + 1;
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
FcChar8 *s = malloc (l);
|
|
|
|
|
|
|
|
if (!s)
|
|
|
|
return 0;
|
|
|
|
if (s1)
|
|
|
|
memcpy (s, s1, s1l + 1);
|
|
|
|
else
|
|
|
|
s[0] = '\0';
|
|
|
|
if (s2)
|
|
|
|
memcpy (s + s1l + 1, s2, s2l + 1);
|
|
|
|
else
|
|
|
|
s[s1l + 1] = '\0';
|
2019-01-31 11:17:47 +01:00
|
|
|
if (s3)
|
|
|
|
memcpy (s + s1l + 1 + s2l + 1, s3, s3l + 1);
|
|
|
|
else
|
|
|
|
s[s1l + 1 + s2l + 1] = '\0';
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2011-11-07 20:25:51 +01:00
|
|
|
int s1l = strlen ((char *) s1);
|
|
|
|
int s2l = strlen ((char *) s2);
|
|
|
|
int l = s1l + s2l + 1;
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *s = malloc (l);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (!s)
|
|
|
|
return 0;
|
2011-11-07 20:25:51 +01:00
|
|
|
memcpy (s, s1, s1l);
|
|
|
|
memcpy (s + s1l, s2, s2l + 1);
|
2002-02-15 00:34:13 +01:00
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-02-15 07:01:28 +01:00
|
|
|
FcStrFree (FcChar8 *s)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
|
|
|
|
#include "../fc-case/fccase.h"
|
|
|
|
|
|
|
|
#define FcCaseFoldUpperCount(cf) \
|
|
|
|
((cf)->method == FC_CASE_FOLD_FULL ? 1 : (cf)->count)
|
|
|
|
|
|
|
|
typedef struct _FcCaseWalker {
|
|
|
|
const FcChar8 *read;
|
|
|
|
const FcChar8 *src;
|
|
|
|
FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS + 1];
|
|
|
|
} FcCaseWalker;
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcStrCaseWalkerInit (const FcChar8 *src, FcCaseWalker *w)
|
|
|
|
{
|
|
|
|
w->src = src;
|
|
|
|
w->read = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcChar8
|
|
|
|
FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
|
|
|
|
{
|
|
|
|
FcChar32 ucs4;
|
|
|
|
int slen;
|
2005-11-22 05:46:55 +01:00
|
|
|
int len = strlen((char*)w->src);
|
2004-12-29 10:15:17 +01:00
|
|
|
|
2005-11-22 05:46:55 +01:00
|
|
|
slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, len + 1);
|
2004-12-29 10:15:17 +01:00
|
|
|
if (slen <= 0)
|
|
|
|
return r;
|
|
|
|
if (FC_MIN_FOLD_CHAR <= ucs4 && ucs4 <= FC_MAX_FOLD_CHAR)
|
|
|
|
{
|
|
|
|
int min = 0;
|
|
|
|
int max = FC_NUM_CASE_FOLD;
|
|
|
|
|
|
|
|
while (min <= max)
|
|
|
|
{
|
|
|
|
int mid = (min + max) >> 1;
|
|
|
|
FcChar32 low = fcCaseFold[mid].upper;
|
|
|
|
FcChar32 high = low + FcCaseFoldUpperCount (&fcCaseFold[mid]);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
if (high <= ucs4)
|
|
|
|
min = mid + 1;
|
|
|
|
else if (ucs4 < low)
|
|
|
|
max = mid - 1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
const FcCaseFold *fold = &fcCaseFold[mid];
|
|
|
|
int dlen;
|
|
|
|
|
|
|
|
switch (fold->method) {
|
|
|
|
case FC_CASE_FOLD_EVEN_ODD:
|
|
|
|
if ((ucs4 & 1) != (fold->upper & 1))
|
|
|
|
return r;
|
|
|
|
/* fall through ... */
|
|
|
|
default:
|
|
|
|
dlen = FcUcs4ToUtf8 (ucs4 + fold->offset, w->utf8);
|
|
|
|
break;
|
|
|
|
case FC_CASE_FOLD_FULL:
|
|
|
|
dlen = fold->count;
|
|
|
|
memcpy (w->utf8, fcCaseFoldChars + fold->offset, dlen);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* consume rest of src utf-8 bytes */
|
|
|
|
w->src += slen - 1;
|
|
|
|
|
|
|
|
/* read from temp buffer */
|
|
|
|
w->utf8[dlen] = '\0';
|
|
|
|
w->read = w->utf8;
|
|
|
|
return *w->read++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcChar8
|
2013-01-18 03:30:10 +01:00
|
|
|
FcStrCaseWalkerNext (FcCaseWalker *w, const char *delims)
|
2004-12-29 10:15:17 +01:00
|
|
|
{
|
|
|
|
FcChar8 r;
|
|
|
|
|
|
|
|
if (w->read)
|
|
|
|
{
|
|
|
|
if ((r = *w->read++))
|
|
|
|
return r;
|
|
|
|
w->read = 0;
|
|
|
|
}
|
|
|
|
do
|
|
|
|
{
|
|
|
|
r = *w->src++;
|
2013-01-18 03:30:10 +01:00
|
|
|
} while (r != 0 && delims && strchr (delims, r));
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
if ((r & 0xc0) == 0xc0)
|
|
|
|
return FcStrCaseWalkerLong (w, r);
|
|
|
|
if ('A' <= r && r <= 'Z')
|
|
|
|
r = r - 'A' + 'a';
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2004-12-29 20:37:14 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrDowncase (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcCaseWalker w;
|
|
|
|
int len = 0;
|
|
|
|
FcChar8 *dst, *d;
|
|
|
|
|
|
|
|
FcStrCaseWalkerInit (s, &w);
|
2013-01-18 03:30:10 +01:00
|
|
|
while (FcStrCaseWalkerNext (&w, NULL))
|
2004-12-29 20:37:14 +01:00
|
|
|
len++;
|
|
|
|
d = dst = malloc (len + 1);
|
|
|
|
if (!d)
|
|
|
|
return 0;
|
|
|
|
FcStrCaseWalkerInit (s, &w);
|
2013-01-18 03:30:10 +01:00
|
|
|
while ((*d++ = FcStrCaseWalkerNext (&w, NULL)));
|
2004-12-29 20:37:14 +01:00
|
|
|
return dst;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
int
|
2002-02-15 07:01:28 +01:00
|
|
|
FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
if (s1 == s2) return 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
|
|
|
for (;;)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2013-01-18 03:30:10 +01:00
|
|
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
|
|
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c1 || (c1 != c2))
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-07-07 01:47:44 +02:00
|
|
|
}
|
|
|
|
return (int) c1 - (int) c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
2013-01-18 03:30:10 +01:00
|
|
|
{
|
|
|
|
return FcStrCmpIgnoreCaseAndDelims (s1, s2, (const FcChar8 *)" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
FcStrCmpIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
|
2002-07-07 01:47:44 +02:00
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
if (s1 == s2) return 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
|
|
|
for (;;)
|
2002-07-07 01:47:44 +02:00
|
|
|
{
|
2013-01-18 03:30:10 +01:00
|
|
|
c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
|
|
|
|
c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c1 || (c1 != c2))
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
2002-05-30 00:07:33 +02:00
|
|
|
return (int) c1 - (int) c2;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
int
|
|
|
|
FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
|
|
|
FcChar8 c1, c2;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
if (s1 == s2)
|
|
|
|
return 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
for (;;)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
c1 = *s1++;
|
|
|
|
c2 = *s2++;
|
2003-03-05 07:09:36 +01:00
|
|
|
if (!c1 || c1 != c2)
|
2002-05-21 19:06:22 +02:00
|
|
|
break;
|
|
|
|
}
|
2002-05-30 00:07:33 +02:00
|
|
|
return (int) c1 - (int) c2;
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
/*
|
|
|
|
* Return a hash value for a string
|
|
|
|
*/
|
|
|
|
|
|
|
|
FcChar32
|
|
|
|
FcStrHashIgnoreCase (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcChar32 h = 0;
|
|
|
|
FcCaseWalker w;
|
|
|
|
FcChar8 c;
|
|
|
|
|
|
|
|
FcStrCaseWalkerInit (s, &w);
|
2013-01-18 03:30:10 +01:00
|
|
|
while ((c = FcStrCaseWalkerNext (&w, NULL)))
|
2004-12-29 10:15:17 +01:00
|
|
|
h = ((h << 3) ^ (h >> 3)) ^ c;
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2003-05-02 03:11:53 +02:00
|
|
|
/*
|
|
|
|
* Is the head of s1 equal to s2?
|
|
|
|
*/
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
|
|
|
for (;;)
|
2003-05-02 03:11:53 +02:00
|
|
|
{
|
2013-01-18 03:30:10 +01:00
|
|
|
c1 = FcStrCaseWalkerNext (&w1, " ");
|
|
|
|
c2 = FcStrCaseWalkerNext (&w2, " ");
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c1 || (c1 != c2))
|
2003-05-02 03:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return c1 == c2 || !c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Does s1 contain an instance of s2 (ignoring blanks and case)?
|
|
|
|
*/
|
|
|
|
|
|
|
|
const FcChar8 *
|
|
|
|
FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
|
|
|
while (*s1)
|
|
|
|
{
|
|
|
|
if (FcStrIsAtIgnoreBlanksAndCase (s1, s2))
|
|
|
|
return s1;
|
|
|
|
s1++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-02 05:25:21 +02:00
|
|
|
static FcBool
|
|
|
|
FcCharIsPunct (const FcChar8 c)
|
|
|
|
{
|
|
|
|
if (c < '0')
|
|
|
|
return FcTrue;
|
|
|
|
if (c <= '9')
|
|
|
|
return FcFalse;
|
|
|
|
if (c < 'A')
|
|
|
|
return FcTrue;
|
|
|
|
if (c <= 'Z')
|
|
|
|
return FcFalse;
|
|
|
|
if (c < 'a')
|
|
|
|
return FcTrue;
|
|
|
|
if (c <= 'z')
|
|
|
|
return FcFalse;
|
|
|
|
if (c <= '~')
|
|
|
|
return FcTrue;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2003-05-02 03:11:53 +02:00
|
|
|
/*
|
|
|
|
* Is the head of s1 equal to s2?
|
|
|
|
*/
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
|
|
|
for (;;)
|
2003-05-02 03:11:53 +02:00
|
|
|
{
|
2013-01-18 03:30:10 +01:00
|
|
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
|
|
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c1 || (c1 != c2))
|
2003-05-02 03:11:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return c1 == c2 || !c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2007-10-25 23:20:06 +02:00
|
|
|
* Does s1 contain an instance of s2 (ignoring blanks and case)?
|
2003-05-02 03:11:53 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
const FcChar8 *
|
|
|
|
FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
|
|
|
while (*s1)
|
|
|
|
{
|
|
|
|
if (FcStrIsAtIgnoreCase (s1, s2))
|
|
|
|
return s1;
|
|
|
|
s1++;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-09-02 05:25:21 +02:00
|
|
|
/*
|
|
|
|
* Does s1 contain an instance of s2 on a word boundary (ignoring case)?
|
|
|
|
*/
|
|
|
|
|
|
|
|
const FcChar8 *
|
|
|
|
FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
|
|
|
FcBool wordStart = FcTrue;
|
|
|
|
int s1len = strlen ((char *) s1);
|
|
|
|
int s2len = strlen ((char *) s2);
|
|
|
|
|
|
|
|
while (s1len >= s2len)
|
|
|
|
{
|
2010-04-12 18:18:50 +02:00
|
|
|
if (wordStart &&
|
2006-09-02 05:25:21 +02:00
|
|
|
FcStrIsAtIgnoreCase (s1, s2) &&
|
|
|
|
(s1len == s2len || FcCharIsPunct (s1[s2len])))
|
|
|
|
{
|
|
|
|
return s1;
|
|
|
|
}
|
|
|
|
wordStart = FcFalse;
|
|
|
|
if (FcCharIsPunct (*s1))
|
|
|
|
wordStart = FcTrue;
|
|
|
|
s1++;
|
|
|
|
s1len--;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-01-18 03:30:10 +01:00
|
|
|
/*
|
2020-07-22 03:42:40 +02:00
|
|
|
* returns the number of strings (ignoring delimiters and case) being matched
|
2013-01-18 03:30:10 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
int
|
|
|
|
FcStrMatchIgnoreCaseAndDelims (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 *delims)
|
|
|
|
{
|
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
if (s1 == s2) return 0;
|
|
|
|
|
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
c1 = FcStrCaseWalkerNext (&w1, (const char *)delims);
|
|
|
|
c2 = FcStrCaseWalkerNext (&w2, (const char *)delims);
|
|
|
|
if (!c1 || (c1 != c2))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return w1.src - s1 - 1;
|
|
|
|
}
|
|
|
|
|
2013-05-08 04:57:49 +02:00
|
|
|
FcBool
|
|
|
|
FcStrGlobMatch (const FcChar8 *glob,
|
|
|
|
const FcChar8 *string)
|
|
|
|
{
|
|
|
|
FcChar8 c;
|
|
|
|
|
|
|
|
while ((c = *glob++))
|
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case '*':
|
|
|
|
/* short circuit common case */
|
|
|
|
if (!*glob)
|
|
|
|
return FcTrue;
|
|
|
|
/* short circuit another common case */
|
|
|
|
if (strchr ((char *) glob, '*') == 0)
|
|
|
|
{
|
|
|
|
size_t l1, l2;
|
|
|
|
|
|
|
|
l1 = strlen ((char *) string);
|
|
|
|
l2 = strlen ((char *) glob);
|
|
|
|
if (l1 < l2)
|
|
|
|
return FcFalse;
|
|
|
|
string += (l1 - l2);
|
|
|
|
}
|
|
|
|
while (*string)
|
|
|
|
{
|
|
|
|
if (FcStrGlobMatch (glob, string))
|
|
|
|
return FcTrue;
|
|
|
|
string++;
|
|
|
|
}
|
|
|
|
return FcFalse;
|
|
|
|
case '?':
|
|
|
|
if (*string++ == '\0')
|
|
|
|
return FcFalse;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (*string++ != c)
|
|
|
|
return FcFalse;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return *string == '\0';
|
|
|
|
}
|
|
|
|
|
2003-05-28 03:34:38 +02:00
|
|
|
const FcChar8 *
|
|
|
|
FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
FcCaseWalker w1, w2;
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
const FcChar8 *cur;
|
2003-05-28 03:34:38 +02:00
|
|
|
|
|
|
|
if (!s1 || !s2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (s1 == s2)
|
|
|
|
return s1;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
FcStrCaseWalkerInit (s1, &w1);
|
|
|
|
FcStrCaseWalkerInit (s2, &w2);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2013-01-18 03:30:10 +01:00
|
|
|
c2 = FcStrCaseWalkerNext (&w2, NULL);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
for (;;)
|
2003-05-28 03:34:38 +02:00
|
|
|
{
|
2004-12-29 10:15:17 +01:00
|
|
|
cur = w1.src;
|
2013-01-18 03:30:10 +01:00
|
|
|
c1 = FcStrCaseWalkerNext (&w1, NULL);
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c1)
|
2003-05-28 03:34:38 +02:00
|
|
|
break;
|
2004-12-29 10:15:17 +01:00
|
|
|
if (c1 == c2)
|
|
|
|
{
|
|
|
|
FcCaseWalker w1t = w1;
|
|
|
|
FcCaseWalker w2t = w2;
|
|
|
|
FcChar8 c1t, c2t;
|
2003-05-28 03:34:38 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
for (;;)
|
|
|
|
{
|
2013-01-18 03:30:10 +01:00
|
|
|
c1t = FcStrCaseWalkerNext (&w1t, NULL);
|
|
|
|
c2t = FcStrCaseWalkerNext (&w2t, NULL);
|
2003-05-28 03:34:38 +02:00
|
|
|
|
2004-12-29 10:15:17 +01:00
|
|
|
if (!c2t)
|
|
|
|
return cur;
|
|
|
|
if (c2t != c1t)
|
|
|
|
break;
|
|
|
|
}
|
2003-05-28 03:34:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const FcChar8 *
|
|
|
|
FcStrStr (const FcChar8 *s1, const FcChar8 *s2)
|
|
|
|
{
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
const FcChar8 * p = s1;
|
|
|
|
const FcChar8 * b = s2;
|
|
|
|
|
|
|
|
if (!s1 || !s2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (s1 == s2)
|
|
|
|
return s1;
|
|
|
|
|
|
|
|
again:
|
|
|
|
c2 = *s2++;
|
|
|
|
|
|
|
|
if (!c2)
|
|
|
|
return 0;
|
|
|
|
|
2010-04-12 18:18:50 +02:00
|
|
|
for (;;)
|
2003-05-28 03:34:38 +02:00
|
|
|
{
|
|
|
|
p = s1;
|
|
|
|
c1 = *s1++;
|
|
|
|
if (!c1 || c1 == c2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c1 != c2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
c1 = *s1;
|
|
|
|
c2 = *s2;
|
|
|
|
if (c1 && c2 && c1 != c2)
|
|
|
|
{
|
|
|
|
s1 = p + 1;
|
|
|
|
s2 = b;
|
|
|
|
goto again;
|
|
|
|
}
|
|
|
|
if (!c2)
|
|
|
|
return p;
|
|
|
|
if (!c1)
|
|
|
|
return 0;
|
|
|
|
++ s1;
|
|
|
|
++ s2;
|
|
|
|
}
|
2006-02-21 16:40:18 +01:00
|
|
|
/* never reached. */
|
2003-05-28 03:34:38 +02:00
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
int
|
2002-08-24 22:08:53 +02:00
|
|
|
FcUtf8ToUcs4 (const FcChar8 *src_orig,
|
|
|
|
FcChar32 *dst,
|
|
|
|
int len)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-08-24 22:08:53 +02:00
|
|
|
const FcChar8 *src = src_orig;
|
|
|
|
FcChar8 s;
|
|
|
|
int extra;
|
|
|
|
FcChar32 result;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (len == 0)
|
|
|
|
return 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
s = *src++;
|
|
|
|
len--;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!(s & 0x80))
|
|
|
|
{
|
|
|
|
result = s;
|
|
|
|
extra = 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
else if (!(s & 0x40))
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (!(s & 0x20))
|
|
|
|
{
|
|
|
|
result = s & 0x1f;
|
|
|
|
extra = 1;
|
|
|
|
}
|
|
|
|
else if (!(s & 0x10))
|
|
|
|
{
|
|
|
|
result = s & 0xf;
|
|
|
|
extra = 2;
|
|
|
|
}
|
|
|
|
else if (!(s & 0x08))
|
|
|
|
{
|
|
|
|
result = s & 0x07;
|
|
|
|
extra = 3;
|
|
|
|
}
|
|
|
|
else if (!(s & 0x04))
|
|
|
|
{
|
|
|
|
result = s & 0x03;
|
|
|
|
extra = 4;
|
|
|
|
}
|
|
|
|
else if ( ! (s & 0x02))
|
|
|
|
{
|
|
|
|
result = s & 0x01;
|
|
|
|
extra = 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (extra > len)
|
|
|
|
return -1;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
while (extra--)
|
|
|
|
{
|
|
|
|
result <<= 6;
|
|
|
|
s = *src++;
|
|
|
|
|
|
|
|
if ((s & 0xc0) != 0x80)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
result |= s & 0x3f;
|
|
|
|
}
|
|
|
|
*dst = result;
|
|
|
|
return src - src_orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2002-08-24 22:08:53 +02:00
|
|
|
FcUtf8Len (const FcChar8 *string,
|
|
|
|
int len,
|
|
|
|
int *nchar,
|
|
|
|
int *wchar)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
int clen;
|
|
|
|
FcChar32 c;
|
|
|
|
FcChar32 max;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
n = 0;
|
|
|
|
max = 0;
|
|
|
|
while (len)
|
|
|
|
{
|
|
|
|
clen = FcUtf8ToUcs4 (string, &c, len);
|
|
|
|
if (clen <= 0) /* malformed UTF8 string */
|
|
|
|
return FcFalse;
|
|
|
|
if (c > max)
|
|
|
|
max = c;
|
|
|
|
string += clen;
|
|
|
|
len -= clen;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
*nchar = n;
|
|
|
|
if (max >= 0x10000)
|
|
|
|
*wchar = 4;
|
|
|
|
else if (max > 0x100)
|
|
|
|
*wchar = 2;
|
|
|
|
else
|
|
|
|
*wchar = 1;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
|
2002-07-13 07:43:25 +02:00
|
|
|
int
|
|
|
|
FcUcs4ToUtf8 (FcChar32 ucs4,
|
|
|
|
FcChar8 dest[FC_UTF8_MAX_LEN])
|
|
|
|
{
|
|
|
|
int bits;
|
|
|
|
FcChar8 *d = dest;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-07-13 07:43:25 +02:00
|
|
|
if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
|
|
|
|
else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
|
|
|
|
else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
|
|
|
|
else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
|
|
|
|
else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
|
|
|
|
else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
|
|
|
|
else return 0;
|
|
|
|
|
|
|
|
for ( ; bits >= 0; bits-= 6) {
|
|
|
|
*d++= ((ucs4 >> bits) & 0x3F) | 0x80;
|
|
|
|
}
|
|
|
|
return d - dest;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define GetUtf16(src,endian) \
|
|
|
|
((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
|
|
|
|
(FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
|
|
|
|
|
|
|
|
int
|
2002-08-24 22:08:53 +02:00
|
|
|
FcUtf16ToUcs4 (const FcChar8 *src_orig,
|
|
|
|
FcEndian endian,
|
|
|
|
FcChar32 *dst,
|
|
|
|
int len) /* in bytes */
|
2002-07-13 07:43:25 +02:00
|
|
|
{
|
2002-08-24 22:08:53 +02:00
|
|
|
const FcChar8 *src = src_orig;
|
|
|
|
FcChar16 a, b;
|
|
|
|
FcChar32 result;
|
2002-07-13 07:43:25 +02:00
|
|
|
|
|
|
|
if (len < 2)
|
|
|
|
return 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-07-13 07:43:25 +02:00
|
|
|
a = GetUtf16 (src, endian); src += 2; len -= 2;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check for surrogate
|
2002-07-13 07:43:25 +02:00
|
|
|
*/
|
|
|
|
if ((a & 0xfc00) == 0xd800)
|
|
|
|
{
|
|
|
|
if (len < 2)
|
|
|
|
return 0;
|
|
|
|
b = GetUtf16 (src, endian); src += 2; len -= 2;
|
|
|
|
/*
|
|
|
|
* Check for invalid surrogate sequence
|
|
|
|
*/
|
|
|
|
if ((b & 0xfc00) != 0xdc00)
|
|
|
|
return 0;
|
|
|
|
result = ((((FcChar32) a & 0x3ff) << 10) |
|
2002-12-14 02:59:38 +01:00
|
|
|
((FcChar32) b & 0x3ff)) + 0x10000;
|
2002-07-13 07:43:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
result = a;
|
|
|
|
*dst = result;
|
|
|
|
return src - src_orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2002-08-24 22:08:53 +02:00
|
|
|
FcUtf16Len (const FcChar8 *string,
|
|
|
|
FcEndian endian,
|
|
|
|
int len, /* in bytes */
|
|
|
|
int *nchar,
|
|
|
|
int *wchar)
|
2002-07-13 07:43:25 +02:00
|
|
|
{
|
|
|
|
int n;
|
|
|
|
int clen;
|
|
|
|
FcChar32 c;
|
|
|
|
FcChar32 max;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-07-13 07:43:25 +02:00
|
|
|
n = 0;
|
|
|
|
max = 0;
|
|
|
|
while (len)
|
|
|
|
{
|
|
|
|
clen = FcUtf16ToUcs4 (string, endian, &c, len);
|
|
|
|
if (clen <= 0) /* malformed UTF8 string */
|
|
|
|
return FcFalse;
|
|
|
|
if (c > max)
|
|
|
|
max = c;
|
|
|
|
string += clen;
|
|
|
|
len -= clen;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
*nchar = n;
|
|
|
|
if (max >= 0x10000)
|
|
|
|
*wchar = 4;
|
|
|
|
else if (max > 0x100)
|
|
|
|
*wchar = 2;
|
|
|
|
else
|
|
|
|
*wchar = 1;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
void
|
|
|
|
FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
|
|
|
|
{
|
2009-03-11 18:56:09 +01:00
|
|
|
if (init)
|
|
|
|
{
|
|
|
|
buf->buf = init;
|
|
|
|
buf->size = size;
|
|
|
|
} else
|
|
|
|
{
|
2009-03-12 17:31:57 +01:00
|
|
|
buf->buf = buf->buf_static;
|
|
|
|
buf->size = sizeof (buf->buf_static);
|
2009-03-11 18:56:09 +01:00
|
|
|
}
|
2002-02-18 23:29:28 +01:00
|
|
|
buf->allocated = FcFalse;
|
|
|
|
buf->failed = FcFalse;
|
|
|
|
buf->len = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FcStrBufDestroy (FcStrBuf *buf)
|
|
|
|
{
|
|
|
|
if (buf->allocated)
|
|
|
|
{
|
|
|
|
free (buf->buf);
|
|
|
|
FcStrBufInit (buf, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FcChar8 *
|
|
|
|
FcStrBufDone (FcStrBuf *buf)
|
|
|
|
{
|
|
|
|
FcChar8 *ret;
|
|
|
|
|
2009-02-10 10:47:24 +01:00
|
|
|
if (buf->failed)
|
|
|
|
ret = NULL;
|
|
|
|
else
|
|
|
|
ret = malloc (buf->len + 1);
|
2002-02-18 23:29:28 +01:00
|
|
|
if (ret)
|
|
|
|
{
|
|
|
|
memcpy (ret, buf->buf, buf->len);
|
|
|
|
ret[buf->len] = '\0';
|
|
|
|
}
|
|
|
|
FcStrBufDestroy (buf);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-03-11 19:07:15 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrBufDoneStatic (FcStrBuf *buf)
|
|
|
|
{
|
|
|
|
FcStrBufChar (buf, '\0');
|
|
|
|
|
|
|
|
if (buf->failed)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return buf->buf;
|
|
|
|
}
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
FcBool
|
|
|
|
FcStrBufChar (FcStrBuf *buf, FcChar8 c)
|
|
|
|
{
|
|
|
|
if (buf->len == buf->size)
|
|
|
|
{
|
|
|
|
FcChar8 *new;
|
|
|
|
int size;
|
|
|
|
|
2009-02-10 10:47:24 +01:00
|
|
|
if (buf->failed)
|
|
|
|
return FcFalse;
|
|
|
|
|
2002-02-18 23:29:28 +01:00
|
|
|
if (buf->allocated)
|
|
|
|
{
|
|
|
|
size = buf->size * 2;
|
|
|
|
new = realloc (buf->buf, size);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-04-27 10:13:45 +02:00
|
|
|
size = buf->size + 64;
|
2002-02-18 23:29:28 +01:00
|
|
|
new = malloc (size);
|
|
|
|
if (new)
|
|
|
|
{
|
|
|
|
buf->allocated = FcTrue;
|
|
|
|
memcpy (new, buf->buf, buf->len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!new)
|
|
|
|
{
|
|
|
|
buf->failed = FcTrue;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
buf->size = size;
|
|
|
|
buf->buf = new;
|
|
|
|
}
|
|
|
|
buf->buf[buf->len++] = c;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcChar8 c;
|
|
|
|
while ((c = *s++))
|
|
|
|
if (!FcStrBufChar (buf, c))
|
|
|
|
return FcFalse;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
|
|
|
|
{
|
|
|
|
while (len-- > 0)
|
|
|
|
if (!FcStrBufChar (buf, *s++))
|
|
|
|
return FcFalse;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2003-03-02 20:12:23 +01:00
|
|
|
FcBool
|
|
|
|
FcStrUsesHome (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
return *s == '~';
|
|
|
|
}
|
|
|
|
|
2018-07-12 00:50:26 +02:00
|
|
|
FcBool
|
|
|
|
FcStrIsAbsoluteFilename (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (*s == '\\' ||
|
2018-08-21 05:08:58 +02:00
|
|
|
(isalpha (*s) && s[1] == ':' && (s[2] == '/' || s[2] == '\\')))
|
2018-07-12 00:50:26 +02:00
|
|
|
return FcTrue;
|
|
|
|
#endif
|
|
|
|
return *s == '/';
|
|
|
|
}
|
|
|
|
|
2013-02-06 11:35:30 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrBuildFilename (const FcChar8 *path,
|
|
|
|
...)
|
|
|
|
{
|
|
|
|
va_list ap;
|
2013-11-02 18:23:56 +01:00
|
|
|
FcStrSet *sset;
|
2013-02-06 11:35:30 +01:00
|
|
|
FcStrList *list;
|
|
|
|
FcChar8 *s, *ret = NULL, *p;
|
|
|
|
size_t len = 0;
|
|
|
|
|
2013-11-02 18:23:56 +01:00
|
|
|
if (!path)
|
|
|
|
return NULL;
|
|
|
|
|
2016-01-09 03:06:31 +01:00
|
|
|
sset = FcStrSetCreateEx (FCSS_ALLOW_DUPLICATES | FCSS_GROW_BY_64);
|
2013-11-02 18:23:56 +01:00
|
|
|
if (!sset)
|
2013-02-06 11:35:30 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (!FcStrSetAdd (sset, path))
|
|
|
|
goto bail0;
|
|
|
|
|
|
|
|
va_start (ap, path);
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
s = (FcChar8 *)va_arg (ap, FcChar8 *);
|
|
|
|
if (!s)
|
|
|
|
break;
|
|
|
|
if (!FcStrSetAdd (sset, s))
|
|
|
|
goto bail1;
|
|
|
|
}
|
|
|
|
list = FcStrListCreate (sset);
|
|
|
|
while ((s = FcStrListNext (list)))
|
|
|
|
{
|
|
|
|
len += strlen ((const char *)s) + 1;
|
|
|
|
}
|
|
|
|
list->n = 0;
|
|
|
|
ret = malloc (sizeof (FcChar8) * (len + 1));
|
|
|
|
if (!ret)
|
|
|
|
goto bail2;
|
|
|
|
p = ret;
|
|
|
|
while ((s = FcStrListNext (list)))
|
|
|
|
{
|
|
|
|
if (p != ret)
|
|
|
|
{
|
|
|
|
p[0] = FC_DIR_SEPARATOR;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
len = strlen ((const char *)s);
|
|
|
|
memcpy (p, s, len);
|
|
|
|
p += len;
|
|
|
|
}
|
|
|
|
*p = 0;
|
|
|
|
|
|
|
|
bail2:
|
|
|
|
FcStrListDone (list);
|
|
|
|
bail1:
|
|
|
|
va_end (ap);
|
|
|
|
bail0:
|
|
|
|
FcStrSetDestroy (sset);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcChar8 *
|
|
|
|
FcStrCopyFilename (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcChar8 *new;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
if (*s == '~')
|
|
|
|
{
|
2003-03-02 20:12:23 +01:00
|
|
|
FcChar8 *home = FcConfigHome ();
|
2006-09-02 23:52:37 +02:00
|
|
|
FcChar8 *full;
|
2003-02-06 20:30:32 +01:00
|
|
|
int size;
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!home)
|
2012-03-12 11:18:19 +01:00
|
|
|
return NULL;
|
2003-02-06 20:30:32 +01:00
|
|
|
size = strlen ((char *) home) + strlen ((char *) s);
|
2018-07-25 05:40:17 +02:00
|
|
|
full = (FcChar8 *) malloc (size + 1);
|
2006-09-03 08:09:44 +02:00
|
|
|
if (!full)
|
2012-03-12 11:18:19 +01:00
|
|
|
return NULL;
|
2006-09-02 23:52:37 +02:00
|
|
|
strcpy ((char *) full, (char *) home);
|
|
|
|
strcat ((char *) full, (char *) s + 1);
|
|
|
|
new = FcStrCanonFilename (full);
|
|
|
|
free (full);
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
|
|
|
else
|
2006-09-02 23:52:37 +02:00
|
|
|
new = FcStrCanonFilename (s);
|
2012-03-12 11:18:19 +01:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcStrLastSlash (const FcChar8 *path)
|
|
|
|
{
|
|
|
|
FcChar8 *slash;
|
|
|
|
|
|
|
|
slash = (FcChar8 *) strrchr ((const char *) path, '/');
|
|
|
|
#ifdef _WIN32
|
|
|
|
{
|
|
|
|
FcChar8 *backslash;
|
|
|
|
|
|
|
|
backslash = (FcChar8 *) strrchr ((const char *) path, '\\');
|
|
|
|
if (!slash || (backslash && backslash > slash))
|
|
|
|
slash = backslash;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return slash;
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcChar8 *
|
|
|
|
FcStrDirname (const FcChar8 *file)
|
|
|
|
{
|
|
|
|
FcChar8 *slash;
|
|
|
|
FcChar8 *dir;
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
slash = FcStrLastSlash (file);
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!slash)
|
|
|
|
return FcStrCopy ((FcChar8 *) ".");
|
|
|
|
dir = malloc ((slash - file) + 1);
|
|
|
|
if (!dir)
|
|
|
|
return 0;
|
|
|
|
strncpy ((char *) dir, (const char *) file, slash - file);
|
|
|
|
dir[slash - file] = '\0';
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcChar8 *
|
|
|
|
FcStrBasename (const FcChar8 *file)
|
|
|
|
{
|
|
|
|
FcChar8 *slash;
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
slash = FcStrLastSlash (file);
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!slash)
|
|
|
|
return FcStrCopy (file);
|
|
|
|
return FcStrCopy (slash + 1);
|
|
|
|
}
|
|
|
|
|
2006-11-13 02:15:55 +01:00
|
|
|
static FcChar8 *
|
2006-09-17 23:34:46 +02:00
|
|
|
FcStrCanonAbsoluteFilename (const FcChar8 *s)
|
2006-08-28 08:40:51 +02:00
|
|
|
{
|
|
|
|
FcChar8 *file;
|
|
|
|
FcChar8 *f;
|
|
|
|
const FcChar8 *slash;
|
2006-09-02 23:52:37 +02:00
|
|
|
int size;
|
2006-09-17 23:34:46 +02:00
|
|
|
|
2006-09-02 23:52:37 +02:00
|
|
|
size = strlen ((char *) s) + 1;
|
|
|
|
file = malloc (size);
|
2006-08-28 08:40:51 +02:00
|
|
|
if (!file)
|
|
|
|
return NULL;
|
|
|
|
slash = NULL;
|
|
|
|
f = file;
|
2012-10-09 04:03:03 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (*s == '/' && *(s+1) == '/') /* Network path, do not squash // */
|
|
|
|
*f++ = *s++;
|
|
|
|
#endif
|
2006-08-28 08:40:51 +02:00
|
|
|
for (;;) {
|
|
|
|
if (*s == '/' || *s == '\0')
|
|
|
|
{
|
|
|
|
if (slash)
|
|
|
|
{
|
|
|
|
switch (s - slash) {
|
2008-08-12 21:10:04 +02:00
|
|
|
case 1:
|
|
|
|
f -= 1; /* squash // and trim final / from file */
|
|
|
|
break;
|
2006-08-28 08:40:51 +02:00
|
|
|
case 2:
|
|
|
|
if (!strncmp ((char *) slash, "/.", 2))
|
|
|
|
{
|
|
|
|
f -= 2; /* trim /. from file */
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (!strncmp ((char *) slash, "/..", 3))
|
|
|
|
{
|
|
|
|
f -= 3; /* trim /.. from file */
|
|
|
|
while (f > file) {
|
|
|
|
if (*--f == '/')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
slash = s;
|
|
|
|
}
|
|
|
|
if (!(*f++ = *s++))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return file;
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-17 23:34:46 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
/*
|
2010-04-12 18:18:50 +02:00
|
|
|
* Convert '\\' to '/' , remove double '/'
|
2006-09-17 23:34:46 +02:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
FcConvertDosPath (char *str)
|
|
|
|
{
|
|
|
|
size_t len = strlen (str);
|
|
|
|
char *p = str;
|
|
|
|
char *dest = str;
|
|
|
|
char *end = str + len;
|
|
|
|
char last = 0;
|
2009-02-04 02:50:29 +01:00
|
|
|
|
|
|
|
if (*p == '\\')
|
|
|
|
{
|
|
|
|
*p = '/';
|
|
|
|
p++;
|
|
|
|
dest++;
|
|
|
|
}
|
2006-09-17 23:34:46 +02:00
|
|
|
while (p < end)
|
|
|
|
{
|
|
|
|
if (*p == '\\')
|
|
|
|
*p = '/';
|
|
|
|
|
|
|
|
if (*p != '/'
|
|
|
|
|| last != '/')
|
|
|
|
{
|
|
|
|
*dest++ = *p;
|
|
|
|
}
|
|
|
|
|
|
|
|
last = *p;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
|
|
|
|
*dest = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
FcChar8 *
|
|
|
|
FcStrCanonFilename (const FcChar8 *s)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
|
|
FcChar8 full[FC_MAX_FILE_LEN + 2];
|
2012-06-13 13:01:30 +02:00
|
|
|
int size = GetFullPathName ((LPCSTR) s, sizeof (full) -1,
|
|
|
|
(LPSTR) full, NULL);
|
2006-09-17 23:34:46 +02:00
|
|
|
|
|
|
|
if (size == 0)
|
|
|
|
perror ("GetFullPathName");
|
|
|
|
|
2012-06-13 13:01:30 +02:00
|
|
|
FcConvertDosPath ((char *) full);
|
2006-09-17 23:34:46 +02:00
|
|
|
return FcStrCanonAbsoluteFilename (full);
|
|
|
|
#else
|
|
|
|
if (s[0] == '/')
|
|
|
|
return FcStrCanonAbsoluteFilename (s);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
FcChar8 *full;
|
|
|
|
FcChar8 *file;
|
|
|
|
|
|
|
|
FcChar8 cwd[FC_MAX_FILE_LEN + 2];
|
|
|
|
if (getcwd ((char *) cwd, FC_MAX_FILE_LEN) == NULL)
|
|
|
|
return NULL;
|
2013-02-06 11:35:30 +01:00
|
|
|
full = FcStrBuildFilename (cwd, s, NULL);
|
2006-09-17 23:34:46 +02:00
|
|
|
file = FcStrCanonAbsoluteFilename (full);
|
|
|
|
FcStrFree (full);
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2006-08-28 08:40:51 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrSet *
|
|
|
|
FcStrSetCreate (void)
|
2016-01-09 03:06:31 +01:00
|
|
|
{
|
|
|
|
return FcStrSetCreateEx (FCSS_DEFAULT);
|
|
|
|
}
|
|
|
|
|
|
|
|
FcStrSet *
|
|
|
|
FcStrSetCreateEx (unsigned int control)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
FcStrSet *set = malloc (sizeof (FcStrSet));
|
|
|
|
if (!set)
|
|
|
|
return 0;
|
2012-10-07 20:41:38 +02:00
|
|
|
FcRefInit (&set->ref, 1);
|
2002-05-21 19:06:22 +02:00
|
|
|
set->num = 0;
|
|
|
|
set->size = 0;
|
2005-08-24 08:21:30 +02:00
|
|
|
set->strs = 0;
|
2016-01-09 03:06:31 +01:00
|
|
|
set->control = control;
|
2002-05-21 19:06:22 +02:00
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
2016-01-09 03:06:31 +01:00
|
|
|
static FcBool
|
|
|
|
_FcStrSetGrow (FcStrSet *set, int growElements)
|
|
|
|
{
|
|
|
|
/* accommodate an additional NULL entry at the end of the array */
|
|
|
|
FcChar8 **strs = malloc ((set->size + growElements + 1) * sizeof (FcChar8 *));
|
|
|
|
if (!strs)
|
|
|
|
return FcFalse;
|
|
|
|
if (set->num)
|
|
|
|
memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
|
|
|
|
if (set->strs)
|
|
|
|
free (set->strs);
|
|
|
|
set->size = set->size + growElements;
|
|
|
|
set->strs = strs;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
static FcBool
|
|
|
|
_FcStrSetAppend (FcStrSet *set, FcChar8 *s)
|
|
|
|
{
|
2016-01-09 03:06:31 +01:00
|
|
|
if (!FcStrSetHasControlBit (set, FCSS_ALLOW_DUPLICATES))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2016-01-09 03:06:31 +01:00
|
|
|
if (FcStrSetMember (set, s))
|
|
|
|
{
|
|
|
|
FcStrFree (s);
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
2005-08-24 08:21:30 +02:00
|
|
|
if (set->num == set->size)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2016-01-09 03:06:31 +01:00
|
|
|
int growElements = FcStrSetHasControlBit (set, FCSS_GROW_BY_64) ? 64 : 1;
|
|
|
|
if (!_FcStrSetGrow(set, growElements))
|
|
|
|
return FcFalse;
|
2005-08-24 08:21:30 +02:00
|
|
|
}
|
|
|
|
set->strs[set->num++] = s;
|
|
|
|
set->strs[set->num] = 0;
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcStrSetMember (FcStrSet *set, const FcChar8 *s)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < set->num; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
if (!FcStrCmp (set->strs[i], s))
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcTrue;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2019-04-03 06:48:42 +02:00
|
|
|
static int
|
|
|
|
fc_strcmp_r (const FcChar8 *s1, const FcChar8 *s2, const FcChar8 **ret)
|
|
|
|
{
|
|
|
|
FcChar8 c1, c2;
|
|
|
|
|
|
|
|
if (s1 == s2)
|
|
|
|
{
|
|
|
|
if (ret)
|
|
|
|
*ret = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
if (s1)
|
|
|
|
c1 = *s1++;
|
|
|
|
else
|
|
|
|
c1 = 0;
|
|
|
|
if (s2)
|
|
|
|
c2 = *s2++;
|
|
|
|
else
|
|
|
|
c2 = 0;
|
|
|
|
if (!c1 || c1 != c2)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ret)
|
|
|
|
*ret = s1;
|
|
|
|
return (int) c1 - (int) c2;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcStrSetMemberAB (FcStrSet *set, const FcChar8 *a, FcChar8 *b, FcChar8 **ret)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
const FcChar8 *s = NULL;
|
|
|
|
|
|
|
|
for (i = 0; i < set->num; i++)
|
|
|
|
{
|
|
|
|
if (!fc_strcmp_r (set->strs[i], a, &s) && s)
|
|
|
|
{
|
|
|
|
if (!fc_strcmp_r (s, b, NULL))
|
|
|
|
{
|
|
|
|
if (ret)
|
|
|
|
*ret = set->strs[i];
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (ret)
|
|
|
|
*ret = NULL;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2002-08-22 09:36:45 +02:00
|
|
|
FcBool
|
|
|
|
FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
if (sa->num != sb->num)
|
|
|
|
return FcFalse;
|
|
|
|
for (i = 0; i < sa->num; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
if (!FcStrSetMember (sb, sa->strs[i]))
|
2002-08-22 09:36:45 +02:00
|
|
|
return FcFalse;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcBool
|
|
|
|
FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcChar8 *new = FcStrCopy (s);
|
|
|
|
if (!new)
|
|
|
|
return FcFalse;
|
|
|
|
if (!_FcStrSetAppend (set, new))
|
|
|
|
{
|
|
|
|
FcStrFree (new);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
FcBool
|
2019-01-31 11:17:47 +01:00
|
|
|
FcStrSetAddTriple (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *c)
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
{
|
2019-01-31 11:17:47 +01:00
|
|
|
FcChar8 *new = FcStrMakeTriple (a, b, c);
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
if (!new)
|
|
|
|
return FcFalse;
|
|
|
|
if (!_FcStrSetAppend (set, new))
|
|
|
|
{
|
|
|
|
FcStrFree (new);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2019-01-31 11:17:47 +01:00
|
|
|
const FcChar8 *
|
|
|
|
FcStrTripleSecond (FcChar8 *str)
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
{
|
|
|
|
FcChar8 *second = str + strlen((char *) str) + 1;
|
|
|
|
|
|
|
|
if (*second == '\0')
|
|
|
|
return 0;
|
|
|
|
return second;
|
|
|
|
}
|
|
|
|
|
2019-01-31 11:17:47 +01:00
|
|
|
const FcChar8 *
|
|
|
|
FcStrTripleThird (FcChar8 *str)
|
|
|
|
{
|
|
|
|
FcChar8 *second = str + strlen ((char *) str) + 1;
|
|
|
|
FcChar8 *third = second + strlen ((char *) second) + 1;
|
|
|
|
|
|
|
|
if (*third == '\0')
|
|
|
|
return 0;
|
|
|
|
return third;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcBool
|
|
|
|
FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
|
|
|
|
{
|
|
|
|
FcChar8 *new = FcStrCopyFilename (s);
|
|
|
|
if (!new)
|
|
|
|
return FcFalse;
|
|
|
|
if (!_FcStrSetAppend (set, new))
|
|
|
|
{
|
|
|
|
FcStrFree (new);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
FcBool
|
2019-01-31 11:17:47 +01:00
|
|
|
FcStrSetAddFilenamePairWithSalt (FcStrSet *set, const FcChar8 *a, const FcChar8 *b, const FcChar8 *salt)
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
{
|
|
|
|
FcChar8 *new_a = NULL;
|
|
|
|
FcChar8 *new_b = NULL;
|
2019-04-03 06:48:42 +02:00
|
|
|
FcChar8 *rs = NULL;
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
FcBool ret;
|
|
|
|
|
|
|
|
if (a)
|
|
|
|
{
|
|
|
|
new_a = FcStrCopyFilename (a);
|
|
|
|
if (!new_a)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
if (b)
|
|
|
|
{
|
|
|
|
new_b = FcStrCopyFilename(b);
|
|
|
|
if (!new_b)
|
|
|
|
{
|
|
|
|
if (new_a)
|
|
|
|
FcStrFree(new_a);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
}
|
2019-04-03 06:48:42 +02:00
|
|
|
/* Override maps with new one if exists */
|
|
|
|
if (FcStrSetMemberAB (set, new_a, new_b, &rs))
|
|
|
|
{
|
|
|
|
FcStrSetDel (set, rs);
|
|
|
|
}
|
2019-01-31 11:17:47 +01:00
|
|
|
ret = FcStrSetAddTriple (set, new_a, new_b, salt);
|
Replace UUID file mechanism with per-directory 'map' attribute [v2]
The UUID files would be placed in each font directory to provide the
unique cache name, independent of path, for that directory. The UUID
files are undesireable for a couple of reasons:
1) They must be placed in the font directories to be useful. This
requires modifying the font directories themselves, introducing
potential visible timestamp changes when running multiple
applications, and makes the cache processing inconsistent between
applications with permission to write to the font directories and
applications without such permission.
2) The UUID contents were generated randomly, which makes the font
cache not reproducible across multiple runs.
One proposed fix for 2) is to make the UUID dependent on the font
directory path, but once we do that, we can simply use the font
directory path itself as the key as the original MD5-based font cache
naming mechanism did.
The goal of the UUID file mechanism was to fix startup time of
flatpaks; as the font path names inside the flatpak did not match the
font path names in the base system, the font cache would need to be
reconstructed the first time the flatpak was launched.
The new mechanism for doing this is to allow each '<dir>' element in
the configuration include a 'map' attribute. When looking for a cache
file for a particular directory, if the directory name starts with the
contents of the <dir> element, that portion of the name will be
replaced with the value of the 'map' attribute.
Outside of the flatpak, nothing need change -- fontconfig will build
cache files using real directory names.
Inside the flatpak, the custom fonts.conf file will now include
mappings such as this:
<dir map="/usr/share/fonts">/run/host/fonts</dir>
When scanning the directory /run/host/fonts/ttf, fontconfig will
use the name /usr/share/fonts/ttf as the source for building the cache
file name.
The existing FC_FILE replacement code used for the UUID-based
implementation continues to correctly adapt font path names seen by
applications.
v2:
Leave FcDirCacheCreateUUID stub around to avoid removing
public API function.
Document 'map' attribute of <dir> element in
fontconfig-user.sgml
Suggested-by: Akira TAGOH <akira@tagoh.org>
Signed-off-by: Keith Packard <keithp@keithp.com>
2018-10-30 00:39:05 +01:00
|
|
|
if (new_a)
|
|
|
|
FcStrFree (new_a);
|
|
|
|
if (new_b)
|
|
|
|
FcStrFree (new_b);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-03-29 13:25:20 +02:00
|
|
|
FcBool
|
|
|
|
FcStrSetAddLangs (FcStrSet *strs, const char *languages)
|
|
|
|
{
|
|
|
|
const char *p = languages, *next;
|
|
|
|
FcChar8 lang[128] = {0}, *normalized_lang;
|
|
|
|
size_t len;
|
|
|
|
FcBool ret = FcFalse;
|
|
|
|
|
|
|
|
if (!languages)
|
|
|
|
return FcFalse;
|
|
|
|
|
|
|
|
while ((next = strchr (p, ':')))
|
|
|
|
{
|
|
|
|
len = next - p;
|
2012-12-11 04:35:02 +01:00
|
|
|
len = FC_MIN (len, 127);
|
2012-03-29 13:25:20 +02:00
|
|
|
strncpy ((char *) lang, p, len);
|
|
|
|
lang[len] = 0;
|
|
|
|
/* ignore an empty item */
|
|
|
|
if (*lang)
|
|
|
|
{
|
|
|
|
normalized_lang = FcLangNormalize ((const FcChar8 *) lang);
|
|
|
|
if (normalized_lang)
|
|
|
|
{
|
|
|
|
FcStrSetAdd (strs, normalized_lang);
|
2012-12-07 11:09:36 +01:00
|
|
|
FcStrFree (normalized_lang);
|
2012-03-29 13:25:20 +02:00
|
|
|
ret = FcTrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
p = next + 1;
|
|
|
|
}
|
|
|
|
if (*p)
|
|
|
|
{
|
|
|
|
normalized_lang = FcLangNormalize ((const FcChar8 *) p);
|
|
|
|
if (normalized_lang)
|
|
|
|
{
|
|
|
|
FcStrSetAdd (strs, normalized_lang);
|
2012-12-07 11:09:36 +01:00
|
|
|
FcStrFree (normalized_lang);
|
2012-03-29 13:25:20 +02:00
|
|
|
ret = FcTrue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcBool
|
|
|
|
FcStrSetDel (FcStrSet *set, const FcChar8 *s)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < set->num; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
if (!FcStrCmp (set->strs[i], s))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2005-08-24 08:21:30 +02:00
|
|
|
FcStrFree (set->strs[i]);
|
2002-05-21 19:06:22 +02:00
|
|
|
/*
|
|
|
|
* copy remaining string pointers and trailing
|
|
|
|
* NULL
|
|
|
|
*/
|
2010-04-12 18:18:50 +02:00
|
|
|
memmove (&set->strs[i], &set->strs[i+1],
|
2002-05-21 19:06:22 +02:00
|
|
|
(set->num - i) * sizeof (FcChar8 *));
|
|
|
|
set->num--;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2019-01-31 08:52:09 +01:00
|
|
|
FcBool
|
|
|
|
FcStrSetDeleteAll (FcStrSet *set)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (FcRefIsConst (&set->ref))
|
|
|
|
return FcFalse;
|
|
|
|
|
|
|
|
for (i = set->num; i > 0; i--)
|
|
|
|
{
|
|
|
|
FcStrFree (set->strs[i - 1]);
|
|
|
|
set->num--;
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2013-01-08 20:01:48 +01:00
|
|
|
/* TODO Make public */
|
|
|
|
static FcStrSet *
|
|
|
|
FcStrSetReference (FcStrSet *set)
|
|
|
|
{
|
|
|
|
if (FcRefIsConst (&set->ref))
|
|
|
|
return set;
|
|
|
|
|
|
|
|
FcRefInc (&set->ref);
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
void
|
|
|
|
FcStrSetDestroy (FcStrSet *set)
|
|
|
|
{
|
2012-10-07 20:41:38 +02:00
|
|
|
int i;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2012-10-07 21:52:25 +02:00
|
|
|
/* We rely on this in FcGetDefaultLangs for caching. */
|
|
|
|
if (FcRefIsConst (&set->ref))
|
|
|
|
return;
|
|
|
|
|
2012-10-07 20:41:38 +02:00
|
|
|
if (FcRefDec (&set->ref) != 1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < set->num; i++)
|
|
|
|
FcStrFree (set->strs[i]);
|
|
|
|
if (set->strs)
|
|
|
|
free (set->strs);
|
|
|
|
free (set);
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
FcStrList *
|
|
|
|
FcStrListCreate (FcStrSet *set)
|
|
|
|
{
|
|
|
|
FcStrList *list;
|
|
|
|
|
|
|
|
list = malloc (sizeof (FcStrList));
|
|
|
|
if (!list)
|
|
|
|
return 0;
|
|
|
|
list->set = set;
|
2013-01-08 20:01:48 +01:00
|
|
|
FcStrSetReference (set);
|
2002-05-21 19:06:22 +02:00
|
|
|
list->n = 0;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2013-10-02 09:34:34 +02:00
|
|
|
void
|
|
|
|
FcStrListFirst (FcStrList *list)
|
|
|
|
{
|
|
|
|
list->n = 0;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcChar8 *
|
|
|
|
FcStrListNext (FcStrList *list)
|
|
|
|
{
|
|
|
|
if (list->n >= list->set->num)
|
|
|
|
return 0;
|
2005-08-24 08:21:30 +02:00
|
|
|
return list->set->strs[list->n++];
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FcStrListDone (FcStrList *list)
|
|
|
|
{
|
|
|
|
FcStrSetDestroy (list->set);
|
|
|
|
free (list);
|
|
|
|
}
|
2006-08-30 13:16:22 +02:00
|
|
|
|
2006-09-05 11:24:01 +02:00
|
|
|
#define __fcstr__
|
|
|
|
#include "fcaliastail.h"
|
|
|
|
#undef __fcstr__
|