quota update partial NTGetUserQuota support
[obnox/wireshark/wip.git] / packet-x11.c
1 /* packet-x11.c
2  * Routines for X11 dissection
3  * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
4  *
5  * $Id: packet-x11.c,v 1.29 2002/01/24 09:20:52 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 1998 Gerald Combs
10  *
11  * Copied from README.developer
12  * 
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  * 
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  * 
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26  */
27
28 /* TODO (in no particular order):
29  *
30  * - keep track of Atom creation by server to be able to display non predefined atoms
31  * - Idem for keysym <-> keycode ???
32  * - Idem for fonts 
33  * - Subtree the request ids (that is x11.create-window.window and x11.change-window.window should be 
34  *   distinct), and add hidden fields (so we still have x11.window).
35  * - add hidden fields so we can have x11.circulate-window in addition to x11.opcode == 13
36  * - add hidden fields so we have x11.listOfStuff.length
37  * - use a faster scheme that linear list searching for the opcode.
38  * - correct display of unicode chars.
39  * - Not everything is homogeneous, in particular the handling of items in list is a total mess.
40  */
41
42 /* By the way, I wrote a program to generate every request and test
43  * that stuff. If you're interested, you can get it at
44  * http://tronche.com/gui/x/
45  */
46
47 #ifdef HAVE_CONFIG_H
48 # include "config.h"
49 #endif
50
51 #include <assert.h>
52 #include <ctype.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55
56 #ifdef HAVE_SYS_TYPES_H
57 # include <sys/types.h>
58 #endif
59
60 #include <string.h>
61 #include <glib.h>
62 #include <epan/packet.h>
63
64 #define cVALS(x) (const value_string*)(x)
65
66 /* Initialize the protocol and registered fields */
67 static int proto_x11 = -1;
68
69 #include "x11-declarations.h"
70
71 /* Initialize the subtree pointers */
72 static gint ett_x11 = -1;
73 static gint ett_x11_request = -1;
74
75 static dissector_handle_t data_handle;
76
77 #define TCP_PORT_X11                    6000
78 #define TCP_PORT_X11_2                  6001
79 #define TCP_PORT_X11_3                  6002
80
81 /************************************************************************
82  ***                                                                  ***
83  ***         E N U M   T A B L E S   D E F I N I T I O N S            ***
84  ***                                                                  ***
85  ************************************************************************/
86
87 static const value_string access_mode_vals[] = {
88       { 0, "Disable" },
89       { 1, "Enable" },
90       { 0, NULL }
91 };
92
93 static const value_string all_temporary_vals[] = {
94       { 0, "AllTemporary" },
95       { 0, NULL }
96 };
97
98 static const value_string alloc_vals[] = {
99       { 0, "None" },
100       { 1, "All" },
101       { 0, NULL }
102 };
103
104 static const value_string allow_events_mode_vals[] = {
105       { 0, "AsyncPointer" },
106       { 1, "SyncPointer" },
107       { 2, "ReplayPointer" },
108       { 3, "AsyncKeyboard" },
109       { 4, "SyncKeyboard" },
110       { 5, "ReplayKeyboard" },
111       { 6, "AsyncBoth" },
112       { 7, "SyncBoth" },
113       { 0, NULL }
114 };
115
116 static const value_string arc_mode_vals[] = {
117       { 0, "Chord" },
118       { 1, "PieSlice" },
119       { 0, NULL }
120 };
121
122 static const char *atom_predefined_interpretation[] = {
123       "<error>",
124       "PRIMARY",
125       "SECONDARY",
126       "ARC",
127       "ATOM",
128       "BITMAP",
129       "CARDINAL",
130       "COLORMAP",
131       "CURSOR",
132       "CUT_BUFFER0",
133       "CUT_BUFFER1",
134       "CUT_BUFFER2",
135       "CUT_BUFFER3",
136       "CUT_BUFFER4",
137       "CUT_BUFFER5",
138       "CUT_BUFFER6",
139       "CUT_BUFFER7",
140       "DRAWABLE",
141       "FONT",
142       "INTEGER",
143       "PIXMAP",
144       "POINT",
145       "RECTANGLE",
146       "RESOURCE_MANAGER",
147       "RGB_COLOR_MAP",
148       "RGB_BEST_MAP",
149       "RGB_BLUE_MAP",
150       "RGB_DEFAULT_MAP",
151       "RGB_GRAY_MAP",
152       "RGB_GREEN_MAP",
153       "RGB_RED_MAP",
154       "STRING",
155       "VISUALID",
156       "WINDOW",
157       "WM_COMMAND",
158       "WM_HINTS",
159       "WM_CLIENT_MACHINE",
160       "WM_ICON_NAME",
161       "WM_ICON_SIZE",
162       "WM_NAME",
163       "WM_NORMAL_HINTS",
164       "WM_SIZE_HINTS",
165       "WM_ZOOM_HINTS",
166       "MIN_SPACE",
167       "NORM_SPACE",
168       "MAX_SPACE",
169       "END_SPACE",
170       "SUPERSCRIPT_X",
171       "SUPERSCRIPT_Y",
172       "SUBSCRIPT_X",
173       "SUBSCRIPT_Y",
174       "UNDERLINE_POSITION",
175       "UNDERLINE_THICKNESS",
176       "STRIKEOUT_ASCENT",
177       "STRIKEOUT_DESCENT",
178       "ITALIC_ANGLE",
179       "X_HEIGHT",
180       "QUAD_WIDTH",
181       "WEIGHT",
182       "POINT_SIZE",
183       "RESOLUTION",
184       "COPYRIGHT",
185       "NOTICE",
186       "FONT_NAME",
187       "FAMILY_NAME",
188       "FULL_NAME",
189       "CAP_HEIGHT",
190       "WM_CLASS",
191       "WM_TRANSIENT_FOR",
192 };
193
194 static const value_string auto_repeat_mode_vals[] = {
195       { 0, "Off" },
196       { 1, "On" },
197       { 2, "Default" },
198       { 0, NULL }
199 };
200
201 static const value_string background_pixmap_vals[] = { 
202       { 0, "None" },
203       { 1, "ParentRelative" },
204       { 0, NULL }
205 };
206
207 static const value_string backing_store_vals[] = {
208       { 0, "NotUseful" },
209       { 1, "WhenMapped" },
210       { 2, "Always" },
211       { 0, NULL }
212 };
213
214 static const value_string border_pixmap_vals[] = { 
215       { 0, "CopyFromParent" },
216       { 0, NULL }
217 };
218
219 static const value_string button_vals[] = {
220       { 0x8000, "AnyButton" },
221       { 0, NULL }
222 };
223
224 static const value_string cap_style_vals[] = {
225       { 0, "NotLast" },
226       { 1, "Butt" },
227       { 2, "Round" },
228       { 3, "Projecting" },
229       { 0, NULL }
230 };
231
232 static const value_string class_vals[] = {
233       { 0, "Cursor" },
234       { 1, "Tile" },
235       { 2, "Stipple" },
236       { 0, NULL }
237 };
238
239 static const value_string close_down_mode_vals[] = {
240       { 0, "Destroy" },
241       { 1, "RetainPermanent" },
242       { 2, "RetainTemporary" },
243       { 0, NULL }
244 };
245
246 static const value_string coordinate_mode_vals[] = {
247       { 0, "Origin" },
248       { 1, "Previous" },
249       { 0, NULL }
250 };
251
252 static const value_string direction_vals[] = { 
253       { 0, "RaiseLowest" },
254       { 1, "LowerHighest" },
255       { 0, NULL }
256 };
257
258 static const value_string family_vals[] = {
259       { 0, "Internet" },
260       { 1, "DECnet" },
261       { 2, "Chaos" },
262       { 0, NULL }
263 };
264
265 static const value_string fill_rule_vals[] = {
266       { 0, "EvenOdd" },
267       { 1, "Winding" },
268       { 0, NULL }
269 };
270
271 static const value_string fill_style_vals[] = {
272       { 0, "Solid" },
273       { 1, "Tiled" },
274       { 2, "Stippled" },
275       { 3, "OpaqueStippled" },
276       { 0, NULL }
277 };
278
279 static const value_string focus_vals[] = {
280       { 0, "None" },
281       { 1, "PointerRoot" },
282       { 0, NULL }
283 };
284
285 static const value_string function_vals[] = {
286       {  0, "Clear" },
287       {  1, "And" },
288       {  2, "AndReverse" },
289       {  3, "Copy" },
290       {  4, "AndInverted" },
291       {  5, "NoOp" },
292       {  6, "Xor" },
293       {  7, "Or" },
294       {  8, "Nor" },
295       {  9, "Equiv" },
296       { 10, "Invert" },
297       { 11, "OrReverse" },
298       { 12, "CopyInverted" },
299       { 13, "OrInverted" },
300       { 14, "Nand" },
301       { 15, "Set" },  
302       {  0, NULL }
303 };
304
305 static const value_string gravity_vals[] = {
306       {  1, "NorthWest" },
307       {  2, "North" },
308       {  3, "NorthEast" },
309       {  4, "West" },
310       {  5, "Center" },
311       {  6, "East" },
312       {  7, "SouthWest" },
313       {  8, "South" },
314       {  9, "SouthEast" },
315       { 10, "Static" },
316       {  0, NULL }
317 };
318
319 static const value_string image_format_vals[] = {
320       { 0, "Bitmap" },
321       { 1, "XYPixmap" },
322       { 2, "ZPixmap" },
323       { 0, NULL }
324 };
325
326 static const value_string image_pixmap_format_vals[] = {
327       { 1, "XYPixmap" },
328       { 2, "ZPixmap" },
329       { 0, NULL }
330 };
331
332 static const value_string join_style_vals[] = {
333       { 0, "Miter" },
334       { 1, "Round" },
335       { 2, "Bevel" },
336       { 0, NULL }
337 };
338
339 static const value_string key_vals[] = {
340       { 0, "AnyKey" },
341       { 0, NULL }
342 };
343
344 #include "packet-x11-keysym.h"
345
346 static const value_string line_style_vals[] = {
347       { 0, "Solid" },
348       { 1, "OnOffDash" },
349       { 2, "DoubleDash" },
350       { 0, NULL }
351 };
352
353 static const value_string mode_vals[] = {
354       { 0, "Replace" },
355       { 1, "Prepend" },
356       { 2, "Append" },
357       { 0, NULL }
358 };
359
360 static const value_string on_off_vals[] = {
361       { 0, "Off" },
362       { 1, "On" },
363       { 0, NULL }
364 };
365
366 static const value_string opcode_vals[] = {
367       {   1, "CreateWindow" },
368       {   2, "ChangeWindowAttributes" },
369       {   3, "GetWindowAttributes" }, 
370       {   4, "DestroyWindow" },
371       {   5, "DestroySubwindows" },
372       {   6, "ChangeSaveSet" },
373       {   7, "ReparentWindow" },
374       {   8, "MapWindow" },
375       {   9, "MapSubwindows" },
376       {  10, "UnmapWindow" },
377       {  11, "UnmapSubwindows" },
378       {  12, "ConfigureWindow" },
379       {  13, "CirculateWindow" },
380       {  14, "GetGeometry" },
381       {  15, "QueryTree" },
382       {  16, "InternAtom" },
383       {  17, "GetAtomName" },
384       {  18, "ChangeProperty" },
385       {  19, "DeleteProperty" },
386       {  20, "GetProperty" },
387       {  21, "ListProperties" },
388       {  22, "SetSelectionOwner" },
389       {  23, "GetSelectionOwner" },
390       {  24, "ConvertSelection" },
391
392       {  26, "GrabPointer" },
393       {  27, "UngrabPointer" },
394       {  28, "GrabButton" },
395       {  29, "UngrabButton" },
396       {  30, "ChangeActivePointerGrab" },
397       {  31, "GrabKeyboard" },
398       {  32, "UngrabKeyboard" },
399       {  33, "GrabKey" },
400       {  34, "UngrabKey" },
401       {  35, "AllowEvents" },
402       {  36, "GrabServer" },
403       {  37, "UngrabServer" },
404       {  38, "QueryPointer" },
405       {  39, "GetMotionEvents" },
406       {  40, "TranslateCoordinates" },
407       {  41, "WarpPointer" },
408       {  42, "SetInputFocus" },
409       {  43, "GetInputFocus" },
410       {  44, "QueryKeymap" },
411       {  45, "OpenFont" },
412       {  46, "CloseFont" },
413       {  47, "QueryFont" },
414       {  48, "QueryTextExtents" },
415       {  49, "ListFonts" },
416       {  50, "ListFontsWithInfo" },
417       {  51, "SetFontPath" },
418       {  52, "GetFontPath" },
419       {  53, "CreatePixmap" },
420       {  54, "FreePixmap" },
421       {  55, "CreateGC" },
422       {  56, "ChangeGC" },
423       {  57, "CopyGC" },
424       {  58, "SetDashes" },
425       {  59, "SetClipRectangles" },
426       {  60, "FreeGC" },
427       {  61, "ClearArea" },
428       {  62, "CopyArea" },
429       {  63, "CopyPlane" },
430       {  64, "PolyPoint" },
431       {  65, "PolyLine" },
432       {  66, "PolySegment" },
433       {  67, "PolyRectangle" },
434       {  68, "PolyArc" },
435       {  69, "FillPoly" },
436       {  70, "PolyFillRectangle" },
437       {  71, "PolyFillArc" },
438       {  72, "PutImage" },
439       {  73, "GetImage" },
440       {  74, "PolyText8" },
441       {  75, "PolyText16" },
442       {  76, "ImageText8" },
443       {  77, "ImageText16" },
444       {  78, "CreateColormap" },
445       {  79, "FreeColormap" },
446       {  80, "CopyColormapAndFree" },
447       {  81, "InstallColormap" },
448       {  82, "UninstallColormap" },
449       {  83, "ListInstalledColormaps" },
450       {  84, "AllocColor" },
451       {  85, "AllocNamedColor" },
452       {  86, "AllocColorCells" },
453       {  87, "AllocColorPlanes" },
454       {  88, "FreeColors" },
455       {  89, "StoreColors" },
456       {  90, "StoreNamedColor" },
457       {  91, "QueryColors" },
458       {  92, "LookupColor" },
459       {  93, "CreateCursor" },
460       {  94, "CreateGlyphCursor" },
461       {  95, "FreeCursor" },
462       {  96, "RecolorCursor" },
463       {  97, "QueryBestSize" },
464       {  98, "QueryExtension" },
465       {  99, "ListExtensions" },
466       { 100, "ChangeKeyboardMapping" },
467       { 101, "GetKeyboardMapping" },
468       { 102, "ChangeKeyboardControl" },
469       { 103, "GetKeyboardControl" },
470       { 104, "Bell" },
471       { 105, "ChangePointerControl" },
472       { 106, "GetPointerControl" },
473       { 107, "SetScreenSaver" },
474       { 108, "GetScreenSaver" },
475       { 109, "ChangeHosts" },
476       { 110, "ListHosts" },
477       { 111, "SetAccessControl" },
478       { 112, "SetCloseDownMode" },
479       { 113, "KillClient" },
480       { 114, "RotateProperties" },
481       { 115, "ForceScreenSaver" },
482       { 116, "SetPointerMapping" },
483       { 117, "GetPointerMapping" },
484       { 118, "SetModifierMapping" },
485       { 119, "GetModifierMapping" },
486       { 127, "NoOperation" },
487       { 0, NULL }
488 };
489
490 static const value_string ordering_vals[] = {
491       { 0, "UnSorted" },
492       { 1, "YSorted" },
493       { 2, "YXSorted" },
494       { 3, "YXBanded" },
495       { 0, NULL }
496 };
497
498 static const value_string plane_mask_vals[] = {
499       { 0xFFFFFFFF, "AllPlanes" },
500       { 0, NULL }
501 };
502
503 static const value_string pointer_keyboard_mode_vals[] = {
504       { 0, "Synchronous" },
505       { 1, "Asynchronous" },
506       { 0, NULL }
507 };
508
509 static const value_string revert_to_vals[] = {
510       { 0, "None" },
511       { 1, "PointerRoot" },
512       { 2, "Parent" },
513       { 0, NULL }
514 };
515
516 static const value_string insert_delete_vals[] = {
517       { 0, "Insert" },
518       { 1, "Delete" },
519       { 0, NULL }
520 };
521
522 static const value_string screen_saver_mode_vals[] = {
523       { 0, "Reset" },
524       { 1, "Activate" },
525       { 0, NULL }
526 };
527
528 static const value_string shape_vals[] = {
529       { 0, "Complex" },
530       { 1, "Nonconvex" },
531       { 2, "Convex" },
532       { 0, NULL }
533 };
534
535 static const value_string stack_mode_vals[] = {
536       { 0, "Above" },
537       { 1, "Below" },
538       { 2, "TopIf" },
539       { 3, "BottomIf" },
540       { 4, "Opposite" },
541       { 0, NULL }
542 };
543
544 static const value_string subwindow_mode_vals[] = {
545       { 0, "ClipByChildren" },
546       { 1, "IncludeInferiors" },
547       { 0, NULL }
548 };
549
550 static const value_string window_class_vals[] = {
551       { 0, "CopyFromParent" },
552       { 1, "InputOutput" },
553       { 2, "InputOnly" },
554       { 0, NULL }
555 };
556
557 static const value_string yes_no_default_vals[] = {
558       { 0, "No" },
559       { 1, "Yes" },
560       { 2, "Default" },
561       { 0, NULL }
562 };
563
564 static const value_string zero_is_any_property_type_vals[] = {
565       { 0, "AnyPropertyType" },
566       { 0, NULL }
567 };
568
569 static const value_string zero_is_none_vals[] = {
570       { 0, "None" },
571       { 0, NULL }
572 };
573
574 /************************************************************************
575  ***                                                                  ***
576  ***         G L O B A L   V A R I A B L E S   ( A R G H H ! )        ***
577  ***                                                                  ***
578  ************************************************************************/
579
580 static int cur_offset;         /* The current offset in the frame */
581 static int next_offset = 0; /* Offset of the next request in the frame */    
582 static gboolean little_endian = TRUE;
583 static proto_tree *t = NULL;
584
585 static struct maskStruct {
586       guint32 _value;
587       int _offset;
588       int _zone;
589       proto_tree *_tree;
590 } lastMask = { 0, 0, 0, NULL };
591
592 /************************************************************************
593  ***                                                                  ***
594  ***           F I E L D   D E C O D I N G   M A C R O S              ***
595  ***                                                                  ***
596  ************************************************************************/
597
598 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
599 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
600 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
601
602 #define FIELD8(name)  (field8(tvb, hf_x11_##name))
603 #define FIELD16(name) (field16(tvb, hf_x11_##name))
604 #define FIELD32(name) (field32(tvb, hf_x11_##name))
605
606 #define BITFIELD(TYPE, position, name) {\
607   if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
608        int unused;\
609        int save = cur_offset;\
610        proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
611                            lastMask._zone, little_endian); \
612        TYPE(name);\
613        unused = save + 4 - cur_offset;\
614        if (unused)\
615            proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
616        cur_offset = save + 4;\
617  }\
618 }
619
620 #define FLAG(position, name) {\
621   if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
622        proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
623
624 #define ATOM(name)     { atom(tvb, t, hf_x11_##name); }
625 #define BITGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Forget"); }
626 #define BITMASK8(name) { bitmask(tvb, hf_x11_##name##_mask, 1); }
627 #define BITMASK16(name) { bitmask(tvb, hf_x11_##name##_mask, 2); }
628 #define BITMASK32(name)  { bitmask(tvb, hf_x11_##name##_mask, 4); }
629 #define BOOL(name)     (add_boolean(tvb, #name, hf_x11_##name))
630 #define BUTTON(name)   { FIELD8(name); }
631 #define CARD8(name)    { FIELD8(name); }
632 #define CARD16(name)   (FIELD16(name))
633 #define CARD32(name)   (FIELD32(name))
634 #define COLOR_FLAGS(name) { colorFlags(tvb, t); }
635 #define COLORMAP(name) { FIELD32(name); }
636 #define CURSOR(name)   { FIELD32(name); }
637 #define DRAWABLE(name) { FIELD32(name); }
638 #define ENUM8(name)    { FIELD8(name); }
639 #define ENUM16(name)   { FIELD16(name); }
640 #define FONT(name)     { FIELD32(name); }
641 #define FONTABLE(name) { FIELD32(name); }
642 #define GCONTEXT(name) { FIELD32(name); }
643 #define INT8(name)     { FIELD8(name); }
644 #define INT16(name)    { FIELD16(name); }
645 #define KEYCODE(name)  { FIELD8(name); }
646 #define LISTofARC(name) { listOfArc(tvb, hf_x11_##name, (next_offset - cur_offset) / 12); }
647 #define LISTofATOM(name, length) { listOfAtom(tvb, hf_x11_##name, (length) / 4); }
648 #define LISTofBYTE(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
649 #define LISTofCARD8(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
650 #define LISTofCARD32(name, length) { listOfCard32(tvb, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
651 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, hf_x11_##name, (length) / 12); }
652 #define LISTofKEYCODE(name, length) { listOfKeycode(tvb, hf_x11_##name, (length)); }
653 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
654       listOfKeysyms(tvb, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
655 #define LISTofPOINT(name, length) { listOfPoint(tvb, hf_x11_##name, (length) / 4); }
656 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
657 #define LISTofSEGMENT(name) { listOfSegment(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
658 #define LISTofSTRING8(name, length) { listOfString8(tvb, hf_x11_##name, hf_x11_##name##_string, (length)); }
659 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, hf_x11_##name, FALSE); }
660 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, hf_x11_##name, TRUE); }
661 #define OPCODE()       { opcode = FIELD8(opcode); }
662 #define PIXMAP(name)   { FIELD32(name); }
663 #define REQUEST_LENGTH() (requestLength(tvb))
664 #define SETofEVENT(name) { setOfEvent(tvb); }
665 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb);}
666 #define SETofKEYMASK(name) { setOfKeyMask(tvb); }
667 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb); }
668 #define STRING8(name, length)  { string8(tvb, #name, hf_x11_##name, length); }
669 #define STRING16(name, length)  { string16(tvb, hf_x11_##name, hf_x11_##name##_bytes, length); }
670 #define TIMESTAMP(name){ timestamp(tvb, #name, hf_x11_##name); }
671 #define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset,  x, little_endian); p += x; }
672 #define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset,  x, little_endian); cur_offset += x; }
673 #define PAD()          { if (next_offset - cur_offset > 0) proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, next_offset - cur_offset, little_endian); cur_offset = next_offset; }
674 #define WINDOW(name)   { FIELD32(name); }
675 #define WINGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Unmap"); }
676
677 #define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
678     proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
679                                v ? "" : " (CopyFromParent)"); cur_offset += 4; }
680
681 /************************************************************************
682  ***                                                                  ***
683  ***                  D E C O D I N G   F I E L D S                   ***
684  ***                                                                  ***
685  ************************************************************************/
686
687 static void atom(tvbuff_t *tvb, proto_tree *t, int hf)
688 {
689       const char *interpretation = NULL;
690
691       guint32 v = VALUE32(tvb, cur_offset);
692       if (v >= 1 && v < array_length(atom_predefined_interpretation))
693             interpretation = atom_predefined_interpretation[v];
694       else if (v)
695             interpretation = "Not a predefined atom";
696       else {
697             header_field_info *hfi = proto_registrar_get_nth(hf);
698             if (hfi -> strings)
699                   interpretation = match_strval(v, cVALS(hfi -> strings));
700       }
701       if (!interpretation) interpretation = "error in Xlib client program ?";
702       proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %u (%s)", 
703                                  proto_registrar_get_nth(hf) -> name, v, interpretation);
704       cur_offset += 4;
705 }
706
707 static void bitmask(tvbuff_t *tvb, int hf, int size)
708 {
709       lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
710       lastMask._offset = cur_offset;
711       lastMask._zone = size;
712       lastMask._tree = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
713       cur_offset += size; 
714 }
715
716 static guint32 add_boolean(tvbuff_t *tvb, const char *nameAsChar, int hf)
717 {
718       guint32 v = VALUE8(tvb, cur_offset);
719       proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
720       cur_offset += 1;
721       return v;
722 }
723
724 static void colorFlags(tvbuff_t *tvb, proto_tree *t)
725 {
726       unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
727       proto_tree *tt;
728       
729       if (do_red_green_blue) {
730             int sep = FALSE;
731             char buffer[512];
732             char *bp = buffer + sprintf(buffer, "flags: ");
733
734             if (do_red_green_blue & 0x1) {
735                   bp += sprintf(bp, "DoRed");
736                   sep = TRUE;
737             }
738
739             if (do_red_green_blue & 0x2) {
740                   if (sep) bp += sprintf(bp, " | ");
741                   bp += sprintf(bp, "DoGreen");
742                   sep = TRUE;
743             }
744
745             if (do_red_green_blue & 0x4) {
746                   if (sep) bp += sprintf(bp, " | ");
747                   bp += sprintf(bp, "DoBlue");
748                   sep = TRUE;
749             }
750
751             if (do_red_green_blue & 0xf8) {
752                   if (sep) bp += sprintf(bp, " + ");
753                   sprintf(bp, "trash");
754             }
755
756             tt = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
757                                             "%s", buffer);
758             if (do_red_green_blue & 0x1)
759                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1, 
760                                          do_red_green_blue & 0x1);
761             if (do_red_green_blue & 0x2)
762                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1, 
763                                          do_red_green_blue & 0x2);
764             if (do_red_green_blue & 0x4)
765                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1, 
766                                          do_red_green_blue & 0x4);
767             if (do_red_green_blue & 0xf8)
768                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1, 
769                                          do_red_green_blue & 0xf8);
770       } else
771             proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
772                                        "flags: none");
773       cur_offset++;
774 }
775
776 static void gravity(tvbuff_t *tvb, const char *nameAsChar, int hf, const char *nullInterpretation)
777 {
778       guint8 v = VALUE8(tvb, cur_offset);
779       if (!v)
780             proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar, 
781                                        nullInterpretation);
782       else
783             proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
784       cur_offset += 1;
785 }
786
787 static void listOfArc(tvbuff_t *tvb, int hf, int length)
788 {
789       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
790       while(length--) {
791             gint16 x = VALUE16(tvb, cur_offset);
792             gint16 y = VALUE16(tvb, cur_offset + 2);
793             guint16 width = VALUE16(tvb, cur_offset + 4);
794             guint16 height = VALUE16(tvb, cur_offset + 6);
795             gint16 angle1 = VALUE16(tvb, cur_offset + 8);
796             gint16 angle2 = VALUE16(tvb, cur_offset + 10);
797
798             proto_tree *ttt = proto_tree_add_none_format(tt, hf_x11_arc, tvb, cur_offset, 12, 
799                                                              "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
800                                                              width, height, x, y, angle1, angle2,
801                                                              angle1 / 64.0, angle2 / 64.0);
802             proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
803             proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
804             proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
805             proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
806             proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
807             proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
808       }
809 }
810
811 static void listOfAtom(tvbuff_t *tvb, int hf, int length)
812 {
813       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
814       while(length--) {
815             if (cur_offset + 4 > next_offset) {
816                 /* List runs past end of message. */
817                 return;
818             }
819             atom(tvb, tt, hf_x11_properties_item);
820       }
821 }
822
823 static void listOfByte(tvbuff_t *tvb, int hf, int length)
824 {
825       if (cur_offset + length > next_offset) {
826             /* List runs past end of message. */
827             length = next_offset -  cur_offset;
828       }
829       if (length <= 0) length = 1;
830       proto_tree_add_item(t, hf, tvb, cur_offset, length, little_endian);
831       cur_offset += length;
832 }
833
834 static void listOfCard32(tvbuff_t *tvb, int hf, int hf_item, int length)
835 {
836       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
837       while(length--) {
838             if (cur_offset + 4 > next_offset) {
839                 /* List runs past end of message. */
840                 return;
841             }
842             proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
843             cur_offset += 4;
844       }
845 }
846
847 static void listOfColorItem(tvbuff_t *tvb, int hf, int length)
848 {
849       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
850       while(length--) {
851             proto_tree *ttt;
852             unsigned do_red_green_blue;
853             guint16 red, green, blue;
854             char buffer[1024];
855             char *bp;
856             const char *sep;
857
858             if (cur_offset + 12 > next_offset) {
859                 /* List runs past end of message. */
860                 return;
861             }
862             red = VALUE16(tvb, cur_offset + 4);
863             green = VALUE16(tvb, cur_offset + 6);
864             blue = VALUE16(tvb, cur_offset + 8);
865             do_red_green_blue = VALUE8(tvb, cur_offset + 10);
866
867             bp = buffer + sprintf(buffer, "colorItem: ");
868             sep = "";
869             if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
870             if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
871             if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
872
873             ttt = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
874             proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
875             proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
876             proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
877             proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
878             colorFlags(tvb, ttt);
879             proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
880       }
881 }
882
883 static GTree *keysymTable = NULL;
884
885 static gint compareGuint32(gconstpointer a, gconstpointer b)
886 {
887       return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
888 }
889
890 static const char *keysymString(guint32 v)
891 {
892       gpointer res;
893       if (!keysymTable) {
894
895             /* This table is so big that we built it only if necessary */
896
897             const value_string *p = keysym_vals_source;
898             keysymTable = g_tree_new(compareGuint32);
899             for(; p -> strptr; p++)
900                   g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
901       }
902       res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
903       return res ? res : "Unknown";
904 }
905
906 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
907
908 static void listOfKeycode(tvbuff_t *tvb, int hf, int length)
909 {
910       char buffer[1024];
911       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
912
913       while(length--) {
914             char *bp = buffer;
915             const char **m;
916             int i;
917
918             if (cur_offset + 8 > next_offset) {
919                 /* List runs past end of message. */
920                 return;
921             }
922             for(i = 8, m = modifiers; i; i--, m++) {
923                   u_char c = tvb_get_guint8(tvb, cur_offset);
924                   cur_offset++;
925                   if (c) bp += sprintf(bp, "  %s=%d", *m, c);
926             }
927
928             proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, cur_offset - 8, 8, tvb_get_ptr(tvb, cur_offset - 8, 8),  "item: %s", buffer);
929       }
930 }
931
932 static void listOfKeysyms(tvbuff_t *tvb, int hf, int hf_item, int keycode_count, int keysyms_per_keycode)
933 {
934       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
935       proto_tree *ttt;
936       int i;
937       char buffer[128];
938       char *bp;
939
940       while(keycode_count--) {
941             if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
942                 /* List runs past end of message. */
943                 return;
944             }
945             bp = buffer + sprintf(buffer, "keysyms:");
946             for(i = 0; i < keysyms_per_keycode; i++) {
947                   bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
948             }
949             *bp = '\0';
950             ttt = proto_tree_add_none_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
951                                                  "%s", buffer);
952             for(i = keysyms_per_keycode; i; i--) {
953                   guint32 v = VALUE32(tvb, cur_offset);
954                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
955                                              "keysym: 0x%08x (%s)", v, keysymString(v));
956                   cur_offset += 4;
957             }
958       }
959 }
960
961 static void listOfPoint(tvbuff_t *tvb, int hf, int length)
962 {
963       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
964       while(length--) {
965             gint16 x, y;
966             proto_tree *ttt;
967
968             if (cur_offset + 4 > next_offset) {
969                 /* List runs past end of message. */
970                 return;
971             }
972             x = VALUE16(tvb, cur_offset);
973             y = VALUE16(tvb, cur_offset + 2);
974
975             ttt = proto_tree_add_none_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
976             proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
977             proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
978       }
979 }
980
981 static void listOfRectangle(tvbuff_t *tvb, int hf, int length)
982 {
983       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
984       while(length--) {
985             gint16 x, y;
986             unsigned width, height;
987             proto_tree *ttt;
988
989             if (cur_offset + 8 > next_offset) {
990                 /* List runs past end of message. */
991                 return;
992             }
993             x = VALUE16(tvb, cur_offset);
994             y = VALUE16(tvb, cur_offset + 2);
995             width = VALUE16(tvb, cur_offset + 4);
996             height = VALUE16(tvb, cur_offset + 6);
997
998             ttt = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, cur_offset, 8, 
999                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1000             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
1001             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
1002             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
1003             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
1004       }
1005 }
1006
1007 static void listOfSegment(tvbuff_t *tvb, int hf, int length)
1008 {
1009       proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
1010       while(length--) {
1011             gint16 x1, y1, x2, y2;
1012             proto_tree *ttt;
1013
1014             if (cur_offset + 8 > next_offset) {
1015                 /* List runs past end of message. */
1016                 return;
1017             }
1018             x1 = VALUE16(tvb, cur_offset);
1019             y1 = VALUE16(tvb, cur_offset + 2);
1020             x2 = VALUE16(tvb, cur_offset + 4);
1021             y2 = VALUE16(tvb, cur_offset + 6);
1022
1023             ttt = proto_tree_add_none_format(tt, hf_x11_segment, tvb, cur_offset, 8, 
1024                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1025             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1026             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1027             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1028             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
1029       }
1030 }
1031
1032 /* XXX - the protocol tree code should handle non-printable characters.
1033    Note that "non-printable characters" may depend on your locale.... */
1034 static void stringCopy(char *dest, const char *source, int length)
1035 {
1036       u_char c;
1037       while(length--) {
1038             c = *source++;
1039             if (!isgraph(c) && c != ' ') c = '.';
1040             *dest++ = c;
1041       }
1042       *dest++ = '\0';
1043 }
1044
1045 static void listOfString8(tvbuff_t *tvb, int hf, int hf_item, int length)
1046 {
1047       char *s = NULL;
1048       guint allocated = 0;
1049       proto_tree *tt;
1050       int i;
1051
1052       /* Compute total length */
1053       
1054       int scanning_offset = cur_offset; /* Scanning pointer */
1055       int l;
1056       for(i = length; i; i--) {
1057             l = tvb_get_guint8(tvb, scanning_offset);
1058             scanning_offset += 1 + l;
1059       }
1060
1061       tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1062
1063       while(length--) {
1064             unsigned l = VALUE8(tvb, cur_offset);
1065             if (allocated < (l + 1)) {
1066                   /* g_realloc doesn't work ??? */
1067                   g_free(s);
1068                   s = g_malloc(l + 1);
1069                   allocated = l + 1;
1070             }
1071             stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1072             proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
1073             cur_offset += l + 1;
1074       }
1075       g_free(s);
1076 }
1077
1078 #define STRING16_MAX_DISPLAYED_LENGTH 150
1079
1080 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1081 {
1082       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1083       for(; length > 0; cur_offset += 2, length--) {
1084             if (tvb_get_guint8(tvb, cur_offset))
1085                 return FALSE;
1086       }
1087       return TRUE;
1088 }
1089
1090 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1091
1092 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1093                                               int hf, int hf_bytes,
1094                                               int offset, unsigned length,
1095                                               char **s, int *sLength)
1096 {
1097       int truncated = FALSE;
1098       unsigned l = length / 2;
1099
1100       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1101             char *dp;
1102             int soffset = offset;
1103
1104             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1105                   truncated = TRUE;
1106                   l = STRING16_MAX_DISPLAYED_LENGTH;
1107             }
1108             if (*sLength < (int) l + 3) {
1109                   g_free(*s);
1110                   *s = g_malloc(l + 3);
1111                   *sLength = l + 3;
1112             }
1113             dp = *s;
1114             *dp++ = '"';
1115             if (truncated) l -= 3;
1116
1117             while(l--) {
1118                   soffset++;
1119                   *dp++ = tvb_get_guint8(tvb, soffset);
1120                   soffset++;
1121             }
1122             *dp++ = '"';
1123
1124             /* If truncated, add an ellipsis */
1125             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1126
1127             *dp++ = '\0';
1128             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s", 
1129                                         proto_registrar_get_nth(hf) -> name, *s);
1130       } else
1131             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1132
1133 }
1134
1135 static void listOfTextItem(tvbuff_t *tvb, int hf, int sizeIs16)
1136 {
1137       int allocated = 0;
1138       char *s = NULL;
1139       proto_tree *tt;
1140       guint32 fid;
1141
1142       /* Compute total length */
1143       
1144       int scanning_offset = cur_offset; /* Scanning pointer */
1145       int l;                            /* Length of an individual item */
1146       int n = 0;                        /* Number of items */
1147
1148       while(scanning_offset < next_offset) {
1149             l = tvb_get_guint8(tvb, scanning_offset);
1150             scanning_offset++;
1151             if (!l) break;
1152             n++;
1153             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1154       }
1155
1156       tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
1157
1158       while(n--) {
1159             unsigned l = VALUE8(tvb, cur_offset);
1160             if (l == 255) { /* Item is a font */
1161                   fid = tvb_get_ntohl(tvb, cur_offset + 1);
1162                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
1163                   cur_offset += 5;
1164             } else { /* Item is a string */
1165                   proto_tree *ttt;
1166                   gint8 delta = VALUE8(tvb, cur_offset + 1);
1167                   if (sizeIs16) l += l;
1168                   if ((unsigned) allocated < l + 1) {
1169                         /* g_realloc doesn't work ??? */
1170                         g_free(s);
1171                         s = g_malloc(l + 1);
1172                         allocated = l + 1;
1173                   }
1174                   stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
1175                   ttt = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
1176                                                        "textitem (string): delta = %d, \"%s\"",
1177                                                        delta, s);
1178                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
1179                   if (sizeIs16)
1180                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16, 
1181                                                           hf_x11_textitem_string_string16_bytes,
1182                                                           cur_offset + 2, l,
1183                                                            &s, &allocated);
1184                   else
1185                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb, 
1186                                                      cur_offset + 2, l, s, "\"%s\"", s);
1187                   cur_offset += l + 2;
1188             }
1189       }
1190       g_free(s);
1191 }
1192
1193 static guint32 field8(tvbuff_t *tvb, int hf)
1194 {
1195       guint32 v = VALUE8(tvb, cur_offset);
1196       header_field_info *hfi = proto_registrar_get_nth(hf);
1197       gchar *enumValue = NULL;
1198       gchar *nameAsChar = hfi -> name;
1199
1200       if (hfi -> strings)
1201             enumValue = match_strval(v, cVALS(hfi -> strings));
1202       if (enumValue)
1203             proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
1204       else
1205             proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
1206       cur_offset += 1;
1207       return v;
1208 }
1209
1210 static guint32 field16(tvbuff_t *tvb, int hf)
1211 {
1212       guint32 v = VALUE16(tvb, cur_offset);
1213       proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
1214       cur_offset += 2;
1215       return v;
1216 }
1217
1218 static guint32 field32(tvbuff_t *tvb, int hf)
1219 {
1220       guint32 v = VALUE32(tvb, cur_offset);
1221       header_field_info *hfi = proto_registrar_get_nth(hf);
1222       gchar *enumValue = NULL;
1223       gchar *nameAsChar = hfi -> name;
1224
1225       if (hfi -> strings)
1226             enumValue = match_strval(v, cVALS(hfi -> strings));
1227       if (enumValue)
1228             proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1229       else
1230             proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, 
1231                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1232                                        nameAsChar, v);
1233       cur_offset += 4;
1234       return v;
1235 }
1236
1237 static void gcAttributes(tvbuff_t *tvb)
1238 {
1239       BITMASK32(gc_value);
1240       BITFIELD(ENUM8,  gc_value_mask, function);
1241       BITFIELD(CARD32, gc_value_mask, plane_mask);
1242       BITFIELD(CARD32, gc_value_mask, foreground);
1243       BITFIELD(CARD32, gc_value_mask, background);
1244       BITFIELD(CARD16, gc_value_mask, line_width);
1245       BITFIELD(ENUM8,  gc_value_mask, line_style);
1246       BITFIELD(ENUM8,  gc_value_mask, cap_style);
1247       BITFIELD(ENUM8,  gc_value_mask, join_style);
1248       BITFIELD(ENUM8,  gc_value_mask, fill_style);
1249       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
1250       BITFIELD(PIXMAP, gc_value_mask, tile);
1251       BITFIELD(PIXMAP, gc_value_mask, stipple);
1252       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
1253       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
1254       BITFIELD(FONT,   gc_value_mask, font);
1255       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
1256       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
1257       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
1258       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
1259       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1260       BITFIELD(CARD16, gc_value_mask, dash_offset);
1261       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
1262       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
1263 }
1264
1265 static void gcMask(tvbuff_t *tvb)
1266 {
1267       BITMASK32(gc_value);
1268       FLAG(gc_value, function);
1269       FLAG(gc_value, plane_mask);
1270       FLAG(gc_value, foreground);
1271       FLAG(gc_value, background);
1272       FLAG(gc_value, line_width);
1273       FLAG(gc_value, line_style);
1274       FLAG(gc_value, cap_style);
1275       FLAG(gc_value, join_style);
1276       FLAG(gc_value, fill_style);
1277       FLAG(gc_value, fill_rule);
1278       FLAG(gc_value, tile);
1279       FLAG(gc_value, stipple);
1280       FLAG(gc_value, tile_stipple_x_origin);
1281       FLAG(gc_value, tile_stipple_y_origin);
1282       FLAG(gc_value, font);
1283       FLAG(gc_value, subwindow_mode);
1284       FLAG(gc_value, graphics_exposures);
1285       FLAG(gc_value, clip_x_origin);
1286       FLAG(gc_value, clip_y_origin);
1287       FLAG(gc_value, clip_mask);
1288       FLAG(gc_value, dash_offset);
1289       FLAG(gc_value, gc_dashes);
1290       FLAG(gc_value, arc_mode);
1291 }
1292
1293 static guint32 requestLength(tvbuff_t *tvb)
1294 {
1295       guint32 res = VALUE16(tvb, cur_offset) * 4;
1296       proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
1297       cur_offset += 2;
1298       return res;
1299 }
1300
1301 static void setOfEvent(tvbuff_t *tvb)
1302 {
1303       struct maskStruct save = lastMask;
1304       BITMASK32(event);
1305       FLAG(event, KeyPress);
1306       FLAG(event, KeyRelease);
1307       FLAG(event, ButtonPress);
1308       FLAG(event, ButtonRelease);
1309       FLAG(event, EnterWindow);
1310       FLAG(event, LeaveWindow);
1311       FLAG(event, PointerMotion);
1312       FLAG(event, PointerMotionHint);
1313       FLAG(event, Button1Motion);
1314       FLAG(event, Button2Motion);
1315       FLAG(event, Button3Motion);
1316       FLAG(event, Button4Motion);
1317       FLAG(event, Button5Motion);
1318       FLAG(event, ButtonMotion);
1319       FLAG(event, KeymapState);
1320       FLAG(event, Exposure);
1321       FLAG(event, VisibilityChange);
1322       FLAG(event, StructureNotify);
1323       FLAG(event, ResizeRedirect);
1324       FLAG(event, SubstructureNotify);
1325       FLAG(event, SubstructureRedirect);
1326       FLAG(event, FocusChange);
1327       FLAG(event, PropertyChange);
1328       FLAG(event, ColormapChange);
1329       FLAG(event, OwnerGrabButton);
1330       FLAG(event, erroneous_bits);
1331       lastMask = save;
1332 }
1333
1334 static void setOfDeviceEvent(tvbuff_t *tvb)
1335 {
1336       struct maskStruct save = lastMask;
1337       BITMASK32(do_not_propagate);
1338       FLAG(do_not_propagate, KeyPress);
1339       FLAG(do_not_propagate, KeyRelease);
1340       FLAG(do_not_propagate, ButtonPress);
1341       FLAG(do_not_propagate, ButtonRelease);
1342       FLAG(do_not_propagate, PointerMotion);
1343       FLAG(do_not_propagate, Button1Motion);
1344       FLAG(do_not_propagate, Button2Motion);
1345       FLAG(do_not_propagate, Button3Motion);
1346       FLAG(do_not_propagate, Button4Motion);
1347       FLAG(do_not_propagate, Button5Motion);
1348       FLAG(do_not_propagate, ButtonMotion);
1349       FLAG(do_not_propagate, erroneous_bits);
1350       lastMask = save;
1351 }
1352
1353 static void setOfKeyMask(tvbuff_t *tvb)
1354 {
1355       struct maskStruct save = lastMask;
1356       lastMask._value = VALUE16(tvb, cur_offset);
1357       lastMask._offset = cur_offset;
1358       lastMask._zone = 2;
1359       if (lastMask._value == 0x8000)
1360             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
1361                                        "modifiers-masks: 0x8000 (AnyModifier)");
1362       else {
1363             lastMask._tree = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2, 
1364                                                  lastMask._value);
1365             FLAG(modifiers, Shift);
1366             FLAG(modifiers, Lock);
1367             FLAG(modifiers, Control);
1368             FLAG(modifiers, Mod1);
1369             FLAG(modifiers, Mod2);
1370             FLAG(modifiers, Mod3);
1371             FLAG(modifiers, Mod4);
1372             FLAG(modifiers, Mod5);
1373             FLAG(modifiers, erroneous_bits);
1374       }
1375       lastMask = save;
1376       cur_offset += 2; 
1377 }
1378
1379 static void setOfPointerEvent(tvbuff_t *tvb)
1380 {
1381       struct maskStruct save = lastMask;
1382       BITMASK16(pointer_event);
1383       FLAG(pointer_event, ButtonPress);
1384       FLAG(pointer_event, ButtonRelease);
1385       FLAG(pointer_event, EnterWindow);
1386       FLAG(pointer_event, LeaveWindow);
1387       FLAG(pointer_event, PointerMotion);
1388       FLAG(pointer_event, PointerMotionHint);
1389       FLAG(pointer_event, Button1Motion);
1390       FLAG(pointer_event, Button2Motion);
1391       FLAG(pointer_event, Button3Motion);
1392       FLAG(pointer_event, Button4Motion);
1393       FLAG(pointer_event, Button5Motion);
1394       FLAG(pointer_event, ButtonMotion);
1395       FLAG(pointer_event, KeymapState);
1396       FLAG(pointer_event, erroneous_bits);
1397       lastMask = save;
1398 }
1399
1400 static void string8(tvbuff_t *tvb, const char *nameAsChar, int hf, unsigned length)
1401 {
1402       char *s = g_malloc(length + 1);
1403       stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
1404       proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
1405       g_free(s);
1406       cur_offset += length;
1407 }
1408
1409 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1410
1411 static void string16(tvbuff_t *tvb, int hf, int hf_bytes, unsigned length)
1412 {
1413       char *s = NULL;
1414       unsigned l = 0;
1415       length += length;
1416       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, cur_offset, length, &s, &l);
1417       g_free(s);
1418       cur_offset += length;
1419 }
1420
1421 static void timestamp(tvbuff_t *tvb, const char *nameAsChar, int hf)
1422 {
1423       guint32 v = VALUE32(tvb, cur_offset);
1424       if (!v)
1425             proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1426       else
1427             proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
1428       cur_offset += 4;
1429 }
1430
1431 static void windowAttributes(tvbuff_t *tvb)
1432 {
1433       BITMASK32(window_value);
1434       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1435       BITFIELD(CARD32, window_value_mask, background_pixel);
1436       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1437       BITFIELD(CARD32, window_value_mask, border_pixel);
1438       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1439       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1440       BITFIELD(ENUM8, window_value_mask, backing_store);
1441       BITFIELD(CARD32, window_value_mask, backing_planes);
1442       BITFIELD(CARD32, window_value_mask, backing_pixel);
1443       BITFIELD(BOOL,   window_value_mask, override_redirect);
1444       BITFIELD(BOOL,   window_value_mask, save_under);
1445       BITFIELD(SETofEVENT, window_value_mask, event_mask);
1446       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1447       BITFIELD(COLORMAP, window_value_mask, colormap);
1448       BITFIELD(CURSOR, window_value_mask, cursor);
1449 }
1450
1451 /************************************************************************
1452  ***                                                                  ***
1453  ***              D E C O D I N G   O N E   P A C K E T               ***
1454  ***                                                                  ***
1455  ************************************************************************/
1456
1457 static int dissect_x11_request_loop(tvbuff_t *tvb, proto_tree *root)
1458 {
1459       int left = tvb_reported_length(tvb), nextLeft;
1460       proto_item *ti;
1461       guint8 v8, v8_2;
1462       guint16 v16;
1463       guint32 v32;
1464
1465       /* The X11 data stream to the server is just a sequence of requests,
1466          each of which contains a length; for now, we dissect all the
1467          requests in this frame until we run out of data in the frame.
1468          Eventually, we should handle requests that cross frame
1469          boundaries.
1470
1471          Note that "in this frame" refers to everything in the frame
1472          as it appeared in the wire, not as it was captured; we want
1473          an exception to be thrown if we go past the end of the
1474          captured data in the frame without going past the end of the
1475          data in the frame. */
1476       for(;;) {
1477             int length, opcode;
1478             
1479             /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
1480             if (left < 4) {
1481                 /* We ran out of data - we don't have enough data in
1482                    the frame to get the length of this request. */
1483                 break;
1484             }
1485             length = VALUE16(tvb, cur_offset + 2) * 4;
1486             /*      fprintf(stderr, "length = %d\n", length);*/
1487             if (left < length) {
1488                 /* We ran out of data - we don't have enough data in
1489                    the frame for the full request. */
1490                 break;
1491             }
1492             if (length < 4) {
1493                 /* Bogus message length? */
1494                 break;
1495             }
1496
1497             next_offset = cur_offset + length;
1498             nextLeft = left - length;
1499
1500             ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
1501             t = proto_item_add_subtree(ti, ett_x11_request);
1502
1503             OPCODE();
1504
1505             switch(opcode) {
1506                 case 1: /* CreateWindow */
1507                   CARD8(depth);
1508                   REQUEST_LENGTH();
1509                   WINDOW(wid);
1510                   WINDOW(parent);
1511                   INT16(x);
1512                   INT16(y);
1513                   CARD16(width);
1514                   CARD16(height);
1515                   CARD16(border_width);
1516                   ENUM16(window_class);
1517                   VISUALID(visual);
1518                   windowAttributes(tvb);
1519                   break;
1520
1521                 case 2: /* ChangeWindowAttributes */
1522                   UNUSED(1);
1523                   REQUEST_LENGTH();
1524                   WINDOW(window);
1525                   windowAttributes(tvb);
1526                   break;
1527
1528                 case 3: /* GetWindowAttributes */
1529                 case 4: /* DestroyWindow */
1530                 case 5: /* DestroySubwindows */
1531                   UNUSED(1);
1532                   REQUEST_LENGTH();
1533                   WINDOW(window);
1534                   break;
1535
1536                 case 6: /* ChangeSaveSet */
1537                   ENUM8(save_set_mode);
1538                   REQUEST_LENGTH();
1539                   WINDOW(window);
1540                   break;
1541
1542                 case 7: /* ReparentWindow */
1543                   UNUSED(1);
1544                   REQUEST_LENGTH();
1545                   WINDOW(window);
1546                   WINDOW(parent);
1547                   INT16(x);
1548                   INT16(y);
1549                   break;
1550
1551                 case 8: /* MapWindow */
1552                 case 9: /* MapSubWindow */
1553                 case 10: /* UnmapWindow */
1554                 case 11: /* UnmapSubwindows */
1555                   UNUSED(1);
1556                   REQUEST_LENGTH();
1557                   WINDOW(window);
1558                   break;
1559
1560                 case 12: /* ConfigureWindow */
1561                   UNUSED(1);
1562                   REQUEST_LENGTH();
1563                   WINDOW(window);
1564                   BITMASK16(configure_window);
1565                   UNUSED(2); 
1566                   BITFIELD(INT16,  configure_window_mask, x);
1567                   BITFIELD(INT16,  configure_window_mask, y);
1568                   BITFIELD(CARD16, configure_window_mask, width);
1569                   BITFIELD(CARD16, configure_window_mask, height);
1570                   BITFIELD(CARD16, configure_window_mask, border_width);
1571                   BITFIELD(WINDOW, configure_window_mask, sibling);
1572                   BITFIELD(ENUM8,  configure_window_mask, stack_mode);
1573                   PAD();
1574                   break;
1575
1576                 case 13: /* CirculateWindow */
1577                   ENUM8(direction);
1578                   REQUEST_LENGTH();
1579                   WINDOW(window);
1580                   break;
1581
1582                 case 14: /* GetGeometry */
1583                 case 15: /* QueryTree */
1584                   UNUSED(1);
1585                   REQUEST_LENGTH();
1586                   DRAWABLE(drawable);
1587                   break;
1588
1589                 case 16: /* InternAtom */
1590                   BOOL(only_if_exists);
1591                   REQUEST_LENGTH();
1592                   v16 = FIELD16(name_length);
1593                   UNUSED(2);
1594                   STRING8(name, v16);
1595                   PAD();
1596                   break;
1597
1598                 case 17: /* GetAtomName */
1599                   UNUSED(1);
1600                   REQUEST_LENGTH();
1601                   ATOM(atom);
1602                   break;
1603
1604                 case 18: /* ChangeProperty */
1605                   ENUM8(mode);
1606                   REQUEST_LENGTH();
1607                   WINDOW(window);
1608                   ATOM(property);
1609                   ATOM(type);
1610                   CARD8(format);
1611                   UNUSED(3);
1612                   v32 = CARD32(data_length);
1613                   LISTofBYTE(data, v32);
1614                   PAD();
1615                   break;
1616
1617                 case 19: /* DeleteProperty */
1618                   UNUSED(1);
1619                   REQUEST_LENGTH();
1620                   WINDOW(window);
1621                   ATOM(property);
1622                   break;
1623
1624                 case 20: /* GetProperty */
1625                   BOOL(delete);
1626                   REQUEST_LENGTH();
1627                   WINDOW(window);
1628                   ATOM(property);
1629                   ATOM(get_property_type);
1630                   CARD32(long_offset);
1631                   CARD32(long_length);
1632                   break;
1633
1634                 case 21: /* ListProperties */
1635                   UNUSED(1);
1636                   REQUEST_LENGTH();
1637                   WINDOW(window);
1638                   break;
1639
1640                 case 22: /* SetSelectionOwner */
1641                   UNUSED(1);
1642                   REQUEST_LENGTH();
1643                   WINDOW(owner);
1644                   ATOM(selection);
1645                   TIMESTAMP(time);
1646                   break;
1647
1648                 case 23: /* GetSelectionOwner */
1649                   UNUSED(1);
1650                   REQUEST_LENGTH();
1651                   ATOM(selection);
1652                   break;
1653
1654                 case 24: /* ConvertSelection */
1655                   UNUSED(1);
1656                   REQUEST_LENGTH();
1657                   WINDOW(requestor);
1658                   ATOM(selection);
1659                   ATOM(target);
1660                   ATOM(property);
1661                   TIMESTAMP(time);
1662                   break;
1663
1664                 case 26: /* GrabPointer */
1665                   BOOL(owner_events);
1666                   REQUEST_LENGTH();
1667                   WINDOW(grab_window);
1668                   SETofPOINTEREVENT(pointer_event_mask);
1669                   ENUM8(pointer_mode);
1670                   ENUM8(keyboard_mode);
1671                   WINDOW(confine_to);
1672                   CURSOR(cursor);
1673                   TIMESTAMP(time);
1674                   break;
1675
1676                 case 27: /* UngrabPointer */
1677                   UNUSED(1);
1678                   REQUEST_LENGTH();
1679                   TIMESTAMP(time);
1680                   break;
1681
1682                 case 28: /* GrabButton */
1683                   BOOL(owner_events);
1684                   REQUEST_LENGTH();
1685                   WINDOW(grab_window);
1686                   SETofPOINTEREVENT(event_mask);
1687                   ENUM8(pointer_mode);
1688                   ENUM8(keyboard_mode);
1689                   WINDOW(confine_to);
1690                   CURSOR(cursor);
1691                   BUTTON(button);
1692                   UNUSED(1);
1693                   SETofKEYMASK(modifiers);
1694                   break;
1695
1696                 case 29: /* UngrabButton */
1697                   BUTTON(button);
1698                   REQUEST_LENGTH();
1699                   WINDOW(grab_window);
1700                   SETofKEYMASK(modifiers);
1701                   UNUSED(2);
1702                   break;
1703
1704                 case 30: /* ChangeActivePointerGrab */
1705                   UNUSED(1);
1706                   REQUEST_LENGTH();
1707                   CURSOR(cursor);
1708                   TIMESTAMP(time);
1709                   SETofPOINTEREVENT(event_mask);
1710                   UNUSED(2);
1711                   break;
1712
1713                 case 31: /* GrabKeyboard */
1714                   BOOL(owner_events);
1715                   REQUEST_LENGTH();
1716                   WINDOW(grab_window);
1717                   TIMESTAMP(time);
1718                   ENUM8(pointer_mode);
1719                   ENUM8(keyboard_mode);
1720                   UNUSED(2);
1721                   break;
1722
1723                 case 32: /* UngrabKeyboard */
1724                   UNUSED(1);
1725                   REQUEST_LENGTH();
1726                   TIMESTAMP(time);
1727                   break;
1728
1729                 case 33: /* GrabKey */
1730                   BOOL(owner_events);
1731                   REQUEST_LENGTH();
1732                   WINDOW(grab_window);
1733                   SETofKEYMASK(modifiers);
1734                   KEYCODE(key);
1735                   ENUM8(pointer_mode);
1736                   ENUM8(keyboard_mode);
1737                   UNUSED(3);
1738                   break;
1739
1740                 case 34: /* UngrabKey */
1741                   KEYCODE(key);
1742                   REQUEST_LENGTH();
1743                   WINDOW(grab_window);
1744                   SETofKEYMASK(modifiers);
1745                   UNUSED(2);
1746                   break;
1747
1748                 case 35: /* AllowEvents */
1749                   ENUM8(allow_events_mode);
1750                   REQUEST_LENGTH();
1751                   TIMESTAMP(time);
1752                   break;
1753
1754                 case 36: /* GrabServer */
1755                   UNUSED(1);
1756                   REQUEST_LENGTH();
1757                   break;
1758
1759                 case 37: /* UngrabServer */
1760                   UNUSED(1);
1761                   REQUEST_LENGTH();
1762                   break;
1763
1764                 case 38: /* QueryPointer */
1765                   UNUSED(1);
1766                   REQUEST_LENGTH();
1767                   WINDOW(window);
1768                   break;
1769
1770                 case 39: /* GetMotionEvents */
1771                   UNUSED(1);
1772                   REQUEST_LENGTH();
1773                   WINDOW(window);
1774                   TIMESTAMP(start);
1775                   TIMESTAMP(stop);
1776                   break;
1777
1778                 case 40: /* TranslateCoordinates */
1779                   UNUSED(1);
1780                   REQUEST_LENGTH();
1781                   WINDOW(src_window);
1782                   WINDOW(dst_window);
1783                   INT16(src_x);
1784                   INT16(src_y);
1785                   break;
1786
1787                 case 41: /* WarpPointer */
1788                   UNUSED(1);
1789                   REQUEST_LENGTH();
1790                   WINDOW(warp_pointer_src_window);
1791                   WINDOW(warp_pointer_dst_window);
1792                   INT16(src_x);
1793                   INT16(src_y);
1794                   CARD16(src_width);
1795                   CARD16(src_height);
1796                   INT16(dst_x);
1797                   INT16(dst_y);
1798                   break;
1799
1800                 case 42: /* SetInputFocus */
1801                   ENUM8(revert_to);
1802                   REQUEST_LENGTH();
1803                   WINDOW(focus);
1804                   TIMESTAMP(time);
1805                   break;
1806
1807                 case 43: /* GetInputFocus */
1808                   UNUSED(1);
1809                   REQUEST_LENGTH();
1810                   break;
1811
1812                 case 44: /* QueryKeymap */
1813                   UNUSED(1);
1814                   REQUEST_LENGTH();
1815                   break;
1816
1817                 case 45: /* OpenFont */
1818                   UNUSED(1);
1819                   REQUEST_LENGTH();
1820                   FONT(fid);
1821                   v16 = FIELD16(name_length);
1822                   UNUSED(2);
1823                   STRING8(name, v16);
1824                   PAD();
1825                   break;
1826
1827                 case 46: /* CloseFont */
1828                   UNUSED(1);
1829                   REQUEST_LENGTH();
1830                   FONT(font);
1831                   break;
1832
1833                 case 47: /* QueryFont */
1834                   UNUSED(1);
1835                   REQUEST_LENGTH();
1836                   FONTABLE(font);
1837                   break;
1838
1839                 case 48: /* QueryTextExtents */
1840                   v8 = BOOL(odd_length);
1841                   REQUEST_LENGTH();
1842                   FONTABLE(font);
1843                   STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
1844                   PAD();
1845                   break;
1846
1847                 case 49: /* ListFonts */
1848                   UNUSED(1);
1849                   REQUEST_LENGTH();
1850                   CARD16(max_names);
1851                   v16 = FIELD16(pattern_length);
1852                   STRING8(pattern, v16);
1853                   PAD();
1854                   break;
1855
1856                 case 50: /* ListFontsWithInfo */
1857                   UNUSED(1);
1858                   REQUEST_LENGTH();
1859                   CARD16(max_names);
1860                   v16 = FIELD16(pattern_length);
1861                   STRING8(pattern, v16);
1862                   PAD();
1863                   break;
1864
1865                 case 51: /* SetFontPath */
1866                   UNUSED(1);
1867                   REQUEST_LENGTH();
1868                   v16 = CARD16(str_number_in_path);
1869                   UNUSED(2);
1870                   LISTofSTRING8(path, v16);
1871                   PAD();
1872                   break;
1873
1874                 case 52: /* GetFontPath */
1875                   UNUSED(1);
1876                   REQUEST_LENGTH();
1877                   break;
1878
1879                 case 53: /* CreatePixmap */
1880                   CARD8(depth);
1881                   REQUEST_LENGTH();
1882                   PIXMAP(pid);
1883                   DRAWABLE(drawable);
1884                   CARD16(width);
1885                   CARD16(height);
1886                   break;
1887
1888                 case 54: /* FreePixmap */
1889                   UNUSED(1);
1890                   REQUEST_LENGTH();
1891                   PIXMAP(pixmap);
1892                   break;
1893
1894                 case 55: /* CreateGC */
1895                   UNUSED(1);
1896                   REQUEST_LENGTH();
1897                   GCONTEXT(cid);
1898                   DRAWABLE(drawable);
1899                   gcAttributes(tvb);
1900                   break;
1901
1902                 case 56: /* ChangeGC */
1903                   UNUSED(1);
1904                   REQUEST_LENGTH();
1905                   GCONTEXT(gc);
1906                   gcAttributes(tvb);
1907                   break;
1908
1909                 case 57: /* CopyGC */
1910                   UNUSED(1);
1911                   REQUEST_LENGTH();
1912                   GCONTEXT(src_gc);
1913                   GCONTEXT(dst_gc);
1914                   gcMask(tvb);
1915                   break;
1916
1917                 case 58: /* SetDashes */
1918                   UNUSED(1);
1919                   REQUEST_LENGTH();
1920                   GCONTEXT(gc);
1921                   CARD16(dash_offset);
1922                   v16 = FIELD16(dashes_length);
1923                   LISTofCARD8(dashes, v16);
1924                   PAD();
1925                   break;
1926
1927                 case 59: /* SetClipRectangles */
1928                   ENUM8(ordering);
1929                   REQUEST_LENGTH();
1930                   GCONTEXT(gc);
1931                   INT16(clip_x_origin);
1932                   INT16(clip_y_origin);
1933                   LISTofRECTANGLE(rectangles);
1934                   break;
1935
1936                 case 60: /* FreeGC */
1937                   UNUSED(1);
1938                   REQUEST_LENGTH();
1939                   GCONTEXT(gc);
1940                   break;
1941
1942                 case 61: /* ClearArea */
1943                   BOOL(exposures);
1944                   REQUEST_LENGTH();
1945                   WINDOW(window);
1946                   INT16(x);
1947                   INT16(y);
1948                   CARD16(width);
1949                   CARD16(height);
1950                   break;
1951
1952                 case 62: /* CopyArea */
1953                   UNUSED(1);
1954                   REQUEST_LENGTH();
1955                   DRAWABLE(src_drawable);
1956                   DRAWABLE(dst_drawable);
1957                   GCONTEXT(gc);
1958                   INT16(src_x);
1959                   INT16(src_y);
1960                   INT16(dst_x);
1961                   INT16(dst_y);
1962                   CARD16(width);
1963                   CARD16(height);
1964                   break;
1965
1966                 case 63: /* CopyPlane */
1967                   UNUSED(1);
1968                   REQUEST_LENGTH();
1969                   DRAWABLE(src_drawable);
1970                   DRAWABLE(dst_drawable);
1971                   GCONTEXT(gc);
1972                   INT16(src_x);
1973                   INT16(src_y);
1974                   INT16(dst_x);
1975                   INT16(dst_y);
1976                   CARD16(width);
1977                   CARD16(height);
1978                   CARD32(bit_plane);
1979                   break;
1980
1981                 case 64: /* PolyPoint */
1982                   ENUM8(coordinate_mode);
1983                   v16 = REQUEST_LENGTH();
1984                   DRAWABLE(drawable);
1985                   GCONTEXT(gc);
1986                   LISTofPOINT(points, v16 - 12);
1987                   break;
1988
1989                 case 65: /* PolyLine */
1990                   ENUM8(coordinate_mode);
1991                   v16 = REQUEST_LENGTH();
1992                   DRAWABLE(drawable);
1993                   GCONTEXT(gc);
1994                   LISTofPOINT(points, v16 - 12);
1995                   break;
1996
1997                 case 66: /* PolySegment */
1998                   UNUSED(1);
1999                   REQUEST_LENGTH();
2000                   DRAWABLE(drawable);
2001                   GCONTEXT(gc);
2002                   LISTofSEGMENT(segments);
2003                   break;
2004
2005                 case 67: /* PolyRectangle */
2006                   UNUSED(1);
2007                   REQUEST_LENGTH();
2008                   DRAWABLE(drawable);
2009                   GCONTEXT(gc);
2010                   LISTofRECTANGLE(rectangles);
2011                   break;
2012
2013                 case 68: /* PolyArc */
2014                   UNUSED(1);
2015                   REQUEST_LENGTH();
2016                   DRAWABLE(drawable);
2017                   GCONTEXT(gc);
2018                   LISTofARC(arcs);
2019                   break;
2020
2021                 case 69: /* FillPoly */
2022                   UNUSED(1);
2023                   v16 = REQUEST_LENGTH();
2024                   DRAWABLE(drawable);
2025                   GCONTEXT(gc);
2026                   ENUM8(shape);
2027                   ENUM8(coordinate_mode);
2028                   UNUSED(2);
2029                   LISTofPOINT(points, v16 - 16);
2030                   break;
2031
2032                 case 70: /* PolyFillRectangle */
2033                   UNUSED(1);
2034                   REQUEST_LENGTH();
2035                   DRAWABLE(drawable);
2036                   GCONTEXT(gc);
2037                   LISTofRECTANGLE(rectangles);
2038                   break;
2039
2040                 case 71: /* PolyFillArc */
2041                   UNUSED(1);
2042                   REQUEST_LENGTH();
2043                   DRAWABLE(drawable);
2044                   GCONTEXT(gc);
2045                   LISTofARC(arcs);
2046                   break;
2047
2048                 case 72: /* PutImage */
2049                   ENUM8(image_format);
2050                   v16 = REQUEST_LENGTH();
2051                   DRAWABLE(drawable);
2052                   GCONTEXT(gc);
2053                   CARD16(width);
2054                   CARD16(height);
2055                   INT16(dst_x);
2056                   INT16(dst_y);
2057                   CARD8(left_pad);
2058                   CARD8(depth);
2059                   UNUSED(2);
2060                   LISTofBYTE(data, v16 - 24);
2061                   PAD();
2062                   break;
2063
2064                 case 73: /* GetImage */
2065                   ENUM8(image_pixmap_format);
2066                   REQUEST_LENGTH();
2067                   DRAWABLE(drawable);
2068                   INT16(x);
2069                   INT16(y);
2070                   CARD16(width);
2071                   CARD16(height);
2072                   CARD32(plane_mask);
2073                   break;
2074
2075                 case 74: /* PolyText8 */
2076                   UNUSED(1);
2077                   v16 = REQUEST_LENGTH();
2078                   DRAWABLE(drawable);
2079                   GCONTEXT(gc);
2080                   INT16(x);
2081                   INT16(y);
2082                   LISTofTEXTITEM8(items);
2083                   PAD();
2084                   break;
2085
2086                 case 75: /* PolyText16 */
2087                   UNUSED(1);
2088                   v16 = REQUEST_LENGTH();
2089                   DRAWABLE(drawable);
2090                   GCONTEXT(gc);
2091                   INT16(x);
2092                   INT16(y);
2093                   LISTofTEXTITEM16(items);
2094                   PAD();
2095                   break;
2096
2097                 case 76: /* ImageText8 */
2098                   v8 = FIELD8(string_length);
2099                   REQUEST_LENGTH();
2100                   DRAWABLE(drawable);
2101                   GCONTEXT(gc);
2102                   INT16(x);
2103                   INT16(y);
2104                   STRING8(string, v8);
2105                   PAD();
2106                   break;
2107
2108                 case 77: /* ImageText16 */
2109                   v8 = FIELD8(string_length);
2110                   REQUEST_LENGTH();
2111                   DRAWABLE(drawable);
2112                   GCONTEXT(gc);
2113                   INT16(x);
2114                   INT16(y);
2115                   STRING16(string16, v8);
2116                   PAD();
2117                   break;
2118
2119                 case 78: /* CreateColormap */
2120                   ENUM8(alloc);
2121                   REQUEST_LENGTH();
2122                   COLORMAP(mid);
2123                   WINDOW(window);
2124                   VISUALID(visual);
2125                   break;
2126
2127                 case 79: /* FreeColormap */
2128                   UNUSED(1);
2129                   REQUEST_LENGTH();
2130                   COLORMAP(cmap);
2131                   break;
2132
2133                 case 80: /* CopyColormapAndFree */
2134                   UNUSED(1);
2135                   REQUEST_LENGTH();
2136                   COLORMAP(mid);
2137                   COLORMAP(src_cmap);
2138                   break;
2139
2140                 case 81: /* InstallColormap */
2141                   UNUSED(1);
2142                   REQUEST_LENGTH();
2143                   COLORMAP(cmap);
2144                   break;
2145
2146                 case 82: /* UninstallColormap */
2147                   UNUSED(1);
2148                   REQUEST_LENGTH();
2149                   COLORMAP(cmap);
2150                   break;
2151
2152                 case 83: /* ListInstalledColormaps */
2153                   UNUSED(1);
2154                   REQUEST_LENGTH();
2155                   WINDOW(window);
2156                   break;
2157
2158                 case 84: /* AllocColor */
2159                   UNUSED(1);
2160                   REQUEST_LENGTH();
2161                   COLORMAP(cmap);
2162                   CARD16(red);
2163                   CARD16(green);
2164                   CARD16(blue);
2165                   UNUSED(2);
2166                   break;
2167
2168                 case 85: /* AllocNamedColor */
2169                   UNUSED(1);
2170                   REQUEST_LENGTH();
2171                   COLORMAP(cmap);
2172                   v16 = FIELD16(name_length);
2173                   UNUSED(2);
2174                   STRING8(name, v16);
2175                   PAD();
2176                   break;
2177
2178                 case 86: /* AllocColorCells */
2179                   BOOL(contiguous);
2180                   REQUEST_LENGTH();
2181                   COLORMAP(cmap);
2182                   CARD16(colors);
2183                   CARD16(planes);
2184                   break;
2185
2186                 case 87: /* AllocColorPlanes */
2187                   BOOL(contiguous);
2188                   REQUEST_LENGTH();
2189                   COLORMAP(cmap);
2190                   CARD16(colors);
2191                   CARD16(reds);
2192                   CARD16(greens);
2193                   CARD16(blues);
2194                   break;
2195
2196                 case 88: /* FreeColors */
2197                   UNUSED(1);
2198                   v16 = REQUEST_LENGTH();
2199                   COLORMAP(cmap);
2200                   CARD32(plane_mask);
2201                   LISTofCARD32(pixels, v16 - 12);
2202                   break;
2203
2204                 case 89: /* StoreColors */
2205                   UNUSED(1);
2206                   v16 = REQUEST_LENGTH();
2207                   COLORMAP(cmap);
2208                   LISTofCOLORITEM(color_items, v16 - 8);
2209                   break;
2210
2211                 case 90: /* StoreNamedColor */
2212                   COLOR_FLAGS(color);
2213                   REQUEST_LENGTH();
2214                   COLORMAP(cmap);
2215                   CARD32(pixel);        
2216                   v16 = FIELD16(name_length);
2217                   UNUSED(2);
2218                   STRING8(name, v16);
2219                   PAD();
2220                   break;
2221
2222                 case 91: /* QueryColors */
2223                   UNUSED(1);
2224                   v16 = REQUEST_LENGTH();
2225                   COLORMAP(cmap);
2226                   LISTofCARD32(pixels, v16 - 8);
2227                   break;
2228
2229                 case 92: /* LookupColor */
2230                   UNUSED(1);
2231                   REQUEST_LENGTH();
2232                   COLORMAP(cmap);
2233                   v16 = FIELD16(name_length);
2234                   UNUSED(2);
2235                   STRING8(name, v16);
2236                   PAD();
2237                   break;
2238
2239                 case 93: /* CreateCursor */
2240                   UNUSED(1);
2241                   REQUEST_LENGTH();
2242                   CURSOR(cid);
2243                   PIXMAP(source_pixmap);
2244                   PIXMAP(mask);
2245                   CARD16(fore_red);
2246                   CARD16(fore_green);
2247                   CARD16(fore_blue);
2248                   CARD16(back_red);
2249                   CARD16(back_green);
2250                   CARD16(back_blue);
2251                   CARD16(x);
2252                   CARD16(y);
2253                   break;
2254
2255                 case 94: /* CreateGlyphCursor */
2256                   UNUSED(1);
2257                   REQUEST_LENGTH();
2258                   CURSOR(cid);
2259                   FONT(source_font);
2260                   FONT(mask_font);
2261                   CARD16(source_char);
2262                   CARD16(mask_char);
2263                   CARD16(fore_red);
2264                   CARD16(fore_green);
2265                   CARD16(fore_blue);
2266                   CARD16(back_red);
2267                   CARD16(back_green);
2268                   CARD16(back_blue);
2269                   break;
2270
2271                 case 95: /* FreeCursor */
2272                   UNUSED(1);
2273                   REQUEST_LENGTH();
2274                   CURSOR(cursor);
2275                   break;
2276
2277                 case 96: /* RecolorCursor */
2278                   UNUSED(1);
2279                   REQUEST_LENGTH();
2280                   CURSOR(cursor);
2281                   CARD16(fore_red);
2282                   CARD16(fore_green);
2283                   CARD16(fore_blue);
2284                   CARD16(back_red);
2285                   CARD16(back_green);
2286                   CARD16(back_blue);
2287                   break;
2288
2289                 case 97: /* QueryBestSize */
2290                   ENUM8(class);
2291                   REQUEST_LENGTH();
2292                   DRAWABLE(drawable);
2293                   CARD16(width);
2294                   CARD16(height);
2295                   break;
2296
2297                 case 98: /* QueryExtension */
2298                   UNUSED(1);
2299                   REQUEST_LENGTH();
2300                   v16 = FIELD16(name_length);
2301                   UNUSED(2);
2302                   STRING8(name, v16);
2303                   PAD();
2304                   break;
2305
2306                 case 99: /* ListExtensions */
2307                   UNUSED(1);
2308                   REQUEST_LENGTH();
2309                   break;
2310
2311                 case 100: /* ChangeKeyboardMapping */
2312                   v8 = FIELD8(keycode_count);
2313                   REQUEST_LENGTH();
2314                   KEYCODE(first_keycode);
2315                   v8_2 = FIELD8(keysyms_per_keycode);
2316                   UNUSED(2);
2317                   LISTofKEYSYM(keysyms, v8, v8_2);
2318                   break;
2319
2320                 case 101: /* GetKeyboardMapping */
2321                   UNUSED(1);
2322                   REQUEST_LENGTH();
2323                   KEYCODE(first_keycode);
2324                   FIELD8(count);
2325                   UNUSED(2);
2326                   break;
2327
2328                 case 102: /* ChangeKeyboardControl */
2329                   UNUSED(1);
2330                   REQUEST_LENGTH();
2331                   BITMASK32(keyboard_value);
2332                   BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2333                   BITFIELD(INT8, keyboard_value_mask, bell_percent);
2334                   BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2335                   BITFIELD(INT16, keyboard_value_mask, bell_duration);
2336                   BITFIELD(INT16, keyboard_value_mask, led);
2337                   BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2338                   BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2339                   BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2340                   break;
2341
2342                 case 103: /* GetKeyboardControl */
2343                   UNUSED(1);
2344                   REQUEST_LENGTH();
2345                   break;
2346
2347                 case 104: /* Bell */
2348                   INT8(percent);
2349                   REQUEST_LENGTH();
2350                   break;
2351
2352                 case 105: /* ChangePointerControl */
2353                   UNUSED(1);
2354                   REQUEST_LENGTH();
2355                   INT16(acceleration_numerator);
2356                   INT16(acceleration_denominator);
2357                   INT16(threshold);
2358                   BOOL(do_acceleration);
2359                   BOOL(do_threshold);
2360                   break;
2361
2362                 case 106: /* GetPointerControl */
2363                   UNUSED(1);
2364                   REQUEST_LENGTH();
2365                   break;
2366
2367                 case 107: /* SetScreenSaver */
2368                   UNUSED(1);
2369                   REQUEST_LENGTH();
2370                   INT16(timeout);
2371                   INT16(interval);
2372                   ENUM8(prefer_blanking);
2373                   ENUM8(allow_exposures);
2374                   UNUSED(2);
2375                   break;
2376
2377                 case 108: /* GetScreenSaver */
2378                   UNUSED(1);
2379                   REQUEST_LENGTH();
2380                   break;
2381
2382                 case 109: /* ChangeHosts */
2383                   ENUM8(change_host_mode);
2384                   REQUEST_LENGTH();
2385                   ENUM8(family);
2386                   UNUSED(1);
2387                   v16 = CARD16(address_length);
2388                   LISTofCARD8(address, v16);
2389                   break;
2390
2391                 case 110: /* ListHosts */
2392                   UNUSED(1);
2393                   REQUEST_LENGTH();
2394                   break;
2395
2396                 case 111: /* SetAccessControl */
2397                   ENUM8(access_mode);
2398                   REQUEST_LENGTH();
2399                   break;
2400
2401                 case 112: /* SetCloseDownMode */
2402                   ENUM8(close_down_mode);
2403                   REQUEST_LENGTH();
2404                   break;
2405
2406                 case 113: /* KillClient */
2407                   UNUSED(1);
2408                   REQUEST_LENGTH();
2409                   CARD32(resource);
2410                   break;
2411
2412                 case 114: /* RotateProperties */
2413                   UNUSED(1);
2414                   v16 = REQUEST_LENGTH();
2415                   WINDOW(window);
2416                   CARD16(property_number);
2417                   INT16(delta);
2418                   LISTofATOM(properties, (v16 - 12));
2419                   break;
2420
2421                 case 115: /* ForceScreenSaver */
2422                   ENUM8(screen_saver_mode);
2423                   REQUEST_LENGTH();
2424                   break;
2425
2426                 case 116: /* SetPointerMapping */
2427                   v8 = FIELD8(map_length);
2428                   REQUEST_LENGTH();
2429                   LISTofCARD8(map, v8);
2430                   PAD();
2431                   break;
2432
2433                 case 117: /* GetPointerMapping */
2434                   UNUSED(1);
2435                   REQUEST_LENGTH();
2436                   break;
2437
2438                 case 118: /* SetModifierMapping */
2439                   v8 = FIELD8(keycodes_per_modifier);
2440                   REQUEST_LENGTH();
2441                   LISTofKEYCODE(keycodes, v8);
2442                   break;
2443
2444                 case 119: /* GetModifierMapping */
2445                   UNUSED(1);
2446                   REQUEST_LENGTH();
2447                   break;
2448                   
2449                 case 127: /* NoOperation */
2450                   UNUSED(1);
2451                   REQUEST_LENGTH();
2452                   break;
2453             }
2454             if (cur_offset < next_offset)
2455                   proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
2456             cur_offset = next_offset;
2457             left = nextLeft;
2458       }
2459
2460       return left;
2461 }
2462
2463 /************************************************************************
2464  ***                                                                  ***
2465  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2466  ***                                                                  ***
2467  ************************************************************************/
2468
2469 static GTree *byte_ordering_cache = NULL;
2470 static GMemChunk *address_chunk = NULL;
2471 static GMemChunk *ipv4_chunk = NULL;
2472 static GMemChunk *ipv6_chunk = NULL;
2473
2474 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2475 {
2476       const address *a = (const address *)aa;
2477       const address *b = (const address *)bb;
2478       int c = b -> type - a -> type;
2479       if (c) return c;
2480       c = b -> len - a -> len;
2481       if (c) return c;
2482       return memcmp(b -> data, a -> data, a -> len);
2483 }
2484
2485 /* If we can't guess, we return TRUE (that is little_endian), cause
2486    I'm developing on a Linux box :-). The (non-)guess isn't cached
2487    however, so we may have more luck next time. I'm quite conservative
2488    in my assertions, cause once it's cached, it's stay in cache, and
2489    we may be fooled up by a packet starting with the end of a request
2490    started in a previous packet...
2491 */
2492
2493 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2494
2495 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2496 {
2497       int res = 0;
2498       while(maskLength--) {
2499             int c = tvb_get_guint8(tvb, offset);
2500             offset++;
2501             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2502       }
2503       return res;
2504 }
2505
2506 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2507 {
2508       if (listLength > length) return FALSE;
2509       while(listLength--) {
2510             int l;
2511             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2512             l = tvb_get_guint8(tvb, offset);
2513             if (!l) break;
2514             l++;
2515             if (l > length) return FALSE;
2516             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2517             offset += l;
2518             length -= l;
2519       }
2520       if (length > 3) return FALSE;
2521       return TRUE;
2522 }
2523
2524 static int rounded4(int n)
2525 {
2526       int remainder = n % 4;
2527       int res = n / 4;
2528       if (remainder) res++;
2529       return res;
2530 }
2531
2532 /* We assume the order to be consistent, until proven wrong. */
2533
2534 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2535 {
2536       switch(tvb_get_guint8(tvb, offset)) {
2537           case 1: /* CreateWindow */
2538             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2539
2540           case 2: /* ChangeWindowAttributes */
2541           case 56: /* ChangeGC */
2542             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2543
2544           case 3: /* GetWindowAttributes */
2545           case 4: /* DestroyWindow */
2546           case 5: /* DestroySubwindows */
2547           case 6: /* ChangeSaveSet */
2548           case 8: /* MapWindow */
2549           case 9: /* MapSubWindow */
2550           case 10: /* UnmapWindow */
2551           case 11: /* UnmapSubwindows */
2552           case 13: /* CirculateWindow */
2553           case 14: /* GetGeometry */
2554           case 15: /* QueryTree */
2555           case 17: /* GetAtomName */
2556           case 21: /* ListProperties */
2557           case 23: /* GetSelectionOwner */
2558           case 27: /* UngrabPointer */
2559           case 32: /* UngrabKeyboard */
2560           case 35: /* AllowEvents */
2561           case 38: /* QueryPointer */
2562           case 46: /* CloseFont */
2563           case 47: /* QueryFont */
2564           case 54: /* FreePixmap */
2565           case 60: /* FreeGC */
2566           case 79: /* FreeColormap */
2567           case 81: /* InstallColormap */
2568           case 82: /* UninstallColormap */
2569           case 83: /* ListInstalledColormaps */
2570           case 95: /* FreeCursor */
2571           case 101: /* GetKeyboardMapping */
2572           case 113: /* KillClient */
2573             return length == 2;
2574
2575           case 7: /* ReparentWindow */
2576           case 22: /* SetSelectionOwner */
2577           case 30: /* ChangeActivePointerGrab */
2578           case 31: /* GrabKeyboard */
2579           case 33: /* GrabKey */
2580           case 39: /* GetMotionEvents */
2581           case 40: /* TranslateCoordinates */
2582           case 53: /* CreatePixmap */
2583           case 57: /* CopyGC */
2584           case 61: /* ClearArea */
2585           case 78: /* CreateColormap */
2586           case 84: /* AllocColor */
2587           case 87: /* AllocColorPlanes */
2588             return length == 4;
2589
2590           case 12: /* ConfigureWindow */
2591             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2592
2593           case 16: /* InternAtom */
2594           case 98: /* QueryExtension */
2595             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2596
2597           case 18: /* ChangeProperty */
2598             {
2599                   int multiplier, type;
2600                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2601                   type = tvb_get_guint8(tvb, 16);
2602                   if (type != 8 && type != 16 && type != 32) return FALSE;
2603                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2604                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2605                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2606             }
2607
2608           case 19: /* DeleteProperty */
2609           case 29: /* UngrabButton */
2610           case 34: /* UngrabKey */
2611           case 42: /* SetInputFocus */
2612           case 80: /* CopyColormapAndFree */
2613           case 86: /* AllocColorCells */
2614           case 97: /* QueryBestSize */
2615           case 105: /* ChangePointerControl */
2616           case 107: /* SetScreenSaver */
2617             return length == 3;
2618
2619           case 20: /* GetProperty */
2620           case 24: /* ConvertSelection */
2621           case 26: /* GrabPointer */
2622           case 28: /* GrabButton */
2623           case 41: /* WarpPointer */
2624             return length == 6;
2625
2626           case 25: /* SendEvent */
2627             return length == 11;
2628
2629           case 36: /* GrabServer */
2630           case 37: /* UngrabServer */
2631           case 43: /* GetInputFocus */
2632           case 44: /* QueryKeymap */
2633           case 52: /* GetFontPath */
2634           case 99: /* ListExtensions */
2635           case 103: /* GetKeyboardControl */
2636           case 104: /* Bell */
2637           case 106: /* GetPointerControl */
2638           case 108: /* GetScreenSaver */
2639           case 110: /* ListHosts */
2640           case 111: /* SetAccessControl */
2641           case 112: /* SetCloseDownMode */
2642           case 115: /* ForceScreenSaver */
2643           case 117: /* GetPointerMapping */
2644           case 119: /* GetModifierMapping */
2645             return length == 1;
2646
2647           case 45: /* OpenFont */
2648           case 85: /* AllocNamedColor */
2649           case 92: /* LookupColor */
2650             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2651
2652           case 48: /* QueryTextExtents */
2653             return length >= 2;
2654
2655           case 49: /* ListFonts */
2656           case 50: /* ListFontsWithInfo */
2657           case 109: /* ChangeHosts */
2658             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2659
2660           case 51: /* SetFontPath */
2661             if (length < 2) return FALSE;
2662             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2663             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2664
2665           case 55: /* CreateGC */
2666             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2667
2668           case 58: /* SetDashes */
2669             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2670
2671           case 59: /* SetClipRectangles */
2672           case 66: /* PolySegment */
2673           case 67: /* PolyRectangle */
2674           case 70: /* PolyFillRectangle */
2675             return length >= 3 && (length - 3) % 2 == 0;
2676
2677           case 62: /* CopyArea */
2678             return length == 7;
2679
2680           case 63: /* CopyPlane */
2681           case 93: /* CreateCursor */
2682           case 94: /* CreateGlyphCursor */
2683             return length == 8;
2684
2685           case 64: /* PolyPoint */
2686           case 65: /* PolyLine */
2687           case 88: /* FreeColors */
2688             return length >= 3;
2689
2690           case 68: /* PolyArc */
2691           case 71: /* PolyFillArc */
2692             return length >= 3 && (length - 3) % 3 == 0;
2693
2694           case 69: /* FillPoly */
2695           case 76: /* ImageText8 */
2696             return length >= 4;
2697
2698           case 72: /* PutImage */
2699             return length >= 6;
2700
2701           case 73: /* GetImage */
2702           case 96: /* RecolorCursor */
2703             return length == 5;
2704
2705           case 74: /* PolyText8 */
2706             if (length < 4) return FALSE;
2707             return TRUE; /* We don't perform many controls on this one */
2708
2709           case 75: /* PolyText16 */
2710             if (length < 4) return FALSE;
2711             return TRUE; /* We don't perform many controls on this one */
2712
2713           case 77: /* ImageText16 */
2714             return length >= 4;
2715
2716           case 89: /* StoreColors */
2717             return length > 2 && (length - 2) % 3 == 0;
2718
2719           case 90: /* StoreNamedColor */
2720             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2721
2722           case 91: /* QueryColors */
2723             return length >= 2;
2724
2725           case 100: /* ChangeKeyboardMapping */
2726             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2727
2728           case 102: /* ChangeKeyboardControl */
2729             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2730
2731           case 114: /* RotateProperties */
2732             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2733
2734           case 116: /* SetPointerMapping */
2735             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2736
2737           case 118: /* SetModifierMapping */
2738             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2739             
2740           case 127: /* NoOperation */
2741             return length >= 1;
2742
2743           default:
2744             return TRUE;
2745       }
2746 }
2747
2748 /* -1 means doesn't match, +1 means match, 0 means don't know */
2749
2750 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2751 {
2752       int offset, nextoffset;
2753       int atLeastOne = 0;
2754
2755       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2756             int length;
2757             length = v16(tvb, offset + 2);
2758             if (!length) return -1;
2759             nextoffset = offset + length * 4;
2760             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2761             atLeastOne = 1;
2762       }
2763       return atLeastOne;
2764 }
2765
2766 static gboolean
2767 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
2768 {
2769       /* With X the client gives the byte ordering for the protocol,
2770          and the port on the server tells us we're speaking X. */
2771
2772       int le, be, decision, decisionToCache;
2773
2774       gboolean is_reply = (pinfo->srcport == pinfo->match_port);
2775       address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
2776       gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2777       if (cache) return cache > 0 ? TRUE : FALSE;
2778       if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
2779
2780       le = x_endian_match(tvb, tvb_get_letohs);
2781       be = x_endian_match(tvb, tvb_get_ntohs);
2782
2783       /* remember that "decision" really means "little_endian". */
2784       if (le == be) {
2785             /* We have no reason to believe it's little- rather than
2786                big-endian, so we guess the shortest length is the
2787                right one.
2788             */
2789             if (!tvb_bytes_exist(tvb, 0, 4))
2790                           /* Not even a way to get the length. We're biased
2791                              toward little endianness here (essentially the
2792                              x86 world right now). Decoding won't go very far
2793                              anyway.
2794                           */
2795                   decision = TRUE;
2796             else
2797                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2798       } else
2799           decision = le >= be;
2800
2801       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2802       if (decisionToCache) {
2803             /* We encode the decision as 1 for TRUE and -1 for FALSE
2804                to be able to distinguish between FALSE and no value in
2805                the cache when recalling the value.
2806             */
2807             int address_length;
2808             char *address_data;
2809             address *cached;
2810             if (addr -> type == AT_IPv4) {
2811                   address_length = 4;
2812                   address_data = g_mem_chunk_alloc(ipv4_chunk);
2813             } else if (addr -> type == AT_IPv6) {
2814                   address_length = 16;
2815                   address_data = g_mem_chunk_alloc(ipv6_chunk);
2816             } else {
2817                   address_length = addr -> len;
2818                   address_data = g_malloc(address_length);
2819             }
2820             cached = g_mem_chunk_alloc(address_chunk);
2821             memcpy(address_data, addr -> data, address_length);
2822             SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2823             g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2824       }
2825             
2826       /*
2827       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n", 
2828               pinfo->fd -> num, le, be, decision, decisionToCache);
2829       */
2830       return decision;
2831 }
2832
2833 /************************************************************************
2834  ***                                                                  ***
2835  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
2836  ***                                                                  ***
2837  ************************************************************************/
2838
2839 static void
2840 dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2841 {
2842 /* Set up structures we will need to add the protocol subtree and manage it */
2843       proto_item *ti;
2844       proto_tree *x11_tree;
2845       int left;
2846         
2847 /* This field shows up as the "Info" column in the display; you should make
2848    it, if possible, summarize what's in the packet, so that a user looking
2849    at the list of packets can tell what type of packet it is. */
2850       if (check_col(pinfo->cinfo, COL_INFO)) 
2851             col_set_str(pinfo->cinfo, COL_INFO, "X11 request");
2852
2853 /* In the interest of speed, if "tree" is NULL, don't do any work not
2854    necessary to generate protocol tree items. */
2855       if (!tree) return;
2856       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2857       x11_tree = proto_item_add_subtree(ti, ett_x11);
2858
2859       cur_offset = 0;
2860       little_endian = guess_byte_ordering(tvb, pinfo);
2861       left = dissect_x11_request_loop(tvb, x11_tree);
2862       if (left)
2863             call_dissector(data_handle,tvb_new_subset(tvb, cur_offset,-1, tvb_reported_length_remaining(tvb,cur_offset)), pinfo, x11_tree);
2864 }
2865
2866 static void
2867 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2868 {
2869 /* Set up structures we will need to add the protocol subtree and manage it */
2870       proto_item *ti;
2871       proto_tree *x11_tree;
2872         
2873 /* This field shows up as the "Info" column in the display; you should make
2874    it, if possible, summarize what's in the packet, so that a user looking
2875    at the list of packets can tell what type of packet it is. */
2876       if (check_col(pinfo->cinfo, COL_INFO)) 
2877             col_set_str(pinfo->cinfo, COL_INFO, "X11 event");
2878
2879 /* In the interest of speed, if "tree" is NULL, don't do any work not
2880    necessary to generate protocol tree items. */
2881       if (tree) {
2882             ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2883             x11_tree = proto_item_add_subtree(ti, ett_x11);
2884
2885 /* Code to process the packet goes here */
2886
2887             call_dissector(data_handle,tvb, pinfo, x11_tree);
2888       }
2889 }
2890
2891 static void
2892 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2893 {
2894       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
2895             col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
2896     
2897       if (pinfo->match_port == pinfo->destport)
2898             dissect_x11_request(tvb, pinfo, tree);
2899       else
2900             dissect_x11_event(tvb, pinfo, tree);
2901 }
2902
2903 /* Register the protocol with Ethereal */
2904 void proto_register_x11(void)
2905 {                 
2906
2907 /* Setup list of header fields */
2908       static hf_register_info hf[] = {
2909 /*
2910   { &hf_x11_FIELDABBREV,
2911   { "FIELDNAME",           "x11.FIELDABBREV",
2912   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,          
2913   "FIELDDESCR", HFILL }
2914   },
2915 */
2916 #include "x11-register-info.h"
2917       };
2918
2919 /* Setup protocol subtree array */
2920       static gint *ett[] = {
2921             &ett_x11,
2922             &ett_x11_request,
2923       };
2924
2925 /* Register the protocol name and description */
2926       proto_x11 = proto_register_protocol("X11", "X11", "x11");
2927
2928 /* Required function calls to register the header fields and subtrees used */
2929       proto_register_field_array(proto_x11, hf, array_length(hf));
2930       proto_register_subtree_array(ett, array_length(ett));
2931
2932       byte_ordering_cache = g_tree_new(compareAddresses);
2933       address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address), 
2934                                       sizeof(address) * 128, G_ALLOC_ONLY);
2935       ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
2936       ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
2937 };
2938
2939
2940 void
2941 proto_reg_handoff_x11(void)
2942 {
2943   dissector_handle_t x11_handle;
2944
2945   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
2946   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
2947   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
2948   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
2949   data_handle = find_dissector("data");
2950 }