fserve.c revision b0d196e1
123a0898aSmrg/* 223a0898aSmrg 323a0898aSmrgCopyright 1990, 1998 The Open Group 423a0898aSmrg 523a0898aSmrgPermission to use, copy, modify, distribute, and sell this software and its 623a0898aSmrgdocumentation for any purpose is hereby granted without fee, provided that 723a0898aSmrgthe above copyright notice appear in all copies and that both that 823a0898aSmrgcopyright notice and this permission notice appear in supporting 923a0898aSmrgdocumentation. 1023a0898aSmrg 1123a0898aSmrgThe above copyright notice and this permission notice shall be included in 1223a0898aSmrgall copies or substantial portions of the Software. 1323a0898aSmrg 1423a0898aSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1523a0898aSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1623a0898aSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1723a0898aSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1823a0898aSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1923a0898aSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2023a0898aSmrg 2123a0898aSmrgExcept as contained in this notice, the name of The Open Group shall not be 2223a0898aSmrgused in advertising or otherwise to promote the sale, use or other dealings 2323a0898aSmrgin this Software without prior written authorization from The Open Group. 2423a0898aSmrg 2523a0898aSmrg*/ 2623a0898aSmrg 2723a0898aSmrg/* 2823a0898aSmrg * Copyright 1990 Network Computing Devices 2923a0898aSmrg * 3023a0898aSmrg * Permission to use, copy, modify, distribute, and sell this software and 3123a0898aSmrg * its documentation for any purpose is hereby granted without fee, provided 3223a0898aSmrg * that the above copyright notice appear in all copies and that both that 3323a0898aSmrg * copyright notice and this permission notice appear in supporting 3423a0898aSmrg * documentation, and that the names of Network Computing Devices, or Digital 3523a0898aSmrg * not be used in advertising or publicity pertaining to distribution 3623a0898aSmrg * of the software without specific, written prior permission. 3723a0898aSmrg * 3823a0898aSmrg * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH 3923a0898aSmrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 4023a0898aSmrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 4123a0898aSmrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 4223a0898aSmrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 4323a0898aSmrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 4423a0898aSmrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 4523a0898aSmrg * THIS SOFTWARE. 4623a0898aSmrg * 4723a0898aSmrg * Author: Dave Lemke, Network Computing Devices, Inc 4823a0898aSmrg */ 4923a0898aSmrg/* 5023a0898aSmrg * font server specific font access 5123a0898aSmrg */ 5223a0898aSmrg 5323a0898aSmrg#ifdef HAVE_CONFIG_H 5423a0898aSmrg#include <config.h> 5523a0898aSmrg#endif 5623a0898aSmrg 5723a0898aSmrg#ifdef WIN32 5823a0898aSmrg#define _WILLWINSOCK_ 5923a0898aSmrg#endif 6023a0898aSmrg#define FONT_t 6123a0898aSmrg#define TRANS_CLIENT 6223a0898aSmrg#include "X11/Xtrans/Xtrans.h" 6323a0898aSmrg#include "X11/Xpoll.h" 6423a0898aSmrg#include <X11/fonts/FS.h> 6523a0898aSmrg#include <X11/fonts/FSproto.h> 6623a0898aSmrg#include <X11/X.h> 6723a0898aSmrg#include <X11/Xos.h> 6823a0898aSmrg#include <X11/fonts/fontmisc.h> 6923a0898aSmrg#include <X11/fonts/fontstruct.h> 7023a0898aSmrg#include "fservestr.h" 7123a0898aSmrg#include <X11/fonts/fontutil.h> 7223a0898aSmrg#include <errno.h> 737673729aSmrg#include <limits.h> 7423a0898aSmrg 7523a0898aSmrg#include <time.h> 7623a0898aSmrg#define Time_t time_t 7723a0898aSmrg 7823a0898aSmrg#ifdef NCD 7923a0898aSmrg#include <ncd/nvram.h> 8023a0898aSmrg#endif 8123a0898aSmrg 8223a0898aSmrg#include <stddef.h> 8323a0898aSmrg 8423a0898aSmrg#ifndef MIN 8523a0898aSmrg#define MIN(a,b) ((a)<(b)?(a):(b)) 8623a0898aSmrg#endif 8723a0898aSmrg#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) 8841c30155Smrg 8923a0898aSmrg#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ 9023a0898aSmrg (pci)->rightSideBearing || \ 9123a0898aSmrg (pci)->ascent || \ 9223a0898aSmrg (pci)->descent || \ 9323a0898aSmrg (pci)->characterWidth) 9423a0898aSmrg 959d21a897Sspz/* 969d21a897Sspz * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words, 979d21a897Sspz * so this converts for doing size comparisons. 989d21a897Sspz */ 997673729aSmrg#define LENGTHOF(r) (SIZEOF(r) >> 2) 1009d21a897Sspz 1019d21a897Sspz/* Somewhat arbitrary limit on maximum reply size we'll try to read. */ 1027673729aSmrg#define MAX_REPLY_LENGTH ((64 * 1024 * 1024) >> 2) 1039d21a897Sspz 10423a0898aSmrgextern void ErrorF(const char *f, ...); 10523a0898aSmrg 10623a0898aSmrgstatic int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 10723a0898aSmrgstatic int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 10841c30155Smrgstatic int fs_read_list_info ( FontPathElementPtr fpe, 10923a0898aSmrg FSBlockDataPtr blockrec ); 11023a0898aSmrg 11123a0898aSmrgextern fd_set _fs_fd_mask; 11223a0898aSmrg 11341c30155Smrgstatic void fs_block_handler ( pointer data, OSTimePtr wt, 11423a0898aSmrg pointer LastSelectMask ); 11523a0898aSmrgstatic int fs_wakeup ( FontPathElementPtr fpe, unsigned long *mask ); 11623a0898aSmrg 11723a0898aSmrg/* 11841c30155Smrg * List of all FPEs 11923a0898aSmrg */ 12023a0898aSmrgstatic FSFpePtr fs_fpes; 12123a0898aSmrg/* 12223a0898aSmrg * Union of all FPE blockStates 12323a0898aSmrg */ 12423a0898aSmrgstatic CARD32 fs_blockState; 12523a0898aSmrg 12623a0898aSmrgstatic int _fs_restart_connection ( FSFpePtr conn ); 12741c30155Smrgstatic void fs_send_query_bitmaps ( FontPathElementPtr fpe, 12823a0898aSmrg FSBlockDataPtr blockrec ); 12923a0898aSmrgstatic int fs_send_close_font ( FontPathElementPtr fpe, Font id ); 13023a0898aSmrgstatic void fs_client_died ( pointer client, FontPathElementPtr fpe ); 13123a0898aSmrgstatic void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); 13223a0898aSmrgstatic void _fs_client_resolution ( FSFpePtr conn ); 13323a0898aSmrgstatic fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); 13423a0898aSmrgstatic int fs_await_reply (FSFpePtr conn); 13523a0898aSmrgstatic void _fs_do_blocked (FSFpePtr conn); 13623a0898aSmrgstatic void fs_cleanup_bfont (FSBlockedFontPtr bfont); 13723a0898aSmrg 13823a0898aSmrgchar _fs_glyph_undefined; 13923a0898aSmrgchar _fs_glyph_requested; 14023a0898aSmrgstatic char _fs_glyph_zero_length; 14123a0898aSmrg 14223a0898aSmrgstatic int generationCount; 14323a0898aSmrg 14423a0898aSmrgstatic int FontServerRequestTimeout = 30 * 1000; 14523a0898aSmrg 14623a0898aSmrgstatic void 14723a0898aSmrg_fs_close_server (FSFpePtr conn); 14823a0898aSmrg 14923a0898aSmrgstatic FSFpePtr 1500b332824Ssnj_fs_init_conn (const char *servername); 15123a0898aSmrg 15223a0898aSmrgstatic int 15323a0898aSmrg_fs_wait_connect (FSFpePtr conn); 15423a0898aSmrg 15523a0898aSmrgstatic int 15623a0898aSmrg_fs_send_init_packets (FSFpePtr conn); 15723a0898aSmrg 15823a0898aSmrgstatic void 15923a0898aSmrg_fs_check_reconnect (FSFpePtr conn); 16023a0898aSmrg 16123a0898aSmrgstatic void 16223a0898aSmrg_fs_start_reconnect (FSFpePtr conn); 16323a0898aSmrg 16423a0898aSmrgstatic void 16523a0898aSmrg_fs_free_conn (FSFpePtr conn); 16623a0898aSmrg 16723a0898aSmrgstatic int 16823a0898aSmrgfs_free_fpe(FontPathElementPtr fpe); 16923a0898aSmrg 17023a0898aSmrg/* 17123a0898aSmrg * Font server access 17223a0898aSmrg * 17323a0898aSmrg * the basic idea for the non-blocking access is to have the function 17423a0898aSmrg * called multiple times until the actual data is returned, instead 17523a0898aSmrg * of ClientBlocked. 17623a0898aSmrg * 17723a0898aSmrg * the first call to the function will cause the request to be sent to 17823a0898aSmrg * the font server, and a block record to be stored in the fpe's list 17923a0898aSmrg * of outstanding requests. the FS block handler also sticks the 18023a0898aSmrg * proper set of fd's into the select mask. when data is ready to be 18123a0898aSmrg * read in, the FS wakup handler will be hit. this will read the 18223a0898aSmrg * data off the wire into the proper block record, and then signal the 18323a0898aSmrg * client that caused the block so that it can restart. it will then 18423a0898aSmrg * call the access function again, which will realize that the data has 18523a0898aSmrg * arrived and return it. 18623a0898aSmrg */ 18723a0898aSmrg 18823a0898aSmrg 18923a0898aSmrg#ifdef DEBUG 19023a0898aSmrgstatic void 19123a0898aSmrg_fs_add_req_log(FSFpePtr conn, int opcode) 19223a0898aSmrg{ 19323a0898aSmrg conn->current_seq++; 19423a0898aSmrg fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", 19523a0898aSmrg conn->current_seq, opcode); 19623a0898aSmrg conn->reqbuffer[conn->reqindex].opcode = opcode; 19723a0898aSmrg conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; 19823a0898aSmrg conn->reqindex++; 19923a0898aSmrg if (conn->reqindex == REQUEST_LOG_SIZE) 20023a0898aSmrg conn->reqindex = 0; 20123a0898aSmrg} 20223a0898aSmrg 20323a0898aSmrgstatic void 20423a0898aSmrg_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) 20523a0898aSmrg{ 20623a0898aSmrg int i; 20723a0898aSmrg 20823a0898aSmrg for (i = 0; i < REQUEST_LOG_SIZE; i++) 20923a0898aSmrg if (conn->reqbuffer[i].sequence == rep->sequenceNumber) 21023a0898aSmrg break; 21123a0898aSmrg if (i == REQUEST_LOG_SIZE) 21223a0898aSmrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", 21323a0898aSmrg rep->sequenceNumber); 21423a0898aSmrg else 21523a0898aSmrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", 21623a0898aSmrg rep->sequenceNumber, 21723a0898aSmrg conn->reqbuffer[i].opcode); 21823a0898aSmrg} 2199d21a897Sspz 2209d21a897Sspz#define _fs_reply_failed(rep, name, op) do { \ 2219d21a897Sspz if (rep) { \ 2229d21a897Sspz if (rep->type == FS_Error) \ 2239d21a897Sspz fprintf (stderr, "Error: %d Request: %s\n", \ 2249d21a897Sspz ((fsError *)rep)->request, #name); \ 2259d21a897Sspz else \ 22681d6fa61Srin fprintf (stderr, "Bad Length for %s Reply: %u %s %d\n", \ 22781d6fa61Srin #name, (unsigned) rep->length, op, LENGTHOF(name));\ 2289d21a897Sspz } \ 2299d21a897Sspz} while (0) 2309d21a897Sspz 23123a0898aSmrg#else 23223a0898aSmrg#define _fs_add_req_log(conn,op) ((conn)->current_seq++) 23323a0898aSmrg#define _fs_add_rep_log(conn,rep) 2349d21a897Sspz#define _fs_reply_failed(rep,name,op) 23523a0898aSmrg#endif 23623a0898aSmrg 23723a0898aSmrgstatic Bool 2380b332824Ssnjfs_name_check(const char *name) 23923a0898aSmrg{ 24023a0898aSmrg /* Just make sure there is a protocol/ prefix */ 24123a0898aSmrg return (name && *name != '/' && strchr(name, '/')); 24223a0898aSmrg} 24323a0898aSmrg 24423a0898aSmrgstatic void 24523a0898aSmrg_fs_client_resolution(FSFpePtr conn) 24623a0898aSmrg{ 24723a0898aSmrg fsSetResolutionReq srreq; 24823a0898aSmrg int num_res; 24923a0898aSmrg FontResolutionPtr res; 25023a0898aSmrg 25123a0898aSmrg res = GetClientResolutions(&num_res); 25223a0898aSmrg 25323a0898aSmrg if (num_res) { 25423a0898aSmrg srreq.reqType = FS_SetResolution; 25523a0898aSmrg srreq.num_resolutions = num_res; 25623a0898aSmrg srreq.length = (SIZEOF(fsSetResolutionReq) + 25723a0898aSmrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 25823a0898aSmrg 25923a0898aSmrg _fs_add_req_log(conn, FS_SetResolution); 26023a0898aSmrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) 26123a0898aSmrg (void)_fs_write_pad(conn, (char *) res, 26223a0898aSmrg (num_res * SIZEOF(fsResolution))); 26323a0898aSmrg } 26423a0898aSmrg} 26523a0898aSmrg 26641c30155Smrg/* 26723a0898aSmrg * close font server and remove any state associated with 26823a0898aSmrg * this connection - this includes any client records. 26923a0898aSmrg */ 27023a0898aSmrg 27123a0898aSmrgstatic void 27223a0898aSmrgfs_close_conn(FSFpePtr conn) 27323a0898aSmrg{ 27423a0898aSmrg FSClientPtr client, nclient; 27523a0898aSmrg 27623a0898aSmrg _fs_close_server (conn); 27741c30155Smrg 27841c30155Smrg for (client = conn->clients; client; client = nclient) 27923a0898aSmrg { 28023a0898aSmrg nclient = client->next; 2817f7f5e4eSmrg free (client); 28223a0898aSmrg } 28323a0898aSmrg conn->clients = NULL; 28423a0898aSmrg} 28523a0898aSmrg 28623a0898aSmrg/* 28723a0898aSmrg * the wakeup handlers have to be set when the FPE is open, and not 28823a0898aSmrg * removed until it is freed, in order to handle unexpected data, like 28923a0898aSmrg * events 29023a0898aSmrg */ 29123a0898aSmrg/* ARGSUSED */ 29223a0898aSmrgstatic int 29323a0898aSmrgfs_init_fpe(FontPathElementPtr fpe) 29423a0898aSmrg{ 29523a0898aSmrg FSFpePtr conn; 2960b332824Ssnj const char *name; 29723a0898aSmrg int err; 29823a0898aSmrg int ret; 29923a0898aSmrg 30023a0898aSmrg /* open font server */ 30123a0898aSmrg /* create FS specific fpe info */ 30223a0898aSmrg name = fpe->name; 30323a0898aSmrg 30423a0898aSmrg /* hack for old style names */ 30523a0898aSmrg if (*name == ':') 30623a0898aSmrg name++; /* skip ':' */ 30723a0898aSmrg 30823a0898aSmrg conn = _fs_init_conn (name); 30923a0898aSmrg if (!conn) 31023a0898aSmrg err = AllocError; 31123a0898aSmrg else 31223a0898aSmrg { 31323a0898aSmrg err = init_fs_handlers (fpe, fs_block_handler); 31423a0898aSmrg if (err != Successful) 31523a0898aSmrg { 31623a0898aSmrg _fs_free_conn (conn); 31723a0898aSmrg err = AllocError; 31823a0898aSmrg } 31923a0898aSmrg else 32023a0898aSmrg { 32123a0898aSmrg fpe->private = conn; 32223a0898aSmrg conn->next = fs_fpes; 32323a0898aSmrg fs_fpes = conn; 32423a0898aSmrg ret = _fs_wait_connect (conn); 32523a0898aSmrg if (ret != FSIO_READY) 32623a0898aSmrg { 32723a0898aSmrg fs_free_fpe (fpe); 32823a0898aSmrg err = BadFontPath; 32923a0898aSmrg } 33023a0898aSmrg else 33123a0898aSmrg err = Successful; 33223a0898aSmrg } 33323a0898aSmrg } 33441c30155Smrg 33523a0898aSmrg if (err == Successful) 33623a0898aSmrg { 33723a0898aSmrg#ifdef NCD 33823a0898aSmrg if (configData.ExtendedFontDiags) 33923a0898aSmrg printf("Connected to font server \"%s\"\n", name); 34023a0898aSmrg#endif 34123a0898aSmrg#ifdef DEBUG 34223a0898aSmrg fprintf (stderr, "connected to FS \"%s\"\n", name); 34323a0898aSmrg#endif 34423a0898aSmrg } 34523a0898aSmrg else 34623a0898aSmrg { 34723a0898aSmrg#ifdef DEBUG 34823a0898aSmrg fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); 34923a0898aSmrg#endif 35023a0898aSmrg#ifdef NCD 35123a0898aSmrg if (configData.ExtendedFontDiags) 35223a0898aSmrg printf("Failed to connect to font server \"%s\"\n", name); 35323a0898aSmrg#endif 35423a0898aSmrg ; 35523a0898aSmrg } 35623a0898aSmrg return err; 35723a0898aSmrg} 35823a0898aSmrg 35923a0898aSmrgstatic int 36023a0898aSmrgfs_reset_fpe(FontPathElementPtr fpe) 36123a0898aSmrg{ 36223a0898aSmrg (void) _fs_send_init_packets((FSFpePtr) fpe->private); 36323a0898aSmrg return Successful; 36423a0898aSmrg} 36523a0898aSmrg 36623a0898aSmrg/* 36723a0898aSmrg * this shouldn't be called till all refs to the FPE are gone 36823a0898aSmrg */ 36923a0898aSmrg 37023a0898aSmrgstatic int 37123a0898aSmrgfs_free_fpe(FontPathElementPtr fpe) 37223a0898aSmrg{ 37323a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private, *prev; 37441c30155Smrg 37523a0898aSmrg /* unhook from chain of all font servers */ 37623a0898aSmrg for (prev = &fs_fpes; *prev; prev = &(*prev)->next) 37723a0898aSmrg { 37823a0898aSmrg if (*prev == conn) 37923a0898aSmrg { 38023a0898aSmrg *prev = conn->next; 38123a0898aSmrg break; 38223a0898aSmrg } 38323a0898aSmrg } 38423a0898aSmrg _fs_unmark_block (conn, conn->blockState); 38523a0898aSmrg fs_close_conn(conn); 38623a0898aSmrg remove_fs_handlers(fpe, fs_block_handler, fs_fpes == 0); 38723a0898aSmrg _fs_free_conn (conn); 38823a0898aSmrg fpe->private = (pointer) 0; 38923a0898aSmrg 39023a0898aSmrg#ifdef NCD 39123a0898aSmrg if (configData.ExtendedFontDiags) 39223a0898aSmrg printf("Disconnected from font server \"%s\"\n", fpe->name); 39323a0898aSmrg#endif 39423a0898aSmrg#ifdef DEBUG 39523a0898aSmrg fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); 39623a0898aSmrg#endif 39723a0898aSmrg 39823a0898aSmrg return Successful; 39923a0898aSmrg} 40023a0898aSmrg 40123a0898aSmrgstatic FSBlockDataPtr 40223a0898aSmrgfs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) 40323a0898aSmrg{ 40423a0898aSmrg FSBlockDataPtr blockrec, 40523a0898aSmrg *prev; 40623a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 40723a0898aSmrg int size; 40823a0898aSmrg 40923a0898aSmrg switch (type) { 41023a0898aSmrg case FS_OPEN_FONT: 41123a0898aSmrg size = sizeof(FSBlockedFontRec); 41223a0898aSmrg break; 41323a0898aSmrg case FS_LOAD_GLYPHS: 41423a0898aSmrg size = sizeof(FSBlockedGlyphRec); 41523a0898aSmrg break; 41623a0898aSmrg case FS_LIST_FONTS: 41723a0898aSmrg size = sizeof(FSBlockedListRec); 41823a0898aSmrg break; 41923a0898aSmrg case FS_LIST_WITH_INFO: 42023a0898aSmrg size = sizeof(FSBlockedListInfoRec); 42123a0898aSmrg break; 42223a0898aSmrg default: 42323a0898aSmrg size = 0; 42423a0898aSmrg break; 42523a0898aSmrg } 4267f7f5e4eSmrg blockrec = malloc(sizeof(FSBlockDataRec) + size); 42723a0898aSmrg if (!blockrec) 42823a0898aSmrg return (FSBlockDataPtr) 0; 42923a0898aSmrg blockrec->data = (pointer) (blockrec + 1); 43023a0898aSmrg blockrec->client = client; 43123a0898aSmrg blockrec->sequenceNumber = -1; 43223a0898aSmrg blockrec->errcode = StillWorking; 43323a0898aSmrg blockrec->type = type; 43423a0898aSmrg blockrec->depending = 0; 43523a0898aSmrg blockrec->next = (FSBlockDataPtr) 0; 43641c30155Smrg 43723a0898aSmrg /* stick it on the end of the list (since its expected last) */ 43823a0898aSmrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 43923a0898aSmrg ; 44023a0898aSmrg *prev = blockrec; 44123a0898aSmrg 44223a0898aSmrg return blockrec; 44323a0898aSmrg} 44423a0898aSmrg 44523a0898aSmrgstatic void 44623a0898aSmrg_fs_set_pending_reply (FSFpePtr conn) 44723a0898aSmrg{ 44823a0898aSmrg FSBlockDataPtr blockrec; 44941c30155Smrg 45023a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 45123a0898aSmrg if (blockrec->errcode == StillWorking) 45223a0898aSmrg break; 45323a0898aSmrg if (blockrec) 45423a0898aSmrg { 45523a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 45623a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 45723a0898aSmrg } 45823a0898aSmrg else 45923a0898aSmrg _fs_unmark_block (conn, FS_PENDING_REPLY); 46023a0898aSmrg} 46123a0898aSmrg 46223a0898aSmrgstatic void 46323a0898aSmrg_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) 46423a0898aSmrg{ 46523a0898aSmrg FSBlockDataPtr *prev; 46623a0898aSmrg 46723a0898aSmrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 46841c30155Smrg if (*prev == blockrec) 46923a0898aSmrg { 47023a0898aSmrg *prev = blockrec->next; 47123a0898aSmrg break; 47223a0898aSmrg } 47323a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 47423a0898aSmrg { 47523a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 47623a0898aSmrg if (bglyph->num_expected_ranges) 4777f7f5e4eSmrg free(bglyph->expected_ranges); 47823a0898aSmrg } 4797f7f5e4eSmrg free(blockrec); 48023a0898aSmrg _fs_set_pending_reply (conn); 48123a0898aSmrg} 48223a0898aSmrg 48323a0898aSmrgstatic void 48423a0898aSmrg_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) 48523a0898aSmrg{ 48623a0898aSmrg FSClientsDependingPtr p; 48741c30155Smrg 48823a0898aSmrg while ((p = *clients_depending)) 48923a0898aSmrg { 49023a0898aSmrg *clients_depending = p->next; 49123a0898aSmrg ClientSignal(p->client); 4927f7f5e4eSmrg free(p); 49323a0898aSmrg } 49423a0898aSmrg} 49523a0898aSmrg 49623a0898aSmrgstatic int 49723a0898aSmrg_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) 49823a0898aSmrg{ 49923a0898aSmrg FSClientsDependingPtr new, cd; 50041c30155Smrg 50141c30155Smrg for (; (cd = *clients_depending); 50223a0898aSmrg clients_depending = &(*clients_depending)->next) 50323a0898aSmrg { 50441c30155Smrg if (cd->client == client) 50523a0898aSmrg return Suspended; 50623a0898aSmrg } 50741c30155Smrg 5087f7f5e4eSmrg new = malloc (sizeof (FSClientsDependingRec)); 50923a0898aSmrg if (!new) 51023a0898aSmrg return BadAlloc; 51123a0898aSmrg 51223a0898aSmrg new->client = client; 51323a0898aSmrg new->next = 0; 51423a0898aSmrg *clients_depending = new; 51523a0898aSmrg return Suspended; 51623a0898aSmrg} 51723a0898aSmrg 51823a0898aSmrg/* 51923a0898aSmrg * When a request is aborted due to a font server failure, 52023a0898aSmrg * signal any depending clients to restart their dependant 52123a0898aSmrg * requests 52223a0898aSmrg */ 52323a0898aSmrgstatic void 52423a0898aSmrg_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 52523a0898aSmrg{ 52623a0898aSmrg switch(blockrec->type) { 52723a0898aSmrg case FS_OPEN_FONT: { 52823a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; 52941c30155Smrg 53023a0898aSmrg fs_cleanup_bfont (bfont); 53123a0898aSmrg _fs_signal_clients_depending(&bfont->clients_depending); 53223a0898aSmrg break; 53323a0898aSmrg } 53423a0898aSmrg case FS_LOAD_GLYPHS: { 53523a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 53641c30155Smrg 53723a0898aSmrg _fs_clean_aborted_loadglyphs(bglyph->pfont, 53823a0898aSmrg bglyph->num_expected_ranges, 53941c30155Smrg bglyph->expected_ranges); 54023a0898aSmrg _fs_signal_clients_depending(&bglyph->clients_depending); 54123a0898aSmrg break; 54223a0898aSmrg } 54323a0898aSmrg case FS_LIST_FONTS: 54423a0898aSmrg break; 54523a0898aSmrg case FS_LIST_WITH_INFO: { 54623a0898aSmrg FSBlockedListInfoPtr binfo; 54723a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 54823a0898aSmrg if (binfo->status == FS_LFWI_REPLY) 54923a0898aSmrg FD_SET(conn->fs_fd, &_fs_fd_mask); 55023a0898aSmrg _fs_free_props (&binfo->info); 55123a0898aSmrg } 55223a0898aSmrg default: 55323a0898aSmrg break; 55423a0898aSmrg } 55523a0898aSmrg} 55623a0898aSmrg 55723a0898aSmrgstatic void 55823a0898aSmrgfs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 55923a0898aSmrg{ 56023a0898aSmrg _fs_clean_aborted_blockrec (conn, blockrec); 56123a0898aSmrg _fs_remove_block_rec (conn, blockrec); 56223a0898aSmrg} 56323a0898aSmrg 56423a0898aSmrg/* 56523a0898aSmrg * Tell the font server we've failed to complete an open and 56623a0898aSmrg * then unload the partially created font 56723a0898aSmrg */ 56823a0898aSmrgstatic void 56923a0898aSmrgfs_cleanup_bfont (FSBlockedFontPtr bfont) 57023a0898aSmrg{ 57123a0898aSmrg FSFontDataRec *fsd; 57223a0898aSmrg 57323a0898aSmrg if (bfont->pfont) 57423a0898aSmrg { 57523a0898aSmrg fsd = (FSFontDataRec *) bfont->pfont->fpePrivate; 57641c30155Smrg 57723a0898aSmrg /* make sure the FS knows we choked on it */ 57823a0898aSmrg fs_send_close_font(bfont->pfont->fpe, bfont->fontid); 57941c30155Smrg 58023a0898aSmrg /* 58141c30155Smrg * Either unload the font if it's being opened for 58223a0898aSmrg * the first time, or smash the generation field to 58323a0898aSmrg * mark this font as an orphan 58423a0898aSmrg */ 58523a0898aSmrg if (!(bfont->flags & FontReopen)) 58623a0898aSmrg { 58723a0898aSmrg if (bfont->freeFont) 58823a0898aSmrg (*bfont->pfont->unload_font) (bfont->pfont); 58923a0898aSmrg#ifdef DEBUG 59023a0898aSmrg else 59123a0898aSmrg fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); 59223a0898aSmrg#endif 59323a0898aSmrg bfont->pfont = 0; 59423a0898aSmrg } 59523a0898aSmrg else 59623a0898aSmrg fsd->generation = -1; 59723a0898aSmrg } 59823a0898aSmrg} 59923a0898aSmrg 60023a0898aSmrg/* 60123a0898aSmrg * Check to see if a complete reply is waiting 60223a0898aSmrg */ 60323a0898aSmrgstatic fsGenericReply * 60423a0898aSmrgfs_get_reply (FSFpePtr conn, int *error) 60523a0898aSmrg{ 60623a0898aSmrg char *buf; 60723a0898aSmrg fsGenericReply *rep; 60823a0898aSmrg int ret; 60923a0898aSmrg 61023a0898aSmrg /* block if the connection is down or paused in lfwi */ 61123a0898aSmrg if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) 61223a0898aSmrg { 61323a0898aSmrg *error = FSIO_BLOCK; 61423a0898aSmrg return 0; 61523a0898aSmrg } 61641c30155Smrg 61723a0898aSmrg ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); 61823a0898aSmrg if (ret != FSIO_READY) 61923a0898aSmrg { 62023a0898aSmrg *error = FSIO_BLOCK; 62123a0898aSmrg return 0; 62223a0898aSmrg } 62341c30155Smrg 62423a0898aSmrg rep = (fsGenericReply *) buf; 62523a0898aSmrg 6269d21a897Sspz /* 6279d21a897Sspz * Refuse to accept replies longer than a maximum reasonable length, 6289d21a897Sspz * before we pass to _fs_start_read, since it will try to resize the 6299d21a897Sspz * incoming connection buffer to this size. Also avoids integer overflow 6309d21a897Sspz * on 32-bit systems. 6319d21a897Sspz */ 6329d21a897Sspz if (rep->length > MAX_REPLY_LENGTH) 6339d21a897Sspz { 634b0d196e1Smrg ErrorF("fserve: reply length %ld > MAX_REPLY_LENGTH, disconnecting" 635b0d196e1Smrg " from font server\n", (long)rep->length); 6367673729aSmrg _fs_connection_died (conn); 6377673729aSmrg *error = FSIO_ERROR; 6387673729aSmrg return 0; 6399d21a897Sspz } 6409d21a897Sspz 64123a0898aSmrg ret = _fs_start_read (conn, rep->length << 2, &buf); 64223a0898aSmrg if (ret != FSIO_READY) 64323a0898aSmrg { 64423a0898aSmrg *error = FSIO_BLOCK; 64523a0898aSmrg return 0; 64623a0898aSmrg } 64723a0898aSmrg 64823a0898aSmrg *error = FSIO_READY; 64941c30155Smrg 65023a0898aSmrg return (fsGenericReply *) buf; 65123a0898aSmrg} 65223a0898aSmrg 65323a0898aSmrgstatic Bool 65423a0898aSmrgfs_reply_ready (FSFpePtr conn) 65523a0898aSmrg{ 65623a0898aSmrg fsGenericReply *rep; 65741c30155Smrg 65823a0898aSmrg if (conn->fs_fd == -1 || !FD_ISSET (conn->fs_fd, &_fs_fd_mask)) 65923a0898aSmrg return FALSE; 66023a0898aSmrg if (fs_data_read (conn) < sizeof (fsGenericReply)) 66123a0898aSmrg return FALSE; 66223a0898aSmrg rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); 66323a0898aSmrg if (fs_data_read (conn) < rep->length << 2) 66423a0898aSmrg return FALSE; 66523a0898aSmrg return TRUE; 66623a0898aSmrg} 66723a0898aSmrg 66823a0898aSmrgstatic void 66923a0898aSmrg_fs_pending_reply (FSFpePtr conn) 67023a0898aSmrg{ 67123a0898aSmrg if (!(conn->blockState & FS_PENDING_REPLY)) 67223a0898aSmrg { 67323a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 67423a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 67523a0898aSmrg } 67623a0898aSmrg} 67723a0898aSmrg 67823a0898aSmrgstatic void 67923a0898aSmrg_fs_prepare_for_reply (FSFpePtr conn) 68023a0898aSmrg{ 68123a0898aSmrg _fs_pending_reply (conn); 68223a0898aSmrg _fs_flush (conn); 68323a0898aSmrg} 68423a0898aSmrg 68523a0898aSmrg/* 68623a0898aSmrg * Block (for a while) awaiting a complete reply 68723a0898aSmrg */ 68823a0898aSmrgstatic int 68923a0898aSmrgfs_await_reply (FSFpePtr conn) 69023a0898aSmrg{ 69123a0898aSmrg int ret; 69241c30155Smrg 69323a0898aSmrg if (conn->blockState & FS_COMPLETE_REPLY) 69423a0898aSmrg return FSIO_READY; 69541c30155Smrg 69623a0898aSmrg while (!fs_get_reply (conn, &ret)) 69723a0898aSmrg { 69823a0898aSmrg if (ret != FSIO_BLOCK) 69923a0898aSmrg return ret; 70023a0898aSmrg if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) 70123a0898aSmrg { 70223a0898aSmrg _fs_connection_died (conn); 70323a0898aSmrg return FSIO_ERROR; 70423a0898aSmrg } 70523a0898aSmrg } 70623a0898aSmrg return FSIO_READY; 70723a0898aSmrg} 70823a0898aSmrg 70923a0898aSmrg/* 71023a0898aSmrg * Process the reply to an OpenBitmapFont request 71123a0898aSmrg */ 71223a0898aSmrgstatic int 71323a0898aSmrgfs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 71423a0898aSmrg{ 71523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 71623a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 71723a0898aSmrg fsOpenBitmapFontReply *rep; 71823a0898aSmrg FSBlockDataPtr blockOrig; 71923a0898aSmrg FSBlockedFontPtr origBfont; 72023a0898aSmrg int ret; 72123a0898aSmrg 72223a0898aSmrg rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); 7239d21a897Sspz if (!rep || rep->type == FS_Error || 7247673729aSmrg (rep->length != LENGTHOF(fsOpenBitmapFontReply))) 72523a0898aSmrg { 72623a0898aSmrg if (ret == FSIO_BLOCK) 72723a0898aSmrg return StillWorking; 72823a0898aSmrg if (rep) 72923a0898aSmrg _fs_done_read (conn, rep->length << 2); 73023a0898aSmrg fs_cleanup_bfont (bfont); 7317673729aSmrg _fs_reply_failed (rep, fsOpenBitmapFontReply, "!="); 73223a0898aSmrg return BadFontName; 73323a0898aSmrg } 73441c30155Smrg 73523a0898aSmrg /* If we're not reopening a font and FS detected a duplicate font 73623a0898aSmrg open request, replace our reference to the new font with a 73723a0898aSmrg reference to an existing font (possibly one not finished 73823a0898aSmrg opening). If this is a reopen, keep the new font reference... 73923a0898aSmrg it's got the metrics and extents we read when the font was opened 74023a0898aSmrg before. This also gives us the freedom to easily close the font 74123a0898aSmrg if we we decide (in fs_read_query_info()) that we don't like what 74223a0898aSmrg we got. */ 74323a0898aSmrg 74441c30155Smrg if (rep->otherid && !(bfont->flags & FontReopen)) 74523a0898aSmrg { 74623a0898aSmrg fs_cleanup_bfont (bfont); 74741c30155Smrg 74823a0898aSmrg /* Find old font if we're completely done getting it from server. */ 74923a0898aSmrg bfont->pfont = find_old_font(rep->otherid); 75023a0898aSmrg bfont->freeFont = FALSE; 75123a0898aSmrg bfont->fontid = rep->otherid; 75223a0898aSmrg bfont->state = FS_DONE_REPLY; 75323a0898aSmrg /* 75423a0898aSmrg * look for a blocked request to open the same font 75523a0898aSmrg */ 75623a0898aSmrg for (blockOrig = conn->blockedRequests; 75723a0898aSmrg blockOrig; 75841c30155Smrg blockOrig = blockOrig->next) 75923a0898aSmrg { 76041c30155Smrg if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) 76123a0898aSmrg { 76223a0898aSmrg origBfont = (FSBlockedFontPtr) blockOrig->data; 76341c30155Smrg if (origBfont->fontid == rep->otherid) 76423a0898aSmrg { 76523a0898aSmrg blockrec->depending = blockOrig->depending; 76623a0898aSmrg blockOrig->depending = blockrec; 76723a0898aSmrg bfont->state = FS_DEPENDING; 76823a0898aSmrg bfont->pfont = origBfont->pfont; 76923a0898aSmrg break; 77023a0898aSmrg } 77123a0898aSmrg } 77223a0898aSmrg } 77323a0898aSmrg if (bfont->pfont == NULL) 77423a0898aSmrg { 77523a0898aSmrg /* XXX - something nasty happened */ 77623a0898aSmrg ret = BadFontName; 77723a0898aSmrg } 77823a0898aSmrg else 77923a0898aSmrg ret = AccessDone; 78023a0898aSmrg } 78123a0898aSmrg else 78223a0898aSmrg { 78323a0898aSmrg bfont->pfont->info.cachable = rep->cachable != 0; 78423a0898aSmrg bfont->state = FS_INFO_REPLY; 78523a0898aSmrg /* 78623a0898aSmrg * Reset the blockrec for the next reply 78723a0898aSmrg */ 78823a0898aSmrg blockrec->sequenceNumber = bfont->queryInfoSequence; 78923a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 79023a0898aSmrg ret = StillWorking; 79123a0898aSmrg } 79223a0898aSmrg _fs_done_read (conn, rep->length << 2); 79323a0898aSmrg return ret; 79423a0898aSmrg} 79523a0898aSmrg 79623a0898aSmrgstatic Bool 79723a0898aSmrgfs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) 79823a0898aSmrg{ 79923a0898aSmrg int i; 80041c30155Smrg 80123a0898aSmrg if (pInfo1->firstCol != pInfo2->firstCol || 80223a0898aSmrg pInfo1->lastCol != pInfo2->lastCol || 80323a0898aSmrg pInfo1->firstRow != pInfo2->firstRow || 80423a0898aSmrg pInfo1->lastRow != pInfo2->lastRow || 80523a0898aSmrg pInfo1->defaultCh != pInfo2->defaultCh || 80623a0898aSmrg pInfo1->noOverlap != pInfo2->noOverlap || 80723a0898aSmrg pInfo1->terminalFont != pInfo2->terminalFont || 80823a0898aSmrg pInfo1->constantMetrics != pInfo2->constantMetrics || 80923a0898aSmrg pInfo1->constantWidth != pInfo2->constantWidth || 81023a0898aSmrg pInfo1->inkInside != pInfo2->inkInside || 81123a0898aSmrg pInfo1->inkMetrics != pInfo2->inkMetrics || 81223a0898aSmrg pInfo1->allExist != pInfo2->allExist || 81323a0898aSmrg pInfo1->drawDirection != pInfo2->drawDirection || 81423a0898aSmrg pInfo1->cachable != pInfo2->cachable || 81523a0898aSmrg pInfo1->anamorphic != pInfo2->anamorphic || 81623a0898aSmrg pInfo1->maxOverlap != pInfo2->maxOverlap || 81723a0898aSmrg pInfo1->fontAscent != pInfo2->fontAscent || 81823a0898aSmrg pInfo1->fontDescent != pInfo2->fontDescent || 81923a0898aSmrg pInfo1->nprops != pInfo2->nprops) 82023a0898aSmrg return FALSE; 82123a0898aSmrg 82223a0898aSmrg#define MATCH(xci1, xci2) \ 82323a0898aSmrg (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ 82423a0898aSmrg ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ 82523a0898aSmrg ((xci1).characterWidth == (xci2).characterWidth) && \ 82623a0898aSmrg ((xci1).ascent == (xci2).ascent) && \ 82723a0898aSmrg ((xci1).descent == (xci2).descent) && \ 82823a0898aSmrg ((xci1).attributes == (xci2).attributes)) 82923a0898aSmrg 83023a0898aSmrg if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || 83123a0898aSmrg !MATCH(pInfo1->minbounds, pInfo2->minbounds) || 83223a0898aSmrg !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || 83323a0898aSmrg !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) 83423a0898aSmrg return FALSE; 83523a0898aSmrg 83623a0898aSmrg#undef MATCH 83723a0898aSmrg 83823a0898aSmrg for (i = 0; i < pInfo1->nprops; i++) 83923a0898aSmrg if (pInfo1->isStringProp[i] != 84023a0898aSmrg pInfo2->isStringProp[i] || 84123a0898aSmrg pInfo1->props[i].name != 84223a0898aSmrg pInfo2->props[i].name || 84323a0898aSmrg pInfo1->props[i].value != 84423a0898aSmrg pInfo2->props[i].value) 84523a0898aSmrg { 84623a0898aSmrg return FALSE; 84723a0898aSmrg } 84823a0898aSmrg return TRUE; 84923a0898aSmrg} 85023a0898aSmrg 85123a0898aSmrgstatic int 85223a0898aSmrgfs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 85323a0898aSmrg{ 85423a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 85523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 85623a0898aSmrg fsQueryXInfoReply *rep; 85723a0898aSmrg char *buf; 8587673729aSmrg long bufleft; /* length of reply left to use */ 85923a0898aSmrg fsPropInfo *pi; 86023a0898aSmrg fsPropOffset *po; 86123a0898aSmrg pointer pd; 86223a0898aSmrg FontInfoPtr pInfo; 86323a0898aSmrg FontInfoRec tempInfo; 86423a0898aSmrg int err; 86523a0898aSmrg int ret; 86623a0898aSmrg 86723a0898aSmrg rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); 8689d21a897Sspz if (!rep || rep->type == FS_Error || 8697673729aSmrg (rep->length < LENGTHOF(fsQueryXInfoReply))) 87023a0898aSmrg { 87123a0898aSmrg if (ret == FSIO_BLOCK) 87223a0898aSmrg return StillWorking; 87323a0898aSmrg if (rep) 87423a0898aSmrg _fs_done_read (conn, rep->length << 2); 87523a0898aSmrg fs_cleanup_bfont (bfont); 8767673729aSmrg _fs_reply_failed (rep, fsQueryXInfoReply, "<"); 87723a0898aSmrg return BadFontName; 87823a0898aSmrg } 87941c30155Smrg 88023a0898aSmrg /* If this is a reopen, accumulate the query info into a dummy 88123a0898aSmrg font and compare to our original data. */ 88223a0898aSmrg if (bfont->flags & FontReopen) 88323a0898aSmrg pInfo = &tempInfo; 88423a0898aSmrg else 88523a0898aSmrg pInfo = &bfont->pfont->info; 88623a0898aSmrg 88723a0898aSmrg buf = (char *) rep; 88823a0898aSmrg buf += SIZEOF(fsQueryXInfoReply); 88941c30155Smrg 8909d21a897Sspz bufleft = rep->length << 2; 8919d21a897Sspz bufleft -= SIZEOF(fsQueryXInfoReply); 8929d21a897Sspz 89323a0898aSmrg /* move the data over */ 89423a0898aSmrg fsUnpack_XFontInfoHeader(rep, pInfo); 89541c30155Smrg 89623a0898aSmrg /* compute accelerators */ 89723a0898aSmrg _fs_init_fontinfo(conn, pInfo); 89823a0898aSmrg 89923a0898aSmrg /* Compute offsets into the reply */ 9009d21a897Sspz if (bufleft < SIZEOF(fsPropInfo)) 9019d21a897Sspz { 9027673729aSmrg ret = -1; 9039d21a897Sspz#ifdef DEBUG 9047673729aSmrg fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n", 9057673729aSmrg bufleft); 9069d21a897Sspz#endif 9077673729aSmrg goto bail; 9089d21a897Sspz } 90923a0898aSmrg pi = (fsPropInfo *) buf; 91023a0898aSmrg buf += SIZEOF (fsPropInfo); 9119d21a897Sspz bufleft -= SIZEOF(fsPropInfo); 91241c30155Smrg 9139d21a897Sspz if ((bufleft / SIZEOF(fsPropOffset)) < pi->num_offsets) 9149d21a897Sspz { 9157673729aSmrg ret = -1; 9169d21a897Sspz#ifdef DEBUG 9177673729aSmrg fprintf(stderr, 91881d6fa61Srin "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %u\n", 91981d6fa61Srin bufleft, (unsigned) pi->num_offsets); 9209d21a897Sspz#endif 9217673729aSmrg goto bail; 9229d21a897Sspz } 92323a0898aSmrg po = (fsPropOffset *) buf; 92423a0898aSmrg buf += pi->num_offsets * SIZEOF(fsPropOffset); 9259d21a897Sspz bufleft -= pi->num_offsets * SIZEOF(fsPropOffset); 92623a0898aSmrg 9279d21a897Sspz if (bufleft < pi->data_len) 9289d21a897Sspz { 9297673729aSmrg ret = -1; 9309d21a897Sspz#ifdef DEBUG 9317673729aSmrg fprintf(stderr, 93281d6fa61Srin "fsQueryXInfo: bufleft (%ld) < data_len (%u)\n", 93381d6fa61Srin bufleft, (unsigned) pi->data_len); 9349d21a897Sspz#endif 9357673729aSmrg goto bail; 9369d21a897Sspz } 93723a0898aSmrg pd = (pointer) buf; 93823a0898aSmrg buf += pi->data_len; 9399d21a897Sspz bufleft -= pi->data_len; 94041c30155Smrg 94123a0898aSmrg /* convert the properties and step over the reply */ 94223a0898aSmrg ret = _fs_convert_props(pi, po, pd, pInfo); 9439d21a897Sspz bail: 94423a0898aSmrg _fs_done_read (conn, rep->length << 2); 94541c30155Smrg 94623a0898aSmrg if (ret == -1) 94723a0898aSmrg { 94823a0898aSmrg fs_cleanup_bfont (bfont); 94923a0898aSmrg return AllocError; 95023a0898aSmrg } 95123a0898aSmrg 95223a0898aSmrg if (bfont->flags & FontReopen) 95323a0898aSmrg { 95423a0898aSmrg /* We're reopening a font that we lost because of a downed 95523a0898aSmrg connection. In the interest of avoiding corruption from 95623a0898aSmrg opening a different font than the old one (we already have 95723a0898aSmrg its metrics, extents, and probably some of its glyphs), 95823a0898aSmrg verify that the metrics and properties all match. */ 95923a0898aSmrg 96023a0898aSmrg if (fs_fonts_match (pInfo, &bfont->pfont->info)) 96123a0898aSmrg { 96223a0898aSmrg err = Successful; 96323a0898aSmrg bfont->state = FS_DONE_REPLY; 96423a0898aSmrg } 96523a0898aSmrg else 96623a0898aSmrg { 96723a0898aSmrg fs_cleanup_bfont (bfont); 96823a0898aSmrg err = BadFontName; 96923a0898aSmrg } 97023a0898aSmrg _fs_free_props (pInfo); 97141c30155Smrg 97223a0898aSmrg return err; 97323a0898aSmrg } 97423a0898aSmrg 97523a0898aSmrg /* 97623a0898aSmrg * Ask for terminal format fonts if possible 97723a0898aSmrg */ 97823a0898aSmrg if (bfont->pfont->info.terminalFont) 97923a0898aSmrg bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | 98023a0898aSmrg BitmapFormatImageRectMax); 98123a0898aSmrg 98223a0898aSmrg /* 98323a0898aSmrg * Figure out if the whole font should get loaded right now. 98423a0898aSmrg */ 98523a0898aSmrg if (glyphCachingMode == CACHING_OFF || 98641c30155Smrg (glyphCachingMode == CACHE_16_BIT_GLYPHS 98723a0898aSmrg && !bfont->pfont->info.lastRow)) 98823a0898aSmrg { 98923a0898aSmrg bfont->flags |= FontLoadAll; 99023a0898aSmrg } 99141c30155Smrg 99223a0898aSmrg /* 99341c30155Smrg * Ready to send the query bitmaps; the terminal font bit has 99423a0898aSmrg * been computed and glyphCaching has been considered 99523a0898aSmrg */ 99623a0898aSmrg if (bfont->flags & FontLoadBitmaps) 99723a0898aSmrg { 99823a0898aSmrg fs_send_query_bitmaps (fpe, blockrec); 99923a0898aSmrg _fs_flush (conn); 100023a0898aSmrg } 100123a0898aSmrg 100223a0898aSmrg bfont->state = FS_EXTENT_REPLY; 100323a0898aSmrg 100423a0898aSmrg /* 100523a0898aSmrg * Reset the blockrec for the next reply 100623a0898aSmrg */ 100723a0898aSmrg blockrec->sequenceNumber = bfont->queryExtentsSequence; 100823a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 100941c30155Smrg 101023a0898aSmrg return StillWorking; 101123a0898aSmrg} 101223a0898aSmrg 101323a0898aSmrgstatic int 101423a0898aSmrgfs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 101523a0898aSmrg{ 101623a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 101723a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 101823a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; 101923a0898aSmrg FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; 102023a0898aSmrg fsQueryXExtents16Reply *rep; 102123a0898aSmrg char *buf; 102223a0898aSmrg int i; 102323a0898aSmrg int numExtents; 102423a0898aSmrg int numInfos; 102523a0898aSmrg int ret; 102623a0898aSmrg Bool haveInk = FALSE; /* need separate ink metrics? */ 102723a0898aSmrg CharInfoPtr ci, pCI; 102823a0898aSmrg char *fsci; 102923a0898aSmrg fsXCharInfo fscilocal; 103023a0898aSmrg FontInfoRec *fi = &bfont->pfont->info; 103123a0898aSmrg 103223a0898aSmrg rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); 10339d21a897Sspz if (!rep || rep->type == FS_Error || 10347673729aSmrg (rep->length < LENGTHOF(fsQueryXExtents16Reply))) 103523a0898aSmrg { 103623a0898aSmrg if (ret == FSIO_BLOCK) 103723a0898aSmrg return StillWorking; 103823a0898aSmrg if (rep) 103923a0898aSmrg _fs_done_read (conn, rep->length << 2); 104023a0898aSmrg fs_cleanup_bfont (bfont); 10417673729aSmrg _fs_reply_failed (rep, fsQueryXExtents16Reply, "<"); 104223a0898aSmrg return BadFontName; 104323a0898aSmrg } 104441c30155Smrg 104523a0898aSmrg /* move the data over */ 104623a0898aSmrg /* need separate inkMetrics for fixed font server protocol version */ 104723a0898aSmrg numExtents = rep->num_extents; 104823a0898aSmrg numInfos = numExtents; 104923a0898aSmrg if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) 105023a0898aSmrg { 105123a0898aSmrg numInfos *= 2; 105223a0898aSmrg haveInk = TRUE; 105323a0898aSmrg } 10549d21a897Sspz if (numInfos >= (INT_MAX / sizeof(CharInfoRec))) { 10559d21a897Sspz#ifdef DEBUG 10567673729aSmrg fprintf(stderr, 10577673729aSmrg "fsQueryXExtents16: numInfos (%d) >= %ld\n", 10587673729aSmrg numInfos, (INT_MAX / sizeof(CharInfoRec))); 10599d21a897Sspz#endif 10607673729aSmrg pCI = NULL; 10619d21a897Sspz } 10629d21a897Sspz else if (numExtents > ((rep->length - LENGTHOF(fsQueryXExtents16Reply)) 10637673729aSmrg / LENGTHOF(fsXCharInfo))) { 10649d21a897Sspz#ifdef DEBUG 10657673729aSmrg fprintf(stderr, 106681d6fa61Srin "fsQueryXExtents16: numExtents (%d) > (%u - %d) / %d\n", 106781d6fa61Srin numExtents, (unsigned) rep->length, 10687673729aSmrg LENGTHOF(fsQueryXExtents16Reply), LENGTHOF(fsXCharInfo)); 10699d21a897Sspz#endif 10707673729aSmrg pCI = NULL; 10719d21a897Sspz } 10729d21a897Sspz else 10737673729aSmrg pCI = malloc(sizeof(CharInfoRec) * numInfos); 107423a0898aSmrg 107541c30155Smrg if (!pCI) 107623a0898aSmrg { 107723a0898aSmrg _fs_done_read (conn, rep->length << 2); 107823a0898aSmrg fs_cleanup_bfont(bfont); 107923a0898aSmrg return AllocError; 108023a0898aSmrg } 108123a0898aSmrg fsfont->encoding = pCI; 108223a0898aSmrg if (haveInk) 108323a0898aSmrg fsfont->inkMetrics = pCI + numExtents; 108423a0898aSmrg else 108523a0898aSmrg fsfont->inkMetrics = pCI; 108623a0898aSmrg 108723a0898aSmrg buf = (char *) rep; 108823a0898aSmrg buf += SIZEOF (fsQueryXExtents16Reply); 108923a0898aSmrg fsci = buf; 109041c30155Smrg 109123a0898aSmrg fsd->glyphs_to_get = 0; 109223a0898aSmrg ci = fsfont->inkMetrics; 109341c30155Smrg for (i = 0; i < numExtents; i++) 109423a0898aSmrg { 109523a0898aSmrg memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ 109623a0898aSmrg _fs_convert_char_info(&fscilocal, &ci->metrics); 109723a0898aSmrg /* Bounds check. */ 109823a0898aSmrg if (ci->metrics.ascent > fi->maxbounds.ascent) 109923a0898aSmrg { 110023a0898aSmrg ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", 110123a0898aSmrg fpe->name, fsd->name, 110223a0898aSmrg ci->metrics.ascent, fi->maxbounds.ascent); 110323a0898aSmrg ci->metrics.ascent = fi->maxbounds.ascent; 110423a0898aSmrg } 110523a0898aSmrg if (ci->metrics.descent > fi->maxbounds.descent) 110623a0898aSmrg { 110723a0898aSmrg ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", 110823a0898aSmrg fpe->name, fsd->name, 110923a0898aSmrg ci->metrics.descent, fi->maxbounds.descent); 111023a0898aSmrg ci->metrics.descent = fi->maxbounds.descent; 111123a0898aSmrg } 111223a0898aSmrg fsci = fsci + SIZEOF(fsXCharInfo); 111323a0898aSmrg /* Initialize the bits field for later glyph-caching use */ 111423a0898aSmrg if (NONZEROMETRICS(&ci->metrics)) 111523a0898aSmrg { 111623a0898aSmrg if (!haveInk && 111723a0898aSmrg (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || 111823a0898aSmrg ci->metrics.ascent == -ci->metrics.descent)) 111923a0898aSmrg pCI[i].bits = &_fs_glyph_zero_length; 112023a0898aSmrg else 112123a0898aSmrg { 112223a0898aSmrg pCI[i].bits = &_fs_glyph_undefined; 112323a0898aSmrg fsd->glyphs_to_get++; 112423a0898aSmrg } 112523a0898aSmrg } 112623a0898aSmrg else 112723a0898aSmrg pCI[i].bits = (char *)0; 112823a0898aSmrg ci++; 112923a0898aSmrg } 113023a0898aSmrg 113123a0898aSmrg /* Done with reply */ 113223a0898aSmrg _fs_done_read (conn, rep->length << 2); 113341c30155Smrg 113423a0898aSmrg /* build bitmap metrics, ImageRectMax style */ 113523a0898aSmrg if (haveInk) 113623a0898aSmrg { 113723a0898aSmrg CharInfoPtr ii; 113823a0898aSmrg 113923a0898aSmrg ci = fsfont->encoding; 114023a0898aSmrg ii = fsfont->inkMetrics; 114123a0898aSmrg for (i = 0; i < numExtents; i++, ci++, ii++) 114223a0898aSmrg { 114323a0898aSmrg if (NONZEROMETRICS(&ii->metrics)) 114423a0898aSmrg { 114523a0898aSmrg ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); 114623a0898aSmrg ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); 114723a0898aSmrg ci->metrics.ascent = FONT_MAX_ASCENT(fi); 114823a0898aSmrg ci->metrics.descent = FONT_MAX_DESCENT(fi); 114923a0898aSmrg ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); 115023a0898aSmrg ci->metrics.attributes = ii->metrics.attributes; 115123a0898aSmrg } 115223a0898aSmrg else 115323a0898aSmrg { 115423a0898aSmrg ci->metrics = ii->metrics; 115523a0898aSmrg } 115623a0898aSmrg /* Bounds check. */ 115723a0898aSmrg if (ci->metrics.ascent > fi->maxbounds.ascent) 115823a0898aSmrg { 115923a0898aSmrg ErrorF("fserve: warning: %s %s ascent (%d) " 116023a0898aSmrg "> maxascent (%d)\n", 116123a0898aSmrg fpe->name, fsd->name, 116223a0898aSmrg ci->metrics.ascent, fi->maxbounds.ascent); 116323a0898aSmrg ci->metrics.ascent = fi->maxbounds.ascent; 116423a0898aSmrg } 116523a0898aSmrg if (ci->metrics.descent > fi->maxbounds.descent) 116623a0898aSmrg { 116723a0898aSmrg ErrorF("fserve: warning: %s %s descent (%d) " 116823a0898aSmrg "> maxdescent (%d)\n", 116923a0898aSmrg fpe->name, fsd->name, 117023a0898aSmrg ci->metrics.descent, fi->maxbounds.descent); 117123a0898aSmrg ci->metrics.descent = fi->maxbounds.descent; 117223a0898aSmrg } 117323a0898aSmrg } 117423a0898aSmrg } 117523a0898aSmrg { 117623a0898aSmrg unsigned int r, c, numCols, firstCol; 117723a0898aSmrg 117823a0898aSmrg firstCol = bfont->pfont->info.firstCol; 117923a0898aSmrg numCols = bfont->pfont->info.lastCol - firstCol + 1; 118023a0898aSmrg c = bfont->pfont->info.defaultCh; 118123a0898aSmrg fsfont->pDefault = 0; 118223a0898aSmrg if (bfont->pfont->info.lastRow) 118323a0898aSmrg { 118423a0898aSmrg r = c >> 8; 118523a0898aSmrg r -= bfont->pfont->info.firstRow; 118623a0898aSmrg c &= 0xff; 118723a0898aSmrg c -= firstCol; 118823a0898aSmrg if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && 118923a0898aSmrg c < numCols) 119023a0898aSmrg fsfont->pDefault = &pCI[r * numCols + c]; 119123a0898aSmrg } 119223a0898aSmrg else 119323a0898aSmrg { 119423a0898aSmrg c -= firstCol; 119523a0898aSmrg if (c < numCols) 119623a0898aSmrg fsfont->pDefault = &pCI[c]; 119723a0898aSmrg } 119823a0898aSmrg } 119923a0898aSmrg bfont->state = FS_GLYPHS_REPLY; 120023a0898aSmrg 120141c30155Smrg if (bfont->flags & FontLoadBitmaps) 120223a0898aSmrg { 120323a0898aSmrg /* 120423a0898aSmrg * Reset the blockrec for the next reply 120523a0898aSmrg */ 120623a0898aSmrg blockrec->sequenceNumber = bfont->queryBitmapsSequence; 120723a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 120823a0898aSmrg return StillWorking; 120923a0898aSmrg } 121023a0898aSmrg return Successful; 121123a0898aSmrg} 121223a0898aSmrg 121323a0898aSmrg#ifdef DEBUG 12147673729aSmrgstatic const char *fs_open_states[] = { 121523a0898aSmrg "OPEN_REPLY ", 121623a0898aSmrg "INFO_REPLY ", 121723a0898aSmrg "EXTENT_REPLY", 121823a0898aSmrg "GLYPHS_REPLY", 121923a0898aSmrg "DONE_REPLY ", 122023a0898aSmrg "DEPENDING ", 122123a0898aSmrg}; 122223a0898aSmrg#endif 122323a0898aSmrg 122423a0898aSmrgstatic int 122523a0898aSmrgfs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 122623a0898aSmrg{ 122723a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 122823a0898aSmrg int err; 122923a0898aSmrg 123023a0898aSmrg#ifdef DEBUG 123123a0898aSmrg fprintf (stderr, "fs_do_open_font state %s %s\n", 123241c30155Smrg fs_open_states[bfont->state], 123323a0898aSmrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); 123423a0898aSmrg#endif 123523a0898aSmrg err = BadFontName; 123623a0898aSmrg switch (bfont->state) { 123723a0898aSmrg case FS_OPEN_REPLY: 123823a0898aSmrg err = fs_read_open_font(fpe, blockrec); 123923a0898aSmrg if (err != StillWorking) { /* already loaded, or error */ 124023a0898aSmrg /* if font's already loaded, massage error code */ 124123a0898aSmrg switch (bfont->state) { 124223a0898aSmrg case FS_DONE_REPLY: 124323a0898aSmrg err = Successful; 124423a0898aSmrg break; 124523a0898aSmrg case FS_DEPENDING: 124623a0898aSmrg err = StillWorking; 124723a0898aSmrg break; 124823a0898aSmrg } 124923a0898aSmrg } 125023a0898aSmrg break; 125123a0898aSmrg case FS_INFO_REPLY: 125223a0898aSmrg err = fs_read_query_info(fpe, blockrec); 125323a0898aSmrg break; 125423a0898aSmrg case FS_EXTENT_REPLY: 125523a0898aSmrg err = fs_read_extent_info(fpe, blockrec); 125623a0898aSmrg break; 125723a0898aSmrg case FS_GLYPHS_REPLY: 125823a0898aSmrg if (bfont->flags & FontLoadBitmaps) 125923a0898aSmrg err = fs_read_glyphs(fpe, blockrec); 126023a0898aSmrg break; 126123a0898aSmrg case FS_DEPENDING: /* can't happen */ 126223a0898aSmrg default: 126323a0898aSmrg break; 126423a0898aSmrg } 126523a0898aSmrg#ifdef DEBUG 126623a0898aSmrg fprintf (stderr, "fs_do_open_font err %d\n", err); 126723a0898aSmrg#endif 126841c30155Smrg if (err != StillWorking) 126923a0898aSmrg { 127023a0898aSmrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 127141c30155Smrg while ((blockrec = blockrec->depending)) 127223a0898aSmrg { 127323a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 127423a0898aSmrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 127523a0898aSmrg } 127623a0898aSmrg } 127723a0898aSmrg return err; 127823a0898aSmrg} 127923a0898aSmrg 128023a0898aSmrgvoid 128123a0898aSmrg_fs_mark_block (FSFpePtr conn, CARD32 mask) 128223a0898aSmrg{ 128323a0898aSmrg conn->blockState |= mask; 128423a0898aSmrg fs_blockState |= mask; 128523a0898aSmrg} 128623a0898aSmrg 128723a0898aSmrgvoid 128823a0898aSmrg_fs_unmark_block (FSFpePtr conn, CARD32 mask) 128923a0898aSmrg{ 129023a0898aSmrg FSFpePtr c; 129141c30155Smrg 129223a0898aSmrg if (conn->blockState & mask) 129323a0898aSmrg { 129423a0898aSmrg conn->blockState &= ~mask; 129523a0898aSmrg fs_blockState = 0; 129623a0898aSmrg for (c = fs_fpes; c; c = c->next) 129723a0898aSmrg fs_blockState |= c->blockState; 129823a0898aSmrg } 129923a0898aSmrg} 130023a0898aSmrg 130123a0898aSmrg/* ARGSUSED */ 130223a0898aSmrgstatic void 130323a0898aSmrgfs_block_handler(pointer data, OSTimePtr wt, pointer LastSelectMask) 130423a0898aSmrg{ 130523a0898aSmrg static struct timeval block_timeout; 130623a0898aSmrg CARD32 now, earliest, wakeup; 130723a0898aSmrg int soonest; 130823a0898aSmrg FSFpePtr conn; 130923a0898aSmrg 131041c30155Smrg XFD_ORSET((fd_set *)LastSelectMask, (fd_set *)LastSelectMask, 131123a0898aSmrg &_fs_fd_mask); 131223a0898aSmrg /* 131323a0898aSmrg * Flush all pending output 131423a0898aSmrg */ 131523a0898aSmrg if (fs_blockState & FS_PENDING_WRITE) 131623a0898aSmrg for (conn = fs_fpes; conn; conn = conn->next) 131723a0898aSmrg if (conn->blockState & FS_PENDING_WRITE) 131823a0898aSmrg _fs_flush (conn); 131923a0898aSmrg /* 132023a0898aSmrg * Check for any fpe with a complete reply, set sleep time to zero 132123a0898aSmrg */ 132223a0898aSmrg if (fs_blockState & FS_COMPLETE_REPLY) 132323a0898aSmrg { 132423a0898aSmrg block_timeout.tv_sec = 0; 132523a0898aSmrg block_timeout.tv_usec = 0; 132623a0898aSmrg if (*wt == NULL) 132723a0898aSmrg *wt = &block_timeout; 132823a0898aSmrg else 132923a0898aSmrg **wt = block_timeout; 133023a0898aSmrg } 133123a0898aSmrg /* 133223a0898aSmrg * Walk through fpe list computing sleep time 133323a0898aSmrg */ 133423a0898aSmrg else if (fs_blockState & (FS_BROKEN_WRITE| 133523a0898aSmrg FS_BROKEN_CONNECTION| 133623a0898aSmrg FS_PENDING_REPLY| 133723a0898aSmrg FS_RECONNECTING)) 133823a0898aSmrg { 133923a0898aSmrg now = GetTimeInMillis (); 134023a0898aSmrg earliest = now + 10000000; 134123a0898aSmrg for (conn = fs_fpes; conn; conn = conn->next) 134223a0898aSmrg { 134323a0898aSmrg if (conn->blockState & FS_RECONNECTING) 134423a0898aSmrg { 134523a0898aSmrg wakeup = conn->blockedConnectTime; 134623a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 134723a0898aSmrg earliest = wakeup; 134823a0898aSmrg } 134923a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 135023a0898aSmrg { 135123a0898aSmrg wakeup = conn->brokenConnectionTime; 135223a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 135323a0898aSmrg earliest = wakeup; 135423a0898aSmrg } 135523a0898aSmrg if (conn->blockState & FS_BROKEN_WRITE) 135623a0898aSmrg { 135723a0898aSmrg wakeup = conn->brokenWriteTime; 135823a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 135923a0898aSmrg earliest = wakeup; 136023a0898aSmrg } 136123a0898aSmrg if (conn->blockState & FS_PENDING_REPLY) 136223a0898aSmrg { 136323a0898aSmrg wakeup = conn->blockedReplyTime; 136423a0898aSmrg if (TimeCmp (wakeup, <, earliest)) 136523a0898aSmrg earliest = wakeup; 136623a0898aSmrg } 136723a0898aSmrg } 136823a0898aSmrg soonest = earliest - now; 136923a0898aSmrg if (soonest < 0) 137023a0898aSmrg soonest = 0; 137123a0898aSmrg block_timeout.tv_sec = soonest / 1000; 137223a0898aSmrg block_timeout.tv_usec = (soonest % 1000) * 1000; 137323a0898aSmrg if (*wt == NULL) 137423a0898aSmrg *wt = &block_timeout; 137523a0898aSmrg else if (soonest < (*wt)->tv_sec * 1000 + (*wt)->tv_usec / 1000) 137623a0898aSmrg **wt = block_timeout; 137723a0898aSmrg } 137823a0898aSmrg} 137923a0898aSmrg 138023a0898aSmrgstatic void 138123a0898aSmrgfs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) 138223a0898aSmrg{ 138341c30155Smrg if (rep->type == FS_Event && rep->data1 == KeepAlive) 138423a0898aSmrg { 138523a0898aSmrg fsNoopReq req; 138623a0898aSmrg 138723a0898aSmrg /* ping it back */ 138823a0898aSmrg req.reqType = FS_Noop; 138923a0898aSmrg req.length = SIZEOF(fsNoopReq) >> 2; 139023a0898aSmrg _fs_add_req_log(conn, FS_Noop); 139123a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); 139223a0898aSmrg } 139323a0898aSmrg /* this should suck up unexpected replies and events */ 139423a0898aSmrg _fs_done_read (conn, rep->length << 2); 139523a0898aSmrg} 139623a0898aSmrg 139723a0898aSmrgstatic void 139823a0898aSmrgfs_read_reply (FontPathElementPtr fpe, pointer client) 139923a0898aSmrg{ 140023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 140123a0898aSmrg FSBlockDataPtr blockrec; 140223a0898aSmrg int ret; 140323a0898aSmrg int err; 140423a0898aSmrg fsGenericReply *rep; 140541c30155Smrg 140623a0898aSmrg if ((rep = fs_get_reply (conn, &ret))) 140723a0898aSmrg { 140823a0898aSmrg _fs_add_rep_log (conn, rep); 140941c30155Smrg for (blockrec = conn->blockedRequests; 141041c30155Smrg blockrec; 141141c30155Smrg blockrec = blockrec->next) 141223a0898aSmrg { 141323a0898aSmrg if (blockrec->sequenceNumber == rep->sequenceNumber) 141423a0898aSmrg break; 141523a0898aSmrg } 141623a0898aSmrg err = Successful; 141741c30155Smrg if (!blockrec) 141823a0898aSmrg { 141923a0898aSmrg fs_handle_unexpected(conn, rep); 142023a0898aSmrg } 142123a0898aSmrg else 142223a0898aSmrg { 142341c30155Smrg /* 142441c30155Smrg * go read it, and if we're done, 142541c30155Smrg * wake up the appropriate client 142623a0898aSmrg */ 142723a0898aSmrg switch (blockrec->type) { 142823a0898aSmrg case FS_OPEN_FONT: 142923a0898aSmrg blockrec->errcode = fs_do_open_font(fpe, blockrec); 143023a0898aSmrg break; 143123a0898aSmrg case FS_LOAD_GLYPHS: 143223a0898aSmrg blockrec->errcode = fs_read_glyphs(fpe, blockrec); 143323a0898aSmrg break; 143423a0898aSmrg case FS_LIST_FONTS: 143523a0898aSmrg blockrec->errcode = fs_read_list(fpe, blockrec); 143623a0898aSmrg break; 143723a0898aSmrg case FS_LIST_WITH_INFO: 143823a0898aSmrg blockrec->errcode = fs_read_list_info(fpe, blockrec); 143923a0898aSmrg break; 144023a0898aSmrg default: 144123a0898aSmrg break; 144223a0898aSmrg } 144323a0898aSmrg err = blockrec->errcode; 144423a0898aSmrg if (err != StillWorking) 144523a0898aSmrg { 144641c30155Smrg while (blockrec) 144723a0898aSmrg { 144823a0898aSmrg blockrec->errcode = err; 144923a0898aSmrg if (client != blockrec->client) 145023a0898aSmrg ClientSignal(blockrec->client); 145123a0898aSmrg blockrec = blockrec->depending; 145223a0898aSmrg } 145323a0898aSmrg _fs_unmark_block (conn, FS_PENDING_REPLY); 145423a0898aSmrg } 145523a0898aSmrg } 145623a0898aSmrg if (fs_reply_ready (conn)) 145723a0898aSmrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 145823a0898aSmrg else 145923a0898aSmrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 146023a0898aSmrg } 146123a0898aSmrg} 146223a0898aSmrg 146323a0898aSmrgstatic int 146423a0898aSmrgfs_wakeup(FontPathElementPtr fpe, unsigned long *mask) 146523a0898aSmrg{ 146623a0898aSmrg fd_set *LastSelectMask = (fd_set *) mask; 146723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 146823a0898aSmrg 146941c30155Smrg /* 147023a0898aSmrg * Don't continue if the fd is -1 (which will be true when the 147123a0898aSmrg * font server terminates 147223a0898aSmrg */ 147323a0898aSmrg if ((conn->blockState & FS_RECONNECTING)) 147423a0898aSmrg _fs_check_reconnect (conn); 147523a0898aSmrg else if ((conn->blockState & FS_COMPLETE_REPLY) || 147623a0898aSmrg (conn->fs_fd != -1 && FD_ISSET(conn->fs_fd, LastSelectMask))) 147723a0898aSmrg fs_read_reply (fpe, 0); 147823a0898aSmrg if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) 147923a0898aSmrg _fs_do_blocked (conn); 148023a0898aSmrg#ifdef DEBUG 148123a0898aSmrg { 148223a0898aSmrg FSBlockDataPtr blockrec; 148323a0898aSmrg FSBlockedFontPtr bfont; 148423a0898aSmrg static CARD32 lastState; 148523a0898aSmrg static FSBlockDataPtr lastBlock; 148623a0898aSmrg 148723a0898aSmrg if (conn->blockState || conn->blockedRequests || lastState || lastBlock) 148823a0898aSmrg { 148923a0898aSmrg fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); 149023a0898aSmrg lastState = conn->blockState; 149123a0898aSmrg lastBlock = conn->blockedRequests; 149223a0898aSmrg } 149323a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 149423a0898aSmrg { 149523a0898aSmrg switch (blockrec->type) { 149623a0898aSmrg case FS_OPEN_FONT: 149723a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 149823a0898aSmrg fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", 149923a0898aSmrg blockrec->errcode, 150023a0898aSmrg blockrec->sequenceNumber, 150123a0898aSmrg fs_open_states[bfont->state], 150241c30155Smrg bfont->pfont ? 150323a0898aSmrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : 150423a0898aSmrg "<freed>"); 150523a0898aSmrg break; 150623a0898aSmrg case FS_LIST_FONTS: 150723a0898aSmrg fprintf (stderr, " Blocked list errcode %d sequence %d\n", 150823a0898aSmrg blockrec->errcode, blockrec->sequenceNumber); 150923a0898aSmrg break; 151023a0898aSmrg default: 151123a0898aSmrg fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", 151223a0898aSmrg blockrec->type, 151323a0898aSmrg blockrec->errcode, 151423a0898aSmrg blockrec->sequenceNumber); 151523a0898aSmrg break; 151623a0898aSmrg } 151723a0898aSmrg } 151823a0898aSmrg } 151941c30155Smrg#endif 152023a0898aSmrg return FALSE; 152123a0898aSmrg} 152223a0898aSmrg 152323a0898aSmrg/* 152423a0898aSmrg * Notice a dead connection and prepare for reconnect 152523a0898aSmrg */ 152623a0898aSmrg 152723a0898aSmrgvoid 152823a0898aSmrg_fs_connection_died(FSFpePtr conn) 152923a0898aSmrg{ 153023a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 153123a0898aSmrg return; 153223a0898aSmrg fs_close_conn(conn); 153323a0898aSmrg conn->brokenConnectionTime = GetTimeInMillis (); 153423a0898aSmrg _fs_mark_block (conn, FS_BROKEN_CONNECTION); 153523a0898aSmrg _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); 153623a0898aSmrg} 153723a0898aSmrg 153823a0898aSmrg/* 153923a0898aSmrg * Signal clients that the connection has come back up 154023a0898aSmrg */ 154123a0898aSmrgstatic int 154223a0898aSmrg_fs_restart_connection(FSFpePtr conn) 154323a0898aSmrg{ 154423a0898aSmrg FSBlockDataPtr block; 154523a0898aSmrg 154623a0898aSmrg _fs_unmark_block (conn, FS_GIVE_UP); 154741c30155Smrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 154823a0898aSmrg { 154923a0898aSmrg if (block->errcode == StillWorking) 155023a0898aSmrg { 155123a0898aSmrg ClientSignal(block->client); 155223a0898aSmrg fs_abort_blockrec(conn, block); 155323a0898aSmrg } 155423a0898aSmrg } 155523a0898aSmrg return TRUE; 155623a0898aSmrg} 155723a0898aSmrg 155823a0898aSmrg/* 155923a0898aSmrg * Declare this font server connection useless 156023a0898aSmrg */ 156123a0898aSmrgstatic void 156223a0898aSmrg_fs_giveup (FSFpePtr conn) 156323a0898aSmrg{ 156423a0898aSmrg FSBlockDataPtr block; 156523a0898aSmrg 156623a0898aSmrg if (conn->blockState & FS_GIVE_UP) 156723a0898aSmrg return; 156823a0898aSmrg#ifdef DEBUG 156923a0898aSmrg fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); 157023a0898aSmrg#endif 157123a0898aSmrg _fs_mark_block (conn, FS_GIVE_UP); 157241c30155Smrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 157323a0898aSmrg { 157423a0898aSmrg if (block->errcode == StillWorking) 157523a0898aSmrg { 157623a0898aSmrg ClientSignal (block->client); 157723a0898aSmrg fs_abort_blockrec (conn, block); 157823a0898aSmrg } 157923a0898aSmrg } 158023a0898aSmrg if (conn->fs_fd >= 0) 158123a0898aSmrg _fs_connection_died (conn); 158223a0898aSmrg} 158323a0898aSmrg 158423a0898aSmrgstatic void 158523a0898aSmrg_fs_do_blocked (FSFpePtr conn) 158623a0898aSmrg{ 158723a0898aSmrg CARD32 now; 158823a0898aSmrg 158923a0898aSmrg now = GetTimeInMillis (); 159023a0898aSmrg if ((conn->blockState & FS_PENDING_REPLY) && 159123a0898aSmrg TimeCmp (conn->blockedReplyTime, <=, now)) 159223a0898aSmrg { 159323a0898aSmrg _fs_giveup (conn); 159423a0898aSmrg } 159541c30155Smrg else 159623a0898aSmrg { 159723a0898aSmrg if (conn->blockState & FS_BROKEN_CONNECTION) 159823a0898aSmrg { 159923a0898aSmrg /* Try to reconnect broken connections */ 160023a0898aSmrg if (TimeCmp (conn->brokenConnectionTime, <=, now)) 160123a0898aSmrg _fs_start_reconnect (conn); 160223a0898aSmrg } 160323a0898aSmrg else if (conn->blockState & FS_BROKEN_WRITE) 160423a0898aSmrg { 160523a0898aSmrg /* Try to flush blocked connections */ 160623a0898aSmrg if (TimeCmp (conn->brokenWriteTime, <=, now)) 160723a0898aSmrg _fs_flush (conn); 160823a0898aSmrg } 160923a0898aSmrg } 161023a0898aSmrg} 161123a0898aSmrg 161223a0898aSmrg/* 161323a0898aSmrg * sends the actual request out 161423a0898aSmrg */ 161523a0898aSmrg/* ARGSUSED */ 161623a0898aSmrgstatic int 161741c30155Smrgfs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 16180b332824Ssnj const char *name, int namelen, 161941c30155Smrg fsBitmapFormat format, fsBitmapFormatMask fmask, 162023a0898aSmrg XID id, FontPtr *ppfont) 162123a0898aSmrg{ 162223a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 162323a0898aSmrg FontPtr font; 162423a0898aSmrg FSBlockDataPtr blockrec = NULL; 162523a0898aSmrg FSBlockedFontPtr bfont; 162623a0898aSmrg FSFontDataPtr fsd; 162723a0898aSmrg fsOpenBitmapFontReq openreq; 162823a0898aSmrg fsQueryXInfoReq inforeq; 162923a0898aSmrg fsQueryXExtents16Req extreq; 163023a0898aSmrg int err; 163123a0898aSmrg unsigned char buf[1024]; 163223a0898aSmrg 163323a0898aSmrg if (conn->blockState & FS_GIVE_UP) 163423a0898aSmrg return BadFontName; 163541c30155Smrg 16360b332824Ssnj if (namelen < 0 || namelen > sizeof (buf) - 1) 163723a0898aSmrg return BadFontName; 163841c30155Smrg 163923a0898aSmrg /* 164023a0898aSmrg * Get the font structure put together, either by reusing 164123a0898aSmrg * the existing one or creating a new one 164223a0898aSmrg */ 164323a0898aSmrg if (flags & FontReopen) 164423a0898aSmrg { 164523a0898aSmrg Atom nameatom, fn = None; 164623a0898aSmrg int i; 164723a0898aSmrg 164823a0898aSmrg font = *ppfont; 164923a0898aSmrg fsd = (FSFontDataPtr)font->fpePrivate; 165023a0898aSmrg /* This is an attempt to reopen a font. Did the font have a 165123a0898aSmrg NAME property? */ 165223a0898aSmrg if ((nameatom = MakeAtom("FONT", 4, 0)) != None) 165323a0898aSmrg { 165423a0898aSmrg for (i = 0; i < font->info.nprops; i++) 165523a0898aSmrg if (font->info.props[i].name == nameatom && 165623a0898aSmrg font->info.isStringProp[i]) 165723a0898aSmrg { 165823a0898aSmrg fn = font->info.props[i].value; 165923a0898aSmrg break; 166023a0898aSmrg } 166123a0898aSmrg } 166223a0898aSmrg if (fn == None || !(name = NameForAtom(fn))) 166323a0898aSmrg { 166423a0898aSmrg name = fsd->name; 166523a0898aSmrg namelen = fsd->namelen; 166623a0898aSmrg } 166723a0898aSmrg else 166823a0898aSmrg namelen = strlen(name); 166923a0898aSmrg } 167023a0898aSmrg else 167123a0898aSmrg { 167223a0898aSmrg font = fs_create_font (fpe, name, namelen, format, fmask); 167323a0898aSmrg if (!font) 167423a0898aSmrg return AllocError; 167541c30155Smrg 167623a0898aSmrg fsd = (FSFontDataPtr)font->fpePrivate; 167723a0898aSmrg } 167841c30155Smrg 167923a0898aSmrg /* make a new block record, and add it to the end of the list */ 168023a0898aSmrg blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); 168123a0898aSmrg if (!blockrec) 168223a0898aSmrg { 168323a0898aSmrg if (!(flags & FontReopen)) 168423a0898aSmrg (*font->unload_font) (font); 168523a0898aSmrg return AllocError; 168623a0898aSmrg } 168741c30155Smrg 168823a0898aSmrg /* 168923a0898aSmrg * Must check this before generating any protocol, otherwise we'll 169023a0898aSmrg * mess up a reconnect in progress 169123a0898aSmrg */ 169223a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 169323a0898aSmrg { 169423a0898aSmrg _fs_pending_reply (conn); 169523a0898aSmrg return Suspended; 169623a0898aSmrg } 169741c30155Smrg 169823a0898aSmrg fsd->generation = conn->generation; 169923a0898aSmrg 170023a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 170123a0898aSmrg bfont->fontid = fsd->fontid; 170223a0898aSmrg bfont->pfont = font; 170323a0898aSmrg bfont->state = FS_OPEN_REPLY; 170423a0898aSmrg bfont->flags = flags; 170523a0898aSmrg bfont->format = fsd->format; 170623a0898aSmrg bfont->clients_depending = (FSClientsDependingPtr)0; 170723a0898aSmrg bfont->freeFont = (flags & FontReopen) == 0; 170823a0898aSmrg 170923a0898aSmrg _fs_client_access (conn, client, (flags & FontOpenSync) != 0); 171023a0898aSmrg _fs_client_resolution(conn); 171123a0898aSmrg 171223a0898aSmrg /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ 171323a0898aSmrg buf[0] = (unsigned char) namelen; 171423a0898aSmrg memcpy(&buf[1], name, namelen); 171523a0898aSmrg openreq.reqType = FS_OpenBitmapFont; 17167f7f5e4eSmrg openreq.pad = 0; 171723a0898aSmrg openreq.fid = fsd->fontid; 171823a0898aSmrg openreq.format_hint = fsd->format; 171923a0898aSmrg openreq.format_mask = fsd->fmask; 172023a0898aSmrg openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; 172123a0898aSmrg 172223a0898aSmrg _fs_add_req_log(conn, FS_OpenBitmapFont); 172323a0898aSmrg _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); 172423a0898aSmrg _fs_write_pad(conn, (char *) buf, namelen + 1); 172523a0898aSmrg 172623a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 172741c30155Smrg 172823a0898aSmrg inforeq.reqType = FS_QueryXInfo; 17297f7f5e4eSmrg inforeq.pad = 0; 173023a0898aSmrg inforeq.id = fsd->fontid; 173123a0898aSmrg inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; 173223a0898aSmrg 173323a0898aSmrg bfont->queryInfoSequence = conn->current_seq + 1; 173441c30155Smrg 173523a0898aSmrg _fs_add_req_log(conn, FS_QueryXInfo); 173623a0898aSmrg _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); 173741c30155Smrg 173823a0898aSmrg if (!(bfont->flags & FontReopen)) 173923a0898aSmrg { 174023a0898aSmrg extreq.reqType = FS_QueryXExtents16; 174123a0898aSmrg extreq.range = fsTrue; 174223a0898aSmrg extreq.fid = fsd->fontid; 174323a0898aSmrg extreq.num_ranges = 0; 174423a0898aSmrg extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; 174541c30155Smrg 174623a0898aSmrg bfont->queryExtentsSequence = conn->current_seq + 1; 174741c30155Smrg 174823a0898aSmrg _fs_add_req_log(conn, FS_QueryXExtents16); 174923a0898aSmrg _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); 175023a0898aSmrg } 175141c30155Smrg 175223a0898aSmrg#ifdef NCD 175341c30155Smrg if (configData.ExtendedFontDiags) 175423a0898aSmrg { 175523a0898aSmrg memcpy(buf, name, MIN(256, namelen)); 175623a0898aSmrg buf[MIN(256, namelen)] = '\0'; 175723a0898aSmrg printf("Requesting font \"%s\" from font server \"%s\"\n", 175823a0898aSmrg buf, font->fpe->name); 175923a0898aSmrg } 176023a0898aSmrg#endif 176123a0898aSmrg _fs_prepare_for_reply (conn); 176241c30155Smrg 176323a0898aSmrg err = blockrec->errcode; 176423a0898aSmrg if (bfont->flags & FontOpenSync) 176523a0898aSmrg { 176623a0898aSmrg while (blockrec->errcode == StillWorking) 176723a0898aSmrg { 176823a0898aSmrg if (fs_await_reply (conn) != FSIO_READY) 176923a0898aSmrg { 177023a0898aSmrg blockrec->errcode = BadFontName; 177123a0898aSmrg break; 177223a0898aSmrg } 177323a0898aSmrg fs_read_reply (font->fpe, client); 177423a0898aSmrg } 177523a0898aSmrg err = blockrec->errcode; 177623a0898aSmrg if (err == Successful) 177723a0898aSmrg *ppfont = bfont->pfont; 177823a0898aSmrg else 177923a0898aSmrg fs_cleanup_bfont (bfont); 178023a0898aSmrg bfont->freeFont = FALSE; 178123a0898aSmrg _fs_remove_block_rec (conn, blockrec); 178223a0898aSmrg } 178323a0898aSmrg return err == StillWorking ? Suspended : err; 178423a0898aSmrg} 178523a0898aSmrg 178623a0898aSmrgstatic void 178723a0898aSmrgfs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 178823a0898aSmrg{ 178923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 179023a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 179123a0898aSmrg fsQueryXBitmaps16Req bitreq; 179223a0898aSmrg 179323a0898aSmrg /* send the request */ 179423a0898aSmrg bitreq.reqType = FS_QueryXBitmaps16; 179523a0898aSmrg bitreq.fid = bfont->fontid; 179623a0898aSmrg bitreq.format = bfont->format; 179723a0898aSmrg bitreq.range = TRUE; 179823a0898aSmrg bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; 179923a0898aSmrg bitreq.num_ranges = 0; 180023a0898aSmrg 180123a0898aSmrg bfont->queryBitmapsSequence = conn->current_seq + 1; 180241c30155Smrg 180323a0898aSmrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 180423a0898aSmrg _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); 180523a0898aSmrg} 180623a0898aSmrg 180723a0898aSmrg/* ARGSUSED */ 180823a0898aSmrgstatic int 180941c30155Smrgfs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 18100b332824Ssnj const char *name, int namelen, 181141c30155Smrg fsBitmapFormat format, fsBitmapFormatMask fmask, 181223a0898aSmrg XID id, FontPtr *ppfont, 181323a0898aSmrg char **alias, FontPtr non_cachable_font) 181423a0898aSmrg{ 181523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 181623a0898aSmrg FSBlockDataPtr blockrec; 181723a0898aSmrg FSBlockedFontPtr bfont; 181823a0898aSmrg int err; 181923a0898aSmrg 182023a0898aSmrg /* libfont interface expects ImageRectMin glyphs */ 182123a0898aSmrg format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; 182223a0898aSmrg 182323a0898aSmrg *alias = (char *) 0; 182423a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 182523a0898aSmrg { 182641c30155Smrg if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) 182723a0898aSmrg { 182823a0898aSmrg err = blockrec->errcode; 182923a0898aSmrg if (err == StillWorking) 183023a0898aSmrg return Suspended; 183141c30155Smrg 183223a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 183323a0898aSmrg if (err == Successful) 183423a0898aSmrg *ppfont = bfont->pfont; 183523a0898aSmrg else 183623a0898aSmrg fs_cleanup_bfont (bfont); 183723a0898aSmrg _fs_remove_block_rec (conn, blockrec); 183823a0898aSmrg return err; 183923a0898aSmrg } 184023a0898aSmrg } 184123a0898aSmrg return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, 184223a0898aSmrg id, ppfont); 184323a0898aSmrg} 184423a0898aSmrg 184523a0898aSmrg/* ARGSUSED */ 184623a0898aSmrgstatic int 184723a0898aSmrgfs_send_close_font(FontPathElementPtr fpe, Font id) 184823a0898aSmrg{ 184923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 185023a0898aSmrg fsCloseReq req; 185123a0898aSmrg 185223a0898aSmrg if (conn->blockState & FS_GIVE_UP) 185323a0898aSmrg return Successful; 185423a0898aSmrg /* tell the font server to close the font */ 185523a0898aSmrg req.reqType = FS_CloseFont; 18567f7f5e4eSmrg req.pad = 0; 185723a0898aSmrg req.length = SIZEOF(fsCloseReq) >> 2; 185823a0898aSmrg req.id = id; 185923a0898aSmrg _fs_add_req_log(conn, FS_CloseFont); 186023a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); 186123a0898aSmrg 186223a0898aSmrg return Successful; 186323a0898aSmrg} 186423a0898aSmrg 186523a0898aSmrg/* ARGSUSED */ 186623a0898aSmrgstatic void 186723a0898aSmrgfs_close_font(FontPathElementPtr fpe, FontPtr pfont) 186823a0898aSmrg{ 186923a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; 187023a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 187123a0898aSmrg 187223a0898aSmrg if (conn->generation == fsd->generation) 187323a0898aSmrg fs_send_close_font(fpe, fsd->fontid); 187423a0898aSmrg 187523a0898aSmrg#ifdef DEBUG 187623a0898aSmrg { 187723a0898aSmrg FSBlockDataPtr blockrec; 187823a0898aSmrg FSBlockedFontPtr bfont; 187923a0898aSmrg 188023a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 188123a0898aSmrg { 188223a0898aSmrg if (blockrec->type == FS_OPEN_FONT) 188323a0898aSmrg { 188423a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 188523a0898aSmrg if (bfont->pfont == pfont) 188623a0898aSmrg fprintf (stderr, "closing font which hasn't been opened\n"); 188723a0898aSmrg } 188823a0898aSmrg } 188923a0898aSmrg } 189023a0898aSmrg#endif 189123a0898aSmrg (*pfont->unload_font) (pfont); 189223a0898aSmrg} 189323a0898aSmrg 189423a0898aSmrgstatic int 189523a0898aSmrgfs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 189623a0898aSmrg{ 189723a0898aSmrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; 189823a0898aSmrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 189923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 190023a0898aSmrg FontPtr pfont = bglyph->pfont; 190123a0898aSmrg /* works for either blocked font 190223a0898aSmrg or glyph rec... pfont is at 190323a0898aSmrg the very beginning of both 190423a0898aSmrg blockrec->data structures */ 190523a0898aSmrg FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); 190623a0898aSmrg FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; 190723a0898aSmrg FontInfoPtr pfi = &pfont->info; 190823a0898aSmrg fsQueryXBitmaps16Reply *rep; 190923a0898aSmrg char *buf; 19107673729aSmrg long bufleft; /* length of reply left to use */ 191123a0898aSmrg fsOffset32 *ppbits; 191223a0898aSmrg fsOffset32 local_off; 191323a0898aSmrg char *off_adr; 191423a0898aSmrg pointer pbitmaps; 191523a0898aSmrg char *bits, *allbits; 191623a0898aSmrg#ifdef DEBUG 191723a0898aSmrg char *origallbits; 191823a0898aSmrg#endif 191923a0898aSmrg int i, 192023a0898aSmrg err; 192123a0898aSmrg int nranges = 0; 192223a0898aSmrg int ret; 192323a0898aSmrg fsRange *nextrange = 0; 192423a0898aSmrg unsigned long minchar, maxchar; 192523a0898aSmrg 192623a0898aSmrg rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); 19279d21a897Sspz if (!rep || rep->type == FS_Error || 19287673729aSmrg (rep->length < LENGTHOF(fsQueryXBitmaps16Reply))) 192923a0898aSmrg { 193023a0898aSmrg if (ret == FSIO_BLOCK) 193123a0898aSmrg return StillWorking; 193223a0898aSmrg if (rep) 193323a0898aSmrg _fs_done_read (conn, rep->length << 2); 193423a0898aSmrg err = AllocError; 19359d21a897Sspz _fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<"); 193623a0898aSmrg goto bail; 193723a0898aSmrg } 193823a0898aSmrg 193923a0898aSmrg buf = (char *) rep; 194023a0898aSmrg buf += SIZEOF (fsQueryXBitmaps16Reply); 194123a0898aSmrg 19429d21a897Sspz bufleft = rep->length << 2; 19439d21a897Sspz bufleft -= SIZEOF (fsQueryXBitmaps16Reply); 19449d21a897Sspz 19459d21a897Sspz if ((bufleft / SIZEOF (fsOffset32)) < rep->num_chars) 19469d21a897Sspz { 19479d21a897Sspz#ifdef DEBUG 19487673729aSmrg fprintf(stderr, 194981d6fa61Srin "fsQueryXBitmaps16: num_chars (%u) > bufleft (%ld) / %d\n", 195081d6fa61Srin (unsigned) rep->num_chars, bufleft, SIZEOF (fsOffset32)); 19519d21a897Sspz#endif 19527673729aSmrg err = AllocError; 19537673729aSmrg goto bail; 19549d21a897Sspz } 195523a0898aSmrg ppbits = (fsOffset32 *) buf; 195623a0898aSmrg buf += SIZEOF (fsOffset32) * (rep->num_chars); 19579d21a897Sspz bufleft -= SIZEOF (fsOffset32) * (rep->num_chars); 19589d21a897Sspz 19597673729aSmrg if (bufleft < rep->nbytes) 19607673729aSmrg { 19617673729aSmrg#ifdef DEBUG 19627673729aSmrg fprintf(stderr, 196381d6fa61Srin "fsQueryXBitmaps16: nbytes (%u) > bufleft (%ld)\n", 196481d6fa61Srin (unsigned) rep->nbytes, bufleft); 19657673729aSmrg#endif 19667673729aSmrg err = AllocError; 19677673729aSmrg goto bail; 19687673729aSmrg } 196923a0898aSmrg pbitmaps = (pointer ) buf; 197023a0898aSmrg 197123a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 197223a0898aSmrg { 197323a0898aSmrg nranges = bglyph->num_expected_ranges; 197423a0898aSmrg nextrange = bglyph->expected_ranges; 197523a0898aSmrg } 197623a0898aSmrg 197723a0898aSmrg /* place the incoming glyphs */ 197823a0898aSmrg if (nranges) 197923a0898aSmrg { 198023a0898aSmrg /* We're operating under the assumption that the ranges 198123a0898aSmrg requested in the LoadGlyphs call were all legal for this 198223a0898aSmrg font, and that individual ranges do not cover multiple 198323a0898aSmrg rows... fs_build_range() is designed to ensure this. */ 198423a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 198523a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 198623a0898aSmrg nextrange->min_char_low - pfi->firstCol; 198723a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 198823a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 198923a0898aSmrg nextrange->max_char_low - pfi->firstCol; 199023a0898aSmrg nextrange++; 199123a0898aSmrg } 199223a0898aSmrg else 199323a0898aSmrg { 199423a0898aSmrg minchar = 0; 199523a0898aSmrg maxchar = rep->num_chars; 199623a0898aSmrg } 199723a0898aSmrg 199823a0898aSmrg off_adr = (char *)ppbits; 199941c30155Smrg 200023a0898aSmrg allbits = fs_alloc_glyphs (pfont, rep->nbytes); 200141c30155Smrg 200223a0898aSmrg if (!allbits) 200323a0898aSmrg { 200423a0898aSmrg err = AllocError; 200523a0898aSmrg goto bail; 200623a0898aSmrg } 200741c30155Smrg 200823a0898aSmrg#ifdef DEBUG 200923a0898aSmrg origallbits = allbits; 201023a0898aSmrg fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", 201123a0898aSmrg (int) rep->num_chars, (int) rep->nbytes, fsd->name); 201223a0898aSmrg#endif 201341c30155Smrg 201423a0898aSmrg for (i = 0; i < rep->num_chars; i++) 201523a0898aSmrg { 201623a0898aSmrg memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ 201723a0898aSmrg if (blockrec->type == FS_OPEN_FONT || 201823a0898aSmrg fsdata->encoding[minchar].bits == &_fs_glyph_requested) 201923a0898aSmrg { 202023a0898aSmrg /* 202123a0898aSmrg * Broken X font server returns bits for missing characters 202223a0898aSmrg * when font is padded 202323a0898aSmrg */ 202423a0898aSmrg if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) 202523a0898aSmrg { 20269d21a897Sspz if (local_off.length && 20277673729aSmrg (local_off.position < rep->nbytes) && 20287673729aSmrg (local_off.length <= (rep->nbytes - local_off.position))) 202923a0898aSmrg { 203023a0898aSmrg bits = allbits; 203123a0898aSmrg allbits += local_off.length; 203223a0898aSmrg memcpy(bits, (char *)pbitmaps + local_off.position, 203323a0898aSmrg local_off.length); 203423a0898aSmrg } 203523a0898aSmrg else 203623a0898aSmrg bits = &_fs_glyph_zero_length; 203723a0898aSmrg } 203823a0898aSmrg else 203923a0898aSmrg bits = 0; 204023a0898aSmrg if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) 204123a0898aSmrg fsd->glyphs_to_get--; 204223a0898aSmrg fsdata->encoding[minchar].bits = bits; 204323a0898aSmrg } 204423a0898aSmrg if (minchar++ == maxchar) 204523a0898aSmrg { 204623a0898aSmrg if (!--nranges) break; 204723a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 204823a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 204923a0898aSmrg nextrange->min_char_low - pfi->firstCol; 205023a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 205123a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 205223a0898aSmrg nextrange->max_char_low - pfi->firstCol; 205323a0898aSmrg nextrange++; 205423a0898aSmrg } 205523a0898aSmrg off_adr += SIZEOF(fsOffset32); 205623a0898aSmrg } 205723a0898aSmrg#ifdef DEBUG 205823a0898aSmrg fprintf (stderr, "Used %d bytes instead of %d\n", 205923a0898aSmrg (int) (allbits - origallbits), (int) rep->nbytes); 206023a0898aSmrg#endif 206123a0898aSmrg 206223a0898aSmrg if (blockrec->type == FS_OPEN_FONT) 206323a0898aSmrg { 206423a0898aSmrg fsd->glyphs_to_get = 0; 206523a0898aSmrg bfont->state = FS_DONE_REPLY; 206623a0898aSmrg } 206723a0898aSmrg err = Successful; 206823a0898aSmrg 206923a0898aSmrgbail: 207023a0898aSmrg _fs_done_read (conn, rep->length << 2); 207123a0898aSmrg return err; 207223a0898aSmrg} 207323a0898aSmrg 207423a0898aSmrgstatic int 207541c30155Smrgfs_send_load_glyphs(pointer client, FontPtr pfont, 207623a0898aSmrg int nranges, fsRange *ranges) 207723a0898aSmrg{ 207823a0898aSmrg FontPathElementPtr fpe = pfont->fpe; 207923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 208023a0898aSmrg FSBlockedGlyphPtr blockedglyph; 208123a0898aSmrg fsQueryXBitmaps16Req req; 208223a0898aSmrg FSBlockDataPtr blockrec; 208323a0898aSmrg 208423a0898aSmrg if (conn->blockState & FS_GIVE_UP) 208523a0898aSmrg return BadCharRange; 208641c30155Smrg 208723a0898aSmrg /* make a new block record, and add it to the end of the list */ 208823a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); 208923a0898aSmrg if (!blockrec) 209023a0898aSmrg return AllocError; 209123a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 209223a0898aSmrg blockedglyph->pfont = pfont; 209323a0898aSmrg blockedglyph->num_expected_ranges = nranges; 209423a0898aSmrg /* Assumption: it's our job to free ranges */ 209523a0898aSmrg blockedglyph->expected_ranges = ranges; 209623a0898aSmrg blockedglyph->clients_depending = (FSClientsDependingPtr)0; 209723a0898aSmrg 209823a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) 209923a0898aSmrg { 210023a0898aSmrg _fs_pending_reply (conn); 210123a0898aSmrg return Suspended; 210223a0898aSmrg } 210341c30155Smrg 210423a0898aSmrg /* send the request */ 210523a0898aSmrg req.reqType = FS_QueryXBitmaps16; 210623a0898aSmrg req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; 210723a0898aSmrg req.format = pfont->format; 210823a0898aSmrg if (pfont->info.terminalFont) 210923a0898aSmrg req.format = (req.format & ~(BitmapFormatImageRectMask)) | 211023a0898aSmrg BitmapFormatImageRectMax; 211123a0898aSmrg req.range = TRUE; 211223a0898aSmrg /* each range takes up 4 bytes */ 211323a0898aSmrg req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; 211423a0898aSmrg req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ 211523a0898aSmrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 211623a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); 211723a0898aSmrg 211823a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 211941c30155Smrg 212023a0898aSmrg /* Send ranges to the server... pack into a char array by hand 212123a0898aSmrg to avoid structure-packing portability problems and to 212223a0898aSmrg handle swapping for version1 protocol */ 212323a0898aSmrg if (nranges) 212423a0898aSmrg { 212523a0898aSmrg#define RANGE_BUFFER_SIZE 64 212623a0898aSmrg#define RANGE_BUFFER_SIZE_MASK 63 212723a0898aSmrg int i; 212823a0898aSmrg char range_buffer[RANGE_BUFFER_SIZE * 4]; 212923a0898aSmrg char *range_buffer_p; 213023a0898aSmrg 213123a0898aSmrg range_buffer_p = range_buffer; 213223a0898aSmrg for (i = 0; i < nranges;) 213323a0898aSmrg { 213423a0898aSmrg if (conn->fsMajorVersion > 1) 213523a0898aSmrg { 213623a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 213723a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 213823a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 213923a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 214023a0898aSmrg } 214123a0898aSmrg else 214223a0898aSmrg { 214323a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 214423a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 214523a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 214623a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 214723a0898aSmrg } 214823a0898aSmrg 214923a0898aSmrg if (!(++i & RANGE_BUFFER_SIZE_MASK)) 215023a0898aSmrg { 215123a0898aSmrg _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); 215223a0898aSmrg range_buffer_p = range_buffer; 215323a0898aSmrg } 215423a0898aSmrg } 215523a0898aSmrg if (i &= RANGE_BUFFER_SIZE_MASK) 215623a0898aSmrg _fs_write(conn, range_buffer, i * 4); 215723a0898aSmrg } 215823a0898aSmrg 215923a0898aSmrg _fs_prepare_for_reply (conn); 216023a0898aSmrg return Suspended; 216123a0898aSmrg} 216223a0898aSmrg 216323a0898aSmrg 21640b332824Ssnjextern pointer __GetServerClient(void); /* This could be any number that 216523a0898aSmrg doesn't conflict with existing 216623a0898aSmrg client values. */ 216723a0898aSmrg 216823a0898aSmrgstatic int 216941c30155Smrg_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, 217023a0898aSmrg unsigned int nchars, int item_size, unsigned char *data) 217123a0898aSmrg{ 217223a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 217323a0898aSmrg int nranges = 0; 217423a0898aSmrg fsRange *ranges = NULL; 217523a0898aSmrg int res; 217623a0898aSmrg FSBlockDataPtr blockrec; 217723a0898aSmrg FSBlockedGlyphPtr blockedglyph; 217823a0898aSmrg FSClientsDependingPtr *clients_depending = NULL; 217923a0898aSmrg int err; 218023a0898aSmrg 218123a0898aSmrg /* see if the result is already there */ 218223a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 218323a0898aSmrg { 218423a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 218523a0898aSmrg { 218623a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 218723a0898aSmrg if (blockedglyph->pfont == pfont) 218823a0898aSmrg { 218923a0898aSmrg /* Look for this request */ 219023a0898aSmrg if (blockrec->client == client) 219123a0898aSmrg { 219223a0898aSmrg err = blockrec->errcode; 219323a0898aSmrg if (err == StillWorking) 219423a0898aSmrg return Suspended; 219523a0898aSmrg _fs_signal_clients_depending(&blockedglyph->clients_depending); 219623a0898aSmrg _fs_remove_block_rec(conn, blockrec); 219723a0898aSmrg return err; 219823a0898aSmrg } 219923a0898aSmrg /* We've found an existing LoadGlyphs blockrec for this 220023a0898aSmrg font but for another client. Rather than build a 220123a0898aSmrg blockrec for it now (which entails some complex 220223a0898aSmrg maintenance), we'll add it to a queue of clients to 220323a0898aSmrg be signalled when the existing LoadGlyphs is 220423a0898aSmrg completed. */ 220523a0898aSmrg clients_depending = &blockedglyph->clients_depending; 220623a0898aSmrg break; 220723a0898aSmrg } 220823a0898aSmrg } 220923a0898aSmrg else if (blockrec->type == FS_OPEN_FONT) 221023a0898aSmrg { 221123a0898aSmrg FSBlockedFontPtr bfont; 221223a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 221323a0898aSmrg if (bfont->pfont == pfont) 221423a0898aSmrg { 221523a0898aSmrg /* 221623a0898aSmrg * An OpenFont is pending for this font, this must 221723a0898aSmrg * be from a reopen attempt, so finish the open 221823a0898aSmrg * attempt and retry the LoadGlyphs 221923a0898aSmrg */ 222023a0898aSmrg if (blockrec->client == client) 222123a0898aSmrg { 222223a0898aSmrg err = blockrec->errcode; 222323a0898aSmrg if (err == StillWorking) 222423a0898aSmrg return Suspended; 222541c30155Smrg 222623a0898aSmrg _fs_signal_clients_depending(&bfont->clients_depending); 222723a0898aSmrg _fs_remove_block_rec(conn, blockrec); 222823a0898aSmrg if (err != Successful) 222923a0898aSmrg return err; 223023a0898aSmrg break; 223123a0898aSmrg } 223223a0898aSmrg /* We've found an existing OpenFont blockrec for this 223323a0898aSmrg font but for another client. Rather than build a 223423a0898aSmrg blockrec for it now (which entails some complex 223523a0898aSmrg maintenance), we'll add it to a queue of clients to 223623a0898aSmrg be signalled when the existing OpenFont is 223723a0898aSmrg completed. */ 223823a0898aSmrg if (blockrec->errcode == StillWorking) 223923a0898aSmrg { 224023a0898aSmrg clients_depending = &bfont->clients_depending; 224123a0898aSmrg break; 224223a0898aSmrg } 224323a0898aSmrg } 224423a0898aSmrg } 224523a0898aSmrg } 224623a0898aSmrg 224723a0898aSmrg /* 224823a0898aSmrg * see if the desired glyphs already exist, and return Successful if they 224923a0898aSmrg * do, otherwise build up character range/character string 225023a0898aSmrg */ 225123a0898aSmrg res = fs_build_range(pfont, range_flag, nchars, item_size, data, 225223a0898aSmrg &nranges, &ranges); 225323a0898aSmrg 225423a0898aSmrg switch (res) 225523a0898aSmrg { 225623a0898aSmrg case AccessDone: 225723a0898aSmrg return Successful; 225823a0898aSmrg 225923a0898aSmrg case Successful: 226023a0898aSmrg break; 226123a0898aSmrg 226223a0898aSmrg default: 226323a0898aSmrg return res; 226423a0898aSmrg } 226523a0898aSmrg 226623a0898aSmrg /* 226723a0898aSmrg * If clients_depending is not null, this request must wait for 226823a0898aSmrg * some prior request(s) to complete. 226923a0898aSmrg */ 227023a0898aSmrg if (clients_depending) 227123a0898aSmrg { 227223a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 227323a0898aSmrg clean up the damage (if any) caused by the fs_build_range() 227423a0898aSmrg call. */ 227523a0898aSmrg if (nranges) 227623a0898aSmrg { 227723a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 22787f7f5e4eSmrg free(ranges); 227923a0898aSmrg } 228023a0898aSmrg return _fs_add_clients_depending(clients_depending, client); 228123a0898aSmrg } 228223a0898aSmrg 228323a0898aSmrg /* 228423a0898aSmrg * If fsd->generation != conn->generation, the font has been closed 228523a0898aSmrg * due to a lost connection. We will reopen it, which will result 228623a0898aSmrg * in one of three things happening: 228723a0898aSmrg * 1) The open will succeed and obtain the same font. Life 228823a0898aSmrg * is wonderful. 228923a0898aSmrg * 2) The open will fail. There is code above to recognize this 229023a0898aSmrg * and flunk the LoadGlyphs request. The client might not be 229123a0898aSmrg * thrilled. 229223a0898aSmrg * 3) Worst case: the open will succeed but the font we open will 229323a0898aSmrg * be different. The fs_read_query_info() procedure attempts 229423a0898aSmrg * to detect this by comparing the existing metrics and 229523a0898aSmrg * properties against those of the reopened font... if they 229623a0898aSmrg * don't match, we flunk the reopen, which eventually results 229723a0898aSmrg * in flunking the LoadGlyphs request. We could go a step 229823a0898aSmrg * further and compare the extents, but this should be 229923a0898aSmrg * sufficient. 230023a0898aSmrg */ 230123a0898aSmrg if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) 230223a0898aSmrg { 230323a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 230423a0898aSmrg clean up the damage caused by the fs_build_range() call. */ 230523a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 23067f7f5e4eSmrg free(ranges); 230723a0898aSmrg 230823a0898aSmrg /* Now try to reopen the font. */ 230923a0898aSmrg return fs_send_open_font(client, pfont->fpe, 231023a0898aSmrg (Mask)FontReopen, (char *)0, 0, 231123a0898aSmrg (fsBitmapFormat)0, (fsBitmapFormatMask)0, 231223a0898aSmrg (XID)0, &pfont); 231323a0898aSmrg } 231423a0898aSmrg 231523a0898aSmrg return fs_send_load_glyphs(client, pfont, nranges, ranges); 231623a0898aSmrg} 231723a0898aSmrg 231823a0898aSmrgint 231923a0898aSmrgfs_load_all_glyphs(FontPtr pfont) 232023a0898aSmrg{ 232123a0898aSmrg int err; 232223a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 232323a0898aSmrg 232423a0898aSmrg /* 232523a0898aSmrg * The purpose of this procedure is to load all glyphs in the event 232623a0898aSmrg * that we're dealing with someone who doesn't understand the finer 232723a0898aSmrg * points of glyph caching... it is called from _fs_get_glyphs() if 232823a0898aSmrg * the latter is called to get glyphs that have not yet been loaded. 232923a0898aSmrg * We assume that the caller will not know how to handle a return 233023a0898aSmrg * value of Suspended (usually the case for a GetGlyphs() caller), 233123a0898aSmrg * so this procedure hangs around, freezing the server, for the 233223a0898aSmrg * request to complete. This is an unpleasant kluge called to 233323a0898aSmrg * perform an unpleasant job that, we hope, will never be required. 233423a0898aSmrg */ 233523a0898aSmrg 23360b332824Ssnj while ((err = _fs_load_glyphs(__GetServerClient(), pfont, TRUE, 0, 0, NULL)) == 233723a0898aSmrg Suspended) 233823a0898aSmrg { 233923a0898aSmrg if (fs_await_reply (conn) != FSIO_READY) 234023a0898aSmrg { 234123a0898aSmrg /* Get rid of blockrec */ 23420b332824Ssnj fs_client_died(__GetServerClient(), pfont->fpe); 234323a0898aSmrg err = BadCharRange; 234423a0898aSmrg break; 234523a0898aSmrg } 23460b332824Ssnj fs_read_reply (pfont->fpe, __GetServerClient()); 234723a0898aSmrg } 234823a0898aSmrg return err; 234923a0898aSmrg} 235023a0898aSmrg 235123a0898aSmrgstatic int 235223a0898aSmrgfs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 235323a0898aSmrg{ 235423a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 235523a0898aSmrg FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; 235623a0898aSmrg fsListFontsReply *rep; 235723a0898aSmrg char *data; 23587673729aSmrg long dataleft; /* length of reply left to use */ 235923a0898aSmrg int length, 236023a0898aSmrg i, 236123a0898aSmrg ret; 236223a0898aSmrg int err; 236323a0898aSmrg 236423a0898aSmrg rep = (fsListFontsReply *) fs_get_reply (conn, &ret); 23659d21a897Sspz if (!rep || rep->type == FS_Error || 23667673729aSmrg (rep->length < LENGTHOF(fsListFontsReply))) 236723a0898aSmrg { 236823a0898aSmrg if (ret == FSIO_BLOCK) 236923a0898aSmrg return StillWorking; 237023a0898aSmrg if (rep) 237123a0898aSmrg _fs_done_read (conn, rep->length << 2); 23729d21a897Sspz _fs_reply_failed (rep, fsListFontsReply, "<"); 237323a0898aSmrg return AllocError; 237423a0898aSmrg } 237523a0898aSmrg data = (char *) rep + SIZEOF (fsListFontsReply); 23769d21a897Sspz dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply); 237723a0898aSmrg 237823a0898aSmrg err = Successful; 237923a0898aSmrg /* copy data into FontPathRecord */ 238041c30155Smrg for (i = 0; i < rep->nFonts; i++) 238123a0898aSmrg { 23827673729aSmrg if (dataleft < 1) 23837673729aSmrg break; 238423a0898aSmrg length = *(unsigned char *)data++; 23857673729aSmrg dataleft--; /* used length byte */ 23867673729aSmrg if (length > dataleft) { 23879d21a897Sspz#ifdef DEBUG 23887673729aSmrg fprintf(stderr, 23897673729aSmrg "fsListFonts: name length (%d) > dataleft (%ld)\n", 23907673729aSmrg length, dataleft); 23919d21a897Sspz#endif 23927673729aSmrg err = BadFontName; 23937673729aSmrg break; 23947673729aSmrg } 239523a0898aSmrg err = AddFontNamesName(blist->names, data, length); 239623a0898aSmrg if (err != Successful) 239723a0898aSmrg break; 239823a0898aSmrg data += length; 23999d21a897Sspz dataleft -= length; 240023a0898aSmrg } 240123a0898aSmrg _fs_done_read (conn, rep->length << 2); 240223a0898aSmrg return err; 240323a0898aSmrg} 240423a0898aSmrg 240523a0898aSmrgstatic int 24060b332824Ssnjfs_send_list_fonts(pointer client, FontPathElementPtr fpe, const char *pattern, 240723a0898aSmrg int patlen, int maxnames, FontNamesPtr newnames) 240823a0898aSmrg{ 240923a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 241023a0898aSmrg FSBlockDataPtr blockrec; 241123a0898aSmrg FSBlockedListPtr blockedlist; 241223a0898aSmrg fsListFontsReq req; 241323a0898aSmrg 241423a0898aSmrg if (conn->blockState & FS_GIVE_UP) 241523a0898aSmrg return BadFontName; 241641c30155Smrg 241723a0898aSmrg /* make a new block record, and add it to the end of the list */ 241823a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); 241923a0898aSmrg if (!blockrec) 242023a0898aSmrg return AllocError; 242123a0898aSmrg blockedlist = (FSBlockedListPtr) blockrec->data; 242223a0898aSmrg blockedlist->names = newnames; 242323a0898aSmrg 242423a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 242523a0898aSmrg { 242623a0898aSmrg _fs_pending_reply (conn); 242723a0898aSmrg return Suspended; 242823a0898aSmrg } 242941c30155Smrg 243023a0898aSmrg _fs_client_access (conn, client, FALSE); 243123a0898aSmrg _fs_client_resolution(conn); 243223a0898aSmrg 243323a0898aSmrg /* send the request */ 243423a0898aSmrg req.reqType = FS_ListFonts; 24357f7f5e4eSmrg req.pad = 0; 243623a0898aSmrg req.maxNames = maxnames; 243723a0898aSmrg req.nbytes = patlen; 243823a0898aSmrg req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; 243923a0898aSmrg _fs_add_req_log(conn, FS_ListFonts); 244023a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); 244123a0898aSmrg _fs_write_pad(conn, (char *) pattern, patlen); 244223a0898aSmrg 244323a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 244441c30155Smrg 244523a0898aSmrg#ifdef NCD 244623a0898aSmrg if (configData.ExtendedFontDiags) { 244723a0898aSmrg char buf[256]; 244823a0898aSmrg 244923a0898aSmrg memcpy(buf, pattern, MIN(256, patlen)); 245023a0898aSmrg buf[MIN(256, patlen)] = '\0'; 245123a0898aSmrg printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", 245223a0898aSmrg buf, fpe->name); 245323a0898aSmrg } 245423a0898aSmrg#endif 245523a0898aSmrg 245623a0898aSmrg _fs_prepare_for_reply (conn); 245723a0898aSmrg return Suspended; 245823a0898aSmrg} 245923a0898aSmrg 246023a0898aSmrgstatic int 246141c30155Smrgfs_list_fonts(pointer client, FontPathElementPtr fpe, 24620b332824Ssnj const char *pattern, int patlen, int maxnames, FontNamesPtr newnames) 246323a0898aSmrg{ 246423a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 246523a0898aSmrg FSBlockDataPtr blockrec; 246623a0898aSmrg int err; 246723a0898aSmrg 246823a0898aSmrg /* see if the result is already there */ 246923a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 247023a0898aSmrg { 247141c30155Smrg if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) 247223a0898aSmrg { 247323a0898aSmrg err = blockrec->errcode; 247423a0898aSmrg if (err == StillWorking) 247523a0898aSmrg return Suspended; 247623a0898aSmrg _fs_remove_block_rec(conn, blockrec); 247723a0898aSmrg return err; 247823a0898aSmrg } 247923a0898aSmrg } 248023a0898aSmrg 248123a0898aSmrg /* didn't find waiting record, so send a new one */ 248223a0898aSmrg return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); 248323a0898aSmrg} 248423a0898aSmrg 248523a0898aSmrg/* 248623a0898aSmrg * Read a single list info reply and restart for the next reply 248723a0898aSmrg */ 248823a0898aSmrgstatic int 248923a0898aSmrgfs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 249023a0898aSmrg{ 249123a0898aSmrg FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; 249223a0898aSmrg fsListFontsWithXInfoReply *rep; 249323a0898aSmrg char *buf; 24947673729aSmrg long bufleft; 249523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 249623a0898aSmrg fsPropInfo *pi; 249723a0898aSmrg fsPropOffset *po; 249823a0898aSmrg pointer pd; 249923a0898aSmrg int ret; 250023a0898aSmrg int err; 250123a0898aSmrg 250223a0898aSmrg /* clean up anything from the last trip */ 250323a0898aSmrg _fs_free_props (&binfo->info); 250423a0898aSmrg 250523a0898aSmrg rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); 25069d21a897Sspz if (!rep || rep->type == FS_Error || 25077673729aSmrg ((rep->nameLength != 0) && 25087673729aSmrg (rep->length < LENGTHOF(fsListFontsWithXInfoReply)))) 250923a0898aSmrg { 251023a0898aSmrg if (ret == FSIO_BLOCK) 251123a0898aSmrg return StillWorking; 251223a0898aSmrg binfo->status = FS_LFWI_FINISHED; 251323a0898aSmrg err = AllocError; 25147673729aSmrg _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<"); 251523a0898aSmrg goto done; 251623a0898aSmrg } 251723a0898aSmrg /* 251823a0898aSmrg * Normal termination -- the list ends with a name of length 0 251923a0898aSmrg */ 252023a0898aSmrg if (rep->nameLength == 0) 252123a0898aSmrg { 252223a0898aSmrg#ifdef DEBUG 252323a0898aSmrg fprintf (stderr, "fs_read_list_info done\n"); 252423a0898aSmrg#endif 252523a0898aSmrg binfo->status = FS_LFWI_FINISHED; 252623a0898aSmrg err = BadFontName; 252723a0898aSmrg goto done; 252823a0898aSmrg } 252923a0898aSmrg 253023a0898aSmrg buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); 25317673729aSmrg bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply); 253241c30155Smrg 253323a0898aSmrg /* 253423a0898aSmrg * The original FS implementation didn't match 253523a0898aSmrg * the spec, version 1 was respecified to match the FS. 253623a0898aSmrg * Version 2 matches the original intent 253723a0898aSmrg */ 253823a0898aSmrg if (conn->fsMajorVersion <= 1) 253923a0898aSmrg { 25407673729aSmrg if (rep->nameLength > bufleft) { 25417673729aSmrg#ifdef DEBUG 25427673729aSmrg fprintf(stderr, 25437673729aSmrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 25447673729aSmrg (int) rep->nameLength, bufleft); 25457673729aSmrg#endif 25467673729aSmrg err = AllocError; 25477673729aSmrg goto done; 25487673729aSmrg } 25497673729aSmrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 255023a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 255123a0898aSmrg buf += _fs_pad_length (rep->nameLength); 25527673729aSmrg bufleft -= _fs_pad_length (rep->nameLength); 255323a0898aSmrg } 255423a0898aSmrg pi = (fsPropInfo *) buf; 25557673729aSmrg if (SIZEOF (fsPropInfo) > bufleft) { 25567673729aSmrg#ifdef DEBUG 25577673729aSmrg fprintf(stderr, 25587673729aSmrg "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n", 25597673729aSmrg (int) SIZEOF (fsPropInfo), bufleft); 25607673729aSmrg#endif 25617673729aSmrg err = AllocError; 25627673729aSmrg goto done; 25637673729aSmrg } 25647673729aSmrg bufleft -= SIZEOF (fsPropInfo); 256523a0898aSmrg buf += SIZEOF (fsPropInfo); 256623a0898aSmrg po = (fsPropOffset *) buf; 25677673729aSmrg if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) { 25687673729aSmrg#ifdef DEBUG 25697673729aSmrg fprintf(stderr, 257081d6fa61Srin "fsListFontsWithXInfo: offset length (%u * %d) > bufleft (%ld)\n", 257181d6fa61Srin (unsigned) pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft); 25727673729aSmrg#endif 25737673729aSmrg err = AllocError; 25747673729aSmrg goto done; 25757673729aSmrg } 25767673729aSmrg bufleft -= pi->num_offsets * SIZEOF (fsPropOffset); 257723a0898aSmrg buf += pi->num_offsets * SIZEOF (fsPropOffset); 257823a0898aSmrg pd = (pointer) buf; 25797673729aSmrg if (pi->data_len > bufleft) { 25807673729aSmrg#ifdef DEBUG 25817673729aSmrg fprintf(stderr, 258281d6fa61Srin "fsListFontsWithXInfo: data length (%u) > bufleft (%ld)\n", 258381d6fa61Srin (unsigned) pi->data_len, bufleft); 25847673729aSmrg#endif 25857673729aSmrg err = AllocError; 25867673729aSmrg goto done; 25877673729aSmrg } 25887673729aSmrg bufleft -= pi->data_len; 258923a0898aSmrg buf += pi->data_len; 259023a0898aSmrg if (conn->fsMajorVersion > 1) 259123a0898aSmrg { 25927673729aSmrg if (rep->nameLength > bufleft) { 25937673729aSmrg#ifdef DEBUG 25947673729aSmrg fprintf(stderr, 25957673729aSmrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 25967673729aSmrg (int) rep->nameLength, bufleft); 25977673729aSmrg#endif 25987673729aSmrg err = AllocError; 25997673729aSmrg goto done; 26007673729aSmrg } 26017673729aSmrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 260223a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 260323a0898aSmrg buf += _fs_pad_length (rep->nameLength); 26047673729aSmrg bufleft -= _fs_pad_length (rep->nameLength); 260523a0898aSmrg } 260623a0898aSmrg 260723a0898aSmrg#ifdef DEBUG 260823a0898aSmrg binfo->name[rep->nameLength] = '\0'; 260923a0898aSmrg fprintf (stderr, "fs_read_list_info %s\n", binfo->name); 261023a0898aSmrg#endif 261123a0898aSmrg err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); 261223a0898aSmrg if (err != Successful) 261323a0898aSmrg { 261423a0898aSmrg binfo->status = FS_LFWI_FINISHED; 261523a0898aSmrg goto done; 261623a0898aSmrg } 261723a0898aSmrg binfo->namelen = rep->nameLength; 261823a0898aSmrg binfo->remaining = rep->nReplies; 261923a0898aSmrg 262023a0898aSmrg binfo->status = FS_LFWI_REPLY; 262141c30155Smrg 262223a0898aSmrg /* disable this font server until we've processed this response */ 262323a0898aSmrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 262423a0898aSmrg FD_CLR(conn->fs_fd, &_fs_fd_mask); 262541c30155Smrgdone: 262623a0898aSmrg _fs_done_read (conn, rep->length << 2); 262723a0898aSmrg return err; 262823a0898aSmrg} 262923a0898aSmrg 263023a0898aSmrg/* ARGSUSED */ 263123a0898aSmrgstatic int 263241c30155Smrgfs_start_list_with_info(pointer client, FontPathElementPtr fpe, 26330b332824Ssnj const char *pattern, int len, int maxnames, pointer *pdata) 263423a0898aSmrg{ 263523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 263623a0898aSmrg FSBlockDataPtr blockrec; 263723a0898aSmrg FSBlockedListInfoPtr binfo; 263823a0898aSmrg fsListFontsWithXInfoReq req; 263923a0898aSmrg 264023a0898aSmrg if (conn->blockState & FS_GIVE_UP) 264123a0898aSmrg return BadFontName; 264223a0898aSmrg 264323a0898aSmrg /* make a new block record, and add it to the end of the list */ 264423a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); 264523a0898aSmrg if (!blockrec) 264623a0898aSmrg return AllocError; 264741c30155Smrg 264823a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 264923a0898aSmrg bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); 265023a0898aSmrg binfo->status = FS_LFWI_WAITING; 265123a0898aSmrg 265223a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 265323a0898aSmrg { 265423a0898aSmrg _fs_pending_reply (conn); 265523a0898aSmrg return Suspended; 265623a0898aSmrg } 265741c30155Smrg 265823a0898aSmrg _fs_client_access (conn, client, FALSE); 265923a0898aSmrg _fs_client_resolution(conn); 266023a0898aSmrg 266123a0898aSmrg /* send the request */ 266223a0898aSmrg req.reqType = FS_ListFontsWithXInfo; 26637f7f5e4eSmrg req.pad = 0; 266423a0898aSmrg req.maxNames = maxnames; 266523a0898aSmrg req.nbytes = len; 266623a0898aSmrg req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; 266723a0898aSmrg _fs_add_req_log(conn, FS_ListFontsWithXInfo); 266823a0898aSmrg (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); 266923a0898aSmrg (void) _fs_write_pad(conn, pattern, len); 267023a0898aSmrg 267123a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 267241c30155Smrg 267323a0898aSmrg#ifdef NCD 267423a0898aSmrg if (configData.ExtendedFontDiags) { 267523a0898aSmrg char buf[256]; 267623a0898aSmrg 267723a0898aSmrg memcpy(buf, pattern, MIN(256, len)); 267823a0898aSmrg buf[MIN(256, len)] = '\0'; 267923a0898aSmrg printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", 268023a0898aSmrg buf, fpe->name); 268123a0898aSmrg } 268223a0898aSmrg#endif 268323a0898aSmrg 268423a0898aSmrg _fs_prepare_for_reply (conn); 268523a0898aSmrg return Successful; 268623a0898aSmrg} 268723a0898aSmrg 268823a0898aSmrg/* ARGSUSED */ 268923a0898aSmrgstatic int 269041c30155Smrgfs_next_list_with_info(pointer client, FontPathElementPtr fpe, 269141c30155Smrg char **namep, int *namelenp, 269223a0898aSmrg FontInfoPtr *pFontInfo, int *numFonts, 269323a0898aSmrg pointer private) 269423a0898aSmrg{ 269523a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 269623a0898aSmrg FSBlockDataPtr blockrec; 269723a0898aSmrg FSBlockedListInfoPtr binfo; 269823a0898aSmrg int err; 269923a0898aSmrg 270023a0898aSmrg /* see if the result is already there */ 270123a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 270241c30155Smrg if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) 270323a0898aSmrg break; 270423a0898aSmrg 270523a0898aSmrg if (!blockrec) 270623a0898aSmrg { 270723a0898aSmrg /* The only good reason for not finding a blockrec would be if 270823a0898aSmrg disconnect/reconnect to the font server wiped it out and the 270923a0898aSmrg code that called us didn't do the right thing to create 271023a0898aSmrg another one. Under those circumstances, we need to return an 271123a0898aSmrg error to prevent that code from attempting to interpret the 271223a0898aSmrg information we don't return. */ 271323a0898aSmrg return BadFontName; 271423a0898aSmrg } 271523a0898aSmrg 271623a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 271741c30155Smrg 271823a0898aSmrg if (binfo->status == FS_LFWI_WAITING) 271923a0898aSmrg return Suspended; 272023a0898aSmrg 272123a0898aSmrg *namep = binfo->name; 272223a0898aSmrg *namelenp = binfo->namelen; 272323a0898aSmrg *pFontInfo = &binfo->info; 272423a0898aSmrg *numFonts = binfo->remaining; 272541c30155Smrg 272623a0898aSmrg /* Restart reply processing from this font server */ 272723a0898aSmrg FD_SET(conn->fs_fd, &_fs_fd_mask); 272823a0898aSmrg if (fs_reply_ready (conn)) 272923a0898aSmrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 273041c30155Smrg 273123a0898aSmrg err = blockrec->errcode; 273223a0898aSmrg switch (binfo->status) { 273323a0898aSmrg case FS_LFWI_FINISHED: 273423a0898aSmrg _fs_remove_block_rec(conn, blockrec); 273523a0898aSmrg break; 273623a0898aSmrg case FS_LFWI_REPLY: 273723a0898aSmrg binfo->status = FS_LFWI_WAITING; 273823a0898aSmrg blockrec->errcode = StillWorking; 273923a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 274023a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 274123a0898aSmrg break; 274223a0898aSmrg } 274341c30155Smrg 274423a0898aSmrg return err; 274523a0898aSmrg} 274623a0898aSmrg 274723a0898aSmrg/* 274823a0898aSmrg * Called when client exits 274923a0898aSmrg */ 275023a0898aSmrg 275123a0898aSmrgstatic void 275223a0898aSmrgfs_client_died(pointer client, FontPathElementPtr fpe) 275323a0898aSmrg{ 275423a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 275523a0898aSmrg FSBlockDataPtr blockrec, 275623a0898aSmrg depending; 275723a0898aSmrg FSClientPtr *prev, cur; 275823a0898aSmrg fsFreeACReq freeac; 275923a0898aSmrg 276023a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 276123a0898aSmrg { 276223a0898aSmrg if (cur->client == client) { 276323a0898aSmrg freeac.reqType = FS_FreeAC; 27647f7f5e4eSmrg freeac.pad = 0; 276523a0898aSmrg freeac.id = cur->acid; 276623a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 276723a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 276823a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 276923a0898aSmrg *prev = cur->next; 27707f7f5e4eSmrg free (cur); 277123a0898aSmrg break; 277223a0898aSmrg } 277323a0898aSmrg } 277423a0898aSmrg /* find a pending requests */ 277523a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 277623a0898aSmrg if (blockrec->client == client) 277723a0898aSmrg break; 277841c30155Smrg 277923a0898aSmrg if (!blockrec) 278023a0898aSmrg return; 278141c30155Smrg 278223a0898aSmrg /* replace the client pointers in this block rec with the chained one */ 278341c30155Smrg if ((depending = blockrec->depending)) 278423a0898aSmrg { 278523a0898aSmrg blockrec->client = depending->client; 278623a0898aSmrg blockrec->depending = depending->depending; 278723a0898aSmrg blockrec = depending; 278823a0898aSmrg } 278923a0898aSmrg fs_abort_blockrec(conn, blockrec); 279023a0898aSmrg} 279123a0898aSmrg 279223a0898aSmrgstatic void 279323a0898aSmrg_fs_client_access (FSFpePtr conn, pointer client, Bool sync) 279423a0898aSmrg{ 279523a0898aSmrg FSClientPtr *prev, cur; 279623a0898aSmrg fsCreateACReq crac; 279723a0898aSmrg fsSetAuthorizationReq setac; 279823a0898aSmrg char *authorizations; 279923a0898aSmrg int authlen; 280023a0898aSmrg Bool new_cur = FALSE; 28017f7f5e4eSmrg char padding[4] = { 0, 0, 0, 0 }; 280223a0898aSmrg 280323a0898aSmrg#ifdef DEBUG 280423a0898aSmrg if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) 280523a0898aSmrg { 280623a0898aSmrg fprintf (stderr, "Sending requests without a connection\n"); 280723a0898aSmrg } 280823a0898aSmrg#endif 280923a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 281023a0898aSmrg { 281123a0898aSmrg if (cur->client == client) 281223a0898aSmrg { 281323a0898aSmrg if (prev != &conn->clients) 281423a0898aSmrg { 281523a0898aSmrg *prev = cur->next; 281623a0898aSmrg cur->next = conn->clients; 281723a0898aSmrg conn->clients = cur; 281823a0898aSmrg } 281923a0898aSmrg break; 282023a0898aSmrg } 282123a0898aSmrg } 282223a0898aSmrg if (!cur) 282323a0898aSmrg { 28247f7f5e4eSmrg cur = malloc (sizeof (FSClientRec)); 282523a0898aSmrg if (!cur) 282623a0898aSmrg return; 282723a0898aSmrg cur->client = client; 282823a0898aSmrg cur->next = conn->clients; 282923a0898aSmrg conn->clients = cur; 283023a0898aSmrg cur->acid = GetNewFontClientID (); 283123a0898aSmrg new_cur = TRUE; 283223a0898aSmrg } 283323a0898aSmrg if (new_cur || cur->auth_generation != client_auth_generation(client)) 283423a0898aSmrg { 283523a0898aSmrg if (!new_cur) 283623a0898aSmrg { 283723a0898aSmrg fsFreeACReq freeac; 283823a0898aSmrg freeac.reqType = FS_FreeAC; 28397f7f5e4eSmrg freeac.pad = 0; 284023a0898aSmrg freeac.id = cur->acid; 284123a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 284223a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 284323a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 284423a0898aSmrg } 284523a0898aSmrg crac.reqType = FS_CreateAC; 284623a0898aSmrg crac.num_auths = set_font_authorizations(&authorizations, &authlen, 284723a0898aSmrg client); 28487f7f5e4eSmrg /* Work around bug in xfs versions up through modular release 1.0.8 28497f7f5e4eSmrg which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ 28507f7f5e4eSmrg if (crac.num_auths == 0) { 28517f7f5e4eSmrg authorizations = padding; 28527f7f5e4eSmrg authlen = 4; 28537f7f5e4eSmrg } 285423a0898aSmrg crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; 285523a0898aSmrg crac.acid = cur->acid; 285623a0898aSmrg _fs_add_req_log(conn, FS_CreateAC); 285723a0898aSmrg _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); 2858b0d196e1Smrg _fs_write_pad(conn, authorizations, authlen); 285923a0898aSmrg /* ignore reply; we don't even care about it */ 286023a0898aSmrg conn->curacid = 0; 286123a0898aSmrg cur->auth_generation = client_auth_generation(client); 286223a0898aSmrg } 286323a0898aSmrg if (conn->curacid != cur->acid) 286423a0898aSmrg { 286523a0898aSmrg setac.reqType = FS_SetAuthorization; 28667f7f5e4eSmrg setac.pad = 0; 286723a0898aSmrg setac.length = sizeof (fsSetAuthorizationReq) >> 2; 286823a0898aSmrg setac.id = cur->acid; 286923a0898aSmrg _fs_add_req_log(conn, FS_SetAuthorization); 287023a0898aSmrg _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); 287123a0898aSmrg conn->curacid = cur->acid; 287223a0898aSmrg } 287323a0898aSmrg} 287423a0898aSmrg 287523a0898aSmrg/* 287623a0898aSmrg * Poll a pending connect 287723a0898aSmrg */ 287823a0898aSmrg 287923a0898aSmrgstatic int 288023a0898aSmrg_fs_check_connect (FSFpePtr conn) 288123a0898aSmrg{ 288223a0898aSmrg int ret; 288341c30155Smrg 288423a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 0); 288523a0898aSmrg switch (ret) { 288623a0898aSmrg case FSIO_READY: 288723a0898aSmrg conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); 288823a0898aSmrg FD_SET (conn->fs_fd, &_fs_fd_mask); 288923a0898aSmrg break; 289023a0898aSmrg case FSIO_BLOCK: 289123a0898aSmrg break; 289223a0898aSmrg } 289323a0898aSmrg return ret; 289423a0898aSmrg} 289523a0898aSmrg 289623a0898aSmrg/* 289723a0898aSmrg * Return an FSIO status while waiting for the completed connection 289823a0898aSmrg * reply to arrive 289923a0898aSmrg */ 290023a0898aSmrg 290123a0898aSmrgstatic fsConnSetup * 290223a0898aSmrg_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) 290323a0898aSmrg{ 290423a0898aSmrg int ret; 290523a0898aSmrg char *data; 290623a0898aSmrg int headlen; 290723a0898aSmrg int len; 290823a0898aSmrg fsConnSetup *setup; 290923a0898aSmrg fsConnSetupAccept *accept; 291023a0898aSmrg 291123a0898aSmrg ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); 291223a0898aSmrg if (ret != FSIO_READY) 291323a0898aSmrg { 291423a0898aSmrg *error = ret; 291523a0898aSmrg return 0; 291623a0898aSmrg } 291741c30155Smrg 291823a0898aSmrg setup = (fsConnSetup *) data; 291923a0898aSmrg if (setup->major_version > FS_PROTOCOL) 292023a0898aSmrg { 292123a0898aSmrg *error = FSIO_ERROR; 292223a0898aSmrg return 0; 292323a0898aSmrg } 292423a0898aSmrg 292523a0898aSmrg headlen = (SIZEOF (fsConnSetup) + 292623a0898aSmrg (setup->alternate_len << 2) + 292723a0898aSmrg (setup->auth_len << 2)); 292823a0898aSmrg /* On anything but Success, no extra data is sent */ 292923a0898aSmrg if (setup->status != AuthSuccess) 293023a0898aSmrg { 293123a0898aSmrg len = headlen; 293223a0898aSmrg } 293323a0898aSmrg else 293423a0898aSmrg { 293523a0898aSmrg ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); 293623a0898aSmrg if (ret != FSIO_READY) 293723a0898aSmrg { 293823a0898aSmrg *error = ret; 293923a0898aSmrg return 0; 294023a0898aSmrg } 294123a0898aSmrg setup = (fsConnSetup *) data; 294223a0898aSmrg accept = (fsConnSetupAccept *) (data + headlen); 294323a0898aSmrg len = headlen + (accept->length << 2); 294423a0898aSmrg } 294523a0898aSmrg ret = _fs_start_read (conn, len, &data); 294623a0898aSmrg if (ret != FSIO_READY) 294723a0898aSmrg { 294823a0898aSmrg *error = ret; 294923a0898aSmrg return 0; 295023a0898aSmrg } 295123a0898aSmrg *setup_len = len; 295223a0898aSmrg return (fsConnSetup *) data; 295323a0898aSmrg} 295423a0898aSmrg 295523a0898aSmrgstatic int 295623a0898aSmrg_fs_send_conn_client_prefix (FSFpePtr conn) 295723a0898aSmrg{ 295823a0898aSmrg fsConnClientPrefix req; 295923a0898aSmrg int endian; 296023a0898aSmrg int ret; 296123a0898aSmrg 296223a0898aSmrg /* send setup prefix */ 296323a0898aSmrg endian = 1; 296423a0898aSmrg if (*(char *) &endian) 296523a0898aSmrg req.byteOrder = 'l'; 296623a0898aSmrg else 296723a0898aSmrg req.byteOrder = 'B'; 296823a0898aSmrg 296923a0898aSmrg req.major_version = FS_PROTOCOL; 297023a0898aSmrg req.minor_version = FS_PROTOCOL_MINOR; 297123a0898aSmrg 297223a0898aSmrg/* XXX add some auth info here */ 297323a0898aSmrg req.num_auths = 0; 297423a0898aSmrg req.auth_len = 0; 297523a0898aSmrg ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); 297623a0898aSmrg if (ret != FSIO_READY) 297723a0898aSmrg return FSIO_ERROR; 297823a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 297923a0898aSmrg return ret; 298023a0898aSmrg} 298123a0898aSmrg 298223a0898aSmrgstatic int 298323a0898aSmrg_fs_recv_conn_setup (FSFpePtr conn) 298423a0898aSmrg{ 298523a0898aSmrg int ret = FSIO_ERROR; 298623a0898aSmrg fsConnSetup *setup; 298723a0898aSmrg FSFpeAltPtr alts; 29889d21a897Sspz unsigned int i, alt_len; 298923a0898aSmrg int setup_len; 299023a0898aSmrg char *alt_save, *alt_names; 299141c30155Smrg 299223a0898aSmrg setup = _fs_get_conn_setup (conn, &ret, &setup_len); 299323a0898aSmrg if (!setup) 299423a0898aSmrg return ret; 299523a0898aSmrg conn->current_seq = 0; 299623a0898aSmrg conn->fsMajorVersion = setup->major_version; 299723a0898aSmrg /* 299823a0898aSmrg * Create an alternate list from the initial server, but 299923a0898aSmrg * don't chain looking for alternates. 300023a0898aSmrg */ 300123a0898aSmrg if (conn->alternate == 0) 300223a0898aSmrg { 300323a0898aSmrg /* 300423a0898aSmrg * free any existing alternates list, allowing the list to 300523a0898aSmrg * be updated 300623a0898aSmrg */ 300723a0898aSmrg if (conn->alts) 300823a0898aSmrg { 30097f7f5e4eSmrg free (conn->alts); 301023a0898aSmrg conn->alts = 0; 301123a0898aSmrg conn->numAlts = 0; 301223a0898aSmrg } 301323a0898aSmrg if (setup->num_alternates) 301423a0898aSmrg { 30159d21a897Sspz size_t alt_name_len = setup->alternate_len << 2; 30167f7f5e4eSmrg alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + 30179d21a897Sspz alt_name_len); 301823a0898aSmrg if (alts) 301923a0898aSmrg { 302023a0898aSmrg alt_names = (char *) (setup + 1); 302123a0898aSmrg alt_save = (char *) (alts + setup->num_alternates); 302223a0898aSmrg for (i = 0; i < setup->num_alternates; i++) 302323a0898aSmrg { 302423a0898aSmrg alts[i].subset = alt_names[0]; 302523a0898aSmrg alt_len = alt_names[1]; 30267673729aSmrg if (alt_len >= alt_name_len) { 30277673729aSmrg /* 30287673729aSmrg * Length is longer than setup->alternate_len 30297673729aSmrg * told us to allocate room for, assume entire 30307673729aSmrg * alternate list is corrupted. 30317673729aSmrg */ 30329d21a897Sspz#ifdef DEBUG 30337673729aSmrg fprintf (stderr, 30347673729aSmrg "invalid alt list (length %lx >= %lx)\n", 30357673729aSmrg (long) alt_len, (long) alt_name_len); 30369d21a897Sspz#endif 30377673729aSmrg free(alts); 30387673729aSmrg return FSIO_ERROR; 30397673729aSmrg } 304023a0898aSmrg alts[i].name = alt_save; 304123a0898aSmrg memcpy (alt_save, alt_names + 2, alt_len); 304223a0898aSmrg alt_save[alt_len] = '\0'; 304323a0898aSmrg alt_save += alt_len + 1; 30447673729aSmrg alt_name_len -= alt_len + 1; 304523a0898aSmrg alt_names += _fs_pad_length (alt_len + 2); 304623a0898aSmrg } 304723a0898aSmrg conn->numAlts = setup->num_alternates; 304823a0898aSmrg conn->alts = alts; 304923a0898aSmrg } 305023a0898aSmrg } 305123a0898aSmrg } 305223a0898aSmrg _fs_done_read (conn, setup_len); 305323a0898aSmrg if (setup->status != AuthSuccess) 305423a0898aSmrg return FSIO_ERROR; 305523a0898aSmrg return FSIO_READY; 305623a0898aSmrg} 305723a0898aSmrg 305823a0898aSmrgstatic int 305923a0898aSmrg_fs_open_server (FSFpePtr conn) 306023a0898aSmrg{ 306123a0898aSmrg int ret; 306223a0898aSmrg char *servername; 306341c30155Smrg 306423a0898aSmrg if (conn->alternate == 0) 306523a0898aSmrg servername = conn->servername; 306623a0898aSmrg else 306723a0898aSmrg servername = conn->alts[conn->alternate-1].name; 306823a0898aSmrg conn->trans_conn = _fs_connect (servername, &ret); 306923a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; 307023a0898aSmrg return ret; 307123a0898aSmrg} 307223a0898aSmrg 307323a0898aSmrgstatic char * 307423a0898aSmrg_fs_catalog_name (char *servername) 307523a0898aSmrg{ 307623a0898aSmrg char *sp; 307723a0898aSmrg 307823a0898aSmrg sp = strchr (servername, '/'); 307923a0898aSmrg if (!sp) 308023a0898aSmrg return 0; 308123a0898aSmrg return strrchr (sp + 1, '/'); 308223a0898aSmrg} 308323a0898aSmrg 308423a0898aSmrgstatic int 308523a0898aSmrg_fs_send_init_packets (FSFpePtr conn) 308623a0898aSmrg{ 308723a0898aSmrg fsSetResolutionReq srreq; 308823a0898aSmrg fsSetCataloguesReq screq; 308923a0898aSmrg int num_cats, 309023a0898aSmrg clen; 309123a0898aSmrg char *catalogues; 309223a0898aSmrg char *cat; 309323a0898aSmrg char len; 309423a0898aSmrg char *end; 309541c30155Smrg int num_res; 309623a0898aSmrg FontResolutionPtr res; 309723a0898aSmrg 309823a0898aSmrg#define CATALOGUE_SEP '+' 309923a0898aSmrg 310023a0898aSmrg res = GetClientResolutions(&num_res); 310141c30155Smrg if (num_res) 310223a0898aSmrg { 310323a0898aSmrg srreq.reqType = FS_SetResolution; 310423a0898aSmrg srreq.num_resolutions = num_res; 310523a0898aSmrg srreq.length = (SIZEOF(fsSetResolutionReq) + 310623a0898aSmrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 310723a0898aSmrg 310823a0898aSmrg _fs_add_req_log(conn, FS_SetResolution); 310923a0898aSmrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) 311023a0898aSmrg return FSIO_ERROR; 311123a0898aSmrg if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) 311223a0898aSmrg return FSIO_ERROR; 311323a0898aSmrg } 311423a0898aSmrg 311523a0898aSmrg catalogues = 0; 311623a0898aSmrg if (conn->alternate != 0) 311723a0898aSmrg catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); 311823a0898aSmrg if (!catalogues) 311923a0898aSmrg catalogues = _fs_catalog_name (conn->servername); 312041c30155Smrg 312123a0898aSmrg if (!catalogues) 312223a0898aSmrg { 312323a0898aSmrg conn->has_catalogues = FALSE; 312423a0898aSmrg return FSIO_READY; 312523a0898aSmrg } 312623a0898aSmrg conn->has_catalogues = TRUE; 312741c30155Smrg 312823a0898aSmrg /* turn cats into counted list */ 312923a0898aSmrg catalogues++; 313023a0898aSmrg 313123a0898aSmrg cat = catalogues; 313223a0898aSmrg num_cats = 0; 313323a0898aSmrg clen = 0; 313423a0898aSmrg while (*cat) 313523a0898aSmrg { 313623a0898aSmrg num_cats++; 313723a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 313823a0898aSmrg if (!end) 313923a0898aSmrg end = cat + strlen (cat); 314023a0898aSmrg clen += (end - cat) + 1; /* length byte + string */ 314123a0898aSmrg cat = end; 314223a0898aSmrg } 314323a0898aSmrg 314423a0898aSmrg screq.reqType = FS_SetCatalogues; 314523a0898aSmrg screq.num_catalogues = num_cats; 314623a0898aSmrg screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; 314741c30155Smrg 314823a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 314923a0898aSmrg if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) 315023a0898aSmrg return FSIO_ERROR; 315141c30155Smrg 315223a0898aSmrg while (*cat) 315323a0898aSmrg { 315423a0898aSmrg num_cats++; 315523a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 315623a0898aSmrg if (!end) 315723a0898aSmrg end = cat + strlen (cat); 315823a0898aSmrg len = end - cat; 315923a0898aSmrg if (_fs_write (conn, &len, 1) != FSIO_READY) 316023a0898aSmrg return FSIO_ERROR; 316123a0898aSmrg if (_fs_write (conn, cat, (int) len) != FSIO_READY) 316223a0898aSmrg return FSIO_ERROR; 316323a0898aSmrg cat = end; 316423a0898aSmrg } 316541c30155Smrg 316623a0898aSmrg if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) 316723a0898aSmrg return FSIO_ERROR; 316841c30155Smrg 316923a0898aSmrg return FSIO_READY; 317023a0898aSmrg} 317123a0898aSmrg 317223a0898aSmrgstatic int 317323a0898aSmrg_fs_send_cat_sync (FSFpePtr conn) 317423a0898aSmrg{ 317523a0898aSmrg fsListCataloguesReq lcreq; 317641c30155Smrg 317723a0898aSmrg /* 317823a0898aSmrg * now sync up with the font server, to see if an error was generated 317923a0898aSmrg * by a bogus catalogue 318023a0898aSmrg */ 318123a0898aSmrg lcreq.reqType = FS_ListCatalogues; 31827673729aSmrg lcreq.data = 0; 318323a0898aSmrg lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; 318423a0898aSmrg lcreq.maxNames = 0; 318523a0898aSmrg lcreq.nbytes = 0; 31867f7f5e4eSmrg lcreq.pad2 = 0; 318723a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 318823a0898aSmrg if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) 318923a0898aSmrg return FSIO_ERROR; 319023a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 319123a0898aSmrg return FSIO_READY; 319223a0898aSmrg} 319323a0898aSmrg 319423a0898aSmrgstatic int 319523a0898aSmrg_fs_recv_cat_sync (FSFpePtr conn) 319623a0898aSmrg{ 319723a0898aSmrg fsGenericReply *reply; 319823a0898aSmrg fsError *error; 319923a0898aSmrg int err; 320023a0898aSmrg int ret; 320123a0898aSmrg 320223a0898aSmrg reply = fs_get_reply (conn, &err); 320323a0898aSmrg if (!reply) 320423a0898aSmrg return err; 320541c30155Smrg 320623a0898aSmrg ret = FSIO_READY; 320723a0898aSmrg if (reply->type == FS_Error) 320823a0898aSmrg { 320923a0898aSmrg error = (fsError *) reply; 321023a0898aSmrg if (error->major_opcode == FS_SetCatalogues) 321123a0898aSmrg ret = FSIO_ERROR; 321223a0898aSmrg } 321323a0898aSmrg _fs_done_read (conn, reply->length << 2); 321423a0898aSmrg return ret; 321523a0898aSmrg} 321623a0898aSmrg 321723a0898aSmrgstatic void 321823a0898aSmrg_fs_close_server (FSFpePtr conn) 321923a0898aSmrg{ 322023a0898aSmrg _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); 322123a0898aSmrg if (conn->trans_conn) 322223a0898aSmrg { 322323a0898aSmrg _FontTransClose (conn->trans_conn); 322423a0898aSmrg conn->trans_conn = 0; 322523a0898aSmrg _fs_io_reinit (conn); 322623a0898aSmrg } 322723a0898aSmrg if (conn->fs_fd >= 0) 322823a0898aSmrg { 322923a0898aSmrg FD_CLR (conn->fs_fd, &_fs_fd_mask); 323023a0898aSmrg conn->fs_fd = -1; 323123a0898aSmrg } 323223a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 323323a0898aSmrg} 323423a0898aSmrg 323523a0898aSmrgstatic int 323623a0898aSmrg_fs_do_setup_connection (FSFpePtr conn) 323723a0898aSmrg{ 323823a0898aSmrg int ret; 323941c30155Smrg 324023a0898aSmrg do 324123a0898aSmrg { 324223a0898aSmrg#ifdef DEBUG 324323a0898aSmrg fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); 324423a0898aSmrg#endif 324523a0898aSmrg switch (conn->fs_conn_state) { 324623a0898aSmrg case FS_CONN_UNCONNECTED: 324723a0898aSmrg ret = _fs_open_server (conn); 324823a0898aSmrg if (ret == FSIO_BLOCK) 324923a0898aSmrg conn->fs_conn_state = FS_CONN_CONNECTING; 325023a0898aSmrg break; 325123a0898aSmrg case FS_CONN_CONNECTING: 325223a0898aSmrg ret = _fs_check_connect (conn); 325323a0898aSmrg break; 325423a0898aSmrg case FS_CONN_CONNECTED: 325523a0898aSmrg ret = _fs_send_conn_client_prefix (conn); 325623a0898aSmrg break; 325723a0898aSmrg case FS_CONN_SENT_PREFIX: 325823a0898aSmrg ret = _fs_recv_conn_setup (conn); 325923a0898aSmrg break; 326023a0898aSmrg case FS_CONN_RECV_INIT: 326123a0898aSmrg ret = _fs_send_init_packets (conn); 326223a0898aSmrg if (conn->has_catalogues) 326323a0898aSmrg ret = _fs_send_cat_sync (conn); 326423a0898aSmrg break; 326523a0898aSmrg case FS_CONN_SENT_CAT: 326623a0898aSmrg if (conn->has_catalogues) 326723a0898aSmrg ret = _fs_recv_cat_sync (conn); 326823a0898aSmrg else 326923a0898aSmrg ret = FSIO_READY; 327023a0898aSmrg break; 327123a0898aSmrg default: 327223a0898aSmrg ret = FSIO_READY; 327323a0898aSmrg break; 327423a0898aSmrg } 327523a0898aSmrg switch (ret) { 327623a0898aSmrg case FSIO_READY: 327723a0898aSmrg if (conn->fs_conn_state < FS_CONN_RUNNING) 327823a0898aSmrg conn->fs_conn_state++; 327923a0898aSmrg break; 328023a0898aSmrg case FSIO_BLOCK: 328123a0898aSmrg if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) 328223a0898aSmrg break; 328323a0898aSmrg ret = FSIO_ERROR; 328423a0898aSmrg /* fall through... */ 328523a0898aSmrg case FSIO_ERROR: 328623a0898aSmrg _fs_close_server (conn); 328723a0898aSmrg /* 328823a0898aSmrg * Try the next alternate 328923a0898aSmrg */ 329023a0898aSmrg if (conn->alternate < conn->numAlts) 329123a0898aSmrg { 329223a0898aSmrg conn->alternate++; 329323a0898aSmrg ret = FSIO_READY; 329423a0898aSmrg } 329523a0898aSmrg else 329623a0898aSmrg conn->alternate = 0; 329723a0898aSmrg break; 329823a0898aSmrg } 329923a0898aSmrg } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); 330023a0898aSmrg if (ret == FSIO_READY) 330123a0898aSmrg conn->generation = ++generationCount; 330223a0898aSmrg return ret; 330323a0898aSmrg} 330423a0898aSmrg 330523a0898aSmrgstatic int 330623a0898aSmrg_fs_wait_connect (FSFpePtr conn) 330723a0898aSmrg{ 330823a0898aSmrg int ret; 330923a0898aSmrg 331023a0898aSmrg for (;;) 331123a0898aSmrg { 331223a0898aSmrg ret = _fs_do_setup_connection (conn); 331323a0898aSmrg if (ret != FSIO_BLOCK) 331423a0898aSmrg break; 331523a0898aSmrg if (conn->fs_conn_state <= FS_CONN_CONNECTING) 331623a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 1000); 331723a0898aSmrg else 331823a0898aSmrg ret = _fs_wait_for_readable (conn, 1000); 331923a0898aSmrg if (ret == FSIO_ERROR) 332023a0898aSmrg break; 332123a0898aSmrg } 332223a0898aSmrg return ret; 332323a0898aSmrg} 332423a0898aSmrg 332523a0898aSmrg/* 332623a0898aSmrg * Poll a connection in the process of reconnecting 332723a0898aSmrg */ 332823a0898aSmrgstatic void 332923a0898aSmrg_fs_check_reconnect (FSFpePtr conn) 333023a0898aSmrg{ 333123a0898aSmrg int ret; 333241c30155Smrg 333323a0898aSmrg ret = _fs_do_setup_connection (conn); 333423a0898aSmrg switch (ret) { 333523a0898aSmrg case FSIO_READY: 333623a0898aSmrg _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); 333723a0898aSmrg _fs_restart_connection (conn); 333823a0898aSmrg break; 333923a0898aSmrg case FSIO_BLOCK: 334023a0898aSmrg break; 334123a0898aSmrg case FSIO_ERROR: 334223a0898aSmrg conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; 334323a0898aSmrg break; 334423a0898aSmrg } 334523a0898aSmrg} 334623a0898aSmrg 334723a0898aSmrg/* 334823a0898aSmrg * Start the reconnection process 334923a0898aSmrg */ 335023a0898aSmrgstatic void 335123a0898aSmrg_fs_start_reconnect (FSFpePtr conn) 335223a0898aSmrg{ 335323a0898aSmrg if (conn->blockState & FS_RECONNECTING) 335423a0898aSmrg return; 335523a0898aSmrg conn->alternate = 0; 335623a0898aSmrg _fs_mark_block (conn, FS_RECONNECTING); 335723a0898aSmrg _fs_unmark_block (conn, FS_BROKEN_CONNECTION); 335823a0898aSmrg _fs_check_reconnect (conn); 335923a0898aSmrg} 336023a0898aSmrg 336123a0898aSmrg 336223a0898aSmrgstatic FSFpePtr 33630b332824Ssnj_fs_init_conn (const char *servername) 336423a0898aSmrg{ 336523a0898aSmrg FSFpePtr conn; 336623a0898aSmrg 33677f7f5e4eSmrg conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); 336823a0898aSmrg if (!conn) 336923a0898aSmrg return 0; 337023a0898aSmrg if (!_fs_io_init (conn)) 337123a0898aSmrg { 33727f7f5e4eSmrg free (conn); 337323a0898aSmrg return 0; 337423a0898aSmrg } 337523a0898aSmrg conn->servername = (char *) (conn + 1); 337623a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 337723a0898aSmrg conn->fs_fd = -1; 337823a0898aSmrg strcpy (conn->servername, servername); 337923a0898aSmrg return conn; 338023a0898aSmrg} 338123a0898aSmrg 338223a0898aSmrgstatic void 338323a0898aSmrg_fs_free_conn (FSFpePtr conn) 338423a0898aSmrg{ 338523a0898aSmrg _fs_close_server (conn); 338623a0898aSmrg _fs_io_fini (conn); 338723a0898aSmrg if (conn->alts) 33887f7f5e4eSmrg free (conn->alts); 33897f7f5e4eSmrg free (conn); 339023a0898aSmrg} 339123a0898aSmrg 339223a0898aSmrg/* 339323a0898aSmrg * called at server init time 339423a0898aSmrg */ 339523a0898aSmrg 339623a0898aSmrgvoid 339723a0898aSmrgfs_register_fpe_functions(void) 339823a0898aSmrg{ 339923a0898aSmrg RegisterFPEFunctions(fs_name_check, 340023a0898aSmrg fs_init_fpe, 340123a0898aSmrg fs_free_fpe, 340223a0898aSmrg fs_reset_fpe, 340323a0898aSmrg fs_open_font, 340423a0898aSmrg fs_close_font, 340523a0898aSmrg fs_list_fonts, 340623a0898aSmrg fs_start_list_with_info, 340723a0898aSmrg fs_next_list_with_info, 340823a0898aSmrg fs_wakeup, 340923a0898aSmrg fs_client_died, 341023a0898aSmrg _fs_load_glyphs, 341123a0898aSmrg NULL, 341223a0898aSmrg NULL, 341323a0898aSmrg NULL); 341423a0898aSmrg} 3415