#define NEED_REPLIES
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xmd.h>
#include <X11/Xproto.h>
#include "scrnintstr.h"
#include "resource.h"
#include "dixstruct.h"
#include "cursorstr.h"
#include "misc.h"
#include "opaque.h"
#include "dixfontstr.h"
#include "closestr.h"
#include "dixfont.h"
#ifdef DEBUG
#include <stdio.h>
#endif
#ifdef PANORAMIX
#include "panoramiX.h"
#endif
#ifdef XF86BIGFONT
#define _XF86BIGFONT_SERVER_
#include <X11/extensions/xf86bigfont.h>
#endif
#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
extern pointer fosNaturalParams;
extern FontPtr defaultFont;
static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
static int num_fpes = 0;
_X_EXPORT FPEFunctions *fpe_functions = (FPEFunctions *) 0;
static int num_fpe_types = 0;
static unsigned char *font_path_string;
static int num_slept_fpes = 0;
static int size_slept_fpes = 0;
static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
static FontPatternCachePtr patternCache;
_X_EXPORT int
FontToXError(err)
int err;
{
switch (err) {
case Successful:
return Success;
case AllocError:
return BadAlloc;
case BadFontName:
return BadName;
case BadFontPath:
case BadFontFormat:
case BadCharRange:
return BadValue;
default:
return err;
}
}
Bool
SetDefaultFont(char *defaultfontname)
{
int err;
FontPtr pf;
XID fid;
fid = FakeClientID(0);
err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
(unsigned) strlen(defaultfontname), defaultfontname);
if (err != Success)
return FALSE;
pf = (FontPtr) LookupIDByType(fid, RT_FONT);
if (pf == (FontPtr) NULL)
return FALSE;
defaultFont = pf;
return TRUE;
}
void
QueueFontWakeup(FontPathElementPtr fpe)
{
int i;
FontPathElementPtr *new;
for (i = 0; i < num_slept_fpes; i++) {
if (slept_fpes[i] == fpe) {
#ifdef DEBUG
fprintf(stderr, "re-queueing fpe wakeup\n");
#endif
return;
}
}
if (num_slept_fpes == size_slept_fpes) {
new = (FontPathElementPtr *)
xrealloc(slept_fpes,
sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
if (!new)
return;
slept_fpes = new;
size_slept_fpes += 4;
}
slept_fpes[num_slept_fpes] = fpe;
num_slept_fpes++;
}
void
RemoveFontWakeup(FontPathElementPtr fpe)
{
int i,
j;
for (i = 0; i < num_slept_fpes; i++) {
if (slept_fpes[i] == fpe) {
for (j = i; j < num_slept_fpes; j++) {
slept_fpes[j] = slept_fpes[j + 1];
}
num_slept_fpes--;
return;
}
}
}
void
FontWakeup(pointer data, int count, pointer LastSelectMask)
{
int i;
FontPathElementPtr fpe;
if (count < 0)
return;
for (i = 0; i < num_slept_fpes; i++) {
fpe = slept_fpes[i];
(void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
}
}
static void
UseFPE(FontPathElementPtr fpe)
{
fpe->refcount++;
}
static void
FreeFPE (FontPathElementPtr fpe)
{
fpe->refcount--;
if (fpe->refcount == 0) {
(*fpe_functions[fpe->type].free_fpe) (fpe);
xfree(fpe->name);
xfree(fpe);
}
}
static Bool
doOpenFont(ClientPtr client, OFclosurePtr c)
{
FontPtr pfont = NullFont;
FontPathElementPtr fpe = NULL;
ScreenPtr pScr;
int err = Successful;
int i;
char *alias,
*newname;
int newlen;
int aliascount = 20;
Mask FontFormat =
((screenInfo.imageByteOrder == LSBFirst) ?
BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
((screenInfo.bitmapBitOrder == LSBFirst) ?
BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
BitmapFormatImageRectMin |
#if GLYPHPADBYTES == 1
BitmapFormatScanlinePad8 |
#endif
#if GLYPHPADBYTES == 2
BitmapFormatScanlinePad16 |
#endif
#if GLYPHPADBYTES == 4
BitmapFormatScanlinePad32 |
#endif
#if GLYPHPADBYTES == 8
BitmapFormatScanlinePad64 |
#endif
BitmapFormatScanlineUnit8;
if (client->clientGone)
{
if (c->current_fpe < c->num_fpes)
{
fpe = c->fpe_list[c->current_fpe];
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
}
err = Successful;
goto bail;
}
while (c->current_fpe < c->num_fpes) {
fpe = c->fpe_list[c->current_fpe];
err = (*fpe_functions[fpe->type].open_font)
((pointer) client, fpe, c->flags,
c->fontname, c->fnamelen, FontFormat,
BitmapFormatMaskByte |
BitmapFormatMaskBit |
BitmapFormatMaskImageRectangle |
BitmapFormatMaskScanLinePad |
BitmapFormatMaskScanLineUnit,
c->fontid, &pfont, &alias,
c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
c->non_cachable_font :
(FontPtr)0);
if (err == FontNameAlias && alias) {
newlen = strlen(alias);
newname = (char *) xrealloc(c->fontname, newlen);
if (!newname) {
err = AllocError;
break;
}
memmove(newname, alias, newlen);
c->fontname = newname;
c->fnamelen = newlen;
c->current_fpe = 0;
if (--aliascount <= 0)
break;
continue;
}
if (err == BadFontName) {
c->current_fpe++;
continue;
}
if (err == Suspended) {
if (!c->slept) {
c->slept = TRUE;
ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
}
return TRUE;
}
break;
}
if (err != Successful)
goto bail;
if (!pfont) {
err = BadFontName;
goto bail;
}
if (!pfont->fpe)
pfont->fpe = fpe;
pfont->refcnt++;
if (pfont->refcnt == 1) {
UseFPE(pfont->fpe);
for (i = 0; i < screenInfo.numScreens; i++) {
pScr = screenInfo.screens[i];
if (pScr->RealizeFont)
{
if (!(*pScr->RealizeFont) (pScr, pfont))
{
CloseFont (pfont, (Font) 0);
err = AllocError;
goto bail;
}
}
}
}
if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
err = AllocError;
goto bail;
}
if (patternCache && pfont != c->non_cachable_font)
CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
pfont);
bail:
if (err != Successful && c->client != serverClient) {
SendErrorToClient(c->client, X_OpenFont, 0,
c->fontid, FontToXError(err));
}
if (c->slept)
ClientWakeup(c->client);
for (i = 0; i < c->num_fpes; i++) {
FreeFPE(c->fpe_list[i]);
}
xfree(c->fpe_list);
xfree(c->fontname);
xfree(c);
return TRUE;
}
int
OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
{
OFclosurePtr c;
int i;
FontPtr cached = (FontPtr)0;
#ifdef FONTDEBUG
char *f;
f = (char *)xalloc(lenfname + 1);
memmove(f, pfontname, lenfname);
f[lenfname] = '\0';
ErrorF("OpenFont: fontname is \"%s\"\n", f);
xfree(f);
#endif
if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
return BadName;
if (patternCache)
{
cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
if (cached && cached->info.cachable)
{
if (!AddResource(fid, RT_FONT, (pointer) cached))
return BadAlloc;
cached->refcnt++;
return Success;
}
}
c = (OFclosurePtr) xalloc(sizeof(OFclosureRec));
if (!c)
return BadAlloc;
c->fontname = (char *) xalloc(lenfname);
c->origFontName = pfontname;
c->origFontNameLen = lenfname;
if (!c->fontname) {
xfree(c);
return BadAlloc;
}
c->fpe_list = (FontPathElementPtr *)
xalloc(sizeof(FontPathElementPtr) * num_fpes);
if (!c->fpe_list) {
xfree(c->fontname);
xfree(c);
return BadAlloc;
}
memmove(c->fontname, pfontname, lenfname);
for (i = 0; i < num_fpes; i++) {
c->fpe_list[i] = font_path_elements[i];
UseFPE(c->fpe_list[i]);
}
c->client = client;
c->fontid = fid;
c->current_fpe = 0;
c->num_fpes = num_fpes;
c->fnamelen = lenfname;
c->slept = FALSE;
c->flags = flags;
c->non_cachable_font = cached;
(void) doOpenFont(client, c);
return Success;
}
_X_EXPORT int
CloseFont(pointer value, XID fid)
{
int nscr;
ScreenPtr pscr;
FontPathElementPtr fpe;
FontPtr pfont = (FontPtr)value;
if (pfont == NullFont)
return (Success);
if (--pfont->refcnt == 0) {
if (patternCache)
RemoveCachedFontPattern (patternCache, pfont);
for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
pscr = screenInfo.screens[nscr];
if (pscr->UnrealizeFont)
(*pscr->UnrealizeFont) (pscr, pfont);
}
if (pfont == defaultFont)
defaultFont = NULL;
#ifdef XF86BIGFONT
XF86BigfontFreeFontShm(pfont);
#endif
fpe = pfont->fpe;
(*fpe_functions[fpe->type].close_font) (fpe, pfont);
FreeFPE(fpe);
}
return (Success);
}
void
QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
{
FontPropPtr pFP;
int r,
c,
i;
xFontProp *prFP;
xCharInfo *prCI;
xCharInfo *charInfos[256];
unsigned char chars[512];
int ninfos;
unsigned long ncols;
unsigned long count;
pReply->minCharOrByte2 = pFont->info.firstCol;
pReply->defaultChar = pFont->info.defaultCh;
pReply->maxCharOrByte2 = pFont->info.lastCol;
pReply->drawDirection = pFont->info.drawDirection;
pReply->allCharsExist = pFont->info.allExist;
pReply->minByte1 = pFont->info.firstRow;
pReply->maxByte1 = pFont->info.lastRow;
pReply->fontAscent = pFont->info.fontAscent;
pReply->fontDescent = pFont->info.fontDescent;
pReply->minBounds = pFont->info.ink_minbounds;
pReply->maxBounds = pFont->info.ink_maxbounds;
pReply->nFontProps = pFont->info.nprops;
pReply->nCharInfos = nProtoCCIStructs;
for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
i < pFont->info.nprops;
i++, pFP++, prFP++) {
prFP->name = pFP->name;
prFP->value = pFP->value;
}
ninfos = 0;
ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
prCI = (xCharInfo *) (prFP);
for (r = pFont->info.firstRow;
ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
r++) {
i = 0;
for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
chars[i++] = r;
chars[i++] = c;
}
(*pFont->get_metrics) (pFont, ncols, chars,
TwoD16Bit, &count, charInfos);
i = 0;
for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
*prCI = *charInfos[i];
prCI++;
ninfos++;
}
}
return;
}
static Bool
doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
{
FontPathElementPtr fpe;
int err = Successful;
FontNamesPtr names = NULL;
char *name, *resolved=NULL;
int namelen, resolvedlen;
int nnames;
int stringLens;
int i;
xListFontsReply reply;
char *bufptr;
char *bufferStart;
int aliascount = 0;
if (client->clientGone)
{
if (c->current.current_fpe < c->num_fpes)
{
fpe = c->fpe_list[c->current.current_fpe];
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
}
err = Successful;
goto bail;
}
if (!c->current.patlen)
goto finish;
while (c->current.current_fpe < c->num_fpes) {
fpe = c->fpe_list[c->current.current_fpe];
err = Successful;
if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
{
err = (*fpe_functions[fpe->type].list_fonts)
((pointer) c->client, fpe, c->current.pattern,
c->current.patlen, c->current.max_names - c->names->nnames,
c->names);
if (err == Suspended) {
if (!c->slept) {
c->slept = TRUE;
ClientSleep(client,
(ClientSleepProcPtr)doListFontsAndAliases,
(pointer) c);
}
return TRUE;
}
err = BadFontName;
}
else
{
if (!c->current.list_started) {
err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
((pointer) c->client, fpe, c->current.pattern,
c->current.patlen, c->current.max_names - c->names->nnames,
&c->current.private);
if (err == Suspended) {
if (!c->slept) {
ClientSleep(client,
(ClientSleepProcPtr)doListFontsAndAliases,
(pointer) c);
c->slept = TRUE;
}
return TRUE;
}
if (err == Successful)
c->current.list_started = TRUE;
}
if (err == Successful) {
char *tmpname;
name = 0;
err = (*fpe_functions[fpe->type].list_next_font_or_alias)
((pointer) c->client, fpe, &name, &namelen, &tmpname,
&resolvedlen, c->current.private);
if (err == Suspended) {
if (!c->slept) {
ClientSleep(client,
(ClientSleepProcPtr)doListFontsAndAliases,
(pointer) c);
c->slept = TRUE;
}
return TRUE;
}
if (err == FontNameAlias) {
if (resolved) xfree(resolved);
resolved = (char *) xalloc(resolvedlen + 1);
if (resolved)
memmove(resolved, tmpname, resolvedlen + 1);
}
}
if (err == Successful)
{
if (c->haveSaved)
{
if (c->savedName)
(void)AddFontNamesName(c->names, c->savedName,
c->savedNameLen);
}
else
(void)AddFontNamesName(c->names, name, namelen);
}
else if (err == FontNameAlias) {
char tmp_pattern[XLFDMAXFONTNAMELEN];
memmove(tmp_pattern, resolved, resolvedlen);
if (c->haveSaved)
{
char *tmpname;
int tmpnamelen;
tmpname = 0;
(void) (*fpe_functions[fpe->type].list_next_font_or_alias)
((pointer) c->client, fpe, &tmpname, &tmpnamelen,
&tmpname, &tmpnamelen, c->current.private);
if (--aliascount <= 0)
{
err = BadFontName;
goto ContBadFontName;
}
}
else
{
c->saved = c->current;
c->haveSaved = TRUE;
if (c->savedName)
xfree(c->savedName);
c->savedName = (char *)xalloc(namelen + 1);
if (c->savedName)
memmove(c->savedName, name, namelen + 1);
c->savedNameLen = namelen;
aliascount = 20;
}
memmove(c->current.pattern, tmp_pattern, resolvedlen);
c->current.patlen = resolvedlen;
c->current.max_names = c->names->nnames + 1;
c->current.current_fpe = -1;
c->current.private = 0;
err = BadFontName;
}
}
if (err == BadFontName) {
ContBadFontName: ;
c->current.list_started = FALSE;
c->current.current_fpe++;
err = Successful;
if (c->haveSaved)
{
if (c->names->nnames == c->current.max_names ||
c->current.current_fpe == c->num_fpes) {
c->haveSaved = FALSE;
c->current = c->saved;
continue;
}
}
if (c->names->nnames == c->current.max_names)
break;
}
}
if (err != Successful) {
SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
goto bail;
}
finish:
names = c->names;
nnames = names->nnames;
client = c->client;
stringLens = 0;
for (i = 0; i < nnames; i++)
stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
reply.type = X_Reply;
reply.length = (stringLens + nnames + 3) >> 2;
reply.nFonts = nnames;
reply.sequenceNumber = client->sequence;
bufptr = bufferStart = (char *) ALLOCATE_LOCAL(reply.length << 2);
if (!bufptr && reply.length) {
SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
goto bail;
}
for (i = 0; i < nnames; i++) {
if (names->length[i] > 255)
reply.nFonts--;
else
{
*bufptr++ = names->length[i];
memmove( bufptr, names->names[i], names->length[i]);
bufptr += names->length[i];
}
}
nnames = reply.nFonts;
reply.length = (stringLens + nnames + 3) >> 2;
client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
(void) WriteToClient(client, stringLens + nnames, bufferStart);
DEALLOCATE_LOCAL(bufferStart);
bail:
if (c->slept)
ClientWakeup(client);
for (i = 0; i < c->num_fpes; i++)
FreeFPE(c->fpe_list[i]);
xfree(c->fpe_list);
if (c->savedName) xfree(c->savedName);
FreeFontNames(names);
xfree(c);
if (resolved) xfree(resolved);
return TRUE;
}
int
ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
unsigned max_names)
{
int i;
LFclosurePtr c;
if (length > XLFDMAXFONTNAMELEN)
return BadAlloc;
if (!(c = (LFclosurePtr) xalloc(sizeof *c)))
return BadAlloc;
c->fpe_list = (FontPathElementPtr *)
xalloc(sizeof(FontPathElementPtr) * num_fpes);
if (!c->fpe_list) {
xfree(c);
return BadAlloc;
}
c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
if (!c->names)
{
xfree(c->fpe_list);
xfree(c);
return BadAlloc;
}
memmove( c->current.pattern, pattern, length);
for (i = 0; i < num_fpes; i++) {
c->fpe_list[i] = font_path_elements[i];
UseFPE(c->fpe_list[i]);
}
c->client = client;
c->num_fpes = num_fpes;
c->current.patlen = length;
c->current.current_fpe = 0;
c->current.max_names = max_names;
c->current.list_started = FALSE;
c->current.private = 0;
c->haveSaved = FALSE;
c->slept = FALSE;
c->savedName = 0;
doListFontsAndAliases(client, c);
return Success;
}
int
doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
{
FontPathElementPtr fpe;
int err = Successful;
char *name;
int namelen;
int numFonts;
FontInfoRec fontInfo,
*pFontInfo;
xListFontsWithInfoReply *reply;
int length;
xFontProp *pFP;
int i;
int aliascount = 0;
xListFontsWithInfoReply finalReply;
if (client->clientGone)
{
if (c->current.current_fpe < c->num_fpes)
{
fpe = c->fpe_list[c->current.current_fpe];
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
}
err = Successful;
goto bail;
}
client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
if (!c->current.patlen)
goto finish;
while (c->current.current_fpe < c->num_fpes)
{
fpe = c->fpe_list[c->current.current_fpe];
err = Successful;
if (!c->current.list_started)
{
err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
(client, fpe, c->current.pattern, c->current.patlen,
c->current.max_names, &c->current.private);
if (err == Suspended)
{
if (!c->slept)
{
ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
c->slept = TRUE;
}
return TRUE;
}
if (err == Successful)
c->current.list_started = TRUE;
}
if (err == Successful)
{
name = 0;
pFontInfo = &fontInfo;
err = (*fpe_functions[fpe->type].list_next_font_with_info)
(client, fpe, &name, &namelen, &pFontInfo,
&numFonts, c->current.private);
if (err == Suspended)
{
if (!c->slept)
{
ClientSleep(client,
(ClientSleepProcPtr)doListFontsWithInfo,
c);
c->slept = TRUE;
}
return TRUE;
}
}
if (err == FontNameAlias)
{
if (c->haveSaved)
{
char *tmpname;
int tmpnamelen;
FontInfoPtr tmpFontInfo;
tmpname = 0;
tmpFontInfo = &fontInfo;
(void) (*fpe_functions[fpe->type].list_next_font_with_info)
(client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
&numFonts, c->current.private);
if (--aliascount <= 0)
{
err = BadFontName;
goto ContBadFontName;
}
}
else
{
c->saved = c->current;
c->haveSaved = TRUE;
c->savedNumFonts = numFonts;
if (c->savedName)
xfree(c->savedName);
c->savedName = (char *)xalloc(namelen + 1);
if (c->savedName)
memmove(c->savedName, name, namelen + 1);
aliascount = 20;
}
memmove(c->current.pattern, name, namelen);
c->current.patlen = namelen;
c->current.max_names = 1;
c->current.current_fpe = 0;
c->current.private = 0;
c->current.list_started = FALSE;
}
else if (err == BadFontName)
{
ContBadFontName: ;
c->current.list_started = FALSE;
c->current.current_fpe++;
err = Successful;
if (c->haveSaved)
{
if (c->current.max_names == 0 ||
c->current.current_fpe == c->num_fpes)
{
c->haveSaved = FALSE;
c->saved.max_names -= (1 - c->current.max_names);
c->current = c->saved;
}
}
else if (c->current.max_names == 0)
break;
}
else if (err == Successful)
{
length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
reply = c->reply;
if (c->length < length)
{
reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
if (!reply)
{
err = AllocError;
break;
}
c->reply = reply;
c->length = length;
}
if (c->haveSaved)
{
numFonts = c->savedNumFonts;
name = c->savedName;
namelen = strlen(name);
}
reply->type = X_Reply;
reply->length = (sizeof *reply - sizeof(xGenericReply) +
pFontInfo->nprops * sizeof(xFontProp) +
namelen + 3) >> 2;
reply->sequenceNumber = client->sequence;
reply->nameLength = namelen;
reply->minBounds = pFontInfo->ink_minbounds;
reply->maxBounds = pFontInfo->ink_maxbounds;
reply->minCharOrByte2 = pFontInfo->firstCol;
reply->maxCharOrByte2 = pFontInfo->lastCol;
reply->defaultChar = pFontInfo->defaultCh;
reply->nFontProps = pFontInfo->nprops;
reply->drawDirection = pFontInfo->drawDirection;
reply->minByte1 = pFontInfo->firstRow;
reply->maxByte1 = pFontInfo->lastRow;
reply->allCharsExist = pFontInfo->allExist;
reply->fontAscent = pFontInfo->fontAscent;
reply->fontDescent = pFontInfo->fontDescent;
reply->nReplies = numFonts;
pFP = (xFontProp *) (reply + 1);
for (i = 0; i < pFontInfo->nprops; i++)
{
pFP->name = pFontInfo->props[i].name;
pFP->value = pFontInfo->props[i].value;
pFP++;
}
WriteSwappedDataToClient(client, length, reply);
(void) WriteToClient(client, namelen, name);
if (pFontInfo == &fontInfo)
{
xfree(fontInfo.props);
xfree(fontInfo.isStringProp);
}
--c->current.max_names;
}
}
finish:
length = sizeof(xListFontsWithInfoReply);
bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
finalReply.type = X_Reply;
finalReply.sequenceNumber = client->sequence;
finalReply.length = (sizeof(xListFontsWithInfoReply)
- sizeof(xGenericReply)) >> 2;
WriteSwappedDataToClient(client, length, &finalReply);
bail:
if (c->slept)
ClientWakeup(client);
for (i = 0; i < c->num_fpes; i++)
FreeFPE(c->fpe_list[i]);
xfree(c->reply);
xfree(c->fpe_list);
if (c->savedName) xfree(c->savedName);
xfree(c);
return TRUE;
}
int
StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
int max_names)
{
int i;
LFWIclosurePtr c;
if (length > XLFDMAXFONTNAMELEN)
return BadAlloc;
if (!(c = (LFWIclosurePtr) xalloc(sizeof *c)))
goto badAlloc;
c->fpe_list = (FontPathElementPtr *)
xalloc(sizeof(FontPathElementPtr) * num_fpes);
if (!c->fpe_list)
{
xfree(c);
goto badAlloc;
}
memmove(c->current.pattern, pattern, length);
for (i = 0; i < num_fpes; i++)
{
c->fpe_list[i] = font_path_elements[i];
UseFPE(c->fpe_list[i]);
}
c->client = client;
c->num_fpes = num_fpes;
c->reply = 0;
c->length = 0;
c->current.patlen = length;
c->current.current_fpe = 0;
c->current.max_names = max_names;
c->current.list_started = FALSE;
c->current.private = 0;
c->savedNumFonts = 0;
c->haveSaved = FALSE;
c->slept = FALSE;
c->savedName = 0;
doListFontsWithInfo(client, c);
return Success;
badAlloc:
return BadAlloc;
}
#define TextEltHeader 2
#define FontShiftSize 5
static XID clearGC[] = { CT_NONE };
#define clearGCmask (GCClipMask)
int
doPolyText(ClientPtr client, register PTclosurePtr c)
{
register FontPtr pFont = c->pGC->font, oldpFont;
Font fid, oldfid;
int err = Success, lgerr;
enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
FontPathElementPtr fpe;
GC *origGC = NULL;
if (client->clientGone)
{
fpe = c->pGC->font->fpe;
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
if (c->slept)
{
c->pDraw = (DrawablePtr)0;
}
else
{
err = Success;
goto bail;
}
}
if (c->slept &&
c->pDraw &&
c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
RC_DRAWABLE, SecurityWriteAccess))
{
fpe = c->pGC->font->fpe;
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
c->pDraw = (DrawablePtr)0;
}
client_state = c->slept ? SLEEPING : NEVER_SLEPT;
while (c->endReq - c->pElt > TextEltHeader)
{
if (*c->pElt == FontChange)
{
if (c->endReq - c->pElt < FontShiftSize)
{
err = BadLength;
goto bail;
}
oldpFont = pFont;
oldfid = fid;
fid = ((Font)*(c->pElt+4))
| ((Font)*(c->pElt+3)) << 8
| ((Font)*(c->pElt+2)) << 16
| ((Font)*(c->pElt+1)) << 24;
pFont = (FontPtr)SecurityLookupIDByType(client, fid, RT_FONT,
SecurityReadAccess);
if (!pFont)
{
client->errorValue = fid;
err = BadFont;
pFont = oldpFont;
fid = oldfid;
c->err = err;
c->endReq = c->pElt;
goto bail;
}
if (client_state == START_SLEEP)
pFont->refcnt++;
else
{
if (pFont != c->pGC->font && c->pDraw)
{
ChangeGC( c->pGC, GCFont, &fid);
ValidateGC(c->pDraw, c->pGC);
if (c->reqType == X_PolyText8)
c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
else
c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
}
if (client_state == SLEEPING)
(void)CloseFont(c->pGC->font, (Font)0);
}
c->pElt += FontShiftSize;
}
else
{
unsigned char *pNextElt;
pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
if ( pNextElt > c->endReq)
{
err = BadLength;
goto bail;
}
if (client_state == START_SLEEP)
{
c->pElt = pNextElt;
continue;
}
if (c->pDraw)
{
lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
c->pElt + TextEltHeader);
}
else lgerr = Successful;
if (lgerr == Suspended)
{
if (!c->slept) {
int len;
GC *pGC;
PTclosurePtr new_closure;
new_closure = (PTclosurePtr) xalloc(sizeof(PTclosureRec));
if (!new_closure)
{
err = BadAlloc;
goto bail;
}
*new_closure = *c;
c = new_closure;
len = c->endReq - c->pElt;
c->data = (unsigned char *)xalloc(len);
if (!c->data)
{
xfree(c);
err = BadAlloc;
goto bail;
}
memmove(c->data, c->pElt, len);
c->pElt = c->data;
c->endReq = c->pElt + len;
pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
if (!pGC)
{
xfree(c->data);
xfree(c);
err = BadAlloc;
goto bail;
}
if ((err = CopyGC(c->pGC, pGC, GCFunction |
GCPlaneMask | GCForeground |
GCBackground | GCFillStyle |
GCTile | GCStipple |
GCTileStipXOrigin |
GCTileStipYOrigin | GCFont |
GCSubwindowMode | GCClipXOrigin |
GCClipYOrigin | GCClipMask)) !=
Success)
{
FreeScratchGC(pGC);
xfree(c->data);
xfree(c);
err = BadAlloc;
goto bail;
}
origGC = c->pGC;
c->pGC = pGC;
ValidateGC(c->pDraw, c->pGC);
c->slept = TRUE;
ClientSleep(client,
(ClientSleepProcPtr)doPolyText,
(pointer) c);
client_state = START_SLEEP;
continue;
}
return TRUE;
}
else if (lgerr != Successful)
{
err = FontToXError(lgerr);
goto bail;
}
if (c->pDraw)
{
c->xorg += *((INT8 *)(c->pElt + 1));
c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
*c->pElt, c->pElt + TextEltHeader);
}
c->pElt = pNextElt;
}
}
bail:
if (client_state == START_SLEEP)
{
if (pFont != origGC->font)
{
ChangeGC(origGC, GCFont, &fid);
ValidateGC(c->pDraw, origGC);
}
c->pElt = c->data;
return TRUE;
}
if (c->err != Success) err = c->err;
if (err != Success && c->client != serverClient) {
#ifdef PANORAMIX
if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
#endif
SendErrorToClient(c->client, c->reqType, 0, 0, err);
}
if (c->slept)
{
ClientWakeup(c->client);
ChangeGC(c->pGC, clearGCmask, clearGC);
CloseFont(c->pGC->font, (Font)0);
c->pGC->font = NullFont;
FreeScratchGC(c->pGC);
xfree(c->data);
xfree(c);
}
return TRUE;
}
int
PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
{
PTclosureRec local_closure;
local_closure.pElt = pElt;
local_closure.endReq = endReq;
local_closure.client = client;
local_closure.pDraw = pDraw;
local_closure.xorg = xorg;
local_closure.yorg = yorg;
if ((local_closure.reqType = reqType) == X_PolyText8)
{
local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
local_closure.itemSize = 1;
}
else
{
local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
local_closure.itemSize = 2;
}
local_closure.pGC = pGC;
local_closure.did = did;
local_closure.err = Success;
local_closure.slept = FALSE;
(void) doPolyText(client, &local_closure);
return Success;
}
#undef TextEltHeader
#undef FontShiftSize
int
doImageText(ClientPtr client, register ITclosurePtr c)
{
int err = Success, lgerr;
FontPathElementPtr fpe;
if (client->clientGone)
{
fpe = c->pGC->font->fpe;
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
err = Success;
goto bail;
}
if (c->slept &&
c->pDraw &&
c->pDraw != (DrawablePtr)SecurityLookupIDByClass(client, c->did,
RC_DRAWABLE, SecurityWriteAccess))
{
fpe = c->pGC->font->fpe;
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
err = Success;
goto bail;
}
lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
if (lgerr == Suspended)
{
if (!c->slept) {
GC *pGC;
unsigned char *data;
ITclosurePtr new_closure;
new_closure = (ITclosurePtr) xalloc(sizeof(ITclosureRec));
if (!new_closure)
{
err = BadAlloc;
goto bail;
}
*new_closure = *c;
c = new_closure;
data = (unsigned char *)xalloc(c->nChars * c->itemSize);
if (!data)
{
xfree(c);
err = BadAlloc;
goto bail;
}
memmove(data, c->data, c->nChars * c->itemSize);
c->data = data;
pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
if (!pGC)
{
xfree(c->data);
xfree(c);
err = BadAlloc;
goto bail;
}
if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
GCForeground | GCBackground | GCFillStyle |
GCTile | GCStipple | GCTileStipXOrigin |
GCTileStipYOrigin | GCFont |
GCSubwindowMode | GCClipXOrigin |
GCClipYOrigin | GCClipMask)) != Success)
{
FreeScratchGC(pGC);
xfree(c->data);
xfree(c);
err = BadAlloc;
goto bail;
}
c->pGC = pGC;
ValidateGC(c->pDraw, c->pGC);
c->slept = TRUE;
ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
}
return TRUE;
}
else if (lgerr != Successful)
{
err = FontToXError(lgerr);
goto bail;
}
if (c->pDraw)
{
(* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
c->nChars, c->data);
}
bail:
if (err != Success && c->client != serverClient) {
SendErrorToClient(c->client, c->reqType, 0, 0, err);
}
if (c->slept)
{
ClientWakeup(c->client);
ChangeGC(c->pGC, clearGCmask, clearGC);
CloseFont(c->pGC->font, (Font)0);
c->pGC->font = NullFont;
FreeScratchGC(c->pGC);
xfree(c->data);
xfree(c);
}
return TRUE;
}
int
ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
unsigned char *data, int xorg, int yorg, int reqType, XID did)
{
ITclosureRec local_closure;
local_closure.client = client;
local_closure.pDraw = pDraw;
local_closure.pGC = pGC;
local_closure.nChars = nChars;
local_closure.data = data;
local_closure.xorg = xorg;
local_closure.yorg = yorg;
if ((local_closure.reqType = reqType) == X_ImageText8)
{
local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
local_closure.itemSize = 1;
}
else
{
local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
local_closure.itemSize = 2;
}
local_closure.did = did;
local_closure.slept = FALSE;
(void) doImageText(client, &local_closure);
return Success;
}
static int
DetermineFPEType(char *pathname)
{
int i;
for (i = 0; i < num_fpe_types; i++) {
if ((*fpe_functions[i].name_check) (pathname))
return i;
}
return -1;
}
static void
FreeFontPath(FontPathElementPtr *list, int n, Bool force)
{
int i;
for (i = 0; i < n; i++) {
if (force) {
int found = 1;
int j;
for (j = i+1; j < n; j++) {
if (list[j] == list[i])
found++;
}
if (list[i]->refcount != found) {
list[i]->refcount = found;
}
}
FreeFPE(list[i]);
}
xfree((char *) list);
}
static FontPathElementPtr
find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
{
FontPathElementPtr fpe;
int i;
for (i = 0; i < num; i++) {
fpe = list[i];
if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
return fpe;
}
return (FontPathElementPtr) 0;
}
static int
SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
{
int i, err = 0;
int valid_paths = 0;
unsigned int len;
unsigned char *cp = paths;
FontPathElementPtr fpe = NULL, *fplist;
fplist = (FontPathElementPtr *)
xalloc(sizeof(FontPathElementPtr) * npaths);
if (!fplist) {
*bad = 0;
return BadAlloc;
}
for (i = 0; i < num_fpe_types; i++) {
if (fpe_functions[i].set_path_hook)
(*fpe_functions[i].set_path_hook) ();
}
for (i = 0; i < npaths; i++)
{
len = (unsigned int) (*cp++);
if (len == 0)
{
if (persist)
ErrorF ("Removing empty element from the valid list of fontpaths\n");
err = BadValue;
}
else
{
fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
if (fpe)
{
err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
if (err == Successful)
{
UseFPE(fpe);
}
else
fpe = 0;
}
if (!fpe)
{
fpe = (FontPathElementPtr) xalloc(sizeof(FontPathElementRec));
if (!fpe)
{
err = BadAlloc;
goto bail;
}
fpe->name = (char *) xalloc(len + 1);
if (!fpe->name)
{
xfree(fpe);
err = BadAlloc;
goto bail;
}
fpe->refcount = 1;
strncpy(fpe->name, (char *) cp, (int) len);
fpe->name[len] = '\0';
fpe->name_length = len;
fpe->type = DetermineFPEType(fpe->name);
if (fpe->type == -1)
err = BadValue;
else
err = (*fpe_functions[fpe->type].init_fpe) (fpe);
if (err != Successful)
{
if (persist)
{
ErrorF("Could not init font path element %s, removing from list!\n",
fpe->name);
}
xfree (fpe->name);
xfree (fpe);
}
}
}
if (err != Successful)
{
if (!persist)
goto bail;
}
else
{
fplist[valid_paths++] = fpe;
}
cp += len;
}
FreeFontPath(font_path_elements, num_fpes, FALSE);
font_path_elements = fplist;
if (patternCache)
EmptyFontPatternCache(patternCache);
num_fpes = valid_paths;
return Success;
bail:
*bad = i;
while (--valid_paths >= 0)
FreeFPE(fplist[valid_paths]);
xfree(fplist);
return FontToXError(err);
}
int
SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error)
{
int err = Success;
if (npaths == 0) {
if (SetDefaultFontPath(defaultFontPath) != Success)
return BadValue;
} else {
err = SetFontPathElements(npaths, paths, error, FALSE);
}
return err;
}
int
SetDefaultFontPath(char *path)
{
unsigned char *cp,
*pp,
*nump,
*newpath;
int num = 1,
len,
err,
size = 0,
bad;
len = strlen(path) + 1;
nump = cp = newpath = (unsigned char *) ALLOCATE_LOCAL(len);
if (!newpath)
return BadAlloc;
pp = (unsigned char *) path;
cp++;
while (*pp) {
if (*pp == ',') {
*nump = (unsigned char) size;
nump = cp++;
pp++;
num++;
size = 0;
} else {
*cp++ = *pp++;
size++;
}
}
*nump = (unsigned char) size;
err = SetFontPathElements(num, newpath, &bad, TRUE);
DEALLOCATE_LOCAL(newpath);
return err;
}
unsigned char *
GetFontPath(int *count, int *length)
{
int i;
unsigned char *c;
int len;
FontPathElementPtr fpe;
len = 0;
for (i = 0; i < num_fpes; i++) {
fpe = font_path_elements[i];
len += fpe->name_length + 1;
}
font_path_string = (unsigned char *) xrealloc(font_path_string, len);
if (!font_path_string)
return NULL;
c = font_path_string;
*length = 0;
for (i = 0; i < num_fpes; i++) {
fpe = font_path_elements[i];
*c = fpe->name_length;
*length += *c++;
memmove(c, fpe->name, fpe->name_length);
c += fpe->name_length;
}
*count = num_fpes;
return font_path_string;
}
_X_EXPORT int
LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size, unsigned char *data)
{
if (fpe_functions[pfont->fpe->type].load_glyphs)
return (*fpe_functions[pfont->fpe->type].load_glyphs)
(client, pfont, 0, nchars, item_size, data);
else
return Successful;
}
void
DeleteClientFontStuff(ClientPtr client)
{
int i;
FontPathElementPtr fpe;
for (i = 0; i < num_fpes; i++)
{
fpe = font_path_elements[i];
if (fpe_functions[fpe->type].client_died)
(*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
}
}
void
InitFonts ()
{
patternCache = MakeFontPatternCache();
#ifndef KDRIVESERVER
if (screenInfo.numScreens > screenInfo.numVideoScreens) {
PrinterFontRegisterFpeFunctions();
FontFileCheckRegisterFpeFunctions();
check_fs_register_fpe_functions();
} else
#endif
{
#ifdef KDRIVESERVER
BuiltinRegisterFpeFunctions();
#endif
FontFileRegisterFpeFunctions();
#ifndef NOFONTSERVERACCESS
fs_register_fpe_functions();
#endif
}
}
int
GetDefaultPointSize ()
{
return 120;
}
FontResolutionPtr
GetClientResolutions (int *num)
{
if (requestingClient && requestingClient->fontResFunc != NULL &&
!requestingClient->clientGone)
{
return (*requestingClient->fontResFunc)(requestingClient, num);
}
else {
static struct _FontResolution res;
ScreenPtr pScreen;
pScreen = screenInfo.screens[0];
res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
if (res.x_resolution < 88)
res.x_resolution = 75;
else
res.x_resolution = 100;
res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
if (res.y_resolution < 88)
res.y_resolution = 75;
else
res.y_resolution = 100;
res.point_size = 120;
*num = 1;
return &res;
}
}
int
RegisterFPEFunctions(NameCheckFunc name_func,
InitFpeFunc init_func,
FreeFpeFunc free_func,
ResetFpeFunc reset_func,
OpenFontFunc open_func,
CloseFontFunc close_func,
ListFontsFunc list_func,
StartLfwiFunc start_lfwi_func,
NextLfwiFunc next_lfwi_func,
WakeupFpeFunc wakeup_func,
ClientDiedFunc client_died,
LoadGlyphsFunc load_glyphs,
StartLaFunc start_list_alias_func,
NextLaFunc next_list_alias_func,
SetPathFunc set_path_func)
{
FPEFunctions *new;
new = (FPEFunctions *) xrealloc(fpe_functions,
(num_fpe_types + 1) * sizeof(FPEFunctions));
if (!new)
return -1;
fpe_functions = new;
fpe_functions[num_fpe_types].name_check = name_func;
fpe_functions[num_fpe_types].open_font = open_func;
fpe_functions[num_fpe_types].close_font = close_func;
fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
fpe_functions[num_fpe_types].list_fonts = list_func;
fpe_functions[num_fpe_types].start_list_fonts_with_info =
start_lfwi_func;
fpe_functions[num_fpe_types].list_next_font_with_info =
next_lfwi_func;
fpe_functions[num_fpe_types].init_fpe = init_func;
fpe_functions[num_fpe_types].free_fpe = free_func;
fpe_functions[num_fpe_types].reset_fpe = reset_func;
fpe_functions[num_fpe_types].client_died = client_died;
fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
start_list_alias_func;
fpe_functions[num_fpe_types].list_next_font_or_alias =
next_list_alias_func;
fpe_functions[num_fpe_types].set_path_hook = set_path_func;
return num_fpe_types++;
}
void
FreeFonts()
{
if (patternCache) {
FreeFontPatternCache(patternCache);
patternCache = 0;
}
FreeFontPath(font_path_elements, num_fpes, TRUE);
font_path_elements = 0;
num_fpes = 0;
xfree(fpe_functions);
num_fpe_types = 0;
fpe_functions = (FPEFunctions *) 0;
}
FontPtr
find_old_font(XID id)
{
return (FontPtr) SecurityLookupIDByType(NullClient, id, RT_NONE,
SecurityUnknownAccess);
}
Font
GetNewFontClientID()
{
return FakeClientID(0);
}
int
StoreFontClientFont(FontPtr pfont, Font id)
{
return AddResource(id, RT_NONE, (pointer) pfont);
}
void
DeleteFontClientID(Font id)
{
FreeResource(id, RT_NONE);
}
int
client_auth_generation(ClientPtr client)
{
return 0;
}
static int fs_handlers_installed = 0;
static unsigned int last_server_gen;
int
init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
{
if (last_server_gen < serverGeneration) {
last_server_gen = serverGeneration;
fs_handlers_installed = 0;
}
if (fs_handlers_installed == 0) {
#ifdef DEBUG
fprintf(stderr, "adding FS b & w handlers\n");
#endif
if (!RegisterBlockAndWakeupHandlers(block_handler,
FontWakeup, (pointer) 0))
return AllocError;
fs_handlers_installed++;
}
QueueFontWakeup(fpe);
return Successful;
}
void
remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
{
if (all) {
if (--fs_handlers_installed == 0) {
#ifdef DEBUG
fprintf(stderr, "removing FS b & w handlers\n");
#endif
RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
(pointer) 0);
}
}
RemoveFontWakeup(fpe);
}
#ifdef DEBUG
#define GLWIDTHBYTESPADDED(bits,nbytes) \
((nbytes) == 1 ? (((bits)+7)>>3) \
:(nbytes) == 2 ? ((((bits)+15)>>3)&~1) \
:(nbytes) == 4 ? ((((bits)+31)>>3)&~3) \
:(nbytes) == 8 ? ((((bits)+63)>>3)&~7) \
: 0)
#define GLYPH_SIZE(ch, nbytes) \
GLWIDTHBYTESPADDED((ch)->metrics.rightSideBearing - \
(ch)->metrics.leftSideBearing, (nbytes))
void
dump_char_ascii(CharInfoPtr cip)
{
int r,
l;
int bpr;
int byte;
static unsigned maskTab[] = {
(1 << 7), (1 << 6), (1 << 5), (1 << 4),
(1 << 3), (1 << 2), (1 << 1), (1 << 0),
};
bpr = GLYPH_SIZE(cip, 4);
for (r = 0; r < (cip->metrics.ascent + cip->metrics.descent); r++) {
pointer row = (pointer) cip->bits + r * bpr;
byte = 0;
for (l = 0; l <= (cip->metrics.rightSideBearing -
cip->metrics.leftSideBearing); l++) {
if (maskTab[l & 7] & row[l >> 3])
putchar('X');
else
putchar('.');
}
putchar('\n');
}
}
#endif