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