First import
[xorg_rtime.git] / xorg-server-1.4 / Xext / xf86bigfont.c
blobf50481f788d6c2222ed7399394a502ba6c34ea36
1 /*
2 * BIGFONT extension for sharing font metrics between clients (if possible)
3 * and for transmitting font metrics to clients in a compressed form.
5 * Copyright (c) 1999-2000 Bruno Haible
6 * Copyright (c) 1999-2000 The XFree86 Project, Inc.
7 */
9 /* THIS IS NOT AN X CONSORTIUM STANDARD */
12 * Big fonts suffer from the following: All clients that have opened a
13 * font can access the complete glyph metrics array (the XFontStruct member
14 * `per_char') directly, without going through a macro. Moreover these
15 * glyph metrics are ink metrics, i.e. are not redundant even for a
16 * fixed-width font. For a Unicode font, the size of this array is 768 KB.
18 * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
19 * metrics data is piped through the socket when the font is opened.
21 * This extension addresses these two problems for local clients, by using
22 * shared memory. It also addresses the second problem for non-local clients,
23 * by compressing the data before transmit by a factor of nearly 6.
25 * If you use this extension, your OS ought to nicely support shared memory.
26 * This means: Shared memory should be swappable to the swap, and the limits
27 * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
28 * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
29 * on segments that have already been marked "removed", because it permits
30 * these segments to be cleaned up by the OS if the X server is killed with
31 * signal SIGKILL.
33 * This extension is transparently exploited by Xlib (functions XQueryFont,
34 * XLoadQueryFont).
37 #ifdef HAVE_DIX_CONFIG_H
38 #include <dix-config.h>
39 #endif
41 #include <sys/types.h>
42 #ifdef HAS_SHM
43 #if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
44 /* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
45 /* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
46 Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
47 PAGE_SIZE. It is defined in <asm/page.h>. */
48 #include <asm/page.h>
49 #endif
50 #ifdef SVR4
51 #include <sys/sysmacros.h>
52 #endif
53 #if defined(ISC) || defined(__CYGWIN__) || defined(__SCO__)
54 #include <sys/param.h>
55 #include <sys/sysmacros.h>
56 #endif
57 #include <sys/ipc.h>
58 #include <sys/shm.h>
59 #include <sys/stat.h>
60 #include <stdlib.h>
61 #include <unistd.h>
62 #include <time.h>
63 #include <errno.h>
64 #endif
66 #include <X11/X.h>
67 #include <X11/Xproto.h>
68 #include "misc.h"
69 #include "os.h"
70 #include "dixstruct.h"
71 #include "gcstruct.h"
72 #include "dixfontstr.h"
73 #include "extnsionst.h"
75 #define _XF86BIGFONT_SERVER_
76 #include <X11/extensions/xf86bigfstr.h>
78 static void XF86BigfontResetProc(
79 ExtensionEntry * /* extEntry */
82 static DISPATCH_PROC(ProcXF86BigfontDispatch);
83 static DISPATCH_PROC(ProcXF86BigfontQueryVersion);
84 static DISPATCH_PROC(ProcXF86BigfontQueryFont);
85 static DISPATCH_PROC(SProcXF86BigfontDispatch);
86 static DISPATCH_PROC(SProcXF86BigfontQueryVersion);
87 static DISPATCH_PROC(SProcXF86BigfontQueryFont);
89 #if 0
90 static unsigned char XF86BigfontReqCode;
91 #endif
93 #ifdef HAS_SHM
95 /* A random signature, transmitted to the clients so they can verify that the
96 shared memory segment they are attaching to was really established by the
97 X server they are talking to. */
98 static CARD32 signature;
100 /* Index for additional information stored in a FontRec's devPrivates array. */
101 static int FontShmdescIndex;
103 static unsigned int pagesize;
105 static Bool badSysCall = FALSE;
107 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__)
109 #include <sys/signal.h>
111 static void
112 SigSysHandler(
113 int signo)
115 badSysCall = TRUE;
118 static Bool
119 CheckForShmSyscall(void)
121 void (*oldHandler)(int);
122 int shmid = -1;
124 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
125 oldHandler = signal(SIGSYS, SigSysHandler);
127 badSysCall = FALSE;
128 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
129 if (shmid != -1)
131 /* Successful allocation - clean up */
132 shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL);
134 else
136 /* Allocation failed */
137 badSysCall = TRUE;
139 signal(SIGSYS, oldHandler);
140 return (!badSysCall);
143 #define MUST_CHECK_FOR_SHM_SYSCALL
145 #endif
147 #endif
149 void
150 XFree86BigfontExtensionInit()
152 #if 0
153 ExtensionEntry* extEntry;
155 if ((extEntry = AddExtension(XF86BIGFONTNAME,
156 XF86BigfontNumberEvents,
157 XF86BigfontNumberErrors,
158 ProcXF86BigfontDispatch,
159 SProcXF86BigfontDispatch,
160 XF86BigfontResetProc,
161 StandardMinorOpcode))) {
162 XF86BigfontReqCode = (unsigned char) extEntry->base;
163 #else
164 if (AddExtension(XF86BIGFONTNAME,
165 XF86BigfontNumberEvents,
166 XF86BigfontNumberErrors,
167 ProcXF86BigfontDispatch,
168 SProcXF86BigfontDispatch,
169 XF86BigfontResetProc,
170 StandardMinorOpcode)) {
171 #endif
172 #ifdef HAS_SHM
173 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
175 * Note: Local-clients will not be optimized without shared memory
176 * support. Remote-client optimization does not depend on shared
177 * memory support. Thus, the extension is still registered even
178 * when shared memory support is not functional.
180 if (!CheckForShmSyscall()) {
181 ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
182 return;
184 #endif
186 srand((unsigned int) time(NULL));
187 signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
188 + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
189 /* fprintf(stderr, "signature = 0x%08X\n", signature); */
191 FontShmdescIndex = AllocateFontPrivateIndex();
193 #if !defined(CSRG_BASED) && !defined(__CYGWIN__)
194 pagesize = SHMLBA;
195 #else
196 # ifdef _SC_PAGESIZE
197 pagesize = sysconf(_SC_PAGESIZE);
198 # else
199 pagesize = getpagesize();
200 # endif
201 #endif
202 #endif
207 /* ========== Management of shared memory segments ========== */
209 #ifdef HAS_SHM
211 #ifdef __linux__
212 /* On Linux, shared memory marked as "removed" can still be attached.
213 Nice feature, because the kernel will automatically free the associated
214 storage when the server and all clients are gone. */
215 #define EARLY_REMOVE
216 #endif
218 typedef struct _ShmDesc {
219 struct _ShmDesc *next;
220 struct _ShmDesc **prev;
221 int shmid;
222 char *attach_addr;
223 } ShmDescRec, *ShmDescPtr;
225 static ShmDescPtr ShmList = (ShmDescPtr) NULL;
227 static ShmDescPtr
228 shmalloc(
229 unsigned int size)
231 ShmDescPtr pDesc;
232 int shmid;
233 char *addr;
235 #ifdef MUST_CHECK_FOR_SHM_SYSCALL
236 if (pagesize == 0)
237 return (ShmDescPtr) NULL;
238 #endif
240 /* On some older Linux systems, the number of shared memory segments
241 system-wide is 127. In Linux 2.4, it is 4095.
242 Therefore there is a tradeoff to be made between allocating a
243 shared memory segment on one hand, and allocating memory and piping
244 the glyph metrics on the other hand. If the glyph metrics size is
245 small, we prefer the traditional way. */
246 if (size < 3500)
247 return (ShmDescPtr) NULL;
249 pDesc = (ShmDescRec *) xalloc(sizeof(ShmDescRec));
250 if (!pDesc)
251 return (ShmDescPtr) NULL;
253 size = (size + pagesize-1) & -pagesize;
254 shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
255 if (shmid == -1) {
256 ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, errno = %d\n",
257 size, errno);
258 xfree(pDesc);
259 return (ShmDescPtr) NULL;
262 if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
263 ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, errno = %d\n",
264 size, errno);
265 shmctl(shmid, IPC_RMID, (void *) 0);
266 xfree(pDesc);
267 return (ShmDescPtr) NULL;
270 #ifdef EARLY_REMOVE
271 shmctl(shmid, IPC_RMID, (void *) 0);
272 #endif
274 pDesc->shmid = shmid;
275 pDesc->attach_addr = addr;
276 if (ShmList) ShmList->prev = &pDesc->next;
277 pDesc->next = ShmList;
278 pDesc->prev = &ShmList;
279 ShmList = pDesc;
281 return pDesc;
284 static void
285 shmdealloc(
286 ShmDescPtr pDesc)
288 #ifndef EARLY_REMOVE
289 shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
290 #endif
291 shmdt(pDesc->attach_addr);
293 if (pDesc->next) pDesc->next->prev = pDesc->prev;
294 *pDesc->prev = pDesc->next;
295 xfree(pDesc);
298 #endif
300 /* Called when a font is closed. */
301 void
302 XF86BigfontFreeFontShm(
303 FontPtr pFont)
305 #ifdef HAS_SHM
306 ShmDescPtr pDesc;
308 /* If during shutdown of the server, XF86BigfontCleanup() has already
309 * called shmdealloc() for all segments, we don't need to do it here.
311 if (!ShmList)
312 return;
314 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
315 if (pDesc)
316 shmdealloc(pDesc);
317 #endif
320 /* Called upon fatal signal. */
321 void
322 XF86BigfontCleanup()
324 #ifdef HAS_SHM
325 while (ShmList)
326 shmdealloc(ShmList);
327 #endif
330 /* Called when a server generation dies. */
331 static void
332 XF86BigfontResetProc(
333 ExtensionEntry* extEntry)
335 /* This function is normally called from CloseDownExtensions(), called
336 * from main(). It will be followed by a call to FreeAllResources(),
337 * which will call XF86BigfontFreeFontShm() for each font. Thus it
338 * appears that we do not need to do anything in this function. --
339 * But I prefer to write robust code, and not keep shared memory lying
340 * around when it's not needed any more. (Someone might close down the
341 * extension without calling FreeAllResources()...)
343 XF86BigfontCleanup();
347 /* ========== Handling of extension specific requests ========== */
349 static int
350 ProcXF86BigfontQueryVersion(
351 ClientPtr client)
353 xXF86BigfontQueryVersionReply reply;
355 REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
356 reply.type = X_Reply;
357 reply.length = 0;
358 reply.sequenceNumber = client->sequence;
359 reply.majorVersion = XF86BIGFONT_MAJOR_VERSION;
360 reply.minorVersion = XF86BIGFONT_MINOR_VERSION;
361 reply.uid = geteuid();
362 reply.gid = getegid();
363 #ifdef HAS_SHM
364 reply.signature = signature;
365 #else
366 reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
367 #endif
368 reply.capabilities =
369 #ifdef HAS_SHM
370 (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
371 #else
373 #endif
374 ; /* may add more bits here in future versions */
375 if (client->swapped) {
376 char tmp;
377 swaps(&reply.sequenceNumber, tmp);
378 swapl(&reply.length, tmp);
379 swaps(&reply.majorVersion, tmp);
380 swaps(&reply.minorVersion, tmp);
381 swapl(&reply.uid, tmp);
382 swapl(&reply.gid, tmp);
383 swapl(&reply.signature, tmp);
385 WriteToClient(client,
386 sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
387 return client->noClientException;
390 static void
391 swapCharInfo(
392 xCharInfo *pCI)
394 char tmp;
396 swaps(&pCI->leftSideBearing, tmp);
397 swaps(&pCI->rightSideBearing, tmp);
398 swaps(&pCI->characterWidth, tmp);
399 swaps(&pCI->ascent, tmp);
400 swaps(&pCI->descent, tmp);
401 swaps(&pCI->attributes, tmp);
404 /* static CARD32 hashCI (xCharInfo *p); */
405 #define hashCI(p) \
406 (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
407 (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
408 (p->characterWidth << 16) + \
409 (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
411 static int
412 ProcXF86BigfontQueryFont(
413 ClientPtr client)
415 FontPtr pFont;
416 REQUEST(xXF86BigfontQueryFontReq);
417 CARD32 stuff_flags;
418 xCharInfo* pmax;
419 xCharInfo* pmin;
420 int nCharInfos;
421 int shmid;
422 #ifdef HAS_SHM
423 ShmDescPtr pDesc;
424 #else
425 #define pDesc 0
426 #endif
427 xCharInfo* pCI;
428 CARD16* pIndex2UniqIndex;
429 CARD16* pUniqIndex2Index;
430 CARD32 nUniqCharInfos;
432 #if 0
433 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
434 #else
435 switch (client->req_len) {
436 case 2: /* client with version 1.0 libX11 */
437 stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
438 break;
439 case 3: /* client with version 1.1 libX11 */
440 stuff_flags = stuff->flags;
441 break;
442 default:
443 return BadLength;
445 #endif
446 client->errorValue = stuff->id; /* EITHER font or gc */
447 pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT,
448 DixReadAccess);
449 if (!pFont) {
450 GC *pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC,
451 DixReadAccess);
452 if (!pGC) {
453 client->errorValue = stuff->id;
454 return BadFont; /* procotol spec says only error is BadFont */
456 pFont = pGC->font;
459 pmax = FONTINKMAX(pFont);
460 pmin = FONTINKMIN(pFont);
461 nCharInfos =
462 (pmax->rightSideBearing == pmin->rightSideBearing
463 && pmax->leftSideBearing == pmin->leftSideBearing
464 && pmax->descent == pmin->descent
465 && pmax->ascent == pmin->ascent
466 && pmax->characterWidth == pmin->characterWidth)
467 ? 0 : N2dChars(pFont);
468 shmid = -1;
469 pCI = NULL;
470 pIndex2UniqIndex = NULL;
471 pUniqIndex2Index = NULL;
472 nUniqCharInfos = 0;
474 if (nCharInfos > 0) {
475 #ifdef HAS_SHM
476 if (!badSysCall)
477 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
478 else
479 pDesc = NULL;
480 if (pDesc) {
481 pCI = (xCharInfo *) pDesc->attach_addr;
482 if (stuff_flags & XF86Bigfont_FLAGS_Shm)
483 shmid = pDesc->shmid;
484 } else {
485 if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
486 pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
487 + sizeof(CARD32));
488 if (pDesc) {
489 pCI = (xCharInfo *) pDesc->attach_addr;
490 shmid = pDesc->shmid;
491 } else {
492 #endif
493 pCI = (xCharInfo *)
494 ALLOCATE_LOCAL(nCharInfos * sizeof(xCharInfo));
495 if (!pCI)
496 return BadAlloc;
497 #ifdef HAS_SHM
499 #endif
500 /* Fill nCharInfos starting at pCI. */
502 xCharInfo* prCI = pCI;
503 int ninfos = 0;
504 int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
505 int row;
506 for (row = pFont->info.firstRow;
507 row <= pFont->info.lastRow && ninfos < nCharInfos;
508 row++) {
509 unsigned char chars[512];
510 xCharInfo* tmpCharInfos[256];
511 unsigned long count;
512 int col;
513 unsigned long i;
514 i = 0;
515 for (col = pFont->info.firstCol;
516 col <= pFont->info.lastCol;
517 col++) {
518 chars[i++] = row;
519 chars[i++] = col;
521 (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
522 &count, tmpCharInfos);
523 for (i = 0; i < count && ninfos < nCharInfos; i++) {
524 *prCI++ = *tmpCharInfos[i];
525 ninfos++;
529 #ifdef HAS_SHM
530 if (pDesc && !badSysCall) {
531 *(CARD32 *)(pCI + nCharInfos) = signature;
532 if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
533 shmdealloc(pDesc);
534 return BadAlloc;
538 #endif
539 if (shmid == -1) {
540 /* Cannot use shared memory, so remove-duplicates the xCharInfos
541 using a temporary hash table. */
542 /* Note that CARD16 is suitable as index type, because
543 nCharInfos <= 0x10000. */
544 CARD32 hashModulus;
545 CARD16* pHash2UniqIndex;
546 CARD16* pUniqIndex2NextUniqIndex;
547 CARD32 NextIndex;
548 CARD32 NextUniqIndex;
549 CARD16* tmp;
550 CARD32 i, j;
552 hashModulus = 67;
553 if (hashModulus > nCharInfos+1)
554 hashModulus = nCharInfos+1;
556 tmp = (CARD16*)
557 ALLOCATE_LOCAL((4*nCharInfos+1) * sizeof(CARD16));
558 if (!tmp) {
559 if (!pDesc) DEALLOCATE_LOCAL(pCI);
560 return BadAlloc;
562 pIndex2UniqIndex = tmp;
563 /* nCharInfos elements */
564 pUniqIndex2Index = tmp + nCharInfos;
565 /* max. nCharInfos elements */
566 pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
567 /* max. nCharInfos elements */
568 pHash2UniqIndex = tmp + 3*nCharInfos;
569 /* hashModulus (<= nCharInfos+1) elements */
571 /* Note that we can use 0xffff as end-of-list indicator, because
572 even if nCharInfos = 0x10000, 0xffff can not occur as valid
573 entry before the last element has been inserted. And once the
574 last element has been inserted, we don't need the hash table
575 any more. */
576 for (j = 0; j < hashModulus; j++)
577 pHash2UniqIndex[j] = (CARD16)(-1);
579 NextUniqIndex = 0;
580 for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
581 xCharInfo* p = &pCI[NextIndex];
582 CARD32 hashCode = hashCI(p) % hashModulus;
583 for (i = pHash2UniqIndex[hashCode];
584 i != (CARD16)(-1);
585 i = pUniqIndex2NextUniqIndex[i]) {
586 j = pUniqIndex2Index[i];
587 if (pCI[j].leftSideBearing == p->leftSideBearing
588 && pCI[j].rightSideBearing == p->rightSideBearing
589 && pCI[j].characterWidth == p->characterWidth
590 && pCI[j].ascent == p->ascent
591 && pCI[j].descent == p->descent
592 && pCI[j].attributes == p->attributes)
593 break;
595 if (i != (CARD16)(-1)) {
596 /* Found *p at Index j, UniqIndex i */
597 pIndex2UniqIndex[NextIndex] = i;
598 } else {
599 /* Allocate a new entry in the Uniq table */
600 if (hashModulus <= 2*NextUniqIndex
601 && hashModulus < nCharInfos+1) {
602 /* Time to increate hash table size */
603 hashModulus = 2*hashModulus+1;
604 if (hashModulus > nCharInfos+1)
605 hashModulus = nCharInfos+1;
606 for (j = 0; j < hashModulus; j++)
607 pHash2UniqIndex[j] = (CARD16)(-1);
608 for (i = 0; i < NextUniqIndex; i++)
609 pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
610 for (i = 0; i < NextUniqIndex; i++) {
611 j = pUniqIndex2Index[i];
612 p = &pCI[j];
613 hashCode = hashCI(p) % hashModulus;
614 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
615 pHash2UniqIndex[hashCode] = i;
617 p = &pCI[NextIndex];
618 hashCode = hashCI(p) % hashModulus;
620 i = NextUniqIndex++;
621 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
622 pHash2UniqIndex[hashCode] = i;
623 pUniqIndex2Index[i] = NextIndex;
624 pIndex2UniqIndex[NextIndex] = i;
627 nUniqCharInfos = NextUniqIndex;
628 /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
633 int nfontprops = pFont->info.nprops;
634 int rlength =
635 sizeof(xXF86BigfontQueryFontReply)
636 + nfontprops * sizeof(xFontProp)
637 + (nCharInfos > 0 && shmid == -1
638 ? nUniqCharInfos * sizeof(xCharInfo)
639 + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
640 : 0);
641 xXF86BigfontQueryFontReply* reply =
642 (xXF86BigfontQueryFontReply *) ALLOCATE_LOCAL(rlength);
643 char* p;
644 if (!reply) {
645 if (nCharInfos > 0) {
646 if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex);
647 if (!pDesc) DEALLOCATE_LOCAL(pCI);
649 return BadAlloc;
651 reply->type = X_Reply;
652 reply->length = (rlength - sizeof(xGenericReply)) >> 2;
653 reply->sequenceNumber = client->sequence;
654 reply->minBounds = pFont->info.ink_minbounds;
655 reply->maxBounds = pFont->info.ink_maxbounds;
656 reply->minCharOrByte2 = pFont->info.firstCol;
657 reply->maxCharOrByte2 = pFont->info.lastCol;
658 reply->defaultChar = pFont->info.defaultCh;
659 reply->nFontProps = pFont->info.nprops;
660 reply->drawDirection = pFont->info.drawDirection;
661 reply->minByte1 = pFont->info.firstRow;
662 reply->maxByte1 = pFont->info.lastRow;
663 reply->allCharsExist = pFont->info.allExist;
664 reply->fontAscent = pFont->info.fontAscent;
665 reply->fontDescent = pFont->info.fontDescent;
666 reply->nCharInfos = nCharInfos;
667 reply->nUniqCharInfos = nUniqCharInfos;
668 reply->shmid = shmid;
669 reply->shmsegoffset = 0;
670 if (client->swapped) {
671 char tmp;
672 swaps(&reply->sequenceNumber, tmp);
673 swapl(&reply->length, tmp);
674 swapCharInfo(&reply->minBounds);
675 swapCharInfo(&reply->maxBounds);
676 swaps(&reply->minCharOrByte2, tmp);
677 swaps(&reply->maxCharOrByte2, tmp);
678 swaps(&reply->defaultChar, tmp);
679 swaps(&reply->nFontProps, tmp);
680 swaps(&reply->fontAscent, tmp);
681 swaps(&reply->fontDescent, tmp);
682 swapl(&reply->nCharInfos, tmp);
683 swapl(&reply->nUniqCharInfos, tmp);
684 swapl(&reply->shmid, tmp);
685 swapl(&reply->shmsegoffset, tmp);
687 p = (char*) &reply[1];
689 FontPropPtr pFP;
690 xFontProp* prFP;
691 int i;
692 for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
693 i < nfontprops;
694 i++, pFP++, prFP++) {
695 prFP->name = pFP->name;
696 prFP->value = pFP->value;
697 if (client->swapped) {
698 char tmp;
699 swapl(&prFP->name, tmp);
700 swapl(&prFP->value, tmp);
703 p = (char*) prFP;
705 if (nCharInfos > 0 && shmid == -1) {
706 xCharInfo* pci;
707 CARD16* ps;
708 int i, j;
709 pci = (xCharInfo*) p;
710 for (i = 0; i < nUniqCharInfos; i++, pci++) {
711 *pci = pCI[pUniqIndex2Index[i]];
712 if (client->swapped)
713 swapCharInfo(pci);
715 ps = (CARD16*) pci;
716 for (j = 0; j < nCharInfos; j++, ps++) {
717 *ps = pIndex2UniqIndex[j];
718 if (client->swapped) {
719 char tmp;
720 swaps(ps, tmp);
724 WriteToClient(client, rlength, (char *)reply);
725 DEALLOCATE_LOCAL(reply);
726 if (nCharInfos > 0) {
727 if (shmid == -1) DEALLOCATE_LOCAL(pIndex2UniqIndex);
728 if (!pDesc) DEALLOCATE_LOCAL(pCI);
730 return (client->noClientException);
734 static int
735 ProcXF86BigfontDispatch(
736 ClientPtr client)
738 REQUEST(xReq);
740 switch (stuff->data) {
741 case X_XF86BigfontQueryVersion:
742 return ProcXF86BigfontQueryVersion(client);
743 case X_XF86BigfontQueryFont:
744 return ProcXF86BigfontQueryFont(client);
745 default:
746 return BadRequest;
750 static int
751 SProcXF86BigfontQueryVersion(
752 ClientPtr client)
754 REQUEST(xXF86BigfontQueryVersionReq);
755 char tmp;
757 swaps(&stuff->length, tmp);
758 return ProcXF86BigfontQueryVersion(client);
761 static int
762 SProcXF86BigfontQueryFont(
763 ClientPtr client)
765 REQUEST(xXF86BigfontQueryFontReq);
766 char tmp;
768 swaps(&stuff->length, tmp);
769 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
770 swapl(&stuff->id, tmp);
771 return ProcXF86BigfontQueryFont(client);
774 static int
775 SProcXF86BigfontDispatch(
776 ClientPtr client)
778 REQUEST(xReq);
780 switch (stuff->data) {
781 case X_XF86BigfontQueryVersion:
782 return SProcXF86BigfontQueryVersion(client);
783 case X_XF86BigfontQueryFont:
784 return SProcXF86BigfontQueryFont(client);
785 default:
786 return BadRequest;