#include "xfs-config.h"
#include <X11/fonts/FS.h>
#include <X11/fonts/FSproto.h>
#include <stdio.h>
#include <X11/Xos.h>
#include "clientstr.h"
#include "difsfnst.h"
#include <X11/fonts/fontstruct.h>
#include "closestr.h"
#include "globals.h"
#include "difs.h"
#include "dispatch.h"
#include <swapreq.h>
#include <swaprep.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif
#include <limits.h>
#ifndef SIZE_MAX
# ifdef ULONG_MAX
# define SIZE_MAX ULONG_MAX
# else
# define SIZE_MAX UINT_MAX
# endif
#endif
void
CopyCharInfo(
CharInfoPtr ci,
fsXCharInfo *dst)
{
xCharInfo *src = &ci->metrics;
dst->ascent = src->ascent;
dst->descent = src->descent;
dst->left = src->leftSideBearing;
dst->right = src->rightSideBearing;
dst->width = src->characterWidth;
dst->attributes = src->attributes;
}
int
convert_props(
FontInfoPtr pinfo,
fsPropInfo **props)
{
int i;
int data_len, cur_off;
char *str;
pointer ptr, off_ptr, string_base;
fsPropOffset local_offset;
data_len = 0;
for (i = 0; i < pinfo->nprops; i++)
{
data_len += strlen(NameForAtom(pinfo->props[i].name));
if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
data_len += strlen(NameForAtom(pinfo->props[i].value));
}
ptr = (pointer) fsalloc(SIZEOF(fsPropInfo)
+ SIZEOF(fsPropOffset) * pinfo->nprops
+ data_len);
if (!ptr)
return AllocError;
string_base = (char *)ptr + SIZEOF(fsPropInfo) + SIZEOF(fsPropOffset) * pinfo->nprops;
((fsPropInfo *)ptr)->num_offsets = pinfo->nprops;
((fsPropInfo *)ptr)->data_len = data_len;
off_ptr = (char *)ptr + SIZEOF(fsPropInfo);
cur_off = 0;
for (i = 0; i < pinfo->nprops; i++)
{
local_offset.name.position = cur_off;
str = NameForAtom(pinfo->props[i].name);
local_offset.name.length = strlen(str);
memmove( (char *)string_base+cur_off, str, local_offset.name.length);
cur_off += local_offset.name.length;
if (NULL != pinfo->isStringProp && pinfo->isStringProp[i])
{
local_offset.value.position = cur_off;
str = NameForAtom(pinfo->props[i].value);
local_offset.value.length = strlen(str);
memmove( (char *)string_base+cur_off, str, local_offset.value.length);
cur_off += local_offset.value.length;
local_offset.type = PropTypeString;
} else {
local_offset.value.position = pinfo->props[i].value;
local_offset.value.length = 0;
local_offset.type = PropTypeSigned;
}
memmove( off_ptr, &local_offset, SIZEOF(fsPropOffset));
off_ptr = (char *)off_ptr + SIZEOF(fsPropOffset);
}
assert(off_ptr == string_base);
assert(cur_off == data_len);
*props = (fsPropInfo *) ptr;
return Successful;
}
static fsRange *
build_range(
Bool type,
pointer src,
int item_size,
int *num,
Bool *all,
FontInfoPtr pfi)
{
fsRange *new = (fsRange *) 0,
*np;
unsigned long src_num;
unsigned long i;
if (type) {
char *rp = (char *) src;
src_num = *num;
if (src_num == 0) {
*all = TRUE;
return new;
}
if (src_num >= SIZE_MAX / sizeof(fsRange) * 2 - 1)
return NULL;
np = new = (fsRange *) fsalloc(sizeof(fsRange) * (src_num + 1) / 2);
if (!np)
return np;
for (i = 1; i < src_num; i += 2)
{
np->min_char_high = (item_size == 1) ? 0 : *rp++;
np->min_char_low = *rp++;
np->max_char_high = (item_size == 1) ? 0 : *rp++;
np->max_char_low = *rp++;
np++;
}
if (i == src_num)
{
np->min_char_high = (item_size == 1) ? 0 : *rp++;
np->min_char_low = *rp++;
np->max_char_high = pfi->lastRow;
np->max_char_low = pfi->lastCol;
np++;
}
*num = np - new;
return new;
} else {
unsigned char *pp = src;
src_num = *num;
if (src_num >= SIZE_MAX / sizeof(fsRange))
return NULL;
np = new = (fsRange *) fsalloc(SIZEOF(fsRange) * src_num);
if (!np)
return np;
for (i = 0; i < src_num; i++) {
if (item_size == 1) {
np->min_char_low = *pp;
np->min_char_high = 0;
} else {
np->min_char_low = ((fsChar2b *) pp)->low;
np->min_char_high = ((fsChar2b *) pp)->high;
}
np->max_char_high = np->min_char_high;
np->max_char_low = np->min_char_low;
if (np > new &&
np->max_char_high == np[-1].max_char_high &&
np->max_char_low == np[-1].max_char_low + 1)
np[-1].max_char_low++;
else
np++;
pp += item_size;
}
*num = np - new;
return new;
}
}
static void
swap_char2b (fsChar2b *values, int number)
{
fsChar2b temp;
int i;
for (i = 0; i < number; i++) {
temp.low = ((fsChar2b_version1 *)values)->low;
temp.high = ((fsChar2b_version1 *)values)->high;
*values++ = temp;
}
}
#define pPtr ((QEclosurePtr) data)
static Bool
do_query_extents(ClientPtr client, pointer data)
{
int err;
unsigned long lendata,
num_extents;
fsXCharInfo *extents;
fsQueryXExtents8Reply reply;
err = GetExtents (pPtr->client, pPtr->pfont,
pPtr->flags, pPtr->nranges, pPtr->range, &num_extents, &extents);
if (err == Suspended) {
if (!pPtr->slept) {
pPtr->pfont->unload_glyphs = NULL;
pPtr->slept = TRUE;
ClientSleep(client, do_query_extents, (pointer) pPtr);
}
return TRUE;
}
if (err != Successful) {
SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
goto finish;
}
reply.type = FS_Reply;
reply.sequenceNumber = pPtr->client->sequence;
reply.num_extents = num_extents;
lendata = SIZEOF(fsXCharInfo) * num_extents;
reply.length = (SIZEOF(fsQueryXExtents8Reply) + lendata) >> 2;
if (client->swapped)
SwapExtents(extents, num_extents);
WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXExtents8Reply), &reply);
(void) WriteToClient(pPtr->client, lendata, (char *) extents);
fsfree((char *) extents);
finish:
if (pPtr->slept)
ClientWakeup(pPtr->client);
if (pPtr->pfont->unload_glyphs)
(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
fsfree(pPtr->range);
fsfree(pPtr);
return TRUE;
}
int
QueryExtents(
ClientPtr client,
ClientFontPtr cfp,
int item_size,
int nranges,
Bool range_flag,
pointer range_data)
{
QEclosurePtr c;
fsRange *fixed_range;
Bool all_glyphs = FALSE;
if (item_size == 2 && client->major_version == 1)
swap_char2b ((fsChar2b *)range_data, nranges);
fixed_range = build_range(range_flag, range_data, item_size,
&nranges, &all_glyphs, &cfp->font->info);
if (!fixed_range && !all_glyphs) {
SendErrToClient(client, FSBadRange, NULL);
return FSBadRange;
}
c = (QEclosurePtr) fsalloc(sizeof(QEclosureRec));
if (!c)
return FSBadAlloc;
c->client = client;
c->slept = FALSE;
c->pfont = cfp->font;
c->flags = (all_glyphs) ? LoadAll : 0;
c->flags |= (item_size == 1) ? EightBitFont : SixteenBitFont;
c->nranges = nranges;
c->range = fixed_range;
(void) do_query_extents(client, (pointer) c);
return FSSuccess;
}
#undef pPtr
#define pPtr ((QBclosurePtr) data)
static Bool
do_query_bitmaps(ClientPtr client, pointer data)
{
int err;
unsigned long num_glyphs;
int data_size;
fsOffset32 *offsets;
pointer glyph_data;
fsQueryXBitmaps8Reply reply;
int freedata;
err = GetBitmaps (pPtr->client, pPtr->pfont, pPtr->format,
pPtr->flags, pPtr->nranges, pPtr->range,
&data_size, &num_glyphs, &offsets, &glyph_data, &freedata);
if (err == Suspended) {
if (!pPtr->slept) {
pPtr->pfont->unload_glyphs = NULL;
pPtr->slept = TRUE;
ClientSleep(client, do_query_bitmaps, (pointer) pPtr);
}
return TRUE;
}
if (err != Successful) {
SendErrToClient(pPtr->client, FontToFSError(err), (pointer) 0);
goto finish;
}
reply.type = FS_Reply;
reply.sequenceNumber = pPtr->client->sequence;
reply.replies_hint = 0;
reply.num_chars = num_glyphs;
reply.nbytes = data_size;
reply.length = (SIZEOF(fsQueryXBitmaps8Reply) + data_size +
(SIZEOF(fsOffset32) * num_glyphs) + 3) >> 2;
WriteReplyToClient(pPtr->client, SIZEOF(fsQueryXBitmaps8Reply), &reply);
if (client->swapped)
SwapLongs((long *)offsets, num_glyphs * 2);
(void) WriteToClient(pPtr->client, (num_glyphs * SIZEOF(fsOffset32)),
(char *) offsets);
(void) WriteToClient(pPtr->client, data_size, (char *) glyph_data);
fsfree((char *) offsets);
if (freedata)
fsfree((char *) glyph_data);
finish:
if (pPtr->slept)
ClientWakeup(pPtr->client);
if (pPtr->pfont->unload_glyphs)
(*pPtr->pfont->unload_glyphs)(pPtr->pfont);
fsfree(pPtr->range);
fsfree(pPtr);
return TRUE;
}
int
QueryBitmaps(
ClientPtr client,
ClientFontPtr cfp,
int item_size,
fsBitmapFormat format,
int nranges,
Bool range_flag,
pointer range_data)
{
QBclosurePtr c;
fsRange *fixed_range;
Bool all_glyphs = FALSE;
if (item_size == 2 && client->major_version == 1)
swap_char2b ((fsChar2b *)range_data, nranges);
fixed_range = build_range(range_flag, range_data, item_size,
&nranges, &all_glyphs, &cfp->font->info);
if (!fixed_range && !all_glyphs) {
SendErrToClient(client, FSBadRange, NULL);
return FSBadRange;
}
c = (QBclosurePtr) fsalloc(sizeof(QBclosureRec));
if (!c)
return FSBadAlloc;
c->client = client;
c->slept = FALSE;
c->pfont = cfp->font;
c->flags = (all_glyphs) ? LoadAll : 0;
c->nranges = nranges;
c->range = fixed_range;
c->format = format;
(void) do_query_bitmaps(client, (pointer) c);
return FSSuccess;
}