aboutsummaryrefslogtreecommitdiff
path: root/libXfont/src/fc
diff options
context:
space:
mode:
Diffstat (limited to 'libXfont/src/fc')
-rw-r--r--libXfont/src/fc/fsconvert.c1438
-rw-r--r--libXfont/src/fc/fserve.c6396
-rw-r--r--libXfont/src/fc/fserve.h182
-rw-r--r--libXfont/src/fc/fservestr.h400
-rw-r--r--libXfont/src/fc/fsio.c903
-rw-r--r--libXfont/src/fc/fsio.h356
-rw-r--r--libXfont/src/fc/fslibos.h436
-rw-r--r--libXfont/src/fc/fstrans.c1
-rw-r--r--libXfont/src/fc/makefile10
9 files changed, 5067 insertions, 5055 deletions
diff --git a/libXfont/src/fc/fsconvert.c b/libXfont/src/fc/fsconvert.c
index 15c5e4200..5c979fc23 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 b02b0b749..f59dbcc9f 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 5999861b6..71f165ae1 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 a6d0d1d53..90f17c29e 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 63d3b4f3c..29c0d7d26 100644
--- a/libXfont/src/fc/fsio.c
+++ b/libXfont/src/fc/fsio.c
@@ -1,451 +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/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 bd0c621e8..0105e4909 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 c49f52e5b..c7c745616 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
diff --git a/libXfont/src/fc/fstrans.c b/libXfont/src/fc/fstrans.c
index c334c2504..74a884e63 100644
--- a/libXfont/src/fc/fstrans.c
+++ b/libXfont/src/fc/fstrans.c
@@ -22,6 +22,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
+#include <dix-config.h>
#endif
#define FONT_t
#define TRANS_CLIENT
diff --git a/libXfont/src/fc/makefile b/libXfont/src/fc/makefile
new file mode 100644
index 000000000..a4b105d26
--- /dev/null
+++ b/libXfont/src/fc/makefile
@@ -0,0 +1,10 @@
+
+INCLUDES := ../.. $(INCLUDES)
+
+LIBRARY = libfc
+
+CSRCS =\
+ fsconvert.c \
+ fserve.c \
+ fsio.c \
+ fstrans.c