From dafebc5bb70303f0b5baf0b087cf4d9a64b5c7f0 Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 12 Sep 2011 11:27:51 +0200 Subject: Synchronised line endinge with release branch --- libXfont/src/fc/fsconvert.c | 1438 +++++----- libXfont/src/fc/fserve.c | 6396 +++++++++++++++++++++---------------------- libXfont/src/fc/fserve.h | 182 +- libXfont/src/fc/fservestr.h | 400 +-- libXfont/src/fc/fsio.c | 904 +++--- libXfont/src/fc/fsio.h | 356 +-- libXfont/src/fc/fslibos.h | 436 +-- 7 files changed, 5056 insertions(+), 5056 deletions(-) (limited to 'libXfont/src/fc') diff --git a/libXfont/src/fc/fsconvert.c b/libXfont/src/fc/fsconvert.c index 5c979fc23..15c5e4200 100644 --- a/libXfont/src/fc/fsconvert.c +++ b/libXfont/src/fc/fsconvert.c @@ -1,719 +1,719 @@ -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. Network Computing Devices - * makes no representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * FS data conversion - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include "fservestr.h" -#include -#include "fslibos.h" - -extern char _fs_glyph_undefined; -extern char _fs_glyph_requested; - -/* - * converts data from font server form to X server form - */ - -void -_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst) -{ - dst->ascent = src->ascent; - dst->descent = src->descent; - dst->leftSideBearing = src->left; - dst->rightSideBearing = src->right; - dst->characterWidth = src->width; - dst->attributes = src->attributes; -} - -void -_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi) -{ - if (conn->fsMajorVersion == 1) { - unsigned short n; - n = pfi->firstCol; - pfi->firstCol = pfi->firstRow; - pfi->firstRow = n; - n = pfi->lastCol; - pfi->lastCol = pfi->lastRow; - pfi->lastRow = n; - pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff) - + ((pfi->defaultCh & 0xff) << 8); - } - - if (FontCouldBeTerminal (pfi)) - { - pfi->terminalFont = TRUE; - pfi->minbounds.ascent = pfi->fontAscent; - pfi->minbounds.descent = pfi->fontDescent; - pfi->minbounds.leftSideBearing = 0; - pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth; - pfi->maxbounds = pfi->minbounds; - } - - FontComputeInfoAccelerators (pfi); -} - -int -_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, - FontInfoPtr pfi) -{ - FontPropPtr dprop; - int i, - nprops; - char *is_str; - fsPropOffset local_off; - char *off_adr; - char *pdc = pd; - -/* stolen from server/include/resource.h */ -#define BAD_RESOURCE 0xe0000000 - - nprops = pfi->nprops = pi->num_offsets; - - if (nprops < 0 - || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) - return -1; - - dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops); - if (!dprop) - return -1; - - is_str = (char *) (dprop + nprops); - pfi->props = dprop; - pfi->isStringProp = is_str; - - off_adr = (char *)po; - for (i = 0; i < nprops; i++, dprop++, is_str++) - { - memcpy(&local_off, off_adr, SIZEOF(fsPropOffset)); - dprop->name = MakeAtom(&pdc[local_off.name.position], - local_off.name.length, 1); - if (local_off.type != PropTypeString) { - *is_str = FALSE; - dprop->value = local_off.value.position; - } else { - *is_str = TRUE; - dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position], - local_off.value.length, 1); - if (dprop->value == BAD_RESOURCE) - { - free (pfi->props); - pfi->nprops = 0; - pfi->props = 0; - pfi->isStringProp = 0; - return -1; - } - } - off_adr += SIZEOF(fsPropOffset); - } - - return nprops; -} - -void -_fs_free_props (FontInfoPtr pfi) -{ - if (pfi->props) - { - free (pfi->props); - pfi->nprops = 0; - pfi->props = 0; - } -} - -int -_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, - fsListFontsWithXInfoReply *fsrep, - fsPropInfo *pi, fsPropOffset *po, pointer pd) -{ - fsUnpack_XFontInfoHeader(fsrep, pfi); - _fs_init_fontinfo(conn, pfi); - - if (_fs_convert_props(pi, po, pd, pfi) == -1) - return AllocError; - - return Successful; -} - - -#define ENCODING_UNDEFINED(enc) \ - ((enc)->bits == &_fs_glyph_undefined ? \ - TRUE : \ - (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \ - FALSE)) - -#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc)) - -/* - * figures out what glyphs to request - * - * Includes logic to attempt to reduce number of round trips to the font - * server: when a glyph is requested, fs_build_range() requests a - * 16-glyph range of glyphs that contains the requested glyph. This is - * predicated on the belief that using a glyph increases the chances - * that nearby glyphs will be used: a good assumption for phonetic - * alphabets, but a questionable one for ideographic/pictographic ones. - */ -/* ARGSUSED */ -int -fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, - int item_size, unsigned char *data, int *nranges, - fsRange **ranges) -{ - FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); - FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate); - register CharInfoPtr encoding = fsfont->encoding; - FontInfoPtr pfi = &(pfont->info); - fsRange range; - int access_done = TRUE; - int err; - register unsigned long firstrow, lastrow, firstcol, lastcol; - register unsigned long row; - register unsigned long col; - register unsigned long loc; - - if (!fsd->glyphs_to_get) - return AccessDone; - - firstrow = pfi->firstRow; - lastrow = pfi->lastRow; - firstcol = pfi->firstCol; - lastcol = pfi->lastCol; - - /* Make sure we have default char */ - if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault)) - { - loc = fsfont->pDefault - encoding; - row = loc / (lastcol - firstcol + 1) + firstrow; - col = loc % (lastcol - firstcol + 1) + firstcol; - - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = row; - - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[loc].bits = &_fs_glyph_requested; - access_done = FALSE; - } - - if (!range_flag && item_size == 1) - { - if (firstrow != 0) return AccessDone; - while (count--) - { - col = *data++; - if (col >= firstcol && col <= lastcol && - GLYPH_UNDEFINED(col - firstcol)) - { - int col1, col2; - col1 = col & 0xf0; - col2 = col1 + 15; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - /* Collect a 16-glyph neighborhood containing the requested - glyph... should in most cases reduce the number of round - trips to the font server. */ - for (col = col1; col <= col2; col++) - { - if (!GLYPH_UNDEFINED(col - firstcol)) continue; - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = 0; - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[col - firstcol].bits = &_fs_glyph_requested; - access_done = FALSE; - } - } - } - } - else - { - fsRange fullrange[1]; - - if (range_flag && count == 0) - { - count = 2; - data = (unsigned char *)fullrange; - fullrange[0].min_char_high = firstrow; - fullrange[0].min_char_low = firstcol; - fullrange[0].max_char_high = lastrow; - fullrange[0].max_char_low = lastcol; - } - - while (count--) - { - int row1, col1, row2, col2; - row1 = row2 = *data++; - col1 = col2 = *data++; - if (range_flag) - { - if (count) - { - row2 = *data++; - col2 = *data++; - count--; - } - else - { - row2 = lastrow; - col2 = lastcol; - } - if (row1 < firstrow) row1 = firstrow; - if (row2 > lastrow) row2 = lastrow; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - } - else - { - if (row1 < firstrow || row1 > lastrow || - col1 < firstcol || col1 > lastcol) - continue; - } - for (row = row1; row <= row2; row++) - { - expand_glyph_range: ; - loc = (row - firstrow) * (lastcol + 1 - firstcol) + - (col1 - firstcol); - for (col = col1; col <= col2; col++, loc++) - { - if (GLYPH_UNDEFINED(loc)) - { - if (row1 == row2 && - (((col1 & 0xf) && col1 > firstcol) || - (col2 & 0xf) != 0xf) && (col2 < lastcol)) - { - /* If we're loading from a single row, expand - range of glyphs loaded to a multiple of - a 16-glyph range -- attempt to reduce number - of round trips to the font server. */ - col1 &= 0xf0; - col2 = (col2 & 0xf0) + 15; - if (col1 < firstcol) col1 = firstcol; - if (col2 > lastcol) col2 = lastcol; - goto expand_glyph_range; - } - range.min_char_low = range.max_char_low = col; - range.min_char_high = range.max_char_high = row; - if ((err = add_range(&range, nranges, ranges, FALSE)) != - Successful) return err; - encoding[loc].bits = &_fs_glyph_requested; - access_done = FALSE; - } - } - } - } - } - - return access_done ? - AccessDone : - Successful; -} - -#undef GLYPH_UNDEFINED -#undef ENCODING_UNDEFINED - - -/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array - performed by fs_build_range(); for use if the associated LoadGlyphs - requests needs to be cancelled. */ - -void -_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, - fsRange *expected_ranges) -{ - register FSFontPtr fsfont; - register int i; - - fsfont = (FSFontPtr) pfont->fontPrivate; - if (fsfont->encoding) - { - fsRange full_range[1]; - if (!num_expected_ranges) - { - full_range[0].min_char_low = pfont->info.firstCol; - full_range[0].min_char_high = pfont->info.firstRow; - full_range[0].max_char_low = pfont->info.lastCol; - full_range[0].max_char_high = pfont->info.lastRow; - num_expected_ranges = 1; - expected_ranges = full_range; - } - - for (i = 0; i < num_expected_ranges; i++) - { - int row, col; - for (row = expected_ranges[i].min_char_high; - row <= expected_ranges[i].max_char_high; - row++) - { - register CharInfoPtr encoding = fsfont->encoding + - ((row - pfont->info.firstRow) * - (pfont->info.lastCol - - pfont->info.firstCol + 1) + - expected_ranges[i].min_char_low - - pfont->info.firstCol); - for (col = expected_ranges[i].min_char_low; - col <= expected_ranges[i].max_char_low; - encoding++, col++) - { - if (encoding->bits == &_fs_glyph_requested) - encoding->bits = &_fs_glyph_undefined; - } - } - } - } -} - -static int -_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - CharInfoPtr *glyphs) /* RETURN */ -{ - FSFontPtr fsdata; - unsigned int firstCol; - register unsigned int numCols; - unsigned int firstRow; - unsigned int numRows; - CharInfoPtr *glyphsBase; - register unsigned int c; - register CharInfoPtr pci; - unsigned int r; - CharInfoPtr encoding; - CharInfoPtr pDefault; - FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate; - int err = Successful; - - fsdata = (FSFontPtr) pFont->fontPrivate; - encoding = fsdata->encoding; - pDefault = fsdata->pDefault; - firstCol = pFont->info.firstCol; - numCols = pFont->info.lastCol - firstCol + 1; - glyphsBase = glyphs; - - /* In this age of glyph caching, any glyphs gotten through this - procedure should already be loaded. If they are not, we are - dealing with someone (perhaps a ddx driver optimizing a font) - that doesn't understand the finer points of glyph caching. The - CHECK_ENCODING macro checks for this condition... if found, it - calls fs_load_all_glyphs(), which corrects it. Since the caller - of this code will not know how to handle a return value of - Suspended, the fs_load_all_glyphs() procedure will block and - freeze the server until the load operation is done. Moral: the - glyphCachingMode flag really must indicate the capabilities of - the ddx drivers. */ - -#define CHECK_ENCODING(cnum) \ - ( pci = encoding + (cnum), \ - fsd->glyphs_to_get ? \ - ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \ - ((err = fs_load_all_glyphs(pFont)), pci) : \ - pci ) : \ - pci ) - - switch (charEncoding) { - - case Linear8Bit: - case TwoD8Bit: - if (pFont->info.firstRow > 0) - break; - if (pFont->info.allExist && pDefault) { - while (err == Successful && count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = CHECK_ENCODING(c); - else - *glyphs++ = pDefault; - } - } else { - while (err == Successful && count--) { - c = (*chars++) - firstCol; - if (c < numCols && CHECK_ENCODING(c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - case Linear16Bit: - if (pFont->info.allExist && pDefault) { - while (err == Successful && count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = CHECK_ENCODING(c); - else - *glyphs++ = pDefault; - } - } else { - while (err == Successful && count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols && CHECK_ENCODING(c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - } - break; - - case TwoD16Bit: - firstRow = pFont->info.firstRow; - numRows = pFont->info.lastRow - firstRow + 1; - while (err == Successful && count--) { - r = (*chars++) - firstRow; - c = (*chars++) - firstCol; - if (r < numRows && c < numCols && - CHECK_ENCODING(r * numCols + c)->bits) - *glyphs++ = pci; - else if (pDefault) - *glyphs++ = pDefault; - } - break; - } - *glyphCount = glyphs - glyphsBase; - return err; -} - - -static int -_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, - FontEncoding charEncoding, - unsigned long *glyphCount, /* RETURN */ - xCharInfo **glyphs) /* RETURN */ -{ - FSFontPtr fsdata; - unsigned int firstCol; - register unsigned int numCols; - unsigned int firstRow; - unsigned int numRows; - xCharInfo **glyphsBase; - register unsigned int c; - unsigned int r; - CharInfoPtr encoding; - CharInfoPtr pDefault; - - fsdata = (FSFontPtr) pFont->fontPrivate; - encoding = fsdata->inkMetrics; - pDefault = fsdata->pDefault; - /* convert default bitmap metric to default ink metric */ - if (pDefault) - pDefault = encoding + (pDefault - fsdata->encoding); - firstCol = pFont->info.firstCol; - numCols = pFont->info.lastCol - firstCol + 1; - glyphsBase = glyphs; - - - /* XXX - this should be much smarter */ - /* make sure the glyphs are there */ - switch (charEncoding) { - - case Linear8Bit: - case TwoD8Bit: - if (pFont->info.firstRow > 0) - break; - if (pFont->info.allExist && pDefault) { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)&encoding[c]; - else - *glyphs++ = (xCharInfo *)pDefault; - } - } else { - while (count--) { - c = (*chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - } - break; - case Linear16Bit: - if (pFont->info.allExist && pDefault) { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else - *glyphs++ = (xCharInfo *)pDefault; - } - } else { - while (count--) { - c = *chars++ << 8; - c = (c | *chars++) - firstCol; - if (c < numCols) - *glyphs++ = (xCharInfo *)(encoding + c); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - } - break; - - case TwoD16Bit: - firstRow = pFont->info.firstRow; - numRows = pFont->info.lastRow - firstRow + 1; - while (count--) { - r = (*chars++) - firstRow; - c = (*chars++) - firstCol; - if (r < numRows && c < numCols) - *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c)); - else if (pDefault) - *glyphs++ = (xCharInfo *)pDefault; - } - break; - } - *glyphCount = glyphs - glyphsBase; - return Successful; -} - - -static void -_fs_unload_font(FontPtr pfont) -{ - FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; - FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; - CharInfoPtr encoding = fsdata->encoding; - FSGlyphPtr glyphs; - - /* - * fsdata points at FSFontRec, FSFontDataRec and name - */ - if (encoding) - free(encoding); - - while ((glyphs = fsdata->glyphs)) - { - fsdata->glyphs = glyphs->next; - free (glyphs); - } - - /* XXX we may get called after the resource DB has been cleaned out */ - if (find_old_font(fsd->fontid)) - DeleteFontClientID (fsd->fontid); - - _fs_free_props (&pfont->info); - - free(fsdata); - - DestroyFontRec(pfont); -} - -FontPtr -fs_create_font (FontPathElementPtr fpe, - char *name, - int namelen, - fsBitmapFormat format, - fsBitmapFormatMask fmask) -{ - FontPtr pfont; - FSFontPtr fsfont; - FSFontDataPtr fsd; - int bit, byte, scan, glyph; - - pfont = CreateFontRec (); - if (!pfont) - return 0; - fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1); - if (!fsfont) - { - DestroyFontRec (pfont); - return 0; - } - fsd = (FSFontDataPtr) (fsfont + 1); - bzero((char *) fsfont, sizeof(FSFontRec)); - bzero((char *) fsd, sizeof(FSFontDataRec)); - - pfont->fpe = fpe; - pfont->fontPrivate = (pointer) fsfont; - pfont->fpePrivate = (pointer) fsd; - - /* These font components will be needed in packGlyphs */ - CheckFSFormat(format, BitmapFormatMaskBit | - BitmapFormatMaskByte | - BitmapFormatMaskScanLineUnit | - BitmapFormatMaskScanLinePad, - &bit, - &byte, - &scan, - &glyph, - NULL); - pfont->format = format; - pfont->bit = bit; - pfont->byte = byte; - pfont->scan = scan; - pfont->glyph = glyph; - - pfont->info.nprops = 0; - pfont->info.props = 0; - pfont->info.isStringProp = 0; - - /* set font function pointers */ - pfont->get_glyphs = _fs_get_glyphs; - pfont->get_metrics = _fs_get_metrics; - pfont->unload_font = _fs_unload_font; - pfont->unload_glyphs = NULL; - - /* set the FPE private information */ - fsd->format = format; - fsd->fmask = fmask; - fsd->name = (char *) (fsd + 1); - memcpy (fsd->name, name, namelen); - fsd->name[namelen] = '\0'; - fsd->fontid = GetNewFontClientID (); - - /* save the ID */ - if (!StoreFontClientFont(pfont, fsd->fontid)) - { - free (fsfont); - DestroyFontRec (pfont); - return 0; - } - - return pfont; -} - -pointer -fs_alloc_glyphs (FontPtr pFont, int size) -{ - FSGlyphPtr glyphs; - FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate; - - glyphs = malloc (sizeof (FSGlyphRec) + size); - glyphs->next = fsfont->glyphs; - fsfont->glyphs = glyphs; - return (pointer) (glyphs + 1); -} +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Network Computing Devices + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * FS data conversion + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include "fservestr.h" +#include +#include "fslibos.h" + +extern char _fs_glyph_undefined; +extern char _fs_glyph_requested; + +/* + * converts data from font server form to X server form + */ + +void +_fs_convert_char_info(fsXCharInfo *src, xCharInfo *dst) +{ + dst->ascent = src->ascent; + dst->descent = src->descent; + dst->leftSideBearing = src->left; + dst->rightSideBearing = src->right; + dst->characterWidth = src->width; + dst->attributes = src->attributes; +} + +void +_fs_init_fontinfo(FSFpePtr conn, FontInfoPtr pfi) +{ + if (conn->fsMajorVersion == 1) { + unsigned short n; + n = pfi->firstCol; + pfi->firstCol = pfi->firstRow; + pfi->firstRow = n; + n = pfi->lastCol; + pfi->lastCol = pfi->lastRow; + pfi->lastRow = n; + pfi->defaultCh = ((pfi->defaultCh >> 8) & 0xff) + + ((pfi->defaultCh & 0xff) << 8); + } + + if (FontCouldBeTerminal (pfi)) + { + pfi->terminalFont = TRUE; + pfi->minbounds.ascent = pfi->fontAscent; + pfi->minbounds.descent = pfi->fontDescent; + pfi->minbounds.leftSideBearing = 0; + pfi->minbounds.rightSideBearing = pfi->minbounds.characterWidth; + pfi->maxbounds = pfi->minbounds; + } + + FontComputeInfoAccelerators (pfi); +} + +int +_fs_convert_props(fsPropInfo *pi, fsPropOffset *po, pointer pd, + FontInfoPtr pfi) +{ + FontPropPtr dprop; + int i, + nprops; + char *is_str; + fsPropOffset local_off; + char *off_adr; + char *pdc = pd; + +/* stolen from server/include/resource.h */ +#define BAD_RESOURCE 0xe0000000 + + nprops = pfi->nprops = pi->num_offsets; + + if (nprops < 0 + || nprops > SIZE_MAX/(sizeof(FontPropRec) + sizeof(char))) + return -1; + + dprop = malloc(sizeof(FontPropRec) * nprops + sizeof (char) * nprops); + if (!dprop) + return -1; + + is_str = (char *) (dprop + nprops); + pfi->props = dprop; + pfi->isStringProp = is_str; + + off_adr = (char *)po; + for (i = 0; i < nprops; i++, dprop++, is_str++) + { + memcpy(&local_off, off_adr, SIZEOF(fsPropOffset)); + dprop->name = MakeAtom(&pdc[local_off.name.position], + local_off.name.length, 1); + if (local_off.type != PropTypeString) { + *is_str = FALSE; + dprop->value = local_off.value.position; + } else { + *is_str = TRUE; + dprop->value = (INT32) MakeAtom(&pdc[local_off.value.position], + local_off.value.length, 1); + if (dprop->value == BAD_RESOURCE) + { + free (pfi->props); + pfi->nprops = 0; + pfi->props = 0; + pfi->isStringProp = 0; + return -1; + } + } + off_adr += SIZEOF(fsPropOffset); + } + + return nprops; +} + +void +_fs_free_props (FontInfoPtr pfi) +{ + if (pfi->props) + { + free (pfi->props); + pfi->nprops = 0; + pfi->props = 0; + } +} + +int +_fs_convert_lfwi_reply(FSFpePtr conn, FontInfoPtr pfi, + fsListFontsWithXInfoReply *fsrep, + fsPropInfo *pi, fsPropOffset *po, pointer pd) +{ + fsUnpack_XFontInfoHeader(fsrep, pfi); + _fs_init_fontinfo(conn, pfi); + + if (_fs_convert_props(pi, po, pd, pfi) == -1) + return AllocError; + + return Successful; +} + + +#define ENCODING_UNDEFINED(enc) \ + ((enc)->bits == &_fs_glyph_undefined ? \ + TRUE : \ + (access_done = access_done && (enc)->bits != &_fs_glyph_requested, \ + FALSE)) + +#define GLYPH_UNDEFINED(loc) ENCODING_UNDEFINED(encoding + (loc)) + +/* + * figures out what glyphs to request + * + * Includes logic to attempt to reduce number of round trips to the font + * server: when a glyph is requested, fs_build_range() requests a + * 16-glyph range of glyphs that contains the requested glyph. This is + * predicated on the belief that using a glyph increases the chances + * that nearby glyphs will be used: a good assumption for phonetic + * alphabets, but a questionable one for ideographic/pictographic ones. + */ +/* ARGSUSED */ +int +fs_build_range(FontPtr pfont, Bool range_flag, unsigned int count, + int item_size, unsigned char *data, int *nranges, + fsRange **ranges) +{ + FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); + FSFontPtr fsfont = (FSFontPtr) (pfont->fontPrivate); + register CharInfoPtr encoding = fsfont->encoding; + FontInfoPtr pfi = &(pfont->info); + fsRange range; + int access_done = TRUE; + int err; + register unsigned long firstrow, lastrow, firstcol, lastcol; + register unsigned long row; + register unsigned long col; + register unsigned long loc; + + if (!fsd->glyphs_to_get) + return AccessDone; + + firstrow = pfi->firstRow; + lastrow = pfi->lastRow; + firstcol = pfi->firstCol; + lastcol = pfi->lastCol; + + /* Make sure we have default char */ + if (fsfont->pDefault && ENCODING_UNDEFINED(fsfont->pDefault)) + { + loc = fsfont->pDefault - encoding; + row = loc / (lastcol - firstcol + 1) + firstrow; + col = loc % (lastcol - firstcol + 1) + firstcol; + + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = row; + + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[loc].bits = &_fs_glyph_requested; + access_done = FALSE; + } + + if (!range_flag && item_size == 1) + { + if (firstrow != 0) return AccessDone; + while (count--) + { + col = *data++; + if (col >= firstcol && col <= lastcol && + GLYPH_UNDEFINED(col - firstcol)) + { + int col1, col2; + col1 = col & 0xf0; + col2 = col1 + 15; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + /* Collect a 16-glyph neighborhood containing the requested + glyph... should in most cases reduce the number of round + trips to the font server. */ + for (col = col1; col <= col2; col++) + { + if (!GLYPH_UNDEFINED(col - firstcol)) continue; + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = 0; + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[col - firstcol].bits = &_fs_glyph_requested; + access_done = FALSE; + } + } + } + } + else + { + fsRange fullrange[1]; + + if (range_flag && count == 0) + { + count = 2; + data = (unsigned char *)fullrange; + fullrange[0].min_char_high = firstrow; + fullrange[0].min_char_low = firstcol; + fullrange[0].max_char_high = lastrow; + fullrange[0].max_char_low = lastcol; + } + + while (count--) + { + int row1, col1, row2, col2; + row1 = row2 = *data++; + col1 = col2 = *data++; + if (range_flag) + { + if (count) + { + row2 = *data++; + col2 = *data++; + count--; + } + else + { + row2 = lastrow; + col2 = lastcol; + } + if (row1 < firstrow) row1 = firstrow; + if (row2 > lastrow) row2 = lastrow; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + } + else + { + if (row1 < firstrow || row1 > lastrow || + col1 < firstcol || col1 > lastcol) + continue; + } + for (row = row1; row <= row2; row++) + { + expand_glyph_range: ; + loc = (row - firstrow) * (lastcol + 1 - firstcol) + + (col1 - firstcol); + for (col = col1; col <= col2; col++, loc++) + { + if (GLYPH_UNDEFINED(loc)) + { + if (row1 == row2 && + (((col1 & 0xf) && col1 > firstcol) || + (col2 & 0xf) != 0xf) && (col2 < lastcol)) + { + /* If we're loading from a single row, expand + range of glyphs loaded to a multiple of + a 16-glyph range -- attempt to reduce number + of round trips to the font server. */ + col1 &= 0xf0; + col2 = (col2 & 0xf0) + 15; + if (col1 < firstcol) col1 = firstcol; + if (col2 > lastcol) col2 = lastcol; + goto expand_glyph_range; + } + range.min_char_low = range.max_char_low = col; + range.min_char_high = range.max_char_high = row; + if ((err = add_range(&range, nranges, ranges, FALSE)) != + Successful) return err; + encoding[loc].bits = &_fs_glyph_requested; + access_done = FALSE; + } + } + } + } + } + + return access_done ? + AccessDone : + Successful; +} + +#undef GLYPH_UNDEFINED +#undef ENCODING_UNDEFINED + + +/* _fs_clean_aborted_loadglyphs(): Undoes the changes to the encoding array + performed by fs_build_range(); for use if the associated LoadGlyphs + requests needs to be cancelled. */ + +void +_fs_clean_aborted_loadglyphs(FontPtr pfont, int num_expected_ranges, + fsRange *expected_ranges) +{ + register FSFontPtr fsfont; + register int i; + + fsfont = (FSFontPtr) pfont->fontPrivate; + if (fsfont->encoding) + { + fsRange full_range[1]; + if (!num_expected_ranges) + { + full_range[0].min_char_low = pfont->info.firstCol; + full_range[0].min_char_high = pfont->info.firstRow; + full_range[0].max_char_low = pfont->info.lastCol; + full_range[0].max_char_high = pfont->info.lastRow; + num_expected_ranges = 1; + expected_ranges = full_range; + } + + for (i = 0; i < num_expected_ranges; i++) + { + int row, col; + for (row = expected_ranges[i].min_char_high; + row <= expected_ranges[i].max_char_high; + row++) + { + register CharInfoPtr encoding = fsfont->encoding + + ((row - pfont->info.firstRow) * + (pfont->info.lastCol - + pfont->info.firstCol + 1) + + expected_ranges[i].min_char_low - + pfont->info.firstCol); + for (col = expected_ranges[i].min_char_low; + col <= expected_ranges[i].max_char_low; + encoding++, col++) + { + if (encoding->bits == &_fs_glyph_requested) + encoding->bits = &_fs_glyph_undefined; + } + } + } + } +} + +static int +_fs_get_glyphs(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + CharInfoPtr *glyphs) /* RETURN */ +{ + FSFontPtr fsdata; + unsigned int firstCol; + register unsigned int numCols; + unsigned int firstRow; + unsigned int numRows; + CharInfoPtr *glyphsBase; + register unsigned int c; + register CharInfoPtr pci; + unsigned int r; + CharInfoPtr encoding; + CharInfoPtr pDefault; + FSFontDataPtr fsd = (FSFontDataPtr) pFont->fpePrivate; + int err = Successful; + + fsdata = (FSFontPtr) pFont->fontPrivate; + encoding = fsdata->encoding; + pDefault = fsdata->pDefault; + firstCol = pFont->info.firstCol; + numCols = pFont->info.lastCol - firstCol + 1; + glyphsBase = glyphs; + + /* In this age of glyph caching, any glyphs gotten through this + procedure should already be loaded. If they are not, we are + dealing with someone (perhaps a ddx driver optimizing a font) + that doesn't understand the finer points of glyph caching. The + CHECK_ENCODING macro checks for this condition... if found, it + calls fs_load_all_glyphs(), which corrects it. Since the caller + of this code will not know how to handle a return value of + Suspended, the fs_load_all_glyphs() procedure will block and + freeze the server until the load operation is done. Moral: the + glyphCachingMode flag really must indicate the capabilities of + the ddx drivers. */ + +#define CHECK_ENCODING(cnum) \ + ( pci = encoding + (cnum), \ + fsd->glyphs_to_get ? \ + ( pci->bits == &_fs_glyph_undefined || pci->bits == &_fs_glyph_requested ? \ + ((err = fs_load_all_glyphs(pFont)), pci) : \ + pci ) : \ + pci ) + + switch (charEncoding) { + + case Linear8Bit: + case TwoD8Bit: + if (pFont->info.firstRow > 0) + break; + if (pFont->info.allExist && pDefault) { + while (err == Successful && count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = CHECK_ENCODING(c); + else + *glyphs++ = pDefault; + } + } else { + while (err == Successful && count--) { + c = (*chars++) - firstCol; + if (c < numCols && CHECK_ENCODING(c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + case Linear16Bit: + if (pFont->info.allExist && pDefault) { + while (err == Successful && count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = CHECK_ENCODING(c); + else + *glyphs++ = pDefault; + } + } else { + while (err == Successful && count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols && CHECK_ENCODING(c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + } + break; + + case TwoD16Bit: + firstRow = pFont->info.firstRow; + numRows = pFont->info.lastRow - firstRow + 1; + while (err == Successful && count--) { + r = (*chars++) - firstRow; + c = (*chars++) - firstCol; + if (r < numRows && c < numCols && + CHECK_ENCODING(r * numCols + c)->bits) + *glyphs++ = pci; + else if (pDefault) + *glyphs++ = pDefault; + } + break; + } + *glyphCount = glyphs - glyphsBase; + return err; +} + + +static int +_fs_get_metrics(FontPtr pFont, unsigned long count, unsigned char *chars, + FontEncoding charEncoding, + unsigned long *glyphCount, /* RETURN */ + xCharInfo **glyphs) /* RETURN */ +{ + FSFontPtr fsdata; + unsigned int firstCol; + register unsigned int numCols; + unsigned int firstRow; + unsigned int numRows; + xCharInfo **glyphsBase; + register unsigned int c; + unsigned int r; + CharInfoPtr encoding; + CharInfoPtr pDefault; + + fsdata = (FSFontPtr) pFont->fontPrivate; + encoding = fsdata->inkMetrics; + pDefault = fsdata->pDefault; + /* convert default bitmap metric to default ink metric */ + if (pDefault) + pDefault = encoding + (pDefault - fsdata->encoding); + firstCol = pFont->info.firstCol; + numCols = pFont->info.lastCol - firstCol + 1; + glyphsBase = glyphs; + + + /* XXX - this should be much smarter */ + /* make sure the glyphs are there */ + switch (charEncoding) { + + case Linear8Bit: + case TwoD8Bit: + if (pFont->info.firstRow > 0) + break; + if (pFont->info.allExist && pDefault) { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)&encoding[c]; + else + *glyphs++ = (xCharInfo *)pDefault; + } + } else { + while (count--) { + c = (*chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + } + break; + case Linear16Bit: + if (pFont->info.allExist && pDefault) { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else + *glyphs++ = (xCharInfo *)pDefault; + } + } else { + while (count--) { + c = *chars++ << 8; + c = (c | *chars++) - firstCol; + if (c < numCols) + *glyphs++ = (xCharInfo *)(encoding + c); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + } + break; + + case TwoD16Bit: + firstRow = pFont->info.firstRow; + numRows = pFont->info.lastRow - firstRow + 1; + while (count--) { + r = (*chars++) - firstRow; + c = (*chars++) - firstCol; + if (r < numRows && c < numCols) + *glyphs++ = (xCharInfo *)(encoding + (r * numCols + c)); + else if (pDefault) + *glyphs++ = (xCharInfo *)pDefault; + } + break; + } + *glyphCount = glyphs - glyphsBase; + return Successful; +} + + +static void +_fs_unload_font(FontPtr pfont) +{ + FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; + FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; + CharInfoPtr encoding = fsdata->encoding; + FSGlyphPtr glyphs; + + /* + * fsdata points at FSFontRec, FSFontDataRec and name + */ + if (encoding) + free(encoding); + + while ((glyphs = fsdata->glyphs)) + { + fsdata->glyphs = glyphs->next; + free (glyphs); + } + + /* XXX we may get called after the resource DB has been cleaned out */ + if (find_old_font(fsd->fontid)) + DeleteFontClientID (fsd->fontid); + + _fs_free_props (&pfont->info); + + free(fsdata); + + DestroyFontRec(pfont); +} + +FontPtr +fs_create_font (FontPathElementPtr fpe, + char *name, + int namelen, + fsBitmapFormat format, + fsBitmapFormatMask fmask) +{ + FontPtr pfont; + FSFontPtr fsfont; + FSFontDataPtr fsd; + int bit, byte, scan, glyph; + + pfont = CreateFontRec (); + if (!pfont) + return 0; + fsfont = malloc (sizeof (FSFontRec) + sizeof (FSFontDataRec) + namelen + 1); + if (!fsfont) + { + DestroyFontRec (pfont); + return 0; + } + fsd = (FSFontDataPtr) (fsfont + 1); + bzero((char *) fsfont, sizeof(FSFontRec)); + bzero((char *) fsd, sizeof(FSFontDataRec)); + + pfont->fpe = fpe; + pfont->fontPrivate = (pointer) fsfont; + pfont->fpePrivate = (pointer) fsd; + + /* These font components will be needed in packGlyphs */ + CheckFSFormat(format, BitmapFormatMaskBit | + BitmapFormatMaskByte | + BitmapFormatMaskScanLineUnit | + BitmapFormatMaskScanLinePad, + &bit, + &byte, + &scan, + &glyph, + NULL); + pfont->format = format; + pfont->bit = bit; + pfont->byte = byte; + pfont->scan = scan; + pfont->glyph = glyph; + + pfont->info.nprops = 0; + pfont->info.props = 0; + pfont->info.isStringProp = 0; + + /* set font function pointers */ + pfont->get_glyphs = _fs_get_glyphs; + pfont->get_metrics = _fs_get_metrics; + pfont->unload_font = _fs_unload_font; + pfont->unload_glyphs = NULL; + + /* set the FPE private information */ + fsd->format = format; + fsd->fmask = fmask; + fsd->name = (char *) (fsd + 1); + memcpy (fsd->name, name, namelen); + fsd->name[namelen] = '\0'; + fsd->fontid = GetNewFontClientID (); + + /* save the ID */ + if (!StoreFontClientFont(pfont, fsd->fontid)) + { + free (fsfont); + DestroyFontRec (pfont); + return 0; + } + + return pfont; +} + +pointer +fs_alloc_glyphs (FontPtr pFont, int size) +{ + FSGlyphPtr glyphs; + FSFontPtr fsfont = (FSFontPtr) pFont->fontPrivate; + + glyphs = malloc (sizeof (FSGlyphRec) + size); + glyphs->next = fsfont->glyphs; + fsfont->glyphs = glyphs; + return (pointer) (glyphs + 1); +} diff --git a/libXfont/src/fc/fserve.c b/libXfont/src/fc/fserve.c index f59dbcc9f..b02b0b749 100644 --- a/libXfont/src/fc/fserve.c +++ b/libXfont/src/fc/fserve.c @@ -1,3198 +1,3198 @@ -/* - -Copyright 1990, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -*/ - -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, 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 names of Network Computing Devices, or Digital - * not be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * - * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, - * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * font server specific font access - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef WIN32 -#define _WILLWINSOCK_ -#endif -#define FONT_t -#define TRANS_CLIENT -#include "X11/Xtrans/Xtrans.h" -#include "X11/Xpoll.h" -#include -#include -#include -#include -#include -#include -#include "fservestr.h" -#include -#include - -#include -#define Time_t time_t - -#ifdef NCD -#include -#endif - -#include - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) - -#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ - (pci)->rightSideBearing || \ - (pci)->ascent || \ - (pci)->descent || \ - (pci)->characterWidth) - -extern void ErrorF(const char *f, ...); - -static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list_info ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); - -extern fd_set _fs_fd_mask; - -static void fs_block_handler ( pointer data, OSTimePtr wt, - pointer LastSelectMask ); -static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); - -/* - * List of all FPEs - */ -static FSFpePtr fs_fpes; -/* - * Union of all FPE blockStates - */ -static CARD32 fs_blockState; - -static int _fs_restart_connection ( FSFpePtr conn ); -static void fs_send_query_bitmaps ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); -static int fs_send_close_font ( FontPathElementPtr fpe, Font id ); -static void fs_client_died ( pointer client, FontPathElementPtr fpe ); -static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); -static void _fs_client_resolution ( FSFpePtr conn ); -static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); -static int fs_await_reply (FSFpePtr conn); -static void _fs_do_blocked (FSFpePtr conn); -static void fs_cleanup_bfont (FSBlockedFontPtr bfont); - -char _fs_glyph_undefined; -char _fs_glyph_requested; -static char _fs_glyph_zero_length; - -static int generationCount; - -static int FontServerRequestTimeout = 30 * 1000; - -static void -_fs_close_server (FSFpePtr conn); - -static FSFpePtr -_fs_init_conn (char *servername); - -static int -_fs_wait_connect (FSFpePtr conn); - -static int -_fs_send_init_packets (FSFpePtr conn); - -static void -_fs_check_reconnect (FSFpePtr conn); - -static void -_fs_start_reconnect (FSFpePtr conn); - -static void -_fs_free_conn (FSFpePtr conn); - -static int -fs_free_fpe(FontPathElementPtr fpe); - -/* - * Font server access - * - * the basic idea for the non-blocking access is to have the function - * called multiple times until the actual data is returned, instead - * of ClientBlocked. - * - * the first call to the function will cause the request to be sent to - * the font server, and a block record to be stored in the fpe's list - * of outstanding requests. the FS block handler also sticks the - * proper set of fd's into the select mask. when data is ready to be - * read in, the FS wakup handler will be hit. this will read the - * data off the wire into the proper block record, and then signal the - * client that caused the block so that it can restart. it will then - * call the access function again, which will realize that the data has - * arrived and return it. - */ - - -#ifdef DEBUG -static void -_fs_add_req_log(FSFpePtr conn, int opcode) -{ - conn->current_seq++; - fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", - conn->current_seq, opcode); - conn->reqbuffer[conn->reqindex].opcode = opcode; - conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; - conn->reqindex++; - if (conn->reqindex == REQUEST_LOG_SIZE) - conn->reqindex = 0; -} - -static void -_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) -{ - int i; - - for (i = 0; i < REQUEST_LOG_SIZE; i++) - if (conn->reqbuffer[i].sequence == rep->sequenceNumber) - break; - if (i == REQUEST_LOG_SIZE) - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", - rep->sequenceNumber); - else - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", - rep->sequenceNumber, - conn->reqbuffer[i].opcode); -} -#else -#define _fs_add_req_log(conn,op) ((conn)->current_seq++) -#define _fs_add_rep_log(conn,rep) -#endif - -static Bool -fs_name_check(char *name) -{ - /* Just make sure there is a protocol/ prefix */ - return (name && *name != '/' && strchr(name, '/')); -} - -static void -_fs_client_resolution(FSFpePtr conn) -{ - fsSetResolutionReq srreq; - int num_res; - FontResolutionPtr res; - - res = GetClientResolutions(&num_res); - - if (num_res) { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) - (void)_fs_write_pad(conn, (char *) res, - (num_res * SIZEOF(fsResolution))); - } -} - -/* - * close font server and remove any state associated with - * this connection - this includes any client records. - */ - -static void -fs_close_conn(FSFpePtr conn) -{ - FSClientPtr client, nclient; - - _fs_close_server (conn); - - for (client = conn->clients; client; client = nclient) - { - nclient = client->next; - free (client); - } - conn->clients = NULL; -} - -/* - * the wakeup handlers have to be set when the FPE is open, and not - * removed until it is freed, in order to handle unexpected data, like - * events - */ -/* ARGSUSED */ -static int -fs_init_fpe(FontPathElementPtr fpe) -{ - FSFpePtr conn; - char *name; - int err; - int ret; - - /* open font server */ - /* create FS specific fpe info */ - name = fpe->name; - - /* hack for old style names */ - if (*name == ':') - name++; /* skip ':' */ - - conn = _fs_init_conn (name); - if (!conn) - err = AllocError; - else - { - err = init_fs_handlers (fpe, fs_block_handler); - if (err != Successful) - { - _fs_free_conn (conn); - err = AllocError; - } - else - { - fpe->private = conn; - conn->next = fs_fpes; - fs_fpes = conn; - ret = _fs_wait_connect (conn); - if (ret != FSIO_READY) - { - fs_free_fpe (fpe); - err = BadFontPath; - } - else - err = Successful; - } - } - - if (err == Successful) - { -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Connected to font server \"%s\"\n", name); -#endif -#ifdef DEBUG - fprintf (stderr, "connected to FS \"%s\"\n", name); -#endif - } - else - { -#ifdef DEBUG - fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); -#endif -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Failed to connect to font server \"%s\"\n", name); -#endif - ; - } - return err; -} - -static int -fs_reset_fpe(FontPathElementPtr fpe) -{ - (void) _fs_send_init_packets((FSFpePtr) fpe->private); - return Successful; -} - -/* - * this shouldn't be called till all refs to the FPE are gone - */ - -static int -fs_free_fpe(FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private, *prev; - - /* unhook from chain of all font servers */ - for (prev = &fs_fpes; *prev; prev = &(*prev)->next) - { - if (*prev == conn) - { - *prev = conn->next; - break; - } - } - _fs_unmark_block (conn, conn->blockState); - fs_close_conn(conn); - remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); - _fs_free_conn (conn); - fpe->private = (pointer) 0; - -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Disconnected from font server \"%s\"\n", fpe->name); -#endif -#ifdef DEBUG - fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); -#endif - - return Successful; -} - -static FSBlockDataPtr -fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) -{ - FSBlockDataPtr blockrec, - *prev; - FSFpePtr conn = (FSFpePtr) fpe->private; - int size; - - switch (type) { - case FS_OPEN_FONT: - size = sizeof(FSBlockedFontRec); - break; - case FS_LOAD_GLYPHS: - size = sizeof(FSBlockedGlyphRec); - break; - case FS_LIST_FONTS: - size = sizeof(FSBlockedListRec); - break; - case FS_LIST_WITH_INFO: - size = sizeof(FSBlockedListInfoRec); - break; - default: - size = 0; - break; - } - blockrec = malloc(sizeof(FSBlockDataRec) + size); - if (!blockrec) - return (FSBlockDataPtr) 0; - blockrec->data = (pointer) (blockrec + 1); - blockrec->client = client; - blockrec->sequenceNumber = -1; - blockrec->errcode = StillWorking; - blockrec->type = type; - blockrec->depending = 0; - blockrec->next = (FSBlockDataPtr) 0; - - /* stick it on the end of the list (since its expected last) */ - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - ; - *prev = blockrec; - - return blockrec; -} - -static void -_fs_set_pending_reply (FSFpePtr conn) -{ - FSBlockDataPtr blockrec; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->errcode == StillWorking) - break; - if (blockrec) - { - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - } - else - _fs_unmark_block (conn, FS_PENDING_REPLY); -} - -static void -_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - FSBlockDataPtr *prev; - - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - if (*prev == blockrec) - { - *prev = blockrec->next; - break; - } - if (blockrec->type == FS_LOAD_GLYPHS) - { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - if (bglyph->num_expected_ranges) - free(bglyph->expected_ranges); - } - free(blockrec); - _fs_set_pending_reply (conn); -} - -static void -_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) -{ - FSClientsDependingPtr p; - - while ((p = *clients_depending)) - { - *clients_depending = p->next; - ClientSignal(p->client); - free(p); - } -} - -static int -_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) -{ - FSClientsDependingPtr new, cd; - - for (; (cd = *clients_depending); - clients_depending = &(*clients_depending)->next) - { - if (cd->client == client) - return Suspended; - } - - new = malloc (sizeof (FSClientsDependingRec)); - if (!new) - return BadAlloc; - - new->client = client; - new->next = 0; - *clients_depending = new; - return Suspended; -} - -/* - * When a request is aborted due to a font server failure, - * signal any depending clients to restart their dependant - * requests - */ -static void -_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - switch(blockrec->type) { - case FS_OPEN_FONT: { - FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; - - fs_cleanup_bfont (bfont); - _fs_signal_clients_depending(&bfont->clients_depending); - break; - } - case FS_LOAD_GLYPHS: { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - - _fs_clean_aborted_loadglyphs(bglyph->pfont, - bglyph->num_expected_ranges, - bglyph->expected_ranges); - _fs_signal_clients_depending(&bglyph->clients_depending); - break; - } - case FS_LIST_FONTS: - break; - case FS_LIST_WITH_INFO: { - FSBlockedListInfoPtr binfo; - binfo = (FSBlockedListInfoPtr) blockrec->data; - if (binfo->status == FS_LFWI_REPLY) - FD_SET(conn->fs_fd, &_fs_fd_mask); - _fs_free_props (&binfo->info); - } - default: - break; - } -} - -static void -fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - _fs_clean_aborted_blockrec (conn, blockrec); - _fs_remove_block_rec (conn, blockrec); -} - -/* - * Tell the font server we've failed to complete an open and - * then unload the partially created font - */ -static void -fs_cleanup_bfont (FSBlockedFontPtr bfont) -{ - FSFontDataRec *fsd; - - if (bfont->pfont) - { - fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; - - /* make sure the FS knows we choked on it */ - fs_send_close_font(bfont->pfont->fpe, bfont->fontid); - - /* - * Either unload the font if it's being opened for - * the first time, or smash the generation field to - * mark this font as an orphan - */ - if (!(bfont->flags & FontReopen)) - { - if (bfont->freeFont) - (*bfont->pfont->unload_font) (bfont->pfont); -#ifdef DEBUG - else - fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); -#endif - bfont->pfont = 0; - } - else - fsd->generation = -1; - } -} - -/* - * Check to see if a complete reply is waiting - */ -static fsGenericReply * -fs_get_reply (FSFpePtr conn, int *error) -{ - char *buf; - fsGenericReply *rep; - int ret; - - /* block if the connection is down or paused in lfwi */ - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - { - *error = FSIO_BLOCK; - return 0; - } - - ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - rep = (fsGenericReply *) buf; - - ret = _fs_start_read (conn, rep->length << 2, &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - *error = FSIO_READY; - - return (fsGenericReply *) buf; -} - -static Bool -fs_reply_ready (FSFpePtr conn) -{ - fsGenericReply *rep; - - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - return FALSE; - if (fs_data_read (conn) < sizeof (fsGenericReply)) - return FALSE; - rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); - if (fs_data_read (conn) < rep->length << 2) - return FALSE; - return TRUE; -} - -static void -_fs_pending_reply (FSFpePtr conn) -{ - if (!(conn->blockState & FS_PENDING_REPLY)) - { - _fs_mark_block (conn, FS_PENDING_REPLY); - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - } -} - -static void -_fs_prepare_for_reply (FSFpePtr conn) -{ - _fs_pending_reply (conn); - _fs_flush (conn); -} - -/* - * Block (for a while) awaiting a complete reply - */ -static int -fs_await_reply (FSFpePtr conn) -{ - int ret; - - if (conn->blockState & FS_COMPLETE_REPLY) - return FSIO_READY; - - while (!fs_get_reply (conn, &ret)) - { - if (ret != FSIO_BLOCK) - return ret; - if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - return FSIO_READY; -} - -/* - * Process the reply to an OpenBitmapFont request - */ -static int -fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsOpenBitmapFontReply *rep; - FSBlockDataPtr blockOrig; - FSBlockedFontPtr origBfont; - int ret; - - rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* If we're not reopening a font and FS detected a duplicate font - open request, replace our reference to the new font with a - reference to an existing font (possibly one not finished - opening). If this is a reopen, keep the new font reference... - it's got the metrics and extents we read when the font was opened - before. This also gives us the freedom to easily close the font - if we we decide (in fs_read_query_info()) that we don't like what - we got. */ - - if (rep->otherid && !(bfont->flags & FontReopen)) - { - fs_cleanup_bfont (bfont); - - /* Find old font if we're completely done getting it from server. */ - bfont->pfont = find_old_font(rep->otherid); - bfont->freeFont = FALSE; - bfont->fontid = rep->otherid; - bfont->state = FS_DONE_REPLY; - /* - * look for a blocked request to open the same font - */ - for (blockOrig = conn->blockedRequests; - blockOrig; - blockOrig = blockOrig->next) - { - if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) - { - origBfont = (FSBlockedFontPtr) blockOrig->data; - if (origBfont->fontid == rep->otherid) - { - blockrec->depending = blockOrig->depending; - blockOrig->depending = blockrec; - bfont->state = FS_DEPENDING; - bfont->pfont = origBfont->pfont; - break; - } - } - } - if (bfont->pfont == NULL) - { - /* XXX - something nasty happened */ - ret = BadFontName; - } - else - ret = AccessDone; - } - else - { - bfont->pfont->info.cachable = rep->cachable != 0; - bfont->state = FS_INFO_REPLY; - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryInfoSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - ret = StillWorking; - } - _fs_done_read (conn, rep->length << 2); - return ret; -} - -static Bool -fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) -{ - int i; - - if (pInfo1->firstCol != pInfo2->firstCol || - pInfo1->lastCol != pInfo2->lastCol || - pInfo1->firstRow != pInfo2->firstRow || - pInfo1->lastRow != pInfo2->lastRow || - pInfo1->defaultCh != pInfo2->defaultCh || - pInfo1->noOverlap != pInfo2->noOverlap || - pInfo1->terminalFont != pInfo2->terminalFont || - pInfo1->constantMetrics != pInfo2->constantMetrics || - pInfo1->constantWidth != pInfo2->constantWidth || - pInfo1->inkInside != pInfo2->inkInside || - pInfo1->inkMetrics != pInfo2->inkMetrics || - pInfo1->allExist != pInfo2->allExist || - pInfo1->drawDirection != pInfo2->drawDirection || - pInfo1->cachable != pInfo2->cachable || - pInfo1->anamorphic != pInfo2->anamorphic || - pInfo1->maxOverlap != pInfo2->maxOverlap || - pInfo1->fontAscent != pInfo2->fontAscent || - pInfo1->fontDescent != pInfo2->fontDescent || - pInfo1->nprops != pInfo2->nprops) - return FALSE; - -#define MATCH(xci1, xci2) \ - (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ - ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ - ((xci1).characterWidth == (xci2).characterWidth) && \ - ((xci1).ascent == (xci2).ascent) && \ - ((xci1).descent == (xci2).descent) && \ - ((xci1).attributes == (xci2).attributes)) - - if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || - !MATCH(pInfo1->minbounds, pInfo2->minbounds) || - !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || - !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) - return FALSE; - -#undef MATCH - - for (i = 0; i < pInfo1->nprops; i++) - if (pInfo1->isStringProp[i] != - pInfo2->isStringProp[i] || - pInfo1->props[i].name != - pInfo2->props[i].name || - pInfo1->props[i].value != - pInfo2->props[i].value) - { - return FALSE; - } - return TRUE; -} - -static int -fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsQueryXInfoReply *rep; - char *buf; - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - FontInfoPtr pInfo; - FontInfoRec tempInfo; - int err; - int ret; - - rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* If this is a reopen, accumulate the query info into a dummy - font and compare to our original data. */ - if (bfont->flags & FontReopen) - pInfo = &tempInfo; - else - pInfo = &bfont->pfont->info; - - buf = (char *) rep; - buf += SIZEOF(fsQueryXInfoReply); - - /* move the data over */ - fsUnpack_XFontInfoHeader(rep, pInfo); - - /* compute accelerators */ - _fs_init_fontinfo(conn, pInfo); - - /* Compute offsets into the reply */ - pi = (fsPropInfo *) buf; - buf += SIZEOF (fsPropInfo); - - po = (fsPropOffset *) buf; - buf += pi->num_offsets * SIZEOF(fsPropOffset); - - pd = (pointer) buf; - buf += pi->data_len; - - /* convert the properties and step over the reply */ - ret = _fs_convert_props(pi, po, pd, pInfo); - _fs_done_read (conn, rep->length << 2); - - if (ret == -1) - { - fs_cleanup_bfont (bfont); - return AllocError; - } - - if (bfont->flags & FontReopen) - { - /* We're reopening a font that we lost because of a downed - connection. In the interest of avoiding corruption from - opening a different font than the old one (we already have - its metrics, extents, and probably some of its glyphs), - verify that the metrics and properties all match. */ - - if (fs_fonts_match (pInfo, &bfont->pfont->info)) - { - err = Successful; - bfont->state = FS_DONE_REPLY; - } - else - { - fs_cleanup_bfont (bfont); - err = BadFontName; - } - _fs_free_props (pInfo); - - return err; - } - - /* - * Ask for terminal format fonts if possible - */ - if (bfont->pfont->info.terminalFont) - bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax); - - /* - * Figure out if the whole font should get loaded right now. - */ - if (glyphCachingMode == CACHING_OFF || - (glyphCachingMode == CACHE_16_BIT_GLYPHS - && !bfont->pfont->info.lastRow)) - { - bfont->flags |= FontLoadAll; - } - - /* - * Ready to send the query bitmaps; the terminal font bit has - * been computed and glyphCaching has been considered - */ - if (bfont->flags & FontLoadBitmaps) - { - fs_send_query_bitmaps (fpe, blockrec); - _fs_flush (conn); - } - - bfont->state = FS_EXTENT_REPLY; - - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryExtentsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - - return StillWorking; -} - -static int -fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; - FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; - fsQueryXExtents16Reply *rep; - char *buf; - int i; - int numExtents; - int numInfos; - int ret; - Bool haveInk = FALSE; /* need separate ink metrics? */ - CharInfoPtr ci, pCI; - char *fsci; - fsXCharInfo fscilocal; - FontInfoRec *fi = &bfont->pfont->info; - - rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - return BadFontName; - } - - /* move the data over */ - /* need separate inkMetrics for fixed font server protocol version */ - numExtents = rep->num_extents; - numInfos = numExtents; - if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) - { - numInfos *= 2; - haveInk = TRUE; - } - ci = pCI = malloc(sizeof(CharInfoRec) * numInfos); - - if (!pCI) - { - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont(bfont); - return AllocError; - } - fsfont->encoding = pCI; - if (haveInk) - fsfont->inkMetrics = pCI + numExtents; - else - fsfont->inkMetrics = pCI; - - buf = (char *) rep; - buf += SIZEOF (fsQueryXExtents16Reply); - fsci = buf; - - fsd->glyphs_to_get = 0; - ci = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++) - { - memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ - _fs_convert_char_info(&fscilocal, &ci->metrics); - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - fsci = fsci + SIZEOF(fsXCharInfo); - /* Initialize the bits field for later glyph-caching use */ - if (NONZEROMETRICS(&ci->metrics)) - { - if (!haveInk && - (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || - ci->metrics.ascent == -ci->metrics.descent)) - pCI[i].bits = &_fs_glyph_zero_length; - else - { - pCI[i].bits = &_fs_glyph_undefined; - fsd->glyphs_to_get++; - } - } - else - pCI[i].bits = (char *)0; - ci++; - } - - /* Done with reply */ - _fs_done_read (conn, rep->length << 2); - - /* build bitmap metrics, ImageRectMax style */ - if (haveInk) - { - CharInfoPtr ii; - - ci = fsfont->encoding; - ii = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++, ci++, ii++) - { - if (NONZEROMETRICS(&ii->metrics)) - { - ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); - ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); - ci->metrics.ascent = FONT_MAX_ASCENT(fi); - ci->metrics.descent = FONT_MAX_DESCENT(fi); - ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); - ci->metrics.attributes = ii->metrics.attributes; - } - else - { - ci->metrics = ii->metrics; - } - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) " - "> maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) " - "> maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - } - } - { - unsigned int r, c, numCols, firstCol; - - firstCol = bfont->pfont->info.firstCol; - numCols = bfont->pfont->info.lastCol - firstCol + 1; - c = bfont->pfont->info.defaultCh; - fsfont->pDefault = 0; - if (bfont->pfont->info.lastRow) - { - r = c >> 8; - r -= bfont->pfont->info.firstRow; - c &= 0xff; - c -= firstCol; - if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && - c < numCols) - fsfont->pDefault = &pCI[r * numCols + c]; - } - else - { - c -= firstCol; - if (c < numCols) - fsfont->pDefault = &pCI[c]; - } - } - bfont->state = FS_GLYPHS_REPLY; - - if (bfont->flags & FontLoadBitmaps) - { - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryBitmapsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - return StillWorking; - } - return Successful; -} - -#ifdef DEBUG -static char *fs_open_states[] = { - "OPEN_REPLY ", - "INFO_REPLY ", - "EXTENT_REPLY", - "GLYPHS_REPLY", - "DONE_REPLY ", - "DEPENDING ", -}; -#endif - -static int -fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - int err; - -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font state %s %s\n", - fs_open_states[bfont->state], - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); -#endif - err = BadFontName; - switch (bfont->state) { - case FS_OPEN_REPLY: - err = fs_read_open_font(fpe, blockrec); - if (err != StillWorking) { /* already loaded, or error */ - /* if font's already loaded, massage error code */ - switch (bfont->state) { - case FS_DONE_REPLY: - err = Successful; - break; - case FS_DEPENDING: - err = StillWorking; - break; - } - } - break; - case FS_INFO_REPLY: - err = fs_read_query_info(fpe, blockrec); - break; - case FS_EXTENT_REPLY: - err = fs_read_extent_info(fpe, blockrec); - break; - case FS_GLYPHS_REPLY: - if (bfont->flags & FontLoadBitmaps) - err = fs_read_glyphs(fpe, blockrec); - break; - case FS_DEPENDING: /* can't happen */ - default: - break; - } -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font err %d\n", err); -#endif - if (err != StillWorking) - { - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - while ((blockrec = blockrec->depending)) - { - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - } - } - return err; -} - -void -_fs_mark_block (FSFpePtr conn, CARD32 mask) -{ - conn->blockState |= mask; - fs_blockState |= mask; -} - -void -_fs_unmark_block (FSFpePtr conn, CARD32 mask) -{ - FSFpePtr c; - - if (conn->blockState & mask) - { - conn->blockState &= ~mask; - fs_blockState = 0; - for (c = fs_fpes; c; c = c->next) - fs_blockState |= c->blockState; - } -} - -/* ARGSUSED */ -static void -fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) -{ - static struct timeval block_timeout; - CARD32 now, earliest, wakeup; - int soonest; - FSFpePtr conn; - - XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, - &_fs_fd_mask); - /* - * Flush all pending output - */ - if (fs_blockState & FS_PENDING_WRITE) - for (conn = fs_fpes; conn; conn = conn->next) - if (conn->blockState & FS_PENDING_WRITE) - _fs_flush (conn); - /* - * Check for any fpe with a complete reply, set sleep time to zero - */ - if (fs_blockState & FS_COMPLETE_REPLY) - { - block_timeout.tv_sec = 0; - block_timeout.tv_usec = 0; - if (*wt == NULL) - *wt = &block_timeout; - else - **wt = block_timeout; - } - /* - * Walk through fpe list computing sleep time - */ - else if (fs_blockState & (FS_BROKEN_WRITE| - FS_BROKEN_CONNECTION| - FS_PENDING_REPLY| - FS_RECONNECTING)) - { - now = GetTimeInMillis (); - earliest = now + 10000000; - for (conn = fs_fpes; conn; conn = conn->next) - { - if (conn->blockState & FS_RECONNECTING) - { - wakeup = conn->blockedConnectTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_CONNECTION) - { - wakeup = conn->brokenConnectionTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_WRITE) - { - wakeup = conn->brokenWriteTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_PENDING_REPLY) - { - wakeup = conn->blockedReplyTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - } - soonest = earliest - now; - if (soonest < 0) - soonest = 0; - block_timeout.tv_sec = soonest / 1000; - block_timeout.tv_usec = (soonest % 1000) * 1000; - if (*wt == NULL) - *wt = &block_timeout; - else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) - **wt = block_timeout; - } -} - -static void -fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) -{ - if (rep->type == FS_Event && rep->data1 == KeepAlive) - { - fsNoopReq req; - - /* ping it back */ - req.reqType = FS_Noop; - req.length = SIZEOF(fsNoopReq) >> 2; - _fs_add_req_log(conn, FS_Noop); - _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); - } - /* this should suck up unexpected replies and events */ - _fs_done_read (conn, rep->length << 2); -} - -static void -fs_read_reply (FontPathElementPtr fpe, pointer client) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int ret; - int err; - fsGenericReply *rep; - - if ((rep = fs_get_reply (conn, &ret))) - { - _fs_add_rep_log (conn, rep); - for (blockrec = conn->blockedRequests; - blockrec; - blockrec = blockrec->next) - { - if (blockrec->sequenceNumber == rep->sequenceNumber) - break; - } - err = Successful; - if (!blockrec) - { - fs_handle_unexpected(conn, rep); - } - else - { - /* - * go read it, and if we're done, - * wake up the appropriate client - */ - switch (blockrec->type) { - case FS_OPEN_FONT: - blockrec->errcode = fs_do_open_font(fpe, blockrec); - break; - case FS_LOAD_GLYPHS: - blockrec->errcode = fs_read_glyphs(fpe, blockrec); - break; - case FS_LIST_FONTS: - blockrec->errcode = fs_read_list(fpe, blockrec); - break; - case FS_LIST_WITH_INFO: - blockrec->errcode = fs_read_list_info(fpe, blockrec); - break; - default: - break; - } - err = blockrec->errcode; - if (err != StillWorking) - { - while (blockrec) - { - blockrec->errcode = err; - if (client != blockrec->client) - ClientSignal(blockrec->client); - blockrec = blockrec->depending; - } - _fs_unmark_block (conn, FS_PENDING_REPLY); - } - } - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - else - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - } -} - -static int -fs_wakeup(FontPathElementPtr fpe, unsigned long *mask) -{ - fd_set *LastSelectMask = (fd_set *) mask; - FSFpePtr conn = (FSFpePtr) fpe->private; - - /* - * Don't continue if the fd is -1 (which will be true when the - * font server terminates - */ - if ((conn->blockState & FS_RECONNECTING)) - _fs_check_reconnect (conn); - else if ((conn->blockState & FS_COMPLETE_REPLY) || - (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) - fs_read_reply (fpe, 0); - if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) - _fs_do_blocked (conn); -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - FSBlockedListPtr blist; - static CARD32 lastState; - static FSBlockDataPtr lastBlock; - - if (conn->blockState || conn->blockedRequests || lastState || lastBlock) - { - fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); - lastState = conn->blockState; - lastBlock = conn->blockedRequests; - } - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - switch (blockrec->type) { - case FS_OPEN_FONT: - bfont = (FSBlockedFontPtr) blockrec->data; - fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", - blockrec->errcode, - blockrec->sequenceNumber, - fs_open_states[bfont->state], - bfont->pfont ? - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : - ""); - break; - case FS_LIST_FONTS: - blist = (FSBlockedListPtr) blockrec->data; - fprintf (stderr, " Blocked list errcode %d sequence %d\n", - blockrec->errcode, blockrec->sequenceNumber); - break; - default: - fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", - blockrec->type, - blockrec->errcode, - blockrec->sequenceNumber); - break; - } - } - } -#endif - return FALSE; -} - -/* - * Notice a dead connection and prepare for reconnect - */ - -void -_fs_connection_died(FSFpePtr conn) -{ - if (conn->blockState & FS_BROKEN_CONNECTION) - return; - fs_close_conn(conn); - conn->brokenConnectionTime = GetTimeInMillis (); - _fs_mark_block (conn, FS_BROKEN_CONNECTION); - _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); -} - -/* - * Signal clients that the connection has come back up - */ -static int -_fs_restart_connection(FSFpePtr conn) -{ - FSBlockDataPtr block; - - _fs_unmark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal(block->client); - fs_abort_blockrec(conn, block); - } - } - return TRUE; -} - -/* - * Declare this font server connection useless - */ -static void -_fs_giveup (FSFpePtr conn) -{ - FSBlockDataPtr block; - - if (conn->blockState & FS_GIVE_UP) - return; -#ifdef DEBUG - fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); -#endif - _fs_mark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal (block->client); - fs_abort_blockrec (conn, block); - } - } - if (conn->fs_fd >= 0) - _fs_connection_died (conn); -} - -static void -_fs_do_blocked (FSFpePtr conn) -{ - CARD32 now; - - now = GetTimeInMillis (); - if ((conn->blockState & FS_PENDING_REPLY) && - TimeCmp (conn->blockedReplyTime, <=, now)) - { - _fs_giveup (conn); - } - else - { - if (conn->blockState & FS_BROKEN_CONNECTION) - { - /* Try to reconnect broken connections */ - if (TimeCmp (conn->brokenConnectionTime, <=, now)) - _fs_start_reconnect (conn); - } - else if (conn->blockState & FS_BROKEN_WRITE) - { - /* Try to flush blocked connections */ - if (TimeCmp (conn->brokenWriteTime, <=, now)) - _fs_flush (conn); - } - } -} - -/* - * sends the actual request out - */ -/* ARGSUSED */ -static int -fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr font; - FSBlockDataPtr blockrec = NULL; - FSBlockedFontPtr bfont; - FSFontDataPtr fsd; - fsOpenBitmapFontReq openreq; - fsQueryXInfoReq inforeq; - fsQueryXExtents16Req extreq; - int err; - unsigned char buf[1024]; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - if (namelen <= 0 || namelen > sizeof (buf) - 1) - return BadFontName; - - /* - * Get the font structure put together, either by reusing - * the existing one or creating a new one - */ - if (flags & FontReopen) - { - Atom nameatom, fn = None; - int i; - - font = *ppfont; - fsd = (FSFontDataPtr)font->fpePrivate; - /* This is an attempt to reopen a font. Did the font have a - NAME property? */ - if ((nameatom = MakeAtom("FONT", 4, 0)) != None) - { - for (i = 0; i < font->info.nprops; i++) - if (font->info.props[i].name == nameatom && - font->info.isStringProp[i]) - { - fn = font->info.props[i].value; - break; - } - } - if (fn == None || !(name = NameForAtom(fn))) - { - name = fsd->name; - namelen = fsd->namelen; - } - else - namelen = strlen(name); - } - else - { - font = fs_create_font (fpe, name, namelen, format, fmask); - if (!font) - return AllocError; - - fsd = (FSFontDataPtr)font->fpePrivate; - } - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); - if (!blockrec) - { - if (!(flags & FontReopen)) - (*font->unload_font) (font); - return AllocError; - } - - /* - * Must check this before generating any protocol, otherwise we'll - * mess up a reconnect in progress - */ - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - fsd->generation = conn->generation; - - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->fontid = fsd->fontid; - bfont->pfont = font; - bfont->state = FS_OPEN_REPLY; - bfont->flags = flags; - bfont->format = fsd->format; - bfont->clients_depending = (FSClientsDependingPtr)0; - bfont->freeFont = (flags & FontReopen) == 0; - - _fs_client_access (conn, client, (flags & FontOpenSync) != 0); - _fs_client_resolution(conn); - - /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ - buf[0] = (unsigned char) namelen; - memcpy(&buf[1], name, namelen); - openreq.reqType = FS_OpenBitmapFont; - openreq.pad = 0; - openreq.fid = fsd->fontid; - openreq.format_hint = fsd->format; - openreq.format_mask = fsd->fmask; - openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; - - _fs_add_req_log(conn, FS_OpenBitmapFont); - _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); - _fs_write_pad(conn, (char *) buf, namelen + 1); - - blockrec->sequenceNumber = conn->current_seq; - - inforeq.reqType = FS_QueryXInfo; - inforeq.pad = 0; - inforeq.id = fsd->fontid; - inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; - - bfont->queryInfoSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXInfo); - _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); - - if (!(bfont->flags & FontReopen)) - { - extreq.reqType = FS_QueryXExtents16; - extreq.range = fsTrue; - extreq.fid = fsd->fontid; - extreq.num_ranges = 0; - extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; - - bfont->queryExtentsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXExtents16); - _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); - } - -#ifdef NCD - if (configData.ExtendedFontDiags) - { - memcpy(buf, name, MIN(256, namelen)); - buf[MIN(256, namelen)] = '\0'; - printf("Requesting font \"%s\" from font server \"%s\"\n", - buf, font->fpe->name); - } -#endif - _fs_prepare_for_reply (conn); - - err = blockrec->errcode; - if (bfont->flags & FontOpenSync) - { - while (blockrec->errcode == StillWorking) - { - if (fs_await_reply (conn) != FSIO_READY) - { - blockrec->errcode = BadFontName; - break; - } - fs_read_reply (font->fpe, client); - } - err = blockrec->errcode; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - bfont->freeFont = FALSE; - _fs_remove_block_rec (conn, blockrec); - } - return err == StillWorking ? Suspended : err; -} - -static void -fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsQueryXBitmaps16Req bitreq; - - /* send the request */ - bitreq.reqType = FS_QueryXBitmaps16; - bitreq.fid = bfont->fontid; - bitreq.format = bfont->format; - bitreq.range = TRUE; - bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; - bitreq.num_ranges = 0; - - bfont->queryBitmapsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); -} - -/* ARGSUSED */ -static int -fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont, - char **alias, FontPtr non_cachable_font) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - int err; - - /* libfont interface expects ImageRectMin glyphs */ - format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; - - *alias = (char *) 0; - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - bfont = (FSBlockedFontPtr) blockrec->data; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - _fs_remove_block_rec (conn, blockrec); - return err; - } - } - return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, - id, ppfont); -} - -/* ARGSUSED */ -static int -fs_send_close_font(FontPathElementPtr fpe, Font id) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - fsCloseReq req; - - if (conn->blockState & FS_GIVE_UP) - return Successful; - /* tell the font server to close the font */ - req.reqType = FS_CloseFont; - req.pad = 0; - req.length = SIZEOF(fsCloseReq) >> 2; - req.id = id; - _fs_add_req_log(conn, FS_CloseFont); - _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); - - return Successful; -} - -/* ARGSUSED */ -static void -fs_close_font(FontPathElementPtr fpe, FontPtr pfont) -{ - FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; - FSFpePtr conn = (FSFpePtr) fpe->private; - - if (conn->generation == fsd->generation) - fs_send_close_font(fpe, fsd->fontid); - -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT) - { - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - fprintf (stderr, "closing font which hasn't been opened\n"); - } - } - } -#endif - (*pfont->unload_font) (pfont); -} - -static int -fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr pfont = bglyph->pfont; - /* works for either blocked font - or glyph rec... pfont is at - the very beginning of both - blockrec->data structures */ - FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); - FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; - FontInfoPtr pfi = &pfont->info; - fsQueryXBitmaps16Reply *rep; - char *buf; - fsOffset32 *ppbits; - fsOffset32 local_off; - char *off_adr; - pointer pbitmaps; - char *bits, *allbits; -#ifdef DEBUG - char *origallbits; -#endif - int i, - err; - int nranges = 0; - int ret; - fsRange *nextrange = 0; - unsigned long minchar, maxchar; - - rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - err = AllocError; - goto bail; - } - - buf = (char *) rep; - buf += SIZEOF (fsQueryXBitmaps16Reply); - - ppbits = (fsOffset32 *) buf; - buf += SIZEOF (fsOffset32) * (rep->num_chars); - - pbitmaps = (pointer ) buf; - - if (blockrec->type == FS_LOAD_GLYPHS) - { - nranges = bglyph->num_expected_ranges; - nextrange = bglyph->expected_ranges; - } - - /* place the incoming glyphs */ - if (nranges) - { - /* We're operating under the assumption that the ranges - requested in the LoadGlyphs call were all legal for this - font, and that individual ranges do not cover multiple - rows... fs_build_range() is designed to ensure this. */ - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - else - { - minchar = 0; - maxchar = rep->num_chars; - } - - off_adr = (char *)ppbits; - - allbits = fs_alloc_glyphs (pfont, rep->nbytes); - - if (!allbits) - { - err = AllocError; - goto bail; - } - -#ifdef DEBUG - origallbits = allbits; - fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", - (int) rep->num_chars, (int) rep->nbytes, fsd->name); -#endif - - for (i = 0; i < rep->num_chars; i++) - { - memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ - if (blockrec->type == FS_OPEN_FONT || - fsdata->encoding[minchar].bits == &_fs_glyph_requested) - { - /* - * Broken X font server returns bits for missing characters - * when font is padded - */ - if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) - { - if (local_off.length) - { - bits = allbits; - allbits += local_off.length; - memcpy(bits, (char *)pbitmaps + local_off.position, - local_off.length); - } - else - bits = &_fs_glyph_zero_length; - } - else - bits = 0; - if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) - fsd->glyphs_to_get--; - fsdata->encoding[minchar].bits = bits; - } - if (minchar++ == maxchar) - { - if (!--nranges) break; - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - off_adr += SIZEOF(fsOffset32); - } -#ifdef DEBUG - fprintf (stderr, "Used %d bytes instead of %d\n", - (int) (allbits - origallbits), (int) rep->nbytes); -#endif - - if (blockrec->type == FS_OPEN_FONT) - { - fsd->glyphs_to_get = 0; - bfont->state = FS_DONE_REPLY; - } - err = Successful; - -bail: - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_load_glyphs(pointer client, FontPtr pfont, - int nranges, fsRange *ranges) -{ - FontPathElementPtr fpe = pfont->fpe; - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedGlyphPtr blockedglyph; - fsQueryXBitmaps16Req req; - FSBlockDataPtr blockrec; - - if (conn->blockState & FS_GIVE_UP) - return BadCharRange; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); - if (!blockrec) - return AllocError; - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - blockedglyph->pfont = pfont; - blockedglyph->num_expected_ranges = nranges; - /* Assumption: it's our job to free ranges */ - blockedglyph->expected_ranges = ranges; - blockedglyph->clients_depending = (FSClientsDependingPtr)0; - - if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - /* send the request */ - req.reqType = FS_QueryXBitmaps16; - req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; - req.format = pfont->format; - if (pfont->info.terminalFont) - req.format = (req.format & ~(BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax; - req.range = TRUE; - /* each range takes up 4 bytes */ - req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; - req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); - - blockrec->sequenceNumber = conn->current_seq; - - /* Send ranges to the server... pack into a char array by hand - to avoid structure-packing portability problems and to - handle swapping for version1 protocol */ - if (nranges) - { -#define RANGE_BUFFER_SIZE 64 -#define RANGE_BUFFER_SIZE_MASK 63 - int i; - char range_buffer[RANGE_BUFFER_SIZE * 4]; - char *range_buffer_p; - - range_buffer_p = range_buffer; - for (i = 0; i < nranges;) - { - if (conn->fsMajorVersion > 1) - { - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - } - else - { - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - } - - if (!(++i & RANGE_BUFFER_SIZE_MASK)) - { - _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); - range_buffer_p = range_buffer; - } - } - if (i &= RANGE_BUFFER_SIZE_MASK) - _fs_write(conn, range_buffer, i * 4); - } - - _fs_prepare_for_reply (conn); - return Suspended; -} - - -extern pointer serverClient; /* This could be any number that - doesn't conflict with existing - client values. */ - -static int -_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, - unsigned int nchars, int item_size, unsigned char *data) -{ - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - int nranges = 0; - fsRange *ranges = NULL; - int res; - FSBlockDataPtr blockrec; - FSBlockedGlyphPtr blockedglyph; - FSClientsDependingPtr *clients_depending = NULL; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LOAD_GLYPHS) - { - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - if (blockedglyph->pfont == pfont) - { - /* Look for this request */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_signal_clients_depending(&blockedglyph->clients_depending); - _fs_remove_block_rec(conn, blockrec); - return err; - } - /* We've found an existing LoadGlyphs blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing LoadGlyphs is - completed. */ - clients_depending = &blockedglyph->clients_depending; - break; - } - } - else if (blockrec->type == FS_OPEN_FONT) - { - FSBlockedFontPtr bfont; - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - { - /* - * An OpenFont is pending for this font, this must - * be from a reopen attempt, so finish the open - * attempt and retry the LoadGlyphs - */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - _fs_signal_clients_depending(&bfont->clients_depending); - _fs_remove_block_rec(conn, blockrec); - if (err != Successful) - return err; - break; - } - /* We've found an existing OpenFont blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing OpenFont is - completed. */ - if (blockrec->errcode == StillWorking) - { - clients_depending = &bfont->clients_depending; - break; - } - } - } - } - - /* - * see if the desired glyphs already exist, and return Successful if they - * do, otherwise build up character range/character string - */ - res = fs_build_range(pfont, range_flag, nchars, item_size, data, - &nranges, &ranges); - - switch (res) - { - case AccessDone: - return Successful; - - case Successful: - break; - - default: - return res; - } - - /* - * If clients_depending is not null, this request must wait for - * some prior request(s) to complete. - */ - if (clients_depending) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage (if any) caused by the fs_build_range() - call. */ - if (nranges) - { - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - free(ranges); - } - return _fs_add_clients_depending(clients_depending, client); - } - - /* - * If fsd->generation != conn->generation, the font has been closed - * due to a lost connection. We will reopen it, which will result - * in one of three things happening: - * 1) The open will succeed and obtain the same font. Life - * is wonderful. - * 2) The open will fail. There is code above to recognize this - * and flunk the LoadGlyphs request. The client might not be - * thrilled. - * 3) Worst case: the open will succeed but the font we open will - * be different. The fs_read_query_info() procedure attempts - * to detect this by comparing the existing metrics and - * properties against those of the reopened font... if they - * don't match, we flunk the reopen, which eventually results - * in flunking the LoadGlyphs request. We could go a step - * further and compare the extents, but this should be - * sufficient. - */ - if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage caused by the fs_build_range() call. */ - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - free(ranges); - - /* Now try to reopen the font. */ - return fs_send_open_font(client, pfont->fpe, - (Mask)FontReopen, (char *)0, 0, - (fsBitmapFormat)0, (fsBitmapFormatMask)0, - (XID)0, &pfont); - } - - return fs_send_load_glyphs(client, pfont, nranges, ranges); -} - -int -fs_load_all_glyphs(FontPtr pfont) -{ - int err; - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - - /* - * The purpose of this procedure is to load all glyphs in the event - * that we're dealing with someone who doesn't understand the finer - * points of glyph caching... it is called from _fs_get_glyphs() if - * the latter is called to get glyphs that have not yet been loaded. - * We assume that the caller will not know how to handle a return - * value of Suspended (usually the case for a GetGlyphs() caller), - * so this procedure hangs around, freezing the server, for the - * request to complete. This is an unpleasant kluge called to - * perform an unpleasant job that, we hope, will never be required. - */ - - while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == - Suspended) - { - if (fs_await_reply (conn) != FSIO_READY) - { - /* Get rid of blockrec */ - fs_client_died(serverClient, pfont->fpe); - err = BadCharRange; - break; - } - fs_read_reply (pfont->fpe, serverClient); - } - return err; -} - -static int -fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; - fsListFontsReply *rep; - char *data; - int length, - i, - ret; - int err; - - rep = (fsListFontsReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - return AllocError; - } - data = (char *) rep + SIZEOF (fsListFontsReply); - - err = Successful; - /* copy data into FontPathRecord */ - for (i = 0; i < rep->nFonts; i++) - { - length = *(unsigned char *)data++; - err = AddFontNamesName(blist->names, data, length); - if (err != Successful) - break; - data += length; - } - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, - int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListPtr blockedlist; - fsListFontsReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); - if (!blockrec) - return AllocError; - blockedlist = (FSBlockedListPtr) blockrec->data; - blockedlist->names = newnames; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFonts; - req.pad = 0; - req.maxNames = maxnames; - req.nbytes = patlen; - req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; - _fs_add_req_log(conn, FS_ListFonts); - _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); - _fs_write_pad(conn, (char *) pattern, patlen); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, patlen)); - buf[MIN(256, patlen)] = '\0'; - printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Suspended; -} - -static int -fs_list_fonts(pointer client, FontPathElementPtr fpe, - char *pattern, int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_remove_block_rec(conn, blockrec); - return err; - } - } - - /* didn't find waiting record, so send a new one */ - return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); -} - -/* - * Read a single list info reply and restart for the next reply - */ -static int -fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; - fsListFontsWithXInfoReply *rep; - char *buf; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - int ret; - int err; - - /* clean up anything from the last trip */ - _fs_free_props (&binfo->info); - - rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error) - { - if (ret == FSIO_BLOCK) - return StillWorking; - binfo->status = FS_LFWI_FINISHED; - err = AllocError; - goto done; - } - /* - * Normal termination -- the list ends with a name of length 0 - */ - if (rep->nameLength == 0) - { -#ifdef DEBUG - fprintf (stderr, "fs_read_list_info done\n"); -#endif - binfo->status = FS_LFWI_FINISHED; - err = BadFontName; - goto done; - } - - buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); - - /* - * The original FS implementation didn't match - * the spec, version 1 was respecified to match the FS. - * Version 2 matches the original intent - */ - if (conn->fsMajorVersion <= 1) - { - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - } - pi = (fsPropInfo *) buf; - buf += SIZEOF (fsPropInfo); - po = (fsPropOffset *) buf; - buf += pi->num_offsets * SIZEOF (fsPropOffset); - pd = (pointer) buf; - buf += pi->data_len; - if (conn->fsMajorVersion > 1) - { - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - } - -#ifdef DEBUG - binfo->name[rep->nameLength] = '\0'; - fprintf (stderr, "fs_read_list_info %s\n", binfo->name); -#endif - err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); - if (err != Successful) - { - binfo->status = FS_LFWI_FINISHED; - goto done; - } - binfo->namelen = rep->nameLength; - binfo->remaining = rep->nReplies; - - binfo->status = FS_LFWI_REPLY; - - /* disable this font server until we've processed this response */ - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - FD_CLR(conn->fs_fd, &_fs_fd_mask); -done: - _fs_done_read (conn, rep->length << 2); - return err; -} - -/* ARGSUSED */ -static int -fs_start_list_with_info(pointer client, FontPathElementPtr fpe, - char *pattern, int len, int maxnames, pointer *pdata) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - fsListFontsWithXInfoReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); - if (!blockrec) - return AllocError; - - binfo = (FSBlockedListInfoPtr) blockrec->data; - bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); - binfo->status = FS_LFWI_WAITING; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFontsWithXInfo; - req.pad = 0; - req.maxNames = maxnames; - req.nbytes = len; - req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; - _fs_add_req_log(conn, FS_ListFontsWithXInfo); - (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); - (void) _fs_write_pad(conn, pattern, len); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, len)); - buf[MIN(256, len)] = '\0'; - printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Successful; -} - -/* ARGSUSED */ -static int -fs_next_list_with_info(pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, - FontInfoPtr *pFontInfo, int *numFonts, - pointer private) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) - break; - - if (!blockrec) - { - /* The only good reason for not finding a blockrec would be if - disconnect/reconnect to the font server wiped it out and the - code that called us didn't do the right thing to create - another one. Under those circumstances, we need to return an - error to prevent that code from attempting to interpret the - information we don't return. */ - return BadFontName; - } - - binfo = (FSBlockedListInfoPtr) blockrec->data; - - if (binfo->status == FS_LFWI_WAITING) - return Suspended; - - *namep = binfo->name; - *namelenp = binfo->namelen; - *pFontInfo = &binfo->info; - *numFonts = binfo->remaining; - - /* Restart reply processing from this font server */ - FD_SET(conn->fs_fd, &_fs_fd_mask); - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - - err = blockrec->errcode; - switch (binfo->status) { - case FS_LFWI_FINISHED: - _fs_remove_block_rec(conn, blockrec); - break; - case FS_LFWI_REPLY: - binfo->status = FS_LFWI_WAITING; - blockrec->errcode = StillWorking; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - break; - } - - return err; -} - -/* - * Called when client exits - */ - -static void -fs_client_died(pointer client, FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec, - depending; - FSClientPtr *prev, cur; - fsFreeACReq freeac; - - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) { - freeac.reqType = FS_FreeAC; - freeac.pad = 0; - freeac.id = cur->acid; - freeac.length = sizeof (fsFreeACReq) >> 2; - _fs_add_req_log(conn, FS_FreeAC); - _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); - *prev = cur->next; - free (cur); - break; - } - } - /* find a pending requests */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->client == client) - break; - - if (!blockrec) - return; - - /* replace the client pointers in this block rec with the chained one */ - if ((depending = blockrec->depending)) - { - blockrec->client = depending->client; - blockrec->depending = depending->depending; - blockrec = depending; - } - fs_abort_blockrec(conn, blockrec); -} - -static void -_fs_client_access (FSFpePtr conn, pointer client, Bool sync) -{ - FSClientPtr *prev, cur; - fsCreateACReq crac; - fsSetAuthorizationReq setac; - char *authorizations; - int authlen; - Bool new_cur = FALSE; - char padding[4] = { 0, 0, 0, 0 }; - -#ifdef DEBUG - if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) - { - fprintf (stderr, "Sending requests without a connection\n"); - } -#endif - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) - { - if (prev != &conn->clients) - { - *prev = cur->next; - cur->next = conn->clients; - conn->clients = cur; - } - break; - } - } - if (!cur) - { - cur = malloc (sizeof (FSClientRec)); - if (!cur) - return; - cur->client = client; - cur->next = conn->clients; - conn->clients = cur; - cur->acid = GetNewFontClientID (); - new_cur = TRUE; - } - if (new_cur || cur->auth_generation != client_auth_generation(client)) - { - if (!new_cur) - { - fsFreeACReq freeac; - freeac.reqType = FS_FreeAC; - freeac.pad = 0; - freeac.id = cur->acid; - freeac.length = sizeof (fsFreeACReq) >> 2; - _fs_add_req_log(conn, FS_FreeAC); - _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); - } - crac.reqType = FS_CreateAC; - crac.num_auths = set_font_authorizations(&authorizations, &authlen, - client); - /* Work around bug in xfs versions up through modular release 1.0.8 - which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ - if (crac.num_auths == 0) { - authorizations = padding; - authlen = 4; - } else { - authlen = (authlen + 3) & ~0x3; - } - crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; - crac.acid = cur->acid; - _fs_add_req_log(conn, FS_CreateAC); - _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); - _fs_write(conn, authorizations, authlen); - /* ignore reply; we don't even care about it */ - conn->curacid = 0; - cur->auth_generation = client_auth_generation(client); - } - if (conn->curacid != cur->acid) - { - setac.reqType = FS_SetAuthorization; - setac.pad = 0; - setac.length = sizeof (fsSetAuthorizationReq) >> 2; - setac.id = cur->acid; - _fs_add_req_log(conn, FS_SetAuthorization); - _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); - conn->curacid = cur->acid; - } -} - -/* - * Poll a pending connect - */ - -static int -_fs_check_connect (FSFpePtr conn) -{ - int ret; - - ret = _fs_poll_connect (conn->trans_conn, 0); - switch (ret) { - case FSIO_READY: - conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); - FD_SET (conn->fs_fd, &_fs_fd_mask); - break; - case FSIO_BLOCK: - break; - } - return ret; -} - -/* - * Return an FSIO status while waiting for the completed connection - * reply to arrive - */ - -static fsConnSetup * -_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) -{ - int ret; - char *data; - int headlen; - int len; - fsConnSetup *setup; - fsConnSetupAccept *accept; - - ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - - setup = (fsConnSetup *) data; - if (setup->major_version > FS_PROTOCOL) - { - *error = FSIO_ERROR; - return 0; - } - - headlen = (SIZEOF (fsConnSetup) + - (setup->alternate_len << 2) + - (setup->auth_len << 2)); - /* On anything but Success, no extra data is sent */ - if (setup->status != AuthSuccess) - { - len = headlen; - } - else - { - ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - setup = (fsConnSetup *) data; - accept = (fsConnSetupAccept *) (data + headlen); - len = headlen + (accept->length << 2); - } - ret = _fs_start_read (conn, len, &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - *setup_len = len; - return (fsConnSetup *) data; -} - -static int -_fs_send_conn_client_prefix (FSFpePtr conn) -{ - fsConnClientPrefix req; - int endian; - int ret; - - /* send setup prefix */ - endian = 1; - if (*(char *) &endian) - req.byteOrder = 'l'; - else - req.byteOrder = 'B'; - - req.major_version = FS_PROTOCOL; - req.minor_version = FS_PROTOCOL_MINOR; - -/* XXX add some auth info here */ - req.num_auths = 0; - req.auth_len = 0; - ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); - if (ret != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return ret; -} - -static int -_fs_recv_conn_setup (FSFpePtr conn) -{ - int ret = FSIO_ERROR; - fsConnSetup *setup; - FSFpeAltPtr alts; - int i, alt_len; - int setup_len; - char *alt_save, *alt_names; - - setup = _fs_get_conn_setup (conn, &ret, &setup_len); - if (!setup) - return ret; - conn->current_seq = 0; - conn->fsMajorVersion = setup->major_version; - /* - * Create an alternate list from the initial server, but - * don't chain looking for alternates. - */ - if (conn->alternate == 0) - { - /* - * free any existing alternates list, allowing the list to - * be updated - */ - if (conn->alts) - { - free (conn->alts); - conn->alts = 0; - conn->numAlts = 0; - } - if (setup->num_alternates) - { - alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + - (setup->alternate_len << 2)); - if (alts) - { - alt_names = (char *) (setup + 1); - alt_save = (char *) (alts + setup->num_alternates); - for (i = 0; i < setup->num_alternates; i++) - { - alts[i].subset = alt_names[0]; - alt_len = alt_names[1]; - alts[i].name = alt_save; - memcpy (alt_save, alt_names + 2, alt_len); - alt_save[alt_len] = '\0'; - alt_save += alt_len + 1; - alt_names += _fs_pad_length (alt_len + 2); - } - conn->numAlts = setup->num_alternates; - conn->alts = alts; - } - } - } - _fs_done_read (conn, setup_len); - if (setup->status != AuthSuccess) - return FSIO_ERROR; - return FSIO_READY; -} - -static int -_fs_open_server (FSFpePtr conn) -{ - int ret; - char *servername; - - if (conn->alternate == 0) - servername = conn->servername; - else - servername = conn->alts[conn->alternate-1].name; - conn->trans_conn = _fs_connect (servername, &ret); - conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; - return ret; -} - -static char * -_fs_catalog_name (char *servername) -{ - char *sp; - - sp = strchr (servername, '/'); - if (!sp) - return 0; - return strrchr (sp + 1, '/'); -} - -static int -_fs_send_init_packets (FSFpePtr conn) -{ - fsSetResolutionReq srreq; - fsSetCataloguesReq screq; - int num_cats, - clen; - char *catalogues; - char *cat; - char len; - char *end; - int num_res; - FontResolutionPtr res; - -#define CATALOGUE_SEP '+' - - res = GetClientResolutions(&num_res); - if (num_res) - { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) - return FSIO_ERROR; - } - - catalogues = 0; - if (conn->alternate != 0) - catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); - if (!catalogues) - catalogues = _fs_catalog_name (conn->servername); - - if (!catalogues) - { - conn->has_catalogues = FALSE; - return FSIO_READY; - } - conn->has_catalogues = TRUE; - - /* turn cats into counted list */ - catalogues++; - - cat = catalogues; - num_cats = 0; - clen = 0; - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - clen += (end - cat) + 1; /* length byte + string */ - cat = end; - } - - screq.reqType = FS_SetCatalogues; - screq.num_catalogues = num_cats; - screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; - - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - len = end - cat; - if (_fs_write (conn, &len, 1) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write (conn, cat, (int) len) != FSIO_READY) - return FSIO_ERROR; - cat = end; - } - - if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) - return FSIO_ERROR; - - return FSIO_READY; -} - -static int -_fs_send_cat_sync (FSFpePtr conn) -{ - fsListCataloguesReq lcreq; - - /* - * now sync up with the font server, to see if an error was generated - * by a bogus catalogue - */ - lcreq.reqType = FS_ListCatalogues; - lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; - lcreq.maxNames = 0; - lcreq.nbytes = 0; - lcreq.pad2 = 0; - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return FSIO_READY; -} - -static int -_fs_recv_cat_sync (FSFpePtr conn) -{ - fsGenericReply *reply; - fsError *error; - int err; - int ret; - - reply = fs_get_reply (conn, &err); - if (!reply) - return err; - - ret = FSIO_READY; - if (reply->type == FS_Error) - { - error = (fsError *) reply; - if (error->major_opcode == FS_SetCatalogues) - ret = FSIO_ERROR; - } - _fs_done_read (conn, reply->length << 2); - return ret; -} - -static void -_fs_close_server (FSFpePtr conn) -{ - _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); - if (conn->trans_conn) - { - _FontTransClose (conn->trans_conn); - conn->trans_conn = 0; - _fs_io_reinit (conn); - } - if (conn->fs_fd >= 0) - { - FD_CLR (conn->fs_fd, &_fs_fd_mask); - conn->fs_fd = -1; - } - conn->fs_conn_state = FS_CONN_UNCONNECTED; -} - -static int -_fs_do_setup_connection (FSFpePtr conn) -{ - int ret; - - do - { -#ifdef DEBUG - fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); -#endif - switch (conn->fs_conn_state) { - case FS_CONN_UNCONNECTED: - ret = _fs_open_server (conn); - if (ret == FSIO_BLOCK) - conn->fs_conn_state = FS_CONN_CONNECTING; - break; - case FS_CONN_CONNECTING: - ret = _fs_check_connect (conn); - break; - case FS_CONN_CONNECTED: - ret = _fs_send_conn_client_prefix (conn); - break; - case FS_CONN_SENT_PREFIX: - ret = _fs_recv_conn_setup (conn); - break; - case FS_CONN_RECV_INIT: - ret = _fs_send_init_packets (conn); - if (conn->has_catalogues) - ret = _fs_send_cat_sync (conn); - break; - case FS_CONN_SENT_CAT: - if (conn->has_catalogues) - ret = _fs_recv_cat_sync (conn); - else - ret = FSIO_READY; - break; - default: - ret = FSIO_READY; - break; - } - switch (ret) { - case FSIO_READY: - if (conn->fs_conn_state < FS_CONN_RUNNING) - conn->fs_conn_state++; - break; - case FSIO_BLOCK: - if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) - break; - ret = FSIO_ERROR; - /* fall through... */ - case FSIO_ERROR: - _fs_close_server (conn); - /* - * Try the next alternate - */ - if (conn->alternate < conn->numAlts) - { - conn->alternate++; - ret = FSIO_READY; - } - else - conn->alternate = 0; - break; - } - } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); - if (ret == FSIO_READY) - conn->generation = ++generationCount; - return ret; -} - -static int -_fs_wait_connect (FSFpePtr conn) -{ - int ret; - - for (;;) - { - ret = _fs_do_setup_connection (conn); - if (ret != FSIO_BLOCK) - break; - if (conn->fs_conn_state <= FS_CONN_CONNECTING) - ret = _fs_poll_connect (conn->trans_conn, 1000); - else - ret = _fs_wait_for_readable (conn, 1000); - if (ret == FSIO_ERROR) - break; - } - return ret; -} - -/* - * Poll a connection in the process of reconnecting - */ -static void -_fs_check_reconnect (FSFpePtr conn) -{ - int ret; - - ret = _fs_do_setup_connection (conn); - switch (ret) { - case FSIO_READY: - _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); - _fs_restart_connection (conn); - break; - case FSIO_BLOCK: - break; - case FSIO_ERROR: - conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; - break; - } -} - -/* - * Start the reconnection process - */ -static void -_fs_start_reconnect (FSFpePtr conn) -{ - if (conn->blockState & FS_RECONNECTING) - return; - conn->alternate = 0; - _fs_mark_block (conn, FS_RECONNECTING); - _fs_unmark_block (conn, FS_BROKEN_CONNECTION); - _fs_check_reconnect (conn); -} - - -static FSFpePtr -_fs_init_conn (char *servername) -{ - FSFpePtr conn; - - conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); - if (!conn) - return 0; - if (!_fs_io_init (conn)) - { - free (conn); - return 0; - } - conn->servername = (char *) (conn + 1); - conn->fs_conn_state = FS_CONN_UNCONNECTED; - conn->fs_fd = -1; - strcpy (conn->servername, servername); - return conn; -} - -static void -_fs_free_conn (FSFpePtr conn) -{ - _fs_close_server (conn); - _fs_io_fini (conn); - if (conn->alts) - free (conn->alts); - free (conn); -} - -/* - * called at server init time - */ - -void -fs_register_fpe_functions(void) -{ - RegisterFPEFunctions(fs_name_check, - fs_init_fpe, - fs_free_fpe, - fs_reset_fpe, - fs_open_font, - fs_close_font, - fs_list_fonts, - fs_start_list_with_info, - fs_next_list_with_info, - fs_wakeup, - fs_client_died, - _fs_load_glyphs, - NULL, - NULL, - NULL); -} +/* + +Copyright 1990, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from The Open Group. + +*/ + +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 names of Network Computing Devices, or Digital + * not be used in advertising or publicity pertaining to distribution + * of the software without specific, written prior permission. + * + * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, + * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + * THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * font server specific font access + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WIN32 +#define _WILLWINSOCK_ +#endif +#define FONT_t +#define TRANS_CLIENT +#include "X11/Xtrans/Xtrans.h" +#include "X11/Xpoll.h" +#include +#include +#include +#include +#include +#include +#include "fservestr.h" +#include +#include + +#include +#define Time_t time_t + +#ifdef NCD +#include +#endif + +#include + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif +#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) + +#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ + (pci)->rightSideBearing || \ + (pci)->ascent || \ + (pci)->descent || \ + (pci)->characterWidth) + +extern void ErrorF(const char *f, ...); + +static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); +static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); +static int fs_read_list_info ( FontPathElementPtr fpe, + FSBlockDataPtr blockrec ); + +extern fd_set _fs_fd_mask; + +static void fs_block_handler ( pointer data, OSTimePtr wt, + pointer LastSelectMask ); +static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); + +/* + * List of all FPEs + */ +static FSFpePtr fs_fpes; +/* + * Union of all FPE blockStates + */ +static CARD32 fs_blockState; + +static int _fs_restart_connection ( FSFpePtr conn ); +static void fs_send_query_bitmaps ( FontPathElementPtr fpe, + FSBlockDataPtr blockrec ); +static int fs_send_close_font ( FontPathElementPtr fpe, Font id ); +static void fs_client_died ( pointer client, FontPathElementPtr fpe ); +static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); +static void _fs_client_resolution ( FSFpePtr conn ); +static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); +static int fs_await_reply (FSFpePtr conn); +static void _fs_do_blocked (FSFpePtr conn); +static void fs_cleanup_bfont (FSBlockedFontPtr bfont); + +char _fs_glyph_undefined; +char _fs_glyph_requested; +static char _fs_glyph_zero_length; + +static int generationCount; + +static int FontServerRequestTimeout = 30 * 1000; + +static void +_fs_close_server (FSFpePtr conn); + +static FSFpePtr +_fs_init_conn (char *servername); + +static int +_fs_wait_connect (FSFpePtr conn); + +static int +_fs_send_init_packets (FSFpePtr conn); + +static void +_fs_check_reconnect (FSFpePtr conn); + +static void +_fs_start_reconnect (FSFpePtr conn); + +static void +_fs_free_conn (FSFpePtr conn); + +static int +fs_free_fpe(FontPathElementPtr fpe); + +/* + * Font server access + * + * the basic idea for the non-blocking access is to have the function + * called multiple times until the actual data is returned, instead + * of ClientBlocked. + * + * the first call to the function will cause the request to be sent to + * the font server, and a block record to be stored in the fpe's list + * of outstanding requests. the FS block handler also sticks the + * proper set of fd's into the select mask. when data is ready to be + * read in, the FS wakup handler will be hit. this will read the + * data off the wire into the proper block record, and then signal the + * client that caused the block so that it can restart. it will then + * call the access function again, which will realize that the data has + * arrived and return it. + */ + + +#ifdef DEBUG +static void +_fs_add_req_log(FSFpePtr conn, int opcode) +{ + conn->current_seq++; + fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", + conn->current_seq, opcode); + conn->reqbuffer[conn->reqindex].opcode = opcode; + conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; + conn->reqindex++; + if (conn->reqindex == REQUEST_LOG_SIZE) + conn->reqindex = 0; +} + +static void +_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) +{ + int i; + + for (i = 0; i < REQUEST_LOG_SIZE; i++) + if (conn->reqbuffer[i].sequence == rep->sequenceNumber) + break; + if (i == REQUEST_LOG_SIZE) + fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", + rep->sequenceNumber); + else + fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", + rep->sequenceNumber, + conn->reqbuffer[i].opcode); +} +#else +#define _fs_add_req_log(conn,op) ((conn)->current_seq++) +#define _fs_add_rep_log(conn,rep) +#endif + +static Bool +fs_name_check(char *name) +{ + /* Just make sure there is a protocol/ prefix */ + return (name && *name != '/' && strchr(name, '/')); +} + +static void +_fs_client_resolution(FSFpePtr conn) +{ + fsSetResolutionReq srreq; + int num_res; + FontResolutionPtr res; + + res = GetClientResolutions(&num_res); + + if (num_res) { + srreq.reqType = FS_SetResolution; + srreq.num_resolutions = num_res; + srreq.length = (SIZEOF(fsSetResolutionReq) + + (num_res * SIZEOF(fsResolution)) + 3) >> 2; + + _fs_add_req_log(conn, FS_SetResolution); + if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) + (void)_fs_write_pad(conn, (char *) res, + (num_res * SIZEOF(fsResolution))); + } +} + +/* + * close font server and remove any state associated with + * this connection - this includes any client records. + */ + +static void +fs_close_conn(FSFpePtr conn) +{ + FSClientPtr client, nclient; + + _fs_close_server (conn); + + for (client = conn->clients; client; client = nclient) + { + nclient = client->next; + free (client); + } + conn->clients = NULL; +} + +/* + * the wakeup handlers have to be set when the FPE is open, and not + * removed until it is freed, in order to handle unexpected data, like + * events + */ +/* ARGSUSED */ +static int +fs_init_fpe(FontPathElementPtr fpe) +{ + FSFpePtr conn; + char *name; + int err; + int ret; + + /* open font server */ + /* create FS specific fpe info */ + name = fpe->name; + + /* hack for old style names */ + if (*name == ':') + name++; /* skip ':' */ + + conn = _fs_init_conn (name); + if (!conn) + err = AllocError; + else + { + err = init_fs_handlers (fpe, fs_block_handler); + if (err != Successful) + { + _fs_free_conn (conn); + err = AllocError; + } + else + { + fpe->private = conn; + conn->next = fs_fpes; + fs_fpes = conn; + ret = _fs_wait_connect (conn); + if (ret != FSIO_READY) + { + fs_free_fpe (fpe); + err = BadFontPath; + } + else + err = Successful; + } + } + + if (err == Successful) + { +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Connected to font server \"%s\"\n", name); +#endif +#ifdef DEBUG + fprintf (stderr, "connected to FS \"%s\"\n", name); +#endif + } + else + { +#ifdef DEBUG + fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); +#endif +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Failed to connect to font server \"%s\"\n", name); +#endif + ; + } + return err; +} + +static int +fs_reset_fpe(FontPathElementPtr fpe) +{ + (void) _fs_send_init_packets((FSFpePtr) fpe->private); + return Successful; +} + +/* + * this shouldn't be called till all refs to the FPE are gone + */ + +static int +fs_free_fpe(FontPathElementPtr fpe) +{ + FSFpePtr conn = (FSFpePtr) fpe->private, *prev; + + /* unhook from chain of all font servers */ + for (prev = &fs_fpes; *prev; prev = &(*prev)->next) + { + if (*prev == conn) + { + *prev = conn->next; + break; + } + } + _fs_unmark_block (conn, conn->blockState); + fs_close_conn(conn); + remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); + _fs_free_conn (conn); + fpe->private = (pointer) 0; + +#ifdef NCD + if (configData.ExtendedFontDiags) + printf("Disconnected from font server \"%s\"\n", fpe->name); +#endif +#ifdef DEBUG + fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); +#endif + + return Successful; +} + +static FSBlockDataPtr +fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) +{ + FSBlockDataPtr blockrec, + *prev; + FSFpePtr conn = (FSFpePtr) fpe->private; + int size; + + switch (type) { + case FS_OPEN_FONT: + size = sizeof(FSBlockedFontRec); + break; + case FS_LOAD_GLYPHS: + size = sizeof(FSBlockedGlyphRec); + break; + case FS_LIST_FONTS: + size = sizeof(FSBlockedListRec); + break; + case FS_LIST_WITH_INFO: + size = sizeof(FSBlockedListInfoRec); + break; + default: + size = 0; + break; + } + blockrec = malloc(sizeof(FSBlockDataRec) + size); + if (!blockrec) + return (FSBlockDataPtr) 0; + blockrec->data = (pointer) (blockrec + 1); + blockrec->client = client; + blockrec->sequenceNumber = -1; + blockrec->errcode = StillWorking; + blockrec->type = type; + blockrec->depending = 0; + blockrec->next = (FSBlockDataPtr) 0; + + /* stick it on the end of the list (since its expected last) */ + for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) + ; + *prev = blockrec; + + return blockrec; +} + +static void +_fs_set_pending_reply (FSFpePtr conn) +{ + FSBlockDataPtr blockrec; + + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->errcode == StillWorking) + break; + if (blockrec) + { + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + _fs_mark_block (conn, FS_PENDING_REPLY); + } + else + _fs_unmark_block (conn, FS_PENDING_REPLY); +} + +static void +_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + FSBlockDataPtr *prev; + + for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) + if (*prev == blockrec) + { + *prev = blockrec->next; + break; + } + if (blockrec->type == FS_LOAD_GLYPHS) + { + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; + if (bglyph->num_expected_ranges) + free(bglyph->expected_ranges); + } + free(blockrec); + _fs_set_pending_reply (conn); +} + +static void +_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) +{ + FSClientsDependingPtr p; + + while ((p = *clients_depending)) + { + *clients_depending = p->next; + ClientSignal(p->client); + free(p); + } +} + +static int +_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) +{ + FSClientsDependingPtr new, cd; + + for (; (cd = *clients_depending); + clients_depending = &(*clients_depending)->next) + { + if (cd->client == client) + return Suspended; + } + + new = malloc (sizeof (FSClientsDependingRec)); + if (!new) + return BadAlloc; + + new->client = client; + new->next = 0; + *clients_depending = new; + return Suspended; +} + +/* + * When a request is aborted due to a font server failure, + * signal any depending clients to restart their dependant + * requests + */ +static void +_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + switch(blockrec->type) { + case FS_OPEN_FONT: { + FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; + + fs_cleanup_bfont (bfont); + _fs_signal_clients_depending(&bfont->clients_depending); + break; + } + case FS_LOAD_GLYPHS: { + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; + + _fs_clean_aborted_loadglyphs(bglyph->pfont, + bglyph->num_expected_ranges, + bglyph->expected_ranges); + _fs_signal_clients_depending(&bglyph->clients_depending); + break; + } + case FS_LIST_FONTS: + break; + case FS_LIST_WITH_INFO: { + FSBlockedListInfoPtr binfo; + binfo = (FSBlockedListInfoPtr) blockrec->data; + if (binfo->status == FS_LFWI_REPLY) + FD_SET(conn->fs_fd, &_fs_fd_mask); + _fs_free_props (&binfo->info); + } + default: + break; + } +} + +static void +fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) +{ + _fs_clean_aborted_blockrec (conn, blockrec); + _fs_remove_block_rec (conn, blockrec); +} + +/* + * Tell the font server we've failed to complete an open and + * then unload the partially created font + */ +static void +fs_cleanup_bfont (FSBlockedFontPtr bfont) +{ + FSFontDataRec *fsd; + + if (bfont->pfont) + { + fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; + + /* make sure the FS knows we choked on it */ + fs_send_close_font(bfont->pfont->fpe, bfont->fontid); + + /* + * Either unload the font if it's being opened for + * the first time, or smash the generation field to + * mark this font as an orphan + */ + if (!(bfont->flags & FontReopen)) + { + if (bfont->freeFont) + (*bfont->pfont->unload_font) (bfont->pfont); +#ifdef DEBUG + else + fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); +#endif + bfont->pfont = 0; + } + else + fsd->generation = -1; + } +} + +/* + * Check to see if a complete reply is waiting + */ +static fsGenericReply * +fs_get_reply (FSFpePtr conn, int *error) +{ + char *buf; + fsGenericReply *rep; + int ret; + + /* block if the connection is down or paused in lfwi */ + if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) + { + *error = FSIO_BLOCK; + return 0; + } + + ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); + if (ret != FSIO_READY) + { + *error = FSIO_BLOCK; + return 0; + } + + rep = (fsGenericReply *) buf; + + ret = _fs_start_read (conn, rep->length << 2, &buf); + if (ret != FSIO_READY) + { + *error = FSIO_BLOCK; + return 0; + } + + *error = FSIO_READY; + + return (fsGenericReply *) buf; +} + +static Bool +fs_reply_ready (FSFpePtr conn) +{ + fsGenericReply *rep; + + if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) + return FALSE; + if (fs_data_read (conn) < sizeof (fsGenericReply)) + return FALSE; + rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); + if (fs_data_read (conn) < rep->length << 2) + return FALSE; + return TRUE; +} + +static void +_fs_pending_reply (FSFpePtr conn) +{ + if (!(conn->blockState & FS_PENDING_REPLY)) + { + _fs_mark_block (conn, FS_PENDING_REPLY); + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + } +} + +static void +_fs_prepare_for_reply (FSFpePtr conn) +{ + _fs_pending_reply (conn); + _fs_flush (conn); +} + +/* + * Block (for a while) awaiting a complete reply + */ +static int +fs_await_reply (FSFpePtr conn) +{ + int ret; + + if (conn->blockState & FS_COMPLETE_REPLY) + return FSIO_READY; + + while (!fs_get_reply (conn, &ret)) + { + if (ret != FSIO_BLOCK) + return ret; + if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + return FSIO_READY; +} + +/* + * Process the reply to an OpenBitmapFont request + */ +static int +fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + fsOpenBitmapFontReply *rep; + FSBlockDataPtr blockOrig; + FSBlockedFontPtr origBfont; + int ret; + + rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* If we're not reopening a font and FS detected a duplicate font + open request, replace our reference to the new font with a + reference to an existing font (possibly one not finished + opening). If this is a reopen, keep the new font reference... + it's got the metrics and extents we read when the font was opened + before. This also gives us the freedom to easily close the font + if we we decide (in fs_read_query_info()) that we don't like what + we got. */ + + if (rep->otherid && !(bfont->flags & FontReopen)) + { + fs_cleanup_bfont (bfont); + + /* Find old font if we're completely done getting it from server. */ + bfont->pfont = find_old_font(rep->otherid); + bfont->freeFont = FALSE; + bfont->fontid = rep->otherid; + bfont->state = FS_DONE_REPLY; + /* + * look for a blocked request to open the same font + */ + for (blockOrig = conn->blockedRequests; + blockOrig; + blockOrig = blockOrig->next) + { + if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) + { + origBfont = (FSBlockedFontPtr) blockOrig->data; + if (origBfont->fontid == rep->otherid) + { + blockrec->depending = blockOrig->depending; + blockOrig->depending = blockrec; + bfont->state = FS_DEPENDING; + bfont->pfont = origBfont->pfont; + break; + } + } + } + if (bfont->pfont == NULL) + { + /* XXX - something nasty happened */ + ret = BadFontName; + } + else + ret = AccessDone; + } + else + { + bfont->pfont->info.cachable = rep->cachable != 0; + bfont->state = FS_INFO_REPLY; + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryInfoSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + ret = StillWorking; + } + _fs_done_read (conn, rep->length << 2); + return ret; +} + +static Bool +fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) +{ + int i; + + if (pInfo1->firstCol != pInfo2->firstCol || + pInfo1->lastCol != pInfo2->lastCol || + pInfo1->firstRow != pInfo2->firstRow || + pInfo1->lastRow != pInfo2->lastRow || + pInfo1->defaultCh != pInfo2->defaultCh || + pInfo1->noOverlap != pInfo2->noOverlap || + pInfo1->terminalFont != pInfo2->terminalFont || + pInfo1->constantMetrics != pInfo2->constantMetrics || + pInfo1->constantWidth != pInfo2->constantWidth || + pInfo1->inkInside != pInfo2->inkInside || + pInfo1->inkMetrics != pInfo2->inkMetrics || + pInfo1->allExist != pInfo2->allExist || + pInfo1->drawDirection != pInfo2->drawDirection || + pInfo1->cachable != pInfo2->cachable || + pInfo1->anamorphic != pInfo2->anamorphic || + pInfo1->maxOverlap != pInfo2->maxOverlap || + pInfo1->fontAscent != pInfo2->fontAscent || + pInfo1->fontDescent != pInfo2->fontDescent || + pInfo1->nprops != pInfo2->nprops) + return FALSE; + +#define MATCH(xci1, xci2) \ + (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ + ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ + ((xci1).characterWidth == (xci2).characterWidth) && \ + ((xci1).ascent == (xci2).ascent) && \ + ((xci1).descent == (xci2).descent) && \ + ((xci1).attributes == (xci2).attributes)) + + if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || + !MATCH(pInfo1->minbounds, pInfo2->minbounds) || + !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || + !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) + return FALSE; + +#undef MATCH + + for (i = 0; i < pInfo1->nprops; i++) + if (pInfo1->isStringProp[i] != + pInfo2->isStringProp[i] || + pInfo1->props[i].name != + pInfo2->props[i].name || + pInfo1->props[i].value != + pInfo2->props[i].value) + { + return FALSE; + } + return TRUE; +} + +static int +fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFpePtr conn = (FSFpePtr) fpe->private; + fsQueryXInfoReply *rep; + char *buf; + fsPropInfo *pi; + fsPropOffset *po; + pointer pd; + FontInfoPtr pInfo; + FontInfoRec tempInfo; + int err; + int ret; + + rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* If this is a reopen, accumulate the query info into a dummy + font and compare to our original data. */ + if (bfont->flags & FontReopen) + pInfo = &tempInfo; + else + pInfo = &bfont->pfont->info; + + buf = (char *) rep; + buf += SIZEOF(fsQueryXInfoReply); + + /* move the data over */ + fsUnpack_XFontInfoHeader(rep, pInfo); + + /* compute accelerators */ + _fs_init_fontinfo(conn, pInfo); + + /* Compute offsets into the reply */ + pi = (fsPropInfo *) buf; + buf += SIZEOF (fsPropInfo); + + po = (fsPropOffset *) buf; + buf += pi->num_offsets * SIZEOF(fsPropOffset); + + pd = (pointer) buf; + buf += pi->data_len; + + /* convert the properties and step over the reply */ + ret = _fs_convert_props(pi, po, pd, pInfo); + _fs_done_read (conn, rep->length << 2); + + if (ret == -1) + { + fs_cleanup_bfont (bfont); + return AllocError; + } + + if (bfont->flags & FontReopen) + { + /* We're reopening a font that we lost because of a downed + connection. In the interest of avoiding corruption from + opening a different font than the old one (we already have + its metrics, extents, and probably some of its glyphs), + verify that the metrics and properties all match. */ + + if (fs_fonts_match (pInfo, &bfont->pfont->info)) + { + err = Successful; + bfont->state = FS_DONE_REPLY; + } + else + { + fs_cleanup_bfont (bfont); + err = BadFontName; + } + _fs_free_props (pInfo); + + return err; + } + + /* + * Ask for terminal format fonts if possible + */ + if (bfont->pfont->info.terminalFont) + bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | + BitmapFormatImageRectMax); + + /* + * Figure out if the whole font should get loaded right now. + */ + if (glyphCachingMode == CACHING_OFF || + (glyphCachingMode == CACHE_16_BIT_GLYPHS + && !bfont->pfont->info.lastRow)) + { + bfont->flags |= FontLoadAll; + } + + /* + * Ready to send the query bitmaps; the terminal font bit has + * been computed and glyphCaching has been considered + */ + if (bfont->flags & FontLoadBitmaps) + { + fs_send_query_bitmaps (fpe, blockrec); + _fs_flush (conn); + } + + bfont->state = FS_EXTENT_REPLY; + + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryExtentsSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + + return StillWorking; +} + +static int +fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; + FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; + fsQueryXExtents16Reply *rep; + char *buf; + int i; + int numExtents; + int numInfos; + int ret; + Bool haveInk = FALSE; /* need separate ink metrics? */ + CharInfoPtr ci, pCI; + char *fsci; + fsXCharInfo fscilocal; + FontInfoRec *fi = &bfont->pfont->info; + + rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont (bfont); + return BadFontName; + } + + /* move the data over */ + /* need separate inkMetrics for fixed font server protocol version */ + numExtents = rep->num_extents; + numInfos = numExtents; + if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) + { + numInfos *= 2; + haveInk = TRUE; + } + ci = pCI = malloc(sizeof(CharInfoRec) * numInfos); + + if (!pCI) + { + _fs_done_read (conn, rep->length << 2); + fs_cleanup_bfont(bfont); + return AllocError; + } + fsfont->encoding = pCI; + if (haveInk) + fsfont->inkMetrics = pCI + numExtents; + else + fsfont->inkMetrics = pCI; + + buf = (char *) rep; + buf += SIZEOF (fsQueryXExtents16Reply); + fsci = buf; + + fsd->glyphs_to_get = 0; + ci = fsfont->inkMetrics; + for (i = 0; i < numExtents; i++) + { + memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ + _fs_convert_char_info(&fscilocal, &ci->metrics); + /* Bounds check. */ + if (ci->metrics.ascent > fi->maxbounds.ascent) + { + ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", + fpe->name, fsd->name, + ci->metrics.ascent, fi->maxbounds.ascent); + ci->metrics.ascent = fi->maxbounds.ascent; + } + if (ci->metrics.descent > fi->maxbounds.descent) + { + ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", + fpe->name, fsd->name, + ci->metrics.descent, fi->maxbounds.descent); + ci->metrics.descent = fi->maxbounds.descent; + } + fsci = fsci + SIZEOF(fsXCharInfo); + /* Initialize the bits field for later glyph-caching use */ + if (NONZEROMETRICS(&ci->metrics)) + { + if (!haveInk && + (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || + ci->metrics.ascent == -ci->metrics.descent)) + pCI[i].bits = &_fs_glyph_zero_length; + else + { + pCI[i].bits = &_fs_glyph_undefined; + fsd->glyphs_to_get++; + } + } + else + pCI[i].bits = (char *)0; + ci++; + } + + /* Done with reply */ + _fs_done_read (conn, rep->length << 2); + + /* build bitmap metrics, ImageRectMax style */ + if (haveInk) + { + CharInfoPtr ii; + + ci = fsfont->encoding; + ii = fsfont->inkMetrics; + for (i = 0; i < numExtents; i++, ci++, ii++) + { + if (NONZEROMETRICS(&ii->metrics)) + { + ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); + ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); + ci->metrics.ascent = FONT_MAX_ASCENT(fi); + ci->metrics.descent = FONT_MAX_DESCENT(fi); + ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); + ci->metrics.attributes = ii->metrics.attributes; + } + else + { + ci->metrics = ii->metrics; + } + /* Bounds check. */ + if (ci->metrics.ascent > fi->maxbounds.ascent) + { + ErrorF("fserve: warning: %s %s ascent (%d) " + "> maxascent (%d)\n", + fpe->name, fsd->name, + ci->metrics.ascent, fi->maxbounds.ascent); + ci->metrics.ascent = fi->maxbounds.ascent; + } + if (ci->metrics.descent > fi->maxbounds.descent) + { + ErrorF("fserve: warning: %s %s descent (%d) " + "> maxdescent (%d)\n", + fpe->name, fsd->name, + ci->metrics.descent, fi->maxbounds.descent); + ci->metrics.descent = fi->maxbounds.descent; + } + } + } + { + unsigned int r, c, numCols, firstCol; + + firstCol = bfont->pfont->info.firstCol; + numCols = bfont->pfont->info.lastCol - firstCol + 1; + c = bfont->pfont->info.defaultCh; + fsfont->pDefault = 0; + if (bfont->pfont->info.lastRow) + { + r = c >> 8; + r -= bfont->pfont->info.firstRow; + c &= 0xff; + c -= firstCol; + if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && + c < numCols) + fsfont->pDefault = &pCI[r * numCols + c]; + } + else + { + c -= firstCol; + if (c < numCols) + fsfont->pDefault = &pCI[c]; + } + } + bfont->state = FS_GLYPHS_REPLY; + + if (bfont->flags & FontLoadBitmaps) + { + /* + * Reset the blockrec for the next reply + */ + blockrec->sequenceNumber = bfont->queryBitmapsSequence; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + return StillWorking; + } + return Successful; +} + +#ifdef DEBUG +static char *fs_open_states[] = { + "OPEN_REPLY ", + "INFO_REPLY ", + "EXTENT_REPLY", + "GLYPHS_REPLY", + "DONE_REPLY ", + "DEPENDING ", +}; +#endif + +static int +fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + int err; + +#ifdef DEBUG + fprintf (stderr, "fs_do_open_font state %s %s\n", + fs_open_states[bfont->state], + ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); +#endif + err = BadFontName; + switch (bfont->state) { + case FS_OPEN_REPLY: + err = fs_read_open_font(fpe, blockrec); + if (err != StillWorking) { /* already loaded, or error */ + /* if font's already loaded, massage error code */ + switch (bfont->state) { + case FS_DONE_REPLY: + err = Successful; + break; + case FS_DEPENDING: + err = StillWorking; + break; + } + } + break; + case FS_INFO_REPLY: + err = fs_read_query_info(fpe, blockrec); + break; + case FS_EXTENT_REPLY: + err = fs_read_extent_info(fpe, blockrec); + break; + case FS_GLYPHS_REPLY: + if (bfont->flags & FontLoadBitmaps) + err = fs_read_glyphs(fpe, blockrec); + break; + case FS_DEPENDING: /* can't happen */ + default: + break; + } +#ifdef DEBUG + fprintf (stderr, "fs_do_open_font err %d\n", err); +#endif + if (err != StillWorking) + { + bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ + while ((blockrec = blockrec->depending)) + { + bfont = (FSBlockedFontPtr) blockrec->data; + bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ + } + } + return err; +} + +void +_fs_mark_block (FSFpePtr conn, CARD32 mask) +{ + conn->blockState |= mask; + fs_blockState |= mask; +} + +void +_fs_unmark_block (FSFpePtr conn, CARD32 mask) +{ + FSFpePtr c; + + if (conn->blockState & mask) + { + conn->blockState &= ~mask; + fs_blockState = 0; + for (c = fs_fpes; c; c = c->next) + fs_blockState |= c->blockState; + } +} + +/* ARGSUSED */ +static void +fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) +{ + static struct timeval block_timeout; + CARD32 now, earliest, wakeup; + int soonest; + FSFpePtr conn; + + XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, + &_fs_fd_mask); + /* + * Flush all pending output + */ + if (fs_blockState & FS_PENDING_WRITE) + for (conn = fs_fpes; conn; conn = conn->next) + if (conn->blockState & FS_PENDING_WRITE) + _fs_flush (conn); + /* + * Check for any fpe with a complete reply, set sleep time to zero + */ + if (fs_blockState & FS_COMPLETE_REPLY) + { + block_timeout.tv_sec = 0; + block_timeout.tv_usec = 0; + if (*wt == NULL) + *wt = &block_timeout; + else + **wt = block_timeout; + } + /* + * Walk through fpe list computing sleep time + */ + else if (fs_blockState & (FS_BROKEN_WRITE| + FS_BROKEN_CONNECTION| + FS_PENDING_REPLY| + FS_RECONNECTING)) + { + now = GetTimeInMillis (); + earliest = now + 10000000; + for (conn = fs_fpes; conn; conn = conn->next) + { + if (conn->blockState & FS_RECONNECTING) + { + wakeup = conn->blockedConnectTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_BROKEN_CONNECTION) + { + wakeup = conn->brokenConnectionTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_BROKEN_WRITE) + { + wakeup = conn->brokenWriteTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + if (conn->blockState & FS_PENDING_REPLY) + { + wakeup = conn->blockedReplyTime; + if (TimeCmp (wakeup, <, earliest)) + earliest = wakeup; + } + } + soonest = earliest - now; + if (soonest < 0) + soonest = 0; + block_timeout.tv_sec = soonest / 1000; + block_timeout.tv_usec = (soonest % 1000) * 1000; + if (*wt == NULL) + *wt = &block_timeout; + else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) + **wt = block_timeout; + } +} + +static void +fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) +{ + if (rep->type == FS_Event && rep->data1 == KeepAlive) + { + fsNoopReq req; + + /* ping it back */ + req.reqType = FS_Noop; + req.length = SIZEOF(fsNoopReq) >> 2; + _fs_add_req_log(conn, FS_Noop); + _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); + } + /* this should suck up unexpected replies and events */ + _fs_done_read (conn, rep->length << 2); +} + +static void +fs_read_reply (FontPathElementPtr fpe, pointer client) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + int ret; + int err; + fsGenericReply *rep; + + if ((rep = fs_get_reply (conn, &ret))) + { + _fs_add_rep_log (conn, rep); + for (blockrec = conn->blockedRequests; + blockrec; + blockrec = blockrec->next) + { + if (blockrec->sequenceNumber == rep->sequenceNumber) + break; + } + err = Successful; + if (!blockrec) + { + fs_handle_unexpected(conn, rep); + } + else + { + /* + * go read it, and if we're done, + * wake up the appropriate client + */ + switch (blockrec->type) { + case FS_OPEN_FONT: + blockrec->errcode = fs_do_open_font(fpe, blockrec); + break; + case FS_LOAD_GLYPHS: + blockrec->errcode = fs_read_glyphs(fpe, blockrec); + break; + case FS_LIST_FONTS: + blockrec->errcode = fs_read_list(fpe, blockrec); + break; + case FS_LIST_WITH_INFO: + blockrec->errcode = fs_read_list_info(fpe, blockrec); + break; + default: + break; + } + err = blockrec->errcode; + if (err != StillWorking) + { + while (blockrec) + { + blockrec->errcode = err; + if (client != blockrec->client) + ClientSignal(blockrec->client); + blockrec = blockrec->depending; + } + _fs_unmark_block (conn, FS_PENDING_REPLY); + } + } + if (fs_reply_ready (conn)) + _fs_mark_block (conn, FS_COMPLETE_REPLY); + else + _fs_unmark_block (conn, FS_COMPLETE_REPLY); + } +} + +static int +fs_wakeup(FontPathElementPtr fpe, unsigned long *mask) +{ + fd_set *LastSelectMask = (fd_set *) mask; + FSFpePtr conn = (FSFpePtr) fpe->private; + + /* + * Don't continue if the fd is -1 (which will be true when the + * font server terminates + */ + if ((conn->blockState & FS_RECONNECTING)) + _fs_check_reconnect (conn); + else if ((conn->blockState & FS_COMPLETE_REPLY) || + (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) + fs_read_reply (fpe, 0); + if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) + _fs_do_blocked (conn); +#ifdef DEBUG + { + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + FSBlockedListPtr blist; + static CARD32 lastState; + static FSBlockDataPtr lastBlock; + + if (conn->blockState || conn->blockedRequests || lastState || lastBlock) + { + fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); + lastState = conn->blockState; + lastBlock = conn->blockedRequests; + } + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + switch (blockrec->type) { + case FS_OPEN_FONT: + bfont = (FSBlockedFontPtr) blockrec->data; + fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", + blockrec->errcode, + blockrec->sequenceNumber, + fs_open_states[bfont->state], + bfont->pfont ? + ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : + ""); + break; + case FS_LIST_FONTS: + blist = (FSBlockedListPtr) blockrec->data; + fprintf (stderr, " Blocked list errcode %d sequence %d\n", + blockrec->errcode, blockrec->sequenceNumber); + break; + default: + fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", + blockrec->type, + blockrec->errcode, + blockrec->sequenceNumber); + break; + } + } + } +#endif + return FALSE; +} + +/* + * Notice a dead connection and prepare for reconnect + */ + +void +_fs_connection_died(FSFpePtr conn) +{ + if (conn->blockState & FS_BROKEN_CONNECTION) + return; + fs_close_conn(conn); + conn->brokenConnectionTime = GetTimeInMillis (); + _fs_mark_block (conn, FS_BROKEN_CONNECTION); + _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); +} + +/* + * Signal clients that the connection has come back up + */ +static int +_fs_restart_connection(FSFpePtr conn) +{ + FSBlockDataPtr block; + + _fs_unmark_block (conn, FS_GIVE_UP); + while ((block = (FSBlockDataPtr) conn->blockedRequests)) + { + if (block->errcode == StillWorking) + { + ClientSignal(block->client); + fs_abort_blockrec(conn, block); + } + } + return TRUE; +} + +/* + * Declare this font server connection useless + */ +static void +_fs_giveup (FSFpePtr conn) +{ + FSBlockDataPtr block; + + if (conn->blockState & FS_GIVE_UP) + return; +#ifdef DEBUG + fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); +#endif + _fs_mark_block (conn, FS_GIVE_UP); + while ((block = (FSBlockDataPtr) conn->blockedRequests)) + { + if (block->errcode == StillWorking) + { + ClientSignal (block->client); + fs_abort_blockrec (conn, block); + } + } + if (conn->fs_fd >= 0) + _fs_connection_died (conn); +} + +static void +_fs_do_blocked (FSFpePtr conn) +{ + CARD32 now; + + now = GetTimeInMillis (); + if ((conn->blockState & FS_PENDING_REPLY) && + TimeCmp (conn->blockedReplyTime, <=, now)) + { + _fs_giveup (conn); + } + else + { + if (conn->blockState & FS_BROKEN_CONNECTION) + { + /* Try to reconnect broken connections */ + if (TimeCmp (conn->brokenConnectionTime, <=, now)) + _fs_start_reconnect (conn); + } + else if (conn->blockState & FS_BROKEN_WRITE) + { + /* Try to flush blocked connections */ + if (TimeCmp (conn->brokenWriteTime, <=, now)) + _fs_flush (conn); + } + } +} + +/* + * sends the actual request out + */ +/* ARGSUSED */ +static int +fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *ppfont) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FontPtr font; + FSBlockDataPtr blockrec = NULL; + FSBlockedFontPtr bfont; + FSFontDataPtr fsd; + fsOpenBitmapFontReq openreq; + fsQueryXInfoReq inforeq; + fsQueryXExtents16Req extreq; + int err; + unsigned char buf[1024]; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + if (namelen <= 0 || namelen > sizeof (buf) - 1) + return BadFontName; + + /* + * Get the font structure put together, either by reusing + * the existing one or creating a new one + */ + if (flags & FontReopen) + { + Atom nameatom, fn = None; + int i; + + font = *ppfont; + fsd = (FSFontDataPtr)font->fpePrivate; + /* This is an attempt to reopen a font. Did the font have a + NAME property? */ + if ((nameatom = MakeAtom("FONT", 4, 0)) != None) + { + for (i = 0; i < font->info.nprops; i++) + if (font->info.props[i].name == nameatom && + font->info.isStringProp[i]) + { + fn = font->info.props[i].value; + break; + } + } + if (fn == None || !(name = NameForAtom(fn))) + { + name = fsd->name; + namelen = fsd->namelen; + } + else + namelen = strlen(name); + } + else + { + font = fs_create_font (fpe, name, namelen, format, fmask); + if (!font) + return AllocError; + + fsd = (FSFontDataPtr)font->fpePrivate; + } + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); + if (!blockrec) + { + if (!(flags & FontReopen)) + (*font->unload_font) (font); + return AllocError; + } + + /* + * Must check this before generating any protocol, otherwise we'll + * mess up a reconnect in progress + */ + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + fsd->generation = conn->generation; + + bfont = (FSBlockedFontPtr) blockrec->data; + bfont->fontid = fsd->fontid; + bfont->pfont = font; + bfont->state = FS_OPEN_REPLY; + bfont->flags = flags; + bfont->format = fsd->format; + bfont->clients_depending = (FSClientsDependingPtr)0; + bfont->freeFont = (flags & FontReopen) == 0; + + _fs_client_access (conn, client, (flags & FontOpenSync) != 0); + _fs_client_resolution(conn); + + /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ + buf[0] = (unsigned char) namelen; + memcpy(&buf[1], name, namelen); + openreq.reqType = FS_OpenBitmapFont; + openreq.pad = 0; + openreq.fid = fsd->fontid; + openreq.format_hint = fsd->format; + openreq.format_mask = fsd->fmask; + openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; + + _fs_add_req_log(conn, FS_OpenBitmapFont); + _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); + _fs_write_pad(conn, (char *) buf, namelen + 1); + + blockrec->sequenceNumber = conn->current_seq; + + inforeq.reqType = FS_QueryXInfo; + inforeq.pad = 0; + inforeq.id = fsd->fontid; + inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; + + bfont->queryInfoSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXInfo); + _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); + + if (!(bfont->flags & FontReopen)) + { + extreq.reqType = FS_QueryXExtents16; + extreq.range = fsTrue; + extreq.fid = fsd->fontid; + extreq.num_ranges = 0; + extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; + + bfont->queryExtentsSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXExtents16); + _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); + } + +#ifdef NCD + if (configData.ExtendedFontDiags) + { + memcpy(buf, name, MIN(256, namelen)); + buf[MIN(256, namelen)] = '\0'; + printf("Requesting font \"%s\" from font server \"%s\"\n", + buf, font->fpe->name); + } +#endif + _fs_prepare_for_reply (conn); + + err = blockrec->errcode; + if (bfont->flags & FontOpenSync) + { + while (blockrec->errcode == StillWorking) + { + if (fs_await_reply (conn) != FSIO_READY) + { + blockrec->errcode = BadFontName; + break; + } + fs_read_reply (font->fpe, client); + } + err = blockrec->errcode; + if (err == Successful) + *ppfont = bfont->pfont; + else + fs_cleanup_bfont (bfont); + bfont->freeFont = FALSE; + _fs_remove_block_rec (conn, blockrec); + } + return err == StillWorking ? Suspended : err; +} + +static void +fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + fsQueryXBitmaps16Req bitreq; + + /* send the request */ + bitreq.reqType = FS_QueryXBitmaps16; + bitreq.fid = bfont->fontid; + bitreq.format = bfont->format; + bitreq.range = TRUE; + bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; + bitreq.num_ranges = 0; + + bfont->queryBitmapsSequence = conn->current_seq + 1; + + _fs_add_req_log(conn, FS_QueryXBitmaps16); + _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); +} + +/* ARGSUSED */ +static int +fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, + char *name, int namelen, + fsBitmapFormat format, fsBitmapFormatMask fmask, + XID id, FontPtr *ppfont, + char **alias, FontPtr non_cachable_font) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + int err; + + /* libfont interface expects ImageRectMin glyphs */ + format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; + + *alias = (char *) 0; + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + + bfont = (FSBlockedFontPtr) blockrec->data; + if (err == Successful) + *ppfont = bfont->pfont; + else + fs_cleanup_bfont (bfont); + _fs_remove_block_rec (conn, blockrec); + return err; + } + } + return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, + id, ppfont); +} + +/* ARGSUSED */ +static int +fs_send_close_font(FontPathElementPtr fpe, Font id) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + fsCloseReq req; + + if (conn->blockState & FS_GIVE_UP) + return Successful; + /* tell the font server to close the font */ + req.reqType = FS_CloseFont; + req.pad = 0; + req.length = SIZEOF(fsCloseReq) >> 2; + req.id = id; + _fs_add_req_log(conn, FS_CloseFont); + _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); + + return Successful; +} + +/* ARGSUSED */ +static void +fs_close_font(FontPathElementPtr fpe, FontPtr pfont) +{ + FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; + FSFpePtr conn = (FSFpePtr) fpe->private; + + if (conn->generation == fsd->generation) + fs_send_close_font(fpe, fsd->fontid); + +#ifdef DEBUG + { + FSBlockDataPtr blockrec; + FSBlockedFontPtr bfont; + + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_OPEN_FONT) + { + bfont = (FSBlockedFontPtr) blockrec->data; + if (bfont->pfont == pfont) + fprintf (stderr, "closing font which hasn't been opened\n"); + } + } + } +#endif + (*pfont->unload_font) (pfont); +} + +static int +fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; + FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; + FSFpePtr conn = (FSFpePtr) fpe->private; + FontPtr pfont = bglyph->pfont; + /* works for either blocked font + or glyph rec... pfont is at + the very beginning of both + blockrec->data structures */ + FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); + FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; + FontInfoPtr pfi = &pfont->info; + fsQueryXBitmaps16Reply *rep; + char *buf; + fsOffset32 *ppbits; + fsOffset32 local_off; + char *off_adr; + pointer pbitmaps; + char *bits, *allbits; +#ifdef DEBUG + char *origallbits; +#endif + int i, + err; + int nranges = 0; + int ret; + fsRange *nextrange = 0; + unsigned long minchar, maxchar; + + rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + err = AllocError; + goto bail; + } + + buf = (char *) rep; + buf += SIZEOF (fsQueryXBitmaps16Reply); + + ppbits = (fsOffset32 *) buf; + buf += SIZEOF (fsOffset32) * (rep->num_chars); + + pbitmaps = (pointer ) buf; + + if (blockrec->type == FS_LOAD_GLYPHS) + { + nranges = bglyph->num_expected_ranges; + nextrange = bglyph->expected_ranges; + } + + /* place the incoming glyphs */ + if (nranges) + { + /* We're operating under the assumption that the ranges + requested in the LoadGlyphs call were all legal for this + font, and that individual ranges do not cover multiple + rows... fs_build_range() is designed to ensure this. */ + minchar = (nextrange->min_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->min_char_low - pfi->firstCol; + maxchar = (nextrange->max_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->max_char_low - pfi->firstCol; + nextrange++; + } + else + { + minchar = 0; + maxchar = rep->num_chars; + } + + off_adr = (char *)ppbits; + + allbits = fs_alloc_glyphs (pfont, rep->nbytes); + + if (!allbits) + { + err = AllocError; + goto bail; + } + +#ifdef DEBUG + origallbits = allbits; + fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", + (int) rep->num_chars, (int) rep->nbytes, fsd->name); +#endif + + for (i = 0; i < rep->num_chars; i++) + { + memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ + if (blockrec->type == FS_OPEN_FONT || + fsdata->encoding[minchar].bits == &_fs_glyph_requested) + { + /* + * Broken X font server returns bits for missing characters + * when font is padded + */ + if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) + { + if (local_off.length) + { + bits = allbits; + allbits += local_off.length; + memcpy(bits, (char *)pbitmaps + local_off.position, + local_off.length); + } + else + bits = &_fs_glyph_zero_length; + } + else + bits = 0; + if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) + fsd->glyphs_to_get--; + fsdata->encoding[minchar].bits = bits; + } + if (minchar++ == maxchar) + { + if (!--nranges) break; + minchar = (nextrange->min_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->min_char_low - pfi->firstCol; + maxchar = (nextrange->max_char_high - pfi->firstRow) * + (pfi->lastCol - pfi->firstCol + 1) + + nextrange->max_char_low - pfi->firstCol; + nextrange++; + } + off_adr += SIZEOF(fsOffset32); + } +#ifdef DEBUG + fprintf (stderr, "Used %d bytes instead of %d\n", + (int) (allbits - origallbits), (int) rep->nbytes); +#endif + + if (blockrec->type == FS_OPEN_FONT) + { + fsd->glyphs_to_get = 0; + bfont->state = FS_DONE_REPLY; + } + err = Successful; + +bail: + _fs_done_read (conn, rep->length << 2); + return err; +} + +static int +fs_send_load_glyphs(pointer client, FontPtr pfont, + int nranges, fsRange *ranges) +{ + FontPathElementPtr fpe = pfont->fpe; + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedGlyphPtr blockedglyph; + fsQueryXBitmaps16Req req; + FSBlockDataPtr blockrec; + + if (conn->blockState & FS_GIVE_UP) + return BadCharRange; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); + if (!blockrec) + return AllocError; + blockedglyph = (FSBlockedGlyphPtr) blockrec->data; + blockedglyph->pfont = pfont; + blockedglyph->num_expected_ranges = nranges; + /* Assumption: it's our job to free ranges */ + blockedglyph->expected_ranges = ranges; + blockedglyph->clients_depending = (FSClientsDependingPtr)0; + + if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + /* send the request */ + req.reqType = FS_QueryXBitmaps16; + req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; + req.format = pfont->format; + if (pfont->info.terminalFont) + req.format = (req.format & ~(BitmapFormatImageRectMask)) | + BitmapFormatImageRectMax; + req.range = TRUE; + /* each range takes up 4 bytes */ + req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; + req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ + _fs_add_req_log(conn, FS_QueryXBitmaps16); + _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); + + blockrec->sequenceNumber = conn->current_seq; + + /* Send ranges to the server... pack into a char array by hand + to avoid structure-packing portability problems and to + handle swapping for version1 protocol */ + if (nranges) + { +#define RANGE_BUFFER_SIZE 64 +#define RANGE_BUFFER_SIZE_MASK 63 + int i; + char range_buffer[RANGE_BUFFER_SIZE * 4]; + char *range_buffer_p; + + range_buffer_p = range_buffer; + for (i = 0; i < nranges;) + { + if (conn->fsMajorVersion > 1) + { + *range_buffer_p++ = ranges[i].min_char_high; + *range_buffer_p++ = ranges[i].min_char_low; + *range_buffer_p++ = ranges[i].max_char_high; + *range_buffer_p++ = ranges[i].max_char_low; + } + else + { + *range_buffer_p++ = ranges[i].min_char_low; + *range_buffer_p++ = ranges[i].min_char_high; + *range_buffer_p++ = ranges[i].max_char_low; + *range_buffer_p++ = ranges[i].max_char_high; + } + + if (!(++i & RANGE_BUFFER_SIZE_MASK)) + { + _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); + range_buffer_p = range_buffer; + } + } + if (i &= RANGE_BUFFER_SIZE_MASK) + _fs_write(conn, range_buffer, i * 4); + } + + _fs_prepare_for_reply (conn); + return Suspended; +} + + +extern pointer serverClient; /* This could be any number that + doesn't conflict with existing + client values. */ + +static int +_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, + unsigned int nchars, int item_size, unsigned char *data) +{ + FSFpePtr conn = (FSFpePtr) pfont->fpe->private; + int nranges = 0; + fsRange *ranges = NULL; + int res; + FSBlockDataPtr blockrec; + FSBlockedGlyphPtr blockedglyph; + FSClientsDependingPtr *clients_depending = NULL; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_LOAD_GLYPHS) + { + blockedglyph = (FSBlockedGlyphPtr) blockrec->data; + if (blockedglyph->pfont == pfont) + { + /* Look for this request */ + if (blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + _fs_signal_clients_depending(&blockedglyph->clients_depending); + _fs_remove_block_rec(conn, blockrec); + return err; + } + /* We've found an existing LoadGlyphs blockrec for this + font but for another client. Rather than build a + blockrec for it now (which entails some complex + maintenance), we'll add it to a queue of clients to + be signalled when the existing LoadGlyphs is + completed. */ + clients_depending = &blockedglyph->clients_depending; + break; + } + } + else if (blockrec->type == FS_OPEN_FONT) + { + FSBlockedFontPtr bfont; + bfont = (FSBlockedFontPtr) blockrec->data; + if (bfont->pfont == pfont) + { + /* + * An OpenFont is pending for this font, this must + * be from a reopen attempt, so finish the open + * attempt and retry the LoadGlyphs + */ + if (blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + + _fs_signal_clients_depending(&bfont->clients_depending); + _fs_remove_block_rec(conn, blockrec); + if (err != Successful) + return err; + break; + } + /* We've found an existing OpenFont blockrec for this + font but for another client. Rather than build a + blockrec for it now (which entails some complex + maintenance), we'll add it to a queue of clients to + be signalled when the existing OpenFont is + completed. */ + if (blockrec->errcode == StillWorking) + { + clients_depending = &bfont->clients_depending; + break; + } + } + } + } + + /* + * see if the desired glyphs already exist, and return Successful if they + * do, otherwise build up character range/character string + */ + res = fs_build_range(pfont, range_flag, nchars, item_size, data, + &nranges, &ranges); + + switch (res) + { + case AccessDone: + return Successful; + + case Successful: + break; + + default: + return res; + } + + /* + * If clients_depending is not null, this request must wait for + * some prior request(s) to complete. + */ + if (clients_depending) + { + /* Since we're not ready to send the load_glyphs request yet, + clean up the damage (if any) caused by the fs_build_range() + call. */ + if (nranges) + { + _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); + free(ranges); + } + return _fs_add_clients_depending(clients_depending, client); + } + + /* + * If fsd->generation != conn->generation, the font has been closed + * due to a lost connection. We will reopen it, which will result + * in one of three things happening: + * 1) The open will succeed and obtain the same font. Life + * is wonderful. + * 2) The open will fail. There is code above to recognize this + * and flunk the LoadGlyphs request. The client might not be + * thrilled. + * 3) Worst case: the open will succeed but the font we open will + * be different. The fs_read_query_info() procedure attempts + * to detect this by comparing the existing metrics and + * properties against those of the reopened font... if they + * don't match, we flunk the reopen, which eventually results + * in flunking the LoadGlyphs request. We could go a step + * further and compare the extents, but this should be + * sufficient. + */ + if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) + { + /* Since we're not ready to send the load_glyphs request yet, + clean up the damage caused by the fs_build_range() call. */ + _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); + free(ranges); + + /* Now try to reopen the font. */ + return fs_send_open_font(client, pfont->fpe, + (Mask)FontReopen, (char *)0, 0, + (fsBitmapFormat)0, (fsBitmapFormatMask)0, + (XID)0, &pfont); + } + + return fs_send_load_glyphs(client, pfont, nranges, ranges); +} + +int +fs_load_all_glyphs(FontPtr pfont) +{ + int err; + FSFpePtr conn = (FSFpePtr) pfont->fpe->private; + + /* + * The purpose of this procedure is to load all glyphs in the event + * that we're dealing with someone who doesn't understand the finer + * points of glyph caching... it is called from _fs_get_glyphs() if + * the latter is called to get glyphs that have not yet been loaded. + * We assume that the caller will not know how to handle a return + * value of Suspended (usually the case for a GetGlyphs() caller), + * so this procedure hangs around, freezing the server, for the + * request to complete. This is an unpleasant kluge called to + * perform an unpleasant job that, we hope, will never be required. + */ + + while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == + Suspended) + { + if (fs_await_reply (conn) != FSIO_READY) + { + /* Get rid of blockrec */ + fs_client_died(serverClient, pfont->fpe); + err = BadCharRange; + break; + } + fs_read_reply (pfont->fpe, serverClient); + } + return err; +} + +static int +fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; + fsListFontsReply *rep; + char *data; + int length, + i, + ret; + int err; + + rep = (fsListFontsReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + if (rep) + _fs_done_read (conn, rep->length << 2); + return AllocError; + } + data = (char *) rep + SIZEOF (fsListFontsReply); + + err = Successful; + /* copy data into FontPathRecord */ + for (i = 0; i < rep->nFonts; i++) + { + length = *(unsigned char *)data++; + err = AddFontNamesName(blist->names, data, length); + if (err != Successful) + break; + data += length; + } + _fs_done_read (conn, rep->length << 2); + return err; +} + +static int +fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, + int patlen, int maxnames, FontNamesPtr newnames) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListPtr blockedlist; + fsListFontsReq req; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); + if (!blockrec) + return AllocError; + blockedlist = (FSBlockedListPtr) blockrec->data; + blockedlist->names = newnames; + + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + _fs_client_access (conn, client, FALSE); + _fs_client_resolution(conn); + + /* send the request */ + req.reqType = FS_ListFonts; + req.pad = 0; + req.maxNames = maxnames; + req.nbytes = patlen; + req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; + _fs_add_req_log(conn, FS_ListFonts); + _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); + _fs_write_pad(conn, (char *) pattern, patlen); + + blockrec->sequenceNumber = conn->current_seq; + +#ifdef NCD + if (configData.ExtendedFontDiags) { + char buf[256]; + + memcpy(buf, pattern, MIN(256, patlen)); + buf[MIN(256, patlen)] = '\0'; + printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", + buf, fpe->name); + } +#endif + + _fs_prepare_for_reply (conn); + return Suspended; +} + +static int +fs_list_fonts(pointer client, FontPathElementPtr fpe, + char *pattern, int patlen, int maxnames, FontNamesPtr newnames) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + { + if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) + { + err = blockrec->errcode; + if (err == StillWorking) + return Suspended; + _fs_remove_block_rec(conn, blockrec); + return err; + } + } + + /* didn't find waiting record, so send a new one */ + return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); +} + +/* + * Read a single list info reply and restart for the next reply + */ +static int +fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) +{ + FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; + fsListFontsWithXInfoReply *rep; + char *buf; + FSFpePtr conn = (FSFpePtr) fpe->private; + fsPropInfo *pi; + fsPropOffset *po; + pointer pd; + int ret; + int err; + + /* clean up anything from the last trip */ + _fs_free_props (&binfo->info); + + rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); + if (!rep || rep->type == FS_Error) + { + if (ret == FSIO_BLOCK) + return StillWorking; + binfo->status = FS_LFWI_FINISHED; + err = AllocError; + goto done; + } + /* + * Normal termination -- the list ends with a name of length 0 + */ + if (rep->nameLength == 0) + { +#ifdef DEBUG + fprintf (stderr, "fs_read_list_info done\n"); +#endif + binfo->status = FS_LFWI_FINISHED; + err = BadFontName; + goto done; + } + + buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); + + /* + * The original FS implementation didn't match + * the spec, version 1 was respecified to match the FS. + * Version 2 matches the original intent + */ + if (conn->fsMajorVersion <= 1) + { + memcpy (binfo->name, buf, rep->nameLength); + buf += _fs_pad_length (rep->nameLength); + } + pi = (fsPropInfo *) buf; + buf += SIZEOF (fsPropInfo); + po = (fsPropOffset *) buf; + buf += pi->num_offsets * SIZEOF (fsPropOffset); + pd = (pointer) buf; + buf += pi->data_len; + if (conn->fsMajorVersion > 1) + { + memcpy (binfo->name, buf, rep->nameLength); + buf += _fs_pad_length (rep->nameLength); + } + +#ifdef DEBUG + binfo->name[rep->nameLength] = '\0'; + fprintf (stderr, "fs_read_list_info %s\n", binfo->name); +#endif + err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); + if (err != Successful) + { + binfo->status = FS_LFWI_FINISHED; + goto done; + } + binfo->namelen = rep->nameLength; + binfo->remaining = rep->nReplies; + + binfo->status = FS_LFWI_REPLY; + + /* disable this font server until we've processed this response */ + _fs_unmark_block (conn, FS_COMPLETE_REPLY); + FD_CLR(conn->fs_fd, &_fs_fd_mask); +done: + _fs_done_read (conn, rep->length << 2); + return err; +} + +/* ARGSUSED */ +static int +fs_start_list_with_info(pointer client, FontPathElementPtr fpe, + char *pattern, int len, int maxnames, pointer *pdata) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListInfoPtr binfo; + fsListFontsWithXInfoReq req; + + if (conn->blockState & FS_GIVE_UP) + return BadFontName; + + /* make a new block record, and add it to the end of the list */ + blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); + if (!blockrec) + return AllocError; + + binfo = (FSBlockedListInfoPtr) blockrec->data; + bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); + binfo->status = FS_LFWI_WAITING; + + if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) + { + _fs_pending_reply (conn); + return Suspended; + } + + _fs_client_access (conn, client, FALSE); + _fs_client_resolution(conn); + + /* send the request */ + req.reqType = FS_ListFontsWithXInfo; + req.pad = 0; + req.maxNames = maxnames; + req.nbytes = len; + req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; + _fs_add_req_log(conn, FS_ListFontsWithXInfo); + (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); + (void) _fs_write_pad(conn, pattern, len); + + blockrec->sequenceNumber = conn->current_seq; + +#ifdef NCD + if (configData.ExtendedFontDiags) { + char buf[256]; + + memcpy(buf, pattern, MIN(256, len)); + buf[MIN(256, len)] = '\0'; + printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", + buf, fpe->name); + } +#endif + + _fs_prepare_for_reply (conn); + return Successful; +} + +/* ARGSUSED */ +static int +fs_next_list_with_info(pointer client, FontPathElementPtr fpe, + char **namep, int *namelenp, + FontInfoPtr *pFontInfo, int *numFonts, + pointer private) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec; + FSBlockedListInfoPtr binfo; + int err; + + /* see if the result is already there */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) + break; + + if (!blockrec) + { + /* The only good reason for not finding a blockrec would be if + disconnect/reconnect to the font server wiped it out and the + code that called us didn't do the right thing to create + another one. Under those circumstances, we need to return an + error to prevent that code from attempting to interpret the + information we don't return. */ + return BadFontName; + } + + binfo = (FSBlockedListInfoPtr) blockrec->data; + + if (binfo->status == FS_LFWI_WAITING) + return Suspended; + + *namep = binfo->name; + *namelenp = binfo->namelen; + *pFontInfo = &binfo->info; + *numFonts = binfo->remaining; + + /* Restart reply processing from this font server */ + FD_SET(conn->fs_fd, &_fs_fd_mask); + if (fs_reply_ready (conn)) + _fs_mark_block (conn, FS_COMPLETE_REPLY); + + err = blockrec->errcode; + switch (binfo->status) { + case FS_LFWI_FINISHED: + _fs_remove_block_rec(conn, blockrec); + break; + case FS_LFWI_REPLY: + binfo->status = FS_LFWI_WAITING; + blockrec->errcode = StillWorking; + conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; + _fs_mark_block (conn, FS_PENDING_REPLY); + break; + } + + return err; +} + +/* + * Called when client exits + */ + +static void +fs_client_died(pointer client, FontPathElementPtr fpe) +{ + FSFpePtr conn = (FSFpePtr) fpe->private; + FSBlockDataPtr blockrec, + depending; + FSClientPtr *prev, cur; + fsFreeACReq freeac; + + for (prev = &conn->clients; (cur = *prev); prev = &cur->next) + { + if (cur->client == client) { + freeac.reqType = FS_FreeAC; + freeac.pad = 0; + freeac.id = cur->acid; + freeac.length = sizeof (fsFreeACReq) >> 2; + _fs_add_req_log(conn, FS_FreeAC); + _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); + *prev = cur->next; + free (cur); + break; + } + } + /* find a pending requests */ + for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) + if (blockrec->client == client) + break; + + if (!blockrec) + return; + + /* replace the client pointers in this block rec with the chained one */ + if ((depending = blockrec->depending)) + { + blockrec->client = depending->client; + blockrec->depending = depending->depending; + blockrec = depending; + } + fs_abort_blockrec(conn, blockrec); +} + +static void +_fs_client_access (FSFpePtr conn, pointer client, Bool sync) +{ + FSClientPtr *prev, cur; + fsCreateACReq crac; + fsSetAuthorizationReq setac; + char *authorizations; + int authlen; + Bool new_cur = FALSE; + char padding[4] = { 0, 0, 0, 0 }; + +#ifdef DEBUG + if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) + { + fprintf (stderr, "Sending requests without a connection\n"); + } +#endif + for (prev = &conn->clients; (cur = *prev); prev = &cur->next) + { + if (cur->client == client) + { + if (prev != &conn->clients) + { + *prev = cur->next; + cur->next = conn->clients; + conn->clients = cur; + } + break; + } + } + if (!cur) + { + cur = malloc (sizeof (FSClientRec)); + if (!cur) + return; + cur->client = client; + cur->next = conn->clients; + conn->clients = cur; + cur->acid = GetNewFontClientID (); + new_cur = TRUE; + } + if (new_cur || cur->auth_generation != client_auth_generation(client)) + { + if (!new_cur) + { + fsFreeACReq freeac; + freeac.reqType = FS_FreeAC; + freeac.pad = 0; + freeac.id = cur->acid; + freeac.length = sizeof (fsFreeACReq) >> 2; + _fs_add_req_log(conn, FS_FreeAC); + _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); + } + crac.reqType = FS_CreateAC; + crac.num_auths = set_font_authorizations(&authorizations, &authlen, + client); + /* Work around bug in xfs versions up through modular release 1.0.8 + which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ + if (crac.num_auths == 0) { + authorizations = padding; + authlen = 4; + } else { + authlen = (authlen + 3) & ~0x3; + } + crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; + crac.acid = cur->acid; + _fs_add_req_log(conn, FS_CreateAC); + _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); + _fs_write(conn, authorizations, authlen); + /* ignore reply; we don't even care about it */ + conn->curacid = 0; + cur->auth_generation = client_auth_generation(client); + } + if (conn->curacid != cur->acid) + { + setac.reqType = FS_SetAuthorization; + setac.pad = 0; + setac.length = sizeof (fsSetAuthorizationReq) >> 2; + setac.id = cur->acid; + _fs_add_req_log(conn, FS_SetAuthorization); + _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); + conn->curacid = cur->acid; + } +} + +/* + * Poll a pending connect + */ + +static int +_fs_check_connect (FSFpePtr conn) +{ + int ret; + + ret = _fs_poll_connect (conn->trans_conn, 0); + switch (ret) { + case FSIO_READY: + conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); + FD_SET (conn->fs_fd, &_fs_fd_mask); + break; + case FSIO_BLOCK: + break; + } + return ret; +} + +/* + * Return an FSIO status while waiting for the completed connection + * reply to arrive + */ + +static fsConnSetup * +_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) +{ + int ret; + char *data; + int headlen; + int len; + fsConnSetup *setup; + fsConnSetupAccept *accept; + + ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + + setup = (fsConnSetup *) data; + if (setup->major_version > FS_PROTOCOL) + { + *error = FSIO_ERROR; + return 0; + } + + headlen = (SIZEOF (fsConnSetup) + + (setup->alternate_len << 2) + + (setup->auth_len << 2)); + /* On anything but Success, no extra data is sent */ + if (setup->status != AuthSuccess) + { + len = headlen; + } + else + { + ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + setup = (fsConnSetup *) data; + accept = (fsConnSetupAccept *) (data + headlen); + len = headlen + (accept->length << 2); + } + ret = _fs_start_read (conn, len, &data); + if (ret != FSIO_READY) + { + *error = ret; + return 0; + } + *setup_len = len; + return (fsConnSetup *) data; +} + +static int +_fs_send_conn_client_prefix (FSFpePtr conn) +{ + fsConnClientPrefix req; + int endian; + int ret; + + /* send setup prefix */ + endian = 1; + if (*(char *) &endian) + req.byteOrder = 'l'; + else + req.byteOrder = 'B'; + + req.major_version = FS_PROTOCOL; + req.minor_version = FS_PROTOCOL_MINOR; + +/* XXX add some auth info here */ + req.num_auths = 0; + req.auth_len = 0; + ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); + if (ret != FSIO_READY) + return FSIO_ERROR; + conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; + return ret; +} + +static int +_fs_recv_conn_setup (FSFpePtr conn) +{ + int ret = FSIO_ERROR; + fsConnSetup *setup; + FSFpeAltPtr alts; + int i, alt_len; + int setup_len; + char *alt_save, *alt_names; + + setup = _fs_get_conn_setup (conn, &ret, &setup_len); + if (!setup) + return ret; + conn->current_seq = 0; + conn->fsMajorVersion = setup->major_version; + /* + * Create an alternate list from the initial server, but + * don't chain looking for alternates. + */ + if (conn->alternate == 0) + { + /* + * free any existing alternates list, allowing the list to + * be updated + */ + if (conn->alts) + { + free (conn->alts); + conn->alts = 0; + conn->numAlts = 0; + } + if (setup->num_alternates) + { + alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + + (setup->alternate_len << 2)); + if (alts) + { + alt_names = (char *) (setup + 1); + alt_save = (char *) (alts + setup->num_alternates); + for (i = 0; i < setup->num_alternates; i++) + { + alts[i].subset = alt_names[0]; + alt_len = alt_names[1]; + alts[i].name = alt_save; + memcpy (alt_save, alt_names + 2, alt_len); + alt_save[alt_len] = '\0'; + alt_save += alt_len + 1; + alt_names += _fs_pad_length (alt_len + 2); + } + conn->numAlts = setup->num_alternates; + conn->alts = alts; + } + } + } + _fs_done_read (conn, setup_len); + if (setup->status != AuthSuccess) + return FSIO_ERROR; + return FSIO_READY; +} + +static int +_fs_open_server (FSFpePtr conn) +{ + int ret; + char *servername; + + if (conn->alternate == 0) + servername = conn->servername; + else + servername = conn->alts[conn->alternate-1].name; + conn->trans_conn = _fs_connect (servername, &ret); + conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; + return ret; +} + +static char * +_fs_catalog_name (char *servername) +{ + char *sp; + + sp = strchr (servername, '/'); + if (!sp) + return 0; + return strrchr (sp + 1, '/'); +} + +static int +_fs_send_init_packets (FSFpePtr conn) +{ + fsSetResolutionReq srreq; + fsSetCataloguesReq screq; + int num_cats, + clen; + char *catalogues; + char *cat; + char len; + char *end; + int num_res; + FontResolutionPtr res; + +#define CATALOGUE_SEP '+' + + res = GetClientResolutions(&num_res); + if (num_res) + { + srreq.reqType = FS_SetResolution; + srreq.num_resolutions = num_res; + srreq.length = (SIZEOF(fsSetResolutionReq) + + (num_res * SIZEOF(fsResolution)) + 3) >> 2; + + _fs_add_req_log(conn, FS_SetResolution); + if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) + return FSIO_ERROR; + if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) + return FSIO_ERROR; + } + + catalogues = 0; + if (conn->alternate != 0) + catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); + if (!catalogues) + catalogues = _fs_catalog_name (conn->servername); + + if (!catalogues) + { + conn->has_catalogues = FALSE; + return FSIO_READY; + } + conn->has_catalogues = TRUE; + + /* turn cats into counted list */ + catalogues++; + + cat = catalogues; + num_cats = 0; + clen = 0; + while (*cat) + { + num_cats++; + end = strchr(cat, CATALOGUE_SEP); + if (!end) + end = cat + strlen (cat); + clen += (end - cat) + 1; /* length byte + string */ + cat = end; + } + + screq.reqType = FS_SetCatalogues; + screq.num_catalogues = num_cats; + screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; + + _fs_add_req_log(conn, FS_SetCatalogues); + if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) + return FSIO_ERROR; + + while (*cat) + { + num_cats++; + end = strchr(cat, CATALOGUE_SEP); + if (!end) + end = cat + strlen (cat); + len = end - cat; + if (_fs_write (conn, &len, 1) != FSIO_READY) + return FSIO_ERROR; + if (_fs_write (conn, cat, (int) len) != FSIO_READY) + return FSIO_ERROR; + cat = end; + } + + if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) + return FSIO_ERROR; + + return FSIO_READY; +} + +static int +_fs_send_cat_sync (FSFpePtr conn) +{ + fsListCataloguesReq lcreq; + + /* + * now sync up with the font server, to see if an error was generated + * by a bogus catalogue + */ + lcreq.reqType = FS_ListCatalogues; + lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; + lcreq.maxNames = 0; + lcreq.nbytes = 0; + lcreq.pad2 = 0; + _fs_add_req_log(conn, FS_SetCatalogues); + if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) + return FSIO_ERROR; + conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; + return FSIO_READY; +} + +static int +_fs_recv_cat_sync (FSFpePtr conn) +{ + fsGenericReply *reply; + fsError *error; + int err; + int ret; + + reply = fs_get_reply (conn, &err); + if (!reply) + return err; + + ret = FSIO_READY; + if (reply->type == FS_Error) + { + error = (fsError *) reply; + if (error->major_opcode == FS_SetCatalogues) + ret = FSIO_ERROR; + } + _fs_done_read (conn, reply->length << 2); + return ret; +} + +static void +_fs_close_server (FSFpePtr conn) +{ + _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); + if (conn->trans_conn) + { + _FontTransClose (conn->trans_conn); + conn->trans_conn = 0; + _fs_io_reinit (conn); + } + if (conn->fs_fd >= 0) + { + FD_CLR (conn->fs_fd, &_fs_fd_mask); + conn->fs_fd = -1; + } + conn->fs_conn_state = FS_CONN_UNCONNECTED; +} + +static int +_fs_do_setup_connection (FSFpePtr conn) +{ + int ret; + + do + { +#ifdef DEBUG + fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); +#endif + switch (conn->fs_conn_state) { + case FS_CONN_UNCONNECTED: + ret = _fs_open_server (conn); + if (ret == FSIO_BLOCK) + conn->fs_conn_state = FS_CONN_CONNECTING; + break; + case FS_CONN_CONNECTING: + ret = _fs_check_connect (conn); + break; + case FS_CONN_CONNECTED: + ret = _fs_send_conn_client_prefix (conn); + break; + case FS_CONN_SENT_PREFIX: + ret = _fs_recv_conn_setup (conn); + break; + case FS_CONN_RECV_INIT: + ret = _fs_send_init_packets (conn); + if (conn->has_catalogues) + ret = _fs_send_cat_sync (conn); + break; + case FS_CONN_SENT_CAT: + if (conn->has_catalogues) + ret = _fs_recv_cat_sync (conn); + else + ret = FSIO_READY; + break; + default: + ret = FSIO_READY; + break; + } + switch (ret) { + case FSIO_READY: + if (conn->fs_conn_state < FS_CONN_RUNNING) + conn->fs_conn_state++; + break; + case FSIO_BLOCK: + if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) + break; + ret = FSIO_ERROR; + /* fall through... */ + case FSIO_ERROR: + _fs_close_server (conn); + /* + * Try the next alternate + */ + if (conn->alternate < conn->numAlts) + { + conn->alternate++; + ret = FSIO_READY; + } + else + conn->alternate = 0; + break; + } + } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); + if (ret == FSIO_READY) + conn->generation = ++generationCount; + return ret; +} + +static int +_fs_wait_connect (FSFpePtr conn) +{ + int ret; + + for (;;) + { + ret = _fs_do_setup_connection (conn); + if (ret != FSIO_BLOCK) + break; + if (conn->fs_conn_state <= FS_CONN_CONNECTING) + ret = _fs_poll_connect (conn->trans_conn, 1000); + else + ret = _fs_wait_for_readable (conn, 1000); + if (ret == FSIO_ERROR) + break; + } + return ret; +} + +/* + * Poll a connection in the process of reconnecting + */ +static void +_fs_check_reconnect (FSFpePtr conn) +{ + int ret; + + ret = _fs_do_setup_connection (conn); + switch (ret) { + case FSIO_READY: + _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); + _fs_restart_connection (conn); + break; + case FSIO_BLOCK: + break; + case FSIO_ERROR: + conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; + break; + } +} + +/* + * Start the reconnection process + */ +static void +_fs_start_reconnect (FSFpePtr conn) +{ + if (conn->blockState & FS_RECONNECTING) + return; + conn->alternate = 0; + _fs_mark_block (conn, FS_RECONNECTING); + _fs_unmark_block (conn, FS_BROKEN_CONNECTION); + _fs_check_reconnect (conn); +} + + +static FSFpePtr +_fs_init_conn (char *servername) +{ + FSFpePtr conn; + + conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); + if (!conn) + return 0; + if (!_fs_io_init (conn)) + { + free (conn); + return 0; + } + conn->servername = (char *) (conn + 1); + conn->fs_conn_state = FS_CONN_UNCONNECTED; + conn->fs_fd = -1; + strcpy (conn->servername, servername); + return conn; +} + +static void +_fs_free_conn (FSFpePtr conn) +{ + _fs_close_server (conn); + _fs_io_fini (conn); + if (conn->alts) + free (conn->alts); + free (conn); +} + +/* + * called at server init time + */ + +void +fs_register_fpe_functions(void) +{ + RegisterFPEFunctions(fs_name_check, + fs_init_fpe, + fs_free_fpe, + fs_reset_fpe, + fs_open_font, + fs_close_font, + fs_list_fonts, + fs_start_list_with_info, + fs_next_list_with_info, + fs_wakeup, + fs_client_died, + _fs_load_glyphs, + NULL, + NULL, + NULL); +} diff --git a/libXfont/src/fc/fserve.h b/libXfont/src/fc/fserve.h index 71f165ae1..5999861b6 100644 --- a/libXfont/src/fc/fserve.h +++ b/libXfont/src/fc/fserve.h @@ -1,91 +1,91 @@ -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - * - */ - -#ifndef _FSERVE_H_ -#define _FSERVE_H_ -/* - * font server data structures - */ - -/* types of block records */ -#define FS_OPEN_FONT 1 -#define FS_LOAD_GLYPHS 2 -#define FS_LIST_FONTS 3 -#define FS_LIST_WITH_INFO 4 - -/* states of OpenFont */ -#define FS_OPEN_REPLY 0 -#define FS_INFO_REPLY 1 -#define FS_EXTENT_REPLY 2 -#define FS_GLYPHS_REPLY 3 -#define FS_DONE_REPLY 4 -#define FS_DEPENDING 5 - -/* status of ListFontsWithInfo */ -#define FS_LFWI_WAITING 0 -#define FS_LFWI_REPLY 1 -#define FS_LFWI_FINISHED 2 - -/* states of connection */ -#define FS_CONN_CLOSED 0 -#define FS_CONN_CONNECTING 1 -#define FS_CONN_READ_HEADER 2 -#define FS_CONN_READ_DATA 3 - -#define AccessDone 0x400 - -typedef struct _fs_font_data *FSFontDataPtr; -typedef struct _fs_blocked_font *FSBlockedFontPtr; -typedef struct _fs_blocked_glyphs *FSBlockedGlyphPtr; -typedef struct _fs_blocked_list *FSBlockedListPtr; -typedef struct _fs_blocked_list_info *FSBlockedListInfoPtr; -typedef struct _fs_block_data *FSBlockDataPtr; -typedef struct _fs_font_table *FSFontTablePtr; -typedef struct _fs_fpe_data *FSFpePtr; - -typedef struct _fs_blocked_bitmaps *FSBlockedBitmapPtr; -typedef struct _fs_blocked_extents *FSBlockedExtentPtr; - -extern void _fs_convert_char_info ( fsXCharInfo *src, xCharInfo *dst ); -extern void _fs_free_props (FontInfoPtr pfi); -extern FontPtr fs_create_font (FontPathElementPtr fpe, - char *name, - int namelen, - fsBitmapFormat format, - fsBitmapFormatMask fmask); - -extern int fs_load_all_glyphs ( FontPtr pfont ); - -/* - * These should be declared elsewhere, but I'm concerned that moving them - * would cause problems building other pieces - */ -extern FontPtr find_old_font (Font id); -extern int set_font_authorizations (char **a, int *len, pointer client); -extern long GetTimeInMillis (void); - - -#endif /* _FSERVE_H_ */ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + * + */ + +#ifndef _FSERVE_H_ +#define _FSERVE_H_ +/* + * font server data structures + */ + +/* types of block records */ +#define FS_OPEN_FONT 1 +#define FS_LOAD_GLYPHS 2 +#define FS_LIST_FONTS 3 +#define FS_LIST_WITH_INFO 4 + +/* states of OpenFont */ +#define FS_OPEN_REPLY 0 +#define FS_INFO_REPLY 1 +#define FS_EXTENT_REPLY 2 +#define FS_GLYPHS_REPLY 3 +#define FS_DONE_REPLY 4 +#define FS_DEPENDING 5 + +/* status of ListFontsWithInfo */ +#define FS_LFWI_WAITING 0 +#define FS_LFWI_REPLY 1 +#define FS_LFWI_FINISHED 2 + +/* states of connection */ +#define FS_CONN_CLOSED 0 +#define FS_CONN_CONNECTING 1 +#define FS_CONN_READ_HEADER 2 +#define FS_CONN_READ_DATA 3 + +#define AccessDone 0x400 + +typedef struct _fs_font_data *FSFontDataPtr; +typedef struct _fs_blocked_font *FSBlockedFontPtr; +typedef struct _fs_blocked_glyphs *FSBlockedGlyphPtr; +typedef struct _fs_blocked_list *FSBlockedListPtr; +typedef struct _fs_blocked_list_info *FSBlockedListInfoPtr; +typedef struct _fs_block_data *FSBlockDataPtr; +typedef struct _fs_font_table *FSFontTablePtr; +typedef struct _fs_fpe_data *FSFpePtr; + +typedef struct _fs_blocked_bitmaps *FSBlockedBitmapPtr; +typedef struct _fs_blocked_extents *FSBlockedExtentPtr; + +extern void _fs_convert_char_info ( fsXCharInfo *src, xCharInfo *dst ); +extern void _fs_free_props (FontInfoPtr pfi); +extern FontPtr fs_create_font (FontPathElementPtr fpe, + char *name, + int namelen, + fsBitmapFormat format, + fsBitmapFormatMask fmask); + +extern int fs_load_all_glyphs ( FontPtr pfont ); + +/* + * These should be declared elsewhere, but I'm concerned that moving them + * would cause problems building other pieces + */ +extern FontPtr find_old_font (Font id); +extern int set_font_authorizations (char **a, int *len, pointer client); +extern long GetTimeInMillis (void); + + +#endif /* _FSERVE_H_ */ diff --git a/libXfont/src/fc/fservestr.h b/libXfont/src/fc/fservestr.h index 90f17c29e..a6d0d1d53 100644 --- a/libXfont/src/fc/fservestr.h +++ b/libXfont/src/fc/fservestr.h @@ -1,200 +1,200 @@ -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and - * its documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ - -#ifndef _FSERVESTR_H_ -#define _FSERVESTR_H_ - -#include "fserve.h" -#include "fsio.h" - -/* - * font server data structures - */ -/* - * font server private storage - */ - -typedef struct _fs_glyph { - struct _fs_glyph *next; -} FSGlyphRec, *FSGlyphPtr; - -typedef struct _fs_font { - CharInfoPtr pDefault; - CharInfoPtr encoding; - CharInfoPtr inkMetrics; - FSGlyphPtr glyphs; -} FSFontRec, *FSFontPtr; - -/* FS special data for the font */ -typedef struct _fs_font_data { - long fontid; - int generation; /* FS generation when opened */ - unsigned long glyphs_to_get; /* # glyphs remaining to be gotten */ - - /* Following data needed in case font needs to be reopened. */ - int namelen; - char *name; - fsBitmapFormat format; - fsBitmapFormatMask fmask; -} FSFontDataRec; - -typedef struct fs_clients_depending { - pointer client; - struct fs_clients_depending *next; -} FSClientsDependingRec, *FSClientsDependingPtr; - -/* OpenFont specific data for blocked request */ -typedef struct _fs_blocked_font { - FontPtr pfont; /* must be first for fs_read_glyphs */ - long fontid; - int state; /* how many of the replies have landed */ - int flags; - Bool freeFont; /* free this font on failure */ - CARD16 queryInfoSequence; - CARD16 queryExtentsSequence; - CARD16 queryBitmapsSequence; - fsBitmapFormat format; - FSClientsDependingPtr clients_depending; -} FSBlockedFontRec; - -/* LoadGlyphs data for blocked request */ -typedef struct _fs_blocked_glyphs { - FontPtr pfont; /* must be first for fs_read_glyphs */ - int num_expected_ranges; - fsRange *expected_ranges; - FSClientsDependingPtr clients_depending; -} FSBlockedGlyphRec; - -/* LoadExtents data for blocked request */ -typedef struct _fs_blocked_extents { - FontPtr pfont; - fsRange *expected_ranges; - int nranges; - unsigned long nextents; - fsXCharInfo *extents; -} FSBlockedExtentRec; - -/* LoadBitmaps data for blocked request */ -typedef struct _fs_blocked_bitmaps { - FontPtr pfont; - fsRange *expected_ranges; - int nranges; - unsigned long size; - unsigned long nglyphs; - fsOffset32 *offsets; - pointer gdata; -} FSBlockedBitmapRec; - -/* state for blocked ListFonts */ -typedef struct _fs_blocked_list { - FontNamesPtr names; -} FSBlockedListRec; - -/* state for blocked ListFontsWithInfo */ -typedef struct _fs_blocked_list_info { - int status; - int namelen; - FontInfoRec info; - char name[256]; - int remaining; -} FSBlockedListInfoRec; - -/* state for blocked request */ -typedef struct _fs_block_data { - int type; /* Open Font, LoadGlyphs, ListFonts, - * ListWithInfo */ - pointer client; /* who wants it */ - CARD16 sequenceNumber; /* expected */ - pointer data; /* type specific data */ - int errcode; /* Suspended, et al. */ - struct _fs_block_data *depending; /* clients depending on this one */ - struct _fs_block_data *next; -} FSBlockDataRec; - -/* state for reconnected to dead font server */ -typedef struct _fs_reconnect { - int i; -} FSReconnectRec, *FSReconnectPtr; - - -#if !defined(UNIXCPP) || defined(ANSICPP) -#define fsCat(x,y) x##_##y -#else -#define fsCat(x,y) x/**/_/**/y -#endif - - -/* copy XCharInfo parts of a protocol reply into a xCharInfo */ - -#define fsUnpack_XCharInfo(packet, structure) \ - (structure)->leftSideBearing = fsCat(packet,left); \ - (structure)->rightSideBearing = fsCat(packet,right); \ - (structure)->characterWidth = fsCat(packet,width); \ - (structure)->ascent = fsCat(packet,ascent); \ - (structure)->descent = fsCat(packet,descent); \ - (structure)->attributes = fsCat(packet,attributes) - - -/* copy XFontInfoHeader parts of a protocol reply into a FontInfoRec */ - -#define fsUnpack_XFontInfoHeader(packet, structure) \ - (structure)->allExist = ((packet)->font_header_flags & FontInfoAllCharsExist) != 0; \ - (structure)->drawDirection = \ - ((packet)->font_header_draw_direction == LeftToRightDrawDirection) ? \ - LeftToRight : RightToLeft; \ - (structure)->inkInside = ((packet)->font_header_flags & FontInfoInkInside) != 0; \ - \ - (structure)->firstRow = (packet)->font_hdr_char_range_min_char_high; \ - (structure)->firstCol = (packet)->font_hdr_char_range_min_char_low; \ - (structure)->lastRow = (packet)->font_hdr_char_range_max_char_high; \ - (structure)->lastCol = (packet)->font_hdr_char_range_max_char_low; \ - (structure)->defaultCh = (packet)->font_header_default_char_low \ - + ((packet)->font_header_default_char_high << 8); \ - \ - (structure)->fontDescent = (packet)->font_header_font_descent; \ - (structure)->fontAscent = (packet)->font_header_font_ascent; \ - \ - fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->minbounds); \ - fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->ink_minbounds); \ - fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->maxbounds); \ - fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->ink_maxbounds) - -extern void _fs_init_fontinfo ( FSFpePtr conn, FontInfoPtr pfi ); -extern int _fs_convert_props ( fsPropInfo *pi, fsPropOffset *po, pointer pd, - FontInfoPtr pfi ); -extern int _fs_convert_lfwi_reply ( FSFpePtr conn, FontInfoPtr pfi, - fsListFontsWithXInfoReply *fsrep, - fsPropInfo *pi, fsPropOffset *po, - pointer pd ); -extern int fs_build_range ( FontPtr pfont, Bool range_flag, - unsigned int count, int item_size, - unsigned char *data, int *nranges, - fsRange **ranges ); -extern void _fs_clean_aborted_loadglyphs ( FontPtr pfont, - int num_expected_ranges, - fsRange *expected_ranges ); -extern void _fs_init_font ( FontPtr pfont ); -extern pointer fs_alloc_glyphs (FontPtr pFont, int size); -#endif /* _FSERVESTR_H_ */ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ + +#ifndef _FSERVESTR_H_ +#define _FSERVESTR_H_ + +#include "fserve.h" +#include "fsio.h" + +/* + * font server data structures + */ +/* + * font server private storage + */ + +typedef struct _fs_glyph { + struct _fs_glyph *next; +} FSGlyphRec, *FSGlyphPtr; + +typedef struct _fs_font { + CharInfoPtr pDefault; + CharInfoPtr encoding; + CharInfoPtr inkMetrics; + FSGlyphPtr glyphs; +} FSFontRec, *FSFontPtr; + +/* FS special data for the font */ +typedef struct _fs_font_data { + long fontid; + int generation; /* FS generation when opened */ + unsigned long glyphs_to_get; /* # glyphs remaining to be gotten */ + + /* Following data needed in case font needs to be reopened. */ + int namelen; + char *name; + fsBitmapFormat format; + fsBitmapFormatMask fmask; +} FSFontDataRec; + +typedef struct fs_clients_depending { + pointer client; + struct fs_clients_depending *next; +} FSClientsDependingRec, *FSClientsDependingPtr; + +/* OpenFont specific data for blocked request */ +typedef struct _fs_blocked_font { + FontPtr pfont; /* must be first for fs_read_glyphs */ + long fontid; + int state; /* how many of the replies have landed */ + int flags; + Bool freeFont; /* free this font on failure */ + CARD16 queryInfoSequence; + CARD16 queryExtentsSequence; + CARD16 queryBitmapsSequence; + fsBitmapFormat format; + FSClientsDependingPtr clients_depending; +} FSBlockedFontRec; + +/* LoadGlyphs data for blocked request */ +typedef struct _fs_blocked_glyphs { + FontPtr pfont; /* must be first for fs_read_glyphs */ + int num_expected_ranges; + fsRange *expected_ranges; + FSClientsDependingPtr clients_depending; +} FSBlockedGlyphRec; + +/* LoadExtents data for blocked request */ +typedef struct _fs_blocked_extents { + FontPtr pfont; + fsRange *expected_ranges; + int nranges; + unsigned long nextents; + fsXCharInfo *extents; +} FSBlockedExtentRec; + +/* LoadBitmaps data for blocked request */ +typedef struct _fs_blocked_bitmaps { + FontPtr pfont; + fsRange *expected_ranges; + int nranges; + unsigned long size; + unsigned long nglyphs; + fsOffset32 *offsets; + pointer gdata; +} FSBlockedBitmapRec; + +/* state for blocked ListFonts */ +typedef struct _fs_blocked_list { + FontNamesPtr names; +} FSBlockedListRec; + +/* state for blocked ListFontsWithInfo */ +typedef struct _fs_blocked_list_info { + int status; + int namelen; + FontInfoRec info; + char name[256]; + int remaining; +} FSBlockedListInfoRec; + +/* state for blocked request */ +typedef struct _fs_block_data { + int type; /* Open Font, LoadGlyphs, ListFonts, + * ListWithInfo */ + pointer client; /* who wants it */ + CARD16 sequenceNumber; /* expected */ + pointer data; /* type specific data */ + int errcode; /* Suspended, et al. */ + struct _fs_block_data *depending; /* clients depending on this one */ + struct _fs_block_data *next; +} FSBlockDataRec; + +/* state for reconnected to dead font server */ +typedef struct _fs_reconnect { + int i; +} FSReconnectRec, *FSReconnectPtr; + + +#if !defined(UNIXCPP) || defined(ANSICPP) +#define fsCat(x,y) x##_##y +#else +#define fsCat(x,y) x/**/_/**/y +#endif + + +/* copy XCharInfo parts of a protocol reply into a xCharInfo */ + +#define fsUnpack_XCharInfo(packet, structure) \ + (structure)->leftSideBearing = fsCat(packet,left); \ + (structure)->rightSideBearing = fsCat(packet,right); \ + (structure)->characterWidth = fsCat(packet,width); \ + (structure)->ascent = fsCat(packet,ascent); \ + (structure)->descent = fsCat(packet,descent); \ + (structure)->attributes = fsCat(packet,attributes) + + +/* copy XFontInfoHeader parts of a protocol reply into a FontInfoRec */ + +#define fsUnpack_XFontInfoHeader(packet, structure) \ + (structure)->allExist = ((packet)->font_header_flags & FontInfoAllCharsExist) != 0; \ + (structure)->drawDirection = \ + ((packet)->font_header_draw_direction == LeftToRightDrawDirection) ? \ + LeftToRight : RightToLeft; \ + (structure)->inkInside = ((packet)->font_header_flags & FontInfoInkInside) != 0; \ + \ + (structure)->firstRow = (packet)->font_hdr_char_range_min_char_high; \ + (structure)->firstCol = (packet)->font_hdr_char_range_min_char_low; \ + (structure)->lastRow = (packet)->font_hdr_char_range_max_char_high; \ + (structure)->lastCol = (packet)->font_hdr_char_range_max_char_low; \ + (structure)->defaultCh = (packet)->font_header_default_char_low \ + + ((packet)->font_header_default_char_high << 8); \ + \ + (structure)->fontDescent = (packet)->font_header_font_descent; \ + (structure)->fontAscent = (packet)->font_header_font_ascent; \ + \ + fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->minbounds); \ + fsUnpack_XCharInfo((packet)->font_header_min_bounds, &(structure)->ink_minbounds); \ + fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->maxbounds); \ + fsUnpack_XCharInfo((packet)->font_header_max_bounds, &(structure)->ink_maxbounds) + +extern void _fs_init_fontinfo ( FSFpePtr conn, FontInfoPtr pfi ); +extern int _fs_convert_props ( fsPropInfo *pi, fsPropOffset *po, pointer pd, + FontInfoPtr pfi ); +extern int _fs_convert_lfwi_reply ( FSFpePtr conn, FontInfoPtr pfi, + fsListFontsWithXInfoReply *fsrep, + fsPropInfo *pi, fsPropOffset *po, + pointer pd ); +extern int fs_build_range ( FontPtr pfont, Bool range_flag, + unsigned int count, int item_size, + unsigned char *data, int *nranges, + fsRange **ranges ); +extern void _fs_clean_aborted_loadglyphs ( FontPtr pfont, + int num_expected_ranges, + fsRange *expected_ranges ); +extern void _fs_init_font ( FontPtr pfont ); +extern pointer fs_alloc_glyphs (FontPtr pFont, int size); +#endif /* _FSERVESTR_H_ */ diff --git a/libXfont/src/fc/fsio.c b/libXfont/src/fc/fsio.c index 29c0d7d26..552c5e62e 100644 --- a/libXfont/src/fc/fsio.c +++ b/libXfont/src/fc/fsio.c @@ -1,452 +1,452 @@ -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * font server i/o routines - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#ifdef WIN32 -#define _WILLWINSOCK_ -#include "X11/Xwinsock.h" -#include "X11/Xwindows.h" -#endif - -#define FONT_t -#define TRANS_CLIENT -#include "X11/Xtrans/Xtrans.h" -#include "X11/Xpoll.h" -#include -#include -#include -#include -#include "fservestr.h" - -#include -#include -#include -#if !defined(WIN32) -#ifndef Lynx -#include -#else -#include -#endif -#endif -#include -#ifdef WIN32 -#define EWOULDBLOCK WSAEWOULDBLOCK -#undef EINTR -#define EINTR WSAEINTR -#endif - - - -static int padlength[4] = {0, 3, 2, 1}; -fd_set _fs_fd_mask; - -static int -_fs_resize (FSBufPtr buf, long size); - -static void -_fs_downsize (FSBufPtr buf, long size); - -int -_fs_poll_connect (XtransConnInfo trans_conn, int timeout) -{ - fd_set w_mask; - struct timeval tv; - int fs_fd = _FontTransGetConnectionNumber (trans_conn); - int ret; - - do - { - tv.tv_usec = 0; - tv.tv_sec = timeout; - FD_ZERO (&w_mask); - FD_SET (fs_fd, &w_mask); - ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv); - } while (ret < 0 && ECHECK(EINTR)); - if (ret == 0) - return FSIO_BLOCK; - if (ret < 0) - return FSIO_ERROR; - return FSIO_READY; -} - -XtransConnInfo -_fs_connect(char *servername, int *err) -{ - XtransConnInfo trans_conn; /* transport connection object */ - int ret; - int i = 0; - int retries = 5; - - /* - * Open the network connection. - */ - if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL ) - { - *err = FSIO_ERROR; - return 0; - } - - /* - * Set the connection non-blocking since we use select() to block. - */ - - _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1); - - do { - i = _FontTransConnect(trans_conn,servername); - } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0)); - - if (i < 0) - { - if (i == TRANS_IN_PROGRESS) - ret = FSIO_BLOCK; - else - ret = FSIO_ERROR; - } - else - ret = FSIO_READY; - - if (ret == FSIO_ERROR) - { - _FontTransClose(trans_conn); - trans_conn = 0; - } - - *err = ret; - return trans_conn; -} - -static int -_fs_fill (FSFpePtr conn) -{ - long avail; - long bytes_read; - Bool waited = FALSE; - - if (_fs_flush (conn) < 0) - return FSIO_ERROR; - /* - * Don't go overboard here; stop reading when we've - * got enough to satisfy the pending request - */ - while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0) - { - avail = conn->inBuf.size - conn->inBuf.insert; - /* - * For SVR4 with a unix-domain connection, ETEST() after selecting - * readable means the server has died. To do this here, we look for - * two consecutive reads returning ETEST(). - */ - ESET (0); - bytes_read =_FontTransRead(conn->trans_conn, - conn->inBuf.buf + conn->inBuf.insert, - avail); - if (bytes_read > 0) { - conn->inBuf.insert += bytes_read; - waited = FALSE; - } - else - { - if (bytes_read == 0 || ETEST ()) - { - if (!waited) - { - waited = TRUE; - if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK) - return FSIO_BLOCK; - continue; - } - } - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - return FSIO_READY; -} - -/* - * Make space and return whether data have already arrived - */ - -int -_fs_start_read (FSFpePtr conn, long size, char **buf) -{ - int ret; - - conn->inNeed = size; - if (fs_inqueued(conn) < size) - { - if (_fs_resize (&conn->inBuf, size) != FSIO_READY) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - ret = _fs_fill (conn); - if (ret == FSIO_ERROR) - return ret; - if (ret == FSIO_BLOCK || fs_inqueued(conn) < size) - return FSIO_BLOCK; - } - if (buf) - *buf = conn->inBuf.buf + conn->inBuf.remove; - return FSIO_READY; -} - -void -_fs_done_read (FSFpePtr conn, long size) -{ - if (conn->inBuf.insert - conn->inBuf.remove < size) - { -#ifdef DEBUG - fprintf (stderr, "_fs_done_read skipping to many bytes\n"); -#endif - return; - } - conn->inBuf.remove += size; - conn->inNeed -= size; - _fs_downsize (&conn->inBuf, FS_BUF_MAX); -} - -long -_fs_pad_length (long len) -{ - return len + padlength[len&3]; -} - -int -_fs_flush (FSFpePtr conn) -{ - long bytes_written; - long remain; - - /* XXX - hack. The right fix is to remember that the font server - has gone away when we first discovered it. */ - if (conn->fs_fd < 0) - return FSIO_ERROR; - - while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0) - { - bytes_written = _FontTransWrite(conn->trans_conn, - conn->outBuf.buf + conn->outBuf.remove, - (int) remain); - if (bytes_written > 0) - { - conn->outBuf.remove += bytes_written; - } - else - { - if (bytes_written == 0 || ETEST ()) - { - conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL; - _fs_mark_block (conn, FS_BROKEN_WRITE); - break; - } - if (!ECHECK (EINTR)) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - } - if (conn->outBuf.remove == conn->outBuf.insert) - { - _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE); - if (conn->outBuf.size > FS_BUF_INC) - conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC); - conn->outBuf.remove = conn->outBuf.insert = 0; - } - return FSIO_READY; -} - -static int -_fs_resize (FSBufPtr buf, long size) -{ - char *new; - long new_size; - - if (buf->remove) - { - if (buf->remove != buf->insert) - { - memmove (buf->buf, - buf->buf + buf->remove, - buf->insert - buf->remove); - } - buf->insert -= buf->remove; - buf->remove = 0; - } - if (buf->size - buf->remove < size) - { - new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC; - new = realloc (buf->buf, new_size); - if (!new) - return FSIO_ERROR; - buf->buf = new; - buf->size = new_size; - } - return FSIO_READY; -} - -static void -_fs_downsize (FSBufPtr buf, long size) -{ - if (buf->insert == buf->remove) - { - buf->insert = buf->remove = 0; - if (buf->size > size) - { - buf->buf = realloc (buf->buf, size); - buf->size = size; - } - } -} - -void -_fs_io_reinit (FSFpePtr conn) -{ - conn->outBuf.insert = conn->outBuf.remove = 0; - _fs_downsize (&conn->outBuf, FS_BUF_INC); - conn->inBuf.insert = conn->inBuf.remove = 0; - _fs_downsize (&conn->inBuf, FS_BUF_MAX); -} - -Bool -_fs_io_init (FSFpePtr conn) -{ - conn->outBuf.insert = conn->outBuf.remove = 0; - conn->outBuf.buf = malloc (FS_BUF_INC); - if (!conn->outBuf.buf) - return FALSE; - conn->outBuf.size = FS_BUF_INC; - - conn->inBuf.insert = conn->inBuf.remove = 0; - conn->inBuf.buf = malloc (FS_BUF_INC); - if (!conn->inBuf.buf) - { - free (conn->outBuf.buf); - conn->outBuf.buf = 0; - return FALSE; - } - conn->inBuf.size = FS_BUF_INC; - - return TRUE; -} - -void -_fs_io_fini (FSFpePtr conn) -{ - if (conn->outBuf.buf) - free (conn->outBuf.buf); - if (conn->inBuf.buf) - free (conn->inBuf.buf); -} - -static int -_fs_do_write(FSFpePtr conn, char *data, long len, long size) -{ - if (size == 0) { -#ifdef DEBUG - fprintf(stderr, "tried to write 0 bytes \n"); -#endif - return FSIO_READY; - } - - if (conn->fs_fd == -1) - return FSIO_ERROR; - - while (conn->outBuf.insert + size > conn->outBuf.size) - { - if (_fs_flush (conn) < 0) - return FSIO_ERROR; - if (_fs_resize (&conn->outBuf, size) < 0) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len); - /* Clear pad data */ - memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len); - conn->outBuf.insert += size; - _fs_mark_block (conn, FS_PENDING_WRITE); - return FSIO_READY; -} - -/* - * Write the indicated bytes - */ -int -_fs_write (FSFpePtr conn, char *data, long len) -{ - return _fs_do_write (conn, data, len, len); -} - -/* - * Write the indicated bytes adding any appropriate pad - */ -int -_fs_write_pad(FSFpePtr conn, char *data, long len) -{ - return _fs_do_write (conn, data, len, len + padlength[len & 3]); -} - -int -_fs_wait_for_readable(FSFpePtr conn, int ms) -{ - fd_set r_mask; - fd_set e_mask; - int result; - struct timeval tv; - - for (;;) { - if (conn->fs_fd < 0) - return FSIO_ERROR; - FD_ZERO(&r_mask); - FD_ZERO(&e_mask); - tv.tv_sec = ms / 1000; - tv.tv_usec = (ms % 1000) * 1000; - FD_SET(conn->fs_fd, &r_mask); - FD_SET(conn->fs_fd, &e_mask); - result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv); - if (result < 0) - { - if (ECHECK(EINTR) || ECHECK(EAGAIN)) - continue; - else - return FSIO_ERROR; - } - if (result == 0) - return FSIO_BLOCK; - if (FD_ISSET(conn->fs_fd, &r_mask)) - return FSIO_READY; - return FSIO_ERROR; - } -} +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ +/* + * font server i/o routines + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef WIN32 +#define _WILLWINSOCK_ +#include "X11/Xwinsock.h" +#include "X11/Xwindows.h" +#endif + +#define FONT_t +#define TRANS_CLIENT +#include "X11/Xtrans/Xtrans.h" +#include "X11/Xpoll.h" +#include +#include +#include +#include +#include "fservestr.h" + +#include +#include +#include +#if !defined(WIN32) +#ifndef Lynx +#include +#else +#include +#endif +#endif +#include +#ifdef WIN32 +#define EWOULDBLOCK WSAEWOULDBLOCK +#undef EINTR +#define EINTR WSAEINTR +#endif + + + +static int padlength[4] = {0, 3, 2, 1}; +fd_set _fs_fd_mask; + +static int +_fs_resize (FSBufPtr buf, long size); + +static void +_fs_downsize (FSBufPtr buf, long size); + +int +_fs_poll_connect (XtransConnInfo trans_conn, int timeout) +{ + fd_set w_mask; + struct timeval tv; + int fs_fd = _FontTransGetConnectionNumber (trans_conn); + int ret; + + do + { + tv.tv_usec = 0; + tv.tv_sec = timeout; + FD_ZERO (&w_mask); + FD_SET (fs_fd, &w_mask); + ret = Select (fs_fd + 1, NULL, &w_mask, NULL, &tv); + } while (ret < 0 && ECHECK(EINTR)); + if (ret == 0) + return FSIO_BLOCK; + if (ret < 0) + return FSIO_ERROR; + return FSIO_READY; +} + +XtransConnInfo +_fs_connect(char *servername, int *err) +{ + XtransConnInfo trans_conn; /* transport connection object */ + int ret; + int i = 0; + int retries = 5; + + /* + * Open the network connection. + */ + if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL ) + { + *err = FSIO_ERROR; + return 0; + } + + /* + * Set the connection non-blocking since we use select() to block. + */ + + _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1); + + do { + i = _FontTransConnect(trans_conn,servername); + } while ((i == TRANS_TRY_CONNECT_AGAIN) && (retries-- > 0)); + + if (i < 0) + { + if (i == TRANS_IN_PROGRESS) + ret = FSIO_BLOCK; + else + ret = FSIO_ERROR; + } + else + ret = FSIO_READY; + + if (ret == FSIO_ERROR) + { + _FontTransClose(trans_conn); + trans_conn = 0; + } + + *err = ret; + return trans_conn; +} + +static int +_fs_fill (FSFpePtr conn) +{ + long avail; + long bytes_read; + Bool waited = FALSE; + + if (_fs_flush (conn) < 0) + return FSIO_ERROR; + /* + * Don't go overboard here; stop reading when we've + * got enough to satisfy the pending request + */ + while ((conn->inNeed - (conn->inBuf.insert - conn->inBuf.remove)) > 0) + { + avail = conn->inBuf.size - conn->inBuf.insert; + /* + * For SVR4 with a unix-domain connection, ETEST() after selecting + * readable means the server has died. To do this here, we look for + * two consecutive reads returning ETEST(). + */ + ESET (0); + bytes_read =_FontTransRead(conn->trans_conn, + conn->inBuf.buf + conn->inBuf.insert, + avail); + if (bytes_read > 0) { + conn->inBuf.insert += bytes_read; + waited = FALSE; + } + else + { + if (bytes_read == 0 || ETEST ()) + { + if (!waited) + { + waited = TRUE; + if (_fs_wait_for_readable (conn, 0) == FSIO_BLOCK) + return FSIO_BLOCK; + continue; + } + } + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + return FSIO_READY; +} + +/* + * Make space and return whether data have already arrived + */ + +int +_fs_start_read (FSFpePtr conn, long size, char **buf) +{ + int ret; + + conn->inNeed = size; + if (fs_inqueued(conn) < size) + { + if (_fs_resize (&conn->inBuf, size) != FSIO_READY) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + ret = _fs_fill (conn); + if (ret == FSIO_ERROR) + return ret; + if (ret == FSIO_BLOCK || fs_inqueued(conn) < size) + return FSIO_BLOCK; + } + if (buf) + *buf = conn->inBuf.buf + conn->inBuf.remove; + return FSIO_READY; +} + +void +_fs_done_read (FSFpePtr conn, long size) +{ + if (conn->inBuf.insert - conn->inBuf.remove < size) + { +#ifdef DEBUG + fprintf (stderr, "_fs_done_read skipping to many bytes\n"); +#endif + return; + } + conn->inBuf.remove += size; + conn->inNeed -= size; + _fs_downsize (&conn->inBuf, FS_BUF_MAX); +} + +long +_fs_pad_length (long len) +{ + return len + padlength[len&3]; +} + +int +_fs_flush (FSFpePtr conn) +{ + long bytes_written; + long remain; + + /* XXX - hack. The right fix is to remember that the font server + has gone away when we first discovered it. */ + if (conn->fs_fd < 0) + return FSIO_ERROR; + + while ((remain = conn->outBuf.insert - conn->outBuf.remove) > 0) + { + bytes_written = _FontTransWrite(conn->trans_conn, + conn->outBuf.buf + conn->outBuf.remove, + (int) remain); + if (bytes_written > 0) + { + conn->outBuf.remove += bytes_written; + } + else + { + if (bytes_written == 0 || ETEST ()) + { + conn->brokenWriteTime = GetTimeInMillis () + FS_FLUSH_POLL; + _fs_mark_block (conn, FS_BROKEN_WRITE); + break; + } + if (!ECHECK (EINTR)) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + } + if (conn->outBuf.remove == conn->outBuf.insert) + { + _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE); + if (conn->outBuf.size > FS_BUF_INC) + conn->outBuf.buf = realloc (conn->outBuf.buf, FS_BUF_INC); + conn->outBuf.remove = conn->outBuf.insert = 0; + } + return FSIO_READY; +} + +static int +_fs_resize (FSBufPtr buf, long size) +{ + char *new; + long new_size; + + if (buf->remove) + { + if (buf->remove != buf->insert) + { + memmove (buf->buf, + buf->buf + buf->remove, + buf->insert - buf->remove); + } + buf->insert -= buf->remove; + buf->remove = 0; + } + if (buf->size - buf->remove < size) + { + new_size = ((buf->remove + size + FS_BUF_INC) / FS_BUF_INC) * FS_BUF_INC; + new = realloc (buf->buf, new_size); + if (!new) + return FSIO_ERROR; + buf->buf = new; + buf->size = new_size; + } + return FSIO_READY; +} + +static void +_fs_downsize (FSBufPtr buf, long size) +{ + if (buf->insert == buf->remove) + { + buf->insert = buf->remove = 0; + if (buf->size > size) + { + buf->buf = realloc (buf->buf, size); + buf->size = size; + } + } +} + +void +_fs_io_reinit (FSFpePtr conn) +{ + conn->outBuf.insert = conn->outBuf.remove = 0; + _fs_downsize (&conn->outBuf, FS_BUF_INC); + conn->inBuf.insert = conn->inBuf.remove = 0; + _fs_downsize (&conn->inBuf, FS_BUF_MAX); +} + +Bool +_fs_io_init (FSFpePtr conn) +{ + conn->outBuf.insert = conn->outBuf.remove = 0; + conn->outBuf.buf = malloc (FS_BUF_INC); + if (!conn->outBuf.buf) + return FALSE; + conn->outBuf.size = FS_BUF_INC; + + conn->inBuf.insert = conn->inBuf.remove = 0; + conn->inBuf.buf = malloc (FS_BUF_INC); + if (!conn->inBuf.buf) + { + free (conn->outBuf.buf); + conn->outBuf.buf = 0; + return FALSE; + } + conn->inBuf.size = FS_BUF_INC; + + return TRUE; +} + +void +_fs_io_fini (FSFpePtr conn) +{ + if (conn->outBuf.buf) + free (conn->outBuf.buf); + if (conn->inBuf.buf) + free (conn->inBuf.buf); +} + +static int +_fs_do_write(FSFpePtr conn, char *data, long len, long size) +{ + if (size == 0) { +#ifdef DEBUG + fprintf(stderr, "tried to write 0 bytes \n"); +#endif + return FSIO_READY; + } + + if (conn->fs_fd == -1) + return FSIO_ERROR; + + while (conn->outBuf.insert + size > conn->outBuf.size) + { + if (_fs_flush (conn) < 0) + return FSIO_ERROR; + if (_fs_resize (&conn->outBuf, size) < 0) + { + _fs_connection_died (conn); + return FSIO_ERROR; + } + } + memcpy (conn->outBuf.buf + conn->outBuf.insert, data, len); + /* Clear pad data */ + memset (conn->outBuf.buf + conn->outBuf.insert + len, 0, size - len); + conn->outBuf.insert += size; + _fs_mark_block (conn, FS_PENDING_WRITE); + return FSIO_READY; +} + +/* + * Write the indicated bytes + */ +int +_fs_write (FSFpePtr conn, char *data, long len) +{ + return _fs_do_write (conn, data, len, len); +} + +/* + * Write the indicated bytes adding any appropriate pad + */ +int +_fs_write_pad(FSFpePtr conn, char *data, long len) +{ + return _fs_do_write (conn, data, len, len + padlength[len & 3]); +} + +int +_fs_wait_for_readable(FSFpePtr conn, int ms) +{ + fd_set r_mask; + fd_set e_mask; + int result; + struct timeval tv; + + for (;;) { + if (conn->fs_fd < 0) + return FSIO_ERROR; + FD_ZERO(&r_mask); + FD_ZERO(&e_mask); + tv.tv_sec = ms / 1000; + tv.tv_usec = (ms % 1000) * 1000; + FD_SET(conn->fs_fd, &r_mask); + FD_SET(conn->fs_fd, &e_mask); + result = Select(conn->fs_fd + 1, &r_mask, NULL, &e_mask, &tv); + if (result < 0) + { + if (ECHECK(EINTR) || ECHECK(EAGAIN)) + continue; + else + return FSIO_ERROR; + } + if (result == 0) + return FSIO_BLOCK; + if (FD_ISSET(conn->fs_fd, &r_mask)) + return FSIO_READY; + return FSIO_ERROR; + } +} diff --git a/libXfont/src/fc/fsio.h b/libXfont/src/fc/fsio.h index 0105e4909..bd0c621e8 100644 --- a/libXfont/src/fc/fsio.h +++ b/libXfont/src/fc/fsio.h @@ -1,178 +1,178 @@ -/* - * Copyright 1990 Network Computing Devices - * - * Permission to use, copy, modify, distribute, and sell this software and its - * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be - * used in advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. Network Computing - * Devices makes no representations about the suitability of this software - * for any purpose. It is provided "as is" without express or implied - * warranty. - * - * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, - * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, - * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE - * OR PERFORMANCE OF THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ - -#ifndef _FSIO_H_ -#define _FSIO_H_ - -#undef DEBUG -#define REQUEST_LOG_SIZE 100 - -typedef struct _fs_fpe_alternate { - char *name; - Bool subset; -} FSFpeAltRec, *FSFpeAltPtr; - - -/* Per client access contexts */ -typedef struct _fs_client_data { - pointer client; - struct _fs_client_data *next; - XID acid; - int auth_generation; -} FSClientRec, *FSClientPtr; - -#define FS_RECONNECT_POLL 1000 -#define FS_RECONNECT_WAIT 5000 -#define FS_GIVEUP_WAIT 20000 -#define FS_REQUEST_TIMEOUT 20000 -#define FS_OPEN_TIMEOUT 30000 -#define FS_REOPEN_TIMEOUT 10000 -#define FS_FLUSH_POLL 1000 - -typedef struct _fs_buf { - char *buf; /* data */ - long size; /* sizeof data */ - long insert; /* where to insert new data */ - long remove; /* where to remove old data */ -} FSBufRec, *FSBufPtr; - -#define FS_BUF_INC 1024 -#define FS_BUF_MAX 32768 - -#define FS_PENDING_WRITE 0x01 /* some write data is queued */ -#define FS_BROKEN_WRITE 0x02 /* writes are broken */ -#define FS_BROKEN_CONNECTION 0x04 /* connection is broken */ -#define FS_PENDING_REPLY 0x08 /* waiting for a reply */ -#define FS_GIVE_UP 0x10 /* font server declared useless */ -#define FS_COMPLETE_REPLY 0x20 /* complete reply ready */ -#define FS_RECONNECTING 0x40 - -#define FS_CONN_UNCONNECTED 0 -#define FS_CONN_CONNECTING 1 -#define FS_CONN_CONNECTED 2 -#define FS_CONN_SENT_PREFIX 3 -#define FS_CONN_RECV_INIT 4 -#define FS_CONN_SENT_CAT 5 -#define FS_CONN_RUNNING 6 - -/* FS specific font FontPathElement data */ -typedef struct _fs_fpe_data { - FSFpePtr next; /* list of all active fs fpes */ - int fs_fd; /* < 0 when not running */ - int fs_conn_state; /* connection state */ - int current_seq; - char *servername; - Bool has_catalogues; - - int generation; - int numAlts; - int alternate; /* which alternate is in use +1 */ - int fsMajorVersion; /* font server major version number */ - FSFpeAltPtr alts; - - FSClientPtr clients; - XID curacid; -#ifdef DEBUG - int reqindex; - struct { - int opcode; - int sequence; - } reqbuffer[REQUEST_LOG_SIZE]; -#endif - FSBufRec outBuf; /* request queue */ - FSBufRec inBuf; /* reply queue */ - long inNeed; /* amount needed for reply */ - - CARD32 blockState; - CARD32 blockedReplyTime; /* time to abort blocked read */ - CARD32 brokenWriteTime; /* time to retry broken write */ - CARD32 blockedConnectTime; /* time to abort blocked connect */ - CARD32 brokenConnectionTime; /* time to retry broken connection */ - - FSBlockDataPtr blockedRequests; - - struct _XtransConnInfo *trans_conn; /* transport connection object */ -} FSFpeRec; - -#define fs_outspace(conn) ((conn)->outBuf.size - (conn)->outBuf.insert) -#define fs_outqueued(conn) ((conn)->outBuf.insert - (conn)->outBuf.remove) -#define fs_inqueued(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) -#define fs_needsflush(conn) (fs_outqueued(conn) != 0) -#define fs_needsfill(conn) (fs_inqueued(conn) < (conn)->inNeed) -#define fs_needsconnect(conn) ((conn)->fs_fd < 0) -#define fs_data_read(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) - -#define FSIO_READY 1 -#define FSIO_BLOCK 0 -#define FSIO_ERROR -1 - -extern Bool _fs_reopen_server ( FSFpePtr conn ); -extern int _fs_write ( FSFpePtr conn, char *data, long size ); -extern int _fs_write_pad ( FSFpePtr conn, char *data, long len ); -extern int _fs_wait_for_readable ( FSFpePtr conn, int ms ); -extern long _fs_pad_length (long len); - -extern void _fs_connection_died ( FSFpePtr conn ); - -extern int _fs_flush (FSFpePtr conn); -extern void _fs_mark_block (FSFpePtr conn, CARD32 mask); -extern void _fs_unmark_block (FSFpePtr conn, CARD32 mask); -extern void _fs_done_read (FSFpePtr conn, long size); -extern void _fs_io_reinit (FSFpePtr conn); -extern int _fs_start_read (FSFpePtr conn, long size, char **buf); -extern Bool _fs_io_init (FSFpePtr conn); -extern void _fs_io_fini (FSFpePtr conn); -extern int _fs_poll_connect (XtransConnInfo trans_conn, int timeout); -extern XtransConnInfo _fs_connect(char *servername, int *ret); - -/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX - * systems are broken and return EWOULDBLOCK when they should return EAGAIN - */ -#ifdef WIN32 -#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) -#else -#if defined(EAGAIN) && defined(EWOULDBLOCK) -#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) -#else -#ifdef EAGAIN -#define ETEST() (errno == EAGAIN) -#else -#define ETEST() (errno == EWOULDBLOCK) -#endif -#endif -#endif -#ifdef WIN32 -#define ECHECK(err) (WSAGetLastError() == err) -#define ESET(val) WSASetLastError(val) -#else -#ifdef ISC -#define ECHECK(err) ((errno == err) || ETEST()) -#else -#define ECHECK(err) (errno == err) -#endif -#define ESET(val) errno = val -#endif - -#endif /* _FSIO_H_ */ +/* + * Copyright 1990 Network Computing Devices + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, 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 Network Computing Devices not be + * used in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. Network Computing + * Devices makes no representations about the suitability of this software + * for any purpose. It is provided "as is" without express or implied + * warranty. + * + * NETWORK COMPUTING DEVICES DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NETWORK COMPUTING DEVICES BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE + * OR PERFORMANCE OF THIS SOFTWARE. + * + * Author: Dave Lemke, Network Computing Devices, Inc + */ + +#ifndef _FSIO_H_ +#define _FSIO_H_ + +#undef DEBUG +#define REQUEST_LOG_SIZE 100 + +typedef struct _fs_fpe_alternate { + char *name; + Bool subset; +} FSFpeAltRec, *FSFpeAltPtr; + + +/* Per client access contexts */ +typedef struct _fs_client_data { + pointer client; + struct _fs_client_data *next; + XID acid; + int auth_generation; +} FSClientRec, *FSClientPtr; + +#define FS_RECONNECT_POLL 1000 +#define FS_RECONNECT_WAIT 5000 +#define FS_GIVEUP_WAIT 20000 +#define FS_REQUEST_TIMEOUT 20000 +#define FS_OPEN_TIMEOUT 30000 +#define FS_REOPEN_TIMEOUT 10000 +#define FS_FLUSH_POLL 1000 + +typedef struct _fs_buf { + char *buf; /* data */ + long size; /* sizeof data */ + long insert; /* where to insert new data */ + long remove; /* where to remove old data */ +} FSBufRec, *FSBufPtr; + +#define FS_BUF_INC 1024 +#define FS_BUF_MAX 32768 + +#define FS_PENDING_WRITE 0x01 /* some write data is queued */ +#define FS_BROKEN_WRITE 0x02 /* writes are broken */ +#define FS_BROKEN_CONNECTION 0x04 /* connection is broken */ +#define FS_PENDING_REPLY 0x08 /* waiting for a reply */ +#define FS_GIVE_UP 0x10 /* font server declared useless */ +#define FS_COMPLETE_REPLY 0x20 /* complete reply ready */ +#define FS_RECONNECTING 0x40 + +#define FS_CONN_UNCONNECTED 0 +#define FS_CONN_CONNECTING 1 +#define FS_CONN_CONNECTED 2 +#define FS_CONN_SENT_PREFIX 3 +#define FS_CONN_RECV_INIT 4 +#define FS_CONN_SENT_CAT 5 +#define FS_CONN_RUNNING 6 + +/* FS specific font FontPathElement data */ +typedef struct _fs_fpe_data { + FSFpePtr next; /* list of all active fs fpes */ + int fs_fd; /* < 0 when not running */ + int fs_conn_state; /* connection state */ + int current_seq; + char *servername; + Bool has_catalogues; + + int generation; + int numAlts; + int alternate; /* which alternate is in use +1 */ + int fsMajorVersion; /* font server major version number */ + FSFpeAltPtr alts; + + FSClientPtr clients; + XID curacid; +#ifdef DEBUG + int reqindex; + struct { + int opcode; + int sequence; + } reqbuffer[REQUEST_LOG_SIZE]; +#endif + FSBufRec outBuf; /* request queue */ + FSBufRec inBuf; /* reply queue */ + long inNeed; /* amount needed for reply */ + + CARD32 blockState; + CARD32 blockedReplyTime; /* time to abort blocked read */ + CARD32 brokenWriteTime; /* time to retry broken write */ + CARD32 blockedConnectTime; /* time to abort blocked connect */ + CARD32 brokenConnectionTime; /* time to retry broken connection */ + + FSBlockDataPtr blockedRequests; + + struct _XtransConnInfo *trans_conn; /* transport connection object */ +} FSFpeRec; + +#define fs_outspace(conn) ((conn)->outBuf.size - (conn)->outBuf.insert) +#define fs_outqueued(conn) ((conn)->outBuf.insert - (conn)->outBuf.remove) +#define fs_inqueued(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) +#define fs_needsflush(conn) (fs_outqueued(conn) != 0) +#define fs_needsfill(conn) (fs_inqueued(conn) < (conn)->inNeed) +#define fs_needsconnect(conn) ((conn)->fs_fd < 0) +#define fs_data_read(conn) ((conn)->inBuf.insert - (conn)->inBuf.remove) + +#define FSIO_READY 1 +#define FSIO_BLOCK 0 +#define FSIO_ERROR -1 + +extern Bool _fs_reopen_server ( FSFpePtr conn ); +extern int _fs_write ( FSFpePtr conn, char *data, long size ); +extern int _fs_write_pad ( FSFpePtr conn, char *data, long len ); +extern int _fs_wait_for_readable ( FSFpePtr conn, int ms ); +extern long _fs_pad_length (long len); + +extern void _fs_connection_died ( FSFpePtr conn ); + +extern int _fs_flush (FSFpePtr conn); +extern void _fs_mark_block (FSFpePtr conn, CARD32 mask); +extern void _fs_unmark_block (FSFpePtr conn, CARD32 mask); +extern void _fs_done_read (FSFpePtr conn, long size); +extern void _fs_io_reinit (FSFpePtr conn); +extern int _fs_start_read (FSFpePtr conn, long size, char **buf); +extern Bool _fs_io_init (FSFpePtr conn); +extern void _fs_io_fini (FSFpePtr conn); +extern int _fs_poll_connect (XtransConnInfo trans_conn, int timeout); +extern XtransConnInfo _fs_connect(char *servername, int *ret); + +/* check for both EAGAIN and EWOULDBLOCK, because some supposedly POSIX + * systems are broken and return EWOULDBLOCK when they should return EAGAIN + */ +#ifdef WIN32 +#define ETEST() (WSAGetLastError() == WSAEWOULDBLOCK) +#else +#if defined(EAGAIN) && defined(EWOULDBLOCK) +#define ETEST() (errno == EAGAIN || errno == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define ETEST() (errno == EAGAIN) +#else +#define ETEST() (errno == EWOULDBLOCK) +#endif +#endif +#endif +#ifdef WIN32 +#define ECHECK(err) (WSAGetLastError() == err) +#define ESET(val) WSASetLastError(val) +#else +#ifdef ISC +#define ECHECK(err) ((errno == err) || ETEST()) +#else +#define ECHECK(err) (errno == err) +#endif +#define ESET(val) errno = val +#endif + +#endif /* _FSIO_H_ */ diff --git a/libXfont/src/fc/fslibos.h b/libXfont/src/fc/fslibos.h index c7c745616..c49f52e5b 100644 --- a/libXfont/src/fc/fslibos.h +++ b/libXfont/src/fc/fslibos.h @@ -1,218 +1,218 @@ -/* - * Copyright 1990 Network Computing Devices; - * Portions Copyright 1987 by Digital Equipment Corporation - */ - -/* - -Copyright 1987, 1994, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall -not be used in advertising or otherwise to promote the sale, use or -other dealings in this Software without prior written authorization -from The Open Group. - -*/ - -/* - * FSlib networking & os include file - */ - -#include - -#ifndef WIN32 - -/* - * makedepend screws up on #undef OPEN_MAX, so we define a new symbol - */ - -#ifndef FONT_OPEN_MAX - -#ifndef X_NOT_POSIX -# ifdef _POSIX_SOURCE -# include -# else -# define _POSIX_SOURCE -# include -# undef _POSIX_SOURCE -# endif -#endif -#ifndef SIZE_MAX -# ifdef ULONG_MAX -# define SIZE_MAX ULONG_MAX -# else -# define SIZE_MAX UINT_MAX -# endif -#endif -#ifndef OPEN_MAX -#if defined(SVR4) -#define OPEN_MAX 256 -#else -#include -#ifndef OPEN_MAX -#ifdef __OSF1__ -#define OPEN_MAX 256 -#else -#ifdef NOFILE -#define OPEN_MAX NOFILE -#else -#define OPEN_MAX NOFILES_MAX -#endif -#endif -#endif -#endif -#endif - -#if OPEN_MAX > 256 -#define FONT_OPEN_MAX 256 -#else -#define FONT_OPEN_MAX OPEN_MAX -#endif - -#endif /* FONT_OPEN_MAX */ - -#ifdef WORD64 -#define NMSKBITS 64 -#else -#define NMSKBITS 32 -#endif - -#define MSKCNT ((FONT_OPEN_MAX + NMSKBITS - 1) / NMSKBITS) - -typedef unsigned long FdSet[MSKCNT]; -typedef FdSet FdSetPtr; - -#if (MSKCNT==1) -#define BITMASK(i) (1 << (i)) -#define MASKIDX(i) 0 -#endif - -#if (MSKCNT>1) -#define BITMASK(i) (1 << ((i) & (NMSKBITS - 1))) -#define MASKIDX(i) ((i) / NMSKBITS) -#endif - -#define MASKWORD(buf, i) buf[MASKIDX(i)] -#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) -#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) -#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) - -#if (MSKCNT==1) -#define COPYBITS(src, dst) dst[0] = src[0] -#define CLEARBITS(buf) buf[0] = 0 -#define MASKANDSETBITS(dst, b1, b2) dst[0] = (b1[0] & b2[0]) -#define ORBITS(dst, b1, b2) dst[0] = (b1[0] | b2[0]) -#define UNSETBITS(dst, b1) (dst[0] &= ~b1[0]) -#define ANYSET(src) (src[0]) -#endif - -#if (MSKCNT==2) -#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; } -#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; } -#define MASKANDSETBITS(dst, b1, b2) {\ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]); } -#define ORBITS(dst, b1, b2) {\ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]); } -#define UNSETBITS(dst, b1) {\ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; } -#define ANYSET(src) (src[0] || src[1]) -#endif - -#if (MSKCNT==3) -#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; \ - dst[2] = src[2]; } -#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; buf[2] = 0; } -#define MASKANDSETBITS(dst, b1, b2) {\ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]);\ - dst[2] = (b1[2] & b2[2]); } -#define ORBITS(dst, b1, b2) {\ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]);\ - dst[2] = (b1[2] | b2[2]); } -#define UNSETBITS(dst, b1) {\ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; \ - dst[2] &= ~b1[2]; } -#define ANYSET(src) (src[0] || src[1] || src[2]) -#endif - -#if (MSKCNT==4) -#define COPYBITS(src, dst) dst[0] = src[0]; dst[1] = src[1]; \ - dst[2] = src[2]; dst[3] = src[3] -#define CLEARBITS(buf) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0 -#define MASKANDSETBITS(dst, b1, b2) \ - dst[0] = (b1[0] & b2[0]);\ - dst[1] = (b1[1] & b2[1]);\ - dst[2] = (b1[2] & b2[2]);\ - dst[3] = (b1[3] & b2[3]) -#define ORBITS(dst, b1, b2) \ - dst[0] = (b1[0] | b2[0]);\ - dst[1] = (b1[1] | b2[1]);\ - dst[2] = (b1[2] | b2[2]);\ - dst[3] = (b1[3] | b2[3]) -#define UNSETBITS(dst, b1) \ - dst[0] &= ~b1[0]; \ - dst[1] &= ~b1[1]; \ - dst[2] &= ~b1[2]; \ - dst[3] &= ~b1[3] -#define ANYSET(src) (src[0] || src[1] || src[2] || src[3]) -#endif - -#if (MSKCNT>4) -#define COPYBITS(src, dst) memmove((caddr_t) dst, (caddr_t) src,\ - MSKCNT*sizeof(long)) -#define CLEARBITS(buf) bzero((caddr_t) buf, MSKCNT*sizeof(long)) -#define MASKANDSETBITS(dst, b1, b2) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] = (b1[cri] & b2[cri]); } -#define ORBITS(dst, b1, b2) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] = (b1[cri] | b2[cri]); } -#define UNSETBITS(dst, b1) \ - { int cri; \ - for (cri=MSKCNT; --cri>=0; ) \ - dst[cri] &= ~b1[cri]; } -#if (MSKCNT==8) -#define ANYSET(src) (src[0] || src[1] || src[2] || src[3] || \ - src[4] || src[5] || src[6] || src[7]) -#endif -#endif - -#else /* not WIN32 */ - -#include -#include - -typedef fd_set FdSet; -typedef FdSet *FdSetPtr; - -#define CLEARBITS(set) FD_ZERO(&set) -#define BITSET(set,s) FD_SET(s,&set) -#define BITCLEAR(set,s) FD_CLR(s,&set) -#define GETBIT(set,s) FD_ISSET(s,&set) -#define ANYSET(set) set->fd_count - -#endif +/* + * Copyright 1990 Network Computing Devices; + * Portions Copyright 1987 by Digital Equipment Corporation + */ + +/* + +Copyright 1987, 1994, 1998 The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +the above copyright notice appear in all copies and that both that +copyright notice and this permission notice appear in supporting +documentation. + +The above copyright notice and this permission notice shall be included +in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall +not be used in advertising or otherwise to promote the sale, use or +other dealings in this Software without prior written authorization +from The Open Group. + +*/ + +/* + * FSlib networking & os include file + */ + +#include + +#ifndef WIN32 + +/* + * makedepend screws up on #undef OPEN_MAX, so we define a new symbol + */ + +#ifndef FONT_OPEN_MAX + +#ifndef X_NOT_POSIX +# ifdef _POSIX_SOURCE +# include +# else +# define _POSIX_SOURCE +# include +# undef _POSIX_SOURCE +# endif +#endif +#ifndef SIZE_MAX +# ifdef ULONG_MAX +# define SIZE_MAX ULONG_MAX +# else +# define SIZE_MAX UINT_MAX +# endif +#endif +#ifndef OPEN_MAX +#if defined(SVR4) +#define OPEN_MAX 256 +#else +#include +#ifndef OPEN_MAX +#ifdef __OSF1__ +#define OPEN_MAX 256 +#else +#ifdef NOFILE +#define OPEN_MAX NOFILE +#else +#define OPEN_MAX NOFILES_MAX +#endif +#endif +#endif +#endif +#endif + +#if OPEN_MAX > 256 +#define FONT_OPEN_MAX 256 +#else +#define FONT_OPEN_MAX OPEN_MAX +#endif + +#endif /* FONT_OPEN_MAX */ + +#ifdef WORD64 +#define NMSKBITS 64 +#else +#define NMSKBITS 32 +#endif + +#define MSKCNT ((FONT_OPEN_MAX + NMSKBITS - 1) / NMSKBITS) + +typedef unsigned long FdSet[MSKCNT]; +typedef FdSet FdSetPtr; + +#if (MSKCNT==1) +#define BITMASK(i) (1 << (i)) +#define MASKIDX(i) 0 +#endif + +#if (MSKCNT>1) +#define BITMASK(i) (1 << ((i) & (NMSKBITS - 1))) +#define MASKIDX(i) ((i) / NMSKBITS) +#endif + +#define MASKWORD(buf, i) buf[MASKIDX(i)] +#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) +#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) +#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) + +#if (MSKCNT==1) +#define COPYBITS(src, dst) dst[0] = src[0] +#define CLEARBITS(buf) buf[0] = 0 +#define MASKANDSETBITS(dst, b1, b2) dst[0] = (b1[0] & b2[0]) +#define ORBITS(dst, b1, b2) dst[0] = (b1[0] | b2[0]) +#define UNSETBITS(dst, b1) (dst[0] &= ~b1[0]) +#define ANYSET(src) (src[0]) +#endif + +#if (MSKCNT==2) +#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; } +#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; } +#define MASKANDSETBITS(dst, b1, b2) {\ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]); } +#define ORBITS(dst, b1, b2) {\ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]); } +#define UNSETBITS(dst, b1) {\ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; } +#define ANYSET(src) (src[0] || src[1]) +#endif + +#if (MSKCNT==3) +#define COPYBITS(src, dst) { dst[0] = src[0]; dst[1] = src[1]; \ + dst[2] = src[2]; } +#define CLEARBITS(buf) { buf[0] = 0; buf[1] = 0; buf[2] = 0; } +#define MASKANDSETBITS(dst, b1, b2) {\ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]);\ + dst[2] = (b1[2] & b2[2]); } +#define ORBITS(dst, b1, b2) {\ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]);\ + dst[2] = (b1[2] | b2[2]); } +#define UNSETBITS(dst, b1) {\ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; \ + dst[2] &= ~b1[2]; } +#define ANYSET(src) (src[0] || src[1] || src[2]) +#endif + +#if (MSKCNT==4) +#define COPYBITS(src, dst) dst[0] = src[0]; dst[1] = src[1]; \ + dst[2] = src[2]; dst[3] = src[3] +#define CLEARBITS(buf) buf[0] = 0; buf[1] = 0; buf[2] = 0; buf[3] = 0 +#define MASKANDSETBITS(dst, b1, b2) \ + dst[0] = (b1[0] & b2[0]);\ + dst[1] = (b1[1] & b2[1]);\ + dst[2] = (b1[2] & b2[2]);\ + dst[3] = (b1[3] & b2[3]) +#define ORBITS(dst, b1, b2) \ + dst[0] = (b1[0] | b2[0]);\ + dst[1] = (b1[1] | b2[1]);\ + dst[2] = (b1[2] | b2[2]);\ + dst[3] = (b1[3] | b2[3]) +#define UNSETBITS(dst, b1) \ + dst[0] &= ~b1[0]; \ + dst[1] &= ~b1[1]; \ + dst[2] &= ~b1[2]; \ + dst[3] &= ~b1[3] +#define ANYSET(src) (src[0] || src[1] || src[2] || src[3]) +#endif + +#if (MSKCNT>4) +#define COPYBITS(src, dst) memmove((caddr_t) dst, (caddr_t) src,\ + MSKCNT*sizeof(long)) +#define CLEARBITS(buf) bzero((caddr_t) buf, MSKCNT*sizeof(long)) +#define MASKANDSETBITS(dst, b1, b2) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] = (b1[cri] & b2[cri]); } +#define ORBITS(dst, b1, b2) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] = (b1[cri] | b2[cri]); } +#define UNSETBITS(dst, b1) \ + { int cri; \ + for (cri=MSKCNT; --cri>=0; ) \ + dst[cri] &= ~b1[cri]; } +#if (MSKCNT==8) +#define ANYSET(src) (src[0] || src[1] || src[2] || src[3] || \ + src[4] || src[5] || src[6] || src[7]) +#endif +#endif + +#else /* not WIN32 */ + +#include +#include + +typedef fd_set FdSet; +typedef FdSet *FdSetPtr; + +#define CLEARBITS(set) FD_ZERO(&set) +#define BITSET(set,s) FD_SET(s,&set) +#define BITCLEAR(set,s) FD_CLR(s,&set) +#define GETBIT(set,s) FD_ISSET(s,&set) +#define ANYSET(set) set->fd_count + +#endif -- cgit v1.2.3