diff lib/fontset.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/fontset.c	Mon Mar 08 04:44:30 2010 +0900
@@ -0,0 +1,372 @@
+#ifndef lint
+static char *rcsid = "$Id: fontset.c,v 1.9 1994/06/02 04:59:23 ishisone Rel $";
+#endif
+/*
+ * Copyright (c) 1991  Software Research Associates, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, provided
+ * that the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Software Research Associates not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.  Software Research
+ * Associates makes no representations about the suitability of this software
+ * for any purpose.  It is provided "as is" without express or implied
+ * warranty.
+ *
+ * Author:  Makoto Ishisone, Software Research Associates, Inc., Japan
+ *
+ *  a FontSet handler for kinput2.
+ */
+
+#include <X11/Intrinsic.h>
+#include <X11/Xatom.h>
+#include <X11/Xmu/CharSet.h>
+#include "CachedAtom.h"
+#include "CachedFont.h"
+#include "KIFontSet.h"
+
+#define DEBUG_VAR debug_fontset
+#include "DebugPrint.h"
+
+typedef struct {
+    String name;
+    String xlfdname;
+} FSFontName;
+
+static char noname[] = "no";
+
+static int match();
+static Cardinal parseFontSet();
+static Boolean tryCharSet();
+static XFontStruct *csSuppliedMatchFont();
+static XFontStruct *exactMatchFont();
+static XFontStruct *csReplacedMatchFont();
+static String getXLFDName();
+
+
+/*- match: returns 1 if the specified string matches the pattern -*/
+static int
+match(s, p)
+register char *s;	/* string */
+register char *p;	/* pattern */
+{
+    register int tmp;
+
+    while ((tmp = *p++) != '\0') {
+	switch (tmp) {
+	case '?':
+	    if (*s++ == '\0') return 0;
+	    continue;
+	case '*':
+	    while ((tmp = match(s, p)) == 0) {
+		if (*s++ == '\0') return -1;
+	    }
+	    return tmp;
+	default:
+	    if (*s++ != tmp) return 0;
+	    continue;
+	}
+    }
+    return (*s == '\0');
+}
+
+/*- countCommas: count number of commas in the string -*/
+static Cardinal
+countCommas(s)
+String s;
+{
+    int n = 0;
+
+    while (*s != '\0') {
+	if (*s++ == ',') n++;
+    }
+    return n;
+}
+
+/*- parseFontSet: separate each font in a font name list -*/
+static Cardinal
+parseFontSet(spec, basenames)
+String spec;		/* IN */
+FSFontName *basenames;	/* OUT */
+{
+    register char *p, *q;
+    Cardinal nnames;
+    int c;
+
+    nnames = 0;
+    p = spec;
+    for (;;) {
+	/* skip leading blanks */
+	while ((c = *p) != '\0' && (c == ' ' || c == '\t' || c == '\n')) p++;
+	if (c == '\0') break;
+
+	basenames[nnames++].name = p;
+
+	/* find comma or NUL char */
+	for (q = p; (c = *q) != '\0' && c != ','; q++) ;
+
+	/* omit trailing blanks */
+	p = q - 1;
+	while ((c = *p) == ' ' || c == '\t' || c == '\n') *p-- = '\0';
+
+	if (*q == '\0') break;
+	*q = '\0';
+	p = q + 1;
+    }
+
+#ifdef DEBUG
+    if (DDEBUG_CONDITION(10)) {
+	if (nnames == 0) {
+	    printf("\tparse error\n");
+	} else {
+	    int i;
+	    printf("\t%d elements\n", nnames);
+	    for (i = 0; i < nnames; i++) printf("\t\t%s\n", basenames[i].name);
+	}
+    }
+#endif
+
+    return nnames;
+}
+
+/*- tryCharSet: apply specified function to the fontnames for getting appropriate font for given character set -*/
+static Boolean
+tryCharSet(dpy, cset, extfont, namelist, numlist, func)
+Display *dpy;
+KICharSet *cset;
+KICharSetFont *extfont;
+FSFontName *namelist;
+Cardinal numlist;
+XFontStruct *(*func)();
+{
+    KICharSetSpec *specs;
+    Cardinal i;
+    XFontStruct *font;
+
+    for (i = 0, specs = cset->specs; i < cset->num_specs; i++, specs++) {
+	font = (*func)(dpy, specs->pattern, namelist, numlist);
+	if (font != NULL) {
+	    extfont->charset = specs->pattern;
+	    extfont->cldata = specs->cldata;
+	    extfont->font = font;
+	    return True;
+	}
+    }
+    return False;
+}
+
+static XFontStruct *
+exactMatchFont(dpy, csetstr, namelist, numlist)
+Display *dpy;
+String csetstr;
+FSFontName *namelist;
+Cardinal numlist;
+{
+    XFontStruct *font;
+
+    while (numlist-- > 0) {
+	String name = (namelist++)->name;
+	String p;
+	int namelen;
+	int hyphen;
+	
+	if (*name != '-' && *name != '+') continue;	/* not an XLFD name */
+	
+	namelen = strlen(name);
+	for (p = name + namelen - 1, hyphen = 0; p > name; p--) {
+	    if (*p == '-') hyphen++;
+	    if (hyphen == 2) goto found;
+	}
+	continue;	/* doesn't contain charset part */
+
+    found:
+	p++;		/* now p points the charset part of the fontname */
+	if (match(p, csetstr) > 0 &&
+	    (font = CachedLoadQueryFontByName(dpy, name)) != NULL) {
+	    TRACE(("\tmatched in exactMatchFont()\n"));
+	    TRACE(("\t\tcset=%s, font=%s\n", csetstr, name));
+	    return font;
+	}
+    }
+    return NULL;
+}
+
+static XFontStruct *
+csSuppliedMatchFont(dpy, csetstr, namelist, numlist)
+Display *dpy;
+String csetstr;
+FSFontName *namelist;
+Cardinal numlist;
+{
+    XFontStruct *font;
+
+    while (numlist-- > 0) {
+	String name = (namelist++)->name;
+	char namebuf[512];
+
+	if (*name != '-' && *name != '+') continue;	/* not an XLFD name */
+
+	(void)strcpy(namebuf, name);
+	(void)strcat(namebuf, "-");
+	(void)strcat(namebuf, csetstr);
+
+	if ((font = CachedLoadQueryFontByName(dpy, namebuf)) != NULL) {
+	    TRACE(("\tmatched in csSuppliedMatchFont()\n"));
+	    TRACE(("\t\tcset=%s, font=%s\n", csetstr, namebuf));
+	    return font;
+	}
+    }
+    return NULL;
+}
+
+static XFontStruct *
+csReplacedMatchFont(dpy, csetstr, namelist, numlist)
+Display *dpy;
+String csetstr;
+FSFontName *namelist;
+Cardinal numlist;
+{
+    XFontStruct *font;
+
+    while (numlist-- > 0) {
+	String name = namelist->name;
+	char namebuf[512];
+	String p;
+	int namelen;
+	int hyphen;
+	
+	if (*name != '-' && *name != '+') {	/* non XLFD name */
+	    if (namelist->xlfdname == NULL ||
+		(namelist->xlfdname == noname &&
+		(namelist->xlfdname = getXLFDName(dpy, name)) == NULL)) {
+		/* this font doesn't have XLFD name */
+		namelist++;
+		continue;
+	    }
+	    name = namelist->xlfdname;
+	}
+	namelist++;
+
+	(void)strcpy(namebuf, name);
+	namelen = strlen(namebuf);
+
+	/* find charset part of the font name */
+	for (p = namebuf + namelen - 1, hyphen = 0; p > namebuf; p--) {
+	    if (*p == '-') hyphen++;
+	    if (hyphen == 2) goto found;
+	}
+	continue;	/* doesn't contain charset part */
+
+    found:
+	p++;		/* now p points the charset part of the fontname */
+
+	/* replace charset part */
+	(void)strcpy(p, csetstr);
+
+	if ((font = CachedLoadQueryFontByName(dpy, namebuf)) != NULL) {
+	    TRACE(("\tmatched in csReplacedMatchFont()\n"));
+	    TRACE(("\t\tcset=%s, font=%s\n", csetstr, namebuf));
+	    return font;
+	}
+    }
+    return NULL;
+}
+
+/*- getXLFDName: obtain XLFD font name from a non XLFD font name -*/
+static String
+getXLFDName(dpy, nonxlfdname)
+Display *dpy;
+String nonxlfdname;
+{
+    XFontStruct *font;
+    Atom fontprop;
+    String name;
+
+    TRACE(("getXLFDName(%s)\n", nonxlfdname));
+    font = CachedLoadQueryFontByName(dpy, nonxlfdname);
+    if (font == NULL) {
+	DPRINT(("getXLFDName(%s):CachedLoadQueryFontByName() failed\n",
+		nonxlfdname));
+	return NULL;
+    }
+    if (!XGetFontProperty(font, XA_FONT, (unsigned long *)&fontprop)) {
+	/* can't get 'FONT' property. so XLFD name cannot be obtained */
+	DPRINT(("getXLFDName(%s): can't get FONT property\n",
+		nonxlfdname));
+	CachedFreeFont(dpy, font);
+	return NULL;
+    }
+
+    CachedFreeFont(dpy, font);
+    name = CachedGetAtomName(dpy, fontprop);
+    TRACE(("\tgot %s\n", name));
+    return (*name == '-' || *name == '+') ? name : NULL;
+}
+
+
+/*
+ * public functions
+ */
+
+int
+ExtractFontsFromFontSet(dpy, fontset, charsets, exfonts, numcsets)
+Display *dpy;
+String fontset;
+KICharSet *charsets;
+KICharSetFont *exfonts;
+Cardinal numcsets;
+{
+    Cardinal nfonts;
+    String fsp;
+    char fsbuf[1024];
+    FSFontName *fnp;
+    FSFontName fnbuf[20];
+    int nfound;
+    int i;
+
+    TRACE(("ExtractFontsFromFontSet(fontset=%s)\n", fontset));
+    for (i = 0; i < numcsets; i++) {
+	exfonts[i].font = NULL;
+	exfonts[i].charset = NULL;
+	exfonts[i].cldata = NULL;
+    }
+
+    if (strlen(fontset) >= sizeof(fsbuf)) {
+	fsp = XtMalloc((unsigned int)(strlen(fontset) + 1));
+    } else {
+	fsp = fsbuf;
+    }
+    XmuCopyISOLatin1Lowered(fsp, fontset);
+
+    if ((nfonts = countCommas(fsp) + 1) >= XtNumber(fnbuf)) {
+	fnp = (FSFontName *)XtMalloc(nfonts * sizeof(FSFontName));
+    } else {
+	fnp = fnbuf;
+    }
+    for (i = 0; i < nfonts; i++) fnp[i].xlfdname = noname;
+
+    if ((nfonts = parseFontSet(fsp, fnp)) == 0) {
+	if (fsp != fsbuf) XtFree(fsp);
+	if (fnp != fnbuf) XtFree((char *)fnp);
+	return 0;
+    }
+
+    nfound = 0;
+    for (i = 0; i < numcsets; i++) {
+	KICharSet *cp = charsets + i;
+	KICharSetFont *fp = exfonts + i;
+
+	TRACE(("\tfor charset #%d\n", i));
+	if (tryCharSet(dpy, cp, fp, fnp, nfonts, exactMatchFont) ||
+	    tryCharSet(dpy, cp, fp, fnp, nfonts, csSuppliedMatchFont) ||
+	    tryCharSet(dpy, cp, fp, fnp, nfonts, csReplacedMatchFont)) {
+	    nfound++;
+	}
+    }
+    if (fsp != fsbuf) XtFree(fsp);
+    if (fnp != fnbuf) XtFree((char *)fnp);
+
+    return nfound;
+}