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