1 /* $TOG: fserve.c /main/49 1997/06/10 11:23:56 barstow $ */
4 Copyright (c) 1990 X Consortium
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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.
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.
28 /* $XFree86: xc/lib/font/fc/fserve.c,v 3.4.2.2 1997/06/11 12:08:41 dawes Exp $ */
31 * Copyright 1990 Network Computing Devices
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.
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
50 * Author: Dave Lemke, Network Computing Devices, Inc
53 * font server specific font access
61 #include "X11/Xpoll.h"
65 #include "fontstruct.h"
66 #include "fservestr.h"
68 #if defined(X_NOT_STDC_ENV) && !defined(__EMX__)
71 extern Time_t time ();
78 #include <ncd/nvram.h>
86 #define MIN(a,b) ((a)<(b)?(a):(b))
89 #define NONZEROMETRICS(pci) ((pci)->leftSideBearing || \
90 (pci)->rightSideBearing || \
93 (pci)->characterWidth)
96 extern FontPtr find_old_font();
98 extern int _fs_build_range();
100 static int fs_read_glyphs();
101 static int fs_read_list();
102 static int fs_read_list_info();
104 static int fs_font_type;
105 extern fd_set _fs_fd_mask;
107 static void fs_block_handler();
108 static int fs_wakeup();
110 static FSFpePtr awaiting_reconnect;
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();
123 char _fs_glyph_undefined;
124 char _fs_glyph_requested;
125 char _fs_glyph_zero_length;
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
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.
146 /* XXX this should probably be a macro once its fully debugged */
149 _fs_add_req_log(conn, opcode)
155 conn->reqbuffer[conn->reqindex++] = opcode;
156 if (conn->reqindex == REQUEST_LOG_SIZE)
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
172 if (name && isalpha(*name) && name[1] == ':')
175 /* Just make sure there is a protocol/ prefix */
176 return (name && *name != '/' && strchr(name, '/'));
180 _fs_client_resolution(conn)
183 fsSetResolutionReq srreq;
185 FontResolutionPtr res;
187 res = GetClientResolutions(&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;
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)));
203 * sends the stuff that's meaningful to a newly opened or reset FS
206 fs_send_init_packets(conn)
209 fsSetResolutionReq srreq;
210 fsSetCataloguesReq screq;
211 fsListCataloguesReq lcreq;
212 fsListCataloguesReply lcreply;
216 char *client_cat = (char *) 0,
221 FontResolutionPtr res;
222 int err = Successful;
224 #define CATALOGUE_SEP '+'
226 res = GetClientResolutions(&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;
233 _fs_add_req_log(conn, FS_SetResolution);
234 if (_fs_write(conn, (char *) &srreq, SIZEOF(fsSetResolutionReq)) == -1)
239 if (_fs_write_pad(conn, (char *) res, (num_res * SIZEOF(fsResolution))) == -1)
245 sp = strrchr(conn->servername, '/');
247 /* don't get tricked by a non-existant catalogue list */
248 if (sp == strchr(conn->servername, '/')) {
250 * try original name -- this might be an alternate with no catalogues
252 sp = strrchr(conn->requestedname, '/');
253 if (sp == strchr(conn->requestedname, '/'))
256 if (sp) { /* turn cats into counted list */
258 /* allocate more than enough room */
259 cp = client_cat = (char *) xalloc(strlen(conn->servername));
266 end = strchr(sp, CATALOGUE_SEP);
268 end = sp + strlen(sp);
269 *cp++ = len = end - sp;
271 memmove(cp, sp, len);
273 if (*sp == CATALOGUE_SEP)
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;
283 _fs_add_req_log(conn, FS_SetCatalogues);
284 if (_fs_write(conn, (char *) &screq, SIZEOF(fsSetCataloguesReq)) == -1)
289 if (_fs_write_pad(conn, (char *) client_cat, clen) == -1)
296 * now sync up with the font server, to see if an error was generated
297 * by a bogus catalogue
299 lcreq.reqType = FS_ListCatalogues;
300 lcreq.length = (SIZEOF(fsListCataloguesReq)) >> 2;
303 _fs_add_req_log(conn, FS_SetCatalogues);
304 if (_fs_write(conn, (char *) &lcreq, SIZEOF(fsListCataloguesReq)) == -1)
311 * next bit will either by the ListCats reply, or an error followed by
314 if (_fs_read(conn, (char *) &lcreply, SIZEOF(fsGenericReply)) == -1) {
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));
327 /* must be reply, swallow the rest of it */
328 _fs_eat_rest_of_error(conn, (fsError *) & lcreply);
336 * close font server and remove any state associated with
337 * this connection - this includes any client records.
344 FSClientPtr client, nclient;
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);
351 if (conn->fs_fd != -1)
352 FD_CLR(conn->fs_fd, &_fs_fd_mask);
354 for (client = conn->clients; client; client = nclient)
356 nclient = client->next;
359 conn->clients = NULL;
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
370 FontPathElementPtr fpe;
376 /* open font server */
377 /* create FS specific fpe info */
382 /* hack for old style names */
384 name++; /* skip ':' */
386 conn = _fs_open_server(name);
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) {
393 xfree(conn->servername);
398 if (init_fs_handlers(fpe, fs_block_handler) != Successful)
400 FD_SET(conn->fs_fd, &_fs_fd_mask);
401 conn->attemptReconnect = TRUE;
404 if (configData.ExtendedFontDiags)
405 printf("Connected to font server \"%s\"\n", name);
412 fprintf(stderr, "failed to connect to FS \"%s\"\n", name);
416 if (configData.ExtendedFontDiags)
417 printf("Failed to connect to font server \"%s\"\n", name);
420 return (errno == ENOMEM) ? AllocError : BadFontPath;
425 FontPathElementPtr fpe;
427 (void) fs_send_init_packets((FSFpePtr) fpe->private);
432 * this shouldn't be called till all refs to the FPE are gone
437 FontPathElementPtr fpe;
439 FSFpePtr conn = (FSFpePtr) fpe->private;
442 prev = &awaiting_reconnect;
446 *prev = recon->next_reconnect;
449 prev = &recon->next_reconnect;
454 remove_fs_handlers(fpe, fs_block_handler,
455 !XFD_ANYSET(&_fs_fd_mask) && !awaiting_reconnect);
458 xfree(conn->servername);
460 fpe->private = (pointer) 0;
463 if (configData.ExtendedFontDiags)
464 printf("Disconnected from font server \"%s\"\n", fpe->name);
470 static FSBlockDataPtr
471 fs_new_block_rec(fpe, client, type)
472 FontPathElementPtr fpe;
476 FSBlockDataPtr blockrec,
478 FSFpePtr fsfpe = (FSFpePtr) fpe->private;
481 blockrec = (FSBlockDataPtr) xalloc(sizeof(FSBlockDataRec));
483 return (FSBlockDataPtr) 0;
486 size = sizeof(FSBlockedFontRec);
489 size = sizeof(FSBlockedGlyphRec);
492 size = sizeof(FSBlockedListRec);
494 case FS_LIST_WITH_INFO:
495 size = sizeof(FSBlockedListInfoRec);
500 blockrec->data = (pointer) xalloc(size);
501 if (!blockrec->data) {
503 return (FSBlockDataPtr) 0;
505 blockrec->client = client;
506 blockrec->sequence_number = fsfpe->current_seq;
507 blockrec->type = type;
508 blockrec->depending = 0;
509 blockrec->next = (FSBlockDataPtr) 0;
511 /* stick it on the end of the list (since its expected last) */
512 br = (FSBlockDataPtr) fsfpe->blocked_requests;
514 fsfpe->blocked_requests = (pointer) blockrec;
525 _fs_remove_block_rec(conn, blockrec)
527 FSBlockDataPtr blockrec;
532 last = (FSBlockDataPtr) 0;
533 br = (FSBlockDataPtr) conn->blocked_requests;
535 if (br == blockrec) {
537 last->next = br->next;
539 conn->blocked_requests = (pointer) br->next;
540 if (br->type == FS_LOAD_GLYPHS)
542 FSBlockedGlyphPtr bglyph = (FSBlockedGlyphPtr)br->data;
543 if (bglyph->num_expected_ranges)
544 xfree(bglyph->expected_ranges);
556 signal_clients_depending(clients_depending)
557 FSClientsDependingPtr *clients_depending;
559 FSClientsDependingPtr p = *clients_depending, p2;
560 *clients_depending = (FSClientsDependingPtr)0;
562 while (p != (FSClientsDependingPtr)0)
565 ClientSignal(p->client);
572 add_clients_depending(clients_depending, client)
573 FSClientsDependingPtr *clients_depending;
576 while (*clients_depending != (FSClientsDependingPtr)0)
578 if ((*clients_depending)->client == client) return Suspended;
579 clients_depending = &(*clients_depending)->next;
581 *clients_depending = (FSClientsDependingPtr)xalloc(
582 sizeof(FSClientsDependingRec));
583 if (!*clients_depending)
586 (*clients_depending)->client = client;
587 (*clients_depending)->next = 0;
592 clean_aborted_blockrec(blockrec)
593 FSBlockDataPtr blockrec;
596 switch(blockrec->type)
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,
607 signal_clients_depending(&bglyph->clients_depending);
612 FSBlockedFontPtr bfont = (FSBlockedFontPtr)blockrec->data;
613 signal_clients_depending(&bfont->clients_depending);
622 fs_abort_blockrec(conn, blockrec)
624 FSBlockDataPtr blockrec;
626 clean_aborted_blockrec(blockrec);
627 _fs_remove_block_rec(conn, blockrec);
633 FSBlockedFontPtr bfont;
638 pfont = bfont->pfont;
639 fsd = (FSFontDataRec *) pfont->fpePrivate;
641 /* xfree better be able to handle NULL */
642 (*pfont->unload_font)(pfont);
643 DeleteFontClientID(fsd->fontid);
645 xfree(pfont->info.isStringProp);
646 xfree(pfont->info.props);
651 bfont->pfont = (FontPtr) 0;
655 _fs_cleanup_font(bfont)
656 FSBlockedFontPtr bfont;
662 fsd = (FSFontDataRec *) bfont->pfont->fpePrivate;
664 /* make sure the FS knows we choked on it */
665 fs_send_close_font(fsd->fpe, bfont->fontid);
669 bfont->errcode = AllocError;
674 fs_read_open_font(fpe, blockrec)
675 FontPathElementPtr fpe;
676 FSBlockDataPtr blockrec;
678 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
679 FSFpePtr conn = (FSFpePtr) fpe->private;
680 fsOpenBitmapFontReply rep;
681 FSBlockDataPtr blockOrig;
682 FSBlockedFontPtr origBfont;
684 /* pull out the OpenFont reply */
685 memcpy(&rep, &blockrec->header, SIZEOF(fsGenericReply));
687 if (rep.type == FS_Error) {
688 _fs_eat_rest_of_error(conn, (fsError *) & rep);
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);
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
709 if (rep.otherid && !(bfont->flags & FontReopen)) {
710 (void) fs_send_close_font(fpe, bfont->fontid);
712 /* Find old font if we're completely done getting it from server. */
714 bfont->pfont = find_old_font(rep.otherid);
715 bfont->fontid = rep.otherid;
716 bfont->state = FS_DONE_REPLY;
718 * look for a blocked request to open the same font
720 for (blockOrig = (FSBlockDataPtr) conn->blocked_requests;
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;
734 if (bfont->pfont == NULL)
736 /* XXX - something nasty happened */
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);
751 fs_read_query_info(fpe, blockrec)
752 FontPathElementPtr fpe;
753 FSBlockDataPtr blockrec;
755 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
756 FSFpePtr conn = (FSFpePtr) fpe->private;
757 fsQueryXInfoReply rep;
761 unsigned long prop_len;
762 FSBlockedFontRec newbfont, *oldbfont;
763 FontRec newpfont, *oldpfont;
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)
770 newbfont = *(oldbfont = bfont);
772 newpfont = *(oldpfont = oldbfont->pfont);
773 newpfont.info.isStringProp = NULL;
774 newpfont.info.props = NULL;
775 newbfont.pfont = &newpfont;
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;
787 /* move the data over */
788 fsUnpack_XFontInfoHeader(&rep, &bfont->pfont->info);
789 _fs_init_fontinfo(conn, &bfont->pfont->info);
791 if (bfont->pfont->info.terminalFont)
794 (bfont->format & ~ (BitmapFormatImageRectMask)) |
795 BitmapFormatImageRectMax;
798 if (_fs_read(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1) {
799 if (bfont->flags & FontReopen) goto bail;
803 prop_len = pi.num_offsets * SIZEOF(fsPropOffset);
804 po = (fsPropOffset *) xalloc(prop_len);
805 pd = (pointer) xalloc(pi.data_len);
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);
816 if (_fs_read_pad(conn, (char *) po, prop_len) == -1 ||
817 _fs_read_pad(conn, (char *) pd, pi.data_len) == -1) {
820 if (bfont->flags & FontReopen) goto bail;
824 if (_fs_convert_props(&pi, po, pd, &bfont->pfont->info) == -1)
828 if (bfont->flags & FontReopen) { err = AllocError ; goto bail; }
829 (void) _fs_cleanup_font(bfont);
835 if (bfont->flags & FontReopen)
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. */
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)
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))
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))
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)
895 if (err != Successful && err != StillWorking)
897 /* Failure. Close the font. */
898 fs_send_close_font(((FSFontDataPtr)oldpfont->fpePrivate)->fpe,
900 ((FSFontDataPtr)oldpfont->fpePrivate)->generation = -1;
902 xfree(newpfont.info.isStringProp);
903 xfree(newpfont.info.props);
905 if (err == Successful) oldbfont->state = FS_DONE_REPLY;
909 if (glyphCachingMode == CACHING_OFF ||
910 glyphCachingMode == CACHE_16_BIT_GLYPHS && !bfont->pfont->info.lastRow)
911 bfont->flags |= FontLoadAll;
913 bfont->state = FS_EXTENT_REPLY;
915 fs_send_query_extents(fpe, blockrec);
920 fs_read_extent_info(fpe, blockrec)
921 FontPathElementPtr fpe;
922 FSBlockDataPtr blockrec;
924 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
925 FSFontDataPtr fsd = (FSFontDataPtr) bfont->pfont->fpePrivate;
926 FSFpePtr conn = (FSFpePtr) fpe->private;
927 fsQueryXExtents16Reply rep;
930 Bool haveInk = FALSE; /* need separate ink metrics? */
933 FSFontPtr fsfont = (FSFontPtr) bfont->pfont->fontPrivate;
935 fsXCharInfo fscilocal;
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) {
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)
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);
959 /* clear the unusable data */
960 _fs_drain_bytes(conn, SIZEOF(fsXCharInfo) * rep.num_extents);
961 _fs_cleanup_font(bfont);
964 fsfont->encoding = pCI;
966 fsfont->inkMetrics = pCI + rep.num_extents;
968 fsfont->inkMetrics = pCI;
970 if (_fs_read_pad(conn, (char *) fsci,
971 SIZEOF(fsXCharInfo) * rep.num_extents) == -1) {
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))
987 (ci->metrics.leftSideBearing == ci->metrics.rightSideBearing ||
988 ci->metrics.ascent == -ci->metrics.descent))
989 pCI[i].bits = &_fs_glyph_zero_length;
992 pCI[i].bits = &_fs_glyph_undefined;
993 fsd->glyphs_to_get++;
997 pCI[i].bits = (char *)0;
1003 /* build bitmap metrics, ImageRectMax style */
1006 FontInfoRec *fi = &bfont->pfont->info;
1009 ci = fsfont->encoding;
1010 ii = fsfont->inkMetrics;
1011 for (i = 0; i < rep.num_extents; i++, ci++, ii++)
1013 if (NONZEROMETRICS(&ii->metrics))
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;
1024 ci->metrics = ii->metrics;
1029 unsigned int r, c, numCols, firstCol;
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)
1038 r -= bfont->pfont->info.firstRow;
1041 if (r < bfont->pfont->info.lastRow-bfont->pfont->info.firstRow+1 &&
1043 fsfont->pDefault = &pCI[r * numCols + c];
1049 fsfont->pDefault = &pCI[c];
1052 bfont->state = FS_GLYPHS_REPLY;
1054 if (bfont->flags & FontLoadBitmaps) {
1055 fs_send_query_bitmaps(fpe, blockrec);
1056 return StillWorking;
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
1066 fs_do_open_font(fpe, blockrec, readheader)
1067 FontPathElementPtr fpe;
1068 FSBlockDataPtr blockrec;
1071 FSBlockedFontPtr bfont = (FSBlockedFontPtr) blockrec->data;
1072 FSFpePtr conn = (FSFpePtr) fpe->private;
1075 switch (bfont->state) {
1078 /* get the next header */
1079 if (_fs_read(conn, (char *) &blockrec->header,
1080 SIZEOF(fsGenericReply)) == -1) {
1081 fs_free_font(bfont);
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) {
1091 bfont->errcode = Successful;
1094 bfont->errcode = StillWorking;
1097 err = bfont->errcode;
1100 /* if more data to read or Sync, fall thru, else return */
1101 if (!(bfont->flags & FontOpenSync)) {
1102 err = bfont->errcode;
1105 if (_fs_read(conn, (char *) &blockrec->header,
1106 SIZEOF(fsGenericReply)) == -1) {
1107 fs_free_font(bfont);
1114 bfont->errcode = fs_read_query_info(fpe, blockrec);
1115 if (bfont->errcode != StillWorking) {
1116 err = bfont->errcode;
1119 if (!(bfont->flags & FontOpenSync)) {
1120 err = bfont->errcode;
1122 /* if more data to read, fall thru, else return */
1124 if (_fs_read(conn, (char *) &blockrec->header,
1125 SIZEOF(fsGenericReply))) {
1126 fs_free_font(bfont);
1132 case FS_EXTENT_REPLY:
1133 bfont->errcode = fs_read_extent_info(fpe, blockrec);
1134 if (bfont->errcode != StillWorking) {
1135 err = bfont->errcode;
1138 if (!(bfont->flags & FontOpenSync)) {
1139 err = bfont->errcode;
1141 } else if (bfont->flags & FontLoadBitmaps) {
1142 if (_fs_read(conn, (char *) &blockrec->header,
1143 SIZEOF(fsGenericReply))) {
1144 fs_free_font(bfont);
1150 case FS_GLYPHS_REPLY:
1151 if (bfont->flags & FontLoadBitmaps) {
1152 bfont->errcode = fs_read_glyphs(fpe, blockrec);
1154 err = bfont->errcode;
1156 case FS_DEPENDING: /* can't happen */
1157 err = bfont->errcode;
1159 err = bfont->errcode;
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() */
1175 fs_block_handler(data, wt, LastSelectMask)
1177 struct timeval **wt;
1178 fd_set* LastSelectMask;
1180 static struct timeval recon_timeout;
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;
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;
1207 fs_handle_unexpected(conn, rep)
1209 fsGenericReply *rep;
1211 if (rep->type == FS_Event && rep->data1 == KeepAlive) {
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));
1220 /* this should suck up unexpected replies and events */
1221 _fs_eat_rest_of_error(conn, (fsError *) rep);
1225 fs_wakeup(fpe, LastSelectMask)
1226 FontPathElementPtr fpe;
1227 fd_set* LastSelectMask;
1229 FSBlockDataPtr blockrec,
1231 FSFpePtr conn = (FSFpePtr) fpe->private;
1235 if (awaiting_reconnect) {
1236 _fs_try_reconnect();
1238 /* see if there's any data to be read */
1241 * Don't continue if the fd is -1 (which will be true when the
1242 * font server terminates
1244 if (conn->fs_fd == -1)
1247 if (FD_ISSET(conn->fs_fd, LastSelectMask)) {
1249 #if defined(NOTDEF) || defined(__EMX__) /* bogus - doesn't deal with EOF very well,
1250 * now does it ... */
1252 * make sure it isn't spurious - mouse events seem to trigger extra
1253 * problems. Under OS/2, this is especially true ...
1255 if (_fs_data_ready(conn) <= 0) {
1260 /* get the header */
1261 if (_fs_read(conn, (char *) &rep, SIZEOF(fsGenericReply)) == -1)
1264 /* find the matching block record */
1266 for (br = (FSBlockDataPtr) conn->blocked_requests; br; br = br->next) {
1267 if ((CARD16)(br->sequence_number & 0xffff) ==
1268 (CARD16)(rep.sequenceNumber - 1))
1272 fs_handle_unexpected(conn, &rep);
1277 memcpy(&blockrec->header, &rep, SIZEOF(fsGenericReply));
1279 /* go read it, and if we're done, wake up the appropriate client */
1280 switch (blockrec->type) {
1282 err = fs_do_open_font(fpe, blockrec, FALSE);
1284 case FS_LOAD_GLYPHS:
1285 err = fs_read_glyphs(fpe, blockrec);
1288 err = fs_read_list(fpe, blockrec);
1290 case FS_LIST_WITH_INFO:
1291 err = fs_read_list_info(fpe, blockrec);
1297 if (err != StillWorking) {
1299 ClientSignal(blockrec->client);
1300 blockrec = blockrec->depending;
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
1307 } else if (awaiting_reconnect) {
1308 _fs_try_reconnect();
1318 _fs_connection_died(conn)
1321 if (!conn->attemptReconnect)
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;
1328 conn->trans_conn = NULL;
1329 conn->next_reconnect = awaiting_reconnect;
1330 awaiting_reconnect = conn;
1334 _fs_restart_connection(conn)
1337 FSBlockDataPtr block;
1339 conn->current_seq = 0;
1340 FD_SET(conn->fs_fd, &_fs_fd_mask);
1341 if (!fs_send_init_packets(conn))
1343 while (block = (FSBlockDataPtr) conn->blocked_requests) {
1344 ClientSignal(block->client);
1345 fs_abort_blockrec(conn, block);
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;
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;
1372 prev = &conn->next_reconnect;
1377 * sends the actual request out
1381 fs_send_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont)
1383 FontPathElementPtr fpe;
1387 fsBitmapFormat format;
1388 fsBitmapFormatMask fmask;
1393 FSBlockDataPtr blockrec = NULL;
1394 FSBlockedFontPtr blockedfont;
1398 fsOpenBitmapFontReq openreq;
1399 int err = Suspended;
1401 unsigned char buf[1024];
1404 if (flags & FontReopen)
1406 Atom nameatom, fn = None;
1410 fsd = (FSFontDataPtr)newfont->fpePrivate;
1411 fsfont = (FSFontPtr)newfont->fontPrivate;
1413 format = fsd->format;
1415 newid = fsd->fontid;
1416 /* This is an attempt to reopen a font. Did the font have a
1418 if ((nameatom = MakeAtom("FONT", 4, 0)) != None)
1420 for (i = 0; i < newfont->info.nprops; i++)
1421 if (newfont->info.props[i].name == nameatom &&
1422 newfont->info.isStringProp[i])
1424 fn = newfont->info.props[i].value;
1428 if (fn == None || !(name = NameForAtom(fn)))
1431 namelen = fsd->namelen;
1434 namelen = strlen(name);
1437 conn = (FSFpePtr) fpe->private;
1438 if (namelen > sizeof (buf) - 1)
1440 _fs_client_access (conn, client, (flags & FontOpenSync) != 0);
1441 _fs_client_resolution(conn);
1444 if (!(flags & FontReopen))
1447 newid = GetNewFontClientID();
1450 newfont = (FontPtr) xalloc(sizeof(FontRec));
1452 /* and the FS data */
1453 fsd = (FSFontDataPtr) xalloc(sizeof(FSFontDataRec));
1455 fsfont = (FSFontPtr) xalloc(sizeof(FSFontRec));
1457 fontname = (char *)xalloc(namelen);
1459 if (!newfont || !fsd || !fsfont || !fontname) {
1461 if (!(flags & FontReopen))
1463 xfree((char *) newfont);
1464 xfree((char *) fsd);
1465 xfree((char *) fsfont);
1466 xfree((char *) fontname);
1468 if (blockrec) fs_abort_blockrec(conn, blockrec);
1471 bzero((char *) newfont, sizeof(FontRec));
1472 bzero((char *) fsfont, sizeof(FSFontRec));
1473 bzero((char *) fsd, sizeof(FSFontDataRec));
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);
1482 if (!(flags & FontReopen))
1484 int bit, byte, scan, glyph;
1486 newfont->refcnt = 0;
1487 newfont->maxPrivate = -1;
1488 newfont->devPrivates = (pointer *) 0;
1489 newfont->format = format;
1491 /* These font components will be needed in packGlyphs */
1492 CheckFSFormat(format, BitmapFormatMaskBit |
1493 BitmapFormatMaskByte |
1494 BitmapFormatMaskScanLineUnit |
1495 BitmapFormatMaskScanLinePad,
1502 newfont->byte = byte;
1503 newfont->scan = scan;
1504 newfont->glyph = glyph;
1507 newfont->fpePrivate = (pointer) fsd;
1508 newfont->fontPrivate = (pointer) fsfont;
1509 _fs_init_font(newfont);
1512 fsd->name = fontname;
1513 fsd->namelen = namelen;
1514 memcpy(fontname, name, namelen);
1515 fsd->format = format;
1518 fsd->fontid = newid;
1519 fsd->generation = conn->generation;
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;
1530 if (!StoreFontClientFont(blockedfont->pfont, blockedfont->fontid)) {
1533 /* do an FS_OpenFont, FS_QueryXInfo and FS_QueryXExtents */
1534 buf[0] = (unsigned char) namelen;
1535 memcpy(&buf[1], name, 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;
1543 _fs_add_req_log(conn, FS_OpenBitmapFont);
1544 _fs_write(conn, (char *) &openreq, SIZEOF(fsOpenBitmapFontReq));
1545 _fs_write_pad(conn, (char *) buf, namelen);
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",
1556 if (flags & FontOpenSync) {
1557 err = fs_do_open_font(fpe, blockrec, TRUE);
1558 if (blockedfont->errcode == Successful) {
1559 *ppfont = blockedfont->pfont;
1561 _fs_cleanup_font(blockedfont);
1563 _fs_remove_block_rec(conn, blockrec);
1569 fs_send_query_info(fpe, blockrec)
1570 FontPathElementPtr fpe;
1571 FSBlockDataPtr blockrec;
1573 FSBlockedFontPtr bfont;
1574 FSFpePtr conn = (FSFpePtr) fpe->private;
1575 fsQueryXInfoReq inforeq;
1577 bfont = (FSBlockedFontPtr) blockrec->data;
1579 inforeq.reqType = FS_QueryXInfo;
1580 inforeq.id = bfont->fontid;
1581 inforeq.length = SIZEOF(fsQueryXInfoReq) >> 2;
1583 blockrec->sequence_number = conn->current_seq;
1584 _fs_add_req_log(conn, FS_QueryXInfo);
1585 _fs_write(conn, (char *) &inforeq, SIZEOF(fsQueryXInfoReq));
1591 fs_send_query_extents(fpe, blockrec)
1592 FontPathElementPtr fpe;
1593 FSBlockDataPtr blockrec;
1595 FSBlockedFontPtr bfont;
1596 FSFpePtr conn = (FSFpePtr) fpe->private;
1597 fsQueryXExtents16Req extreq;
1599 bfont = (FSBlockedFontPtr) blockrec->data;
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;
1607 blockrec->sequence_number = conn->current_seq;
1608 _fs_add_req_log(conn, FS_QueryXExtents16);
1609 _fs_write(conn, (char *) &extreq, SIZEOF(fsQueryXExtents16Req));
1615 fs_send_query_bitmaps(fpe, blockrec)
1616 FontPathElementPtr fpe;
1617 FSBlockDataPtr blockrec;
1619 FSBlockedFontPtr bfont;
1620 FSFpePtr conn = (FSFpePtr) fpe->private;
1621 fsQueryXBitmaps16Req bitreq;
1624 bfont = (FSBlockedFontPtr) blockrec->data;
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;
1634 blockrec->sequence_number = conn->current_seq;
1635 _fs_add_req_log(conn, FS_QueryXBitmaps16);
1636 _fs_write(conn, (char *) &bitreq, SIZEOF(fsQueryXBitmaps16Req));
1643 fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
1644 alias, non_cachable_font)
1646 FontPathElementPtr fpe;
1649 fsBitmapFormat format;
1650 fsBitmapFormatMask fmask;
1655 FontPtr non_cachable_font; /* Not used in this FPE */
1657 FSFpePtr conn = (FSFpePtr) fpe->private;
1658 FSBlockDataPtr blockrec;
1659 FSBlockedFontPtr blockedfont;
1662 /* libfont interface expects ImageRectMin glyphs */
1663 format = format & ~BitmapFormatImageRectMask | BitmapFormatImageRectMin;
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;
1676 _fs_cleanup_font(blockedfont);
1679 _fs_remove_block_rec(conn, blockrec);
1682 blockrec = blockrec->next;
1684 return fs_send_open_font(client, fpe, flags, name, namelen, format, fmask,
1690 fs_send_close_font(fpe, id)
1691 FontPathElementPtr fpe;
1694 FSFpePtr conn = (FSFpePtr) fpe->private;
1697 /* tell the font server to close the font */
1698 req.reqType = FS_CloseFont;
1699 req.length = SIZEOF(fsCloseReq) >> 2;
1701 _fs_add_req_log(conn, FS_CloseFont);
1702 _fs_write(conn, (char *) &req, SIZEOF(fsCloseReq));
1709 fs_close_font(fpe, pfont)
1710 FontPathElementPtr fpe;
1713 FSFontDataPtr fsd = (FSFontDataPtr) pfont->fpePrivate;
1714 FSFpePtr conn = (FSFpePtr) fpe->private;
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);
1726 xfree(pfont->info.isStringProp);
1727 xfree(pfont->info.props);
1728 xfree(pfont->devPrivates);
1736 fs_read_glyphs(fpe, blockrec)
1737 FontPathElementPtr fpe;
1738 FSBlockDataPtr blockrec;
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;
1752 fsOffset32 local_off;
1761 fsRange *ranges, *nextrange;
1762 unsigned long minchar, maxchar;
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);
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;
1778 /* allocate space for glyphs */
1779 offset_size = SIZEOF(fsOffset32) * (rep.num_chars);
1780 glyph_size = (rep.length << 2) - SIZEOF(fsQueryXBitmaps16Reply)
1782 ppbits = (fsOffset32 *) xalloc(offset_size);
1783 pbitmaps = (pointer) xalloc(glyph_size);
1784 if (glyph_size && !pbitmaps || !ppbits)
1790 (void) _fs_drain_bytes_pad(conn, offset_size);
1791 (void) _fs_drain_bytes_pad(conn, glyph_size);
1793 if (blockrec->type == FS_OPEN_FONT)
1794 _fs_cleanup_font(bfont);
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;
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;
1813 if (blockrec->type == FS_LOAD_GLYPHS)
1815 nranges = bglyph->num_expected_ranges;
1816 nextrange = ranges = bglyph->expected_ranges;
1819 /* place the incoming glyphs */
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;
1837 maxchar = rep.num_chars;
1840 off_adr = (char *)ppbits;
1841 for (i = 0; i < rep.num_chars; i++)
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)
1847 if (local_off.length)
1849 bits = (char *)xalloc(local_off.length);
1857 memcpy(bits, pbitmaps + local_off.position,
1860 else if (NONZEROMETRICS(&fsdata->encoding[minchar].metrics))
1861 bits = &_fs_glyph_zero_length;
1864 if (fsdata->encoding[minchar].bits == &_fs_glyph_requested)
1865 fsd->glyphs_to_get--;
1866 fsdata->encoding[minchar].bits = bits;
1868 if (minchar++ == maxchar)
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;
1879 off_adr += SIZEOF(fsOffset32);
1885 if (blockrec->type == FS_OPEN_FONT)
1887 fsd->glyphs_to_get = 0;
1888 bfont->state = FS_DONE_REPLY;
1893 if (blockrec->type == FS_LOAD_GLYPHS)
1895 bglyph->done = TRUE;
1896 bglyph->errcode = err;
1905 fs_send_load_glyphs(client, pfont, nranges, ranges)
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;
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);
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;
1930 blockrec->sequence_number = conn->current_seq;
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;
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));
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 */
1951 #define RANGE_BUFFER_SIZE 64
1952 #define RANGE_BUFFER_SIZE_MASK 63
1954 char range_buffer[RANGE_BUFFER_SIZE * 4];
1955 char *range_buffer_p;
1957 range_buffer_p = range_buffer;
1958 for (i = 0; i < nranges;)
1960 if (conn->fsMajorVersion > 1)
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;
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;
1975 if (!(++i & RANGE_BUFFER_SIZE_MASK))
1977 _fs_write(conn, range_buffer, RANGE_BUFFER_SIZE * 4);
1978 range_buffer_p = range_buffer;
1981 if (i &= RANGE_BUFFER_SIZE_MASK)
1982 _fs_write(conn, range_buffer, i * 4);
1990 fs_load_all_glyphs(pfont)
1993 extern pointer serverClient; /* This could be any number that
1994 doesn't conflict with existing
1997 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
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.
2011 while ((err = _fs_load_glyphs(serverClient, pfont, TRUE, 0, 0, NULL)) ==
2014 fd_set TempSelectMask;
2015 if (_fs_wait_for_readable(conn) == -1)
2017 /* We lost our connection. Don't wait to reestablish it;
2019 _fs_connection_died(conn);
2021 /* Get rid of blockrec */
2022 fs_client_died(serverClient, pfont->fpe);
2024 return BadCharRange; /* As good an error as any other */
2026 FD_SET(conn->fs_fd, &TempSelectMask);
2027 fs_wakeup(pfont->fpe, &TempSelectMask);
2035 _fs_load_glyphs(client, pfont, range_flag, nchars, item_size, data)
2039 unsigned int nchars;
2041 unsigned char *data;
2045 fsRange *ranges = NULL;
2047 FSBlockDataPtr blockrec;
2048 FSBlockedGlyphPtr blockedglyph;
2049 FSFpePtr conn = (FSFpePtr) pfont->fpe->private;
2050 FSClientsDependingPtr *clients_depending = NULL;
2052 /* see if the result is already there */
2054 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2056 if (blockrec->type == FS_LOAD_GLYPHS)
2058 blockedglyph = (FSBlockedGlyphPtr) blockrec->data;
2059 if (blockedglyph->pfont == pfont)
2061 if (blockrec->client == client)
2063 if (blockedglyph->done)
2065 int errcode = blockedglyph->errcode;
2066 signal_clients_depending(&blockedglyph->
2068 _fs_remove_block_rec(conn, blockrec);
2071 else return Suspended;
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
2079 clients_depending = &blockedglyph->clients_depending;
2083 else if (blockrec->type == FS_OPEN_FONT)
2085 FSBlockedFontPtr bfont;
2086 bfont = (FSBlockedFontPtr) blockrec->data;
2087 if (bfont->pfont == pfont)
2089 if (blockrec->client == client)
2091 if (bfont->state == FS_DONE_REPLY)
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;
2099 else return Suspended;
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
2107 if (bfont->state != FS_DONE_REPLY)
2109 clients_depending = &bfont->clients_depending;
2115 blockrec = blockrec->next;
2119 * see if the desired glyphs already exist, and return Successful if they
2120 * do, otherwise build up character range/character string
2122 res = fs_build_range(pfont, range_flag, nchars, item_size, data,
2138 * If clients_depending is not null, this request must wait for
2139 * some prior request(s) to complete.
2141 if (clients_depending)
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()
2148 _fs_clean_aborted_loadglyphs(pfont, nranges, ranges);
2151 return add_clients_depending(clients_depending, client);
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
2160 * 2) The open will fail. There is code above to recognize this
2161 * and flunk the LoadGlyphs request. The client might not be
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
2172 if (((FSFontDataPtr)pfont->fpePrivate)->generation != conn->generation)
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);
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,
2186 return fs_send_load_glyphs(client, pfont, nranges, ranges);
2192 fs_read_list(fpe, blockrec)
2193 FontPathElementPtr fpe;
2194 FSBlockDataPtr blockrec;
2196 FSBlockedListPtr blist = (FSBlockedListPtr) blockrec->data;
2197 FSFpePtr conn = (FSFpePtr) fpe->private;
2198 fsListFontsReply rep;
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);
2213 if (_fs_read(conn, (char *) &rep + SIZEOF(fsGenericReply),
2214 SIZEOF(fsListFontsReply) - SIZEOF(fsGenericReply)) == -1) {
2215 /* nothing to free (i think) */
2216 return StillWorking;
2218 length = (rep.length << 2) - SIZEOF(fsListFontsReply);
2219 data = (char *) xalloc(length);
2221 _fs_drain_bytes_pad(conn, length);
2225 if (_fs_read_pad(conn, data, length) == -1) {
2226 /* nothing to free (i think) */
2227 return StillWorking;
2229 /* copy data into FontPathRecord */
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;
2245 fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2247 FontPathElementPtr fpe;
2251 FontNamesPtr newnames;
2253 FSBlockDataPtr blockrec;
2254 FSBlockedListPtr blockedlist;
2255 FSFpePtr conn = (FSFpePtr) fpe->private;
2258 _fs_client_access (conn, client, FALSE);
2259 _fs_client_resolution(conn);
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);
2265 blockedlist = (FSBlockedListPtr) blockrec->data;
2266 blockedlist->patlen = patlen;
2267 blockedlist->errcode = Successful;
2268 blockedlist->names = newnames;
2269 blockedlist->done = FALSE;
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);
2281 if (configData.ExtendedFontDiags) {
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",
2295 fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2297 FontPathElementPtr fpe;
2301 FontNamesPtr newnames;
2303 FSBlockDataPtr blockrec;
2304 FSBlockedListPtr blockedlist;
2305 FSFpePtr conn = (FSFpePtr) fpe->private;
2308 /* see if the result is already there */
2309 blockrec = (FSBlockDataPtr) conn->blocked_requests;
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);
2319 blockrec = blockrec->next;
2322 /* didn't find waiting record, so send a new one */
2323 return fs_send_list_fonts(client, fpe, pattern, patlen, maxnames, newnames);
2326 static int padlength[4] = {0, 3, 2, 1};
2329 fs_read_list_info(fpe, blockrec)
2330 FontPathElementPtr fpe;
2331 FSBlockDataPtr blockrec;
2333 FSBlockedListInfoPtr binfo = (FSBlockedListInfoPtr) blockrec->data;
2334 fsListFontsWithXInfoReply rep;
2335 FSFpePtr conn = (FSFpePtr) fpe->private;
2342 /* clean up anything from the last trip */
2349 xfree(binfo->pfi->isStringProp);
2350 xfree(binfo->pfi->props);
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;
2362 if (conn->fsMajorVersion > 1)
2363 if (rep.nameLength == 0)
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) {
2370 if (rep.nameLength == 0)
2374 name = (char *) xalloc(rep.nameLength);
2375 binfo->pfi = (FontInfoPtr) xalloc(sizeof(FontInfoRec));
2376 if (!name || !binfo->pfi) {
2380 _fs_drain_bytes(conn,
2381 rep.length - (SIZEOF(fsListFontsWithXInfoReply) -
2382 SIZEOF(fsGenericReply)));
2383 binfo->errcode = AllocError;
2386 if (conn->fsMajorVersion == 1)
2387 if (_fs_read_pad(conn, name, rep.nameLength) == -1)
2389 if (_fs_read_pad(conn, (char *) &pi, SIZEOF(fsPropInfo)) == -1)
2392 po = (fsPropOffset *) xalloc(SIZEOF(fsPropOffset) * pi.num_offsets);
2393 pd = (pointer) xalloc(pi.data_len);
2400 binfo->errcode = AllocError;
2403 err = _fs_read_pad(conn, (char *) po,
2404 (pi.num_offsets * SIZEOF(fsPropOffset)));
2407 if (conn->fsMajorVersion > 1)
2408 err = _fs_read(conn, (char *) pd, pi.data_len);
2410 err = _fs_read_pad(conn, (char *) pd, pi.data_len);
2412 if (err != -1 && conn->fsMajorVersion != 1)
2414 err = _fs_read(conn, name, rep.nameLength);
2416 err = _fs_drain_bytes(conn, padlength[(pi.data_len+rep.nameLength)&3]);
2428 if (_fs_convert_lfwi_reply(conn, binfo->pfi, &rep, &pi, po, pd) != Successful)
2440 binfo->namelen = rep.nameLength;
2441 binfo->remaining = rep.nReplies;
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);
2451 binfo->status = FS_LFWI_FINISHED;
2452 binfo->errcode = BadFontName;
2453 binfo->name = (char *) 0;
2459 fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2461 FontPathElementPtr fpe;
2467 FSBlockDataPtr blockrec;
2468 FSBlockedListInfoPtr blockedinfo;
2469 fsListFontsWithXInfoReq req;
2470 FSFpePtr conn = (FSFpePtr) fpe->private;
2472 _fs_client_access (conn, client, FALSE);
2473 _fs_client_resolution(conn);
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);
2479 blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2480 bzero((char *) blockedinfo, sizeof(FSBlockedListInfoRec));
2481 blockedinfo->status = FS_LFWI_WAITING;
2482 blockedinfo->errcode = Suspended;
2484 /* send the request */
2485 req.reqType = FS_ListFontsWithXInfo;
2486 req.maxNames = maxnames;
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);
2494 if (configData.ExtendedFontDiags) {
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",
2509 fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2512 FontPathElementPtr fpe;
2515 FontInfoPtr *pFontInfo;
2519 FSBlockDataPtr blockrec;
2520 FSBlockedListInfoPtr blockedinfo;
2521 FSFpePtr conn = (FSFpePtr) fpe->private;
2523 /* see if the result is already there */
2524 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2526 if (blockrec->type == FS_LIST_WITH_INFO &&
2527 blockrec->client == client) {
2528 blockedinfo = (FSBlockedListInfoPtr) blockrec->data;
2531 blockrec = blockrec->next;
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. */
2545 if (blockedinfo->status == FS_LFWI_WAITING)
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;
2556 _fs_remove_block_rec(conn, blockrec);
2559 if (blockedinfo->status == FS_LFWI_REPLY) {
2560 blockedinfo->status = FS_LFWI_WAITING;
2563 return blockedinfo->errcode;
2568 * Called when client exits
2572 fs_client_died(client, fpe)
2574 FontPathElementPtr fpe;
2576 FSFpePtr conn = (FSFpePtr) fpe->private;
2577 FSBlockDataPtr blockrec,
2579 FSClientPtr *prev, cur;
2582 for (prev = &conn->clients; cur = *prev; prev = &cur->next)
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));
2595 /* see if the result is already there */
2596 blockrec = (FSBlockDataPtr) conn->blocked_requests;
2598 if (blockrec->client == client)
2600 blockrec = blockrec->next;
2604 if (blockrec->type == FS_LIST_WITH_INFO)
2606 FSBlockedListInfoPtr binfo;
2607 binfo = (FSBlockedListInfoPtr) blockrec->data;
2608 if (binfo->status == FS_LFWI_REPLY)
2609 FD_SET(conn->fs_fd, &_fs_fd_mask);
2617 xfree(binfo->pfi->isStringProp);
2618 xfree(binfo->pfi->props);
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;
2629 fs_abort_blockrec(conn, blockrec);
2633 _fs_client_access (conn, client, sync)
2638 FSClientPtr *prev, cur;
2640 fsSetAuthorizationReq setac;
2642 char *authorizations;
2644 Bool new_cur = FALSE;
2646 for (prev = &conn->clients; cur = *prev; prev = &cur->next)
2648 if (cur->client == client)
2650 if (prev != &conn->clients)
2653 cur->next = conn->clients;
2654 conn->clients = cur;
2661 cur = (FSClientPtr) xalloc (sizeof (FSClientRec));
2664 cur->client = client;
2665 cur->next = conn->clients;
2666 conn->clients = cur;
2667 cur->acid = GetNewFontClientID ();
2670 if (new_cur || cur->auth_generation != client_auth_generation(client))
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));
2681 crac.reqType = FS_CreateAC;
2682 crac.num_auths = set_font_authorizations(&authorizations, &authlen,
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
2695 if (_fs_read(conn, (char *) &rep, sizeof (fsGenericReply)) == -1)
2697 fs_handle_unexpected(conn, &rep);
2699 /* ignore reply; we don't even care about it */
2701 cur->auth_generation = client_auth_generation(client);
2703 if (conn->curacid != cur->acid)
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;
2715 * called at server init time
2719 fs_register_fpe_functions()
2721 fs_font_type = RegisterFPEFunctions(fs_name_check,
2728 fs_start_list_with_info,
2729 fs_next_list_with_info,
2739 check_fs_open_font(client, fpe, flags, name, namelen, format, fmask, id, ppfont,
2740 alias, non_cachable_font)
2742 FontPathElementPtr fpe;
2745 fsBitmapFormat format;
2746 fsBitmapFormatMask fmask;
2751 FontPtr non_cachable_font; /* Not used in this FPE */
2753 if (XpClientIsBitmapClient(client))
2754 return (fs_open_font(client, fpe, flags, name, namelen, format,
2755 fmask, id, ppfont, alias, non_cachable_font) );
2760 check_fs_list_fonts(client, fpe, pattern, patlen, maxnames, newnames)
2762 FontPathElementPtr fpe;
2766 FontNamesPtr newnames;
2768 if (XpClientIsBitmapClient(client))
2769 return (fs_list_fonts(client, fpe, pattern, patlen, maxnames,
2775 check_fs_start_list_with_info(client, fpe, pattern, len, maxnames, pdata)
2777 FontPathElementPtr fpe;
2783 if (XpClientIsBitmapClient(client))
2784 return (fs_start_list_with_info(client, fpe, pattern, len, maxnames,
2790 check_fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo, numFonts,
2793 FontPathElementPtr fpe;
2796 FontInfoPtr *pFontInfo;
2800 if (XpClientIsBitmapClient(client))
2801 return (fs_next_list_with_info(client, fpe, namep, namelenp, pFontInfo,
2807 check_fs_register_fpe_functions()
2809 fs_font_type = RegisterFPEFunctions(fs_name_check,
2815 check_fs_list_fonts,
2816 check_fs_start_list_with_info,
2817 check_fs_next_list_with_info,