1 #include "dxpcconf.h"
2 #include <string.h>
3 #include "X-headers.H"
4 #include "ServerChannel.H"
5 #include "EncodeBuffer.H"
6 #include "DecodeBuffer.H"
7 #include "util.H"
8 
ServerChannel(int xServerFD,unsigned int statisticsLevel)9 ServerChannel::ServerChannel(int xServerFD,
10                              unsigned int
11                              statisticsLevel) :
12     readBuffer_(xServerFD, this),
13     fd_(xServerFD),
14     firstRequest_(1),
15     firstReply_(1),
16     statisticsLevel_(statisticsLevel)
17 {
18     if (compressImages)
19     {
20         decompresser = new Decompresser(compressImages);
21     }
22     else
23     {
24         decompresser = 0;
25     }
26 }
27 
28 
~ServerChannel()29 ServerChannel::~ServerChannel()
30 {
31     if (statisticsLevel_ > 0)
32     {
33         *logofs << "\n*** dxpc Server-side Compression Statistics ***\n";
34         unsigned int replyBitsIn, replyBitsOut;
35 
36         if (statisticsLevel_ >= 2)
37         {
38             *logofs << "\nCompression of replies by request message type:\n";
39         }
40         replyStats_.summarize(replyBitsIn, replyBitsOut,
41                               (statisticsLevel_ >= 2));
42 
43         if (statisticsLevel_ >= 2)
44         {
45             *logofs <<
46                 "\nCompression of events and errors by message type:\n";
47         }
48         unsigned int bitsIn, bitsOut;
49 
50         stats_.summarize(bitsIn, bitsOut, (statisticsLevel_ >= 2));
51 
52         if (statisticsLevel_ >= 2)
53         {
54             *logofs << '\n' << framingBitsOut_ <<
55                 " bits used for dxpc message framing and multiplexing\n";
56         }
57 
58         unsigned int totalBitsIn = bitsIn + replyBitsIn;
59         unsigned int totalBitsOut = bitsOut + replyBitsOut + framingBitsOut_;
60 
61         *logofs << "\nOverall compression:" << ENDL << "  " <<
62             totalBitsIn << " bits compressed to " << totalBitsOut << ENDL;
63         if (totalBitsOut > 0)
64         {
65             *logofs << "  (" << (float) totalBitsIn / (float) totalBitsOut <<
66                 ":1 compression ratio)" << ENDL << ENDL;
67         }
68     }
69 
70     if (decompresser)
71     {
72         delete decompresser;
73 
74         decompresser = 0;
75     }
76 }
77 
78 
doRead(EncodeBuffer & encodeBuffer)79 int ServerChannel::doRead(EncodeBuffer & encodeBuffer)
80 {
81     if (!readBuffer_.doRead())
82         return 0;
83 
84     const unsigned char *buffer;
85     unsigned int size;
86 
87     while ((buffer = readBuffer_.getMessage(size)) != 0)
88     {
89         if (firstReply_)
90         {
91             imageByteOrder_ = buffer[30];
92             bitmapBitOrder_ = buffer[31];
93             scanlineUnit_ = buffer[32];
94             scanlinePad_ = buffer[33];
95             firstReply_ = 0;
96             encodeBuffer.encodeValue((unsigned int) buffer[0], 8);
97             encodeBuffer.encodeValue((unsigned int) buffer[1], 8);
98             encodeBuffer.encodeValue(GetUINT(buffer + 2, bigEndian_), 16);
99             encodeBuffer.encodeValue(GetUINT(buffer + 4, bigEndian_), 16);
100             encodeBuffer.encodeValue(GetUINT(buffer + 6, bigEndian_), 16);
101             if (ServerCache::lastInitReply.compare(size - 8, buffer + 8))
102                 encodeBuffer.encodeValue(1, 1);
103             else
104             {
105                 encodeBuffer.encodeValue(0, 1);
106                 for (unsigned int i = 8; i < size; i++)
107                     encodeBuffer.encodeValue((unsigned int) buffer[i], 8);
108             }
109         }
110         else
111         {
112             if (buffer[0] == 1)
113             {
114                 // reply
115                 unsigned int sequenceNum = GetUINT(buffer + 2, bigEndian_);
116                 unsigned int sequenceNumDiff =
117                     sequenceNum - serverCache_.lastSequenceNum;
118                 serverCache_.lastSequenceNum = sequenceNum;
119 
120                 unsigned char opcode = *buffer;
121 
122                 encodeBuffer.encodeCachedValue(opcode, 8,
123                                                serverCache_.
124                                                opcodeCache[serverCache_.
125                                                            lastOpcode]);
126                 serverCache_.lastOpcode = opcode;
127                 encodeBuffer.encodeCachedValue(sequenceNumDiff, 16,
128                                                serverCache_.
129                                                replySequenceNumCache, 7);
130 
131                 unsigned short int nextSequenceNum;
132                 unsigned int requestOpcode = 256;
133                 unsigned char nextOpcode;
134 
135                 if (sequenceNumQueue_.peek(nextSequenceNum, nextOpcode) &&
136                     (nextSequenceNum == sequenceNum))
137                 {
138                     // we've found the request that generated this reply, so it's
139                     // possible to compress the reply based on the request type
140                     unsigned int requestData[3];
141 
142                     sequenceNumQueue_.pop(nextSequenceNum, nextOpcode,
143                                           requestData[0], requestData[1],
144                                           requestData[2]);
145                     requestOpcode = nextOpcode;
146                     switch (nextOpcode)
147                     {
148                     case X_AllocColor:
149                         {
150                             const unsigned char *nextSrc = buffer + 8;
151 
152                             for (unsigned int i = 0; i < 3; i++)
153                             {
154                                 unsigned int colorValue =
155                                     GetUINT(nextSrc, bigEndian_);
156                                 nextSrc += 2;
157                                 if (colorValue == requestData[i])
158                                     encodeBuffer.encodeValue(1, 1);
159                                 else
160                                 {
161                                     encodeBuffer.encodeValue(0, 1);
162                                     encodeBuffer.encodeValue(colorValue -
163                                                              colorValue, 16,
164                                                              6);
165                                 }
166                             }
167                             unsigned int pixel =
168                                 GetULONG(buffer + 16, bigEndian_);
169                             encodeBuffer.encodeValue(pixel, 32, 9);
170                         }
171                         break;
172                     case X_GetAtomName:
173                         {
174                             unsigned int nameLength =
175                                 GetUINT(buffer + 8, bigEndian_);
176                             encodeBuffer.encodeValue(nameLength, 16, 6);
177                             const unsigned char *nextSrc = buffer + 32;
178 
179                             clientCache_.internAtomTextCompressor.reset();
180                             for (unsigned int i = 0; i < nameLength; i++)
181                                 clientCache_.internAtomTextCompressor.
182                                     encodeChar(*nextSrc++, encodeBuffer);
183                         }
184                         break;
185                     case X_GetGeometry:
186                         {
187                             encodeBuffer.encodeCachedValue(buffer[1], 8,
188                                                            serverCache_.
189                                                            depthCache);
190                             encodeBuffer.
191                                 encodeCachedValue(GetULONG
192                                                   (buffer + 8, bigEndian_),
193                                                   29,
194                                                   serverCache_.
195                                                   getGeometryRootCache, 9);
196                             const unsigned char *nextSrc = buffer + 12;
197 
198                             for (unsigned int i = 0; i < 5; i++)
199                             {
200                                 encodeBuffer.
201                                     encodeCachedValue(GetUINT
202                                                       (nextSrc, bigEndian_),
203                                                       16,
204                                                       *serverCache_.
205                                                       getGeometryGeomCache[i],
206                                                       8);
207                                 nextSrc += 2;
208                             }
209                         }
210                         break;
211                     case X_GetInputFocus:
212                         {
213                             encodeBuffer.encodeValue((unsigned int) buffer[1],
214                                                      2);
215                             encodeBuffer.
216                                 encodeCachedValue(GetULONG
217                                                   (buffer + 8, bigEndian_),
218                                                   29,
219                                                   serverCache_.
220                                                   getInputFocusWindowCache,
221                                                   9);
222                         }
223                         break;
224                     case X_GetKeyboardMapping:
225                         {
226                             unsigned int keysymsPerKeycode =
227                                 (unsigned int) buffer[1];
228                             if (ServerCache::getKeyboardMappingLastMap.
229                                 compare(size - 32, buffer + 32)
230                                 && (keysymsPerKeycode ==
231                                     ServerCache::
232                                     getKeyboardMappingLastKeysymsPerKeycode))
233                             {
234                                 encodeBuffer.encodeValue(1, 1);
235                                 break;
236                             }
237                             ServerCache::
238                                 getKeyboardMappingLastKeysymsPerKeycode =
239                                 keysymsPerKeycode;
240                             encodeBuffer.encodeValue(0, 1);
241                             unsigned int numKeycodes =
242                                 (((size - 32) / keysymsPerKeycode) >> 2);
243                             encodeBuffer.encodeValue(numKeycodes, 8);
244                             encodeBuffer.encodeValue(keysymsPerKeycode, 8, 4);
245                             const unsigned char *nextSrc = buffer + 32;
246                             unsigned char previous = 0;
247 
248                             for (unsigned int count =
249                                  numKeycodes * keysymsPerKeycode; count;
250                                  --count)
251                             {
252                                 unsigned int keysym =
253                                     GetULONG(nextSrc, bigEndian_);
254                                 nextSrc += 4;
255                                 if (keysym == NoSymbol)
256                                     encodeBuffer.encodeValue(1, 1);
257                                 else
258                                 {
259                                     encodeBuffer.encodeValue(0, 1);
260                                     unsigned int first3Bytes = (keysym >> 8);
261 
262                                     encodeBuffer.
263                                         encodeCachedValue(first3Bytes, 24,
264                                                           serverCache_.
265                                                           getKeyboardMappingKeysymCache,
266                                                           9);
267                                     unsigned char lastByte =
268                                         (unsigned char) (keysym & 0xff);
269                                     encodeBuffer.encodeCachedValue(lastByte -
270                                                                    previous,
271                                                                    8,
272                                                                    serverCache_.
273                                                                    getKeyboardMappingLastByteCache,
274                                                                    5);
275                                     previous = lastByte;
276                                 }
277                             }
278                         }
279                         break;
280                     case X_GetModifierMapping:
281                         {
282                             encodeBuffer.encodeValue((unsigned int) buffer[1],
283                                                      8);
284                             const unsigned char *nextDest = buffer + 32;
285 
286                             if (ServerCache::getModifierMappingLastMap.
287                                 compare(size - 32, nextDest))
288                             {
289                                 encodeBuffer.encodeValue(1, 1);
290                                 break;
291                             }
292                             encodeBuffer.encodeValue(0, 1);
293                             for (unsigned int count = size - 32; count;
294                                  count--)
295                             {
296                                 unsigned char next = *nextDest++;
297 
298                                 if (next == 0)
299                                     encodeBuffer.encodeValue(1, 1);
300                                 else
301                                 {
302                                     encodeBuffer.encodeValue(0, 1);
303                                     encodeBuffer.encodeValue(next, 8);
304                                 }
305                             }
306                         }
307                         break;
308                     case X_GetProperty:
309                         {
310                             unsigned char format = (unsigned int) buffer[1];
311 
312                             encodeBuffer.encodeCachedValue(format, 8,
313                                                            serverCache_.
314                                                            getPropertyFormatCache);
315                             unsigned int numBytes =
316                                 GetULONG(buffer + 16, bigEndian_);
317                             encodeBuffer.encodeValue(numBytes, 32, 9);
318                             if (format == 16)
319                                 numBytes <<= 1;
320                             else if (format == 32)
321                                 numBytes <<= 2;
322                             encodeBuffer.
323                                 encodeCachedValue(GetULONG
324                                                   (buffer + 8, bigEndian_),
325                                                   29,
326                                                   serverCache_.
327                                                   getPropertyTypeCache, 9);
328                             encodeBuffer.
329                                 encodeValue(GetULONG(buffer + 12, bigEndian_),
330                                             32, 9);
331                             const unsigned char *nextSrc = buffer + 32;
332 
333                             if (format == 8)
334                             {
335                                 if (requestData[0] == XA_RESOURCE_MANAGER)
336                                 {
337                                     if (ServerCache::xResources.
338                                         compare(numBytes, buffer + 32))
339                                     {
340                                         encodeBuffer.encodeValue(1, 1);
341                                         break;
342                                     }
343                                     encodeBuffer.encodeValue(0, 1);
344                                 }
345                                 serverCache_.getPropertyTextCompressor.
346                                     reset();
347                                 for (unsigned int i = 0; i < numBytes; i++)
348                                 {
349                                     unsigned char nextChar;
350 
351                                     serverCache_.getPropertyTextCompressor.
352                                         encodeChar(nextChar =
353                                                    *nextSrc++, encodeBuffer);
354                                     if (nextChar == 10)
355                                     {
356                                         serverCache_.
357                                             getPropertyTextCompressor.
358                                             reset(nextChar);
359                                     }
360                                 }
361                             }
362                             else
363                             {
364                                 for (unsigned int i = 0; i < numBytes; i++)
365                                     encodeBuffer.
366                                         encodeValue((unsigned int) *nextSrc++,
367                                                     8);
368                             }
369                         }
370                         break;
371                     case X_GetSelectionOwner:
372                         {
373                             encodeBuffer.
374                                 encodeCachedValue(GetULONG
375                                                   (buffer + 8, bigEndian_),
376                                                   29,
377                                                   serverCache_.
378                                                   getSelectionOwnerCache, 9);
379                         }
380                         break;
381                     case X_GetWindowAttributes:
382                         {
383                             encodeBuffer.encodeValue((unsigned int) buffer[1],
384                                                      2);
385                             encodeBuffer.
386                                 encodeCachedValue(GetULONG
387                                                   (buffer + 8, bigEndian_),
388                                                   29,
389                                                   serverCache_.visualCache,
390                                                   9);
391                             encodeBuffer.
392                                 encodeCachedValue(GetUINT
393                                                   (buffer + 12, bigEndian_),
394                                                   16,
395                                                   serverCache_.
396                                                   getWindowAttributesClassCache,
397                                                   3);
398                             encodeBuffer.encodeCachedValue(buffer[14], 8,
399                                                            serverCache_.
400                                                            getWindowAttributesBitGravityCache);
401                             encodeBuffer.encodeCachedValue(buffer[15], 8,
402                                                            serverCache_.
403                                                            getWindowAttributesWinGravityCache);
404                             encodeBuffer.
405                                 encodeCachedValue(GetULONG
406                                                   (buffer + 16, bigEndian_),
407                                                   32,
408                                                   serverCache_.
409                                                   getWindowAttributesPlanesCache,
410                                                   9);
411                             encodeBuffer.
412                                 encodeCachedValue(GetULONG
413                                                   (buffer + 20, bigEndian_),
414                                                   32,
415                                                   serverCache_.
416                                                   getWindowAttributesPixelCache,
417                                                   9);
418                             encodeBuffer.
419                                 encodeValue((unsigned int) buffer[24], 1);
420                             encodeBuffer.
421                                 encodeValue((unsigned int) buffer[25], 1);
422                             encodeBuffer.
423                                 encodeValue((unsigned int) buffer[26], 2);
424                             encodeBuffer.
425                                 encodeValue((unsigned int) buffer[27], 1);
426                             encodeBuffer.
427                                 encodeCachedValue(GetULONG
428                                                   (buffer + 28, bigEndian_),
429                                                   29,
430                                                   serverCache_.colormapCache,
431                                                   9);
432                             encodeBuffer.
433                                 encodeCachedValue(GetULONG
434                                                   (buffer + 32, bigEndian_),
435                                                   32,
436                                                   serverCache_.
437                                                   getWindowAttributesAllEventsCache);
438                             encodeBuffer.
439                                 encodeCachedValue(GetULONG
440                                                   (buffer + 36, bigEndian_),
441                                                   32,
442                                                   serverCache_.
443                                                   getWindowAttributesYourEventsCache);
444                             encodeBuffer.
445                                 encodeCachedValue(GetUINT
446                                                   (buffer + 40, bigEndian_),
447                                                   16,
448                                                   serverCache_.
449                                                   getWindowAttributesDontPropagateCache);
450                         }
451                         break;
452                     case X_GrabKeyboard:
453                     case X_GrabPointer:
454                         {
455                             encodeBuffer.encodeValue((unsigned int) buffer[1],
456                                                      3);
457                         }
458                         break;
459                     case X_InternAtom:
460                         {
461                             encodeBuffer.
462                                 encodeValue(GetULONG(buffer + 8, bigEndian_),
463                                             29, 9);
464                         }
465                         break;
466                     case X_ListExtensions:
467                         {
468                             encodeBuffer.
469                                 encodeValue(GetULONG(buffer + 4, bigEndian_),
470                                             32, 8);
471                             unsigned int numExtensions =
472                                 (unsigned int) buffer[1];
473                             encodeBuffer.encodeValue(numExtensions, 8);
474                             const unsigned char *nextSrc = buffer + 32;
475 
476                             for (; numExtensions; numExtensions--)
477                             {
478                                 unsigned int length =
479                                     (unsigned int) (*nextSrc++);
480                                 encodeBuffer.encodeValue(length, 8);
481                                 if (!strncmp((char *) nextSrc, "MIT-SHM", 7))
482                                     memcpy((unsigned char *) nextSrc,
483                                            "NOT-SHM", 7);
484                                 for (; length; length--)
485                                     encodeBuffer.
486                                         encodeValue((unsigned
487                                                      int) (*nextSrc++), 8);
488                             }
489                         }
490                         break;
491                     case X_ListFonts:
492                         {
493                             encodeBuffer.
494                                 encodeValue(GetULONG(buffer + 4, bigEndian_),
495                                             32, 8);
496                             unsigned int numFonts =
497                                 GetUINT(buffer + 8, bigEndian_);
498                             encodeBuffer.encodeValue(numFonts, 16, 6);
499                             const unsigned char *nextSrc = buffer + 32;
500 
501                             for (; numFonts; numFonts--)
502                             {
503                                 unsigned int length =
504                                     (unsigned int) (*nextSrc++);
505                                 encodeBuffer.encodeValue(length, 8);
506                                 serverCache_.getPropertyTextCompressor.
507                                     reset();
508                                 for (; length; length--)
509                                     serverCache_.getPropertyTextCompressor.
510                                         encodeChar(*nextSrc++, encodeBuffer);
511                             }
512                         }
513                         break;
514                     case X_LookupColor:
515                     case X_AllocNamedColor:
516                         {
517                             const unsigned char *nextSrc = buffer + 8;
518 
519                             if (nextOpcode == X_AllocNamedColor)
520                             {
521                                 encodeBuffer.
522                                     encodeValue(GetULONG(nextSrc, bigEndian_),
523                                                 32, 9);
524                                 nextSrc += 4;
525                             }
526                             unsigned int count = 3;
527 
528                             do
529                             {
530                                 unsigned int exactColor =
531                                     GetUINT(nextSrc, bigEndian_);
532                                 encodeBuffer.encodeValue(exactColor, 16, 9);
533                                 unsigned int visualColor =
534                                     GetUINT(nextSrc + 6,
535                                             bigEndian_) - exactColor;
536                                 encodeBuffer.encodeValue(visualColor, 16, 5);
537                                 nextSrc += 2;
538                             }
539                             while (--count);
540                         }
541                         break;
542                     case X_QueryBestSize:
543                         {
544                             encodeBuffer.
545                                 encodeValue(GetUINT(buffer + 8, bigEndian_),
546                                             16, 8);
547                             encodeBuffer.
548                                 encodeValue(GetUINT(buffer + 10, bigEndian_),
549                                             16, 8);
550                         }
551                         break;
552                     case X_QueryColors:
553                         {
554                             unsigned int numColors = ((size - 32) >> 3);
555                             const unsigned char *nextSrc = buffer + 40;
556                             unsigned char *nextDest =
557                                 (unsigned char *) buffer + 38;
558                             for (unsigned int c = 1; c < numColors; c++)
559                             {
560                                 for (unsigned int i = 0; i < 6; i++)
561                                     *nextDest++ = *nextSrc++;
562                                 nextSrc += 2;
563                             }
564                             unsigned int colorsLength = numColors * 6;
565 
566                             if (serverCache_.queryColorsLastReply.
567                                 compare(colorsLength, buffer + 32))
568                                 encodeBuffer.encodeValue(1, 1);
569                             else
570                             {
571                                 const unsigned char *nextSrc = buffer + 32;
572 
573                                 encodeBuffer.encodeValue(0, 1);
574                                 encodeBuffer.encodeValue(numColors, 16, 5);
575                                 for (numColors *= 3; numColors; numColors--)
576                                 {
577                                     encodeBuffer.
578                                         encodeValue(GetUINT
579                                                     (nextSrc, bigEndian_),
580                                                     16);
581                                     nextSrc += 2;
582                                 }
583                             }
584                         }
585                         break;
586                     case X_QueryExtension:
587                         {
588                             // requestData[0] will be nonzero if the request is for
589                             // an extension that dxpc should hide, like MIT-SHM
590                             if (requestData[0])
591                             {
592                                 encodeBuffer.encodeValue(0, 1);
593                                 encodeBuffer.encodeValue(0, 8);
594                             }
595                             else
596                             {
597                                 encodeBuffer.
598                                     encodeValue((unsigned int) buffer[8], 1);
599                                 encodeBuffer.
600                                     encodeValue((unsigned int) buffer[9], 8);
601                             }
602                             encodeBuffer.
603                                 encodeValue((unsigned int) buffer[10], 8);
604                             encodeBuffer.
605                                 encodeValue((unsigned int) buffer[11], 8);
606                         }
607                         break;
608                     case X_QueryFont:
609                         {
610                             unsigned int numProperties =
611                                 GetUINT(buffer + 46, bigEndian_);
612                             unsigned int numCharInfos =
613                                 GetULONG(buffer + 56, bigEndian_);
614                             encodeBuffer.encodeValue(numProperties, 16, 8);
615                             encodeBuffer.encodeValue(numCharInfos, 32, 10);
616                             encodeCharInfo_(buffer + 8, encodeBuffer);
617                             encodeCharInfo_(buffer + 24, encodeBuffer);
618                             encodeBuffer.
619                                 encodeValue(GetUINT(buffer + 40, bigEndian_),
620                                             16, 9);
621                             encodeBuffer.
622                                 encodeValue(GetUINT(buffer + 42, bigEndian_),
623                                             16, 9);
624                             encodeBuffer.
625                                 encodeValue(GetUINT(buffer + 44, bigEndian_),
626                                             16, 9);
627                             encodeBuffer.
628                                 encodeValue((unsigned int) buffer[48], 1);
629                             encodeBuffer.
630                                 encodeValue((unsigned int) buffer[49], 8);
631                             encodeBuffer.
632                                 encodeValue((unsigned int) buffer[50], 8);
633                             encodeBuffer.
634                                 encodeValue((unsigned int) buffer[51], 1);
635                             encodeBuffer.
636                                 encodeValue(GetUINT(buffer + 52, bigEndian_),
637                                             16, 9);
638                             encodeBuffer.
639                                 encodeValue(GetUINT(buffer + 54, bigEndian_),
640                                             16, 9);
641                             const unsigned char *nextSrc = buffer + 60;
642                             unsigned int index;
643 
644                             if (ServerCache::queryFontFontCache.
645                                 lookup(numProperties * 8 + numCharInfos * 12,
646                                        nextSrc, index))
647                             {
648                                 encodeBuffer.encodeValue(1, 1);
649                                 encodeBuffer.encodeValue(index, 4);
650                                 break;
651                             }
652                             encodeBuffer.encodeValue(0, 1);
653                             for (; numProperties; numProperties--)
654                             {
655                                 encodeBuffer.
656                                     encodeValue(GetULONG(nextSrc, bigEndian_),
657                                                 32, 9);
658                                 encodeBuffer.
659                                     encodeValue(GetULONG
660                                                 (nextSrc + 4, bigEndian_), 32,
661                                                 9);
662                                 nextSrc += 8;
663                             }
664                             for (; numCharInfos; numCharInfos--)
665                             {
666                                 encodeCharInfo_(nextSrc, encodeBuffer);
667                                 nextSrc += 12;
668                             }
669                         }
670                         break;
671                     case X_QueryPointer:
672                         {
673                             encodeBuffer.encodeValue((unsigned int) buffer[1],
674                                                      1);
675                             encodeBuffer.
676                                 encodeCachedValue(GetULONG
677                                                   (buffer + 8, bigEndian_),
678                                                   29,
679                                                   serverCache_.
680                                                   queryPointerRootCache, 9);
681                             encodeBuffer.
682                                 encodeCachedValue(GetULONG
683                                                   (buffer + 12, bigEndian_),
684                                                   29,
685                                                   serverCache_.
686                                                   queryPointerChildCache, 9);
687                             unsigned int rootX =
688                                 GetUINT(buffer + 16, bigEndian_);
689                             unsigned int rootY =
690                                 GetUINT(buffer + 18, bigEndian_);
691                             unsigned int eventX =
692                                 GetUINT(buffer + 20, bigEndian_);
693                             unsigned int eventY =
694                                 GetUINT(buffer + 22, bigEndian_);
695                             eventX -= rootX;
696                             eventY -= rootY;
697                             encodeBuffer.encodeCachedValue(rootX -
698                                                            serverCache_.
699                                                            motionNotifyLastRootX,
700                                                            16,
701                                                            serverCache_.
702                                                            motionNotifyRootXCache,
703                                                            8);
704                             serverCache_.motionNotifyLastRootX = rootX;
705                             encodeBuffer.encodeCachedValue(rootY -
706                                                            serverCache_.
707                                                            motionNotifyLastRootY,
708                                                            16,
709                                                            serverCache_.
710                                                            motionNotifyRootYCache,
711                                                            8);
712                             serverCache_.motionNotifyLastRootY = rootY;
713                             encodeBuffer.encodeCachedValue(eventX, 16,
714                                                            serverCache_.
715                                                            motionNotifyEventXCache,
716                                                            8);
717                             encodeBuffer.encodeCachedValue(eventY, 16,
718                                                            serverCache_.
719                                                            motionNotifyEventYCache,
720                                                            8);
721                             encodeBuffer.
722                                 encodeCachedValue(GetUINT
723                                                   (buffer + 24, bigEndian_),
724                                                   16,
725                                                   serverCache_.
726                                                   motionNotifyStateCache);
727                         }
728                         break;
729                     case X_QueryTree:
730                         {
731                             encodeBuffer.encodeValue(buffer[1], 8);
732                             encodeBuffer.
733                                 encodeValue(GetULONG(buffer + 4, bigEndian_),
734                                             32);
735                             for (unsigned int i = 8; i < size; i++)
736                                 encodeBuffer.
737                                     encodeValue((unsigned int) buffer[i], 8);
738                         }
739                         break;
740                     case X_TranslateCoords:
741                         {
742                             encodeBuffer.encodeValue((unsigned int) buffer[1],
743                                                      1);
744                             encodeBuffer.
745                                 encodeCachedValue(GetULONG
746                                                   (buffer + 8, bigEndian_),
747                                                   29,
748                                                   serverCache_.
749                                                   translateCoordsChildCache,
750                                                   9);
751                             encodeBuffer.
752                                 encodeCachedValue(GetUINT
753                                                   (buffer + 12, bigEndian_),
754                                                   16,
755                                                   serverCache_.
756                                                   translateCoordsXCache, 8);
757                             encodeBuffer.
758                                 encodeCachedValue(GetUINT
759                                                   (buffer + 14, bigEndian_),
760                                                   16,
761                                                   serverCache_.
762                                                   translateCoordsYCache, 8);
763                         }
764                         break;
765                     default:
766                         {
767                             CERR <<
768                                 "assertion failed in ServerXReader::processMessage():\n"
769                                 <<
770                                 " no matching request for reply with sequence number "
771                                 << sequenceNum << ENDL;
772                         }
773                     }
774                 }
775                 else
776                 {
777                     encodeBuffer.encodeValue(buffer[1], 8);
778                     encodeBuffer.encodeValue(GetULONG(buffer + 4, bigEndian_),
779                                              32);
780                     for (unsigned int i = 8; i < size; i++)
781                         encodeBuffer.encodeValue((unsigned int) buffer[i], 8);
782                 }
783                 replyStats_.add(requestOpcode, size << 3,
784                                 encodeBuffer.getCumulativeBitsWritten());
785             }
786             else
787             {
788                 // event or error
789                 unsigned int sequenceNum = GetUINT(buffer + 2, bigEndian_);
790                 unsigned int sequenceNumDiff =
791                     sequenceNum - serverCache_.lastSequenceNum;
792                 serverCache_.lastSequenceNum = sequenceNum;
793                 unsigned int opcode = (unsigned int) *buffer;
794 
795                 encodeBuffer.encodeCachedValue(opcode, 8,
796                                                serverCache_.
797                                                opcodeCache[serverCache_.
798                                                            lastOpcode]);
799                 serverCache_.lastOpcode = opcode;
800                 encodeBuffer.encodeCachedValue(sequenceNumDiff, 16,
801                                                serverCache_.
802                                                eventSequenceNumCache, 7);
803 
804                 // check if this is an error that matches a sequence number for
805                 // which we were expecting a reply
806                 unsigned short int dummySequenceNum;
807                 unsigned char dummyOpcode;
808 
809                 if (sequenceNumQueue_.peek(dummySequenceNum, dummyOpcode) &&
810                     ((unsigned int) dummySequenceNum == sequenceNum))
811                     sequenceNumQueue_.pop(dummySequenceNum, dummyOpcode);
812 
813                 switch (*buffer)
814                 {
815                 case 0:
816                     {
817                         unsigned char code = buffer[1];
818 
819                         encodeBuffer.encodeCachedValue(code, 8,
820                                                        serverCache_.
821                                                        errorCodeCache);
822                         if ((code != 11) && (code != 8) && (code != 15)
823                             && (code != 1))
824                             encodeBuffer.
825                                 encodeValue(GetULONG(buffer + 4, bigEndian_),
826                                             32, 16);
827                         if (code >= 18)
828                             encodeBuffer.
829                                 encodeCachedValue(GetUINT
830                                                   (buffer + 8, bigEndian_),
831                                                   16,
832                                                   serverCache_.
833                                                   errorMinorCache);
834                         encodeBuffer.encodeCachedValue(buffer[10], 8,
835                                                        serverCache_.
836                                                        errorMajorCache);
837                         if (code >= 18)
838                         {
839                             const unsigned char *nextSrc = buffer + 11;
840 
841                             for (unsigned int i = 11; i < 32; i++)
842                                 encodeBuffer.encodeValue(*nextSrc++, 8);
843                         }
844                     }
845                     break;
846                 case ButtonPress:
847                 case ButtonRelease:
848                 case KeyPress:
849                 case KeyRelease:
850                 case MotionNotify:
851                 case EnterNotify:
852                 case LeaveNotify:
853                     {
854                         unsigned char detail = buffer[1];
855 
856                         if (*buffer == MotionNotify)
857                             encodeBuffer.encodeValue((unsigned int) detail,
858                                                      1);
859                         else if ((*buffer == EnterNotify)
860                                  || (*buffer == LeaveNotify))
861                             encodeBuffer.encodeValue((unsigned int) detail,
862                                                      3);
863                         else if (*buffer == KeyRelease)
864                         {
865                             if (detail == serverCache_.keyPressLastKey)
866                                 encodeBuffer.encodeValue(1, 1);
867                             else
868                             {
869                                 encodeBuffer.encodeValue(0, 1);
870                                 encodeBuffer.
871                                     encodeValue((unsigned int) detail, 8);
872                             }
873                         }
874                         else if ((*buffer == ButtonPress)
875                                  || (*buffer == ButtonRelease))
876                             encodeBuffer.encodeCachedValue(detail, 8,
877                                                            serverCache_.
878                                                            buttonCache);
879                         else
880                             encodeBuffer.encodeValue((unsigned int) detail,
881                                                      8);
882                         unsigned int timestamp =
883                             GetULONG(buffer + 4, bigEndian_);
884                         unsigned int timestampDiff =
885                             timestamp - serverCache_.lastTimestamp;
886                         serverCache_.lastTimestamp = timestamp;
887                         encodeBuffer.encodeCachedValue(timestampDiff, 32,
888                                                        serverCache_.
889                                                        motionNotifyTimestampCache,
890                                                        9);
891                         int skipRest = 0;
892 
893                         if (*buffer == KeyRelease)
894                         {
895                             skipRest = 1;
896                             for (unsigned int i = 8; i < 31; i++)
897                             {
898                                 if (buffer[i] !=
899                                     serverCache_.keyPressCache[i - 8])
900                                 {
901                                     skipRest = 0;
902                                     break;
903                                 }
904                             }
905                             encodeBuffer.encodeValue(skipRest, 1);
906                         }
907                         if (!skipRest)
908                         {
909                             const unsigned char *nextSrc = buffer + 8;
910 
911                             for (unsigned int i = 0; i < 3; i++)
912                             {
913                                 encodeBuffer.
914                                     encodeCachedValue(GetULONG
915                                                       (nextSrc, bigEndian_),
916                                                       29,
917                                                       *serverCache_.
918                                                       motionNotifyWindowCache
919                                                       [i], 6);
920                                 nextSrc += 4;
921                             }
922                             unsigned int rootX =
923                                 GetUINT(buffer + 20, bigEndian_);
924                             unsigned int rootY =
925                                 GetUINT(buffer + 22, bigEndian_);
926                             unsigned int eventX =
927                                 GetUINT(buffer + 24, bigEndian_);
928                             unsigned int eventY =
929                                 GetUINT(buffer + 26, bigEndian_);
930                             eventX -= rootX;
931                             eventY -= rootY;
932                             encodeBuffer.encodeCachedValue(rootX -
933                                                            serverCache_.
934                                                            motionNotifyLastRootX,
935                                                            16,
936                                                            serverCache_.
937                                                            motionNotifyRootXCache,
938                                                            6);
939                             serverCache_.motionNotifyLastRootX = rootX;
940                             encodeBuffer.encodeCachedValue(rootY -
941                                                            serverCache_.
942                                                            motionNotifyLastRootY,
943                                                            16,
944                                                            serverCache_.
945                                                            motionNotifyRootYCache,
946                                                            6);
947                             serverCache_.motionNotifyLastRootY = rootY;
948                             encodeBuffer.encodeCachedValue(eventX, 16,
949                                                            serverCache_.
950                                                            motionNotifyEventXCache,
951                                                            6);
952                             encodeBuffer.encodeCachedValue(eventY, 16,
953                                                            serverCache_.
954                                                            motionNotifyEventYCache,
955                                                            6);
956                             encodeBuffer.
957                                 encodeCachedValue(GetUINT
958                                                   (buffer + 28, bigEndian_),
959                                                   16,
960                                                   serverCache_.
961                                                   motionNotifyStateCache);
962                             if ((*buffer == EnterNotify)
963                                 || (*buffer == LeaveNotify))
964                                 encodeBuffer.
965                                     encodeValue((unsigned int) buffer[30], 2);
966                             else
967                                 encodeBuffer.
968                                     encodeValue((unsigned int) buffer[30], 1);
969                             if ((*buffer == EnterNotify)
970                                 || (*buffer == LeaveNotify))
971                                 encodeBuffer.
972                                     encodeValue((unsigned int) buffer[31], 2);
973                             else if (*buffer == KeyPress)
974                             {
975                                 serverCache_.keyPressLastKey = detail;
976                                 for (unsigned int i = 8; i < 31; i++)
977                                 {
978                                     serverCache_.keyPressCache[i - 8] =
979                                         buffer[i];
980                                 }
981                             }
982                         }
983                     }
984                     break;
985                 case ColormapNotify:
986                     {
987                         encodeBuffer.
988                             encodeCachedValue(GetULONG
989                                               (buffer + 4, bigEndian_), 29,
990                                               serverCache_.
991                                               colormapNotifyWindowCache, 8);
992                         encodeBuffer.
993                             encodeCachedValue(GetULONG
994                                               (buffer + 8, bigEndian_), 29,
995                                               serverCache_.
996                                               colormapNotifyColormapCache, 8);
997                         encodeBuffer.encodeValue((unsigned int) buffer[12],
998                                                  1);
999                         encodeBuffer.encodeValue((unsigned int) buffer[13],
1000                                                  1);
1001                     }
1002                     break;
1003                 case ConfigureNotify:
1004                     {
1005                         const unsigned char *nextSrc = buffer + 4;
1006 
1007                         for (unsigned int i = 0; i < 3; i++)
1008                         {
1009                             encodeBuffer.
1010                                 encodeCachedValue(GetULONG
1011                                                   (nextSrc, bigEndian_), 29,
1012                                                   *serverCache_.
1013                                                   configureNotifyWindowCache
1014                                                   [i], 9);
1015                             nextSrc += 4;
1016                         }
1017                         for (unsigned int j = 0; j < 5; j++)
1018                         {
1019                             encodeBuffer.
1020                                 encodeCachedValue(GetUINT
1021                                                   (nextSrc, bigEndian_), 16,
1022                                                   *serverCache_.
1023                                                   configureNotifyGeomCache[j],
1024                                                   8);
1025                             nextSrc += 2;
1026                         }
1027                         encodeBuffer.encodeValue(*nextSrc, 1);
1028                     }
1029                     break;
1030                 case CreateNotify:
1031                     {
1032                         encodeBuffer.
1033                             encodeCachedValue(GetULONG
1034                                               (buffer + 4, bigEndian_), 29,
1035                                               serverCache_.
1036                                               createNotifyWindowCache, 9);
1037                         unsigned int window =
1038                             GetULONG(buffer + 8, bigEndian_);
1039                         encodeBuffer.encodeValue(window -
1040                                                  serverCache_.
1041                                                  createNotifyLastWindow, 29,
1042                                                  5);
1043                         serverCache_.createNotifyLastWindow = window;
1044                         const unsigned char *nextSrc = buffer + 12;
1045 
1046                         for (unsigned int i = 0; i < 5; i++)
1047                         {
1048                             encodeBuffer.
1049                                 encodeValue(GetUINT(nextSrc, bigEndian_), 16,
1050                                             9);
1051                             nextSrc += 2;
1052                         }
1053                         encodeBuffer.encodeValue((unsigned int) *nextSrc, 1);
1054                     }
1055                     break;
1056                 case Expose:
1057                     {
1058                         encodeBuffer.
1059                             encodeCachedValue(GetULONG
1060                                               (buffer + 4, bigEndian_), 29,
1061                                               serverCache_.exposeWindowCache,
1062                                               9);
1063                         const unsigned char *nextSrc = buffer + 8;
1064 
1065                         for (unsigned int i = 0; i < 5; i++)
1066                         {
1067                             encodeBuffer.
1068                                 encodeCachedValue(GetUINT
1069                                                   (nextSrc, bigEndian_), 16,
1070                                                   *serverCache_.
1071                                                   exposeGeomCache[i], 6);
1072                             nextSrc += 2;
1073                         }
1074                     }
1075                     break;
1076                 case FocusIn:
1077                 case FocusOut:
1078                     {
1079                         encodeBuffer.encodeValue((unsigned int) buffer[1], 3);
1080                         encodeBuffer.
1081                             encodeCachedValue(GetULONG
1082                                               (buffer + 4, bigEndian_), 29,
1083                                               serverCache_.focusInWindowCache,
1084                                               9);
1085                         encodeBuffer.encodeValue((unsigned int) buffer[8], 2);
1086                     }
1087                     break;
1088                 case KeymapNotify:
1089                     {
1090                         if (ServerCache::lastKeymap.compare(31, buffer + 1))
1091                             encodeBuffer.encodeValue(1, 1);
1092                         else
1093                         {
1094                             encodeBuffer.encodeValue(0, 1);
1095                             const unsigned char *nextSrc = buffer + 1;
1096 
1097                             for (unsigned int i = 1; i < 32; i++)
1098                                 encodeBuffer.
1099                                     encodeValue((unsigned int) *nextSrc++, 8);
1100                         }
1101                     }
1102                     break;
1103                 case MapNotify:
1104                 case UnmapNotify:
1105                 case DestroyNotify:
1106                     {
1107                         encodeBuffer.
1108                             encodeCachedValue(GetULONG
1109                                               (buffer + 4, bigEndian_), 29,
1110                                               serverCache_.
1111                                               mapNotifyEventCache, 9);
1112                         encodeBuffer.
1113                             encodeCachedValue(GetULONG
1114                                               (buffer + 8, bigEndian_), 29,
1115                                               serverCache_.
1116                                               mapNotifyWindowCache, 9);
1117                         if ((*buffer == MapNotify)
1118                             || (*buffer == UnmapNotify))
1119                             encodeBuffer.
1120                                 encodeValue((unsigned int) buffer[12], 1);
1121                     }
1122                     break;
1123                 case NoExpose:
1124                     {
1125                         encodeBuffer.
1126                             encodeCachedValue(GetULONG
1127                                               (buffer + 4, bigEndian_), 29,
1128                                               serverCache_.
1129                                               noExposeDrawableCache, 9);
1130                         encodeBuffer.
1131                             encodeCachedValue(GetUINT(buffer + 8, bigEndian_),
1132                                               16,
1133                                               serverCache_.
1134                                               noExposeMinorCache);
1135                         encodeBuffer.encodeCachedValue(buffer[10], 8,
1136                                                        serverCache_.
1137                                                        noExposeMajorCache);
1138                     }
1139                     break;
1140                 case PropertyNotify:
1141                     {
1142                         encodeBuffer.
1143                             encodeCachedValue(GetULONG
1144                                               (buffer + 4, bigEndian_), 29,
1145                                               serverCache_.
1146                                               propertyNotifyWindowCache, 9);
1147                         encodeBuffer.
1148                             encodeCachedValue(GetULONG
1149                                               (buffer + 8, bigEndian_), 29,
1150                                               serverCache_.
1151                                               propertyNotifyAtomCache, 9);
1152                         unsigned int timestamp =
1153                             GetULONG(buffer + 12, bigEndian_);
1154                         unsigned int timestampDiff =
1155                             timestamp - serverCache_.lastTimestamp;
1156                         serverCache_.lastTimestamp = timestamp;
1157                         encodeBuffer.encodeValue(timestampDiff, 32, 9);
1158                         encodeBuffer.encodeValue((unsigned int) buffer[16],
1159                                                  1);
1160                     }
1161                     break;
1162                 case ReparentNotify:
1163                     {
1164                         const unsigned char *nextSrc = buffer + 4;
1165 
1166                         for (unsigned int i = 0; i < 3; i++)
1167                         {
1168                             encodeBuffer.
1169                                 encodeCachedValue(GetULONG
1170                                                   (nextSrc, bigEndian_), 29,
1171                                                   serverCache_.
1172                                                   reparentNotifyWindowCache,
1173                                                   9);
1174                             nextSrc += 4;
1175                         }
1176                         encodeBuffer.encodeValue(GetUINT(nextSrc, bigEndian_),
1177                                                  16, 6);
1178                         encodeBuffer.
1179                             encodeValue(GetUINT(nextSrc + 2, bigEndian_), 16,
1180                                         6);
1181                         encodeBuffer.encodeValue((unsigned int) buffer[20],
1182                                                  1);
1183                     }
1184                     break;
1185                 case SelectionClear:
1186                     {
1187                         unsigned int timestamp =
1188                             GetULONG(buffer + 4, bigEndian_);
1189                         unsigned int timestampDiff =
1190                             timestamp - serverCache_.lastTimestamp;
1191                         serverCache_.lastTimestamp = timestamp;
1192                         encodeBuffer.encodeValue(timestampDiff, 32, 9);
1193                         encodeBuffer.
1194                             encodeCachedValue(GetULONG
1195                                               (buffer + 8, bigEndian_), 29,
1196                                               serverCache_.
1197                                               selectionClearWindowCache, 9);
1198                         encodeBuffer.
1199                             encodeCachedValue(GetULONG
1200                                               (buffer + 12, bigEndian_), 29,
1201                                               serverCache_.
1202                                               selectionClearAtomCache, 9);
1203                     }
1204                     break;
1205                 case SelectionRequest:
1206                     {
1207                         unsigned int timestamp =
1208                             GetULONG(buffer + 4, bigEndian_);
1209                         unsigned int timestampDiff =
1210                             timestamp - serverCache_.lastTimestamp;
1211                         serverCache_.lastTimestamp = timestamp;
1212                         encodeBuffer.encodeValue(timestampDiff, 32, 9);
1213                         encodeBuffer.
1214                             encodeCachedValue(GetULONG
1215                                               (buffer + 8, bigEndian_), 29,
1216                                               serverCache_.
1217                                               selectionClearWindowCache, 9);
1218                         encodeBuffer.
1219                             encodeCachedValue(GetULONG
1220                                               (buffer + 12, bigEndian_), 29,
1221                                               serverCache_.
1222                                               selectionClearWindowCache, 9);
1223                         encodeBuffer.
1224                             encodeCachedValue(GetULONG
1225                                               (buffer + 16, bigEndian_), 29,
1226                                               serverCache_.
1227                                               selectionClearAtomCache, 9);
1228                         encodeBuffer.
1229                             encodeCachedValue(GetULONG
1230                                               (buffer + 20, bigEndian_), 29,
1231                                               serverCache_.
1232                                               selectionClearAtomCache, 9);
1233                         encodeBuffer.
1234                             encodeCachedValue(GetULONG
1235                                               (buffer + 24, bigEndian_), 29,
1236                                               serverCache_.
1237                                               selectionClearAtomCache, 9);
1238                     }
1239                     break;
1240                 case VisibilityNotify:
1241                     {
1242                         encodeBuffer.
1243                             encodeCachedValue(GetULONG
1244                                               (buffer + 4, bigEndian_), 29,
1245                                               serverCache_.
1246                                               visibilityNotifyWindowCache, 9);
1247                         encodeBuffer.encodeValue((unsigned int) buffer[8], 2);
1248                     }
1249                     break;
1250                 default:
1251                     {
1252                         encodeBuffer.encodeValue(buffer[1], 8);
1253                         for (unsigned int i = 4; i < size; i++)
1254                             encodeBuffer.encodeValue((unsigned int) buffer[i],
1255                                                      8);
1256                     }
1257                 }
1258                 stats_.add(*buffer, size << 3,
1259                            encodeBuffer.getCumulativeBitsWritten());
1260             }
1261         }
1262     }
1263     return 1;
1264 }
1265 
1266 
doWrite(const unsigned char * message,unsigned int length)1267 int ServerChannel::doWrite(const unsigned char *message, unsigned int length)
1268 {
1269     writeBuffer_.reset();
1270 
1271     // uncompress messages
1272     DecodeBuffer decodeBuffer(message, length);
1273 
1274     if (firstRequest_)
1275     {
1276         unsigned char *outputMessage = writeBuffer_.addMessage(length);
1277         unsigned char *nextDest = outputMessage;
1278 
1279         for (unsigned int i = 0; i < length; i++)
1280         {
1281             unsigned int nextByte;
1282 
1283             decodeBuffer.decodeValue(nextByte, 8);
1284             *nextDest++ = (unsigned char) nextByte;
1285         }
1286         if (*outputMessage == 0x42)
1287             setBigEndian(1);
1288         else
1289             setBigEndian(0);
1290         firstRequest_ = 0;
1291     }
1292     else
1293     {
1294         unsigned char opcode;
1295 
1296         while (decodeBuffer.decodeCachedValue(opcode, 8,
1297                                               clientCache_.
1298                                               opcodeCache[clientCache_.
1299                                                           lastOpcode], 8, 1))
1300         {
1301             clientCache_.lastOpcode = opcode;
1302             clientCache_.lastRequestSequenceNum++;
1303             unsigned char *outputMessage;
1304             unsigned int outputLength;
1305             unsigned int value; // general-purpose temp variable for decoding ints
1306 
1307             unsigned char cValue;       // general-purpose temp variable for decoding chars
1308 
1309             switch (opcode)
1310             {
1311             case X_AllocColor:
1312                 {
1313                     outputLength = 16;
1314                     outputMessage = writeBuffer_.addMessage(outputLength);
1315                     decodeBuffer.decodeCachedValue(value, 29,
1316                                                    clientCache_.colormapCache,
1317                                                    9);
1318                     PutULONG(value, outputMessage + 4, bigEndian_);
1319                     unsigned char *nextDest = outputMessage + 8;
1320                     unsigned int colorData[3];
1321 
1322                     for (unsigned int i = 0; i < 3; i++)
1323                     {
1324                         decodeBuffer.decodeCachedValue(value, 16,
1325                                                        *(clientCache_.
1326                                                          allocColorRGBCache
1327                                                          [i]), 4);
1328                         PutUINT(value, nextDest, bigEndian_);
1329                         colorData[i] = value;
1330                         nextDest += 2;
1331                     }
1332                     sequenceNumQueue_.push(clientCache_.
1333                                            lastRequestSequenceNum, opcode,
1334                                            colorData[0], colorData[1],
1335                                            colorData[2]);
1336                 }
1337                 break;
1338             case X_ChangeProperty:
1339                 {
1340                     unsigned char format;
1341 
1342                     decodeBuffer.decodeCachedValue(format, 8,
1343                                                    clientCache_.
1344                                                    changePropertyFormatCache);
1345                     unsigned int dataLength;
1346 
1347                     decodeBuffer.decodeValue(dataLength, 32, 6);
1348                     outputLength = 24 + RoundUp4(dataLength * (format >> 3));
1349                     outputMessage = writeBuffer_.addMessage(outputLength);
1350                     decodeBuffer.decodeValue(value, 2);
1351                     outputMessage[1] = (unsigned char) value;
1352                     decodeBuffer.decodeCachedValue(value, 29,
1353                                                    clientCache_.windowCache,
1354                                                    9);
1355                     PutULONG(value, outputMessage + 4, bigEndian_);
1356                     decodeBuffer.decodeCachedValue(value, 29,
1357                                                    clientCache_.
1358                                                    changePropertyPropertyCache,
1359                                                    9);
1360                     PutULONG(value, outputMessage + 8, bigEndian_);
1361                     decodeBuffer.decodeCachedValue(value, 29,
1362                                                    clientCache_.
1363                                                    changePropertyTypeCache,
1364                                                    9);
1365                     PutULONG(value, outputMessage + 12, bigEndian_);
1366                     outputMessage[16] = format;
1367                     PutULONG(dataLength, outputMessage + 20, bigEndian_);
1368                     unsigned char *nextDest = outputMessage + 24;
1369 
1370                     if (format == 8)
1371                     {
1372                         clientCache_.changePropertyTextCompressor.reset();
1373                         for (unsigned int i = 0; i < dataLength; i++)
1374                             *nextDest++ =
1375                                 clientCache_.changePropertyTextCompressor.
1376                                 decodeChar(decodeBuffer);
1377                     }
1378                     else if (format == 32)
1379                     {
1380                         for (unsigned int i = 0; i < dataLength; i++)
1381                         {
1382                             decodeBuffer.decodeCachedValue(value, 32,
1383                                                            clientCache_.
1384                                                            changePropertyData32Cache);
1385                             PutULONG(value, nextDest, bigEndian_);
1386                             nextDest += 4;
1387                         }
1388                     }
1389                     else
1390                     {
1391                         for (unsigned int i = 0; i < dataLength; i++)
1392                         {
1393                             decodeBuffer.decodeValue(value, 16);
1394                             PutUINT(value, nextDest, bigEndian_);
1395                             nextDest += 2;
1396                         }
1397                     }
1398                 }
1399                 break;
1400             case X_ChangeWindowAttributes:
1401                 {
1402                     unsigned int numAttrs;
1403 
1404                     decodeBuffer.decodeValue(numAttrs, 4);
1405                     outputLength = 12 + (numAttrs << 2);
1406                     outputMessage = writeBuffer_.addMessage(outputLength);
1407                     decodeBuffer.decodeCachedValue(value, 29,
1408                                                    clientCache_.windowCache,
1409                                                    9);
1410                     PutULONG(value, outputMessage + 4, bigEndian_);
1411                     unsigned int bitmask;
1412 
1413                     decodeBuffer.decodeCachedValue(bitmask, 15,
1414                                                    clientCache_.
1415                                                    createWindowBitmaskCache);
1416                     PutULONG(bitmask, outputMessage + 8, bigEndian_);
1417                     unsigned char *nextDest = outputMessage + 12;
1418                     unsigned int mask = 0x1;
1419 
1420                     for (unsigned int i = 0; i < 15; i++)
1421                     {
1422                         if (bitmask & mask)
1423                         {
1424                             decodeBuffer.decodeCachedValue(value, 32,
1425                                                            *clientCache_.
1426                                                            createWindowAttrCache
1427                                                            [i]);
1428                             PutULONG(value, nextDest, bigEndian_);
1429                             nextDest += 4;
1430                         }
1431                         mask <<= 1;
1432                     }
1433                 }
1434                 break;
1435             case X_ClearArea:
1436                 {
1437                     outputLength = 16;
1438                     outputMessage = writeBuffer_.addMessage(outputLength);
1439                     decodeBuffer.decodeValue(value, 1);
1440                     outputMessage[1] = (unsigned char) value;
1441                     decodeBuffer.decodeCachedValue(value, 29,
1442                                                    clientCache_.windowCache,
1443                                                    9);
1444                     PutULONG(value, outputMessage + 4, bigEndian_);
1445                     unsigned char *nextDest = outputMessage + 8;
1446 
1447                     for (unsigned int i = 0; i < 4; i++)
1448                     {
1449                         decodeBuffer.decodeCachedValue(value, 16,
1450                                                        *clientCache_.
1451                                                        clearAreaGeomCache[i],
1452                                                        8);
1453                         PutUINT(value, nextDest, bigEndian_);
1454                         nextDest += 2;
1455                     }
1456                 }
1457                 break;
1458             case X_CloseFont:
1459                 {
1460                     outputLength = 8;
1461                     outputMessage = writeBuffer_.addMessage(outputLength);
1462                     decodeBuffer.decodeValue(value, 29, 5);
1463                     clientCache_.lastFont += value;
1464                     clientCache_.lastFont &= 0x1fffffff;
1465                     PutULONG(clientCache_.lastFont, outputMessage + 4,
1466                              bigEndian_);
1467                 }
1468                 break;
1469             case X_ConfigureWindow:
1470                 {
1471                     outputLength = 12;
1472                     outputMessage = writeBuffer_.addMessage(outputLength);
1473                     writeBuffer_.registerPointer(&outputMessage);
1474                     decodeBuffer.decodeCachedValue(value, 29,
1475                                                    clientCache_.windowCache,
1476                                                    9);
1477                     PutULONG(value, outputMessage + 4, bigEndian_);
1478                     unsigned int bitmask;
1479 
1480                     decodeBuffer.decodeCachedValue(bitmask, 7,
1481                                                    clientCache_.
1482                                                    configureWindowBitmaskCache);
1483                     PutUINT(bitmask, outputMessage + 8, bigEndian_);
1484                     unsigned int mask = 0x1;
1485 
1486                     for (unsigned int i = 0; i < 7; i++)
1487                     {
1488                         if (bitmask & mask)
1489                         {
1490                             unsigned char *nextDest =
1491                                 writeBuffer_.addMessage(4);
1492                             outputLength += 4;
1493                             decodeBuffer.decodeCachedValue(value,
1494                                                            CONFIGUREWINDOW_FIELD_WIDTH
1495                                                            [i],
1496                                                            *clientCache_.
1497                                                            configureWindowAttrCache
1498                                                            [i], 8);
1499                             PutULONG(value, nextDest, bigEndian_);
1500                             nextDest += 4;
1501                         }
1502                         mask <<= 1;
1503                     }
1504                     writeBuffer_.unregisterPointer();
1505                 }
1506                 break;
1507             case X_ConvertSelection:
1508                 {
1509                     outputLength = 24;
1510                     outputMessage = writeBuffer_.addMessage(outputLength);
1511                     decodeBuffer.decodeCachedValue(value, 29,
1512                                                    clientCache_.
1513                                                    convertSelectionRequestorCache,
1514                                                    9);
1515                     PutULONG(value, outputMessage + 4, bigEndian_);
1516                     unsigned char *nextDest = outputMessage + 8;
1517 
1518                     for (unsigned int i = 0; i < 3; i++)
1519                     {
1520                         decodeBuffer.decodeCachedValue(value, 29,
1521                                                        *(clientCache_.
1522                                                          convertSelectionAtomCache
1523                                                          [i]), 9);
1524                         PutULONG(value, nextDest, bigEndian_);
1525                         nextDest += 4;
1526                     }
1527                     decodeBuffer.decodeValue(value, 32, 4);
1528                     clientCache_.convertSelectionLastTimestamp += value;
1529                     PutULONG(clientCache_.convertSelectionLastTimestamp,
1530                              nextDest, bigEndian_);
1531                 }
1532                 break;
1533             case X_CopyArea:
1534                 {
1535                     outputLength = 28;
1536                     outputMessage = writeBuffer_.addMessage(outputLength);
1537                     decodeBuffer.decodeCachedValue(value, 29,
1538                                                    clientCache_.drawableCache,
1539                                                    9);
1540                     PutULONG(value, outputMessage + 4, bigEndian_);
1541                     decodeBuffer.decodeCachedValue(value, 29,
1542                                                    clientCache_.drawableCache,
1543                                                    9);
1544                     PutULONG(value, outputMessage + 8, bigEndian_);
1545                     decodeBuffer.decodeCachedValue(value, 29,
1546                                                    clientCache_.gcCache, 9);
1547                     PutULONG(value, outputMessage + 12, bigEndian_);
1548                     unsigned char *nextDest = outputMessage + 16;
1549 
1550                     for (unsigned int i = 0; i < 6; i++)
1551                     {
1552                         decodeBuffer.decodeCachedValue(value, 16,
1553                                                        *clientCache_.
1554                                                        copyAreaGeomCache[i],
1555                                                        8);
1556                         PutUINT(value, nextDest, bigEndian_);
1557                         nextDest += 2;
1558                     }
1559                 }
1560                 break;
1561             case X_CopyGC:
1562                 {
1563                     outputLength = 16;
1564                     outputMessage = writeBuffer_.addMessage(outputLength);
1565                     decodeBuffer.decodeCachedValue(value, 29,
1566                                                    clientCache_.gcCache, 9);
1567                     PutULONG(value, outputMessage + 4, bigEndian_);
1568                     decodeBuffer.decodeCachedValue(value, 29,
1569                                                    clientCache_.gcCache, 9);
1570                     PutULONG(value, outputMessage + 8, bigEndian_);
1571                     decodeBuffer.decodeCachedValue(value, 23,
1572                                                    clientCache_.
1573                                                    createGCBitmaskCache);
1574                     PutULONG(value, outputMessage + 12, bigEndian_);
1575                 }
1576                 break;
1577             case X_CopyPlane:
1578                 {
1579                     outputLength = 32;
1580                     outputMessage = writeBuffer_.addMessage(outputLength);
1581                     decodeBuffer.decodeCachedValue(value, 29,
1582                                                    clientCache_.drawableCache,
1583                                                    9);
1584                     PutULONG(value, outputMessage + 4, bigEndian_);
1585                     decodeBuffer.decodeCachedValue(value, 29,
1586                                                    clientCache_.drawableCache,
1587                                                    9);
1588                     PutULONG(value, outputMessage + 8, bigEndian_);
1589                     decodeBuffer.decodeCachedValue(value, 29,
1590                                                    clientCache_.gcCache, 9);
1591                     PutULONG(value, outputMessage + 12, bigEndian_);
1592                     unsigned char *nextDest = outputMessage + 16;
1593 
1594                     for (unsigned int i = 0; i < 6; i++)
1595                     {
1596                         decodeBuffer.decodeCachedValue(value, 16,
1597                                                        *clientCache_.
1598                                                        copyPlaneGeomCache[i],
1599                                                        8);
1600                         PutUINT(value, nextDest, bigEndian_);
1601                         nextDest += 2;
1602                     }
1603                     decodeBuffer.decodeCachedValue(value, 32,
1604                                                    clientCache_.
1605                                                    copyPlaneBitPlaneCache,
1606                                                    10);
1607                     PutULONG(value, outputMessage + 28, bigEndian_);
1608                 }
1609                 break;
1610             case X_CreateGC:
1611             case X_ChangeGC:
1612                 {
1613                     outputLength = 12;
1614                     if (opcode == X_CreateGC)
1615                         outputLength += 4;
1616                     outputMessage = writeBuffer_.addMessage(outputLength);
1617                     writeBuffer_.registerPointer(&outputMessage);
1618                     decodeBuffer.decodeCachedValue(value, 29,
1619                                                    clientCache_.gcCache, 9);
1620                     PutULONG(value, outputMessage + 4, bigEndian_);
1621                     unsigned int offset = 8;
1622 
1623                     if (opcode == X_CreateGC)
1624                     {
1625                         decodeBuffer.decodeCachedValue(value, 29,
1626                                                        clientCache_.
1627                                                        drawableCache, 9);
1628                         PutULONG(value, outputMessage + offset, bigEndian_);
1629                         offset += 4;
1630                     }
1631                     unsigned int bitmask;
1632 
1633                     decodeBuffer.decodeCachedValue(bitmask, 23,
1634                                                    clientCache_.
1635                                                    createGCBitmaskCache);
1636                     PutULONG(bitmask, outputMessage + offset, bigEndian_);
1637                     unsigned int mask = 0x1;
1638 
1639                     for (unsigned int i = 0; i < 23; i++)
1640                     {
1641                         if (bitmask & mask)
1642                         {
1643                             unsigned char *nextDest =
1644                                 writeBuffer_.addMessage(4);
1645                             outputLength += 4;
1646                             unsigned int fieldWidth = CREATEGC_FIELD_WIDTH[i];
1647 
1648                             if (fieldWidth <= 4)
1649                                 decodeBuffer.decodeValue(value, fieldWidth);
1650                             else
1651                                 decodeBuffer.decodeCachedValue(value,
1652                                                                fieldWidth,
1653                                                                *clientCache_.
1654                                                                createGCAttrCache
1655                                                                [i]);
1656                             PutULONG(value, nextDest, bigEndian_);
1657                         }
1658                         mask <<= 1;
1659                     }
1660                     writeBuffer_.unregisterPointer();
1661                 }
1662                 break;
1663             case X_CreatePixmap:
1664                 {
1665                     outputLength = 16;
1666                     outputMessage = writeBuffer_.addMessage(outputLength);
1667                     decodeBuffer.decodeCachedValue(cValue, 8,
1668                                                    clientCache_.depthCache);
1669                     outputMessage[1] = cValue;
1670                     decodeBuffer.decodeValue(value, 1);
1671                     if (!value)
1672                     {
1673                         decodeBuffer.decodeValue(value, 29, 4);
1674                         clientCache_.createPixmapLastPixmap += value;
1675                         clientCache_.createPixmapLastPixmap &= 0x1fffffff;
1676                     }
1677                     PutULONG(clientCache_.createPixmapLastPixmap,
1678                              outputMessage + 4, bigEndian_);
1679                     decodeBuffer.decodeCachedValue(value, 29,
1680                                                    clientCache_.drawableCache,
1681                                                    9);
1682                     PutULONG(value, outputMessage + 8, bigEndian_);
1683                     decodeBuffer.decodeCachedValue(value, 16,
1684                                                    clientCache_.
1685                                                    createPixmapXCache, 8);
1686                     PutUINT(value, outputMessage + 12, bigEndian_);
1687                     decodeBuffer.decodeCachedValue(value, 16,
1688                                                    clientCache_.
1689                                                    createPixmapYCache, 8);
1690                     PutUINT(value, outputMessage + 14, bigEndian_);
1691                 }
1692                 break;
1693             case X_CreateWindow:
1694                 {
1695                     outputLength = 32;
1696                     outputMessage = writeBuffer_.addMessage(outputLength);
1697                     writeBuffer_.registerPointer(&outputMessage);
1698                     decodeBuffer.decodeCachedValue(cValue, 8,
1699                                                    clientCache_.depthCache);
1700                     outputMessage[1] = cValue;
1701                     decodeBuffer.decodeCachedValue(value, 29,
1702                                                    clientCache_.windowCache,
1703                                                    9);
1704                     PutULONG(value, outputMessage + 8, bigEndian_);
1705                     decodeBuffer.decodeCachedValue(value, 29,
1706                                                    clientCache_.windowCache,
1707                                                    9);
1708                     PutULONG(value, outputMessage + 4, bigEndian_);
1709                     unsigned char *nextDest = outputMessage + 12;
1710                     unsigned int i;
1711 
1712                     for (i = 0; i < 6; i++)
1713                     {
1714                         decodeBuffer.decodeCachedValue(value, 16,
1715                                                        *clientCache_.
1716                                                        createWindowGeomCache
1717                                                        [i], 8);
1718                         PutUINT(value, nextDest, bigEndian_);
1719                         nextDest += 2;
1720                     }
1721                     decodeBuffer.decodeCachedValue(value, 29,
1722                                                    clientCache_.visualCache);
1723                     PutULONG(value, outputMessage + 24, bigEndian_);
1724                     unsigned int bitmask;
1725 
1726                     decodeBuffer.decodeCachedValue(bitmask, 15,
1727                                                    clientCache_.
1728                                                    createWindowBitmaskCache);
1729                     unsigned int newbitmask = bitmask;
1730 
1731                     int addBackingStore = 0;
1732 
1733                     if ((wantBackingStore != NotUseful)
1734                         && !(bitmask & CWBackingStore))
1735                     {
1736                         addBackingStore = 1;
1737                         newbitmask |= CWBackingStore;
1738                     }
1739                     PutULONG(newbitmask, outputMessage + 28, bigEndian_);
1740                     unsigned int mask = 0x1;
1741 
1742                     for (i = 0; i < 15; i++)
1743                     {
1744                         if (bitmask & mask)
1745                         {
1746                             nextDest = writeBuffer_.addMessage(4);
1747                             outputLength += 4;
1748                             decodeBuffer.decodeCachedValue(value, 32,
1749                                                            *clientCache_.
1750                                                            createWindowAttrCache
1751                                                            [i]);
1752                             PutULONG(value, nextDest, bigEndian_);
1753                         }
1754                         else if (mask == CWBackingStore && addBackingStore)
1755                         {
1756                             nextDest = writeBuffer_.addMessage(4);
1757                             outputLength += 4;
1758                             PutULONG(wantBackingStore, nextDest, bigEndian_);
1759                         }
1760                         mask <<= 1;
1761                     }
1762                     writeBuffer_.unregisterPointer();
1763                 }
1764                 break;
1765             case X_DeleteProperty:
1766                 {
1767                     outputLength = 12;
1768                     outputMessage = writeBuffer_.addMessage(outputLength);
1769                     decodeBuffer.decodeCachedValue(value, 29,
1770                                                    clientCache_.windowCache,
1771                                                    9);
1772                     PutULONG(value, outputMessage + 4, bigEndian_);
1773                     decodeBuffer.decodeValue(value, 29, 9);
1774                     PutULONG(value, outputMessage + 8, bigEndian_);
1775                 }
1776                 break;
1777             case X_FillPoly:
1778                 {
1779                     unsigned int numPoints;
1780 
1781                     decodeBuffer.decodeCachedValue(numPoints, 14,
1782                                                    clientCache_.
1783                                                    fillPolyNumPointsCache, 4);
1784                     outputLength = 16 + (numPoints << 2);
1785                     outputMessage = writeBuffer_.addMessage(outputLength);
1786                     decodeBuffer.decodeCachedValue(value, 29,
1787                                                    clientCache_.drawableCache,
1788                                                    9);
1789                     PutULONG(value, outputMessage + 4, bigEndian_);
1790                     decodeBuffer.decodeCachedValue(value, 29,
1791                                                    clientCache_.gcCache, 9);
1792                     PutULONG(value, outputMessage + 8, bigEndian_);
1793                     decodeBuffer.decodeValue(value, 2);
1794                     outputMessage[12] = (unsigned char) value;
1795                     unsigned int relativeCoordMode;
1796 
1797                     decodeBuffer.decodeValue(relativeCoordMode, 1);
1798                     outputMessage[13] = (unsigned char) relativeCoordMode;
1799                     unsigned char *nextDest = outputMessage + 16;
1800                     unsigned int pointIndex = 0;
1801 
1802                     for (unsigned int i = 0; i < numPoints; i++)
1803                     {
1804                         if (relativeCoordMode)
1805                         {
1806                             decodeBuffer.decodeCachedValue(value, 16,
1807                                                            *clientCache_.
1808                                                            fillPolyXRelCache
1809                                                            [pointIndex], 8);
1810                             PutUINT(value, nextDest, bigEndian_);
1811                             nextDest += 2;
1812                             decodeBuffer.decodeCachedValue(value, 16,
1813                                                            *clientCache_.
1814                                                            fillPolyYRelCache
1815                                                            [pointIndex], 8);
1816                             PutUINT(value, nextDest, bigEndian_);
1817                             nextDest += 2;
1818                         }
1819                         else
1820                         {
1821                             unsigned int x, y;
1822 
1823                             decodeBuffer.decodeValue(value, 1);
1824                             if (value)
1825                             {
1826                                 decodeBuffer.decodeValue(value, 3);
1827                                 x = clientCache_.fillPolyRecentX[value];
1828                                 y = clientCache_.fillPolyRecentY[value];
1829                             }
1830                             else
1831                             {
1832                                 decodeBuffer.decodeCachedValue(x, 16,
1833                                                                *clientCache_.
1834                                                                fillPolyXAbsCache
1835                                                                [pointIndex],
1836                                                                8);
1837                                 decodeBuffer.decodeCachedValue(y, 16,
1838                                                                *clientCache_.
1839                                                                fillPolyYAbsCache
1840                                                                [pointIndex],
1841                                                                8);
1842                                 clientCache_.fillPolyRecentX[clientCache_.
1843                                                              fillPolyIndex] =
1844                                     x;
1845                                 clientCache_.fillPolyRecentY[clientCache_.
1846                                                              fillPolyIndex] =
1847                                     y;
1848                                 clientCache_.fillPolyIndex++;
1849                                 if (clientCache_.fillPolyIndex == 8)
1850                                     clientCache_.fillPolyIndex = 0;
1851                             }
1852                             PutUINT(x, nextDest, bigEndian_);
1853                             nextDest += 2;
1854                             PutUINT(y, nextDest, bigEndian_);
1855                             nextDest += 2;
1856                         }
1857                         if (pointIndex + 1 < FILL_POLY_MAX_POINTS)
1858                             pointIndex++;
1859                     }
1860                 }
1861                 break;
1862             case X_FreeColors:
1863                 {
1864                     unsigned int numPixels;
1865 
1866                     decodeBuffer.decodeValue(numPixels, 16, 4);
1867                     outputLength = 12 + (numPixels << 2);
1868                     outputMessage = writeBuffer_.addMessage(outputLength);
1869                     decodeBuffer.decodeCachedValue(value, 29,
1870                                                    clientCache_.colormapCache,
1871                                                    9);
1872                     PutULONG(value, outputMessage + 4, bigEndian_);
1873                     decodeBuffer.decodeValue(value, 32, 4);
1874                     PutULONG(value, outputMessage + 8, bigEndian_);
1875                     unsigned char *nextDest = outputMessage + 12;
1876 
1877                     while (numPixels)
1878                     {
1879                         decodeBuffer.decodeValue(value, 32, 8);
1880                         PutULONG(value, nextDest, bigEndian_);
1881                         nextDest += 4;
1882                         numPixels--;
1883                     }
1884                 }
1885                 break;
1886             case X_FreeCursor:
1887                 {
1888                     outputLength = 8;
1889                     outputMessage = writeBuffer_.addMessage(outputLength);
1890                     decodeBuffer.decodeCachedValue(value, 29,
1891                                                    clientCache_.cursorCache,
1892                                                    9);
1893                     PutULONG(value, outputMessage + 4, bigEndian_);
1894                 }
1895                 break;
1896             case X_FreeGC:
1897                 {
1898                     outputLength = 8;
1899                     outputMessage = writeBuffer_.addMessage(outputLength);
1900                     decodeBuffer.decodeCachedValue(value, 29,
1901                                                    clientCache_.gcCache, 9);
1902                     PutULONG(value, outputMessage + 4, bigEndian_);
1903                 }
1904                 break;
1905             case X_FreePixmap:
1906                 {
1907                     outputLength = 8;
1908                     outputMessage = writeBuffer_.addMessage(outputLength);
1909                     decodeBuffer.decodeValue(value, 1);
1910                     if (!value)
1911                     {
1912                         decodeBuffer.decodeValue(value, 29, 4);
1913                         clientCache_.createPixmapLastPixmap += value;
1914                         clientCache_.createPixmapLastPixmap &= 0x1fffffff;
1915                     }
1916                     PutULONG(clientCache_.createPixmapLastPixmap,
1917                              outputMessage + 4, bigEndian_);
1918                 }
1919                 break;
1920             case X_GetAtomName:
1921                 {
1922                     outputLength = 8;
1923                     outputMessage = writeBuffer_.addMessage(outputLength);
1924                     decodeBuffer.decodeValue(value, 29, 9);
1925                     PutULONG(value, outputMessage + 4, bigEndian_);
1926                     sequenceNumQueue_.push(clientCache_.
1927                                            lastRequestSequenceNum, opcode);
1928                 }
1929                 break;
1930             case X_GetGeometry:
1931                 {
1932                     outputLength = 8;
1933                     outputMessage = writeBuffer_.addMessage(outputLength);
1934                     decodeBuffer.decodeCachedValue(value, 29,
1935                                                    clientCache_.drawableCache,
1936                                                    9);
1937                     PutULONG(value, outputMessage + 4, bigEndian_);
1938                     sequenceNumQueue_.push(clientCache_.
1939                                            lastRequestSequenceNum, opcode);
1940                 }
1941                 break;
1942             case X_GetInputFocus:
1943             case X_GetModifierMapping:
1944                 {
1945                     outputLength = 4;
1946                     outputMessage = writeBuffer_.addMessage(outputLength);
1947                     sequenceNumQueue_.push(clientCache_.
1948                                            lastRequestSequenceNum, opcode);
1949                 }
1950                 break;
1951             case X_GetKeyboardMapping:
1952                 {
1953                     outputLength = 8;
1954                     outputMessage = writeBuffer_.addMessage(outputLength);
1955                     decodeBuffer.decodeValue(value, 8);
1956                     outputMessage[4] = value;
1957                     decodeBuffer.decodeValue(value, 8);
1958                     outputMessage[5] = value;
1959                     sequenceNumQueue_.push(clientCache_.
1960                                            lastRequestSequenceNum, opcode);
1961                 }
1962                 break;
1963             case X_GetProperty:
1964                 {
1965                     outputLength = 24;
1966                     outputMessage = writeBuffer_.addMessage(outputLength);
1967                     decodeBuffer.decodeValue(value, 1);
1968                     outputMessage[1] = (unsigned char) value;
1969                     decodeBuffer.decodeCachedValue(value, 29,
1970                                                    clientCache_.windowCache,
1971                                                    9);
1972                     PutULONG(value, outputMessage + 4, bigEndian_);
1973                     unsigned int property;
1974 
1975                     decodeBuffer.decodeValue(property, 29, 9);
1976                     PutULONG(property, outputMessage + 8, bigEndian_);
1977                     decodeBuffer.decodeValue(value, 29, 9);
1978                     PutULONG(value, outputMessage + 12, bigEndian_);
1979                     decodeBuffer.decodeValue(value, 32, 2);
1980                     PutULONG(value, outputMessage + 16, bigEndian_);
1981                     decodeBuffer.decodeValue(value, 32, 8);
1982                     PutULONG(value, outputMessage + 20, bigEndian_);
1983                     sequenceNumQueue_.push(clientCache_.
1984                                            lastRequestSequenceNum, opcode,
1985                                            property);
1986                 }
1987                 break;
1988             case X_GetSelectionOwner:
1989                 {
1990                     outputLength = 8;
1991                     outputMessage = writeBuffer_.addMessage(outputLength);
1992                     decodeBuffer.decodeCachedValue(value, 29,
1993                                                    clientCache_.
1994                                                    getSelectionOwnerSelectionCache,
1995                                                    9);
1996                     PutULONG(value, outputMessage + 4, bigEndian_);
1997                     sequenceNumQueue_.push(clientCache_.
1998                                            lastRequestSequenceNum, opcode);
1999                 }
2000                 break;
2001             case X_GrabButton:
2002             case X_GrabPointer:
2003                 {
2004                     outputLength = 24;
2005                     outputMessage = writeBuffer_.addMessage(outputLength);
2006                     decodeBuffer.decodeValue(value, 1);
2007                     outputMessage[1] = (unsigned char) value;
2008                     decodeBuffer.decodeCachedValue(value, 29,
2009                                                    clientCache_.windowCache,
2010                                                    9);
2011                     PutULONG(value, outputMessage + 4, bigEndian_);
2012                     decodeBuffer.decodeCachedValue(value, 16,
2013                                                    clientCache_.
2014                                                    grabButtonEventMaskCache);
2015                     PutUINT(value, outputMessage + 8, bigEndian_);
2016                     decodeBuffer.decodeValue(value, 1);
2017                     outputMessage[10] = (unsigned char) value;
2018                     decodeBuffer.decodeValue(value, 1);
2019                     outputMessage[11] = (unsigned char) value;
2020                     decodeBuffer.decodeCachedValue(value, 29,
2021                                                    clientCache_.
2022                                                    grabButtonConfineCache, 9);
2023                     PutULONG(value, outputMessage + 12, bigEndian_);
2024                     decodeBuffer.decodeCachedValue(value, 29,
2025                                                    clientCache_.cursorCache,
2026                                                    9);
2027                     PutULONG(value, outputMessage + 16, bigEndian_);
2028                     if (opcode == X_GrabButton)
2029                     {
2030                         decodeBuffer.decodeCachedValue(cValue, 8,
2031                                                        clientCache_.
2032                                                        grabButtonButtonCache);
2033                         outputMessage[20] = cValue;
2034                         decodeBuffer.decodeCachedValue(value, 16,
2035                                                        clientCache_.
2036                                                        grabButtonModifierCache);
2037                         PutUINT(value, outputMessage + 22, bigEndian_);
2038                     }
2039                     else
2040                     {
2041                         decodeBuffer.decodeValue(value, 32, 4);
2042                         clientCache_.grabKeyboardLastTimestamp += value;
2043                         PutULONG(clientCache_.grabKeyboardLastTimestamp,
2044                                  outputMessage + 20, bigEndian_);
2045                         sequenceNumQueue_.push(clientCache_.
2046                                                lastRequestSequenceNum,
2047                                                opcode);
2048                     }
2049                 }
2050                 break;
2051             case X_GrabKeyboard:
2052                 {
2053                     outputLength = 16;
2054                     outputMessage = writeBuffer_.addMessage(outputLength);
2055                     decodeBuffer.decodeValue(value, 1);
2056                     outputMessage[1] = (unsigned char) value;
2057                     decodeBuffer.decodeCachedValue(value, 29,
2058                                                    clientCache_.windowCache,
2059                                                    9);
2060                     PutULONG(value, outputMessage + 4, bigEndian_);
2061                     decodeBuffer.decodeValue(value, 32, 4);
2062                     clientCache_.grabKeyboardLastTimestamp += value;
2063                     PutULONG(clientCache_.grabKeyboardLastTimestamp,
2064                              outputMessage + 8, bigEndian_);
2065                     decodeBuffer.decodeValue(value, 1);
2066                     outputMessage[12] = (unsigned char) value;
2067                     decodeBuffer.decodeValue(value, 1);
2068                     outputMessage[13] = (unsigned char) value;
2069                     sequenceNumQueue_.push(clientCache_.
2070                                            lastRequestSequenceNum, opcode);
2071                 }
2072                 break;
2073             case X_GrabServer:
2074             case X_UngrabServer:
2075             case X_NoOperation:
2076                 {
2077                     outputLength = 4;
2078                     outputMessage = writeBuffer_.addMessage(outputLength);
2079                 }
2080                 break;
2081             case X_ImageText8:
2082                 {
2083                     unsigned int textLength;
2084 
2085                     decodeBuffer.decodeValue(textLength, 8);
2086                     outputLength = 16 + RoundUp4(textLength);
2087                     outputMessage = writeBuffer_.addMessage(outputLength);
2088                     outputMessage[1] = (unsigned char) textLength;
2089                     decodeBuffer.decodeCachedValue(value, 29,
2090                                                    clientCache_.drawableCache,
2091                                                    9);
2092                     PutULONG(value, outputMessage + 4, bigEndian_);
2093                     decodeBuffer.decodeCachedValue(value, 29,
2094                                                    clientCache_.gcCache, 9);
2095                     PutULONG(value, outputMessage + 8, bigEndian_);
2096                     decodeBuffer.decodeCachedValue(value, 16,
2097                                                    clientCache_.
2098                                                    imageText8CacheX, 8);
2099                     clientCache_.imageText8LastX += value;
2100                     clientCache_.imageText8LastX &= 0xffff;
2101                     PutUINT(clientCache_.imageText8LastX,
2102                             outputMessage + 12, bigEndian_);
2103                     decodeBuffer.decodeCachedValue(value, 16,
2104                                                    clientCache_.
2105                                                    imageText8CacheY, 8);
2106                     clientCache_.imageText8LastY += value;
2107                     clientCache_.imageText8LastY &= 0xffff;
2108                     PutUINT(clientCache_.imageText8LastY,
2109                             outputMessage + 14, bigEndian_);
2110                     unsigned char *nextDest = outputMessage + 16;
2111 
2112                     clientCache_.imageText8TextCompressor.reset();
2113                     while (textLength)
2114                     {
2115                         *nextDest++ =
2116                             clientCache_.imageText8TextCompressor.
2117                             decodeChar(decodeBuffer);
2118                         textLength--;
2119                     }
2120                 }
2121                 break;
2122             case X_InternAtom:
2123                 {
2124                     unsigned int nameLength;
2125 
2126                     decodeBuffer.decodeValue(nameLength, 16, 6);
2127                     outputLength = RoundUp4(nameLength) + 8;
2128                     outputMessage = writeBuffer_.addMessage(outputLength);
2129                     PutUINT(nameLength, outputMessage + 4, bigEndian_);
2130                     decodeBuffer.decodeValue(value, 1);
2131                     outputMessage[1] = (unsigned char) value;
2132                     unsigned char *nextDest = outputMessage + 8;
2133 
2134                     clientCache_.internAtomTextCompressor.reset();
2135                     for (unsigned int i = 0; i < nameLength; i++)
2136                         *nextDest++ =
2137                             clientCache_.internAtomTextCompressor.
2138                             decodeChar(decodeBuffer);
2139                     sequenceNumQueue_.push(clientCache_.
2140                                            lastRequestSequenceNum, opcode);
2141                 }
2142                 break;
2143             case X_ListExtensions:
2144                 {
2145                     outputLength = 4;
2146                     outputMessage = writeBuffer_.addMessage(outputLength);
2147                     sequenceNumQueue_.push(clientCache_.
2148                                            lastRequestSequenceNum, opcode);
2149                 }
2150                 break;
2151             case X_ListFonts:
2152                 {
2153                     unsigned int textLength;
2154 
2155                     decodeBuffer.decodeValue(textLength, 16, 6);
2156                     outputLength = 8 + RoundUp4(textLength);
2157                     outputMessage = writeBuffer_.addMessage(outputLength);
2158                     PutUINT(textLength, outputMessage + 6, bigEndian_);
2159                     decodeBuffer.decodeValue(value, 16, 6);
2160                     PutUINT(value, outputMessage + 4, bigEndian_);
2161                     unsigned char *nextDest = outputMessage + 8;
2162 
2163                     clientCache_.polyText8TextCompressor.reset();
2164                     for (unsigned int i = 0; i < textLength; i++)
2165                         *nextDest++ =
2166                             clientCache_.polyText8TextCompressor.
2167                             decodeChar(decodeBuffer);
2168                     sequenceNumQueue_.push(clientCache_.
2169                                            lastRequestSequenceNum, opcode);
2170                 }
2171                 break;
2172             case X_LookupColor:
2173             case X_AllocNamedColor:
2174                 {
2175                     unsigned int textLength;
2176 
2177                     decodeBuffer.decodeValue(textLength, 16, 6);
2178                     outputLength = 12 + RoundUp4(textLength);
2179                     outputMessage = writeBuffer_.addMessage(outputLength);
2180                     decodeBuffer.decodeCachedValue(value, 29,
2181                                                    clientCache_.colormapCache,
2182                                                    9);
2183                     PutULONG(value, outputMessage + 4, bigEndian_);
2184                     PutUINT(textLength, outputMessage + 8, bigEndian_);
2185                     unsigned char *nextDest = outputMessage + 12;
2186 
2187                     clientCache_.polyText8TextCompressor.reset();
2188                     for (unsigned int i = 0; i < textLength; i++)
2189                         *nextDest++ =
2190                             clientCache_.polyText8TextCompressor.
2191                             decodeChar(decodeBuffer);
2192                     sequenceNumQueue_.push(clientCache_.
2193                                            lastRequestSequenceNum, opcode);
2194                 }
2195                 break;
2196             case X_MapWindow:
2197             case X_UnmapWindow:
2198             case X_MapSubwindows:
2199             case X_GetWindowAttributes:
2200             case X_DestroyWindow:
2201             case X_DestroySubwindows:
2202             case X_QueryPointer:
2203             case X_QueryTree:
2204                 {
2205                     outputLength = 8;
2206                     outputMessage = writeBuffer_.addMessage(outputLength);
2207                     decodeBuffer.decodeCachedValue(value, 29,
2208                                                    clientCache_.windowCache,
2209                                                    9);
2210                     PutULONG(value, outputMessage + 4, bigEndian_);
2211                     if ((opcode == X_QueryPointer) ||
2212                         (opcode == X_GetWindowAttributes) ||
2213                         (opcode == X_QueryTree))
2214                         sequenceNumQueue_.push(clientCache_.
2215                                                lastRequestSequenceNum,
2216                                                opcode);
2217                 }
2218                 break;
2219             case X_OpenFont:
2220                 {
2221                     unsigned int nameLength;
2222 
2223                     decodeBuffer.decodeValue(nameLength, 16, 7);
2224                     outputLength = RoundUp4(12 + nameLength);
2225                     outputMessage = writeBuffer_.addMessage(outputLength);
2226                     PutUINT(nameLength, outputMessage + 8, bigEndian_);
2227                     decodeBuffer.decodeValue(value, 29, 5);
2228                     clientCache_.lastFont += value;
2229                     clientCache_.lastFont &= 0x1fffffff;
2230                     PutULONG(clientCache_.lastFont, outputMessage + 4,
2231                              bigEndian_);
2232                     unsigned char *nextDest = outputMessage + 12;
2233 
2234                     clientCache_.openFontTextCompressor.reset();
2235                     for (; nameLength; nameLength--)
2236                         *nextDest++ =
2237                             clientCache_.openFontTextCompressor.
2238                             decodeChar(decodeBuffer);
2239                 }
2240                 break;
2241             case X_PolyFillRectangle:
2242                 {
2243                     outputLength = 12;
2244                     outputMessage = writeBuffer_.addMessage(outputLength);
2245                     writeBuffer_.registerPointer(&outputMessage);
2246                     decodeBuffer.decodeCachedValue(value, 29,
2247                                                    clientCache_.drawableCache,
2248                                                    9);
2249                     PutULONG(value, outputMessage + 4, bigEndian_);
2250                     decodeBuffer.decodeCachedValue(value, 29,
2251                                                    clientCache_.gcCache, 9);
2252                     PutULONG(value, outputMessage + 8, bigEndian_);
2253 
2254                     unsigned int index = 0;
2255                     unsigned int lastX = 0, lastY = 0, lastWidth =
2256                         0, lastHeight = 0;
2257                     unsigned int numRectangles = 0;
2258 
2259                     for (;;)
2260                     {
2261                         outputLength += 8;
2262                         writeBuffer_.addMessage(8);
2263                         unsigned char *nextDest = outputMessage + 12 +
2264                             (numRectangles << 3);
2265                         numRectangles++;
2266                         decodeBuffer.decodeCachedValue(value, 16,
2267                                                        *clientCache_.
2268                                                        polyFillRectangleCacheX
2269                                                        [index], 8);
2270                         value += lastX;
2271                         PutUINT(value, nextDest, bigEndian_);
2272                         lastX = value;
2273                         nextDest += 2;
2274                         decodeBuffer.decodeCachedValue(value, 16,
2275                                                        *clientCache_.
2276                                                        polyFillRectangleCacheY
2277                                                        [index], 8);
2278                         value += lastY;
2279                         PutUINT(value, nextDest, bigEndian_);
2280                         lastY = value;
2281                         nextDest += 2;
2282                         decodeBuffer.decodeCachedValue(value, 16,
2283                                                        *clientCache_.
2284                                                        polyFillRectangleCacheWidth
2285                                                        [index], 8);
2286                         value += lastWidth;
2287                         PutUINT(value, nextDest, bigEndian_);
2288                         lastWidth = value;
2289                         nextDest += 2;
2290                         decodeBuffer.decodeCachedValue(value, 16,
2291                                                        *clientCache_.
2292                                                        polyFillRectangleCacheHeight
2293                                                        [index], 8);
2294                         value += lastHeight;
2295                         PutUINT(value, nextDest, bigEndian_);
2296                         lastHeight = value;
2297                         nextDest += 2;
2298                         index = 1;
2299 
2300                         decodeBuffer.decodeValue(value, 1);
2301                         if (!value)
2302                             break;
2303                     }
2304                     writeBuffer_.unregisterPointer();
2305                 }
2306                 break;
2307             case X_PolyPoint:
2308                 {
2309                     unsigned int numPoints;
2310 
2311                     decodeBuffer.decodeValue(numPoints, 16, 4);
2312                     outputLength = (numPoints << 2) + 12;
2313                     outputMessage = writeBuffer_.addMessage(outputLength);
2314                     unsigned int relativeCoordMode;
2315 
2316                     decodeBuffer.decodeValue(relativeCoordMode, 1);
2317                     outputMessage[1] = (unsigned char) relativeCoordMode;
2318                     decodeBuffer.decodeCachedValue(value, 29,
2319                                                    clientCache_.drawableCache,
2320                                                    9);
2321                     PutULONG(value, outputMessage + 4, bigEndian_);
2322                     decodeBuffer.decodeCachedValue(value, 29,
2323                                                    clientCache_.gcCache, 9);
2324                     PutULONG(value, outputMessage + 8, bigEndian_);
2325                     unsigned char *nextDest = outputMessage + 12;
2326                     unsigned int index = 0;
2327                     unsigned int lastX = 0, lastY = 0;
2328 
2329                     for (unsigned int i = 0; i < numPoints; i++)
2330                     {
2331                         decodeBuffer.decodeCachedValue(value, 16,
2332                                                        *clientCache_.
2333                                                        polyPointCacheX[index],
2334                                                        8);
2335                         lastX += value;
2336                         PutUINT(lastX, nextDest, bigEndian_);
2337                         nextDest += 2;
2338                         decodeBuffer.decodeCachedValue(value, 16,
2339                                                        *clientCache_.
2340                                                        polyPointCacheY[index],
2341                                                        8);
2342                         lastY += value;
2343                         PutUINT(lastY, nextDest, bigEndian_);
2344                         nextDest += 2;
2345                         index = 1;
2346                     }
2347                 }
2348                 break;
2349             case X_PolyLine:
2350                 {
2351                     unsigned int numPoints;
2352 
2353                     decodeBuffer.decodeValue(numPoints, 16, 4);
2354                     outputLength = (numPoints << 2) + 12;
2355                     outputMessage = writeBuffer_.addMessage(outputLength);
2356                     unsigned int relativeCoordMode;
2357 
2358                     decodeBuffer.decodeValue(relativeCoordMode, 1);
2359                     outputMessage[1] = (unsigned char) relativeCoordMode;
2360                     decodeBuffer.decodeCachedValue(value, 29,
2361                                                    clientCache_.drawableCache,
2362                                                    9);
2363                     PutULONG(value, outputMessage + 4, bigEndian_);
2364                     decodeBuffer.decodeCachedValue(value, 29,
2365                                                    clientCache_.gcCache, 9);
2366                     PutULONG(value, outputMessage + 8, bigEndian_);
2367                     unsigned char *nextDest = outputMessage + 12;
2368                     unsigned int index = 0;
2369                     unsigned int lastX = 0, lastY = 0;
2370 
2371                     for (unsigned int i = 0; i < numPoints; i++)
2372                     {
2373                         decodeBuffer.decodeCachedValue(value, 16,
2374                                                        *clientCache_.
2375                                                        polyLineCacheX[index],
2376                                                        8);
2377                         lastX += value;
2378                         PutUINT(lastX, nextDest, bigEndian_);
2379                         nextDest += 2;
2380                         decodeBuffer.decodeCachedValue(value, 16,
2381                                                        *clientCache_.
2382                                                        polyLineCacheY[index],
2383                                                        8);
2384                         lastY += value;
2385                         PutUINT(lastY, nextDest, bigEndian_);
2386                         nextDest += 2;
2387                         index = 1;
2388                     }
2389                 }
2390                 break;
2391             case X_PolyRectangle:
2392                 {
2393                     unsigned int numRectangles;
2394 
2395                     decodeBuffer.decodeValue(numRectangles, 16, 3);
2396                     outputLength = (numRectangles << 3) + 12;
2397                     outputMessage = writeBuffer_.addMessage(outputLength);
2398                     decodeBuffer.decodeCachedValue(value, 29,
2399                                                    clientCache_.drawableCache,
2400                                                    9);
2401                     PutULONG(value, outputMessage + 4, bigEndian_);
2402                     decodeBuffer.decodeCachedValue(value, 29,
2403                                                    clientCache_.gcCache, 9);
2404                     PutULONG(value, outputMessage + 8, bigEndian_);
2405                     unsigned char *nextDest = outputMessage + 12;
2406 
2407                     for (unsigned int i = 0; i < numRectangles; i++)
2408                         for (unsigned int k = 0; k < 4; k++)
2409                         {
2410                             decodeBuffer.decodeCachedValue(value, 16,
2411                                                            *clientCache_.
2412                                                            polyRectangleGeomCache
2413                                                            [k], 8);
2414                             PutUINT(value, nextDest, bigEndian_);
2415                             nextDest += 2;
2416                         }
2417                 }
2418                 break;
2419             case X_PolySegment:
2420                 {
2421                     unsigned int numSegments;
2422 
2423                     decodeBuffer.decodeValue(numSegments, 16, 4);
2424                     outputLength = (numSegments << 3) + 12;
2425                     outputMessage = writeBuffer_.addMessage(outputLength);
2426                     decodeBuffer.decodeCachedValue(value, 29,
2427                                                    clientCache_.drawableCache,
2428                                                    9);
2429                     PutULONG(value, outputMessage + 4, bigEndian_);
2430                     decodeBuffer.decodeCachedValue(value, 29,
2431                                                    clientCache_.gcCache, 9);
2432                     PutULONG(value, outputMessage + 8, bigEndian_);
2433                     unsigned char *nextDest = outputMessage + 12;
2434 
2435                     for (numSegments *= 2; numSegments; numSegments--)
2436                     {
2437                         unsigned int index;
2438 
2439                         decodeBuffer.decodeValue(index, 1);
2440                         unsigned int x;
2441 
2442                         decodeBuffer.decodeCachedValue(x, 16,
2443                                                        clientCache_.
2444                                                        polySegmentCacheX, 6);
2445                         x += clientCache_.polySegmentLastX[index];
2446                         PutUINT(x, nextDest, bigEndian_);
2447                         nextDest += 2;
2448 
2449                         unsigned int y;
2450 
2451                         decodeBuffer.decodeCachedValue(y, 16,
2452                                                        clientCache_.
2453                                                        polySegmentCacheY, 6);
2454                         y += clientCache_.polySegmentLastY[index];
2455                         PutUINT(y, nextDest, bigEndian_);
2456                         nextDest += 2;
2457 
2458                         clientCache_.polySegmentLastX[clientCache_.
2459                                                       polySegmentCacheIndex] =
2460                             x;
2461                         clientCache_.polySegmentLastY[clientCache_.
2462                                                       polySegmentCacheIndex] =
2463                             y;
2464 
2465                         if (clientCache_.polySegmentCacheIndex == 1)
2466                             clientCache_.polySegmentCacheIndex = 0;
2467                         else
2468                             clientCache_.polySegmentCacheIndex = 1;
2469                     }
2470                 }
2471                 break;
2472             case X_PolyText8:
2473                 {
2474                     outputLength = 16;
2475                     outputMessage = writeBuffer_.addMessage(outputLength);
2476                     decodeBuffer.decodeCachedValue(value, 29,
2477                                                    clientCache_.drawableCache,
2478                                                    9);
2479                     PutULONG(value, outputMessage + 4, bigEndian_);
2480                     decodeBuffer.decodeCachedValue(value, 29,
2481                                                    clientCache_.gcCache, 9);
2482                     PutULONG(value, outputMessage + 8, bigEndian_);
2483                     decodeBuffer.decodeCachedValue(value, 16,
2484                                                    clientCache_.
2485                                                    polyText8CacheX, 8);
2486                     clientCache_.polyText8LastX += value;
2487                     clientCache_.polyText8LastX &= 0xffff;
2488                     PutUINT(clientCache_.polyText8LastX, outputMessage + 12,
2489                             bigEndian_);
2490                     decodeBuffer.decodeCachedValue(value, 16,
2491                                                    clientCache_.
2492                                                    polyText8CacheY, 8);
2493                     clientCache_.polyText8LastY += value;
2494                     clientCache_.polyText8LastY &= 0xffff;
2495                     PutUINT(clientCache_.polyText8LastY, outputMessage + 14,
2496                             bigEndian_);
2497                     unsigned int addedLength = 0;
2498 
2499                     writeBuffer_.registerPointer(&outputMessage);
2500                     for (;;)
2501                     {
2502                         decodeBuffer.decodeValue(value, 1);
2503                         if (!value)
2504                             break;
2505                         unsigned int textLength;
2506 
2507                         decodeBuffer.decodeValue(textLength, 8);
2508                         if (textLength == 255)
2509                         {
2510                             addedLength += 5;
2511                             unsigned char *nextSegment =
2512                                 writeBuffer_.addMessage(5);
2513                             *nextSegment = (unsigned char) textLength;
2514                             decodeBuffer.decodeCachedValue(value, 29,
2515                                                            clientCache_.
2516                                                            polyText8FontCache);
2517                             PutULONG(value, nextSegment + 1, 1);
2518                         }
2519                         else
2520                         {
2521                             addedLength += (textLength + 2);
2522                             unsigned char *nextSegment =
2523                                 writeBuffer_.addMessage(textLength + 2);
2524                             *nextSegment = (unsigned char) textLength;
2525                             unsigned char *nextDest = nextSegment + 1;
2526 
2527                             decodeBuffer.decodeCachedValue(cValue, 8,
2528                                                            clientCache_.
2529                                                            polyText8DeltaCache);
2530                             *nextDest++ = cValue;
2531                             clientCache_.polyText8TextCompressor.reset();
2532                             while (textLength)
2533                             {
2534                                 *nextDest++ =
2535                                     clientCache_.polyText8TextCompressor.
2536                                     decodeChar(decodeBuffer);
2537                                 textLength--;
2538                             }
2539                         }
2540                     }
2541                     outputLength += addedLength;
2542                     unsigned int mod4 = (addedLength & 0x3);
2543 
2544                     if (mod4)
2545                     {
2546                         unsigned int extra = 4 - mod4;
2547                         unsigned char *nextDest =
2548                             writeBuffer_.addMessage(extra);
2549                         for (unsigned int i = 0; i < extra; i++)
2550                             *nextDest++ = 0;
2551                         outputLength += extra;
2552                     }
2553                     writeBuffer_.unregisterPointer();
2554                 }
2555                 break;
2556             case X_PutImage:
2557                 {
2558                     decodeBuffer.decodeValue(value, 16, 8);
2559                     outputLength = (value << 2);
2560                     outputMessage = writeBuffer_.addMessage(outputLength);
2561                     decodeBuffer.decodeValue(value, 2);
2562                     outputMessage[1] = (unsigned char) value;
2563                     decodeBuffer.decodeCachedValue(value, 29,
2564                                                    clientCache_.drawableCache,
2565                                                    9);
2566                     PutULONG(value, outputMessage + 4, bigEndian_);
2567                     decodeBuffer.decodeCachedValue(value, 29,
2568                                                    clientCache_.gcCache, 9);
2569                     PutULONG(value, outputMessage + 8, bigEndian_);
2570                     unsigned int width;
2571 
2572                     decodeBuffer.decodeCachedValue(width, 16,
2573                                                    clientCache_.
2574                                                    putImageWidthCache, 8);
2575                     PutUINT(width, outputMessage + 12, bigEndian_);
2576                     unsigned int height;
2577 
2578                     decodeBuffer.decodeCachedValue(height, 16,
2579                                                    clientCache_.
2580                                                    putImageHeightCache, 8);
2581                     PutUINT(height, outputMessage + 14, bigEndian_);
2582                     decodeBuffer.decodeCachedValue(value, 16,
2583                                                    clientCache_.
2584                                                    putImageXCache, 8);
2585                     clientCache_.putImageLastX += value;
2586                     clientCache_.putImageLastX &= 0xffff;
2587                     PutUINT(clientCache_.putImageLastX, outputMessage + 16,
2588                             bigEndian_);
2589                     decodeBuffer.decodeCachedValue(value, 16,
2590                                                    clientCache_.
2591                                                    putImageYCache, 8);
2592                     clientCache_.putImageLastY += value;
2593                     clientCache_.putImageLastY &= 0xffff;
2594                     PutUINT(clientCache_.putImageLastY, outputMessage + 18,
2595                             bigEndian_);
2596                     decodeBuffer.decodeCachedValue(cValue, 8,
2597                                                    clientCache_.
2598                                                    putImageOffsetCache);
2599                     outputMessage[20] = cValue;
2600                     decodeBuffer.decodeCachedValue(cValue, 8,
2601                                                    clientCache_.depthCache);
2602                     outputMessage[21] = cValue;
2603                     unsigned char *nextDest = outputMessage + 24;
2604 
2605                     decodeBuffer.decodeValue(value, COMPRESSION_TYPE_BITS);
2606 
2607                     CompressionType compressionType = (CompressionType) value;
2608 
2609                     if (decompresser
2610                         && compressionType != NO_STREAM_COMPRESSION)
2611                     {
2612                         decompresser->decompressBuffer(compressionType,
2613                                                        nextDest,
2614                                                        decodeBuffer);
2615                     }
2616                     else if ((outputMessage[1] == 0) && (height <= 32) &&
2617                              (width > height * PUT_IMAGE_MIN_ASPECT_RATIO))
2618                     {
2619                         // bitmap that probably contains text; encode using a variant of
2620                         // text-compression algorithm
2621                         unsigned int widthInBits =
2622                             ((width / scanlinePad_) * scanlinePad_);
2623                         if (widthInBits < width)
2624                             widthInBits += scanlinePad_;
2625                         unsigned int widthInBytes = (widthInBits >> 3);
2626                         unsigned char *nextDest = outputMessage + 24;
2627 
2628                         memset(nextDest, 0, outputLength - 24);
2629                         unsigned char destMask = 0x80;
2630 
2631                         clientCache_.putImageLastPixels.reset();
2632                         for (unsigned int xCoord = 0; xCoord < width;
2633                              xCoord++)
2634                         {
2635                             unsigned int modelNum =
2636                                 clientCache_.putImageLastPixels.getValue();
2637                             unsigned int columnValue;
2638 
2639                             decodeBuffer.decodeCachedValue(columnValue,
2640                                                            height,
2641                                                            clientCache_.
2642                                                            putImagePixelCache
2643                                                            [modelNum %
2644                                                             PUT_IMAGE_PIXEL_CACHE_SIZE],
2645                                                            clientCache_.
2646                                                            columnPixel0Coder,
2647                                                            clientCache_.
2648                                                            columnPixel1Coder);
2649                             unsigned char *next = nextDest;
2650                             unsigned int mask = (1 << (height - 1));
2651 
2652                             for (unsigned int h = 0; h < height; h++)
2653                             {
2654                                 if (columnValue & mask)
2655                                     *next |= destMask;
2656                                 next += widthInBytes;
2657                                 mask >>= 1;
2658                             }
2659                             destMask >>= 1;
2660                             if (destMask == 0)
2661                             {
2662                                 destMask = 0x80;
2663                                 nextDest++;
2664                             }
2665                             clientCache_.putImageLastPixels.add(columnValue);
2666                         }
2667                         if ((imageByteOrder_ == 0) && (bitmapBitOrder_ == 0))
2668                         {
2669                             unsigned char *next = outputMessage + 24;
2670 
2671                             for (unsigned int i = 24; i < outputLength; i++)
2672                             {
2673                                 *next = REVERSED_BYTE[*next];
2674                                 next++;
2675                             }
2676                         }
2677                     }
2678                     else if (outputMessage[1] == 0)
2679                     {
2680                         // bitmap--use "Modified-Modified-Read" FAX coding
2681                         if (width + 2 > clientCache_.putImageLineSize)
2682                         {
2683                             delete[]clientCache_.putImageReferenceLine;
2684                             delete[]clientCache_.putImageCodingLine;
2685                             clientCache_.putImageLineSize = width + 2;
2686                             clientCache_.putImageReferenceLine =
2687                                 new unsigned int[width + 2];
2688                             clientCache_.putImageCodingLine =
2689                                 new unsigned int[width + 2];
2690                         }
2691                         unsigned int widthInBits =
2692                             ((width / scanlinePad_) * scanlinePad_);
2693                         if (widthInBits < width)
2694                             widthInBits += scanlinePad_;
2695                         unsigned int widthInBytes = (widthInBits >> 3);
2696                         unsigned int lastPixelValue = 0;
2697 
2698                         for (unsigned int h = 0; h < height; h++)
2699                         {
2700                             unsigned int codingLineLength = 0;
2701                             unsigned char *nextDest =
2702                                 outputMessage + 24 + h * widthInBytes;
2703                             *nextDest = 0;
2704                             unsigned char destMask = 0x80;
2705 
2706                             if (h == 0)
2707                             {
2708                                 unsigned int pixelValue;
2709 
2710                                 decodeBuffer.decodeValue(pixelValue, 1);
2711                                 for (unsigned int xCoord = 0; xCoord < width;)
2712                                 {
2713                                     if (pixelValue)
2714                                     {
2715                                         if (pixelValue != lastPixelValue)
2716                                             clientCache_.
2717                                                 putImageCodingLine
2718                                                 [codingLineLength++] = xCoord;
2719                                         unsigned int runLength =
2720                                             clientCache_.putImagePixel1Coder.
2721                                             decode(decodeBuffer);
2722                                         while (runLength--)
2723                                         {
2724                                             *nextDest |= destMask;
2725                                             destMask >>= 1;
2726                                             if (destMask == 0)
2727                                             {
2728                                                 destMask = 0x80;
2729                                                 nextDest++;
2730                                                 if (xCoord + 1 < width)
2731                                                     *nextDest = 0;
2732                                             }
2733                                             xCoord++;
2734                                         }
2735                                         pixelValue = 0;
2736                                         lastPixelValue = 1;
2737                                     }
2738                                     else
2739                                     {
2740                                         if (pixelValue != lastPixelValue)
2741                                             clientCache_.
2742                                                 putImageCodingLine
2743                                                 [codingLineLength++] = xCoord;
2744                                         unsigned int runLength =
2745                                             clientCache_.putImagePixel0Coder.
2746                                             decode(decodeBuffer);
2747                                         while (runLength--)
2748                                         {
2749                                             destMask >>= 1;
2750                                             if (destMask == 0)
2751                                             {
2752                                                 destMask = 0x80;
2753                                                 nextDest++;
2754                                                 if (xCoord + 1 < width)
2755                                                     *nextDest = 0;
2756                                             }
2757                                             xCoord++;
2758                                         }
2759                                         pixelValue = 1;
2760                                         lastPixelValue = 0;
2761                                     }
2762                                 }
2763                                 clientCache_.
2764                                     putImageCodingLine[codingLineLength++] =
2765                                     width;
2766                             }
2767                             else
2768                             {
2769                                 unsigned int lastX = 0;
2770                                 unsigned int nextReferenceIndex = 0;
2771 
2772                                 while (lastX < width)
2773                                 {
2774                                     ScanlineDiff diffCode =
2775                                         (ScanlineDiff) clientCache_.
2776                                         putImageDiffCoder.
2777                                         decode(decodeBuffer);
2778                                     switch (diffCode)
2779                                     {
2780                                     case SD_VERTICAL_0:
2781                                         {
2782                                             lastX =
2783                                                 clientCache_.
2784                                                 putImageCodingLine
2785                                                 [codingLineLength++] =
2786                                                 clientCache_.
2787                                                 putImageReferenceLine
2788                                                 [nextReferenceIndex++];
2789                                         }
2790                                         break;
2791                                     case SD_VERTICAL_PLUS_1:
2792                                         {
2793                                             lastX =
2794                                                 clientCache_.
2795                                                 putImageCodingLine
2796                                                 [codingLineLength++] =
2797                                                 clientCache_.
2798                                                 putImageReferenceLine
2799                                                 [nextReferenceIndex++] + 1;
2800                                         }
2801                                         break;
2802                                     case SD_VERTICAL_PLUS_2:
2803                                         {
2804                                             lastX =
2805                                                 clientCache_.
2806                                                 putImageCodingLine
2807                                                 [codingLineLength++] =
2808                                                 clientCache_.
2809                                                 putImageReferenceLine
2810                                                 [nextReferenceIndex++] + 2;
2811                                         }
2812                                         break;
2813                                     case SD_VERTICAL_MINUS_1:
2814                                         {
2815                                             lastX =
2816                                                 clientCache_.
2817                                                 putImageCodingLine
2818                                                 [codingLineLength++] =
2819                                                 clientCache_.
2820                                                 putImageReferenceLine
2821                                                 [nextReferenceIndex++] - 1;
2822                                         }
2823                                         break;
2824                                     case SD_VERTICAL_MINUS_2:
2825                                         {
2826                                             lastX =
2827                                                 clientCache_.
2828                                                 putImageCodingLine
2829                                                 [codingLineLength++] =
2830                                                 clientCache_.
2831                                                 putImageReferenceLine
2832                                                 [nextReferenceIndex++] - 2;
2833                                         }
2834                                         break;
2835                                     case SD_PASS:
2836                                         {
2837                                             nextReferenceIndex += 2;
2838                                         }
2839                                         break;
2840                                     case SD_HORIZONTAL:
2841                                         {
2842                                             unsigned int diff;
2843 
2844                                             if (codingLineLength & 1)
2845                                                 diff =
2846                                                     clientCache_.
2847                                                     putImagePixel0Coder.
2848                                                     decode(decodeBuffer);
2849                                             else
2850                                                 diff =
2851                                                     clientCache_.
2852                                                     putImagePixel1Coder.
2853                                                     decode(decodeBuffer);
2854                                             lastX += diff;
2855                                             lastX &= 0xffff;
2856                                             clientCache_.
2857                                                 putImageCodingLine
2858                                                 [codingLineLength++] = lastX;
2859                                             if (codingLineLength & 1)
2860                                                 diff =
2861                                                     clientCache_.
2862                                                     putImagePixel0Coder.
2863                                                     decode(decodeBuffer);
2864                                             else
2865                                                 diff =
2866                                                     clientCache_.
2867                                                     putImagePixel1Coder.
2868                                                     decode(decodeBuffer);
2869                                             lastX += diff;
2870                                             lastX &= 0xffff;
2871                                             clientCache_.
2872                                                 putImageCodingLine
2873                                                 [codingLineLength++] = lastX;
2874                                         }
2875                                     default:
2876                                         {
2877                                         }
2878                                     }
2879                                 }
2880                             }
2881 
2882                             clientCache_.
2883                                 putImageCodingLine[codingLineLength++] =
2884                                 width;
2885                             unsigned int pixelValue = 0;
2886                             unsigned int lastPixelChange = 0;
2887                             unsigned int *nextPixelChange =
2888                                 clientCache_.putImageCodingLine;
2889                             for (unsigned int xCoord = 0; xCoord < width;)
2890                             {
2891                                 unsigned int count =
2892                                     *nextPixelChange - lastPixelChange;
2893                                 lastPixelChange = *nextPixelChange++;
2894                                 for (; count; count--)
2895                                 {
2896                                     if (pixelValue)
2897                                         *nextDest |= destMask;
2898                                     destMask >>= 1;
2899                                     if (destMask == 0)
2900                                     {
2901                                         destMask = 0x80;
2902                                         nextDest++;
2903                                         if (xCoord + 1 < width)
2904                                             *nextDest = 0;
2905                                     }
2906                                     xCoord++;
2907                                 }
2908                                 if (pixelValue)
2909                                     pixelValue = 0;
2910                                 else
2911                                     pixelValue = 1;
2912                             }
2913 
2914                             unsigned int *tmp =
2915                                 clientCache_.putImageReferenceLine;
2916                             clientCache_.putImageReferenceLine =
2917                                 clientCache_.putImageCodingLine;
2918                             clientCache_.putImageCodingLine = tmp;
2919                         }
2920                         const unsigned char *end =
2921                             outputMessage + outputLength;
2922                         if ((imageByteOrder_ == 0) && (bitmapBitOrder_ == 0))
2923                         {
2924                             for (unsigned char *next = outputMessage + 24;
2925                                  next < end; next++)
2926                                 *next = REVERSED_BYTE[*next];
2927                         }
2928                         unsigned char *next =
2929                             outputMessage + 24 + widthInBytes;
2930                         const unsigned char *prev = outputMessage + 24;
2931 
2932                         for (; next < end;)
2933                             *next++ ^= *prev++;
2934                     }
2935                     else
2936                     {
2937                         // pixmap
2938                         if (outputMessage[21] == 8)
2939                         {
2940                             for (unsigned int i = 24; i < outputLength; i++)
2941                             {
2942                                 decodeBuffer.decodeCachedValue(cValue, 8,
2943                                                                clientCache_.
2944                                                                putImageByteCache,
2945                                                                4);
2946                                 *nextDest++ = cValue;
2947                             }
2948                         }
2949                         else
2950                         {
2951                             for (unsigned int i = 24; i < outputLength; i++)
2952                             {
2953                                 decodeBuffer.decodeValue(value, 8);
2954                                 *nextDest++ = (unsigned char) value;
2955                             }
2956                         }
2957                     }
2958                 }
2959                 break;
2960             case X_QueryBestSize:
2961                 {
2962                     outputLength = 12;
2963                     outputMessage = writeBuffer_.addMessage(outputLength);
2964                     decodeBuffer.decodeValue(value, 2);
2965                     outputMessage[1] = (unsigned char) value;
2966                     decodeBuffer.decodeCachedValue(value, 29,
2967                                                    clientCache_.drawableCache,
2968                                                    9);
2969                     PutULONG(value, outputMessage + 4, bigEndian_);
2970                     decodeBuffer.decodeValue(value, 16, 8);
2971                     PutUINT(value, outputMessage + 8, bigEndian_);
2972                     decodeBuffer.decodeValue(value, 16, 8);
2973                     PutUINT(value, outputMessage + 10, bigEndian_);
2974                     sequenceNumQueue_.push(clientCache_.
2975                                            lastRequestSequenceNum, opcode);
2976                 }
2977                 break;
2978             case X_QueryColors:
2979                 {
2980                     unsigned int numColors;
2981 
2982                     decodeBuffer.decodeValue(numColors, 16, 5);
2983                     outputLength = (numColors << 2) + 8;
2984                     outputMessage = writeBuffer_.addMessage(outputLength);
2985                     decodeBuffer.decodeCachedValue(value, 29,
2986                                                    clientCache_.colormapCache,
2987                                                    9);
2988                     PutULONG(value, outputMessage + 4, bigEndian_);
2989                     unsigned char *nextDest = outputMessage + 8;
2990                     unsigned int predictedPixel =
2991                         clientCache_.queryColorsLastPixel;
2992                     for (unsigned int i = 0; i < numColors; i++)
2993                     {
2994                         unsigned int pixel;
2995 
2996                         decodeBuffer.decodeValue(value, 1);
2997                         if (value)
2998                             pixel = predictedPixel;
2999                         else
3000                             decodeBuffer.decodeValue(pixel, 32, 9);
3001                         PutULONG(pixel, nextDest, bigEndian_);
3002                         if (i == 0)
3003                             clientCache_.queryColorsLastPixel = pixel;
3004                         predictedPixel = pixel + 1;
3005                         nextDest += 4;
3006                     }
3007                     sequenceNumQueue_.push(clientCache_.
3008                                            lastRequestSequenceNum, opcode);
3009                 }
3010                 break;
3011             case X_QueryExtension:
3012                 {
3013                     unsigned int nameLength;
3014 
3015                     decodeBuffer.decodeValue(nameLength, 16, 6);
3016                     outputLength = 8 + RoundUp4(nameLength);
3017                     outputMessage = writeBuffer_.addMessage(outputLength);
3018                     PutUINT(nameLength, outputMessage + 4, bigEndian_);
3019                     unsigned char *nextDest = outputMessage + 8;
3020 
3021                     for (unsigned int i = 0; i < nameLength; i++)
3022                     {
3023                         decodeBuffer.decodeValue(value, 8);
3024                         *nextDest++ = (unsigned char) value;
3025                     }
3026                     unsigned int hideExtension = 0;
3027 
3028                     if (!strncmp((char *) outputMessage + 8, "MIT-SHM", 7))
3029                     {
3030                         *logofs << "hiding MIT-SHM!";
3031                         hideExtension = 1;
3032                     }
3033                     sequenceNumQueue_.push(clientCache_.
3034                                            lastRequestSequenceNum, opcode,
3035                                            hideExtension);
3036                 }
3037                 break;
3038             case X_QueryFont:
3039                 {
3040                     outputLength = 8;
3041                     outputMessage = writeBuffer_.addMessage(outputLength);
3042                     decodeBuffer.decodeValue(value, 29, 5);
3043                     clientCache_.lastFont += value;
3044                     clientCache_.lastFont &= 0x1fffffff;
3045                     PutULONG(clientCache_.lastFont, outputMessage + 4,
3046                              bigEndian_);
3047                     sequenceNumQueue_.push(clientCache_.
3048                                            lastRequestSequenceNum, opcode);
3049                 }
3050                 break;
3051             case X_SetClipRectangles:
3052                 {
3053                     unsigned int numRectangles;
3054 
3055                     decodeBuffer.decodeValue(numRectangles, 13, 4);
3056                     outputLength = (numRectangles << 3) + 12;
3057                     outputMessage = writeBuffer_.addMessage(outputLength);
3058                     decodeBuffer.decodeValue(value, 2);
3059                     outputMessage[1] = (unsigned char) value;
3060                     decodeBuffer.decodeCachedValue(value, 29,
3061                                                    clientCache_.gcCache, 9);
3062                     PutULONG(value, outputMessage + 4, bigEndian_);
3063                     decodeBuffer.decodeCachedValue(value, 16,
3064                                                    clientCache_.
3065                                                    setClipRectanglesXCache,
3066                                                    8);
3067                     PutUINT(value, outputMessage + 8, bigEndian_);
3068                     decodeBuffer.decodeCachedValue(value, 16,
3069                                                    clientCache_.
3070                                                    setClipRectanglesYCache,
3071                                                    8);
3072                     PutUINT(value, outputMessage + 10, bigEndian_);
3073                     unsigned char *nextDest = outputMessage + 12;
3074 
3075                     for (unsigned int i = 0; i < numRectangles; i++)
3076                     {
3077                         for (unsigned int k = 0; k < 4; k++)
3078                         {
3079                             decodeBuffer.decodeCachedValue(value, 16,
3080                                                            *clientCache_.
3081                                                            setClipRectanglesGeomCache
3082                                                            [k], 8);
3083                             PutUINT(value, nextDest, bigEndian_);
3084                             nextDest += 2;
3085                         }
3086                     }
3087                 }
3088                 break;
3089             case X_SetDashes:
3090                 {
3091                     unsigned int numDashes;
3092 
3093                     decodeBuffer.decodeCachedValue(numDashes, 16,
3094                                                    clientCache_.
3095                                                    setDashesLengthCache, 5);
3096                     outputLength = 12 + RoundUp4(numDashes);
3097                     outputMessage = writeBuffer_.addMessage(outputLength);
3098                     PutUINT(numDashes, outputMessage + 10, bigEndian_);
3099                     decodeBuffer.decodeCachedValue(value, 29,
3100                                                    clientCache_.gcCache, 9);
3101                     PutULONG(value, outputMessage + 4, bigEndian_);
3102                     decodeBuffer.decodeCachedValue(value, 16,
3103                                                    clientCache_.
3104                                                    setDashesOffsetCache, 5);
3105                     PutUINT(value, outputMessage + 8, bigEndian_);
3106                     unsigned char *nextDest = outputMessage + 12;
3107 
3108                     for (unsigned int i = 0; i < numDashes; i++)
3109                     {
3110                         decodeBuffer.decodeCachedValue(cValue, 8,
3111                                                        clientCache_.
3112                                                        setDashesDashCache_[i &
3113                                                                            1],
3114                                                        5);
3115                         *nextDest++ = cValue;
3116                     }
3117                 }
3118                 break;
3119             case X_SetSelectionOwner:
3120                 {
3121                     outputLength = 16;
3122                     outputMessage = writeBuffer_.addMessage(outputLength);
3123                     decodeBuffer.decodeCachedValue(value, 29,
3124                                                    clientCache_.
3125                                                    setSelectionOwnerCache, 9);
3126                     PutULONG(value, outputMessage + 4, bigEndian_);
3127                     decodeBuffer.decodeCachedValue(value, 29,
3128                                                    clientCache_.
3129                                                    getSelectionOwnerSelectionCache,
3130                                                    9);
3131                     PutULONG(value, outputMessage + 8, bigEndian_);
3132                     decodeBuffer.decodeCachedValue(value, 32,
3133                                                    clientCache_.
3134                                                    setSelectionOwnerTimestampCache,
3135                                                    9);
3136                     PutULONG(value, outputMessage + 12, bigEndian_);
3137                 }
3138                 break;
3139             case X_TranslateCoords:
3140                 {
3141                     outputLength = 16;
3142                     outputMessage = writeBuffer_.addMessage(outputLength);
3143                     decodeBuffer.decodeCachedValue(value, 29,
3144                                                    clientCache_.
3145                                                    translateCoordsSrcCache,
3146                                                    9);
3147                     PutULONG(value, outputMessage + 4, bigEndian_);
3148                     decodeBuffer.decodeCachedValue(value, 29,
3149                                                    clientCache_.
3150                                                    translateCoordsDestCache,
3151                                                    9);
3152                     PutULONG(value, outputMessage + 8, bigEndian_);
3153                     decodeBuffer.decodeCachedValue(value, 16,
3154                                                    clientCache_.
3155                                                    translateCoordsXCache, 8);
3156                     PutUINT(value, outputMessage + 12, bigEndian_);
3157                     decodeBuffer.decodeCachedValue(value, 16,
3158                                                    clientCache_.
3159                                                    translateCoordsYCache, 8);
3160                     PutUINT(value, outputMessage + 14, bigEndian_);
3161                     sequenceNumQueue_.push(clientCache_.
3162                                            lastRequestSequenceNum, opcode);
3163                 }
3164                 break;
3165             default:
3166                 {
3167                     unsigned int secondByte;
3168 
3169                     decodeBuffer.decodeValue(secondByte, 8);
3170                     decodeBuffer.decodeValue(outputLength, 16, 8);
3171                     outputLength <<= 2;
3172                     outputMessage = writeBuffer_.addMessage(outputLength);
3173                     outputMessage[1] = (unsigned char) secondByte;
3174                     unsigned char *nextDest = outputMessage + 4;
3175 
3176                     for (unsigned int i = 4; i < outputLength; i++)
3177                     {
3178                         unsigned int nextByte;
3179 
3180                         decodeBuffer.decodeValue(nextByte, 8);
3181                         *nextDest++ = (unsigned char) nextByte;
3182                     }
3183                 }
3184             }
3185             *outputMessage = (unsigned char) opcode;
3186             PutUINT(outputLength >> 2, outputMessage + 2, bigEndian_);
3187         }
3188     }
3189 
3190     if (WriteAll(fd_, writeBuffer_.getData(), writeBuffer_.getLength()) < 0)
3191         return 0;
3192     else
3193         return 1;
3194 }
3195 
3196 
setBigEndian(int flag)3197 void ServerChannel:: setBigEndian(int flag)
3198 {
3199     bigEndian_ = flag;
3200     readBuffer_.setBigEndian(flag);
3201 }
3202 
3203 
encodeCharInfo_(const unsigned char * nextSrc,EncodeBuffer & encodeBuffer)3204 void ServerChannel::encodeCharInfo_(const unsigned char *nextSrc,
3205                                     EncodeBuffer & encodeBuffer)
3206 {
3207     unsigned int value = GetUINT(nextSrc, bigEndian_) |
3208         (GetUINT(nextSrc + 10, bigEndian_) << 16);
3209     encodeBuffer.encodeCachedValue(value, 32,
3210                                    *serverCache_.queryFontCharInfoCache[0],
3211                                    6);
3212     nextSrc += 2;
3213     for (unsigned int i = 1; i < 5; i++)
3214     {
3215         unsigned int value = GetUINT(nextSrc, bigEndian_);
3216 
3217         nextSrc += 2;
3218         encodeBuffer.encodeCachedValue(value, 16,
3219                                        *serverCache_.
3220                                        queryFontCharInfoCache[i], 6);
3221     }
3222 }
3223