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