fserve.c revision 60da515c
1a96d7823Smrg/* 2a96d7823Smrg 3a96d7823SmrgCopyright 1990, 1998 The Open Group 4a96d7823Smrg 5a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its 6a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that 7a96d7823Smrgthe above copyright notice appear in all copies and that both that 8a96d7823Smrgcopyright notice and this permission notice appear in supporting 9a96d7823Smrgdocumentation. 10a96d7823Smrg 11a96d7823SmrgThe above copyright notice and this permission notice shall be included in 12a96d7823Smrgall copies or substantial portions of the Software. 13a96d7823Smrg 14a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15a96d7823SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16a96d7823SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17a96d7823SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18a96d7823SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19a96d7823SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20a96d7823Smrg 21a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall not be 22a96d7823Smrgused in advertising or otherwise to promote the sale, use or other dealings 23a96d7823Smrgin this Software without prior written authorization from The Open Group. 24a96d7823Smrg 25a96d7823Smrg*/ 26a96d7823Smrg 27a96d7823Smrg/* 28a96d7823Smrg * Copyright 1990 Network Computing Devices 29a96d7823Smrg * 30a96d7823Smrg * Permission to use, copy, modify, distribute, and sell this software and 31a96d7823Smrg * its documentation for any purpose is hereby granted without fee, provided 32a96d7823Smrg * that the above copyright notice appear in all copies and that both that 33a96d7823Smrg * copyright notice and this permission notice appear in supporting 34a96d7823Smrg * documentation, and that the names of Network Computing Devices, or Digital 35a96d7823Smrg * not be used in advertising or publicity pertaining to distribution 36a96d7823Smrg * of the software without specific, written prior permission. 37a96d7823Smrg * 38a96d7823Smrg * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH 39a96d7823Smrg * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF 40a96d7823Smrg * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES, 41a96d7823Smrg * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 42a96d7823Smrg * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 43a96d7823Smrg * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS 44a96d7823Smrg * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 45a96d7823Smrg * THIS SOFTWARE. 46a96d7823Smrg * 47a96d7823Smrg * Author: Dave Lemke, Network Computing Devices, Inc 48a96d7823Smrg */ 49a96d7823Smrg/* 50a96d7823Smrg * font server specific font access 51a96d7823Smrg */ 52a96d7823Smrg 53a96d7823Smrg#ifdef HAVE_CONFIG_H 54a96d7823Smrg#include <config.h> 55a96d7823Smrg#endif 56a96d7823Smrg#include "libxfontint.h" 57c7b4381aSmrg#include "src/util/replace.h" 58a96d7823Smrg 59a96d7823Smrg#ifdef WIN32 60a96d7823Smrg#define _WILLWINSOCK_ 61a96d7823Smrg#endif 62a96d7823Smrg#define FONT_t 63a96d7823Smrg#define TRANS_CLIENT 64a96d7823Smrg#include "X11/Xtrans/Xtrans.h" 65a96d7823Smrg#include "X11/Xpoll.h" 66a96d7823Smrg#include <X11/fonts/FS.h> 67a96d7823Smrg#include <X11/fonts/FSproto.h> 68a96d7823Smrg#include <X11/X.h> 69a96d7823Smrg#include <X11/Xos.h> 70a96d7823Smrg#include <X11/fonts/fontmisc.h> 71a96d7823Smrg#include <X11/fonts/fontstruct.h> 72a96d7823Smrg#include "fservestr.h" 73a96d7823Smrg#include <X11/fonts/fontutil.h> 74a96d7823Smrg#include <errno.h> 75a96d7823Smrg#include <limits.h> 76a96d7823Smrg 77a96d7823Smrg#include <time.h> 78a96d7823Smrg#define Time_t time_t 79a96d7823Smrg 80a96d7823Smrg#ifdef NCD 81a96d7823Smrg#include <ncd/nvram.h> 82a96d7823Smrg#endif 83a96d7823Smrg 84a96d7823Smrg#include <stddef.h> 85a96d7823Smrg 86a96d7823Smrg#ifndef MIN 87a96d7823Smrg#define MIN(a,b) ((a)<(b)?(a):(b)) 88a96d7823Smrg#endif 89a96d7823Smrg#define TimeCmp(a,c,b) ((int) ((a) - (b)) c 0) 90a96d7823Smrg 91a96d7823Smrg#define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \ 92a96d7823Smrg (pci)->rightSideBearing || \ 93a96d7823Smrg (pci)->ascent || \ 94a96d7823Smrg (pci)->descent || \ 95a96d7823Smrg (pci)->characterWidth) 96a96d7823Smrg 97a96d7823Smrg/* 98a96d7823Smrg * SIZEOF(r) is in bytes, length fields in the protocol are in 32-bit words, 99a96d7823Smrg * so this converts for doing size comparisons. 100a96d7823Smrg */ 101a96d7823Smrg#define LENGTHOF(r) (SIZEOF(r) >> 2) 102a96d7823Smrg 103a96d7823Smrg/* Somewhat arbitrary limit on maximum reply size we'll try to read. */ 104a96d7823Smrg#define MAX_REPLY_LENGTH ((64 * 1024 * 1024) >> 2) 105a96d7823Smrg 106a96d7823Smrgstatic int fs_read_glyphs ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 107a96d7823Smrgstatic int fs_read_list ( FontPathElementPtr fpe, FSBlockDataPtr blockrec ); 108a96d7823Smrgstatic int fs_read_list_info ( FontPathElementPtr fpe, 109a96d7823Smrg FSBlockDataPtr blockrec ); 110a96d7823Smrg 111a96d7823Smrgstatic void fs_block_handler ( void *wt ); 112a96d7823Smrg 113a96d7823Smrgstatic int fs_wakeup ( FontPathElementPtr fpe ); 114a96d7823Smrg 115a96d7823Smrg/* 116a96d7823Smrg * List of all FPEs 117a96d7823Smrg */ 118a96d7823Smrgstatic FSFpePtr fs_fpes; 119a96d7823Smrg/* 120a96d7823Smrg * Union of all FPE blockStates 121a96d7823Smrg */ 122a96d7823Smrgstatic CARD32 fs_blockState; 123a96d7823Smrg 124a96d7823Smrgstatic int _fs_restart_connection ( FSFpePtr conn ); 125a96d7823Smrgstatic void fs_send_query_bitmaps ( FontPathElementPtr fpe, 126a96d7823Smrg FSBlockDataPtr blockrec ); 12760da515cSmrgstatic int fs_send_close_font (FSFpePtr conn, Font id); 128a96d7823Smrgstatic void fs_client_died ( pointer client, FontPathElementPtr fpe ); 129a96d7823Smrgstatic void _fs_client_access ( FSFpePtr conn, pointer client, Bool sync ); 130a96d7823Smrgstatic void _fs_client_resolution ( FSFpePtr conn ); 131a96d7823Smrgstatic fsGenericReply *fs_get_reply (FSFpePtr conn, int *error); 132a96d7823Smrgstatic int fs_await_reply (FSFpePtr conn); 133a96d7823Smrgstatic void _fs_do_blocked (FSFpePtr conn); 13460da515cSmrgstatic void fs_cleanup_bfont (FSFpePtr conn, FSBlockedFontPtr bfont); 135a96d7823Smrg 136a96d7823Smrgchar _fs_glyph_undefined; 137a96d7823Smrgchar _fs_glyph_requested; 138a96d7823Smrgstatic char _fs_glyph_zero_length; 139a96d7823Smrg 140a96d7823Smrgstatic int generationCount; 141a96d7823Smrg 142a96d7823Smrgstatic int FontServerRequestTimeout = 30 * 1000; 143a96d7823Smrg 144a96d7823Smrgstatic void 145a96d7823Smrg_fs_close_server (FSFpePtr conn); 146a96d7823Smrg 147a96d7823Smrgstatic FSFpePtr 148a96d7823Smrg_fs_init_conn (const char *servername, FontPathElementPtr fpe); 149a96d7823Smrg 150a96d7823Smrgstatic int 151a96d7823Smrg_fs_wait_connect (FSFpePtr conn); 152a96d7823Smrg 153a96d7823Smrgstatic int 154a96d7823Smrg_fs_send_init_packets (FSFpePtr conn); 155a96d7823Smrg 156a96d7823Smrgstatic void 157a96d7823Smrg_fs_check_reconnect (FSFpePtr conn); 158a96d7823Smrg 159a96d7823Smrgstatic void 160a96d7823Smrg_fs_start_reconnect (FSFpePtr conn); 161a96d7823Smrg 162a96d7823Smrgstatic void 163a96d7823Smrg_fs_free_conn (FSFpePtr conn); 164a96d7823Smrg 165a96d7823Smrgstatic int 166a96d7823Smrgfs_free_fpe(FontPathElementPtr fpe); 167a96d7823Smrg 168a96d7823Smrgstatic void 169a96d7823Smrgfs_fd_handler(int fd, void *data); 170a96d7823Smrg 171a96d7823Smrg/* 172a96d7823Smrg * Font server access 173a96d7823Smrg * 174a96d7823Smrg * the basic idea for the non-blocking access is to have the function 175a96d7823Smrg * called multiple times until the actual data is returned, instead 176a96d7823Smrg * of ClientBlocked. 177a96d7823Smrg * 178a96d7823Smrg * the first call to the function will cause the request to be sent to 179a96d7823Smrg * the font server, and a block record to be stored in the fpe's list 180a96d7823Smrg * of outstanding requests. the FS block handler also sticks the 181a96d7823Smrg * proper set of fd's into the select mask. when data is ready to be 182a96d7823Smrg * read in, the FS wakup handler will be hit. this will read the 183a96d7823Smrg * data off the wire into the proper block record, and then signal the 184a96d7823Smrg * client that caused the block so that it can restart. it will then 185a96d7823Smrg * call the access function again, which will realize that the data has 186a96d7823Smrg * arrived and return it. 187a96d7823Smrg */ 188a96d7823Smrg 189a96d7823Smrg 190a96d7823Smrg#ifdef DEBUG 191a96d7823Smrgstatic void 192a96d7823Smrg_fs_add_req_log(FSFpePtr conn, int opcode) 193a96d7823Smrg{ 194a96d7823Smrg conn->current_seq++; 195a96d7823Smrg fprintf (stderr, "\t\tRequest: %5d Opcode: %2d\n", 196a96d7823Smrg conn->current_seq, opcode); 197a96d7823Smrg conn->reqbuffer[conn->reqindex].opcode = opcode; 198a96d7823Smrg conn->reqbuffer[conn->reqindex].sequence = conn->current_seq; 199a96d7823Smrg conn->reqindex++; 200a96d7823Smrg if (conn->reqindex == REQUEST_LOG_SIZE) 201a96d7823Smrg conn->reqindex = 0; 202a96d7823Smrg} 203a96d7823Smrg 204a96d7823Smrgstatic void 205a96d7823Smrg_fs_add_rep_log (FSFpePtr conn, fsGenericReply *rep) 206a96d7823Smrg{ 207a96d7823Smrg int i; 208a96d7823Smrg 209a96d7823Smrg for (i = 0; i < REQUEST_LOG_SIZE; i++) 210a96d7823Smrg if (conn->reqbuffer[i].sequence == rep->sequenceNumber) 211a96d7823Smrg break; 212a96d7823Smrg if (i == REQUEST_LOG_SIZE) 213a96d7823Smrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: unknown\n", 214a96d7823Smrg rep->sequenceNumber); 215a96d7823Smrg else 216a96d7823Smrg fprintf (stderr, "\t\t\t\t\tReply: %5d Opcode: %d\n", 217a96d7823Smrg rep->sequenceNumber, 218a96d7823Smrg conn->reqbuffer[i].opcode); 219a96d7823Smrg} 220a96d7823Smrg 221a96d7823Smrg#define _fs_reply_failed(rep, name, op) do { \ 222a96d7823Smrg if (rep) { \ 223a96d7823Smrg if (rep->type == FS_Error) \ 224a96d7823Smrg fprintf (stderr, "Error: %d Request: %s\n", \ 225a96d7823Smrg ((fsError *)rep)->request, #name); \ 226a96d7823Smrg else \ 227c7b4381aSmrg fprintf (stderr, "Bad Length for %s Reply: %u %s %d\n", \ 228c7b4381aSmrg #name, (unsigned) rep->length, op, LENGTHOF(name));\ 229a96d7823Smrg } \ 230a96d7823Smrg} while (0) 231a96d7823Smrg 232a96d7823Smrg#else 233a96d7823Smrg#define _fs_add_req_log(conn,op) ((conn)->current_seq++) 234a96d7823Smrg#define _fs_add_rep_log(conn,rep) 235a96d7823Smrg#define _fs_reply_failed(rep,name,op) 236a96d7823Smrg#endif 237a96d7823Smrg 238a96d7823Smrgstatic Bool 239a96d7823Smrgfs_name_check(const char *name) 240a96d7823Smrg{ 241a96d7823Smrg /* Just make sure there is a protocol/ prefix */ 242a96d7823Smrg return (name && *name != '/' && strchr(name, '/')); 243a96d7823Smrg} 244a96d7823Smrg 245a96d7823Smrgstatic void 246a96d7823Smrg_fs_client_resolution(FSFpePtr conn) 247a96d7823Smrg{ 248a96d7823Smrg fsSetResolutionReq srreq; 249a96d7823Smrg int num_res; 250a96d7823Smrg FontResolutionPtr res; 251a96d7823Smrg 252a96d7823Smrg res = GetClientResolutions(&num_res); 253a96d7823Smrg 254a96d7823Smrg if (num_res) { 255a96d7823Smrg srreq.reqType = FS_SetResolution; 256a96d7823Smrg srreq.num_resolutions = num_res; 257a96d7823Smrg srreq.length = (SIZEOF(fsSetResolutionReq) + 258a96d7823Smrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 259a96d7823Smrg 260a96d7823Smrg _fs_add_req_log(conn, FS_SetResolution); 261a96d7823Smrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1) 262a96d7823Smrg (void)_fs_write_pad(conn, (char *) res, 263a96d7823Smrg (num_res * SIZEOF(fsResolution))); 264a96d7823Smrg } 265a96d7823Smrg} 266a96d7823Smrg 267a96d7823Smrg/* 268a96d7823Smrg * close font server and remove any state associated with 269a96d7823Smrg * this connection - this includes any client records. 270a96d7823Smrg */ 271a96d7823Smrg 272a96d7823Smrgstatic void 273a96d7823Smrgfs_close_conn(FSFpePtr conn) 274a96d7823Smrg{ 275a96d7823Smrg FSClientPtr client, nclient; 276a96d7823Smrg 277a96d7823Smrg _fs_close_server (conn); 278a96d7823Smrg 279a96d7823Smrg for (client = conn->clients; client; client = nclient) 280a96d7823Smrg { 281a96d7823Smrg nclient = client->next; 282a96d7823Smrg free (client); 283a96d7823Smrg } 284a96d7823Smrg conn->clients = NULL; 285a96d7823Smrg} 286a96d7823Smrg 287a96d7823Smrg/* 288a96d7823Smrg * the wakeup handlers have to be set when the FPE is open, and not 289a96d7823Smrg * removed until it is freed, in order to handle unexpected data, like 290a96d7823Smrg * events 291a96d7823Smrg */ 292a96d7823Smrg/* ARGSUSED */ 293a96d7823Smrgstatic int 294a96d7823Smrgfs_init_fpe(FontPathElementPtr fpe) 295a96d7823Smrg{ 296a96d7823Smrg FSFpePtr conn; 297a96d7823Smrg const char *name; 298a96d7823Smrg int err; 299a96d7823Smrg int ret; 300a96d7823Smrg 301a96d7823Smrg /* open font server */ 302a96d7823Smrg /* create FS specific fpe info */ 303a96d7823Smrg name = fpe->name; 304a96d7823Smrg 305a96d7823Smrg /* hack for old style names */ 306a96d7823Smrg if (*name == ':') 307a96d7823Smrg name++; /* skip ':' */ 308a96d7823Smrg 309a96d7823Smrg conn = _fs_init_conn (name, fpe); 310a96d7823Smrg if (!conn) 311a96d7823Smrg err = AllocError; 312a96d7823Smrg else 313a96d7823Smrg { 314a96d7823Smrg err = init_fs_handlers2 (fpe, fs_block_handler); 315a96d7823Smrg if (err != Successful) 316a96d7823Smrg { 317a96d7823Smrg _fs_free_conn (conn); 318a96d7823Smrg err = AllocError; 319a96d7823Smrg } 320a96d7823Smrg else 321a96d7823Smrg { 322a96d7823Smrg fpe->private = conn; 323a96d7823Smrg conn->next = fs_fpes; 324a96d7823Smrg fs_fpes = conn; 325a96d7823Smrg ret = _fs_wait_connect (conn); 326a96d7823Smrg if (ret != FSIO_READY) 327a96d7823Smrg { 328a96d7823Smrg fs_free_fpe (fpe); 329a96d7823Smrg err = BadFontPath; 330a96d7823Smrg } 331a96d7823Smrg else 332a96d7823Smrg err = Successful; 333a96d7823Smrg } 334a96d7823Smrg } 335a96d7823Smrg 336a96d7823Smrg if (err == Successful) 337a96d7823Smrg { 338a96d7823Smrg#ifdef NCD 339a96d7823Smrg if (configData.ExtendedFontDiags) 340a96d7823Smrg printf("Connected to font server \"%s\"\n", name); 341a96d7823Smrg#endif 342a96d7823Smrg#ifdef DEBUG 343a96d7823Smrg fprintf (stderr, "connected to FS \"%s\"\n", name); 344a96d7823Smrg#endif 345a96d7823Smrg } 346a96d7823Smrg else 347a96d7823Smrg { 348a96d7823Smrg#ifdef DEBUG 349a96d7823Smrg fprintf(stderr, "failed to connect to FS \"%s\" %d\n", name, err); 350a96d7823Smrg#endif 351a96d7823Smrg#ifdef NCD 352a96d7823Smrg if (configData.ExtendedFontDiags) 353a96d7823Smrg printf("Failed to connect to font server \"%s\"\n", name); 354a96d7823Smrg#endif 355a96d7823Smrg ; 356a96d7823Smrg } 357a96d7823Smrg return err; 358a96d7823Smrg} 359a96d7823Smrg 360a96d7823Smrgstatic int 361a96d7823Smrgfs_reset_fpe(FontPathElementPtr fpe) 362a96d7823Smrg{ 363a96d7823Smrg (void) _fs_send_init_packets((FSFpePtr) fpe->private); 364a96d7823Smrg return Successful; 365a96d7823Smrg} 366a96d7823Smrg 367a96d7823Smrg/* 368a96d7823Smrg * this shouldn't be called till all refs to the FPE are gone 369a96d7823Smrg */ 370a96d7823Smrg 371a96d7823Smrgstatic int 372a96d7823Smrgfs_free_fpe(FontPathElementPtr fpe) 373a96d7823Smrg{ 374a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private, *prev; 375a96d7823Smrg 376a96d7823Smrg /* unhook from chain of all font servers */ 377a96d7823Smrg for (prev = &fs_fpes; *prev; prev = &(*prev)->next) 378a96d7823Smrg { 379a96d7823Smrg if (*prev == conn) 380a96d7823Smrg { 381a96d7823Smrg *prev = conn->next; 382a96d7823Smrg break; 383a96d7823Smrg } 384a96d7823Smrg } 385a96d7823Smrg _fs_unmark_block (conn, conn->blockState); 386a96d7823Smrg fs_close_conn(conn); 387a96d7823Smrg remove_fs_handlers2(fpe, fs_block_handler, fs_fpes == 0); 388a96d7823Smrg _fs_free_conn (conn); 389a96d7823Smrg fpe->private = (pointer) 0; 390a96d7823Smrg 391a96d7823Smrg#ifdef NCD 392a96d7823Smrg if (configData.ExtendedFontDiags) 393a96d7823Smrg printf("Disconnected from font server \"%s\"\n", fpe->name); 394a96d7823Smrg#endif 395a96d7823Smrg#ifdef DEBUG 396a96d7823Smrg fprintf (stderr, "disconnect from FS \"%s\"\n", fpe->name); 397a96d7823Smrg#endif 398a96d7823Smrg 399a96d7823Smrg return Successful; 400a96d7823Smrg} 401a96d7823Smrg 402a96d7823Smrgstatic FSBlockDataPtr 403a96d7823Smrgfs_new_block_rec(FontPathElementPtr fpe, pointer client, int type) 404a96d7823Smrg{ 405a96d7823Smrg FSBlockDataPtr blockrec, 406a96d7823Smrg *prev; 407a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 408a96d7823Smrg int size; 409a96d7823Smrg 410a96d7823Smrg switch (type) { 411a96d7823Smrg case FS_OPEN_FONT: 412a96d7823Smrg size = sizeof(FSBlockedFontRec); 413a96d7823Smrg break; 414a96d7823Smrg case FS_LOAD_GLYPHS: 415a96d7823Smrg size = sizeof(FSBlockedGlyphRec); 416a96d7823Smrg break; 417a96d7823Smrg case FS_LIST_FONTS: 418a96d7823Smrg size = sizeof(FSBlockedListRec); 419a96d7823Smrg break; 420a96d7823Smrg case FS_LIST_WITH_INFO: 421a96d7823Smrg size = sizeof(FSBlockedListInfoRec); 422a96d7823Smrg break; 423a96d7823Smrg default: 424a96d7823Smrg size = 0; 425a96d7823Smrg break; 426a96d7823Smrg } 427a96d7823Smrg blockrec = malloc(sizeof(FSBlockDataRec) + size); 428a96d7823Smrg if (!blockrec) 429a96d7823Smrg return (FSBlockDataPtr) 0; 430a96d7823Smrg blockrec->data = (pointer) (blockrec + 1); 431a96d7823Smrg blockrec->client = client; 432a96d7823Smrg blockrec->sequenceNumber = -1; 433a96d7823Smrg blockrec->errcode = StillWorking; 434a96d7823Smrg blockrec->type = type; 435a96d7823Smrg blockrec->depending = 0; 436a96d7823Smrg blockrec->next = (FSBlockDataPtr) 0; 437a96d7823Smrg 438a96d7823Smrg /* stick it on the end of the list (since its expected last) */ 439a96d7823Smrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 440a96d7823Smrg ; 441a96d7823Smrg *prev = blockrec; 442a96d7823Smrg 443a96d7823Smrg return blockrec; 444a96d7823Smrg} 445a96d7823Smrg 446a96d7823Smrgstatic void 447a96d7823Smrg_fs_set_pending_reply (FSFpePtr conn) 448a96d7823Smrg{ 449a96d7823Smrg FSBlockDataPtr blockrec; 450a96d7823Smrg 451a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 452a96d7823Smrg if (blockrec->errcode == StillWorking) 453a96d7823Smrg break; 454a96d7823Smrg if (blockrec) 455a96d7823Smrg { 456a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 457a96d7823Smrg _fs_mark_block (conn, FS_PENDING_REPLY); 458a96d7823Smrg } 459a96d7823Smrg else 460a96d7823Smrg _fs_unmark_block (conn, FS_PENDING_REPLY); 461a96d7823Smrg} 462a96d7823Smrg 463a96d7823Smrgstatic void 464a96d7823Smrg_fs_remove_block_rec(FSFpePtr conn, FSBlockDataPtr blockrec) 465a96d7823Smrg{ 466a96d7823Smrg FSBlockDataPtr *prev; 467a96d7823Smrg 468a96d7823Smrg for (prev = &conn->blockedRequests; *prev; prev = &(*prev)->next) 469a96d7823Smrg if (*prev == blockrec) 470a96d7823Smrg { 471a96d7823Smrg *prev = blockrec->next; 472a96d7823Smrg break; 473a96d7823Smrg } 474a96d7823Smrg if (blockrec->type == FS_LOAD_GLYPHS) 475a96d7823Smrg { 476a96d7823Smrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 477a96d7823Smrg if (bglyph->num_expected_ranges) 478a96d7823Smrg free(bglyph->expected_ranges); 479a96d7823Smrg } 480a96d7823Smrg free(blockrec); 481a96d7823Smrg _fs_set_pending_reply (conn); 482a96d7823Smrg} 483a96d7823Smrg 484a96d7823Smrgstatic void 485a96d7823Smrg_fs_signal_clients_depending(FSClientsDependingPtr *clients_depending) 486a96d7823Smrg{ 487a96d7823Smrg FSClientsDependingPtr p; 488a96d7823Smrg 489a96d7823Smrg while ((p = *clients_depending)) 490a96d7823Smrg { 491a96d7823Smrg *clients_depending = p->next; 492a96d7823Smrg ClientSignal(p->client); 493a96d7823Smrg free(p); 494a96d7823Smrg } 495a96d7823Smrg} 496a96d7823Smrg 497a96d7823Smrgstatic int 498a96d7823Smrg_fs_add_clients_depending(FSClientsDependingPtr *clients_depending, pointer client) 499a96d7823Smrg{ 500a96d7823Smrg FSClientsDependingPtr new, cd; 501a96d7823Smrg 502a96d7823Smrg for (; (cd = *clients_depending); 503a96d7823Smrg clients_depending = &(*clients_depending)->next) 504a96d7823Smrg { 505a96d7823Smrg if (cd->client == client) 506a96d7823Smrg return Suspended; 507a96d7823Smrg } 508a96d7823Smrg 509a96d7823Smrg new = malloc (sizeof (FSClientsDependingRec)); 510a96d7823Smrg if (!new) 511a96d7823Smrg return BadAlloc; 512a96d7823Smrg 513a96d7823Smrg new->client = client; 514a96d7823Smrg new->next = 0; 515a96d7823Smrg *clients_depending = new; 516a96d7823Smrg return Suspended; 517a96d7823Smrg} 518a96d7823Smrg 519a96d7823Smrgstatic void 520a96d7823Smrgconn_start_listening(FSFpePtr conn) 521a96d7823Smrg{ 522a96d7823Smrg if (!conn->fs_listening) { 523a96d7823Smrg add_fs_fd(conn->fs_fd, fs_fd_handler, conn->fpe); 524a96d7823Smrg conn->fs_listening = TRUE; 525a96d7823Smrg } 526a96d7823Smrg} 527a96d7823Smrg 528a96d7823Smrgstatic void 529a96d7823Smrgconn_stop_listening(FSFpePtr conn) 530a96d7823Smrg{ 531a96d7823Smrg if (conn->fs_listening) { 532a96d7823Smrg remove_fs_fd(conn->fs_fd); 533a96d7823Smrg conn->fs_listening = FALSE; 534a96d7823Smrg } 535a96d7823Smrg} 536a96d7823Smrg 537a96d7823Smrg/* 538a96d7823Smrg * When a request is aborted due to a font server failure, 539a96d7823Smrg * signal any depending clients to restart their dependant 540a96d7823Smrg * requests 541a96d7823Smrg */ 542a96d7823Smrgstatic void 543a96d7823Smrg_fs_clean_aborted_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 544a96d7823Smrg{ 545a96d7823Smrg switch(blockrec->type) { 546a96d7823Smrg case FS_OPEN_FONT: { 547a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data; 548a96d7823Smrg 54960da515cSmrg fs_cleanup_bfont (conn, bfont); 550a96d7823Smrg _fs_signal_clients_depending(&bfont->clients_depending); 551a96d7823Smrg break; 552a96d7823Smrg } 553a96d7823Smrg case FS_LOAD_GLYPHS: { 554a96d7823Smrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data; 555a96d7823Smrg 556a96d7823Smrg _fs_clean_aborted_loadglyphs(bglyph->pfont, 557a96d7823Smrg bglyph->num_expected_ranges, 558a96d7823Smrg bglyph->expected_ranges); 559a96d7823Smrg _fs_signal_clients_depending(&bglyph->clients_depending); 560a96d7823Smrg break; 561a96d7823Smrg } 562a96d7823Smrg case FS_LIST_FONTS: 563a96d7823Smrg break; 564a96d7823Smrg case FS_LIST_WITH_INFO: { 565a96d7823Smrg FSBlockedListInfoPtr binfo; 566a96d7823Smrg binfo = (FSBlockedListInfoPtr) blockrec->data; 567a96d7823Smrg if (binfo->status == FS_LFWI_REPLY) 568a96d7823Smrg conn_start_listening(conn); 569a96d7823Smrg _fs_free_props (&binfo->info); 570a96d7823Smrg } 571a96d7823Smrg default: 572a96d7823Smrg break; 573a96d7823Smrg } 574a96d7823Smrg} 575a96d7823Smrg 576a96d7823Smrgstatic void 577a96d7823Smrgfs_abort_blockrec(FSFpePtr conn, FSBlockDataPtr blockrec) 578a96d7823Smrg{ 579a96d7823Smrg _fs_clean_aborted_blockrec (conn, blockrec); 580a96d7823Smrg _fs_remove_block_rec (conn, blockrec); 581a96d7823Smrg} 582a96d7823Smrg 583a96d7823Smrg/* 584a96d7823Smrg * Tell the font server we've failed to complete an open and 585a96d7823Smrg * then unload the partially created font 586a96d7823Smrg */ 587a96d7823Smrgstatic void 58860da515cSmrgfs_cleanup_bfont (FSFpePtr conn, FSBlockedFontPtr bfont) 589a96d7823Smrg{ 590a96d7823Smrg if (bfont->pfont) 591a96d7823Smrg { 592a96d7823Smrg /* make sure the FS knows we choked on it */ 59360da515cSmrg fs_send_close_font(conn, bfont->fontid); 594a96d7823Smrg 595a96d7823Smrg /* 596a96d7823Smrg * Either unload the font if it's being opened for 597a96d7823Smrg * the first time, or smash the generation field to 598a96d7823Smrg * mark this font as an orphan 599a96d7823Smrg */ 600a96d7823Smrg if (!(bfont->flags & FontReopen)) 601a96d7823Smrg { 602a96d7823Smrg if (bfont->freeFont) 603a96d7823Smrg (*bfont->pfont->unload_font) (bfont->pfont); 604a96d7823Smrg#ifdef DEBUG 605a96d7823Smrg else 606a96d7823Smrg fprintf (stderr, "Not freeing other font in cleanup_bfont\n"); 607a96d7823Smrg#endif 608a96d7823Smrg bfont->pfont = 0; 609a96d7823Smrg } 610a96d7823Smrg else 61160da515cSmrg { 61260da515cSmrg FSFontDataRec *fsd = (FSFontDataRec *)bfont->pfont->fpePrivate; 613a96d7823Smrg fsd->generation = -1; 61460da515cSmrg } 615a96d7823Smrg } 616a96d7823Smrg} 617a96d7823Smrg 618a96d7823Smrg/* 619a96d7823Smrg * Check to see if a complete reply is waiting 620a96d7823Smrg */ 621a96d7823Smrgstatic fsGenericReply * 622a96d7823Smrgfs_get_reply (FSFpePtr conn, int *error) 623a96d7823Smrg{ 624a96d7823Smrg char *buf; 625a96d7823Smrg fsGenericReply *rep; 626a96d7823Smrg int ret; 627a96d7823Smrg 628a96d7823Smrg /* block if the connection is down or paused in lfwi */ 629a96d7823Smrg if (conn->fs_fd == -1 || !conn->fs_listening) 630a96d7823Smrg { 631a96d7823Smrg *error = FSIO_BLOCK; 632a96d7823Smrg return 0; 633a96d7823Smrg } 634a96d7823Smrg 635a96d7823Smrg ret = _fs_start_read (conn, sizeof (fsGenericReply), &buf); 636a96d7823Smrg if (ret != FSIO_READY) 637a96d7823Smrg { 638a96d7823Smrg *error = FSIO_BLOCK; 639a96d7823Smrg return 0; 640a96d7823Smrg } 641a96d7823Smrg 642a96d7823Smrg rep = (fsGenericReply *) buf; 643a96d7823Smrg 644a96d7823Smrg /* 645a96d7823Smrg * Refuse to accept replies longer than a maximum reasonable length, 646a96d7823Smrg * before we pass to _fs_start_read, since it will try to resize the 647a96d7823Smrg * incoming connection buffer to this size. Also avoids integer overflow 648a96d7823Smrg * on 32-bit systems. 649a96d7823Smrg */ 650a96d7823Smrg if (rep->length > MAX_REPLY_LENGTH) 651a96d7823Smrg { 652fd60135fSmrg ErrorF("fserve: reply length %ld > MAX_REPLY_LENGTH, disconnecting" 653fd60135fSmrg " from font server\n", (long)rep->length); 654a96d7823Smrg _fs_connection_died (conn); 655a96d7823Smrg *error = FSIO_ERROR; 656a96d7823Smrg return 0; 657a96d7823Smrg } 658a96d7823Smrg 659a96d7823Smrg ret = _fs_start_read (conn, rep->length << 2, &buf); 660a96d7823Smrg if (ret != FSIO_READY) 661a96d7823Smrg { 662a96d7823Smrg *error = FSIO_BLOCK; 663a96d7823Smrg return 0; 664a96d7823Smrg } 665a96d7823Smrg 666a96d7823Smrg *error = FSIO_READY; 667a96d7823Smrg 668a96d7823Smrg return (fsGenericReply *) buf; 669a96d7823Smrg} 670a96d7823Smrg 671a96d7823Smrgstatic Bool 672a96d7823Smrgfs_reply_ready (FSFpePtr conn) 673a96d7823Smrg{ 674a96d7823Smrg fsGenericReply *rep; 675a96d7823Smrg 676a96d7823Smrg if (conn->fs_fd == -1 || !conn->fs_listening) 677a96d7823Smrg return FALSE; 678a96d7823Smrg if (fs_data_read (conn) < sizeof (fsGenericReply)) 679a96d7823Smrg return FALSE; 680a96d7823Smrg rep = (fsGenericReply *) (conn->inBuf.buf + conn->inBuf.remove); 681a96d7823Smrg if (fs_data_read (conn) < rep->length << 2) 682a96d7823Smrg return FALSE; 683a96d7823Smrg return TRUE; 684a96d7823Smrg} 685a96d7823Smrg 686a96d7823Smrgstatic void 687a96d7823Smrg_fs_pending_reply (FSFpePtr conn) 688a96d7823Smrg{ 689a96d7823Smrg if (!(conn->blockState & FS_PENDING_REPLY)) 690a96d7823Smrg { 691a96d7823Smrg _fs_mark_block (conn, FS_PENDING_REPLY); 692a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 693a96d7823Smrg } 694a96d7823Smrg} 695a96d7823Smrg 696a96d7823Smrgstatic void 697a96d7823Smrg_fs_prepare_for_reply (FSFpePtr conn) 698a96d7823Smrg{ 699a96d7823Smrg _fs_pending_reply (conn); 700a96d7823Smrg _fs_flush (conn); 701a96d7823Smrg} 702a96d7823Smrg 703a96d7823Smrg/* 704a96d7823Smrg * Block (for a while) awaiting a complete reply 705a96d7823Smrg */ 706a96d7823Smrgstatic int 707a96d7823Smrgfs_await_reply (FSFpePtr conn) 708a96d7823Smrg{ 709a96d7823Smrg int ret; 710a96d7823Smrg 711a96d7823Smrg if (conn->blockState & FS_COMPLETE_REPLY) 712a96d7823Smrg return FSIO_READY; 713a96d7823Smrg 714a96d7823Smrg while (!fs_get_reply (conn, &ret)) 715a96d7823Smrg { 716a96d7823Smrg if (ret != FSIO_BLOCK) 717a96d7823Smrg return ret; 718a96d7823Smrg if (_fs_wait_for_readable (conn, FontServerRequestTimeout) != FSIO_READY) 719a96d7823Smrg { 720a96d7823Smrg _fs_connection_died (conn); 721a96d7823Smrg return FSIO_ERROR; 722a96d7823Smrg } 723a96d7823Smrg } 724a96d7823Smrg return FSIO_READY; 725a96d7823Smrg} 726a96d7823Smrg 727a96d7823Smrg/* 728a96d7823Smrg * Process the reply to an OpenBitmapFont request 729a96d7823Smrg */ 730a96d7823Smrgstatic int 731a96d7823Smrgfs_read_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 732a96d7823Smrg{ 733a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 734a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 735a96d7823Smrg fsOpenBitmapFontReply *rep; 736a96d7823Smrg FSBlockDataPtr blockOrig; 737a96d7823Smrg FSBlockedFontPtr origBfont; 738a96d7823Smrg int ret; 739a96d7823Smrg 740a96d7823Smrg rep = (fsOpenBitmapFontReply *) fs_get_reply (conn, &ret); 741a96d7823Smrg if (!rep || rep->type == FS_Error || 742a96d7823Smrg (rep->length != LENGTHOF(fsOpenBitmapFontReply))) 743a96d7823Smrg { 744a96d7823Smrg if (ret == FSIO_BLOCK) 745a96d7823Smrg return StillWorking; 746a96d7823Smrg if (rep) 747a96d7823Smrg _fs_done_read (conn, rep->length << 2); 74860da515cSmrg fs_cleanup_bfont (conn, bfont); 749a96d7823Smrg _fs_reply_failed (rep, fsOpenBitmapFontReply, "!="); 750a96d7823Smrg return BadFontName; 751a96d7823Smrg } 752a96d7823Smrg 753a96d7823Smrg /* If we're not reopening a font and FS detected a duplicate font 754a96d7823Smrg open request, replace our reference to the new font with a 755a96d7823Smrg reference to an existing font (possibly one not finished 756a96d7823Smrg opening). If this is a reopen, keep the new font reference... 757a96d7823Smrg it's got the metrics and extents we read when the font was opened 758a96d7823Smrg before. This also gives us the freedom to easily close the font 759a96d7823Smrg if we we decide (in fs_read_query_info()) that we don't like what 760a96d7823Smrg we got. */ 761a96d7823Smrg 762a96d7823Smrg if (rep->otherid && !(bfont->flags & FontReopen)) 763a96d7823Smrg { 76460da515cSmrg fs_cleanup_bfont (conn, bfont); 765a96d7823Smrg 766a96d7823Smrg /* Find old font if we're completely done getting it from server. */ 767a96d7823Smrg bfont->pfont = find_old_font(rep->otherid); 768a96d7823Smrg bfont->freeFont = FALSE; 769a96d7823Smrg bfont->fontid = rep->otherid; 770a96d7823Smrg bfont->state = FS_DONE_REPLY; 771a96d7823Smrg /* 772a96d7823Smrg * look for a blocked request to open the same font 773a96d7823Smrg */ 774a96d7823Smrg for (blockOrig = conn->blockedRequests; 775a96d7823Smrg blockOrig; 776a96d7823Smrg blockOrig = blockOrig->next) 777a96d7823Smrg { 778a96d7823Smrg if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) 779a96d7823Smrg { 780a96d7823Smrg origBfont = (FSBlockedFontPtr) blockOrig->data; 781a96d7823Smrg if (origBfont->fontid == rep->otherid) 782a96d7823Smrg { 783a96d7823Smrg blockrec->depending = blockOrig->depending; 784a96d7823Smrg blockOrig->depending = blockrec; 785a96d7823Smrg bfont->state = FS_DEPENDING; 786a96d7823Smrg bfont->pfont = origBfont->pfont; 787a96d7823Smrg break; 788a96d7823Smrg } 789a96d7823Smrg } 790a96d7823Smrg } 791a96d7823Smrg if (bfont->pfont == NULL) 792a96d7823Smrg { 793a96d7823Smrg /* XXX - something nasty happened */ 794a96d7823Smrg ret = BadFontName; 795a96d7823Smrg } 796a96d7823Smrg else 797a96d7823Smrg ret = AccessDone; 798a96d7823Smrg } 799a96d7823Smrg else 800a96d7823Smrg { 801a96d7823Smrg bfont->pfont->info.cachable = rep->cachable != 0; 802a96d7823Smrg bfont->state = FS_INFO_REPLY; 803a96d7823Smrg /* 804a96d7823Smrg * Reset the blockrec for the next reply 805a96d7823Smrg */ 806a96d7823Smrg blockrec->sequenceNumber = bfont->queryInfoSequence; 807a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 808a96d7823Smrg ret = StillWorking; 809a96d7823Smrg } 810a96d7823Smrg _fs_done_read (conn, rep->length << 2); 811a96d7823Smrg return ret; 812a96d7823Smrg} 813a96d7823Smrg 814a96d7823Smrgstatic Bool 815a96d7823Smrgfs_fonts_match (FontInfoPtr pInfo1, FontInfoPtr pInfo2) 816a96d7823Smrg{ 817a96d7823Smrg int i; 818a96d7823Smrg 819a96d7823Smrg if (pInfo1->firstCol != pInfo2->firstCol || 820a96d7823Smrg pInfo1->lastCol != pInfo2->lastCol || 821a96d7823Smrg pInfo1->firstRow != pInfo2->firstRow || 822a96d7823Smrg pInfo1->lastRow != pInfo2->lastRow || 823a96d7823Smrg pInfo1->defaultCh != pInfo2->defaultCh || 824a96d7823Smrg pInfo1->noOverlap != pInfo2->noOverlap || 825a96d7823Smrg pInfo1->terminalFont != pInfo2->terminalFont || 826a96d7823Smrg pInfo1->constantMetrics != pInfo2->constantMetrics || 827a96d7823Smrg pInfo1->constantWidth != pInfo2->constantWidth || 828a96d7823Smrg pInfo1->inkInside != pInfo2->inkInside || 829a96d7823Smrg pInfo1->inkMetrics != pInfo2->inkMetrics || 830a96d7823Smrg pInfo1->allExist != pInfo2->allExist || 831a96d7823Smrg pInfo1->drawDirection != pInfo2->drawDirection || 832a96d7823Smrg pInfo1->cachable != pInfo2->cachable || 833a96d7823Smrg pInfo1->anamorphic != pInfo2->anamorphic || 834a96d7823Smrg pInfo1->maxOverlap != pInfo2->maxOverlap || 835a96d7823Smrg pInfo1->fontAscent != pInfo2->fontAscent || 836a96d7823Smrg pInfo1->fontDescent != pInfo2->fontDescent || 837a96d7823Smrg pInfo1->nprops != pInfo2->nprops) 838a96d7823Smrg return FALSE; 839a96d7823Smrg 840a96d7823Smrg#define MATCH(xci1, xci2) \ 841a96d7823Smrg (((xci1).leftSideBearing == (xci2).leftSideBearing) && \ 842a96d7823Smrg ((xci1).rightSideBearing == (xci2).rightSideBearing) && \ 843a96d7823Smrg ((xci1).characterWidth == (xci2).characterWidth) && \ 844a96d7823Smrg ((xci1).ascent == (xci2).ascent) && \ 845a96d7823Smrg ((xci1).descent == (xci2).descent) && \ 846a96d7823Smrg ((xci1).attributes == (xci2).attributes)) 847a96d7823Smrg 848a96d7823Smrg if (!MATCH(pInfo1->maxbounds, pInfo2->maxbounds) || 849a96d7823Smrg !MATCH(pInfo1->minbounds, pInfo2->minbounds) || 850a96d7823Smrg !MATCH(pInfo1->ink_maxbounds, pInfo2->ink_maxbounds) || 851a96d7823Smrg !MATCH(pInfo1->ink_minbounds, pInfo2->ink_minbounds)) 852a96d7823Smrg return FALSE; 853a96d7823Smrg 854a96d7823Smrg#undef MATCH 855a96d7823Smrg 856a96d7823Smrg for (i = 0; i < pInfo1->nprops; i++) 857a96d7823Smrg if (pInfo1->isStringProp[i] != 858a96d7823Smrg pInfo2->isStringProp[i] || 859a96d7823Smrg pInfo1->props[i].name != 860a96d7823Smrg pInfo2->props[i].name || 861a96d7823Smrg pInfo1->props[i].value != 862a96d7823Smrg pInfo2->props[i].value) 863a96d7823Smrg { 864a96d7823Smrg return FALSE; 865a96d7823Smrg } 866a96d7823Smrg return TRUE; 867a96d7823Smrg} 868a96d7823Smrg 869a96d7823Smrgstatic int 870a96d7823Smrgfs_read_query_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 871a96d7823Smrg{ 872a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 873a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 874a96d7823Smrg fsQueryXInfoReply *rep; 875a96d7823Smrg char *buf; 876a96d7823Smrg long bufleft; /* length of reply left to use */ 877a96d7823Smrg fsPropInfo *pi; 878a96d7823Smrg fsPropOffset *po; 879a96d7823Smrg pointer pd; 880a96d7823Smrg FontInfoPtr pInfo; 881a96d7823Smrg FontInfoRec tempInfo; 882a96d7823Smrg int err; 883a96d7823Smrg int ret; 884a96d7823Smrg 885a96d7823Smrg rep = (fsQueryXInfoReply *) fs_get_reply (conn, &ret); 886a96d7823Smrg if (!rep || rep->type == FS_Error || 887a96d7823Smrg (rep->length < LENGTHOF(fsQueryXInfoReply))) 888a96d7823Smrg { 889a96d7823Smrg if (ret == FSIO_BLOCK) 890a96d7823Smrg return StillWorking; 891a96d7823Smrg if (rep) 892a96d7823Smrg _fs_done_read (conn, rep->length << 2); 89360da515cSmrg fs_cleanup_bfont (conn, bfont); 894a96d7823Smrg _fs_reply_failed (rep, fsQueryXInfoReply, "<"); 895a96d7823Smrg return BadFontName; 896a96d7823Smrg } 897a96d7823Smrg 898a96d7823Smrg /* If this is a reopen, accumulate the query info into a dummy 899a96d7823Smrg font and compare to our original data. */ 900a96d7823Smrg if (bfont->flags & FontReopen) 901a96d7823Smrg pInfo = &tempInfo; 902a96d7823Smrg else 903a96d7823Smrg pInfo = &bfont->pfont->info; 904a96d7823Smrg 905a96d7823Smrg buf = (char *) rep; 906a96d7823Smrg buf += SIZEOF(fsQueryXInfoReply); 907a96d7823Smrg 908a96d7823Smrg bufleft = rep->length << 2; 909a96d7823Smrg bufleft -= SIZEOF(fsQueryXInfoReply); 910a96d7823Smrg 911a96d7823Smrg /* move the data over */ 912a96d7823Smrg fsUnpack_XFontInfoHeader(rep, pInfo); 913a96d7823Smrg 914a96d7823Smrg /* compute accelerators */ 915a96d7823Smrg _fs_init_fontinfo(conn, pInfo); 916a96d7823Smrg 917a96d7823Smrg /* Compute offsets into the reply */ 918a96d7823Smrg if (bufleft < SIZEOF(fsPropInfo)) 919a96d7823Smrg { 920a96d7823Smrg ret = -1; 921a96d7823Smrg#ifdef DEBUG 922a96d7823Smrg fprintf(stderr, "fsQueryXInfo: bufleft (%ld) < SIZEOF(fsPropInfo)\n", 923a96d7823Smrg bufleft); 924a96d7823Smrg#endif 925a96d7823Smrg goto bail; 926a96d7823Smrg } 927a96d7823Smrg pi = (fsPropInfo *) buf; 928a96d7823Smrg buf += SIZEOF (fsPropInfo); 929a96d7823Smrg bufleft -= SIZEOF(fsPropInfo); 930a96d7823Smrg 931a96d7823Smrg if ((bufleft / SIZEOF(fsPropOffset)) < pi->num_offsets) 932a96d7823Smrg { 933a96d7823Smrg ret = -1; 934a96d7823Smrg#ifdef DEBUG 935a96d7823Smrg fprintf(stderr, 936c7b4381aSmrg "fsQueryXInfo: bufleft (%ld) / SIZEOF(fsPropOffset) < %u\n", 937c7b4381aSmrg bufleft, (unsigned) pi->num_offsets); 938a96d7823Smrg#endif 939a96d7823Smrg goto bail; 940a96d7823Smrg } 941a96d7823Smrg po = (fsPropOffset *) buf; 942a96d7823Smrg buf += pi->num_offsets * SIZEOF(fsPropOffset); 943a96d7823Smrg bufleft -= pi->num_offsets * SIZEOF(fsPropOffset); 944a96d7823Smrg 945a96d7823Smrg if (bufleft < pi->data_len) 946a96d7823Smrg { 947a96d7823Smrg ret = -1; 948a96d7823Smrg#ifdef DEBUG 949a96d7823Smrg fprintf(stderr, 950c7b4381aSmrg "fsQueryXInfo: bufleft (%ld) < data_len (%u)\n", 951c7b4381aSmrg bufleft, (unsigned) pi->data_len); 952a96d7823Smrg#endif 953a96d7823Smrg goto bail; 954a96d7823Smrg } 955a96d7823Smrg pd = (pointer) buf; 956a96d7823Smrg buf += pi->data_len; 957a96d7823Smrg bufleft -= pi->data_len; 958a96d7823Smrg 959a96d7823Smrg /* convert the properties and step over the reply */ 960a96d7823Smrg ret = _fs_convert_props(pi, po, pd, pInfo); 961a96d7823Smrg bail: 962a96d7823Smrg _fs_done_read (conn, rep->length << 2); 963a96d7823Smrg 964a96d7823Smrg if (ret == -1) 965a96d7823Smrg { 96660da515cSmrg fs_cleanup_bfont (conn, bfont); 967a96d7823Smrg return AllocError; 968a96d7823Smrg } 969a96d7823Smrg 970a96d7823Smrg if (bfont->flags & FontReopen) 971a96d7823Smrg { 972a96d7823Smrg /* We're reopening a font that we lost because of a downed 973a96d7823Smrg connection. In the interest of avoiding corruption from 974a96d7823Smrg opening a different font than the old one (we already have 975a96d7823Smrg its metrics, extents, and probably some of its glyphs), 976a96d7823Smrg verify that the metrics and properties all match. */ 977a96d7823Smrg 978a96d7823Smrg if (fs_fonts_match (pInfo, &bfont->pfont->info)) 979a96d7823Smrg { 980a96d7823Smrg err = Successful; 981a96d7823Smrg bfont->state = FS_DONE_REPLY; 982a96d7823Smrg } 983a96d7823Smrg else 984a96d7823Smrg { 98560da515cSmrg fs_cleanup_bfont (conn, bfont); 986a96d7823Smrg err = BadFontName; 987a96d7823Smrg } 988a96d7823Smrg _fs_free_props (pInfo); 989a96d7823Smrg 990a96d7823Smrg return err; 991a96d7823Smrg } 992a96d7823Smrg 993a96d7823Smrg /* 994a96d7823Smrg * Ask for terminal format fonts if possible 995a96d7823Smrg */ 996a96d7823Smrg if (bfont->pfont->info.terminalFont) 997a96d7823Smrg bfont->format = ((bfont->format & ~ (BitmapFormatImageRectMask)) | 998a96d7823Smrg BitmapFormatImageRectMax); 999a96d7823Smrg 1000a96d7823Smrg /* 1001a96d7823Smrg * Figure out if the whole font should get loaded right now. 1002a96d7823Smrg */ 1003a96d7823Smrg if (glyphCachingMode == CACHING_OFF || 1004a96d7823Smrg (glyphCachingMode == CACHE_16_BIT_GLYPHS 1005a96d7823Smrg && !bfont->pfont->info.lastRow)) 1006a96d7823Smrg { 1007a96d7823Smrg bfont->flags |= FontLoadAll; 1008a96d7823Smrg } 1009a96d7823Smrg 1010a96d7823Smrg /* 1011a96d7823Smrg * Ready to send the query bitmaps; the terminal font bit has 1012a96d7823Smrg * been computed and glyphCaching has been considered 1013a96d7823Smrg */ 1014a96d7823Smrg if (bfont->flags & FontLoadBitmaps) 1015a96d7823Smrg { 1016a96d7823Smrg fs_send_query_bitmaps (fpe, blockrec); 1017a96d7823Smrg _fs_flush (conn); 1018a96d7823Smrg } 1019a96d7823Smrg 1020a96d7823Smrg bfont->state = FS_EXTENT_REPLY; 1021a96d7823Smrg 1022a96d7823Smrg /* 1023a96d7823Smrg * Reset the blockrec for the next reply 1024a96d7823Smrg */ 1025a96d7823Smrg blockrec->sequenceNumber = bfont->queryExtentsSequence; 1026a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 1027a96d7823Smrg 1028a96d7823Smrg return StillWorking; 1029a96d7823Smrg} 1030a96d7823Smrg 1031a96d7823Smrgstatic int 1032a96d7823Smrgfs_read_extent_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 1033a96d7823Smrg{ 1034a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1035a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 1036a96d7823Smrg FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate; 1037a96d7823Smrg FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate; 1038a96d7823Smrg fsQueryXExtents16Reply *rep; 1039a96d7823Smrg char *buf; 1040a96d7823Smrg int i; 1041a96d7823Smrg int numExtents; 1042a96d7823Smrg int numInfos; 1043a96d7823Smrg int ret; 1044a96d7823Smrg Bool haveInk = FALSE; /* need separate ink metrics? */ 1045a96d7823Smrg CharInfoPtr ci, pCI; 1046a96d7823Smrg char *fsci; 1047a96d7823Smrg fsXCharInfo fscilocal; 1048a96d7823Smrg FontInfoRec *fi = &bfont->pfont->info; 1049a96d7823Smrg 1050a96d7823Smrg rep = (fsQueryXExtents16Reply *) fs_get_reply (conn, &ret); 1051a96d7823Smrg if (!rep || rep->type == FS_Error || 1052a96d7823Smrg (rep->length < LENGTHOF(fsQueryXExtents16Reply))) 1053a96d7823Smrg { 1054a96d7823Smrg if (ret == FSIO_BLOCK) 1055a96d7823Smrg return StillWorking; 1056a96d7823Smrg if (rep) 1057a96d7823Smrg _fs_done_read (conn, rep->length << 2); 105860da515cSmrg fs_cleanup_bfont (conn, bfont); 1059a96d7823Smrg _fs_reply_failed (rep, fsQueryXExtents16Reply, "<"); 1060a96d7823Smrg return BadFontName; 1061a96d7823Smrg } 1062a96d7823Smrg 1063a96d7823Smrg /* move the data over */ 1064a96d7823Smrg /* need separate inkMetrics for fixed font server protocol version */ 1065a96d7823Smrg numExtents = rep->num_extents; 1066a96d7823Smrg numInfos = numExtents; 1067a96d7823Smrg if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1) 1068a96d7823Smrg { 1069a96d7823Smrg numInfos *= 2; 1070a96d7823Smrg haveInk = TRUE; 1071a96d7823Smrg } 1072a96d7823Smrg if (numInfos >= (INT_MAX / sizeof(CharInfoRec))) { 1073a96d7823Smrg#ifdef DEBUG 1074a96d7823Smrg fprintf(stderr, 1075a96d7823Smrg "fsQueryXExtents16: numInfos (%d) >= %ld\n", 1076a96d7823Smrg numInfos, (INT_MAX / sizeof(CharInfoRec))); 1077a96d7823Smrg#endif 1078a96d7823Smrg pCI = NULL; 1079a96d7823Smrg } 1080a96d7823Smrg else if (numExtents > ((rep->length - LENGTHOF(fsQueryXExtents16Reply)) 1081a96d7823Smrg / LENGTHOF(fsXCharInfo))) { 1082a96d7823Smrg#ifdef DEBUG 1083a96d7823Smrg fprintf(stderr, 1084c7b4381aSmrg "fsQueryXExtents16: numExtents (%d) > (%u - %d) / %d\n", 1085c7b4381aSmrg numExtents, (unsigned) rep->length, 1086a96d7823Smrg LENGTHOF(fsQueryXExtents16Reply), LENGTHOF(fsXCharInfo)); 1087a96d7823Smrg#endif 1088a96d7823Smrg pCI = NULL; 1089a96d7823Smrg } 1090a96d7823Smrg else 1091c7b4381aSmrg pCI = mallocarray(numInfos, sizeof(CharInfoRec)); 1092a96d7823Smrg 1093a96d7823Smrg if (!pCI) 1094a96d7823Smrg { 1095a96d7823Smrg _fs_done_read (conn, rep->length << 2); 109660da515cSmrg fs_cleanup_bfont(conn, bfont); 1097a96d7823Smrg return AllocError; 1098a96d7823Smrg } 1099a96d7823Smrg fsfont->encoding = pCI; 1100a96d7823Smrg if (haveInk) 1101a96d7823Smrg fsfont->inkMetrics = pCI + numExtents; 1102a96d7823Smrg else 1103a96d7823Smrg fsfont->inkMetrics = pCI; 1104a96d7823Smrg 1105a96d7823Smrg buf = (char *) rep; 1106a96d7823Smrg buf += SIZEOF (fsQueryXExtents16Reply); 1107a96d7823Smrg fsci = buf; 1108a96d7823Smrg 1109a96d7823Smrg fsd->glyphs_to_get = 0; 1110a96d7823Smrg ci = fsfont->inkMetrics; 1111a96d7823Smrg for (i = 0; i < numExtents; i++) 1112a96d7823Smrg { 1113a96d7823Smrg memcpy(&fscilocal, fsci, SIZEOF(fsXCharInfo)); /* align it */ 1114a96d7823Smrg _fs_convert_char_info(&fscilocal, &ci->metrics); 1115a96d7823Smrg /* Bounds check. */ 1116a96d7823Smrg if (ci->metrics.ascent > fi->maxbounds.ascent) 1117a96d7823Smrg { 1118a96d7823Smrg ErrorF("fserve: warning: %s %s ascent (%d) > maxascent (%d)\n", 1119a96d7823Smrg fpe->name, fsd->name, 1120a96d7823Smrg ci->metrics.ascent, fi->maxbounds.ascent); 1121a96d7823Smrg ci->metrics.ascent = fi->maxbounds.ascent; 1122a96d7823Smrg } 1123a96d7823Smrg if (ci->metrics.descent > fi->maxbounds.descent) 1124a96d7823Smrg { 1125a96d7823Smrg ErrorF("fserve: warning: %s %s descent (%d) > maxdescent (%d)\n", 1126a96d7823Smrg fpe->name, fsd->name, 1127a96d7823Smrg ci->metrics.descent, fi->maxbounds.descent); 1128a96d7823Smrg ci->metrics.descent = fi->maxbounds.descent; 1129a96d7823Smrg } 1130a96d7823Smrg fsci = fsci + SIZEOF(fsXCharInfo); 1131a96d7823Smrg /* Initialize the bits field for later glyph-caching use */ 1132a96d7823Smrg if (NONZEROMETRICS(&ci->metrics)) 1133a96d7823Smrg { 1134a96d7823Smrg if (!haveInk && 1135a96d7823Smrg (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing || 1136a96d7823Smrg ci->metrics.ascent == -ci->metrics.descent)) 1137a96d7823Smrg pCI[i].bits = &_fs_glyph_zero_length; 1138a96d7823Smrg else 1139a96d7823Smrg { 1140a96d7823Smrg pCI[i].bits = &_fs_glyph_undefined; 1141a96d7823Smrg fsd->glyphs_to_get++; 1142a96d7823Smrg } 1143a96d7823Smrg } 1144a96d7823Smrg else 1145a96d7823Smrg pCI[i].bits = (char *)0; 1146a96d7823Smrg ci++; 1147a96d7823Smrg } 1148a96d7823Smrg 1149a96d7823Smrg /* Done with reply */ 1150a96d7823Smrg _fs_done_read (conn, rep->length << 2); 1151a96d7823Smrg 1152a96d7823Smrg /* build bitmap metrics, ImageRectMax style */ 1153a96d7823Smrg if (haveInk) 1154a96d7823Smrg { 1155a96d7823Smrg CharInfoPtr ii; 1156a96d7823Smrg 1157a96d7823Smrg ci = fsfont->encoding; 1158a96d7823Smrg ii = fsfont->inkMetrics; 1159a96d7823Smrg for (i = 0; i < numExtents; i++, ci++, ii++) 1160a96d7823Smrg { 1161a96d7823Smrg if (NONZEROMETRICS(&ii->metrics)) 1162a96d7823Smrg { 1163a96d7823Smrg ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi); 1164a96d7823Smrg ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi); 1165a96d7823Smrg ci->metrics.ascent = FONT_MAX_ASCENT(fi); 1166a96d7823Smrg ci->metrics.descent = FONT_MAX_DESCENT(fi); 1167a96d7823Smrg ci->metrics.characterWidth = FONT_MAX_WIDTH(fi); 1168a96d7823Smrg ci->metrics.attributes = ii->metrics.attributes; 1169a96d7823Smrg } 1170a96d7823Smrg else 1171a96d7823Smrg { 1172a96d7823Smrg ci->metrics = ii->metrics; 1173a96d7823Smrg } 1174a96d7823Smrg /* Bounds check. */ 1175a96d7823Smrg if (ci->metrics.ascent > fi->maxbounds.ascent) 1176a96d7823Smrg { 1177a96d7823Smrg ErrorF("fserve: warning: %s %s ascent (%d) " 1178a96d7823Smrg "> maxascent (%d)\n", 1179a96d7823Smrg fpe->name, fsd->name, 1180a96d7823Smrg ci->metrics.ascent, fi->maxbounds.ascent); 1181a96d7823Smrg ci->metrics.ascent = fi->maxbounds.ascent; 1182a96d7823Smrg } 1183a96d7823Smrg if (ci->metrics.descent > fi->maxbounds.descent) 1184a96d7823Smrg { 1185a96d7823Smrg ErrorF("fserve: warning: %s %s descent (%d) " 1186a96d7823Smrg "> maxdescent (%d)\n", 1187a96d7823Smrg fpe->name, fsd->name, 1188a96d7823Smrg ci->metrics.descent, fi->maxbounds.descent); 1189a96d7823Smrg ci->metrics.descent = fi->maxbounds.descent; 1190a96d7823Smrg } 1191a96d7823Smrg } 1192a96d7823Smrg } 1193a96d7823Smrg { 1194a96d7823Smrg unsigned int r, c, numCols, firstCol; 1195a96d7823Smrg 1196a96d7823Smrg firstCol = bfont->pfont->info.firstCol; 1197a96d7823Smrg numCols = bfont->pfont->info.lastCol - firstCol + 1; 1198a96d7823Smrg c = bfont->pfont->info.defaultCh; 1199a96d7823Smrg fsfont->pDefault = 0; 1200a96d7823Smrg if (bfont->pfont->info.lastRow) 1201a96d7823Smrg { 1202a96d7823Smrg r = c >> 8; 1203a96d7823Smrg r -= bfont->pfont->info.firstRow; 1204a96d7823Smrg c &= 0xff; 1205a96d7823Smrg c -= firstCol; 1206a96d7823Smrg if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 && 1207a96d7823Smrg c < numCols) 1208a96d7823Smrg fsfont->pDefault = &pCI[r * numCols + c]; 1209a96d7823Smrg } 1210a96d7823Smrg else 1211a96d7823Smrg { 1212a96d7823Smrg c -= firstCol; 1213a96d7823Smrg if (c < numCols) 1214a96d7823Smrg fsfont->pDefault = &pCI[c]; 1215a96d7823Smrg } 1216a96d7823Smrg } 1217a96d7823Smrg bfont->state = FS_GLYPHS_REPLY; 1218a96d7823Smrg 1219a96d7823Smrg if (bfont->flags & FontLoadBitmaps) 1220a96d7823Smrg { 1221a96d7823Smrg /* 1222a96d7823Smrg * Reset the blockrec for the next reply 1223a96d7823Smrg */ 1224a96d7823Smrg blockrec->sequenceNumber = bfont->queryBitmapsSequence; 1225a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 1226a96d7823Smrg return StillWorking; 1227a96d7823Smrg } 1228a96d7823Smrg return Successful; 1229a96d7823Smrg} 1230a96d7823Smrg 1231a96d7823Smrg#ifdef DEBUG 1232a96d7823Smrgstatic const char *fs_open_states[] = { 1233a96d7823Smrg "OPEN_REPLY ", 1234a96d7823Smrg "INFO_REPLY ", 1235a96d7823Smrg "EXTENT_REPLY", 1236a96d7823Smrg "GLYPHS_REPLY", 1237a96d7823Smrg "DONE_REPLY ", 1238a96d7823Smrg "DEPENDING ", 1239a96d7823Smrg}; 1240a96d7823Smrg#endif 1241a96d7823Smrg 1242a96d7823Smrgstatic int 1243a96d7823Smrgfs_do_open_font(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 1244a96d7823Smrg{ 1245a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 1246a96d7823Smrg int err; 1247a96d7823Smrg 1248a96d7823Smrg#ifdef DEBUG 1249a96d7823Smrg fprintf (stderr, "fs_do_open_font state %s %s\n", 1250a96d7823Smrg fs_open_states[bfont->state], 1251a96d7823Smrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name); 1252a96d7823Smrg#endif 1253a96d7823Smrg err = BadFontName; 1254a96d7823Smrg switch (bfont->state) { 1255a96d7823Smrg case FS_OPEN_REPLY: 1256a96d7823Smrg err = fs_read_open_font(fpe, blockrec); 1257a96d7823Smrg if (err != StillWorking) { /* already loaded, or error */ 1258a96d7823Smrg /* if font's already loaded, massage error code */ 1259a96d7823Smrg switch (bfont->state) { 1260a96d7823Smrg case FS_DONE_REPLY: 1261a96d7823Smrg err = Successful; 1262a96d7823Smrg break; 1263a96d7823Smrg case FS_DEPENDING: 1264a96d7823Smrg err = StillWorking; 1265a96d7823Smrg break; 1266a96d7823Smrg } 1267a96d7823Smrg } 1268a96d7823Smrg break; 1269a96d7823Smrg case FS_INFO_REPLY: 1270a96d7823Smrg err = fs_read_query_info(fpe, blockrec); 1271a96d7823Smrg break; 1272a96d7823Smrg case FS_EXTENT_REPLY: 1273a96d7823Smrg err = fs_read_extent_info(fpe, blockrec); 1274a96d7823Smrg break; 1275a96d7823Smrg case FS_GLYPHS_REPLY: 1276a96d7823Smrg if (bfont->flags & FontLoadBitmaps) 1277a96d7823Smrg err = fs_read_glyphs(fpe, blockrec); 1278a96d7823Smrg break; 1279a96d7823Smrg case FS_DEPENDING: /* can't happen */ 1280a96d7823Smrg default: 1281a96d7823Smrg break; 1282a96d7823Smrg } 1283a96d7823Smrg#ifdef DEBUG 1284a96d7823Smrg fprintf (stderr, "fs_do_open_font err %d\n", err); 1285a96d7823Smrg#endif 1286a96d7823Smrg if (err != StillWorking) 1287a96d7823Smrg { 1288a96d7823Smrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 1289a96d7823Smrg while ((blockrec = blockrec->depending)) 1290a96d7823Smrg { 1291a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 1292a96d7823Smrg bfont->state = FS_DONE_REPLY; /* for _fs_load_glyphs() */ 1293a96d7823Smrg } 1294a96d7823Smrg } 1295a96d7823Smrg return err; 1296a96d7823Smrg} 1297a96d7823Smrg 1298a96d7823Smrgvoid 1299a96d7823Smrg_fs_mark_block (FSFpePtr conn, CARD32 mask) 1300a96d7823Smrg{ 1301a96d7823Smrg conn->blockState |= mask; 1302a96d7823Smrg fs_blockState |= mask; 1303a96d7823Smrg} 1304a96d7823Smrg 1305a96d7823Smrgvoid 1306a96d7823Smrg_fs_unmark_block (FSFpePtr conn, CARD32 mask) 1307a96d7823Smrg{ 1308a96d7823Smrg FSFpePtr c; 1309a96d7823Smrg 1310a96d7823Smrg if (conn->blockState & mask) 1311a96d7823Smrg { 1312a96d7823Smrg conn->blockState &= ~mask; 1313a96d7823Smrg fs_blockState = 0; 1314a96d7823Smrg for (c = fs_fpes; c; c = c->next) 1315a96d7823Smrg fs_blockState |= c->blockState; 1316a96d7823Smrg } 1317a96d7823Smrg} 1318a96d7823Smrg 1319a96d7823Smrg/* ARGSUSED */ 1320a96d7823Smrgstatic void 1321a96d7823Smrgfs_block_handler(void *wt) 1322a96d7823Smrg{ 1323a96d7823Smrg CARD32 now, earliest, wakeup; 1324a96d7823Smrg int soonest; 1325a96d7823Smrg FSFpePtr conn; 1326a96d7823Smrg 1327a96d7823Smrg /* 1328a96d7823Smrg * Flush all pending output 1329a96d7823Smrg */ 1330a96d7823Smrg if (fs_blockState & FS_PENDING_WRITE) 1331a96d7823Smrg for (conn = fs_fpes; conn; conn = conn->next) 1332a96d7823Smrg if (conn->blockState & FS_PENDING_WRITE) 1333a96d7823Smrg _fs_flush (conn); 1334a96d7823Smrg /* 1335a96d7823Smrg * Check for any fpe with a complete reply, set sleep time to zero 1336a96d7823Smrg */ 1337a96d7823Smrg if (fs_blockState & FS_COMPLETE_REPLY) 1338a96d7823Smrg adjust_fs_wait_for_delay(wt, 0); 1339a96d7823Smrg /* 1340a96d7823Smrg * Walk through fpe list computing sleep time 1341a96d7823Smrg */ 1342a96d7823Smrg else if (fs_blockState & (FS_BROKEN_WRITE| 1343a96d7823Smrg FS_BROKEN_CONNECTION| 1344a96d7823Smrg FS_PENDING_REPLY| 1345a96d7823Smrg FS_RECONNECTING)) 1346a96d7823Smrg { 1347a96d7823Smrg now = GetTimeInMillis (); 1348a96d7823Smrg earliest = now + 10000000; 1349a96d7823Smrg for (conn = fs_fpes; conn; conn = conn->next) 1350a96d7823Smrg { 1351a96d7823Smrg if (conn->blockState & FS_RECONNECTING) 1352a96d7823Smrg { 1353a96d7823Smrg wakeup = conn->blockedConnectTime; 1354a96d7823Smrg if (TimeCmp (wakeup, <, earliest)) 1355a96d7823Smrg earliest = wakeup; 1356a96d7823Smrg } 1357a96d7823Smrg if (conn->blockState & FS_BROKEN_CONNECTION) 1358a96d7823Smrg { 1359a96d7823Smrg wakeup = conn->brokenConnectionTime; 1360a96d7823Smrg if (TimeCmp (wakeup, <, earliest)) 1361a96d7823Smrg earliest = wakeup; 1362a96d7823Smrg } 1363a96d7823Smrg if (conn->blockState & FS_BROKEN_WRITE) 1364a96d7823Smrg { 1365a96d7823Smrg wakeup = conn->brokenWriteTime; 1366a96d7823Smrg if (TimeCmp (wakeup, <, earliest)) 1367a96d7823Smrg earliest = wakeup; 1368a96d7823Smrg } 1369a96d7823Smrg if (conn->blockState & FS_PENDING_REPLY) 1370a96d7823Smrg { 1371a96d7823Smrg wakeup = conn->blockedReplyTime; 1372a96d7823Smrg if (TimeCmp (wakeup, <, earliest)) 1373a96d7823Smrg earliest = wakeup; 1374a96d7823Smrg } 1375a96d7823Smrg } 1376a96d7823Smrg soonest = earliest - now; 1377a96d7823Smrg if (soonest < 0) 1378a96d7823Smrg soonest = 0; 1379a96d7823Smrg adjust_fs_wait_for_delay(wt, soonest); 1380a96d7823Smrg } 1381a96d7823Smrg} 1382a96d7823Smrg 1383a96d7823Smrgstatic void 1384a96d7823Smrgfs_handle_unexpected(FSFpePtr conn, fsGenericReply *rep) 1385a96d7823Smrg{ 1386a96d7823Smrg if (rep->type == FS_Event && rep->data1 == KeepAlive) 1387a96d7823Smrg { 1388a96d7823Smrg fsNoopReq req; 1389a96d7823Smrg 1390a96d7823Smrg /* ping it back */ 1391a96d7823Smrg req.reqType = FS_Noop; 1392a96d7823Smrg req.length = SIZEOF(fsNoopReq) >> 2; 1393a96d7823Smrg _fs_add_req_log(conn, FS_Noop); 1394a96d7823Smrg _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq)); 1395a96d7823Smrg } 1396a96d7823Smrg /* this should suck up unexpected replies and events */ 1397a96d7823Smrg _fs_done_read (conn, rep->length << 2); 1398a96d7823Smrg} 1399a96d7823Smrg 1400a96d7823Smrgstatic void 1401a96d7823Smrgfs_read_reply (FontPathElementPtr fpe, pointer client) 1402a96d7823Smrg{ 1403a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1404a96d7823Smrg FSBlockDataPtr blockrec; 1405a96d7823Smrg int ret; 1406a96d7823Smrg int err; 1407a96d7823Smrg fsGenericReply *rep; 1408a96d7823Smrg 1409a96d7823Smrg if ((rep = fs_get_reply (conn, &ret))) 1410a96d7823Smrg { 1411a96d7823Smrg _fs_add_rep_log (conn, rep); 1412a96d7823Smrg for (blockrec = conn->blockedRequests; 1413a96d7823Smrg blockrec; 1414a96d7823Smrg blockrec = blockrec->next) 1415a96d7823Smrg { 1416a96d7823Smrg if (blockrec->sequenceNumber == rep->sequenceNumber) 1417a96d7823Smrg break; 1418a96d7823Smrg } 1419a96d7823Smrg err = Successful; 1420a96d7823Smrg if (!blockrec) 1421a96d7823Smrg { 1422a96d7823Smrg fs_handle_unexpected(conn, rep); 1423a96d7823Smrg } 1424a96d7823Smrg else 1425a96d7823Smrg { 1426a96d7823Smrg /* 1427a96d7823Smrg * go read it, and if we're done, 1428a96d7823Smrg * wake up the appropriate client 1429a96d7823Smrg */ 1430a96d7823Smrg switch (blockrec->type) { 1431a96d7823Smrg case FS_OPEN_FONT: 1432a96d7823Smrg blockrec->errcode = fs_do_open_font(fpe, blockrec); 1433a96d7823Smrg break; 1434a96d7823Smrg case FS_LOAD_GLYPHS: 1435a96d7823Smrg blockrec->errcode = fs_read_glyphs(fpe, blockrec); 1436a96d7823Smrg break; 1437a96d7823Smrg case FS_LIST_FONTS: 1438a96d7823Smrg blockrec->errcode = fs_read_list(fpe, blockrec); 1439a96d7823Smrg break; 1440a96d7823Smrg case FS_LIST_WITH_INFO: 1441a96d7823Smrg blockrec->errcode = fs_read_list_info(fpe, blockrec); 1442a96d7823Smrg break; 1443a96d7823Smrg default: 1444a96d7823Smrg break; 1445a96d7823Smrg } 1446a96d7823Smrg err = blockrec->errcode; 1447a96d7823Smrg if (err != StillWorking) 1448a96d7823Smrg { 1449a96d7823Smrg while (blockrec) 1450a96d7823Smrg { 1451a96d7823Smrg blockrec->errcode = err; 1452a96d7823Smrg if (client != blockrec->client) 1453a96d7823Smrg ClientSignal(blockrec->client); 1454a96d7823Smrg blockrec = blockrec->depending; 1455a96d7823Smrg } 1456a96d7823Smrg _fs_unmark_block (conn, FS_PENDING_REPLY); 1457a96d7823Smrg } 1458a96d7823Smrg } 1459a96d7823Smrg if (fs_reply_ready (conn)) 1460a96d7823Smrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 1461a96d7823Smrg else 1462a96d7823Smrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 1463a96d7823Smrg } 1464a96d7823Smrg} 1465a96d7823Smrg 1466a96d7823Smrgstatic void 1467a96d7823Smrgfs_fd_handler(int fd, void *data) 1468a96d7823Smrg{ 1469a96d7823Smrg FontPathElementPtr fpe = data; 1470a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1471a96d7823Smrg 1472a96d7823Smrg /* 1473a96d7823Smrg * Don't continue if the fd is -1 (which will be true when the 1474a96d7823Smrg * font server terminates 1475a96d7823Smrg */ 1476a96d7823Smrg if ((conn->blockState & FS_RECONNECTING)) 1477a96d7823Smrg _fs_check_reconnect (conn); 1478a96d7823Smrg else if ((conn->fs_fd != -1)) 1479a96d7823Smrg fs_read_reply (fpe, 0); 1480a96d7823Smrg} 1481a96d7823Smrg 1482a96d7823Smrgstatic int 1483a96d7823Smrgfs_wakeup(FontPathElementPtr fpe) 1484a96d7823Smrg{ 1485a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1486a96d7823Smrg 1487a96d7823Smrg if (conn->blockState & (FS_PENDING_REPLY|FS_BROKEN_CONNECTION|FS_BROKEN_WRITE)) 1488a96d7823Smrg _fs_do_blocked (conn); 1489a96d7823Smrg if (conn->blockState & FS_COMPLETE_REPLY) 1490a96d7823Smrg fs_read_reply (fpe, 0); 1491a96d7823Smrg#ifdef DEBUG 1492a96d7823Smrg { 1493a96d7823Smrg FSBlockDataPtr blockrec; 1494a96d7823Smrg FSBlockedFontPtr bfont; 1495a96d7823Smrg static CARD32 lastState; 1496a96d7823Smrg static FSBlockDataPtr lastBlock; 1497a96d7823Smrg 1498a96d7823Smrg if (conn->blockState || conn->blockedRequests || lastState || lastBlock) 1499a96d7823Smrg { 1500a96d7823Smrg fprintf (stderr, " Block State 0x%x\n", (int) conn->blockState); 1501a96d7823Smrg lastState = conn->blockState; 1502a96d7823Smrg lastBlock = conn->blockedRequests; 1503a96d7823Smrg } 1504a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 1505a96d7823Smrg { 1506a96d7823Smrg switch (blockrec->type) { 1507a96d7823Smrg case FS_OPEN_FONT: 1508a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 1509a96d7823Smrg fprintf (stderr, " Blocked font errcode %d sequence %d state %s %s\n", 1510a96d7823Smrg blockrec->errcode, 1511a96d7823Smrg blockrec->sequenceNumber, 1512a96d7823Smrg fs_open_states[bfont->state], 1513a96d7823Smrg bfont->pfont ? 1514a96d7823Smrg ((FSFontDataPtr) (bfont->pfont->fpePrivate))->name : 1515a96d7823Smrg "<freed>"); 1516a96d7823Smrg break; 1517a96d7823Smrg case FS_LIST_FONTS: 1518a96d7823Smrg fprintf (stderr, " Blocked list errcode %d sequence %d\n", 1519a96d7823Smrg blockrec->errcode, blockrec->sequenceNumber); 1520a96d7823Smrg break; 1521a96d7823Smrg default: 1522a96d7823Smrg fprintf (stderr, " Blocked type %d errcode %d sequence %d\n", 1523a96d7823Smrg blockrec->type, 1524a96d7823Smrg blockrec->errcode, 1525a96d7823Smrg blockrec->sequenceNumber); 1526a96d7823Smrg break; 1527a96d7823Smrg } 1528a96d7823Smrg } 1529a96d7823Smrg } 1530a96d7823Smrg#endif 1531a96d7823Smrg return FALSE; 1532a96d7823Smrg} 1533a96d7823Smrg 1534a96d7823Smrg/* 1535a96d7823Smrg * Notice a dead connection and prepare for reconnect 1536a96d7823Smrg */ 1537a96d7823Smrg 1538a96d7823Smrgvoid 1539a96d7823Smrg_fs_connection_died(FSFpePtr conn) 1540a96d7823Smrg{ 1541a96d7823Smrg if (conn->blockState & FS_BROKEN_CONNECTION) 1542a96d7823Smrg return; 1543a96d7823Smrg fs_close_conn(conn); 1544a96d7823Smrg conn->brokenConnectionTime = GetTimeInMillis (); 1545a96d7823Smrg _fs_mark_block (conn, FS_BROKEN_CONNECTION); 1546a96d7823Smrg _fs_unmark_block (conn, FS_BROKEN_WRITE|FS_PENDING_WRITE|FS_RECONNECTING); 1547a96d7823Smrg} 1548a96d7823Smrg 1549a96d7823Smrg/* 1550a96d7823Smrg * Signal clients that the connection has come back up 1551a96d7823Smrg */ 1552a96d7823Smrgstatic int 1553a96d7823Smrg_fs_restart_connection(FSFpePtr conn) 1554a96d7823Smrg{ 1555a96d7823Smrg FSBlockDataPtr block; 1556a96d7823Smrg 1557a96d7823Smrg _fs_unmark_block (conn, FS_GIVE_UP); 1558a96d7823Smrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 1559a96d7823Smrg { 1560a96d7823Smrg if (block->errcode == StillWorking) 1561a96d7823Smrg { 1562a96d7823Smrg ClientSignal(block->client); 1563a96d7823Smrg fs_abort_blockrec(conn, block); 1564a96d7823Smrg } 1565a96d7823Smrg } 1566a96d7823Smrg return TRUE; 1567a96d7823Smrg} 1568a96d7823Smrg 1569a96d7823Smrg/* 1570a96d7823Smrg * Declare this font server connection useless 1571a96d7823Smrg */ 1572a96d7823Smrgstatic void 1573a96d7823Smrg_fs_giveup (FSFpePtr conn) 1574a96d7823Smrg{ 1575a96d7823Smrg FSBlockDataPtr block; 1576a96d7823Smrg 1577a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 1578a96d7823Smrg return; 1579a96d7823Smrg#ifdef DEBUG 1580a96d7823Smrg fprintf (stderr, "give up on FS \"%s\"\n", conn->servername); 1581a96d7823Smrg#endif 1582a96d7823Smrg _fs_mark_block (conn, FS_GIVE_UP); 1583a96d7823Smrg while ((block = (FSBlockDataPtr) conn->blockedRequests)) 1584a96d7823Smrg { 1585a96d7823Smrg if (block->errcode == StillWorking) 1586a96d7823Smrg { 1587a96d7823Smrg ClientSignal (block->client); 1588a96d7823Smrg fs_abort_blockrec (conn, block); 1589a96d7823Smrg } 1590a96d7823Smrg } 1591a96d7823Smrg if (conn->fs_fd >= 0) 1592a96d7823Smrg _fs_connection_died (conn); 1593a96d7823Smrg} 1594a96d7823Smrg 1595a96d7823Smrgstatic void 1596a96d7823Smrg_fs_do_blocked (FSFpePtr conn) 1597a96d7823Smrg{ 1598a96d7823Smrg CARD32 now; 1599a96d7823Smrg 1600a96d7823Smrg now = GetTimeInMillis (); 1601a96d7823Smrg if ((conn->blockState & FS_PENDING_REPLY) && 1602a96d7823Smrg TimeCmp (conn->blockedReplyTime, <=, now)) 1603a96d7823Smrg { 1604a96d7823Smrg _fs_giveup (conn); 1605a96d7823Smrg } 1606a96d7823Smrg else 1607a96d7823Smrg { 1608a96d7823Smrg if (conn->blockState & FS_BROKEN_CONNECTION) 1609a96d7823Smrg { 1610a96d7823Smrg /* Try to reconnect broken connections */ 1611a96d7823Smrg if (TimeCmp (conn->brokenConnectionTime, <=, now)) 1612a96d7823Smrg _fs_start_reconnect (conn); 1613a96d7823Smrg } 1614a96d7823Smrg else if (conn->blockState & FS_BROKEN_WRITE) 1615a96d7823Smrg { 1616a96d7823Smrg /* Try to flush blocked connections */ 1617a96d7823Smrg if (TimeCmp (conn->brokenWriteTime, <=, now)) 1618a96d7823Smrg _fs_flush (conn); 1619a96d7823Smrg } 1620a96d7823Smrg } 1621a96d7823Smrg} 1622a96d7823Smrg 1623a96d7823Smrg/* 1624a96d7823Smrg * sends the actual request out 1625a96d7823Smrg */ 1626a96d7823Smrg/* ARGSUSED */ 1627a96d7823Smrgstatic int 1628a96d7823Smrgfs_send_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 1629a96d7823Smrg const char *name, int namelen, 1630a96d7823Smrg fsBitmapFormat format, fsBitmapFormatMask fmask, 1631a96d7823Smrg XID id, FontPtr *ppfont) 1632a96d7823Smrg{ 1633a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1634a96d7823Smrg FontPtr font; 1635a96d7823Smrg FSBlockDataPtr blockrec = NULL; 1636a96d7823Smrg FSBlockedFontPtr bfont; 1637a96d7823Smrg FSFontDataPtr fsd; 1638a96d7823Smrg fsOpenBitmapFontReq openreq; 1639a96d7823Smrg fsQueryXInfoReq inforeq; 1640a96d7823Smrg fsQueryXExtents16Req extreq; 1641a96d7823Smrg int err; 1642a96d7823Smrg unsigned char buf[1024]; 1643a96d7823Smrg 1644a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 1645a96d7823Smrg return BadFontName; 1646a96d7823Smrg 1647a96d7823Smrg if (namelen < 0 || namelen > sizeof (buf) - 1) 1648a96d7823Smrg return BadFontName; 1649a96d7823Smrg 1650a96d7823Smrg /* 1651a96d7823Smrg * Get the font structure put together, either by reusing 1652a96d7823Smrg * the existing one or creating a new one 1653a96d7823Smrg */ 1654a96d7823Smrg if (flags & FontReopen) 1655a96d7823Smrg { 1656a96d7823Smrg Atom nameatom, fn = None; 1657a96d7823Smrg int i; 1658a96d7823Smrg 1659a96d7823Smrg font = *ppfont; 1660a96d7823Smrg fsd = (FSFontDataPtr)font->fpePrivate; 1661a96d7823Smrg /* This is an attempt to reopen a font. Did the font have a 1662a96d7823Smrg NAME property? */ 1663a96d7823Smrg if ((nameatom = MakeAtom("FONT", 4, 0)) != None) 1664a96d7823Smrg { 1665a96d7823Smrg for (i = 0; i < font->info.nprops; i++) 1666a96d7823Smrg if (font->info.props[i].name == nameatom && 1667a96d7823Smrg font->info.isStringProp[i]) 1668a96d7823Smrg { 1669a96d7823Smrg fn = font->info.props[i].value; 1670a96d7823Smrg break; 1671a96d7823Smrg } 1672a96d7823Smrg } 1673a96d7823Smrg if (fn == None || !(name = NameForAtom(fn))) 1674a96d7823Smrg { 1675a96d7823Smrg name = fsd->name; 1676a96d7823Smrg namelen = fsd->namelen; 1677a96d7823Smrg } 1678a96d7823Smrg else 1679a96d7823Smrg namelen = strlen(name); 1680a96d7823Smrg } 1681a96d7823Smrg else 1682a96d7823Smrg { 1683a96d7823Smrg font = fs_create_font (fpe, name, namelen, format, fmask); 1684a96d7823Smrg if (!font) 1685a96d7823Smrg return AllocError; 1686a96d7823Smrg 1687a96d7823Smrg fsd = (FSFontDataPtr)font->fpePrivate; 1688a96d7823Smrg } 1689a96d7823Smrg 1690a96d7823Smrg /* make a new block record, and add it to the end of the list */ 1691a96d7823Smrg blockrec = fs_new_block_rec(font->fpe, client, FS_OPEN_FONT); 1692a96d7823Smrg if (!blockrec) 1693a96d7823Smrg { 1694a96d7823Smrg if (!(flags & FontReopen)) 1695a96d7823Smrg (*font->unload_font) (font); 1696a96d7823Smrg return AllocError; 1697a96d7823Smrg } 1698a96d7823Smrg 1699a96d7823Smrg fsd->generation = conn->generation; 1700a96d7823Smrg 1701a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 1702a96d7823Smrg bfont->fontid = fsd->fontid; 1703a96d7823Smrg bfont->pfont = font; 1704a96d7823Smrg bfont->state = FS_OPEN_REPLY; 1705a96d7823Smrg bfont->flags = flags; 1706a96d7823Smrg bfont->format = fsd->format; 1707a96d7823Smrg bfont->clients_depending = (FSClientsDependingPtr)0; 1708a96d7823Smrg bfont->freeFont = (flags & FontReopen) == 0; 1709a96d7823Smrg 171060da515cSmrg /* 171160da515cSmrg * Must check this before generating any protocol, otherwise we'll 171260da515cSmrg * mess up a reconnect in progress 171360da515cSmrg */ 171460da515cSmrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 171560da515cSmrg { 171660da515cSmrg _fs_pending_reply (conn); 171760da515cSmrg return Suspended; 171860da515cSmrg } 171960da515cSmrg 1720a96d7823Smrg _fs_client_access (conn, client, (flags & FontOpenSync) != 0); 1721a96d7823Smrg _fs_client_resolution(conn); 1722a96d7823Smrg 1723a96d7823Smrg /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */ 1724a96d7823Smrg buf[0] = (unsigned char) namelen; 1725a96d7823Smrg memcpy(&buf[1], name, namelen); 1726a96d7823Smrg openreq.reqType = FS_OpenBitmapFont; 1727a96d7823Smrg openreq.pad = 0; 1728a96d7823Smrg openreq.fid = fsd->fontid; 1729a96d7823Smrg openreq.format_hint = fsd->format; 1730a96d7823Smrg openreq.format_mask = fsd->fmask; 1731a96d7823Smrg openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 4) >> 2; 1732a96d7823Smrg 1733a96d7823Smrg _fs_add_req_log(conn, FS_OpenBitmapFont); 1734a96d7823Smrg _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq)); 1735a96d7823Smrg _fs_write_pad(conn, (char *) buf, namelen + 1); 1736a96d7823Smrg 1737a96d7823Smrg blockrec->sequenceNumber = conn->current_seq; 1738a96d7823Smrg 1739a96d7823Smrg inforeq.reqType = FS_QueryXInfo; 1740a96d7823Smrg inforeq.pad = 0; 1741a96d7823Smrg inforeq.id = fsd->fontid; 1742a96d7823Smrg inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2; 1743a96d7823Smrg 1744a96d7823Smrg bfont->queryInfoSequence = conn->current_seq + 1; 1745a96d7823Smrg 1746a96d7823Smrg _fs_add_req_log(conn, FS_QueryXInfo); 1747a96d7823Smrg _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq)); 1748a96d7823Smrg 1749a96d7823Smrg if (!(bfont->flags & FontReopen)) 1750a96d7823Smrg { 1751a96d7823Smrg extreq.reqType = FS_QueryXExtents16; 1752a96d7823Smrg extreq.range = fsTrue; 1753a96d7823Smrg extreq.fid = fsd->fontid; 1754a96d7823Smrg extreq.num_ranges = 0; 1755a96d7823Smrg extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2; 1756a96d7823Smrg 1757a96d7823Smrg bfont->queryExtentsSequence = conn->current_seq + 1; 1758a96d7823Smrg 1759a96d7823Smrg _fs_add_req_log(conn, FS_QueryXExtents16); 1760a96d7823Smrg _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req)); 1761a96d7823Smrg } 1762a96d7823Smrg 1763a96d7823Smrg#ifdef NCD 1764a96d7823Smrg if (configData.ExtendedFontDiags) 1765a96d7823Smrg { 1766a96d7823Smrg memcpy(buf, name, MIN(256, namelen)); 1767a96d7823Smrg buf[MIN(256, namelen)] = '\0'; 1768a96d7823Smrg printf("Requesting font \"%s\" from font server \"%s\"\n", 1769a96d7823Smrg buf, font->fpe->name); 1770a96d7823Smrg } 1771a96d7823Smrg#endif 1772a96d7823Smrg _fs_prepare_for_reply (conn); 1773a96d7823Smrg 1774a96d7823Smrg err = blockrec->errcode; 1775a96d7823Smrg if (bfont->flags & FontOpenSync) 1776a96d7823Smrg { 1777a96d7823Smrg while (blockrec->errcode == StillWorking) 1778a96d7823Smrg { 1779a96d7823Smrg if (fs_await_reply (conn) != FSIO_READY) 1780a96d7823Smrg { 1781a96d7823Smrg blockrec->errcode = BadFontName; 1782a96d7823Smrg break; 1783a96d7823Smrg } 1784a96d7823Smrg fs_read_reply (font->fpe, client); 1785a96d7823Smrg } 1786a96d7823Smrg err = blockrec->errcode; 1787a96d7823Smrg if (err == Successful) 1788a96d7823Smrg *ppfont = bfont->pfont; 1789a96d7823Smrg else 179060da515cSmrg fs_cleanup_bfont (conn, bfont); 1791a96d7823Smrg bfont->freeFont = FALSE; 1792a96d7823Smrg _fs_remove_block_rec (conn, blockrec); 1793a96d7823Smrg } 1794a96d7823Smrg return err == StillWorking ? Suspended : err; 1795a96d7823Smrg} 1796a96d7823Smrg 1797a96d7823Smrgstatic void 1798a96d7823Smrgfs_send_query_bitmaps(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 1799a96d7823Smrg{ 1800a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1801a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 1802a96d7823Smrg fsQueryXBitmaps16Req bitreq; 1803a96d7823Smrg 1804a96d7823Smrg /* send the request */ 1805a96d7823Smrg bitreq.reqType = FS_QueryXBitmaps16; 1806a96d7823Smrg bitreq.fid = bfont->fontid; 1807a96d7823Smrg bitreq.format = bfont->format; 1808a96d7823Smrg bitreq.range = TRUE; 1809a96d7823Smrg bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2; 1810a96d7823Smrg bitreq.num_ranges = 0; 1811a96d7823Smrg 1812a96d7823Smrg bfont->queryBitmapsSequence = conn->current_seq + 1; 1813a96d7823Smrg 1814a96d7823Smrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 1815a96d7823Smrg _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req)); 1816a96d7823Smrg} 1817a96d7823Smrg 1818a96d7823Smrg/* ARGSUSED */ 1819a96d7823Smrgstatic int 1820a96d7823Smrgfs_open_font(pointer client, FontPathElementPtr fpe, Mask flags, 1821a96d7823Smrg const char *name, int namelen, 1822a96d7823Smrg fsBitmapFormat format, fsBitmapFormatMask fmask, 1823a96d7823Smrg XID id, FontPtr *ppfont, 1824a96d7823Smrg char **alias, FontPtr non_cachable_font) 1825a96d7823Smrg{ 1826a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1827a96d7823Smrg FSBlockDataPtr blockrec; 1828a96d7823Smrg FSBlockedFontPtr bfont; 1829a96d7823Smrg int err; 1830a96d7823Smrg 1831a96d7823Smrg /* libfont interface expects ImageRectMin glyphs */ 1832a96d7823Smrg format = (format & ~BitmapFormatImageRectMask) | BitmapFormatImageRectMin; 1833a96d7823Smrg 1834a96d7823Smrg *alias = (char *) 0; 1835a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 1836a96d7823Smrg { 1837a96d7823Smrg if (blockrec->type == FS_OPEN_FONT && blockrec->client == client) 1838a96d7823Smrg { 1839a96d7823Smrg err = blockrec->errcode; 1840a96d7823Smrg if (err == StillWorking) 1841a96d7823Smrg return Suspended; 1842a96d7823Smrg 1843a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 1844a96d7823Smrg if (err == Successful) 1845a96d7823Smrg *ppfont = bfont->pfont; 1846a96d7823Smrg else 184760da515cSmrg fs_cleanup_bfont (conn, bfont); 1848a96d7823Smrg _fs_remove_block_rec (conn, blockrec); 1849a96d7823Smrg return err; 1850a96d7823Smrg } 1851a96d7823Smrg } 1852a96d7823Smrg return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, 1853a96d7823Smrg id, ppfont); 1854a96d7823Smrg} 1855a96d7823Smrg 1856a96d7823Smrg/* ARGSUSED */ 1857a96d7823Smrgstatic int 185860da515cSmrgfs_send_close_font(FSFpePtr conn, Font id) 1859a96d7823Smrg{ 1860a96d7823Smrg fsCloseReq req; 1861a96d7823Smrg 1862a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 1863a96d7823Smrg return Successful; 1864a96d7823Smrg /* tell the font server to close the font */ 1865a96d7823Smrg req.reqType = FS_CloseFont; 1866a96d7823Smrg req.pad = 0; 1867a96d7823Smrg req.length = SIZEOF(fsCloseReq) >> 2; 1868a96d7823Smrg req.id = id; 1869a96d7823Smrg _fs_add_req_log(conn, FS_CloseFont); 1870a96d7823Smrg _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq)); 1871a96d7823Smrg 1872a96d7823Smrg return Successful; 1873a96d7823Smrg} 1874a96d7823Smrg 1875a96d7823Smrg/* ARGSUSED */ 1876a96d7823Smrgstatic void 1877a96d7823Smrgfs_close_font(FontPathElementPtr fpe, FontPtr pfont) 1878a96d7823Smrg{ 1879a96d7823Smrg FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate; 1880a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1881a96d7823Smrg 1882a96d7823Smrg if (conn->generation == fsd->generation) 188360da515cSmrg fs_send_close_font(conn, fsd->fontid); 1884a96d7823Smrg 1885a96d7823Smrg#ifdef DEBUG 1886a96d7823Smrg { 1887a96d7823Smrg FSBlockDataPtr blockrec; 1888a96d7823Smrg FSBlockedFontPtr bfont; 1889a96d7823Smrg 1890a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 1891a96d7823Smrg { 1892a96d7823Smrg if (blockrec->type == FS_OPEN_FONT) 1893a96d7823Smrg { 1894a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 1895a96d7823Smrg if (bfont->pfont == pfont) 1896a96d7823Smrg fprintf (stderr, "closing font which hasn't been opened\n"); 1897a96d7823Smrg } 1898a96d7823Smrg } 1899a96d7823Smrg } 1900a96d7823Smrg#endif 1901a96d7823Smrg (*pfont->unload_font) (pfont); 1902a96d7823Smrg} 1903a96d7823Smrg 1904a96d7823Smrgstatic int 1905a96d7823Smrgfs_read_glyphs(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 1906a96d7823Smrg{ 1907a96d7823Smrg FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data; 1908a96d7823Smrg FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data; 1909a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 1910a96d7823Smrg FontPtr pfont = bglyph->pfont; 1911a96d7823Smrg /* works for either blocked font 1912a96d7823Smrg or glyph rec... pfont is at 1913a96d7823Smrg the very beginning of both 1914a96d7823Smrg blockrec->data structures */ 1915a96d7823Smrg FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate); 1916a96d7823Smrg FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate; 1917a96d7823Smrg FontInfoPtr pfi = &pfont->info; 1918a96d7823Smrg fsQueryXBitmaps16Reply *rep; 1919a96d7823Smrg char *buf; 1920a96d7823Smrg long bufleft; /* length of reply left to use */ 1921a96d7823Smrg fsOffset32 *ppbits; 1922a96d7823Smrg fsOffset32 local_off; 1923a96d7823Smrg char *off_adr; 1924a96d7823Smrg pointer pbitmaps; 1925a96d7823Smrg char *bits, *allbits; 1926a96d7823Smrg#ifdef DEBUG 1927a96d7823Smrg char *origallbits; 1928a96d7823Smrg#endif 1929a96d7823Smrg int i, 1930a96d7823Smrg err; 1931a96d7823Smrg int nranges = 0; 1932a96d7823Smrg int ret; 1933a96d7823Smrg fsRange *nextrange = 0; 1934a96d7823Smrg unsigned long minchar, maxchar; 1935a96d7823Smrg 1936a96d7823Smrg rep = (fsQueryXBitmaps16Reply *) fs_get_reply (conn, &ret); 1937a96d7823Smrg if (!rep || rep->type == FS_Error || 1938a96d7823Smrg (rep->length < LENGTHOF(fsQueryXBitmaps16Reply))) 1939a96d7823Smrg { 1940a96d7823Smrg if (ret == FSIO_BLOCK) 1941a96d7823Smrg return StillWorking; 1942a96d7823Smrg if (rep) 1943a96d7823Smrg _fs_done_read (conn, rep->length << 2); 1944a96d7823Smrg err = AllocError; 1945a96d7823Smrg _fs_reply_failed (rep, fsQueryXBitmaps16Reply, "<"); 1946a96d7823Smrg goto bail; 1947a96d7823Smrg } 1948a96d7823Smrg 1949a96d7823Smrg buf = (char *) rep; 1950a96d7823Smrg buf += SIZEOF (fsQueryXBitmaps16Reply); 1951a96d7823Smrg 1952a96d7823Smrg bufleft = rep->length << 2; 1953a96d7823Smrg bufleft -= SIZEOF (fsQueryXBitmaps16Reply); 1954a96d7823Smrg 1955a96d7823Smrg if ((bufleft / SIZEOF (fsOffset32)) < rep->num_chars) 1956a96d7823Smrg { 1957a96d7823Smrg#ifdef DEBUG 1958a96d7823Smrg fprintf(stderr, 1959c7b4381aSmrg "fsQueryXBitmaps16: num_chars (%u) > bufleft (%ld) / %d\n", 1960c7b4381aSmrg (unsigned) rep->num_chars, bufleft, SIZEOF (fsOffset32)); 1961a96d7823Smrg#endif 1962a96d7823Smrg err = AllocError; 1963a96d7823Smrg goto bail; 1964a96d7823Smrg } 1965a96d7823Smrg ppbits = (fsOffset32 *) buf; 1966a96d7823Smrg buf += SIZEOF (fsOffset32) * (rep->num_chars); 1967a96d7823Smrg bufleft -= SIZEOF (fsOffset32) * (rep->num_chars); 1968a96d7823Smrg 1969a96d7823Smrg if (bufleft < rep->nbytes) 1970a96d7823Smrg { 1971a96d7823Smrg#ifdef DEBUG 1972a96d7823Smrg fprintf(stderr, 1973c7b4381aSmrg "fsQueryXBitmaps16: nbytes (%u) > bufleft (%ld)\n", 1974c7b4381aSmrg (unsigned) rep->nbytes, bufleft); 1975a96d7823Smrg#endif 1976a96d7823Smrg err = AllocError; 1977a96d7823Smrg goto bail; 1978a96d7823Smrg } 1979a96d7823Smrg pbitmaps = (pointer ) buf; 1980a96d7823Smrg 1981a96d7823Smrg if (blockrec->type == FS_LOAD_GLYPHS) 1982a96d7823Smrg { 1983a96d7823Smrg nranges = bglyph->num_expected_ranges; 1984a96d7823Smrg nextrange = bglyph->expected_ranges; 1985a96d7823Smrg } 1986a96d7823Smrg 1987a96d7823Smrg /* place the incoming glyphs */ 1988a96d7823Smrg if (nranges) 1989a96d7823Smrg { 1990a96d7823Smrg /* We're operating under the assumption that the ranges 1991a96d7823Smrg requested in the LoadGlyphs call were all legal for this 1992a96d7823Smrg font, and that individual ranges do not cover multiple 1993a96d7823Smrg rows... fs_build_range() is designed to ensure this. */ 1994a96d7823Smrg minchar = (nextrange->min_char_high - pfi->firstRow) * 1995a96d7823Smrg (pfi->lastCol - pfi->firstCol + 1) + 1996a96d7823Smrg nextrange->min_char_low - pfi->firstCol; 1997a96d7823Smrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 1998a96d7823Smrg (pfi->lastCol - pfi->firstCol + 1) + 1999a96d7823Smrg nextrange->max_char_low - pfi->firstCol; 2000a96d7823Smrg nextrange++; 2001a96d7823Smrg } 2002a96d7823Smrg else 2003a96d7823Smrg { 2004a96d7823Smrg minchar = 0; 2005a96d7823Smrg maxchar = rep->num_chars; 2006a96d7823Smrg } 2007a96d7823Smrg 2008a96d7823Smrg off_adr = (char *)ppbits; 2009a96d7823Smrg 2010a96d7823Smrg allbits = fs_alloc_glyphs (pfont, rep->nbytes); 2011a96d7823Smrg 2012a96d7823Smrg if (!allbits) 2013a96d7823Smrg { 2014a96d7823Smrg err = AllocError; 2015a96d7823Smrg goto bail; 2016a96d7823Smrg } 2017a96d7823Smrg 2018a96d7823Smrg#ifdef DEBUG 2019a96d7823Smrg origallbits = allbits; 2020a96d7823Smrg fprintf (stderr, "Reading %d glyphs in %d bytes for %s\n", 2021a96d7823Smrg (int) rep->num_chars, (int) rep->nbytes, fsd->name); 2022a96d7823Smrg#endif 2023a96d7823Smrg 2024a96d7823Smrg for (i = 0; i < rep->num_chars; i++) 2025a96d7823Smrg { 2026a96d7823Smrg memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */ 2027a96d7823Smrg if (blockrec->type == FS_OPEN_FONT || 2028a96d7823Smrg fsdata->encoding[minchar].bits == &_fs_glyph_requested) 2029a96d7823Smrg { 2030a96d7823Smrg /* 2031a96d7823Smrg * Broken X font server returns bits for missing characters 2032a96d7823Smrg * when font is padded 2033a96d7823Smrg */ 2034a96d7823Smrg if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics)) 2035a96d7823Smrg { 2036a96d7823Smrg if (local_off.length && 2037a96d7823Smrg (local_off.position < rep->nbytes) && 2038a96d7823Smrg (local_off.length <= (rep->nbytes - local_off.position))) 2039a96d7823Smrg { 2040a96d7823Smrg bits = allbits; 2041a96d7823Smrg allbits += local_off.length; 2042a96d7823Smrg memcpy(bits, (char *)pbitmaps + local_off.position, 2043a96d7823Smrg local_off.length); 2044a96d7823Smrg } 2045a96d7823Smrg else 2046a96d7823Smrg bits = &_fs_glyph_zero_length; 2047a96d7823Smrg } 2048a96d7823Smrg else 2049a96d7823Smrg bits = 0; 2050a96d7823Smrg if (fsdata->encoding[minchar].bits == &_fs_glyph_requested) 2051a96d7823Smrg fsd->glyphs_to_get--; 2052a96d7823Smrg fsdata->encoding[minchar].bits = bits; 2053a96d7823Smrg } 2054a96d7823Smrg if (minchar++ == maxchar) 2055a96d7823Smrg { 2056a96d7823Smrg if (!--nranges) break; 2057a96d7823Smrg minchar = (nextrange->min_char_high - pfi->firstRow) * 2058a96d7823Smrg (pfi->lastCol - pfi->firstCol + 1) + 2059a96d7823Smrg nextrange->min_char_low - pfi->firstCol; 2060a96d7823Smrg maxchar = (nextrange->max_char_high - pfi->firstRow) * 2061a96d7823Smrg (pfi->lastCol - pfi->firstCol + 1) + 2062a96d7823Smrg nextrange->max_char_low - pfi->firstCol; 2063a96d7823Smrg nextrange++; 2064a96d7823Smrg } 2065a96d7823Smrg off_adr += SIZEOF(fsOffset32); 2066a96d7823Smrg } 2067a96d7823Smrg#ifdef DEBUG 2068a96d7823Smrg fprintf (stderr, "Used %d bytes instead of %d\n", 2069a96d7823Smrg (int) (allbits - origallbits), (int) rep->nbytes); 2070a96d7823Smrg#endif 2071a96d7823Smrg 2072a96d7823Smrg if (blockrec->type == FS_OPEN_FONT) 2073a96d7823Smrg { 2074a96d7823Smrg fsd->glyphs_to_get = 0; 2075a96d7823Smrg bfont->state = FS_DONE_REPLY; 2076a96d7823Smrg } 2077a96d7823Smrg err = Successful; 2078a96d7823Smrg 2079a96d7823Smrgbail: 2080c7b4381aSmrg if (rep) 2081c7b4381aSmrg _fs_done_read (conn, rep->length << 2); 2082a96d7823Smrg return err; 2083a96d7823Smrg} 2084a96d7823Smrg 2085a96d7823Smrgstatic int 2086a96d7823Smrgfs_send_load_glyphs(pointer client, FontPtr pfont, 2087a96d7823Smrg int nranges, fsRange *ranges) 2088a96d7823Smrg{ 2089a96d7823Smrg FontPathElementPtr fpe = pfont->fpe; 2090a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2091a96d7823Smrg FSBlockedGlyphPtr blockedglyph; 2092a96d7823Smrg fsQueryXBitmaps16Req req; 2093a96d7823Smrg FSBlockDataPtr blockrec; 2094a96d7823Smrg 2095a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 2096a96d7823Smrg return BadCharRange; 2097a96d7823Smrg 2098a96d7823Smrg /* make a new block record, and add it to the end of the list */ 2099a96d7823Smrg blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS); 2100a96d7823Smrg if (!blockrec) 2101a96d7823Smrg return AllocError; 2102a96d7823Smrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 2103a96d7823Smrg blockedglyph->pfont = pfont; 2104a96d7823Smrg blockedglyph->num_expected_ranges = nranges; 2105a96d7823Smrg /* Assumption: it's our job to free ranges */ 2106a96d7823Smrg blockedglyph->expected_ranges = ranges; 2107a96d7823Smrg blockedglyph->clients_depending = (FSClientsDependingPtr)0; 2108a96d7823Smrg 2109a96d7823Smrg if (conn->blockState & (FS_BROKEN_CONNECTION|FS_RECONNECTING)) 2110a96d7823Smrg { 2111a96d7823Smrg _fs_pending_reply (conn); 2112a96d7823Smrg return Suspended; 2113a96d7823Smrg } 2114a96d7823Smrg 2115a96d7823Smrg /* send the request */ 2116a96d7823Smrg req.reqType = FS_QueryXBitmaps16; 2117a96d7823Smrg req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid; 2118a96d7823Smrg req.format = pfont->format; 2119a96d7823Smrg if (pfont->info.terminalFont) 2120a96d7823Smrg req.format = (req.format & ~(BitmapFormatImageRectMask)) | 2121a96d7823Smrg BitmapFormatImageRectMax; 2122a96d7823Smrg req.range = TRUE; 2123a96d7823Smrg /* each range takes up 4 bytes */ 2124a96d7823Smrg req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges; 2125a96d7823Smrg req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */ 2126a96d7823Smrg _fs_add_req_log(conn, FS_QueryXBitmaps16); 2127a96d7823Smrg _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req)); 2128a96d7823Smrg 2129a96d7823Smrg blockrec->sequenceNumber = conn->current_seq; 2130a96d7823Smrg 2131a96d7823Smrg /* Send ranges to the server... pack into a char array by hand 2132a96d7823Smrg to avoid structure-packing portability problems and to 2133a96d7823Smrg handle swapping for version1 protocol */ 2134a96d7823Smrg if (nranges) 2135a96d7823Smrg { 2136a96d7823Smrg#define RANGE_BUFFER_SIZE 64 2137a96d7823Smrg#define RANGE_BUFFER_SIZE_MASK 63 2138a96d7823Smrg int i; 2139a96d7823Smrg char range_buffer[RANGE_BUFFER_SIZE * 4]; 2140a96d7823Smrg char *range_buffer_p; 2141a96d7823Smrg 2142a96d7823Smrg range_buffer_p = range_buffer; 2143a96d7823Smrg for (i = 0; i < nranges;) 2144a96d7823Smrg { 2145a96d7823Smrg if (conn->fsMajorVersion > 1) 2146a96d7823Smrg { 2147a96d7823Smrg *range_buffer_p++ = ranges[i].min_char_high; 2148a96d7823Smrg *range_buffer_p++ = ranges[i].min_char_low; 2149a96d7823Smrg *range_buffer_p++ = ranges[i].max_char_high; 2150a96d7823Smrg *range_buffer_p++ = ranges[i].max_char_low; 2151a96d7823Smrg } 2152a96d7823Smrg else 2153a96d7823Smrg { 2154a96d7823Smrg *range_buffer_p++ = ranges[i].min_char_low; 2155a96d7823Smrg *range_buffer_p++ = ranges[i].min_char_high; 2156a96d7823Smrg *range_buffer_p++ = ranges[i].max_char_low; 2157a96d7823Smrg *range_buffer_p++ = ranges[i].max_char_high; 2158a96d7823Smrg } 2159a96d7823Smrg 2160a96d7823Smrg if (!(++i & RANGE_BUFFER_SIZE_MASK)) 2161a96d7823Smrg { 2162a96d7823Smrg _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4); 2163a96d7823Smrg range_buffer_p = range_buffer; 2164a96d7823Smrg } 2165a96d7823Smrg } 2166a96d7823Smrg if (i &= RANGE_BUFFER_SIZE_MASK) 2167a96d7823Smrg _fs_write(conn, range_buffer, i * 4); 2168a96d7823Smrg } 2169a96d7823Smrg 2170a96d7823Smrg _fs_prepare_for_reply (conn); 2171a96d7823Smrg return Suspended; 2172a96d7823Smrg} 2173a96d7823Smrg 2174a96d7823Smrgstatic int 2175a96d7823Smrg_fs_load_glyphs(pointer client, FontPtr pfont, Bool range_flag, 2176a96d7823Smrg unsigned int nchars, int item_size, unsigned char *data) 2177a96d7823Smrg{ 2178a96d7823Smrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 2179a96d7823Smrg int nranges = 0; 2180a96d7823Smrg fsRange *ranges = NULL; 2181a96d7823Smrg int res; 2182a96d7823Smrg FSBlockDataPtr blockrec; 2183a96d7823Smrg FSBlockedGlyphPtr blockedglyph; 2184a96d7823Smrg FSClientsDependingPtr *clients_depending = NULL; 2185a96d7823Smrg int err; 2186a96d7823Smrg 2187a96d7823Smrg /* see if the result is already there */ 2188a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 2189a96d7823Smrg { 2190a96d7823Smrg if (blockrec->type == FS_LOAD_GLYPHS) 2191a96d7823Smrg { 2192a96d7823Smrg blockedglyph = (FSBlockedGlyphPtr) blockrec->data; 2193a96d7823Smrg if (blockedglyph->pfont == pfont) 2194a96d7823Smrg { 2195a96d7823Smrg /* Look for this request */ 2196a96d7823Smrg if (blockrec->client == client) 2197a96d7823Smrg { 2198a96d7823Smrg err = blockrec->errcode; 2199a96d7823Smrg if (err == StillWorking) 2200a96d7823Smrg return Suspended; 2201a96d7823Smrg _fs_signal_clients_depending(&blockedglyph->clients_depending); 2202a96d7823Smrg _fs_remove_block_rec(conn, blockrec); 2203a96d7823Smrg return err; 2204a96d7823Smrg } 2205a96d7823Smrg /* We've found an existing LoadGlyphs blockrec for this 2206a96d7823Smrg font but for another client. Rather than build a 2207a96d7823Smrg blockrec for it now (which entails some complex 2208a96d7823Smrg maintenance), we'll add it to a queue of clients to 2209a96d7823Smrg be signalled when the existing LoadGlyphs is 2210a96d7823Smrg completed. */ 2211a96d7823Smrg clients_depending = &blockedglyph->clients_depending; 2212a96d7823Smrg break; 2213a96d7823Smrg } 2214a96d7823Smrg } 2215a96d7823Smrg else if (blockrec->type == FS_OPEN_FONT) 2216a96d7823Smrg { 2217a96d7823Smrg FSBlockedFontPtr bfont; 2218a96d7823Smrg bfont = (FSBlockedFontPtr) blockrec->data; 2219a96d7823Smrg if (bfont->pfont == pfont) 2220a96d7823Smrg { 2221a96d7823Smrg /* 2222a96d7823Smrg * An OpenFont is pending for this font, this must 2223a96d7823Smrg * be from a reopen attempt, so finish the open 2224a96d7823Smrg * attempt and retry the LoadGlyphs 2225a96d7823Smrg */ 2226a96d7823Smrg if (blockrec->client == client) 2227a96d7823Smrg { 2228a96d7823Smrg err = blockrec->errcode; 2229a96d7823Smrg if (err == StillWorking) 2230a96d7823Smrg return Suspended; 2231a96d7823Smrg 2232a96d7823Smrg _fs_signal_clients_depending(&bfont->clients_depending); 2233a96d7823Smrg _fs_remove_block_rec(conn, blockrec); 2234a96d7823Smrg if (err != Successful) 2235a96d7823Smrg return err; 2236a96d7823Smrg break; 2237a96d7823Smrg } 2238a96d7823Smrg /* We've found an existing OpenFont blockrec for this 2239a96d7823Smrg font but for another client. Rather than build a 2240a96d7823Smrg blockrec for it now (which entails some complex 2241a96d7823Smrg maintenance), we'll add it to a queue of clients to 2242a96d7823Smrg be signalled when the existing OpenFont is 2243a96d7823Smrg completed. */ 2244a96d7823Smrg if (blockrec->errcode == StillWorking) 2245a96d7823Smrg { 2246a96d7823Smrg clients_depending = &bfont->clients_depending; 2247a96d7823Smrg break; 2248a96d7823Smrg } 2249a96d7823Smrg } 2250a96d7823Smrg } 2251a96d7823Smrg } 2252a96d7823Smrg 2253a96d7823Smrg /* 2254a96d7823Smrg * see if the desired glyphs already exist, and return Successful if they 2255a96d7823Smrg * do, otherwise build up character range/character string 2256a96d7823Smrg */ 2257a96d7823Smrg res = fs_build_range(pfont, range_flag, nchars, item_size, data, 2258a96d7823Smrg &nranges, &ranges); 2259a96d7823Smrg 2260a96d7823Smrg switch (res) 2261a96d7823Smrg { 2262a96d7823Smrg case AccessDone: 2263a96d7823Smrg return Successful; 2264a96d7823Smrg 2265a96d7823Smrg case Successful: 2266a96d7823Smrg break; 2267a96d7823Smrg 2268a96d7823Smrg default: 2269a96d7823Smrg return res; 2270a96d7823Smrg } 2271a96d7823Smrg 2272a96d7823Smrg /* 2273a96d7823Smrg * If clients_depending is not null, this request must wait for 2274a96d7823Smrg * some prior request(s) to complete. 2275a96d7823Smrg */ 2276a96d7823Smrg if (clients_depending) 2277a96d7823Smrg { 2278a96d7823Smrg /* Since we're not ready to send the load_glyphs request yet, 2279a96d7823Smrg clean up the damage (if any) caused by the fs_build_range() 2280a96d7823Smrg call. */ 2281a96d7823Smrg if (nranges) 2282a96d7823Smrg { 2283a96d7823Smrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 2284a96d7823Smrg free(ranges); 2285a96d7823Smrg } 2286a96d7823Smrg return _fs_add_clients_depending(clients_depending, client); 2287a96d7823Smrg } 2288a96d7823Smrg 2289a96d7823Smrg /* 2290a96d7823Smrg * If fsd->generation != conn->generation, the font has been closed 2291a96d7823Smrg * due to a lost connection. We will reopen it, which will result 2292a96d7823Smrg * in one of three things happening: 2293a96d7823Smrg * 1) The open will succeed and obtain the same font. Life 2294a96d7823Smrg * is wonderful. 2295a96d7823Smrg * 2) The open will fail. There is code above to recognize this 2296a96d7823Smrg * and flunk the LoadGlyphs request. The client might not be 2297a96d7823Smrg * thrilled. 2298a96d7823Smrg * 3) Worst case: the open will succeed but the font we open will 2299a96d7823Smrg * be different. The fs_read_query_info() procedure attempts 2300a96d7823Smrg * to detect this by comparing the existing metrics and 2301a96d7823Smrg * properties against those of the reopened font... if they 2302a96d7823Smrg * don't match, we flunk the reopen, which eventually results 2303a96d7823Smrg * in flunking the LoadGlyphs request. We could go a step 2304a96d7823Smrg * further and compare the extents, but this should be 2305a96d7823Smrg * sufficient. 2306a96d7823Smrg */ 2307a96d7823Smrg if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation) 2308a96d7823Smrg { 2309a96d7823Smrg /* Since we're not ready to send the load_glyphs request yet, 2310a96d7823Smrg clean up the damage caused by the fs_build_range() call. */ 2311a96d7823Smrg _fs_clean_aborted_loadglyphs(pfont, nranges, ranges); 2312a96d7823Smrg free(ranges); 2313a96d7823Smrg 2314a96d7823Smrg /* Now try to reopen the font. */ 2315a96d7823Smrg return fs_send_open_font(client, pfont->fpe, 2316a96d7823Smrg (Mask)FontReopen, (char *)0, 0, 2317a96d7823Smrg (fsBitmapFormat)0, (fsBitmapFormatMask)0, 2318a96d7823Smrg (XID)0, &pfont); 2319a96d7823Smrg } 2320a96d7823Smrg 2321a96d7823Smrg return fs_send_load_glyphs(client, pfont, nranges, ranges); 2322a96d7823Smrg} 2323a96d7823Smrg 2324a96d7823Smrgint 2325a96d7823Smrgfs_load_all_glyphs(FontPtr pfont) 2326a96d7823Smrg{ 2327a96d7823Smrg int err; 2328a96d7823Smrg FSFpePtr conn = (FSFpePtr) pfont->fpe->private; 2329a96d7823Smrg 2330a96d7823Smrg /* 2331a96d7823Smrg * The purpose of this procedure is to load all glyphs in the event 2332a96d7823Smrg * that we're dealing with someone who doesn't understand the finer 2333a96d7823Smrg * points of glyph caching... it is called from _fs_get_glyphs() if 2334a96d7823Smrg * the latter is called to get glyphs that have not yet been loaded. 2335a96d7823Smrg * We assume that the caller will not know how to handle a return 2336a96d7823Smrg * value of Suspended (usually the case for a GetGlyphs() caller), 2337a96d7823Smrg * so this procedure hangs around, freezing the server, for the 2338a96d7823Smrg * request to complete. This is an unpleasant kluge called to 2339a96d7823Smrg * perform an unpleasant job that, we hope, will never be required. 2340a96d7823Smrg */ 2341a96d7823Smrg 2342a96d7823Smrg while ((err = _fs_load_glyphs(__GetServerClient(), pfont, TRUE, 0, 0, NULL)) == 2343a96d7823Smrg Suspended) 2344a96d7823Smrg { 2345a96d7823Smrg if (fs_await_reply (conn) != FSIO_READY) 2346a96d7823Smrg { 2347a96d7823Smrg /* Get rid of blockrec */ 2348a96d7823Smrg fs_client_died(__GetServerClient(), pfont->fpe); 2349a96d7823Smrg err = BadCharRange; 2350a96d7823Smrg break; 2351a96d7823Smrg } 2352a96d7823Smrg fs_read_reply (pfont->fpe, __GetServerClient()); 2353a96d7823Smrg } 2354a96d7823Smrg return err; 2355a96d7823Smrg} 2356a96d7823Smrg 2357a96d7823Smrgstatic int 2358a96d7823Smrgfs_read_list(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 2359a96d7823Smrg{ 2360a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2361a96d7823Smrg FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data; 2362a96d7823Smrg fsListFontsReply *rep; 2363a96d7823Smrg char *data; 2364a96d7823Smrg long dataleft; /* length of reply left to use */ 2365a96d7823Smrg int length, 2366a96d7823Smrg i, 2367a96d7823Smrg ret; 2368a96d7823Smrg int err; 2369a96d7823Smrg 2370a96d7823Smrg rep = (fsListFontsReply *) fs_get_reply (conn, &ret); 2371a96d7823Smrg if (!rep || rep->type == FS_Error || 2372a96d7823Smrg (rep->length < LENGTHOF(fsListFontsReply))) 2373a96d7823Smrg { 2374a96d7823Smrg if (ret == FSIO_BLOCK) 2375a96d7823Smrg return StillWorking; 2376a96d7823Smrg if (rep) 2377a96d7823Smrg _fs_done_read (conn, rep->length << 2); 2378a96d7823Smrg _fs_reply_failed (rep, fsListFontsReply, "<"); 2379a96d7823Smrg return AllocError; 2380a96d7823Smrg } 2381a96d7823Smrg data = (char *) rep + SIZEOF (fsListFontsReply); 2382a96d7823Smrg dataleft = (rep->length << 2) - SIZEOF (fsListFontsReply); 2383a96d7823Smrg 2384a96d7823Smrg err = Successful; 2385a96d7823Smrg /* copy data into FontPathRecord */ 2386a96d7823Smrg for (i = 0; i < rep->nFonts; i++) 2387a96d7823Smrg { 2388a96d7823Smrg if (dataleft < 1) 2389a96d7823Smrg break; 2390a96d7823Smrg length = *(unsigned char *)data++; 2391a96d7823Smrg dataleft--; /* used length byte */ 2392a96d7823Smrg if (length > dataleft) { 2393a96d7823Smrg#ifdef DEBUG 2394a96d7823Smrg fprintf(stderr, 2395a96d7823Smrg "fsListFonts: name length (%d) > dataleft (%ld)\n", 2396a96d7823Smrg length, dataleft); 2397a96d7823Smrg#endif 2398a96d7823Smrg err = BadFontName; 2399a96d7823Smrg break; 2400a96d7823Smrg } 2401a96d7823Smrg err = xfont2_add_font_names_name(blist->names, data, length); 2402a96d7823Smrg if (err != Successful) 2403a96d7823Smrg break; 2404a96d7823Smrg data += length; 2405a96d7823Smrg dataleft -= length; 2406a96d7823Smrg } 2407a96d7823Smrg _fs_done_read (conn, rep->length << 2); 2408a96d7823Smrg return err; 2409a96d7823Smrg} 2410a96d7823Smrg 2411a96d7823Smrgstatic int 2412a96d7823Smrgfs_send_list_fonts(pointer client, FontPathElementPtr fpe, const char *pattern, 2413a96d7823Smrg int patlen, int maxnames, FontNamesPtr newnames) 2414a96d7823Smrg{ 2415a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2416a96d7823Smrg FSBlockDataPtr blockrec; 2417a96d7823Smrg FSBlockedListPtr blockedlist; 2418a96d7823Smrg fsListFontsReq req; 2419a96d7823Smrg 2420a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 2421a96d7823Smrg return BadFontName; 2422a96d7823Smrg 2423a96d7823Smrg /* make a new block record, and add it to the end of the list */ 2424a96d7823Smrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS); 2425a96d7823Smrg if (!blockrec) 2426a96d7823Smrg return AllocError; 2427a96d7823Smrg blockedlist = (FSBlockedListPtr) blockrec->data; 2428a96d7823Smrg blockedlist->names = newnames; 2429a96d7823Smrg 2430a96d7823Smrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 2431a96d7823Smrg { 2432a96d7823Smrg _fs_pending_reply (conn); 2433a96d7823Smrg return Suspended; 2434a96d7823Smrg } 2435a96d7823Smrg 2436a96d7823Smrg _fs_client_access (conn, client, FALSE); 2437a96d7823Smrg _fs_client_resolution(conn); 2438a96d7823Smrg 2439a96d7823Smrg /* send the request */ 2440a96d7823Smrg req.reqType = FS_ListFonts; 2441a96d7823Smrg req.pad = 0; 2442a96d7823Smrg req.maxNames = maxnames; 2443a96d7823Smrg req.nbytes = patlen; 2444a96d7823Smrg req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2; 2445a96d7823Smrg _fs_add_req_log(conn, FS_ListFonts); 2446a96d7823Smrg _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq)); 2447a96d7823Smrg _fs_write_pad(conn, (char *) pattern, patlen); 2448a96d7823Smrg 2449a96d7823Smrg blockrec->sequenceNumber = conn->current_seq; 2450a96d7823Smrg 2451a96d7823Smrg#ifdef NCD 2452a96d7823Smrg if (configData.ExtendedFontDiags) { 2453a96d7823Smrg char buf[256]; 2454a96d7823Smrg 2455a96d7823Smrg memcpy(buf, pattern, MIN(256, patlen)); 2456a96d7823Smrg buf[MIN(256, patlen)] = '\0'; 2457a96d7823Smrg printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n", 2458a96d7823Smrg buf, fpe->name); 2459a96d7823Smrg } 2460a96d7823Smrg#endif 2461a96d7823Smrg 2462a96d7823Smrg _fs_prepare_for_reply (conn); 2463a96d7823Smrg return Suspended; 2464a96d7823Smrg} 2465a96d7823Smrg 2466a96d7823Smrgstatic int 2467a96d7823Smrgfs_list_fonts(pointer client, FontPathElementPtr fpe, 2468a96d7823Smrg const char *pattern, int patlen, int maxnames, FontNamesPtr newnames) 2469a96d7823Smrg{ 2470a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2471a96d7823Smrg FSBlockDataPtr blockrec; 2472a96d7823Smrg int err; 2473a96d7823Smrg 2474a96d7823Smrg /* see if the result is already there */ 2475a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 2476a96d7823Smrg { 2477a96d7823Smrg if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) 2478a96d7823Smrg { 2479a96d7823Smrg err = blockrec->errcode; 2480a96d7823Smrg if (err == StillWorking) 2481a96d7823Smrg return Suspended; 2482a96d7823Smrg _fs_remove_block_rec(conn, blockrec); 2483a96d7823Smrg return err; 2484a96d7823Smrg } 2485a96d7823Smrg } 2486a96d7823Smrg 2487a96d7823Smrg /* didn't find waiting record, so send a new one */ 2488a96d7823Smrg return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames); 2489a96d7823Smrg} 2490a96d7823Smrg 2491a96d7823Smrg/* 2492a96d7823Smrg * Read a single list info reply and restart for the next reply 2493a96d7823Smrg */ 2494a96d7823Smrgstatic int 2495a96d7823Smrgfs_read_list_info(FontPathElementPtr fpe, FSBlockDataPtr blockrec) 2496a96d7823Smrg{ 2497a96d7823Smrg FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data; 2498a96d7823Smrg fsListFontsWithXInfoReply *rep; 2499a96d7823Smrg char *buf; 2500a96d7823Smrg long bufleft; 2501a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2502a96d7823Smrg fsPropInfo *pi; 2503a96d7823Smrg fsPropOffset *po; 2504a96d7823Smrg pointer pd; 2505a96d7823Smrg int ret; 2506a96d7823Smrg int err; 2507a96d7823Smrg 2508a96d7823Smrg /* clean up anything from the last trip */ 2509a96d7823Smrg _fs_free_props (&binfo->info); 2510a96d7823Smrg 2511a96d7823Smrg rep = (fsListFontsWithXInfoReply *) fs_get_reply (conn, &ret); 2512a96d7823Smrg if (!rep || rep->type == FS_Error || 2513a96d7823Smrg ((rep->nameLength != 0) && 2514a96d7823Smrg (rep->length < LENGTHOF(fsListFontsWithXInfoReply)))) 2515a96d7823Smrg { 2516a96d7823Smrg if (ret == FSIO_BLOCK) 2517a96d7823Smrg return StillWorking; 2518a96d7823Smrg binfo->status = FS_LFWI_FINISHED; 2519a96d7823Smrg err = AllocError; 2520a96d7823Smrg _fs_reply_failed (rep, fsListFontsWithXInfoReply, "<"); 2521a96d7823Smrg goto done; 2522a96d7823Smrg } 2523a96d7823Smrg /* 2524a96d7823Smrg * Normal termination -- the list ends with a name of length 0 2525a96d7823Smrg */ 2526a96d7823Smrg if (rep->nameLength == 0) 2527a96d7823Smrg { 2528a96d7823Smrg#ifdef DEBUG 2529a96d7823Smrg fprintf (stderr, "fs_read_list_info done\n"); 2530a96d7823Smrg#endif 2531a96d7823Smrg binfo->status = FS_LFWI_FINISHED; 2532a96d7823Smrg err = BadFontName; 2533a96d7823Smrg goto done; 2534a96d7823Smrg } 2535a96d7823Smrg 2536a96d7823Smrg buf = (char *) rep + SIZEOF (fsListFontsWithXInfoReply); 2537a96d7823Smrg bufleft = (rep->length << 2) - SIZEOF (fsListFontsWithXInfoReply); 2538a96d7823Smrg 2539a96d7823Smrg /* 2540a96d7823Smrg * The original FS implementation didn't match 2541a96d7823Smrg * the spec, version 1 was respecified to match the FS. 2542a96d7823Smrg * Version 2 matches the original intent 2543a96d7823Smrg */ 2544a96d7823Smrg if (conn->fsMajorVersion <= 1) 2545a96d7823Smrg { 2546a96d7823Smrg if (rep->nameLength > bufleft) { 2547a96d7823Smrg#ifdef DEBUG 2548a96d7823Smrg fprintf(stderr, 2549a96d7823Smrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 2550a96d7823Smrg (int) rep->nameLength, bufleft); 2551a96d7823Smrg#endif 2552a96d7823Smrg err = AllocError; 2553a96d7823Smrg goto done; 2554a96d7823Smrg } 2555a96d7823Smrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 2556a96d7823Smrg memcpy (binfo->name, buf, rep->nameLength); 2557a96d7823Smrg buf += _fs_pad_length (rep->nameLength); 2558a96d7823Smrg bufleft -= _fs_pad_length (rep->nameLength); 2559a96d7823Smrg } 2560a96d7823Smrg pi = (fsPropInfo *) buf; 2561a96d7823Smrg if (SIZEOF (fsPropInfo) > bufleft) { 2562a96d7823Smrg#ifdef DEBUG 2563a96d7823Smrg fprintf(stderr, 2564a96d7823Smrg "fsListFontsWithXInfo: PropInfo length (%d) > bufleft (%ld)\n", 2565a96d7823Smrg (int) SIZEOF (fsPropInfo), bufleft); 2566a96d7823Smrg#endif 2567a96d7823Smrg err = AllocError; 2568a96d7823Smrg goto done; 2569a96d7823Smrg } 2570a96d7823Smrg bufleft -= SIZEOF (fsPropInfo); 2571a96d7823Smrg buf += SIZEOF (fsPropInfo); 2572a96d7823Smrg po = (fsPropOffset *) buf; 2573a96d7823Smrg if (pi->num_offsets > (bufleft / SIZEOF (fsPropOffset))) { 2574a96d7823Smrg#ifdef DEBUG 2575a96d7823Smrg fprintf(stderr, 2576c7b4381aSmrg "fsListFontsWithXInfo: offset length (%u * %d) > bufleft (%ld)\n", 2577c7b4381aSmrg (unsigned) pi->num_offsets, (int) SIZEOF (fsPropOffset), bufleft); 2578a96d7823Smrg#endif 2579a96d7823Smrg err = AllocError; 2580a96d7823Smrg goto done; 2581a96d7823Smrg } 2582a96d7823Smrg bufleft -= pi->num_offsets * SIZEOF (fsPropOffset); 2583a96d7823Smrg buf += pi->num_offsets * SIZEOF (fsPropOffset); 2584a96d7823Smrg pd = (pointer) buf; 2585a96d7823Smrg if (pi->data_len > bufleft) { 2586a96d7823Smrg#ifdef DEBUG 2587a96d7823Smrg fprintf(stderr, 2588c7b4381aSmrg "fsListFontsWithXInfo: data length (%u) > bufleft (%ld)\n", 2589c7b4381aSmrg (unsigned) pi->data_len, bufleft); 2590a96d7823Smrg#endif 2591a96d7823Smrg err = AllocError; 2592a96d7823Smrg goto done; 2593a96d7823Smrg } 2594a96d7823Smrg bufleft -= pi->data_len; 2595a96d7823Smrg buf += pi->data_len; 2596a96d7823Smrg if (conn->fsMajorVersion > 1) 2597a96d7823Smrg { 2598a96d7823Smrg if (rep->nameLength > bufleft) { 2599a96d7823Smrg#ifdef DEBUG 2600a96d7823Smrg fprintf(stderr, 2601a96d7823Smrg "fsListFontsWithXInfo: name length (%d) > bufleft (%ld)\n", 2602a96d7823Smrg (int) rep->nameLength, bufleft); 2603a96d7823Smrg#endif 2604a96d7823Smrg err = AllocError; 2605a96d7823Smrg goto done; 2606a96d7823Smrg } 2607a96d7823Smrg /* binfo->name is a 256 char array, rep->nameLength is a CARD8 */ 2608a96d7823Smrg memcpy (binfo->name, buf, rep->nameLength); 2609a96d7823Smrg buf += _fs_pad_length (rep->nameLength); 2610a96d7823Smrg bufleft -= _fs_pad_length (rep->nameLength); 2611a96d7823Smrg } 2612a96d7823Smrg 2613a96d7823Smrg#ifdef DEBUG 2614a96d7823Smrg binfo->name[rep->nameLength] = '\0'; 2615a96d7823Smrg fprintf (stderr, "fs_read_list_info %s\n", binfo->name); 2616a96d7823Smrg#endif 2617a96d7823Smrg err = _fs_convert_lfwi_reply(conn, &binfo->info, rep, pi, po, pd); 2618a96d7823Smrg if (err != Successful) 2619a96d7823Smrg { 2620a96d7823Smrg binfo->status = FS_LFWI_FINISHED; 2621a96d7823Smrg goto done; 2622a96d7823Smrg } 2623a96d7823Smrg binfo->namelen = rep->nameLength; 2624a96d7823Smrg binfo->remaining = rep->nReplies; 2625a96d7823Smrg 2626a96d7823Smrg binfo->status = FS_LFWI_REPLY; 2627a96d7823Smrg 2628a96d7823Smrg /* disable this font server until we've processed this response */ 2629a96d7823Smrg _fs_unmark_block (conn, FS_COMPLETE_REPLY); 2630a96d7823Smrg conn_stop_listening(conn); 2631a96d7823Smrgdone: 2632a96d7823Smrg _fs_done_read (conn, rep->length << 2); 2633a96d7823Smrg return err; 2634a96d7823Smrg} 2635a96d7823Smrg 2636a96d7823Smrg/* ARGSUSED */ 2637a96d7823Smrgstatic int 2638a96d7823Smrgfs_start_list_with_info(pointer client, FontPathElementPtr fpe, 2639a96d7823Smrg const char *pattern, int len, int maxnames, pointer *pdata) 2640a96d7823Smrg{ 2641a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2642a96d7823Smrg FSBlockDataPtr blockrec; 2643a96d7823Smrg FSBlockedListInfoPtr binfo; 2644a96d7823Smrg fsListFontsWithXInfoReq req; 2645a96d7823Smrg 2646a96d7823Smrg if (conn->blockState & FS_GIVE_UP) 2647a96d7823Smrg return BadFontName; 2648a96d7823Smrg 2649a96d7823Smrg /* make a new block record, and add it to the end of the list */ 2650a96d7823Smrg blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO); 2651a96d7823Smrg if (!blockrec) 2652a96d7823Smrg return AllocError; 2653a96d7823Smrg 2654a96d7823Smrg binfo = (FSBlockedListInfoPtr) blockrec->data; 2655a96d7823Smrg bzero((char *) binfo, sizeof(FSBlockedListInfoRec)); 2656a96d7823Smrg binfo->status = FS_LFWI_WAITING; 2657a96d7823Smrg 2658a96d7823Smrg if (conn->blockState & (FS_BROKEN_CONNECTION | FS_RECONNECTING)) 2659a96d7823Smrg { 2660a96d7823Smrg _fs_pending_reply (conn); 2661a96d7823Smrg return Suspended; 2662a96d7823Smrg } 2663a96d7823Smrg 2664a96d7823Smrg _fs_client_access (conn, client, FALSE); 2665a96d7823Smrg _fs_client_resolution(conn); 2666a96d7823Smrg 2667a96d7823Smrg /* send the request */ 2668a96d7823Smrg req.reqType = FS_ListFontsWithXInfo; 2669a96d7823Smrg req.pad = 0; 2670a96d7823Smrg req.maxNames = maxnames; 2671a96d7823Smrg req.nbytes = len; 2672a96d7823Smrg req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2; 2673a96d7823Smrg _fs_add_req_log(conn, FS_ListFontsWithXInfo); 2674a96d7823Smrg (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq)); 2675a96d7823Smrg (void) _fs_write_pad(conn, pattern, len); 2676a96d7823Smrg 2677a96d7823Smrg blockrec->sequenceNumber = conn->current_seq; 2678a96d7823Smrg 2679a96d7823Smrg#ifdef NCD 2680a96d7823Smrg if (configData.ExtendedFontDiags) { 2681a96d7823Smrg char buf[256]; 2682a96d7823Smrg 2683a96d7823Smrg memcpy(buf, pattern, MIN(256, len)); 2684a96d7823Smrg buf[MIN(256, len)] = '\0'; 2685a96d7823Smrg printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n", 2686a96d7823Smrg buf, fpe->name); 2687a96d7823Smrg } 2688a96d7823Smrg#endif 2689a96d7823Smrg 2690a96d7823Smrg _fs_prepare_for_reply (conn); 2691a96d7823Smrg return Successful; 2692a96d7823Smrg} 2693a96d7823Smrg 2694a96d7823Smrg/* ARGSUSED */ 2695a96d7823Smrgstatic int 2696a96d7823Smrgfs_next_list_with_info(pointer client, FontPathElementPtr fpe, 2697a96d7823Smrg char **namep, int *namelenp, 2698a96d7823Smrg FontInfoPtr *pFontInfo, int *numFonts, 2699a96d7823Smrg pointer private) 2700a96d7823Smrg{ 2701a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2702a96d7823Smrg FSBlockDataPtr blockrec; 2703a96d7823Smrg FSBlockedListInfoPtr binfo; 2704a96d7823Smrg int err; 2705a96d7823Smrg 2706a96d7823Smrg /* see if the result is already there */ 2707a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 2708a96d7823Smrg if (blockrec->type == FS_LIST_WITH_INFO && blockrec->client == client) 2709a96d7823Smrg break; 2710a96d7823Smrg 2711a96d7823Smrg if (!blockrec) 2712a96d7823Smrg { 2713a96d7823Smrg /* The only good reason for not finding a blockrec would be if 2714a96d7823Smrg disconnect/reconnect to the font server wiped it out and the 2715a96d7823Smrg code that called us didn't do the right thing to create 2716a96d7823Smrg another one. Under those circumstances, we need to return an 2717a96d7823Smrg error to prevent that code from attempting to interpret the 2718a96d7823Smrg information we don't return. */ 2719a96d7823Smrg return BadFontName; 2720a96d7823Smrg } 2721a96d7823Smrg 2722a96d7823Smrg binfo = (FSBlockedListInfoPtr) blockrec->data; 2723a96d7823Smrg 2724a96d7823Smrg if (binfo->status == FS_LFWI_WAITING) 2725a96d7823Smrg return Suspended; 2726a96d7823Smrg 2727a96d7823Smrg *namep = binfo->name; 2728a96d7823Smrg *namelenp = binfo->namelen; 2729a96d7823Smrg *pFontInfo = &binfo->info; 2730a96d7823Smrg *numFonts = binfo->remaining; 2731a96d7823Smrg 2732a96d7823Smrg /* Restart reply processing from this font server */ 2733a96d7823Smrg conn_start_listening(conn); 2734a96d7823Smrg if (fs_reply_ready (conn)) 2735a96d7823Smrg _fs_mark_block (conn, FS_COMPLETE_REPLY); 2736a96d7823Smrg 2737a96d7823Smrg err = blockrec->errcode; 2738a96d7823Smrg switch (binfo->status) { 2739a96d7823Smrg case FS_LFWI_FINISHED: 2740a96d7823Smrg _fs_remove_block_rec(conn, blockrec); 2741a96d7823Smrg break; 2742a96d7823Smrg case FS_LFWI_REPLY: 2743a96d7823Smrg binfo->status = FS_LFWI_WAITING; 2744a96d7823Smrg blockrec->errcode = StillWorking; 2745a96d7823Smrg conn->blockedReplyTime = GetTimeInMillis () + FontServerRequestTimeout; 2746a96d7823Smrg _fs_mark_block (conn, FS_PENDING_REPLY); 2747a96d7823Smrg break; 2748a96d7823Smrg } 2749a96d7823Smrg 2750a96d7823Smrg return err; 2751a96d7823Smrg} 2752a96d7823Smrg 2753a96d7823Smrg/* 2754a96d7823Smrg * Called when client exits 2755a96d7823Smrg */ 2756a96d7823Smrg 2757a96d7823Smrgstatic void 2758a96d7823Smrgfs_client_died(pointer client, FontPathElementPtr fpe) 2759a96d7823Smrg{ 2760a96d7823Smrg FSFpePtr conn = (FSFpePtr) fpe->private; 2761a96d7823Smrg FSBlockDataPtr blockrec, 2762a96d7823Smrg depending; 2763a96d7823Smrg FSClientPtr *prev, cur; 2764a96d7823Smrg fsFreeACReq freeac; 2765a96d7823Smrg 2766a96d7823Smrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 2767a96d7823Smrg { 2768a96d7823Smrg if (cur->client == client) { 2769a96d7823Smrg freeac.reqType = FS_FreeAC; 2770a96d7823Smrg freeac.pad = 0; 2771a96d7823Smrg freeac.id = cur->acid; 2772a96d7823Smrg freeac.length = sizeof (fsFreeACReq) >> 2; 2773a96d7823Smrg _fs_add_req_log(conn, FS_FreeAC); 2774a96d7823Smrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 2775a96d7823Smrg *prev = cur->next; 2776a96d7823Smrg free (cur); 2777a96d7823Smrg break; 2778a96d7823Smrg } 2779a96d7823Smrg } 2780a96d7823Smrg /* find a pending requests */ 2781a96d7823Smrg for (blockrec = conn->blockedRequests; blockrec; blockrec = blockrec->next) 2782a96d7823Smrg if (blockrec->client == client) 2783a96d7823Smrg break; 2784a96d7823Smrg 2785a96d7823Smrg if (!blockrec) 2786a96d7823Smrg return; 2787a96d7823Smrg 2788a96d7823Smrg /* replace the client pointers in this block rec with the chained one */ 2789a96d7823Smrg if ((depending = blockrec->depending)) 2790a96d7823Smrg { 2791a96d7823Smrg blockrec->client = depending->client; 2792a96d7823Smrg blockrec->depending = depending->depending; 2793a96d7823Smrg blockrec = depending; 2794a96d7823Smrg } 2795a96d7823Smrg fs_abort_blockrec(conn, blockrec); 2796a96d7823Smrg} 2797a96d7823Smrg 2798a96d7823Smrgstatic void 2799a96d7823Smrg_fs_client_access (FSFpePtr conn, pointer client, Bool sync) 2800a96d7823Smrg{ 2801a96d7823Smrg FSClientPtr *prev, cur; 2802a96d7823Smrg fsCreateACReq crac; 2803a96d7823Smrg fsSetAuthorizationReq setac; 2804a96d7823Smrg char *authorizations; 2805a96d7823Smrg int authlen; 2806a96d7823Smrg Bool new_cur = FALSE; 2807a96d7823Smrg char padding[4] = { 0, 0, 0, 0 }; 2808a96d7823Smrg 2809a96d7823Smrg#ifdef DEBUG 2810a96d7823Smrg if (conn->blockState & (FS_RECONNECTING|FS_BROKEN_CONNECTION)) 2811a96d7823Smrg { 2812a96d7823Smrg fprintf (stderr, "Sending requests without a connection\n"); 2813a96d7823Smrg } 2814a96d7823Smrg#endif 2815a96d7823Smrg for (prev = &conn->clients; (cur = *prev); prev = &cur->next) 2816a96d7823Smrg { 2817a96d7823Smrg if (cur->client == client) 2818a96d7823Smrg { 2819a96d7823Smrg if (prev != &conn->clients) 2820a96d7823Smrg { 2821a96d7823Smrg *prev = cur->next; 2822a96d7823Smrg cur->next = conn->clients; 2823a96d7823Smrg conn->clients = cur; 2824a96d7823Smrg } 2825a96d7823Smrg break; 2826a96d7823Smrg } 2827a96d7823Smrg } 2828a96d7823Smrg if (!cur) 2829a96d7823Smrg { 2830a96d7823Smrg cur = malloc (sizeof (FSClientRec)); 2831a96d7823Smrg if (!cur) 2832a96d7823Smrg return; 2833a96d7823Smrg cur->client = client; 2834a96d7823Smrg cur->next = conn->clients; 2835a96d7823Smrg conn->clients = cur; 2836a96d7823Smrg cur->acid = GetNewFontClientID (); 2837a96d7823Smrg new_cur = TRUE; 2838a96d7823Smrg } 2839a96d7823Smrg if (new_cur || cur->auth_generation != client_auth_generation(client)) 2840a96d7823Smrg { 2841a96d7823Smrg if (!new_cur) 2842a96d7823Smrg { 2843a96d7823Smrg fsFreeACReq freeac; 2844a96d7823Smrg freeac.reqType = FS_FreeAC; 2845a96d7823Smrg freeac.pad = 0; 2846a96d7823Smrg freeac.id = cur->acid; 2847a96d7823Smrg freeac.length = sizeof (fsFreeACReq) >> 2; 2848a96d7823Smrg _fs_add_req_log(conn, FS_FreeAC); 2849a96d7823Smrg _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq)); 2850a96d7823Smrg } 2851a96d7823Smrg crac.reqType = FS_CreateAC; 2852a96d7823Smrg crac.num_auths = set_font_authorizations(&authorizations, &authlen, 2853a96d7823Smrg client); 2854a96d7823Smrg /* Work around bug in xfs versions up through modular release 1.0.8 2855a96d7823Smrg which rejects CreateAC packets with num_auths = 0 & authlen < 4 */ 2856a96d7823Smrg if (crac.num_auths == 0) { 2857a96d7823Smrg authorizations = padding; 2858a96d7823Smrg authlen = 4; 2859a96d7823Smrg } 2860a96d7823Smrg crac.length = (sizeof (fsCreateACReq) + authlen) >> 2; 2861a96d7823Smrg crac.acid = cur->acid; 2862a96d7823Smrg _fs_add_req_log(conn, FS_CreateAC); 2863a96d7823Smrg _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq)); 2864fd60135fSmrg _fs_write_pad(conn, authorizations, authlen); 2865a96d7823Smrg /* ignore reply; we don't even care about it */ 2866a96d7823Smrg conn->curacid = 0; 2867a96d7823Smrg cur->auth_generation = client_auth_generation(client); 2868a96d7823Smrg } 2869a96d7823Smrg if (conn->curacid != cur->acid) 2870a96d7823Smrg { 2871a96d7823Smrg setac.reqType = FS_SetAuthorization; 2872a96d7823Smrg setac.pad = 0; 2873a96d7823Smrg setac.length = sizeof (fsSetAuthorizationReq) >> 2; 2874a96d7823Smrg setac.id = cur->acid; 2875a96d7823Smrg _fs_add_req_log(conn, FS_SetAuthorization); 2876a96d7823Smrg _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq)); 2877a96d7823Smrg conn->curacid = cur->acid; 2878a96d7823Smrg } 2879a96d7823Smrg} 2880a96d7823Smrg 2881a96d7823Smrg/* 2882a96d7823Smrg * Poll a pending connect 2883a96d7823Smrg */ 2884a96d7823Smrg 2885a96d7823Smrgstatic int 2886a96d7823Smrg_fs_check_connect (FSFpePtr conn) 2887a96d7823Smrg{ 2888a96d7823Smrg int ret; 2889a96d7823Smrg 2890a96d7823Smrg ret = _fs_poll_connect (conn->trans_conn, 0); 2891a96d7823Smrg switch (ret) { 2892a96d7823Smrg case FSIO_READY: 2893a96d7823Smrg conn->fs_fd = _FontTransGetConnectionNumber (conn->trans_conn); 2894a96d7823Smrg conn_start_listening(conn); 2895a96d7823Smrg break; 2896a96d7823Smrg case FSIO_BLOCK: 2897a96d7823Smrg break; 2898a96d7823Smrg } 2899a96d7823Smrg return ret; 2900a96d7823Smrg} 2901a96d7823Smrg 2902a96d7823Smrg/* 2903a96d7823Smrg * Return an FSIO status while waiting for the completed connection 2904a96d7823Smrg * reply to arrive 2905a96d7823Smrg */ 2906a96d7823Smrg 2907a96d7823Smrgstatic fsConnSetup * 2908a96d7823Smrg_fs_get_conn_setup (FSFpePtr conn, int *error, int *setup_len) 2909a96d7823Smrg{ 2910a96d7823Smrg int ret; 2911a96d7823Smrg char *data; 2912a96d7823Smrg int headlen; 2913a96d7823Smrg int len; 2914a96d7823Smrg fsConnSetup *setup; 2915a96d7823Smrg fsConnSetupAccept *accept; 2916a96d7823Smrg 2917a96d7823Smrg ret = _fs_start_read (conn, SIZEOF (fsConnSetup), &data); 2918a96d7823Smrg if (ret != FSIO_READY) 2919a96d7823Smrg { 2920a96d7823Smrg *error = ret; 2921a96d7823Smrg return 0; 2922a96d7823Smrg } 2923a96d7823Smrg 2924a96d7823Smrg setup = (fsConnSetup *) data; 2925a96d7823Smrg if (setup->major_version > FS_PROTOCOL) 2926a96d7823Smrg { 2927a96d7823Smrg *error = FSIO_ERROR; 2928a96d7823Smrg return 0; 2929a96d7823Smrg } 2930a96d7823Smrg 2931a96d7823Smrg headlen = (SIZEOF (fsConnSetup) + 2932a96d7823Smrg (setup->alternate_len << 2) + 2933a96d7823Smrg (setup->auth_len << 2)); 2934a96d7823Smrg /* On anything but Success, no extra data is sent */ 2935a96d7823Smrg if (setup->status != AuthSuccess) 2936a96d7823Smrg { 2937a96d7823Smrg len = headlen; 2938a96d7823Smrg } 2939a96d7823Smrg else 2940a96d7823Smrg { 2941a96d7823Smrg ret = _fs_start_read (conn, headlen + SIZEOF (fsConnSetupAccept), &data); 2942a96d7823Smrg if (ret != FSIO_READY) 2943a96d7823Smrg { 2944a96d7823Smrg *error = ret; 2945a96d7823Smrg return 0; 2946a96d7823Smrg } 2947a96d7823Smrg setup = (fsConnSetup *) data; 2948a96d7823Smrg accept = (fsConnSetupAccept *) (data + headlen); 2949a96d7823Smrg len = headlen + (accept->length << 2); 2950a96d7823Smrg } 2951a96d7823Smrg ret = _fs_start_read (conn, len, &data); 2952a96d7823Smrg if (ret != FSIO_READY) 2953a96d7823Smrg { 2954a96d7823Smrg *error = ret; 2955a96d7823Smrg return 0; 2956a96d7823Smrg } 2957a96d7823Smrg *setup_len = len; 2958a96d7823Smrg return (fsConnSetup *) data; 2959a96d7823Smrg} 2960a96d7823Smrg 2961a96d7823Smrgstatic int 2962a96d7823Smrg_fs_send_conn_client_prefix (FSFpePtr conn) 2963a96d7823Smrg{ 2964a96d7823Smrg fsConnClientPrefix req; 2965a96d7823Smrg int endian; 2966a96d7823Smrg int ret; 2967a96d7823Smrg 2968a96d7823Smrg /* send setup prefix */ 2969a96d7823Smrg endian = 1; 2970a96d7823Smrg if (*(char *) &endian) 2971a96d7823Smrg req.byteOrder = 'l'; 2972a96d7823Smrg else 2973a96d7823Smrg req.byteOrder = 'B'; 2974a96d7823Smrg 2975a96d7823Smrg req.major_version = FS_PROTOCOL; 2976a96d7823Smrg req.minor_version = FS_PROTOCOL_MINOR; 2977a96d7823Smrg 2978a96d7823Smrg/* XXX add some auth info here */ 2979a96d7823Smrg req.num_auths = 0; 2980a96d7823Smrg req.auth_len = 0; 2981a96d7823Smrg ret = _fs_write (conn, (char *) &req, SIZEOF (fsConnClientPrefix)); 2982a96d7823Smrg if (ret != FSIO_READY) 2983a96d7823Smrg return FSIO_ERROR; 2984a96d7823Smrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 2985a96d7823Smrg return ret; 2986a96d7823Smrg} 2987a96d7823Smrg 2988a96d7823Smrgstatic int 2989a96d7823Smrg_fs_recv_conn_setup (FSFpePtr conn) 2990a96d7823Smrg{ 2991a96d7823Smrg int ret = FSIO_ERROR; 2992a96d7823Smrg fsConnSetup *setup; 2993a96d7823Smrg FSFpeAltPtr alts; 2994a96d7823Smrg unsigned int i, alt_len; 2995a96d7823Smrg int setup_len; 2996a96d7823Smrg char *alt_save, *alt_names; 2997a96d7823Smrg 2998a96d7823Smrg setup = _fs_get_conn_setup (conn, &ret, &setup_len); 2999a96d7823Smrg if (!setup) 3000a96d7823Smrg return ret; 3001a96d7823Smrg conn->current_seq = 0; 3002a96d7823Smrg conn->fsMajorVersion = setup->major_version; 3003a96d7823Smrg /* 3004a96d7823Smrg * Create an alternate list from the initial server, but 3005a96d7823Smrg * don't chain looking for alternates. 3006a96d7823Smrg */ 3007a96d7823Smrg if (conn->alternate == 0) 3008a96d7823Smrg { 3009a96d7823Smrg /* 3010a96d7823Smrg * free any existing alternates list, allowing the list to 3011a96d7823Smrg * be updated 3012a96d7823Smrg */ 3013a96d7823Smrg if (conn->alts) 3014a96d7823Smrg { 3015a96d7823Smrg free (conn->alts); 3016a96d7823Smrg conn->alts = 0; 3017a96d7823Smrg conn->numAlts = 0; 3018a96d7823Smrg } 3019a96d7823Smrg if (setup->num_alternates) 3020a96d7823Smrg { 3021a96d7823Smrg size_t alt_name_len = setup->alternate_len << 2; 3022a96d7823Smrg alts = malloc (setup->num_alternates * sizeof (FSFpeAltRec) + 3023a96d7823Smrg alt_name_len); 3024a96d7823Smrg if (alts) 3025a96d7823Smrg { 3026a96d7823Smrg alt_names = (char *) (setup + 1); 3027a96d7823Smrg alt_save = (char *) (alts + setup->num_alternates); 3028a96d7823Smrg for (i = 0; i < setup->num_alternates; i++) 3029a96d7823Smrg { 3030a96d7823Smrg alts[i].subset = alt_names[0]; 3031a96d7823Smrg alt_len = alt_names[1]; 3032a96d7823Smrg if (alt_len >= alt_name_len) { 3033a96d7823Smrg /* 3034a96d7823Smrg * Length is longer than setup->alternate_len 3035a96d7823Smrg * told us to allocate room for, assume entire 3036a96d7823Smrg * alternate list is corrupted. 3037a96d7823Smrg */ 3038a96d7823Smrg#ifdef DEBUG 3039a96d7823Smrg fprintf (stderr, 3040a96d7823Smrg "invalid alt list (length %lx >= %lx)\n", 3041a96d7823Smrg (long) alt_len, (long) alt_name_len); 3042a96d7823Smrg#endif 3043a96d7823Smrg free(alts); 3044a96d7823Smrg return FSIO_ERROR; 3045a96d7823Smrg } 3046a96d7823Smrg alts[i].name = alt_save; 3047a96d7823Smrg memcpy (alt_save, alt_names + 2, alt_len); 3048a96d7823Smrg alt_save[alt_len] = '\0'; 3049a96d7823Smrg alt_save += alt_len + 1; 3050a96d7823Smrg alt_name_len -= alt_len + 1; 3051a96d7823Smrg alt_names += _fs_pad_length (alt_len + 2); 3052a96d7823Smrg } 3053a96d7823Smrg conn->numAlts = setup->num_alternates; 3054a96d7823Smrg conn->alts = alts; 3055a96d7823Smrg } 3056a96d7823Smrg } 3057a96d7823Smrg } 3058a96d7823Smrg _fs_done_read (conn, setup_len); 3059a96d7823Smrg if (setup->status != AuthSuccess) 3060a96d7823Smrg return FSIO_ERROR; 3061a96d7823Smrg return FSIO_READY; 3062a96d7823Smrg} 3063a96d7823Smrg 3064a96d7823Smrgstatic int 3065a96d7823Smrg_fs_open_server (FSFpePtr conn) 3066a96d7823Smrg{ 3067a96d7823Smrg int ret; 3068a96d7823Smrg char *servername; 3069a96d7823Smrg 3070a96d7823Smrg if (conn->alternate == 0) 3071a96d7823Smrg servername = conn->servername; 3072a96d7823Smrg else 3073a96d7823Smrg servername = conn->alts[conn->alternate-1].name; 3074a96d7823Smrg conn->trans_conn = _fs_connect (servername, &ret); 3075a96d7823Smrg conn->blockedConnectTime = GetTimeInMillis () + FS_RECONNECT_WAIT; 3076a96d7823Smrg return ret; 3077a96d7823Smrg} 3078a96d7823Smrg 3079a96d7823Smrgstatic char * 3080a96d7823Smrg_fs_catalog_name (char *servername) 3081a96d7823Smrg{ 3082a96d7823Smrg char *sp; 3083a96d7823Smrg 3084a96d7823Smrg sp = strchr (servername, '/'); 3085a96d7823Smrg if (!sp) 3086a96d7823Smrg return 0; 3087a96d7823Smrg return strrchr (sp + 1, '/'); 3088a96d7823Smrg} 3089a96d7823Smrg 3090a96d7823Smrgstatic int 3091a96d7823Smrg_fs_send_init_packets (FSFpePtr conn) 3092a96d7823Smrg{ 3093a96d7823Smrg fsSetResolutionReq srreq; 3094a96d7823Smrg fsSetCataloguesReq screq; 3095a96d7823Smrg int num_cats, 3096a96d7823Smrg clen; 3097a96d7823Smrg char *catalogues; 3098a96d7823Smrg char *cat; 3099a96d7823Smrg char len; 3100a96d7823Smrg char *end; 3101a96d7823Smrg int num_res; 3102a96d7823Smrg FontResolutionPtr res; 3103a96d7823Smrg 3104a96d7823Smrg#define CATALOGUE_SEP '+' 3105a96d7823Smrg 3106a96d7823Smrg res = GetClientResolutions(&num_res); 3107a96d7823Smrg if (num_res) 3108a96d7823Smrg { 3109a96d7823Smrg srreq.reqType = FS_SetResolution; 3110a96d7823Smrg srreq.num_resolutions = num_res; 3111a96d7823Smrg srreq.length = (SIZEOF(fsSetResolutionReq) + 3112a96d7823Smrg (num_res * SIZEOF(fsResolution)) + 3) >> 2; 3113a96d7823Smrg 3114a96d7823Smrg _fs_add_req_log(conn, FS_SetResolution); 3115a96d7823Smrg if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != FSIO_READY) 3116a96d7823Smrg return FSIO_ERROR; 3117a96d7823Smrg if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) != FSIO_READY) 3118a96d7823Smrg return FSIO_ERROR; 3119a96d7823Smrg } 3120a96d7823Smrg 3121a96d7823Smrg catalogues = 0; 3122a96d7823Smrg if (conn->alternate != 0) 3123a96d7823Smrg catalogues = _fs_catalog_name (conn->alts[conn->alternate-1].name); 3124a96d7823Smrg if (!catalogues) 3125a96d7823Smrg catalogues = _fs_catalog_name (conn->servername); 3126a96d7823Smrg 3127a96d7823Smrg if (!catalogues) 3128a96d7823Smrg { 3129a96d7823Smrg conn->has_catalogues = FALSE; 3130a96d7823Smrg return FSIO_READY; 3131a96d7823Smrg } 3132a96d7823Smrg conn->has_catalogues = TRUE; 3133a96d7823Smrg 3134a96d7823Smrg /* turn cats into counted list */ 3135a96d7823Smrg catalogues++; 3136a96d7823Smrg 3137a96d7823Smrg cat = catalogues; 3138a96d7823Smrg num_cats = 0; 3139a96d7823Smrg clen = 0; 3140a96d7823Smrg while (*cat) 3141a96d7823Smrg { 3142a96d7823Smrg num_cats++; 3143a96d7823Smrg end = strchr(cat, CATALOGUE_SEP); 3144a96d7823Smrg if (!end) 3145a96d7823Smrg end = cat + strlen (cat); 3146a96d7823Smrg clen += (end - cat) + 1; /* length byte + string */ 3147a96d7823Smrg cat = end; 3148a96d7823Smrg } 3149a96d7823Smrg 3150a96d7823Smrg screq.reqType = FS_SetCatalogues; 3151a96d7823Smrg screq.num_catalogues = num_cats; 3152a96d7823Smrg screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2; 3153a96d7823Smrg 3154a96d7823Smrg _fs_add_req_log(conn, FS_SetCatalogues); 3155a96d7823Smrg if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) != FSIO_READY) 3156a96d7823Smrg return FSIO_ERROR; 3157a96d7823Smrg 3158a96d7823Smrg while (*cat) 3159a96d7823Smrg { 3160a96d7823Smrg num_cats++; 3161a96d7823Smrg end = strchr(cat, CATALOGUE_SEP); 3162a96d7823Smrg if (!end) 3163a96d7823Smrg end = cat + strlen (cat); 3164a96d7823Smrg len = end - cat; 3165a96d7823Smrg if (_fs_write (conn, &len, 1) != FSIO_READY) 3166a96d7823Smrg return FSIO_ERROR; 3167a96d7823Smrg if (_fs_write (conn, cat, (int) len) != FSIO_READY) 3168a96d7823Smrg return FSIO_ERROR; 3169a96d7823Smrg cat = end; 3170a96d7823Smrg } 3171a96d7823Smrg 3172a96d7823Smrg if (_fs_write (conn, "....", _fs_pad_length (clen) - clen) != FSIO_READY) 3173a96d7823Smrg return FSIO_ERROR; 3174a96d7823Smrg 3175a96d7823Smrg return FSIO_READY; 3176a96d7823Smrg} 3177a96d7823Smrg 3178a96d7823Smrgstatic int 3179a96d7823Smrg_fs_send_cat_sync (FSFpePtr conn) 3180a96d7823Smrg{ 3181a96d7823Smrg fsListCataloguesReq lcreq; 3182a96d7823Smrg 3183a96d7823Smrg /* 3184a96d7823Smrg * now sync up with the font server, to see if an error was generated 3185a96d7823Smrg * by a bogus catalogue 3186a96d7823Smrg */ 3187a96d7823Smrg lcreq.reqType = FS_ListCatalogues; 3188a96d7823Smrg lcreq.data = 0; 3189a96d7823Smrg lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2; 3190a96d7823Smrg lcreq.maxNames = 0; 3191a96d7823Smrg lcreq.nbytes = 0; 3192a96d7823Smrg lcreq.pad2 = 0; 3193a96d7823Smrg _fs_add_req_log(conn, FS_SetCatalogues); 3194a96d7823Smrg if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) != FSIO_READY) 3195a96d7823Smrg return FSIO_ERROR; 3196a96d7823Smrg conn->blockedConnectTime = GetTimeInMillis () + FontServerRequestTimeout; 3197a96d7823Smrg return FSIO_READY; 3198a96d7823Smrg} 3199a96d7823Smrg 3200a96d7823Smrgstatic int 3201a96d7823Smrg_fs_recv_cat_sync (FSFpePtr conn) 3202a96d7823Smrg{ 3203a96d7823Smrg fsGenericReply *reply; 3204a96d7823Smrg fsError *error; 3205a96d7823Smrg int err; 3206a96d7823Smrg int ret; 3207a96d7823Smrg 3208a96d7823Smrg reply = fs_get_reply (conn, &err); 3209a96d7823Smrg if (!reply) 3210a96d7823Smrg return err; 3211a96d7823Smrg 3212a96d7823Smrg ret = FSIO_READY; 3213a96d7823Smrg if (reply->type == FS_Error) 3214a96d7823Smrg { 3215a96d7823Smrg error = (fsError *) reply; 3216a96d7823Smrg if (error->major_opcode == FS_SetCatalogues) 3217a96d7823Smrg ret = FSIO_ERROR; 3218a96d7823Smrg } 3219a96d7823Smrg _fs_done_read (conn, reply->length << 2); 3220a96d7823Smrg return ret; 3221a96d7823Smrg} 3222a96d7823Smrg 3223a96d7823Smrgstatic void 3224a96d7823Smrg_fs_close_server (FSFpePtr conn) 3225a96d7823Smrg{ 3226a96d7823Smrg _fs_unmark_block (conn, FS_PENDING_WRITE|FS_BROKEN_WRITE|FS_COMPLETE_REPLY|FS_BROKEN_CONNECTION); 3227a96d7823Smrg if (conn->trans_conn) 3228a96d7823Smrg { 3229a96d7823Smrg _FontTransClose (conn->trans_conn); 3230a96d7823Smrg conn->trans_conn = 0; 3231a96d7823Smrg _fs_io_reinit (conn); 3232a96d7823Smrg } 3233a96d7823Smrg if (conn->fs_fd >= 0) 3234a96d7823Smrg { 3235a96d7823Smrg conn_stop_listening(conn); 3236a96d7823Smrg conn->fs_fd = -1; 3237a96d7823Smrg } 3238a96d7823Smrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 3239a96d7823Smrg} 3240a96d7823Smrg 3241a96d7823Smrgstatic int 3242a96d7823Smrg_fs_do_setup_connection (FSFpePtr conn) 3243a96d7823Smrg{ 3244a96d7823Smrg int ret; 3245a96d7823Smrg 3246a96d7823Smrg do 3247a96d7823Smrg { 3248a96d7823Smrg#ifdef DEBUG 3249a96d7823Smrg fprintf (stderr, "fs_do_setup_connection state %d\n", conn->fs_conn_state); 3250a96d7823Smrg#endif 3251a96d7823Smrg switch (conn->fs_conn_state) { 3252a96d7823Smrg case FS_CONN_UNCONNECTED: 3253a96d7823Smrg ret = _fs_open_server (conn); 3254a96d7823Smrg if (ret == FSIO_BLOCK) 3255a96d7823Smrg conn->fs_conn_state = FS_CONN_CONNECTING; 3256a96d7823Smrg break; 3257a96d7823Smrg case FS_CONN_CONNECTING: 3258a96d7823Smrg ret = _fs_check_connect (conn); 3259a96d7823Smrg break; 3260a96d7823Smrg case FS_CONN_CONNECTED: 3261a96d7823Smrg ret = _fs_send_conn_client_prefix (conn); 3262a96d7823Smrg break; 3263a96d7823Smrg case FS_CONN_SENT_PREFIX: 3264a96d7823Smrg ret = _fs_recv_conn_setup (conn); 3265a96d7823Smrg break; 3266a96d7823Smrg case FS_CONN_RECV_INIT: 3267a96d7823Smrg ret = _fs_send_init_packets (conn); 3268a96d7823Smrg if (conn->has_catalogues) 3269a96d7823Smrg ret = _fs_send_cat_sync (conn); 3270a96d7823Smrg break; 3271a96d7823Smrg case FS_CONN_SENT_CAT: 3272a96d7823Smrg if (conn->has_catalogues) 3273a96d7823Smrg ret = _fs_recv_cat_sync (conn); 3274a96d7823Smrg else 3275a96d7823Smrg ret = FSIO_READY; 3276a96d7823Smrg break; 3277a96d7823Smrg default: 3278a96d7823Smrg ret = FSIO_READY; 3279a96d7823Smrg break; 3280a96d7823Smrg } 3281a96d7823Smrg switch (ret) { 3282a96d7823Smrg case FSIO_READY: 3283a96d7823Smrg if (conn->fs_conn_state < FS_CONN_RUNNING) 3284a96d7823Smrg conn->fs_conn_state++; 3285a96d7823Smrg break; 3286a96d7823Smrg case FSIO_BLOCK: 3287a96d7823Smrg if (TimeCmp (GetTimeInMillis (), <, conn->blockedConnectTime)) 3288a96d7823Smrg break; 3289a96d7823Smrg ret = FSIO_ERROR; 3290a96d7823Smrg /* fall through... */ 3291a96d7823Smrg case FSIO_ERROR: 3292a96d7823Smrg _fs_close_server (conn); 3293a96d7823Smrg /* 3294a96d7823Smrg * Try the next alternate 3295a96d7823Smrg */ 3296a96d7823Smrg if (conn->alternate < conn->numAlts) 3297a96d7823Smrg { 3298a96d7823Smrg conn->alternate++; 3299a96d7823Smrg ret = FSIO_READY; 3300a96d7823Smrg } 3301a96d7823Smrg else 3302a96d7823Smrg conn->alternate = 0; 3303a96d7823Smrg break; 3304a96d7823Smrg } 3305a96d7823Smrg } while (conn->fs_conn_state != FS_CONN_RUNNING && ret == FSIO_READY); 3306a96d7823Smrg if (ret == FSIO_READY) 3307a96d7823Smrg conn->generation = ++generationCount; 3308a96d7823Smrg return ret; 3309a96d7823Smrg} 3310a96d7823Smrg 3311a96d7823Smrgstatic int 3312a96d7823Smrg_fs_wait_connect (FSFpePtr conn) 3313a96d7823Smrg{ 3314a96d7823Smrg int ret; 3315a96d7823Smrg 3316a96d7823Smrg for (;;) 3317a96d7823Smrg { 3318a96d7823Smrg ret = _fs_do_setup_connection (conn); 3319a96d7823Smrg if (ret != FSIO_BLOCK) 3320a96d7823Smrg break; 3321a96d7823Smrg if (conn->fs_conn_state <= FS_CONN_CONNECTING) 3322a96d7823Smrg ret = _fs_poll_connect (conn->trans_conn, 1000); 3323a96d7823Smrg else 3324a96d7823Smrg ret = _fs_wait_for_readable (conn, 1000); 3325a96d7823Smrg if (ret == FSIO_ERROR) 3326a96d7823Smrg break; 3327a96d7823Smrg } 3328a96d7823Smrg return ret; 3329a96d7823Smrg} 3330a96d7823Smrg 3331a96d7823Smrg/* 3332a96d7823Smrg * Poll a connection in the process of reconnecting 3333a96d7823Smrg */ 3334a96d7823Smrgstatic void 3335a96d7823Smrg_fs_check_reconnect (FSFpePtr conn) 3336a96d7823Smrg{ 3337a96d7823Smrg int ret; 3338a96d7823Smrg 3339a96d7823Smrg ret = _fs_do_setup_connection (conn); 3340a96d7823Smrg switch (ret) { 3341a96d7823Smrg case FSIO_READY: 3342a96d7823Smrg _fs_unmark_block (conn, FS_RECONNECTING|FS_GIVE_UP); 3343a96d7823Smrg _fs_restart_connection (conn); 3344a96d7823Smrg break; 3345a96d7823Smrg case FSIO_BLOCK: 3346a96d7823Smrg break; 3347a96d7823Smrg case FSIO_ERROR: 3348a96d7823Smrg conn->brokenConnectionTime = GetTimeInMillis () + FS_RECONNECT_POLL; 3349a96d7823Smrg break; 3350a96d7823Smrg } 3351a96d7823Smrg} 3352a96d7823Smrg 3353a96d7823Smrg/* 3354a96d7823Smrg * Start the reconnection process 3355a96d7823Smrg */ 3356a96d7823Smrgstatic void 3357a96d7823Smrg_fs_start_reconnect (FSFpePtr conn) 3358a96d7823Smrg{ 3359a96d7823Smrg if (conn->blockState & FS_RECONNECTING) 3360a96d7823Smrg return; 3361a96d7823Smrg conn->alternate = 0; 3362a96d7823Smrg _fs_mark_block (conn, FS_RECONNECTING); 3363a96d7823Smrg _fs_unmark_block (conn, FS_BROKEN_CONNECTION); 3364a96d7823Smrg _fs_check_reconnect (conn); 3365a96d7823Smrg} 3366a96d7823Smrg 3367a96d7823Smrg 3368a96d7823Smrgstatic FSFpePtr 3369a96d7823Smrg_fs_init_conn (const char *servername, FontPathElementPtr fpe) 3370a96d7823Smrg{ 3371a96d7823Smrg FSFpePtr conn; 3372c7b4381aSmrg size_t snlen = strlen (servername) + 1; 3373a96d7823Smrg 3374c7b4381aSmrg conn = calloc (1, sizeof (FSFpeRec) + snlen); 3375a96d7823Smrg if (!conn) 3376a96d7823Smrg return 0; 3377a96d7823Smrg if (!_fs_io_init (conn)) 3378a96d7823Smrg { 3379a96d7823Smrg free (conn); 3380a96d7823Smrg return 0; 3381a96d7823Smrg } 3382a96d7823Smrg conn->servername = (char *) (conn + 1); 3383a96d7823Smrg conn->fs_conn_state = FS_CONN_UNCONNECTED; 3384a96d7823Smrg conn->fs_fd = -1; 3385a96d7823Smrg conn->fpe = fpe; 3386c7b4381aSmrg strlcpy (conn->servername, servername, snlen); 3387a96d7823Smrg return conn; 3388a96d7823Smrg} 3389a96d7823Smrg 3390a96d7823Smrgstatic void 3391a96d7823Smrg_fs_free_conn (FSFpePtr conn) 3392a96d7823Smrg{ 3393a96d7823Smrg _fs_close_server (conn); 3394a96d7823Smrg _fs_io_fini (conn); 3395a96d7823Smrg if (conn->alts) 3396a96d7823Smrg free (conn->alts); 3397a96d7823Smrg free (conn); 3398a96d7823Smrg} 3399a96d7823Smrg 3400a96d7823Smrg/* 3401a96d7823Smrg * called at server init time 3402a96d7823Smrg */ 3403a96d7823Smrg 3404a96d7823Smrgstatic const xfont2_fpe_funcs_rec fs_fpe_funcs = { 3405a96d7823Smrg .version = XFONT2_FPE_FUNCS_VERSION, 3406a96d7823Smrg .name_check = fs_name_check, 3407a96d7823Smrg .init_fpe = fs_init_fpe, 3408a96d7823Smrg .free_fpe = fs_free_fpe, 3409a96d7823Smrg .reset_fpe = fs_reset_fpe, 3410a96d7823Smrg .open_font = fs_open_font, 3411a96d7823Smrg .close_font = fs_close_font, 3412a96d7823Smrg .list_fonts = fs_list_fonts, 3413a96d7823Smrg .start_list_fonts_with_info = fs_start_list_with_info, 3414a96d7823Smrg .list_next_font_with_info = fs_next_list_with_info, 3415a96d7823Smrg .wakeup_fpe = fs_wakeup, 3416a96d7823Smrg .client_died = fs_client_died, 3417a96d7823Smrg .load_glyphs = _fs_load_glyphs, 3418a96d7823Smrg .start_list_fonts_and_aliases = (StartLaFunc) 0, 3419a96d7823Smrg .list_next_font_or_alias = (NextLaFunc) 0, 3420a96d7823Smrg .set_path_hook = (SetPathFunc) 0 3421a96d7823Smrg}; 3422a96d7823Smrg 3423a96d7823Smrgvoid 3424a96d7823Smrgfs_register_fpe_functions(void) 3425a96d7823Smrg{ 3426a96d7823Smrg register_fpe_funcs(&fs_fpe_funcs); 3427a96d7823Smrg} 3428