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
_fs_add_req_log(conn,opcode)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
fs_name_check(name)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
_fs_client_resolution(conn)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
fs_send_init_packets(conn)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
fs_close_conn(conn)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
fs_init_fpe(fpe)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
fs_reset_fpe(fpe)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
fs_free_fpe(fpe)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
fs_new_block_rec(fpe,client,type)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
_fs_remove_block_rec(conn,blockrec)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
signal_clients_depending(clients_depending)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
add_clients_depending(clients_depending,client)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
clean_aborted_blockrec(blockrec)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
fs_abort_blockrec(conn,blockrec)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
fs_free_font(bfont)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
_fs_cleanup_font(bfont)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
fs_read_open_font(fpe,blockrec)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
fs_read_query_info(fpe,blockrec)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
fs_read_extent_info(fpe,blockrec)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
fs_do_open_font(fpe,blockrec,readheader)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
fs_block_handler(data,wt,LastSelectMask)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
fs_handle_unexpected(conn,rep)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
fs_wakeup(fpe,LastSelectMask)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
1239 /* see if there's any data to be read */
1240
1241 /*
1242 * Don't continue if the fd is -1 (which will be true when the
1243 * font server terminates
1244 */
1245 if (conn->fs_fd == -1)
1246 return FALSE;
1247
1248 if (FD_ISSET(conn->fs_fd, LastSelectMask)) {
1249
1250 #if defined(NOTDEF) || defined(__EMX__) /* bogus - doesn't deal with EOF very well,
1251 * now does it ... */
1252 /*
1253 * make sure it isn't spurious - mouse events seem to trigger extra
1254 * problems. Under OS/2, this is especially true ...
1255 */
1256 if (_fs_data_ready(conn) <= 0) {
1257 return FALSE;
1258 }
1259 #endif
1260
1261 /* get the header */
1262 if (_fs_read(conn, (char *) &rep, SIZEOF(fsGenericReply)) == -1)
1263 return FALSE;
1264
1265 /* find the matching block record */
1266
1267 for (br = (FSBlockDataPtr) conn->blocked_requests; br; br = br->next) {
1268 if ((CARD16)(br->sequence_number & 0xffff) ==
1269 (CARD16)(rep.sequenceNumber - 1))
1270 break;
1271 }
1272 if (!br) {
1273 fs_handle_unexpected(conn, &rep);
1274 return FALSE;
1275 }
1276 blockrec = br;
1277
1278 memcpy(&blockrec->header, &rep, SIZEOF(fsGenericReply));
1279
1280 /* go read it, and if we're done, wake up the appropriate client */
1281 switch (blockrec->type) {
1282 case FS_OPEN_FONT:
1283 err = fs_do_open_font(fpe, blockrec, FALSE);
1284 break;
1285 case FS_LOAD_GLYPHS:
1286 err = fs_read_glyphs(fpe, blockrec);
1287 break;
1288 case FS_LIST_FONTS:
1289 err = fs_read_list(fpe, blockrec);
1290 break;
1291 case FS_LIST_WITH_INFO:
1292 err = fs_read_list_info(fpe, blockrec);
1293 break;
1294 default:
1295 break;
1296 }
1297
1298 if (err != StillWorking) {
1299 while (blockrec) {
1300 ClientSignal(blockrec->client);
1301 blockrec = blockrec->depending;
1302 }
1303 }
1304 /*
1305 * Xx we could loop here and eat any additional replies, but it should
1306 * feel more responsive for other clients if we come back later
1307 */
1308 } else if (awaiting_reconnect) {
1309 _fs_try_reconnect();
1310 }
1311 return FALSE;
1312 }
1313
1314 /*
1315 * Reconnection code
1316 */
1317
1318 void
_fs_connection_died(conn)1319 _fs_connection_died(conn)
1320 FSFpePtr conn;
1321 {
1322 if (!conn->attemptReconnect)
1323 return;
1324 conn->attemptReconnect = FALSE;
1325 fs_close_conn(conn);
1326 conn->time_to_try = time((Time_t *) 0) + FS_RECONNECT_WAIT;
1327 conn->reconnect_delay = FS_RECONNECT_WAIT;
1328 conn->fs_fd = -1;
1329 conn->trans_conn = NULL;
1330 conn->next_reconnect = awaiting_reconnect;
1331 awaiting_reconnect = conn;
1332 }
1333
1334 static int
_fs_restart_connection(conn)1335 _fs_restart_connection(conn)
1336 FSFpePtr conn;
1337 {
1338 FSBlockDataPtr block;
1339
1340 conn->current_seq = 0;
1341 FD_SET(conn->fs_fd, &_fs_fd_mask);
1342 if (!fs_send_init_packets(conn))
1343 return FALSE;
1344 while (block = (FSBlockDataPtr) conn->blocked_requests) {
1345 ClientSignal(block->client);
1346 fs_abort_blockrec(conn, block);
1347 }
1348 return TRUE;
1349 }
1350
1351 static void
_fs_try_reconnect()1352 _fs_try_reconnect()
1353 {
1354 FSFpePtr conn,
1355 *prev;
1356 Time_t now;
1357
1358 prev = &awaiting_reconnect;
1359 now = time((Time_t *) 0);
1360 while (conn = *prev) {
1361 if (now - conn->time_to_try > 0) {
1362 if (_fs_reopen_server(conn) && _fs_restart_connection(conn)) {
1363 conn->attemptReconnect = TRUE;
1364 *prev = conn->next_reconnect;
1365 if (prev == &awaiting_reconnect) continue;
1366 } else {
1367 if (conn->reconnect_delay < FS_MAX_RECONNECT_WAIT)
1368 conn->reconnect_delay *= 2;
1369 now = time((Time_t *) 0);
1370 conn->time_to_try = now + conn->reconnect_delay;
1371 }
1372 }
1373 prev = &conn->next_reconnect;
1374 }
1375 }
1376
1377 /*
1378 * sends the actual request out
1379 */
1380 /* ARGSUSED */
1381 static int
fs_send_open_font(client,fpe,flags,name,namelen,format,fmask,id,ppfont)1382 fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont)
1383 pointer client;
1384 FontPathElementPtr fpe;
1385 Mask flags;
1386 char *name;
1387 int namelen;
1388 fsBitmapFormat format;
1389 fsBitmapFormatMask fmask;
1390 XID id;
1391 FontPtr *ppfont;
1392 {
1393 FontPtr newfont;
1394 FSBlockDataPtr blockrec = NULL;
1395 FSBlockedFontPtr blockedfont;
1396 FSFontDataPtr fsd;
1397 FSFontPtr fsfont;
1398 FSFpePtr conn;
1399 fsOpenBitmapFontReq openreq;
1400 int err = Suspended;
1401 XID newid;
1402 unsigned char buf[1024];
1403 char *fontname;
1404
1405 if (flags & FontReopen)
1406 {
1407 Atom nameatom, fn = None;
1408 int i;
1409
1410 newfont = *ppfont;
1411 fsd = (FSFontDataPtr)newfont->fpePrivate;
1412 fsfont = (FSFontPtr)newfont->fontPrivate;
1413 fpe = newfont->fpe;
1414 format = fsd->format;
1415 fmask = fsd->fmask;
1416 newid = fsd->fontid;
1417 /* This is an attempt to reopen a font. Did the font have a
1418 NAME property? */
1419 if ((nameatom = MakeAtom("FONT", 4, 0)) != None)
1420 {
1421 for (i = 0; i < newfont->info.nprops; i++)
1422 if (newfont->info.props[i].name == nameatom &&
1423 newfont->info.isStringProp[i])
1424 {
1425 fn = newfont->info.props[i].value;
1426 break;
1427 }
1428 }
1429 if (fn == None || !(name = NameForAtom(fn)))
1430 {
1431 name = fsd->name;
1432 namelen = fsd->namelen;
1433 }
1434 else
1435 namelen = strlen(name);
1436 }
1437
1438 conn = (FSFpePtr) fpe->private;
1439 if (namelen > sizeof (buf) - 1)
1440 return BadFontName;
1441 _fs_client_access (conn, client, (flags & FontOpenSync) != 0);
1442 _fs_client_resolution(conn);
1443
1444
1445 if (!(flags & FontReopen))
1446 {
1447
1448 newid = GetNewFontClientID();
1449
1450 /* make the font */
1451 newfont = (FontPtr) xalloc(sizeof(FontRec));
1452
1453 /* and the FS data */
1454 fsd = (FSFontDataPtr) xalloc(sizeof(FSFontDataRec));
1455
1456 fsfont = (FSFontPtr) xalloc(sizeof(FSFontRec));
1457
1458 fontname = (char *)xalloc(namelen);
1459
1460 if (!newfont || !fsd || !fsfont || !fontname) {
1461 lowmem:
1462 if (!(flags & FontReopen))
1463 {
1464 xfree((char *) newfont);
1465 xfree((char *) fsd);
1466 xfree((char *) fsfont);
1467 xfree((char *) fontname);
1468 }
1469 if (blockrec) fs_abort_blockrec(conn, blockrec);
1470 return AllocError;
1471 }
1472 bzero((char *) newfont, sizeof(FontRec));
1473 bzero((char *) fsfont, sizeof(FSFontRec));
1474 bzero((char *) fsd, sizeof(FSFontDataRec));
1475 }
1476
1477 /* make a new block record, and add it to the end of the list */
1478 blockrec = fs_new_block_rec(fpe, client, FS_OPEN_FONT);
1479 if (!blockrec) {
1480 goto lowmem;
1481 }
1482
1483 if (!(flags & FontReopen))
1484 {
1485 int bit, byte, scan, glyph;
1486
1487 newfont->refcnt = 0;
1488 newfont->maxPrivate = -1;
1489 newfont->devPrivates = (pointer *) 0;
1490 newfont->format = format;
1491
1492 /* These font components will be needed in packGlyphs */
1493 CheckFSFormat(format, BitmapFormatMaskBit |
1494 BitmapFormatMaskByte |
1495 BitmapFormatMaskScanLineUnit |
1496 BitmapFormatMaskScanLinePad,
1497 &bit,
1498 &byte,
1499 &scan,
1500 &glyph,
1501 NULL);
1502 newfont->bit = bit;
1503 newfont->byte = byte;
1504 newfont->scan = scan;
1505 newfont->glyph = glyph;
1506
1507 newfont->fpe = fpe;
1508 newfont->fpePrivate = (pointer) fsd;
1509 newfont->fontPrivate = (pointer) fsfont;
1510 _fs_init_font(newfont);
1511
1512 fsd->fpe = fpe;
1513 fsd->name = fontname;
1514 fsd->namelen = namelen;
1515 memcpy(fontname, name, namelen);
1516 fsd->format = format;
1517 fsd->fmask = fmask;
1518 }
1519 fsd->fontid = newid;
1520 fsd->generation = conn->generation;
1521
1522 blockedfont = (FSBlockedFontPtr) blockrec->data;
1523 blockedfont->fontid = newid;
1524 blockedfont->pfont = newfont;
1525 blockedfont->state = FS_OPEN_REPLY;
1526 blockedfont->flags = flags;
1527 blockedfont->format = format;
1528 blockedfont->clients_depending = (FSClientsDependingPtr)0;
1529
1530 /* save the ID */
1531 if (!StoreFontClientFont(blockedfont->pfont, blockedfont->fontid)) {
1532 goto lowmem;
1533 }
1534 /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
1535 buf[0] = (unsigned char) namelen;
1536 memcpy(&buf[1], name, namelen);
1537 namelen++;
1538 openreq.reqType = FS_OpenBitmapFont;
1539 openreq.fid = newid;
1540 openreq.format_hint = format;
1541 openreq.format_mask = fmask;
1542 openreq.length = (SIZEOF(fsOpenBitmapFontReq) + namelen + 3) >> 2;
1543
1544 _fs_add_req_log(conn, FS_OpenBitmapFont);
1545 _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq));
1546 _fs_write_pad(conn, (char *) buf, namelen);
1547
1548 #ifdef NCD
1549 if (configData.ExtendedFontDiags) {
1550 memcpy(buf, name, MIN(256, namelen));
1551 buf[MIN(256, namelen)] = '\0';
1552 printf("Requesting font \"%s\" from font server \"%s\"\n",
1553 buf, fpe->name);
1554 }
1555 #endif
1556
1557 if (flags & FontOpenSync) {
1558 err = fs_do_open_font(fpe, blockrec, TRUE);
1559 if (blockedfont->errcode == Successful) {
1560 *ppfont = blockedfont->pfont;
1561 } else {
1562 _fs_cleanup_font(blockedfont);
1563 }
1564 _fs_remove_block_rec(conn, blockrec);
1565 }
1566 return err;
1567 }
1568
1569 static int
fs_send_query_info(fpe,blockrec)1570 fs_send_query_info(fpe, blockrec)
1571 FontPathElementPtr fpe;
1572 FSBlockDataPtr blockrec;
1573 {
1574 FSBlockedFontPtr bfont;
1575 FSFpePtr conn = (FSFpePtr) fpe->private;
1576 fsQueryXInfoReq inforeq;
1577
1578 bfont = (FSBlockedFontPtr) blockrec->data;
1579
1580 inforeq.reqType = FS_QueryXInfo;
1581 inforeq.id = bfont->fontid;
1582 inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
1583
1584 blockrec->sequence_number = conn->current_seq;
1585 _fs_add_req_log(conn, FS_QueryXInfo);
1586 _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
1587
1588 return Successful;
1589 }
1590
1591 static int
fs_send_query_extents(fpe,blockrec)1592 fs_send_query_extents(fpe, blockrec)
1593 FontPathElementPtr fpe;
1594 FSBlockDataPtr blockrec;
1595 {
1596 FSBlockedFontPtr bfont;
1597 FSFpePtr conn = (FSFpePtr) fpe->private;
1598 fsQueryXExtents16Req extreq;
1599
1600 bfont = (FSBlockedFontPtr) blockrec->data;
1601
1602 extreq.reqType = FS_QueryXExtents16;
1603 extreq.range = fsTrue;
1604 extreq.fid = bfont->fontid;
1605 extreq.num_ranges = 0;
1606 extreq.length = SIZEOF(fsQueryXExtents16Req) >> 2;
1607
1608 blockrec->sequence_number = conn->current_seq;
1609 _fs_add_req_log(conn, FS_QueryXExtents16);
1610 _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
1611
1612 return Successful;
1613 }
1614
1615 static int
fs_send_query_bitmaps(fpe,blockrec)1616 fs_send_query_bitmaps(fpe, blockrec)
1617 FontPathElementPtr fpe;
1618 FSBlockDataPtr blockrec;
1619 {
1620 FSBlockedFontPtr bfont;
1621 FSFpePtr conn = (FSFpePtr) fpe->private;
1622 fsQueryXBitmaps16Req bitreq;
1623
1624
1625 bfont = (FSBlockedFontPtr) blockrec->data;
1626
1627 /* send the request */
1628 bitreq.reqType = FS_QueryXBitmaps16;
1629 bitreq.fid = bfont->fontid;
1630 bitreq.format = bfont->format;
1631 bitreq.range = TRUE;
1632 bitreq.length = SIZEOF(fsQueryXBitmaps16Req) >> 2;
1633 bitreq.num_ranges = 0;
1634
1635 blockrec->sequence_number = conn->current_seq;
1636 _fs_add_req_log(conn, FS_QueryXBitmaps16);
1637 _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
1638
1639 return Successful;
1640 }
1641
1642 /* ARGSUSED */
1643 static int
fs_open_font(client,fpe,flags,name,namelen,format,fmask,id,ppfont,alias,non_cachable_font)1644 fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
1645 alias, non_cachable_font)
1646 pointer client;
1647 FontPathElementPtr fpe;
1648 Mask flags;
1649 char *name;
1650 fsBitmapFormat format;
1651 fsBitmapFormatMask fmask;
1652 int namelen;
1653 XID id;
1654 FontPtr *ppfont;
1655 char **alias;
1656 FontPtr non_cachable_font; /* Not used in this FPE */
1657 {
1658 FSFpePtr conn = (FSFpePtr) fpe->private;
1659 FSBlockDataPtr blockrec;
1660 FSBlockedFontPtr blockedfont;
1661 int err;
1662
1663 /* libfont interface expects ImageRectMin glyphs */
1664 format = format & ~BitmapFormatImageRectMask | BitmapFormatImageRectMin;
1665
1666 *alias = (char *) 0;
1667 /* XX if we find the blockrec for the font */
1668 blockrec = (FSBlockDataPtr) conn->blocked_requests;
1669 while (blockrec != (FSBlockDataPtr) 0) {
1670 if (blockrec->type == FS_OPEN_FONT &&
1671 blockrec->client == client) {
1672 blockedfont = (FSBlockedFontPtr) blockrec->data;
1673 err = blockedfont->errcode;
1674 if (err == Successful) {
1675 *ppfont = blockedfont->pfont;
1676 } else {
1677 _fs_cleanup_font(blockedfont);
1678 }
1679 /* cleanup */
1680 _fs_remove_block_rec(conn, blockrec);
1681 return err;
1682 }
1683 blockrec = blockrec->next;
1684 }
1685 return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
1686 id, ppfont);
1687 }
1688
1689 /* ARGSUSED */
1690 static int
fs_send_close_font(fpe,id)1691 fs_send_close_font(fpe, id)
1692 FontPathElementPtr fpe;
1693 Font id;
1694 {
1695 FSFpePtr conn = (FSFpePtr) fpe->private;
1696 fsCloseReq req;
1697
1698 /* tell the font server to close the font */
1699 req.reqType = FS_CloseFont;
1700 req.length = SIZEOF(fsCloseReq) >> 2;
1701 req.id = id;
1702 _fs_add_req_log(conn, FS_CloseFont);
1703 _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq));
1704
1705 return Successful;
1706 }
1707
1708 /* ARGSUSED */
1709 static int
fs_close_font(fpe,pfont)1710 fs_close_font(fpe, pfont)
1711 FontPathElementPtr fpe;
1712 FontPtr pfont;
1713 {
1714 FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
1715 FSFpePtr conn = (FSFpePtr) fpe->private;
1716
1717 /* XXX we may get called after the resource DB has been cleaned out */
1718 if (find_old_font(fsd->fontid))
1719 DeleteFontClientID(fsd->fontid);
1720 if (conn->generation == fsd->generation)
1721 fs_send_close_font(fpe, fsd->fontid);
1722 (*pfont->unload_font) (pfont);
1723
1724
1725 xfree(fsd->name);
1726 xfree(fsd);
1727 xfree(pfont->info.isStringProp);
1728 xfree(pfont->info.props);
1729 xfree(pfont->devPrivates);
1730 xfree(pfont);
1731
1732
1733 return Successful;
1734 }
1735
1736 static int
fs_read_glyphs(fpe,blockrec)1737 fs_read_glyphs(fpe, blockrec)
1738 FontPathElementPtr fpe;
1739 FSBlockDataPtr blockrec;
1740 {
1741 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr) blockrec->data;
1742 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1743 FSFpePtr conn = (FSFpePtr) fpe->private;
1744 FontPtr pfont = bglyph->pfont; /* works for either blocked font
1745 or glyph rec... pfont is at
1746 the very beginning of both
1747 blockrec->data structures */
1748 FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
1749 FSFontPtr fsdata = (FSFontPtr) pfont->fontPrivate;
1750 FontInfoPtr pfi = &pfont->info;
1751 fsQueryXBitmaps16Reply rep;
1752 fsOffset32 *ppbits;
1753 fsOffset32 local_off;
1754 char *off_adr;
1755 pointer pbitmaps;
1756 char *bits;
1757 int glyph_size,
1758 offset_size,
1759 i,
1760 err;
1761 int nranges = 0;
1762 fsRange *ranges, *nextrange;
1763 unsigned long minchar, maxchar;
1764
1765 /* get reply header */
1766 memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
1767 if (rep.type == FS_Error) {
1768 /* XXX -- translate FS error */
1769 _fs_eat_rest_of_error(conn, (fsError *) & rep);
1770 err = AllocError;
1771 goto bail;
1772 }
1773 if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
1774 SIZEOF(fsQueryXBitmaps16Reply) - SIZEOF(fsGenericReply)) == -1) {
1775 if (blockrec->type == FS_OPEN_FONT)
1776 fs_free_font(bfont);
1777 return StillWorking;
1778 }
1779 /* allocate space for glyphs */
1780 offset_size = SIZEOF(fsOffset32) * (rep.num_chars);
1781 glyph_size = (rep.length << 2) - SIZEOF(fsQueryXBitmaps16Reply)
1782 - offset_size;
1783 ppbits = (fsOffset32 *) xalloc(offset_size);
1784 pbitmaps = (pointer) xalloc(glyph_size);
1785 if (glyph_size && !pbitmaps || !ppbits)
1786 {
1787 xfree(pbitmaps);
1788 xfree(ppbits);
1789
1790 /* clear wire */
1791 (void) _fs_drain_bytes_pad(conn, offset_size);
1792 (void) _fs_drain_bytes_pad(conn, glyph_size);
1793
1794 if (blockrec->type == FS_OPEN_FONT)
1795 _fs_cleanup_font(bfont);
1796 err = AllocError;
1797 goto bail;
1798 }
1799
1800 /* read offsets */
1801 if (_fs_read_pad(conn, (char *) ppbits, offset_size) == -1) {
1802 if (blockrec->type == FS_OPEN_FONT)
1803 fs_free_font(bfont);
1804 return StillWorking;
1805 }
1806
1807 /* read glyphs */
1808 if (_fs_read_pad(conn, (char *) pbitmaps, glyph_size) == -1) {
1809 if (blockrec->type == FS_OPEN_FONT)
1810 fs_free_font(bfont);
1811 return StillWorking;
1812 }
1813
1814 if (blockrec->type == FS_LOAD_GLYPHS)
1815 {
1816 nranges = bglyph->num_expected_ranges;
1817 nextrange = ranges = bglyph->expected_ranges;
1818 }
1819
1820 /* place the incoming glyphs */
1821 if (nranges)
1822 {
1823 /* We're operating under the assumption that the ranges
1824 requested in the LoadGlyphs call were all legal for this
1825 font, and that individual ranges do not cover multiple
1826 rows... fs_build_range() is designed to ensure this. */
1827 minchar = (nextrange->min_char_high - pfi->firstRow) *
1828 (pfi->lastCol - pfi->firstCol + 1) +
1829 nextrange->min_char_low - pfi->firstCol;
1830 maxchar = (nextrange->max_char_high - pfi->firstRow) *
1831 (pfi->lastCol - pfi->firstCol + 1) +
1832 nextrange->max_char_low - pfi->firstCol;
1833 nextrange++;
1834 }
1835 else
1836 {
1837 minchar = 0;
1838 maxchar = rep.num_chars;
1839 }
1840
1841 off_adr = (char *)ppbits;
1842 for (i = 0; i < rep.num_chars; i++)
1843 {
1844 memcpy(&local_off, off_adr, SIZEOF(fsOffset32)); /* align it */
1845 if (blockrec->type == FS_OPEN_FONT ||
1846 fsdata->encoding[minchar].bits == &_fs_glyph_requested)
1847 {
1848 if (local_off.length)
1849 {
1850 bits = (char *)xalloc(local_off.length);
1851 if (bits == NULL)
1852 {
1853 xfree(ppbits);
1854 xfree(pbitmaps);
1855 err = AllocError;
1856 goto bail;
1857 }
1858 memcpy(bits, pbitmaps + local_off.position,
1859 local_off.length);
1860 }
1861 else if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
1862 bits = &_fs_glyph_zero_length;
1863 else
1864 bits = 0;
1865 if (fsdata->encoding[minchar].bits == &_fs_glyph_requested)
1866 fsd->glyphs_to_get--;
1867 fsdata->encoding[minchar].bits = bits;
1868 }
1869 if (minchar++ == maxchar)
1870 {
1871 if (!--nranges) break;
1872 minchar = (nextrange->min_char_high - pfi->firstRow) *
1873 (pfi->lastCol - pfi->firstCol + 1) +
1874 nextrange->min_char_low - pfi->firstCol;
1875 maxchar = (nextrange->max_char_high - pfi->firstRow) *
1876 (pfi->lastCol - pfi->firstCol + 1) +
1877 nextrange->max_char_low - pfi->firstCol;
1878 nextrange++;
1879 }
1880 off_adr += SIZEOF(fsOffset32);
1881 }
1882
1883 xfree(ppbits);
1884 xfree(pbitmaps);
1885
1886 if (blockrec->type == FS_OPEN_FONT)
1887 {
1888 fsd->glyphs_to_get = 0;
1889 bfont->state = FS_DONE_REPLY;
1890 }
1891 err = Successful;
1892
1893 bail:
1894 if (blockrec->type == FS_LOAD_GLYPHS)
1895 {
1896 bglyph->done = TRUE;
1897 bglyph->errcode = err;
1898 }
1899
1900 return err;
1901 }
1902
1903
1904
1905 static int
fs_send_load_glyphs(client,pfont,nranges,ranges)1906 fs_send_load_glyphs(client, pfont, nranges, ranges)
1907 pointer client;
1908 FontPtr pfont;
1909 int nranges;
1910 fsRange *ranges;
1911 {
1912 FSBlockedGlyphPtr blockedglyph;
1913 fsQueryXBitmaps16Req req;
1914 FSFontDataPtr fsd = (FSFontDataPtr) (pfont->fpePrivate);
1915 FontPathElementPtr fpe = fsd->fpe;
1916 FSFpePtr conn = (FSFpePtr) fpe->private;
1917 FSBlockDataPtr blockrec;
1918
1919 /* make a new block record, and add it to the end of the list */
1920 blockrec = fs_new_block_rec(fpe, client, FS_LOAD_GLYPHS);
1921 if (!blockrec)
1922 return AllocError;
1923 blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
1924 blockedglyph->pfont = pfont;
1925 blockedglyph->num_expected_ranges = nranges;
1926 /* Assumption: it's our job to free ranges */
1927 blockedglyph->expected_ranges = ranges;
1928 blockedglyph->done = FALSE;
1929 blockedglyph->clients_depending = (FSClientsDependingPtr)0;
1930
1931 blockrec->sequence_number = conn->current_seq;
1932
1933 /* send the request */
1934 req.reqType = FS_QueryXBitmaps16;
1935 req.fid = ((FSFontDataPtr) pfont->fpePrivate)->fontid;
1936 req.format = pfont->format;
1937 if (pfont->info.terminalFont)
1938 req.format = req.format & ~(BitmapFormatImageRectMask) |
1939 BitmapFormatImageRectMax;
1940 req.range = TRUE;
1941 /* each range takes up 4 bytes */
1942 req.length = (SIZEOF(fsQueryXBitmaps16Req) >> 2) + nranges;
1943 req.num_ranges = nranges * 2; /* protocol wants count of fsChar2bs */
1944 _fs_add_req_log(conn, FS_QueryXBitmaps16);
1945 _fs_write(conn, (char *) &req, SIZEOF(fsQueryXBitmaps16Req));
1946
1947 /* Send ranges to the server... pack into a char array by hand
1948 to avoid structure-packing portability problems and to
1949 handle swapping for version1 protocol */
1950 if (nranges)
1951 {
1952 #define RANGE_BUFFER_SIZE 64
1953 #define RANGE_BUFFER_SIZE_MASK 63
1954 int i;
1955 char range_buffer[RANGE_BUFFER_SIZE * 4];
1956 char *range_buffer_p;
1957
1958 range_buffer_p = range_buffer;
1959 for (i = 0; i < nranges;)
1960 {
1961 if (conn->fsMajorVersion > 1)
1962 {
1963 *range_buffer_p++ = ranges[i].min_char_high;
1964 *range_buffer_p++ = ranges[i].min_char_low;
1965 *range_buffer_p++ = ranges[i].max_char_high;
1966 *range_buffer_p++ = ranges[i].max_char_low;
1967 }
1968 else
1969 {
1970 *range_buffer_p++ = ranges[i].min_char_low;
1971 *range_buffer_p++ = ranges[i].min_char_high;
1972 *range_buffer_p++ = ranges[i].max_char_low;
1973 *range_buffer_p++ = ranges[i].max_char_high;
1974 }
1975
1976 if (!(++i & RANGE_BUFFER_SIZE_MASK))
1977 {
1978 _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4);
1979 range_buffer_p = range_buffer;
1980 }
1981 }
1982 if (i &= RANGE_BUFFER_SIZE_MASK)
1983 _fs_write(conn, range_buffer, i * 4);
1984 }
1985
1986 return Suspended;
1987 }
1988
1989
1990 int
fs_load_all_glyphs(pfont)1991 fs_load_all_glyphs(pfont)
1992 FontPtr pfont;
1993 {
1994 extern pointer serverClient; /* This could be any number that
1995 doesn't conflict with existing
1996 client values. */
1997 int err;
1998 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
1999
2000 /*
2001 * The purpose of this procedure is to load all glyphs in the event
2002 * that we're dealing with someone who doesn't understand the finer
2003 * points of glyph caching... it is called from _fs_get_glyphs() if
2004 * the latter is called to get glyphs that have not yet been loaded.
2005 * We assume that the caller will not know how to handle a return
2006 * value of Suspended (usually the case for a GetGlyphs() caller),
2007 * so this procedure hangs around, freezing the server, for the
2008 * request to complete. This is an unpleasant kluge called to
2009 * perform an unpleasant job that, we hope, will never be required.
2010 */
2011
2012 while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) ==
2013 Suspended)
2014 {
2015 fd_set TempSelectMask;
2016 if (_fs_wait_for_readable(conn) == -1)
2017 {
2018 /* We lost our connection. Don't wait to reestablish it;
2019 just give up. */
2020 _fs_connection_died(conn);
2021
2022 /* Get rid of blockrec */
2023 fs_client_died(serverClient, pfont->fpe);
2024
2025 return BadCharRange; /* As good an error as any other */
2026 }
2027 FD_SET(conn->fs_fd, &TempSelectMask);
2028 fs_wakeup(pfont->fpe, &TempSelectMask);
2029 }
2030
2031 return err;
2032 }
2033
2034
2035 int
_fs_load_glyphs(client,pfont,range_flag,nchars,item_size,data)2036 _fs_load_glyphs(client, pfont, range_flag, nchars, item_size, data)
2037 pointer client;
2038 FontPtr pfont;
2039 Bool range_flag;
2040 unsigned int nchars;
2041 int item_size;
2042 unsigned char *data;
2043 {
2044
2045 int nranges = 0;
2046 fsRange *ranges = NULL;
2047 int res;
2048 FSBlockDataPtr blockrec;
2049 FSBlockedGlyphPtr blockedglyph;
2050 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
2051 FSClientsDependingPtr *clients_depending = NULL;
2052
2053 /* see if the result is already there */
2054
2055 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2056 while (blockrec) {
2057 if (blockrec->type == FS_LOAD_GLYPHS)
2058 {
2059 blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
2060 if (blockedglyph->pfont == pfont)
2061 {
2062 if (blockrec->client == client)
2063 {
2064 if (blockedglyph->done)
2065 {
2066 int errcode = blockedglyph->errcode;
2067 signal_clients_depending(&blockedglyph->
2068 clients_depending);
2069 _fs_remove_block_rec(conn, blockrec);
2070 return errcode;
2071 }
2072 else return Suspended;
2073 }
2074 /* We've found an existing LoadGlyphs blockrec for this
2075 font but for another client. Rather than build a
2076 blockrec for it now (which entails some complex
2077 maintenance), we'll add it to a queue of clients to
2078 be signalled when the existing LoadGlyphs is
2079 completed. */
2080 clients_depending = &blockedglyph->clients_depending;
2081 break;
2082 }
2083 }
2084 else if (blockrec->type == FS_OPEN_FONT)
2085 {
2086 FSBlockedFontPtr bfont;
2087 bfont = (FSBlockedFontPtr) blockrec->data;
2088 if (bfont->pfont == pfont)
2089 {
2090 if (blockrec->client == client)
2091 {
2092 if (bfont->state == FS_DONE_REPLY)
2093 {
2094 int errcode = bfont->errcode;
2095 signal_clients_depending(&bfont->clients_depending);
2096 _fs_remove_block_rec(conn, blockrec);
2097 if (errcode == Successful) break;
2098 else return errcode;
2099 }
2100 else return Suspended;
2101 }
2102 /* We've found an existing OpenFont blockrec for this
2103 font but for another client. Rather than build a
2104 blockrec for it now (which entails some complex
2105 maintenance), we'll add it to a queue of clients to
2106 be signalled when the existing OpenFont is
2107 completed. */
2108 if (bfont->state != FS_DONE_REPLY)
2109 {
2110 clients_depending = &bfont->clients_depending;
2111 break;
2112 }
2113 }
2114 }
2115
2116 blockrec = blockrec->next;
2117 }
2118
2119 /*
2120 * see if the desired glyphs already exist, and return Successful if they
2121 * do, otherwise build up character range/character string
2122 */
2123 res = fs_build_range(pfont, range_flag, nchars, item_size, data,
2124 &nranges, &ranges);
2125
2126 switch (res)
2127 {
2128 case AccessDone:
2129 return Successful;
2130
2131 case Successful:
2132 break;
2133
2134 default:
2135 return res;
2136 }
2137
2138 /*
2139 * If clients_depending is not null, this request must wait for
2140 * some prior request(s) to complete.
2141 */
2142 if (clients_depending)
2143 {
2144 /* Since we're not ready to send the load_glyphs request yet,
2145 clean up the damage (if any) caused by the fs_build_range()
2146 call. */
2147 if (nranges)
2148 {
2149 _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2150 xfree(ranges);
2151 }
2152 return add_clients_depending(clients_depending, client);
2153 }
2154
2155 /*
2156 * If fsd->generation != conn->generation, the font has been closed
2157 * due to a lost connection. We will reopen it, which will result
2158 * in one of three things happening:
2159 * 1) The open will succeed and obtain the same font. Life
2160 * is wonderful.
2161 * 2) The open will fail. There is code above to recognize this
2162 * and flunk the LoadGlyphs request. The client might not be
2163 * thrilled.
2164 * 3) Worst case: the open will succeed but the font we open will
2165 * be different. The fs_read_query_info() procedure attempts
2166 * to detect this by comparing the existing metrics and
2167 * properties against those of the reopened font... if they
2168 * don't match, we flunk the reopen, which eventually results
2169 * in flunking the LoadGlyphs request. We could go a step
2170 * further and compare the extents, but this should be
2171 * sufficient.
2172 */
2173 if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation)
2174 {
2175 /* Since we're not ready to send the load_glyphs request yet,
2176 clean up the damage caused by the fs_build_range() call. */
2177 _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2178 xfree(ranges);
2179
2180 /* Now try to reopen the font. */
2181 return fs_send_open_font(client, (FontPathElementPtr)0,
2182 (Mask)FontReopen, (char *)0, 0,
2183 (fsBitmapFormat)0, (fsBitmapFormatMask)0,
2184 (XID)0, &pfont);
2185 }
2186
2187 return fs_send_load_glyphs(client, pfont, nranges, ranges);
2188 }
2189
2190
2191
2192 static int
fs_read_list(fpe,blockrec)2193 fs_read_list(fpe, blockrec)
2194 FontPathElementPtr fpe;
2195 FSBlockDataPtr blockrec;
2196 {
2197 FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
2198 FSFpePtr conn = (FSFpePtr) fpe->private;
2199 fsListFontsReply rep;
2200 char *data,
2201 *dp;
2202 int length,
2203 i;
2204
2205 blist->done = TRUE;
2206
2207 /* read reply header */
2208 memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
2209 if (rep.type == FS_Error) {
2210 /* XXX -- translate FS error */
2211 _fs_eat_rest_of_error(conn, (fsError *) & rep);
2212 return AllocError;
2213 }
2214 if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
2215 SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) == -1) {
2216 /* nothing to free (i think) */
2217 return StillWorking;
2218 }
2219 length = (rep.length << 2) - SIZEOF(fsListFontsReply);
2220 data = (char *) xalloc(length);
2221 if (!data) {
2222 _fs_drain_bytes_pad(conn, length);
2223 return AllocError;
2224 }
2225 /* read the list */
2226 if (_fs_read_pad(conn, data, length) == -1) {
2227 /* nothing to free (i think) */
2228 return StillWorking;
2229 }
2230 /* copy data into FontPathRecord */
2231 dp = data;
2232 for (i = 0; i < rep.nFonts; i++) {
2233 length = *(unsigned char *)dp++;
2234 if (AddFontNamesName(blist->names, dp, length) != Successful) {
2235 blist->errcode = AllocError;
2236 break;
2237 }
2238 dp += length;
2239 }
2240
2241 xfree(data);
2242 return Successful;
2243 }
2244
2245 static int
fs_send_list_fonts(client,fpe,pattern,patlen,maxnames,newnames)2246 fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2247 pointer client;
2248 FontPathElementPtr fpe;
2249 char *pattern;
2250 int patlen;
2251 int maxnames;
2252 FontNamesPtr newnames;
2253 {
2254 FSBlockDataPtr blockrec;
2255 FSBlockedListPtr blockedlist;
2256 FSFpePtr conn = (FSFpePtr) fpe->private;
2257 fsListFontsReq req;
2258
2259 _fs_client_access (conn, client, FALSE);
2260 _fs_client_resolution(conn);
2261
2262 /* make a new block record, and add it to the end of the list */
2263 blockrec = fs_new_block_rec(fpe, client, FS_LIST_FONTS);
2264 if (!blockrec)
2265 return AllocError;
2266 blockedlist = (FSBlockedListPtr) blockrec->data;
2267 blockedlist->patlen = patlen;
2268 blockedlist->errcode = Successful;
2269 blockedlist->names = newnames;
2270 blockedlist->done = FALSE;
2271
2272 /* send the request */
2273 req.reqType = FS_ListFonts;
2274 req.maxNames = maxnames;
2275 req.nbytes = patlen;
2276 req.length = (SIZEOF(fsListFontsReq) + patlen + 3) >> 2;
2277 _fs_add_req_log(conn, FS_ListFonts);
2278 _fs_write(conn, (char *) &req, SIZEOF(fsListFontsReq));
2279 _fs_write_pad(conn, (char *) pattern, patlen);
2280
2281 #ifdef NCD
2282 if (configData.ExtendedFontDiags) {
2283 char buf[256];
2284
2285 memcpy(buf, pattern, MIN(256, patlen));
2286 buf[MIN(256, patlen)] = '\0';
2287 printf("Listing fonts on pattern \"%s\" from font server \"%s\"\n",
2288 buf, fpe->name);
2289 }
2290 #endif
2291
2292 return Suspended;
2293 }
2294
2295 static int
fs_list_fonts(client,fpe,pattern,patlen,maxnames,newnames)2296 fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2297 pointer client;
2298 FontPathElementPtr fpe;
2299 char *pattern;
2300 int patlen;
2301 int maxnames;
2302 FontNamesPtr newnames;
2303 {
2304 FSBlockDataPtr blockrec;
2305 FSBlockedListPtr blockedlist;
2306 FSFpePtr conn = (FSFpePtr) fpe->private;
2307 int err;
2308
2309 /* see if the result is already there */
2310 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2311 while (blockrec) {
2312 if (blockrec->type == FS_LIST_FONTS && blockrec->client == client) {
2313 blockedlist = (FSBlockedListPtr) blockrec->data;
2314 if (blockedlist->patlen == patlen && blockedlist->done) {
2315 err = blockedlist->errcode;
2316 _fs_remove_block_rec(conn, blockrec);
2317 return err;
2318 }
2319 }
2320 blockrec = blockrec->next;
2321 }
2322
2323 /* didn't find waiting record, so send a new one */
2324 return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
2325 }
2326
2327 static int padlength[4] = {0, 3, 2, 1};
2328
2329 static int
fs_read_list_info(fpe,blockrec)2330 fs_read_list_info(fpe, blockrec)
2331 FontPathElementPtr fpe;
2332 FSBlockDataPtr blockrec;
2333 {
2334 FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
2335 fsListFontsWithXInfoReply rep;
2336 FSFpePtr conn = (FSFpePtr) fpe->private;
2337 fsPropInfo pi;
2338 fsPropOffset *po;
2339 char *name;
2340 pointer pd;
2341 int err;
2342
2343 /* clean up anything from the last trip */
2344 if (binfo->name)
2345 {
2346 xfree(binfo->name);
2347 binfo->name = NULL;
2348 }
2349 if (binfo->pfi) {
2350 xfree(binfo->pfi->isStringProp);
2351 xfree(binfo->pfi->props);
2352 xfree(binfo->pfi);
2353 binfo->pfi = NULL;
2354 }
2355 /* get reply header */
2356 memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
2357 if (rep.type == FS_Error) {
2358 /* XXX -- translate FS error */
2359 _fs_eat_rest_of_error(conn, (fsError *) & rep);
2360 binfo->errcode = AllocError;
2361 return AllocError;
2362 }
2363 if (conn->fsMajorVersion > 1)
2364 if (rep.nameLength == 0)
2365 goto done;
2366 /* old protocol sent a full-length reply even for the last one */
2367 if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
2368 SIZEOF(fsListFontsWithXInfoReply) - SIZEOF(fsGenericReply)) == -1) {
2369 goto done;
2370 }
2371 if (rep.nameLength == 0)
2372 goto done;
2373
2374 /* read the data */
2375 name = (char *) xalloc(rep.nameLength);
2376 binfo->pfi = (FontInfoPtr) xalloc(sizeof(FontInfoRec));
2377 if (!name || !binfo->pfi) {
2378 xfree(name);
2379 xfree(binfo->pfi);
2380 binfo->pfi = NULL;
2381 _fs_drain_bytes(conn,
2382 rep.length - (SIZEOF(fsListFontsWithXInfoReply) -
2383 SIZEOF(fsGenericReply)));
2384 binfo->errcode = AllocError;
2385 return AllocError;
2386 }
2387 if (conn->fsMajorVersion == 1)
2388 if (_fs_read_pad(conn, name, rep.nameLength) == -1)
2389 goto done;
2390 if (_fs_read_pad(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1)
2391 goto done;
2392
2393 po = (fsPropOffset *) xalloc(SIZEOF(fsPropOffset) * pi.num_offsets);
2394 pd = (pointer) xalloc(pi.data_len);
2395 if (!po || !pd) {
2396 xfree(name);
2397 xfree(po);
2398 xfree(pd);
2399 xfree (binfo->pfi);
2400 binfo->pfi = NULL;
2401 binfo->errcode = AllocError;
2402 return AllocError;
2403 }
2404 err = _fs_read_pad(conn, (char *) po,
2405 (pi.num_offsets * SIZEOF(fsPropOffset)));
2406 if (err != -1)
2407 {
2408 if (conn->fsMajorVersion > 1)
2409 err = _fs_read(conn, (char *) pd, pi.data_len);
2410 else
2411 err = _fs_read_pad(conn, (char *) pd, pi.data_len);
2412 }
2413 if (err != -1 && conn->fsMajorVersion != 1)
2414 {
2415 err = _fs_read(conn, name, rep.nameLength);
2416 if (err != -1)
2417 err = _fs_drain_bytes(conn, padlength[(pi.data_len+rep.nameLength)&3]);
2418 }
2419
2420 if (err == -1) {
2421 xfree(name);
2422 xfree(po);
2423 xfree(pd);
2424 xfree (binfo->pfi);
2425 binfo->pfi = NULL;
2426 goto done;
2427 }
2428
2429 if (_fs_convert_lfwi_reply(conn, binfo->pfi, &rep, &pi, po, pd) != Successful)
2430 {
2431 xfree(name);
2432 xfree(po);
2433 xfree(pd);
2434 xfree (binfo->pfi);
2435 binfo->pfi = NULL;
2436 goto done;
2437 }
2438 xfree(po);
2439 xfree(pd);
2440 binfo->name = name;
2441 binfo->namelen = rep.nameLength;
2442 binfo->remaining = rep.nReplies;
2443
2444 binfo->status = FS_LFWI_REPLY;
2445 binfo->errcode = Suspended;
2446 /* disable this font server until we've processed this response */
2447 FD_CLR(conn->fs_fd, &_fs_fd_mask);
2448
2449 return Successful;
2450
2451 done:
2452 binfo->status = FS_LFWI_FINISHED;
2453 binfo->errcode = BadFontName;
2454 binfo->name = (char *) 0;
2455 return Successful;
2456 }
2457
2458 /* ARGSUSED */
2459 static int
fs_start_list_with_info(client,fpe,pattern,len,maxnames,pdata)2460 fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2461 pointer client;
2462 FontPathElementPtr fpe;
2463 char *pattern;
2464 int len;
2465 int maxnames;
2466 pointer *pdata;
2467 {
2468 FSBlockDataPtr blockrec;
2469 FSBlockedListInfoPtr blockedinfo;
2470 fsListFontsWithXInfoReq req;
2471 FSFpePtr conn = (FSFpePtr) fpe->private;
2472
2473 _fs_client_access (conn, client, FALSE);
2474 _fs_client_resolution(conn);
2475
2476 /* make a new block record, and add it to the end of the list */
2477 blockrec = fs_new_block_rec(fpe, client, FS_LIST_WITH_INFO);
2478 if (!blockrec)
2479 return AllocError;
2480 blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2481 bzero((char *) blockedinfo, sizeof(FSBlockedListInfoRec));
2482 blockedinfo->status = FS_LFWI_WAITING;
2483 blockedinfo->errcode = Suspended;
2484
2485 /* send the request */
2486 req.reqType = FS_ListFontsWithXInfo;
2487 req.maxNames = maxnames;
2488 req.nbytes = len;
2489 req.length = (SIZEOF(fsListFontsWithXInfoReq) + len + 3) >> 2;
2490 _fs_add_req_log(conn, FS_ListFontsWithXInfo);
2491 (void) _fs_write(conn, (char *) &req, SIZEOF(fsListFontsWithXInfoReq));
2492 (void) _fs_write_pad(conn, pattern, len);
2493
2494 #ifdef NCD
2495 if (configData.ExtendedFontDiags) {
2496 char buf[256];
2497
2498 memcpy(buf, pattern, MIN(256, len));
2499 buf[MIN(256, len)] = '\0';
2500 printf("Listing fonts with info on pattern \"%s\" from font server \"%s\"\n",
2501 buf, fpe->name);
2502 }
2503 #endif
2504
2505 return Successful;
2506 }
2507
2508 /* ARGSUSED */
2509 static int
fs_next_list_with_info(client,fpe,namep,namelenp,pFontInfo,numFonts,private)2510 fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2511 private)
2512 pointer client;
2513 FontPathElementPtr fpe;
2514 char **namep;
2515 int *namelenp;
2516 FontInfoPtr *pFontInfo;
2517 int *numFonts;
2518 pointer private;
2519 {
2520 FSBlockDataPtr blockrec;
2521 FSBlockedListInfoPtr blockedinfo;
2522 FSFpePtr conn = (FSFpePtr) fpe->private;
2523
2524 /* see if the result is already there */
2525 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2526 while (blockrec) {
2527 if (blockrec->type == FS_LIST_WITH_INFO &&
2528 blockrec->client == client) {
2529 blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2530 break;
2531 }
2532 blockrec = blockrec->next;
2533 }
2534
2535 if (!blockrec)
2536 {
2537 /* The only good reason for not finding a blockrec would be if
2538 disconnect/reconnect to the font server wiped it out and the
2539 code that called us didn't do the right thing to create
2540 another one. Under those circumstances, we need to return an
2541 error to prevent that code from attempting to interpret the
2542 information we don't return. */
2543 return BadFontName;
2544 }
2545
2546 if (blockedinfo->status == FS_LFWI_WAITING)
2547 return Suspended;
2548
2549 *namep = blockedinfo->name;
2550 *namelenp = blockedinfo->namelen;
2551 *pFontInfo = blockedinfo->pfi;
2552 *numFonts = blockedinfo->remaining;
2553 FD_SET(conn->fs_fd, &_fs_fd_mask);
2554 if (blockedinfo->status == FS_LFWI_FINISHED) {
2555 int err = blockedinfo->errcode;
2556
2557 _fs_remove_block_rec(conn, blockrec);
2558 return err;
2559 }
2560 if (blockedinfo->status == FS_LFWI_REPLY) {
2561 blockedinfo->status = FS_LFWI_WAITING;
2562 return Successful;
2563 } else {
2564 return blockedinfo->errcode;
2565 }
2566 }
2567
2568 /*
2569 * Called when client exits
2570 */
2571
2572 static void
fs_client_died(client,fpe)2573 fs_client_died(client, fpe)
2574 pointer client;
2575 FontPathElementPtr fpe;
2576 {
2577 FSFpePtr conn = (FSFpePtr) fpe->private;
2578 FSBlockDataPtr blockrec,
2579 depending;
2580 FSClientPtr *prev, cur;
2581 fsFreeACReq freeac;
2582
2583 for (prev = &conn->clients; cur = *prev; prev = &cur->next)
2584 {
2585 if (cur->client == client) {
2586 freeac.reqType = FS_FreeAC;
2587 freeac.id = cur->acid;
2588 freeac.length = sizeof (fsFreeACReq) >> 2;
2589 _fs_add_req_log(conn, FS_FreeAC);
2590 _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2591 *prev = cur->next;
2592 xfree (cur);
2593 break;
2594 }
2595 }
2596 /* see if the result is already there */
2597 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2598 while (blockrec) {
2599 if (blockrec->client == client)
2600 break;
2601 blockrec = blockrec->next;
2602 }
2603 if (!blockrec)
2604 return;
2605 if (blockrec->type == FS_LIST_WITH_INFO)
2606 {
2607 FSBlockedListInfoPtr binfo;
2608 binfo = (FSBlockedListInfoPtr) blockrec->data;
2609 if (binfo->status == FS_LFWI_REPLY)
2610 FD_SET(conn->fs_fd, &_fs_fd_mask);
2611 if (binfo->name)
2612 {
2613 xfree(binfo->name);
2614 binfo->name = NULL;
2615 }
2616 if (binfo->pfi)
2617 {
2618 xfree(binfo->pfi->isStringProp);
2619 xfree(binfo->pfi->props);
2620 xfree(binfo->pfi);
2621 binfo->pfi = NULL;
2622 }
2623 }
2624 /* replace the client pointers in this block rec with the chained one */
2625 if (depending = blockrec->depending) {
2626 blockrec->client = depending->client;
2627 blockrec->depending = depending->depending;
2628 blockrec = depending;
2629 }
2630 fs_abort_blockrec(conn, blockrec);
2631 }
2632
2633 static void
_fs_client_access(conn,client,sync)2634 _fs_client_access (conn, client, sync)
2635 FSFpePtr conn;
2636 pointer client;
2637 Bool sync;
2638 {
2639 FSClientPtr *prev, cur;
2640 fsCreateACReq crac;
2641 fsSetAuthorizationReq setac;
2642 fsGenericReply rep;
2643 char *authorizations;
2644 int authlen;
2645 Bool new_cur = FALSE;
2646
2647 for (prev = &conn->clients; cur = *prev; prev = &cur->next)
2648 {
2649 if (cur->client == client)
2650 {
2651 if (prev != &conn->clients)
2652 {
2653 *prev = cur->next;
2654 cur->next = conn->clients;
2655 conn->clients = cur;
2656 }
2657 break;
2658 }
2659 }
2660 if (!cur)
2661 {
2662 cur = (FSClientPtr) xalloc (sizeof (FSClientRec));
2663 if (!cur)
2664 return;
2665 cur->client = client;
2666 cur->next = conn->clients;
2667 conn->clients = cur;
2668 cur->acid = GetNewFontClientID ();
2669 new_cur = TRUE;
2670 }
2671 if (new_cur || cur->auth_generation != client_auth_generation(client))
2672 {
2673 if (!new_cur)
2674 {
2675 fsFreeACReq freeac;
2676 freeac.reqType = FS_FreeAC;
2677 freeac.id = cur->acid;
2678 freeac.length = sizeof (fsFreeACReq) >> 2;
2679 _fs_add_req_log(conn, FS_FreeAC);
2680 _fs_write (conn, (char *) &freeac, sizeof (fsFreeACReq));
2681 }
2682 crac.reqType = FS_CreateAC;
2683 crac.num_auths = set_font_authorizations(&authorizations, &authlen,
2684 client);
2685 authlen = crac.num_auths ? (authlen + 3) & ~0x3 : 0;
2686 crac.length = (sizeof (fsCreateACReq) + authlen) >> 2;
2687 crac.acid = cur->acid;
2688 _fs_add_req_log(conn, FS_CreateAC);
2689 _fs_write(conn, (char *) &crac, sizeof (fsCreateACReq));
2690 _fs_write(conn, authorizations, authlen);
2691 /* if we're synchronous, open_font will be confused by
2692 * the reply; eat it and continue
2693 */
2694 if (sync)
2695 {
2696 if (_fs_read(conn, (char *) &rep, sizeof (fsGenericReply)) == -1)
2697 return;
2698 fs_handle_unexpected(conn, &rep);
2699 }
2700 /* ignore reply; we don't even care about it */
2701 conn->curacid = 0;
2702 cur->auth_generation = client_auth_generation(client);
2703 }
2704 if (conn->curacid != cur->acid)
2705 {
2706 setac.reqType = FS_SetAuthorization;
2707 setac.length = sizeof (fsSetAuthorizationReq) >> 2;
2708 setac.id = cur->acid;
2709 _fs_add_req_log(conn, FS_SetAuthorization);
2710 _fs_write(conn, (char *) &setac, sizeof (fsSetAuthorizationReq));
2711 conn->curacid = cur->acid;
2712 }
2713 }
2714
2715 /*
2716 * called at server init time
2717 */
2718
2719 void
fs_register_fpe_functions()2720 fs_register_fpe_functions()
2721 {
2722 fs_font_type = RegisterFPEFunctions(fs_name_check,
2723 fs_init_fpe,
2724 fs_free_fpe,
2725 fs_reset_fpe,
2726 fs_open_font,
2727 fs_close_font,
2728 fs_list_fonts,
2729 fs_start_list_with_info,
2730 fs_next_list_with_info,
2731 fs_wakeup,
2732 fs_client_died,
2733 _fs_load_glyphs,
2734 (int (*))0,
2735 (int (*))0,
2736 (void (*))0);
2737 }
2738
2739 static int
check_fs_open_font(client,fpe,flags,name,namelen,format,fmask,id,ppfont,alias,non_cachable_font)2740 check_fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
2741 alias, non_cachable_font)
2742 pointer client;
2743 FontPathElementPtr fpe;
2744 Mask flags;
2745 char *name;
2746 fsBitmapFormat format;
2747 fsBitmapFormatMask fmask;
2748 int namelen;
2749 XID id;
2750 FontPtr *ppfont;
2751 char **alias;
2752 FontPtr non_cachable_font; /* Not used in this FPE */
2753 {
2754 if (XpClientIsBitmapClient(client))
2755 return (fs_open_font(client, fpe, flags, name, namelen, format,
2756 fmask, id, ppfont, alias, non_cachable_font) );
2757 return BadFontName;
2758 }
2759
2760 static int
check_fs_list_fonts(client,fpe,pattern,patlen,maxnames,newnames)2761 check_fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2762 pointer client;
2763 FontPathElementPtr fpe;
2764 char *pattern;
2765 int patlen;
2766 int maxnames;
2767 FontNamesPtr newnames;
2768 {
2769 if (XpClientIsBitmapClient(client))
2770 return (fs_list_fonts(client, fpe, pattern, patlen, maxnames,
2771 newnames));
2772 return BadFontName;
2773 }
2774
2775 static int
check_fs_start_list_with_info(client,fpe,pattern,len,maxnames,pdata)2776 check_fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2777 pointer client;
2778 FontPathElementPtr fpe;
2779 char *pattern;
2780 int len;
2781 int maxnames;
2782 pointer *pdata;
2783 {
2784 if (XpClientIsBitmapClient(client))
2785 return (fs_start_list_with_info(client, fpe, pattern, len, maxnames,
2786 pdata));
2787 return BadFontName;
2788 }
2789
2790 static int
check_fs_next_list_with_info(client,fpe,namep,namelenp,pFontInfo,numFonts,private)2791 check_fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2792 private)
2793 pointer client;
2794 FontPathElementPtr fpe;
2795 char **namep;
2796 int *namelenp;
2797 FontInfoPtr *pFontInfo;
2798 int *numFonts;
2799 pointer private;
2800 {
2801 if (XpClientIsBitmapClient(client))
2802 return (fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo,
2803 numFonts,private));
2804 return BadFontName;
2805 }
2806
2807 void
check_fs_register_fpe_functions()2808 check_fs_register_fpe_functions()
2809 {
2810 fs_font_type = RegisterFPEFunctions(fs_name_check,
2811 fs_init_fpe,
2812 fs_free_fpe,
2813 fs_reset_fpe,
2814 check_fs_open_font,
2815 fs_close_font,
2816 check_fs_list_fonts,
2817 check_fs_start_list_with_info,
2818 check_fs_next_list_with_info,
2819 fs_wakeup,
2820 fs_client_died,
2821 _fs_load_glyphs,
2822 (int (*))0,
2823 (int (*))0,
2824 (void (*))0);
2825 }
2826