6e17e08f1af26abaa94b5f7889e7d0b299338b3f
[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.39 2002/04/15 00:10:26 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 next_offset = 0; /* Offset of the next request in the frame */    
608 static gboolean little_endian = TRUE;
609
610 /************************************************************************
611  ***                                                                  ***
612  ***           F I E L D   D E C O D I N G   M A C R O S              ***
613  ***                                                                  ***
614  ************************************************************************/
615
616 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
617 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
618 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
619
620 #define FIELD8(name)  (field8(tvb, offsetp, t, hf_x11_##name))
621 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name))
622 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name))
623
624 #define BITFIELD(TYPE, position, name) {\
625   int unused;\
626   int save = *offsetp;\
627   proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
628                       bitmask_size, little_endian); \
629   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
630        TYPE(name);\
631        unused = save + 4 - *offsetp;\
632        if (unused)\
633            proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
634        *offsetp = save + 4;\
635  }\
636 }
637
638 #define FLAG(position, name) {\
639        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
640
641 #define FLAG_IF_NONZERO(position, name) {\
642   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
643        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
644
645 #define ATOM(name)     { atom(tvb, offsetp, t, hf_x11_##name); }
646 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, #name, hf_x11_##name, "Forget"); }
647 #define BITMASK(name, size) {\
648       proto_item *ti; \
649       guint32 bitmask_value; \
650       int bitmask_offset; \
651       int bitmask_size; \
652       proto_tree *bitmask_tree; \
653       bitmask_value = ((size == 1) ? VALUE8(tvb, *offsetp) : \
654                        ((size == 2) ? VALUE16(tvb, *offsetp) : \
655                                       VALUE32(tvb, *offsetp))); \
656       bitmask_offset = *offsetp; \
657       bitmask_size = size; \
658       ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
659       bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
660       *offsetp += size;
661 #define ENDBITMASK      }
662 #define BITMASK8(name)  BITMASK(name, 1);
663 #define BITMASK16(name) BITMASK(name, 2);
664 #define BITMASK32(name) BITMASK(name, 4);
665 #define BOOL(name)     (add_boolean(tvb, offsetp, t, hf_x11_##name))
666 #define BUTTON(name)   { FIELD8(name); }
667 #define CARD8(name)    { FIELD8(name); }
668 #define CARD16(name)   (FIELD16(name))
669 #define CARD32(name)   (FIELD32(name))
670 #define COLOR_FLAGS(name) { colorFlags(tvb, offsetp, t); }
671 #define COLORMAP(name) { FIELD32(name); }
672 #define CURSOR(name)   { FIELD32(name); }
673 #define DRAWABLE(name) { FIELD32(name); }
674 #define ENUM8(name)    { FIELD8(name); }
675 #define ENUM16(name)   { FIELD16(name); }
676 #define FONT(name)     { FIELD32(name); }
677 #define FONTABLE(name) { FIELD32(name); }
678 #define GCONTEXT(name) { FIELD32(name); }
679 #define INT8(name)     { FIELD8(name); }
680 #define INT16(name)    { FIELD16(name); }
681 #define KEYCODE(name)  { FIELD8(name); }
682 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12); }
683 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4); }
684 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length)); }
685 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length)); }
686 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
687 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12); }
688 #define LISTofKEYCODE(name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, (length)); }
689 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
690       listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
691 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4); }
692 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
693 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
694 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length)); }
695 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE); }
696 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE); }
697 #define OPCODE()       { opcode = FIELD8(opcode); }
698 #define PIXMAP(name)   { FIELD32(name); }
699 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t))
700 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t); }
701 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t);}
702 #define SETofKEYMASK(name) { setOfKeyMask(tvb, offsetp, t); }
703 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t); }
704 #define STRING8(name, length)  { string8(tvb, offsetp, t, #name, hf_x11_##name, length); }
705 #define STRING16(name, length)  { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length); }
706 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, #name, hf_x11_##name); }
707 #define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp,  x, little_endian); *offsetp += x; }
708 #define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp,  x, little_endian); *offsetp += x; }
709 #define PAD()          { if (next_offset - *offsetp > 0) proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, next_offset - *offsetp, little_endian); *offsetp = next_offset; }
710 #define WINDOW(name)   { FIELD32(name); }
711 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, #name, hf_x11_##name, "Unmap"); }
712
713 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
714     proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
715                                v ? "" : " (CopyFromParent)"); *offsetp += 4; }
716
717 /************************************************************************
718  ***                                                                  ***
719  ***                  D E C O D I N G   F I E L D S                   ***
720  ***                                                                  ***
721  ************************************************************************/
722
723 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
724 {
725       const char *interpretation = NULL;
726
727       guint32 v = VALUE32(tvb, *offsetp);
728       if (v >= 1 && v < array_length(atom_predefined_interpretation))
729             interpretation = atom_predefined_interpretation[v];
730       else if (v)
731             interpretation = "Not a predefined atom";
732       else {
733             header_field_info *hfi = proto_registrar_get_nth(hf);
734             if (hfi -> strings)
735                   interpretation = match_strval(v, cVALS(hfi -> strings));
736       }
737       if (!interpretation) interpretation = "error in Xlib client program ?";
738       proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)", 
739                                  proto_registrar_get_nth(hf) -> name, v, interpretation);
740       *offsetp += 4;
741 }
742
743 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
744 {
745       guint32 v = VALUE8(tvb, *offsetp);
746       proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
747       *offsetp += 1;
748       return v;
749 }
750
751 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
752 {
753       unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
754       proto_item *ti;
755       proto_tree *tt;
756       
757       if (do_red_green_blue) {
758             int sep = FALSE;
759             char buffer[512];
760             char *bp = buffer + sprintf(buffer, "flags: ");
761
762             if (do_red_green_blue & 0x1) {
763                   bp += sprintf(bp, "DoRed");
764                   sep = TRUE;
765             }
766
767             if (do_red_green_blue & 0x2) {
768                   if (sep) bp += sprintf(bp, " | ");
769                   bp += sprintf(bp, "DoGreen");
770                   sep = TRUE;
771             }
772
773             if (do_red_green_blue & 0x4) {
774                   if (sep) bp += sprintf(bp, " | ");
775                   bp += sprintf(bp, "DoBlue");
776                   sep = TRUE;
777             }
778
779             if (do_red_green_blue & 0xf8) {
780                   if (sep) bp += sprintf(bp, " + ");
781                   sprintf(bp, "trash");
782             }
783
784             ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
785                                             "%s", buffer);
786             tt = proto_item_add_subtree(ti, ett_x11_color_flags);
787             if (do_red_green_blue & 0x1)
788                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1, 
789                                          do_red_green_blue & 0x1);
790             if (do_red_green_blue & 0x2)
791                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1, 
792                                          do_red_green_blue & 0x2);
793             if (do_red_green_blue & 0x4)
794                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1, 
795                                          do_red_green_blue & 0x4);
796             if (do_red_green_blue & 0xf8)
797                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1, 
798                                          do_red_green_blue & 0xf8);
799       } else
800             proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
801                                        "flags: none");
802       *offsetp += 1;
803 }
804
805 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
806     const char *nameAsChar, int hf, const char *nullInterpretation)
807 {
808       guint8 v = VALUE8(tvb, *offsetp);
809       if (!v)
810             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)", nameAsChar, 
811                                        nullInterpretation);
812       else
813             proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
814       *offsetp += 1;
815 }
816
817 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
818     int length)
819 {
820       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
821       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
822       while(length--) {
823             gint16 x = VALUE16(tvb, *offsetp);
824             gint16 y = VALUE16(tvb, *offsetp + 2);
825             guint16 width = VALUE16(tvb, *offsetp + 4);
826             guint16 height = VALUE16(tvb, *offsetp + 6);
827             gint16 angle1 = VALUE16(tvb, *offsetp + 8);
828             gint16 angle2 = VALUE16(tvb, *offsetp + 10);
829
830             proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12, 
831                                                              "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
832                                                              width, height, x, y, angle1, angle2,
833                                                              angle1 / 64.0, angle2 / 64.0);
834             proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
835             proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
836             *offsetp += 2;
837             proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
838             *offsetp += 2;
839             proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
840             *offsetp += 2;
841             proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
842             *offsetp += 2;
843             proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
844             *offsetp += 2;
845             proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
846             *offsetp += 2;
847       }
848 }
849
850 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
851     int length)
852 {
853       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
854       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
855       while(length--) {
856             if (*offsetp + 4 > next_offset) {
857                 /* List runs past end of message. */
858                 return;
859             }
860             atom(tvb, offsetp, tt, hf_x11_properties_item);
861       }
862 }
863
864 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
865     int length)
866 {
867       if (*offsetp + length > next_offset) {
868             /* List runs past end of message. */
869             length = next_offset -  *offsetp;
870       }
871       if (length <= 0) length = 1;
872       proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
873       *offsetp += length;
874 }
875
876 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
877     int hf_item, int length)
878 {
879       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
880       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
881       while(length--) {
882             if (*offsetp + 4 > next_offset) {
883                 /* List runs past end of message. */
884                 return;
885             }
886             proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
887             *offsetp += 4;
888       }
889 }
890
891 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
892     int length)
893 {
894       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
895       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
896       while(length--) {
897             proto_item *tti;
898             proto_tree *ttt;
899             unsigned do_red_green_blue;
900             guint16 red, green, blue;
901             char buffer[1024];
902             char *bp;
903             const char *sep;
904
905             if (*offsetp + 12 > next_offset) {
906                 /* List runs past end of message. */
907                 return;
908             }
909             red = VALUE16(tvb, *offsetp + 4);
910             green = VALUE16(tvb, *offsetp + 6);
911             blue = VALUE16(tvb, *offsetp + 8);
912             do_red_green_blue = VALUE8(tvb, *offsetp + 10);
913
914             bp = buffer + sprintf(buffer, "colorItem: ");
915             sep = "";
916             if (do_red_green_blue & 0x1) {
917                 bp += sprintf(bp, "red = %d", red);
918                 sep = ", ";
919             }
920             if (do_red_green_blue & 0x2) {
921                 bp += sprintf(bp, "%sgreen = %d", sep, green);
922                 sep = ", ";
923             }
924             if (do_red_green_blue & 0x4)
925                 bp += sprintf(bp, "%sblue = %d", sep, blue);
926
927             tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
928             ttt = proto_item_add_subtree(tti, ett_x11_color_item);
929             proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
930             *offsetp += 4;
931             proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
932             *offsetp += 2;
933             proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
934             *offsetp += 2;
935             proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
936             *offsetp += 2;
937             colorFlags(tvb, offsetp, ttt);
938             proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
939             *offsetp += 1;
940       }
941 }
942
943 static GTree *keysymTable = NULL;
944
945 static gint compareGuint32(gconstpointer a, gconstpointer b)
946 {
947       return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);;
948 }
949
950 static const char *keysymString(guint32 v)
951 {
952       gpointer res;
953       if (!keysymTable) {
954
955             /* This table is so big that we built it only if necessary */
956
957             const value_string *p = keysym_vals_source;
958             keysymTable = g_tree_new(compareGuint32);
959             for(; p -> strptr; p++)
960                   g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
961       }
962       res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
963       return res ? res : "Unknown";
964 }
965
966 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
967
968 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
969     int length)
970 {
971       char buffer[1024];
972       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
973       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
974
975       while(length--) {
976             char *bp = buffer;
977             const char **m;
978             int i;
979
980             if (*offsetp + 8 > next_offset) {
981                 /* List runs past end of message. */
982                 return;
983             }
984             for(i = 8, m = modifiers; i; i--, m++) {
985                 u_char c = tvb_get_guint8(tvb, *offsetp);
986                 *offsetp += 1;
987                 if (c)
988                     bp += sprintf(bp, "  %s=%d", *m, c);
989             }
990
991             proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, *offsetp - 8, 8, tvb_get_ptr(tvb, *offsetp - 8, 8),      "item: %s", buffer);
992       }
993 }
994
995 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
996     int hf_item, int keycode_count, int keysyms_per_keycode)
997 {
998       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
999       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1000       proto_item *tti;
1001       proto_tree *ttt;
1002       int i;
1003       char buffer[128];
1004       char *bp;
1005
1006       while(keycode_count--) {
1007             if (*offsetp + keysyms_per_keycode * 4 > next_offset) {
1008                 /* List runs past end of message. */
1009                 return;
1010             }
1011             bp = buffer + sprintf(buffer, "keysyms:");
1012             for(i = 0; i < keysyms_per_keycode; i++) {
1013                   bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, *offsetp + i * 4)));
1014             }
1015             *bp = '\0';
1016             tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp, keysyms_per_keycode * 4,
1017                                                  "%s", buffer);
1018             ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1019             for(i = keysyms_per_keycode; i; i--) {
1020                   guint32 v = VALUE32(tvb, *offsetp);
1021                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, *offsetp, 4, v,
1022                                              "keysym: 0x%08x (%s)", v, keysymString(v));
1023                   *offsetp += 4;
1024             }
1025       }
1026 }
1027
1028 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf, int length)
1029 {
1030       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1031       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1032       while(length--) {
1033             gint16 x, y;
1034             proto_item *tti;
1035             proto_tree *ttt;
1036
1037             if (*offsetp + 4 > next_offset) {
1038                 /* List runs past end of message. */
1039                 return;
1040             }
1041             x = VALUE16(tvb, *offsetp);
1042             y = VALUE16(tvb, *offsetp + 2);
1043
1044             tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1045             ttt = proto_item_add_subtree(tti, ett_x11_point);
1046             proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1047             *offsetp += 2;
1048             proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1049             *offsetp += 2;
1050       }
1051 }
1052
1053 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1054     int length)
1055 {
1056       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1057       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1058       while(length--) {
1059             gint16 x, y;
1060             unsigned width, height;
1061             proto_item *tti;
1062             proto_tree *ttt;
1063
1064             if (*offsetp + 8 > next_offset) {
1065                 /* List runs past end of message. */
1066                 return;
1067             }
1068             x = VALUE16(tvb, *offsetp);
1069             y = VALUE16(tvb, *offsetp + 2);
1070             width = VALUE16(tvb, *offsetp + 4);
1071             height = VALUE16(tvb, *offsetp + 6);
1072
1073             tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8, 
1074                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1075             ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1076             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1077             *offsetp += 2;
1078             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1079             *offsetp += 2;
1080             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1081             *offsetp += 2;
1082             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1083             *offsetp += 2;
1084       }
1085 }
1086
1087 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1088     int length)
1089 {
1090       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1091       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1092       while(length--) {
1093             gint16 x1, y1, x2, y2;
1094             proto_item *tti;
1095             proto_tree *ttt;
1096
1097             if (*offsetp + 8 > next_offset) {
1098                 /* List runs past end of message. */
1099                 return;
1100             }
1101             x1 = VALUE16(tvb, *offsetp);
1102             y1 = VALUE16(tvb, *offsetp + 2);
1103             x2 = VALUE16(tvb, *offsetp + 4);
1104             y2 = VALUE16(tvb, *offsetp + 6);
1105
1106             tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8, 
1107                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1108             ttt = proto_item_add_subtree(tti, ett_x11_segment);
1109             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1110             *offsetp += 2;
1111             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1112             *offsetp += 2;
1113             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1114             *offsetp += 2;
1115             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1116             *offsetp += 2;
1117       }
1118 }
1119
1120 /* XXX - the protocol tree code should handle non-printable characters.
1121    Note that "non-printable characters" may depend on your locale.... */
1122 static void stringCopy(char *dest, const char *source, int length)
1123 {
1124       u_char c;
1125       while(length--) {
1126             c = *source++;
1127             if (!isgraph(c) && c != ' ') c = '.';
1128             *dest++ = c;
1129       }
1130       *dest++ = '\0';
1131 }
1132
1133 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1134     int hf_item, int length)
1135 {
1136       char *s = NULL;
1137       guint allocated = 0;
1138       proto_item *ti;
1139       proto_tree *tt;
1140       int i;
1141
1142       /* Compute total length */
1143       
1144       int scanning_offset = *offsetp; /* Scanning pointer */
1145       int l;
1146       for(i = length; i; i--) {
1147             l = tvb_get_guint8(tvb, scanning_offset);
1148             scanning_offset += 1 + l;
1149       }
1150
1151       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1152       tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1153
1154       /*
1155        * In case we throw an exception, clean up whatever stuff we've
1156        * allocated (if any).
1157        */
1158       CLEANUP_PUSH(g_free, s);
1159
1160       while(length--) {
1161             unsigned l = VALUE8(tvb, *offsetp);
1162             if (allocated < (l + 1)) {
1163                   /* g_realloc doesn't work ??? */
1164                   g_free(s);
1165                   s = g_malloc(l + 1);
1166                   allocated = l + 1;
1167             }
1168             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1169             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1170             *offsetp += l + 1;
1171       }
1172
1173       /*
1174        * Call the cleanup handler to free the string and pop the handler.
1175        */
1176       CLEANUP_CALL_AND_POP;
1177 }
1178
1179 #define STRING16_MAX_DISPLAYED_LENGTH 150
1180
1181 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1182 {
1183       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1184       for(; length > 0; offset += 2, length--) {
1185             if (tvb_get_guint8(tvb, offset))
1186                 return FALSE;
1187       }
1188       return TRUE;
1189 }
1190
1191 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1192
1193 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1194                                               int hf, int hf_bytes,
1195                                               int offset, unsigned length,
1196                                               char **s, int *sLength)
1197 {
1198       int truncated = FALSE;
1199       unsigned l = length / 2;
1200
1201       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1202             char *dp;
1203             int soffset = offset;
1204
1205             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1206                   truncated = TRUE;
1207                   l = STRING16_MAX_DISPLAYED_LENGTH;
1208             }
1209             if (*sLength < (int) l + 3) {
1210                   g_free(*s);
1211                   *s = g_malloc(l + 3);
1212                   *sLength = l + 3;
1213             }
1214             dp = *s;
1215             *dp++ = '"';
1216             if (truncated) l -= 3;
1217
1218             while(l--) {
1219                   soffset++;
1220                   *dp++ = tvb_get_guint8(tvb, soffset);
1221                   soffset++;
1222             }
1223             *dp++ = '"';
1224
1225             /* If truncated, add an ellipsis */
1226             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1227
1228             *dp++ = '\0';
1229             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s", 
1230                                         proto_registrar_get_nth(hf) -> name, *s);
1231       } else
1232             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1233
1234 }
1235
1236 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1237     int sizeIs16)
1238 {
1239       int allocated = 0;
1240       char *s = NULL;
1241       proto_item *ti;
1242       proto_tree *tt;
1243       guint32 fid;
1244
1245       /* Compute total length */
1246       
1247       int scanning_offset = *offsetp; /* Scanning pointer */
1248       int l;                            /* Length of an individual item */
1249       int n = 0;                        /* Number of items */
1250
1251       while(scanning_offset < next_offset) {
1252             l = tvb_get_guint8(tvb, scanning_offset);
1253             scanning_offset++;
1254             if (!l) break;
1255             n++;
1256             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1257       }
1258
1259       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1260       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
1261
1262       /*
1263        * In case we throw an exception, clean up whatever stuff we've
1264        * allocated (if any).
1265        */
1266       CLEANUP_PUSH(g_free, s);
1267
1268       while(n--) {
1269             unsigned l = VALUE8(tvb, *offsetp);
1270             if (l == 255) { /* Item is a font */
1271                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
1272                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
1273                   *offsetp += 5;
1274             } else { /* Item is a string */
1275                   proto_item *tti;
1276                   proto_tree *ttt;
1277                   gint8 delta = VALUE8(tvb, *offsetp + 1);
1278                   if (sizeIs16) l += l;
1279                   if ((unsigned) allocated < l + 1) {
1280                         /* g_realloc doesn't work ??? */
1281                         g_free(s);
1282                         s = g_malloc(l + 1);
1283                         allocated = l + 1;
1284                   }
1285                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
1286                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
1287                                                        "textitem (string): delta = %d, \"%s\"",
1288                                                        delta, s);
1289                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
1290                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
1291                   if (sizeIs16)
1292                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16, 
1293                                                           hf_x11_textitem_string_string16_bytes,
1294                                                           *offsetp + 2, l,
1295                                                            &s, &allocated);
1296                   else
1297                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb, 
1298                                                      *offsetp + 2, l, s, "\"%s\"", s);
1299                   *offsetp += l + 2;
1300             }
1301       }
1302
1303       /*
1304        * Call the cleanup handler to free the string and pop the handler.
1305        */
1306       CLEANUP_CALL_AND_POP;
1307 }
1308
1309 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1310 {
1311       guint32 v = VALUE8(tvb, *offsetp);
1312       header_field_info *hfi = proto_registrar_get_nth(hf);
1313       gchar *enumValue = NULL;
1314       gchar *nameAsChar = hfi -> name;
1315
1316       if (hfi -> strings)
1317             enumValue = match_strval(v, cVALS(hfi -> strings));
1318       if (enumValue)
1319             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
1320       else
1321             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
1322       *offsetp += 1;
1323       return v;
1324 }
1325
1326 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1327 {
1328       guint32 v = VALUE16(tvb, *offsetp);
1329       proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
1330       *offsetp += 2;
1331       return v;
1332 }
1333
1334 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1335 {
1336       guint32 v = VALUE32(tvb, *offsetp);
1337       header_field_info *hfi = proto_registrar_get_nth(hf);
1338       gchar *enumValue = NULL;
1339       gchar *nameAsChar = hfi -> name;
1340
1341       if (hfi -> strings)
1342             enumValue = match_strval(v, cVALS(hfi -> strings));
1343       if (enumValue)
1344             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1345       else
1346             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, 
1347                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1348                                        nameAsChar, v);
1349       *offsetp += 4;
1350       return v;
1351 }
1352
1353 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1354 {
1355       BITMASK32(gc_value);
1356       BITFIELD(ENUM8,  gc_value_mask, function);
1357       BITFIELD(CARD32, gc_value_mask, plane_mask);
1358       BITFIELD(CARD32, gc_value_mask, foreground);
1359       BITFIELD(CARD32, gc_value_mask, background);
1360       BITFIELD(CARD16, gc_value_mask, line_width);
1361       BITFIELD(ENUM8,  gc_value_mask, line_style);
1362       BITFIELD(ENUM8,  gc_value_mask, cap_style);
1363       BITFIELD(ENUM8,  gc_value_mask, join_style);
1364       BITFIELD(ENUM8,  gc_value_mask, fill_style);
1365       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
1366       BITFIELD(PIXMAP, gc_value_mask, tile);
1367       BITFIELD(PIXMAP, gc_value_mask, stipple);
1368       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
1369       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
1370       BITFIELD(FONT,   gc_value_mask, font);
1371       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
1372       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
1373       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
1374       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
1375       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1376       BITFIELD(CARD16, gc_value_mask, dash_offset);
1377       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
1378       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
1379       ENDBITMASK;
1380 }
1381
1382 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1383 {
1384       BITMASK32(gc_value);
1385       FLAG(gc_value, function);
1386       FLAG(gc_value, plane_mask);
1387       FLAG(gc_value, foreground);
1388       FLAG(gc_value, background);
1389       FLAG(gc_value, line_width);
1390       FLAG(gc_value, line_style);
1391       FLAG(gc_value, cap_style);
1392       FLAG(gc_value, join_style);
1393       FLAG(gc_value, fill_style);
1394       FLAG(gc_value, fill_rule);
1395       FLAG(gc_value, tile);
1396       FLAG(gc_value, stipple);
1397       FLAG(gc_value, tile_stipple_x_origin);
1398       FLAG(gc_value, tile_stipple_y_origin);
1399       FLAG(gc_value, font);
1400       FLAG(gc_value, subwindow_mode);
1401       FLAG(gc_value, graphics_exposures);
1402       FLAG(gc_value, clip_x_origin);
1403       FLAG(gc_value, clip_y_origin);
1404       FLAG(gc_value, clip_mask);
1405       FLAG(gc_value, dash_offset);
1406       FLAG(gc_value, gc_dashes);
1407       FLAG(gc_value, arc_mode);
1408       ENDBITMASK;
1409 }
1410
1411 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1412 {
1413       guint32 res = VALUE16(tvb, *offsetp) * 4;
1414       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
1415       *offsetp += 2;
1416       return res;
1417 }
1418
1419 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1420 {
1421       BITMASK32(event);
1422       FLAG(event, KeyPress);
1423       FLAG(event, KeyRelease);
1424       FLAG(event, ButtonPress);
1425       FLAG(event, ButtonRelease);
1426       FLAG(event, EnterWindow);
1427       FLAG(event, LeaveWindow);
1428       FLAG(event, PointerMotion);
1429       FLAG(event, PointerMotionHint);
1430       FLAG(event, Button1Motion);
1431       FLAG(event, Button2Motion);
1432       FLAG(event, Button3Motion);
1433       FLAG(event, Button4Motion);
1434       FLAG(event, Button5Motion);
1435       FLAG(event, ButtonMotion);
1436       FLAG(event, KeymapState);
1437       FLAG(event, Exposure);
1438       FLAG(event, VisibilityChange);
1439       FLAG(event, StructureNotify);
1440       FLAG(event, ResizeRedirect);
1441       FLAG(event, SubstructureNotify);
1442       FLAG(event, SubstructureRedirect);
1443       FLAG(event, FocusChange);
1444       FLAG(event, PropertyChange);
1445       FLAG(event, ColormapChange);
1446       FLAG(event, OwnerGrabButton);
1447       FLAG_IF_NONZERO(event, erroneous_bits);
1448       ENDBITMASK;
1449 }
1450
1451 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1452 {
1453       BITMASK32(do_not_propagate);
1454       FLAG(do_not_propagate, KeyPress);
1455       FLAG(do_not_propagate, KeyRelease);
1456       FLAG(do_not_propagate, ButtonPress);
1457       FLAG(do_not_propagate, ButtonRelease);
1458       FLAG(do_not_propagate, PointerMotion);
1459       FLAG(do_not_propagate, Button1Motion);
1460       FLAG(do_not_propagate, Button2Motion);
1461       FLAG(do_not_propagate, Button3Motion);
1462       FLAG(do_not_propagate, Button4Motion);
1463       FLAG(do_not_propagate, Button5Motion);
1464       FLAG(do_not_propagate, ButtonMotion);
1465       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
1466       ENDBITMASK;
1467 }
1468
1469 static void setOfKeyMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1470 {
1471       proto_item *ti;
1472       guint32 bitmask_value;
1473       int bitmask_offset;
1474       int bitmask_size;
1475       proto_tree *bitmask_tree;
1476
1477       bitmask_value = VALUE16(tvb, *offsetp);
1478       bitmask_offset = *offsetp;
1479       bitmask_size = 2;
1480       if (bitmask_value == 0x8000)
1481             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
1482                                        "modifiers-masks: 0x8000 (AnyModifier)");
1483       else {
1484             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2, 
1485                                                  bitmask_value);
1486             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
1487             FLAG(modifiers, Shift);
1488             FLAG(modifiers, Lock);
1489             FLAG(modifiers, Control);
1490             FLAG(modifiers, Mod1);
1491             FLAG(modifiers, Mod2);
1492             FLAG(modifiers, Mod3);
1493             FLAG(modifiers, Mod4);
1494             FLAG(modifiers, Mod5);
1495             FLAG_IF_NONZERO(modifiers, erroneous_bits);
1496       }
1497       *offsetp += 2; 
1498 }
1499
1500 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1501 {
1502       BITMASK16(pointer_event);
1503       FLAG(pointer_event, ButtonPress);
1504       FLAG(pointer_event, ButtonRelease);
1505       FLAG(pointer_event, EnterWindow);
1506       FLAG(pointer_event, LeaveWindow);
1507       FLAG(pointer_event, PointerMotion);
1508       FLAG(pointer_event, PointerMotionHint);
1509       FLAG(pointer_event, Button1Motion);
1510       FLAG(pointer_event, Button2Motion);
1511       FLAG(pointer_event, Button3Motion);
1512       FLAG(pointer_event, Button4Motion);
1513       FLAG(pointer_event, Button5Motion);
1514       FLAG(pointer_event, ButtonMotion);
1515       FLAG(pointer_event, KeymapState);
1516       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
1517       ENDBITMASK;
1518 }
1519
1520 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1521     const char *nameAsChar, int hf, unsigned length)
1522 {
1523       char *s = g_malloc(length + 1);
1524
1525       /*
1526        * In case we throw an exception, clean up whatever stuff we've
1527        * allocated (if any).
1528        */
1529       CLEANUP_PUSH(g_free, s);
1530
1531       stringCopy(s, tvb_get_ptr(tvb, *offsetp, length), length);
1532       proto_tree_add_string_format(t, hf, tvb, *offsetp, length, s, "%s: %s", nameAsChar, s);
1533
1534       /*
1535        * Call the cleanup handler to free the string and pop the handler.
1536        */
1537       CLEANUP_CALL_AND_POP;
1538
1539       *offsetp += length;
1540 }
1541
1542 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1543
1544 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1545     int hf_bytes, unsigned length)
1546 {
1547       char *s = NULL;
1548       unsigned l = 0;
1549
1550       /*
1551        * In case we throw an exception, clean up whatever stuff we've
1552        * allocated (if any).
1553        */
1554       CLEANUP_PUSH(g_free, s);
1555
1556       length += length;
1557       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length, &s, &l);
1558
1559       /*
1560        * Call the cleanup handler to free the string and pop the handler.
1561        */
1562       CLEANUP_CALL_AND_POP;
1563
1564       *offsetp += length;
1565 }
1566
1567 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1568     const char *nameAsChar, int hf)
1569 {
1570       guint32 v = VALUE32(tvb, *offsetp);
1571       if (!v)
1572             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1573       else
1574             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
1575       *offsetp += 4;
1576 }
1577
1578 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1579 {
1580       BITMASK32(window_value);
1581       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1582       BITFIELD(CARD32, window_value_mask, background_pixel);
1583       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1584       BITFIELD(CARD32, window_value_mask, border_pixel);
1585       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1586       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1587       BITFIELD(ENUM8, window_value_mask, backing_store);
1588       BITFIELD(CARD32, window_value_mask, backing_planes);
1589       BITFIELD(CARD32, window_value_mask, backing_pixel);
1590       BITFIELD(BOOL,   window_value_mask, override_redirect);
1591       BITFIELD(BOOL,   window_value_mask, save_under);
1592       BITFIELD(SETofEVENT, window_value_mask, event_mask);
1593       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1594       BITFIELD(COLORMAP, window_value_mask, colormap);
1595       BITFIELD(CURSOR, window_value_mask, cursor);
1596       ENDBITMASK;
1597 }
1598
1599 /************************************************************************
1600  ***                                                                  ***
1601  ***              D E C O D I N G   O N E   P A C K E T               ***
1602  ***                                                                  ***
1603  ************************************************************************/
1604
1605 static int dissect_x11_requests_loop(tvbuff_t *tvb, int *offsetp, proto_tree *root)
1606 {
1607       int left = tvb_reported_length(tvb), nextLeft;
1608       proto_item *ti;
1609       proto_tree *t;
1610       guint8 v8, v8_2;
1611       guint16 v16;
1612       guint32 v32;
1613
1614       /* The X11 data stream to the server is just a sequence of requests,
1615          each of which contains a length; for now, we dissect all the
1616          requests in this frame until we run out of data in the frame.
1617          Eventually, we should handle requests that cross frame
1618          boundaries.
1619
1620          Note that "in this frame" refers to everything in the frame
1621          as it appeared in the wire, not as it was captured; we want
1622          an exception to be thrown if we go past the end of the
1623          captured data in the frame without going past the end of the
1624          data in the frame. */
1625       for(;;) {
1626             int length, opcode;
1627             
1628             /* fprintf(stderr, "Starting loop, left = %d, *offsetp = %d\n", left, *offsetp); */
1629             if (left < 4) {
1630                 /* We ran out of data - we don't have enough data in
1631                    the frame to get the length of this request. */
1632                 break;
1633             }
1634             length = VALUE16(tvb, *offsetp + 2) * 4;
1635             /*      fprintf(stderr, "length = %d\n", length);*/
1636             if (left < length) {
1637                 /* We ran out of data - we don't have enough data in
1638                    the frame for the full request. */
1639                 break;
1640             }
1641             if (length < 4) {
1642                 /* Bogus message length? */
1643                 break;
1644             }
1645
1646             next_offset = *offsetp + length;
1647             nextLeft = left - length;
1648
1649             ti = proto_tree_add_uint(root, hf_x11_request, tvb, *offsetp, length, tvb_get_guint8(tvb, *offsetp));
1650             t = proto_item_add_subtree(ti, ett_x11_request);
1651
1652             OPCODE();
1653
1654             switch(opcode) {
1655                 case 1: /* CreateWindow */
1656                   CARD8(depth);
1657                   REQUEST_LENGTH();
1658                   WINDOW(wid);
1659                   WINDOW(parent);
1660                   INT16(x);
1661                   INT16(y);
1662                   CARD16(width);
1663                   CARD16(height);
1664                   CARD16(border_width);
1665                   ENUM16(window_class);
1666                   VISUALID(visual);
1667                   windowAttributes(tvb, offsetp, t);
1668                   break;
1669
1670                 case 2: /* ChangeWindowAttributes */
1671                   UNUSED(1);
1672                   REQUEST_LENGTH();
1673                   WINDOW(window);
1674                   windowAttributes(tvb, offsetp, t);
1675                   break;
1676
1677                 case 3: /* GetWindowAttributes */
1678                 case 4: /* DestroyWindow */
1679                 case 5: /* DestroySubwindows */
1680                   UNUSED(1);
1681                   REQUEST_LENGTH();
1682                   WINDOW(window);
1683                   break;
1684
1685                 case 6: /* ChangeSaveSet */
1686                   ENUM8(save_set_mode);
1687                   REQUEST_LENGTH();
1688                   WINDOW(window);
1689                   break;
1690
1691                 case 7: /* ReparentWindow */
1692                   UNUSED(1);
1693                   REQUEST_LENGTH();
1694                   WINDOW(window);
1695                   WINDOW(parent);
1696                   INT16(x);
1697                   INT16(y);
1698                   break;
1699
1700                 case 8: /* MapWindow */
1701                 case 9: /* MapSubWindow */
1702                 case 10: /* UnmapWindow */
1703                 case 11: /* UnmapSubwindows */
1704                   UNUSED(1);
1705                   REQUEST_LENGTH();
1706                   WINDOW(window);
1707                   break;
1708
1709                 case 12: /* ConfigureWindow */
1710                   UNUSED(1);
1711                   REQUEST_LENGTH();
1712                   WINDOW(window);
1713                   BITMASK16(configure_window);
1714                   UNUSED(2); 
1715                   BITFIELD(INT16,  configure_window_mask, x);
1716                   BITFIELD(INT16,  configure_window_mask, y);
1717                   BITFIELD(CARD16, configure_window_mask, width);
1718                   BITFIELD(CARD16, configure_window_mask, height);
1719                   BITFIELD(CARD16, configure_window_mask, border_width);
1720                   BITFIELD(WINDOW, configure_window_mask, sibling);
1721                   BITFIELD(ENUM8,  configure_window_mask, stack_mode);
1722                   ENDBITMASK;
1723                   PAD();
1724                   break;
1725
1726                 case 13: /* CirculateWindow */
1727                   ENUM8(direction);
1728                   REQUEST_LENGTH();
1729                   WINDOW(window);
1730                   break;
1731
1732                 case 14: /* GetGeometry */
1733                 case 15: /* QueryTree */
1734                   UNUSED(1);
1735                   REQUEST_LENGTH();
1736                   DRAWABLE(drawable);
1737                   break;
1738
1739                 case 16: /* InternAtom */
1740                   BOOL(only_if_exists);
1741                   REQUEST_LENGTH();
1742                   v16 = FIELD16(name_length);
1743                   UNUSED(2);
1744                   STRING8(name, v16);
1745                   PAD();
1746                   break;
1747
1748                 case 17: /* GetAtomName */
1749                   UNUSED(1);
1750                   REQUEST_LENGTH();
1751                   ATOM(atom);
1752                   break;
1753
1754                 case 18: /* ChangeProperty */
1755                   ENUM8(mode);
1756                   REQUEST_LENGTH();
1757                   WINDOW(window);
1758                   ATOM(property);
1759                   ATOM(type);
1760                   CARD8(format);
1761                   UNUSED(3);
1762                   v32 = CARD32(data_length);
1763                   LISTofBYTE(data, v32);
1764                   PAD();
1765                   break;
1766
1767                 case 19: /* DeleteProperty */
1768                   UNUSED(1);
1769                   REQUEST_LENGTH();
1770                   WINDOW(window);
1771                   ATOM(property);
1772                   break;
1773
1774                 case 20: /* GetProperty */
1775                   BOOL(delete);
1776                   REQUEST_LENGTH();
1777                   WINDOW(window);
1778                   ATOM(property);
1779                   ATOM(get_property_type);
1780                   CARD32(long_offset);
1781                   CARD32(long_length);
1782                   break;
1783
1784                 case 21: /* ListProperties */
1785                   UNUSED(1);
1786                   REQUEST_LENGTH();
1787                   WINDOW(window);
1788                   break;
1789
1790                 case 22: /* SetSelectionOwner */
1791                   UNUSED(1);
1792                   REQUEST_LENGTH();
1793                   WINDOW(owner);
1794                   ATOM(selection);
1795                   TIMESTAMP(time);
1796                   break;
1797
1798                 case 23: /* GetSelectionOwner */
1799                   UNUSED(1);
1800                   REQUEST_LENGTH();
1801                   ATOM(selection);
1802                   break;
1803
1804                 case 24: /* ConvertSelection */
1805                   UNUSED(1);
1806                   REQUEST_LENGTH();
1807                   WINDOW(requestor);
1808                   ATOM(selection);
1809                   ATOM(target);
1810                   ATOM(property);
1811                   TIMESTAMP(time);
1812                   break;
1813
1814                 case 26: /* GrabPointer */
1815                   BOOL(owner_events);
1816                   REQUEST_LENGTH();
1817                   WINDOW(grab_window);
1818                   SETofPOINTEREVENT(pointer_event_mask);
1819                   ENUM8(pointer_mode);
1820                   ENUM8(keyboard_mode);
1821                   WINDOW(confine_to);
1822                   CURSOR(cursor);
1823                   TIMESTAMP(time);
1824                   break;
1825
1826                 case 27: /* UngrabPointer */
1827                   UNUSED(1);
1828                   REQUEST_LENGTH();
1829                   TIMESTAMP(time);
1830                   break;
1831
1832                 case 28: /* GrabButton */
1833                   BOOL(owner_events);
1834                   REQUEST_LENGTH();
1835                   WINDOW(grab_window);
1836                   SETofPOINTEREVENT(event_mask);
1837                   ENUM8(pointer_mode);
1838                   ENUM8(keyboard_mode);
1839                   WINDOW(confine_to);
1840                   CURSOR(cursor);
1841                   BUTTON(button);
1842                   UNUSED(1);
1843                   SETofKEYMASK(modifiers);
1844                   break;
1845
1846                 case 29: /* UngrabButton */
1847                   BUTTON(button);
1848                   REQUEST_LENGTH();
1849                   WINDOW(grab_window);
1850                   SETofKEYMASK(modifiers);
1851                   UNUSED(2);
1852                   break;
1853
1854                 case 30: /* ChangeActivePointerGrab */
1855                   UNUSED(1);
1856                   REQUEST_LENGTH();
1857                   CURSOR(cursor);
1858                   TIMESTAMP(time);
1859                   SETofPOINTEREVENT(event_mask);
1860                   UNUSED(2);
1861                   break;
1862
1863                 case 31: /* GrabKeyboard */
1864                   BOOL(owner_events);
1865                   REQUEST_LENGTH();
1866                   WINDOW(grab_window);
1867                   TIMESTAMP(time);
1868                   ENUM8(pointer_mode);
1869                   ENUM8(keyboard_mode);
1870                   UNUSED(2);
1871                   break;
1872
1873                 case 32: /* UngrabKeyboard */
1874                   UNUSED(1);
1875                   REQUEST_LENGTH();
1876                   TIMESTAMP(time);
1877                   break;
1878
1879                 case 33: /* GrabKey */
1880                   BOOL(owner_events);
1881                   REQUEST_LENGTH();
1882                   WINDOW(grab_window);
1883                   SETofKEYMASK(modifiers);
1884                   KEYCODE(key);
1885                   ENUM8(pointer_mode);
1886                   ENUM8(keyboard_mode);
1887                   UNUSED(3);
1888                   break;
1889
1890                 case 34: /* UngrabKey */
1891                   KEYCODE(key);
1892                   REQUEST_LENGTH();
1893                   WINDOW(grab_window);
1894                   SETofKEYMASK(modifiers);
1895                   UNUSED(2);
1896                   break;
1897
1898                 case 35: /* AllowEvents */
1899                   ENUM8(allow_events_mode);
1900                   REQUEST_LENGTH();
1901                   TIMESTAMP(time);
1902                   break;
1903
1904                 case 36: /* GrabServer */
1905                   UNUSED(1);
1906                   REQUEST_LENGTH();
1907                   break;
1908
1909                 case 37: /* UngrabServer */
1910                   UNUSED(1);
1911                   REQUEST_LENGTH();
1912                   break;
1913
1914                 case 38: /* QueryPointer */
1915                   UNUSED(1);
1916                   REQUEST_LENGTH();
1917                   WINDOW(window);
1918                   break;
1919
1920                 case 39: /* GetMotionEvents */
1921                   UNUSED(1);
1922                   REQUEST_LENGTH();
1923                   WINDOW(window);
1924                   TIMESTAMP(start);
1925                   TIMESTAMP(stop);
1926                   break;
1927
1928                 case 40: /* TranslateCoordinates */
1929                   UNUSED(1);
1930                   REQUEST_LENGTH();
1931                   WINDOW(src_window);
1932                   WINDOW(dst_window);
1933                   INT16(src_x);
1934                   INT16(src_y);
1935                   break;
1936
1937                 case 41: /* WarpPointer */
1938                   UNUSED(1);
1939                   REQUEST_LENGTH();
1940                   WINDOW(warp_pointer_src_window);
1941                   WINDOW(warp_pointer_dst_window);
1942                   INT16(src_x);
1943                   INT16(src_y);
1944                   CARD16(src_width);
1945                   CARD16(src_height);
1946                   INT16(dst_x);
1947                   INT16(dst_y);
1948                   break;
1949
1950                 case 42: /* SetInputFocus */
1951                   ENUM8(revert_to);
1952                   REQUEST_LENGTH();
1953                   WINDOW(focus);
1954                   TIMESTAMP(time);
1955                   break;
1956
1957                 case 43: /* GetInputFocus */
1958                   UNUSED(1);
1959                   REQUEST_LENGTH();
1960                   break;
1961
1962                 case 44: /* QueryKeymap */
1963                   UNUSED(1);
1964                   REQUEST_LENGTH();
1965                   break;
1966
1967                 case 45: /* OpenFont */
1968                   UNUSED(1);
1969                   REQUEST_LENGTH();
1970                   FONT(fid);
1971                   v16 = FIELD16(name_length);
1972                   UNUSED(2);
1973                   STRING8(name, v16);
1974                   PAD();
1975                   break;
1976
1977                 case 46: /* CloseFont */
1978                   UNUSED(1);
1979                   REQUEST_LENGTH();
1980                   FONT(font);
1981                   break;
1982
1983                 case 47: /* QueryFont */
1984                   UNUSED(1);
1985                   REQUEST_LENGTH();
1986                   FONTABLE(font);
1987                   break;
1988
1989                 case 48: /* QueryTextExtents */
1990                   v8 = BOOL(odd_length);
1991                   REQUEST_LENGTH();
1992                   FONTABLE(font);
1993                   STRING16(string16, (next_offset - *offsetp - (v8 ? 2 : 0)) / 2);
1994                   PAD();
1995                   break;
1996
1997                 case 49: /* ListFonts */
1998                   UNUSED(1);
1999                   REQUEST_LENGTH();
2000                   CARD16(max_names);
2001                   v16 = FIELD16(pattern_length);
2002                   STRING8(pattern, v16);
2003                   PAD();
2004                   break;
2005
2006                 case 50: /* ListFontsWithInfo */
2007                   UNUSED(1);
2008                   REQUEST_LENGTH();
2009                   CARD16(max_names);
2010                   v16 = FIELD16(pattern_length);
2011                   STRING8(pattern, v16);
2012                   PAD();
2013                   break;
2014
2015                 case 51: /* SetFontPath */
2016                   UNUSED(1);
2017                   REQUEST_LENGTH();
2018                   v16 = CARD16(str_number_in_path);
2019                   UNUSED(2);
2020                   LISTofSTRING8(path, v16);
2021                   PAD();
2022                   break;
2023
2024                 case 52: /* GetFontPath */
2025                   UNUSED(1);
2026                   REQUEST_LENGTH();
2027                   break;
2028
2029                 case 53: /* CreatePixmap */
2030                   CARD8(depth);
2031                   REQUEST_LENGTH();
2032                   PIXMAP(pid);
2033                   DRAWABLE(drawable);
2034                   CARD16(width);
2035                   CARD16(height);
2036                   break;
2037
2038                 case 54: /* FreePixmap */
2039                   UNUSED(1);
2040                   REQUEST_LENGTH();
2041                   PIXMAP(pixmap);
2042                   break;
2043
2044                 case 55: /* CreateGC */
2045                   UNUSED(1);
2046                   REQUEST_LENGTH();
2047                   GCONTEXT(cid);
2048                   DRAWABLE(drawable);
2049                   gcAttributes(tvb, offsetp, t);
2050                   break;
2051
2052                 case 56: /* ChangeGC */
2053                   UNUSED(1);
2054                   REQUEST_LENGTH();
2055                   GCONTEXT(gc);
2056                   gcAttributes(tvb, offsetp, t);
2057                   break;
2058
2059                 case 57: /* CopyGC */
2060                   UNUSED(1);
2061                   REQUEST_LENGTH();
2062                   GCONTEXT(src_gc);
2063                   GCONTEXT(dst_gc);
2064                   gcMask(tvb, offsetp, t);
2065                   break;
2066
2067                 case 58: /* SetDashes */
2068                   UNUSED(1);
2069                   REQUEST_LENGTH();
2070                   GCONTEXT(gc);
2071                   CARD16(dash_offset);
2072                   v16 = FIELD16(dashes_length);
2073                   LISTofCARD8(dashes, v16);
2074                   PAD();
2075                   break;
2076
2077                 case 59: /* SetClipRectangles */
2078                   ENUM8(ordering);
2079                   REQUEST_LENGTH();
2080                   GCONTEXT(gc);
2081                   INT16(clip_x_origin);
2082                   INT16(clip_y_origin);
2083                   LISTofRECTANGLE(rectangles);
2084                   break;
2085
2086                 case 60: /* FreeGC */
2087                   UNUSED(1);
2088                   REQUEST_LENGTH();
2089                   GCONTEXT(gc);
2090                   break;
2091
2092                 case 61: /* ClearArea */
2093                   BOOL(exposures);
2094                   REQUEST_LENGTH();
2095                   WINDOW(window);
2096                   INT16(x);
2097                   INT16(y);
2098                   CARD16(width);
2099                   CARD16(height);
2100                   break;
2101
2102                 case 62: /* CopyArea */
2103                   UNUSED(1);
2104                   REQUEST_LENGTH();
2105                   DRAWABLE(src_drawable);
2106                   DRAWABLE(dst_drawable);
2107                   GCONTEXT(gc);
2108                   INT16(src_x);
2109                   INT16(src_y);
2110                   INT16(dst_x);
2111                   INT16(dst_y);
2112                   CARD16(width);
2113                   CARD16(height);
2114                   break;
2115
2116                 case 63: /* CopyPlane */
2117                   UNUSED(1);
2118                   REQUEST_LENGTH();
2119                   DRAWABLE(src_drawable);
2120                   DRAWABLE(dst_drawable);
2121                   GCONTEXT(gc);
2122                   INT16(src_x);
2123                   INT16(src_y);
2124                   INT16(dst_x);
2125                   INT16(dst_y);
2126                   CARD16(width);
2127                   CARD16(height);
2128                   CARD32(bit_plane);
2129                   break;
2130
2131                 case 64: /* PolyPoint */
2132                   ENUM8(coordinate_mode);
2133                   v16 = REQUEST_LENGTH();
2134                   DRAWABLE(drawable);
2135                   GCONTEXT(gc);
2136                   LISTofPOINT(points, v16 - 12);
2137                   break;
2138
2139                 case 65: /* PolyLine */
2140                   ENUM8(coordinate_mode);
2141                   v16 = REQUEST_LENGTH();
2142                   DRAWABLE(drawable);
2143                   GCONTEXT(gc);
2144                   LISTofPOINT(points, v16 - 12);
2145                   break;
2146
2147                 case 66: /* PolySegment */
2148                   UNUSED(1);
2149                   REQUEST_LENGTH();
2150                   DRAWABLE(drawable);
2151                   GCONTEXT(gc);
2152                   LISTofSEGMENT(segments);
2153                   break;
2154
2155                 case 67: /* PolyRectangle */
2156                   UNUSED(1);
2157                   REQUEST_LENGTH();
2158                   DRAWABLE(drawable);
2159                   GCONTEXT(gc);
2160                   LISTofRECTANGLE(rectangles);
2161                   break;
2162
2163                 case 68: /* PolyArc */
2164                   UNUSED(1);
2165                   REQUEST_LENGTH();
2166                   DRAWABLE(drawable);
2167                   GCONTEXT(gc);
2168                   LISTofARC(arcs);
2169                   break;
2170
2171                 case 69: /* FillPoly */
2172                   UNUSED(1);
2173                   v16 = REQUEST_LENGTH();
2174                   DRAWABLE(drawable);
2175                   GCONTEXT(gc);
2176                   ENUM8(shape);
2177                   ENUM8(coordinate_mode);
2178                   UNUSED(2);
2179                   LISTofPOINT(points, v16 - 16);
2180                   break;
2181
2182                 case 70: /* PolyFillRectangle */
2183                   UNUSED(1);
2184                   REQUEST_LENGTH();
2185                   DRAWABLE(drawable);
2186                   GCONTEXT(gc);
2187                   LISTofRECTANGLE(rectangles);
2188                   break;
2189
2190                 case 71: /* PolyFillArc */
2191                   UNUSED(1);
2192                   REQUEST_LENGTH();
2193                   DRAWABLE(drawable);
2194                   GCONTEXT(gc);
2195                   LISTofARC(arcs);
2196                   break;
2197
2198                 case 72: /* PutImage */
2199                   ENUM8(image_format);
2200                   v16 = REQUEST_LENGTH();
2201                   DRAWABLE(drawable);
2202                   GCONTEXT(gc);
2203                   CARD16(width);
2204                   CARD16(height);
2205                   INT16(dst_x);
2206                   INT16(dst_y);
2207                   CARD8(left_pad);
2208                   CARD8(depth);
2209                   UNUSED(2);
2210                   LISTofBYTE(data, v16 - 24);
2211                   PAD();
2212                   break;
2213
2214                 case 73: /* GetImage */
2215                   ENUM8(image_pixmap_format);
2216                   REQUEST_LENGTH();
2217                   DRAWABLE(drawable);
2218                   INT16(x);
2219                   INT16(y);
2220                   CARD16(width);
2221                   CARD16(height);
2222                   CARD32(plane_mask);
2223                   break;
2224
2225                 case 74: /* PolyText8 */
2226                   UNUSED(1);
2227                   v16 = REQUEST_LENGTH();
2228                   DRAWABLE(drawable);
2229                   GCONTEXT(gc);
2230                   INT16(x);
2231                   INT16(y);
2232                   LISTofTEXTITEM8(items);
2233                   PAD();
2234                   break;
2235
2236                 case 75: /* PolyText16 */
2237                   UNUSED(1);
2238                   v16 = REQUEST_LENGTH();
2239                   DRAWABLE(drawable);
2240                   GCONTEXT(gc);
2241                   INT16(x);
2242                   INT16(y);
2243                   LISTofTEXTITEM16(items);
2244                   PAD();
2245                   break;
2246
2247                 case 76: /* ImageText8 */
2248                   v8 = FIELD8(string_length);
2249                   REQUEST_LENGTH();
2250                   DRAWABLE(drawable);
2251                   GCONTEXT(gc);
2252                   INT16(x);
2253                   INT16(y);
2254                   STRING8(string, v8);
2255                   PAD();
2256                   break;
2257
2258                 case 77: /* ImageText16 */
2259                   v8 = FIELD8(string_length);
2260                   REQUEST_LENGTH();
2261                   DRAWABLE(drawable);
2262                   GCONTEXT(gc);
2263                   INT16(x);
2264                   INT16(y);
2265                   STRING16(string16, v8);
2266                   PAD();
2267                   break;
2268
2269                 case 78: /* CreateColormap */
2270                   ENUM8(alloc);
2271                   REQUEST_LENGTH();
2272                   COLORMAP(mid);
2273                   WINDOW(window);
2274                   VISUALID(visual);
2275                   break;
2276
2277                 case 79: /* FreeColormap */
2278                   UNUSED(1);
2279                   REQUEST_LENGTH();
2280                   COLORMAP(cmap);
2281                   break;
2282
2283                 case 80: /* CopyColormapAndFree */
2284                   UNUSED(1);
2285                   REQUEST_LENGTH();
2286                   COLORMAP(mid);
2287                   COLORMAP(src_cmap);
2288                   break;
2289
2290                 case 81: /* InstallColormap */
2291                   UNUSED(1);
2292                   REQUEST_LENGTH();
2293                   COLORMAP(cmap);
2294                   break;
2295
2296                 case 82: /* UninstallColormap */
2297                   UNUSED(1);
2298                   REQUEST_LENGTH();
2299                   COLORMAP(cmap);
2300                   break;
2301
2302                 case 83: /* ListInstalledColormaps */
2303                   UNUSED(1);
2304                   REQUEST_LENGTH();
2305                   WINDOW(window);
2306                   break;
2307
2308                 case 84: /* AllocColor */
2309                   UNUSED(1);
2310                   REQUEST_LENGTH();
2311                   COLORMAP(cmap);
2312                   CARD16(red);
2313                   CARD16(green);
2314                   CARD16(blue);
2315                   UNUSED(2);
2316                   break;
2317
2318                 case 85: /* AllocNamedColor */
2319                   UNUSED(1);
2320                   REQUEST_LENGTH();
2321                   COLORMAP(cmap);
2322                   v16 = FIELD16(name_length);
2323                   UNUSED(2);
2324                   STRING8(name, v16);
2325                   PAD();
2326                   break;
2327
2328                 case 86: /* AllocColorCells */
2329                   BOOL(contiguous);
2330                   REQUEST_LENGTH();
2331                   COLORMAP(cmap);
2332                   CARD16(colors);
2333                   CARD16(planes);
2334                   break;
2335
2336                 case 87: /* AllocColorPlanes */
2337                   BOOL(contiguous);
2338                   REQUEST_LENGTH();
2339                   COLORMAP(cmap);
2340                   CARD16(colors);
2341                   CARD16(reds);
2342                   CARD16(greens);
2343                   CARD16(blues);
2344                   break;
2345
2346                 case 88: /* FreeColors */
2347                   UNUSED(1);
2348                   v16 = REQUEST_LENGTH();
2349                   COLORMAP(cmap);
2350                   CARD32(plane_mask);
2351                   LISTofCARD32(pixels, v16 - 12);
2352                   break;
2353
2354                 case 89: /* StoreColors */
2355                   UNUSED(1);
2356                   v16 = REQUEST_LENGTH();
2357                   COLORMAP(cmap);
2358                   LISTofCOLORITEM(color_items, v16 - 8);
2359                   break;
2360
2361                 case 90: /* StoreNamedColor */
2362                   COLOR_FLAGS(color);
2363                   REQUEST_LENGTH();
2364                   COLORMAP(cmap);
2365                   CARD32(pixel);        
2366                   v16 = FIELD16(name_length);
2367                   UNUSED(2);
2368                   STRING8(name, v16);
2369                   PAD();
2370                   break;
2371
2372                 case 91: /* QueryColors */
2373                   UNUSED(1);
2374                   v16 = REQUEST_LENGTH();
2375                   COLORMAP(cmap);
2376                   LISTofCARD32(pixels, v16 - 8);
2377                   break;
2378
2379                 case 92: /* LookupColor */
2380                   UNUSED(1);
2381                   REQUEST_LENGTH();
2382                   COLORMAP(cmap);
2383                   v16 = FIELD16(name_length);
2384                   UNUSED(2);
2385                   STRING8(name, v16);
2386                   PAD();
2387                   break;
2388
2389                 case 93: /* CreateCursor */
2390                   UNUSED(1);
2391                   REQUEST_LENGTH();
2392                   CURSOR(cid);
2393                   PIXMAP(source_pixmap);
2394                   PIXMAP(mask);
2395                   CARD16(fore_red);
2396                   CARD16(fore_green);
2397                   CARD16(fore_blue);
2398                   CARD16(back_red);
2399                   CARD16(back_green);
2400                   CARD16(back_blue);
2401                   CARD16(x);
2402                   CARD16(y);
2403                   break;
2404
2405                 case 94: /* CreateGlyphCursor */
2406                   UNUSED(1);
2407                   REQUEST_LENGTH();
2408                   CURSOR(cid);
2409                   FONT(source_font);
2410                   FONT(mask_font);
2411                   CARD16(source_char);
2412                   CARD16(mask_char);
2413                   CARD16(fore_red);
2414                   CARD16(fore_green);
2415                   CARD16(fore_blue);
2416                   CARD16(back_red);
2417                   CARD16(back_green);
2418                   CARD16(back_blue);
2419                   break;
2420
2421                 case 95: /* FreeCursor */
2422                   UNUSED(1);
2423                   REQUEST_LENGTH();
2424                   CURSOR(cursor);
2425                   break;
2426
2427                 case 96: /* RecolorCursor */
2428                   UNUSED(1);
2429                   REQUEST_LENGTH();
2430                   CURSOR(cursor);
2431                   CARD16(fore_red);
2432                   CARD16(fore_green);
2433                   CARD16(fore_blue);
2434                   CARD16(back_red);
2435                   CARD16(back_green);
2436                   CARD16(back_blue);
2437                   break;
2438
2439                 case 97: /* QueryBestSize */
2440                   ENUM8(class);
2441                   REQUEST_LENGTH();
2442                   DRAWABLE(drawable);
2443                   CARD16(width);
2444                   CARD16(height);
2445                   break;
2446
2447                 case 98: /* QueryExtension */
2448                   UNUSED(1);
2449                   REQUEST_LENGTH();
2450                   v16 = FIELD16(name_length);
2451                   UNUSED(2);
2452                   STRING8(name, v16);
2453                   PAD();
2454                   break;
2455
2456                 case 99: /* ListExtensions */
2457                   UNUSED(1);
2458                   REQUEST_LENGTH();
2459                   break;
2460
2461                 case 100: /* ChangeKeyboardMapping */
2462                   v8 = FIELD8(keycode_count);
2463                   REQUEST_LENGTH();
2464                   KEYCODE(first_keycode);
2465                   v8_2 = FIELD8(keysyms_per_keycode);
2466                   UNUSED(2);
2467                   LISTofKEYSYM(keysyms, v8, v8_2);
2468                   break;
2469
2470                 case 101: /* GetKeyboardMapping */
2471                   UNUSED(1);
2472                   REQUEST_LENGTH();
2473                   KEYCODE(first_keycode);
2474                   FIELD8(count);
2475                   UNUSED(2);
2476                   break;
2477
2478                 case 102: /* ChangeKeyboardControl */
2479                   UNUSED(1);
2480                   REQUEST_LENGTH();
2481                   BITMASK32(keyboard_value);
2482                   BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2483                   BITFIELD(INT8, keyboard_value_mask, bell_percent);
2484                   BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2485                   BITFIELD(INT16, keyboard_value_mask, bell_duration);
2486                   BITFIELD(INT16, keyboard_value_mask, led);
2487                   BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2488                   BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2489                   BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2490                   ENDBITMASK;
2491                   break;
2492
2493                 case 103: /* GetKeyboardControl */
2494                   UNUSED(1);
2495                   REQUEST_LENGTH();
2496                   break;
2497
2498                 case 104: /* Bell */
2499                   INT8(percent);
2500                   REQUEST_LENGTH();
2501                   break;
2502
2503                 case 105: /* ChangePointerControl */
2504                   UNUSED(1);
2505                   REQUEST_LENGTH();
2506                   INT16(acceleration_numerator);
2507                   INT16(acceleration_denominator);
2508                   INT16(threshold);
2509                   BOOL(do_acceleration);
2510                   BOOL(do_threshold);
2511                   break;
2512
2513                 case 106: /* GetPointerControl */
2514                   UNUSED(1);
2515                   REQUEST_LENGTH();
2516                   break;
2517
2518                 case 107: /* SetScreenSaver */
2519                   UNUSED(1);
2520                   REQUEST_LENGTH();
2521                   INT16(timeout);
2522                   INT16(interval);
2523                   ENUM8(prefer_blanking);
2524                   ENUM8(allow_exposures);
2525                   UNUSED(2);
2526                   break;
2527
2528                 case 108: /* GetScreenSaver */
2529                   UNUSED(1);
2530                   REQUEST_LENGTH();
2531                   break;
2532
2533                 case 109: /* ChangeHosts */
2534                   ENUM8(change_host_mode);
2535                   REQUEST_LENGTH();
2536                   ENUM8(family);
2537                   UNUSED(1);
2538                   v16 = CARD16(address_length);
2539                   LISTofCARD8(address, v16);
2540                   break;
2541
2542                 case 110: /* ListHosts */
2543                   UNUSED(1);
2544                   REQUEST_LENGTH();
2545                   break;
2546
2547                 case 111: /* SetAccessControl */
2548                   ENUM8(access_mode);
2549                   REQUEST_LENGTH();
2550                   break;
2551
2552                 case 112: /* SetCloseDownMode */
2553                   ENUM8(close_down_mode);
2554                   REQUEST_LENGTH();
2555                   break;
2556
2557                 case 113: /* KillClient */
2558                   UNUSED(1);
2559                   REQUEST_LENGTH();
2560                   CARD32(resource);
2561                   break;
2562
2563                 case 114: /* RotateProperties */
2564                   UNUSED(1);
2565                   v16 = REQUEST_LENGTH();
2566                   WINDOW(window);
2567                   CARD16(property_number);
2568                   INT16(delta);
2569                   LISTofATOM(properties, (v16 - 12));
2570                   break;
2571
2572                 case 115: /* ForceScreenSaver */
2573                   ENUM8(screen_saver_mode);
2574                   REQUEST_LENGTH();
2575                   break;
2576
2577                 case 116: /* SetPointerMapping */
2578                   v8 = FIELD8(map_length);
2579                   REQUEST_LENGTH();
2580                   LISTofCARD8(map, v8);
2581                   PAD();
2582                   break;
2583
2584                 case 117: /* GetPointerMapping */
2585                   UNUSED(1);
2586                   REQUEST_LENGTH();
2587                   break;
2588
2589                 case 118: /* SetModifierMapping */
2590                   v8 = FIELD8(keycodes_per_modifier);
2591                   REQUEST_LENGTH();
2592                   LISTofKEYCODE(keycodes, v8);
2593                   break;
2594
2595                 case 119: /* GetModifierMapping */
2596                   UNUSED(1);
2597                   REQUEST_LENGTH();
2598                   break;
2599                   
2600                 case 127: /* NoOperation */
2601                   UNUSED(1);
2602                   REQUEST_LENGTH();
2603                   break;
2604             }
2605             if (*offsetp < next_offset)
2606                   proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, next_offset - *offsetp, little_endian);
2607             *offsetp = next_offset;
2608             left = nextLeft;
2609       }
2610
2611       return left;
2612 }
2613
2614 /************************************************************************
2615  ***                                                                  ***
2616  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2617  ***                                                                  ***
2618  ************************************************************************/
2619
2620 static GTree *byte_ordering_cache = NULL;
2621 static GMemChunk *address_chunk = NULL;
2622 static GMemChunk *ipv4_chunk = NULL;
2623 static GMemChunk *ipv6_chunk = NULL;
2624
2625 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2626 {
2627       const address *a = (const address *)aa;
2628       const address *b = (const address *)bb;
2629       int c = b -> type - a -> type;
2630       if (c) return c;
2631       c = b -> len - a -> len;
2632       if (c) return c;
2633       return memcmp(b -> data, a -> data, a -> len);
2634 }
2635
2636 /* If we can't guess, we return TRUE (that is little_endian), cause
2637    I'm developing on a Linux box :-). The (non-)guess isn't cached
2638    however, so we may have more luck next time. I'm quite conservative
2639    in my assertions, cause once it's cached, it's stay in cache, and
2640    we may be fooled up by a packet starting with the end of a request
2641    started in a previous packet...
2642 */
2643
2644 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2645
2646 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2647 {
2648       int res = 0;
2649       while(maskLength--) {
2650             int c = tvb_get_guint8(tvb, offset);
2651             offset++;
2652             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2653       }
2654       return res;
2655 }
2656
2657 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2658 {
2659       if (listLength > length) return FALSE;
2660       while(listLength--) {
2661             int l;
2662             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2663             l = tvb_get_guint8(tvb, offset);
2664             if (!l) break;
2665             l++;
2666             if (l > length) return FALSE;
2667             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2668             offset += l;
2669             length -= l;
2670       }
2671       if (length > 3) return FALSE;
2672       return TRUE;
2673 }
2674
2675 static int rounded4(int n)
2676 {
2677       int remainder = n % 4;
2678       int res = n / 4;
2679       if (remainder) res++;
2680       return res;
2681 }
2682
2683 /* We assume the order to be consistent, until proven wrong. */
2684
2685 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2686 {
2687       switch(tvb_get_guint8(tvb, offset)) {
2688           case 1: /* CreateWindow */
2689             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2690
2691           case 2: /* ChangeWindowAttributes */
2692           case 56: /* ChangeGC */
2693             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2694
2695           case 3: /* GetWindowAttributes */
2696           case 4: /* DestroyWindow */
2697           case 5: /* DestroySubwindows */
2698           case 6: /* ChangeSaveSet */
2699           case 8: /* MapWindow */
2700           case 9: /* MapSubWindow */
2701           case 10: /* UnmapWindow */
2702           case 11: /* UnmapSubwindows */
2703           case 13: /* CirculateWindow */
2704           case 14: /* GetGeometry */
2705           case 15: /* QueryTree */
2706           case 17: /* GetAtomName */
2707           case 21: /* ListProperties */
2708           case 23: /* GetSelectionOwner */
2709           case 27: /* UngrabPointer */
2710           case 32: /* UngrabKeyboard */
2711           case 35: /* AllowEvents */
2712           case 38: /* QueryPointer */
2713           case 46: /* CloseFont */
2714           case 47: /* QueryFont */
2715           case 54: /* FreePixmap */
2716           case 60: /* FreeGC */
2717           case 79: /* FreeColormap */
2718           case 81: /* InstallColormap */
2719           case 82: /* UninstallColormap */
2720           case 83: /* ListInstalledColormaps */
2721           case 95: /* FreeCursor */
2722           case 101: /* GetKeyboardMapping */
2723           case 113: /* KillClient */
2724             return length == 2;
2725
2726           case 7: /* ReparentWindow */
2727           case 22: /* SetSelectionOwner */
2728           case 30: /* ChangeActivePointerGrab */
2729           case 31: /* GrabKeyboard */
2730           case 33: /* GrabKey */
2731           case 39: /* GetMotionEvents */
2732           case 40: /* TranslateCoordinates */
2733           case 53: /* CreatePixmap */
2734           case 57: /* CopyGC */
2735           case 61: /* ClearArea */
2736           case 78: /* CreateColormap */
2737           case 84: /* AllocColor */
2738           case 87: /* AllocColorPlanes */
2739             return length == 4;
2740
2741           case 12: /* ConfigureWindow */
2742             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2743
2744           case 16: /* InternAtom */
2745           case 98: /* QueryExtension */
2746             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2747
2748           case 18: /* ChangeProperty */
2749             {
2750                   int multiplier, type;
2751                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2752                   type = tvb_get_guint8(tvb, 16);
2753                   if (type != 8 && type != 16 && type != 32) return FALSE;
2754                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2755                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2756                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2757             }
2758
2759           case 19: /* DeleteProperty */
2760           case 29: /* UngrabButton */
2761           case 34: /* UngrabKey */
2762           case 42: /* SetInputFocus */
2763           case 80: /* CopyColormapAndFree */
2764           case 86: /* AllocColorCells */
2765           case 97: /* QueryBestSize */
2766           case 105: /* ChangePointerControl */
2767           case 107: /* SetScreenSaver */
2768             return length == 3;
2769
2770           case 20: /* GetProperty */
2771           case 24: /* ConvertSelection */
2772           case 26: /* GrabPointer */
2773           case 28: /* GrabButton */
2774           case 41: /* WarpPointer */
2775             return length == 6;
2776
2777           case 25: /* SendEvent */
2778             return length == 11;
2779
2780           case 36: /* GrabServer */
2781           case 37: /* UngrabServer */
2782           case 43: /* GetInputFocus */
2783           case 44: /* QueryKeymap */
2784           case 52: /* GetFontPath */
2785           case 99: /* ListExtensions */
2786           case 103: /* GetKeyboardControl */
2787           case 104: /* Bell */
2788           case 106: /* GetPointerControl */
2789           case 108: /* GetScreenSaver */
2790           case 110: /* ListHosts */
2791           case 111: /* SetAccessControl */
2792           case 112: /* SetCloseDownMode */
2793           case 115: /* ForceScreenSaver */
2794           case 117: /* GetPointerMapping */
2795           case 119: /* GetModifierMapping */
2796             return length == 1;
2797
2798           case 45: /* OpenFont */
2799           case 85: /* AllocNamedColor */
2800           case 92: /* LookupColor */
2801             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2802
2803           case 48: /* QueryTextExtents */
2804             return length >= 2;
2805
2806           case 49: /* ListFonts */
2807           case 50: /* ListFontsWithInfo */
2808           case 109: /* ChangeHosts */
2809             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2810
2811           case 51: /* SetFontPath */
2812             if (length < 2) return FALSE;
2813             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2814             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2815
2816           case 55: /* CreateGC */
2817             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2818
2819           case 58: /* SetDashes */
2820             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2821
2822           case 59: /* SetClipRectangles */
2823           case 66: /* PolySegment */
2824           case 67: /* PolyRectangle */
2825           case 70: /* PolyFillRectangle */
2826             return length >= 3 && (length - 3) % 2 == 0;
2827
2828           case 62: /* CopyArea */
2829             return length == 7;
2830
2831           case 63: /* CopyPlane */
2832           case 93: /* CreateCursor */
2833           case 94: /* CreateGlyphCursor */
2834             return length == 8;
2835
2836           case 64: /* PolyPoint */
2837           case 65: /* PolyLine */
2838           case 88: /* FreeColors */
2839             return length >= 3;
2840
2841           case 68: /* PolyArc */
2842           case 71: /* PolyFillArc */
2843             return length >= 3 && (length - 3) % 3 == 0;
2844
2845           case 69: /* FillPoly */
2846           case 76: /* ImageText8 */
2847             return length >= 4;
2848
2849           case 72: /* PutImage */
2850             return length >= 6;
2851
2852           case 73: /* GetImage */
2853           case 96: /* RecolorCursor */
2854             return length == 5;
2855
2856           case 74: /* PolyText8 */
2857             if (length < 4) return FALSE;
2858             return TRUE; /* We don't perform many controls on this one */
2859
2860           case 75: /* PolyText16 */
2861             if (length < 4) return FALSE;
2862             return TRUE; /* We don't perform many controls on this one */
2863
2864           case 77: /* ImageText16 */
2865             return length >= 4;
2866
2867           case 89: /* StoreColors */
2868             return length > 2 && (length - 2) % 3 == 0;
2869
2870           case 90: /* StoreNamedColor */
2871             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2872
2873           case 91: /* QueryColors */
2874             return length >= 2;
2875
2876           case 100: /* ChangeKeyboardMapping */
2877             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2878
2879           case 102: /* ChangeKeyboardControl */
2880             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2881
2882           case 114: /* RotateProperties */
2883             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2884
2885           case 116: /* SetPointerMapping */
2886             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2887
2888           case 118: /* SetModifierMapping */
2889             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2890             
2891           case 127: /* NoOperation */
2892             return length >= 1;
2893
2894           default:
2895             return TRUE;
2896       }
2897 }
2898
2899 /* -1 means doesn't match, +1 means match, 0 means don't know */
2900
2901 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2902 {
2903       int offset, nextoffset;
2904       int atLeastOne = 0;
2905
2906       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2907             int length;
2908             length = v16(tvb, offset + 2);
2909             if (!length) return -1;
2910             nextoffset = offset + length * 4;
2911             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2912             atLeastOne = 1;
2913       }
2914       return atLeastOne;
2915 }
2916
2917 static gboolean
2918 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
2919 {
2920       /* With X the client gives the byte ordering for the protocol,
2921          and the port on the server tells us we're speaking X. */
2922
2923       int le, be, decision, decisionToCache;
2924
2925       gboolean is_reply = (pinfo->srcport == pinfo->match_port);
2926       address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
2927       gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2928       if (cache) return cache > 0 ? TRUE : FALSE;
2929       if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
2930
2931       le = x_endian_match(tvb, tvb_get_letohs);
2932       be = x_endian_match(tvb, tvb_get_ntohs);
2933
2934       /* remember that "decision" really means "little_endian". */
2935       if (le == be) {
2936             /* We have no reason to believe it's little- rather than
2937                big-endian, so we guess the shortest length is the
2938                right one.
2939             */
2940             if (!tvb_bytes_exist(tvb, 0, 4))
2941                   /* Not even a way to get the length. We're biased
2942                      toward little endianness here (essentially the
2943                      x86 world right now). Decoding won't go very far
2944                      anyway.
2945                   */
2946                   decision = TRUE;
2947             else
2948                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2949       } else
2950           decision = le >= be;
2951
2952       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2953       if (decisionToCache) {
2954             /* We encode the decision as 1 for TRUE and -1 for FALSE
2955                to be able to distinguish between FALSE and no value in
2956                the cache when recalling the value.
2957             */
2958             int address_length;
2959             char *address_data;
2960             address *cached;
2961             if (addr -> type == AT_IPv4) {
2962                   address_length = 4;
2963                   address_data = g_mem_chunk_alloc(ipv4_chunk);
2964             } else if (addr -> type == AT_IPv6) {
2965                   address_length = 16;
2966                   address_data = g_mem_chunk_alloc(ipv6_chunk);
2967             } else {
2968                   address_length = addr -> len;
2969                   address_data = g_malloc(address_length);
2970             }
2971             cached = g_mem_chunk_alloc(address_chunk);
2972             memcpy(address_data, addr -> data, address_length);
2973             SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2974             g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2975       }
2976             
2977       /*
2978       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n", 
2979               pinfo->fd -> num, le, be, decision, decisionToCache);
2980       */
2981       return decision;
2982 }
2983
2984 /************************************************************************
2985  ***                                                                  ***
2986  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
2987  ***                                                                  ***
2988  ************************************************************************/
2989
2990 static void
2991 dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2992 {
2993 /* Set up structures we will need to add the protocol subtree and manage it */
2994       proto_item *ti;
2995       proto_tree *x11_tree;
2996       int offset;
2997       int left;
2998         
2999 /* This field shows up as the "Info" column in the display; you should make
3000    it, if possible, summarize what's in the packet, so that a user looking
3001    at the list of packets can tell what type of packet it is. */
3002       if (check_col(pinfo->cinfo, COL_INFO)) 
3003             col_set_str(pinfo->cinfo, COL_INFO, "Requests");
3004
3005 /* In the interest of speed, if "tree" is NULL, don't do any work not
3006    necessary to generate protocol tree items. */
3007       if (!tree) return;
3008       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
3009       x11_tree = proto_item_add_subtree(ti, ett_x11);
3010
3011       offset = 0;
3012       little_endian = guess_byte_ordering(tvb, pinfo);
3013       left = dissect_x11_requests_loop(tvb, &offset, x11_tree);
3014       if (left)
3015             call_dissector(data_handle, tvb_new_subset(tvb, offset,-1, tvb_reported_length_remaining(tvb, offset)), pinfo, x11_tree);
3016 }
3017
3018 static void
3019 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3020 {
3021 /* Set up structures we will need to add the protocol subtree and manage it */
3022       proto_item *ti;
3023       proto_tree *x11_tree;
3024         
3025 /* This field shows up as the "Info" column in the display; you should make
3026    it, if possible, summarize what's in the packet, so that a user looking
3027    at the list of packets can tell what type of packet it is. */
3028       if (check_col(pinfo->cinfo, COL_INFO)) 
3029             col_set_str(pinfo->cinfo, COL_INFO, "Replies/events");
3030
3031 /* In the interest of speed, if "tree" is NULL, don't do any work not
3032    necessary to generate protocol tree items. */
3033       if (!tree) return;
3034       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
3035       x11_tree = proto_item_add_subtree(ti, ett_x11);
3036
3037       /*
3038        * XXX - dissect these in a loop, like the requests.
3039        */
3040       call_dissector(data_handle,tvb, pinfo, x11_tree);
3041 }
3042
3043 static void
3044 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3045 {
3046       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
3047             col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
3048     
3049       if (pinfo->match_port == pinfo->destport)
3050             dissect_x11_requests(tvb, pinfo, tree);
3051       else
3052             dissect_x11_replies(tvb, pinfo, tree);
3053 }
3054
3055 /* Register the protocol with Ethereal */
3056 void proto_register_x11(void)
3057 {                 
3058
3059 /* Setup list of header fields */
3060       static hf_register_info hf[] = {
3061 /*
3062   { &hf_x11_FIELDABBREV,
3063   { "FIELDNAME",           "x11.FIELDABBREV",
3064   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,          
3065   "FIELDDESCR", HFILL }
3066   },
3067 */
3068 #include "x11-register-info.h"
3069       };
3070
3071 /* Setup protocol subtree array */
3072       static gint *ett[] = {
3073             &ett_x11,
3074             &ett_x11_request,
3075             &ett_x11_color_flags,
3076             &ett_x11_list_of_arc,
3077             &ett_x11_arc,
3078             &ett_x11_list_of_atom,
3079             &ett_x11_list_of_card32,
3080             &ett_x11_list_of_color_item,
3081             &ett_x11_color_item,
3082             &ett_x11_list_of_keycode,
3083             &ett_x11_list_of_keysyms,
3084             &ett_x11_keysym,
3085             &ett_x11_list_of_point,
3086             &ett_x11_point,
3087             &ett_x11_list_of_rectangle,
3088             &ett_x11_rectangle,
3089             &ett_x11_list_of_segment,
3090             &ett_x11_segment,
3091             &ett_x11_list_of_string8,
3092             &ett_x11_list_of_text_item,
3093             &ett_x11_text_item,
3094             &ett_x11_gc_value_mask,
3095             &ett_x11_event_mask,
3096             &ett_x11_do_not_propagate_mask,
3097             &ett_x11_set_of_key_mask,
3098             &ett_x11_pointer_event_mask,
3099             &ett_x11_window_value_mask,
3100             &ett_x11_configure_window_mask,
3101             &ett_x11_keyboard_value_mask,
3102       };
3103
3104 /* Register the protocol name and description */
3105       proto_x11 = proto_register_protocol("X11", "X11", "x11");
3106
3107 /* Required function calls to register the header fields and subtrees used */
3108       proto_register_field_array(proto_x11, hf, array_length(hf));
3109       proto_register_subtree_array(ett, array_length(ett));
3110
3111       byte_ordering_cache = g_tree_new(compareAddresses);
3112       address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address), 
3113                                       sizeof(address) * 128, G_ALLOC_ONLY);
3114       ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
3115       ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
3116 };
3117
3118
3119 void
3120 proto_reg_handoff_x11(void)
3121 {
3122   dissector_handle_t x11_handle;
3123
3124   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
3125   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
3126   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
3127   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
3128   data_handle = find_dissector("data");
3129 }