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