Bug Summary

File:fc/fserve.c
Location:line 1316, column 2
Description:Value stored to 'err' is never read

Annotated Source Code

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