Match 'ultra' on word boundaries to detect ultra bold fonts. (bug 2511)

Added FcStrContainsWord to detect strings on word boundaries.
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 3cf1686..d93292d 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -935,8 +935,18 @@
     int	i;
 
     for (i = 0; i < nc; i++)
-	if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
-	    return c[i].value;
+    {
+	if (c[i].name[0] == '<')
+	{
+	    if (FcStrContainsWord (string, c[i].name + 1))
+		return c[i].value;
+	}
+	else
+	{
+	    if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
+		return c[i].value;
+	}
+    }
     return -1;
 }
 
@@ -958,6 +968,8 @@
     { (FC8) "superbold",	FC_WEIGHT_EXTRABOLD },
     { (FC8) "ultrabold",	FC_WEIGHT_ULTRABOLD },
     { (FC8) "bold",		FC_WEIGHT_BOLD },
+    { (FC8) "<ultra",		FC_WEIGHT_ULTRABOLD }, /* only if a word */
+    { (FC8) "bold",		FC_WEIGHT_BOLD },
     { (FC8) "black",		FC_WEIGHT_BLACK },
     { (FC8) "heavy",		FC_WEIGHT_HEAVY },
 };
diff --git a/src/fcint.h b/src/fcint.h
index 3b9f3c8..8e57453 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -1046,6 +1046,9 @@
 const FcChar8 *
 FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2);
 
+const FcChar8 *
+FcStrContainsWord (const FcChar8 *s1, const FcChar8 *s2);
+
 FcBool
 FcStrUsesHome (const FcChar8 *s);
 
diff --git a/src/fcstr.c b/src/fcstr.c
index 5faf579..f803bad 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -320,6 +320,26 @@
     return 0;
 }
 
+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;
+}
+
 /*
  * Is the head of s1 equal to s2?
  */
@@ -344,7 +364,7 @@
 }
 
 /*
- * Does s1 contain an instance of s2 (ignoring blanks and case)?
+ * Does s1 contain an instance of s2 (ignoring case)?
  */
 
 const FcChar8 *
@@ -359,6 +379,34 @@
     return 0;
 }
 
+/*
+ * 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)
+    {
+	if (wordStart && 
+	    FcStrIsAtIgnoreCase (s1, s2) &&
+	    (s1len == s2len || FcCharIsPunct (s1[s2len])))
+	{
+	    return s1;
+	}
+	wordStart = FcFalse;
+	if (FcCharIsPunct (*s1))
+	    wordStart = FcTrue;
+	s1++;
+	s1len--;
+    }
+    return 0;
+}
+
 const FcChar8 *
 FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
 {