]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fc/fserve.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / lib / font / fc / fserve.c
1 /* $TOG: fserve.c /main/49 1997/06/10 11:23:56 barstow $ */
2 /*
3
4 Copyright (c) 1990  X Consortium
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
26
27 */
28 /* $XFree86: xc/lib/font/fc/fserve.c,v 3.4.2.2 1997/06/11 12:08:41 dawes Exp $ */
29
30 /*
31  * Copyright 1990 Network Computing Devices
32  *
33  * Permission to use, copy, modify, distribute, and sell this software and
34  * its documentation for any purpose is hereby granted without fee, provided
35  * that the above copyright notice appear in all copies and that both that
36  * copyright notice and this permission notice appear in supporting
37  * documentation, and that the names of Network Computing Devices, or Digital
38  * not be used in advertising or publicity pertaining to distribution
39  * of the software without specific, written prior permission.
40  *
41  * NETWORK COMPUTING DEVICES, AND DIGITAL AND DISCLAIM ALL WARRANTIES WITH
42  * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
43  * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NETWORK COMPUTING DEVICES,
44  * OR DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
45  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
46  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
47  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
48  * THIS SOFTWARE.
49  *
50  * Author:      Dave Lemke, Network Computing Devices, Inc
51  */
52 /*
53  * font server specific font access
54  */
55
56 #ifdef WIN32
57 #define _WILLWINSOCK_
58 #endif
59 #include        <X11/X.h>
60 #include        <X11/Xos.h>
61 #include        "X11/Xpoll.h"
62 #include        "FS.h"
63 #include        "FSproto.h"
64 #include        "fontmisc.h"
65 #include        "fontstruct.h"
66 #include        "fservestr.h"
67 #include        <errno.h>
68 #if defined(X_NOT_STDC_ENV) && !defined(__EMX__)
69 extern int errno;
70 #define Time_t long
71 extern Time_t time ();
72 #else
73 #include        <time.h>
74 #define Time_t time_t
75 #endif
76
77 #ifdef NCD
78 #include        <ncd/nvram.h>
79 #endif
80
81 #ifndef NULL
82 #define NULL 0
83 #endif
84
85 #ifndef MIN
86 #define MIN(a,b)    ((a)<(b)?(a):(b))
87 #endif
88
89 #define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \
90                              (pci)->rightSideBearing || \
91                              (pci)->ascent || \
92                              (pci)->descent || \
93                              (pci)->characterWidth)
94
95
96 extern FontPtr find_old_font();
97
98 extern int  _fs_build_range();
99
100 static int  fs_read_glyphs();
101 static int  fs_read_list();
102 static int  fs_read_list_info();
103
104 static int  fs_font_type;
105 extern fd_set _fs_fd_mask;
106
107 static void fs_block_handler();
108 static int  fs_wakeup();
109
110 static FSFpePtr awaiting_reconnect;
111
112 void        _fs_connection_died();
113 static int  _fs_restart_connection();
114 static void _fs_try_reconnect();
115 static int  fs_send_query_info();
116 static int  fs_send_query_extents();
117 static int  fs_send_query_bitmaps();
118 static int  fs_send_close_font();
119 static void fs_client_died();
120 static void _fs_client_access();
121 static void _fs_client_resolution();
122
123 char _fs_glyph_undefined;
124 char _fs_glyph_requested;
125 char _fs_glyph_zero_length;
126
127 /*
128  * Font server access
129  *
130  * the basic idea for the non-blocking access is to have the function
131  * called multiple times until the actual data is returned, instead
132  * of ClientBlocked.
133  *
134  * the first call to the function will cause the request to be sent to
135  * the font server, and a block record to be stored in the fpe's list
136  * of outstanding requests.  the FS block handler also sticks the
137  * proper set of fd's into the select mask.  when data is ready to be
138  * read in, the FS wakup handler will be hit.  this will read the
139  * data off the wire into the proper block record, and then signal the
140  * client that caused the block so that it can restart.  it will then
141  * call the access function again, which will realize that the data has
142  * arrived and return it.
143  */
144
145
146 /* XXX this should probably be a macro once its fully debugged */
147 /* ARGSUSED */
148 static void
149 _fs_add_req_log(conn, opcode)
150     FSFpePtr    conn;
151     int         opcode;
152 {
153
154 #ifdef DEBUG
155     conn->reqbuffer[conn->reqindex++] = opcode;
156     if (conn->reqindex == REQUEST_LOG_SIZE)
157         conn->reqindex = 0;
158 #endif
159
160     conn->current_seq++;
161 }
162
163 static Bool
164 fs_name_check(name)
165     char       *name;
166 {
167 #ifdef __EMX__
168     /* OS/2 uses D:/XFree86/.... as fontfile pathnames, so check that
169      * there is not only a protocol/ prefix, but also that the first chars
170      * are not a drive letter
171      */
172     if (name && isalpha(*name) && name[1] == ':')
173       return FALSE;
174 #endif
175     /* Just make sure there is a protocol/ prefix */
176     return (name && *name != '/' && strchr(name, '/'));
177 }
178
179 static void
180 _fs_client_resolution(conn)
181     FSFpePtr    conn;
182 {
183     fsSetResolutionReq srreq;
184     int         num_res;
185     FontResolutionPtr res;
186
187     res = GetClientResolutions(&num_res);
188
189     if (num_res) {
190         srreq.reqType = FS_SetResolution;
191         srreq.num_resolutions = num_res;
192         srreq.length = (SIZEOF(fsSetResolutionReq) +
193                         (num_res * SIZEOF(fsResolution)) + 3) >> 2;
194
195         _fs_add_req_log(conn, FS_SetResolution);
196         if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) != -1)
197             (void)_fs_write_pad(conn, (char *) res,
198                                 (num_res * SIZEOF(fsResolution)));
199     }
200 }
201
202 /*
203  * sends the stuff that's meaningful to a newly opened or reset FS
204  */
205 static int
206 fs_send_init_packets(conn)
207     FSFpePtr    conn;
208 {
209     fsSetResolutionReq srreq;
210     fsSetCataloguesReq screq;
211     fsListCataloguesReq lcreq;
212     fsListCataloguesReply lcreply;
213     int         num_cats,
214                 clen,
215                 len;
216     char       *client_cat = (char *) 0,
217                *cp,
218                *sp,
219                *end;
220     int         num_res;
221     FontResolutionPtr res;
222     int         err = Successful;
223
224 #define CATALOGUE_SEP   '+'
225
226     res = GetClientResolutions(&num_res);
227     if (num_res) {
228         srreq.reqType = FS_SetResolution;
229         srreq.num_resolutions = num_res;
230         srreq.length = (SIZEOF(fsSetResolutionReq) +
231                         (num_res * SIZEOF(fsResolution)) + 3) >> 2;
232
233         _fs_add_req_log(conn, FS_SetResolution);
234         if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) == -1)
235         {
236             err = BadFontPath;
237             goto fail;
238         }
239         if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) == -1)
240         {
241             err = BadFontPath;
242             goto fail;
243         }
244     }
245     sp = strrchr(conn->servername, '/');
246
247     /* don't get tricked by a non-existant catalogue list */
248     if (sp == strchr(conn->servername, '/')) {
249         /*
250          * try original name -- this might be an alternate with no catalogues
251          */
252         sp = strrchr(conn->requestedname, '/');
253         if (sp == strchr(conn->requestedname, '/'))
254                 sp = (char *) 0;
255     }
256     if (sp) {                   /* turn cats into counted list */
257         sp++;
258         /* allocate more than enough room */
259         cp = client_cat = (char *) xalloc(strlen(conn->servername));
260         if (!cp) {
261             err = BadAlloc;
262             goto fail;
263         }
264         num_cats = 0;
265         while (*sp) {
266             end = strchr(sp, CATALOGUE_SEP);
267             if (!end)
268                 end = sp + strlen(sp);
269             *cp++ = len = end - sp;
270             num_cats++;
271             memmove(cp, sp, len);
272             sp += len;
273             if (*sp == CATALOGUE_SEP)
274                 sp++;
275             cp += len;
276         }
277         clen = cp - client_cat;
278         /* our list checked out, so send it */
279         screq.reqType = FS_SetCatalogues;
280         screq.num_catalogues = num_cats;
281         screq.length = (SIZEOF(fsSetCataloguesReq) + clen + 3) >> 2;
282
283         _fs_add_req_log(conn, FS_SetCatalogues);
284         if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) == -1)
285         {
286             err = BadFontPath;
287             goto fail;
288         }
289         if (_fs_write_pad(conn, (char *) client_cat, clen) == -1)
290         {
291             err = BadFontPath;
292             goto fail;
293         }
294
295         /*
296          * now sync up with the font server, to see if an error was generated
297          * by a bogus catalogue
298          */
299         lcreq.reqType = FS_ListCatalogues;
300         lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2;
301         lcreq.maxNames = 0;
302         lcreq.nbytes = 0;
303         _fs_add_req_log(conn, FS_SetCatalogues);
304         if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) == -1)
305         {
306             err = BadFontPath;
307             goto fail;
308         }
309
310         /*
311          * next bit will either by the ListCats reply, or an error followed by
312          * the reply
313          */
314         if (_fs_read(conn, (char *) &lcreply, SIZEOF(fsGenericReply)) == -1) {
315             err = BadFontPath;
316             goto fail;
317         }
318         if (lcreply.type == FS_Error &&
319                 ((fsError *) & lcreply)->major_opcode == FS_SetCatalogues) {
320             _fs_eat_rest_of_error(conn, (fsError *) & lcreply);
321             /* get ListCats response */
322             (void) _fs_read(conn, (char *) &lcreply,
323                             SIZEOF(fsListCataloguesReply));
324             err = BadFontPath;
325             goto fail;
326         }
327         /* must be reply, swallow the rest of it */
328         _fs_eat_rest_of_error(conn, (fsError *) & lcreply);
329     }
330 fail:
331     xfree(client_cat);
332     return err;
333 }
334
335 /* 
336  * close font server and remove any state associated with
337  * this connection - this includes any client records.
338  */
339
340 static void
341 fs_close_conn(conn)
342     FSFpePtr    conn;
343 {
344     FSClientPtr client, nclient;
345
346     /* XXX - hack.  The right fix is to remember that the font server
347        has gone away when we first discovered it. */
348     if (conn->trans_conn)
349         (void) _FontTransClose (conn->trans_conn);
350
351     if (conn->fs_fd != -1)
352       FD_CLR(conn->fs_fd, &_fs_fd_mask);
353
354     for (client = conn->clients; client; client = nclient) 
355     {
356         nclient = client->next;
357         xfree (client);
358     }
359     conn->clients = NULL;
360 }
361
362 /*
363  * the wakeup handlers have to be set when the FPE is open, and not
364  * removed until it is freed, in order to handle unexpected data, like
365  * events
366  */
367 /* ARGSUSED */
368 static int
369 fs_init_fpe(fpe)
370     FontPathElementPtr fpe;
371 {
372     FSFpePtr    conn;
373     char       *name;
374     int         err;
375
376     /* open font server */
377     /* create FS specific fpe info */
378     errno = 0;
379
380     name = fpe->name;
381
382     /* hack for old style names */
383     if (*name == ':')
384         name++;                 /* skip ':' */
385
386     conn = _fs_open_server(name);
387     if (conn) {
388         conn->requestedname = fpe->name; /* stash this for later init use */
389         fpe->private = (pointer) conn;
390         err = fs_send_init_packets(conn);
391         if (err != Successful) {
392             fs_close_conn(conn);
393             xfree(conn->servername);
394             xfree(conn->alts);
395             xfree(conn);
396             return err;
397         }
398         if (init_fs_handlers(fpe, fs_block_handler) != Successful)
399             return AllocError;
400         FD_SET(conn->fs_fd, &_fs_fd_mask);
401         conn->attemptReconnect = TRUE;
402
403 #ifdef NCD
404         if (configData.ExtendedFontDiags)
405             printf("Connected to font server \"%s\"\n", name);
406 #endif
407
408         return err;
409     }
410
411 #ifdef DEBUG
412     fprintf(stderr, "failed to connect to FS \"%s\"\n", name);
413 #endif
414
415 #ifdef NCD
416     if (configData.ExtendedFontDiags)
417         printf("Failed to connect to font server \"%s\"\n", name);
418 #endif
419
420     return (errno == ENOMEM) ? AllocError : BadFontPath;
421 }
422
423 static int
424 fs_reset_fpe(fpe)
425     FontPathElementPtr fpe;
426 {
427     (void) fs_send_init_packets((FSFpePtr) fpe->private);
428     return Successful;
429 }
430
431 /*
432  * this shouldn't be called till all refs to the FPE are gone
433  */
434
435 static int
436 fs_free_fpe(fpe)
437     FontPathElementPtr fpe;
438 {
439     FSFpePtr    conn = (FSFpePtr) fpe->private;
440     FSFpePtr    recon,
441                *prev;
442     prev = &awaiting_reconnect;
443     while (*prev) {
444         recon = *prev;
445         if (conn == recon) {
446             *prev = recon->next_reconnect;
447             break;
448         }
449         prev = &recon->next_reconnect;
450     }
451
452     fs_close_conn(conn);
453
454     remove_fs_handlers(fpe, fs_block_handler,
455                        !XFD_ANYSET(&_fs_fd_mask) && !awaiting_reconnect);
456
457     xfree(conn->alts);
458     xfree(conn->servername);
459     xfree(conn);
460     fpe->private = (pointer) 0;
461
462 #ifdef NCD
463     if (configData.ExtendedFontDiags)
464         printf("Disconnected from font server \"%s\"\n", fpe->name);
465 #endif
466
467     return Successful;
468 }
469
470 static      FSBlockDataPtr
471 fs_new_block_rec(fpe, client, type)
472     FontPathElementPtr fpe;
473     pointer     client;
474     int         type;
475 {
476     FSBlockDataPtr blockrec,
477                 br;
478     FSFpePtr    fsfpe = (FSFpePtr) fpe->private;
479     int         size;
480
481     blockrec = (FSBlockDataPtr) xalloc(sizeof(FSBlockDataRec));
482     if (!blockrec)
483         return (FSBlockDataPtr) 0;
484     switch (type) {
485     case FS_OPEN_FONT:
486         size = sizeof(FSBlockedFontRec);
487         break;
488     case FS_LOAD_GLYPHS:
489         size = sizeof(FSBlockedGlyphRec);
490         break;
491     case FS_LIST_FONTS:
492         size = sizeof(FSBlockedListRec);
493         break;
494     case FS_LIST_WITH_INFO:
495         size = sizeof(FSBlockedListInfoRec);
496         break;
497     default:
498         break;
499     }
500     blockrec->data = (pointer) xalloc(size);
501     if (!blockrec->data) {
502         xfree(blockrec);
503         return (FSBlockDataPtr) 0;
504     }
505     blockrec->client = client;
506     blockrec->sequence_number = fsfpe->current_seq;
507     blockrec->type = type;
508     blockrec->depending = 0;
509     blockrec->next = (FSBlockDataPtr) 0;
510
511     /* stick it on the end of the list (since its expected last) */
512     br = (FSBlockDataPtr) fsfpe->blocked_requests;
513     if (!br) {
514         fsfpe->blocked_requests = (pointer) blockrec;
515     } else {
516         while (br->next)
517             br = br->next;
518         br->next = blockrec;
519     }
520
521     return blockrec;
522 }
523
524 static void
525 _fs_remove_block_rec(conn, blockrec)
526     FSFpePtr    conn;
527     FSBlockDataPtr blockrec;
528 {
529     FSBlockDataPtr br,
530                 last;
531
532     last = (FSBlockDataPtr) 0;
533     br = (FSBlockDataPtr) conn->blocked_requests;
534     while (br) {
535         if (br == blockrec) {
536             if (last)
537                 last->next = br->next;
538             else
539                 conn->blocked_requests = (pointer) br->next;
540             if (br->type == FS_LOAD_GLYPHS)
541             {
542                 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)br->data;
543                 if (bglyph->num_expected_ranges)
544                     xfree(bglyph->expected_ranges);
545             }
546             xfree(br->data);
547             xfree(br);
548             return;
549         }
550         last = br;
551         br = br->next;
552     }
553 }
554
555 static void
556 signal_clients_depending(clients_depending)
557 FSClientsDependingPtr *clients_depending;
558 {
559     FSClientsDependingPtr p = *clients_depending, p2;
560     *clients_depending = (FSClientsDependingPtr)0;
561
562     while (p != (FSClientsDependingPtr)0)
563     {
564         p2 = p;
565         ClientSignal(p->client);
566         p = p->next;
567         xfree(p2);
568     }
569 }
570
571 static int
572 add_clients_depending(clients_depending, client)
573 FSClientsDependingPtr *clients_depending;
574 pointer client;
575 {
576     while (*clients_depending != (FSClientsDependingPtr)0)
577     {
578         if ((*clients_depending)->client == client) return Suspended;
579         clients_depending = &(*clients_depending)->next;
580     }
581     *clients_depending = (FSClientsDependingPtr)xalloc(
582                              sizeof(FSClientsDependingRec));
583     if (!*clients_depending)
584         return BadAlloc;
585
586     (*clients_depending)->client = client;
587     (*clients_depending)->next = 0;
588     return Suspended;
589 }
590
591 static void
592 clean_aborted_blockrec(blockrec)
593     FSBlockDataPtr blockrec;
594 {
595
596     switch(blockrec->type)
597     {
598         case FS_LOAD_GLYPHS:
599         {
600             FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)blockrec->data;
601             FontPtr pfont = bglyph->pfont;
602             int num_expected_ranges = bglyph->num_expected_ranges;
603             fsRange *expected_ranges = bglyph->expected_ranges;
604             _fs_clean_aborted_loadglyphs(pfont,
605                                      num_expected_ranges,
606                                      expected_ranges);
607             signal_clients_depending(&bglyph->clients_depending);
608             break;
609         }
610         case FS_OPEN_FONT:
611         {
612             FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
613             signal_clients_depending(&bfont->clients_depending);
614             break;
615         }
616         default:
617             break;
618     }
619 }
620
621 static void
622 fs_abort_blockrec(conn, blockrec)
623     FSFpePtr    conn;
624     FSBlockDataPtr blockrec;
625 {
626     clean_aborted_blockrec(blockrec);
627     _fs_remove_block_rec(conn, blockrec);
628 }
629
630
631 static void
632 fs_free_font(bfont)
633     FSBlockedFontPtr bfont;
634 {
635     FontPtr     pfont;
636     FSFontDataRec *fsd;
637
638     pfont = bfont->pfont;
639     fsd = (FSFontDataRec *) pfont->fpePrivate;
640
641     /* xfree better be able to handle NULL */
642     (*pfont->unload_font)(pfont);
643     DeleteFontClientID(fsd->fontid);
644     xfree(fsd->name);
645     xfree(pfont->info.isStringProp);
646     xfree(pfont->info.props);
647
648     xfree(pfont);
649     xfree(fsd);
650
651     bfont->pfont = (FontPtr) 0;
652 }
653
654 static void
655 _fs_cleanup_font(bfont)
656     FSBlockedFontPtr bfont;
657 {
658     FSFontDataRec *fsd;
659
660     if (bfont->pfont)
661     {
662         fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
663     
664         /* make sure the FS knows we choked on it */
665         fs_send_close_font(fsd->fpe, bfont->fontid);
666     
667         fs_free_font(bfont);
668     }
669     bfont->errcode = AllocError;
670 }
671
672
673 static int
674 fs_read_open_font(fpe, blockrec)
675     FontPathElementPtr fpe;
676     FSBlockDataPtr blockrec;
677 {
678     FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
679     FSFpePtr    conn = (FSFpePtr) fpe->private;
680     fsOpenBitmapFontReply rep;
681     FSBlockDataPtr blockOrig;
682     FSBlockedFontPtr origBfont;
683
684     /* pull out the OpenFont reply */
685     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
686
687     if (rep.type == FS_Error) {
688         _fs_eat_rest_of_error(conn, (fsError *) & rep);
689         return BadFontName;
690     } else {                    /* get rest of reply */
691         if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
692               SIZEOF(fsOpenBitmapFontReply) - SIZEOF(fsGenericReply)) == -1) {
693             /* If we're not reopening a font, we'll allocate the
694                structures again after connection is reestablished.  */
695             if (!(bfont->flags & FontReopen)) fs_free_font(bfont);
696             return StillWorking;
697         }
698     }
699
700     /* If we're not reopening a font and FS detected a duplicate font
701        open request, replace our reference to the new font with a
702        reference to an existing font (possibly one not finished
703        opening).  If this is a reopen, keep the new font reference...
704        it's got the metrics and extents we read when the font was opened
705        before.  This also gives us the freedom to easily close the font
706        if we we decide (in fs_read_query_info()) that we don't like what
707        we got. */
708
709     if (rep.otherid && !(bfont->flags & FontReopen)) {
710         (void) fs_send_close_font(fpe, bfont->fontid);
711
712         /* Find old font if we're completely done getting it from server. */
713         fs_free_font(bfont);
714         bfont->pfont = find_old_font(rep.otherid);
715         bfont->fontid = rep.otherid;
716         bfont->state = FS_DONE_REPLY;
717         /*
718          * look for a blocked request to open the same font
719          */
720         for (blockOrig = (FSBlockDataPtr) conn->blocked_requests;
721                 blockOrig;
722                 blockOrig = blockOrig->next) {
723             if (blockOrig != blockrec && blockOrig->type == FS_OPEN_FONT) {
724                 origBfont = (FSBlockedFontPtr) blockOrig->data;
725                 if (origBfont->fontid == rep.otherid) {
726                     blockrec->depending = blockOrig->depending;
727                     blockOrig->depending = blockrec;
728                     bfont->state = FS_DEPENDING;
729                     bfont->pfont = origBfont->pfont;
730                     break;
731                 }
732             }
733         }
734         if (bfont->pfont == NULL)
735         {
736             /* XXX - something nasty happened */
737             return BadFontName;
738         }
739         return AccessDone;
740     }
741
742     bfont->pfont->info.cachable = rep.cachable != 0;
743     bfont->state = FS_INFO_REPLY;
744     /* ask for the next stage */
745     (void) fs_send_query_info(fpe, blockrec);
746     return StillWorking;
747 }
748
749
750 static int
751 fs_read_query_info(fpe, blockrec)
752     FontPathElementPtr fpe;
753     FSBlockDataPtr blockrec;
754 {
755     FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
756     FSFpePtr    conn = (FSFpePtr) fpe->private;
757     fsQueryXInfoReply rep;
758     fsPropInfo  pi;
759     fsPropOffset *po;
760     pointer     pd;
761     unsigned long prop_len;
762     FSBlockedFontRec newbfont, *oldbfont;
763     FontRec newpfont, *oldpfont;
764     int err;
765
766     /* If this is a reopen, accumulate the query info into a dummy
767        font and compare to our original data. */
768     if (bfont->flags & FontReopen)
769     {
770         newbfont = *(oldbfont = bfont);
771         bfont = &newbfont;
772         newpfont = *(oldpfont = oldbfont->pfont);
773         newpfont.info.isStringProp = NULL;
774         newpfont.info.props = NULL;
775         newbfont.pfont = &newpfont;
776         err = StillWorking;
777     }
778
779     /* pull out the QueryXInfo reply */
780     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
781     if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
782                  SIZEOF(fsQueryXInfoReply) - SIZEOF(fsGenericReply)) == -1) {
783         if (bfont->flags & FontReopen) goto bail;
784         fs_free_font(bfont);
785         return StillWorking;
786     }
787     /* move the data over */
788     fsUnpack_XFontInfoHeader(&rep, &bfont->pfont->info);
789     _fs_init_fontinfo(conn, &bfont->pfont->info);
790
791     if (bfont->pfont->info.terminalFont)
792     {
793         bfont->format =
794             (bfont->format & ~ (BitmapFormatImageRectMask)) |
795             BitmapFormatImageRectMax;
796     }
797
798     if (_fs_read(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1) {
799         if (bfont->flags & FontReopen) goto bail;
800         fs_free_font(bfont);
801         return StillWorking;
802     }
803     prop_len = pi.num_offsets * SIZEOF(fsPropOffset);
804     po = (fsPropOffset *) xalloc(prop_len);
805     pd = (pointer) xalloc(pi.data_len);
806     if (!po || !pd) {
807         xfree(pd);
808         xfree(po);
809         /* clear the wire */
810         (void) _fs_drain_bytes(conn, prop_len + pi.data_len);
811         /* clean up the font */
812         if (bfont->flags & FontReopen) { err = AllocError ; goto bail; }
813         (void) _fs_cleanup_font(bfont);
814         return AllocError;
815     }
816     if (_fs_read_pad(conn, (char *) po, prop_len) == -1 ||
817             _fs_read_pad(conn, (char *) pd, pi.data_len) == -1) {
818         xfree(pd);
819         xfree(po);
820         if (bfont->flags & FontReopen) goto bail;
821         fs_free_font(bfont);
822         return StillWorking;
823     }
824     if (_fs_convert_props(&pi, po, pd, &bfont->pfont->info) == -1)
825     {
826         xfree(po);
827         xfree(pd);
828         if (bfont->flags & FontReopen) { err = AllocError ; goto bail; }
829         (void) _fs_cleanup_font(bfont);
830         return AllocError;
831     }
832     xfree(po);
833     xfree(pd);
834
835     if (bfont->flags & FontReopen)
836     {
837         int i;
838
839         err = BadFontName;
840
841         /* We're reopening a font that we lost because of a downed
842            connection.  In the interest of avoiding corruption from
843            opening a different font than the old one (we already have
844            its metrics, extents, and probably some of its glyphs),
845            verify that the metrics and properties all match.  */
846
847         if (newpfont.info.firstCol != oldpfont->info.firstCol ||
848             newpfont.info.lastCol != oldpfont->info.lastCol ||
849             newpfont.info.firstRow != oldpfont->info.firstRow ||
850             newpfont.info.lastRow != oldpfont->info.lastRow ||
851             newpfont.info.defaultCh != oldpfont->info.defaultCh ||
852             newpfont.info.noOverlap != oldpfont->info.noOverlap ||
853             newpfont.info.terminalFont != oldpfont->info.terminalFont ||
854             newpfont.info.constantMetrics != oldpfont->info.constantMetrics ||
855             newpfont.info.constantWidth != oldpfont->info.constantWidth ||
856             newpfont.info.inkInside != oldpfont->info.inkInside ||
857             newpfont.info.inkMetrics != oldpfont->info.inkMetrics ||
858             newpfont.info.allExist != oldpfont->info.allExist ||
859             newpfont.info.drawDirection != oldpfont->info.drawDirection ||
860             newpfont.info.cachable != oldpfont->info.cachable ||
861             newpfont.info.anamorphic != oldpfont->info.anamorphic ||
862             newpfont.info.maxOverlap != oldpfont->info.maxOverlap ||
863             newpfont.info.fontAscent != oldpfont->info.fontAscent ||
864             newpfont.info.fontDescent != oldpfont->info.fontDescent ||
865             newpfont.info.nprops != oldpfont->info.nprops)
866             goto bail;
867
868 #define MATCH(xci1, xci2) \
869         (((xci1).leftSideBearing == (xci2).leftSideBearing) && \
870          ((xci1).rightSideBearing == (xci2).rightSideBearing) && \
871          ((xci1).characterWidth == (xci2).characterWidth) && \
872          ((xci1).ascent == (xci2).ascent) && \
873          ((xci1).descent == (xci2).descent) && \
874          ((xci1).attributes == (xci2).attributes))
875
876         if (!MATCH(newpfont.info.maxbounds, oldpfont->info.maxbounds) ||
877             !MATCH(newpfont.info.minbounds, oldpfont->info.minbounds) ||
878             !MATCH(newpfont.info.ink_maxbounds, oldpfont->info.ink_maxbounds) ||
879             !MATCH(newpfont.info.ink_minbounds, oldpfont->info.ink_minbounds))
880             goto bail;
881
882 #undef MATCH
883
884         for (i = 0; i < newpfont.info.nprops; i++)
885             if (newpfont.info.isStringProp[i] !=
886                     oldpfont->info.isStringProp[i] ||
887                 newpfont.info.props[i].name !=
888                     oldpfont->info.props[i].name ||
889                 newpfont.info.props[i].value !=
890                     oldpfont->info.props[i].value)
891                 goto bail;
892
893         err = Successful;
894     bail:
895         if (err != Successful && err != StillWorking)
896         {
897             /* Failure.  Close the font. */
898             fs_send_close_font(((FSFontDataPtr)oldpfont->fpePrivate)->fpe,
899                                bfont->fontid);
900             ((FSFontDataPtr)oldpfont->fpePrivate)->generation  = -1;
901         }
902         xfree(newpfont.info.isStringProp);
903         xfree(newpfont.info.props);
904
905         if (err == Successful) oldbfont->state = FS_DONE_REPLY;
906         return err;
907     }
908
909     if (glyphCachingMode == CACHING_OFF ||
910         glyphCachingMode == CACHE_16_BIT_GLYPHS && !bfont->pfont->info.lastRow)
911         bfont->flags |= FontLoadAll;
912
913     bfont->state = FS_EXTENT_REPLY;
914
915     fs_send_query_extents(fpe, blockrec);
916     return StillWorking;
917 }
918
919 static int
920 fs_read_extent_info(fpe, blockrec)
921     FontPathElementPtr fpe;
922     FSBlockDataPtr blockrec;
923 {
924     FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
925     FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate;
926     FSFpePtr    conn = (FSFpePtr) fpe->private;
927     fsQueryXExtents16Reply rep;
928     int         i;
929     int         numInfos;
930     Bool        haveInk = FALSE; /* need separate ink metrics? */
931     CharInfoPtr ci,
932                 pCI;
933     FSFontPtr   fsfont = (FSFontPtr) bfont->pfont->fontPrivate;
934     fsXCharInfo *fsci;
935     fsXCharInfo fscilocal;
936     pointer fscip;
937
938     /* read the QueryXExtents reply */
939     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
940     if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
941               SIZEOF(fsQueryXExtents16Reply) - SIZEOF(fsGenericReply)) == -1) {
942         fs_free_font(bfont);
943         return StillWorking;
944     }
945     /* move the data over */
946     /* need separate inkMetrics for fixed font server protocol version */
947     numInfos =  rep.num_extents;
948     if (bfont->pfont->info.terminalFont && conn->fsMajorVersion > 1)
949     {
950         numInfos *= 2;
951         haveInk = TRUE;
952     }
953     ci = pCI = (CharInfoPtr) xalloc(sizeof(CharInfoRec) * numInfos);
954 /* XXX this could be done with an ALLOCATE_LOCAL */
955     fsci = (fsXCharInfo *) xalloc(SIZEOF(fsXCharInfo) * rep.num_extents);
956     if (!pCI || !fsci) {
957         xfree(pCI);
958         xfree(fsci);
959         /* clear the unusable data */
960         _fs_drain_bytes(conn, SIZEOF(fsXCharInfo) * rep.num_extents);
961         _fs_cleanup_font(bfont);
962         return AllocError;
963     }
964     fsfont->encoding = pCI;
965     if (haveInk)
966         fsfont->inkMetrics = pCI + rep.num_extents;
967     else
968         fsfont->inkMetrics = pCI;
969
970     if (_fs_read_pad(conn, (char *) fsci,
971                      SIZEOF(fsXCharInfo) * rep.num_extents) == -1) {
972         fs_free_font(bfont);
973         xfree(fsci);
974         return StillWorking;
975     }
976     fsd->glyphs_to_get = 0;
977     fscip = (pointer) fsci;
978     ci = fsfont->inkMetrics;
979     for (i = 0; i < rep.num_extents; i++) {
980         memcpy(&fscilocal, fscip, SIZEOF(fsXCharInfo)); /* align it */
981         _fs_convert_char_info(&fscilocal, &ci->metrics);
982         fscip += SIZEOF(fsXCharInfo);
983         /* Initialize the bits field for later glyph-caching use */
984         if (NONZEROMETRICS(&ci->metrics))
985         {
986             if (!haveInk &&
987                 (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing ||
988                  ci->metrics.ascent == -ci->metrics.descent))
989                 pCI[i].bits = &_fs_glyph_zero_length;
990             else
991             {
992                 pCI[i].bits = &_fs_glyph_undefined;
993                 fsd->glyphs_to_get++;
994             }
995         }
996         else
997             pCI[i].bits = (char *)0;
998         ci++;
999     }
1000
1001     xfree(fsci);
1002
1003     /* build bitmap metrics, ImageRectMax style */
1004     if (haveInk)
1005     {
1006         FontInfoRec *fi = &bfont->pfont->info;
1007         CharInfoPtr ii;
1008
1009         ci = fsfont->encoding;
1010         ii = fsfont->inkMetrics;
1011         for (i = 0; i < rep.num_extents; i++, ci++, ii++)
1012         {
1013             if (NONZEROMETRICS(&ii->metrics))
1014             {
1015                 ci->metrics.leftSideBearing = FONT_MIN_LEFT(fi);
1016                 ci->metrics.rightSideBearing = FONT_MAX_RIGHT(fi);
1017                 ci->metrics.ascent = FONT_MAX_ASCENT(fi);
1018                 ci->metrics.descent = FONT_MAX_DESCENT(fi);
1019                 ci->metrics.characterWidth = FONT_MAX_WIDTH(fi);
1020                 ci->metrics.attributes = ii->metrics.attributes;
1021             }
1022             else
1023             {
1024                 ci->metrics = ii->metrics;
1025             }
1026         }
1027     }
1028     {
1029         unsigned int r, c, numCols, firstCol;
1030
1031         firstCol = bfont->pfont->info.firstCol;
1032         numCols = bfont->pfont->info.lastCol - firstCol + 1;
1033         c = bfont->pfont->info.defaultCh;
1034         fsfont->pDefault = 0;
1035         if (bfont->pfont->info.lastRow)
1036         {
1037             r = c >> 8;
1038             r -= bfont->pfont->info.firstRow;
1039             c &= 0xff;
1040             c -= firstCol;
1041             if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 &&
1042                 c < numCols)
1043                 fsfont->pDefault = &pCI[r * numCols + c];
1044         }
1045         else
1046         {
1047             c -= firstCol;
1048             if (c < numCols)
1049                 fsfont->pDefault = &pCI[c];
1050         }
1051     }
1052     bfont->state = FS_GLYPHS_REPLY;
1053
1054     if (bfont->flags & FontLoadBitmaps) {
1055         fs_send_query_bitmaps(fpe, blockrec);
1056         return StillWorking;
1057     }
1058     return Successful;
1059 }
1060
1061 /*
1062  * XXX should probably continue to read here if we can, but must be sure
1063  * it's our packet waiting, rather than another interspersed
1064  */
1065 static int
1066 fs_do_open_font(fpe, blockrec, readheader)
1067     FontPathElementPtr fpe;
1068     FSBlockDataPtr blockrec;
1069     Bool        readheader;
1070 {
1071     FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1072     FSFpePtr    conn = (FSFpePtr) fpe->private;
1073     int         err;
1074
1075     switch (bfont->state) {
1076     case FS_OPEN_REPLY:
1077         if (readheader) {
1078             /* get the next header */
1079             if (_fs_read(conn, (char *) &blockrec->header,
1080                          SIZEOF(fsGenericReply)) == -1) {
1081                 fs_free_font(bfont);
1082                 err = StillWorking;
1083                 break;
1084             }
1085         }
1086         bfont->errcode = fs_read_open_font(fpe, blockrec);
1087         if (bfont->errcode != StillWorking) {   /* already loaded, or error */
1088             /* if font's already loaded, massage error code */
1089             switch (bfont->state) {
1090             case FS_DONE_REPLY:
1091                 bfont->errcode = Successful;
1092                 break;
1093             case FS_DEPENDING:
1094                 bfont->errcode = StillWorking;
1095                 break;
1096             }
1097             err = bfont->errcode;
1098             break;
1099         }
1100         /* if more data to read or Sync, fall thru, else return */
1101         if (!(bfont->flags & FontOpenSync)) {
1102             err = bfont->errcode;
1103             break;
1104         } else {
1105             if (_fs_read(conn, (char *) &blockrec->header,
1106                          SIZEOF(fsGenericReply)) == -1) {
1107                 fs_free_font(bfont);
1108                 err = StillWorking;
1109                 break;
1110             }
1111         }
1112         /* fall through */
1113     case FS_INFO_REPLY:
1114         bfont->errcode = fs_read_query_info(fpe, blockrec);
1115         if (bfont->errcode != StillWorking) {
1116             err = bfont->errcode;
1117             break;
1118         }
1119         if (!(bfont->flags & FontOpenSync)) {
1120             err = bfont->errcode;
1121             break;
1122             /* if more data to read, fall thru, else return */
1123         } else {
1124             if (_fs_read(conn, (char *) &blockrec->header,
1125                          SIZEOF(fsGenericReply))) {
1126                 fs_free_font(bfont);
1127                 err = StillWorking;
1128                 break;
1129             }
1130         }
1131         /* fall through */
1132     case FS_EXTENT_REPLY:
1133         bfont->errcode = fs_read_extent_info(fpe, blockrec);
1134         if (bfont->errcode != StillWorking) {
1135             err = bfont->errcode;
1136             break;
1137         }
1138         if (!(bfont->flags & FontOpenSync)) {
1139             err = bfont->errcode;
1140             break;
1141         } else if (bfont->flags & FontLoadBitmaps) {
1142             if (_fs_read(conn, (char *) &blockrec->header,
1143                          SIZEOF(fsGenericReply))) {
1144                 fs_free_font(bfont);
1145                 err = StillWorking;
1146                 break;
1147             }
1148         }
1149         /* fall through */
1150     case FS_GLYPHS_REPLY:
1151         if (bfont->flags & FontLoadBitmaps) {
1152             bfont->errcode = fs_read_glyphs(fpe, blockrec);
1153         }
1154         err = bfont->errcode;
1155         break;
1156     case FS_DEPENDING:          /* can't happen */
1157         err = bfont->errcode;
1158     default:
1159         err = bfont->errcode;
1160         break;
1161     }
1162     if (err != StillWorking) {
1163         bfont->state = FS_DONE_REPLY;   /* for _fs_load_glyphs() */
1164         while (blockrec = blockrec->depending) {
1165             bfont = (FSBlockedFontPtr) blockrec->data;
1166             bfont->errcode = err;
1167             bfont->state = FS_DONE_REPLY;       /* for _fs_load_glyphs() */
1168         }
1169     }
1170     return err;
1171 }
1172
1173 /* ARGSUSED */
1174 static void
1175 fs_block_handler(data, wt, LastSelectMask)
1176     pointer     data;
1177     struct timeval **wt;
1178     fd_set*      LastSelectMask;
1179 {
1180     static struct timeval recon_timeout;
1181     Time_t      now,
1182                 soonest;
1183     FSFpePtr    recon;
1184
1185     XFD_ORSET(LastSelectMask, LastSelectMask, &_fs_fd_mask);
1186     if (recon = awaiting_reconnect) {
1187         now = time((Time_t *) 0);
1188         soonest = recon->time_to_try;
1189         while (recon = recon->next_reconnect) {
1190             if (recon->time_to_try < soonest)
1191                 soonest = recon->time_to_try;
1192         }
1193         if (soonest < now)
1194             soonest = now;
1195         soonest = soonest - now;
1196         recon_timeout.tv_sec = soonest;
1197         recon_timeout.tv_usec = 0;
1198         if (*wt == (struct timeval *) 0) {
1199             *wt = &recon_timeout;
1200         } else if ((*wt)->tv_sec > soonest) {
1201             **wt = recon_timeout;
1202         }
1203     }
1204 }
1205
1206 static void
1207 fs_handle_unexpected(conn, rep)
1208     FSFpePtr    conn;
1209     fsGenericReply *rep;
1210 {
1211     if (rep->type == FS_Event && rep->data1 == KeepAlive) {
1212         fsNoopReq   req;
1213
1214         /* ping it back */
1215         req.reqType = FS_Noop;
1216         req.length = SIZEOF(fsNoopReq) >> 2;
1217         _fs_add_req_log(conn, FS_Noop);
1218         _fs_write(conn, (char *) &req, SIZEOF(fsNoopReq));
1219     }
1220     /* this should suck up unexpected replies and events */
1221     _fs_eat_rest_of_error(conn, (fsError *) rep);
1222 }
1223
1224 static int
1225 fs_wakeup(fpe, LastSelectMask)
1226     FontPathElementPtr fpe;
1227     fd_set* LastSelectMask;
1228 {
1229     FSBlockDataPtr blockrec,
1230                 br;
1231     FSFpePtr    conn = (FSFpePtr) fpe->private;
1232     int         err;
1233     fsGenericReply rep;
1234
1235     if (awaiting_reconnect) {
1236         _fs_try_reconnect();
1237     }
1238     /* see if there's any data to be read */
1239
1240     /* 
1241      * Don't continue if the fd is -1 (which will be true when the
1242      * font server terminates
1243      */
1244     if (conn->fs_fd == -1)
1245         return FALSE;
1246
1247     if (FD_ISSET(conn->fs_fd, LastSelectMask)) {
1248
1249 #if defined(NOTDEF) || defined(__EMX__)         /* bogus - doesn't deal with EOF very well,
1250                                  * now does it ... */
1251         /*
1252          * make sure it isn't spurious - mouse events seem to trigger extra
1253          * problems. Under OS/2, this is especially true ...
1254          */
1255         if (_fs_data_ready(conn) <= 0) {
1256             return FALSE;
1257         }
1258 #endif
1259
1260         /* get the header */
1261         if (_fs_read(conn, (char *) &rep, SIZEOF(fsGenericReply)) == -1)
1262             return FALSE;
1263
1264         /* find the matching block record */
1265
1266         for (br = (FSBlockDataPtr) conn->blocked_requests; br; br = br->next) {
1267             if ((CARD16)(br->sequence_number & 0xffff) ==
1268                 (CARD16)(rep.sequenceNumber - 1))
1269                 break;
1270         }
1271         if (!br) {
1272             fs_handle_unexpected(conn, &rep);
1273             return FALSE;
1274         }
1275         blockrec = br;
1276
1277         memcpy(&blockrec->header, &rep, SIZEOF(fsGenericReply));
1278
1279         /* go read it, and if we're done, wake up the appropriate client */
1280         switch (blockrec->type) {
1281         case FS_OPEN_FONT:
1282             err = fs_do_open_font(fpe, blockrec, FALSE);
1283             break;
1284         case FS_LOAD_GLYPHS:
1285             err = fs_read_glyphs(fpe, blockrec);
1286             break;
1287         case FS_LIST_FONTS:
1288             err = fs_read_list(fpe, blockrec);
1289             break;
1290         case FS_LIST_WITH_INFO:
1291             err = fs_read_list_info(fpe, blockrec);
1292             break;
1293         default:
1294             break;
1295         }
1296
1297         if (err != StillWorking) {
1298             while (blockrec) {
1299                 ClientSignal(blockrec->client);
1300                 blockrec = blockrec->depending;
1301             }
1302         }
1303         /*
1304          * Xx we could loop here and eat any additional replies, but it should
1305          * feel more responsive for other clients if we come back later
1306          */
1307     } else if (awaiting_reconnect) {
1308         _fs_try_reconnect();
1309     }
1310     return FALSE;
1311 }
1312
1313 /*
1314  * Reconnection code
1315  */
1316
1317 void
1318 _fs_connection_died(conn)
1319     FSFpePtr    conn;
1320 {
1321     if (!conn->attemptReconnect)
1322         return;
1323     conn->attemptReconnect = FALSE;
1324     fs_close_conn(conn);
1325     conn->time_to_try = time((Time_t *) 0) + FS_RECONNECT_WAIT;
1326     conn->reconnect_delay = FS_RECONNECT_WAIT;
1327     conn->fs_fd = -1;
1328     conn->trans_conn = NULL;
1329     conn->next_reconnect = awaiting_reconnect;
1330     awaiting_reconnect = conn;
1331 }
1332
1333 static int
1334 _fs_restart_connection(conn)
1335     FSFpePtr    conn;
1336 {
1337     FSBlockDataPtr block;
1338
1339     conn->current_seq = 0;
1340     FD_SET(conn->fs_fd, &_fs_fd_mask);
1341     if (!fs_send_init_packets(conn))
1342         return FALSE;
1343     while (block = (FSBlockDataPtr) conn->blocked_requests) {
1344         ClientSignal(block->client);
1345         fs_abort_blockrec(conn, block);
1346     }
1347     return TRUE;
1348 }
1349
1350 static void
1351 _fs_try_reconnect()
1352 {
1353     FSFpePtr    conn,
1354                *prev;
1355     Time_t      now;
1356
1357     prev = &awaiting_reconnect;
1358     now = time((Time_t *) 0);
1359     while (conn = *prev) {
1360         if (now - conn->time_to_try > 0) {
1361             if (_fs_reopen_server(conn) && _fs_restart_connection(conn)) {
1362                 conn->attemptReconnect = TRUE;
1363                 *prev = conn->next_reconnect;
1364                 if (prev == &awaiting_reconnect) continue;
1365             } else {
1366                 if (conn->reconnect_delay < FS_MAX_RECONNECT_WAIT)
1367                     conn->reconnect_delay *= 2;
1368                 now = time((Time_t *) 0);
1369                 conn->time_to_try = now + conn->reconnect_delay;
1370             }
1371         }
1372         prev = &conn->next_reconnect;
1373     }
1374 }
1375
1376 /*
1377  * sends the actual request out
1378  */
1379 /* ARGSUSED */
1380 static int
1381 fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont)
1382     pointer     client;
1383     FontPathElementPtr fpe;
1384     Mask        flags;
1385     char       *name;
1386     int         namelen;
1387     fsBitmapFormat format;
1388     fsBitmapFormatMask fmask;
1389     XID         id;
1390     FontPtr    *ppfont;
1391 {
1392     FontPtr     newfont;
1393     FSBlockDataPtr blockrec = NULL;
1394     FSBlockedFontPtr blockedfont;
1395     FSFontDataPtr fsd;
1396     FSFontPtr   fsfont;
1397     FSFpePtr    conn;
1398     fsOpenBitmapFontReq openreq;
1399     int         err = Suspended;
1400     XID         newid;
1401     unsigned char buf[1024];
1402     char       *fontname;
1403
1404     if (flags & FontReopen)
1405     {
1406         Atom nameatom, fn = None;
1407         int i;
1408
1409         newfont = *ppfont;
1410         fsd = (FSFontDataPtr)newfont->fpePrivate;
1411         fsfont = (FSFontPtr)newfont->fontPrivate;
1412         fpe = newfont->fpe;
1413         format = fsd->format;
1414         fmask = fsd->fmask;
1415         newid = fsd->fontid;
1416         /* This is an attempt to reopen a font.  Did the font have a
1417            NAME property? */
1418         if ((nameatom = MakeAtom("FONT", 4, 0)) != None)
1419         {
1420             for (i = 0; i < newfont->info.nprops; i++)
1421                 if (newfont->info.props[i].name == nameatom &&
1422                     newfont->info.isStringProp[i])
1423                 {
1424                     fn = newfont->info.props[i].value;
1425                     break;
1426                 }
1427         }
1428         if (fn == None || !(name = NameForAtom(fn)))
1429         {
1430             name = fsd->name;
1431             namelen = fsd->namelen;
1432         }
1433         else
1434             namelen = strlen(name);
1435     }
1436
1437     conn = (FSFpePtr) fpe->private;
1438     if (namelen > sizeof (buf) - 1)
1439         return BadFontName;
1440     _fs_client_access (conn, client, (flags & FontOpenSync) != 0);
1441     _fs_client_resolution(conn);
1442
1443
1444     if (!(flags & FontReopen))
1445     {
1446
1447         newid = GetNewFontClientID();
1448
1449         /* make the font */
1450         newfont = (FontPtr) xalloc(sizeof(FontRec));
1451
1452         /* and the FS data */
1453         fsd = (FSFontDataPtr) xalloc(sizeof(FSFontDataRec));
1454
1455         fsfont = (FSFontPtr) xalloc(sizeof(FSFontRec));
1456
1457         fontname = (char *)xalloc(namelen);
1458
1459         if (!newfont || !fsd || !fsfont || !fontname) {
1460 lowmem:
1461             if (!(flags & FontReopen))
1462             {
1463                 xfree((char *) newfont);
1464                 xfree((char *) fsd);
1465                 xfree((char *) fsfont);
1466                 xfree((char *) fontname);
1467             }
1468             if (blockrec) fs_abort_blockrec(conn, blockrec);
1469             return AllocError;
1470         }
1471         bzero((char *) newfont, sizeof(FontRec));
1472         bzero((char *) fsfont, sizeof(FSFontRec));
1473         bzero((char *) fsd, sizeof(FSFontDataRec));
1474     }
1475
1476     /* make a new block record, and add it to the end of the list */
1477     blockrec = fs_new_block_rec(fpe, client, FS_OPEN_FONT);
1478     if (!blockrec) {
1479         goto lowmem;
1480     }
1481
1482     if (!(flags & FontReopen))
1483     {
1484         int bit, byte, scan, glyph;
1485
1486         newfont->refcnt = 0;
1487         newfont->maxPrivate = -1;
1488         newfont->devPrivates = (pointer *) 0;
1489         newfont->format = format;
1490
1491         /* These font components will be needed in packGlyphs */
1492         CheckFSFormat(format, BitmapFormatMaskBit |
1493                               BitmapFormatMaskByte |
1494                               BitmapFormatMaskScanLineUnit |
1495                               BitmapFormatMaskScanLinePad,
1496                       &bit,
1497                       &byte,
1498                       &scan,
1499                       &glyph,
1500                       NULL);
1501         newfont->bit = bit;
1502         newfont->byte = byte;
1503         newfont->scan = scan;
1504         newfont->glyph = glyph;
1505
1506         newfont->fpe = fpe;
1507         newfont->fpePrivate = (pointer) fsd;
1508         newfont->fontPrivate = (pointer) fsfont;
1509         _fs_init_font(newfont);
1510
1511         fsd->fpe = fpe;
1512         fsd->name = fontname;
1513         fsd->namelen = namelen;
1514         memcpy(fontname, name, namelen);
1515         fsd->format = format;
1516         fsd->fmask = fmask;
1517     }
1518     fsd->fontid = newid;
1519     fsd->generation = conn->generation;
1520
1521     blockedfont = (FSBlockedFontPtr) blockrec->data;
1522     blockedfont->fontid = newid;
1523     blockedfont->pfont = newfont;
1524     blockedfont->state = FS_OPEN_REPLY;
1525     blockedfont->flags = flags;
1526     blockedfont->format = format;
1527     blockedfont->clients_depending = (FSClientsDependingPtr)0;
1528
1529     /* save the ID */
1530     if (!StoreFontClientFont(blockedfont->pfont, blockedfont->fontid)) {
1531         goto lowmem;
1532     }
1533     /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
1534     buf[0] = (unsigned char) namelen;
1535     memcpy(&buf[1], name, namelen);
1536     namelen++;
1537     openreq.reqType = FS_OpenBitmapFont;
1538     openreq.fid = newid;
1539     openreq.format_hint = format;
1540     openreq.format_mask = fmask;
1541     openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 3) >> 2;
1542
1543     _fs_add_req_log(conn, FS_OpenBitmapFont);
1544     _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq));
1545     _fs_write_pad(conn, (char *) buf, namelen);
1546
1547 #ifdef NCD
1548     if (configData.ExtendedFontDiags) {
1549         memcpy(buf, name, MIN(256, namelen));
1550         buf[MIN(256, namelen)] = '\0';
1551         printf("Requesting font \"%s\" from font server \"%s\"\n",
1552                buf, fpe->name);
1553     }
1554 #endif
1555
1556     if (flags & FontOpenSync) {
1557         err = fs_do_open_font(fpe, blockrec, TRUE);
1558         if (blockedfont->errcode == Successful) {
1559             *ppfont = blockedfont->pfont;
1560         } else {
1561             _fs_cleanup_font(blockedfont);
1562         }
1563         _fs_remove_block_rec(conn, blockrec);
1564     }
1565     return err;
1566 }
1567
1568 static int
1569 fs_send_query_info(fpe, blockrec)
1570     FontPathElementPtr fpe;
1571     FSBlockDataPtr blockrec;
1572 {
1573     FSBlockedFontPtr bfont;
1574     FSFpePtr    conn = (FSFpePtr) fpe->private;
1575     fsQueryXInfoReq inforeq;
1576
1577     bfont = (FSBlockedFontPtr) blockrec->data;
1578
1579     inforeq.reqType = FS_QueryXInfo;
1580     inforeq.id = bfont->fontid;
1581     inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
1582
1583     blockrec->sequence_number = conn->current_seq;
1584     _fs_add_req_log(conn, FS_QueryXInfo);
1585     _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
1586
1587     return Successful;
1588 }
1589
1590 static int
1591 fs_send_query_extents(fpe, blockrec)
1592     FontPathElementPtr fpe;
1593     FSBlockDataPtr blockrec;
1594 {
1595     FSBlockedFontPtr bfont;
1596     FSFpePtr    conn = (FSFpePtr) fpe->private;
1597     fsQueryXExtents16Req extreq;
1598
1599     bfont = (FSBlockedFontPtr) blockrec->data;
1600
1601     extreq.reqType = FS_QueryXExtents16;
1602     extreq.range = fsTrue;
1603     extreq.fid = bfont->fontid;
1604     extreq.num_ranges = 0;
1605     extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2;
1606
1607     blockrec->sequence_number = conn->current_seq;
1608     _fs_add_req_log(conn, FS_QueryXExtents16);
1609     _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
1610
1611     return Successful;
1612 }
1613
1614 static int
1615 fs_send_query_bitmaps(fpe, blockrec)
1616     FontPathElementPtr fpe;
1617     FSBlockDataPtr blockrec;
1618 {
1619     FSBlockedFontPtr bfont;
1620     FSFpePtr    conn = (FSFpePtr) fpe->private;
1621     fsQueryXBitmaps16Req bitreq;
1622
1623
1624     bfont = (FSBlockedFontPtr) blockrec->data;
1625
1626     /* send the request */
1627     bitreq.reqType = FS_QueryXBitmaps16;
1628     bitreq.fid = bfont->fontid;
1629     bitreq.format = bfont->format;
1630     bitreq.range = TRUE;
1631     bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2;
1632     bitreq.num_ranges = 0;
1633
1634     blockrec->sequence_number = conn->current_seq;
1635     _fs_add_req_log(conn, FS_QueryXBitmaps16);
1636     _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
1637
1638     return Successful;
1639 }
1640
1641 /* ARGSUSED */
1642 static int
1643 fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
1644              alias, non_cachable_font)
1645     pointer     client;
1646     FontPathElementPtr fpe;
1647     Mask        flags;
1648     char       *name;
1649     fsBitmapFormat format;
1650     fsBitmapFormatMask fmask;
1651     int         namelen;
1652     XID         id;
1653     FontPtr    *ppfont;
1654     char      **alias;
1655     FontPtr     non_cachable_font;      /* Not used in this FPE */
1656 {
1657     FSFpePtr    conn = (FSFpePtr) fpe->private;
1658     FSBlockDataPtr blockrec;
1659     FSBlockedFontPtr blockedfont;
1660     int         err;
1661
1662     /* libfont interface expects ImageRectMin glyphs */
1663     format = format & ~BitmapFormatImageRectMask | BitmapFormatImageRectMin;
1664
1665     *alias = (char *) 0;
1666     /* XX if we find the blockrec for the font */
1667     blockrec = (FSBlockDataPtr) conn->blocked_requests;
1668     while (blockrec != (FSBlockDataPtr) 0) {
1669         if (blockrec->type == FS_OPEN_FONT &&
1670                 blockrec->client == client) {
1671             blockedfont = (FSBlockedFontPtr) blockrec->data;
1672             err = blockedfont->errcode;
1673             if (err == Successful) {
1674                 *ppfont = blockedfont->pfont;
1675             } else {
1676                 _fs_cleanup_font(blockedfont);
1677             }
1678             /* cleanup */
1679             _fs_remove_block_rec(conn, blockrec);
1680             return err;
1681         }
1682         blockrec = blockrec->next;
1683     }
1684     return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
1685                              id, ppfont);
1686 }
1687
1688 /* ARGSUSED */
1689 static int
1690 fs_send_close_font(fpe, id)
1691     FontPathElementPtr fpe;
1692     Font        id;
1693 {
1694     FSFpePtr    conn = (FSFpePtr) fpe->private;
1695     fsCloseReq  req;
1696
1697     /* tell the font server to close the font */
1698     req.reqType = FS_CloseFont;
1699     req.length = SIZEOF(fsCloseReq) >> 2;
1700     req.id = id;
1701     _fs_add_req_log(conn, FS_CloseFont);
1702     _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq));
1703
1704     return Successful;
1705 }
1706
1707 /* ARGSUSED */
1708 static int
1709 fs_close_font(fpe, pfont)
1710     FontPathElementPtr fpe;
1711     FontPtr     pfont;
1712 {
1713     FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
1714     FSFpePtr    conn = (FSFpePtr) fpe->private;
1715
1716     /* XXX we may get called after the resource DB has been cleaned out */
1717     if (find_old_font(fsd->fontid))
1718         DeleteFontClientID(fsd->fontid);
1719     if (conn->generation == fsd->generation)
1720         fs_send_close_font(fpe, fsd->fontid);
1721     (*pfont->unload_font) (pfont);
1722
1723
1724     xfree(fsd->name);
1725     xfree(fsd);
1726     xfree(pfont->info.isStringProp);
1727     xfree(pfont->info.props);
1728     xfree(pfont->devPrivates);
1729     xfree(pfont);
1730
1731
1732     return Successful;
1733 }
1734
1735 static int
1736 fs_read_glyphs(fpe, blockrec)
1737     FontPathElementPtr fpe;
1738     FSBlockDataPtr blockrec;
1739 {
1740     FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data;
1741     FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1742     FSFpePtr    conn = (FSFpePtr) fpe->private;
1743     FontPtr pfont = bglyph->pfont;      /* works for either blocked font
1744                                            or glyph rec...  pfont is at
1745                                            the very beginning of both
1746                                            blockrec->data structures */
1747     FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
1748     FSFontPtr   fsdata = (FSFontPtr) pfont->fontPrivate;
1749     FontInfoPtr pfi = &pfont->info;
1750     fsQueryXBitmaps16Reply rep;
1751     fsOffset32   *ppbits;
1752     fsOffset32  local_off;
1753     char        *off_adr;
1754     pointer     pbitmaps;
1755     char        *bits;
1756     int         glyph_size,
1757                 offset_size,
1758                 i,
1759                 err;
1760     int         nranges = 0;
1761     fsRange     *ranges, *nextrange;
1762     unsigned long minchar, maxchar;
1763
1764     /* get reply header */
1765     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
1766     if (rep.type == FS_Error) {
1767 /* XXX -- translate FS error */
1768         _fs_eat_rest_of_error(conn, (fsError *) & rep);
1769         err = AllocError;
1770         goto bail;
1771     }
1772     if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
1773               SIZEOF(fsQueryXBitmaps16Reply) - SIZEOF(fsGenericReply)) == -1) {
1774         if (blockrec->type == FS_OPEN_FONT)
1775             fs_free_font(bfont);
1776         return StillWorking;
1777     }
1778     /* allocate space for glyphs */
1779     offset_size = SIZEOF(fsOffset32) * (rep.num_chars);
1780     glyph_size = (rep.length << 2) - SIZEOF(fsQueryXBitmaps16Reply)
1781         - offset_size;
1782     ppbits = (fsOffset32 *) xalloc(offset_size);
1783     pbitmaps = (pointer) xalloc(glyph_size);
1784     if (glyph_size && !pbitmaps || !ppbits)
1785     {
1786         xfree(pbitmaps);
1787         xfree(ppbits);
1788
1789         /* clear wire */
1790         (void) _fs_drain_bytes_pad(conn, offset_size);
1791         (void) _fs_drain_bytes_pad(conn, glyph_size);
1792
1793         if (blockrec->type == FS_OPEN_FONT)
1794             _fs_cleanup_font(bfont);
1795         err = AllocError;
1796         goto bail;
1797     }
1798
1799     /* read offsets */
1800     if (_fs_read_pad(conn, (char *) ppbits, offset_size) == -1) {
1801         if (blockrec->type == FS_OPEN_FONT)
1802             fs_free_font(bfont);
1803         return StillWorking;
1804     }
1805
1806     /* read glyphs */
1807     if (_fs_read_pad(conn, (char *) pbitmaps, glyph_size) == -1) {
1808         if (blockrec->type == FS_OPEN_FONT)
1809             fs_free_font(bfont);
1810         return StillWorking;
1811     }
1812
1813     if (blockrec->type == FS_LOAD_GLYPHS)
1814     {
1815         nranges = bglyph->num_expected_ranges;
1816         nextrange = ranges = bglyph->expected_ranges;
1817     }
1818
1819     /* place the incoming glyphs */
1820     if (nranges)
1821     {
1822         /* We're operating under the assumption that the ranges
1823            requested in the LoadGlyphs call were all legal for this
1824            font, and that individual ranges do not cover multiple
1825            rows...  fs_build_range() is designed to ensure this. */
1826         minchar = (nextrange->min_char_high - pfi->firstRow) *
1827                   (pfi->lastCol - pfi->firstCol + 1) +
1828                   nextrange->min_char_low - pfi->firstCol;
1829         maxchar = (nextrange->max_char_high - pfi->firstRow) *
1830                   (pfi->lastCol - pfi->firstCol + 1) +
1831                   nextrange->max_char_low - pfi->firstCol;
1832         nextrange++;
1833     }
1834     else
1835     {
1836         minchar = 0;
1837         maxchar = rep.num_chars;
1838     }
1839
1840     off_adr = (char *)ppbits;
1841     for (i = 0; i < rep.num_chars; i++)
1842     {
1843         memcpy(&local_off, off_adr, SIZEOF(fsOffset32));        /* align it */
1844         if (blockrec->type == FS_OPEN_FONT ||
1845             fsdata->encoding[minchar].bits == &_fs_glyph_requested)
1846         {
1847             if (local_off.length)
1848             {
1849                 bits = (char *)xalloc(local_off.length);
1850                 if (bits == NULL)
1851                 {
1852                     xfree(ppbits);
1853                     xfree(pbitmaps);
1854                     err = AllocError;
1855                     goto bail;
1856                 }
1857                 memcpy(bits, pbitmaps + local_off.position,
1858                        local_off.length);
1859             }
1860             else if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
1861                 bits = &_fs_glyph_zero_length;
1862             else
1863                 bits = 0;
1864             if (fsdata->encoding[minchar].bits == &_fs_glyph_requested)
1865                 fsd->glyphs_to_get--;
1866             fsdata->encoding[minchar].bits = bits;
1867         }
1868         if (minchar++ == maxchar)
1869         {
1870             if (!--nranges) break;
1871             minchar = (nextrange->min_char_high - pfi->firstRow) *
1872                       (pfi->lastCol - pfi->firstCol + 1) +
1873                       nextrange->min_char_low - pfi->firstCol;
1874             maxchar = (nextrange->max_char_high - pfi->firstRow) *
1875                       (pfi->lastCol - pfi->firstCol + 1) +
1876                       nextrange->max_char_low - pfi->firstCol;
1877             nextrange++;
1878         }
1879         off_adr += SIZEOF(fsOffset32);
1880     }
1881
1882     xfree(ppbits);
1883     xfree(pbitmaps);
1884
1885     if (blockrec->type == FS_OPEN_FONT)
1886     {
1887         fsd->glyphs_to_get = 0;
1888         bfont->state = FS_DONE_REPLY;
1889     }
1890     err = Successful;
1891
1892 bail:
1893     if (blockrec->type == FS_LOAD_GLYPHS)
1894     {
1895         bglyph->done = TRUE;
1896         bglyph->errcode = err;
1897     }
1898
1899     return err;
1900 }
1901
1902
1903
1904 static int
1905 fs_send_load_glyphs(client, pfont, nranges, ranges)
1906     pointer     client;
1907     FontPtr     pfont;
1908     int         nranges;
1909     fsRange     *ranges;
1910 {
1911     FSBlockedGlyphPtr blockedglyph;
1912     fsQueryXBitmaps16Req req;
1913     FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
1914     FontPathElementPtr fpe = fsd->fpe;
1915     FSFpePtr    conn = (FSFpePtr) fpe->private;
1916     FSBlockDataPtr blockrec;
1917
1918     /* make a new block record, and add it to the end of the list */
1919     blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS);
1920     if (!blockrec)
1921         return AllocError;
1922     blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
1923     blockedglyph->pfont = pfont;
1924     blockedglyph->num_expected_ranges = nranges;
1925     /* Assumption: it's our job to free ranges */
1926     blockedglyph->expected_ranges = ranges;
1927     blockedglyph->done = FALSE;
1928     blockedglyph->clients_depending = (FSClientsDependingPtr)0;
1929
1930     blockrec->sequence_number = conn->current_seq;
1931
1932     /* send the request */
1933     req.reqType = FS_QueryXBitmaps16;
1934     req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid;
1935     req.format = pfont->format;
1936     if (pfont->info.terminalFont)
1937         req.format = req.format & ~(BitmapFormatImageRectMask) |
1938                      BitmapFormatImageRectMax;
1939     req.range = TRUE;
1940     /* each range takes up 4 bytes */
1941     req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges;
1942     req.num_ranges = nranges * 2;       /* protocol wants count of fsChar2bs */
1943     _fs_add_req_log(conn, FS_QueryXBitmaps16);
1944     _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req));
1945
1946     /* Send ranges to the server... pack into a char array by hand
1947        to avoid structure-packing portability problems and to
1948        handle swapping for version1 protocol */
1949     if (nranges)
1950     {
1951 #define RANGE_BUFFER_SIZE 64
1952 #define RANGE_BUFFER_SIZE_MASK 63
1953         int i;
1954         char range_buffer[RANGE_BUFFER_SIZE * 4];
1955         char *range_buffer_p;
1956
1957         range_buffer_p = range_buffer;
1958         for (i = 0; i < nranges;)
1959         {
1960             if (conn->fsMajorVersion > 1)
1961             {
1962                 *range_buffer_p++ = ranges[i].min_char_high;
1963                 *range_buffer_p++ = ranges[i].min_char_low;
1964                 *range_buffer_p++ = ranges[i].max_char_high;
1965                 *range_buffer_p++ = ranges[i].max_char_low;
1966             }
1967             else
1968             {
1969                 *range_buffer_p++ = ranges[i].min_char_low;
1970                 *range_buffer_p++ = ranges[i].min_char_high;
1971                 *range_buffer_p++ = ranges[i].max_char_low;
1972                 *range_buffer_p++ = ranges[i].max_char_high;
1973             }
1974
1975             if (!(++i & RANGE_BUFFER_SIZE_MASK))
1976             {
1977                 _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4);
1978                 range_buffer_p = range_buffer;
1979             }
1980         }
1981         if (i &= RANGE_BUFFER_SIZE_MASK)
1982             _fs_write(conn, range_buffer, i * 4);
1983     }
1984
1985     return Suspended;
1986 }
1987
1988
1989 int
1990 fs_load_all_glyphs(pfont)
1991     FontPtr     pfont;
1992 {
1993     extern pointer serverClient;        /* This could be any number that
1994                                            doesn't conflict with existing
1995                                            client values. */
1996     int err;
1997     FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
1998
1999     /*
2000      * The purpose of this procedure is to load all glyphs in the event
2001      * that we're dealing with someone who doesn't understand the finer
2002      * points of glyph caching...  it is called from _fs_get_glyphs() if
2003      * the latter is called to get glyphs that have not yet been loaded.
2004      * We assume that the caller will not know how to handle a return
2005      * value of Suspended (usually the case for a GetGlyphs() caller),
2006      * so this procedure hangs around, freezing the server, for the
2007      * request to complete.  This is an unpleasant kluge called to
2008      * perform an unpleasant job that, we hope, will never be required.
2009      */
2010
2011     while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) ==
2012            Suspended)
2013     {
2014         fd_set TempSelectMask;
2015         if (_fs_wait_for_readable(conn) == -1)
2016         {
2017             /* We lost our connection.  Don't wait to reestablish it;
2018                just give up. */
2019             _fs_connection_died(conn);
2020
2021             /* Get rid of blockrec */
2022             fs_client_died(serverClient, pfont->fpe);
2023
2024             return BadCharRange;        /* As good an error as any other */
2025         }
2026         FD_SET(conn->fs_fd, &TempSelectMask);
2027         fs_wakeup(pfont->fpe, &TempSelectMask);
2028     }
2029
2030     return err;
2031 }
2032
2033
2034 int
2035 _fs_load_glyphs(client, pfont, range_flag, nchars, item_size, data)
2036     pointer     client;
2037     FontPtr     pfont;
2038     Bool        range_flag;
2039     unsigned int nchars;
2040     int         item_size;
2041     unsigned char *data;
2042 {
2043
2044     int         nranges = 0;
2045     fsRange     *ranges = NULL;
2046     int         res;
2047     FSBlockDataPtr blockrec;
2048     FSBlockedGlyphPtr blockedglyph;
2049     FSFpePtr    conn = (FSFpePtr) pfont->fpe->private;
2050     FSClientsDependingPtr *clients_depending = NULL;
2051
2052     /* see if the result is already there */
2053
2054     blockrec = (FSBlockDataPtr) conn->blocked_requests;
2055     while (blockrec) {
2056         if (blockrec->type == FS_LOAD_GLYPHS)
2057         {
2058             blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
2059             if (blockedglyph->pfont == pfont)
2060             {
2061                 if (blockrec->client == client)
2062                 {
2063                     if (blockedglyph->done)
2064                     {
2065                         int errcode = blockedglyph->errcode;
2066                         signal_clients_depending(&blockedglyph->
2067                                                  clients_depending);
2068                         _fs_remove_block_rec(conn, blockrec);
2069                         return errcode;
2070                     }
2071                     else return Suspended;
2072                 }
2073                 /* We've found an existing LoadGlyphs blockrec for this
2074                    font but for another client.  Rather than build a
2075                    blockrec for it now (which entails some complex
2076                    maintenance), we'll add it to a queue of clients to
2077                    be signalled when the existing LoadGlyphs is
2078                    completed.  */
2079                 clients_depending = &blockedglyph->clients_depending;
2080                 break;
2081             }
2082         }
2083         else if (blockrec->type == FS_OPEN_FONT)
2084         {
2085             FSBlockedFontPtr bfont;
2086             bfont = (FSBlockedFontPtr) blockrec->data;
2087             if (bfont->pfont == pfont)
2088             {
2089                 if (blockrec->client == client)
2090                 {
2091                     if (bfont->state == FS_DONE_REPLY)
2092                     {
2093                         int errcode = bfont->errcode;
2094                         signal_clients_depending(&bfont->clients_depending);
2095                         _fs_remove_block_rec(conn, blockrec);
2096                         if (errcode == Successful) break;
2097                         else return errcode;
2098                     }
2099                     else return Suspended;
2100                 }
2101                 /* We've found an existing OpenFont blockrec for this
2102                    font but for another client.  Rather than build a
2103                    blockrec for it now (which entails some complex
2104                    maintenance), we'll add it to a queue of clients to
2105                    be signalled when the existing OpenFont is
2106                    completed.  */
2107                 if (bfont->state != FS_DONE_REPLY)
2108                 {
2109                     clients_depending = &bfont->clients_depending;
2110                     break;
2111                 }
2112             }
2113         }
2114                  
2115         blockrec = blockrec->next;
2116     }
2117
2118     /*
2119      * see if the desired glyphs already exist, and return Successful if they
2120      * do, otherwise build up character range/character string
2121      */
2122     res = fs_build_range(pfont, range_flag, nchars, item_size, data,
2123                          &nranges, &ranges);
2124
2125     switch (res)
2126     {
2127         case AccessDone:
2128             return Successful;
2129
2130         case Successful:
2131             break;
2132
2133         default:
2134             return res;
2135     }
2136
2137     /*
2138      * If clients_depending is not null, this request must wait for
2139      * some prior request(s) to complete.
2140      */
2141     if (clients_depending)
2142     {
2143         /* Since we're not ready to send the load_glyphs request yet,
2144            clean up the damage (if any) caused by the fs_build_range()
2145            call. */
2146         if (nranges)
2147         {
2148             _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2149             xfree(ranges);
2150         }
2151         return add_clients_depending(clients_depending, client);
2152     }
2153
2154     /*
2155      * If fsd->generation != conn->generation, the font has been closed
2156      * due to a lost connection.  We will reopen it, which will result
2157      * in one of three things happening:
2158      *   1) The open will succeed and obtain the same font.  Life
2159      *      is wonderful.
2160      *   2) The open will fail.  There is code above to recognize this
2161      *      and flunk the LoadGlyphs request.  The client might not be
2162      *      thrilled.
2163      *   3) Worst case: the open will succeed but the font we open will
2164      *      be different.  The fs_read_query_info() procedure attempts
2165      *      to detect this by comparing the existing metrics and
2166      *      properties against those of the reopened font... if they
2167      *      don't match, we flunk the reopen, which eventually results
2168      *      in flunking the LoadGlyphs request.  We could go a step
2169      *      further and compare the extents, but this should be
2170      *      sufficient.
2171      */
2172     if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation)
2173     {
2174         /* Since we're not ready to send the load_glyphs request yet,
2175            clean up the damage caused by the fs_build_range() call. */
2176         _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2177         xfree(ranges);
2178
2179         /* Now try to reopen the font. */
2180         return fs_send_open_font(client, (FontPathElementPtr)0,
2181                                  (Mask)FontReopen, (char *)0, 0,
2182                                  (fsBitmapFormat)0, (fsBitmapFormatMask)0,
2183                                  (XID)0, &pfont);
2184     }
2185
2186     return fs_send_load_glyphs(client, pfont, nranges, ranges);
2187 }
2188
2189
2190
2191 static int
2192 fs_read_list(fpe, blockrec)
2193     FontPathElementPtr fpe;
2194     FSBlockDataPtr blockrec;
2195 {
2196     FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
2197     FSFpePtr    conn = (FSFpePtr) fpe->private;
2198     fsListFontsReply rep;
2199     char       *data,
2200                *dp;
2201     int         length,
2202                 i;
2203
2204     blist->done = TRUE;
2205
2206     /* read reply header */
2207     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
2208     if (rep.type == FS_Error) {
2209 /* XXX -- translate FS error */
2210         _fs_eat_rest_of_error(conn, (fsError *) & rep);
2211         return AllocError;
2212     }
2213     if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
2214                  SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) == -1) {
2215         /* nothing to free (i think) */
2216         return StillWorking;
2217     }
2218     length = (rep.length << 2) - SIZEOF(fsListFontsReply);
2219     data = (char *) xalloc(length);
2220     if (!data) {
2221         _fs_drain_bytes_pad(conn, length);
2222         return AllocError;
2223     }
2224     /* read the list */
2225     if (_fs_read_pad(conn, data, length) == -1) {
2226         /* nothing to free (i think) */
2227         return StillWorking;
2228     }
2229     /* copy data into FontPathRecord */
2230     dp = data;
2231     for (i = 0; i < rep.nFonts; i++) {
2232         length = *(unsigned char *)dp++;
2233         if (AddFontNamesName(blist->names, dp, length) != Successful) {
2234             blist->errcode = AllocError;
2235             break;
2236         }
2237         dp += length;
2238     }
2239
2240     xfree(data);
2241     return Successful;
2242 }
2243
2244 static int
2245 fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2246     pointer     client;
2247     FontPathElementPtr fpe;
2248     char       *pattern;
2249     int         patlen;
2250     int         maxnames;
2251     FontNamesPtr newnames;
2252 {
2253     FSBlockDataPtr blockrec;
2254     FSBlockedListPtr blockedlist;
2255     FSFpePtr    conn = (FSFpePtr) fpe->private;
2256     fsListFontsReq req;
2257
2258     _fs_client_access (conn, client, FALSE);
2259     _fs_client_resolution(conn);
2260
2261     /* make a new block record, and add it to the end of the list */
2262     blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS);
2263     if (!blockrec)
2264         return AllocError;
2265     blockedlist = (FSBlockedListPtr) blockrec->data;
2266     blockedlist->patlen = patlen;
2267     blockedlist->errcode = Successful;
2268     blockedlist->names = newnames;
2269     blockedlist->done = FALSE;
2270
2271     /* send the request */
2272     req.reqType = FS_ListFonts;
2273     req.maxNames = maxnames;
2274     req.nbytes = patlen;
2275     req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2;
2276     _fs_add_req_log(conn, FS_ListFonts);
2277     _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq));
2278     _fs_write_pad(conn, (char *) pattern, patlen);
2279
2280 #ifdef NCD
2281     if (configData.ExtendedFontDiags) {
2282         char        buf[256];
2283
2284         memcpy(buf, pattern, MIN(256, patlen));
2285         buf[MIN(256, patlen)] = '\0';
2286         printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n",
2287                buf, fpe->name);
2288     }
2289 #endif
2290
2291     return Suspended;
2292 }
2293
2294 static int
2295 fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2296     pointer     client;
2297     FontPathElementPtr fpe;
2298     char       *pattern;
2299     int         patlen;
2300     int         maxnames;
2301     FontNamesPtr newnames;
2302 {
2303     FSBlockDataPtr blockrec;
2304     FSBlockedListPtr blockedlist;
2305     FSFpePtr    conn = (FSFpePtr) fpe->private;
2306     int         err;
2307
2308     /* see if the result is already there */
2309     blockrec = (FSBlockDataPtr) conn->blocked_requests;
2310     while (blockrec) {
2311         if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) {
2312             blockedlist = (FSBlockedListPtr) blockrec->data;
2313             if (blockedlist->patlen == patlen && blockedlist->done) {
2314                 err = blockedlist->errcode;
2315                 _fs_remove_block_rec(conn, blockrec);
2316                 return err;
2317             }
2318         }
2319         blockrec = blockrec->next;
2320     }
2321
2322     /* didn't find waiting record, so send a new one */
2323     return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
2324 }
2325
2326 static int  padlength[4] = {0, 3, 2, 1};
2327
2328 static int
2329 fs_read_list_info(fpe, blockrec)
2330     FontPathElementPtr fpe;
2331     FSBlockDataPtr blockrec;
2332 {
2333     FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
2334     fsListFontsWithXInfoReply rep;
2335     FSFpePtr    conn = (FSFpePtr) fpe->private;
2336     fsPropInfo  pi;
2337     fsPropOffset *po;
2338     char       *name;
2339     pointer     pd;
2340     int         err;
2341
2342     /* clean up anything from the last trip */
2343     if (binfo->name)
2344     {
2345         xfree(binfo->name);
2346         binfo->name = NULL;
2347     }
2348     if (binfo->pfi) {
2349         xfree(binfo->pfi->isStringProp);
2350         xfree(binfo->pfi->props);
2351         xfree(binfo->pfi);
2352         binfo->pfi = NULL;
2353     }
2354     /* get reply header */
2355     memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
2356     if (rep.type == FS_Error) {
2357 /* XXX -- translate FS error */
2358         _fs_eat_rest_of_error(conn, (fsError *) & rep);
2359         binfo->errcode = AllocError;
2360         return AllocError;
2361     }
2362     if (conn->fsMajorVersion > 1)
2363         if (rep.nameLength == 0)
2364             goto done;
2365     /* old protocol sent a full-length reply even for the last one */
2366     if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
2367           SIZEOF(fsListFontsWithXInfoReply) - SIZEOF(fsGenericReply)) == -1) {
2368         goto done;
2369     }
2370     if (rep.nameLength == 0)
2371         goto done;
2372
2373     /* read the data */
2374     name = (char *) xalloc(rep.nameLength);
2375     binfo->pfi = (FontInfoPtr) xalloc(sizeof(FontInfoRec));
2376     if (!name || !binfo->pfi) {
2377         xfree(name);
2378         xfree(binfo->pfi);
2379         binfo->pfi = NULL;
2380         _fs_drain_bytes(conn,
2381                         rep.length - (SIZEOF(fsListFontsWithXInfoReply) -
2382                                       SIZEOF(fsGenericReply)));
2383         binfo->errcode = AllocError;
2384         return AllocError;
2385     }
2386     if (conn->fsMajorVersion == 1)
2387         if (_fs_read_pad(conn, name, rep.nameLength) == -1)
2388             goto done;
2389     if (_fs_read_pad(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1)
2390             goto done;
2391
2392     po = (fsPropOffset *) xalloc(SIZEOF(fsPropOffset) * pi.num_offsets);
2393     pd = (pointer) xalloc(pi.data_len);
2394     if (!po || !pd) {
2395         xfree(name);
2396         xfree(po);
2397         xfree(pd);
2398         xfree (binfo->pfi);
2399         binfo->pfi = NULL;
2400         binfo->errcode = AllocError;
2401         return AllocError;
2402     }
2403     err = _fs_read_pad(conn, (char *) po,
2404                        (pi.num_offsets * SIZEOF(fsPropOffset)));
2405     if (err != -1)
2406     {
2407         if (conn->fsMajorVersion > 1)
2408             err = _fs_read(conn, (char *) pd, pi.data_len);
2409         else
2410             err = _fs_read_pad(conn, (char *) pd, pi.data_len);
2411     }
2412     if (err != -1  &&  conn->fsMajorVersion != 1)
2413     {
2414         err = _fs_read(conn, name, rep.nameLength);
2415         if (err != -1)
2416             err = _fs_drain_bytes(conn, padlength[(pi.data_len+rep.nameLength)&3]);
2417     }
2418
2419     if (err == -1) {
2420         xfree(name);
2421         xfree(po);
2422         xfree(pd);
2423         xfree (binfo->pfi);
2424         binfo->pfi = NULL;
2425         goto done;
2426     }
2427
2428     if (_fs_convert_lfwi_reply(conn, binfo->pfi, &rep, &pi, po, pd) != Successful)
2429     {
2430         xfree(name);
2431         xfree(po);
2432         xfree(pd);
2433         xfree (binfo->pfi);
2434         binfo->pfi = NULL;
2435         goto done;
2436     }
2437     xfree(po);
2438     xfree(pd);
2439     binfo->name = name;
2440     binfo->namelen = rep.nameLength;
2441     binfo->remaining = rep.nReplies;
2442
2443     binfo->status = FS_LFWI_REPLY;
2444     binfo->errcode = Suspended;
2445     /* disable this font server until we've processed this response */
2446     FD_CLR(conn->fs_fd, &_fs_fd_mask);
2447
2448     return Successful;
2449
2450 done:
2451     binfo->status = FS_LFWI_FINISHED;
2452     binfo->errcode = BadFontName;
2453     binfo->name = (char *) 0;
2454     return Successful;
2455 }
2456
2457 /* ARGSUSED */
2458 static int
2459 fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2460     pointer     client;
2461     FontPathElementPtr fpe;
2462     char       *pattern;
2463     int         len;
2464     int         maxnames;
2465     pointer    *pdata;
2466 {
2467     FSBlockDataPtr blockrec;
2468     FSBlockedListInfoPtr blockedinfo;
2469     fsListFontsWithXInfoReq req;
2470     FSFpePtr    conn = (FSFpePtr) fpe->private;
2471
2472     _fs_client_access (conn, client, FALSE);
2473     _fs_client_resolution(conn);
2474
2475     /* make a new block record, and add it to the end of the list */
2476     blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO);
2477     if (!blockrec)
2478         return AllocError;
2479     blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2480     bzero((char *) blockedinfo, sizeof(FSBlockedListInfoRec));
2481     blockedinfo->status = FS_LFWI_WAITING;
2482     blockedinfo->errcode = Suspended;
2483
2484     /* send the request */
2485     req.reqType = FS_ListFontsWithXInfo;
2486     req.maxNames = maxnames;
2487     req.nbytes = len;
2488     req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2;
2489     _fs_add_req_log(conn, FS_ListFontsWithXInfo);
2490     (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq));
2491     (void) _fs_write_pad(conn, pattern, len);
2492
2493 #ifdef NCD
2494     if (configData.ExtendedFontDiags) {
2495         char        buf[256];
2496
2497         memcpy(buf, pattern, MIN(256, len));
2498         buf[MIN(256, len)] = '\0';
2499         printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n",
2500                buf, fpe->name);
2501     }
2502 #endif
2503
2504     return Successful;
2505 }
2506
2507 /* ARGSUSED */
2508 static int
2509 fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2510                        private)
2511     pointer     client;
2512     FontPathElementPtr fpe;
2513     char      **namep;
2514     int        *namelenp;
2515     FontInfoPtr *pFontInfo;
2516     int        *numFonts;
2517     pointer     private;
2518 {
2519     FSBlockDataPtr blockrec;
2520     FSBlockedListInfoPtr blockedinfo;
2521     FSFpePtr    conn = (FSFpePtr) fpe->private;
2522
2523     /* see if the result is already there */
2524     blockrec = (FSBlockDataPtr) conn->blocked_requests;
2525     while (blockrec) {
2526         if (blockrec->type == FS_LIST_WITH_INFO &&
2527                 blockrec->client == client) {
2528             blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2529             break;
2530         }
2531         blockrec = blockrec->next;
2532     }
2533
2534     if (!blockrec)
2535     {
2536         /* The only good reason for not finding a blockrec would be if
2537            disconnect/reconnect to the font server wiped it out and the
2538            code that called us didn't do the right thing to create
2539            another one.  Under those circumstances, we need to return an
2540            error to prevent that code from attempting to interpret the
2541            information we don't return.  */
2542         return BadFontName;
2543     }
2544
2545     if (blockedinfo->status == FS_LFWI_WAITING)
2546         return Suspended;
2547
2548     *namep = blockedinfo->name;
2549     *namelenp = blockedinfo->namelen;
2550     *pFontInfo = blockedinfo->pfi;
2551     *numFonts = blockedinfo->remaining;
2552     FD_SET(conn->fs_fd, &_fs_fd_mask);
2553     if (blockedinfo->status == FS_LFWI_FINISHED) {
2554         int         err = blockedinfo->errcode;
2555
2556         _fs_remove_block_rec(conn, blockrec);
2557         return err;
2558     }
2559     if (blockedinfo->status == FS_LFWI_REPLY) {
2560         blockedinfo->status = FS_LFWI_WAITING;
2561         return Successful;
2562     } else {
2563         return blockedinfo->errcode;
2564     }
2565 }
2566
2567 /*
2568  * Called when client exits
2569  */
2570
2571 static void
2572 fs_client_died(client, fpe)
2573     pointer     client;
2574     FontPathElementPtr fpe;
2575 {
2576     FSFpePtr    conn = (FSFpePtr) fpe->private;
2577     FSBlockDataPtr blockrec,
2578                 depending;
2579     FSClientPtr *prev, cur;
2580     fsFreeACReq freeac;
2581
2582     for (prev = &conn->clients; cur = *prev; prev = &cur->next)
2583     {
2584         if (cur->client == client) {
2585             freeac.reqType = FS_FreeAC;
2586             freeac.id = cur->acid;
2587             freeac.length = sizeof (fsFreeACReq) >> 2;
2588             _fs_add_req_log(conn, FS_FreeAC);
2589             _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2590             *prev = cur->next;
2591             xfree (cur);
2592             break;
2593         }
2594     }
2595     /* see if the result is already there */
2596     blockrec = (FSBlockDataPtr) conn->blocked_requests;
2597     while (blockrec) {
2598         if (blockrec->client == client)
2599             break;
2600         blockrec = blockrec->next;
2601     }
2602     if (!blockrec)
2603         return;
2604     if (blockrec->type == FS_LIST_WITH_INFO)
2605     {
2606         FSBlockedListInfoPtr binfo;
2607         binfo = (FSBlockedListInfoPtr) blockrec->data;
2608         if (binfo->status == FS_LFWI_REPLY)
2609             FD_SET(conn->fs_fd, &_fs_fd_mask);
2610         if (binfo->name)
2611         {
2612             xfree(binfo->name);
2613             binfo->name = NULL;
2614         }
2615         if (binfo->pfi) 
2616         {
2617             xfree(binfo->pfi->isStringProp);
2618             xfree(binfo->pfi->props);
2619             xfree(binfo->pfi);
2620             binfo->pfi = NULL;
2621         }
2622     }
2623     /* replace the client pointers in this block rec with the chained one */
2624     if (depending = blockrec->depending) {
2625         blockrec->client = depending->client;
2626         blockrec->depending = depending->depending;
2627         blockrec = depending;
2628     }
2629     fs_abort_blockrec(conn, blockrec);
2630 }
2631
2632 static void
2633 _fs_client_access (conn, client, sync)
2634     FSFpePtr    conn;
2635     pointer     client;
2636     Bool        sync;
2637 {
2638     FSClientPtr *prev,      cur;
2639     fsCreateACReq           crac;
2640     fsSetAuthorizationReq   setac;
2641     fsGenericReply          rep;
2642     char                    *authorizations;
2643     int                     authlen;
2644     Bool                    new_cur = FALSE;
2645
2646     for (prev = &conn->clients; cur = *prev; prev = &cur->next)
2647     {
2648         if (cur->client == client)
2649         {
2650             if (prev != &conn->clients)
2651             {
2652                 *prev = cur->next;
2653                 cur->next = conn->clients;
2654                 conn->clients = cur;
2655             }
2656             break;
2657         }
2658     }
2659     if (!cur)
2660     {
2661         cur = (FSClientPtr) xalloc (sizeof (FSClientRec));
2662         if (!cur)
2663             return;
2664         cur->client = client;
2665         cur->next = conn->clients;
2666         conn->clients = cur;
2667         cur->acid = GetNewFontClientID ();
2668         new_cur = TRUE;
2669     }
2670     if (new_cur || cur->auth_generation != client_auth_generation(client))
2671     {
2672         if (!new_cur)
2673         {
2674             fsFreeACReq freeac;
2675             freeac.reqType = FS_FreeAC;
2676             freeac.id = cur->acid;
2677             freeac.length = sizeof (fsFreeACReq) >> 2;
2678             _fs_add_req_log(conn, FS_FreeAC);
2679             _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2680         }
2681         crac.reqType = FS_CreateAC;
2682         crac.num_auths = set_font_authorizations(&authorizations, &authlen,
2683                                                  client);
2684         authlen = crac.num_auths ? (authlen + 3) & ~0x3 : 0;
2685         crac.length = (sizeof (fsCreateACReq) + authlen) >> 2;
2686         crac.acid = cur->acid;
2687         _fs_add_req_log(conn, FS_CreateAC);
2688         _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq));
2689         _fs_write(conn, authorizations, authlen);
2690         /* if we're synchronous, open_font will be confused by
2691          * the reply; eat it and continue
2692          */
2693         if (sync)
2694         {
2695             if (_fs_read(conn, (char *) &rep, sizeof (fsGenericReply)) == -1)
2696                 return;
2697             fs_handle_unexpected(conn, &rep);
2698         }
2699         /* ignore reply; we don't even care about it */
2700         conn->curacid = 0;
2701         cur->auth_generation = client_auth_generation(client);
2702     }
2703     if (conn->curacid != cur->acid)
2704     {
2705         setac.reqType = FS_SetAuthorization;
2706         setac.length = sizeof (fsSetAuthorizationReq) >> 2;
2707         setac.id = cur->acid;
2708         _fs_add_req_log(conn, FS_SetAuthorization);
2709         _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq));
2710         conn->curacid = cur->acid;
2711     }
2712 }
2713
2714 /*
2715  * called at server init time
2716  */
2717
2718 void
2719 fs_register_fpe_functions()
2720 {
2721     fs_font_type = RegisterFPEFunctions(fs_name_check,
2722                                         fs_init_fpe,
2723                                         fs_free_fpe,
2724                                         fs_reset_fpe,
2725                                         fs_open_font,
2726                                         fs_close_font,
2727                                         fs_list_fonts,
2728                                         fs_start_list_with_info,
2729                                         fs_next_list_with_info,
2730                                         fs_wakeup,
2731                                         fs_client_died,
2732                                         _fs_load_glyphs,
2733                                         (int (*))0,
2734                                         (int (*))0,
2735                                         (void (*))0);
2736 }
2737
2738 static int
2739 check_fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
2740              alias, non_cachable_font)
2741     pointer     client;
2742     FontPathElementPtr fpe;
2743     Mask        flags;
2744     char       *name;
2745     fsBitmapFormat format;
2746     fsBitmapFormatMask fmask;
2747     int         namelen;
2748     XID         id;
2749     FontPtr    *ppfont;
2750     char      **alias;
2751     FontPtr     non_cachable_font;      /* Not used in this FPE */
2752 {
2753     if (XpClientIsBitmapClient(client))
2754         return (fs_open_font(client, fpe, flags, name, namelen, format, 
2755                         fmask, id, ppfont, alias, non_cachable_font) );
2756     return BadFontName;
2757 }
2758
2759 static int
2760 check_fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2761     pointer     client;
2762     FontPathElementPtr fpe;
2763     char       *pattern;
2764     int         patlen;
2765     int         maxnames;
2766     FontNamesPtr newnames;
2767 {
2768     if (XpClientIsBitmapClient(client))
2769         return (fs_list_fonts(client, fpe, pattern, patlen, maxnames, 
2770                 newnames));
2771     return BadFontName;
2772 }
2773
2774 static int
2775 check_fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2776     pointer     client;
2777     FontPathElementPtr fpe;
2778     char       *pattern;
2779     int         len;
2780     int         maxnames;
2781     pointer    *pdata;
2782 {
2783     if (XpClientIsBitmapClient(client))
2784         return (fs_start_list_with_info(client, fpe, pattern, len, maxnames,
2785                 pdata));
2786     return BadFontName;
2787 }
2788
2789 static int
2790 check_fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2791                        private)
2792     pointer     client;
2793     FontPathElementPtr fpe;
2794     char      **namep;
2795     int        *namelenp;
2796     FontInfoPtr *pFontInfo;
2797     int        *numFonts;
2798     pointer     private;
2799 {
2800     if (XpClientIsBitmapClient(client))
2801         return (fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, 
2802                 numFonts,private));
2803     return BadFontName;
2804 }
2805
2806 void
2807 check_fs_register_fpe_functions()
2808 {
2809     fs_font_type = RegisterFPEFunctions(fs_name_check,
2810                                         fs_init_fpe,
2811                                         fs_free_fpe,
2812                                         fs_reset_fpe,
2813                                         check_fs_open_font,
2814                                         fs_close_font,
2815                                         check_fs_list_fonts,
2816                                         check_fs_start_list_with_info,
2817                                         check_fs_next_list_with_info,
2818                                         fs_wakeup,
2819                                         fs_client_died,
2820                                         _fs_load_glyphs,
2821                                         (int (*))0,
2822                                         (int (*))0,
2823                                         (void (*))0);
2824 }