summaryrefslogtreecommitdiff
path: root/src/fc
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:40 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:40 +0000
commit153e8da44452905ae04a0e20ad0d85f40399b4ca (patch)
treeb4e614de58d4b596dab3dcc7fd4054ec96db592a /src/fc
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'src/fc')
-rw-r--r--src/fc/fsconvert.c702
-rw-r--r--src/fc/fserve.c2815
-rw-r--r--src/fc/fserve.h68
-rw-r--r--src/fc/fservestr.h188
-rw-r--r--src/fc/fsio.c612
-rw-r--r--src/fc/fsio.h82
-rw-r--r--src/fc/fslibos.h212
7 files changed, 4679 insertions, 0 deletions
diff --git a/src/fc/fsconvert.c b/src/fc/fsconvert.c
new file mode 100644
index 0000000..1c8c6d1
--- /dev/null
+++ b/src/fc/fsconvert.c
@@ -0,0 +1,702 @@
+/* $Xorg: fsconvert.c,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * 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
+ */
+
+#include <X11/X.h>
+#include "FS.h"
+#include "FSproto.h"
+#include "fontmisc.h"
+#include "fontstruct.h"
+#include "fservestr.h"
+
+extern char _fs_glyph_undefined;
+extern char _fs_glyph_requested;
+extern char _fs_glyph_zero_length;
+
+extern int _fs_load_glyphs();
+
+/*
+ * converts data from font server form to X server form
+ */
+
+void
+_fs_convert_char_info(src, dst)
+ 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(conn, pfi)
+ 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(pi, po, pd, pfi)
+ fsPropInfo *pi;
+ fsPropOffset *po;
+ pointer pd;
+ FontInfoPtr pfi;
+{
+ FontPropPtr dprop;
+ int i,
+ nprops;
+ char *is_str;
+ fsPropOffset local_off;
+ char *off_adr;
+
+/* stolen from server/include/resource.h */
+#define BAD_RESOURCE 0xe0000000
+
+ nprops = pfi->nprops = pi->num_offsets;
+
+ dprop = (FontPropPtr) xalloc(sizeof(FontPropRec) * nprops);
+ is_str = (char *) xalloc(sizeof(char) * nprops);
+ if (!dprop || !is_str) {
+ xfree(is_str);
+ xfree(dprop);
+ return -1;
+ }
+ 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(&pd[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(&pd[local_off.value.position],
+ local_off.value.length, 1);
+ if (dprop->value == BAD_RESOURCE)
+ {
+ xfree (pfi->props);
+ xfree (pfi->isStringProp);
+ pfi->props = 0;
+ pfi->isStringProp = 0;
+ return -1;
+ }
+ }
+ off_adr += SIZEOF(fsPropOffset);
+ }
+
+ return nprops;
+}
+
+int
+_fs_convert_lfwi_reply(conn, pfi, fsrep, pi, po, pd)
+ 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(pfont, range_flag, count, item_size, data, nranges, ranges)
+ FontPtr pfont;
+ Bool range_flag;
+ register unsigned int count;
+ int item_size;
+ register 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(pfont, num_expected_ranges, expected_ranges)
+ FontPtr pfont;
+ int num_expected_ranges;
+ fsRange *expected_ranges;
+{
+ register FSFontPtr fsfont;
+ register FSFontDataRec *fsd;
+ register int i;
+
+ fsfont = (FSFontPtr) pfont->fontPrivate;
+ fsd = (FSFontDataRec *) pfont->fpePrivate;
+ 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;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * figures out what extents to request
+ * this is where lots of extra
+ * smarts wants to live
+ */
+/* ARGSUSED */
+int
+_fs_check_extents(pfont, flags, nranges, range, blockrec)
+ FontPtr pfont;
+ Mask flags;
+ int nranges;
+ fsRange *range;
+ FSBlockDataPtr blockrec;
+{
+/* XXX -- either fill in the requested info if we have it somewhere
+ * and return AccessDone, or else return Successful
+ */
+ return Successful;
+}
+
+/*
+ * figures out what glyphs to request
+ * this is where lots of extra
+ * smarts wants to live
+ */
+/* ARGSUSED */
+int
+_fs_check_bitmaps(pfont, format, flags, nranges, range, blockrec)
+ FontPtr pfont;
+ fsBitmapFormat format;
+ Mask flags;
+ int nranges;
+ fsRange *range;
+ FSBlockDataPtr blockrec;
+{
+/* XXX -- either fill in the requested info if we have it somewhere
+ * and return AccessDone, or else return Successful
+ */
+ return Successful;
+}
+
+int
+_fs_get_glyphs(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register 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 itemSize;
+ 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;
+
+
+ if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
+ itemSize = 1;
+ else
+ itemSize = 2;
+
+ /* 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(pFont, count, chars, charEncoding, glyphCount, glyphs)
+ FontPtr pFont;
+ unsigned long count;
+ register 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;
+ int itemSize;
+
+ fsdata = (FSFontPtr) pFont->fontPrivate;
+ encoding = fsdata->inkMetrics;
+ pDefault = fsdata->pDefault;
+ firstCol = pFont->info.firstCol;
+ numCols = pFont->info.lastCol - firstCol + 1;
+ glyphsBase = glyphs;
+
+
+ /* XXX - this should be much smarter */
+ /* make sure the glyphs are there */
+ if (charEncoding == Linear8Bit || charEncoding == TwoD8Bit)
+ itemSize = 1;
+ else
+ itemSize = 2;
+
+ 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;
+}
+
+
+void
+_fs_unload_font(pfont)
+ FontPtr pfont;
+{
+ FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
+
+ if (fsdata->encoding)
+ {
+ register int i;
+ register CharInfoPtr encoding = fsdata->encoding;
+ FontInfoPtr pfi = &pfont->info;
+ for (i = (pfi->lastCol - pfi->firstCol + 1) *
+ (pfi->lastRow - pfi->firstRow + 1);
+ i > 0;
+ encoding++, i--)
+ {
+ if (encoding->bits &&
+ encoding->bits != &_fs_glyph_undefined &&
+ encoding->bits != &_fs_glyph_requested &&
+ encoding->bits != &_fs_glyph_zero_length)
+ xfree(encoding->bits);
+ }
+ }
+ xfree(fsdata->encoding);
+ xfree(fsdata);
+
+ pfont->fontPrivate = 0;
+}
+
+void
+_fs_init_font(pfont)
+ FontPtr pfont;
+{
+ /* 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 = (void (*)())0;
+}
diff --git a/src/fc/fserve.c b/src/fc/fserve.c
new file mode 100644
index 0000000..95ce811
--- /dev/null
+++ b/src/fc/fserve.c
@@ -0,0 +1,2815 @@
+/* $Xorg: fserve.c,v 1.4 2001/02/09 02:04:02 xorgcvs Exp $ */
+/*
+
+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 WIN32
+#define _WILLWINSOCK_
+#endif
+#include <X11/X.h>
+#include <X11/Xos.h>
+#include "X11/Xpoll.h"
+#include "FS.h"
+#include "FSproto.h"
+#include "fontmisc.h"
+#include "fontstruct.h"
+#include "fservestr.h"
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#define Time_t long
+extern Time_t time ();
+#else
+#include <time.h>
+#define Time_t time_t
+#endif
+
+#ifdef NCD
+#include <ncd/nvram.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \
+ (pci)->rightSideBearing || \
+ (pci)->ascent || \
+ (pci)->descent || \
+ (pci)->characterWidth)
+
+
+extern FontPtr find_old_font();
+
+extern int _fs_build_range();
+
+static int fs_read_glyphs();
+static int fs_read_list();
+static int fs_read_list_info();
+
+static int fs_font_type;
+extern fd_set _fs_fd_mask;
+
+static void fs_block_handler();
+static int fs_wakeup();
+
+static FSFpePtr awaiting_reconnect;
+
+void _fs_connection_died();
+static int _fs_restart_connection();
+static void _fs_try_reconnect();
+static int fs_send_query_info();
+static int fs_send_query_extents();
+static int fs_send_query_bitmaps();
+static int fs_send_close_font();
+static void fs_client_died();
+static void _fs_client_access();
+static void _fs_client_resolution();
+
+char _fs_glyph_undefined;
+char _fs_glyph_requested;
+char _fs_glyph_zero_length;
+
+/*
+ * 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.
+ */
+
+
+/* XXX this should probably be a macro once its fully debugged */
+/* ARGSUSED */
+static void
+_fs_add_req_log(conn, opcode)
+ FSFpePtr conn;
+ int opcode;
+{
+
+#ifdef DEBUG
+ conn->reqbuffer[conn->reqindex++] = opcode;
+ if (conn->reqindex == REQUEST_LOG_SIZE)
+ conn->reqindex = 0;
+#endif
+
+ conn->current_seq++;
+}
+
+static Bool
+fs_name_check(name)
+ char *name;
+{
+ /* Just make sure there is a protocol/ prefix */
+
+ return (name && *name != '/' && strchr(name, '/'));
+}
+
+static void
+_fs_client_resolution(conn)
+ 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)));
+ }
+}
+
+/*
+ * sends the stuff that's meaningful to a newly opened or reset FS
+ */
+static int
+fs_send_init_packets(conn)
+ FSFpePtr conn;
+{
+ fsSetResolutionReq srreq;
+ fsSetCataloguesReq screq;
+ fsListCataloguesReq lcreq;
+ fsListCataloguesReply lcreply;
+ int num_cats,
+ clen,
+ len;
+ char *client_cat = (char *) 0,
+ *cp,
+ *sp,
+ *end;
+ int num_res;
+ FontResolutionPtr res;
+ int err = Successful;
+
+#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)) == -1)
+ {
+ err = BadFontPath;
+ goto fail;
+ }
+ if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) == -1)
+ {
+ err = BadFontPath;
+ goto fail;
+ }
+ }
+ sp = strrchr(conn->servername, '/');
+
+ /* don't get tricked by a non-existant catalogue list */
+ if (sp == strchr(conn->servername, '/')) {
+ /*
+ * try original name -- this might be an alternate with no catalogues
+ */
+ sp = strrchr(conn->requestedname, '/');
+ if (sp == strchr(conn->requestedname, '/'))
+ sp = (char *) 0;
+ }
+ if (sp) { /* turn cats into counted list */
+ sp++;
+ /* allocate more than enough room */
+ cp = client_cat = (char *) xalloc(strlen(conn->servername));
+ if (!cp) {
+ err = BadAlloc;
+ goto fail;
+ }
+ num_cats = 0;
+ while (*sp) {
+ end = strchr(sp, CATALOGUE_SEP);
+ if (!end)
+ end = sp + strlen(sp);
+ *cp++ = len = end - sp;
+ num_cats++;
+ memmove(cp, sp, len);
+ sp += len;
+ if (*sp == CATALOGUE_SEP)
+ sp++;
+ cp += len;
+ }
+ clen = cp - client_cat;
+ /* our list checked out, so send it */
+ 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)) == -1)
+ {
+ err = BadFontPath;
+ goto fail;
+ }
+ if (_fs_write_pad(conn, (char *) client_cat, clen) == -1)
+ {
+ err = BadFontPath;
+ goto fail;
+ }
+
+ /*
+ * 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;
+ _fs_add_req_log(conn, FS_SetCatalogues);
+ if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) == -1)
+ {
+ err = BadFontPath;
+ goto fail;
+ }
+
+ /*
+ * next bit will either by the ListCats reply, or an error followed by
+ * the reply
+ */
+ if (_fs_read(conn, (char *) &lcreply, SIZEOF(fsGenericReply)) == -1) {
+ err = BadFontPath;
+ goto fail;
+ }
+ if (lcreply.type == FS_Error &&
+ ((fsError *) & lcreply)->major_opcode == FS_SetCatalogues) {
+ _fs_eat_rest_of_error(conn, (fsError *) & lcreply);
+ /* get ListCats response */
+ (void) _fs_read(conn, (char *) &lcreply,
+ SIZEOF(fsListCataloguesReply));
+ err = BadFontPath;
+ goto fail;
+ }
+ /* must be reply, swallow the rest of it */
+ _fs_eat_rest_of_error(conn, (fsError *) & lcreply);
+ }
+fail:
+ xfree(client_cat);
+ return err;
+}
+
+/*
+ * close font server and remove any state associated with
+ * this connection - this includes any client records.
+ */
+
+static void
+fs_close_conn(conn)
+ FSFpePtr conn;
+{
+ FSClientPtr client, nclient;
+
+ /* XXX - hack. The right fix is to remember that the font server
+ has gone away when we first discovered it. */
+ if (conn->trans_conn)
+ (void) _FontTransClose (conn->trans_conn);
+
+ if (conn->fs_fd != -1)
+ FD_CLR(conn->fs_fd, &_fs_fd_mask);
+
+ for (client = conn->clients; client; client = nclient)
+ {
+ nclient = client->next;
+ xfree (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(fpe)
+ FontPathElementPtr fpe;
+{
+ FSFpePtr conn;
+ char *name;
+ int err;
+
+ /* open font server */
+ /* create FS specific fpe info */
+ errno = 0;
+
+ name = fpe->name;
+
+ /* hack for old style names */
+ if (*name == ':')
+ name++; /* skip ':' */
+
+ conn = _fs_open_server(name);
+ if (conn) {
+ conn->requestedname = fpe->name; /* stash this for later init use */
+ fpe->private = (pointer) conn;
+ err = fs_send_init_packets(conn);
+ if (err != Successful) {
+ fs_close_conn(conn);
+ xfree(conn->servername);
+ xfree(conn->alts);
+ xfree(conn);
+ return err;
+ }
+ if (init_fs_handlers(fpe, fs_block_handler) != Successful)
+ return AllocError;
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ conn->attemptReconnect = TRUE;
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Connected to font server \"%s\"\n", name);
+#endif
+
+ return err;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "failed to connect to FS \"%s\"\n", name);
+#endif
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Failed to connect to font server \"%s\"\n", name);
+#endif
+
+ return (errno == ENOMEM) ? AllocError : BadFontPath;
+}
+
+static int
+fs_reset_fpe(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(fpe)
+ FontPathElementPtr fpe;
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSFpePtr recon,
+ *prev;
+ prev = &awaiting_reconnect;
+ while (*prev) {
+ recon = *prev;
+ if (conn == recon) {
+ *prev = recon->next_reconnect;
+ break;
+ }
+ prev = &recon->next_reconnect;
+ }
+
+ fs_close_conn(conn);
+
+ remove_fs_handlers(fpe, fs_block_handler,
+ !XFD_ANYSET(&_fs_fd_mask) && !awaiting_reconnect);
+
+ xfree(conn->alts);
+ xfree(conn->servername);
+ xfree(conn);
+ fpe->private = (pointer) 0;
+
+#ifdef NCD
+ if (configData.ExtendedFontDiags)
+ printf("Disconnected from font server \"%s\"\n", fpe->name);
+#endif
+
+ return Successful;
+}
+
+static FSBlockDataPtr
+fs_new_block_rec(fpe, client, type)
+ FontPathElementPtr fpe;
+ pointer client;
+ int type;
+{
+ FSBlockDataPtr blockrec,
+ br;
+ FSFpePtr fsfpe = (FSFpePtr) fpe->private;
+ int size;
+
+ blockrec = (FSBlockDataPtr) xalloc(sizeof(FSBlockDataRec));
+ if (!blockrec)
+ return (FSBlockDataPtr) 0;
+ 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:
+ break;
+ }
+ blockrec->data = (pointer) xalloc(size);
+ if (!blockrec->data) {
+ xfree(blockrec);
+ return (FSBlockDataPtr) 0;
+ }
+ blockrec->client = client;
+ blockrec->sequence_number = fsfpe->current_seq;
+ blockrec->type = type;
+ blockrec->depending = 0;
+ blockrec->next = (FSBlockDataPtr) 0;
+
+ /* stick it on the end of the list (since its expected last) */
+ br = (FSBlockDataPtr) fsfpe->blocked_requests;
+ if (!br) {
+ fsfpe->blocked_requests = (pointer) blockrec;
+ } else {
+ while (br->next)
+ br = br->next;
+ br->next = blockrec;
+ }
+
+ return blockrec;
+}
+
+static void
+_fs_remove_block_rec(conn, blockrec)
+ FSFpePtr conn;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockDataPtr br,
+ last;
+
+ last = (FSBlockDataPtr) 0;
+ br = (FSBlockDataPtr) conn->blocked_requests;
+ while (br) {
+ if (br == blockrec) {
+ if (last)
+ last->next = br->next;
+ else
+ conn->blocked_requests = (pointer) br->next;
+ if (br->type == FS_LOAD_GLYPHS)
+ {
+ FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)br->data;
+ if (bglyph->num_expected_ranges)
+ xfree(bglyph->expected_ranges);
+ }
+ xfree(br->data);
+ xfree(br);
+ return;
+ }
+ last = br;
+ br = br->next;
+ }
+}
+
+static void
+signal_clients_depending(clients_depending)
+FSClientsDependingPtr *clients_depending;
+{
+ FSClientsDependingPtr p = *clients_depending, p2;
+ *clients_depending = (FSClientsDependingPtr)0;
+
+ while (p != (FSClientsDependingPtr)0)
+ {
+ p2 = p;
+ ClientSignal(p->client);
+ p = p->next;
+ xfree(p2);
+ }
+}
+
+static int
+add_clients_depending(clients_depending, client)
+FSClientsDependingPtr *clients_depending;
+pointer client;
+{
+ while (*clients_depending != (FSClientsDependingPtr)0)
+ {
+ if ((*clients_depending)->client == client) return Suspended;
+ clients_depending = &(*clients_depending)->next;
+ }
+ *clients_depending = (FSClientsDependingPtr)xalloc(
+ sizeof(FSClientsDependingRec));
+ if (!*clients_depending)
+ return BadAlloc;
+
+ (*clients_depending)->client = client;
+ (*clients_depending)->next = 0;
+ return Suspended;
+}
+
+static void
+clean_aborted_blockrec(blockrec)
+ FSBlockDataPtr blockrec;
+{
+
+ switch(blockrec->type)
+ {
+ case FS_LOAD_GLYPHS:
+ {
+ FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
+ FontPtr pfont = bglyph->pfont;
+ int num_expected_ranges = bglyph->num_expected_ranges;
+ fsRange *expected_ranges = bglyph->expected_ranges;
+ _fs_clean_aborted_loadglyphs(pfont,
+ num_expected_ranges,
+ expected_ranges);
+ signal_clients_depending(&bglyph->clients_depending);
+ break;
+ }
+ case FS_OPEN_FONT:
+ {
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
+ signal_clients_depending(&bfont->clients_depending);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void
+fs_abort_blockrec(conn, blockrec)
+ FSFpePtr conn;
+ FSBlockDataPtr blockrec;
+{
+ clean_aborted_blockrec(blockrec);
+ _fs_remove_block_rec(conn, blockrec);
+}
+
+
+static void
+fs_free_font(bfont)
+ FSBlockedFontPtr bfont;
+{
+ FontPtr pfont;
+ FSFontDataRec *fsd;
+
+ pfont = bfont->pfont;
+ fsd = (FSFontDataRec *) pfont->fpePrivate;
+
+ /* xfree better be able to handle NULL */
+ (*pfont->unload_font)(pfont);
+ DeleteFontClientID(fsd->fontid);
+ xfree(fsd->name);
+ xfree(pfont->info.isStringProp);
+ xfree(pfont->info.props);
+
+ xfree(pfont);
+ xfree(fsd);
+
+ bfont->pfont = (FontPtr) 0;
+}
+
+static void
+_fs_cleanup_font(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(fsd->fpe, bfont->fontid);
+
+ fs_free_font(bfont);
+ }
+ bfont->errcode = AllocError;
+}
+
+
+static int
+fs_read_open_font(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsOpenBitmapFontReply rep;
+ FSBlockDataPtr blockOrig;
+ FSBlockedFontPtr origBfont;
+
+ /* pull out the OpenFont reply */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+
+ if (rep.type == FS_Error) {
+ _fs_eat_rest_of_error(conn, (fsError *) & rep);
+ return BadFontName;
+ } else { /* get rest of reply */
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsOpenBitmapFontReply) - SIZEOF(fsGenericReply)) == -1) {
+ /* If we're not reopening a font, we'll allocate the
+ structures again after connection is reestablished. */
+ if (!(bfont->flags & FontReopen)) fs_free_font(bfont);
+ return StillWorking;
+ }
+ }
+
+ /* 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)) {
+ (void) fs_send_close_font(fpe, bfont->fontid);
+
+ /* Find old font if we're completely done getting it from server. */
+ fs_free_font(bfont);
+ bfont->pfont = find_old_font(rep.otherid);
+ bfont->fontid = rep.otherid;
+ bfont->state = FS_DONE_REPLY;
+ /*
+ * look for a blocked request to open the same font
+ */
+ for (blockOrig = (FSBlockDataPtr) conn->blocked_requests;
+ 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 */
+ return BadFontName;
+ }
+ return AccessDone;
+ }
+
+ bfont->pfont->info.cachable = rep.cachable != 0;
+ bfont->state = FS_INFO_REPLY;
+ /* ask for the next stage */
+ (void) fs_send_query_info(fpe, blockrec);
+ return StillWorking;
+}
+
+
+static int
+fs_read_query_info(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXInfoReply rep;
+ fsPropInfo pi;
+ fsPropOffset *po;
+ pointer pd;
+ unsigned long prop_len;
+ FSBlockedFontRec newbfont, *oldbfont;
+ FontRec newpfont, *oldpfont;
+ int err;
+
+ /* If this is a reopen, accumulate the query info into a dummy
+ font and compare to our original data. */
+ if (bfont->flags & FontReopen)
+ {
+ newbfont = *(oldbfont = bfont);
+ bfont = &newbfont;
+ newpfont = *(oldpfont = oldbfont->pfont);
+ newpfont.info.isStringProp = NULL;
+ newpfont.info.props = NULL;
+ newbfont.pfont = &newpfont;
+ err = StillWorking;
+ }
+
+ /* pull out the QueryXInfo reply */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsQueryXInfoReply) - SIZEOF(fsGenericReply)) == -1) {
+ if (bfont->flags & FontReopen) goto bail;
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+ /* move the data over */
+ fsUnpack_XFontInfoHeader(&rep, &bfont->pfont->info);
+ _fs_init_fontinfo(conn, &bfont->pfont->info);
+
+ if (bfont->pfont->info.terminalFont)
+ {
+ bfont->format =
+ (bfont->format & ~ (BitmapFormatImageRectMask)) |
+ BitmapFormatImageRectMax;
+ }
+
+ if (_fs_read(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1) {
+ if (bfont->flags & FontReopen) goto bail;
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+ prop_len = pi.num_offsets * SIZEOF(fsPropOffset);
+ po = (fsPropOffset *) xalloc(prop_len);
+ pd = (pointer) xalloc(pi.data_len);
+ if (!po || !pd) {
+ xfree(pd);
+ xfree(po);
+ /* clear the wire */
+ (void) _fs_drain_bytes(conn, prop_len + pi.data_len);
+ /* clean up the font */
+ if (bfont->flags & FontReopen) { err = AllocError ; goto bail; }
+ (void) _fs_cleanup_font(bfont);
+ return AllocError;
+ }
+ if (_fs_read_pad(conn, (char *) po, prop_len) == -1 ||
+ _fs_read_pad(conn, (char *) pd, pi.data_len) == -1) {
+ xfree(pd);
+ xfree(po);
+ if (bfont->flags & FontReopen) goto bail;
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+ if (_fs_convert_props(&pi, po, pd, &bfont->pfont->info) == -1)
+ {
+ xfree(po);
+ xfree(pd);
+ if (bfont->flags & FontReopen) { err = AllocError ; goto bail; }
+ (void) _fs_cleanup_font(bfont);
+ return AllocError;
+ }
+ xfree(po);
+ xfree(pd);
+
+ if (bfont->flags & FontReopen)
+ {
+ int i;
+
+ err = BadFontName;
+
+ /* 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 (newpfont.info.firstCol != oldpfont->info.firstCol ||
+ newpfont.info.lastCol != oldpfont->info.lastCol ||
+ newpfont.info.firstRow != oldpfont->info.firstRow ||
+ newpfont.info.lastRow != oldpfont->info.lastRow ||
+ newpfont.info.defaultCh != oldpfont->info.defaultCh ||
+ newpfont.info.noOverlap != oldpfont->info.noOverlap ||
+ newpfont.info.terminalFont != oldpfont->info.terminalFont ||
+ newpfont.info.constantMetrics != oldpfont->info.constantMetrics ||
+ newpfont.info.constantWidth != oldpfont->info.constantWidth ||
+ newpfont.info.inkInside != oldpfont->info.inkInside ||
+ newpfont.info.inkMetrics != oldpfont->info.inkMetrics ||
+ newpfont.info.allExist != oldpfont->info.allExist ||
+ newpfont.info.drawDirection != oldpfont->info.drawDirection ||
+ newpfont.info.cachable != oldpfont->info.cachable ||
+ newpfont.info.anamorphic != oldpfont->info.anamorphic ||
+ newpfont.info.maxOverlap != oldpfont->info.maxOverlap ||
+ newpfont.info.fontAscent != oldpfont->info.fontAscent ||
+ newpfont.info.fontDescent != oldpfont->info.fontDescent ||
+ newpfont.info.nprops != oldpfont->info.nprops)
+ goto bail;
+
+#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(newpfont.info.maxbounds, oldpfont->info.maxbounds) ||
+ !MATCH(newpfont.info.minbounds, oldpfont->info.minbounds) ||
+ !MATCH(newpfont.info.ink_maxbounds, oldpfont->info.ink_maxbounds) ||
+ !MATCH(newpfont.info.ink_minbounds, oldpfont->info.ink_minbounds))
+ goto bail;
+
+#undef MATCH
+
+ for (i = 0; i < newpfont.info.nprops; i++)
+ if (newpfont.info.isStringProp[i] !=
+ oldpfont->info.isStringProp[i] ||
+ newpfont.info.props[i].name !=
+ oldpfont->info.props[i].name ||
+ newpfont.info.props[i].value !=
+ oldpfont->info.props[i].value)
+ goto bail;
+
+ err = Successful;
+ bail:
+ if (err != Successful && err != StillWorking)
+ {
+ /* Failure. Close the font. */
+ fs_send_close_font(((FSFontDataPtr)oldpfont->fpePrivate)->fpe,
+ bfont->fontid);
+ ((FSFontDataPtr)oldpfont->fpePrivate)->generation = -1;
+ }
+ xfree(newpfont.info.isStringProp);
+ xfree(newpfont.info.props);
+
+ if (err == Successful) oldbfont->state = FS_DONE_REPLY;
+ return err;
+ }
+
+ if (glyphCachingMode == CACHING_OFF ||
+ glyphCachingMode == CACHE_16_BIT_GLYPHS && !bfont->pfont->info.lastRow)
+ bfont->flags |= FontLoadAll;
+
+ bfont->state = FS_EXTENT_REPLY;
+
+ fs_send_query_extents(fpe, blockrec);
+ return StillWorking;
+}
+
+static int
+fs_read_extent_info(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXExtents16Reply rep;
+ int i;
+ int numInfos;
+ Bool haveInk = FALSE; /* need separate ink metrics? */
+ CharInfoPtr ci,
+ pCI;
+ FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate;
+ fsXCharInfo *fsci;
+ fsXCharInfo fscilocal;
+ pointer fscip;
+
+ /* read the QueryXExtents reply */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsQueryXExtents16Reply) - SIZEOF(fsGenericReply)) == -1) {
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+ /* move the data over */
+ /* need separate inkMetrics for fixed font server protocol version */
+ numInfos = rep.num_extents;
+ if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1)
+ {
+ numInfos *= 2;
+ haveInk = TRUE;
+ }
+ ci = pCI = (CharInfoPtr) xalloc(sizeof(CharInfoRec) * numInfos);
+/* XXX this could be done with an ALLOCATE_LOCAL */
+ fsci = (fsXCharInfo *) xalloc(SIZEOF(fsXCharInfo) * rep.num_extents);
+ if (!pCI || !fsci) {
+ xfree(pCI);
+ xfree(fsci);
+ /* clear the unusable data */
+ _fs_drain_bytes(conn, SIZEOF(fsXCharInfo) * rep.num_extents);
+ _fs_cleanup_font(bfont);
+ return AllocError;
+ }
+ fsfont->encoding = pCI;
+ if (haveInk)
+ fsfont->inkMetrics = pCI + rep.num_extents;
+ else
+ fsfont->inkMetrics = pCI;
+
+ if (_fs_read_pad(conn, (char *) fsci,
+ SIZEOF(fsXCharInfo) * rep.num_extents) == -1) {
+ fs_free_font(bfont);
+ xfree(fsci);
+ return StillWorking;
+ }
+ fsd->glyphs_to_get = 0;
+ fscip = (pointer) fsci;
+ ci = fsfont->inkMetrics;
+ for (i = 0; i < rep.num_extents; i++) {
+ memcpy(&fscilocal, fscip, SIZEOF(fsXCharInfo)); /* align it */
+ _fs_convert_char_info(&fscilocal, &ci->metrics);
+ fscip += 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++;
+ }
+
+ xfree(fsci);
+
+ /* build bitmap metrics, ImageRectMax style */
+ if (haveInk)
+ {
+ FontInfoRec *fi = &bfont->pfont->info;
+ CharInfoPtr ii;
+
+ ci = fsfont->encoding;
+ ii = fsfont->inkMetrics;
+ for (i = 0; i < rep.num_extents; 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;
+ }
+ }
+ }
+ {
+ 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) {
+ fs_send_query_bitmaps(fpe, blockrec);
+ return StillWorking;
+ }
+ return Successful;
+}
+
+/*
+ * XXX should probably continue to read here if we can, but must be sure
+ * it's our packet waiting, rather than another interspersed
+ */
+static int
+fs_do_open_font(fpe, blockrec, readheader)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+ Bool readheader;
+{
+ FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ int err;
+
+ switch (bfont->state) {
+ case FS_OPEN_REPLY:
+ if (readheader) {
+ /* get the next header */
+ if (_fs_read(conn, (char *) &blockrec->header,
+ SIZEOF(fsGenericReply)) == -1) {
+ fs_free_font(bfont);
+ err = StillWorking;
+ break;
+ }
+ }
+ bfont->errcode = fs_read_open_font(fpe, blockrec);
+ if (bfont->errcode != StillWorking) { /* already loaded, or error */
+ /* if font's already loaded, massage error code */
+ switch (bfont->state) {
+ case FS_DONE_REPLY:
+ bfont->errcode = Successful;
+ break;
+ case FS_DEPENDING:
+ bfont->errcode = StillWorking;
+ break;
+ }
+ err = bfont->errcode;
+ break;
+ }
+ /* if more data to read or Sync, fall thru, else return */
+ if (!(bfont->flags & FontOpenSync)) {
+ err = bfont->errcode;
+ break;
+ } else {
+ if (_fs_read(conn, (char *) &blockrec->header,
+ SIZEOF(fsGenericReply)) == -1) {
+ fs_free_font(bfont);
+ err = StillWorking;
+ break;
+ }
+ }
+ /* fall through */
+ case FS_INFO_REPLY:
+ bfont->errcode = fs_read_query_info(fpe, blockrec);
+ if (bfont->errcode != StillWorking) {
+ err = bfont->errcode;
+ break;
+ }
+ if (!(bfont->flags & FontOpenSync)) {
+ err = bfont->errcode;
+ break;
+ /* if more data to read, fall thru, else return */
+ } else {
+ if (_fs_read(conn, (char *) &blockrec->header,
+ SIZEOF(fsGenericReply))) {
+ fs_free_font(bfont);
+ err = StillWorking;
+ break;
+ }
+ }
+ /* fall through */
+ case FS_EXTENT_REPLY:
+ bfont->errcode = fs_read_extent_info(fpe, blockrec);
+ if (bfont->errcode != StillWorking) {
+ err = bfont->errcode;
+ break;
+ }
+ if (!(bfont->flags & FontOpenSync)) {
+ err = bfont->errcode;
+ break;
+ } else if (bfont->flags & FontLoadBitmaps) {
+ if (_fs_read(conn, (char *) &blockrec->header,
+ SIZEOF(fsGenericReply))) {
+ fs_free_font(bfont);
+ err = StillWorking;
+ break;
+ }
+ }
+ /* fall through */
+ case FS_GLYPHS_REPLY:
+ if (bfont->flags & FontLoadBitmaps) {
+ bfont->errcode = fs_read_glyphs(fpe, blockrec);
+ }
+ err = bfont->errcode;
+ break;
+ case FS_DEPENDING: /* can't happen */
+ err = bfont->errcode;
+ default:
+ err = bfont->errcode;
+ break;
+ }
+ if (err != StillWorking) {
+ bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
+ while (blockrec = blockrec->depending) {
+ bfont = (FSBlockedFontPtr) blockrec->data;
+ bfont->errcode = err;
+ bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */
+ }
+ }
+ return err;
+}
+
+/* ARGSUSED */
+static void
+fs_block_handler(data, wt, LastSelectMask)
+ pointer data;
+ struct timeval **wt;
+ fd_set* LastSelectMask;
+{
+ static struct timeval recon_timeout;
+ Time_t now,
+ soonest;
+ FSFpePtr recon;
+
+ XFD_ORSET(LastSelectMask, LastSelectMask, &_fs_fd_mask);
+ if (recon = awaiting_reconnect) {
+ now = time((Time_t *) 0);
+ soonest = recon->time_to_try;
+ while (recon = recon->next_reconnect) {
+ if (recon->time_to_try < soonest)
+ soonest = recon->time_to_try;
+ }
+ if (soonest < now)
+ soonest = now;
+ soonest = soonest - now;
+ recon_timeout.tv_sec = soonest;
+ recon_timeout.tv_usec = 0;
+ if (*wt == (struct timeval *) 0) {
+ *wt = &recon_timeout;
+ } else if ((*wt)->tv_sec > soonest) {
+ **wt = recon_timeout;
+ }
+ }
+}
+
+static void
+fs_handle_unexpected(conn, rep)
+ 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_eat_rest_of_error(conn, (fsError *) rep);
+}
+
+static int
+fs_wakeup(fpe, LastSelectMask)
+ FontPathElementPtr fpe;
+ fd_set* LastSelectMask;
+{
+ FSBlockDataPtr blockrec,
+ br;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ int err;
+ fsGenericReply rep;
+
+ /* see if there's any data to be read */
+
+ /*
+ * Don't continue if the fd is -1 (which will be true when the
+ * font server terminates
+ */
+ if (conn->fs_fd == -1)
+ return FALSE;
+
+ if (FD_ISSET(conn->fs_fd, LastSelectMask)) {
+
+#ifdef NOTDEF /* bogus - doesn't deal with EOF very well,
+ * now does it ... */
+ /*
+ * make sure it isn't spurious - mouse events seem to trigger extra
+ * problems
+ */
+ if (_fs_data_ready(conn) <= 0) {
+ return FALSE;
+ }
+#endif
+
+ /* get the header */
+ if (_fs_read(conn, (char *) &rep, SIZEOF(fsGenericReply)) == -1)
+ return FALSE;
+
+ /* find the matching block record */
+
+ for (br = (FSBlockDataPtr) conn->blocked_requests; br; br = br->next) {
+ if ((CARD16)(br->sequence_number & 0xffff) ==
+ (CARD16)(rep.sequenceNumber - 1))
+ break;
+ }
+ if (!br) {
+ fs_handle_unexpected(conn, &rep);
+ return FALSE;
+ }
+ blockrec = br;
+
+ memcpy(&blockrec->header, &rep, SIZEOF(fsGenericReply));
+
+ /* go read it, and if we're done, wake up the appropriate client */
+ switch (blockrec->type) {
+ case FS_OPEN_FONT:
+ err = fs_do_open_font(fpe, blockrec, FALSE);
+ break;
+ case FS_LOAD_GLYPHS:
+ err = fs_read_glyphs(fpe, blockrec);
+ break;
+ case FS_LIST_FONTS:
+ err = fs_read_list(fpe, blockrec);
+ break;
+ case FS_LIST_WITH_INFO:
+ err = fs_read_list_info(fpe, blockrec);
+ break;
+ default:
+ break;
+ }
+
+ if (err != StillWorking) {
+ while (blockrec) {
+ ClientSignal(blockrec->client);
+ blockrec = blockrec->depending;
+ }
+ }
+ /*
+ * Xx we could loop here and eat any additional replies, but it should
+ * feel more responsive for other clients if we come back later
+ */
+ } else if (awaiting_reconnect) {
+ _fs_try_reconnect();
+ }
+ return FALSE;
+}
+
+/*
+ * Reconnection code
+ */
+
+void
+_fs_connection_died(conn)
+ FSFpePtr conn;
+{
+ if (!conn->attemptReconnect)
+ return;
+ conn->attemptReconnect = FALSE;
+ fs_close_conn(conn);
+ conn->time_to_try = time((Time_t *) 0) + FS_RECONNECT_WAIT;
+ conn->reconnect_delay = FS_RECONNECT_WAIT;
+ conn->fs_fd = -1;
+ conn->trans_conn = NULL;
+ conn->next_reconnect = awaiting_reconnect;
+ awaiting_reconnect = conn;
+}
+
+static int
+_fs_restart_connection(conn)
+ FSFpePtr conn;
+{
+ FSBlockDataPtr block;
+
+ conn->current_seq = 0;
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ if (!fs_send_init_packets(conn))
+ return FALSE;
+ while (block = (FSBlockDataPtr) conn->blocked_requests) {
+ ClientSignal(block->client);
+ fs_abort_blockrec(conn, block);
+ }
+ return TRUE;
+}
+
+static void
+_fs_try_reconnect()
+{
+ FSFpePtr conn,
+ *prev;
+ Time_t now;
+
+ prev = &awaiting_reconnect;
+ now = time((Time_t *) 0);
+ while (conn = *prev) {
+ if (now - conn->time_to_try > 0) {
+ if (_fs_reopen_server(conn) && _fs_restart_connection(conn)) {
+ conn->attemptReconnect = TRUE;
+ *prev = conn->next_reconnect;
+ if (prev == &awaiting_reconnect) continue;
+ } else {
+ if (conn->reconnect_delay < FS_MAX_RECONNECT_WAIT)
+ conn->reconnect_delay *= 2;
+ now = time((Time_t *) 0);
+ conn->time_to_try = now + conn->reconnect_delay;
+ }
+ }
+ prev = &conn->next_reconnect;
+ }
+}
+
+/*
+ * sends the actual request out
+ */
+/* ARGSUSED */
+static int
+fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont)
+ pointer client;
+ FontPathElementPtr fpe;
+ Mask flags;
+ char *name;
+ int namelen;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ XID id;
+ FontPtr *ppfont;
+{
+ FontPtr newfont;
+ FSBlockDataPtr blockrec = NULL;
+ FSBlockedFontPtr blockedfont;
+ FSFontDataPtr fsd;
+ FSFontPtr fsfont;
+ FSFpePtr conn;
+ fsOpenBitmapFontReq openreq;
+ int err = Suspended;
+ XID newid;
+ unsigned char buf[1024];
+ char *fontname;
+
+ if (flags & FontReopen)
+ {
+ Atom nameatom, fn = None;
+ int i;
+
+ newfont = *ppfont;
+ fsd = (FSFontDataPtr)newfont->fpePrivate;
+ fsfont = (FSFontPtr)newfont->fontPrivate;
+ fpe = newfont->fpe;
+ format = fsd->format;
+ fmask = fsd->fmask;
+ newid = fsd->fontid;
+ /* 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 < newfont->info.nprops; i++)
+ if (newfont->info.props[i].name == nameatom &&
+ newfont->info.isStringProp[i])
+ {
+ fn = newfont->info.props[i].value;
+ break;
+ }
+ }
+ if (fn == None || !(name = NameForAtom(fn)))
+ {
+ name = fsd->name;
+ namelen = fsd->namelen;
+ }
+ else
+ namelen = strlen(name);
+ }
+
+ conn = (FSFpePtr) fpe->private;
+ if (namelen > sizeof (buf) - 1)
+ return BadFontName;
+ _fs_client_access (conn, client, (flags & FontOpenSync) != 0);
+ _fs_client_resolution(conn);
+
+
+ if (!(flags & FontReopen))
+ {
+
+ newid = GetNewFontClientID();
+
+ /* make the font */
+ newfont = (FontPtr) xalloc(sizeof(FontRec));
+
+ /* and the FS data */
+ fsd = (FSFontDataPtr) xalloc(sizeof(FSFontDataRec));
+
+ fsfont = (FSFontPtr) xalloc(sizeof(FSFontRec));
+
+ fontname = (char *)xalloc(namelen);
+
+ if (!newfont || !fsd || !fsfont || !fontname) {
+lowmem:
+ if (!(flags & FontReopen))
+ {
+ xfree((char *) newfont);
+ xfree((char *) fsd);
+ xfree((char *) fsfont);
+ xfree((char *) fontname);
+ }
+ if (blockrec) fs_abort_blockrec(conn, blockrec);
+ return AllocError;
+ }
+ bzero((char *) newfont, sizeof(FontRec));
+ bzero((char *) fsfont, sizeof(FSFontRec));
+ bzero((char *) fsd, sizeof(FSFontDataRec));
+ }
+
+ /* make a new block record, and add it to the end of the list */
+ blockrec = fs_new_block_rec(fpe, client, FS_OPEN_FONT);
+ if (!blockrec) {
+ goto lowmem;
+ }
+
+ if (!(flags & FontReopen))
+ {
+ int bit, byte, scan, glyph;
+
+ newfont->refcnt = 0;
+ newfont->maxPrivate = -1;
+ newfont->devPrivates = (pointer *) 0;
+ newfont->format = format;
+
+ /* These font components will be needed in packGlyphs */
+ CheckFSFormat(format, BitmapFormatMaskBit |
+ BitmapFormatMaskByte |
+ BitmapFormatMaskScanLineUnit |
+ BitmapFormatMaskScanLinePad,
+ &bit,
+ &byte,
+ &scan,
+ &glyph,
+ NULL);
+ newfont->bit = bit;
+ newfont->byte = byte;
+ newfont->scan = scan;
+ newfont->glyph = glyph;
+
+ newfont->fpe = fpe;
+ newfont->fpePrivate = (pointer) fsd;
+ newfont->fontPrivate = (pointer) fsfont;
+ _fs_init_font(newfont);
+
+ fsd->fpe = fpe;
+ fsd->name = fontname;
+ fsd->namelen = namelen;
+ memcpy(fontname, name, namelen);
+ fsd->format = format;
+ fsd->fmask = fmask;
+ }
+ fsd->fontid = newid;
+ fsd->generation = conn->generation;
+
+ blockedfont = (FSBlockedFontPtr) blockrec->data;
+ blockedfont->fontid = newid;
+ blockedfont->pfont = newfont;
+ blockedfont->state = FS_OPEN_REPLY;
+ blockedfont->flags = flags;
+ blockedfont->format = format;
+ blockedfont->clients_depending = (FSClientsDependingPtr)0;
+
+ /* save the ID */
+ if (!StoreFontClientFont(blockedfont->pfont, blockedfont->fontid)) {
+ goto lowmem;
+ }
+ /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
+ buf[0] = (unsigned char) namelen;
+ memcpy(&buf[1], name, namelen);
+ namelen++;
+ openreq.reqType = FS_OpenBitmapFont;
+ openreq.fid = newid;
+ openreq.format_hint = format;
+ openreq.format_mask = fmask;
+ openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 3) >> 2;
+
+ _fs_add_req_log(conn, FS_OpenBitmapFont);
+ _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq));
+ _fs_write_pad(conn, (char *) buf, namelen);
+
+#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, fpe->name);
+ }
+#endif
+
+ if (flags & FontOpenSync) {
+ err = fs_do_open_font(fpe, blockrec, TRUE);
+ if (blockedfont->errcode == Successful) {
+ *ppfont = blockedfont->pfont;
+ } else {
+ _fs_cleanup_font(blockedfont);
+ }
+ _fs_remove_block_rec(conn, blockrec);
+ }
+ return err;
+}
+
+static int
+fs_send_query_info(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXInfoReq inforeq;
+
+ bfont = (FSBlockedFontPtr) blockrec->data;
+
+ inforeq.reqType = FS_QueryXInfo;
+ inforeq.id = bfont->fontid;
+ inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
+
+ blockrec->sequence_number = conn->current_seq;
+ _fs_add_req_log(conn, FS_QueryXInfo);
+ _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
+
+ return Successful;
+}
+
+static int
+fs_send_query_extents(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXExtents16Req extreq;
+
+ bfont = (FSBlockedFontPtr) blockrec->data;
+
+ extreq.reqType = FS_QueryXExtents16;
+ extreq.range = fsTrue;
+ extreq.fid = bfont->fontid;
+ extreq.num_ranges = 0;
+ extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2;
+
+ blockrec->sequence_number = conn->current_seq;
+ _fs_add_req_log(conn, FS_QueryXExtents16);
+ _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
+
+ return Successful;
+}
+
+static int
+fs_send_query_bitmaps(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedFontPtr bfont;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsQueryXBitmaps16Req bitreq;
+
+
+ bfont = (FSBlockedFontPtr) blockrec->data;
+
+ /* 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;
+
+ blockrec->sequence_number = conn->current_seq;
+ _fs_add_req_log(conn, FS_QueryXBitmaps16);
+ _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
+
+ return Successful;
+}
+
+/* ARGSUSED */
+static int
+fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
+ alias, non_cachable_font)
+ pointer client;
+ FontPathElementPtr fpe;
+ Mask flags;
+ char *name;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ int namelen;
+ XID id;
+ FontPtr *ppfont;
+ char **alias;
+ FontPtr non_cachable_font; /* Not used in this FPE */
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+ FSBlockedFontPtr blockedfont;
+ int err;
+
+ /* libfont interface expects ImageRectMin glyphs */
+ format = format & ~BitmapFormatImageRectMask | BitmapFormatImageRectMin;
+
+ *alias = (char *) 0;
+ /* XX if we find the blockrec for the font */
+ blockrec = (FSBlockDataPtr) conn->blocked_requests;
+ while (blockrec != (FSBlockDataPtr) 0) {
+ if (blockrec->type == FS_OPEN_FONT &&
+ blockrec->client == client) {
+ blockedfont = (FSBlockedFontPtr) blockrec->data;
+ err = blockedfont->errcode;
+ if (err == Successful) {
+ *ppfont = blockedfont->pfont;
+ } else {
+ _fs_cleanup_font(blockedfont);
+ }
+ /* cleanup */
+ _fs_remove_block_rec(conn, blockrec);
+ return err;
+ }
+ blockrec = blockrec->next;
+ }
+ return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
+ id, ppfont);
+}
+
+/* ARGSUSED */
+static int
+fs_send_close_font(fpe, id)
+ FontPathElementPtr fpe;
+ Font id;
+{
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsCloseReq req;
+
+ /* tell the font server to close the font */
+ req.reqType = FS_CloseFont;
+ 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 int
+fs_close_font(fpe, pfont)
+ FontPathElementPtr fpe;
+ FontPtr pfont;
+{
+ FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+
+ /* XXX we may get called after the resource DB has been cleaned out */
+ if (find_old_font(fsd->fontid))
+ DeleteFontClientID(fsd->fontid);
+ if (conn->generation == fsd->generation)
+ fs_send_close_font(fpe, fsd->fontid);
+ (*pfont->unload_font) (pfont);
+
+
+ xfree(fsd->name);
+ xfree(fsd);
+ xfree(pfont->info.isStringProp);
+ xfree(pfont->info.props);
+ xfree(pfont->devPrivates);
+ xfree(pfont);
+
+
+ return Successful;
+}
+
+static int
+fs_read_glyphs(fpe, blockrec)
+ 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;
+ fsOffset32 *ppbits;
+ fsOffset32 local_off;
+ char *off_adr;
+ pointer pbitmaps;
+ char *bits;
+ int glyph_size,
+ offset_size,
+ i,
+ err;
+ int nranges = 0;
+ fsRange *ranges, *nextrange;
+ unsigned long minchar, maxchar;
+
+ /* get reply header */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+ if (rep.type == FS_Error) {
+/* XXX -- translate FS error */
+ _fs_eat_rest_of_error(conn, (fsError *) & rep);
+ err = AllocError;
+ goto bail;
+ }
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsQueryXBitmaps16Reply) - SIZEOF(fsGenericReply)) == -1) {
+ if (blockrec->type == FS_OPEN_FONT)
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+ /* allocate space for glyphs */
+ offset_size = SIZEOF(fsOffset32) * (rep.num_chars);
+ glyph_size = (rep.length << 2) - SIZEOF(fsQueryXBitmaps16Reply)
+ - offset_size;
+ ppbits = (fsOffset32 *) xalloc(offset_size);
+ pbitmaps = (pointer) xalloc(glyph_size);
+ if (glyph_size && !pbitmaps || !ppbits)
+ {
+ xfree(pbitmaps);
+ xfree(ppbits);
+
+ /* clear wire */
+ (void) _fs_drain_bytes_pad(conn, offset_size);
+ (void) _fs_drain_bytes_pad(conn, glyph_size);
+
+ if (blockrec->type == FS_OPEN_FONT)
+ _fs_cleanup_font(bfont);
+ err = AllocError;
+ goto bail;
+ }
+
+ /* read offsets */
+ if (_fs_read_pad(conn, (char *) ppbits, offset_size) == -1) {
+ if (blockrec->type == FS_OPEN_FONT)
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+
+ /* read glyphs */
+ if (_fs_read_pad(conn, (char *) pbitmaps, glyph_size) == -1) {
+ if (blockrec->type == FS_OPEN_FONT)
+ fs_free_font(bfont);
+ return StillWorking;
+ }
+
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ nranges = bglyph->num_expected_ranges;
+ nextrange = ranges = 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;
+ 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)
+ {
+ if (local_off.length)
+ {
+ bits = (char *)xalloc(local_off.length);
+ if (bits == NULL)
+ {
+ xfree(ppbits);
+ xfree(pbitmaps);
+ err = AllocError;
+ goto bail;
+ }
+ memcpy(bits, pbitmaps + local_off.position,
+ local_off.length);
+ }
+ else if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
+ 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);
+ }
+
+ xfree(ppbits);
+ xfree(pbitmaps);
+
+ if (blockrec->type == FS_OPEN_FONT)
+ {
+ fsd->glyphs_to_get = 0;
+ bfont->state = FS_DONE_REPLY;
+ }
+ err = Successful;
+
+bail:
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ bglyph->done = TRUE;
+ bglyph->errcode = err;
+ }
+
+ return err;
+}
+
+
+
+static int
+fs_send_load_glyphs(client, pfont, nranges, ranges)
+ pointer client;
+ FontPtr pfont;
+ int nranges;
+ fsRange *ranges;
+{
+ FSBlockedGlyphPtr blockedglyph;
+ fsQueryXBitmaps16Req req;
+ FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
+ FontPathElementPtr fpe = fsd->fpe;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ FSBlockDataPtr blockrec;
+
+ /* 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->done = FALSE;
+ blockedglyph->clients_depending = (FSClientsDependingPtr)0;
+
+ blockrec->sequence_number = conn->current_seq;
+
+ /* 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));
+
+ /* 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);
+ }
+
+ return Suspended;
+}
+
+
+int
+fs_load_all_glyphs(pfont)
+ FontPtr pfont;
+{
+ extern pointer serverClient; /* This could be any number that
+ doesn't conflict with existing
+ client values. */
+ 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)
+ {
+ fd_set TempSelectMask;
+
+ FD_ZERO (&TempSelectMask);
+
+ if (_fs_wait_for_readable(conn) == -1)
+ {
+ /* We lost our connection. Don't wait to reestablish it;
+ just give up. */
+ _fs_connection_died(conn);
+
+ /* Get rid of blockrec */
+ fs_client_died(serverClient, pfont->fpe);
+
+ return BadCharRange; /* As good an error as any other */
+ }
+ FD_SET(conn->fs_fd, &TempSelectMask);
+ fs_wakeup(pfont->fpe, &TempSelectMask);
+ }
+
+ return err;
+}
+
+
+int
+_fs_load_glyphs(client, pfont, range_flag, nchars, item_size, data)
+ pointer client;
+ FontPtr pfont;
+ Bool range_flag;
+ unsigned int nchars;
+ int item_size;
+ unsigned char *data;
+{
+
+ int nranges = 0;
+ fsRange *ranges = NULL;
+ int res;
+ FSBlockDataPtr blockrec;
+ FSBlockedGlyphPtr blockedglyph;
+ FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
+ FSClientsDependingPtr *clients_depending = NULL;
+
+ /* see if the result is already there */
+
+ blockrec = (FSBlockDataPtr) conn->blocked_requests;
+ while (blockrec) {
+ if (blockrec->type == FS_LOAD_GLYPHS)
+ {
+ blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
+ if (blockedglyph->pfont == pfont)
+ {
+ if (blockrec->client == client)
+ {
+ if (blockedglyph->done)
+ {
+ int errcode = blockedglyph->errcode;
+ signal_clients_depending(&blockedglyph->
+ clients_depending);
+ _fs_remove_block_rec(conn, blockrec);
+ return errcode;
+ }
+ else return Suspended;
+ }
+ /* 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)
+ {
+ if (blockrec->client == client)
+ {
+ if (bfont->state == FS_DONE_REPLY)
+ {
+ int errcode = bfont->errcode;
+ signal_clients_depending(&bfont->clients_depending);
+ _fs_remove_block_rec(conn, blockrec);
+ if (errcode == Successful) break;
+ else return errcode;
+ }
+ else return Suspended;
+ }
+ /* 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 (bfont->state != FS_DONE_REPLY)
+ {
+ clients_depending = &bfont->clients_depending;
+ break;
+ }
+ }
+ }
+
+ blockrec = blockrec->next;
+ }
+
+ /*
+ * 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);
+ xfree(ranges);
+ }
+ return 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);
+ xfree(ranges);
+
+ /* Now try to reopen the font. */
+ return fs_send_open_font(client, (FontPathElementPtr)0,
+ (Mask)FontReopen, (char *)0, 0,
+ (fsBitmapFormat)0, (fsBitmapFormatMask)0,
+ (XID)0, &pfont);
+ }
+
+ return fs_send_load_glyphs(client, pfont, nranges, ranges);
+}
+
+
+
+static int
+fs_read_list(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsListFontsReply rep;
+ char *data,
+ *dp;
+ int length,
+ i;
+
+ blist->done = TRUE;
+
+ /* read reply header */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+ if (rep.type == FS_Error) {
+/* XXX -- translate FS error */
+ _fs_eat_rest_of_error(conn, (fsError *) & rep);
+ return AllocError;
+ }
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) == -1) {
+ /* nothing to free (i think) */
+ return StillWorking;
+ }
+ length = (rep.length << 2) - SIZEOF(fsListFontsReply);
+ data = (char *) xalloc(length);
+ if (!data) {
+ _fs_drain_bytes_pad(conn, length);
+ return AllocError;
+ }
+ /* read the list */
+ if (_fs_read_pad(conn, data, length) == -1) {
+ /* nothing to free (i think) */
+ return StillWorking;
+ }
+ /* copy data into FontPathRecord */
+ dp = data;
+ for (i = 0; i < rep.nFonts; i++) {
+ length = *(unsigned char *)dp++;
+ if (AddFontNamesName(blist->names, dp, length) != Successful) {
+ blist->errcode = AllocError;
+ break;
+ }
+ dp += length;
+ }
+
+ xfree(data);
+ return Successful;
+}
+
+static int
+fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
+ pointer client;
+ FontPathElementPtr fpe;
+ char *pattern;
+ int patlen;
+ int maxnames;
+ FontNamesPtr newnames;
+{
+ FSBlockDataPtr blockrec;
+ FSBlockedListPtr blockedlist;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsListFontsReq req;
+
+ _fs_client_access (conn, client, FALSE);
+ _fs_client_resolution(conn);
+
+ /* 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->patlen = patlen;
+ blockedlist->errcode = Successful;
+ blockedlist->names = newnames;
+ blockedlist->done = FALSE;
+
+ /* send the request */
+ req.reqType = FS_ListFonts;
+ 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);
+
+#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
+
+ return Suspended;
+}
+
+static int
+fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
+ pointer client;
+ FontPathElementPtr fpe;
+ char *pattern;
+ int patlen;
+ int maxnames;
+ FontNamesPtr newnames;
+{
+ FSBlockDataPtr blockrec;
+ FSBlockedListPtr blockedlist;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ int err;
+
+ /* see if the result is already there */
+ blockrec = (FSBlockDataPtr) conn->blocked_requests;
+ while (blockrec) {
+ if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) {
+ blockedlist = (FSBlockedListPtr) blockrec->data;
+ if (blockedlist->patlen == patlen && blockedlist->done) {
+ err = blockedlist->errcode;
+ _fs_remove_block_rec(conn, blockrec);
+ return err;
+ }
+ }
+ blockrec = blockrec->next;
+ }
+
+ /* didn't find waiting record, so send a new one */
+ return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
+}
+
+static int padlength[4] = {0, 3, 2, 1};
+
+static int
+fs_read_list_info(fpe, blockrec)
+ FontPathElementPtr fpe;
+ FSBlockDataPtr blockrec;
+{
+ FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
+ fsListFontsWithXInfoReply rep;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+ fsPropInfo pi;
+ fsPropOffset *po;
+ char *name;
+ pointer pd;
+ int err;
+
+ /* clean up anything from the last trip */
+ if (binfo->name)
+ {
+ xfree(binfo->name);
+ binfo->name = NULL;
+ }
+ if (binfo->pfi) {
+ xfree(binfo->pfi->isStringProp);
+ xfree(binfo->pfi->props);
+ xfree(binfo->pfi);
+ binfo->pfi = NULL;
+ }
+ /* get reply header */
+ memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
+ if (rep.type == FS_Error) {
+/* XXX -- translate FS error */
+ _fs_eat_rest_of_error(conn, (fsError *) & rep);
+ binfo->errcode = AllocError;
+ return AllocError;
+ }
+ if (conn->fsMajorVersion > 1)
+ if (rep.nameLength == 0)
+ goto done;
+ /* old protocol sent a full-length reply even for the last one */
+ if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
+ SIZEOF(fsListFontsWithXInfoReply) - SIZEOF(fsGenericReply)) == -1) {
+ goto done;
+ }
+ if (rep.nameLength == 0)
+ goto done;
+
+ /* read the data */
+ name = (char *) xalloc(rep.nameLength);
+ binfo->pfi = (FontInfoPtr) xalloc(sizeof(FontInfoRec));
+ if (!name || !binfo->pfi) {
+ xfree(name);
+ xfree(binfo->pfi);
+ binfo->pfi = NULL;
+ _fs_drain_bytes(conn,
+ rep.length - (SIZEOF(fsListFontsWithXInfoReply) -
+ SIZEOF(fsGenericReply)));
+ binfo->errcode = AllocError;
+ return AllocError;
+ }
+ if (conn->fsMajorVersion == 1)
+ if (_fs_read_pad(conn, name, rep.nameLength) == -1)
+ goto done;
+ if (_fs_read_pad(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1)
+ goto done;
+
+ po = (fsPropOffset *) xalloc(SIZEOF(fsPropOffset) * pi.num_offsets);
+ pd = (pointer) xalloc(pi.data_len);
+ if (!po || !pd) {
+ xfree(name);
+ xfree(po);
+ xfree(pd);
+ xfree (binfo->pfi);
+ binfo->pfi = NULL;
+ binfo->errcode = AllocError;
+ return AllocError;
+ }
+ err = _fs_read_pad(conn, (char *) po,
+ (pi.num_offsets * SIZEOF(fsPropOffset)));
+ if (err != -1)
+ {
+ if (conn->fsMajorVersion > 1)
+ err = _fs_read(conn, (char *) pd, pi.data_len);
+ else
+ err = _fs_read_pad(conn, (char *) pd, pi.data_len);
+ }
+ if (err != -1 && conn->fsMajorVersion != 1)
+ {
+ err = _fs_read(conn, name, rep.nameLength);
+ if (err != -1)
+ err = _fs_drain_bytes(conn, padlength[(pi.data_len+rep.nameLength)&3]);
+ }
+
+ if (err == -1) {
+ xfree(name);
+ xfree(po);
+ xfree(pd);
+ xfree (binfo->pfi);
+ binfo->pfi = NULL;
+ goto done;
+ }
+
+ if (_fs_convert_lfwi_reply(conn, binfo->pfi, &rep, &pi, po, pd) != Successful)
+ {
+ xfree(name);
+ xfree(po);
+ xfree(pd);
+ xfree (binfo->pfi);
+ binfo->pfi = NULL;
+ goto done;
+ }
+ xfree(po);
+ xfree(pd);
+ binfo->name = name;
+ binfo->namelen = rep.nameLength;
+ binfo->remaining = rep.nReplies;
+
+ binfo->status = FS_LFWI_REPLY;
+ binfo->errcode = Suspended;
+ /* disable this font server until we've processed this response */
+ FD_CLR(conn->fs_fd, &_fs_fd_mask);
+
+ return Successful;
+
+done:
+ binfo->status = FS_LFWI_FINISHED;
+ binfo->errcode = BadFontName;
+ binfo->name = (char *) 0;
+ return Successful;
+}
+
+/* ARGSUSED */
+static int
+fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
+ pointer client;
+ FontPathElementPtr fpe;
+ char *pattern;
+ int len;
+ int maxnames;
+ pointer *pdata;
+{
+ FSBlockDataPtr blockrec;
+ FSBlockedListInfoPtr blockedinfo;
+ fsListFontsWithXInfoReq req;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+
+ _fs_client_access (conn, client, FALSE);
+ _fs_client_resolution(conn);
+
+ /* 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;
+ blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
+ bzero((char *) blockedinfo, sizeof(FSBlockedListInfoRec));
+ blockedinfo->status = FS_LFWI_WAITING;
+ blockedinfo->errcode = Suspended;
+
+ /* send the request */
+ req.reqType = FS_ListFontsWithXInfo;
+ 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);
+
+#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
+
+ return Successful;
+}
+
+/* ARGSUSED */
+static int
+fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
+ private)
+ pointer client;
+ FontPathElementPtr fpe;
+ char **namep;
+ int *namelenp;
+ FontInfoPtr *pFontInfo;
+ int *numFonts;
+ pointer private;
+{
+ FSBlockDataPtr blockrec;
+ FSBlockedListInfoPtr blockedinfo;
+ FSFpePtr conn = (FSFpePtr) fpe->private;
+
+ /* see if the result is already there */
+ blockrec = (FSBlockDataPtr) conn->blocked_requests;
+ while (blockrec) {
+ if (blockrec->type == FS_LIST_WITH_INFO &&
+ blockrec->client == client) {
+ blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
+ break;
+ }
+ blockrec = blockrec->next;
+ }
+
+ 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;
+ }
+
+ if (blockedinfo->status == FS_LFWI_WAITING)
+ return Suspended;
+
+ *namep = blockedinfo->name;
+ *namelenp = blockedinfo->namelen;
+ *pFontInfo = blockedinfo->pfi;
+ *numFonts = blockedinfo->remaining;
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ if (blockedinfo->status == FS_LFWI_FINISHED) {
+ int err = blockedinfo->errcode;
+
+ _fs_remove_block_rec(conn, blockrec);
+ return err;
+ }
+ if (blockedinfo->status == FS_LFWI_REPLY) {
+ blockedinfo->status = FS_LFWI_WAITING;
+ return Successful;
+ } else {
+ return blockedinfo->errcode;
+ }
+}
+
+/*
+ * Called when client exits
+ */
+
+static void
+fs_client_died(client, fpe)
+ 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.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;
+ xfree (cur);
+ break;
+ }
+ }
+ /* see if the result is already there */
+ blockrec = (FSBlockDataPtr) conn->blocked_requests;
+ while (blockrec) {
+ if (blockrec->client == client)
+ break;
+ blockrec = blockrec->next;
+ }
+ if (!blockrec)
+ return;
+ if (blockrec->type == FS_LIST_WITH_INFO)
+ {
+ FSBlockedListInfoPtr binfo;
+ binfo = (FSBlockedListInfoPtr) blockrec->data;
+ if (binfo->status == FS_LFWI_REPLY)
+ FD_SET(conn->fs_fd, &_fs_fd_mask);
+ if (binfo->name)
+ {
+ xfree(binfo->name);
+ binfo->name = NULL;
+ }
+ if (binfo->pfi)
+ {
+ xfree(binfo->pfi->isStringProp);
+ xfree(binfo->pfi->props);
+ xfree(binfo->pfi);
+ binfo->pfi = NULL;
+ }
+ }
+ /* 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 (conn, client, sync)
+ FSFpePtr conn;
+ pointer client;
+ Bool sync;
+{
+ FSClientPtr *prev, cur;
+ fsCreateACReq crac;
+ fsSetAuthorizationReq setac;
+ fsGenericReply rep;
+ char *authorizations;
+ int authlen;
+ Bool new_cur = FALSE;
+
+ 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 = (FSClientPtr) xalloc (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.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);
+ authlen = crac.num_auths ? (authlen + 3) & ~0x3 : 0;
+ 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);
+ /* if we're synchronous, open_font will be confused by
+ * the reply; eat it and continue
+ */
+ if (sync)
+ {
+ if (_fs_read(conn, (char *) &rep, sizeof (fsGenericReply)) == -1)
+ return;
+ fs_handle_unexpected(conn, &rep);
+ }
+ /* 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.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;
+ }
+}
+
+/*
+ * called at server init time
+ */
+
+void
+fs_register_fpe_functions()
+{
+ fs_font_type = 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,
+ (int (*))0,
+ (int (*))0,
+ (void (*))0);
+}
+
+static int
+check_fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
+ alias, non_cachable_font)
+ pointer client;
+ FontPathElementPtr fpe;
+ Mask flags;
+ char *name;
+ fsBitmapFormat format;
+ fsBitmapFormatMask fmask;
+ int namelen;
+ XID id;
+ FontPtr *ppfont;
+ char **alias;
+ FontPtr non_cachable_font; /* Not used in this FPE */
+{
+ if (XpClientIsBitmapClient(client))
+ return (fs_open_font(client, fpe, flags, name, namelen, format,
+ fmask, id, ppfont, alias, non_cachable_font) );
+ return BadFontName;
+}
+
+static int
+check_fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
+ pointer client;
+ FontPathElementPtr fpe;
+ char *pattern;
+ int patlen;
+ int maxnames;
+ FontNamesPtr newnames;
+{
+ if (XpClientIsBitmapClient(client))
+ return (fs_list_fonts(client, fpe, pattern, patlen, maxnames,
+ newnames));
+ return BadFontName;
+}
+
+static int
+check_fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
+ pointer client;
+ FontPathElementPtr fpe;
+ char *pattern;
+ int len;
+ int maxnames;
+ pointer *pdata;
+{
+ if (XpClientIsBitmapClient(client))
+ return (fs_start_list_with_info(client, fpe, pattern, len, maxnames,
+ pdata));
+ return BadFontName;
+}
+
+static int
+check_fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
+ private)
+ pointer client;
+ FontPathElementPtr fpe;
+ char **namep;
+ int *namelenp;
+ FontInfoPtr *pFontInfo;
+ int *numFonts;
+ pointer private;
+{
+ if (XpClientIsBitmapClient(client))
+ return (fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo,
+ numFonts,private));
+ return BadFontName;
+}
+
+void
+check_fs_register_fpe_functions()
+{
+ fs_font_type = RegisterFPEFunctions(fs_name_check,
+ fs_init_fpe,
+ fs_free_fpe,
+ fs_reset_fpe,
+ check_fs_open_font,
+ fs_close_font,
+ check_fs_list_fonts,
+ check_fs_start_list_with_info,
+ check_fs_next_list_with_info,
+ fs_wakeup,
+ fs_client_died,
+ _fs_load_glyphs,
+ (int (*))0,
+ (int (*))0,
+ (void (*))0);
+}
diff --git a/src/fc/fserve.h b/src/fc/fserve.h
new file mode 100644
index 0000000..b5370d0
--- /dev/null
+++ b/src/fc/fserve.h
@@ -0,0 +1,68 @@
+/* $Xorg: fserve.h,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * 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
+
+#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_blocked_bitmaps *FSBlockedBitmapPtr;
+typedef struct _fs_blocked_extents *FSBlockedExtentPtr;
+
+extern void fs_convert_char_info();
+
+#endif /* _FSERVE_H_ */
diff --git a/src/fc/fservestr.h b/src/fc/fservestr.h
new file mode 100644
index 0000000..891d4ae
--- /dev/null
+++ b/src/fc/fservestr.h
@@ -0,0 +1,188 @@
+/* $Xorg: fservestr.h,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * 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_font {
+ CharInfoPtr pDefault;
+ CharInfoPtr encoding;
+ CharInfoPtr inkMetrics;
+} FSFontRec, *FSFontPtr;
+
+/* FS special data for the font */
+typedef struct _fs_font_data {
+ long fontid;
+ int generation; /* FS generation when opened */
+ FontPathElementPtr fpe;
+ 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;
+ long fontid;
+ int state; /* how many of the replies have landed */
+ int errcode;
+ int flags;
+ fsBitmapFormat format;
+ FSClientsDependingPtr clients_depending;
+} FSBlockedFontRec;
+
+/* LoadGlyphs data for blocked request */
+typedef struct _fs_blocked_glyphs {
+ FontPtr pfont;
+ int num_expected_ranges;
+ fsRange *expected_ranges;
+ int errcode;
+ Bool done;
+ FSClientsDependingPtr clients_depending;
+} FSBlockedGlyphRec;
+
+/* LoadExtents data for blocked request */
+typedef struct _fs_blocked_extents {
+ FontPtr pfont;
+ fsRange *expected_ranges;
+ int nranges;
+ Bool done;
+ unsigned long nextents;
+ fsXCharInfo *extents;
+} FSBlockedExtentRec;
+
+/* LoadBitmaps data for blocked request */
+typedef struct _fs_blocked_bitmaps {
+ FontPtr pfont;
+ fsRange *expected_ranges;
+ int nranges;
+ Bool done;
+ unsigned long size;
+ unsigned long nglyphs;
+ fsOffset32 *offsets;
+ pointer gdata;
+} FSBlockedBitmapRec;
+
+/* state for blocked ListFonts */
+typedef struct _fs_blocked_list {
+ FontNamesPtr names;
+ int patlen;
+ int errcode;
+ Bool done;
+} FSBlockedListRec;
+
+/* state for blocked ListFontsWithInfo */
+typedef struct _fs_blocked_list_info {
+ int status;
+ char *name;
+ int namelen;
+ FontInfoPtr pfi;
+ int remaining;
+ int errcode;
+} FSBlockedListInfoRec;
+
+/* state for blocked request */
+typedef struct _fs_block_data {
+ int type; /* Open Font, LoadGlyphs, ListFonts,
+ * ListWithInfo */
+ pointer client; /* who wants it */
+ int sequence_number;/* expected */
+ fsGenericReply header;
+ pointer data; /* type specific data */
+ 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(__STDC__) && !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)
+
+
+#endif /* _FSERVESTR_H_ */
diff --git a/src/fc/fsio.c b/src/fc/fsio.c
new file mode 100644
index 0000000..578d86a
--- /dev/null
+++ b/src/fc/fsio.c
@@ -0,0 +1,612 @@
+/* $Xorg: fsio.c,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * 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 WIN32
+#define _WILLWINSOCK_
+#endif
+
+#include "FS.h"
+#include "FSproto.h"
+
+#include "X11/Xtrans.h"
+#include "X11/Xpoll.h"
+#include "fontmisc.h"
+#include "fsio.h"
+
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#endif
+#include <errno.h>
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+#ifdef WIN32
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#undef EINTR
+#define EINTR WSAEINTR
+#endif
+
+/* 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
+#define ECHECK(err) (errno == err)
+#define ESET(val) errno = val
+#endif
+
+static int padlength[4] = {0, 3, 2, 1};
+fd_set _fs_fd_mask;
+
+int _fs_wait_for_readable();
+
+#ifdef SIGNALRETURNSINT
+#define SIGNAL_T int
+#else
+#define SIGNAL_T void
+#endif
+
+/* ARGSUSED */
+static SIGNAL_T
+_fs_alarm(foo)
+ int foo;
+{
+ return;
+}
+
+static XtransConnInfo
+_fs_connect(servername, timeout)
+ char *servername;
+ int timeout;
+{
+ XtransConnInfo trans_conn; /* transport connection object */
+ int ret = -1;
+#ifdef SIGALRM
+ unsigned oldTime;
+
+ SIGNAL_T(*oldAlarm) ();
+#endif
+
+ /*
+ * Open the network connection.
+ */
+ if( (trans_conn=_FontTransOpenCOTSClient(servername)) == NULL )
+ {
+ return (NULL);
+ }
+
+#ifdef SIGALRM
+ oldTime = alarm((unsigned) 0);
+ oldAlarm = signal(SIGALRM, _fs_alarm);
+ alarm((unsigned) timeout);
+#endif
+
+ ret = _FontTransConnect(trans_conn,servername);
+
+#ifdef SIGALRM
+ alarm((unsigned) 0);
+ signal(SIGALRM, oldAlarm);
+ alarm(oldTime);
+#endif
+
+ if (ret < 0)
+ {
+ _FontTransClose(trans_conn);
+ return (NULL);
+ }
+
+ /*
+ * Set the connection non-blocking since we use select() to block.
+ */
+
+ _FontTransSetOption(trans_conn, TRANS_NONBLOCKING, 1);
+
+ return trans_conn;
+}
+
+static int generationCount;
+
+/* ARGSUSED */
+static Bool
+_fs_setup_connection(conn, servername, timeout, copy_name_p)
+ FSFpePtr conn;
+ char *servername;
+ int timeout;
+ Bool copy_name_p;
+{
+ fsConnClientPrefix prefix;
+ fsConnSetup rep;
+ int setuplength;
+ fsConnSetupAccept conn_accept;
+ int endian;
+ int i;
+ int alt_len;
+ char *auth_data = NULL,
+ *vendor_string = NULL,
+ *alt_data = NULL,
+ *alt_dst;
+ FSFpeAltPtr alts;
+ int nalts;
+
+ if ((conn->trans_conn = _fs_connect(servername, 5)) == NULL)
+ return FALSE;
+
+ conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn);
+
+ conn->generation = ++generationCount;
+
+ /* send setup prefix */
+ endian = 1;
+ if (*(char *) &endian)
+ prefix.byteOrder = 'l';
+ else
+ prefix.byteOrder = 'B';
+
+ prefix.major_version = FS_PROTOCOL;
+ prefix.minor_version = FS_PROTOCOL_MINOR;
+
+/* XXX add some auth info here */
+ prefix.num_auths = 0;
+ prefix.auth_len = 0;
+
+ if (_fs_write(conn, (char *) &prefix, SIZEOF(fsConnClientPrefix)) == -1)
+ return FALSE;
+
+ /* read setup info */
+ if (_fs_read(conn, (char *) &rep, SIZEOF(fsConnSetup)) == -1)
+ return FALSE;
+
+ conn->fsMajorVersion = rep.major_version;
+ if (rep.major_version > FS_PROTOCOL)
+ return FALSE;
+
+ alts = 0;
+ /* parse alternate list */
+ if ((nalts = rep.num_alternates)) {
+ setuplength = rep.alternate_len << 2;
+ alts = (FSFpeAltPtr) xalloc(nalts * sizeof(FSFpeAltRec) +
+ setuplength);
+ if (!alts) {
+ _FontTransClose(conn->trans_conn);
+ errno = ENOMEM;
+ return FALSE;
+ }
+ alt_data = (char *) (alts + nalts);
+ if (_fs_read(conn, (char *) alt_data, setuplength) == -1) {
+ xfree(alts);
+ return FALSE;
+ }
+ alt_dst = alt_data;
+ for (i = 0; i < nalts; i++) {
+ alts[i].subset = alt_data[0];
+ alt_len = alt_data[1];
+ alts[i].name = alt_dst;
+ memmove(alt_dst, alt_data + 2, alt_len);
+ alt_dst[alt_len] = '\0';
+ alt_dst += (alt_len + 1);
+ alt_data += (2 + alt_len + padlength[(2 + alt_len) & 3]);
+ }
+ }
+ if (conn->alts)
+ xfree(conn->alts);
+ conn->alts = alts;
+ conn->numAlts = nalts;
+
+ setuplength = rep.auth_len << 2;
+ if (setuplength &&
+ !(auth_data = (char *) xalloc((unsigned int) setuplength))) {
+ _FontTransClose(conn->trans_conn);
+ errno = ENOMEM;
+ return FALSE;
+ }
+ if (_fs_read(conn, (char *) auth_data, setuplength) == -1) {
+ xfree(auth_data);
+ return FALSE;
+ }
+ if (rep.status != AuthSuccess) {
+ xfree(auth_data);
+ _FontTransClose(conn->trans_conn);
+ errno = EPERM;
+ return FALSE;
+ }
+ /* get rest */
+ if (_fs_read(conn, (char *) &conn_accept, (long) SIZEOF(fsConnSetupAccept)) == -1) {
+ xfree(auth_data);
+ return FALSE;
+ }
+ if ((vendor_string = (char *)
+ xalloc((unsigned) conn_accept.vendor_len + 1)) == NULL) {
+ xfree(auth_data);
+ _FontTransClose(conn->trans_conn);
+ errno = ENOMEM;
+ return FALSE;
+ }
+ if (_fs_read_pad(conn, (char *) vendor_string, conn_accept.vendor_len) == -1) {
+ xfree(vendor_string);
+ xfree(auth_data);
+ return FALSE;
+ }
+ xfree(auth_data);
+ xfree(vendor_string);
+
+ if (copy_name_p)
+ {
+ conn->servername = (char *) xalloc(strlen(servername) + 1);
+ if (conn->servername == NULL)
+ return FALSE;
+ strcpy(conn->servername, servername);
+ }
+ else
+ conn->servername = servername;
+
+ return TRUE;
+}
+
+static Bool
+_fs_try_alternates(conn, timeout)
+ FSFpePtr conn;
+ int timeout;
+{
+ int i;
+
+ for (i = 0; i < conn->numAlts; i++)
+ if (_fs_setup_connection(conn, conn->alts[i].name, timeout, TRUE))
+ return TRUE;
+ return FALSE;
+}
+
+#define FS_OPEN_TIMEOUT 30
+#define FS_REOPEN_TIMEOUT 10
+
+FSFpePtr
+_fs_open_server(servername)
+ char *servername;
+{
+ FSFpePtr conn;
+
+ conn = (FSFpePtr) xalloc(sizeof(FSFpeRec));
+ if (!conn) {
+ errno = ENOMEM;
+ return (FSFpePtr) NULL;
+ }
+ bzero((char *) conn, sizeof(FSFpeRec));
+ if (!_fs_setup_connection(conn, servername, FS_OPEN_TIMEOUT, TRUE)) {
+ if (!_fs_try_alternates(conn, FS_OPEN_TIMEOUT)) {
+ xfree(conn->alts);
+ xfree(conn);
+ return (FSFpePtr) NULL;
+ }
+ }
+ return conn;
+}
+
+Bool
+_fs_reopen_server(conn)
+ FSFpePtr conn;
+{
+ if (_fs_setup_connection(conn, conn->servername, FS_REOPEN_TIMEOUT, FALSE))
+ return TRUE;
+ if (_fs_try_alternates(conn, FS_REOPEN_TIMEOUT))
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * expects everything to be here. *not* to be called when reading huge
+ * numbers of replies, but rather to get each chunk
+ */
+int
+_fs_read(conn, data, size)
+ FSFpePtr conn;
+ char *data;
+ unsigned long size;
+{
+ long bytes_read;
+
+ if (size == 0) {
+
+#ifdef DEBUG
+ fprintf(stderr, "tried to read 0 bytes \n");
+#endif
+
+ return 0;
+ }
+ ESET(0);
+ while ((bytes_read = _FontTransRead(conn->trans_conn,
+ data, (int) size)) != size) {
+ if (bytes_read > 0) {
+ size -= bytes_read;
+ data += bytes_read;
+ } else if (ETEST()) {
+ /* in a perfect world, this shouldn't happen */
+ /* ... but then, its less than perfect... */
+ if (_fs_wait_for_readable(conn) == -1) { /* check for error */
+ _fs_connection_died(conn);
+ ESET(EPIPE);
+ return -1;
+ }
+ ESET(0);
+ } else if (ECHECK(EINTR)) {
+ continue;
+ } else { /* something bad happened */
+ if (conn->fs_fd > 0)
+ _fs_connection_died(conn);
+ ESET(EPIPE);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+_fs_write(conn, data, size)
+ FSFpePtr conn;
+ char *data;
+ unsigned long size;
+{
+ long bytes_written;
+
+ if (size == 0) {
+
+#ifdef DEBUG
+ fprintf(stderr, "tried to write 0 bytes \n");
+#endif
+
+ return 0;
+ }
+
+ /* XXX - hack. The right fix is to remember that the font server
+ has gone away when we first discovered it. */
+ if (!conn->trans_conn)
+ return -1;
+
+ ESET(0);
+ while ((bytes_written = _FontTransWrite(conn->trans_conn,
+ data, (int) size)) != size) {
+ if (bytes_written > 0) {
+ size -= bytes_written;
+ data += bytes_written;
+ } else if (ETEST()) {
+ /* XXX -- we assume this can't happen */
+
+#ifdef DEBUG
+ fprintf(stderr, "fs_write blocking\n");
+#endif
+ } else if (ECHECK(EINTR)) {
+ continue;
+ } else { /* something bad happened */
+ _fs_connection_died(conn);
+ ESET(EPIPE);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+_fs_read_pad(conn, data, len)
+ FSFpePtr conn;
+ char *data;
+ int len;
+{
+ char pad[3];
+
+ if (_fs_read(conn, data, len) == -1)
+ return -1;
+
+ /* read the junk */
+ if (padlength[len & 3]) {
+ return _fs_read(conn, pad, padlength[len & 3]);
+ }
+ return 0;
+}
+
+int
+_fs_write_pad(conn, data, len)
+ FSFpePtr conn;
+ char *data;
+ int len;
+{
+ static char pad[3];
+
+ if (_fs_write(conn, data, len) == -1)
+ return -1;
+
+ /* write the pad */
+ if (padlength[len & 3]) {
+ return _fs_write(conn, pad, padlength[len & 3]);
+ }
+ return 0;
+}
+
+/*
+ * returns the amount of data waiting to be read
+ */
+int
+_fs_data_ready(conn)
+ FSFpePtr conn;
+{
+ BytesReadable_t readable;
+
+ if (_FontTransBytesReadable(conn->trans_conn, &readable) < 0)
+ return -1;
+ return readable;
+}
+
+int
+_fs_wait_for_readable(conn)
+ FSFpePtr conn;
+{
+ fd_set r_mask;
+ fd_set e_mask;
+ int result;
+
+#ifdef DEBUG
+ fprintf(stderr, "read would block\n");
+#endif
+
+ do {
+ FD_ZERO(&r_mask);
+ FD_ZERO(&e_mask);
+ 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, NULL);
+ if (result == -1) {
+ if (ECHECK(EINTR) || ECHECK(EAGAIN))
+ continue;
+ else
+ return -1;
+ }
+ if (result && FD_ISSET(conn->fs_fd, &e_mask))
+ return -1;
+ } while (result <= 0);
+
+ return 0;
+}
+
+int
+_fs_set_bit(mask, fd)
+ fd_set* mask;
+ int fd;
+{
+ FD_SET(fd, mask);
+ return fd;
+}
+
+int
+_fs_is_bit_set(mask, fd)
+ fd_set* mask;
+ int fd;
+{
+ return FD_ISSET(fd, mask);
+}
+
+void
+_fs_bit_clear(mask, fd)
+ fd_set* mask;
+ int fd;
+{
+ FD_CLR(fd, mask);
+}
+
+int
+_fs_any_bit_set(mask)
+ fd_set* mask;
+{
+ return XFD_ANYSET(mask);
+}
+
+void
+_fs_or_bits(dst, m1, m2)
+ fd_set* dst;
+ fd_set* m1;
+ fd_set* m2;
+{
+#ifdef WIN32
+ int i;
+ if (dst != m1) {
+ for (i = m1->fd_count; --i >= 0; ) {
+ if (!FD_ISSET(m1->fd_array[i], dst))
+ FD_SET(m1->fd_array[i], dst);
+ }
+ }
+ if (dst != m2) {
+ for (i = m2->fd_count; --i >= 0; ) {
+ if (!FD_ISSET(m2->fd_array[i], dst))
+ FD_SET(m2->fd_array[i], dst);
+ }
+ }
+#else
+ XFD_ORSET(dst, m1, m2);
+#endif
+}
+
+int
+_fs_drain_bytes(conn, len)
+ FSFpePtr conn;
+ int len;
+{
+ char buf[128];
+
+#ifdef DEBUG
+ fprintf(stderr, "draining wire\n");
+#endif
+
+ while (len > 0) {
+ if (_fs_read(conn, buf, (len < 128) ? len : 128) < 0)
+ return -1;
+ len -= 128;
+ }
+ return 0;
+}
+
+void
+_fs_drain_bytes_pad(conn, len)
+ FSFpePtr conn;
+ int len;
+{
+ _fs_drain_bytes(conn, len);
+
+ /* read the junk */
+ if (padlength[len & 3]) {
+ _fs_drain_bytes(conn, padlength[len & 3]);
+ }
+}
+
+void
+_fs_eat_rest_of_error(conn, err)
+ FSFpePtr conn;
+ fsError *err;
+{
+ int len = (err->length - (SIZEOF(fsGenericReply) >> 2)) << 2;
+
+#ifdef DEBUG
+ fprintf(stderr, "clearing error\n");
+#endif
+
+ _fs_drain_bytes(conn, len);
+}
diff --git a/src/fc/fsio.h b/src/fc/fsio.h
new file mode 100644
index 0000000..dd33cdf
--- /dev/null
+++ b/src/fc/fsio.h
@@ -0,0 +1,82 @@
+/* $Xorg: fsio.h,v 1.3 2000/08/17 19:46:36 cpqbld Exp $ */
+/*
+ * 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_
+
+#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_WAIT 5
+#define FS_MAX_RECONNECT_WAIT 80
+
+/* FS specific font FontPathElement data */
+typedef struct _fs_fpe_data {
+ int fs_fd;
+ int current_seq;
+ char *servername;
+ char *requestedname; /* client's name for this connection */
+
+ int generation;
+ int numAlts;
+ int fsMajorVersion; /* font server major version number */
+ FSFpeAltPtr alts;
+
+ FSClientPtr clients;
+ XID curacid;
+#ifdef DEBUG
+ int reqindex;
+ int reqbuffer[REQUEST_LOG_SIZE];
+#endif
+
+ int attemptReconnect;
+
+/* XXX massive crock to get around stupid #include interferences */
+ pointer blocked_requests;
+/* Data for reconnect - put it here to avoid allocate failure nightmare */
+ long time_to_try;
+ long reconnect_delay;
+ struct _fs_fpe_data *next_reconnect;
+ struct _XtransConnInfo *trans_conn; /* transport connection object */
+} FSFpeRec, *FSFpePtr;
+
+FSFpePtr _fs_open_server();
+void _fs_bit_clear();
+
+#endif /* _FSIO_H_ */
diff --git a/src/fc/fslibos.h b/src/fc/fslibos.h
new file mode 100644
index 0000000..d666ea4
--- /dev/null
+++ b/src/fc/fslibos.h
@@ -0,0 +1,212 @@
+/* $Xorg: fslibos.h,v 1.4 2001/02/09 02:04:03 xorgcvs Exp $ */
+/*
+ * 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.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 OPEN_MAX
+#ifdef 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