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