fserve.c revision 7673729a
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 15023a0898aSmrg_fs_init_conn (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 \ 2269d21a897Sspz fprintf (stderr, "Bad Length for %s Reply: %d %s %d\n", \ 2279d21a897Sspz #name, 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 23823a0898aSmrgfs_name_check(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; 29623a0898aSmrg 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 { 6347673729aSmrg ErrorF("fserve: reply length %d > MAX_REPLY_LENGTH, disconnecting" 6357673729aSmrg " from font server\n", 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, 9187673729aSmrg "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %d\n", 9197673729aSmrg bufleft, 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, 9327673729aSmrg "fsQueryXInfo: bufleft (%ld) < data_len (%d)\n", 9337673729aSmrg bufleft, 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, 10667673729aSmrg "fsQueryXExtents16: numExtents (%d) > (%d - %d) / %d\n", 10677673729aSmrg numExtents, 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, 161841c30155Smrg 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 163623a0898aSmrg 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, 181041c30155Smrg 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, 19497673729aSmrg "fsQueryXBitmaps16: num_chars (%d) > bufleft (%ld) / %d\n", 19507673729aSmrg 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 0 19609d21a897Sspz if (bufleft < rep->nbytes) 19619d21a897Sspz { 19629d21a897Sspz#ifdef DEBUG 19639d21a897Sspz fprintf(stderr, 19649d21a897Sspz "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n", 19659d21a897Sspz rep->nbytes, bufleft); 19669d21a897Sspz#endif 19679d21a897Sspz err = AllocError; 19689d21a897Sspz goto bail; 19699d21a897Sspz } 19707673729aSmrg#endif 197123a0898aSmrg 19727673729aSmrg if (bufleft < rep->nbytes) 19737673729aSmrg { 19747673729aSmrg#ifdef DEBUG 19757673729aSmrg fprintf(stderr, 19767673729aSmrg "fsQueryXBitmaps16: nbytes (%d) > bufleft (%ld)\n", 19777673729aSmrg rep->nbytes, bufleft); 19787673729aSmrg#endif 19797673729aSmrg err = AllocError; 19807673729aSmrg goto bail; 19817673729aSmrg } 198223a0898aSmrg pbitmaps = (pointer ) buf; 198323a0898aSmrg 198423a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 198523a0898aSmrg { 198623a0898aSmrg nranges = bglyph->num_expected_ranges; 198723a0898aSmrg nextrange = bglyph->expected_ranges; 198823a0898aSmrg } 198923a0898aSmrg 199023a0898aSmrg /* place the incoming glyphs */ 199123a0898aSmrg if (nranges) 199223a0898aSmrg { 199323a0898aSmrg /* We're operating under the assumption that the ranges 199423a0898aSmrg requested in the LoadGlyphs call were all legal for this 199523a0898aSmrg font, and that individual ranges do not cover multiple 199623a0898aSmrg rows... fs_build_range() is designed to ensure this. */ 199723a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 199823a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 199923a0898aSmrg nextrange->min_char_low - pfi->firstCol; 200023a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 200123a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 200223a0898aSmrg nextrange->max_char_low - pfi->firstCol; 200323a0898aSmrg nextrange++; 200423a0898aSmrg } 200523a0898aSmrg else 200623a0898aSmrg { 200723a0898aSmrg minchar = 0; 200823a0898aSmrg maxchar = rep->num_chars; 200923a0898aSmrg } 201023a0898aSmrg 201123a0898aSmrg off_adr = (char *)ppbits; 201241c30155Smrg 201323a0898aSmrg allbits = fs_alloc_glyphs (pfont, rep->nbytes); 201441c30155Smrg 201523a0898aSmrg if (!allbits) 201623a0898aSmrg { 201723a0898aSmrg err = AllocError; 201823a0898aSmrg goto bail; 201923a0898aSmrg } 202041c30155Smrg 202123a0898aSmrg#ifdef DEBUG 202223a0898aSmrg origallbits = allbits; 202323a0898aSmrg fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", 202423a0898aSmrg (int) rep->num_chars, (int) rep->nbytes, fsd->name); 202523a0898aSmrg#endif 202641c30155Smrg 202723a0898aSmrg for (i = 0; i < rep->num_chars; i++) 202823a0898aSmrg { 202923a0898aSmrg memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ 203023a0898aSmrg if (blockrec->type == FS_OPEN_FONT || 203123a0898aSmrg fsdata->encoding[minchar].bits == &_fs_glyph_requested) 203223a0898aSmrg { 203323a0898aSmrg /* 203423a0898aSmrg * Broken X font server returns bits for missing characters 203523a0898aSmrg * when font is padded 203623a0898aSmrg */ 203723a0898aSmrg if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) 203823a0898aSmrg { 20399d21a897Sspz if (local_off.length && 20407673729aSmrg (local_off.position < rep->nbytes) && 20417673729aSmrg (local_off.length <= (rep->nbytes - local_off.position))) 204223a0898aSmrg { 204323a0898aSmrg bits = allbits; 204423a0898aSmrg allbits += local_off.length; 204523a0898aSmrg memcpy(bits, (char *)pbitmaps + local_off.position, 204623a0898aSmrg local_off.length); 204723a0898aSmrg } 204823a0898aSmrg else 204923a0898aSmrg bits = &_fs_glyph_zero_length; 205023a0898aSmrg } 205123a0898aSmrg else 205223a0898aSmrg bits = 0; 205323a0898aSmrg if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) 205423a0898aSmrg fsd->glyphs_to_get--; 205523a0898aSmrg fsdata->encoding[minchar].bits = bits; 205623a0898aSmrg } 205723a0898aSmrg if (minchar++ == maxchar) 205823a0898aSmrg { 205923a0898aSmrg if (!--nranges) break; 206023a0898aSmrg minchar = (nextrange->min_char_high - pfi->firstRow) * 206123a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 206223a0898aSmrg nextrange->min_char_low - pfi->firstCol; 206323a0898aSmrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 206423a0898aSmrg (pfi->lastCol - pfi->firstCol + 1) + 206523a0898aSmrg nextrange->max_char_low - pfi->firstCol; 206623a0898aSmrg nextrange++; 206723a0898aSmrg } 206823a0898aSmrg off_adr += SIZEOF(fsOffset32); 206923a0898aSmrg } 207023a0898aSmrg#ifdef DEBUG 207123a0898aSmrg fprintf (stderr, "Used %d bytes instead of %d\n", 207223a0898aSmrg (int) (allbits - origallbits), (int) rep->nbytes); 207323a0898aSmrg#endif 207423a0898aSmrg 207523a0898aSmrg if (blockrec->type == FS_OPEN_FONT) 207623a0898aSmrg { 207723a0898aSmrg fsd->glyphs_to_get = 0; 207823a0898aSmrg bfont->state = FS_DONE_REPLY; 207923a0898aSmrg } 208023a0898aSmrg err = Successful; 208123a0898aSmrg 208223a0898aSmrgbail: 208323a0898aSmrg _fs_done_read (conn, rep->length << 2); 208423a0898aSmrg return err; 208523a0898aSmrg} 208623a0898aSmrg 208723a0898aSmrgstatic int 208841c30155Smrgfs_send_load_glyphs(pointer client, FontPtr pfont, 208923a0898aSmrg int nranges, fsRange *ranges) 209023a0898aSmrg{ 209123a0898aSmrg FontPathElementPtr fpe = pfont->fpe; 209223a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 209323a0898aSmrg FSBlockedGlyphPtr blockedglyph; 209423a0898aSmrg fsQueryXBitmaps16Req req; 209523a0898aSmrg FSBlockDataPtr blockrec; 209623a0898aSmrg 209723a0898aSmrg if (conn->blockState & FS_GIVE_UP) 209823a0898aSmrg return BadCharRange; 209941c30155Smrg 210023a0898aSmrg /* make a new block record, and add it to the end of the list */ 210123a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); 210223a0898aSmrg if (!blockrec) 210323a0898aSmrg return AllocError; 210423a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 210523a0898aSmrg blockedglyph->pfont = pfont; 210623a0898aSmrg blockedglyph->num_expected_ranges = nranges; 210723a0898aSmrg /* Assumption: it's our job to free ranges */ 210823a0898aSmrg blockedglyph->expected_ranges = ranges; 210923a0898aSmrg blockedglyph->clients_depending = (FSClientsDependingPtr)0; 211023a0898aSmrg 211123a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) 211223a0898aSmrg { 211323a0898aSmrg _fs_pending_reply (conn); 211423a0898aSmrg return Suspended; 211523a0898aSmrg } 211641c30155Smrg 211723a0898aSmrg /* send the request */ 211823a0898aSmrg req.reqType = FS_QueryXBitmaps16; 211923a0898aSmrg req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; 212023a0898aSmrg req.format = pfont->format; 212123a0898aSmrg if (pfont->info.terminalFont) 212223a0898aSmrg req.format = (req.format & ~(BitmapFormatImageRectMask)) | 212323a0898aSmrg BitmapFormatImageRectMax; 212423a0898aSmrg req.range = TRUE; 212523a0898aSmrg /* each range takes up 4 bytes */ 212623a0898aSmrg req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; 212723a0898aSmrg req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ 212823a0898aSmrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 212923a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); 213023a0898aSmrg 213123a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 213241c30155Smrg 213323a0898aSmrg /* Send ranges to the server... pack into a char array by hand 213423a0898aSmrg to avoid structure-packing portability problems and to 213523a0898aSmrg handle swapping for version1 protocol */ 213623a0898aSmrg if (nranges) 213723a0898aSmrg { 213823a0898aSmrg#define RANGE_BUFFER_SIZE 64 213923a0898aSmrg#define RANGE_BUFFER_SIZE_MASK 63 214023a0898aSmrg int i; 214123a0898aSmrg char range_buffer[RANGE_BUFFER_SIZE * 4]; 214223a0898aSmrg char *range_buffer_p; 214323a0898aSmrg 214423a0898aSmrg range_buffer_p = range_buffer; 214523a0898aSmrg for (i = 0; i < nranges;) 214623a0898aSmrg { 214723a0898aSmrg if (conn->fsMajorVersion > 1) 214823a0898aSmrg { 214923a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 215023a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 215123a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 215223a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 215323a0898aSmrg } 215423a0898aSmrg else 215523a0898aSmrg { 215623a0898aSmrg *range_buffer_p++ = ranges[i].min_char_low; 215723a0898aSmrg *range_buffer_p++ = ranges[i].min_char_high; 215823a0898aSmrg *range_buffer_p++ = ranges[i].max_char_low; 215923a0898aSmrg *range_buffer_p++ = ranges[i].max_char_high; 216023a0898aSmrg } 216123a0898aSmrg 216223a0898aSmrg if (!(++i & RANGE_BUFFER_SIZE_MASK)) 216323a0898aSmrg { 216423a0898aSmrg _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); 216523a0898aSmrg range_buffer_p = range_buffer; 216623a0898aSmrg } 216723a0898aSmrg } 216823a0898aSmrg if (i &= RANGE_BUFFER_SIZE_MASK) 216923a0898aSmrg _fs_write(conn, range_buffer, i * 4); 217023a0898aSmrg } 217123a0898aSmrg 217223a0898aSmrg _fs_prepare_for_reply (conn); 217323a0898aSmrg return Suspended; 217423a0898aSmrg} 217523a0898aSmrg 217623a0898aSmrg 217723a0898aSmrgextern pointer serverClient; /* This could be any number that 217823a0898aSmrg doesn't conflict with existing 217923a0898aSmrg client values. */ 218023a0898aSmrg 218123a0898aSmrgstatic int 218241c30155Smrg_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, 218323a0898aSmrg unsigned int nchars, int item_size, unsigned char *data) 218423a0898aSmrg{ 218523a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 218623a0898aSmrg int nranges = 0; 218723a0898aSmrg fsRange *ranges = NULL; 218823a0898aSmrg int res; 218923a0898aSmrg FSBlockDataPtr blockrec; 219023a0898aSmrg FSBlockedGlyphPtr blockedglyph; 219123a0898aSmrg FSClientsDependingPtr *clients_depending = NULL; 219223a0898aSmrg int err; 219323a0898aSmrg 219423a0898aSmrg /* see if the result is already there */ 219523a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 219623a0898aSmrg { 219723a0898aSmrg if (blockrec->type == FS_LOAD_GLYPHS) 219823a0898aSmrg { 219923a0898aSmrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 220023a0898aSmrg if (blockedglyph->pfont == pfont) 220123a0898aSmrg { 220223a0898aSmrg /* Look for this request */ 220323a0898aSmrg if (blockrec->client == client) 220423a0898aSmrg { 220523a0898aSmrg err = blockrec->errcode; 220623a0898aSmrg if (err == StillWorking) 220723a0898aSmrg return Suspended; 220823a0898aSmrg _fs_signal_clients_depending(&blockedglyph->clients_depending); 220923a0898aSmrg _fs_remove_block_rec(conn, blockrec); 221023a0898aSmrg return err; 221123a0898aSmrg } 221223a0898aSmrg /* We've found an existing LoadGlyphs blockrec for this 221323a0898aSmrg font but for another client. Rather than build a 221423a0898aSmrg blockrec for it now (which entails some complex 221523a0898aSmrg maintenance), we'll add it to a queue of clients to 221623a0898aSmrg be signalled when the existing LoadGlyphs is 221723a0898aSmrg completed. */ 221823a0898aSmrg clients_depending = &blockedglyph->clients_depending; 221923a0898aSmrg break; 222023a0898aSmrg } 222123a0898aSmrg } 222223a0898aSmrg else if (blockrec->type == FS_OPEN_FONT) 222323a0898aSmrg { 222423a0898aSmrg FSBlockedFontPtr bfont; 222523a0898aSmrg bfont = (FSBlockedFontPtr) blockrec->data; 222623a0898aSmrg if (bfont->pfont == pfont) 222723a0898aSmrg { 222823a0898aSmrg /* 222923a0898aSmrg * An OpenFont is pending for this font, this must 223023a0898aSmrg * be from a reopen attempt, so finish the open 223123a0898aSmrg * attempt and retry the LoadGlyphs 223223a0898aSmrg */ 223323a0898aSmrg if (blockrec->client == client) 223423a0898aSmrg { 223523a0898aSmrg err = blockrec->errcode; 223623a0898aSmrg if (err == StillWorking) 223723a0898aSmrg return Suspended; 223841c30155Smrg 223923a0898aSmrg _fs_signal_clients_depending(&bfont->clients_depending); 224023a0898aSmrg _fs_remove_block_rec(conn, blockrec); 224123a0898aSmrg if (err != Successful) 224223a0898aSmrg return err; 224323a0898aSmrg break; 224423a0898aSmrg } 224523a0898aSmrg /* We've found an existing OpenFont blockrec for this 224623a0898aSmrg font but for another client. Rather than build a 224723a0898aSmrg blockrec for it now (which entails some complex 224823a0898aSmrg maintenance), we'll add it to a queue of clients to 224923a0898aSmrg be signalled when the existing OpenFont is 225023a0898aSmrg completed. */ 225123a0898aSmrg if (blockrec->errcode == StillWorking) 225223a0898aSmrg { 225323a0898aSmrg clients_depending = &bfont->clients_depending; 225423a0898aSmrg break; 225523a0898aSmrg } 225623a0898aSmrg } 225723a0898aSmrg } 225823a0898aSmrg } 225923a0898aSmrg 226023a0898aSmrg /* 226123a0898aSmrg * see if the desired glyphs already exist, and return Successful if they 226223a0898aSmrg * do, otherwise build up character range/character string 226323a0898aSmrg */ 226423a0898aSmrg res = fs_build_range(pfont, range_flag, nchars, item_size, data, 226523a0898aSmrg &nranges, &ranges); 226623a0898aSmrg 226723a0898aSmrg switch (res) 226823a0898aSmrg { 226923a0898aSmrg case AccessDone: 227023a0898aSmrg return Successful; 227123a0898aSmrg 227223a0898aSmrg case Successful: 227323a0898aSmrg break; 227423a0898aSmrg 227523a0898aSmrg default: 227623a0898aSmrg return res; 227723a0898aSmrg } 227823a0898aSmrg 227923a0898aSmrg /* 228023a0898aSmrg * If clients_depending is not null, this request must wait for 228123a0898aSmrg * some prior request(s) to complete. 228223a0898aSmrg */ 228323a0898aSmrg if (clients_depending) 228423a0898aSmrg { 228523a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 228623a0898aSmrg clean up the damage (if any) caused by the fs_build_range() 228723a0898aSmrg call. */ 228823a0898aSmrg if (nranges) 228923a0898aSmrg { 229023a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 22917f7f5e4eSmrg free(ranges); 229223a0898aSmrg } 229323a0898aSmrg return _fs_add_clients_depending(clients_depending, client); 229423a0898aSmrg } 229523a0898aSmrg 229623a0898aSmrg /* 229723a0898aSmrg * If fsd->generation != conn->generation, the font has been closed 229823a0898aSmrg * due to a lost connection. We will reopen it, which will result 229923a0898aSmrg * in one of three things happening: 230023a0898aSmrg * 1) The open will succeed and obtain the same font. Life 230123a0898aSmrg * is wonderful. 230223a0898aSmrg * 2) The open will fail. There is code above to recognize this 230323a0898aSmrg * and flunk the LoadGlyphs request. The client might not be 230423a0898aSmrg * thrilled. 230523a0898aSmrg * 3) Worst case: the open will succeed but the font we open will 230623a0898aSmrg * be different. The fs_read_query_info() procedure attempts 230723a0898aSmrg * to detect this by comparing the existing metrics and 230823a0898aSmrg * properties against those of the reopened font... if they 230923a0898aSmrg * don't match, we flunk the reopen, which eventually results 231023a0898aSmrg * in flunking the LoadGlyphs request. We could go a step 231123a0898aSmrg * further and compare the extents, but this should be 231223a0898aSmrg * sufficient. 231323a0898aSmrg */ 231423a0898aSmrg if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) 231523a0898aSmrg { 231623a0898aSmrg /* Since we're not ready to send the load_glyphs request yet, 231723a0898aSmrg clean up the damage caused by the fs_build_range() call. */ 231823a0898aSmrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 23197f7f5e4eSmrg free(ranges); 232023a0898aSmrg 232123a0898aSmrg /* Now try to reopen the font. */ 232223a0898aSmrg return fs_send_open_font(client, pfont->fpe, 232323a0898aSmrg (Mask)FontReopen, (char *)0, 0, 232423a0898aSmrg (fsBitmapFormat)0, (fsBitmapFormatMask)0, 232523a0898aSmrg (XID)0, &pfont); 232623a0898aSmrg } 232723a0898aSmrg 232823a0898aSmrg return fs_send_load_glyphs(client, pfont, nranges, ranges); 232923a0898aSmrg} 233023a0898aSmrg 233123a0898aSmrgint 233223a0898aSmrgfs_load_all_glyphs(FontPtr pfont) 233323a0898aSmrg{ 233423a0898aSmrg int err; 233523a0898aSmrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 233623a0898aSmrg 233723a0898aSmrg /* 233823a0898aSmrg * The purpose of this procedure is to load all glyphs in the event 233923a0898aSmrg * that we're dealing with someone who doesn't understand the finer 234023a0898aSmrg * points of glyph caching... it is called from _fs_get_glyphs() if 234123a0898aSmrg * the latter is called to get glyphs that have not yet been loaded. 234223a0898aSmrg * We assume that the caller will not know how to handle a return 234323a0898aSmrg * value of Suspended (usually the case for a GetGlyphs() caller), 234423a0898aSmrg * so this procedure hangs around, freezing the server, for the 234523a0898aSmrg * request to complete. This is an unpleasant kluge called to 234623a0898aSmrg * perform an unpleasant job that, we hope, will never be required. 234723a0898aSmrg */ 234823a0898aSmrg 234923a0898aSmrg while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) == 235023a0898aSmrg Suspended) 235123a0898aSmrg { 235223a0898aSmrg if (fs_await_reply (conn) != FSIO_READY) 235323a0898aSmrg { 235423a0898aSmrg /* Get rid of blockrec */ 235523a0898aSmrg fs_client_died(serverClient, pfont->fpe); 235623a0898aSmrg err = BadCharRange; 235723a0898aSmrg break; 235823a0898aSmrg } 235923a0898aSmrg fs_read_reply (pfont->fpe, serverClient); 236023a0898aSmrg } 236123a0898aSmrg return err; 236223a0898aSmrg} 236323a0898aSmrg 236423a0898aSmrgstatic int 236523a0898aSmrgfs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 236623a0898aSmrg{ 236723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 236823a0898aSmrg FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; 236923a0898aSmrg fsListFontsReply *rep; 237023a0898aSmrg char *data; 23717673729aSmrg long dataleft; /* length of reply left to use */ 237223a0898aSmrg int length, 237323a0898aSmrg i, 237423a0898aSmrg ret; 237523a0898aSmrg int err; 237623a0898aSmrg 237723a0898aSmrg rep = (fsListFontsReply *) fs_get_reply (conn, &ret); 23789d21a897Sspz if (!rep || rep->type == FS_Error || 23797673729aSmrg (rep->length < LENGTHOF(fsListFontsReply))) 238023a0898aSmrg { 238123a0898aSmrg if (ret == FSIO_BLOCK) 238223a0898aSmrg return StillWorking; 238323a0898aSmrg if (rep) 238423a0898aSmrg _fs_done_read (conn, rep->length << 2); 23859d21a897Sspz _fs_reply_failed (rep, fsListFontsReply, "<"); 238623a0898aSmrg return AllocError; 238723a0898aSmrg } 238823a0898aSmrg data = (char *) rep + SIZEOF (fsListFontsReply); 23899d21a897Sspz dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply); 239023a0898aSmrg 239123a0898aSmrg err = Successful; 239223a0898aSmrg /* copy data into FontPathRecord */ 239341c30155Smrg for (i = 0; i < rep->nFonts; i++) 239423a0898aSmrg { 23957673729aSmrg if (dataleft < 1) 23967673729aSmrg break; 239723a0898aSmrg length = *(unsigned char *)data++; 23987673729aSmrg dataleft--; /* used length byte */ 23997673729aSmrg if (length > dataleft) { 24009d21a897Sspz#ifdef DEBUG 24017673729aSmrg fprintf(stderr, 24027673729aSmrg "fsListFonts: name length (%d) > dataleft (%ld)\n", 24037673729aSmrg length, dataleft); 24049d21a897Sspz#endif 24057673729aSmrg err = BadFontName; 24067673729aSmrg break; 24077673729aSmrg } 240823a0898aSmrg err = AddFontNamesName(blist->names, data, length); 240923a0898aSmrg if (err != Successful) 241023a0898aSmrg break; 241123a0898aSmrg data += length; 24129d21a897Sspz dataleft -= length; 241323a0898aSmrg } 241423a0898aSmrg _fs_done_read (conn, rep->length << 2); 241523a0898aSmrg return err; 241623a0898aSmrg} 241723a0898aSmrg 241823a0898aSmrgstatic int 241941c30155Smrgfs_send_list_fonts(pointer client, FontPathElementPtr fpe, char *pattern, 242023a0898aSmrg int patlen, int maxnames, FontNamesPtr newnames) 242123a0898aSmrg{ 242223a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 242323a0898aSmrg FSBlockDataPtr blockrec; 242423a0898aSmrg FSBlockedListPtr blockedlist; 242523a0898aSmrg fsListFontsReq req; 242623a0898aSmrg 242723a0898aSmrg if (conn->blockState & FS_GIVE_UP) 242823a0898aSmrg return BadFontName; 242941c30155Smrg 243023a0898aSmrg /* make a new block record, and add it to the end of the list */ 243123a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); 243223a0898aSmrg if (!blockrec) 243323a0898aSmrg return AllocError; 243423a0898aSmrg blockedlist = (FSBlockedListPtr) blockrec->data; 243523a0898aSmrg blockedlist->names = newnames; 243623a0898aSmrg 243723a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 243823a0898aSmrg { 243923a0898aSmrg _fs_pending_reply (conn); 244023a0898aSmrg return Suspended; 244123a0898aSmrg } 244241c30155Smrg 244323a0898aSmrg _fs_client_access (conn, client, FALSE); 244423a0898aSmrg _fs_client_resolution(conn); 244523a0898aSmrg 244623a0898aSmrg /* send the request */ 244723a0898aSmrg req.reqType = FS_ListFonts; 24487f7f5e4eSmrg req.pad = 0; 244923a0898aSmrg req.maxNames = maxnames; 245023a0898aSmrg req.nbytes = patlen; 245123a0898aSmrg req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; 245223a0898aSmrg _fs_add_req_log(conn, FS_ListFonts); 245323a0898aSmrg _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); 245423a0898aSmrg _fs_write_pad(conn, (char *) pattern, patlen); 245523a0898aSmrg 245623a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 245741c30155Smrg 245823a0898aSmrg#ifdef NCD 245923a0898aSmrg if (configData.ExtendedFontDiags) { 246023a0898aSmrg char buf[256]; 246123a0898aSmrg 246223a0898aSmrg memcpy(buf, pattern, MIN(256, patlen)); 246323a0898aSmrg buf[MIN(256, patlen)] = '\0'; 246423a0898aSmrg printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", 246523a0898aSmrg buf, fpe->name); 246623a0898aSmrg } 246723a0898aSmrg#endif 246823a0898aSmrg 246923a0898aSmrg _fs_prepare_for_reply (conn); 247023a0898aSmrg return Suspended; 247123a0898aSmrg} 247223a0898aSmrg 247323a0898aSmrgstatic int 247441c30155Smrgfs_list_fonts(pointer client, FontPathElementPtr fpe, 247523a0898aSmrg char *pattern, int patlen, int maxnames, FontNamesPtr newnames) 247623a0898aSmrg{ 247723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 247823a0898aSmrg FSBlockDataPtr blockrec; 247923a0898aSmrg int err; 248023a0898aSmrg 248123a0898aSmrg /* see if the result is already there */ 248223a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 248323a0898aSmrg { 248441c30155Smrg if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) 248523a0898aSmrg { 248623a0898aSmrg err = blockrec->errcode; 248723a0898aSmrg if (err == StillWorking) 248823a0898aSmrg return Suspended; 248923a0898aSmrg _fs_remove_block_rec(conn, blockrec); 249023a0898aSmrg return err; 249123a0898aSmrg } 249223a0898aSmrg } 249323a0898aSmrg 249423a0898aSmrg /* didn't find waiting record, so send a new one */ 249523a0898aSmrg return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); 249623a0898aSmrg} 249723a0898aSmrg 249823a0898aSmrg/* 249923a0898aSmrg * Read a single list info reply and restart for the next reply 250023a0898aSmrg */ 250123a0898aSmrgstatic int 250223a0898aSmrgfs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 250323a0898aSmrg{ 250423a0898aSmrg FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; 250523a0898aSmrg fsListFontsWithXInfoReply *rep; 250623a0898aSmrg char *buf; 25077673729aSmrg long bufleft; 250823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 250923a0898aSmrg fsPropInfo *pi; 251023a0898aSmrg fsPropOffset *po; 251123a0898aSmrg pointer pd; 251223a0898aSmrg int ret; 251323a0898aSmrg int err; 251423a0898aSmrg 251523a0898aSmrg /* clean up anything from the last trip */ 251623a0898aSmrg _fs_free_props (&binfo->info); 251723a0898aSmrg 251823a0898aSmrg rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); 25199d21a897Sspz if (!rep || rep->type == FS_Error || 25207673729aSmrg ((rep->nameLength != 0) && 25217673729aSmrg (rep->length < LENGTHOF(fsListFontsWithXInfoReply)))) 252223a0898aSmrg { 252323a0898aSmrg if (ret == FSIO_BLOCK) 252423a0898aSmrg return StillWorking; 252523a0898aSmrg binfo->status = FS_LFWI_FINISHED; 252623a0898aSmrg err = AllocError; 25277673729aSmrg _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<"); 252823a0898aSmrg goto done; 252923a0898aSmrg } 253023a0898aSmrg /* 253123a0898aSmrg * Normal termination -- the list ends with a name of length 0 253223a0898aSmrg */ 253323a0898aSmrg if (rep->nameLength == 0) 253423a0898aSmrg { 253523a0898aSmrg#ifdef DEBUG 253623a0898aSmrg fprintf (stderr, "fs_read_list_info done\n"); 253723a0898aSmrg#endif 253823a0898aSmrg binfo->status = FS_LFWI_FINISHED; 253923a0898aSmrg err = BadFontName; 254023a0898aSmrg goto done; 254123a0898aSmrg } 254223a0898aSmrg 254323a0898aSmrg buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); 25447673729aSmrg bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply); 254541c30155Smrg 254623a0898aSmrg /* 254723a0898aSmrg * The original FS implementation didn't match 254823a0898aSmrg * the spec, version 1 was respecified to match the FS. 254923a0898aSmrg * Version 2 matches the original intent 255023a0898aSmrg */ 255123a0898aSmrg if (conn->fsMajorVersion <= 1) 255223a0898aSmrg { 25537673729aSmrg if (rep->nameLength > bufleft) { 25547673729aSmrg#ifdef DEBUG 25557673729aSmrg fprintf(stderr, 25567673729aSmrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 25577673729aSmrg (int) rep->nameLength, bufleft); 25587673729aSmrg#endif 25597673729aSmrg err = AllocError; 25607673729aSmrg goto done; 25617673729aSmrg } 25627673729aSmrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 256323a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 256423a0898aSmrg buf += _fs_pad_length (rep->nameLength); 25657673729aSmrg bufleft -= _fs_pad_length (rep->nameLength); 256623a0898aSmrg } 256723a0898aSmrg pi = (fsPropInfo *) buf; 25687673729aSmrg if (SIZEOF (fsPropInfo) > bufleft) { 25697673729aSmrg#ifdef DEBUG 25707673729aSmrg fprintf(stderr, 25717673729aSmrg "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n", 25727673729aSmrg (int) SIZEOF (fsPropInfo), bufleft); 25737673729aSmrg#endif 25747673729aSmrg err = AllocError; 25757673729aSmrg goto done; 25767673729aSmrg } 25777673729aSmrg bufleft -= SIZEOF (fsPropInfo); 257823a0898aSmrg buf += SIZEOF (fsPropInfo); 257923a0898aSmrg po = (fsPropOffset *) buf; 25807673729aSmrg if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) { 25817673729aSmrg#ifdef DEBUG 25827673729aSmrg fprintf(stderr, 25837673729aSmrg "fsListFontsWithXInfo: offset length (%d * %d) > bufleft (%ld)\n", 25847673729aSmrg pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft); 25857673729aSmrg#endif 25867673729aSmrg err = AllocError; 25877673729aSmrg goto done; 25887673729aSmrg } 25897673729aSmrg bufleft -= pi->num_offsets * SIZEOF (fsPropOffset); 259023a0898aSmrg buf += pi->num_offsets * SIZEOF (fsPropOffset); 259123a0898aSmrg pd = (pointer) buf; 25927673729aSmrg if (pi->data_len > bufleft) { 25937673729aSmrg#ifdef DEBUG 25947673729aSmrg fprintf(stderr, 25957673729aSmrg "fsListFontsWithXInfo: data length (%d) > bufleft (%ld)\n", 25967673729aSmrg pi->data_len, bufleft); 25977673729aSmrg#endif 25987673729aSmrg err = AllocError; 25997673729aSmrg goto done; 26007673729aSmrg } 26017673729aSmrg bufleft -= pi->data_len; 260223a0898aSmrg buf += pi->data_len; 260323a0898aSmrg if (conn->fsMajorVersion > 1) 260423a0898aSmrg { 26057673729aSmrg if (rep->nameLength > bufleft) { 26067673729aSmrg#ifdef DEBUG 26077673729aSmrg fprintf(stderr, 26087673729aSmrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 26097673729aSmrg (int) rep->nameLength, bufleft); 26107673729aSmrg#endif 26117673729aSmrg err = AllocError; 26127673729aSmrg goto done; 26137673729aSmrg } 26147673729aSmrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 261523a0898aSmrg memcpy (binfo->name, buf, rep->nameLength); 261623a0898aSmrg buf += _fs_pad_length (rep->nameLength); 26177673729aSmrg bufleft -= _fs_pad_length (rep->nameLength); 261823a0898aSmrg } 261923a0898aSmrg 262023a0898aSmrg#ifdef DEBUG 262123a0898aSmrg binfo->name[rep->nameLength] = '\0'; 262223a0898aSmrg fprintf (stderr, "fs_read_list_info %s\n", binfo->name); 262323a0898aSmrg#endif 262423a0898aSmrg err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); 262523a0898aSmrg if (err != Successful) 262623a0898aSmrg { 262723a0898aSmrg binfo->status = FS_LFWI_FINISHED; 262823a0898aSmrg goto done; 262923a0898aSmrg } 263023a0898aSmrg binfo->namelen = rep->nameLength; 263123a0898aSmrg binfo->remaining = rep->nReplies; 263223a0898aSmrg 263323a0898aSmrg binfo->status = FS_LFWI_REPLY; 263441c30155Smrg 263523a0898aSmrg /* disable this font server until we've processed this response */ 263623a0898aSmrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 263723a0898aSmrg FD_CLR(conn->fs_fd, &_fs_fd_mask); 263841c30155Smrgdone: 263923a0898aSmrg _fs_done_read (conn, rep->length << 2); 264023a0898aSmrg return err; 264123a0898aSmrg} 264223a0898aSmrg 264323a0898aSmrg/* ARGSUSED */ 264423a0898aSmrgstatic int 264541c30155Smrgfs_start_list_with_info(pointer client, FontPathElementPtr fpe, 264623a0898aSmrg char *pattern, int len, int maxnames, pointer *pdata) 264723a0898aSmrg{ 264823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 264923a0898aSmrg FSBlockDataPtr blockrec; 265023a0898aSmrg FSBlockedListInfoPtr binfo; 265123a0898aSmrg fsListFontsWithXInfoReq req; 265223a0898aSmrg 265323a0898aSmrg if (conn->blockState & FS_GIVE_UP) 265423a0898aSmrg return BadFontName; 265523a0898aSmrg 265623a0898aSmrg /* make a new block record, and add it to the end of the list */ 265723a0898aSmrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); 265823a0898aSmrg if (!blockrec) 265923a0898aSmrg return AllocError; 266041c30155Smrg 266123a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 266223a0898aSmrg bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); 266323a0898aSmrg binfo->status = FS_LFWI_WAITING; 266423a0898aSmrg 266523a0898aSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 266623a0898aSmrg { 266723a0898aSmrg _fs_pending_reply (conn); 266823a0898aSmrg return Suspended; 266923a0898aSmrg } 267041c30155Smrg 267123a0898aSmrg _fs_client_access (conn, client, FALSE); 267223a0898aSmrg _fs_client_resolution(conn); 267323a0898aSmrg 267423a0898aSmrg /* send the request */ 267523a0898aSmrg req.reqType = FS_ListFontsWithXInfo; 26767f7f5e4eSmrg req.pad = 0; 267723a0898aSmrg req.maxNames = maxnames; 267823a0898aSmrg req.nbytes = len; 267923a0898aSmrg req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; 268023a0898aSmrg _fs_add_req_log(conn, FS_ListFontsWithXInfo); 268123a0898aSmrg (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); 268223a0898aSmrg (void) _fs_write_pad(conn, pattern, len); 268323a0898aSmrg 268423a0898aSmrg blockrec->sequenceNumber = conn->current_seq; 268541c30155Smrg 268623a0898aSmrg#ifdef NCD 268723a0898aSmrg if (configData.ExtendedFontDiags) { 268823a0898aSmrg char buf[256]; 268923a0898aSmrg 269023a0898aSmrg memcpy(buf, pattern, MIN(256, len)); 269123a0898aSmrg buf[MIN(256, len)] = '\0'; 269223a0898aSmrg printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", 269323a0898aSmrg buf, fpe->name); 269423a0898aSmrg } 269523a0898aSmrg#endif 269623a0898aSmrg 269723a0898aSmrg _fs_prepare_for_reply (conn); 269823a0898aSmrg return Successful; 269923a0898aSmrg} 270023a0898aSmrg 270123a0898aSmrg/* ARGSUSED */ 270223a0898aSmrgstatic int 270341c30155Smrgfs_next_list_with_info(pointer client, FontPathElementPtr fpe, 270441c30155Smrg char **namep, int *namelenp, 270523a0898aSmrg FontInfoPtr *pFontInfo, int *numFonts, 270623a0898aSmrg pointer private) 270723a0898aSmrg{ 270823a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 270923a0898aSmrg FSBlockDataPtr blockrec; 271023a0898aSmrg FSBlockedListInfoPtr binfo; 271123a0898aSmrg int err; 271223a0898aSmrg 271323a0898aSmrg /* see if the result is already there */ 271423a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 271541c30155Smrg if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) 271623a0898aSmrg break; 271723a0898aSmrg 271823a0898aSmrg if (!blockrec) 271923a0898aSmrg { 272023a0898aSmrg /* The only good reason for not finding a blockrec would be if 272123a0898aSmrg disconnect/reconnect to the font server wiped it out and the 272223a0898aSmrg code that called us didn't do the right thing to create 272323a0898aSmrg another one. Under those circumstances, we need to return an 272423a0898aSmrg error to prevent that code from attempting to interpret the 272523a0898aSmrg information we don't return. */ 272623a0898aSmrg return BadFontName; 272723a0898aSmrg } 272823a0898aSmrg 272923a0898aSmrg binfo = (FSBlockedListInfoPtr) blockrec->data; 273041c30155Smrg 273123a0898aSmrg if (binfo->status == FS_LFWI_WAITING) 273223a0898aSmrg return Suspended; 273323a0898aSmrg 273423a0898aSmrg *namep = binfo->name; 273523a0898aSmrg *namelenp = binfo->namelen; 273623a0898aSmrg *pFontInfo = &binfo->info; 273723a0898aSmrg *numFonts = binfo->remaining; 273841c30155Smrg 273923a0898aSmrg /* Restart reply processing from this font server */ 274023a0898aSmrg FD_SET(conn->fs_fd, &_fs_fd_mask); 274123a0898aSmrg if (fs_reply_ready (conn)) 274223a0898aSmrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 274341c30155Smrg 274423a0898aSmrg err = blockrec->errcode; 274523a0898aSmrg switch (binfo->status) { 274623a0898aSmrg case FS_LFWI_FINISHED: 274723a0898aSmrg _fs_remove_block_rec(conn, blockrec); 274823a0898aSmrg break; 274923a0898aSmrg case FS_LFWI_REPLY: 275023a0898aSmrg binfo->status = FS_LFWI_WAITING; 275123a0898aSmrg blockrec->errcode = StillWorking; 275223a0898aSmrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 275323a0898aSmrg _fs_mark_block (conn, FS_PENDING_REPLY); 275423a0898aSmrg break; 275523a0898aSmrg } 275641c30155Smrg 275723a0898aSmrg return err; 275823a0898aSmrg} 275923a0898aSmrg 276023a0898aSmrg/* 276123a0898aSmrg * Called when client exits 276223a0898aSmrg */ 276323a0898aSmrg 276423a0898aSmrgstatic void 276523a0898aSmrgfs_client_died(pointer client, FontPathElementPtr fpe) 276623a0898aSmrg{ 276723a0898aSmrg FSFpePtr conn = (FSFpePtr) fpe->private; 276823a0898aSmrg FSBlockDataPtr blockrec, 276923a0898aSmrg depending; 277023a0898aSmrg FSClientPtr *prev, cur; 277123a0898aSmrg fsFreeACReq freeac; 277223a0898aSmrg 277323a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 277423a0898aSmrg { 277523a0898aSmrg if (cur->client == client) { 277623a0898aSmrg freeac.reqType = FS_FreeAC; 27777f7f5e4eSmrg freeac.pad = 0; 277823a0898aSmrg freeac.id = cur->acid; 277923a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 278023a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 278123a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 278223a0898aSmrg *prev = cur->next; 27837f7f5e4eSmrg free (cur); 278423a0898aSmrg break; 278523a0898aSmrg } 278623a0898aSmrg } 278723a0898aSmrg /* find a pending requests */ 278823a0898aSmrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 278923a0898aSmrg if (blockrec->client == client) 279023a0898aSmrg break; 279141c30155Smrg 279223a0898aSmrg if (!blockrec) 279323a0898aSmrg return; 279441c30155Smrg 279523a0898aSmrg /* replace the client pointers in this block rec with the chained one */ 279641c30155Smrg if ((depending = blockrec->depending)) 279723a0898aSmrg { 279823a0898aSmrg blockrec->client = depending->client; 279923a0898aSmrg blockrec->depending = depending->depending; 280023a0898aSmrg blockrec = depending; 280123a0898aSmrg } 280223a0898aSmrg fs_abort_blockrec(conn, blockrec); 280323a0898aSmrg} 280423a0898aSmrg 280523a0898aSmrgstatic void 280623a0898aSmrg_fs_client_access (FSFpePtr conn, pointer client, Bool sync) 280723a0898aSmrg{ 280823a0898aSmrg FSClientPtr *prev, cur; 280923a0898aSmrg fsCreateACReq crac; 281023a0898aSmrg fsSetAuthorizationReq setac; 281123a0898aSmrg char *authorizations; 281223a0898aSmrg int authlen; 281323a0898aSmrg Bool new_cur = FALSE; 28147f7f5e4eSmrg char padding[4] = { 0, 0, 0, 0 }; 281523a0898aSmrg 281623a0898aSmrg#ifdef DEBUG 281723a0898aSmrg if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) 281823a0898aSmrg { 281923a0898aSmrg fprintf (stderr, "Sending requests without a connection\n"); 282023a0898aSmrg } 282123a0898aSmrg#endif 282223a0898aSmrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 282323a0898aSmrg { 282423a0898aSmrg if (cur->client == client) 282523a0898aSmrg { 282623a0898aSmrg if (prev != &conn->clients) 282723a0898aSmrg { 282823a0898aSmrg *prev = cur->next; 282923a0898aSmrg cur->next = conn->clients; 283023a0898aSmrg conn->clients = cur; 283123a0898aSmrg } 283223a0898aSmrg break; 283323a0898aSmrg } 283423a0898aSmrg } 283523a0898aSmrg if (!cur) 283623a0898aSmrg { 28377f7f5e4eSmrg cur = malloc (sizeof (FSClientRec)); 283823a0898aSmrg if (!cur) 283923a0898aSmrg return; 284023a0898aSmrg cur->client = client; 284123a0898aSmrg cur->next = conn->clients; 284223a0898aSmrg conn->clients = cur; 284323a0898aSmrg cur->acid = GetNewFontClientID (); 284423a0898aSmrg new_cur = TRUE; 284523a0898aSmrg } 284623a0898aSmrg if (new_cur || cur->auth_generation != client_auth_generation(client)) 284723a0898aSmrg { 284823a0898aSmrg if (!new_cur) 284923a0898aSmrg { 285023a0898aSmrg fsFreeACReq freeac; 285123a0898aSmrg freeac.reqType = FS_FreeAC; 28527f7f5e4eSmrg freeac.pad = 0; 285323a0898aSmrg freeac.id = cur->acid; 285423a0898aSmrg freeac.length = sizeof (fsFreeACReq) >> 2; 285523a0898aSmrg _fs_add_req_log(conn, FS_FreeAC); 285623a0898aSmrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 285723a0898aSmrg } 285823a0898aSmrg crac.reqType = FS_CreateAC; 285923a0898aSmrg crac.num_auths = set_font_authorizations(&authorizations, &authlen, 286023a0898aSmrg client); 28617f7f5e4eSmrg /* Work around bug in xfs versions up through modular release 1.0.8 28627f7f5e4eSmrg which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ 28637f7f5e4eSmrg if (crac.num_auths == 0) { 28647f7f5e4eSmrg authorizations = padding; 28657f7f5e4eSmrg authlen = 4; 28667f7f5e4eSmrg } else { 28677f7f5e4eSmrg authlen = (authlen + 3) & ~0x3; 28687f7f5e4eSmrg } 286923a0898aSmrg crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; 287023a0898aSmrg crac.acid = cur->acid; 287123a0898aSmrg _fs_add_req_log(conn, FS_CreateAC); 287223a0898aSmrg _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); 287323a0898aSmrg _fs_write(conn, authorizations, authlen); 287423a0898aSmrg /* ignore reply; we don't even care about it */ 287523a0898aSmrg conn->curacid = 0; 287623a0898aSmrg cur->auth_generation = client_auth_generation(client); 287723a0898aSmrg } 287823a0898aSmrg if (conn->curacid != cur->acid) 287923a0898aSmrg { 288023a0898aSmrg setac.reqType = FS_SetAuthorization; 28817f7f5e4eSmrg setac.pad = 0; 288223a0898aSmrg setac.length = sizeof (fsSetAuthorizationReq) >> 2; 288323a0898aSmrg setac.id = cur->acid; 288423a0898aSmrg _fs_add_req_log(conn, FS_SetAuthorization); 288523a0898aSmrg _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); 288623a0898aSmrg conn->curacid = cur->acid; 288723a0898aSmrg } 288823a0898aSmrg} 288923a0898aSmrg 289023a0898aSmrg/* 289123a0898aSmrg * Poll a pending connect 289223a0898aSmrg */ 289323a0898aSmrg 289423a0898aSmrgstatic int 289523a0898aSmrg_fs_check_connect (FSFpePtr conn) 289623a0898aSmrg{ 289723a0898aSmrg int ret; 289841c30155Smrg 289923a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 0); 290023a0898aSmrg switch (ret) { 290123a0898aSmrg case FSIO_READY: 290223a0898aSmrg conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); 290323a0898aSmrg FD_SET (conn->fs_fd, &_fs_fd_mask); 290423a0898aSmrg break; 290523a0898aSmrg case FSIO_BLOCK: 290623a0898aSmrg break; 290723a0898aSmrg } 290823a0898aSmrg return ret; 290923a0898aSmrg} 291023a0898aSmrg 291123a0898aSmrg/* 291223a0898aSmrg * Return an FSIO status while waiting for the completed connection 291323a0898aSmrg * reply to arrive 291423a0898aSmrg */ 291523a0898aSmrg 291623a0898aSmrgstatic fsConnSetup * 291723a0898aSmrg_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) 291823a0898aSmrg{ 291923a0898aSmrg int ret; 292023a0898aSmrg char *data; 292123a0898aSmrg int headlen; 292223a0898aSmrg int len; 292323a0898aSmrg fsConnSetup *setup; 292423a0898aSmrg fsConnSetupAccept *accept; 292523a0898aSmrg 292623a0898aSmrg ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); 292723a0898aSmrg if (ret != FSIO_READY) 292823a0898aSmrg { 292923a0898aSmrg *error = ret; 293023a0898aSmrg return 0; 293123a0898aSmrg } 293241c30155Smrg 293323a0898aSmrg setup = (fsConnSetup *) data; 293423a0898aSmrg if (setup->major_version > FS_PROTOCOL) 293523a0898aSmrg { 293623a0898aSmrg *error = FSIO_ERROR; 293723a0898aSmrg return 0; 293823a0898aSmrg } 293923a0898aSmrg 294023a0898aSmrg headlen = (SIZEOF (fsConnSetup) + 294123a0898aSmrg (setup->alternate_len << 2) + 294223a0898aSmrg (setup->auth_len << 2)); 294323a0898aSmrg /* On anything but Success, no extra data is sent */ 294423a0898aSmrg if (setup->status != AuthSuccess) 294523a0898aSmrg { 294623a0898aSmrg len = headlen; 294723a0898aSmrg } 294823a0898aSmrg else 294923a0898aSmrg { 295023a0898aSmrg ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); 295123a0898aSmrg if (ret != FSIO_READY) 295223a0898aSmrg { 295323a0898aSmrg *error = ret; 295423a0898aSmrg return 0; 295523a0898aSmrg } 295623a0898aSmrg setup = (fsConnSetup *) data; 295723a0898aSmrg accept = (fsConnSetupAccept *) (data + headlen); 295823a0898aSmrg len = headlen + (accept->length << 2); 295923a0898aSmrg } 296023a0898aSmrg ret = _fs_start_read (conn, len, &data); 296123a0898aSmrg if (ret != FSIO_READY) 296223a0898aSmrg { 296323a0898aSmrg *error = ret; 296423a0898aSmrg return 0; 296523a0898aSmrg } 296623a0898aSmrg *setup_len = len; 296723a0898aSmrg return (fsConnSetup *) data; 296823a0898aSmrg} 296923a0898aSmrg 297023a0898aSmrgstatic int 297123a0898aSmrg_fs_send_conn_client_prefix (FSFpePtr conn) 297223a0898aSmrg{ 297323a0898aSmrg fsConnClientPrefix req; 297423a0898aSmrg int endian; 297523a0898aSmrg int ret; 297623a0898aSmrg 297723a0898aSmrg /* send setup prefix */ 297823a0898aSmrg endian = 1; 297923a0898aSmrg if (*(char *) &endian) 298023a0898aSmrg req.byteOrder = 'l'; 298123a0898aSmrg else 298223a0898aSmrg req.byteOrder = 'B'; 298323a0898aSmrg 298423a0898aSmrg req.major_version = FS_PROTOCOL; 298523a0898aSmrg req.minor_version = FS_PROTOCOL_MINOR; 298623a0898aSmrg 298723a0898aSmrg/* XXX add some auth info here */ 298823a0898aSmrg req.num_auths = 0; 298923a0898aSmrg req.auth_len = 0; 299023a0898aSmrg ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); 299123a0898aSmrg if (ret != FSIO_READY) 299223a0898aSmrg return FSIO_ERROR; 299323a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 299423a0898aSmrg return ret; 299523a0898aSmrg} 299623a0898aSmrg 299723a0898aSmrgstatic int 299823a0898aSmrg_fs_recv_conn_setup (FSFpePtr conn) 299923a0898aSmrg{ 300023a0898aSmrg int ret = FSIO_ERROR; 300123a0898aSmrg fsConnSetup *setup; 300223a0898aSmrg FSFpeAltPtr alts; 30039d21a897Sspz unsigned int i, alt_len; 300423a0898aSmrg int setup_len; 300523a0898aSmrg char *alt_save, *alt_names; 300641c30155Smrg 300723a0898aSmrg setup = _fs_get_conn_setup (conn, &ret, &setup_len); 300823a0898aSmrg if (!setup) 300923a0898aSmrg return ret; 301023a0898aSmrg conn->current_seq = 0; 301123a0898aSmrg conn->fsMajorVersion = setup->major_version; 301223a0898aSmrg /* 301323a0898aSmrg * Create an alternate list from the initial server, but 301423a0898aSmrg * don't chain looking for alternates. 301523a0898aSmrg */ 301623a0898aSmrg if (conn->alternate == 0) 301723a0898aSmrg { 301823a0898aSmrg /* 301923a0898aSmrg * free any existing alternates list, allowing the list to 302023a0898aSmrg * be updated 302123a0898aSmrg */ 302223a0898aSmrg if (conn->alts) 302323a0898aSmrg { 30247f7f5e4eSmrg free (conn->alts); 302523a0898aSmrg conn->alts = 0; 302623a0898aSmrg conn->numAlts = 0; 302723a0898aSmrg } 302823a0898aSmrg if (setup->num_alternates) 302923a0898aSmrg { 30309d21a897Sspz size_t alt_name_len = setup->alternate_len << 2; 30317f7f5e4eSmrg alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + 30329d21a897Sspz alt_name_len); 303323a0898aSmrg if (alts) 303423a0898aSmrg { 303523a0898aSmrg alt_names = (char *) (setup + 1); 303623a0898aSmrg alt_save = (char *) (alts + setup->num_alternates); 303723a0898aSmrg for (i = 0; i < setup->num_alternates; i++) 303823a0898aSmrg { 303923a0898aSmrg alts[i].subset = alt_names[0]; 304023a0898aSmrg alt_len = alt_names[1]; 30417673729aSmrg if (alt_len >= alt_name_len) { 30427673729aSmrg /* 30437673729aSmrg * Length is longer than setup->alternate_len 30447673729aSmrg * told us to allocate room for, assume entire 30457673729aSmrg * alternate list is corrupted. 30467673729aSmrg */ 30479d21a897Sspz#ifdef DEBUG 30487673729aSmrg fprintf (stderr, 30497673729aSmrg "invalid alt list (length %lx >= %lx)\n", 30507673729aSmrg (long) alt_len, (long) alt_name_len); 30519d21a897Sspz#endif 30527673729aSmrg free(alts); 30537673729aSmrg return FSIO_ERROR; 30547673729aSmrg } 305523a0898aSmrg alts[i].name = alt_save; 305623a0898aSmrg memcpy (alt_save, alt_names + 2, alt_len); 305723a0898aSmrg alt_save[alt_len] = '\0'; 305823a0898aSmrg alt_save += alt_len + 1; 30597673729aSmrg alt_name_len -= alt_len + 1; 306023a0898aSmrg alt_names += _fs_pad_length (alt_len + 2); 306123a0898aSmrg } 306223a0898aSmrg conn->numAlts = setup->num_alternates; 306323a0898aSmrg conn->alts = alts; 306423a0898aSmrg } 306523a0898aSmrg } 306623a0898aSmrg } 306723a0898aSmrg _fs_done_read (conn, setup_len); 306823a0898aSmrg if (setup->status != AuthSuccess) 306923a0898aSmrg return FSIO_ERROR; 307023a0898aSmrg return FSIO_READY; 307123a0898aSmrg} 307223a0898aSmrg 307323a0898aSmrgstatic int 307423a0898aSmrg_fs_open_server (FSFpePtr conn) 307523a0898aSmrg{ 307623a0898aSmrg int ret; 307723a0898aSmrg char *servername; 307841c30155Smrg 307923a0898aSmrg if (conn->alternate == 0) 308023a0898aSmrg servername = conn->servername; 308123a0898aSmrg else 308223a0898aSmrg servername = conn->alts[conn->alternate-1].name; 308323a0898aSmrg conn->trans_conn = _fs_connect (servername, &ret); 308423a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; 308523a0898aSmrg return ret; 308623a0898aSmrg} 308723a0898aSmrg 308823a0898aSmrgstatic char * 308923a0898aSmrg_fs_catalog_name (char *servername) 309023a0898aSmrg{ 309123a0898aSmrg char *sp; 309223a0898aSmrg 309323a0898aSmrg sp = strchr (servername, '/'); 309423a0898aSmrg if (!sp) 309523a0898aSmrg return 0; 309623a0898aSmrg return strrchr (sp + 1, '/'); 309723a0898aSmrg} 309823a0898aSmrg 309923a0898aSmrgstatic int 310023a0898aSmrg_fs_send_init_packets (FSFpePtr conn) 310123a0898aSmrg{ 310223a0898aSmrg fsSetResolutionReq srreq; 310323a0898aSmrg fsSetCataloguesReq screq; 310423a0898aSmrg int num_cats, 310523a0898aSmrg clen; 310623a0898aSmrg char *catalogues; 310723a0898aSmrg char *cat; 310823a0898aSmrg char len; 310923a0898aSmrg char *end; 311041c30155Smrg int num_res; 311123a0898aSmrg FontResolutionPtr res; 311223a0898aSmrg 311323a0898aSmrg#define CATALOGUE_SEP '+' 311423a0898aSmrg 311523a0898aSmrg res = GetClientResolutions(&num_res); 311641c30155Smrg if (num_res) 311723a0898aSmrg { 311823a0898aSmrg srreq.reqType = FS_SetResolution; 311923a0898aSmrg srreq.num_resolutions = num_res; 312023a0898aSmrg srreq.length = (SIZEOF(fsSetResolutionReq) + 312123a0898aSmrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 312223a0898aSmrg 312323a0898aSmrg _fs_add_req_log(conn, FS_SetResolution); 312423a0898aSmrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) 312523a0898aSmrg return FSIO_ERROR; 312623a0898aSmrg if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) 312723a0898aSmrg return FSIO_ERROR; 312823a0898aSmrg } 312923a0898aSmrg 313023a0898aSmrg catalogues = 0; 313123a0898aSmrg if (conn->alternate != 0) 313223a0898aSmrg catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); 313323a0898aSmrg if (!catalogues) 313423a0898aSmrg catalogues = _fs_catalog_name (conn->servername); 313541c30155Smrg 313623a0898aSmrg if (!catalogues) 313723a0898aSmrg { 313823a0898aSmrg conn->has_catalogues = FALSE; 313923a0898aSmrg return FSIO_READY; 314023a0898aSmrg } 314123a0898aSmrg conn->has_catalogues = TRUE; 314241c30155Smrg 314323a0898aSmrg /* turn cats into counted list */ 314423a0898aSmrg catalogues++; 314523a0898aSmrg 314623a0898aSmrg cat = catalogues; 314723a0898aSmrg num_cats = 0; 314823a0898aSmrg clen = 0; 314923a0898aSmrg while (*cat) 315023a0898aSmrg { 315123a0898aSmrg num_cats++; 315223a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 315323a0898aSmrg if (!end) 315423a0898aSmrg end = cat + strlen (cat); 315523a0898aSmrg clen += (end - cat) + 1; /* length byte + string */ 315623a0898aSmrg cat = end; 315723a0898aSmrg } 315823a0898aSmrg 315923a0898aSmrg screq.reqType = FS_SetCatalogues; 316023a0898aSmrg screq.num_catalogues = num_cats; 316123a0898aSmrg screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; 316241c30155Smrg 316323a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 316423a0898aSmrg if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) 316523a0898aSmrg return FSIO_ERROR; 316641c30155Smrg 316723a0898aSmrg while (*cat) 316823a0898aSmrg { 316923a0898aSmrg num_cats++; 317023a0898aSmrg end = strchr(cat, CATALOGUE_SEP); 317123a0898aSmrg if (!end) 317223a0898aSmrg end = cat + strlen (cat); 317323a0898aSmrg len = end - cat; 317423a0898aSmrg if (_fs_write (conn, &len, 1) != FSIO_READY) 317523a0898aSmrg return FSIO_ERROR; 317623a0898aSmrg if (_fs_write (conn, cat, (int) len) != FSIO_READY) 317723a0898aSmrg return FSIO_ERROR; 317823a0898aSmrg cat = end; 317923a0898aSmrg } 318041c30155Smrg 318123a0898aSmrg if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) 318223a0898aSmrg return FSIO_ERROR; 318341c30155Smrg 318423a0898aSmrg return FSIO_READY; 318523a0898aSmrg} 318623a0898aSmrg 318723a0898aSmrgstatic int 318823a0898aSmrg_fs_send_cat_sync (FSFpePtr conn) 318923a0898aSmrg{ 319023a0898aSmrg fsListCataloguesReq lcreq; 319141c30155Smrg 319223a0898aSmrg /* 319323a0898aSmrg * now sync up with the font server, to see if an error was generated 319423a0898aSmrg * by a bogus catalogue 319523a0898aSmrg */ 319623a0898aSmrg lcreq.reqType = FS_ListCatalogues; 31977673729aSmrg lcreq.data = 0; 319823a0898aSmrg lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; 319923a0898aSmrg lcreq.maxNames = 0; 320023a0898aSmrg lcreq.nbytes = 0; 32017f7f5e4eSmrg lcreq.pad2 = 0; 320223a0898aSmrg _fs_add_req_log(conn, FS_SetCatalogues); 320323a0898aSmrg if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) 320423a0898aSmrg return FSIO_ERROR; 320523a0898aSmrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 320623a0898aSmrg return FSIO_READY; 320723a0898aSmrg} 320823a0898aSmrg 320923a0898aSmrgstatic int 321023a0898aSmrg_fs_recv_cat_sync (FSFpePtr conn) 321123a0898aSmrg{ 321223a0898aSmrg fsGenericReply *reply; 321323a0898aSmrg fsError *error; 321423a0898aSmrg int err; 321523a0898aSmrg int ret; 321623a0898aSmrg 321723a0898aSmrg reply = fs_get_reply (conn, &err); 321823a0898aSmrg if (!reply) 321923a0898aSmrg return err; 322041c30155Smrg 322123a0898aSmrg ret = FSIO_READY; 322223a0898aSmrg if (reply->type == FS_Error) 322323a0898aSmrg { 322423a0898aSmrg error = (fsError *) reply; 322523a0898aSmrg if (error->major_opcode == FS_SetCatalogues) 322623a0898aSmrg ret = FSIO_ERROR; 322723a0898aSmrg } 322823a0898aSmrg _fs_done_read (conn, reply->length << 2); 322923a0898aSmrg return ret; 323023a0898aSmrg} 323123a0898aSmrg 323223a0898aSmrgstatic void 323323a0898aSmrg_fs_close_server (FSFpePtr conn) 323423a0898aSmrg{ 323523a0898aSmrg _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); 323623a0898aSmrg if (conn->trans_conn) 323723a0898aSmrg { 323823a0898aSmrg _FontTransClose (conn->trans_conn); 323923a0898aSmrg conn->trans_conn = 0; 324023a0898aSmrg _fs_io_reinit (conn); 324123a0898aSmrg } 324223a0898aSmrg if (conn->fs_fd >= 0) 324323a0898aSmrg { 324423a0898aSmrg FD_CLR (conn->fs_fd, &_fs_fd_mask); 324523a0898aSmrg conn->fs_fd = -1; 324623a0898aSmrg } 324723a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 324823a0898aSmrg} 324923a0898aSmrg 325023a0898aSmrgstatic int 325123a0898aSmrg_fs_do_setup_connection (FSFpePtr conn) 325223a0898aSmrg{ 325323a0898aSmrg int ret; 325441c30155Smrg 325523a0898aSmrg do 325623a0898aSmrg { 325723a0898aSmrg#ifdef DEBUG 325823a0898aSmrg fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); 325923a0898aSmrg#endif 326023a0898aSmrg switch (conn->fs_conn_state) { 326123a0898aSmrg case FS_CONN_UNCONNECTED: 326223a0898aSmrg ret = _fs_open_server (conn); 326323a0898aSmrg if (ret == FSIO_BLOCK) 326423a0898aSmrg conn->fs_conn_state = FS_CONN_CONNECTING; 326523a0898aSmrg break; 326623a0898aSmrg case FS_CONN_CONNECTING: 326723a0898aSmrg ret = _fs_check_connect (conn); 326823a0898aSmrg break; 326923a0898aSmrg case FS_CONN_CONNECTED: 327023a0898aSmrg ret = _fs_send_conn_client_prefix (conn); 327123a0898aSmrg break; 327223a0898aSmrg case FS_CONN_SENT_PREFIX: 327323a0898aSmrg ret = _fs_recv_conn_setup (conn); 327423a0898aSmrg break; 327523a0898aSmrg case FS_CONN_RECV_INIT: 327623a0898aSmrg ret = _fs_send_init_packets (conn); 327723a0898aSmrg if (conn->has_catalogues) 327823a0898aSmrg ret = _fs_send_cat_sync (conn); 327923a0898aSmrg break; 328023a0898aSmrg case FS_CONN_SENT_CAT: 328123a0898aSmrg if (conn->has_catalogues) 328223a0898aSmrg ret = _fs_recv_cat_sync (conn); 328323a0898aSmrg else 328423a0898aSmrg ret = FSIO_READY; 328523a0898aSmrg break; 328623a0898aSmrg default: 328723a0898aSmrg ret = FSIO_READY; 328823a0898aSmrg break; 328923a0898aSmrg } 329023a0898aSmrg switch (ret) { 329123a0898aSmrg case FSIO_READY: 329223a0898aSmrg if (conn->fs_conn_state < FS_CONN_RUNNING) 329323a0898aSmrg conn->fs_conn_state++; 329423a0898aSmrg break; 329523a0898aSmrg case FSIO_BLOCK: 329623a0898aSmrg if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) 329723a0898aSmrg break; 329823a0898aSmrg ret = FSIO_ERROR; 329923a0898aSmrg /* fall through... */ 330023a0898aSmrg case FSIO_ERROR: 330123a0898aSmrg _fs_close_server (conn); 330223a0898aSmrg /* 330323a0898aSmrg * Try the next alternate 330423a0898aSmrg */ 330523a0898aSmrg if (conn->alternate < conn->numAlts) 330623a0898aSmrg { 330723a0898aSmrg conn->alternate++; 330823a0898aSmrg ret = FSIO_READY; 330923a0898aSmrg } 331023a0898aSmrg else 331123a0898aSmrg conn->alternate = 0; 331223a0898aSmrg break; 331323a0898aSmrg } 331423a0898aSmrg } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); 331523a0898aSmrg if (ret == FSIO_READY) 331623a0898aSmrg conn->generation = ++generationCount; 331723a0898aSmrg return ret; 331823a0898aSmrg} 331923a0898aSmrg 332023a0898aSmrgstatic int 332123a0898aSmrg_fs_wait_connect (FSFpePtr conn) 332223a0898aSmrg{ 332323a0898aSmrg int ret; 332423a0898aSmrg 332523a0898aSmrg for (;;) 332623a0898aSmrg { 332723a0898aSmrg ret = _fs_do_setup_connection (conn); 332823a0898aSmrg if (ret != FSIO_BLOCK) 332923a0898aSmrg break; 333023a0898aSmrg if (conn->fs_conn_state <= FS_CONN_CONNECTING) 333123a0898aSmrg ret = _fs_poll_connect (conn->trans_conn, 1000); 333223a0898aSmrg else 333323a0898aSmrg ret = _fs_wait_for_readable (conn, 1000); 333423a0898aSmrg if (ret == FSIO_ERROR) 333523a0898aSmrg break; 333623a0898aSmrg } 333723a0898aSmrg return ret; 333823a0898aSmrg} 333923a0898aSmrg 334023a0898aSmrg/* 334123a0898aSmrg * Poll a connection in the process of reconnecting 334223a0898aSmrg */ 334323a0898aSmrgstatic void 334423a0898aSmrg_fs_check_reconnect (FSFpePtr conn) 334523a0898aSmrg{ 334623a0898aSmrg int ret; 334741c30155Smrg 334823a0898aSmrg ret = _fs_do_setup_connection (conn); 334923a0898aSmrg switch (ret) { 335023a0898aSmrg case FSIO_READY: 335123a0898aSmrg _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); 335223a0898aSmrg _fs_restart_connection (conn); 335323a0898aSmrg break; 335423a0898aSmrg case FSIO_BLOCK: 335523a0898aSmrg break; 335623a0898aSmrg case FSIO_ERROR: 335723a0898aSmrg conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; 335823a0898aSmrg break; 335923a0898aSmrg } 336023a0898aSmrg} 336123a0898aSmrg 336223a0898aSmrg/* 336323a0898aSmrg * Start the reconnection process 336423a0898aSmrg */ 336523a0898aSmrgstatic void 336623a0898aSmrg_fs_start_reconnect (FSFpePtr conn) 336723a0898aSmrg{ 336823a0898aSmrg if (conn->blockState & FS_RECONNECTING) 336923a0898aSmrg return; 337023a0898aSmrg conn->alternate = 0; 337123a0898aSmrg _fs_mark_block (conn, FS_RECONNECTING); 337223a0898aSmrg _fs_unmark_block (conn, FS_BROKEN_CONNECTION); 337323a0898aSmrg _fs_check_reconnect (conn); 337423a0898aSmrg} 337523a0898aSmrg 337623a0898aSmrg 337723a0898aSmrgstatic FSFpePtr 337823a0898aSmrg_fs_init_conn (char *servername) 337923a0898aSmrg{ 338023a0898aSmrg FSFpePtr conn; 338123a0898aSmrg 33827f7f5e4eSmrg conn = calloc (1, sizeof (FSFpeRec) + strlen (servername) + 1); 338323a0898aSmrg if (!conn) 338423a0898aSmrg return 0; 338523a0898aSmrg if (!_fs_io_init (conn)) 338623a0898aSmrg { 33877f7f5e4eSmrg free (conn); 338823a0898aSmrg return 0; 338923a0898aSmrg } 339023a0898aSmrg conn->servername = (char *) (conn + 1); 339123a0898aSmrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 339223a0898aSmrg conn->fs_fd = -1; 339323a0898aSmrg strcpy (conn->servername, servername); 339423a0898aSmrg return conn; 339523a0898aSmrg} 339623a0898aSmrg 339723a0898aSmrgstatic void 339823a0898aSmrg_fs_free_conn (FSFpePtr conn) 339923a0898aSmrg{ 340023a0898aSmrg _fs_close_server (conn); 340123a0898aSmrg _fs_io_fini (conn); 340223a0898aSmrg if (conn->alts) 34037f7f5e4eSmrg free (conn->alts); 34047f7f5e4eSmrg free (conn); 340523a0898aSmrg} 340623a0898aSmrg 340723a0898aSmrg/* 340823a0898aSmrg * called at server init time 340923a0898aSmrg */ 341023a0898aSmrg 341123a0898aSmrgvoid 341223a0898aSmrgfs_register_fpe_functions(void) 341323a0898aSmrg{ 341423a0898aSmrg RegisterFPEFunctions(fs_name_check, 341523a0898aSmrg fs_init_fpe, 341623a0898aSmrg fs_free_fpe, 341723a0898aSmrg fs_reset_fpe, 341823a0898aSmrg fs_open_font, 341923a0898aSmrg fs_close_font, 342023a0898aSmrg fs_list_fonts, 342123a0898aSmrg fs_start_list_with_info, 342223a0898aSmrg fs_next_list_with_info, 342323a0898aSmrg fs_wakeup, 342423a0898aSmrg fs_client_died, 342523a0898aSmrg _fs_load_glyphs, 342623a0898aSmrg NULL, 342723a0898aSmrg NULL, 342823a0898aSmrg NULL); 342923a0898aSmrg} 3430