#ifdef HAVE_DMX_CONFIG_H
#include <dmx-config.h>
#endif
#define DMX_FONTPATH_DEBUG 0
#include "dmx.h"
#include "dmxsync.h"
#include "dmxfont.h"
#include "dmxlog.h"
#include <X11/fonts/fontstruct.h>
#include "dixfont.h"
#include "dixstruct.h"
static int (*dmxSaveProcVector[256])(ClientPtr);
static int dmxFontLastError;
static int dmxFontErrorHandler(Display *dpy, XErrorEvent *ev)
{
dmxFontLastError = ev->error_code;
return 0;
}
static char **dmxGetFontPath(int *npaths)
{
char **fp;
unsigned char *c, *paths;
char *newfp;
int len, l, i;
paths = GetFontPath(npaths, &len);
newfp = xalloc(*npaths + len);
c = (unsigned char *)newfp;
fp = xalloc(*npaths * sizeof(*fp));
memmove(newfp, paths+1, *npaths + len - 1);
l = *paths;
for (i = 0; i < *npaths; i++) {
fp[i] = (char *)c;
c += l;
l = *c;
*c++ = '\0';
}
#if DMX_FONTPATH_DEBUG
for (i = 0; i < *npaths; i++)
dmxLog(dmxDebug, "FontPath[%d] = %s\n", i, fp[i]);
#endif
return fp;
}
static void dmxFreeFontPath(char **fp)
{
xfree(fp[0]);
xfree(fp);
}
static Bool dmxCheckFontPathElement(DMXScreenInfo *dmxScreen, char *fp)
{
int (*oldErrorHandler)(Display *, XErrorEvent *);
if (!dmxScreen->beDisplay)
return TRUE;
dmxFontLastError = 0;
oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler);
XSetFontPath(dmxScreen->beDisplay, &fp, 1);
dmxSync(dmxScreen, TRUE);
XSetErrorHandler(oldErrorHandler);
return (dmxFontLastError == 0);
}
static int dmxSetFontPath(DMXScreenInfo *dmxScreen)
{
int (*oldErrorHandler)(Display *, XErrorEvent *);
char **fp;
int result = Success;
int npaths;
if (!dmxScreen->beDisplay)
return result;
fp = dmxGetFontPath(&npaths);
if (!fp) return BadAlloc;
dmxFontLastError = 0;
oldErrorHandler = XSetErrorHandler(dmxFontErrorHandler);
XSetFontPath(dmxScreen->beDisplay, fp, npaths);
dmxSync(dmxScreen, TRUE);
XSetErrorHandler(oldErrorHandler);
if (dmxFontLastError) {
result = dmxFontLastError;
}
dmxFreeFontPath(fp);
return result;
}
static int dmxCheckFontPath(DMXScreenInfo *dmxScreen, int *error)
{
char **oldFontPath;
int nOldPaths;
int result = Success;
if (!dmxScreen->beDisplay)
return result;
oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths);
result = dmxSetFontPath(dmxScreen);
XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths);
XFreeFontPath(oldFontPath);
dmxSync(dmxScreen, FALSE);
return result;
}
static int dmxProcSetFontPath(ClientPtr client)
{
unsigned char *ptr;
unsigned long nbytes, total, n;
long nfonts;
int i, result;
int error;
unsigned char *oldFontPath, *tmpFontPath;
int nOldPaths;
int lenOldPaths;
REQUEST(xSetFontPathReq);
REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
total = nbytes;
ptr = (unsigned char *)&stuff[1];
nfonts = stuff->nFonts;
while (--nfonts >= 0) {
if ((total == 0) || (total < (n = (*ptr + 1))))
return BadLength;
total -= n;
ptr += n;
}
if (total >= 4)
return BadLength;
tmpFontPath = GetFontPath(&nOldPaths, &lenOldPaths);
oldFontPath = xalloc(nOldPaths + lenOldPaths);
memmove(oldFontPath, tmpFontPath, nOldPaths + lenOldPaths);
result = SetFontPath(client, stuff->nFonts, (unsigned char *)&stuff[1],
&error);
if (!result) {
for (i = 0; i < dmxNumScreens; i++)
if ((result = dmxCheckFontPath(&dmxScreens[i], &error)))
break;
if (result) {
int ignoreresult, ignoreerror;
ignoreresult = SetFontPath(client, nOldPaths, oldFontPath,
&ignoreerror);
} else {
result = client->noClientException;
client->errorValue = error;
}
}
xfree(oldFontPath);
return result;
}
void dmxInitFonts(void)
{
int i;
for (i = 0; i < 256; i++)
dmxSaveProcVector[i] = ProcVector[i];
ProcVector[X_SetFontPath] = dmxProcSetFontPath;
}
void dmxResetFonts(void)
{
int i;
for (i = 0; i < 256; i++)
ProcVector[i] = dmxSaveProcVector[i];
}
Bool dmxBELoadFont(ScreenPtr pScreen, FontPtr pFont)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex);
char *name;
char **oldFontPath = NULL;
int nOldPaths;
Atom name_atom, value_atom;
int i;
if (!pFontPriv)
return FALSE;
if (pFontPriv->font[pScreen->myNum]) {
return TRUE;
}
oldFontPath = XGetFontPath(dmxScreen->beDisplay, &nOldPaths);
if (dmxSetFontPath(dmxScreen)) {
char **fp;
int npaths;
Bool *goodfps;
fp = dmxGetFontPath(&npaths);
if (!fp) {
dmxLog(dmxError,
"No default font path set.\n");
dmxLog(dmxError,
"Please see the Xdmx man page for information on how to\n");
dmxLog(dmxError,
"initialize the DMX server's default font path.\n");
XFreeFontPath(oldFontPath);
return FALSE;
}
if (!dmxFontPath)
dmxLog(dmxWarning, "No default font path is set.\n");
goodfps = xalloc(npaths * sizeof(*goodfps));
dmxLog(dmxError,
"The DMX server failed to set the following font paths on "
"screen #%d:\n", pScreen->myNum);
for (i = 0; i < npaths; i++)
if (!(goodfps[i] = dmxCheckFontPathElement(dmxScreen, fp[i])))
dmxLog(dmxError, " %s\n", fp[i]);
if (dmxIgnoreBadFontPaths) {
char *newfp;
int newnpaths = 0;
int len = 0;
int j = 0;
int error;
dmxLog(dmxError,
"These font paths will not be used because the "
"\"-ignorebadfontpaths\"\n");
dmxLog(dmxError,
"option is set.\n");
for (i = 0; i < npaths; i++)
if (goodfps[i]) {
len += strlen(fp[i]) + 1;
newnpaths++;
}
if (!newnpaths) {
dmxLog(dmxError,
"After removing the font paths above, no valid font "
"paths were\n");
dmxLog(dmxError,
"available. Please check that the font paths set on "
"the command\n");
dmxLog(dmxError,
"line or in the configuration file via the "
"\"-fontpath\" option\n");
dmxLog(dmxError,
"are valid on all back-end servers. See the Xdmx man "
"page for\n");
dmxLog(dmxError,
"more information on font paths.\n");
dmxFreeFontPath(fp);
XFreeFontPath(oldFontPath);
xfree(goodfps);
return FALSE;
}
newfp = xalloc(len * sizeof(*newfp));
for (i = 0; i < npaths; i++) {
if (goodfps[i]) {
int n = strlen(fp[i]);
newfp[j++] = n;
strncpy(&newfp[j], fp[i], n);
j += n;
}
}
if (SetFontPath(NULL, newnpaths, (unsigned char *)newfp, &error)) {
dmxLog(dmxError, "Cannot reset the default font path.\n");
}
} else if (dmxFontPath) {
dmxLog(dmxError,
"Please remove these font paths from the command line "
"or\n");
dmxLog(dmxError,
"configuration file, or set the \"-ignorebadfontpaths\" "
"option to\n");
dmxLog(dmxError,
"ignore them. For more information on these options, see "
"the\n");
dmxLog(dmxError,
"Xdmx man page.\n");
} else {
dmxLog(dmxError,
"Please specify the font paths that are available on all "
"back-end\n");
dmxLog(dmxError,
"servers with the \"-fontpath\" option, or use the "
"\"-ignorebadfontpaths\"\n");
dmxLog(dmxError,
"to ignore bad defaults. For more information on "
"these and other\n");
dmxLog(dmxError,
"font-path-related options, see the Xdmx man page.\n");
}
if (!dmxIgnoreBadFontPaths ||
(dmxIgnoreBadFontPaths && dmxSetFontPath(dmxScreen))) {
dmxFreeFontPath(fp);
XFreeFontPath(oldFontPath);
xfree(goodfps);
return FALSE;
}
}
name_atom = MakeAtom("FONT", 4, TRUE);
value_atom = 0L;
for (i = 0; i < pFont->info.nprops; i++) {
if ((Atom)pFont->info.props[i].name == name_atom) {
value_atom = pFont->info.props[i].value;
break;
}
}
if (!value_atom) return FALSE;
name = (char *)NameForAtom(value_atom);
if (!name) return FALSE;
pFontPriv->font[pScreen->myNum] =
XLoadQueryFont(dmxScreen->beDisplay, name);
XSetFontPath(dmxScreen->beDisplay, oldFontPath, nOldPaths);
XFreeFontPath(oldFontPath);
dmxSync(dmxScreen, FALSE);
if (!pFontPriv->font[pScreen->myNum]) return FALSE;
return TRUE;
}
Bool dmxRealizeFont(ScreenPtr pScreen, FontPtr pFont)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxFontPrivPtr pFontPriv;
if (!(pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) {
FontSetPrivate(pFont, dmxFontPrivateIndex, NULL);
pFontPriv = xalloc(sizeof(dmxFontPrivRec));
if (!pFontPriv) return FALSE;
pFontPriv->font = NULL;
MAXSCREENSALLOC(pFontPriv->font);
if (!pFontPriv->font) {
xfree(pFontPriv);
return FALSE;
}
pFontPriv->refcnt = 0;
}
FontSetPrivate(pFont, dmxFontPrivateIndex, (pointer)pFontPriv);
if (dmxScreen->beDisplay) {
if (!dmxBELoadFont(pScreen, pFont))
return FALSE;
pFontPriv->refcnt++;
} else {
pFontPriv->font[pScreen->myNum] = NULL;
}
return TRUE;
}
Bool dmxBEFreeFont(ScreenPtr pScreen, FontPtr pFont)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxFontPrivPtr pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex);
if (pFontPriv && pFontPriv->font[pScreen->myNum]) {
XFreeFont(dmxScreen->beDisplay, pFontPriv->font[pScreen->myNum]);
pFontPriv->font[pScreen->myNum] = NULL;
return TRUE;
}
return FALSE;
}
Bool dmxUnrealizeFont(ScreenPtr pScreen, FontPtr pFont)
{
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
dmxFontPrivPtr pFontPriv;
if ((pFontPriv = FontGetPrivate(pFont, dmxFontPrivateIndex))) {
if (!pFontPriv->refcnt) {
MAXSCREENSFREE(pFontPriv->font);
xfree(pFontPriv);
FontSetPrivate(pFont, dmxFontPrivateIndex, NULL);
} else if (pFontPriv->font[pScreen->myNum]) {
if (dmxScreen->beDisplay)
dmxBEFreeFont(pScreen, pFont);
if (--pFontPriv->refcnt == 0
#if 1
|| screenInfo.numScreens == 1
#endif
) {
MAXSCREENSFREE(pFontPriv->font);
xfree(pFontPriv);
FontSetPrivate(pFont, dmxFontPrivateIndex, NULL);
}
}
}
return TRUE;
}