diff options
Diffstat (limited to 'nx-X11/lib/font/fc/fserve.c')
-rw-r--r-- | nx-X11/lib/font/fc/fserve.c | 3480 |
1 files changed, 0 insertions, 3480 deletions
diff --git a/nx-X11/lib/font/fc/fserve.c b/nx-X11/lib/font/fc/fserve.c deleted file mode 100644 index 6bbb8c2a0..000000000 --- a/nx-X11/lib/font/fc/fserve.c +++ /dev/null @@ -1,3480 +0,0 @@ -/* $XdotOrg: xc/lib/font/fc/fserve.c,v 1.8 2005/07/09 06:36:12 keithp Exp $ */ -/* $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. - -*/ -/* $XFree86: xc/lib/font/fc/fserve.c,v 3.26tsi 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 names of Network Computing Devices, or Digital - * not be used in advertising or publicity pertaining to distribution - * of the software without specific, written prior permission. - * - * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, - * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - * - * Author: Dave Lemke, Network Computing Devices, Inc - */ -/* - * font server specific font access - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#ifdef WIN32 -#define _WILLWINSOCK_ -#endif -#define FONT_t -#define TRANS_CLIENT -#include "X11/Xtrans/Xtrans.h" -#include "X11/Xpoll.h" -#include <X11/fonts/FS.h> -#include <X11/fonts/FSproto.h> -#include <X11/X.h> -#include <X11/Xos.h> -#include <X11/fonts/fontmisc.h> -#include <X11/fonts/fontstruct.h> -#include "fservestr.h" -#include <X11/fonts/fontutil.h> -#include <errno.h> -#include <limits.h> - -#include <time.h> -#define Time_t time_t - -#ifdef NCD -#include <ncd/nvram.h> -#endif - -#include <stddef.h> - -#ifndef MIN -#define MIN(a,b) ((a)<(b)?(a):(b)) -#endif -#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) - -#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ - (pci)->rightSideBearing || \ - (pci)->ascent || \ - (pci)->descent || \ - (pci)->characterWidth) - -/* - * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words, - * so this converts for doing size comparisons. - */ -#define LENGTHOF(r) (SIZEOF(r) >> 2) - -/* Somewhat arbitrary limit on maximum reply size we'll try to read. */ -#define MAX_REPLY_LENGTH ((64 * 1024 * 1024) >> 2) - -extern void ErrorF(const char *f, ...); - -static int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); -static int fs_read_list_info ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); - -extern fd_set _fs_fd_mask; - -static void fs_block_handler ( pointer data, OSTimePtr wt, - pointer LastSelectMask ); -static int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); - -/* - * List of all FPEs - */ -static FSFpePtr fs_fpes; -/* - * Union of all FPE blockStates - */ -static CARD32 fs_blockState; - -static int _fs_restart_connection ( FSFpePtr conn ); -static void fs_send_query_bitmaps ( FontPathElementPtr fpe, - FSBlockDataPtr blockrec ); -static int fs_send_close_font ( FontPathElementPtr fpe, Font id ); -static void fs_client_died ( pointer client, FontPathElementPtr fpe ); -static void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); -static void _fs_client_resolution ( FSFpePtr conn ); -static fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); -static int fs_await_reply (FSFpePtr conn); -static void _fs_do_blocked (FSFpePtr conn); -static void fs_cleanup_bfont (FSBlockedFontPtr bfont); - -char _fs_glyph_undefined; -char _fs_glyph_requested; -char _fs_glyph_zero_length; - -static int generationCount; - -int FontServerRequestTimeout = 30 * 1000; - -static void -_fs_close_server (FSFpePtr conn); - -static FSFpePtr -_fs_init_conn (char *servername); - -static int -_fs_wait_connect (FSFpePtr conn); - -static int -_fs_send_init_packets (FSFpePtr conn); - -static void -_fs_check_reconnect (FSFpePtr conn); - -static void -_fs_start_reconnect (FSFpePtr conn); - -static void -_fs_free_conn (FSFpePtr conn); - -static int -fs_free_fpe(FontPathElementPtr fpe); - -/* - * Font server access - * - * the basic idea for the non-blocking access is to have the function - * called multiple times until the actual data is returned, instead - * of ClientBlocked. - * - * the first call to the function will cause the request to be sent to - * the font server, and a block record to be stored in the fpe's list - * of outstanding requests. the FS block handler also sticks the - * proper set of fd's into the select mask. when data is ready to be - * read in, the FS wakup handler will be hit. this will read the - * data off the wire into the proper block record, and then signal the - * client that caused the block so that it can restart. it will then - * call the access function again, which will realize that the data has - * arrived and return it. - */ - - -#ifdef DEBUG -static void -_fs_add_req_log(FSFpePtr conn, int opcode) -{ - conn->current_seq++; - fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", - conn->current_seq, opcode); - conn->reqbuffer[conn->reqindex].opcode = opcode; - conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; - conn->reqindex++; - if (conn->reqindex == REQUEST_LOG_SIZE) - conn->reqindex = 0; -} - -static void -_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) -{ - int i; - - for (i = 0; i < REQUEST_LOG_SIZE; i++) - if (conn->reqbuffer[i].sequence == rep->sequenceNumber) - break; - if (i == REQUEST_LOG_SIZE) - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", - rep->sequenceNumber); - else - fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", - rep->sequenceNumber, - conn->reqbuffer[i].opcode); -} - -#define _fs_reply_failed(rep, name, op) do { \ - if (rep) { \ - if (rep->type == FS_Error) \ - fprintf (stderr, "Error: %d Request: %s\n", \ - ((fsError *)rep)->request, #name); \ - else \ - fprintf (stderr, "Bad Length for %s Reply: %d %s %d\n", \ - #name, rep->length, op, LENGTHOF(name)); \ - } \ -} while (0) - -#else -#define _fs_add_req_log(conn,op) ((conn)->current_seq++) -#define _fs_add_rep_log(conn,rep) -#define _fs_reply_failed(rep,name,op) -#endif - -static Bool -fs_name_check(char *name) -{ -#ifdef __UNIXOS2__ - /* OS/2 uses D:/usr/X11R6/.... as fontfile pathnames, so check that - * there is not only a protocol/ prefix, but also that the first chars - * are not a drive letter - */ - if (name && isalpha(*name) && name[1] == ':') - return FALSE; -#endif - /* Just make sure there is a protocol/ prefix */ - return (name && *name != '/' && strchr(name, '/')); -} - -static void -_fs_client_resolution(FSFpePtr conn) -{ - fsSetResolutionReq srreq; - int num_res; - FontResolutionPtr res; - - res = GetClientResolutions(&num_res); - - if (num_res) { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) - (void)_fs_write_pad(conn, (char *) res, - (num_res * SIZEOF(fsResolution))); - } -} - -/* - * close font server and remove any state associated with - * this connection - this includes any client records. - */ - -static void -fs_close_conn(FSFpePtr conn) -{ - FSClientPtr client, nclient; - - _fs_close_server (conn); - - for (client = conn->clients; client; client = nclient) - { - nclient = client->next; - 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(FontPathElementPtr fpe) -{ - FSFpePtr conn; - char *name; - int err; - int ret; - - /* open font server */ - /* create FS specific fpe info */ - name = fpe->name; - - /* hack for old style names */ - if (*name == ':') - name++; /* skip ':' */ - - conn = _fs_init_conn (name); - if (!conn) - err = AllocError; - else - { - err = init_fs_handlers (fpe, fs_block_handler); - if (err != Successful) - { - _fs_free_conn (conn); - err = AllocError; - } - else - { - fpe->private = conn; - conn->next = fs_fpes; - fs_fpes = conn; - ret = _fs_wait_connect (conn); - if (ret != FSIO_READY) - { - fs_free_fpe (fpe); - err = BadFontPath; - } - else - err = Successful; - } - } - - if (err == Successful) - { -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Connected to font server \"%s\"\n", name); -#endif -#ifdef DEBUG - fprintf (stderr, "connected to FS \"%s\"\n", name); -#endif - } - else - { -#ifdef DEBUG - fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); -#endif -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Failed to connect to font server \"%s\"\n", name); -#endif - ; - } - return err; -} - -static int -fs_reset_fpe(FontPathElementPtr fpe) -{ - (void) _fs_send_init_packets((FSFpePtr) fpe->private); - return Successful; -} - -/* - * this shouldn't be called till all refs to the FPE are gone - */ - -static int -fs_free_fpe(FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private, *prev; - - /* unhook from chain of all font servers */ - for (prev = &fs_fpes; *prev; prev = &(*prev)->next) - { - if (*prev == conn) - { - *prev = conn->next; - break; - } - } - _fs_unmark_block (conn, conn->blockState); - fs_close_conn(conn); - remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); - _fs_free_conn (conn); - fpe->private = (pointer) 0; - -#ifdef NCD - if (configData.ExtendedFontDiags) - printf("Disconnected from font server \"%s\"\n", fpe->name); -#endif -#ifdef DEBUG - fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); -#endif - - return Successful; -} - -static FSBlockDataPtr -fs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) -{ - FSBlockDataPtr blockrec, - *prev; - FSFpePtr conn = (FSFpePtr) fpe->private; - int size; - - switch (type) { - case FS_OPEN_FONT: - size = sizeof(FSBlockedFontRec); - break; - case FS_LOAD_GLYPHS: - size = sizeof(FSBlockedGlyphRec); - break; - case FS_LIST_FONTS: - size = sizeof(FSBlockedListRec); - break; - case FS_LIST_WITH_INFO: - size = sizeof(FSBlockedListInfoRec); - break; - default: - size = 0; - break; - } - blockrec = (FSBlockDataPtr) xalloc(sizeof(FSBlockDataRec) + size); - if (!blockrec) - return (FSBlockDataPtr) 0; - blockrec->data = (pointer) (blockrec + 1); - blockrec->client = client; - blockrec->sequenceNumber = -1; - blockrec->errcode = StillWorking; - blockrec->type = type; - blockrec->depending = 0; - blockrec->next = (FSBlockDataPtr) 0; - - /* stick it on the end of the list (since its expected last) */ - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - ; - *prev = blockrec; - - return blockrec; -} - -static void -_fs_set_pending_reply (FSFpePtr conn) -{ - FSBlockDataPtr blockrec; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->errcode == StillWorking) - break; - if (blockrec) - { - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - } - else - _fs_unmark_block (conn, FS_PENDING_REPLY); -} - -static void -_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - FSBlockDataPtr *prev; - - for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) - if (*prev == blockrec) - { - *prev = blockrec->next; - break; - } - if (blockrec->type == FS_LOAD_GLYPHS) - { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - if (bglyph->num_expected_ranges) - xfree(bglyph->expected_ranges); - } - xfree(blockrec); - _fs_set_pending_reply (conn); -} - -static void -_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) -{ - FSClientsDependingPtr p; - - while ((p = *clients_depending)) - { - *clients_depending = p->next; - ClientSignal(p->client); - xfree(p); - } -} - -static int -_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) -{ - FSClientsDependingPtr new, cd; - - for (; (cd = *clients_depending); - clients_depending = &(*clients_depending)->next) - { - if (cd->client == client) - return Suspended; - } - - new = (FSClientsDependingPtr)xalloc (sizeof (FSClientsDependingRec)); - if (!new) - return BadAlloc; - - new->client = client; - new->next = 0; - *clients_depending = new; - return Suspended; -} - -/* - * When a request is aborted due to a font server failure, - * signal any depending clients to restart their dependant - * requests - */ -static void -_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - switch(blockrec->type) { - case FS_OPEN_FONT: { - FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; - - fs_cleanup_bfont (bfont); - _fs_signal_clients_depending(&bfont->clients_depending); - break; - } - case FS_LOAD_GLYPHS: { - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; - - _fs_clean_aborted_loadglyphs(bglyph->pfont, - bglyph->num_expected_ranges, - bglyph->expected_ranges); - _fs_signal_clients_depending(&bglyph->clients_depending); - break; - } - case FS_LIST_FONTS: - break; - case FS_LIST_WITH_INFO: { - FSBlockedListInfoPtr binfo; - binfo = (FSBlockedListInfoPtr) blockrec->data; - if (binfo->status == FS_LFWI_REPLY) - FD_SET(conn->fs_fd, &_fs_fd_mask); - _fs_free_props (&binfo->info); - } - default: - break; - } -} - -static void -fs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) -{ - _fs_clean_aborted_blockrec (conn, blockrec); - _fs_remove_block_rec (conn, blockrec); -} - -/* - * Tell the font server we've failed to complete an open and - * then unload the partially created font - */ -static void -fs_cleanup_bfont (FSBlockedFontPtr bfont) -{ - FSFontDataRec *fsd; - - if (bfont->pfont) - { - fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; - - /* make sure the FS knows we choked on it */ - fs_send_close_font(bfont->pfont->fpe, bfont->fontid); - - /* - * Either unload the font if it's being opened for - * the first time, or smash the generation field to - * mark this font as an orphan - */ - if (!(bfont->flags & FontReopen)) - { - if (bfont->freeFont) - (*bfont->pfont->unload_font) (bfont->pfont); -#ifdef DEBUG - else - fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); -#endif - bfont->pfont = 0; - } - else - fsd->generation = -1; - } -} - -/* - * Check to see if a complete reply is waiting - */ -static fsGenericReply * -fs_get_reply (FSFpePtr conn, int *error) -{ - char *buf; - fsGenericReply *rep; - int ret; - - /* block if the connection is down or paused in lfwi */ - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - { - *error = FSIO_BLOCK; - return 0; - } - - ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - rep = (fsGenericReply *) buf; - - /* - * Refuse to accept replies longer than a maximum reasonable length, - * before we pass to _fs_start_read, since it will try to resize the - * incoming connection buffer to this size. Also avoids integer overflow - * on 32-bit systems. - */ - if (rep->length > MAX_REPLY_LENGTH) - { - ErrorF("fserve: reply length %d > MAX_REPLY_LENGTH, disconnecting" - " from font server\n", rep->length); - _fs_connection_died (conn); - *error = FSIO_ERROR; - return 0; - } - - ret = _fs_start_read (conn, rep->length << 2, &buf); - if (ret != FSIO_READY) - { - *error = FSIO_BLOCK; - return 0; - } - - *error = FSIO_READY; - - return (fsGenericReply *) buf; -} - -static Bool -fs_reply_ready (FSFpePtr conn) -{ - fsGenericReply *rep; - - if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) - return FALSE; - if (fs_data_read (conn) < sizeof (fsGenericReply)) - return FALSE; - rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); - if (fs_data_read (conn) < rep->length << 2) - return FALSE; - return TRUE; -} - -static void -_fs_pending_reply (FSFpePtr conn) -{ - if (!(conn->blockState & FS_PENDING_REPLY)) - { - _fs_mark_block (conn, FS_PENDING_REPLY); - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - } -} - -static void -_fs_prepare_for_reply (FSFpePtr conn) -{ - _fs_pending_reply (conn); - _fs_flush (conn); -} - -/* - * Block (for a while) awaiting a complete reply - */ -static int -fs_await_reply (FSFpePtr conn) -{ - int ret; - - if (conn->blockState & FS_COMPLETE_REPLY) - return FSIO_READY; - - while (!fs_get_reply (conn, &ret)) - { - if (ret != FSIO_BLOCK) - return ret; - if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) - { - _fs_connection_died (conn); - return FSIO_ERROR; - } - } - return FSIO_READY; -} - -/* - * Process the reply to an OpenBitmapFont request - */ -static int -fs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsOpenBitmapFontReply *rep; - FSBlockDataPtr blockOrig; - FSBlockedFontPtr origBfont; - int ret; - - rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - (rep->length != LENGTHOF(fsOpenBitmapFontReply))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - _fs_reply_failed (rep, fsOpenBitmapFontReply, "!="); - return BadFontName; - } - - /* If we're not reopening a font and FS detected a duplicate font - open request, replace our reference to the new font with a - reference to an existing font (possibly one not finished - opening). If this is a reopen, keep the new font reference... - it's got the metrics and extents we read when the font was opened - before. This also gives us the freedom to easily close the font - if we we decide (in fs_read_query_info()) that we don't like what - we got. */ - - if (rep->otherid && !(bfont->flags & FontReopen)) - { - fs_cleanup_bfont (bfont); - - /* Find old font if we're completely done getting it from server. */ - bfont->pfont = find_old_font(rep->otherid); - bfont->freeFont = FALSE; - bfont->fontid = rep->otherid; - bfont->state = FS_DONE_REPLY; - /* - * look for a blocked request to open the same font - */ - for (blockOrig = conn->blockedRequests; - blockOrig; - blockOrig = blockOrig->next) - { - if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) - { - origBfont = (FSBlockedFontPtr) blockOrig->data; - if (origBfont->fontid == rep->otherid) - { - blockrec->depending = blockOrig->depending; - blockOrig->depending = blockrec; - bfont->state = FS_DEPENDING; - bfont->pfont = origBfont->pfont; - break; - } - } - } - if (bfont->pfont == NULL) - { - /* XXX - something nasty happened */ - ret = BadFontName; - } - else - ret = AccessDone; - } - else - { - bfont->pfont->info.cachable = rep->cachable != 0; - bfont->state = FS_INFO_REPLY; - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryInfoSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - ret = StillWorking; - } - _fs_done_read (conn, rep->length << 2); - return ret; -} - -static Bool -fs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) -{ - int i; - - if (pInfo1->firstCol != pInfo2->firstCol || - pInfo1->lastCol != pInfo2->lastCol || - pInfo1->firstRow != pInfo2->firstRow || - pInfo1->lastRow != pInfo2->lastRow || - pInfo1->defaultCh != pInfo2->defaultCh || - pInfo1->noOverlap != pInfo2->noOverlap || - pInfo1->terminalFont != pInfo2->terminalFont || - pInfo1->constantMetrics != pInfo2->constantMetrics || - pInfo1->constantWidth != pInfo2->constantWidth || - pInfo1->inkInside != pInfo2->inkInside || - pInfo1->inkMetrics != pInfo2->inkMetrics || - pInfo1->allExist != pInfo2->allExist || - pInfo1->drawDirection != pInfo2->drawDirection || - pInfo1->cachable != pInfo2->cachable || - pInfo1->anamorphic != pInfo2->anamorphic || - pInfo1->maxOverlap != pInfo2->maxOverlap || - pInfo1->fontAscent != pInfo2->fontAscent || - pInfo1->fontDescent != pInfo2->fontDescent || - pInfo1->nprops != pInfo2->nprops) - return FALSE; - -#define MATCH(xci1, xci2) \ - (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ - ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ - ((xci1).characterWidth == (xci2).characterWidth) && \ - ((xci1).ascent == (xci2).ascent) && \ - ((xci1).descent == (xci2).descent) && \ - ((xci1).attributes == (xci2).attributes)) - - if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || - !MATCH(pInfo1->minbounds, pInfo2->minbounds) || - !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || - !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) - return FALSE; - -#undef MATCH - - for (i = 0; i < pInfo1->nprops; i++) - if (pInfo1->isStringProp[i] != - pInfo2->isStringProp[i] || - pInfo1->props[i].name != - pInfo2->props[i].name || - pInfo1->props[i].value != - pInfo2->props[i].value) - { - return FALSE; - } - return TRUE; -} - -static int -fs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsQueryXInfoReply *rep; - char *buf; - long bufleft = 0; /* length of reply left to use */ - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - FontInfoPtr pInfo; - FontInfoRec tempInfo; - int err; - int ret; - - rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - (rep->length < LENGTHOF(fsQueryXInfoReply))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - _fs_reply_failed (rep, fsQueryXInfoReply, "<"); - return BadFontName; - } - - /* If this is a reopen, accumulate the query info into a dummy - font and compare to our original data. */ - if (bfont->flags & FontReopen) - pInfo = &tempInfo; - else - pInfo = &bfont->pfont->info; - - buf = (char *) rep; - buf += SIZEOF(fsQueryXInfoReply); - - bufleft = rep->length << 2; - bufleft -= SIZEOF(fsQueryXInfoReply); - - /* move the data over */ - fsUnpack_XFontInfoHeader(rep, pInfo); - - /* compute accelerators */ - _fs_init_fontinfo(conn, pInfo); - - /* Compute offsets into the reply */ - if (bufleft < SIZEOF(fsPropInfo)) - { - ret = -1; -#ifdef DEBUG - fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n", - bufleft); -#endif - goto bail; - } - pi = (fsPropInfo *) buf; - buf += SIZEOF (fsPropInfo); - bufleft -= SIZEOF (fsPropInfo); - - if ((bufleft / SIZEOF (fsPropOffset)) < pi->num_offsets) - { - ret = -1; -#ifdef DEBUG - fprintf(stderr, - "fsQueryXInfo: (bufleft / SIZEOF (fsPropOffset)) (%ld) < pi->num_offsets (%d)\n", - bufleft / SIZEOF (fsPropOffset), pi->num_offsets); -#endif - goto bail; - } - po = (fsPropOffset *) buf; - buf += pi->num_offsets * SIZEOF(fsPropOffset); - bufleft -= pi->num_offsets * SIZEOF(fsPropOffset); - - if (bufleft < pi->data_len) - { - ret = -1; -#ifdef DEBUG - fprintf(stderr, - "fsQueryXInfo: bufleft (%ld) < data_len (%d)\n", - bufleft, pi->data_len); -#endif - goto bail; - } - pd = (pointer) buf; - buf += pi->data_len; - bufleft -= pi->data_len; - - /* convert the properties and step over the reply */ - ret = _fs_convert_props(pi, po, pd, pInfo); - bail: - _fs_done_read (conn, rep->length << 2); - - if (ret == -1) - { - fs_cleanup_bfont (bfont); - return AllocError; - } - - if (bfont->flags & FontReopen) - { - /* We're reopening a font that we lost because of a downed - connection. In the interest of avoiding corruption from - opening a different font than the old one (we already have - its metrics, extents, and probably some of its glyphs), - verify that the metrics and properties all match. */ - - if (fs_fonts_match (pInfo, &bfont->pfont->info)) - { - err = Successful; - bfont->state = FS_DONE_REPLY; - } - else - { - fs_cleanup_bfont (bfont); - err = BadFontName; - } - _fs_free_props (pInfo); - - return err; - } - - /* - * Ask for terminal format fonts if possible - */ - if (bfont->pfont->info.terminalFont) - bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax); - - /* - * Figure out if the whole font should get loaded right now. - */ - if (glyphCachingMode == CACHING_OFF || - (glyphCachingMode == CACHE_16_BIT_GLYPHS - && !bfont->pfont->info.lastRow)) - { - bfont->flags |= FontLoadAll; - } - - /* - * Ready to send the query bitmaps; the terminal font bit has - * been computed and glyphCaching has been considered - */ - if (bfont->flags & FontLoadBitmaps) - { - fs_send_query_bitmaps (fpe, blockrec); - _fs_flush (conn); - } - - bfont->state = FS_EXTENT_REPLY; - - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryExtentsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - - return StillWorking; -} - -static int -fs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; - FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; - fsQueryXExtents16Reply *rep; - char *buf; - int i; - int numExtents; - int numInfos; - int ret; - Bool haveInk = FALSE; /* need separate ink metrics? */ - CharInfoPtr ci, pCI; - char *fsci; - fsXCharInfo fscilocal; - FontInfoRec *fi = &bfont->pfont->info; - - rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - (rep->length < LENGTHOF(fsQueryXExtents16Reply))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont (bfont); - _fs_reply_failed (rep, fsQueryXExtents16Reply, "<"); - return BadFontName; - } - - /* move the data over */ - /* need separate inkMetrics for fixed font server protocol version */ - numExtents = rep->num_extents; - numInfos = numExtents; - if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) - { - numInfos *= 2; - haveInk = TRUE; - } - if (numInfos >= (INT_MAX / sizeof(CharInfoRec))) { -#ifdef DEBUG - fprintf(stderr, - "fsQueryXExtents16: numInfos (%d) >= %ld\n", - numInfos, (INT_MAX / sizeof(CharInfoRec))); -#endif - pCI = NULL; - } - else if (numExtents > ((rep->length - LENGTHOF(fsQueryXExtents16Reply)) - / LENGTHOF(fsXCharInfo))) { -#ifdef DEBUG - fprintf(stderr, - "fsQueryXExtents16: numExtents (%d) > (%d - %d) / %d\n", - numExtents, rep->length, - LENGTHOF(fsQueryXExtents16Reply), LENGTHOF(fsXCharInfo)); -#endif - pCI = NULL; - } - else - pCI = malloc(sizeof(CharInfoRec) * numInfos); - - if (!pCI) - { - _fs_done_read (conn, rep->length << 2); - fs_cleanup_bfont(bfont); - return AllocError; - } - fsfont->encoding = pCI; - if (haveInk) - fsfont->inkMetrics = pCI + numExtents; - else - fsfont->inkMetrics = pCI; - - buf = (char *) rep; - buf += SIZEOF (fsQueryXExtents16Reply); - fsci = buf; - - fsd->glyphs_to_get = 0; - ci = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++) - { - memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ - _fs_convert_char_info(&fscilocal, &ci->metrics); - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - fsci = fsci + SIZEOF(fsXCharInfo); - /* Initialize the bits field for later glyph-caching use */ - if (NONZEROMETRICS(&ci->metrics)) - { - if (!haveInk && - (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || - ci->metrics.ascent == -ci->metrics.descent)) - pCI[i].bits = &_fs_glyph_zero_length; - else - { - pCI[i].bits = &_fs_glyph_undefined; - fsd->glyphs_to_get++; - } - } - else - pCI[i].bits = (char *)0; - ci++; - } - - /* Done with reply */ - _fs_done_read (conn, rep->length << 2); - - /* build bitmap metrics, ImageRectMax style */ - if (haveInk) - { - CharInfoPtr ii; - - ci = fsfont->encoding; - ii = fsfont->inkMetrics; - for (i = 0; i < numExtents; i++, ci++, ii++) - { - if (NONZEROMETRICS(&ii->metrics)) - { - ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); - ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); - ci->metrics.ascent = FONT_MAX_ASCENT(fi); - ci->metrics.descent = FONT_MAX_DESCENT(fi); - ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); - ci->metrics.attributes = ii->metrics.attributes; - } - else - { - ci->metrics = ii->metrics; - } - /* Bounds check. */ - if (ci->metrics.ascent > fi->maxbounds.ascent) - { - ErrorF("fserve: warning: %s %s ascent (%d) " - "> maxascent (%d)\n", - fpe->name, fsd->name, - ci->metrics.ascent, fi->maxbounds.ascent); - ci->metrics.ascent = fi->maxbounds.ascent; - } - if (ci->metrics.descent > fi->maxbounds.descent) - { - ErrorF("fserve: warning: %s %s descent (%d) " - "> maxdescent (%d)\n", - fpe->name, fsd->name, - ci->metrics.descent, fi->maxbounds.descent); - ci->metrics.descent = fi->maxbounds.descent; - } - } - } - { - unsigned int r, c, numCols, firstCol; - - firstCol = bfont->pfont->info.firstCol; - numCols = bfont->pfont->info.lastCol - firstCol + 1; - c = bfont->pfont->info.defaultCh; - fsfont->pDefault = 0; - if (bfont->pfont->info.lastRow) - { - r = c >> 8; - r -= bfont->pfont->info.firstRow; - c &= 0xff; - c -= firstCol; - if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && - c < numCols) - fsfont->pDefault = &pCI[r * numCols + c]; - } - else - { - c -= firstCol; - if (c < numCols) - fsfont->pDefault = &pCI[c]; - } - } - bfont->state = FS_GLYPHS_REPLY; - - if (bfont->flags & FontLoadBitmaps) - { - /* - * Reset the blockrec for the next reply - */ - blockrec->sequenceNumber = bfont->queryBitmapsSequence; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - return StillWorking; - } - return Successful; -} - -#ifdef DEBUG -static char *fs_open_states[] = { - "OPEN_REPLY ", - "INFO_REPLY ", - "EXTENT_REPLY", - "GLYPHS_REPLY", - "DONE_REPLY ", - "DEPENDING ", -}; -#endif - -static int -fs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - int err; - -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font state %s %s\n", - fs_open_states[bfont->state], - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); -#endif - err = BadFontName; - switch (bfont->state) { - case FS_OPEN_REPLY: - err = fs_read_open_font(fpe, blockrec); - if (err != StillWorking) { /* already loaded, or error */ - /* if font's already loaded, massage error code */ - switch (bfont->state) { - case FS_DONE_REPLY: - err = Successful; - break; - case FS_DEPENDING: - err = StillWorking; - break; - } - } - break; - case FS_INFO_REPLY: - err = fs_read_query_info(fpe, blockrec); - break; - case FS_EXTENT_REPLY: - err = fs_read_extent_info(fpe, blockrec); - break; - case FS_GLYPHS_REPLY: - if (bfont->flags & FontLoadBitmaps) - err = fs_read_glyphs(fpe, blockrec); - break; - case FS_DEPENDING: /* can't happen */ - default: - break; - } -#ifdef DEBUG - fprintf (stderr, "fs_do_open_font err %d\n", err); -#endif - if (err != StillWorking) - { - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - while ((blockrec = blockrec->depending)) - { - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ - } - } - return err; -} - -void -_fs_mark_block (FSFpePtr conn, CARD32 mask) -{ - conn->blockState |= mask; - fs_blockState |= mask; -} - -void -_fs_unmark_block (FSFpePtr conn, CARD32 mask) -{ - FSFpePtr c; - - if (conn->blockState & mask) - { - conn->blockState &= ~mask; - fs_blockState = 0; - for (c = fs_fpes; c; c = c->next) - fs_blockState |= c->blockState; - } -} - -/* ARGSUSED */ -static void -fs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) -{ - static struct timeval block_timeout; - CARD32 now, earliest, wakeup; - int soonest; - FSFpePtr conn; - - XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, - &_fs_fd_mask); - /* - * Flush all pending output - */ - if (fs_blockState & FS_PENDING_WRITE) - for (conn = fs_fpes; conn; conn = conn->next) - if (conn->blockState & FS_PENDING_WRITE) - _fs_flush (conn); - /* - * Check for any fpe with a complete reply, set sleep time to zero - */ - if (fs_blockState & FS_COMPLETE_REPLY) - { - block_timeout.tv_sec = 0; - block_timeout.tv_usec = 0; - if (*wt == NULL) - *wt = &block_timeout; - else - **wt = block_timeout; - } - /* - * Walk through fpe list computing sleep time - */ - else if (fs_blockState & (FS_BROKEN_WRITE| - FS_BROKEN_CONNECTION| - FS_PENDING_REPLY| - FS_RECONNECTING)) - { - now = GetTimeInMillis (); - earliest = now + 10000000; - for (conn = fs_fpes; conn; conn = conn->next) - { - if (conn->blockState & FS_RECONNECTING) - { - wakeup = conn->blockedConnectTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_CONNECTION) - { - wakeup = conn->brokenConnectionTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_BROKEN_WRITE) - { - wakeup = conn->brokenWriteTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - if (conn->blockState & FS_PENDING_REPLY) - { - wakeup = conn->blockedReplyTime; - if (TimeCmp (wakeup, <, earliest)) - earliest = wakeup; - } - } - soonest = earliest - now; - if (soonest < 0) - soonest = 0; - block_timeout.tv_sec = soonest / 1000; - block_timeout.tv_usec = (soonest % 1000) * 1000; - if (*wt == NULL) - *wt = &block_timeout; - else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) - **wt = block_timeout; - } -} - -static void -fs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) -{ - if (rep->type == FS_Event && rep->data1 == KeepAlive) - { - fsNoopReq req; - - /* ping it back */ - req.reqType = FS_Noop; - req.length = SIZEOF(fsNoopReq) >> 2; - _fs_add_req_log(conn, FS_Noop); - _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); - } - /* this should suck up unexpected replies and events */ - _fs_done_read (conn, rep->length << 2); -} - -static void -fs_read_reply (FontPathElementPtr fpe, pointer client) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int ret; - int err; - fsGenericReply *rep; - - if ((rep = fs_get_reply (conn, &ret))) - { - _fs_add_rep_log (conn, rep); - for (blockrec = conn->blockedRequests; - blockrec; - blockrec = blockrec->next) - { - if (blockrec->sequenceNumber == rep->sequenceNumber) - break; - } - err = Successful; - if (!blockrec) - { - fs_handle_unexpected(conn, rep); - } - else - { - /* - * go read it, and if we're done, - * wake up the appropriate client - */ - switch (blockrec->type) { - case FS_OPEN_FONT: - blockrec->errcode = fs_do_open_font(fpe, blockrec); - break; - case FS_LOAD_GLYPHS: - blockrec->errcode = fs_read_glyphs(fpe, blockrec); - break; - case FS_LIST_FONTS: - blockrec->errcode = fs_read_list(fpe, blockrec); - break; - case FS_LIST_WITH_INFO: - blockrec->errcode = fs_read_list_info(fpe, blockrec); - break; - default: - break; - } - err = blockrec->errcode; - if (err != StillWorking) - { - while (blockrec) - { - blockrec->errcode = err; - if (client != blockrec->client) - ClientSignal(blockrec->client); - blockrec = blockrec->depending; - } - _fs_unmark_block (conn, FS_PENDING_REPLY); - } - } - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - else - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - } -} - -static int -fs_wakeup(FontPathElementPtr fpe, unsigned long *mask) -{ - fd_set *LastSelectMask = (fd_set *) mask; - FSFpePtr conn = (FSFpePtr) fpe->private; - - /* - * Don't continue if the fd is -1 (which will be true when the - * font server terminates - */ - if ((conn->blockState & FS_RECONNECTING)) - _fs_check_reconnect (conn); - else if ((conn->blockState & FS_COMPLETE_REPLY) || - (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) - fs_read_reply (fpe, 0); - if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) - _fs_do_blocked (conn); -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - FSBlockedListPtr blist; - static CARD32 lastState; - static FSBlockDataPtr lastBlock; - - if (conn->blockState || conn->blockedRequests || lastState || lastBlock) - { - fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); - lastState = conn->blockState; - lastBlock = conn->blockedRequests; - } - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - switch (blockrec->type) { - case FS_OPEN_FONT: - bfont = (FSBlockedFontPtr) blockrec->data; - fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", - blockrec->errcode, - blockrec->sequenceNumber, - fs_open_states[bfont->state], - bfont->pfont ? - ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : - "<freed>"); - break; - case FS_LIST_FONTS: - blist = (FSBlockedListPtr) blockrec->data; - fprintf (stderr, " Blocked list errcode %d sequence %d\n", - blockrec->errcode, blockrec->sequenceNumber); - break; - default: - fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", - blockrec->type, - blockrec->errcode, - blockrec->sequenceNumber); - break; - } - } - } -#endif - return FALSE; -} - -/* - * Notice a dead connection and prepare for reconnect - */ - -void -_fs_connection_died(FSFpePtr conn) -{ - if (conn->blockState & FS_BROKEN_CONNECTION) - return; - fs_close_conn(conn); - conn->brokenConnectionTime = GetTimeInMillis (); - _fs_mark_block (conn, FS_BROKEN_CONNECTION); - _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); -} - -/* - * Signal clients that the connection has come back up - */ -static int -_fs_restart_connection(FSFpePtr conn) -{ - FSBlockDataPtr block; - - _fs_unmark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal(block->client); - fs_abort_blockrec(conn, block); - } - } - return TRUE; -} - -/* - * Declare this font server connection useless - */ -static void -_fs_giveup (FSFpePtr conn) -{ - FSBlockDataPtr block; - - if (conn->blockState & FS_GIVE_UP) - return; -#ifdef DEBUG - fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); -#endif - _fs_mark_block (conn, FS_GIVE_UP); - while ((block = (FSBlockDataPtr) conn->blockedRequests)) - { - if (block->errcode == StillWorking) - { - ClientSignal (block->client); - fs_abort_blockrec (conn, block); - } - } - if (conn->fs_fd >= 0) - _fs_connection_died (conn); -} - -static void -_fs_do_blocked (FSFpePtr conn) -{ - CARD32 now; - - now = GetTimeInMillis (); - if ((conn->blockState & FS_PENDING_REPLY) && - TimeCmp (conn->blockedReplyTime, <=, now)) - { - _fs_giveup (conn); - } - else - { - if (conn->blockState & FS_BROKEN_CONNECTION) - { - /* Try to reconnect broken connections */ - if (TimeCmp (conn->brokenConnectionTime, <=, now)) - _fs_start_reconnect (conn); - } - else if (conn->blockState & FS_BROKEN_WRITE) - { - /* Try to flush blocked connections */ - if (TimeCmp (conn->brokenWriteTime, <=, now)) - _fs_flush (conn); - } - } -} - -/* - * sends the actual request out - */ -/* ARGSUSED */ -static int -fs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr font; - FSBlockDataPtr blockrec = NULL; - FSBlockedFontPtr bfont; - FSFontDataPtr fsd; - fsOpenBitmapFontReq openreq; - fsQueryXInfoReq inforeq; - fsQueryXExtents16Req extreq; - int err; - unsigned char buf[1024]; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - if (namelen <= 0 || namelen > sizeof (buf) - 1) - return BadFontName; - - /* - * Get the font structure put together, either by reusing - * the existing one or creating a new one - */ - if (flags & FontReopen) - { - Atom nameatom, fn = None; - int i; - - font = *ppfont; - fsd = (FSFontDataPtr)font->fpePrivate; - /* This is an attempt to reopen a font. Did the font have a - NAME property? */ - if ((nameatom = MakeAtom("FONT", 4, 0)) != None) - { - for (i = 0; i < font->info.nprops; i++) - if (font->info.props[i].name == nameatom && - font->info.isStringProp[i]) - { - fn = font->info.props[i].value; - break; - } - } - if (fn == None || !(name = NameForAtom(fn))) - { - name = fsd->name; - namelen = fsd->namelen; - } - else - namelen = strlen(name); - } - else - { - font = fs_create_font (fpe, name, namelen, format, fmask); - if (!font) - return AllocError; - - fsd = (FSFontDataPtr)font->fpePrivate; - } - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); - if (!blockrec) - { - if (!(flags & FontReopen)) - (*font->unload_font) (font); - return AllocError; - } - - /* - * Must check this before generating any protocol, otherwise we'll - * mess up a reconnect in progress - */ - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - fsd->generation = conn->generation; - - bfont = (FSBlockedFontPtr) blockrec->data; - bfont->fontid = fsd->fontid; - bfont->pfont = font; - bfont->state = FS_OPEN_REPLY; - bfont->flags = flags; - bfont->format = fsd->format; - bfont->clients_depending = (FSClientsDependingPtr)0; - bfont->freeFont = (flags & FontReopen) == 0; - - _fs_client_access (conn, client, (flags & FontOpenSync) != 0); - _fs_client_resolution(conn); - - /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ - buf[0] = (unsigned char) namelen; - memcpy(&buf[1], name, namelen); - openreq.reqType = FS_OpenBitmapFont; - openreq.fid = fsd->fontid; - openreq.format_hint = fsd->format; - openreq.format_mask = fsd->fmask; - openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; - - _fs_add_req_log(conn, FS_OpenBitmapFont); - _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); - _fs_write_pad(conn, (char *) buf, namelen + 1); - - blockrec->sequenceNumber = conn->current_seq; - - inforeq.reqType = FS_QueryXInfo; - inforeq.id = fsd->fontid; - inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; - - bfont->queryInfoSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXInfo); - _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); - - if (!(bfont->flags & FontReopen)) - { - extreq.reqType = FS_QueryXExtents16; - extreq.range = fsTrue; - extreq.fid = fsd->fontid; - extreq.num_ranges = 0; - extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; - - bfont->queryExtentsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXExtents16); - _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); - } - -#ifdef NCD - if (configData.ExtendedFontDiags) - { - memcpy(buf, name, MIN(256, namelen)); - buf[MIN(256, namelen)] = '\0'; - printf("Requesting font \"%s\" from font server \"%s\"\n", - buf, font->fpe->name); - } -#endif - _fs_prepare_for_reply (conn); - - err = blockrec->errcode; - if (bfont->flags & FontOpenSync) - { - while (blockrec->errcode == StillWorking) - { - if (fs_await_reply (conn) != FSIO_READY) - { - blockrec->errcode = BadFontName; - break; - } - fs_read_reply (font->fpe, client); - } - err = blockrec->errcode; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - bfont->freeFont = FALSE; - _fs_remove_block_rec (conn, blockrec); - } - return err == StillWorking ? Suspended : err; -} - -static void -fs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - fsQueryXBitmaps16Req bitreq; - - /* send the request */ - bitreq.reqType = FS_QueryXBitmaps16; - bitreq.fid = bfont->fontid; - bitreq.format = bfont->format; - bitreq.range = TRUE; - bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; - bitreq.num_ranges = 0; - - bfont->queryBitmapsSequence = conn->current_seq + 1; - - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); -} - -/* ARGSUSED */ -static int -fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont, - char **alias, FontPtr non_cachable_font) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - int err; - - /* libfont interface expects ImageRectMin glyphs */ - format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; - - *alias = (char *) 0; - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - bfont = (FSBlockedFontPtr) blockrec->data; - if (err == Successful) - *ppfont = bfont->pfont; - else - fs_cleanup_bfont (bfont); - _fs_remove_block_rec (conn, blockrec); - return err; - } - } - return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, - id, ppfont); -} - -/* ARGSUSED */ -static int -fs_send_close_font(FontPathElementPtr fpe, Font id) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - fsCloseReq req; - - if (conn->blockState & FS_GIVE_UP) - return Successful; - /* tell the font server to close the font */ - req.reqType = FS_CloseFont; - req.length = SIZEOF(fsCloseReq) >> 2; - req.id = id; - _fs_add_req_log(conn, FS_CloseFont); - _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); - - return Successful; -} - -/* ARGSUSED */ -static void -fs_close_font(FontPathElementPtr fpe, FontPtr pfont) -{ - FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; - FSFpePtr conn = (FSFpePtr) fpe->private; - - if (conn->generation == fsd->generation) - fs_send_close_font(fpe, fsd->fontid); - -#ifdef DEBUG - { - FSBlockDataPtr blockrec; - FSBlockedFontPtr bfont; - - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_OPEN_FONT) - { - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - fprintf (stderr, "closing font which hasn't been opened\n"); - } - } - } -#endif - (*pfont->unload_font) (pfont); -} - -static int -fs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; - FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; - FSFpePtr conn = (FSFpePtr) fpe->private; - FontPtr pfont = bglyph->pfont; - /* works for either blocked font - or glyph rec... pfont is at - the very beginning of both - blockrec->data structures */ - FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); - FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; - FontInfoPtr pfi = &pfont->info; - fsQueryXBitmaps16Reply *rep; - char *buf; - long bufleft = 0; /* length of reply left to use */ - fsOffset32 *ppbits; - fsOffset32 local_off; - char *off_adr; - pointer pbitmaps; - char *bits, *allbits; -#ifdef DEBUG - char *origallbits; -#endif - int i, - err; - int nranges = 0; - int ret; - fsRange *nextrange = 0; - unsigned long minchar, maxchar; - - rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - (rep->length < LENGTHOF(fsQueryXBitmaps16Reply))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - err = AllocError; - _fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<"); - goto bail; - } - - buf = (char *) rep; - buf += SIZEOF (fsQueryXBitmaps16Reply); - - bufleft = rep->length << 2; - bufleft -= SIZEOF (fsQueryXBitmaps16Reply); - - if ((bufleft / SIZEOF (fsOffset32)) < rep->num_chars) - { -#ifdef DEBUG - fprintf(stderr, - "fsQueryXBitmaps16: num_chars (%d) > bufleft (%ld) / %d\n", - rep->num_chars, bufleft, SIZEOF (fsOffset32)); -#endif - err = AllocError; - goto bail; - } - ppbits = (fsOffset32 *) buf; - buf += SIZEOF (fsOffset32) * (rep->num_chars); - bufleft -= SIZEOF (fsOffset32) * (rep->num_chars); - - if (bufleft < rep->nbytes) - { -#ifdef DEBUG - fprintf(stderr, - "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n", - rep->nbytes, bufleft); -#endif - err = AllocError; - goto bail; - } - pbitmaps = (pointer ) buf; - - if (blockrec->type == FS_LOAD_GLYPHS) - { - nranges = bglyph->num_expected_ranges; - nextrange = bglyph->expected_ranges; - } - - /* place the incoming glyphs */ - if (nranges) - { - /* We're operating under the assumption that the ranges - requested in the LoadGlyphs call were all legal for this - font, and that individual ranges do not cover multiple - rows... fs_build_range() is designed to ensure this. */ - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - else - { - minchar = 0; - maxchar = rep->num_chars; - } - - off_adr = (char *)ppbits; - - allbits = fs_alloc_glyphs (pfont, rep->nbytes); - - if (!allbits) - { - err = AllocError; - goto bail; - } - -#ifdef DEBUG - origallbits = allbits; - fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", - (int) rep->num_chars, (int) rep->nbytes, fsd->name); -#endif - - for (i = 0; i < rep->num_chars; i++) - { - memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ - if (blockrec->type == FS_OPEN_FONT || - fsdata->encoding[minchar].bits == &_fs_glyph_requested) - { - /* - * Broken X font server returns bits for missing characters - * when font is padded - */ - if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) - { - if (local_off.length && - (local_off.position < rep->nbytes) && - (local_off.length <= (rep->nbytes - local_off.position))) - { - bits = allbits; - allbits += local_off.length; - memcpy(bits, (char *)pbitmaps + local_off.position, - local_off.length); - } - else - bits = &_fs_glyph_zero_length; - } - else - bits = 0; - if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) - fsd->glyphs_to_get--; - fsdata->encoding[minchar].bits = bits; - } - if (minchar++ == maxchar) - { - if (!--nranges) break; - minchar = (nextrange->min_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->min_char_low - pfi->firstCol; - maxchar = (nextrange->max_char_high - pfi->firstRow) * - (pfi->lastCol - pfi->firstCol + 1) + - nextrange->max_char_low - pfi->firstCol; - nextrange++; - } - off_adr += SIZEOF(fsOffset32); - } -#ifdef DEBUG - fprintf (stderr, "Used %d bytes instead of %d\n", - (int) (allbits - origallbits), (int) rep->nbytes); -#endif - - if (blockrec->type == FS_OPEN_FONT) - { - fsd->glyphs_to_get = 0; - bfont->state = FS_DONE_REPLY; - } - err = Successful; - -bail: - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_load_glyphs(pointer client, FontPtr pfont, - int nranges, fsRange *ranges) -{ - FontPathElementPtr fpe = pfont->fpe; - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedGlyphPtr blockedglyph; - fsQueryXBitmaps16Req req; - FSBlockDataPtr blockrec; - - if (conn->blockState & FS_GIVE_UP) - return BadCharRange; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); - if (!blockrec) - return AllocError; - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - blockedglyph->pfont = pfont; - blockedglyph->num_expected_ranges = nranges; - /* Assumption: it's our job to free ranges */ - blockedglyph->expected_ranges = ranges; - blockedglyph->clients_depending = (FSClientsDependingPtr)0; - - if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - /* send the request */ - req.reqType = FS_QueryXBitmaps16; - req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; - req.format = pfont->format; - if (pfont->info.terminalFont) - req.format = (req.format & ~(BitmapFormatImageRectMask)) | - BitmapFormatImageRectMax; - req.range = TRUE; - /* each range takes up 4 bytes */ - req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; - req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ - _fs_add_req_log(conn, FS_QueryXBitmaps16); - _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); - - blockrec->sequenceNumber = conn->current_seq; - - /* Send ranges to the server... pack into a char array by hand - to avoid structure-packing portability problems and to - handle swapping for version1 protocol */ - if (nranges) - { -#define RANGE_BUFFER_SIZE 64 -#define RANGE_BUFFER_SIZE_MASK 63 - int i; - char range_buffer[RANGE_BUFFER_SIZE * 4]; - char *range_buffer_p; - - range_buffer_p = range_buffer; - for (i = 0; i < nranges;) - { - if (conn->fsMajorVersion > 1) - { - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - } - else - { - *range_buffer_p++ = ranges[i].min_char_low; - *range_buffer_p++ = ranges[i].min_char_high; - *range_buffer_p++ = ranges[i].max_char_low; - *range_buffer_p++ = ranges[i].max_char_high; - } - - if (!(++i & RANGE_BUFFER_SIZE_MASK)) - { - _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); - range_buffer_p = range_buffer; - } - } - if (i &= RANGE_BUFFER_SIZE_MASK) - _fs_write(conn, range_buffer, i * 4); - } - - _fs_prepare_for_reply (conn); - return Suspended; -} - - -extern pointer serverClient; /* This could be any number that - doesn't conflict with existing - client values. */ - -int -fs_load_all_glyphs(FontPtr pfont) -{ - int err; - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - - /* - * The purpose of this procedure is to load all glyphs in the event - * that we're dealing with someone who doesn't understand the finer - * points of glyph caching... it is called from _fs_get_glyphs() if - * the latter is called to get glyphs that have not yet been loaded. - * We assume that the caller will not know how to handle a return - * value of Suspended (usually the case for a GetGlyphs() caller), - * so this procedure hangs around, freezing the server, for the - * request to complete. This is an unpleasant kluge called to - * perform an unpleasant job that, we hope, will never be required. - */ - - while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == - Suspended) - { - if (fs_await_reply (conn) != FSIO_READY) - { - /* Get rid of blockrec */ - fs_client_died(serverClient, pfont->fpe); - err = BadCharRange; - break; - } - fs_read_reply (pfont->fpe, serverClient); - } - return err; -} - - -int -_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, - unsigned int nchars, int item_size, unsigned char *data) -{ - FSFpePtr conn = (FSFpePtr) pfont->fpe->private; - int nranges = 0; - fsRange *ranges = NULL; - int res; - FSBlockDataPtr blockrec; - FSBlockedGlyphPtr blockedglyph; - FSClientsDependingPtr *clients_depending = NULL; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LOAD_GLYPHS) - { - blockedglyph = (FSBlockedGlyphPtr) blockrec->data; - if (blockedglyph->pfont == pfont) - { - /* Look for this request */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_signal_clients_depending(&blockedglyph->clients_depending); - _fs_remove_block_rec(conn, blockrec); - return err; - } - /* We've found an existing LoadGlyphs blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing LoadGlyphs is - completed. */ - clients_depending = &blockedglyph->clients_depending; - break; - } - } - else if (blockrec->type == FS_OPEN_FONT) - { - FSBlockedFontPtr bfont; - bfont = (FSBlockedFontPtr) blockrec->data; - if (bfont->pfont == pfont) - { - /* - * An OpenFont is pending for this font, this must - * be from a reopen attempt, so finish the open - * attempt and retry the LoadGlyphs - */ - if (blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - - _fs_signal_clients_depending(&bfont->clients_depending); - _fs_remove_block_rec(conn, blockrec); - if (err != Successful) - return err; - break; - } - /* We've found an existing OpenFont blockrec for this - font but for another client. Rather than build a - blockrec for it now (which entails some complex - maintenance), we'll add it to a queue of clients to - be signalled when the existing OpenFont is - completed. */ - if (blockrec->errcode == StillWorking) - { - clients_depending = &bfont->clients_depending; - break; - } - } - } - } - - /* - * see if the desired glyphs already exist, and return Successful if they - * do, otherwise build up character range/character string - */ - res = fs_build_range(pfont, range_flag, nchars, item_size, data, - &nranges, &ranges); - - switch (res) - { - case AccessDone: - return Successful; - - case Successful: - break; - - default: - return res; - } - - /* - * If clients_depending is not null, this request must wait for - * some prior request(s) to complete. - */ - if (clients_depending) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage (if any) caused by the fs_build_range() - call. */ - if (nranges) - { - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - xfree(ranges); - } - return _fs_add_clients_depending(clients_depending, client); - } - - /* - * If fsd->generation != conn->generation, the font has been closed - * due to a lost connection. We will reopen it, which will result - * in one of three things happening: - * 1) The open will succeed and obtain the same font. Life - * is wonderful. - * 2) The open will fail. There is code above to recognize this - * and flunk the LoadGlyphs request. The client might not be - * thrilled. - * 3) Worst case: the open will succeed but the font we open will - * be different. The fs_read_query_info() procedure attempts - * to detect this by comparing the existing metrics and - * properties against those of the reopened font... if they - * don't match, we flunk the reopen, which eventually results - * in flunking the LoadGlyphs request. We could go a step - * further and compare the extents, but this should be - * sufficient. - */ - if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) - { - /* Since we're not ready to send the load_glyphs request yet, - clean up the damage caused by the fs_build_range() call. */ - _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); - xfree(ranges); - - /* Now try to reopen the font. */ - return fs_send_open_font(client, pfont->fpe, - (Mask)FontReopen, (char *)0, 0, - (fsBitmapFormat)0, (fsBitmapFormatMask)0, - (XID)0, &pfont); - } - - return fs_send_load_glyphs(client, pfont, nranges, ranges); -} - -static int -fs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; - fsListFontsReply *rep; - char *data; - long dataleft; /* length of reply left to use */ - int length, - i, - ret; - int err; - - rep = (fsListFontsReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - (rep->length < LENGTHOF(fsListFontsReply))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - if (rep) - _fs_done_read (conn, rep->length << 2); - _fs_reply_failed (rep, fsListFontsReply, "<"); - return AllocError; - } - data = (char *) rep + SIZEOF (fsListFontsReply); - dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply); - - err = Successful; - /* copy data into FontPathRecord */ - for (i = 0; i < rep->nFonts; i++) - { - if (dataleft < 1) - break; - length = *(unsigned char *)data++; - dataleft--; /* used length byte */ - if (length > dataleft) { -#ifdef DEBUG - fprintf(stderr, - "fsListFonts: name length (%d) > dataleft (%ld)\n", - length, dataleft); -#endif - err = BadFontName; - break; - } - err = AddFontNamesName(blist->names, data, length); - if (err != Successful) - break; - data += length; - dataleft -= length; - } - _fs_done_read (conn, rep->length << 2); - return err; -} - -static int -fs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, - int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListPtr blockedlist; - fsListFontsReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); - if (!blockrec) - return AllocError; - blockedlist = (FSBlockedListPtr) blockrec->data; - blockedlist->names = newnames; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFonts; - req.maxNames = maxnames; - req.nbytes = patlen; - req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; - _fs_add_req_log(conn, FS_ListFonts); - _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); - _fs_write_pad(conn, (char *) pattern, patlen); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, patlen)); - buf[MIN(256, patlen)] = '\0'; - printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Suspended; -} - -static int -fs_list_fonts(pointer client, FontPathElementPtr fpe, - char *pattern, int patlen, int maxnames, FontNamesPtr newnames) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - { - if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) - { - err = blockrec->errcode; - if (err == StillWorking) - return Suspended; - _fs_remove_block_rec(conn, blockrec); - return err; - } - } - - /* didn't find waiting record, so send a new one */ - return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); -} - -/* - * Read a single list info reply and restart for the next reply - */ -static int -fs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) -{ - FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; - fsListFontsWithXInfoReply *rep; - char *buf; - long bufleft = 0; - FSFpePtr conn = (FSFpePtr) fpe->private; - fsPropInfo *pi; - fsPropOffset *po; - pointer pd; - int ret; - int err; - - /* clean up anything from the last trip */ - _fs_free_props (&binfo->info); - - rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); - if (!rep || rep->type == FS_Error || - ((rep->nameLength != 0) && - (rep->length < LENGTHOF(fsListFontsWithXInfoReply)))) - { - if (ret == FSIO_BLOCK) - return StillWorking; - binfo->status = FS_LFWI_FINISHED; - err = AllocError; - _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<"); - goto done; - } - /* - * Normal termination -- the list ends with a name of length 0 - */ - if (rep->nameLength == 0) - { -#ifdef DEBUG - fprintf (stderr, "fs_read_list_info done\n"); -#endif - binfo->status = FS_LFWI_FINISHED; - err = BadFontName; - goto done; - } - - buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); - bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply); - - /* - * The original FS implementation didn't match - * the spec, version 1 was respecified to match the FS. - * Version 2 matches the original intent - */ - if (conn->fsMajorVersion <= 1) - { - if (rep->nameLength > bufleft) { -#ifdef DEBUG - fprintf(stderr, - "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", - (int) rep->nameLength, bufleft); -#endif - err = AllocError; - goto done; - } - /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - bufleft -= _fs_pad_length (rep->nameLength); - } - pi = (fsPropInfo *) buf; - if (SIZEOF (fsPropInfo) > bufleft) { -#ifdef DEBUG - fprintf(stderr, - "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n", - (int) SIZEOF (fsPropInfo), bufleft); -#endif - err = AllocError; - goto done; - } - bufleft -= SIZEOF (fsPropInfo); - buf += SIZEOF (fsPropInfo); - po = (fsPropOffset *) buf; - if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) { -#ifdef DEBUG - fprintf(stderr, - "fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n", - pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft); -#endif - err = AllocError; - goto done; - } - bufleft -= pi->num_offsets * SIZEOF (fsPropOffset); - buf += pi->num_offsets * SIZEOF (fsPropOffset); - pd = (pointer) buf; - if (pi->data_len > bufleft) { -#ifdef DEBUG - fprintf(stderr, - "fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n", - pi->data_len, bufleft); -#endif - err = AllocError; - goto done; - } - bufleft -= pi->data_len; - buf += pi->data_len; - if (conn->fsMajorVersion > 1) - { - if (rep->nameLength > bufleft) { -#ifdef DEBUG - fprintf(stderr, - "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", - (int) rep->nameLength, bufleft); -#endif - err = AllocError; - goto done; - } - /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ - memcpy (binfo->name, buf, rep->nameLength); - buf += _fs_pad_length (rep->nameLength); - bufleft -= _fs_pad_length (rep->nameLength); - } - -#ifdef DEBUG - binfo->name[rep->nameLength] = '\0'; - fprintf (stderr, "fs_read_list_info %s\n", binfo->name); -#endif - err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); - if (err != Successful) - { - binfo->status = FS_LFWI_FINISHED; - goto done; - } - binfo->namelen = rep->nameLength; - binfo->remaining = rep->nReplies; - - binfo->status = FS_LFWI_REPLY; - - /* disable this font server until we've processed this response */ - _fs_unmark_block (conn, FS_COMPLETE_REPLY); - FD_CLR(conn->fs_fd, &_fs_fd_mask); -done: - _fs_done_read (conn, rep->length << 2); - return err; -} - -/* ARGSUSED */ -static int -fs_start_list_with_info(pointer client, FontPathElementPtr fpe, - char *pattern, int len, int maxnames, pointer *pdata) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - fsListFontsWithXInfoReq req; - - if (conn->blockState & FS_GIVE_UP) - return BadFontName; - - /* make a new block record, and add it to the end of the list */ - blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); - if (!blockrec) - return AllocError; - - binfo = (FSBlockedListInfoPtr) blockrec->data; - bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); - binfo->status = FS_LFWI_WAITING; - - if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) - { - _fs_pending_reply (conn); - return Suspended; - } - - _fs_client_access (conn, client, FALSE); - _fs_client_resolution(conn); - - /* send the request */ - req.reqType = FS_ListFontsWithXInfo; - req.maxNames = maxnames; - req.nbytes = len; - req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; - _fs_add_req_log(conn, FS_ListFontsWithXInfo); - (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); - (void) _fs_write_pad(conn, pattern, len); - - blockrec->sequenceNumber = conn->current_seq; - -#ifdef NCD - if (configData.ExtendedFontDiags) { - char buf[256]; - - memcpy(buf, pattern, MIN(256, len)); - buf[MIN(256, len)] = '\0'; - printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", - buf, fpe->name); - } -#endif - - _fs_prepare_for_reply (conn); - return Successful; -} - -/* ARGSUSED */ -static int -fs_next_list_with_info(pointer client, FontPathElementPtr fpe, - char **namep, int *namelenp, - FontInfoPtr *pFontInfo, int *numFonts, - pointer private) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec; - FSBlockedListInfoPtr binfo; - int err; - - /* see if the result is already there */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) - break; - - if (!blockrec) - { - /* The only good reason for not finding a blockrec would be if - disconnect/reconnect to the font server wiped it out and the - code that called us didn't do the right thing to create - another one. Under those circumstances, we need to return an - error to prevent that code from attempting to interpret the - information we don't return. */ - return BadFontName; - } - - binfo = (FSBlockedListInfoPtr) blockrec->data; - - if (binfo->status == FS_LFWI_WAITING) - return Suspended; - - *namep = binfo->name; - *namelenp = binfo->namelen; - *pFontInfo = &binfo->info; - *numFonts = binfo->remaining; - - /* Restart reply processing from this font server */ - FD_SET(conn->fs_fd, &_fs_fd_mask); - if (fs_reply_ready (conn)) - _fs_mark_block (conn, FS_COMPLETE_REPLY); - - err = blockrec->errcode; - switch (binfo->status) { - case FS_LFWI_FINISHED: - _fs_remove_block_rec(conn, blockrec); - break; - case FS_LFWI_REPLY: - binfo->status = FS_LFWI_WAITING; - blockrec->errcode = StillWorking; - conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; - _fs_mark_block (conn, FS_PENDING_REPLY); - break; - } - - return err; -} - -/* - * Called when client exits - */ - -static void -fs_client_died(pointer client, FontPathElementPtr fpe) -{ - FSFpePtr conn = (FSFpePtr) fpe->private; - FSBlockDataPtr blockrec, - depending; - FSClientPtr *prev, cur; - fsFreeACReq freeac; - - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) { - freeac.reqType = FS_FreeAC; - freeac.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; - } - } - /* find a pending requests */ - for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) - if (blockrec->client == client) - break; - - if (!blockrec) - return; - - /* replace the client pointers in this block rec with the chained one */ - if ((depending = blockrec->depending)) - { - blockrec->client = depending->client; - blockrec->depending = depending->depending; - blockrec = depending; - } - fs_abort_blockrec(conn, blockrec); -} - -static void -_fs_client_access (FSFpePtr conn, pointer client, Bool sync) -{ - FSClientPtr *prev, cur; - fsCreateACReq crac; - fsSetAuthorizationReq setac; - char *authorizations; - int authlen; - Bool new_cur = FALSE; - -#ifdef DEBUG - if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) - { - fprintf (stderr, "Sending requests without a connection\n"); - } -#endif - for (prev = &conn->clients; (cur = *prev); prev = &cur->next) - { - if (cur->client == client) - { - if (prev != &conn->clients) - { - *prev = cur->next; - cur->next = conn->clients; - conn->clients = cur; - } - break; - } - } - if (!cur) - { - cur = (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); - /* 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; - } -} - -/* - * Poll a pending connect - */ - -static int -_fs_check_connect (FSFpePtr conn) -{ - int ret; - - ret = _fs_poll_connect (conn->trans_conn, 0); - switch (ret) { - case FSIO_READY: - conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); - FD_SET (conn->fs_fd, &_fs_fd_mask); - break; - case FSIO_BLOCK: - break; - } - return ret; -} - -/* - * Return an FSIO status while waiting for the completed connection - * reply to arrive - */ - -static fsConnSetup * -_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) -{ - int ret; - char *data; - int headlen; - int len; - fsConnSetup *setup; - fsConnSetupAccept *accept; - - ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - - setup = (fsConnSetup *) data; - if (setup->major_version > FS_PROTOCOL) - { - *error = FSIO_ERROR; - return 0; - } - - headlen = (SIZEOF (fsConnSetup) + - (setup->alternate_len << 2) + - (setup->auth_len << 2)); - /* On anything but Success, no extra data is sent */ - if (setup->status != AuthSuccess) - { - len = headlen; - } - else - { - ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - setup = (fsConnSetup *) data; - accept = (fsConnSetupAccept *) (data + headlen); - len = headlen + (accept->length << 2); - } - ret = _fs_start_read (conn, len, &data); - if (ret != FSIO_READY) - { - *error = ret; - return 0; - } - *setup_len = len; - return (fsConnSetup *) data; -} - -static int -_fs_send_conn_client_prefix (FSFpePtr conn) -{ - fsConnClientPrefix req; - int endian; - int ret; - - /* send setup prefix */ - endian = 1; - if (*(char *) &endian) - req.byteOrder = 'l'; - else - req.byteOrder = 'B'; - - req.major_version = FS_PROTOCOL; - req.minor_version = FS_PROTOCOL_MINOR; - -/* XXX add some auth info here */ - req.num_auths = 0; - req.auth_len = 0; - ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); - if (ret != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return ret; -} - -static int -_fs_recv_conn_setup (FSFpePtr conn) -{ - int ret; - fsConnSetup *setup; - FSFpeAltPtr alts; - unsigned int i, alt_len; - int setup_len; - char *alt_save, *alt_names; - - setup = _fs_get_conn_setup (conn, &ret, &setup_len); - if (!setup) - return ret; - conn->current_seq = 0; - conn->fsMajorVersion = setup->major_version; - /* - * Create an alternate list from the initial server, but - * don't chain looking for alternates. - */ - if (conn->alternate == 0) - { - /* - * free any existing alternates list, allowing the list to - * be updated - */ - if (conn->alts) - { - xfree (conn->alts); - conn->alts = 0; - conn->numAlts = 0; - } - if (setup->num_alternates) - { - size_t alt_name_len = setup->alternate_len << 2; - alts = (FSFpeAltPtr) xalloc (setup->num_alternates * - sizeof (FSFpeAltRec) + alt_name_len); - if (alts) - { - alt_names = (char *) (setup + 1); - alt_save = (char *) (alts + setup->num_alternates); - for (i = 0; i < setup->num_alternates; i++) - { - alts[i].subset = alt_names[0]; - alt_len = alt_names[1]; - if (alt_len >= alt_name_len) { - /* - * Length is longer than setup->alternate_len - * told us to allocate room for, assume entire - * alternate list is corrupted. - */ -#ifdef DEBUG - fprintf (stderr, - "invalid alt list (length %lx >= %lx)\n", - (long) alt_len, (long) alt_name_len); -#endif - xfree(alts); - return FSIO_ERROR; - } - alts[i].name = alt_save; - memcpy (alt_save, alt_names + 2, alt_len); - alt_save[alt_len] = '\0'; - alt_save += alt_len + 1; - alt_name_len -= alt_len + 1; - alt_names += _fs_pad_length (alt_len + 2); - } - conn->numAlts = setup->num_alternates; - conn->alts = alts; - } - } - } - _fs_done_read (conn, setup_len); - if (setup->status != AuthSuccess) - return FSIO_ERROR; - return FSIO_READY; -} - -static int -_fs_open_server (FSFpePtr conn) -{ - int ret; - char *servername; - - if (conn->alternate == 0) - servername = conn->servername; - else - servername = conn->alts[conn->alternate-1].name; - conn->trans_conn = _fs_connect (servername, &ret); - conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; - return ret; -} - -static char * -_fs_catalog_name (char *servername) -{ - char *sp; - - sp = strchr (servername, '/'); - if (!sp) - return 0; - return strrchr (sp + 1, '/'); -} - -static int -_fs_send_init_packets (FSFpePtr conn) -{ - fsSetResolutionReq srreq; - fsSetCataloguesReq screq; - int num_cats, - clen; - char *catalogues; - char *cat; - char len; - char *end; - int num_res; - FontResolutionPtr res; - -#define CATALOGUE_SEP '+' - - res = GetClientResolutions(&num_res); - if (num_res) - { - srreq.reqType = FS_SetResolution; - srreq.num_resolutions = num_res; - srreq.length = (SIZEOF(fsSetResolutionReq) + - (num_res * SIZEOF(fsResolution)) + 3) >> 2; - - _fs_add_req_log(conn, FS_SetResolution); - if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) - return FSIO_ERROR; - } - - catalogues = 0; - if (conn->alternate != 0) - catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); - if (!catalogues) - catalogues = _fs_catalog_name (conn->servername); - - if (!catalogues) - { - conn->has_catalogues = FALSE; - return FSIO_READY; - } - conn->has_catalogues = TRUE; - - /* turn cats into counted list */ - catalogues++; - - cat = catalogues; - num_cats = 0; - clen = 0; - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - clen += (end - cat) + 1; /* length byte + string */ - cat = end; - } - - screq.reqType = FS_SetCatalogues; - screq.num_catalogues = num_cats; - screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; - - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - - while (*cat) - { - num_cats++; - end = strchr(cat, CATALOGUE_SEP); - if (!end) - end = cat + strlen (cat); - len = end - cat; - if (_fs_write (conn, &len, 1) != FSIO_READY) - return FSIO_ERROR; - if (_fs_write (conn, cat, (int) len) != FSIO_READY) - return FSIO_ERROR; - cat = end; - } - - if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) - return FSIO_ERROR; - - return FSIO_READY; -} - -static int -_fs_send_cat_sync (FSFpePtr conn) -{ - fsListCataloguesReq lcreq; - - /* - * now sync up with the font server, to see if an error was generated - * by a bogus catalogue - */ - lcreq.reqType = FS_ListCatalogues; - lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; - lcreq.maxNames = 0; - lcreq.nbytes = 0; - _fs_add_req_log(conn, FS_SetCatalogues); - if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) - return FSIO_ERROR; - conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; - return FSIO_READY; -} - -static int -_fs_recv_cat_sync (FSFpePtr conn) -{ - fsGenericReply *reply; - fsError *error; - int err; - int ret; - - reply = fs_get_reply (conn, &err); - if (!reply) - return err; - - ret = FSIO_READY; - if (reply->type == FS_Error) - { - error = (fsError *) reply; - if (error->major_opcode == FS_SetCatalogues) - ret = FSIO_ERROR; - } - _fs_done_read (conn, reply->length << 2); - return ret; -} - -static void -_fs_close_server (FSFpePtr conn) -{ - _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); - if (conn->trans_conn) - { - _FontTransClose (conn->trans_conn); - conn->trans_conn = 0; - _fs_io_reinit (conn); - } - if (conn->fs_fd >= 0) - { - FD_CLR (conn->fs_fd, &_fs_fd_mask); - conn->fs_fd = -1; - } - conn->fs_conn_state = FS_CONN_UNCONNECTED; -} - -static int -_fs_do_setup_connection (FSFpePtr conn) -{ - int ret; - - do - { -#ifdef DEBUG - fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); -#endif - switch (conn->fs_conn_state) { - case FS_CONN_UNCONNECTED: - ret = _fs_open_server (conn); - if (ret == FSIO_BLOCK) - conn->fs_conn_state = FS_CONN_CONNECTING; - break; - case FS_CONN_CONNECTING: - ret = _fs_check_connect (conn); - break; - case FS_CONN_CONNECTED: - ret = _fs_send_conn_client_prefix (conn); - break; - case FS_CONN_SENT_PREFIX: - ret = _fs_recv_conn_setup (conn); - break; - case FS_CONN_RECV_INIT: - ret = _fs_send_init_packets (conn); - if (conn->has_catalogues) - ret = _fs_send_cat_sync (conn); - break; - case FS_CONN_SENT_CAT: - if (conn->has_catalogues) - ret = _fs_recv_cat_sync (conn); - else - ret = FSIO_READY; - break; - default: - ret = FSIO_READY; - break; - } - switch (ret) { - case FSIO_READY: - if (conn->fs_conn_state < FS_CONN_RUNNING) - conn->fs_conn_state++; - break; - case FSIO_BLOCK: - if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) - break; - ret = FSIO_ERROR; - /* fall through... */ - case FSIO_ERROR: - _fs_close_server (conn); - /* - * Try the next alternate - */ - if (conn->alternate < conn->numAlts) - { - conn->alternate++; - ret = FSIO_READY; - } - else - conn->alternate = 0; - break; - } - } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); - if (ret == FSIO_READY) - conn->generation = ++generationCount; - return ret; -} - -static int -_fs_wait_connect (FSFpePtr conn) -{ - int ret; - - for (;;) - { - ret = _fs_do_setup_connection (conn); - if (ret != FSIO_BLOCK) - break; - if (conn->fs_conn_state <= FS_CONN_CONNECTING) - ret = _fs_poll_connect (conn->trans_conn, 1000); - else - ret = _fs_wait_for_readable (conn, 1000); - if (ret == FSIO_ERROR) - break; - } - return ret; -} - -/* - * Poll a connection in the process of reconnecting - */ -static void -_fs_check_reconnect (FSFpePtr conn) -{ - int ret; - - ret = _fs_do_setup_connection (conn); - switch (ret) { - case FSIO_READY: - _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); - _fs_restart_connection (conn); - break; - case FSIO_BLOCK: - break; - case FSIO_ERROR: - conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; - break; - } -} - -/* - * Start the reconnection process - */ -static void -_fs_start_reconnect (FSFpePtr conn) -{ - if (conn->blockState & FS_RECONNECTING) - return; - conn->alternate = 0; - _fs_mark_block (conn, FS_RECONNECTING); - _fs_unmark_block (conn, FS_BROKEN_CONNECTION); - _fs_check_reconnect (conn); -} - - -static FSFpePtr -_fs_init_conn (char *servername) -{ - FSFpePtr conn; - - conn = xalloc (sizeof (FSFpeRec) + strlen (servername) + 1); - if (!conn) - return 0; - memset (conn, '\0', sizeof (FSFpeRec)); - if (!_fs_io_init (conn)) - { - xfree (conn); - return 0; - } - conn->servername = (char *) (conn + 1); - conn->fs_conn_state = FS_CONN_UNCONNECTED; - conn->fs_fd = -1; - strcpy (conn->servername, servername); - return conn; -} - -static void -_fs_free_conn (FSFpePtr conn) -{ - _fs_close_server (conn); - _fs_io_fini (conn); - if (conn->alts) - xfree (conn->alts); - xfree (conn); -} - -/* - * called at server init time - */ - -void -fs_register_fpe_functions(void) -{ - RegisterFPEFunctions(fs_name_check, - fs_init_fpe, - fs_free_fpe, - fs_reset_fpe, - fs_open_font, - fs_close_font, - fs_list_fonts, - fs_start_list_with_info, - fs_next_list_with_info, - fs_wakeup, - fs_client_died, - _fs_load_glyphs, - NULL, - NULL, - NULL); -} - -static int -check_fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, - char *name, int namelen, - fsBitmapFormat format, fsBitmapFormatMask fmask, - XID id, FontPtr *ppfont, - char **alias, FontPtr non_cachable_font) -{ - 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(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(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(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(void) -{ - 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, - NULL, - NULL, - NULL); -} |