"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "xlab-0.8.3/decode11.c" of archive xlab-0.8.3.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*
    2  * $Id: decode11.c,v 1.4 1998/07/24 11:59:13 marc Exp $
    3  *
    4  *  Decoding and switching routines for the X11 protocol
    5  *
    6  *      James Peterson, 1988
    7  *      (c) Copyright MCC, 1988
    8  *      (c) Marc Vertes, 1998
    9  *
   10  */
   11 
   12 #include "scope.h"
   13 #include "x11.h"
   14 #include "print11.h"
   15 #include "server.h"
   16 #include "record.h"
   17 #include "common.h"
   18 
   19 /*
   20  * There are 4 types of things in X11: requests, replies, errors, and events.
   21  *
   22  * Each of them has a format defined by a small integer that defines
   23  * the type of the thing.
   24  *
   25  * Requests have an opcode in the first byte.
   26  * Events have a code in the first byte.
   27  * Errors have a code in the second byte (the first byte is 0)
   28  * Replies ...
   29  *
   30  * Replies have a sequence number in bytes 2 and 3.  The sequence
   31  * number should be used to identify the request that was sent, and
   32  * from that request we can determine the type of the reply.
   33  */
   34 
   35 /*----------------------------------------------------------------------*/
   36 /*
   37  * We need to keep the sequence number for a request to match it with
   38  * an expected reply.  The sequence number is associated only with the
   39  * particular connection that we have. We would expect these replies
   40  * to be handled as a FIFO queue.
   41  */
   42 
   43 struct QueueEntry {
   44     struct QueueEntry *Next;
   45     long SequenceNumber;
   46     short Request;
   47 };
   48 
   49 /* free space list of Q entries */
   50 static struct QueueEntry *FreeQEntries = NULL;
   51 
   52 /* define a queue of entries for each FD */
   53 struct QueueHeader {
   54     struct QueueEntry *Head;
   55     struct QueueEntry *Tail;
   56 };
   57 
   58 struct QueueHeader ReplyQ[StaticMaxFD];
   59 
   60 /*----------------------------------------------------------------------*/
   61 struct QueueEntry *NewQEntry(SequenceNumber, Request)
   62     long SequenceNumber;
   63     short Request;
   64 {
   65     struct QueueEntry *p;
   66 
   67     /* Get a Queue Entry */
   68     if (FreeQEntries == NULL) {
   69 	/* create new queue entry */
   70 	p = (struct QueueEntry *) Malloc((long) (sizeof(*p)));
   71     } else {
   72 	/* reuse an old queue entry */
   73 	p = FreeQEntries;
   74 	FreeQEntries = FreeQEntries->Next;
   75     }
   76 
   77     /* fill in its values */
   78     p->Next = NULL;
   79     p->SequenceNumber = SequenceNumber;
   80     p->Request = Request;
   81     return (p);
   82 }
   83 
   84 /*----------------------------------------------------------------------*/
   85 void InitReplyQ()
   86 {
   87     short i;
   88     for (i = 0; i < StaticMaxFD; i++) {
   89 	ReplyQ[i].Head = NULL;
   90 	ReplyQ[i].Tail = NULL;
   91     }
   92 }
   93 
   94 /*----------------------------------------------------------------------*/
   95 void FlushReplyQ(fd)
   96     FD fd;
   97 {
   98     struct QueueEntry *p;
   99     struct QueueEntry *NextQEntry;
  100 
  101     /* go down the reply queue and free all entries */
  102     for (p = ReplyQ[fd].Head; p != NULL; p = NextQEntry) {
  103 	NextQEntry = p->Next;
  104 
  105 	/* put freed entry on list of free entries (for later reuse)  */
  106 	p->Next = FreeQEntries;
  107 	FreeQEntries = p;
  108     }
  109 
  110     ReplyQ[fd].Head = NULL;
  111     ReplyQ[fd].Tail = NULL;
  112 }
  113 
  114 /*----------------------------------------------------------------------*/
  115 void DumpReplyQ(fd)
  116     FD fd;
  117 {
  118     fprintf(stderr, "ReplyQ[%ld] = { Head 0x%lx; Tail 0x%lx }\n",
  119 	    (long) fd, (long) ReplyQ[fd].Head, (long) ReplyQ[fd].Tail);
  120     {
  121 	struct QueueEntry *p;
  122 	for (p = ReplyQ[fd].Head; p != NULL; p = p->Next)
  123 	    fprintf(stderr, "0x%lx = { Next 0x%lx; SequenceNumber %ld; Request %d }\n",
  124 		    (long) p, (long) p->Next, p->SequenceNumber, p->Request);
  125     }
  126 }
  127 
  128 /*----------------------------------------------------------------------*/
  129 /* A reply is expected to the type of request given for the fd associated
  130  * with this one
  131  */
  132 void SequencedReplyExpected(fd, SequenceNumber, RequestType)
  133     FD fd;
  134     long SequenceNumber;
  135     short RequestType;
  136 {
  137     struct QueueEntry *p;
  138 
  139     debug(8, (stderr, "Reply expected: sequence %ld and request type %d for fd %d\n",
  140 	      SequenceNumber, RequestType, fd));
  141     /* create a new queue entry */
  142     p = NewQEntry(SequenceNumber, RequestType);
  143 
  144     /* find the server associated with this client */
  145     fd = FDPair(fd);
  146     if (fd < 0 || fd >= StaticMaxFD)
  147 	return;
  148 
  149     /* attach the new queue entry to the end of the queue for the Server */
  150     if (ReplyQ[fd].Tail != NULL)
  151 	(ReplyQ[fd].Tail)->Next = p;
  152     else
  153 	ReplyQ[fd].Head = p;
  154     ReplyQ[fd].Tail = p;
  155 
  156     debug(8, (stderr, "Save sequence %ld and request type %d for fd %d\n",
  157 	      p->SequenceNumber, p->Request, fd));
  158 }
  159 
  160 
  161 /*----------------------------------------------------------------------*/
  162 static FD Lastfd;
  163 static long LastSequenceNumber;
  164 static short LastReplyType;
  165 
  166 /*
  167  * Search for the type of request that is associated with a reply
  168  * to the given sequence number for this fd
  169  */
  170 
  171 short CheckReplyTable(fd, SequenceNumber)
  172     FD fd;
  173     short SequenceNumber;
  174 {
  175     struct QueueEntry *p;
  176     struct QueueEntry *trailer;
  177 
  178     if (debuglevel & 128)
  179 	DumpReplyQ(fd);
  180     for (trailer = NULL, p = ReplyQ[fd].Head;
  181 	 p != NULL;
  182 	 trailer = p, p = p->Next) {
  183 	/* look for matching sequence number in queue of this fd */
  184 	if (SequenceNumber == ((short) (0xFFFF & p->SequenceNumber))) {
  185 	    /* save the Request type */
  186 	    Lastfd = fd;
  187 	    LastSequenceNumber = p->SequenceNumber;
  188 	    LastReplyType = p->Request;
  189 
  190 	    /* pull the queue entry out of the queue for this fd */
  191 	    if (trailer == NULL)
  192 		ReplyQ[fd].Head = p->Next;
  193 	    else
  194 		trailer->Next = p->Next;
  195 	    if (ReplyQ[fd].Tail == p)
  196 		ReplyQ[fd].Tail = trailer;
  197 
  198 
  199 	    /* put freed entry on list of free entries (for later reuse)  */
  200 	    p->Next = FreeQEntries;
  201 	    FreeQEntries = p;
  202 
  203 	    debug(8, (stderr, "Reply on fd %d for sequence %d is type %d\n",
  204 		      fd, SequenceNumber, LastReplyType));
  205 	    return (LastReplyType);
  206 	}
  207     }
  208 
  209     /* not expecting a reply for that sequence number */
  210     debug(8, (stderr, "Reply on fd %d for sequence %d is not found\n",
  211 	      fd, SequenceNumber));
  212     return (0);
  213 }
  214 
  215 /*----------------------------------------------------------------------*/
  216 /*
  217  * A reply is expected to the type of request given for the
  218  * sequence number associated with this fd.
  219  */
  220 void ReplyExpected(fd, Request)
  221     FD fd;
  222     short Request;
  223 {
  224     SequencedReplyExpected(fd, CS[fd].SequenceNumber, Request);
  225 }
  226 
  227 /*----------------------------------------------------------------------*/
  228 /*
  229  * Another reply is expected for the same reply as we just had
  230  * This is only used with ListFontsWithInfo
  231  */
  232 void KeepLastReplyExpected()
  233 {
  234     SequencedReplyExpected(Lastfd, LastSequenceNumber, LastReplyType);
  235 }
  236 
  237 /*----------------------------------------------------------------------*/
  238 void DecodeRequest(fd, buf, n)
  239     FD fd;
  240     unsigned char *buf;
  241     long n;
  242 {
  243     short Request = IByte(&buf[0]);
  244 
  245     bcopy((char *) &(CS[fd].SequenceNumber), (char *) SBf, sizeof(long));
  246     SetIndentLevel(PRINTCLIENT);
  247 
  248     if (Verbose > 3)
  249 	DumpItem("Request", fd, buf, n);
  250     if (Request <= 0 || 127 < Request) {
  251 /*      if (Request == 130 || Request == 128) { */
  252 
  253 	warn("Extended request opcode");
  254     } else
  255 	switch (Request) {
  256 	case 1:
  257 	    CreateWindow(buf);
  258 	    break;
  259 	case 2:
  260 	    ChangeWindowAttributes(buf);
  261 	    break;
  262 	case 3:
  263 	    GetWindowAttributes(buf);
  264 	    ReplyExpected(fd, Request);
  265 	    break;
  266 	case 4:
  267 	    DestroyWindow(buf);
  268 	    break;
  269 	case 5:
  270 	    DestroySubwindows(buf);
  271 	    break;
  272 	case 6:
  273 	    ChangeSaveSet(buf);
  274 	    break;
  275 	case 7:
  276 	    ReparentWindow(buf);
  277 	    break;
  278 	case 8:
  279 	    MapWindow(buf);
  280 	    break;
  281 	case 9:
  282 	    MapSubwindows(buf);
  283 	    break;
  284 	case 10:
  285 	    UnmapWindow(buf);
  286 	    break;
  287 	case 11:
  288 	    UnmapSubwindows(buf);
  289 	    break;
  290 	case 12:
  291 	    ConfigureWindow(buf);
  292 	    break;
  293 	case 13:
  294 	    CirculateWindow(buf);
  295 	    break;
  296 	case 14:
  297 	    GetGeometry(buf);
  298 	    ReplyExpected(fd, Request);
  299 	    break;
  300 	case 15:
  301 	    QueryTree(buf);
  302 	    ReplyExpected(fd, Request);
  303 	    break;
  304 	case 16:
  305 	    InternAtom(buf);
  306 	    ReplyExpected(fd, Request);
  307 	    break;
  308 	case 17:
  309 	    GetAtomName(buf);
  310 	    ReplyExpected(fd, Request);
  311 	    break;
  312 	case 18:
  313 	    ChangeProperty(buf);
  314 	    break;
  315 	case 19:
  316 	    DeleteProperty(buf);
  317 	    break;
  318 	case 20:
  319 	    GetProperty(buf);
  320 	    ReplyExpected(fd, Request);
  321 	    break;
  322 	case 21:
  323 	    ListProperties(buf);
  324 	    ReplyExpected(fd, Request);
  325 	    break;
  326 	case 22:
  327 	    SetSelectionOwner(buf);
  328 	    break;
  329 	case 23:
  330 	    GetSelectionOwner(buf);
  331 	    ReplyExpected(fd, Request);
  332 	    break;
  333 	case 24:
  334 	    ConvertSelection(buf);
  335 	    break;
  336 	case 25:
  337 	    SendEvent(buf);
  338 	    break;
  339 	case 26:
  340 	    GrabPointer(buf);
  341 	    ReplyExpected(fd, Request);
  342 	    break;
  343 	case 27:
  344 	    UngrabPointer(buf);
  345 	    break;
  346 	case 28:
  347 	    GrabButton(buf);
  348 	    break;
  349 	case 29:
  350 	    UngrabButton(buf);
  351 	    break;
  352 	case 30:
  353 	    ChangeActivePointerGrab(buf);
  354 	    break;
  355 	case 31:
  356 	    GrabKeyboard(buf);
  357 	    ReplyExpected(fd, Request);
  358 	    break;
  359 	case 32:
  360 	    UngrabKeyboard(buf);
  361 	    break;
  362 	case 33:
  363 	    GrabKey(buf);
  364 	    break;
  365 	case 34:
  366 	    UngrabKey(buf);
  367 	    break;
  368 	case 35:
  369 	    AllowEvents(buf);
  370 	    break;
  371 	case 36:
  372 	    GrabServer(buf);
  373 	    break;
  374 	case 37:
  375 	    UngrabServer(buf);
  376 	    break;
  377 	case 38:
  378 	    QueryPointer(buf);
  379 	    ReplyExpected(fd, Request);
  380 	    break;
  381 	case 39:
  382 	    GetMotionEvents(buf);
  383 	    ReplyExpected(fd, Request);
  384 	    break;
  385 	case 40:
  386 	    TranslateCoordinates(buf);
  387 	    ReplyExpected(fd, Request);
  388 	    break;
  389 	case 41:
  390 	    WarpPointer(buf);
  391 	    break;
  392 	case 42:
  393 	    SetInputFocus(buf);
  394 	    break;
  395 	case 43:
  396 	    GetInputFocus(buf);
  397 	    ReplyExpected(fd, Request);
  398 	    break;
  399 	case 44:
  400 	    QueryKeymap(buf);
  401 	    ReplyExpected(fd, Request);
  402 	    break;
  403 	case 45:
  404 	    OpenFont(buf);
  405 	    break;
  406 	case 46:
  407 	    CloseFont(buf);
  408 	    break;
  409 	case 47:
  410 	    QueryFont(buf);
  411 	    ReplyExpected(fd, Request);
  412 	    break;
  413 	case 48:
  414 	    QueryTextExtents(buf);
  415 	    ReplyExpected(fd, Request);
  416 	    break;
  417 	case 49:
  418 	    ListFonts(buf);
  419 	    ReplyExpected(fd, Request);
  420 	    break;
  421 	case 50:
  422 	    ListFontsWithInfo(buf);
  423 	    ReplyExpected(fd, Request);
  424 	    break;
  425 	case 51:
  426 	    SetFontPath(buf);
  427 	    break;
  428 	case 52:
  429 	    GetFontPath(buf);
  430 	    ReplyExpected(fd, Request);
  431 	    break;
  432 	case 53:
  433 	    CreatePixmap(buf);
  434 	    break;
  435 	case 54:
  436 	    FreePixmap(buf);
  437 	    break;
  438 	case 55:
  439 	    CreateGC(buf);
  440 	    break;
  441 	case 56:
  442 	    ChangeGC(buf);
  443 	    break;
  444 	case 57:
  445 	    CopyGC(buf);
  446 	    break;
  447 	case 58:
  448 	    SetDashes(buf);
  449 	    break;
  450 	case 59:
  451 	    SetClipRectangles(buf);
  452 	    break;
  453 	case 60:
  454 	    FreeGC(buf);
  455 	    break;
  456 	case 61:
  457 	    ClearArea(buf);
  458 	    break;
  459 	case 62:
  460 	    CopyArea(buf);
  461 	    break;
  462 	case 63:
  463 	    CopyPlane(buf);
  464 	    break;
  465 	case 64:
  466 	    PolyPoint(buf);
  467 	    break;
  468 	case 65:
  469 	    PolyLine(buf);
  470 	    break;
  471 	case 66:
  472 	    PolySegment(buf);
  473 	    break;
  474 	case 67:
  475 	    PolyRectangle(buf);
  476 	    break;
  477 	case 68:
  478 	    PolyArc(buf);
  479 	    break;
  480 	case 69:
  481 	    FillPoly(buf);
  482 	    break;
  483 	case 70:
  484 	    PolyFillRectangle(buf);
  485 	    break;
  486 	case 71:
  487 	    PolyFillArc(buf);
  488 	    break;
  489 	case 72:
  490 	    PutImage(buf);
  491 	    break;
  492 	case 73:
  493 	    GetImage(buf);
  494 	    ReplyExpected(fd, Request);
  495 	    break;
  496 	case 74:
  497 	    PolyText8(buf);
  498 	    break;
  499 	case 75:
  500 	    PolyText16(buf);
  501 	    break;
  502 	case 76:
  503 	    ImageText8(buf);
  504 	    break;
  505 	case 77:
  506 	    ImageText16(buf);
  507 	    break;
  508 	case 78:
  509 	    CreateColormap(buf);
  510 	    break;
  511 	case 79:
  512 	    FreeColormap(buf);
  513 	    break;
  514 	case 80:
  515 	    CopyColormapAndFree(buf);
  516 	    break;
  517 	case 81:
  518 	    InstallColormap(buf);
  519 	    break;
  520 	case 82:
  521 	    UninstallColormap(buf);
  522 	    break;
  523 	case 83:
  524 	    ListInstalledColormaps(buf);
  525 	    ReplyExpected(fd, Request);
  526 	    break;
  527 	case 84:
  528 	    AllocColor(buf);
  529 	    ReplyExpected(fd, Request);
  530 	    break;
  531 	case 85:
  532 	    AllocNamedColor(buf);
  533 	    ReplyExpected(fd, Request);
  534 	    break;
  535 	case 86:
  536 	    AllocColorCells(buf);
  537 	    ReplyExpected(fd, Request);
  538 	    break;
  539 	case 87:
  540 	    AllocColorPlanes(buf);
  541 	    ReplyExpected(fd, Request);
  542 	    break;
  543 	case 88:
  544 	    FreeColors(buf);
  545 	    break;
  546 	case 89:
  547 	    StoreColors(buf);
  548 	    break;
  549 	case 90:
  550 	    StoreNamedColor(buf);
  551 	    break;
  552 	case 91:
  553 	    QueryColors(buf);
  554 	    ReplyExpected(fd, Request);
  555 	    break;
  556 	case 92:
  557 	    LookupColor(buf);
  558 	    ReplyExpected(fd, Request);
  559 	    break;
  560 	case 93:
  561 	    CreateCursor(buf);
  562 	    break;
  563 	case 94:
  564 	    CreateGlyphCursor(buf);
  565 	    break;
  566 	case 95:
  567 	    FreeCursor(buf);
  568 	    break;
  569 	case 96:
  570 	    RecolorCursor(buf);
  571 	    break;
  572 	case 97:
  573 	    QueryBestSize(buf);
  574 	    ReplyExpected(fd, Request);
  575 	    break;
  576 	case 98:
  577 	    QueryExtension(buf);
  578 	    ReplyExpected(fd, Request);
  579 	    break;
  580 	case 99:
  581 	    ListExtensions(buf);
  582 	    ReplyExpected(fd, Request);
  583 	    break;
  584 	case 100:
  585 	    ChangeKeyboardMapping(buf);
  586 	    break;
  587 	case 101:
  588 	    GetKeyboardMapping(buf);
  589 	    ReplyExpected(fd, Request);
  590 	    break;
  591 	case 102:
  592 	    ChangeKeyboardControl(buf);
  593 	    break;
  594 	case 103:
  595 	    GetKeyboardControl(buf);
  596 	    ReplyExpected(fd, Request);
  597 	    break;
  598 	case 104:
  599 	    Bell(buf);
  600 	    break;
  601 	case 105:
  602 	    ChangePointerControl(buf);
  603 	    break;
  604 	case 106:
  605 	    GetPointerControl(buf);
  606 	    ReplyExpected(fd, Request);
  607 	    break;
  608 	case 107:
  609 	    SetScreenSaver(buf);
  610 	    break;
  611 	case 108:
  612 	    GetScreenSaver(buf);
  613 	    ReplyExpected(fd, Request);
  614 	    break;
  615 	case 109:
  616 	    ChangeHosts(buf);
  617 	    break;
  618 	case 110:
  619 	    ListHosts(buf);
  620 	    ReplyExpected(fd, Request);
  621 	    break;
  622 	case 111:
  623 	    SetAccessControl(buf);
  624 	    break;
  625 	case 112:
  626 	    SetCloseDownMode(buf);
  627 	    break;
  628 	case 113:
  629 	    KillClient(buf);
  630 	    break;
  631 	case 114:
  632 	    RotateProperties(buf);
  633 	    break;
  634 	case 115:
  635 	    ForceScreenSaver(buf);
  636 	    break;
  637 	case 116:
  638 	    SetPointerMapping(buf);
  639 	    ReplyExpected(fd, Request);
  640 	    break;
  641 	case 117:
  642 	    GetPointerMapping(buf);
  643 	    ReplyExpected(fd, Request);
  644 	    break;
  645 	case 118:
  646 	    SetModifierMapping(buf);
  647 	    ReplyExpected(fd, Request);
  648 	    break;
  649 	case 119:
  650 	    GetModifierMapping(buf);
  651 	    ReplyExpected(fd, Request);
  652 	    break;
  653 	case 127:
  654 	    NoOperation(buf);
  655 	    break;
  656 	default:
  657 	    warn("Unimplemented request opcode");
  658 	    break;
  659 	}
  660 }
  661 
  662 /*----------------------------------------------------------------------*/
  663 int GrabTimeoutProc(timer, message)
  664     TimerID timer;
  665     char *message;
  666 {
  667     extern unsigned long int GrabTimeout;
  668 
  669     fprintf(stderr,
  670 	    "xscript: deadlock prevention feature activated.\n");
  671 
  672     fprintf(stderr,
  673 	    "xscript: %s: %ld-second timeout expired; aborting.\n",
  674 	    message,
  675 	    GrabTimeout);
  676 
  677     fprintf(stderr,
  678 	 "xscript: to change timeout, rerun with -G<timeout> option.\n");
  679 
  680     exit(1);
  681 }
  682 
  683 /*----------------------------------------------------------------------*/
  684 int whichGrab = -1;
  685 int status = -1;
  686 
  687 void ProcessGrab(fd, buf, n)
  688     FD fd;
  689     unsigned char *buf;
  690     long n;
  691 {
  692     static TimerID blastGrabTimer[3] =
  693     {0, 0, 0};
  694     extern unsigned long int GrabTimeout;
  695     char *message = (char *)NULL;
  696     short Request = IByte(&buf[0]);
  697     int i;
  698     int j;
  699 
  700     switch (Request) {
  701 
  702     case 26:
  703 	/* GrabPointer */
  704 	whichGrab = 1;
  705 	status = 1;
  706 	message = "GrabPointer";
  707 	break;
  708     case 27:
  709 	/* UngrabPointer */
  710 	whichGrab = 1;
  711 	status = 0;
  712 	break;
  713 
  714     case 31:
  715 	/* GrabKeyboard */
  716 	whichGrab = 2;
  717 	status = 1;
  718 	message = "GrabKeyboard";
  719 	break;
  720     case 32:
  721 	/* UngrabKeyboard */
  722 	whichGrab = 2;
  723 	status = 0;
  724 	break;
  725 
  726     case 35:
  727 	/* AllowEvents */
  728 	{
  729 	    short mode = IByte(&buf[1]);
  730 	    switch (mode) {
  731 	    case 0:		/* AsyncPointer */
  732 		whichGrab = 1;
  733 		status = 0;
  734 		break;
  735 	    case 1:		/* SyncPointer */
  736 		whichGrab = 1;
  737 		status = 1;
  738 		message = "AllowEvents(SyncPointer)";
  739 		break;
  740 	    case 2:		/* ReplayPointer */
  741 		whichGrab = 1;
  742 		status = 0;
  743 		break;
  744 
  745 	    case 3:		/* AsyncKeyboard */
  746 		whichGrab = 2;
  747 		status = 0;
  748 		break;
  749 	    case 4:		/* SyncKeyboard */
  750 		whichGrab = 2;
  751 		status = 1;
  752 		message = "AllowEvents(SyncKeyboard)";
  753 		break;
  754 	    case 5:		/* ReplayKeyboard */
  755 		whichGrab = 2;
  756 		status = 0;
  757 		break;
  758 
  759 	    case 6:		/* AsyncBoth */
  760 		whichGrab = 3;
  761 		status = 0;
  762 		break;
  763 	    case 7:		/* SyncBoth */
  764 		whichGrab = 3;
  765 		status = 1;
  766 		message = "AllowEvents(SyncBoth)";
  767 		break;
  768 	    }
  769 	}
  770 	break;
  771 
  772     case 36:
  773 	/* GrabServer */
  774 	whichGrab = 4;
  775 	status = 1;
  776 	message = "GrabServer";
  777 	break;
  778     case 37:
  779 	/* UngrabServer */
  780 	whichGrab = 4;
  781 	status = 0;
  782 	break;
  783     }
  784 
  785     if (status >= 0) {
  786 	for (i = 0; i <= 2; i++) {
  787 	    j = 1 & (whichGrab >> i);
  788 	    if (j) {
  789 		switch (status) {
  790 
  791 		case 1:	/* start a grab */
  792 		    if (blastGrabTimer[i])
  793 			DeleteTimer(blastGrabTimer[i]);
  794 		    blastGrabTimer[i] = CreateTimer(1000 * GrabTimeout,
  795 						    (void (*)()) GrabTimeoutProc,
  796 						    message);
  797 		    break;
  798 		case 0:	/* end a grab */
  799 		    if (blastGrabTimer[i]) {
  800 			DeleteTimer(blastGrabTimer[i]);
  801 			blastGrabTimer[i] = 0;
  802 		    }
  803 		    break;
  804 		}
  805 	    }
  806 	}
  807     }
  808 }
  809 
  810 /*----------------------------------------------------------------------*/
  811 /*
  812  * This function is activated during replay to avoid lost sequence
  813  * messages due to Xlib requests buffering.
  814  */
  815 void FixReplySeq(fd, buf, n)
  816     FD fd;
  817     unsigned char *buf;
  818     long n;
  819 {
  820     static unsigned short last_rep_seq = 0;
  821     unsigned short SequenceNumber = IShort(&buf[2]);
  822     /* unsigned short Request = CheckReplyTable(fd, SequenceNumber); */
  823     FD pairfd = FDPair(fd);
  824     unsigned short int seq = 0;
  825     /* obtain the sequence number from the client-side CS structure */
  826 
  827     if (pairfd >= StaticMaxFD)
  828 	pairfd = -1;
  829     if (pairfd >= 0)
  830 	seq = CS[pairfd].SequenceNumber;
  831 
  832     CS[pairfd].SequenceNumber = IShort(&buf[2]);
  833 
  834     fprintf(stderr, "Reply seq %x  <--> CS.req %x, last %x\n", SequenceNumber, seq, last_rep_seq);
  835     last_rep_seq = SequenceNumber;
  836 }
  837 
  838 /*----------------------------------------------------------------------*/
  839 void DecodeReply(fd, buf, n)
  840     FD fd;
  841     unsigned char *buf;
  842     long n;
  843 {
  844     short SequenceNumber = IShort(&buf[2]);
  845     short Request = CheckReplyTable(fd, SequenceNumber);
  846 
  847     if (Request == 0) {
  848 	warn("Unexpected reply");
  849 	return;
  850     }
  851     SetIndentLevel(PRINTSERVER);
  852     RBf[0] = Request /* for the PrintField in the Reply procedure */ ;
  853     if (Verbose > 3)
  854 	DumpItem("Reply", fd, buf, n);
  855     if (Request == 130 || Request == 128) {
  856 	warn("Extended reply opcode");
  857     } else if (Request <= 0 || 127 < Request)
  858 	warn("Extended reply opcode");
  859     else
  860 	switch (Request) {
  861 	case 3:
  862 	    GetWindowAttributesReply(buf);
  863 	    break;
  864 	case 14:
  865 	    GetGeometryReply(buf);
  866 	    break;
  867 	case 15:
  868 	    QueryTreeReply(buf);
  869 	    break;
  870 	case 16:
  871 	    InternAtomReply(buf);
  872 	    break;
  873 	case 17:
  874 	    GetAtomNameReply(buf);
  875 	    break;
  876 	case 20:
  877 	    GetPropertyReply(buf);
  878 	    break;
  879 	case 21:
  880 	    ListPropertiesReply(buf);
  881 	    break;
  882 	case 23:
  883 	    GetSelectionOwnerReply(buf);
  884 	    break;
  885 	case 26:
  886 	    GrabPointerReply(buf);
  887 	    break;
  888 	case 31:
  889 	    GrabKeyboardReply(buf);
  890 	    break;
  891 	case 38:
  892 	    QueryPointerReply(buf);
  893 	    break;
  894 	case 39:
  895 	    GetMotionEventsReply(buf);
  896 	    break;
  897 	case 40:
  898 	    TranslateCoordinatesReply(buf);
  899 	    break;
  900 	case 43:
  901 	    GetInputFocusReply(buf);
  902 	    break;
  903 	case 44:
  904 	    QueryKeymapReply(buf);
  905 	    break;
  906 	case 47:
  907 	    QueryFontReply(buf);
  908 	    break;
  909 	case 48:
  910 	    QueryTextExtentsReply(buf);
  911 	    break;
  912 	case 49:
  913 	    ListFontsReply(buf);
  914 	    break;
  915 	case 50:
  916 	    ListFontsWithInfoReply(buf);
  917 	    break;
  918 	case 52:
  919 	    GetFontPathReply(buf);
  920 	    break;
  921 	case 73:
  922 	    GetImageReply(buf);
  923 	    break;
  924 	case 83:
  925 	    ListInstalledColormapsReply(buf);
  926 	    break;
  927 	case 84:
  928 	    AllocColorReply(buf);
  929 	    break;
  930 	case 85:
  931 	    AllocNamedColorReply(buf);
  932 	    break;
  933 	case 86:
  934 	    AllocColorCellsReply(buf);
  935 	    break;
  936 	case 87:
  937 	    AllocColorPlanesReply(buf);
  938 	    break;
  939 	case 91:
  940 	    QueryColorsReply(buf);
  941 	    break;
  942 	case 92:
  943 	    LookupColorReply(buf);
  944 	    break;
  945 	case 97:
  946 	    QueryBestSizeReply(buf);
  947 	    break;
  948 	case 98:
  949 	    QueryExtensionReply(buf);
  950 	    break;
  951 	case 99:
  952 	    ListExtensionsReply(buf);
  953 	    break;
  954 	case 101:
  955 	    GetKeyboardMappingReply(buf);
  956 	    break;
  957 	case 103:
  958 	    GetKeyboardControlReply(buf);
  959 	    break;
  960 	case 106:
  961 	    GetPointerControlReply(buf);
  962 	    break;
  963 	case 108:
  964 	    GetScreenSaverReply(buf);
  965 	    break;
  966 	case 110:
  967 	    ListHostsReply(buf);
  968 	    break;
  969 	case 116:
  970 	    SetPointerMappingReply(buf);
  971 	    break;
  972 	case 117:
  973 	    GetPointerMappingReply(buf);
  974 	    break;
  975 	case 118:
  976 	    SetModifierMappingReply(buf);
  977 	    break;
  978 	case 119:
  979 	    GetModifierMappingReply(buf);
  980 	    break;
  981 	default:
  982 	    warn("Unimplemented reply opcode");
  983 	    break;
  984 	}
  985 }
  986 
  987 /*----------------------------------------------------------------------*/
  988 void DecodeError(fd, buf, n)
  989     FD fd;
  990     unsigned char *buf;
  991     long n;
  992 {
  993     short Error = IByte(&buf[1]);
  994     SetIndentLevel(PRINTSERVER);
  995     if (Verbose > 3)
  996 	DumpItem("Error", fd, buf, n);
  997