diff options
Diffstat (limited to 'libXfont/src/fc')
-rw-r--r-- | libXfont/src/fc/fsconvert.c | 1438 | ||||
-rw-r--r-- | libXfont/src/fc/fserve.c | 6396 | ||||
-rw-r--r-- | libXfont/src/fc/fserve.h | 182 | ||||
-rw-r--r-- | libXfont/src/fc/fservestr.h | 400 | ||||
-rw-r--r-- | libXfont/src/fc/fsio.c | 904 | ||||
-rw-r--r-- | libXfont/src/fc/fsio.h | 356 | ||||
-rw-r--r-- | libXfont/src/fc/fslibos.h | 436 |
7 files changed, 5056 insertions, 5056 deletions
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 <config.h>
-#endif
-#include <X11/X.h>
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xpoll.h>
-#include <X11/fonts/FS.h>
-#include <X11/fonts/FSproto.h>
-#include <X11/fonts/fontmisc.h>
-#include <X11/fonts/fontstruct.h>
-#include "fservestr.h"
-#include <X11/fonts/fontutil.h>
-#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 <config.h> +#endif +#include <X11/X.h> +#include <X11/Xtrans/Xtrans.h> +#include <X11/Xpoll.h> +#include <X11/fonts/FS.h> +#include <X11/fonts/FSproto.h> +#include <X11/fonts/fontmisc.h> +#include <X11/fonts/fontstruct.h> +#include "fservestr.h" +#include <X11/fonts/fontutil.h> +#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 <config.h>
-#endif
-
-#ifdef WIN32
-#define _WILLWINSOCK_
-#endif
-#define FONT_t
-#define TRANS_CLIENT
-#include "X11/Xtrans/Xtrans.h"
-#include "X11/Xpoll.h"
-#include <X11/fonts/FS.h>
-#include <X11/fonts/FSproto.h>
-#include <X11/X.h>
-#include <X11/Xos.h>
-#include <X11/fonts/fontmisc.h>
-#include <X11/fonts/fontstruct.h>
-#include "fservestr.h"
-#include <X11/fonts/fontutil.h>
-#include <errno.h>
-
-#include <time.h>
-#define Time_t time_t
-
-#ifdef NCD
-#include <ncd/nvram.h>
-#endif
-
-#include <stddef.h>
-
-#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 :
- "<freed>");
- 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 <config.h> +#endif + +#ifdef WIN32 +#define _WILLWINSOCK_ +#endif +#define FONT_t +#define TRANS_CLIENT +#include "X11/Xtrans/Xtrans.h" +#include "X11/Xpoll.h" +#include <X11/fonts/FS.h> +#include <X11/fonts/FSproto.h> +#include <X11/X.h> +#include <X11/Xos.h> +#include <X11/fonts/fontmisc.h> +#include <X11/fonts/fontstruct.h> +#include "fservestr.h" +#include <X11/fonts/fontutil.h> +#include <errno.h> + +#include <time.h> +#define Time_t time_t + +#ifdef NCD +#include <ncd/nvram.h> +#endif + +#include <stddef.h> + +#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 : + "<freed>"); + 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 <config.h>
-#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 <X11/fonts/FS.h>
-#include <X11/fonts/FSproto.h>
-#include <X11/fonts/fontmisc.h>
-#include <X11/fonts/fontstruct.h>
-#include "fservestr.h"
-
-#include <stdio.h>
-#include <signal.h>
-#include <sys/types.h>
-#if !defined(WIN32)
-#ifndef Lynx
-#include <sys/socket.h>
-#else
-#include <socket.h>
-#endif
-#endif
-#include <errno.h>
-#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 <config.h> +#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 <X11/fonts/FS.h> +#include <X11/fonts/FSproto.h> +#include <X11/fonts/fontmisc.h> +#include <X11/fonts/fontstruct.h> +#include "fservestr.h" + +#include <stdio.h> +#include <signal.h> +#include <sys/types.h> +#if !defined(WIN32) +#ifndef Lynx +#include <sys/socket.h> +#else +#include <socket.h> +#endif +#endif +#include <errno.h> +#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 <X11/Xtrans/Xtrans.h>
-
-#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 <limits.h>
-# else
-# define _POSIX_SOURCE
-# include <limits.h>
-# 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 <sys/param.h>
-#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 <X11/Xwinsock.h>
-#include <X11/Xw32defs.h>
-
-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 <X11/Xtrans/Xtrans.h> + +#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 <limits.h> +# else +# define _POSIX_SOURCE +# include <limits.h> +# 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 <sys/param.h> +#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 <X11/Xwinsock.h> +#include <X11/Xw32defs.h> + +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 |