fserve.c revision 23a0898a
123a0898aSmrg/* $XdotOrg: lib/Xfont/src/fc/fserve.c,v 1.8 2005/07/09 06:36:12 keithp Exp $ */ 223a0898aSmrg/* $Xorg: fserve.c,v 1.4 2001/02/09 02:04:02 xorgcvs Exp $ */ 323a0898aSmrg/* 423a0898aSmrg 523a0898aSmrgCopyright 1990, 1998 The Open Group 623a0898aSmrg 723a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its 823a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that 923a0898aSmrgthe above copyright notice appear in all copies and that both that 1023a0898aSmrgcopyright notice and this permission notice appear in supporting 1123a0898aSmrgdocumentation. 1223a0898aSmrg 1323a0898aSmrgThe above copyright notice and this permission notice shall be included in 1423a0898aSmrgall copies or substantial portions of the Software. 1523a0898aSmrg 1623a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1723a0898aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1823a0898aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1923a0898aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2023a0898aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2123a0898aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2223a0898aSmrg 2323a0898aSmrgExcept as contained in this notice, the name of The Open Group shall not be 2423a0898aSmrgused in advertising or otherwise to promote the sale, use or other dealings 2523a0898aSmrgin this Software without prior written authorization from The Open Group. 2623a0898aSmrg 2723a0898aSmrg*/ 2823a0898aSmrg/* $XFree86: xc/lib/font/fc/fserve.c,v 3.26tsi Exp $ */ 2923a0898aSmrg 3023a0898aSmrg/* 3123a0898aSmrg * Copyright 1990 Network Computing Devices 3223a0898aSmrg * 3323a0898aSmrg * Permission to use, copy, modify, distribute, and sell this software and 3423a0898aSmrg * its documentation for any purpose is hereby granted without fee, provided 3523a0898aSmrg * that the above copyright notice appear in all copies and that both that 3623a0898aSmrg * copyright notice and this permission notice appear in supporting 3723a0898aSmrg * documentation, and that the names of Network Computing Devices, or Digital 3823a0898aSmrg * not be used in advertising or publicity pertaining to distribution 3923a0898aSmrg * of the software without specific, written prior permission. 4023a0898aSmrg * 4123a0898aSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH 4223a0898aSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 4323a0898aSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 4423a0898aSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 4523a0898aSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 4623a0898aSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 4723a0898aSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 4823a0898aSmrg * THIS SOFTWARE. 4923a0898aSmrg * 5023a0898aSmrg * Author: Dave Lemke, Network Computing Devices, Inc 5123a0898aSmrg */ 5223a0898aSmrg/* 5323a0898aSmrg * font server specific font access 5423a0898aSmrg */ 5523a0898aSmrg 5623a0898aSmrg#ifdef HAVE_CONFIG_H 5723a0898aSmrg#include <config.h> 5823a0898aSmrg#endif 5923a0898aSmrg 6023a0898aSmrg#ifdef WIN32 6123a0898aSmrg#define _WILLWINSOCK_ 6223a0898aSmrg#endif 6323a0898aSmrg#define FONT_t 6423a0898aSmrg#define TRANS_CLIENT 6523a0898aSmrg#include "X11/Xtrans/Xtrans.h" 6623a0898aSmrg#include "X11/Xpoll.h" 6723a0898aSmrg#include <X11/fonts/FS.h> 6823a0898aSmrg#include <X11/fonts/FSproto.h> 6923a0898aSmrg#include <X11/X.h> 7023a0898aSmrg#include <X11/Xos.h> 7123a0898aSmrg#include <X11/fonts/fontmisc.h> 7223a0898aSmrg#include <X11/fonts/fontstruct.h> 7323a0898aSmrg#include "fservestr.h" 7423a0898aSmrg#include <X11/fonts/fontutil.h> 7523a0898aSmrg#include <errno.h> 7623a0898aSmrg 7723a0898aSmrg#include <time.h> 7823a0898aSmrg#define Time_t time_t 7923a0898aSmrg 8023a0898aSmrg#ifdef NCD 8123a0898aSmrg#include <ncd/nvram.h> 8223a0898aSmrg#endif 8323a0898aSmrg 8423a0898aSmrg#include <stddef.h> 8523a0898aSmrg 8623a0898aSmrg#ifndef MIN 8723a0898aSmrg#define MIN(a,b) ((a)<(b)?(a):(b)) 8823a0898aSmrg#endif 8923a0898aSmrg#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) 9023a0898aSmrg 9123a0898aSmrg#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ 9223a0898aSmrg (pci)->rightSideBearing || \ 9323a0898aSmrg (pci)->ascent || \ 9423a0898aSmrg (pci)->descent || \ 9523a0898aSmrg (pci)->characterWidth) 9623a0898aSmrg 9723a0898aSmrgextern void ErrorF(const char *f, ...); 9823a0898aSmrg 9923a0898aSmrgstatic int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 10023a0898aSmrgstatic int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 10123a0898aSmrgstatic int fs_read_list_info ( FontPathElementPtr fpe, 10223a0898aSmrg FSBlockDataPtr blockrec ); 10323a0898aSmrg 10423a0898aSmrgextern fd_set _fs_fd_mask; 10523a0898aSmrg 10623a0898aSmrgstatic void fs_block_handler ( pointer data, OSTimePtr wt, 10723a0898aSmrg pointer LastSelectMask ); 10823a0898aSmrgstatic int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); 10923a0898aSmrg 11023a0898aSmrg/* 11123a0898aSmrg * List of all FPEs 11223a0898aSmrg */ 11323a0898aSmrgstatic FSFpePtr fs_fpes; 11423a0898aSmrg/* 11523a0898aSmrg * Union of all FPE blockStates 11623a0898aSmrg */ 11723a0898aSmrgstatic CARD32 fs_blockState; 11823a0898aSmrg 11923a0898aSmrgstatic int _fs_restart_connection ( FSFpePtr conn ); 12023a0898aSmrgstatic void fs_send_query_bitmaps ( FontPathElementPtr fpe, 12123a0898aSmrg FSBlockDataPtr blockrec ); 12223a0898aSmrgstatic int fs_send_close_font ( FontPathElementPtr fpe, Font id ); 12323a0898aSmrgstatic void fs_client_died ( pointer client, FontPathElementPtr fpe ); 12423a0898aSmrgstatic void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); 12523a0898aSmrgstatic void _fs_client_resolution ( FSFpePtr conn ); 12623a0898aSmrgstatic fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); 12723a0898aSmrgstatic int fs_await_reply (FSFpePtr conn); 12823a0898aSmrgstatic void _fs_do_blocked (FSFpePtr conn); 12923a0898aSmrgstatic void fs_cleanup_bfont (FSBlockedFontPtr bfont); 13023a0898aSmrg 13123a0898aSmrgchar _fs_glyph_undefined; 13223a0898aSmrgchar _fs_glyph_requested; 13323a0898aSmrgstatic char _fs_glyph_zero_length; 13423a0898aSmrg 13523a0898aSmrgstatic int generationCount; 13623a0898aSmrg 13723a0898aSmrgstatic int FontServerRequestTimeout = 30 * 1000; 13823a0898aSmrg 13923a0898aSmrgstatic void 14023a0898aSmrg_fs_close_server (FSFpePtr conn); 14123a0898aSmrg 14223a0898aSmrgstatic FSFpePtr 14323a0898aSmrg_fs_init_conn (char *servername); 14423a0898aSmrg 14523a0898aSmrgstatic int 14623a0898aSmrg_fs_wait_connect (FSFpePtr conn); 14723a0898aSmrg 14823a0898aSmrgstatic int 14923a0898aSmrg_fs_send_init_packets (FSFpePtr conn); 15023a0898aSmrg 15123a0898aSmrgstatic void 15223a0898aSmrg_fs_check_reconnect (FSFpePtr conn); 15323a0898aSmrg 15423a0898aSmrgstatic void 15523a0898aSmrg_fs_start_reconnect (FSFpePtr conn); 15623a0898aSmrg 15723a0898aSmrgstatic void 15823a0898aSmrg_fs_free_conn (FSFpePtr conn); 15923a0898aSmrg 16023a0898aSmrgstatic int 16123a0898aSmrgfs_free_fpe(FontPathElementPtr fpe); 16223a0898aSmrg 16323a0898aSmrg/* 16423a0898aSmrg * Font server access 16523a0898aSmrg * 16623a0898aSmrg * the basic idea for the non-blocking access is to have the function 16723a0898aSmrg * called multiple times until the actual data is returned, instead 16823a0898aSmrg * of ClientBlocked. 16923a0898aSmrg * 17023a0898aSmrg * the first call to the function will cause the request to be sent to 17123a0898aSmrg * the font server, and a block record to be stored in the fpe's list 17223a0898aSmrg * of outstanding requests. the FS block handler also sticks the 17323a0898aSmrg * proper set of fd's into the select mask. when data is ready to be 17423a0898aSmrg * read in, the FS wakup handler will be hit. this will read the 17523a0898aSmrg * data off the wire into the proper block record, and then signal the 17623a0898aSmrg * client that caused the block so that it can restart. it will then 17723a0898aSmrg * call the access function again, which will realize that the data has 17823a0898aSmrg * arrived and return it. 17923a0898aSmrg */ 18023a0898aSmrg 18123a0898aSmrg 18223a0898aSmrg#ifdef DEBUG 18323a0898aSmrgstatic void 18423a0898aSmrg_fs_add_req_log(FSFpePtr conn, int opcode) 18523a0898aSmrg{ 18623a0898aSmrg conn->current_seq++; 18723a0898aSmrg fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", 18823a0898aSmrg conn->current_seq, opcode); 18923a0898aSmrg conn->reqbuffer[conn->reqindex].opcode = opcode; 19023a0898aSmrg conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; 19123a0898aSmrg conn->reqindex++; 19223a0898aSmrg if (conn->reqindex == REQUEST_LOG_SIZE) 19323a0898aSmrg conn->reqindex = 0; 19423a0898aSmrg} 19523a0898aSmrg 19623a0898aSmrgstatic void 19723a0898aSmrg_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) 19823a0898aSmrg{ 19923a0898aSmrg int i; 20023a0898aSmrg 20123a0898aSmrg for (i = 0; i < REQUEST_LOG_SIZE; i++) 20223a0898aSmrg if (conn->reqbuffer[i].sequence == rep->sequenceNumber) 20323a0898aSmrg break; 20423a0898aSmrg if (i == REQUEST_LOG_SIZE) 20523a0898aSmrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", 20623a0898aSmrg rep->sequenceNumber); 20723a0898aSmrg else 20823a0898aSmrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", 20923a0898aSmrg rep->sequenceNumber, 21023a0898aSmrg conn->reqbuffer[i].opcode); 21123a0898aSmrg} 21223a0898aSmrg#else 21323a0898aSmrg#define _fs_add_req_log(conn,op) ((conn)->current_seq++) 21423a0898aSmrg#define _fs_add_rep_log(conn,rep) 21523a0898aSmrg#endif 21623a0898aSmrg 21723a0898aSmrgstatic Bool 21823a0898aSmrgfs_name_check(char *name) 21923a0898aSmrg{ 22023a0898aSmrg#ifdef __UNIXOS2__ 22123a0898aSmrg /* OS/2 uses D:/usr/X11R6/.... as fontfile pathnames, so check that 22223a0898aSmrg * there is not only a protocol/ prefix, but also that the first chars 22323a0898aSmrg * are not a drive letter 22423a0898aSmrg */ 22523a0898aSmrg if (name && isalpha(*name) && name[1] == ':') 22623a0898aSmrg return FALSE; 22723a0898aSmrg#endif 22823a0898aSmrg /* Just make sure there is a protocol/ prefix */ 22923a0898aSmrg return (name && *name != '/' && strchr(name, '/')); 23023a0898aSmrg} 23123a0898aSmrg 23223a0898aSmrgstatic void 23323a0898aSmrg_fs_client_resolution(FSFpePtr conn) 23423a0898aSmrg{ 23523a0898aSmrg fsSetResolutionReq srreq; 23623a0898aSmrg int num_res; 23723a0898aSmrg FontResolutionPtr res; 23823a0898aSmrg 23923a0898aSmrg res = GetClientResolutions(&num_res); 24023a0898aSmrg 24123a0898aSmrg if (num_res) { 24223a0898aSmrg srreq.reqType = FS_SetResolution; 24323a0898aSmrg srreq.num_resolutions = num_res; 24423a0898aSmrg srreq.length = (SIZEOF(fsSetResolutionReq) + 24523a0898aSmrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 24623a0898aSmrg 24723a0898aSmrg _fs_add_req_log(conn, FS_SetResolution); 24823a0898aSmrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) 24923a0898aSmrg (void)_fs_write_pad(conn, (char *) res, 25023a0898aSmrg (num_res * SIZEOF(fsResolution))); 25123a0898aSmrg } 25223a0898aSmrg} 25323a0898aSmrg 25423a0898aSmrg/* 25523a0898aSmrg * close font server and remove any state associated with 25623a0898aSmrg * this connection - this includes any client records. 25723a0898aSmrg */ 25823a0898aSmrg 25923a0898aSmrgstatic void 26023a0898aSmrgfs_close_conn(FSFpePtr conn) 26123a0898aSmrg{ 26223a0898aSmrg FSClientPtr client, nclient; 26323a0898aSmrg 26423a0898aSmrg _fs_close_server (conn); 26523a0898aSmrg 26623a0898aSmrg for (client = conn->clients; client; client = nclient) 26723a0898aSmrg { 26823a0898aSmrg nclient = client->next; 26923a0898aSmrg xfree (client); 27023a0898aSmrg } 27123a0898aSmrg conn->clients = NULL; 27223a0898aSmrg} 27323a0898aSmrg 27423a0898aSmrg/* 27523a0898aSmrg * the wakeup handlers have to be set when the FPE is open, and not 27623a0898aSmrg * removed until it is freed, in order to handle unexpected data, like 27723a0898aSmrg * events 27823a0898aSmrg */ 27923a0898aSmrg/* ARGSUSED */ 28023a0898aSmrgstatic int 28123a0898aSmrgfs_init_fpe(FontPathElementPtr fpe) 28223a0898aSmrg{ 28323a0898aSmrg FSFpePtr conn; 28423a0898aSmrg char *name; 28523a0898aSmrg int err; 28623a0898aSmrg int ret; 28723a0898aSmrg 28823a0898aSmrg /* open font server */ 28923a0898aSmrg /* create FS specific fpe info */ 29023a0898aSmrg name = fpe->name; 29123a0898aSmrg 29223a0898aSmrg /* hack for old style names */ 29323a0898aSmrg if (*name == ':') 29423a0898aSmrg name++; /* skip ':' */ 29523a0898aSmrg 29623a0898aSmrg conn = _fs_init_conn (name); 29723a0898aSmrg if (!conn) 29823a0898aSmrg err = AllocError; 29923a0898aSmrg else 30023a0898aSmrg { 30123a0898aSmrg err = init_fs_handlers (fpe, fs_block_handler); 30223a0898aSmrg if (err != Successful) 30323a0898aSmrg { 30423a0898aSmrg _fs_free_conn (conn); 30523a0898aSmrg err = AllocError; 30623a0898aSmrg } 30723a0898aSmrg else 30823a0898aSmrg { 30923a0898aSmrg fpe->private = conn; 31023a0898aSmrg conn->next = fs_fpes; 31123a0898aSmrg fs_fpes = conn; 31223a0898aSmrg ret = _fs_wait_connect (conn); 31323a0898aSmrg if (ret != FSIO_READY) 31423a0898aSmrg { 31523a0898aSmrg fs_free_fpe (fpe); 31623a0898aSmrg err = BadFontPath; 31723a0898aSmrg } 31823a0898aSmrg else 31923a0898aSmrg err = Successful; 32023a0898aSmrg } 32123a0898aSmrg } 32223a0898aSmrg 32323a0898aSmrg if (err == Successful) 32423a0898aSmrg { 32523a0898aSmrg#ifdef NCD 32623a0898aSmrg if (configData.ExtendedFontDiags) 32723a0898aSmrg printf("Connected to font server \"%s\"\n", name); 32823a0898aSmrg#endif 32923a0898aSmrg#ifdef DEBUG 33023a0898aSmrg fprintf (stderr, "connected to FS \"%s\"\n", name); 33123a0898aSmrg#endif 33223a0898aSmrg } 33323a0898aSmrg else 33423a0898aSmrg { 33523a0898aSmrg#ifdef DEBUG 33623a0898aSmrg fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); 33723a0898aSmrg#endif 33823a0898aSmrg#ifdef NCD 33923a0898aSmrg if (configData.ExtendedFontDiags) 34023a0898aSmrg printf("Failed to connect to font server \"%s\"\n", name); 34123a0898aSmrg#endif 34223a0898aSmrg ; 34323a0898aSmrg } 34423a0898aSmrg return err; 34523a0898aSmrg} 34623a0898aSmrg 34723a0898aSmrgstatic int 34823a0898aSmrgfs_reset_fpe(FontPathElementPtr fpe) 34923a0898aSmrg{ 35023a0898aSmrg (void) _fs_send_init_packets((FSFpePtr) fpe->private); 35123a0898aSmrg return Successful; 35223a0898aSmrg} 35323a0898aSmrg 35423a0898aSmrg/* 35523a0898aSmrg * this shouldn't be called till all refs to the FPE are gone 35623a0898aSmrg */ 35723a0898aSmrg 35823a0898aSmrgstatic int 35923a0898aSmrgfs_free_fpe(FontPathElementPtr fpe) 36023a0898aSmrg{ 36123a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private, *prev; 36223a0898aSmrg 36323a0898aSmrg /* unhook from chain of all font servers */ 36423a0898aSmrg for (prev = &fs_fpes; *prev; prev = &(*prev)->next) 36523a0898aSmrg { 36623a0898aSmrg if (*prev == conn) 36723a0898aSmrg { 36823a0898aSmrg *prev = conn->next; 36923a0898aSmrg break; 37023a0898aSmrg } 37123a0898aSmrg } 37223a0898aSmrg _fs_unmark_block (conn, conn->blockState); 37323a0898aSmrg fs_close_conn(conn); 37423a0898aSmrg remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); 37523a0898aSmrg _fs_free_conn (conn); 37623a0898aSmrg fpe->private = (pointer) 0; 37723a0898aSmrg 37823a0898aSmrg#ifdef NCD 37923a0898aSmrg if (configData.ExtendedFontDiags) 38023a0898aSmrg printf("Disconnected from font server \"%s\"\n", fpe->name); 38123a0898aSmrg#endif 38223a0898aSmrg#ifdef DEBUG 38323a0898aSmrg fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); 38423a0898aSmrg#endif 38523a0898aSmrg 38623a0898aSmrg return Successful; 38723a0898aSmrg} 38823a0898aSmrg 38923a0898aSmrgstatic FSBlockDataPtr 39023a0898aSmrgfs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) 39123a0898aSmrg{ 39223a0898aSmrg FSBlockDataPtr blockrec, 39323a0898aSmrg *prev; 39423a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 39523a0898aSmrg int size; 39623a0898aSmrg 39723a0898aSmrg switch (type) { 39823a0898aSmrg case FS_OPEN_FONT: 39923a0898aSmrg size = sizeof(FSBlockedFontRec); 40023a0898aSmrg break; 40123a0898aSmrg case FS_LOAD_GLYPHS: 40223a0898aSmrg size = sizeof(FSBlockedGlyphRec); 40323a0898aSmrg break; 40423a0898aSmrg case FS_LIST_FONTS: 40523a0898aSmrg size = sizeof(FSBlockedListRec); 40623a0898aSmrg break; 40723a0898aSmrg case FS_LIST_WITH_INFO: 40823a0898aSmrg size = sizeof(FSBlockedListInfoRec); 40923a0898aSmrg break; 41023a0898aSmrg default: 41123a0898aSmrg size = 0; 41223a0898aSmrg break; 41323a0898aSmrg } 41423a0898aSmrg blockrec = (FSBlockDataPtr) xalloc(sizeof(FSBlockDataRec) + size); 41523a0898aSmrg if (!blockrec) 41623a0898aSmrg return (FSBlockDataPtr) 0; 41723a0898aSmrg blockrec->data = (pointer) (blockrec + 1); 41823a0898aSmrg blockrec->client = client; 41923a0898aSmrg blockrec->sequenceNumber = -1; 42023a0898aSmrg blockrec->errcode = StillWorking; 42123a0898aSmrg blockrec->type = type; 42223a0898aSmrg blockrec->depending = 0; 42323a0898aSmrg blockrec->next = (FSBlockDataPtr) 0; 42423a0898aSmrg 42523a0898aSmrg /* stick it on the end of the list (since its expected last) */ 42623a0898aSmrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 42723a0898aSmrg ; 42823a0898aSmrg *prev = blockrec; 42923a0898aSmrg 43023a0898aSmrg return blockrec; 43123a0898aSmrg} 43223a0898aSmrg 43323a0898aSmrgstatic void 43423a0898aSmrg_fs_set_pending_reply (FSFpePtr conn) 43523a0898aSmrg{ 43623a0898aSmrg FSBlockDataPtr blockrec; 43723a0898aSmrg 43823a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 43923a0898aSmrg if (blockrec->errcode == StillWorking) 44023a0898aSmrg break; 44123a0898aSmrg if (blockrec) 44223a0898aSmrg { 44323a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 44423a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 44523a0898aSmrg } 44623a0898aSmrg else 44723a0898aSmrg _fs_unmark_block (conn, FS_PENDING_REPLY); 44823a0898aSmrg} 44923a0898aSmrg 45023a0898aSmrgstatic void 45123a0898aSmrg_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) 45223a0898aSmrg{ 45323a0898aSmrg FSBlockDataPtr *prev; 45423a0898aSmrg 45523a0898aSmrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 45623a0898aSmrg if (*prev == blockrec) 45723a0898aSmrg { 45823a0898aSmrg *prev = blockrec->next; 45923a0898aSmrg break; 46023a0898aSmrg } 46123a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 46223a0898aSmrg { 46323a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 46423a0898aSmrg if (bglyph->num_expected_ranges) 46523a0898aSmrg xfree(bglyph->expected_ranges); 46623a0898aSmrg } 46723a0898aSmrg xfree(blockrec); 46823a0898aSmrg _fs_set_pending_reply (conn); 46923a0898aSmrg} 47023a0898aSmrg 47123a0898aSmrgstatic void 47223a0898aSmrg_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) 47323a0898aSmrg{ 47423a0898aSmrg FSClientsDependingPtr p; 47523a0898aSmrg 47623a0898aSmrg while ((p = *clients_depending)) 47723a0898aSmrg { 47823a0898aSmrg *clients_depending = p->next; 47923a0898aSmrg ClientSignal(p->client); 48023a0898aSmrg xfree(p); 48123a0898aSmrg } 48223a0898aSmrg} 48323a0898aSmrg 48423a0898aSmrgstatic int 48523a0898aSmrg_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) 48623a0898aSmrg{ 48723a0898aSmrg FSClientsDependingPtr new, cd; 48823a0898aSmrg 48923a0898aSmrg for (; (cd = *clients_depending); 49023a0898aSmrg clients_depending = &(*clients_depending)->next) 49123a0898aSmrg { 49223a0898aSmrg if (cd->client == client) 49323a0898aSmrg return Suspended; 49423a0898aSmrg } 49523a0898aSmrg 49623a0898aSmrg new = (FSClientsDependingPtr)xalloc (sizeof (FSClientsDependingRec)); 49723a0898aSmrg if (!new) 49823a0898aSmrg return BadAlloc; 49923a0898aSmrg 50023a0898aSmrg new->client = client; 50123a0898aSmrg new->next = 0; 50223a0898aSmrg *clients_depending = new; 50323a0898aSmrg return Suspended; 50423a0898aSmrg} 50523a0898aSmrg 50623a0898aSmrg/* 50723a0898aSmrg * When a request is aborted due to a font server failure, 50823a0898aSmrg * signal any depending clients to restart their dependant 50923a0898aSmrg * requests 51023a0898aSmrg */ 51123a0898aSmrgstatic void 51223a0898aSmrg_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 51323a0898aSmrg{ 51423a0898aSmrg switch(blockrec->type) { 51523a0898aSmrg case FS_OPEN_FONT: { 51623a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; 51723a0898aSmrg 51823a0898aSmrg fs_cleanup_bfont (bfont); 51923a0898aSmrg _fs_signal_clients_depending(&bfont->clients_depending); 52023a0898aSmrg break; 52123a0898aSmrg } 52223a0898aSmrg case FS_LOAD_GLYPHS: { 52323a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 52423a0898aSmrg 52523a0898aSmrg _fs_clean_aborted_loadglyphs(bglyph->pfont, 52623a0898aSmrg bglyph->num_expected_ranges, 52723a0898aSmrg bglyph->expected_ranges); 52823a0898aSmrg _fs_signal_clients_depending(&bglyph->clients_depending); 52923a0898aSmrg break; 53023a0898aSmrg } 53123a0898aSmrg case FS_LIST_FONTS: 53223a0898aSmrg break; 53323a0898aSmrg case FS_LIST_WITH_INFO: { 53423a0898aSmrg FSBlockedListInfoPtr binfo; 53523a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 53623a0898aSmrg if (binfo->status == FS_LFWI_REPLY) 53723a0898aSmrg FD_SET(conn->fs_fd, &_fs_fd_mask); 53823a0898aSmrg _fs_free_props (&binfo->info); 53923a0898aSmrg } 54023a0898aSmrg default: 54123a0898aSmrg break; 54223a0898aSmrg } 54323a0898aSmrg} 54423a0898aSmrg 54523a0898aSmrgstatic void 54623a0898aSmrgfs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 54723a0898aSmrg{ 54823a0898aSmrg _fs_clean_aborted_blockrec (conn, blockrec); 54923a0898aSmrg _fs_remove_block_rec (conn, blockrec); 55023a0898aSmrg} 55123a0898aSmrg 55223a0898aSmrg/* 55323a0898aSmrg * Tell the font server we've failed to complete an open and 55423a0898aSmrg * then unload the partially created font 55523a0898aSmrg */ 55623a0898aSmrgstatic void 55723a0898aSmrgfs_cleanup_bfont (FSBlockedFontPtr bfont) 55823a0898aSmrg{ 55923a0898aSmrg FSFontDataRec *fsd; 56023a0898aSmrg 56123a0898aSmrg if (bfont->pfont) 56223a0898aSmrg { 56323a0898aSmrg fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; 56423a0898aSmrg 56523a0898aSmrg /* make sure the FS knows we choked on it */ 56623a0898aSmrg fs_send_close_font(bfont->pfont->fpe, bfont->fontid); 56723a0898aSmrg 56823a0898aSmrg /* 56923a0898aSmrg * Either unload the font if it's being opened for 57023a0898aSmrg * the first time, or smash the generation field to 57123a0898aSmrg * mark this font as an orphan 57223a0898aSmrg */ 57323a0898aSmrg if (!(bfont->flags & FontReopen)) 57423a0898aSmrg { 57523a0898aSmrg if (bfont->freeFont) 57623a0898aSmrg (*bfont->pfont->unload_font) (bfont->pfont); 57723a0898aSmrg#ifdef DEBUG 57823a0898aSmrg else 57923a0898aSmrg fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); 58023a0898aSmrg#endif 58123a0898aSmrg bfont->pfont = 0; 58223a0898aSmrg } 58323a0898aSmrg else 58423a0898aSmrg fsd->generation = -1; 58523a0898aSmrg } 58623a0898aSmrg} 58723a0898aSmrg 58823a0898aSmrg/* 58923a0898aSmrg * Check to see if a complete reply is waiting 59023a0898aSmrg */ 59123a0898aSmrgstatic fsGenericReply * 59223a0898aSmrgfs_get_reply (FSFpePtr conn, int *error) 59323a0898aSmrg{ 59423a0898aSmrg char *buf; 59523a0898aSmrg fsGenericReply *rep; 59623a0898aSmrg int ret; 59723a0898aSmrg 59823a0898aSmrg /* block if the connection is down or paused in lfwi */ 59923a0898aSmrg if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) 60023a0898aSmrg { 60123a0898aSmrg *error = FSIO_BLOCK; 60223a0898aSmrg return 0; 60323a0898aSmrg } 60423a0898aSmrg 60523a0898aSmrg ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); 60623a0898aSmrg if (ret != FSIO_READY) 60723a0898aSmrg { 60823a0898aSmrg *error = FSIO_BLOCK; 60923a0898aSmrg return 0; 61023a0898aSmrg } 61123a0898aSmrg 61223a0898aSmrg rep = (fsGenericReply *) buf; 61323a0898aSmrg 61423a0898aSmrg ret = _fs_start_read (conn, rep->length << 2, &buf); 61523a0898aSmrg if (ret != FSIO_READY) 61623a0898aSmrg { 61723a0898aSmrg *error = FSIO_BLOCK; 61823a0898aSmrg return 0; 61923a0898aSmrg } 62023a0898aSmrg 62123a0898aSmrg *error = FSIO_READY; 62223a0898aSmrg 62323a0898aSmrg return (fsGenericReply *) buf; 62423a0898aSmrg} 62523a0898aSmrg 62623a0898aSmrgstatic Bool 62723a0898aSmrgfs_reply_ready (FSFpePtr conn) 62823a0898aSmrg{ 62923a0898aSmrg fsGenericReply *rep; 63023a0898aSmrg 63123a0898aSmrg if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) 63223a0898aSmrg return FALSE; 63323a0898aSmrg if (fs_data_read (conn) < sizeof (fsGenericReply)) 63423a0898aSmrg return FALSE; 63523a0898aSmrg rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); 63623a0898aSmrg if (fs_data_read (conn) < rep->length << 2) 63723a0898aSmrg return FALSE; 63823a0898aSmrg return TRUE; 63923a0898aSmrg} 64023a0898aSmrg 64123a0898aSmrgstatic void 64223a0898aSmrg_fs_pending_reply (FSFpePtr conn) 64323a0898aSmrg{ 64423a0898aSmrg if (!(conn->blockState & FS_PENDING_REPLY)) 64523a0898aSmrg { 64623a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 64723a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 64823a0898aSmrg } 64923a0898aSmrg} 65023a0898aSmrg 65123a0898aSmrgstatic void 65223a0898aSmrg_fs_prepare_for_reply (FSFpePtr conn) 65323a0898aSmrg{ 65423a0898aSmrg _fs_pending_reply (conn); 65523a0898aSmrg _fs_flush (conn); 65623a0898aSmrg} 65723a0898aSmrg 65823a0898aSmrg/* 65923a0898aSmrg * Block (for a while) awaiting a complete reply 66023a0898aSmrg */ 66123a0898aSmrgstatic int 66223a0898aSmrgfs_await_reply (FSFpePtr conn) 66323a0898aSmrg{ 66423a0898aSmrg int ret; 66523a0898aSmrg 66623a0898aSmrg if (conn->blockState & FS_COMPLETE_REPLY) 66723a0898aSmrg return FSIO_READY; 66823a0898aSmrg 66923a0898aSmrg while (!fs_get_reply (conn, &ret)) 67023a0898aSmrg { 67123a0898aSmrg if (ret != FSIO_BLOCK) 67223a0898aSmrg return ret; 67323a0898aSmrg if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) 67423a0898aSmrg { 67523a0898aSmrg _fs_connection_died (conn); 67623a0898aSmrg return FSIO_ERROR; 67723a0898aSmrg } 67823a0898aSmrg } 67923a0898aSmrg return FSIO_READY; 68023a0898aSmrg} 68123a0898aSmrg 68223a0898aSmrg/* 68323a0898aSmrg * Process the reply to an OpenBitmapFont request 68423a0898aSmrg */ 68523a0898aSmrgstatic int 68623a0898aSmrgfs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 68723a0898aSmrg{ 68823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 68923a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 69023a0898aSmrg fsOpenBitmapFontReply *rep; 69123a0898aSmrg FSBlockDataPtr blockOrig; 69223a0898aSmrg FSBlockedFontPtr origBfont; 69323a0898aSmrg int ret; 69423a0898aSmrg 69523a0898aSmrg rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); 69623a0898aSmrg if (!rep || rep->type == FS_Error) 69723a0898aSmrg { 69823a0898aSmrg if (ret == FSIO_BLOCK) 69923a0898aSmrg return StillWorking; 70023a0898aSmrg if (rep) 70123a0898aSmrg _fs_done_read (conn, rep->length << 2); 70223a0898aSmrg fs_cleanup_bfont (bfont); 70323a0898aSmrg return BadFontName; 70423a0898aSmrg } 70523a0898aSmrg 70623a0898aSmrg /* If we're not reopening a font and FS detected a duplicate font 70723a0898aSmrg open request, replace our reference to the new font with a 70823a0898aSmrg reference to an existing font (possibly one not finished 70923a0898aSmrg opening). If this is a reopen, keep the new font reference... 71023a0898aSmrg it's got the metrics and extents we read when the font was opened 71123a0898aSmrg before. This also gives us the freedom to easily close the font 71223a0898aSmrg if we we decide (in fs_read_query_info()) that we don't like what 71323a0898aSmrg we got. */ 71423a0898aSmrg 71523a0898aSmrg if (rep->otherid && !(bfont->flags & FontReopen)) 71623a0898aSmrg { 71723a0898aSmrg fs_cleanup_bfont (bfont); 71823a0898aSmrg 71923a0898aSmrg /* Find old font if we're completely done getting it from server. */ 72023a0898aSmrg bfont->pfont = find_old_font(rep->otherid); 72123a0898aSmrg bfont->freeFont = FALSE; 72223a0898aSmrg bfont->fontid = rep->otherid; 72323a0898aSmrg bfont->state = FS_DONE_REPLY; 72423a0898aSmrg /* 72523a0898aSmrg * look for a blocked request to open the same font 72623a0898aSmrg */ 72723a0898aSmrg for (blockOrig = conn->blockedRequests; 72823a0898aSmrg blockOrig; 72923a0898aSmrg blockOrig = blockOrig->next) 73023a0898aSmrg { 73123a0898aSmrg if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) 73223a0898aSmrg { 73323a0898aSmrg origBfont = (FSBlockedFontPtr) blockOrig->data; 73423a0898aSmrg if (origBfont->fontid == rep->otherid) 73523a0898aSmrg { 73623a0898aSmrg blockrec->depending = blockOrig->depending; 73723a0898aSmrg blockOrig->depending = blockrec; 73823a0898aSmrg bfont->state = FS_DEPENDING; 73923a0898aSmrg bfont->pfont = origBfont->pfont; 74023a0898aSmrg break; 74123a0898aSmrg } 74223a0898aSmrg } 74323a0898aSmrg } 74423a0898aSmrg if (bfont->pfont == NULL) 74523a0898aSmrg { 74623a0898aSmrg /* XXX - something nasty happened */ 74723a0898aSmrg ret = BadFontName; 74823a0898aSmrg } 74923a0898aSmrg else 75023a0898aSmrg ret = AccessDone; 75123a0898aSmrg } 75223a0898aSmrg else 75323a0898aSmrg { 75423a0898aSmrg bfont->pfont->info.cachable = rep->cachable != 0; 75523a0898aSmrg bfont->state = FS_INFO_REPLY; 75623a0898aSmrg /* 75723a0898aSmrg * Reset the blockrec for the next reply 75823a0898aSmrg */ 75923a0898aSmrg blockrec->sequenceNumber = bfont->queryInfoSequence; 76023a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 76123a0898aSmrg ret = StillWorking; 76223a0898aSmrg } 76323a0898aSmrg _fs_done_read (conn, rep->length << 2); 76423a0898aSmrg return ret; 76523a0898aSmrg} 76623a0898aSmrg 76723a0898aSmrgstatic Bool 76823a0898aSmrgfs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) 76923a0898aSmrg{ 77023a0898aSmrg int i; 77123a0898aSmrg 77223a0898aSmrg if (pInfo1->firstCol != pInfo2->firstCol || 77323a0898aSmrg pInfo1->lastCol != pInfo2->lastCol || 77423a0898aSmrg pInfo1->firstRow != pInfo2->firstRow || 77523a0898aSmrg pInfo1->lastRow != pInfo2->lastRow || 77623a0898aSmrg pInfo1->defaultCh != pInfo2->defaultCh || 77723a0898aSmrg pInfo1->noOverlap != pInfo2->noOverlap || 77823a0898aSmrg pInfo1->terminalFont != pInfo2->terminalFont || 77923a0898aSmrg pInfo1->constantMetrics != pInfo2->constantMetrics || 78023a0898aSmrg pInfo1->constantWidth != pInfo2->constantWidth || 78123a0898aSmrg pInfo1->inkInside != pInfo2->inkInside || 78223a0898aSmrg pInfo1->inkMetrics != pInfo2->inkMetrics || 78323a0898aSmrg pInfo1->allExist != pInfo2->allExist || 78423a0898aSmrg pInfo1->drawDirection != pInfo2->drawDirection || 78523a0898aSmrg pInfo1->cachable != pInfo2->cachable || 78623a0898aSmrg pInfo1->anamorphic != pInfo2->anamorphic || 78723a0898aSmrg pInfo1->maxOverlap != pInfo2->maxOverlap || 78823a0898aSmrg pInfo1->fontAscent != pInfo2->fontAscent || 78923a0898aSmrg pInfo1->fontDescent != pInfo2->fontDescent || 79023a0898aSmrg pInfo1->nprops != pInfo2->nprops) 79123a0898aSmrg return FALSE; 79223a0898aSmrg 79323a0898aSmrg#define MATCH(xci1, xci2) \ 79423a0898aSmrg (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ 79523a0898aSmrg ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ 79623a0898aSmrg ((xci1).characterWidth == (xci2).characterWidth) && \ 79723a0898aSmrg ((xci1).ascent == (xci2).ascent) && \ 79823a0898aSmrg ((xci1).descent == (xci2).descent) && \ 79923a0898aSmrg ((xci1).attributes == (xci2).attributes)) 80023a0898aSmrg 80123a0898aSmrg if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || 80223a0898aSmrg !MATCH(pInfo1->minbounds, pInfo2->minbounds) || 80323a0898aSmrg !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || 80423a0898aSmrg !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) 80523a0898aSmrg return FALSE; 80623a0898aSmrg 80723a0898aSmrg#undef MATCH 80823a0898aSmrg 80923a0898aSmrg for (i = 0; i < pInfo1->nprops; i++) 81023a0898aSmrg if (pInfo1->isStringProp[i] != 81123a0898aSmrg pInfo2->isStringProp[i] || 81223a0898aSmrg pInfo1->props[i].name != 81323a0898aSmrg pInfo2->props[i].name || 81423a0898aSmrg pInfo1->props[i].value != 81523a0898aSmrg pInfo2->props[i].value) 81623a0898aSmrg { 81723a0898aSmrg return FALSE; 81823a0898aSmrg } 81923a0898aSmrg return TRUE; 82023a0898aSmrg} 82123a0898aSmrg 82223a0898aSmrgstatic int 82323a0898aSmrgfs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 82423a0898aSmrg{ 82523a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 82623a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 82723a0898aSmrg fsQueryXInfoReply *rep; 82823a0898aSmrg char *buf; 82923a0898aSmrg fsPropInfo *pi; 83023a0898aSmrg fsPropOffset *po; 83123a0898aSmrg pointer pd; 83223a0898aSmrg FontInfoPtr pInfo; 83323a0898aSmrg FontInfoRec tempInfo; 83423a0898aSmrg int err; 83523a0898aSmrg int ret; 83623a0898aSmrg 83723a0898aSmrg rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); 83823a0898aSmrg if (!rep || rep->type == FS_Error) 83923a0898aSmrg { 84023a0898aSmrg if (ret == FSIO_BLOCK) 84123a0898aSmrg return StillWorking; 84223a0898aSmrg if (rep) 84323a0898aSmrg _fs_done_read (conn, rep->length << 2); 84423a0898aSmrg fs_cleanup_bfont (bfont); 84523a0898aSmrg return BadFontName; 84623a0898aSmrg } 84723a0898aSmrg 84823a0898aSmrg /* If this is a reopen, accumulate the query info into a dummy 84923a0898aSmrg font and compare to our original data. */ 85023a0898aSmrg if (bfont->flags & FontReopen) 85123a0898aSmrg pInfo = &tempInfo; 85223a0898aSmrg else 85323a0898aSmrg pInfo = &bfont->pfont->info; 85423a0898aSmrg 85523a0898aSmrg buf = (char *) rep; 85623a0898aSmrg buf += SIZEOF(fsQueryXInfoReply); 85723a0898aSmrg 85823a0898aSmrg /* move the data over */ 85923a0898aSmrg fsUnpack_XFontInfoHeader(rep, pInfo); 86023a0898aSmrg 86123a0898aSmrg /* compute accelerators */ 86223a0898aSmrg _fs_init_fontinfo(conn, pInfo); 86323a0898aSmrg 86423a0898aSmrg /* Compute offsets into the reply */ 86523a0898aSmrg pi = (fsPropInfo *) buf; 86623a0898aSmrg buf += SIZEOF (fsPropInfo); 86723a0898aSmrg 86823a0898aSmrg po = (fsPropOffset *) buf; 86923a0898aSmrg buf += pi->num_offsets * SIZEOF(fsPropOffset); 87023a0898aSmrg 87123a0898aSmrg pd = (pointer) buf; 87223a0898aSmrg buf += pi->data_len; 87323a0898aSmrg 87423a0898aSmrg /* convert the properties and step over the reply */ 87523a0898aSmrg ret = _fs_convert_props(pi, po, pd, pInfo); 87623a0898aSmrg _fs_done_read (conn, rep->length << 2); 87723a0898aSmrg 87823a0898aSmrg if (ret == -1) 87923a0898aSmrg { 88023a0898aSmrg fs_cleanup_bfont (bfont); 88123a0898aSmrg return AllocError; 88223a0898aSmrg } 88323a0898aSmrg 88423a0898aSmrg if (bfont->flags & FontReopen) 88523a0898aSmrg { 88623a0898aSmrg /* We're reopening a font that we lost because of a downed 88723a0898aSmrg connection. In the interest of avoiding corruption from 88823a0898aSmrg opening a different font than the old one (we already have 88923a0898aSmrg its metrics, extents, and probably some of its glyphs), 89023a0898aSmrg verify that the metrics and properties all match. */ 89123a0898aSmrg 89223a0898aSmrg if (fs_fonts_match (pInfo, &bfont->pfont->info)) 89323a0898aSmrg { 89423a0898aSmrg err = Successful; 89523a0898aSmrg bfont->state = FS_DONE_REPLY; 89623a0898aSmrg } 89723a0898aSmrg else 89823a0898aSmrg { 89923a0898aSmrg fs_cleanup_bfont (bfont); 90023a0898aSmrg err = BadFontName; 90123a0898aSmrg } 90223a0898aSmrg _fs_free_props (pInfo); 90323a0898aSmrg 90423a0898aSmrg return err; 90523a0898aSmrg } 90623a0898aSmrg 90723a0898aSmrg /* 90823a0898aSmrg * Ask for terminal format fonts if possible 90923a0898aSmrg */ 91023a0898aSmrg if (bfont->pfont->info.terminalFont) 91123a0898aSmrg bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | 91223a0898aSmrg BitmapFormatImageRectMax); 91323a0898aSmrg 91423a0898aSmrg /* 91523a0898aSmrg * Figure out if the whole font should get loaded right now. 91623a0898aSmrg */ 91723a0898aSmrg if (glyphCachingMode == CACHING_OFF || 91823a0898aSmrg (glyphCachingMode == CACHE_16_BIT_GLYPHS 91923a0898aSmrg && !bfont->pfont->info.lastRow)) 92023a0898aSmrg { 92123a0898aSmrg bfont->flags |= FontLoadAll; 92223a0898aSmrg } 92323a0898aSmrg 92423a0898aSmrg /* 92523a0898aSmrg * Ready to send the query bitmaps; the terminal font bit has 92623a0898aSmrg * been computed and glyphCaching has been considered 92723a0898aSmrg */ 92823a0898aSmrg if (bfont->flags & FontLoadBitmaps) 92923a0898aSmrg { 93023a0898aSmrg fs_send_query_bitmaps (fpe, blockrec); 93123a0898aSmrg _fs_flush (conn); 93223a0898aSmrg } 93323a0898aSmrg 93423a0898aSmrg bfont->state = FS_EXTENT_REPLY; 93523a0898aSmrg 93623a0898aSmrg /* 93723a0898aSmrg * Reset the blockrec for the next reply 93823a0898aSmrg */ 93923a0898aSmrg blockrec->sequenceNumber = bfont->queryExtentsSequence; 94023a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 94123a0898aSmrg 94223a0898aSmrg return StillWorking; 94323a0898aSmrg} 94423a0898aSmrg 94523a0898aSmrgstatic int 94623a0898aSmrgfs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 94723a0898aSmrg{ 94823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 94923a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 95023a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; 95123a0898aSmrg FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; 95223a0898aSmrg fsQueryXExtents16Reply *rep; 95323a0898aSmrg char *buf; 95423a0898aSmrg int i; 95523a0898aSmrg int numExtents; 95623a0898aSmrg int numInfos; 95723a0898aSmrg int ret; 95823a0898aSmrg Bool haveInk = FALSE; /* need separate ink metrics? */ 95923a0898aSmrg CharInfoPtr ci, pCI; 96023a0898aSmrg char *fsci; 96123a0898aSmrg fsXCharInfo fscilocal; 96223a0898aSmrg FontInfoRec *fi = &bfont->pfont->info; 96323a0898aSmrg 96423a0898aSmrg rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); 96523a0898aSmrg if (!rep || rep->type == FS_Error) 96623a0898aSmrg { 96723a0898aSmrg if (ret == FSIO_BLOCK) 96823a0898aSmrg return StillWorking; 96923a0898aSmrg if (rep) 97023a0898aSmrg _fs_done_read (conn, rep->length << 2); 97123a0898aSmrg fs_cleanup_bfont (bfont); 97223a0898aSmrg return BadFontName; 97323a0898aSmrg } 97423a0898aSmrg 97523a0898aSmrg /* move the data over */ 97623a0898aSmrg /* need separate inkMetrics for fixed font server protocol version */ 97723a0898aSmrg numExtents = rep->num_extents; 97823a0898aSmrg numInfos = numExtents; 97923a0898aSmrg if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) 98023a0898aSmrg { 98123a0898aSmrg numInfos *= 2; 98223a0898aSmrg haveInk = TRUE; 98323a0898aSmrg } 98423a0898aSmrg ci = pCI = (CharInfoPtr) xalloc(sizeof(CharInfoRec) * numInfos); 98523a0898aSmrg 98623a0898aSmrg if (!pCI) 98723a0898aSmrg { 98823a0898aSmrg _fs_done_read (conn, rep->length << 2); 98923a0898aSmrg fs_cleanup_bfont(bfont); 99023a0898aSmrg return AllocError; 99123a0898aSmrg } 99223a0898aSmrg fsfont->encoding = pCI; 99323a0898aSmrg if (haveInk) 99423a0898aSmrg fsfont->inkMetrics = pCI + numExtents; 99523a0898aSmrg else 99623a0898aSmrg fsfont->inkMetrics = pCI; 99723a0898aSmrg 99823a0898aSmrg buf = (char *) rep; 99923a0898aSmrg buf += SIZEOF (fsQueryXExtents16Reply); 100023a0898aSmrg fsci = buf; 100123a0898aSmrg 100223a0898aSmrg fsd->glyphs_to_get = 0; 100323a0898aSmrg ci = fsfont->inkMetrics; 100423a0898aSmrg for (i = 0; i < numExtents; i++) 100523a0898aSmrg { 100623a0898aSmrg memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ 100723a0898aSmrg _fs_convert_char_info(&fscilocal, &ci->metrics); 100823a0898aSmrg /* Bounds check. */ 100923a0898aSmrg if (ci->metrics.ascent > fi->maxbounds.ascent) 101023a0898aSmrg { 101123a0898aSmrg ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", 101223a0898aSmrg fpe->name, fsd->name, 101323a0898aSmrg ci->metrics.ascent, fi->maxbounds.ascent); 101423a0898aSmrg ci->metrics.ascent = fi->maxbounds.ascent; 101523a0898aSmrg } 101623a0898aSmrg if (ci->metrics.descent > fi->maxbounds.descent) 101723a0898aSmrg { 101823a0898aSmrg ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", 101923a0898aSmrg fpe->name, fsd->name, 102023a0898aSmrg ci->metrics.descent, fi->maxbounds.descent); 102123a0898aSmrg ci->metrics.descent = fi->maxbounds.descent; 102223a0898aSmrg } 102323a0898aSmrg fsci = fsci + SIZEOF(fsXCharInfo); 102423a0898aSmrg /* Initialize the bits field for later glyph-caching use */ 102523a0898aSmrg if (NONZEROMETRICS(&ci->metrics)) 102623a0898aSmrg { 102723a0898aSmrg if (!haveInk && 102823a0898aSmrg (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || 102923a0898aSmrg ci->metrics.ascent == -ci->metrics.descent)) 103023a0898aSmrg pCI[i].bits = &_fs_glyph_zero_length; 103123a0898aSmrg else 103223a0898aSmrg { 103323a0898aSmrg pCI[i].bits = &_fs_glyph_undefined; 103423a0898aSmrg fsd->glyphs_to_get++; 103523a0898aSmrg } 103623a0898aSmrg } 103723a0898aSmrg else 103823a0898aSmrg pCI[i].bits = (char *)0; 103923a0898aSmrg ci++; 104023a0898aSmrg } 104123a0898aSmrg 104223a0898aSmrg /* Done with reply */ 104323a0898aSmrg _fs_done_read (conn, rep->length << 2); 104423a0898aSmrg 104523a0898aSmrg /* build bitmap metrics, ImageRectMax style */ 104623a0898aSmrg if (haveInk) 104723a0898aSmrg { 104823a0898aSmrg CharInfoPtr ii; 104923a0898aSmrg 105023a0898aSmrg ci = fsfont->encoding; 105123a0898aSmrg ii = fsfont->inkMetrics; 105223a0898aSmrg for (i = 0; i < numExtents; i++, ci++, ii++) 105323a0898aSmrg { 105423a0898aSmrg if (NONZEROMETRICS(&ii->metrics)) 105523a0898aSmrg { 105623a0898aSmrg ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); 105723a0898aSmrg ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); 105823a0898aSmrg ci->metrics.ascent = FONT_MAX_ASCENT(fi); 105923a0898aSmrg ci->metrics.descent = FONT_MAX_DESCENT(fi); 106023a0898aSmrg ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); 106123a0898aSmrg ci->metrics.attributes = ii->metrics.attributes; 106223a0898aSmrg } 106323a0898aSmrg else 106423a0898aSmrg { 106523a0898aSmrg ci->metrics = ii->metrics; 106623a0898aSmrg } 106723a0898aSmrg /* Bounds check. */ 106823a0898aSmrg if (ci->metrics.ascent > fi->maxbounds.ascent) 106923a0898aSmrg { 107023a0898aSmrg ErrorF("fserve: warning: %s %s ascent (%d) " 107123a0898aSmrg "> maxascent (%d)\n", 107223a0898aSmrg fpe->name, fsd->name, 107323a0898aSmrg ci->metrics.ascent, fi->maxbounds.ascent); 107423a0898aSmrg ci->metrics.ascent = fi->maxbounds.ascent; 107523a0898aSmrg } 107623a0898aSmrg if (ci->metrics.descent > fi->maxbounds.descent) 107723a0898aSmrg { 107823a0898aSmrg ErrorF("fserve: warning: %s %s descent (%d) " 107923a0898aSmrg "> maxdescent (%d)\n", 108023a0898aSmrg fpe->name, fsd->name, 108123a0898aSmrg ci->metrics.descent, fi->maxbounds.descent); 108223a0898aSmrg ci->metrics.descent = fi->maxbounds.descent; 108323a0898aSmrg } 108423a0898aSmrg } 108523a0898aSmrg } 108623a0898aSmrg { 108723a0898aSmrg unsigned int r, c, numCols, firstCol; 108823a0898aSmrg 108923a0898aSmrg firstCol = bfont->pfont->info.firstCol; 109023a0898aSmrg numCols = bfont->pfont->info.lastCol - firstCol + 1; 109123a0898aSmrg c = bfont->pfont->info.defaultCh; 109223a0898aSmrg fsfont->pDefault = 0; 109323a0898aSmrg if (bfont->pfont->info.lastRow) 109423a0898aSmrg { 109523a0898aSmrg r = c >> 8; 109623a0898aSmrg r -= bfont->pfont->info.firstRow; 109723a0898aSmrg c &= 0xff; 109823a0898aSmrg c -= firstCol; 109923a0898aSmrg if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && 110023a0898aSmrg c < numCols) 110123a0898aSmrg fsfont->pDefault = &pCI[r * numCols + c]; 110223a0898aSmrg } 110323a0898aSmrg else 110423a0898aSmrg { 110523a0898aSmrg c -= firstCol; 110623a0898aSmrg if (c < numCols) 110723a0898aSmrg fsfont->pDefault = &pCI[c]; 110823a0898aSmrg } 110923a0898aSmrg } 111023a0898aSmrg bfont->state = FS_GLYPHS_REPLY; 111123a0898aSmrg 111223a0898aSmrg if (bfont->flags & FontLoadBitmaps) 111323a0898aSmrg { 111423a0898aSmrg /* 111523a0898aSmrg * Reset the blockrec for the next reply 111623a0898aSmrg */ 111723a0898aSmrg blockrec->sequenceNumber = bfont->queryBitmapsSequence; 111823a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 111923a0898aSmrg return StillWorking; 112023a0898aSmrg } 112123a0898aSmrg return Successful; 112223a0898aSmrg} 112323a0898aSmrg 112423a0898aSmrg#ifdef DEBUG 112523a0898aSmrgstatic char *fs_open_states[] = { 112623a0898aSmrg "OPEN_REPLY ", 112723a0898aSmrg "INFO_REPLY ", 112823a0898aSmrg "EXTENT_REPLY", 112923a0898aSmrg "GLYPHS_REPLY", 113023a0898aSmrg "DONE_REPLY ", 113123a0898aSmrg "DEPENDING ", 113223a0898aSmrg}; 113323a0898aSmrg#endif 113423a0898aSmrg 113523a0898aSmrgstatic int 113623a0898aSmrgfs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 113723a0898aSmrg{ 113823a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 113923a0898aSmrg int err; 114023a0898aSmrg 114123a0898aSmrg#ifdef DEBUG 114223a0898aSmrg fprintf (stderr, "fs_do_open_font state %s %s\n", 114323a0898aSmrg fs_open_states[bfont->state], 114423a0898aSmrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); 114523a0898aSmrg#endif 114623a0898aSmrg err = BadFontName; 114723a0898aSmrg switch (bfont->state) { 114823a0898aSmrg case FS_OPEN_REPLY: 114923a0898aSmrg err = fs_read_open_font(fpe, blockrec); 115023a0898aSmrg if (err != StillWorking) { /* already loaded, or error */ 115123a0898aSmrg /* if font's already loaded, massage error code */ 115223a0898aSmrg switch (bfont->state) { 115323a0898aSmrg case FS_DONE_REPLY: 115423a0898aSmrg err = Successful; 115523a0898aSmrg break; 115623a0898aSmrg case FS_DEPENDING: 115723a0898aSmrg err = StillWorking; 115823a0898aSmrg break; 115923a0898aSmrg } 116023a0898aSmrg } 116123a0898aSmrg break; 116223a0898aSmrg case FS_INFO_REPLY: 116323a0898aSmrg err = fs_read_query_info(fpe, blockrec); 116423a0898aSmrg break; 116523a0898aSmrg case FS_EXTENT_REPLY: 116623a0898aSmrg err = fs_read_extent_info(fpe, blockrec); 116723a0898aSmrg break; 116823a0898aSmrg case FS_GLYPHS_REPLY: 116923a0898aSmrg if (bfont->flags & FontLoadBitmaps) 117023a0898aSmrg err = fs_read_glyphs(fpe, blockrec); 117123a0898aSmrg break; 117223a0898aSmrg case FS_DEPENDING: /* can't happen */ 117323a0898aSmrg default: 117423a0898aSmrg break; 117523a0898aSmrg } 117623a0898aSmrg#ifdef DEBUG 117723a0898aSmrg fprintf (stderr, "fs_do_open_font err %d\n", err); 117823a0898aSmrg#endif 117923a0898aSmrg if (err != StillWorking) 118023a0898aSmrg { 118123a0898aSmrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 118223a0898aSmrg while ((blockrec = blockrec->depending)) 118323a0898aSmrg { 118423a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 118523a0898aSmrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 118623a0898aSmrg } 118723a0898aSmrg } 118823a0898aSmrg return err; 118923a0898aSmrg} 119023a0898aSmrg 119123a0898aSmrgvoid 119223a0898aSmrg_fs_mark_block (FSFpePtr conn, CARD32 mask) 119323a0898aSmrg{ 119423a0898aSmrg conn->blockState |= mask; 119523a0898aSmrg fs_blockState |= mask; 119623a0898aSmrg} 119723a0898aSmrg 119823a0898aSmrgvoid 119923a0898aSmrg_fs_unmark_block (FSFpePtr conn, CARD32 mask) 120023a0898aSmrg{ 120123a0898aSmrg FSFpePtr c; 120223a0898aSmrg 120323a0898aSmrg if (conn->blockState & mask) 120423a0898aSmrg { 120523a0898aSmrg conn->blockState &= ~mask; 120623a0898aSmrg fs_blockState = 0; 120723a0898aSmrg for (c = fs_fpes; c; c = c->next) 120823a0898aSmrg fs_blockState |= c->blockState; 120923a0898aSmrg } 121023a0898aSmrg} 121123a0898aSmrg 121223a0898aSmrg/* ARGSUSED */ 121323a0898aSmrgstatic void 121423a0898aSmrgfs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) 121523a0898aSmrg{ 121623a0898aSmrg static struct timeval block_timeout; 121723a0898aSmrg CARD32 now, earliest, wakeup; 121823a0898aSmrg int soonest; 121923a0898aSmrg FSFpePtr conn; 122023a0898aSmrg 122123a0898aSmrg XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, 122223a0898aSmrg &_fs_fd_mask); 122323a0898aSmrg /* 122423a0898aSmrg * Flush all pending output 122523a0898aSmrg */ 122623a0898aSmrg if (fs_blockState & FS_PENDING_WRITE) 122723a0898aSmrg for (conn = fs_fpes; conn; conn = conn->next) 122823a0898aSmrg if (conn->blockState & FS_PENDING_WRITE) 122923a0898aSmrg _fs_flush (conn); 123023a0898aSmrg /* 123123a0898aSmrg * Check for any fpe with a complete reply, set sleep time to zero 123223a0898aSmrg */ 123323a0898aSmrg if (fs_blockState & FS_COMPLETE_REPLY) 123423a0898aSmrg { 123523a0898aSmrg block_timeout.tv_sec = 0; 123623a0898aSmrg block_timeout.tv_usec = 0; 123723a0898aSmrg if (*wt == NULL) 123823a0898aSmrg *wt = &block_timeout; 123923a0898aSmrg else 124023a0898aSmrg **wt = block_timeout; 124123a0898aSmrg } 124223a0898aSmrg /* 124323a0898aSmrg * Walk through fpe list computing sleep time 124423a0898aSmrg */ 124523a0898aSmrg else if (fs_blockState & (FS_BROKEN_WRITE| 124623a0898aSmrg FS_BROKEN_CONNECTION| 124723a0898aSmrg FS_PENDING_REPLY| 124823a0898aSmrg FS_RECONNECTING)) 124923a0898aSmrg { 125023a0898aSmrg now = GetTimeInMillis (); 125123a0898aSmrg earliest = now + 10000000; 125223a0898aSmrg for (conn = fs_fpes; conn; conn = conn->next) 125323a0898aSmrg { 125423a0898aSmrg if (conn->blockState & FS_RECONNECTING) 125523a0898aSmrg { 125623a0898aSmrg wakeup = conn->blockedConnectTime; 125723a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 125823a0898aSmrg earliest = wakeup; 125923a0898aSmrg } 126023a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 126123a0898aSmrg { 126223a0898aSmrg wakeup = conn->brokenConnectionTime; 126323a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 126423a0898aSmrg earliest = wakeup; 126523a0898aSmrg } 126623a0898aSmrg if (conn->blockState & FS_BROKEN_WRITE) 126723a0898aSmrg { 126823a0898aSmrg wakeup = conn->brokenWriteTime; 126923a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 127023a0898aSmrg earliest = wakeup; 127123a0898aSmrg } 127223a0898aSmrg if (conn->blockState & FS_PENDING_REPLY) 127323a0898aSmrg { 127423a0898aSmrg wakeup = conn->blockedReplyTime; 127523a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 127623a0898aSmrg earliest = wakeup; 127723a0898aSmrg } 127823a0898aSmrg } 127923a0898aSmrg soonest = earliest - now; 128023a0898aSmrg if (soonest < 0) 128123a0898aSmrg soonest = 0; 128223a0898aSmrg block_timeout.tv_sec = soonest / 1000; 128323a0898aSmrg block_timeout.tv_usec = (soonest % 1000) * 1000; 128423a0898aSmrg if (*wt == NULL) 128523a0898aSmrg *wt = &block_timeout; 128623a0898aSmrg else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) 128723a0898aSmrg **wt = block_timeout; 128823a0898aSmrg } 128923a0898aSmrg} 129023a0898aSmrg 129123a0898aSmrgstatic void 129223a0898aSmrgfs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) 129323a0898aSmrg{ 129423a0898aSmrg if (rep->type == FS_Event && rep->data1 == KeepAlive) 129523a0898aSmrg { 129623a0898aSmrg fsNoopReq req; 129723a0898aSmrg 129823a0898aSmrg /* ping it back */ 129923a0898aSmrg req.reqType = FS_Noop; 130023a0898aSmrg req.length = SIZEOF(fsNoopReq) >> 2; 130123a0898aSmrg _fs_add_req_log(conn, FS_Noop); 130223a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); 130323a0898aSmrg } 130423a0898aSmrg /* this should suck up unexpected replies and events */ 130523a0898aSmrg _fs_done_read (conn, rep->length << 2); 130623a0898aSmrg} 130723a0898aSmrg 130823a0898aSmrgstatic void 130923a0898aSmrgfs_read_reply (FontPathElementPtr fpe, pointer client) 131023a0898aSmrg{ 131123a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 131223a0898aSmrg FSBlockDataPtr blockrec; 131323a0898aSmrg int ret; 131423a0898aSmrg int err; 131523a0898aSmrg fsGenericReply *rep; 131623a0898aSmrg 131723a0898aSmrg if ((rep = fs_get_reply (conn, &ret))) 131823a0898aSmrg { 131923a0898aSmrg _fs_add_rep_log (conn, rep); 132023a0898aSmrg for (blockrec = conn->blockedRequests; 132123a0898aSmrg blockrec; 132223a0898aSmrg blockrec = blockrec->next) 132323a0898aSmrg { 132423a0898aSmrg if (blockrec->sequenceNumber == rep->sequenceNumber) 132523a0898aSmrg break; 132623a0898aSmrg } 132723a0898aSmrg err = Successful; 132823a0898aSmrg if (!blockrec) 132923a0898aSmrg { 133023a0898aSmrg fs_handle_unexpected(conn, rep); 133123a0898aSmrg } 133223a0898aSmrg else 133323a0898aSmrg { 133423a0898aSmrg /* 133523a0898aSmrg * go read it, and if we're done, 133623a0898aSmrg * wake up the appropriate client 133723a0898aSmrg */ 133823a0898aSmrg switch (blockrec->type) { 133923a0898aSmrg case FS_OPEN_FONT: 134023a0898aSmrg blockrec->errcode = fs_do_open_font(fpe, blockrec); 134123a0898aSmrg break; 134223a0898aSmrg case FS_LOAD_GLYPHS: 134323a0898aSmrg blockrec->errcode = fs_read_glyphs(fpe, blockrec); 134423a0898aSmrg break; 134523a0898aSmrg case FS_LIST_FONTS: 134623a0898aSmrg blockrec->errcode = fs_read_list(fpe, blockrec); 134723a0898aSmrg break; 134823a0898aSmrg case FS_LIST_WITH_INFO: 134923a0898aSmrg blockrec->errcode = fs_read_list_info(fpe, blockrec); 135023a0898aSmrg break; 135123a0898aSmrg default: 135223a0898aSmrg break; 135323a0898aSmrg } 135423a0898aSmrg err = blockrec->errcode; 135523a0898aSmrg if (err != StillWorking) 135623a0898aSmrg { 135723a0898aSmrg while (blockrec) 135823a0898aSmrg { 135923a0898aSmrg blockrec->errcode = err; 136023a0898aSmrg if (client != blockrec->client) 136123a0898aSmrg ClientSignal(blockrec->client); 136223a0898aSmrg blockrec = blockrec->depending; 136323a0898aSmrg } 136423a0898aSmrg _fs_unmark_block (conn, FS_PENDING_REPLY); 136523a0898aSmrg } 136623a0898aSmrg } 136723a0898aSmrg if (fs_reply_ready (conn)) 136823a0898aSmrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 136923a0898aSmrg else 137023a0898aSmrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 137123a0898aSmrg } 137223a0898aSmrg} 137323a0898aSmrg 137423a0898aSmrgstatic int 137523a0898aSmrgfs_wakeup(FontPathElementPtr fpe, unsigned long *mask) 137623a0898aSmrg{ 137723a0898aSmrg fd_set *LastSelectMask = (fd_set *) mask; 137823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 137923a0898aSmrg 138023a0898aSmrg /* 138123a0898aSmrg * Don't continue if the fd is -1 (which will be true when the 138223a0898aSmrg * font server terminates 138323a0898aSmrg */ 138423a0898aSmrg if ((conn->blockState & FS_RECONNECTING)) 138523a0898aSmrg _fs_check_reconnect (conn); 138623a0898aSmrg else if ((conn->blockState & FS_COMPLETE_REPLY) || 138723a0898aSmrg (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) 138823a0898aSmrg fs_read_reply (fpe, 0); 138923a0898aSmrg if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) 139023a0898aSmrg _fs_do_blocked (conn); 139123a0898aSmrg#ifdef DEBUG 139223a0898aSmrg { 139323a0898aSmrg FSBlockDataPtr blockrec; 139423a0898aSmrg FSBlockedFontPtr bfont; 139523a0898aSmrg FSBlockedListPtr blist; 139623a0898aSmrg static CARD32 lastState; 139723a0898aSmrg static FSBlockDataPtr lastBlock; 139823a0898aSmrg 139923a0898aSmrg if (conn->blockState || conn->blockedRequests || lastState || lastBlock) 140023a0898aSmrg { 140123a0898aSmrg fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); 140223a0898aSmrg lastState = conn->blockState; 140323a0898aSmrg lastBlock = conn->blockedRequests; 140423a0898aSmrg } 140523a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 140623a0898aSmrg { 140723a0898aSmrg switch (blockrec->type) { 140823a0898aSmrg case FS_OPEN_FONT: 140923a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 141023a0898aSmrg fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", 141123a0898aSmrg blockrec->errcode, 141223a0898aSmrg blockrec->sequenceNumber, 141323a0898aSmrg fs_open_states[bfont->state], 141423a0898aSmrg bfont->pfont ? 141523a0898aSmrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : 141623a0898aSmrg "<freed>"); 141723a0898aSmrg break; 141823a0898aSmrg case FS_LIST_FONTS: 141923a0898aSmrg blist = (FSBlockedListPtr) blockrec->data; 142023a0898aSmrg fprintf (stderr, " Blocked list errcode %d sequence %d\n", 142123a0898aSmrg blockrec->errcode, blockrec->sequenceNumber); 142223a0898aSmrg break; 142323a0898aSmrg default: 142423a0898aSmrg fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", 142523a0898aSmrg blockrec->type, 142623a0898aSmrg blockrec->errcode, 142723a0898aSmrg blockrec->sequenceNumber); 142823a0898aSmrg break; 142923a0898aSmrg } 143023a0898aSmrg } 143123a0898aSmrg } 143223a0898aSmrg#endif 143323a0898aSmrg return FALSE; 143423a0898aSmrg} 143523a0898aSmrg 143623a0898aSmrg/* 143723a0898aSmrg * Notice a dead connection and prepare for reconnect 143823a0898aSmrg */ 143923a0898aSmrg 144023a0898aSmrgvoid 144123a0898aSmrg_fs_connection_died(FSFpePtr conn) 144223a0898aSmrg{ 144323a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 144423a0898aSmrg return; 144523a0898aSmrg fs_close_conn(conn); 144623a0898aSmrg conn->brokenConnectionTime = GetTimeInMillis (); 144723a0898aSmrg _fs_mark_block (conn, FS_BROKEN_CONNECTION); 144823a0898aSmrg _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); 144923a0898aSmrg} 145023a0898aSmrg 145123a0898aSmrg/* 145223a0898aSmrg * Signal clients that the connection has come back up 145323a0898aSmrg */ 145423a0898aSmrgstatic int 145523a0898aSmrg_fs_restart_connection(FSFpePtr conn) 145623a0898aSmrg{ 145723a0898aSmrg FSBlockDataPtr block; 145823a0898aSmrg 145923a0898aSmrg _fs_unmark_block (conn, FS_GIVE_UP); 146023a0898aSmrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 146123a0898aSmrg { 146223a0898aSmrg if (block->errcode == StillWorking) 146323a0898aSmrg { 146423a0898aSmrg ClientSignal(block->client); 146523a0898aSmrg fs_abort_blockrec(conn, block); 146623a0898aSmrg } 146723a0898aSmrg } 146823a0898aSmrg return TRUE; 146923a0898aSmrg} 147023a0898aSmrg 147123a0898aSmrg/* 147223a0898aSmrg * Declare this font server connection useless 147323a0898aSmrg */ 147423a0898aSmrgstatic void 147523a0898aSmrg_fs_giveup (FSFpePtr conn) 147623a0898aSmrg{ 147723a0898aSmrg FSBlockDataPtr block; 147823a0898aSmrg 147923a0898aSmrg if (conn->blockState & FS_GIVE_UP) 148023a0898aSmrg return; 148123a0898aSmrg#ifdef DEBUG 148223a0898aSmrg fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); 148323a0898aSmrg#endif 148423a0898aSmrg _fs_mark_block (conn, FS_GIVE_UP); 148523a0898aSmrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 148623a0898aSmrg { 148723a0898aSmrg if (block->errcode == StillWorking) 148823a0898aSmrg { 148923a0898aSmrg ClientSignal (block->client); 149023a0898aSmrg fs_abort_blockrec (conn, block); 149123a0898aSmrg } 149223a0898aSmrg } 149323a0898aSmrg if (conn->fs_fd >= 0) 149423a0898aSmrg _fs_connection_died (conn); 149523a0898aSmrg} 149623a0898aSmrg 149723a0898aSmrgstatic void 149823a0898aSmrg_fs_do_blocked (FSFpePtr conn) 149923a0898aSmrg{ 150023a0898aSmrg CARD32 now; 150123a0898aSmrg 150223a0898aSmrg now = GetTimeInMillis (); 150323a0898aSmrg if ((conn->blockState & FS_PENDING_REPLY) && 150423a0898aSmrg TimeCmp (conn->blockedReplyTime, <=, now)) 150523a0898aSmrg { 150623a0898aSmrg _fs_giveup (conn); 150723a0898aSmrg } 150823a0898aSmrg else 150923a0898aSmrg { 151023a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 151123a0898aSmrg { 151223a0898aSmrg /* Try to reconnect broken connections */ 151323a0898aSmrg if (TimeCmp (conn->brokenConnectionTime, <=, now)) 151423a0898aSmrg _fs_start_reconnect (conn); 151523a0898aSmrg } 151623a0898aSmrg else if (conn->blockState & FS_BROKEN_WRITE) 151723a0898aSmrg { 151823a0898aSmrg /* Try to flush blocked connections */ 151923a0898aSmrg if (TimeCmp (conn->brokenWriteTime, <=, now)) 152023a0898aSmrg _fs_flush (conn); 152123a0898aSmrg } 152223a0898aSmrg } 152323a0898aSmrg} 152423a0898aSmrg 152523a0898aSmrg/* 152623a0898aSmrg * sends the actual request out 152723a0898aSmrg */ 152823a0898aSmrg/* ARGSUSED */ 152923a0898aSmrgstatic int 153023a0898aSmrgfs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 153123a0898aSmrg char *name, int namelen, 153223a0898aSmrg fsBitmapFormat format, fsBitmapFormatMask fmask, 153323a0898aSmrg XID id, FontPtr *ppfont) 153423a0898aSmrg{ 153523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 153623a0898aSmrg FontPtr font; 153723a0898aSmrg FSBlockDataPtr blockrec = NULL; 153823a0898aSmrg FSBlockedFontPtr bfont; 153923a0898aSmrg FSFontDataPtr fsd; 154023a0898aSmrg fsOpenBitmapFontReq openreq; 154123a0898aSmrg fsQueryXInfoReq inforeq; 154223a0898aSmrg fsQueryXExtents16Req extreq; 154323a0898aSmrg int err; 154423a0898aSmrg unsigned char buf[1024]; 154523a0898aSmrg 154623a0898aSmrg if (conn->blockState & FS_GIVE_UP) 154723a0898aSmrg return BadFontName; 154823a0898aSmrg 154923a0898aSmrg if (namelen <= 0 || namelen > sizeof (buf) - 1) 155023a0898aSmrg return BadFontName; 155123a0898aSmrg 155223a0898aSmrg /* 155323a0898aSmrg * Get the font structure put together, either by reusing 155423a0898aSmrg * the existing one or creating a new one 155523a0898aSmrg */ 155623a0898aSmrg if (flags & FontReopen) 155723a0898aSmrg { 155823a0898aSmrg Atom nameatom, fn = None; 155923a0898aSmrg int i; 156023a0898aSmrg 156123a0898aSmrg font = *ppfont; 156223a0898aSmrg fsd = (FSFontDataPtr)font->fpePrivate; 156323a0898aSmrg /* This is an attempt to reopen a font. Did the font have a 156423a0898aSmrg NAME property? */ 156523a0898aSmrg if ((nameatom = MakeAtom("FONT", 4, 0)) != None) 156623a0898aSmrg { 156723a0898aSmrg for (i = 0; i < font->info.nprops; i++) 156823a0898aSmrg if (font->info.props[i].name == nameatom && 156923a0898aSmrg font->info.isStringProp[i]) 157023a0898aSmrg { 157123a0898aSmrg fn = font->info.props[i].value; 157223a0898aSmrg break; 157323a0898aSmrg } 157423a0898aSmrg } 157523a0898aSmrg if (fn == None || !(name = NameForAtom(fn))) 157623a0898aSmrg { 157723a0898aSmrg name = fsd->name; 157823a0898aSmrg namelen = fsd->namelen; 157923a0898aSmrg } 158023a0898aSmrg else 158123a0898aSmrg namelen = strlen(name); 158223a0898aSmrg } 158323a0898aSmrg else 158423a0898aSmrg { 158523a0898aSmrg font = fs_create_font (fpe, name, namelen, format, fmask); 158623a0898aSmrg if (!font) 158723a0898aSmrg return AllocError; 158823a0898aSmrg 158923a0898aSmrg fsd = (FSFontDataPtr)font->fpePrivate; 159023a0898aSmrg } 159123a0898aSmrg 159223a0898aSmrg /* make a new block record, and add it to the end of the list */ 159323a0898aSmrg blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); 159423a0898aSmrg if (!blockrec) 159523a0898aSmrg { 159623a0898aSmrg if (!(flags & FontReopen)) 159723a0898aSmrg (*font->unload_font) (font); 159823a0898aSmrg return AllocError; 159923a0898aSmrg } 160023a0898aSmrg 160123a0898aSmrg /* 160223a0898aSmrg * Must check this before generating any protocol, otherwise we'll 160323a0898aSmrg * mess up a reconnect in progress 160423a0898aSmrg */ 160523a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 160623a0898aSmrg { 160723a0898aSmrg _fs_pending_reply (conn); 160823a0898aSmrg return Suspended; 160923a0898aSmrg } 161023a0898aSmrg 161123a0898aSmrg fsd->generation = conn->generation; 161223a0898aSmrg 161323a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 161423a0898aSmrg bfont->fontid = fsd->fontid; 161523a0898aSmrg bfont->pfont = font; 161623a0898aSmrg bfont->state = FS_OPEN_REPLY; 161723a0898aSmrg bfont->flags = flags; 161823a0898aSmrg bfont->format = fsd->format; 161923a0898aSmrg bfont->clients_depending = (FSClientsDependingPtr)0; 162023a0898aSmrg bfont->freeFont = (flags & FontReopen) == 0; 162123a0898aSmrg 162223a0898aSmrg _fs_client_access (conn, client, (flags & FontOpenSync) != 0); 162323a0898aSmrg _fs_client_resolution(conn); 162423a0898aSmrg 162523a0898aSmrg /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ 162623a0898aSmrg buf[0] = (unsigned char) namelen; 162723a0898aSmrg memcpy(&buf[1], name, namelen); 162823a0898aSmrg openreq.reqType = FS_OpenBitmapFont; 162923a0898aSmrg openreq.fid = fsd->fontid; 163023a0898aSmrg openreq.format_hint = fsd->format; 163123a0898aSmrg openreq.format_mask = fsd->fmask; 163223a0898aSmrg openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; 163323a0898aSmrg 163423a0898aSmrg _fs_add_req_log(conn, FS_OpenBitmapFont); 163523a0898aSmrg _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); 163623a0898aSmrg _fs_write_pad(conn, (char *) buf, namelen + 1); 163723a0898aSmrg 163823a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 163923a0898aSmrg 164023a0898aSmrg inforeq.reqType = FS_QueryXInfo; 164123a0898aSmrg inforeq.id = fsd->fontid; 164223a0898aSmrg inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; 164323a0898aSmrg 164423a0898aSmrg bfont->queryInfoSequence = conn->current_seq + 1; 164523a0898aSmrg 164623a0898aSmrg _fs_add_req_log(conn, FS_QueryXInfo); 164723a0898aSmrg _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); 164823a0898aSmrg 164923a0898aSmrg if (!(bfont->flags & FontReopen)) 165023a0898aSmrg { 165123a0898aSmrg extreq.reqType = FS_QueryXExtents16; 165223a0898aSmrg extreq.range = fsTrue; 165323a0898aSmrg extreq.fid = fsd->fontid; 165423a0898aSmrg extreq.num_ranges = 0; 165523a0898aSmrg extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; 165623a0898aSmrg 165723a0898aSmrg bfont->queryExtentsSequence = conn->current_seq + 1; 165823a0898aSmrg 165923a0898aSmrg _fs_add_req_log(conn, FS_QueryXExtents16); 166023a0898aSmrg _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); 166123a0898aSmrg } 166223a0898aSmrg 166323a0898aSmrg#ifdef NCD 166423a0898aSmrg if (configData.ExtendedFontDiags) 166523a0898aSmrg { 166623a0898aSmrg memcpy(buf, name, MIN(256, namelen)); 166723a0898aSmrg buf[MIN(256, namelen)] = '\0'; 166823a0898aSmrg printf("Requesting font \"%s\" from font server \"%s\"\n", 166923a0898aSmrg buf, font->fpe->name); 167023a0898aSmrg } 167123a0898aSmrg#endif 167223a0898aSmrg _fs_prepare_for_reply (conn); 167323a0898aSmrg 167423a0898aSmrg err = blockrec->errcode; 167523a0898aSmrg if (bfont->flags & FontOpenSync) 167623a0898aSmrg { 167723a0898aSmrg while (blockrec->errcode == StillWorking) 167823a0898aSmrg { 167923a0898aSmrg if (fs_await_reply (conn) != FSIO_READY) 168023a0898aSmrg { 168123a0898aSmrg blockrec->errcode = BadFontName; 168223a0898aSmrg break; 168323a0898aSmrg } 168423a0898aSmrg fs_read_reply (font->fpe, client); 168523a0898aSmrg } 168623a0898aSmrg err = blockrec->errcode; 168723a0898aSmrg if (err == Successful) 168823a0898aSmrg *ppfont = bfont->pfont; 168923a0898aSmrg else 169023a0898aSmrg fs_cleanup_bfont (bfont); 169123a0898aSmrg bfont->freeFont = FALSE; 169223a0898aSmrg _fs_remove_block_rec (conn, blockrec); 169323a0898aSmrg } 169423a0898aSmrg return err == StillWorking ? Suspended : err; 169523a0898aSmrg} 169623a0898aSmrg 169723a0898aSmrgstatic void 169823a0898aSmrgfs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 169923a0898aSmrg{ 170023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 170123a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 170223a0898aSmrg fsQueryXBitmaps16Req bitreq; 170323a0898aSmrg 170423a0898aSmrg /* send the request */ 170523a0898aSmrg bitreq.reqType = FS_QueryXBitmaps16; 170623a0898aSmrg bitreq.fid = bfont->fontid; 170723a0898aSmrg bitreq.format = bfont->format; 170823a0898aSmrg bitreq.range = TRUE; 170923a0898aSmrg bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; 171023a0898aSmrg bitreq.num_ranges = 0; 171123a0898aSmrg 171223a0898aSmrg bfont->queryBitmapsSequence = conn->current_seq + 1; 171323a0898aSmrg 171423a0898aSmrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 171523a0898aSmrg _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); 171623a0898aSmrg} 171723a0898aSmrg 171823a0898aSmrg/* ARGSUSED */ 171923a0898aSmrgstatic int 172023a0898aSmrgfs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 172123a0898aSmrg char *name, int namelen, 172223a0898aSmrg fsBitmapFormat format, fsBitmapFormatMask fmask, 172323a0898aSmrg XID id, FontPtr *ppfont, 172423a0898aSmrg char **alias, FontPtr non_cachable_font) 172523a0898aSmrg{ 172623a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 172723a0898aSmrg FSBlockDataPtr blockrec; 172823a0898aSmrg FSBlockedFontPtr bfont; 172923a0898aSmrg int err; 173023a0898aSmrg 173123a0898aSmrg /* libfont interface expects ImageRectMin glyphs */ 173223a0898aSmrg format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; 173323a0898aSmrg 173423a0898aSmrg *alias = (char *) 0; 173523a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 173623a0898aSmrg { 173723a0898aSmrg if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) 173823a0898aSmrg { 173923a0898aSmrg err = blockrec->errcode; 174023a0898aSmrg if (err == StillWorking) 174123a0898aSmrg return Suspended; 174223a0898aSmrg 174323a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 174423a0898aSmrg if (err == Successful) 174523a0898aSmrg *ppfont = bfont->pfont; 174623a0898aSmrg else 174723a0898aSmrg fs_cleanup_bfont (bfont); 174823a0898aSmrg _fs_remove_block_rec (conn, blockrec); 174923a0898aSmrg return err; 175023a0898aSmrg } 175123a0898aSmrg } 175223a0898aSmrg return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, 175323a0898aSmrg id, ppfont); 175423a0898aSmrg} 175523a0898aSmrg 175623a0898aSmrg/* ARGSUSED */ 175723a0898aSmrgstatic int 175823a0898aSmrgfs_send_close_font(FontPathElementPtr fpe, Font id) 175923a0898aSmrg{ 176023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 176123a0898aSmrg fsCloseReq req; 176223a0898aSmrg 176323a0898aSmrg if (conn->blockState & FS_GIVE_UP) 176423a0898aSmrg return Successful; 176523a0898aSmrg /* tell the font server to close the font */ 176623a0898aSmrg req.reqType = FS_CloseFont; 176723a0898aSmrg req.length = SIZEOF(fsCloseReq) >> 2; 176823a0898aSmrg req.id = id; 176923a0898aSmrg _fs_add_req_log(conn, FS_CloseFont); 177023a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); 177123a0898aSmrg 177223a0898aSmrg return Successful; 177323a0898aSmrg} 177423a0898aSmrg 177523a0898aSmrg/* ARGSUSED */ 177623a0898aSmrgstatic void 177723a0898aSmrgfs_close_font(FontPathElementPtr fpe, FontPtr pfont) 177823a0898aSmrg{ 177923a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; 178023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 178123a0898aSmrg 178223a0898aSmrg if (conn->generation == fsd->generation) 178323a0898aSmrg fs_send_close_font(fpe, fsd->fontid); 178423a0898aSmrg 178523a0898aSmrg#ifdef DEBUG 178623a0898aSmrg { 178723a0898aSmrg FSBlockDataPtr blockrec; 178823a0898aSmrg FSBlockedFontPtr bfont; 178923a0898aSmrg 179023a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 179123a0898aSmrg { 179223a0898aSmrg if (blockrec->type == FS_OPEN_FONT) 179323a0898aSmrg { 179423a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 179523a0898aSmrg if (bfont->pfont == pfont) 179623a0898aSmrg fprintf (stderr, "closing font which hasn't been opened\n"); 179723a0898aSmrg } 179823a0898aSmrg } 179923a0898aSmrg } 180023a0898aSmrg#endif 180123a0898aSmrg (*pfont->unload_font) (pfont); 180223a0898aSmrg} 180323a0898aSmrg 180423a0898aSmrgstatic int 180523a0898aSmrgfs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 180623a0898aSmrg{ 180723a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; 180823a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 180923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 181023a0898aSmrg FontPtr pfont = bglyph->pfont; 181123a0898aSmrg /* works for either blocked font 181223a0898aSmrg or glyph rec... pfont is at 181323a0898aSmrg the very beginning of both 181423a0898aSmrg blockrec->data structures */ 181523a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); 181623a0898aSmrg FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; 181723a0898aSmrg FontInfoPtr pfi = &pfont->info; 181823a0898aSmrg fsQueryXBitmaps16Reply *rep; 181923a0898aSmrg char *buf; 182023a0898aSmrg fsOffset32 *ppbits; 182123a0898aSmrg fsOffset32 local_off; 182223a0898aSmrg char *off_adr; 182323a0898aSmrg pointer pbitmaps; 182423a0898aSmrg char *bits, *allbits; 182523a0898aSmrg#ifdef DEBUG 182623a0898aSmrg char *origallbits; 182723a0898aSmrg#endif 182823a0898aSmrg int i, 182923a0898aSmrg err; 183023a0898aSmrg int nranges = 0; 183123a0898aSmrg int ret; 183223a0898aSmrg fsRange *nextrange = 0; 183323a0898aSmrg unsigned long minchar, maxchar; 183423a0898aSmrg 183523a0898aSmrg rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); 183623a0898aSmrg if (!rep || rep->type == FS_Error) 183723a0898aSmrg { 183823a0898aSmrg if (ret == FSIO_BLOCK) 183923a0898aSmrg return StillWorking; 184023a0898aSmrg if (rep) 184123a0898aSmrg _fs_done_read (conn, rep->length << 2); 184223a0898aSmrg err = AllocError; 184323a0898aSmrg goto bail; 184423a0898aSmrg } 184523a0898aSmrg 184623a0898aSmrg buf = (char *) rep; 184723a0898aSmrg buf += SIZEOF (fsQueryXBitmaps16Reply); 184823a0898aSmrg 184923a0898aSmrg ppbits = (fsOffset32 *) buf; 185023a0898aSmrg buf += SIZEOF (fsOffset32) * (rep->num_chars); 185123a0898aSmrg 185223a0898aSmrg pbitmaps = (pointer ) buf; 185323a0898aSmrg 185423a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 185523a0898aSmrg { 185623a0898aSmrg nranges = bglyph->num_expected_ranges; 185723a0898aSmrg nextrange = bglyph->expected_ranges; 185823a0898aSmrg } 185923a0898aSmrg 186023a0898aSmrg /* place the incoming glyphs */ 186123a0898aSmrg if (nranges) 186223a0898aSmrg { 186323a0898aSmrg /* We're operating under the assumption that the ranges 186423a0898aSmrg requested in the LoadGlyphs call were all legal for this 186523a0898aSmrg font, and that individual ranges do not cover multiple 186623a0898aSmrg rows... fs_build_range() is designed to ensure this. */ 186723a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 186823a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 186923a0898aSmrg nextrange->min_char_low - pfi->firstCol; 187023a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 187123a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 187223a0898aSmrg nextrange->max_char_low - pfi->firstCol; 187323a0898aSmrg nextrange++; 187423a0898aSmrg } 187523a0898aSmrg else 187623a0898aSmrg { 187723a0898aSmrg minchar = 0; 187823a0898aSmrg maxchar = rep->num_chars; 187923a0898aSmrg } 188023a0898aSmrg 188123a0898aSmrg off_adr = (char *)ppbits; 188223a0898aSmrg 188323a0898aSmrg allbits = fs_alloc_glyphs (pfont, rep->nbytes); 188423a0898aSmrg 188523a0898aSmrg if (!allbits) 188623a0898aSmrg { 188723a0898aSmrg err = AllocError; 188823a0898aSmrg goto bail; 188923a0898aSmrg } 189023a0898aSmrg 189123a0898aSmrg#ifdef DEBUG 189223a0898aSmrg origallbits = allbits; 189323a0898aSmrg fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", 189423a0898aSmrg (int) rep->num_chars, (int) rep->nbytes, fsd->name); 189523a0898aSmrg#endif 189623a0898aSmrg 189723a0898aSmrg for (i = 0; i < rep->num_chars; i++) 189823a0898aSmrg { 189923a0898aSmrg memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ 190023a0898aSmrg if (blockrec->type == FS_OPEN_FONT || 190123a0898aSmrg fsdata->encoding[minchar].bits == &_fs_glyph_requested) 190223a0898aSmrg { 190323a0898aSmrg /* 190423a0898aSmrg * Broken X font server returns bits for missing characters 190523a0898aSmrg * when font is padded 190623a0898aSmrg */ 190723a0898aSmrg if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) 190823a0898aSmrg { 190923a0898aSmrg if (local_off.length) 191023a0898aSmrg { 191123a0898aSmrg bits = allbits; 191223a0898aSmrg allbits += local_off.length; 191323a0898aSmrg memcpy(bits, (char *)pbitmaps + local_off.position, 191423a0898aSmrg local_off.length); 191523a0898aSmrg } 191623a0898aSmrg else 191723a0898aSmrg bits = &_fs_glyph_zero_length; 191823a0898aSmrg } 191923a0898aSmrg else 192023a0898aSmrg bits = 0; 192123a0898aSmrg if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) 192223a0898aSmrg fsd->glyphs_to_get--; 192323a0898aSmrg fsdata->encoding[minchar].bits = bits; 192423a0898aSmrg } 192523a0898aSmrg if (minchar++ == maxchar) 192623a0898aSmrg { 192723a0898aSmrg if (!--nranges) break; 192823a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 192923a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 193023a0898aSmrg nextrange->min_char_low - pfi->firstCol; 193123a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 193223a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 193323a0898aSmrg nextrange->max_char_low - pfi->firstCol; 193423a0898aSmrg nextrange++; 193523a0898aSmrg } 193623a0898aSmrg off_adr += SIZEOF(fsOffset32); 193723a0898aSmrg } 193823a0898aSmrg#ifdef DEBUG 193923a0898aSmrg fprintf (stderr, "Used %d bytes instead of %d\n", 194023a0898aSmrg (int) (allbits - origallbits), (int) rep->nbytes); 194123a0898aSmrg#endif 194223a0898aSmrg 194323a0898aSmrg if (blockrec->type == FS_OPEN_FONT) 194423a0898aSmrg { 194523a0898aSmrg fsd->glyphs_to_get = 0; 194623a0898aSmrg bfont->state = FS_DONE_REPLY; 194723a0898aSmrg } 194823a0898aSmrg err = Successful; 194923a0898aSmrg 195023a0898aSmrgbail: 195123a0898aSmrg _fs_done_read (conn, rep->length << 2); 195223a0898aSmrg return err; 195323a0898aSmrg} 195423a0898aSmrg 195523a0898aSmrgstatic int 195623a0898aSmrgfs_send_load_glyphs(pointer client, FontPtr pfont, 195723a0898aSmrg int nranges, fsRange *ranges) 195823a0898aSmrg{ 195923a0898aSmrg FontPathElementPtr fpe = pfont->fpe; 196023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 196123a0898aSmrg FSBlockedGlyphPtr blockedglyph; 196223a0898aSmrg fsQueryXBitmaps16Req req; 196323a0898aSmrg FSBlockDataPtr blockrec; 196423a0898aSmrg 196523a0898aSmrg if (conn->blockState & FS_GIVE_UP) 196623a0898aSmrg return BadCharRange; 196723a0898aSmrg 196823a0898aSmrg /* make a new block record, and add it to the end of the list */ 196923a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); 197023a0898aSmrg if (!blockrec) 197123a0898aSmrg return AllocError; 197223a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 197323a0898aSmrg blockedglyph->pfont = pfont; 197423a0898aSmrg blockedglyph->num_expected_ranges = nranges; 197523a0898aSmrg /* Assumption: it's our job to free ranges */ 197623a0898aSmrg blockedglyph->expected_ranges = ranges; 197723a0898aSmrg blockedglyph->clients_depending = (FSClientsDependingPtr)0; 197823a0898aSmrg 197923a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) 198023a0898aSmrg { 198123a0898aSmrg _fs_pending_reply (conn); 198223a0898aSmrg return Suspended; 198323a0898aSmrg } 198423a0898aSmrg 198523a0898aSmrg /* send the request */ 198623a0898aSmrg req.reqType = FS_QueryXBitmaps16; 198723a0898aSmrg req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; 198823a0898aSmrg req.format = pfont->format; 198923a0898aSmrg if (pfont->info.terminalFont) 199023a0898aSmrg req.format = (req.format & ~(BitmapFormatImageRectMask)) | 199123a0898aSmrg BitmapFormatImageRectMax; 199223a0898aSmrg req.range = TRUE; 199323a0898aSmrg /* each range takes up 4 bytes */ 199423a0898aSmrg req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; 199523a0898aSmrg req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ 199623a0898aSmrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 199723a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); 199823a0898aSmrg 199923a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 200023a0898aSmrg 200123a0898aSmrg /* Send ranges to the server... pack into a char array by hand 200223a0898aSmrg to avoid structure-packing portability problems and to 200323a0898aSmrg handle swapping for version1 protocol */ 200423a0898aSmrg if (nranges) 200523a0898aSmrg { 200623a0898aSmrg#define RANGE_BUFFER_SIZE 64 200723a0898aSmrg#define RANGE_BUFFER_SIZE_MASK 63 200823a0898aSmrg int i; 200923a0898aSmrg char range_buffer[RANGE_BUFFER_SIZE * 4]; 201023a0898aSmrg char *range_buffer_p; 201123a0898aSmrg 201223a0898aSmrg range_buffer_p = range_buffer; 201323a0898aSmrg for (i = 0; i < nranges;) 201423a0898aSmrg { 201523a0898aSmrg if (conn->fsMajorVersion > 1) 201623a0898aSmrg { 201723a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 201823a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 201923a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 202023a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 202123a0898aSmrg } 202223a0898aSmrg else 202323a0898aSmrg { 202423a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 202523a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 202623a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 202723a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 202823a0898aSmrg } 202923a0898aSmrg 203023a0898aSmrg if (!(++i & RANGE_BUFFER_SIZE_MASK)) 203123a0898aSmrg { 203223a0898aSmrg _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); 203323a0898aSmrg range_buffer_p = range_buffer; 203423a0898aSmrg } 203523a0898aSmrg } 203623a0898aSmrg if (i &= RANGE_BUFFER_SIZE_MASK) 203723a0898aSmrg _fs_write(conn, range_buffer, i * 4); 203823a0898aSmrg } 203923a0898aSmrg 204023a0898aSmrg _fs_prepare_for_reply (conn); 204123a0898aSmrg return Suspended; 204223a0898aSmrg} 204323a0898aSmrg 204423a0898aSmrg 204523a0898aSmrgextern pointer serverClient; /* This could be any number that 204623a0898aSmrg doesn't conflict with existing 204723a0898aSmrg client values. */ 204823a0898aSmrg 204923a0898aSmrgstatic int 205023a0898aSmrg_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, 205123a0898aSmrg unsigned int nchars, int item_size, unsigned char *data) 205223a0898aSmrg{ 205323a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 205423a0898aSmrg int nranges = 0; 205523a0898aSmrg fsRange *ranges = NULL; 205623a0898aSmrg int res; 205723a0898aSmrg FSBlockDataPtr blockrec; 205823a0898aSmrg FSBlockedGlyphPtr blockedglyph; 205923a0898aSmrg FSClientsDependingPtr *clients_depending = NULL; 206023a0898aSmrg int err; 206123a0898aSmrg 206223a0898aSmrg /* see if the result is already there */ 206323a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 206423a0898aSmrg { 206523a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 206623a0898aSmrg { 206723a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 206823a0898aSmrg if (blockedglyph->pfont == pfont) 206923a0898aSmrg { 207023a0898aSmrg /* Look for this request */ 207123a0898aSmrg if (blockrec->client == client) 207223a0898aSmrg { 207323a0898aSmrg err = blockrec->errcode; 207423a0898aSmrg if (err == StillWorking) 207523a0898aSmrg return Suspended; 207623a0898aSmrg _fs_signal_clients_depending(&blockedglyph->clients_depending); 207723a0898aSmrg _fs_remove_block_rec(conn, blockrec); 207823a0898aSmrg return err; 207923a0898aSmrg } 208023a0898aSmrg /* We've found an existing LoadGlyphs blockrec for this 208123a0898aSmrg font but for another client. Rather than build a 208223a0898aSmrg blockrec for it now (which entails some complex 208323a0898aSmrg maintenance), we'll add it to a queue of clients to 208423a0898aSmrg be signalled when the existing LoadGlyphs is 208523a0898aSmrg completed. */ 208623a0898aSmrg clients_depending = &blockedglyph->clients_depending; 208723a0898aSmrg break; 208823a0898aSmrg } 208923a0898aSmrg } 209023a0898aSmrg else if (blockrec->type == FS_OPEN_FONT) 209123a0898aSmrg { 209223a0898aSmrg FSBlockedFontPtr bfont; 209323a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 209423a0898aSmrg if (bfont->pfont == pfont) 209523a0898aSmrg { 209623a0898aSmrg /* 209723a0898aSmrg * An OpenFont is pending for this font, this must 209823a0898aSmrg * be from a reopen attempt, so finish the open 209923a0898aSmrg * attempt and retry the LoadGlyphs 210023a0898aSmrg */ 210123a0898aSmrg if (blockrec->client == client) 210223a0898aSmrg { 210323a0898aSmrg err = blockrec->errcode; 210423a0898aSmrg if (err == StillWorking) 210523a0898aSmrg return Suspended; 210623a0898aSmrg 210723a0898aSmrg _fs_signal_clients_depending(&bfont->clients_depending); 210823a0898aSmrg _fs_remove_block_rec(conn, blockrec); 210923a0898aSmrg if (err != Successful) 211023a0898aSmrg return err; 211123a0898aSmrg break; 211223a0898aSmrg } 211323a0898aSmrg /* We've found an existing OpenFont blockrec for this 211423a0898aSmrg font but for another client. Rather than build a 211523a0898aSmrg blockrec for it now (which entails some complex 211623a0898aSmrg maintenance), we'll add it to a queue of clients to 211723a0898aSmrg be signalled when the existing OpenFont is 211823a0898aSmrg completed. */ 211923a0898aSmrg if (blockrec->errcode == StillWorking) 212023a0898aSmrg { 212123a0898aSmrg clients_depending = &bfont->clients_depending; 212223a0898aSmrg break; 212323a0898aSmrg } 212423a0898aSmrg } 212523a0898aSmrg } 212623a0898aSmrg } 212723a0898aSmrg 212823a0898aSmrg /* 212923a0898aSmrg * see if the desired glyphs already exist, and return Successful if they 213023a0898aSmrg * do, otherwise build up character range/character string 213123a0898aSmrg */ 213223a0898aSmrg res = fs_build_range(pfont, range_flag, nchars, item_size, data, 213323a0898aSmrg &nranges, &ranges); 213423a0898aSmrg 213523a0898aSmrg switch (res) 213623a0898aSmrg { 213723a0898aSmrg case AccessDone: 213823a0898aSmrg return Successful; 213923a0898aSmrg 214023a0898aSmrg case Successful: 214123a0898aSmrg break; 214223a0898aSmrg 214323a0898aSmrg default: 214423a0898aSmrg return res; 214523a0898aSmrg } 214623a0898aSmrg 214723a0898aSmrg /* 214823a0898aSmrg * If clients_depending is not null, this request must wait for 214923a0898aSmrg * some prior request(s) to complete. 215023a0898aSmrg */ 215123a0898aSmrg if (clients_depending) 215223a0898aSmrg { 215323a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 215423a0898aSmrg clean up the damage (if any) caused by the fs_build_range() 215523a0898aSmrg call. */ 215623a0898aSmrg if (nranges) 215723a0898aSmrg { 215823a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 215923a0898aSmrg xfree(ranges); 216023a0898aSmrg } 216123a0898aSmrg return _fs_add_clients_depending(clients_depending, client); 216223a0898aSmrg } 216323a0898aSmrg 216423a0898aSmrg /* 216523a0898aSmrg * If fsd->generation != conn->generation, the font has been closed 216623a0898aSmrg * due to a lost connection. We will reopen it, which will result 216723a0898aSmrg * in one of three things happening: 216823a0898aSmrg * 1) The open will succeed and obtain the same font. Life 216923a0898aSmrg * is wonderful. 217023a0898aSmrg * 2) The open will fail. There is code above to recognize this 217123a0898aSmrg * and flunk the LoadGlyphs request. The client might not be 217223a0898aSmrg * thrilled. 217323a0898aSmrg * 3) Worst case: the open will succeed but the font we open will 217423a0898aSmrg * be different. The fs_read_query_info() procedure attempts 217523a0898aSmrg * to detect this by comparing the existing metrics and 217623a0898aSmrg * properties against those of the reopened font... if they 217723a0898aSmrg * don't match, we flunk the reopen, which eventually results 217823a0898aSmrg * in flunking the LoadGlyphs request. We could go a step 217923a0898aSmrg * further and compare the extents, but this should be 218023a0898aSmrg * sufficient. 218123a0898aSmrg */ 218223a0898aSmrg if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) 218323a0898aSmrg { 218423a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 218523a0898aSmrg clean up the damage caused by the fs_build_range() call. */ 218623a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 218723a0898aSmrg xfree(ranges); 218823a0898aSmrg 218923a0898aSmrg /* Now try to reopen the font. */ 219023a0898aSmrg return fs_send_open_font(client, pfont->fpe, 219123a0898aSmrg (Mask)FontReopen, (char *)0, 0, 219223a0898aSmrg (fsBitmapFormat)0, (fsBitmapFormatMask)0, 219323a0898aSmrg (XID)0, &pfont); 219423a0898aSmrg } 219523a0898aSmrg 219623a0898aSmrg return fs_send_load_glyphs(client, pfont, nranges, ranges); 219723a0898aSmrg} 219823a0898aSmrg 219923a0898aSmrgint 220023a0898aSmrgfs_load_all_glyphs(FontPtr pfont) 220123a0898aSmrg{ 220223a0898aSmrg int err; 220323a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 220423a0898aSmrg 220523a0898aSmrg /* 220623a0898aSmrg * The purpose of this procedure is to load all glyphs in the event 220723a0898aSmrg * that we're dealing with someone who doesn't understand the finer 220823a0898aSmrg * points of glyph caching... it is called from _fs_get_glyphs() if 220923a0898aSmrg * the latter is called to get glyphs that have not yet been loaded. 221023a0898aSmrg * We assume that the caller will not know how to handle a return 221123a0898aSmrg * value of Suspended (usually the case for a GetGlyphs() caller), 221223a0898aSmrg * so this procedure hangs around, freezing the server, for the 221323a0898aSmrg * request to complete. This is an unpleasant kluge called to 221423a0898aSmrg * perform an unpleasant job that, we hope, will never be required. 221523a0898aSmrg */ 221623a0898aSmrg 221723a0898aSmrg while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == 221823a0898aSmrg Suspended) 221923a0898aSmrg { 222023a0898aSmrg if (fs_await_reply (conn) != FSIO_READY) 222123a0898aSmrg { 222223a0898aSmrg /* Get rid of blockrec */ 222323a0898aSmrg fs_client_died(serverClient, pfont->fpe); 222423a0898aSmrg err = BadCharRange; 222523a0898aSmrg break; 222623a0898aSmrg } 222723a0898aSmrg fs_read_reply (pfont->fpe, serverClient); 222823a0898aSmrg } 222923a0898aSmrg return err; 223023a0898aSmrg} 223123a0898aSmrg 223223a0898aSmrgstatic int 223323a0898aSmrgfs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 223423a0898aSmrg{ 223523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 223623a0898aSmrg FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; 223723a0898aSmrg fsListFontsReply *rep; 223823a0898aSmrg char *data; 223923a0898aSmrg int length, 224023a0898aSmrg i, 224123a0898aSmrg ret; 224223a0898aSmrg int err; 224323a0898aSmrg 224423a0898aSmrg rep = (fsListFontsReply *) fs_get_reply (conn, &ret); 224523a0898aSmrg if (!rep || rep->type == FS_Error) 224623a0898aSmrg { 224723a0898aSmrg if (ret == FSIO_BLOCK) 224823a0898aSmrg return StillWorking; 224923a0898aSmrg if (rep) 225023a0898aSmrg _fs_done_read (conn, rep->length << 2); 225123a0898aSmrg return AllocError; 225223a0898aSmrg } 225323a0898aSmrg data = (char *) rep + SIZEOF (fsListFontsReply); 225423a0898aSmrg 225523a0898aSmrg err = Successful; 225623a0898aSmrg /* copy data into FontPathRecord */ 225723a0898aSmrg for (i = 0; i < rep->nFonts; i++) 225823a0898aSmrg { 225923a0898aSmrg length = *(unsigned char *)data++; 226023a0898aSmrg err = AddFontNamesName(blist->names, data, length); 226123a0898aSmrg if (err != Successful) 226223a0898aSmrg break; 226323a0898aSmrg data += length; 226423a0898aSmrg } 226523a0898aSmrg _fs_done_read (conn, rep->length << 2); 226623a0898aSmrg return err; 226723a0898aSmrg} 226823a0898aSmrg 226923a0898aSmrgstatic int 227023a0898aSmrgfs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, 227123a0898aSmrg int patlen, int maxnames, FontNamesPtr newnames) 227223a0898aSmrg{ 227323a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 227423a0898aSmrg FSBlockDataPtr blockrec; 227523a0898aSmrg FSBlockedListPtr blockedlist; 227623a0898aSmrg fsListFontsReq req; 227723a0898aSmrg 227823a0898aSmrg if (conn->blockState & FS_GIVE_UP) 227923a0898aSmrg return BadFontName; 228023a0898aSmrg 228123a0898aSmrg /* make a new block record, and add it to the end of the list */ 228223a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); 228323a0898aSmrg if (!blockrec) 228423a0898aSmrg return AllocError; 228523a0898aSmrg blockedlist = (FSBlockedListPtr) blockrec->data; 228623a0898aSmrg blockedlist->names = newnames; 228723a0898aSmrg 228823a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 228923a0898aSmrg { 229023a0898aSmrg _fs_pending_reply (conn); 229123a0898aSmrg return Suspended; 229223a0898aSmrg } 229323a0898aSmrg 229423a0898aSmrg _fs_client_access (conn, client, FALSE); 229523a0898aSmrg _fs_client_resolution(conn); 229623a0898aSmrg 229723a0898aSmrg /* send the request */ 229823a0898aSmrg req.reqType = FS_ListFonts; 229923a0898aSmrg req.maxNames = maxnames; 230023a0898aSmrg req.nbytes = patlen; 230123a0898aSmrg req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; 230223a0898aSmrg _fs_add_req_log(conn, FS_ListFonts); 230323a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); 230423a0898aSmrg _fs_write_pad(conn, (char *) pattern, patlen); 230523a0898aSmrg 230623a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 230723a0898aSmrg 230823a0898aSmrg#ifdef NCD 230923a0898aSmrg if (configData.ExtendedFontDiags) { 231023a0898aSmrg char buf[256]; 231123a0898aSmrg 231223a0898aSmrg memcpy(buf, pattern, MIN(256, patlen)); 231323a0898aSmrg buf[MIN(256, patlen)] = '\0'; 231423a0898aSmrg printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", 231523a0898aSmrg buf, fpe->name); 231623a0898aSmrg } 231723a0898aSmrg#endif 231823a0898aSmrg 231923a0898aSmrg _fs_prepare_for_reply (conn); 232023a0898aSmrg return Suspended; 232123a0898aSmrg} 232223a0898aSmrg 232323a0898aSmrgstatic int 232423a0898aSmrgfs_list_fonts(pointer client, FontPathElementPtr fpe, 232523a0898aSmrg char *pattern, int patlen, int maxnames, FontNamesPtr newnames) 232623a0898aSmrg{ 232723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 232823a0898aSmrg FSBlockDataPtr blockrec; 232923a0898aSmrg int err; 233023a0898aSmrg 233123a0898aSmrg /* see if the result is already there */ 233223a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 233323a0898aSmrg { 233423a0898aSmrg if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) 233523a0898aSmrg { 233623a0898aSmrg err = blockrec->errcode; 233723a0898aSmrg if (err == StillWorking) 233823a0898aSmrg return Suspended; 233923a0898aSmrg _fs_remove_block_rec(conn, blockrec); 234023a0898aSmrg return err; 234123a0898aSmrg } 234223a0898aSmrg } 234323a0898aSmrg 234423a0898aSmrg /* didn't find waiting record, so send a new one */ 234523a0898aSmrg return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); 234623a0898aSmrg} 234723a0898aSmrg 234823a0898aSmrg/* 234923a0898aSmrg * Read a single list info reply and restart for the next reply 235023a0898aSmrg */ 235123a0898aSmrgstatic int 235223a0898aSmrgfs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 235323a0898aSmrg{ 235423a0898aSmrg FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; 235523a0898aSmrg fsListFontsWithXInfoReply *rep; 235623a0898aSmrg char *buf; 235723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 235823a0898aSmrg fsPropInfo *pi; 235923a0898aSmrg fsPropOffset *po; 236023a0898aSmrg pointer pd; 236123a0898aSmrg int ret; 236223a0898aSmrg int err; 236323a0898aSmrg 236423a0898aSmrg /* clean up anything from the last trip */ 236523a0898aSmrg _fs_free_props (&binfo->info); 236623a0898aSmrg 236723a0898aSmrg rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); 236823a0898aSmrg if (!rep || rep->type == FS_Error) 236923a0898aSmrg { 237023a0898aSmrg if (ret == FSIO_BLOCK) 237123a0898aSmrg return StillWorking; 237223a0898aSmrg binfo->status = FS_LFWI_FINISHED; 237323a0898aSmrg err = AllocError; 237423a0898aSmrg goto done; 237523a0898aSmrg } 237623a0898aSmrg /* 237723a0898aSmrg * Normal termination -- the list ends with a name of length 0 237823a0898aSmrg */ 237923a0898aSmrg if (rep->nameLength == 0) 238023a0898aSmrg { 238123a0898aSmrg#ifdef DEBUG 238223a0898aSmrg fprintf (stderr, "fs_read_list_info done\n"); 238323a0898aSmrg#endif 238423a0898aSmrg binfo->status = FS_LFWI_FINISHED; 238523a0898aSmrg err = BadFontName; 238623a0898aSmrg goto done; 238723a0898aSmrg } 238823a0898aSmrg 238923a0898aSmrg buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); 239023a0898aSmrg 239123a0898aSmrg /* 239223a0898aSmrg * The original FS implementation didn't match 239323a0898aSmrg * the spec, version 1 was respecified to match the FS. 239423a0898aSmrg * Version 2 matches the original intent 239523a0898aSmrg */ 239623a0898aSmrg if (conn->fsMajorVersion <= 1) 239723a0898aSmrg { 239823a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 239923a0898aSmrg buf += _fs_pad_length (rep->nameLength); 240023a0898aSmrg } 240123a0898aSmrg pi = (fsPropInfo *) buf; 240223a0898aSmrg buf += SIZEOF (fsPropInfo); 240323a0898aSmrg po = (fsPropOffset *) buf; 240423a0898aSmrg buf += pi->num_offsets * SIZEOF (fsPropOffset); 240523a0898aSmrg pd = (pointer) buf; 240623a0898aSmrg buf += pi->data_len; 240723a0898aSmrg if (conn->fsMajorVersion > 1) 240823a0898aSmrg { 240923a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 241023a0898aSmrg buf += _fs_pad_length (rep->nameLength); 241123a0898aSmrg } 241223a0898aSmrg 241323a0898aSmrg#ifdef DEBUG 241423a0898aSmrg binfo->name[rep->nameLength] = '\0'; 241523a0898aSmrg fprintf (stderr, "fs_read_list_info %s\n", binfo->name); 241623a0898aSmrg#endif 241723a0898aSmrg err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); 241823a0898aSmrg if (err != Successful) 241923a0898aSmrg { 242023a0898aSmrg binfo->status = FS_LFWI_FINISHED; 242123a0898aSmrg goto done; 242223a0898aSmrg } 242323a0898aSmrg binfo->namelen = rep->nameLength; 242423a0898aSmrg binfo->remaining = rep->nReplies; 242523a0898aSmrg 242623a0898aSmrg binfo->status = FS_LFWI_REPLY; 242723a0898aSmrg 242823a0898aSmrg /* disable this font server until we've processed this response */ 242923a0898aSmrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 243023a0898aSmrg FD_CLR(conn->fs_fd, &_fs_fd_mask); 243123a0898aSmrgdone: 243223a0898aSmrg _fs_done_read (conn, rep->length << 2); 243323a0898aSmrg return err; 243423a0898aSmrg} 243523a0898aSmrg 243623a0898aSmrg/* ARGSUSED */ 243723a0898aSmrgstatic int 243823a0898aSmrgfs_start_list_with_info(pointer client, FontPathElementPtr fpe, 243923a0898aSmrg char *pattern, int len, int maxnames, pointer *pdata) 244023a0898aSmrg{ 244123a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 244223a0898aSmrg FSBlockDataPtr blockrec; 244323a0898aSmrg FSBlockedListInfoPtr binfo; 244423a0898aSmrg fsListFontsWithXInfoReq req; 244523a0898aSmrg 244623a0898aSmrg if (conn->blockState & FS_GIVE_UP) 244723a0898aSmrg return BadFontName; 244823a0898aSmrg 244923a0898aSmrg /* make a new block record, and add it to the end of the list */ 245023a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); 245123a0898aSmrg if (!blockrec) 245223a0898aSmrg return AllocError; 245323a0898aSmrg 245423a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 245523a0898aSmrg bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); 245623a0898aSmrg binfo->status = FS_LFWI_WAITING; 245723a0898aSmrg 245823a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 245923a0898aSmrg { 246023a0898aSmrg _fs_pending_reply (conn); 246123a0898aSmrg return Suspended; 246223a0898aSmrg } 246323a0898aSmrg 246423a0898aSmrg _fs_client_access (conn, client, FALSE); 246523a0898aSmrg _fs_client_resolution(conn); 246623a0898aSmrg 246723a0898aSmrg /* send the request */ 246823a0898aSmrg req.reqType = FS_ListFontsWithXInfo; 246923a0898aSmrg req.maxNames = maxnames; 247023a0898aSmrg req.nbytes = len; 247123a0898aSmrg req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; 247223a0898aSmrg _fs_add_req_log(conn, FS_ListFontsWithXInfo); 247323a0898aSmrg (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); 247423a0898aSmrg (void) _fs_write_pad(conn, pattern, len); 247523a0898aSmrg 247623a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 247723a0898aSmrg 247823a0898aSmrg#ifdef NCD 247923a0898aSmrg if (configData.ExtendedFontDiags) { 248023a0898aSmrg char buf[256]; 248123a0898aSmrg 248223a0898aSmrg memcpy(buf, pattern, MIN(256, len)); 248323a0898aSmrg buf[MIN(256, len)] = '\0'; 248423a0898aSmrg printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", 248523a0898aSmrg buf, fpe->name); 248623a0898aSmrg } 248723a0898aSmrg#endif 248823a0898aSmrg 248923a0898aSmrg _fs_prepare_for_reply (conn); 249023a0898aSmrg return Successful; 249123a0898aSmrg} 249223a0898aSmrg 249323a0898aSmrg/* ARGSUSED */ 249423a0898aSmrgstatic int 249523a0898aSmrgfs_next_list_with_info(pointer client, FontPathElementPtr fpe, 249623a0898aSmrg char **namep, int *namelenp, 249723a0898aSmrg FontInfoPtr *pFontInfo, int *numFonts, 249823a0898aSmrg pointer private) 249923a0898aSmrg{ 250023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 250123a0898aSmrg FSBlockDataPtr blockrec; 250223a0898aSmrg FSBlockedListInfoPtr binfo; 250323a0898aSmrg int err; 250423a0898aSmrg 250523a0898aSmrg /* see if the result is already there */ 250623a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 250723a0898aSmrg if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) 250823a0898aSmrg break; 250923a0898aSmrg 251023a0898aSmrg if (!blockrec) 251123a0898aSmrg { 251223a0898aSmrg /* The only good reason for not finding a blockrec would be if 251323a0898aSmrg disconnect/reconnect to the font server wiped it out and the 251423a0898aSmrg code that called us didn't do the right thing to create 251523a0898aSmrg another one. Under those circumstances, we need to return an 251623a0898aSmrg error to prevent that code from attempting to interpret the 251723a0898aSmrg information we don't return. */ 251823a0898aSmrg return BadFontName; 251923a0898aSmrg } 252023a0898aSmrg 252123a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 252223a0898aSmrg 252323a0898aSmrg if (binfo->status == FS_LFWI_WAITING) 252423a0898aSmrg return Suspended; 252523a0898aSmrg 252623a0898aSmrg *namep = binfo->name; 252723a0898aSmrg *namelenp = binfo->namelen; 252823a0898aSmrg *pFontInfo = &binfo->info; 252923a0898aSmrg *numFonts = binfo->remaining; 253023a0898aSmrg 253123a0898aSmrg /* Restart reply processing from this font server */ 253223a0898aSmrg FD_SET(conn->fs_fd, &_fs_fd_mask); 253323a0898aSmrg if (fs_reply_ready (conn)) 253423a0898aSmrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 253523a0898aSmrg 253623a0898aSmrg err = blockrec->errcode; 253723a0898aSmrg switch (binfo->status) { 253823a0898aSmrg case FS_LFWI_FINISHED: 253923a0898aSmrg _fs_remove_block_rec(conn, blockrec); 254023a0898aSmrg break; 254123a0898aSmrg case FS_LFWI_REPLY: 254223a0898aSmrg binfo->status = FS_LFWI_WAITING; 254323a0898aSmrg blockrec->errcode = StillWorking; 254423a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 254523a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 254623a0898aSmrg break; 254723a0898aSmrg } 254823a0898aSmrg 254923a0898aSmrg return err; 255023a0898aSmrg} 255123a0898aSmrg 255223a0898aSmrg/* 255323a0898aSmrg * Called when client exits 255423a0898aSmrg */ 255523a0898aSmrg 255623a0898aSmrgstatic void 255723a0898aSmrgfs_client_died(pointer client, FontPathElementPtr fpe) 255823a0898aSmrg{ 255923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 256023a0898aSmrg FSBlockDataPtr blockrec, 256123a0898aSmrg depending; 256223a0898aSmrg FSClientPtr *prev, cur; 256323a0898aSmrg fsFreeACReq freeac; 256423a0898aSmrg 256523a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 256623a0898aSmrg { 256723a0898aSmrg if (cur->client == client) { 256823a0898aSmrg freeac.reqType = FS_FreeAC; 256923a0898aSmrg freeac.id = cur->acid; 257023a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 257123a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 257223a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 257323a0898aSmrg *prev = cur->next; 257423a0898aSmrg xfree (cur); 257523a0898aSmrg break; 257623a0898aSmrg } 257723a0898aSmrg } 257823a0898aSmrg /* find a pending requests */ 257923a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 258023a0898aSmrg if (blockrec->client == client) 258123a0898aSmrg break; 258223a0898aSmrg 258323a0898aSmrg if (!blockrec) 258423a0898aSmrg return; 258523a0898aSmrg 258623a0898aSmrg /* replace the client pointers in this block rec with the chained one */ 258723a0898aSmrg if ((depending = blockrec->depending)) 258823a0898aSmrg { 258923a0898aSmrg blockrec->client = depending->client; 259023a0898aSmrg blockrec->depending = depending->depending; 259123a0898aSmrg blockrec = depending; 259223a0898aSmrg } 259323a0898aSmrg fs_abort_blockrec(conn, blockrec); 259423a0898aSmrg} 259523a0898aSmrg 259623a0898aSmrgstatic void 259723a0898aSmrg_fs_client_access (FSFpePtr conn, pointer client, Bool sync) 259823a0898aSmrg{ 259923a0898aSmrg FSClientPtr *prev, cur; 260023a0898aSmrg fsCreateACReq crac; 260123a0898aSmrg fsSetAuthorizationReq setac; 260223a0898aSmrg char *authorizations; 260323a0898aSmrg int authlen; 260423a0898aSmrg Bool new_cur = FALSE; 260523a0898aSmrg 260623a0898aSmrg#ifdef DEBUG 260723a0898aSmrg if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) 260823a0898aSmrg { 260923a0898aSmrg fprintf (stderr, "Sending requests without a connection\n"); 261023a0898aSmrg } 261123a0898aSmrg#endif 261223a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 261323a0898aSmrg { 261423a0898aSmrg if (cur->client == client) 261523a0898aSmrg { 261623a0898aSmrg if (prev != &conn->clients) 261723a0898aSmrg { 261823a0898aSmrg *prev = cur->next; 261923a0898aSmrg cur->next = conn->clients; 262023a0898aSmrg conn->clients = cur; 262123a0898aSmrg } 262223a0898aSmrg break; 262323a0898aSmrg } 262423a0898aSmrg } 262523a0898aSmrg if (!cur) 262623a0898aSmrg { 262723a0898aSmrg cur = (FSClientPtr) xalloc (sizeof (FSClientRec)); 262823a0898aSmrg if (!cur) 262923a0898aSmrg return; 263023a0898aSmrg cur->client = client; 263123a0898aSmrg cur->next = conn->clients; 263223a0898aSmrg conn->clients = cur; 263323a0898aSmrg cur->acid = GetNewFontClientID (); 263423a0898aSmrg new_cur = TRUE; 263523a0898aSmrg } 263623a0898aSmrg if (new_cur || cur->auth_generation != client_auth_generation(client)) 263723a0898aSmrg { 263823a0898aSmrg if (!new_cur) 263923a0898aSmrg { 264023a0898aSmrg fsFreeACReq freeac; 264123a0898aSmrg freeac.reqType = FS_FreeAC; 264223a0898aSmrg freeac.id = cur->acid; 264323a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 264423a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 264523a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 264623a0898aSmrg } 264723a0898aSmrg crac.reqType = FS_CreateAC; 264823a0898aSmrg crac.num_auths = set_font_authorizations(&authorizations, &authlen, 264923a0898aSmrg client); 265023a0898aSmrg authlen = crac.num_auths ? (authlen + 3) & ~0x3 : 0; 265123a0898aSmrg crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; 265223a0898aSmrg crac.acid = cur->acid; 265323a0898aSmrg _fs_add_req_log(conn, FS_CreateAC); 265423a0898aSmrg _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); 265523a0898aSmrg _fs_write(conn, authorizations, authlen); 265623a0898aSmrg /* ignore reply; we don't even care about it */ 265723a0898aSmrg conn->curacid = 0; 265823a0898aSmrg cur->auth_generation = client_auth_generation(client); 265923a0898aSmrg } 266023a0898aSmrg if (conn->curacid != cur->acid) 266123a0898aSmrg { 266223a0898aSmrg setac.reqType = FS_SetAuthorization; 266323a0898aSmrg setac.length = sizeof (fsSetAuthorizationReq) >> 2; 266423a0898aSmrg setac.id = cur->acid; 266523a0898aSmrg _fs_add_req_log(conn, FS_SetAuthorization); 266623a0898aSmrg _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); 266723a0898aSmrg conn->curacid = cur->acid; 266823a0898aSmrg } 266923a0898aSmrg} 267023a0898aSmrg 267123a0898aSmrg/* 267223a0898aSmrg * Poll a pending connect 267323a0898aSmrg */ 267423a0898aSmrg 267523a0898aSmrgstatic int 267623a0898aSmrg_fs_check_connect (FSFpePtr conn) 267723a0898aSmrg{ 267823a0898aSmrg int ret; 267923a0898aSmrg 268023a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 0); 268123a0898aSmrg switch (ret) { 268223a0898aSmrg case FSIO_READY: 268323a0898aSmrg conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); 268423a0898aSmrg FD_SET (conn->fs_fd, &_fs_fd_mask); 268523a0898aSmrg break; 268623a0898aSmrg case FSIO_BLOCK: 268723a0898aSmrg break; 268823a0898aSmrg } 268923a0898aSmrg return ret; 269023a0898aSmrg} 269123a0898aSmrg 269223a0898aSmrg/* 269323a0898aSmrg * Return an FSIO status while waiting for the completed connection 269423a0898aSmrg * reply to arrive 269523a0898aSmrg */ 269623a0898aSmrg 269723a0898aSmrgstatic fsConnSetup * 269823a0898aSmrg_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) 269923a0898aSmrg{ 270023a0898aSmrg int ret; 270123a0898aSmrg char *data; 270223a0898aSmrg int headlen; 270323a0898aSmrg int len; 270423a0898aSmrg fsConnSetup *setup; 270523a0898aSmrg fsConnSetupAccept *accept; 270623a0898aSmrg 270723a0898aSmrg ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); 270823a0898aSmrg if (ret != FSIO_READY) 270923a0898aSmrg { 271023a0898aSmrg *error = ret; 271123a0898aSmrg return 0; 271223a0898aSmrg } 271323a0898aSmrg 271423a0898aSmrg setup = (fsConnSetup *) data; 271523a0898aSmrg if (setup->major_version > FS_PROTOCOL) 271623a0898aSmrg { 271723a0898aSmrg *error = FSIO_ERROR; 271823a0898aSmrg return 0; 271923a0898aSmrg } 272023a0898aSmrg 272123a0898aSmrg headlen = (SIZEOF (fsConnSetup) + 272223a0898aSmrg (setup->alternate_len << 2) + 272323a0898aSmrg (setup->auth_len << 2)); 272423a0898aSmrg /* On anything but Success, no extra data is sent */ 272523a0898aSmrg if (setup->status != AuthSuccess) 272623a0898aSmrg { 272723a0898aSmrg len = headlen; 272823a0898aSmrg } 272923a0898aSmrg else 273023a0898aSmrg { 273123a0898aSmrg ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); 273223a0898aSmrg if (ret != FSIO_READY) 273323a0898aSmrg { 273423a0898aSmrg *error = ret; 273523a0898aSmrg return 0; 273623a0898aSmrg } 273723a0898aSmrg setup = (fsConnSetup *) data; 273823a0898aSmrg accept = (fsConnSetupAccept *) (data + headlen); 273923a0898aSmrg len = headlen + (accept->length << 2); 274023a0898aSmrg } 274123a0898aSmrg ret = _fs_start_read (conn, len, &data); 274223a0898aSmrg if (ret != FSIO_READY) 274323a0898aSmrg { 274423a0898aSmrg *error = ret; 274523a0898aSmrg return 0; 274623a0898aSmrg } 274723a0898aSmrg *setup_len = len; 274823a0898aSmrg return (fsConnSetup *) data; 274923a0898aSmrg} 275023a0898aSmrg 275123a0898aSmrgstatic int 275223a0898aSmrg_fs_send_conn_client_prefix (FSFpePtr conn) 275323a0898aSmrg{ 275423a0898aSmrg fsConnClientPrefix req; 275523a0898aSmrg int endian; 275623a0898aSmrg int ret; 275723a0898aSmrg 275823a0898aSmrg /* send setup prefix */ 275923a0898aSmrg endian = 1; 276023a0898aSmrg if (*(char *) &endian) 276123a0898aSmrg req.byteOrder = 'l'; 276223a0898aSmrg else 276323a0898aSmrg req.byteOrder = 'B'; 276423a0898aSmrg 276523a0898aSmrg req.major_version = FS_PROTOCOL; 276623a0898aSmrg req.minor_version = FS_PROTOCOL_MINOR; 276723a0898aSmrg 276823a0898aSmrg/* XXX add some auth info here */ 276923a0898aSmrg req.num_auths = 0; 277023a0898aSmrg req.auth_len = 0; 277123a0898aSmrg ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); 277223a0898aSmrg if (ret != FSIO_READY) 277323a0898aSmrg return FSIO_ERROR; 277423a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 277523a0898aSmrg return ret; 277623a0898aSmrg} 277723a0898aSmrg 277823a0898aSmrgstatic int 277923a0898aSmrg_fs_recv_conn_setup (FSFpePtr conn) 278023a0898aSmrg{ 278123a0898aSmrg int ret = FSIO_ERROR; 278223a0898aSmrg fsConnSetup *setup; 278323a0898aSmrg FSFpeAltPtr alts; 278423a0898aSmrg int i, alt_len; 278523a0898aSmrg int setup_len; 278623a0898aSmrg char *alt_save, *alt_names; 278723a0898aSmrg 278823a0898aSmrg setup = _fs_get_conn_setup (conn, &ret, &setup_len); 278923a0898aSmrg if (!setup) 279023a0898aSmrg return ret; 279123a0898aSmrg conn->current_seq = 0; 279223a0898aSmrg conn->fsMajorVersion = setup->major_version; 279323a0898aSmrg /* 279423a0898aSmrg * Create an alternate list from the initial server, but 279523a0898aSmrg * don't chain looking for alternates. 279623a0898aSmrg */ 279723a0898aSmrg if (conn->alternate == 0) 279823a0898aSmrg { 279923a0898aSmrg /* 280023a0898aSmrg * free any existing alternates list, allowing the list to 280123a0898aSmrg * be updated 280223a0898aSmrg */ 280323a0898aSmrg if (conn->alts) 280423a0898aSmrg { 280523a0898aSmrg xfree (conn->alts); 280623a0898aSmrg conn->alts = 0; 280723a0898aSmrg conn->numAlts = 0; 280823a0898aSmrg } 280923a0898aSmrg if (setup->num_alternates) 281023a0898aSmrg { 281123a0898aSmrg alts = (FSFpeAltPtr) xalloc (setup->num_alternates * 281223a0898aSmrg sizeof (FSFpeAltRec) + 281323a0898aSmrg (setup->alternate_len << 2)); 281423a0898aSmrg if (alts) 281523a0898aSmrg { 281623a0898aSmrg alt_names = (char *) (setup + 1); 281723a0898aSmrg alt_save = (char *) (alts + setup->num_alternates); 281823a0898aSmrg for (i = 0; i < setup->num_alternates; i++) 281923a0898aSmrg { 282023a0898aSmrg alts[i].subset = alt_names[0]; 282123a0898aSmrg alt_len = alt_names[1]; 282223a0898aSmrg alts[i].name = alt_save; 282323a0898aSmrg memcpy (alt_save, alt_names + 2, alt_len); 282423a0898aSmrg alt_save[alt_len] = '\0'; 282523a0898aSmrg alt_save += alt_len + 1; 282623a0898aSmrg alt_names += _fs_pad_length (alt_len + 2); 282723a0898aSmrg } 282823a0898aSmrg conn->numAlts = setup->num_alternates; 282923a0898aSmrg conn->alts = alts; 283023a0898aSmrg } 283123a0898aSmrg } 283223a0898aSmrg } 283323a0898aSmrg _fs_done_read (conn, setup_len); 283423a0898aSmrg if (setup->status != AuthSuccess) 283523a0898aSmrg return FSIO_ERROR; 283623a0898aSmrg return FSIO_READY; 283723a0898aSmrg} 283823a0898aSmrg 283923a0898aSmrgstatic int 284023a0898aSmrg_fs_open_server (FSFpePtr conn) 284123a0898aSmrg{ 284223a0898aSmrg int ret; 284323a0898aSmrg char *servername; 284423a0898aSmrg 284523a0898aSmrg if (conn->alternate == 0) 284623a0898aSmrg servername = conn->servername; 284723a0898aSmrg else 284823a0898aSmrg servername = conn->alts[conn->alternate-1].name; 284923a0898aSmrg conn->trans_conn = _fs_connect (servername, &ret); 285023a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; 285123a0898aSmrg return ret; 285223a0898aSmrg} 285323a0898aSmrg 285423a0898aSmrgstatic char * 285523a0898aSmrg_fs_catalog_name (char *servername) 285623a0898aSmrg{ 285723a0898aSmrg char *sp; 285823a0898aSmrg 285923a0898aSmrg sp = strchr (servername, '/'); 286023a0898aSmrg if (!sp) 286123a0898aSmrg return 0; 286223a0898aSmrg return strrchr (sp + 1, '/'); 286323a0898aSmrg} 286423a0898aSmrg 286523a0898aSmrgstatic int 286623a0898aSmrg_fs_send_init_packets (FSFpePtr conn) 286723a0898aSmrg{ 286823a0898aSmrg fsSetResolutionReq srreq; 286923a0898aSmrg fsSetCataloguesReq screq; 287023a0898aSmrg int num_cats, 287123a0898aSmrg clen; 287223a0898aSmrg char *catalogues; 287323a0898aSmrg char *cat; 287423a0898aSmrg char len; 287523a0898aSmrg char *end; 287623a0898aSmrg int num_res; 287723a0898aSmrg FontResolutionPtr res; 287823a0898aSmrg 287923a0898aSmrg#define CATALOGUE_SEP '+' 288023a0898aSmrg 288123a0898aSmrg res = GetClientResolutions(&num_res); 288223a0898aSmrg if (num_res) 288323a0898aSmrg { 288423a0898aSmrg srreq.reqType = FS_SetResolution; 288523a0898aSmrg srreq.num_resolutions = num_res; 288623a0898aSmrg srreq.length = (SIZEOF(fsSetResolutionReq) + 288723a0898aSmrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 288823a0898aSmrg 288923a0898aSmrg _fs_add_req_log(conn, FS_SetResolution); 289023a0898aSmrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) 289123a0898aSmrg return FSIO_ERROR; 289223a0898aSmrg if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) 289323a0898aSmrg return FSIO_ERROR; 289423a0898aSmrg } 289523a0898aSmrg 289623a0898aSmrg catalogues = 0; 289723a0898aSmrg if (conn->alternate != 0) 289823a0898aSmrg catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); 289923a0898aSmrg if (!catalogues) 290023a0898aSmrg catalogues = _fs_catalog_name (conn->servername); 290123a0898aSmrg 290223a0898aSmrg if (!catalogues) 290323a0898aSmrg { 290423a0898aSmrg conn->has_catalogues = FALSE; 290523a0898aSmrg return FSIO_READY; 290623a0898aSmrg } 290723a0898aSmrg conn->has_catalogues = TRUE; 290823a0898aSmrg 290923a0898aSmrg /* turn cats into counted list */ 291023a0898aSmrg catalogues++; 291123a0898aSmrg 291223a0898aSmrg cat = catalogues; 291323a0898aSmrg num_cats = 0; 291423a0898aSmrg clen = 0; 291523a0898aSmrg while (*cat) 291623a0898aSmrg { 291723a0898aSmrg num_cats++; 291823a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 291923a0898aSmrg if (!end) 292023a0898aSmrg end = cat + strlen (cat); 292123a0898aSmrg clen += (end - cat) + 1; /* length byte + string */ 292223a0898aSmrg cat = end; 292323a0898aSmrg } 292423a0898aSmrg 292523a0898aSmrg screq.reqType = FS_SetCatalogues; 292623a0898aSmrg screq.num_catalogues = num_cats; 292723a0898aSmrg screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; 292823a0898aSmrg 292923a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 293023a0898aSmrg if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) 293123a0898aSmrg return FSIO_ERROR; 293223a0898aSmrg 293323a0898aSmrg while (*cat) 293423a0898aSmrg { 293523a0898aSmrg num_cats++; 293623a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 293723a0898aSmrg if (!end) 293823a0898aSmrg end = cat + strlen (cat); 293923a0898aSmrg len = end - cat; 294023a0898aSmrg if (_fs_write (conn, &len, 1) != FSIO_READY) 294123a0898aSmrg return FSIO_ERROR; 294223a0898aSmrg if (_fs_write (conn, cat, (int) len) != FSIO_READY) 294323a0898aSmrg return FSIO_ERROR; 294423a0898aSmrg cat = end; 294523a0898aSmrg } 294623a0898aSmrg 294723a0898aSmrg if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) 294823a0898aSmrg return FSIO_ERROR; 294923a0898aSmrg 295023a0898aSmrg return FSIO_READY; 295123a0898aSmrg} 295223a0898aSmrg 295323a0898aSmrgstatic int 295423a0898aSmrg_fs_send_cat_sync (FSFpePtr conn) 295523a0898aSmrg{ 295623a0898aSmrg fsListCataloguesReq lcreq; 295723a0898aSmrg 295823a0898aSmrg /* 295923a0898aSmrg * now sync up with the font server, to see if an error was generated 296023a0898aSmrg * by a bogus catalogue 296123a0898aSmrg */ 296223a0898aSmrg lcreq.reqType = FS_ListCatalogues; 296323a0898aSmrg lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; 296423a0898aSmrg lcreq.maxNames = 0; 296523a0898aSmrg lcreq.nbytes = 0; 296623a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 296723a0898aSmrg if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) 296823a0898aSmrg return FSIO_ERROR; 296923a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 297023a0898aSmrg return FSIO_READY; 297123a0898aSmrg} 297223a0898aSmrg 297323a0898aSmrgstatic int 297423a0898aSmrg_fs_recv_cat_sync (FSFpePtr conn) 297523a0898aSmrg{ 297623a0898aSmrg fsGenericReply *reply; 297723a0898aSmrg fsError *error; 297823a0898aSmrg int err; 297923a0898aSmrg int ret; 298023a0898aSmrg 298123a0898aSmrg reply = fs_get_reply (conn, &err); 298223a0898aSmrg if (!reply) 298323a0898aSmrg return err; 298423a0898aSmrg 298523a0898aSmrg ret = FSIO_READY; 298623a0898aSmrg if (reply->type == FS_Error) 298723a0898aSmrg { 298823a0898aSmrg error = (fsError *) reply; 298923a0898aSmrg if (error->major_opcode == FS_SetCatalogues) 299023a0898aSmrg ret = FSIO_ERROR; 299123a0898aSmrg } 299223a0898aSmrg _fs_done_read (conn, reply->length << 2); 299323a0898aSmrg return ret; 299423a0898aSmrg} 299523a0898aSmrg 299623a0898aSmrgstatic void 299723a0898aSmrg_fs_close_server (FSFpePtr conn) 299823a0898aSmrg{ 299923a0898aSmrg _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); 300023a0898aSmrg if (conn->trans_conn) 300123a0898aSmrg { 300223a0898aSmrg _FontTransClose (conn->trans_conn); 300323a0898aSmrg conn->trans_conn = 0; 300423a0898aSmrg _fs_io_reinit (conn); 300523a0898aSmrg } 300623a0898aSmrg if (conn->fs_fd >= 0) 300723a0898aSmrg { 300823a0898aSmrg FD_CLR (conn->fs_fd, &_fs_fd_mask); 300923a0898aSmrg conn->fs_fd = -1; 301023a0898aSmrg } 301123a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 301223a0898aSmrg} 301323a0898aSmrg 301423a0898aSmrgstatic int 301523a0898aSmrg_fs_do_setup_connection (FSFpePtr conn) 301623a0898aSmrg{ 301723a0898aSmrg int ret; 301823a0898aSmrg 301923a0898aSmrg do 302023a0898aSmrg { 302123a0898aSmrg#ifdef DEBUG 302223a0898aSmrg fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); 302323a0898aSmrg#endif 302423a0898aSmrg switch (conn->fs_conn_state) { 302523a0898aSmrg case FS_CONN_UNCONNECTED: 302623a0898aSmrg ret = _fs_open_server (conn); 302723a0898aSmrg if (ret == FSIO_BLOCK) 302823a0898aSmrg conn->fs_conn_state = FS_CONN_CONNECTING; 302923a0898aSmrg break; 303023a0898aSmrg case FS_CONN_CONNECTING: 303123a0898aSmrg ret = _fs_check_connect (conn); 303223a0898aSmrg break; 303323a0898aSmrg case FS_CONN_CONNECTED: 303423a0898aSmrg ret = _fs_send_conn_client_prefix (conn); 303523a0898aSmrg break; 303623a0898aSmrg case FS_CONN_SENT_PREFIX: 303723a0898aSmrg ret = _fs_recv_conn_setup (conn); 303823a0898aSmrg break; 303923a0898aSmrg case FS_CONN_RECV_INIT: 304023a0898aSmrg ret = _fs_send_init_packets (conn); 304123a0898aSmrg if (conn->has_catalogues) 304223a0898aSmrg ret = _fs_send_cat_sync (conn); 304323a0898aSmrg break; 304423a0898aSmrg case FS_CONN_SENT_CAT: 304523a0898aSmrg if (conn->has_catalogues) 304623a0898aSmrg ret = _fs_recv_cat_sync (conn); 304723a0898aSmrg else 304823a0898aSmrg ret = FSIO_READY; 304923a0898aSmrg break; 305023a0898aSmrg default: 305123a0898aSmrg ret = FSIO_READY; 305223a0898aSmrg break; 305323a0898aSmrg } 305423a0898aSmrg switch (ret) { 305523a0898aSmrg case FSIO_READY: 305623a0898aSmrg if (conn->fs_conn_state < FS_CONN_RUNNING) 305723a0898aSmrg conn->fs_conn_state++; 305823a0898aSmrg break; 305923a0898aSmrg case FSIO_BLOCK: 306023a0898aSmrg if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) 306123a0898aSmrg break; 306223a0898aSmrg ret = FSIO_ERROR; 306323a0898aSmrg /* fall through... */ 306423a0898aSmrg case FSIO_ERROR: 306523a0898aSmrg _fs_close_server (conn); 306623a0898aSmrg /* 306723a0898aSmrg * Try the next alternate 306823a0898aSmrg */ 306923a0898aSmrg if (conn->alternate < conn->numAlts) 307023a0898aSmrg { 307123a0898aSmrg conn->alternate++; 307223a0898aSmrg ret = FSIO_READY; 307323a0898aSmrg } 307423a0898aSmrg else 307523a0898aSmrg conn->alternate = 0; 307623a0898aSmrg break; 307723a0898aSmrg } 307823a0898aSmrg } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); 307923a0898aSmrg if (ret == FSIO_READY) 308023a0898aSmrg conn->generation = ++generationCount; 308123a0898aSmrg return ret; 308223a0898aSmrg} 308323a0898aSmrg 308423a0898aSmrgstatic int 308523a0898aSmrg_fs_wait_connect (FSFpePtr conn) 308623a0898aSmrg{ 308723a0898aSmrg int ret; 308823a0898aSmrg 308923a0898aSmrg for (;;) 309023a0898aSmrg { 309123a0898aSmrg ret = _fs_do_setup_connection (conn); 309223a0898aSmrg if (ret != FSIO_BLOCK) 309323a0898aSmrg break; 309423a0898aSmrg if (conn->fs_conn_state <= FS_CONN_CONNECTING) 309523a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 1000); 309623a0898aSmrg else 309723a0898aSmrg ret = _fs_wait_for_readable (conn, 1000); 309823a0898aSmrg if (ret == FSIO_ERROR) 309923a0898aSmrg break; 310023a0898aSmrg } 310123a0898aSmrg return ret; 310223a0898aSmrg} 310323a0898aSmrg 310423a0898aSmrg/* 310523a0898aSmrg * Poll a connection in the process of reconnecting 310623a0898aSmrg */ 310723a0898aSmrgstatic void 310823a0898aSmrg_fs_check_reconnect (FSFpePtr conn) 310923a0898aSmrg{ 311023a0898aSmrg int ret; 311123a0898aSmrg 311223a0898aSmrg ret = _fs_do_setup_connection (conn); 311323a0898aSmrg switch (ret) { 311423a0898aSmrg case FSIO_READY: 311523a0898aSmrg _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); 311623a0898aSmrg _fs_restart_connection (conn); 311723a0898aSmrg break; 311823a0898aSmrg case FSIO_BLOCK: 311923a0898aSmrg break; 312023a0898aSmrg case FSIO_ERROR: 312123a0898aSmrg conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; 312223a0898aSmrg break; 312323a0898aSmrg } 312423a0898aSmrg} 312523a0898aSmrg 312623a0898aSmrg/* 312723a0898aSmrg * Start the reconnection process 312823a0898aSmrg */ 312923a0898aSmrgstatic void 313023a0898aSmrg_fs_start_reconnect (FSFpePtr conn) 313123a0898aSmrg{ 313223a0898aSmrg if (conn->blockState & FS_RECONNECTING) 313323a0898aSmrg return; 313423a0898aSmrg conn->alternate = 0; 313523a0898aSmrg _fs_mark_block (conn, FS_RECONNECTING); 313623a0898aSmrg _fs_unmark_block (conn, FS_BROKEN_CONNECTION); 313723a0898aSmrg _fs_check_reconnect (conn); 313823a0898aSmrg} 313923a0898aSmrg 314023a0898aSmrg 314123a0898aSmrgstatic FSFpePtr 314223a0898aSmrg_fs_init_conn (char *servername) 314323a0898aSmrg{ 314423a0898aSmrg FSFpePtr conn; 314523a0898aSmrg 314623a0898aSmrg conn = xalloc (sizeof (FSFpeRec) + strlen (servername) + 1); 314723a0898aSmrg if (!conn) 314823a0898aSmrg return 0; 314923a0898aSmrg memset (conn, '\0', sizeof (FSFpeRec)); 315023a0898aSmrg if (!_fs_io_init (conn)) 315123a0898aSmrg { 315223a0898aSmrg xfree (conn); 315323a0898aSmrg return 0; 315423a0898aSmrg } 315523a0898aSmrg conn->servername = (char *) (conn + 1); 315623a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 315723a0898aSmrg conn->fs_fd = -1; 315823a0898aSmrg strcpy (conn->servername, servername); 315923a0898aSmrg return conn; 316023a0898aSmrg} 316123a0898aSmrg 316223a0898aSmrgstatic void 316323a0898aSmrg_fs_free_conn (FSFpePtr conn) 316423a0898aSmrg{ 316523a0898aSmrg _fs_close_server (conn); 316623a0898aSmrg _fs_io_fini (conn); 316723a0898aSmrg if (conn->alts) 316823a0898aSmrg xfree (conn->alts); 316923a0898aSmrg xfree (conn); 317023a0898aSmrg} 317123a0898aSmrg 317223a0898aSmrg/* 317323a0898aSmrg * called at server init time 317423a0898aSmrg */ 317523a0898aSmrg 317623a0898aSmrgvoid 317723a0898aSmrgfs_register_fpe_functions(void) 317823a0898aSmrg{ 317923a0898aSmrg RegisterFPEFunctions(fs_name_check, 318023a0898aSmrg fs_init_fpe, 318123a0898aSmrg fs_free_fpe, 318223a0898aSmrg fs_reset_fpe, 318323a0898aSmrg fs_open_font, 318423a0898aSmrg fs_close_font, 318523a0898aSmrg fs_list_fonts, 318623a0898aSmrg fs_start_list_with_info, 318723a0898aSmrg fs_next_list_with_info, 318823a0898aSmrg fs_wakeup, 318923a0898aSmrg fs_client_died, 319023a0898aSmrg _fs_load_glyphs, 319123a0898aSmrg NULL, 319223a0898aSmrg NULL, 319323a0898aSmrg NULL); 319423a0898aSmrg} 319523a0898aSmrg 319623a0898aSmrgstatic int 319723a0898aSmrgcheck_fs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 319823a0898aSmrg char *name, int namelen, 319923a0898aSmrg fsBitmapFormat format, fsBitmapFormatMask fmask, 320023a0898aSmrg XID id, FontPtr *ppfont, 320123a0898aSmrg char **alias, FontPtr non_cachable_font) 320223a0898aSmrg{ 320323a0898aSmrg if (XpClientIsBitmapClient(client)) 320423a0898aSmrg return (fs_open_font(client, fpe, flags, name, namelen, format, 320523a0898aSmrg fmask, id, ppfont, alias, non_cachable_font) ); 320623a0898aSmrg return BadFontName; 320723a0898aSmrg} 320823a0898aSmrg 320923a0898aSmrgstatic int 321023a0898aSmrgcheck_fs_list_fonts(pointer client, FontPathElementPtr fpe, 321123a0898aSmrg char *pattern, int patlen, int maxnames, 321223a0898aSmrg FontNamesPtr newnames) 321323a0898aSmrg{ 321423a0898aSmrg if (XpClientIsBitmapClient(client)) 321523a0898aSmrg return (fs_list_fonts(client, fpe, pattern, patlen, maxnames, 321623a0898aSmrg newnames)); 321723a0898aSmrg return BadFontName; 321823a0898aSmrg} 321923a0898aSmrg 322023a0898aSmrgstatic int 322123a0898aSmrgcheck_fs_start_list_with_info(pointer client, FontPathElementPtr fpe, 322223a0898aSmrg char *pattern, int len, int maxnames, 322323a0898aSmrg pointer *pdata) 322423a0898aSmrg{ 322523a0898aSmrg if (XpClientIsBitmapClient(client)) 322623a0898aSmrg return (fs_start_list_with_info(client, fpe, pattern, len, maxnames, 322723a0898aSmrg pdata)); 322823a0898aSmrg return BadFontName; 322923a0898aSmrg} 323023a0898aSmrg 323123a0898aSmrgstatic int 323223a0898aSmrgcheck_fs_next_list_with_info(pointer client, FontPathElementPtr fpe, 323323a0898aSmrg char **namep, int *namelenp, 323423a0898aSmrg FontInfoPtr *pFontInfo, int *numFonts, 323523a0898aSmrg pointer private) 323623a0898aSmrg{ 323723a0898aSmrg if (XpClientIsBitmapClient(client)) 323823a0898aSmrg return (fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, 323923a0898aSmrg numFonts,private)); 324023a0898aSmrg return BadFontName; 324123a0898aSmrg} 324223a0898aSmrg 324323a0898aSmrgvoid 324423a0898aSmrgcheck_fs_register_fpe_functions(void) 324523a0898aSmrg{ 324623a0898aSmrg RegisterFPEFunctions(fs_name_check, 324723a0898aSmrg fs_init_fpe, 324823a0898aSmrg fs_free_fpe, 324923a0898aSmrg fs_reset_fpe, 325023a0898aSmrg check_fs_open_font, 325123a0898aSmrg fs_close_font, 325223a0898aSmrg check_fs_list_fonts, 325323a0898aSmrg check_fs_start_list_with_info, 325423a0898aSmrg check_fs_next_list_with_info, 325523a0898aSmrg fs_wakeup, 325623a0898aSmrg fs_client_died, 325723a0898aSmrg _fs_load_glyphs, 325823a0898aSmrg NULL, 325923a0898aSmrg NULL, 326023a0898aSmrg NULL); 326123a0898aSmrg} 3262