xf86bigfont.c revision 4642e01f
1/* 2 * BIGFONT extension for sharing font metrics between clients (if possible) 3 * and for transmitting font metrics to clients in a compressed form. 4 * 5 * Copyright (c) 1999-2000 Bruno Haible 6 * Copyright (c) 1999-2000 The XFree86 Project, Inc. 7 */ 8 9/* THIS IS NOT AN X CONSORTIUM STANDARD */ 10 11/* 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. 17 * 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. 20 * 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. 24 * 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. 32 * 33 * This extension is transparently exploited by Xlib (functions XQueryFont, 34 * XLoadQueryFont). 35 */ 36 37#ifdef HAVE_DIX_CONFIG_H 38#include <dix-config.h> 39#endif 40 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(__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 65 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" 74 75#define _XF86BIGFONT_SERVER_ 76#include <X11/extensions/xf86bigfstr.h> 77 78static void XF86BigfontResetProc( 79 ExtensionEntry * /* extEntry */ 80 ); 81 82static DISPATCH_PROC(ProcXF86BigfontDispatch); 83static DISPATCH_PROC(ProcXF86BigfontQueryVersion); 84static DISPATCH_PROC(ProcXF86BigfontQueryFont); 85static DISPATCH_PROC(SProcXF86BigfontDispatch); 86static DISPATCH_PROC(SProcXF86BigfontQueryVersion); 87static DISPATCH_PROC(SProcXF86BigfontQueryFont); 88 89#ifdef HAS_SHM 90 91/* A random signature, transmitted to the clients so they can verify that the 92 shared memory segment they are attaching to was really established by the 93 X server they are talking to. */ 94static CARD32 signature; 95 96/* Index for additional information stored in a FontRec's devPrivates array. */ 97static int FontShmdescIndex; 98 99static unsigned int pagesize; 100 101static Bool badSysCall = FALSE; 102 103#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 104 105#include <sys/signal.h> 106 107static void 108SigSysHandler( 109 int signo) 110{ 111 badSysCall = TRUE; 112} 113 114static Bool 115CheckForShmSyscall(void) 116{ 117 void (*oldHandler)(int); 118 int shmid = -1; 119 120 /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 121 oldHandler = signal(SIGSYS, SigSysHandler); 122 123 badSysCall = FALSE; 124 shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 125 if (shmid != -1) 126 { 127 /* Successful allocation - clean up */ 128 shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); 129 } 130 else 131 { 132 /* Allocation failed */ 133 badSysCall = TRUE; 134 } 135 signal(SIGSYS, oldHandler); 136 return (!badSysCall); 137} 138 139#define MUST_CHECK_FOR_SHM_SYSCALL 140 141#endif 142 143#endif 144 145void 146XFree86BigfontExtensionInit() 147{ 148 if (AddExtension(XF86BIGFONTNAME, 149 XF86BigfontNumberEvents, 150 XF86BigfontNumberErrors, 151 ProcXF86BigfontDispatch, 152 SProcXF86BigfontDispatch, 153 XF86BigfontResetProc, 154 StandardMinorOpcode)) { 155#ifdef HAS_SHM 156#ifdef MUST_CHECK_FOR_SHM_SYSCALL 157 /* 158 * Note: Local-clients will not be optimized without shared memory 159 * support. Remote-client optimization does not depend on shared 160 * memory support. Thus, the extension is still registered even 161 * when shared memory support is not functional. 162 */ 163 if (!CheckForShmSyscall()) { 164 ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n"); 165 return; 166 } 167#endif 168 169 srand((unsigned int) time(NULL)); 170 signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16) 171 + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand()); 172 /* fprintf(stderr, "signature = 0x%08X\n", signature); */ 173 174 FontShmdescIndex = AllocateFontPrivateIndex(); 175 176#if !defined(CSRG_BASED) && !defined(__CYGWIN__) 177 pagesize = SHMLBA; 178#else 179# ifdef _SC_PAGESIZE 180 pagesize = sysconf(_SC_PAGESIZE); 181# else 182 pagesize = getpagesize(); 183# endif 184#endif 185#endif 186 } 187} 188 189 190/* ========== Management of shared memory segments ========== */ 191 192#ifdef HAS_SHM 193 194#ifdef __linux__ 195/* On Linux, shared memory marked as "removed" can still be attached. 196 Nice feature, because the kernel will automatically free the associated 197 storage when the server and all clients are gone. */ 198#define EARLY_REMOVE 199#endif 200 201typedef struct _ShmDesc { 202 struct _ShmDesc *next; 203 struct _ShmDesc **prev; 204 int shmid; 205 char *attach_addr; 206} ShmDescRec, *ShmDescPtr; 207 208static ShmDescPtr ShmList = (ShmDescPtr) NULL; 209 210static ShmDescPtr 211shmalloc( 212 unsigned int size) 213{ 214 ShmDescPtr pDesc; 215 int shmid; 216 char *addr; 217 218#ifdef MUST_CHECK_FOR_SHM_SYSCALL 219 if (pagesize == 0) 220 return (ShmDescPtr) NULL; 221#endif 222 223 /* On some older Linux systems, the number of shared memory segments 224 system-wide is 127. In Linux 2.4, it is 4095. 225 Therefore there is a tradeoff to be made between allocating a 226 shared memory segment on one hand, and allocating memory and piping 227 the glyph metrics on the other hand. If the glyph metrics size is 228 small, we prefer the traditional way. */ 229 if (size < 3500) 230 return (ShmDescPtr) NULL; 231 232 pDesc = (ShmDescRec *) xalloc(sizeof(ShmDescRec)); 233 if (!pDesc) 234 return (ShmDescPtr) NULL; 235 236 size = (size + pagesize-1) & -pagesize; 237 shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); 238 if (shmid == -1) { 239 ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n", 240 size, strerror(errno)); 241 xfree(pDesc); 242 return (ShmDescPtr) NULL; 243 } 244 245 if ((addr = shmat(shmid, 0, 0)) == (char *)-1) { 246 ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n", 247 size, strerror(errno)); 248 shmctl(shmid, IPC_RMID, (void *) 0); 249 xfree(pDesc); 250 return (ShmDescPtr) NULL; 251 } 252 253#ifdef EARLY_REMOVE 254 shmctl(shmid, IPC_RMID, (void *) 0); 255#endif 256 257 pDesc->shmid = shmid; 258 pDesc->attach_addr = addr; 259 if (ShmList) ShmList->prev = &pDesc->next; 260 pDesc->next = ShmList; 261 pDesc->prev = &ShmList; 262 ShmList = pDesc; 263 264 return pDesc; 265} 266 267static void 268shmdealloc( 269 ShmDescPtr pDesc) 270{ 271#ifndef EARLY_REMOVE 272 shmctl(pDesc->shmid, IPC_RMID, (void *) 0); 273#endif 274 shmdt(pDesc->attach_addr); 275 276 if (pDesc->next) pDesc->next->prev = pDesc->prev; 277 *pDesc->prev = pDesc->next; 278 xfree(pDesc); 279} 280 281#endif 282 283/* Called when a font is closed. */ 284void 285XF86BigfontFreeFontShm( 286 FontPtr pFont) 287{ 288#ifdef HAS_SHM 289 ShmDescPtr pDesc; 290 291 /* If during shutdown of the server, XF86BigfontCleanup() has already 292 * called shmdealloc() for all segments, we don't need to do it here. 293 */ 294 if (!ShmList) 295 return; 296 297 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); 298 if (pDesc) 299 shmdealloc(pDesc); 300#endif 301} 302 303/* Called upon fatal signal. */ 304void 305XF86BigfontCleanup() 306{ 307#ifdef HAS_SHM 308 while (ShmList) 309 shmdealloc(ShmList); 310#endif 311} 312 313/* Called when a server generation dies. */ 314static void 315XF86BigfontResetProc( 316 ExtensionEntry* extEntry) 317{ 318 /* This function is normally called from CloseDownExtensions(), called 319 * from main(). It will be followed by a call to FreeAllResources(), 320 * which will call XF86BigfontFreeFontShm() for each font. Thus it 321 * appears that we do not need to do anything in this function. -- 322 * But I prefer to write robust code, and not keep shared memory lying 323 * around when it's not needed any more. (Someone might close down the 324 * extension without calling FreeAllResources()...) 325 */ 326 XF86BigfontCleanup(); 327} 328 329 330/* ========== Handling of extension specific requests ========== */ 331 332static int 333ProcXF86BigfontQueryVersion( 334 ClientPtr client) 335{ 336 xXF86BigfontQueryVersionReply reply; 337 338 REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq); 339 reply.type = X_Reply; 340 reply.length = 0; 341 reply.sequenceNumber = client->sequence; 342 reply.majorVersion = XF86BIGFONT_MAJOR_VERSION; 343 reply.minorVersion = XF86BIGFONT_MINOR_VERSION; 344 reply.uid = geteuid(); 345 reply.gid = getegid(); 346#ifdef HAS_SHM 347 reply.signature = signature; 348#else 349 reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */ 350#endif 351 reply.capabilities = 352#ifdef HAS_SHM 353 (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0) 354#else 355 0 356#endif 357 ; /* may add more bits here in future versions */ 358 if (client->swapped) { 359 char tmp; 360 swaps(&reply.sequenceNumber, tmp); 361 swapl(&reply.length, tmp); 362 swaps(&reply.majorVersion, tmp); 363 swaps(&reply.minorVersion, tmp); 364 swapl(&reply.uid, tmp); 365 swapl(&reply.gid, tmp); 366 swapl(&reply.signature, tmp); 367 } 368 WriteToClient(client, 369 sizeof(xXF86BigfontQueryVersionReply), (char *)&reply); 370 return client->noClientException; 371} 372 373static void 374swapCharInfo( 375 xCharInfo *pCI) 376{ 377 char tmp; 378 379 swaps(&pCI->leftSideBearing, tmp); 380 swaps(&pCI->rightSideBearing, tmp); 381 swaps(&pCI->characterWidth, tmp); 382 swaps(&pCI->ascent, tmp); 383 swaps(&pCI->descent, tmp); 384 swaps(&pCI->attributes, tmp); 385} 386 387/* static CARD32 hashCI (xCharInfo *p); */ 388#define hashCI(p) \ 389 (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \ 390 (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \ 391 (p->characterWidth << 16) + \ 392 (p->ascent << 11) + (p->descent << 6)) ^ p->attributes) 393 394static int 395ProcXF86BigfontQueryFont( 396 ClientPtr client) 397{ 398 FontPtr pFont; 399 REQUEST(xXF86BigfontQueryFontReq); 400 CARD32 stuff_flags; 401 xCharInfo* pmax; 402 xCharInfo* pmin; 403 int nCharInfos; 404 int shmid; 405#ifdef HAS_SHM 406 ShmDescPtr pDesc; 407#else 408#define pDesc 0 409#endif 410 xCharInfo* pCI; 411 CARD16* pIndex2UniqIndex; 412 CARD16* pUniqIndex2Index; 413 CARD32 nUniqCharInfos; 414 415#if 0 416 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); 417#else 418 switch (client->req_len) { 419 case 2: /* client with version 1.0 libX11 */ 420 stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0); 421 break; 422 case 3: /* client with version 1.1 libX11 */ 423 stuff_flags = stuff->flags; 424 break; 425 default: 426 return BadLength; 427 } 428#endif 429 client->errorValue = stuff->id; /* EITHER font or gc */ 430 pFont = (FontPtr)SecurityLookupIDByType(client, stuff->id, RT_FONT, 431 DixGetAttrAccess); 432 if (!pFont) { 433 GC *pGC = (GC *) SecurityLookupIDByType(client, stuff->id, RT_GC, 434 DixGetAttrAccess); 435 if (!pGC) { 436 client->errorValue = stuff->id; 437 return BadFont; /* procotol spec says only error is BadFont */ 438 } 439 pFont = pGC->font; 440 } 441 442 pmax = FONTINKMAX(pFont); 443 pmin = FONTINKMIN(pFont); 444 nCharInfos = 445 (pmax->rightSideBearing == pmin->rightSideBearing 446 && pmax->leftSideBearing == pmin->leftSideBearing 447 && pmax->descent == pmin->descent 448 && pmax->ascent == pmin->ascent 449 && pmax->characterWidth == pmin->characterWidth) 450 ? 0 : N2dChars(pFont); 451 shmid = -1; 452 pCI = NULL; 453 pIndex2UniqIndex = NULL; 454 pUniqIndex2Index = NULL; 455 nUniqCharInfos = 0; 456 457 if (nCharInfos > 0) { 458#ifdef HAS_SHM 459 if (!badSysCall) 460 pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex); 461 else 462 pDesc = NULL; 463 if (pDesc) { 464 pCI = (xCharInfo *) pDesc->attach_addr; 465 if (stuff_flags & XF86Bigfont_FLAGS_Shm) 466 shmid = pDesc->shmid; 467 } else { 468 if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall) 469 pDesc = shmalloc(nCharInfos * sizeof(xCharInfo) 470 + sizeof(CARD32)); 471 if (pDesc) { 472 pCI = (xCharInfo *) pDesc->attach_addr; 473 shmid = pDesc->shmid; 474 } else { 475#endif 476 pCI = (xCharInfo *) 477 xalloc(nCharInfos * sizeof(xCharInfo)); 478 if (!pCI) 479 return BadAlloc; 480#ifdef HAS_SHM 481 } 482#endif 483 /* Fill nCharInfos starting at pCI. */ 484 { 485 xCharInfo* prCI = pCI; 486 int ninfos = 0; 487 int ncols = pFont->info.lastCol - pFont->info.firstCol + 1; 488 int row; 489 for (row = pFont->info.firstRow; 490 row <= pFont->info.lastRow && ninfos < nCharInfos; 491 row++) { 492 unsigned char chars[512]; 493 xCharInfo* tmpCharInfos[256]; 494 unsigned long count; 495 int col; 496 unsigned long i; 497 i = 0; 498 for (col = pFont->info.firstCol; 499 col <= pFont->info.lastCol; 500 col++) { 501 chars[i++] = row; 502 chars[i++] = col; 503 } 504 (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit, 505 &count, tmpCharInfos); 506 for (i = 0; i < count && ninfos < nCharInfos; i++) { 507 *prCI++ = *tmpCharInfos[i]; 508 ninfos++; 509 } 510 } 511 } 512#ifdef HAS_SHM 513 if (pDesc && !badSysCall) { 514 *(CARD32 *)(pCI + nCharInfos) = signature; 515 if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) { 516 shmdealloc(pDesc); 517 return BadAlloc; 518 } 519 } 520 } 521#endif 522 if (shmid == -1) { 523 /* Cannot use shared memory, so remove-duplicates the xCharInfos 524 using a temporary hash table. */ 525 /* Note that CARD16 is suitable as index type, because 526 nCharInfos <= 0x10000. */ 527 CARD32 hashModulus; 528 CARD16* pHash2UniqIndex; 529 CARD16* pUniqIndex2NextUniqIndex; 530 CARD32 NextIndex; 531 CARD32 NextUniqIndex; 532 CARD16* tmp; 533 CARD32 i, j; 534 535 hashModulus = 67; 536 if (hashModulus > nCharInfos+1) 537 hashModulus = nCharInfos+1; 538 539 tmp = (CARD16*) 540 xalloc((4*nCharInfos+1) * sizeof(CARD16)); 541 if (!tmp) { 542 if (!pDesc) xfree(pCI); 543 return BadAlloc; 544 } 545 pIndex2UniqIndex = tmp; 546 /* nCharInfos elements */ 547 pUniqIndex2Index = tmp + nCharInfos; 548 /* max. nCharInfos elements */ 549 pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos; 550 /* max. nCharInfos elements */ 551 pHash2UniqIndex = tmp + 3*nCharInfos; 552 /* hashModulus (<= nCharInfos+1) elements */ 553 554 /* Note that we can use 0xffff as end-of-list indicator, because 555 even if nCharInfos = 0x10000, 0xffff can not occur as valid 556 entry before the last element has been inserted. And once the 557 last element has been inserted, we don't need the hash table 558 any more. */ 559 for (j = 0; j < hashModulus; j++) 560 pHash2UniqIndex[j] = (CARD16)(-1); 561 562 NextUniqIndex = 0; 563 for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) { 564 xCharInfo* p = &pCI[NextIndex]; 565 CARD32 hashCode = hashCI(p) % hashModulus; 566 for (i = pHash2UniqIndex[hashCode]; 567 i != (CARD16)(-1); 568 i = pUniqIndex2NextUniqIndex[i]) { 569 j = pUniqIndex2Index[i]; 570 if (pCI[j].leftSideBearing == p->leftSideBearing 571 && pCI[j].rightSideBearing == p->rightSideBearing 572 && pCI[j].characterWidth == p->characterWidth 573 && pCI[j].ascent == p->ascent 574 && pCI[j].descent == p->descent 575 && pCI[j].attributes == p->attributes) 576 break; 577 } 578 if (i != (CARD16)(-1)) { 579 /* Found *p at Index j, UniqIndex i */ 580 pIndex2UniqIndex[NextIndex] = i; 581 } else { 582 /* Allocate a new entry in the Uniq table */ 583 if (hashModulus <= 2*NextUniqIndex 584 && hashModulus < nCharInfos+1) { 585 /* Time to increate hash table size */ 586 hashModulus = 2*hashModulus+1; 587 if (hashModulus > nCharInfos+1) 588 hashModulus = nCharInfos+1; 589 for (j = 0; j < hashModulus; j++) 590 pHash2UniqIndex[j] = (CARD16)(-1); 591 for (i = 0; i < NextUniqIndex; i++) 592 pUniqIndex2NextUniqIndex[i] = (CARD16)(-1); 593 for (i = 0; i < NextUniqIndex; i++) { 594 j = pUniqIndex2Index[i]; 595 p = &pCI[j]; 596 hashCode = hashCI(p) % hashModulus; 597 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; 598 pHash2UniqIndex[hashCode] = i; 599 } 600 p = &pCI[NextIndex]; 601 hashCode = hashCI(p) % hashModulus; 602 } 603 i = NextUniqIndex++; 604 pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode]; 605 pHash2UniqIndex[hashCode] = i; 606 pUniqIndex2Index[i] = NextIndex; 607 pIndex2UniqIndex[NextIndex] = i; 608 } 609 } 610 nUniqCharInfos = NextUniqIndex; 611 /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */ 612 } 613 } 614 615 { 616 int nfontprops = pFont->info.nprops; 617 int rlength = 618 sizeof(xXF86BigfontQueryFontReply) 619 + nfontprops * sizeof(xFontProp) 620 + (nCharInfos > 0 && shmid == -1 621 ? nUniqCharInfos * sizeof(xCharInfo) 622 + (nCharInfos+1)/2 * 2 * sizeof(CARD16) 623 : 0); 624 xXF86BigfontQueryFontReply* reply = 625 (xXF86BigfontQueryFontReply *) xalloc(rlength); 626 char* p; 627 if (!reply) { 628 if (nCharInfos > 0) { 629 if (shmid == -1) xfree(pIndex2UniqIndex); 630 if (!pDesc) xfree(pCI); 631 } 632 return BadAlloc; 633 } 634 reply->type = X_Reply; 635 reply->length = (rlength - sizeof(xGenericReply)) >> 2; 636 reply->sequenceNumber = client->sequence; 637 reply->minBounds = pFont->info.ink_minbounds; 638 reply->maxBounds = pFont->info.ink_maxbounds; 639 reply->minCharOrByte2 = pFont->info.firstCol; 640 reply->maxCharOrByte2 = pFont->info.lastCol; 641 reply->defaultChar = pFont->info.defaultCh; 642 reply->nFontProps = pFont->info.nprops; 643 reply->drawDirection = pFont->info.drawDirection; 644 reply->minByte1 = pFont->info.firstRow; 645 reply->maxByte1 = pFont->info.lastRow; 646 reply->allCharsExist = pFont->info.allExist; 647 reply->fontAscent = pFont->info.fontAscent; 648 reply->fontDescent = pFont->info.fontDescent; 649 reply->nCharInfos = nCharInfos; 650 reply->nUniqCharInfos = nUniqCharInfos; 651 reply->shmid = shmid; 652 reply->shmsegoffset = 0; 653 if (client->swapped) { 654 char tmp; 655 swaps(&reply->sequenceNumber, tmp); 656 swapl(&reply->length, tmp); 657 swapCharInfo(&reply->minBounds); 658 swapCharInfo(&reply->maxBounds); 659 swaps(&reply->minCharOrByte2, tmp); 660 swaps(&reply->maxCharOrByte2, tmp); 661 swaps(&reply->defaultChar, tmp); 662 swaps(&reply->nFontProps, tmp); 663 swaps(&reply->fontAscent, tmp); 664 swaps(&reply->fontDescent, tmp); 665 swapl(&reply->nCharInfos, tmp); 666 swapl(&reply->nUniqCharInfos, tmp); 667 swapl(&reply->shmid, tmp); 668 swapl(&reply->shmsegoffset, tmp); 669 } 670 p = (char*) &reply[1]; 671 { 672 FontPropPtr pFP; 673 xFontProp* prFP; 674 int i; 675 for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p; 676 i < nfontprops; 677 i++, pFP++, prFP++) { 678 prFP->name = pFP->name; 679 prFP->value = pFP->value; 680 if (client->swapped) { 681 char tmp; 682 swapl(&prFP->name, tmp); 683 swapl(&prFP->value, tmp); 684 } 685 } 686 p = (char*) prFP; 687 } 688 if (nCharInfos > 0 && shmid == -1) { 689 xCharInfo* pci; 690 CARD16* ps; 691 int i, j; 692 pci = (xCharInfo*) p; 693 for (i = 0; i < nUniqCharInfos; i++, pci++) { 694 *pci = pCI[pUniqIndex2Index[i]]; 695 if (client->swapped) 696 swapCharInfo(pci); 697 } 698 ps = (CARD16*) pci; 699 for (j = 0; j < nCharInfos; j++, ps++) { 700 *ps = pIndex2UniqIndex[j]; 701 if (client->swapped) { 702 char tmp; 703 swaps(ps, tmp); 704 } 705 } 706 } 707 WriteToClient(client, rlength, (char *)reply); 708 xfree(reply); 709 if (nCharInfos > 0) { 710 if (shmid == -1) xfree(pIndex2UniqIndex); 711 if (!pDesc) xfree(pCI); 712 } 713 return (client->noClientException); 714 } 715} 716 717static int 718ProcXF86BigfontDispatch( 719 ClientPtr client) 720{ 721 REQUEST(xReq); 722 723 switch (stuff->data) { 724 case X_XF86BigfontQueryVersion: 725 return ProcXF86BigfontQueryVersion(client); 726 case X_XF86BigfontQueryFont: 727 return ProcXF86BigfontQueryFont(client); 728 default: 729 return BadRequest; 730 } 731} 732 733static int 734SProcXF86BigfontQueryVersion( 735 ClientPtr client) 736{ 737 REQUEST(xXF86BigfontQueryVersionReq); 738 char tmp; 739 740 swaps(&stuff->length, tmp); 741 return ProcXF86BigfontQueryVersion(client); 742} 743 744static int 745SProcXF86BigfontQueryFont( 746 ClientPtr client) 747{ 748 REQUEST(xXF86BigfontQueryFontReq); 749 char tmp; 750 751 swaps(&stuff->length, tmp); 752 REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq); 753 swapl(&stuff->id, tmp); 754 return ProcXF86BigfontQueryFont(client); 755} 756 757static int 758SProcXF86BigfontDispatch( 759 ClientPtr client) 760{ 761 REQUEST(xReq); 762 763 switch (stuff->data) { 764 case X_XF86BigfontQueryVersion: 765 return SProcXF86BigfontQueryVersion(client); 766 case X_XF86BigfontQueryFont: 767 return SProcXF86BigfontQueryFont(client); 768 default: 769 return BadRequest; 770 } 771} 772