Get rid of another global variable.
[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.37 2002/04/14 22:50:07 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       while(length--) {
1155             unsigned l = VALUE8(tvb, *offsetp);
1156             if (allocated < (l + 1)) {
1157                   /* g_realloc doesn't work ??? */
1158                   g_free(s);
1159                   s = g_malloc(l + 1);
1160                   allocated = l + 1;
1161             }
1162             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1163             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1164             *offsetp += l + 1;
1165       }
1166       g_free(s);
1167 }
1168
1169 #define STRING16_MAX_DISPLAYED_LENGTH 150
1170
1171 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1172 {
1173       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1174       for(; length > 0; offset += 2, length--) {
1175             if (tvb_get_guint8(tvb, offset))
1176                 return FALSE;
1177       }
1178       return TRUE;
1179 }
1180
1181 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1182
1183 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1184                                               int hf, int hf_bytes,
1185                                               int offset, unsigned length,
1186                                               char **s, int *sLength)
1187 {
1188       int truncated = FALSE;
1189       unsigned l = length / 2;
1190
1191       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1192             char *dp;
1193             int soffset = offset;
1194
1195             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1196                   truncated = TRUE;
1197                   l = STRING16_MAX_DISPLAYED_LENGTH;
1198             }
1199             if (*sLength < (int) l + 3) {
1200                   g_free(*s);
1201                   *s = g_malloc(l + 3);
1202                   *sLength = l + 3;
1203             }
1204             dp = *s;
1205             *dp++ = '"';
1206             if (truncated) l -= 3;
1207
1208             while(l--) {
1209                   soffset++;
1210                   *dp++ = tvb_get_guint8(tvb, soffset);
1211                   soffset++;
1212             }
1213             *dp++ = '"';
1214
1215             /* If truncated, add an ellipsis */
1216             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1217
1218             *dp++ = '\0';
1219             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s", 
1220                                         proto_registrar_get_nth(hf) -> name, *s);
1221       } else
1222             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1223
1224 }
1225
1226 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1227     int sizeIs16)
1228 {
1229       int allocated = 0;
1230       char *s = NULL;
1231       proto_item *ti;
1232       proto_tree *tt;
1233       guint32 fid;
1234
1235       /* Compute total length */
1236       
1237       int scanning_offset = *offsetp; /* Scanning pointer */
1238       int l;                            /* Length of an individual item */
1239       int n = 0;                        /* Number of items */
1240
1241       while(scanning_offset < next_offset) {
1242             l = tvb_get_guint8(tvb, scanning_offset);
1243             scanning_offset++;
1244             if (!l) break;
1245             n++;
1246             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
1247       }
1248
1249       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1250       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
1251
1252       while(n--) {
1253             unsigned l = VALUE8(tvb, *offsetp);
1254             if (l == 255) { /* Item is a font */
1255                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
1256                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
1257                   *offsetp += 5;
1258             } else { /* Item is a string */
1259                   proto_item *tti;
1260                   proto_tree *ttt;
1261                   gint8 delta = VALUE8(tvb, *offsetp + 1);
1262                   if (sizeIs16) l += l;
1263                   if ((unsigned) allocated < l + 1) {
1264                         /* g_realloc doesn't work ??? */
1265                         g_free(s);
1266                         s = g_malloc(l + 1);
1267                         allocated = l + 1;
1268                   }
1269                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
1270                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
1271                                                        "textitem (string): delta = %d, \"%s\"",
1272                                                        delta, s);
1273                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
1274                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
1275                   if (sizeIs16)
1276                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16, 
1277                                                           hf_x11_textitem_string_string16_bytes,
1278                                                           *offsetp + 2, l,
1279                                                            &s, &allocated);
1280                   else
1281                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb, 
1282                                                      *offsetp + 2, l, s, "\"%s\"", s);
1283                   *offsetp += l + 2;
1284             }
1285       }
1286       g_free(s);
1287 }
1288
1289 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1290 {
1291       guint32 v = VALUE8(tvb, *offsetp);
1292       header_field_info *hfi = proto_registrar_get_nth(hf);
1293       gchar *enumValue = NULL;
1294       gchar *nameAsChar = hfi -> name;
1295
1296       if (hfi -> strings)
1297             enumValue = match_strval(v, cVALS(hfi -> strings));
1298       if (enumValue)
1299             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: %u (%s)", nameAsChar, v, enumValue);
1300       else
1301             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
1302       *offsetp += 1;
1303       return v;
1304 }
1305
1306 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1307 {
1308       guint32 v = VALUE16(tvb, *offsetp);
1309       proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
1310       *offsetp += 2;
1311       return v;
1312 }
1313
1314 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1315 {
1316       guint32 v = VALUE32(tvb, *offsetp);
1317       header_field_info *hfi = proto_registrar_get_nth(hf);
1318       gchar *enumValue = NULL;
1319       gchar *nameAsChar = hfi -> name;
1320
1321       if (hfi -> strings)
1322             enumValue = match_strval(v, cVALS(hfi -> strings));
1323       if (enumValue)
1324             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
1325       else
1326             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, 
1327                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
1328                                        nameAsChar, v);
1329       *offsetp += 4;
1330       return v;
1331 }
1332
1333 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1334 {
1335       BITMASK32(gc_value);
1336       BITFIELD(ENUM8,  gc_value_mask, function);
1337       BITFIELD(CARD32, gc_value_mask, plane_mask);
1338       BITFIELD(CARD32, gc_value_mask, foreground);
1339       BITFIELD(CARD32, gc_value_mask, background);
1340       BITFIELD(CARD16, gc_value_mask, line_width);
1341       BITFIELD(ENUM8,  gc_value_mask, line_style);
1342       BITFIELD(ENUM8,  gc_value_mask, cap_style);
1343       BITFIELD(ENUM8,  gc_value_mask, join_style);
1344       BITFIELD(ENUM8,  gc_value_mask, fill_style);
1345       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
1346       BITFIELD(PIXMAP, gc_value_mask, tile);
1347       BITFIELD(PIXMAP, gc_value_mask, stipple);
1348       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
1349       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
1350       BITFIELD(FONT,   gc_value_mask, font);
1351       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
1352       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
1353       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
1354       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
1355       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
1356       BITFIELD(CARD16, gc_value_mask, dash_offset);
1357       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
1358       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
1359       ENDBITMASK;
1360 }
1361
1362 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1363 {
1364       BITMASK32(gc_value);
1365       FLAG(gc_value, function);
1366       FLAG(gc_value, plane_mask);
1367       FLAG(gc_value, foreground);
1368       FLAG(gc_value, background);
1369       FLAG(gc_value, line_width);
1370       FLAG(gc_value, line_style);
1371       FLAG(gc_value, cap_style);
1372       FLAG(gc_value, join_style);
1373       FLAG(gc_value, fill_style);
1374       FLAG(gc_value, fill_rule);
1375       FLAG(gc_value, tile);
1376       FLAG(gc_value, stipple);
1377       FLAG(gc_value, tile_stipple_x_origin);
1378       FLAG(gc_value, tile_stipple_y_origin);
1379       FLAG(gc_value, font);
1380       FLAG(gc_value, subwindow_mode);
1381       FLAG(gc_value, graphics_exposures);
1382       FLAG(gc_value, clip_x_origin);
1383       FLAG(gc_value, clip_y_origin);
1384       FLAG(gc_value, clip_mask);
1385       FLAG(gc_value, dash_offset);
1386       FLAG(gc_value, gc_dashes);
1387       FLAG(gc_value, arc_mode);
1388       ENDBITMASK;
1389 }
1390
1391 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1392 {
1393       guint32 res = VALUE16(tvb, *offsetp) * 4;
1394       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
1395       *offsetp += 2;
1396       return res;
1397 }
1398
1399 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1400 {
1401       BITMASK32(event);
1402       FLAG(event, KeyPress);
1403       FLAG(event, KeyRelease);
1404       FLAG(event, ButtonPress);
1405       FLAG(event, ButtonRelease);
1406       FLAG(event, EnterWindow);
1407       FLAG(event, LeaveWindow);
1408       FLAG(event, PointerMotion);
1409       FLAG(event, PointerMotionHint);
1410       FLAG(event, Button1Motion);
1411       FLAG(event, Button2Motion);
1412       FLAG(event, Button3Motion);
1413       FLAG(event, Button4Motion);
1414       FLAG(event, Button5Motion);
1415       FLAG(event, ButtonMotion);
1416       FLAG(event, KeymapState);
1417       FLAG(event, Exposure);
1418       FLAG(event, VisibilityChange);
1419       FLAG(event, StructureNotify);
1420       FLAG(event, ResizeRedirect);
1421       FLAG(event, SubstructureNotify);
1422       FLAG(event, SubstructureRedirect);
1423       FLAG(event, FocusChange);
1424       FLAG(event, PropertyChange);
1425       FLAG(event, ColormapChange);
1426       FLAG(event, OwnerGrabButton);
1427       FLAG_IF_NONZERO(event, erroneous_bits);
1428       ENDBITMASK;
1429 }
1430
1431 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1432 {
1433       BITMASK32(do_not_propagate);
1434       FLAG(do_not_propagate, KeyPress);
1435       FLAG(do_not_propagate, KeyRelease);
1436       FLAG(do_not_propagate, ButtonPress);
1437       FLAG(do_not_propagate, ButtonRelease);
1438       FLAG(do_not_propagate, PointerMotion);
1439       FLAG(do_not_propagate, Button1Motion);
1440       FLAG(do_not_propagate, Button2Motion);
1441       FLAG(do_not_propagate, Button3Motion);
1442       FLAG(do_not_propagate, Button4Motion);
1443       FLAG(do_not_propagate, Button5Motion);
1444       FLAG(do_not_propagate, ButtonMotion);
1445       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
1446       ENDBITMASK;
1447 }
1448
1449 static void setOfKeyMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1450 {
1451       proto_item *ti;
1452       guint32 bitmask_value;
1453       int bitmask_offset;
1454       int bitmask_size;
1455       proto_tree *bitmask_tree;
1456
1457       bitmask_value = VALUE16(tvb, *offsetp);
1458       bitmask_offset = *offsetp;
1459       bitmask_size = 2;
1460       if (bitmask_value == 0x8000)
1461             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
1462                                        "modifiers-masks: 0x8000 (AnyModifier)");
1463       else {
1464             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2, 
1465                                                  bitmask_value);
1466             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
1467             FLAG(modifiers, Shift);
1468             FLAG(modifiers, Lock);
1469             FLAG(modifiers, Control);
1470             FLAG(modifiers, Mod1);
1471             FLAG(modifiers, Mod2);
1472             FLAG(modifiers, Mod3);
1473             FLAG(modifiers, Mod4);
1474             FLAG(modifiers, Mod5);
1475             FLAG_IF_NONZERO(modifiers, erroneous_bits);
1476       }
1477       *offsetp += 2; 
1478 }
1479
1480 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1481 {
1482       BITMASK16(pointer_event);
1483       FLAG(pointer_event, ButtonPress);
1484       FLAG(pointer_event, ButtonRelease);
1485       FLAG(pointer_event, EnterWindow);
1486       FLAG(pointer_event, LeaveWindow);
1487       FLAG(pointer_event, PointerMotion);
1488       FLAG(pointer_event, PointerMotionHint);
1489       FLAG(pointer_event, Button1Motion);
1490       FLAG(pointer_event, Button2Motion);
1491       FLAG(pointer_event, Button3Motion);
1492       FLAG(pointer_event, Button4Motion);
1493       FLAG(pointer_event, Button5Motion);
1494       FLAG(pointer_event, ButtonMotion);
1495       FLAG(pointer_event, KeymapState);
1496       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
1497       ENDBITMASK;
1498 }
1499
1500 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1501     const char *nameAsChar, int hf, unsigned length)
1502 {
1503       char *s = g_malloc(length + 1);
1504
1505       stringCopy(s, tvb_get_ptr(tvb, *offsetp, length), length);
1506       proto_tree_add_string_format(t, hf, tvb, *offsetp, length, s, "%s: %s", nameAsChar, s);
1507       g_free(s);
1508       *offsetp += length;
1509 }
1510
1511 /* The length is the length of the _byte_zone_ (twice the length of the string) */
1512
1513 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1514     int hf_bytes, unsigned length)
1515 {
1516       char *s = NULL;
1517       unsigned l = 0;
1518
1519       length += length;
1520       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length, &s, &l);
1521       g_free(s);
1522       *offsetp += length;
1523 }
1524
1525 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1526     const char *nameAsChar, int hf)
1527 {
1528       guint32 v = VALUE32(tvb, *offsetp);
1529       if (!v)
1530             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
1531       else
1532             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
1533       *offsetp += 4;
1534 }
1535
1536 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1537 {
1538       BITMASK32(window_value);
1539       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
1540       BITFIELD(CARD32, window_value_mask, background_pixel);
1541       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
1542       BITFIELD(CARD32, window_value_mask, border_pixel);
1543       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
1544       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
1545       BITFIELD(ENUM8, window_value_mask, backing_store);
1546       BITFIELD(CARD32, window_value_mask, backing_planes);
1547       BITFIELD(CARD32, window_value_mask, backing_pixel);
1548       BITFIELD(BOOL,   window_value_mask, override_redirect);
1549       BITFIELD(BOOL,   window_value_mask, save_under);
1550       BITFIELD(SETofEVENT, window_value_mask, event_mask);
1551       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
1552       BITFIELD(COLORMAP, window_value_mask, colormap);
1553       BITFIELD(CURSOR, window_value_mask, cursor);
1554       ENDBITMASK;
1555 }
1556
1557 /************************************************************************
1558  ***                                                                  ***
1559  ***              D E C O D I N G   O N E   P A C K E T               ***
1560  ***                                                                  ***
1561  ************************************************************************/
1562
1563 static int dissect_x11_request_loop(tvbuff_t *tvb, int *offsetp, proto_tree *root)
1564 {
1565       int left = tvb_reported_length(tvb), nextLeft;
1566       proto_item *ti;
1567       proto_tree *t;
1568       guint8 v8, v8_2;
1569       guint16 v16;
1570       guint32 v32;
1571
1572       /* The X11 data stream to the server is just a sequence of requests,
1573          each of which contains a length; for now, we dissect all the
1574          requests in this frame until we run out of data in the frame.
1575          Eventually, we should handle requests that cross frame
1576          boundaries.
1577
1578          Note that "in this frame" refers to everything in the frame
1579          as it appeared in the wire, not as it was captured; we want
1580          an exception to be thrown if we go past the end of the
1581          captured data in the frame without going past the end of the
1582          data in the frame. */
1583       for(;;) {
1584             int length, opcode;
1585             
1586             /* fprintf(stderr, "Starting loop, left = %d, *offsetp = %d\n", left, *offsetp); */
1587             if (left < 4) {
1588                 /* We ran out of data - we don't have enough data in
1589                    the frame to get the length of this request. */
1590                 break;
1591             }
1592             length = VALUE16(tvb, *offsetp + 2) * 4;
1593             /*      fprintf(stderr, "length = %d\n", length);*/
1594             if (left < length) {
1595                 /* We ran out of data - we don't have enough data in
1596                    the frame for the full request. */
1597                 break;
1598             }
1599             if (length < 4) {
1600                 /* Bogus message length? */
1601                 break;
1602             }
1603
1604             next_offset = *offsetp + length;
1605             nextLeft = left - length;
1606
1607             ti = proto_tree_add_uint(root, hf_x11_request, tvb, *offsetp, length, tvb_get_guint8(tvb, *offsetp));
1608             t = proto_item_add_subtree(ti, ett_x11_request);
1609
1610             OPCODE();
1611
1612             switch(opcode) {
1613                 case 1: /* CreateWindow */
1614                   CARD8(depth);
1615                   REQUEST_LENGTH();
1616                   WINDOW(wid);
1617                   WINDOW(parent);
1618                   INT16(x);
1619                   INT16(y);
1620                   CARD16(width);
1621                   CARD16(height);
1622                   CARD16(border_width);
1623                   ENUM16(window_class);
1624                   VISUALID(visual);
1625                   windowAttributes(tvb, offsetp, t);
1626                   break;
1627
1628                 case 2: /* ChangeWindowAttributes */
1629                   UNUSED(1);
1630                   REQUEST_LENGTH();
1631                   WINDOW(window);
1632                   windowAttributes(tvb, offsetp, t);
1633                   break;
1634
1635                 case 3: /* GetWindowAttributes */
1636                 case 4: /* DestroyWindow */
1637                 case 5: /* DestroySubwindows */
1638                   UNUSED(1);
1639                   REQUEST_LENGTH();
1640                   WINDOW(window);
1641                   break;
1642
1643                 case 6: /* ChangeSaveSet */
1644                   ENUM8(save_set_mode);
1645                   REQUEST_LENGTH();
1646                   WINDOW(window);
1647                   break;
1648
1649                 case 7: /* ReparentWindow */
1650                   UNUSED(1);
1651                   REQUEST_LENGTH();
1652                   WINDOW(window);
1653                   WINDOW(parent);
1654                   INT16(x);
1655                   INT16(y);
1656                   break;
1657
1658                 case 8: /* MapWindow */
1659                 case 9: /* MapSubWindow */
1660                 case 10: /* UnmapWindow */
1661                 case 11: /* UnmapSubwindows */
1662                   UNUSED(1);
1663                   REQUEST_LENGTH();
1664                   WINDOW(window);
1665                   break;
1666
1667                 case 12: /* ConfigureWindow */
1668                   UNUSED(1);
1669                   REQUEST_LENGTH();
1670                   WINDOW(window);
1671                   BITMASK16(configure_window);
1672                   UNUSED(2); 
1673                   BITFIELD(INT16,  configure_window_mask, x);
1674                   BITFIELD(INT16,  configure_window_mask, y);
1675                   BITFIELD(CARD16, configure_window_mask, width);
1676                   BITFIELD(CARD16, configure_window_mask, height);
1677                   BITFIELD(CARD16, configure_window_mask, border_width);
1678                   BITFIELD(WINDOW, configure_window_mask, sibling);
1679                   BITFIELD(ENUM8,  configure_window_mask, stack_mode);
1680                   ENDBITMASK;
1681                   PAD();
1682                   break;
1683
1684                 case 13: /* CirculateWindow */
1685                   ENUM8(direction);
1686                   REQUEST_LENGTH();
1687                   WINDOW(window);
1688                   break;
1689
1690                 case 14: /* GetGeometry */
1691                 case 15: /* QueryTree */
1692                   UNUSED(1);
1693                   REQUEST_LENGTH();
1694                   DRAWABLE(drawable);
1695                   break;
1696
1697                 case 16: /* InternAtom */
1698                   BOOL(only_if_exists);
1699                   REQUEST_LENGTH();
1700                   v16 = FIELD16(name_length);
1701                   UNUSED(2);
1702                   STRING8(name, v16);
1703                   PAD();
1704                   break;
1705
1706                 case 17: /* GetAtomName */
1707                   UNUSED(1);
1708                   REQUEST_LENGTH();
1709                   ATOM(atom);
1710                   break;
1711
1712                 case 18: /* ChangeProperty */
1713                   ENUM8(mode);
1714                   REQUEST_LENGTH();
1715                   WINDOW(window);
1716                   ATOM(property);
1717                   ATOM(type);
1718                   CARD8(format);
1719                   UNUSED(3);
1720                   v32 = CARD32(data_length);
1721                   LISTofBYTE(data, v32);
1722                   PAD();
1723                   break;
1724
1725                 case 19: /* DeleteProperty */
1726                   UNUSED(1);
1727                   REQUEST_LENGTH();
1728                   WINDOW(window);
1729                   ATOM(property);
1730                   break;
1731
1732                 case 20: /* GetProperty */
1733                   BOOL(delete);
1734                   REQUEST_LENGTH();
1735                   WINDOW(window);
1736                   ATOM(property);
1737                   ATOM(get_property_type);
1738                   CARD32(long_offset);
1739                   CARD32(long_length);
1740                   break;
1741
1742                 case 21: /* ListProperties */
1743                   UNUSED(1);
1744                   REQUEST_LENGTH();
1745                   WINDOW(window);
1746                   break;
1747
1748                 case 22: /* SetSelectionOwner */
1749                   UNUSED(1);
1750                   REQUEST_LENGTH();
1751                   WINDOW(owner);
1752                   ATOM(selection);
1753                   TIMESTAMP(time);
1754                   break;
1755
1756                 case 23: /* GetSelectionOwner */
1757                   UNUSED(1);
1758                   REQUEST_LENGTH();
1759                   ATOM(selection);
1760                   break;
1761
1762                 case 24: /* ConvertSelection */
1763                   UNUSED(1);
1764                   REQUEST_LENGTH();
1765                   WINDOW(requestor);
1766                   ATOM(selection);
1767                   ATOM(target);
1768                   ATOM(property);
1769                   TIMESTAMP(time);
1770                   break;
1771
1772                 case 26: /* GrabPointer */
1773                   BOOL(owner_events);
1774                   REQUEST_LENGTH();
1775                   WINDOW(grab_window);
1776                   SETofPOINTEREVENT(pointer_event_mask);
1777                   ENUM8(pointer_mode);
1778                   ENUM8(keyboard_mode);
1779                   WINDOW(confine_to);
1780                   CURSOR(cursor);
1781                   TIMESTAMP(time);
1782                   break;
1783
1784                 case 27: /* UngrabPointer */
1785                   UNUSED(1);
1786                   REQUEST_LENGTH();
1787                   TIMESTAMP(time);
1788                   break;
1789
1790                 case 28: /* GrabButton */
1791                   BOOL(owner_events);
1792                   REQUEST_LENGTH();
1793                   WINDOW(grab_window);
1794                   SETofPOINTEREVENT(event_mask);
1795                   ENUM8(pointer_mode);
1796                   ENUM8(keyboard_mode);
1797                   WINDOW(confine_to);
1798                   CURSOR(cursor);
1799                   BUTTON(button);
1800                   UNUSED(1);
1801                   SETofKEYMASK(modifiers);
1802                   break;
1803
1804                 case 29: /* UngrabButton */
1805                   BUTTON(button);
1806                   REQUEST_LENGTH();
1807                   WINDOW(grab_window);
1808                   SETofKEYMASK(modifiers);
1809                   UNUSED(2);
1810                   break;
1811
1812                 case 30: /* ChangeActivePointerGrab */
1813                   UNUSED(1);
1814                   REQUEST_LENGTH();
1815                   CURSOR(cursor);
1816                   TIMESTAMP(time);
1817                   SETofPOINTEREVENT(event_mask);
1818                   UNUSED(2);
1819                   break;
1820
1821                 case 31: /* GrabKeyboard */
1822                   BOOL(owner_events);
1823                   REQUEST_LENGTH();
1824                   WINDOW(grab_window);
1825                   TIMESTAMP(time);
1826                   ENUM8(pointer_mode);
1827                   ENUM8(keyboard_mode);
1828                   UNUSED(2);
1829                   break;
1830
1831                 case 32: /* UngrabKeyboard */
1832                   UNUSED(1);
1833                   REQUEST_LENGTH();
1834                   TIMESTAMP(time);
1835                   break;
1836
1837                 case 33: /* GrabKey */
1838                   BOOL(owner_events);
1839                   REQUEST_LENGTH();
1840                   WINDOW(grab_window);
1841                   SETofKEYMASK(modifiers);
1842                   KEYCODE(key);
1843                   ENUM8(pointer_mode);
1844                   ENUM8(keyboard_mode);
1845                   UNUSED(3);
1846                   break;
1847
1848                 case 34: /* UngrabKey */
1849                   KEYCODE(key);
1850                   REQUEST_LENGTH();
1851                   WINDOW(grab_window);
1852                   SETofKEYMASK(modifiers);
1853                   UNUSED(2);
1854                   break;
1855
1856                 case 35: /* AllowEvents */
1857                   ENUM8(allow_events_mode);
1858                   REQUEST_LENGTH();
1859                   TIMESTAMP(time);
1860                   break;
1861
1862                 case 36: /* GrabServer */
1863                   UNUSED(1);
1864                   REQUEST_LENGTH();
1865                   break;
1866
1867                 case 37: /* UngrabServer */
1868                   UNUSED(1);
1869                   REQUEST_LENGTH();
1870                   break;
1871
1872                 case 38: /* QueryPointer */
1873                   UNUSED(1);
1874                   REQUEST_LENGTH();
1875                   WINDOW(window);
1876                   break;
1877
1878                 case 39: /* GetMotionEvents */
1879                   UNUSED(1);
1880                   REQUEST_LENGTH();
1881                   WINDOW(window);
1882                   TIMESTAMP(start);
1883                   TIMESTAMP(stop);
1884                   break;
1885
1886                 case 40: /* TranslateCoordinates */
1887                   UNUSED(1);
1888                   REQUEST_LENGTH();
1889                   WINDOW(src_window);
1890                   WINDOW(dst_window);
1891                   INT16(src_x);
1892                   INT16(src_y);
1893                   break;
1894
1895                 case 41: /* WarpPointer */
1896                   UNUSED(1);
1897                   REQUEST_LENGTH();
1898                   WINDOW(warp_pointer_src_window);
1899                   WINDOW(warp_pointer_dst_window);
1900                   INT16(src_x);
1901                   INT16(src_y);
1902                   CARD16(src_width);
1903                   CARD16(src_height);
1904                   INT16(dst_x);
1905                   INT16(dst_y);
1906                   break;
1907
1908                 case 42: /* SetInputFocus */
1909                   ENUM8(revert_to);
1910                   REQUEST_LENGTH();
1911                   WINDOW(focus);
1912                   TIMESTAMP(time);
1913                   break;
1914
1915                 case 43: /* GetInputFocus */
1916                   UNUSED(1);
1917                   REQUEST_LENGTH();
1918                   break;
1919
1920                 case 44: /* QueryKeymap */
1921                   UNUSED(1);
1922                   REQUEST_LENGTH();
1923                   break;
1924
1925                 case 45: /* OpenFont */
1926                   UNUSED(1);
1927                   REQUEST_LENGTH();
1928                   FONT(fid);
1929                   v16 = FIELD16(name_length);
1930                   UNUSED(2);
1931                   STRING8(name, v16);
1932                   PAD();
1933                   break;
1934
1935                 case 46: /* CloseFont */
1936                   UNUSED(1);
1937                   REQUEST_LENGTH();
1938                   FONT(font);
1939                   break;
1940
1941                 case 47: /* QueryFont */
1942                   UNUSED(1);
1943                   REQUEST_LENGTH();
1944                   FONTABLE(font);
1945                   break;
1946
1947                 case 48: /* QueryTextExtents */
1948                   v8 = BOOL(odd_length);
1949                   REQUEST_LENGTH();
1950                   FONTABLE(font);
1951                   STRING16(string16, (next_offset - *offsetp - (v8 ? 2 : 0)) / 2);
1952                   PAD();
1953                   break;
1954
1955                 case 49: /* ListFonts */
1956                   UNUSED(1);
1957                   REQUEST_LENGTH();
1958                   CARD16(max_names);
1959                   v16 = FIELD16(pattern_length);
1960                   STRING8(pattern, v16);
1961                   PAD();
1962                   break;
1963
1964                 case 50: /* ListFontsWithInfo */
1965                   UNUSED(1);
1966                   REQUEST_LENGTH();
1967                   CARD16(max_names);
1968                   v16 = FIELD16(pattern_length);
1969                   STRING8(pattern, v16);
1970                   PAD();
1971                   break;
1972
1973                 case 51: /* SetFontPath */
1974                   UNUSED(1);
1975                   REQUEST_LENGTH();
1976                   v16 = CARD16(str_number_in_path);
1977                   UNUSED(2);
1978                   LISTofSTRING8(path, v16);
1979                   PAD();
1980                   break;
1981
1982                 case 52: /* GetFontPath */
1983                   UNUSED(1);
1984                   REQUEST_LENGTH();
1985                   break;
1986
1987                 case 53: /* CreatePixmap */
1988                   CARD8(depth);
1989                   REQUEST_LENGTH();
1990                   PIXMAP(pid);
1991                   DRAWABLE(drawable);
1992                   CARD16(width);
1993                   CARD16(height);
1994                   break;
1995
1996                 case 54: /* FreePixmap */
1997                   UNUSED(1);
1998                   REQUEST_LENGTH();
1999                   PIXMAP(pixmap);
2000                   break;
2001
2002                 case 55: /* CreateGC */
2003                   UNUSED(1);
2004                   REQUEST_LENGTH();
2005                   GCONTEXT(cid);
2006                   DRAWABLE(drawable);
2007                   gcAttributes(tvb, offsetp, t);
2008                   break;
2009
2010                 case 56: /* ChangeGC */
2011                   UNUSED(1);
2012                   REQUEST_LENGTH();
2013                   GCONTEXT(gc);
2014                   gcAttributes(tvb, offsetp, t);
2015                   break;
2016
2017                 case 57: /* CopyGC */
2018                   UNUSED(1);
2019                   REQUEST_LENGTH();
2020                   GCONTEXT(src_gc);
2021                   GCONTEXT(dst_gc);
2022                   gcMask(tvb, offsetp, t);
2023                   break;
2024
2025                 case 58: /* SetDashes */
2026                   UNUSED(1);
2027                   REQUEST_LENGTH();
2028                   GCONTEXT(gc);
2029                   CARD16(dash_offset);
2030                   v16 = FIELD16(dashes_length);
2031                   LISTofCARD8(dashes, v16);
2032                   PAD();
2033                   break;
2034
2035                 case 59: /* SetClipRectangles */
2036                   ENUM8(ordering);
2037                   REQUEST_LENGTH();
2038                   GCONTEXT(gc);
2039                   INT16(clip_x_origin);
2040                   INT16(clip_y_origin);
2041                   LISTofRECTANGLE(rectangles);
2042                   break;
2043
2044                 case 60: /* FreeGC */
2045                   UNUSED(1);
2046                   REQUEST_LENGTH();
2047                   GCONTEXT(gc);
2048                   break;
2049
2050                 case 61: /* ClearArea */
2051                   BOOL(exposures);
2052                   REQUEST_LENGTH();
2053                   WINDOW(window);
2054                   INT16(x);
2055                   INT16(y);
2056                   CARD16(width);
2057                   CARD16(height);
2058                   break;
2059
2060                 case 62: /* CopyArea */
2061                   UNUSED(1);
2062                   REQUEST_LENGTH();
2063                   DRAWABLE(src_drawable);
2064                   DRAWABLE(dst_drawable);
2065                   GCONTEXT(gc);
2066                   INT16(src_x);
2067                   INT16(src_y);
2068                   INT16(dst_x);
2069                   INT16(dst_y);
2070                   CARD16(width);
2071                   CARD16(height);
2072                   break;
2073
2074                 case 63: /* CopyPlane */
2075                   UNUSED(1);
2076                   REQUEST_LENGTH();
2077                   DRAWABLE(src_drawable);
2078                   DRAWABLE(dst_drawable);
2079                   GCONTEXT(gc);
2080                   INT16(src_x);
2081                   INT16(src_y);
2082                   INT16(dst_x);
2083                   INT16(dst_y);
2084                   CARD16(width);
2085                   CARD16(height);
2086                   CARD32(bit_plane);
2087                   break;
2088
2089                 case 64: /* PolyPoint */
2090                   ENUM8(coordinate_mode);
2091                   v16 = REQUEST_LENGTH();
2092                   DRAWABLE(drawable);
2093                   GCONTEXT(gc);
2094                   LISTofPOINT(points, v16 - 12);
2095                   break;
2096
2097                 case 65: /* PolyLine */
2098                   ENUM8(coordinate_mode);
2099                   v16 = REQUEST_LENGTH();
2100                   DRAWABLE(drawable);
2101                   GCONTEXT(gc);
2102                   LISTofPOINT(points, v16 - 12);
2103                   break;
2104
2105                 case 66: /* PolySegment */
2106                   UNUSED(1);
2107                   REQUEST_LENGTH();
2108                   DRAWABLE(drawable);
2109                   GCONTEXT(gc);
2110                   LISTofSEGMENT(segments);
2111                   break;
2112
2113                 case 67: /* PolyRectangle */
2114                   UNUSED(1);
2115                   REQUEST_LENGTH();
2116                   DRAWABLE(drawable);
2117                   GCONTEXT(gc);
2118                   LISTofRECTANGLE(rectangles);
2119                   break;
2120
2121                 case 68: /* PolyArc */
2122                   UNUSED(1);
2123                   REQUEST_LENGTH();
2124                   DRAWABLE(drawable);
2125                   GCONTEXT(gc);
2126                   LISTofARC(arcs);
2127                   break;
2128
2129                 case 69: /* FillPoly */
2130                   UNUSED(1);
2131                   v16 = REQUEST_LENGTH();
2132                   DRAWABLE(drawable);
2133                   GCONTEXT(gc);
2134                   ENUM8(shape);
2135                   ENUM8(coordinate_mode);
2136                   UNUSED(2);
2137                   LISTofPOINT(points, v16 - 16);
2138                   break;
2139
2140                 case 70: /* PolyFillRectangle */
2141                   UNUSED(1);
2142                   REQUEST_LENGTH();
2143                   DRAWABLE(drawable);
2144                   GCONTEXT(gc);
2145                   LISTofRECTANGLE(rectangles);
2146                   break;
2147
2148                 case 71: /* PolyFillArc */
2149                   UNUSED(1);
2150                   REQUEST_LENGTH();
2151                   DRAWABLE(drawable);
2152                   GCONTEXT(gc);
2153                   LISTofARC(arcs);
2154                   break;
2155
2156                 case 72: /* PutImage */
2157                   ENUM8(image_format);
2158                   v16 = REQUEST_LENGTH();
2159                   DRAWABLE(drawable);
2160                   GCONTEXT(gc);
2161                   CARD16(width);
2162                   CARD16(height);
2163                   INT16(dst_x);
2164                   INT16(dst_y);
2165                   CARD8(left_pad);
2166                   CARD8(depth);
2167                   UNUSED(2);
2168                   LISTofBYTE(data, v16 - 24);
2169                   PAD();
2170                   break;
2171
2172                 case 73: /* GetImage */
2173                   ENUM8(image_pixmap_format);
2174                   REQUEST_LENGTH();
2175                   DRAWABLE(drawable);
2176                   INT16(x);
2177                   INT16(y);
2178                   CARD16(width);
2179                   CARD16(height);
2180                   CARD32(plane_mask);
2181                   break;
2182
2183                 case 74: /* PolyText8 */
2184                   UNUSED(1);
2185                   v16 = REQUEST_LENGTH();
2186                   DRAWABLE(drawable);
2187                   GCONTEXT(gc);
2188                   INT16(x);
2189                   INT16(y);
2190                   LISTofTEXTITEM8(items);
2191                   PAD();
2192                   break;
2193
2194                 case 75: /* PolyText16 */
2195                   UNUSED(1);
2196                   v16 = REQUEST_LENGTH();
2197                   DRAWABLE(drawable);
2198                   GCONTEXT(gc);
2199                   INT16(x);
2200                   INT16(y);
2201                   LISTofTEXTITEM16(items);
2202                   PAD();
2203                   break;
2204
2205                 case 76: /* ImageText8 */
2206                   v8 = FIELD8(string_length);
2207                   REQUEST_LENGTH();
2208                   DRAWABLE(drawable);
2209                   GCONTEXT(gc);
2210                   INT16(x);
2211                   INT16(y);
2212                   STRING8(string, v8);
2213                   PAD();
2214                   break;
2215
2216                 case 77: /* ImageText16 */
2217                   v8 = FIELD8(string_length);
2218                   REQUEST_LENGTH();
2219                   DRAWABLE(drawable);
2220                   GCONTEXT(gc);
2221                   INT16(x);
2222                   INT16(y);
2223                   STRING16(string16, v8);
2224                   PAD();
2225                   break;
2226
2227                 case 78: /* CreateColormap */
2228                   ENUM8(alloc);
2229                   REQUEST_LENGTH();
2230                   COLORMAP(mid);
2231                   WINDOW(window);
2232                   VISUALID(visual);
2233                   break;
2234
2235                 case 79: /* FreeColormap */
2236                   UNUSED(1);
2237                   REQUEST_LENGTH();
2238                   COLORMAP(cmap);
2239                   break;
2240
2241                 case 80: /* CopyColormapAndFree */
2242                   UNUSED(1);
2243                   REQUEST_LENGTH();
2244                   COLORMAP(mid);
2245                   COLORMAP(src_cmap);
2246                   break;
2247
2248                 case 81: /* InstallColormap */
2249                   UNUSED(1);
2250                   REQUEST_LENGTH();
2251                   COLORMAP(cmap);
2252                   break;
2253
2254                 case 82: /* UninstallColormap */
2255                   UNUSED(1);
2256                   REQUEST_LENGTH();
2257                   COLORMAP(cmap);
2258                   break;
2259
2260                 case 83: /* ListInstalledColormaps */
2261                   UNUSED(1);
2262                   REQUEST_LENGTH();
2263                   WINDOW(window);
2264                   break;
2265
2266                 case 84: /* AllocColor */
2267                   UNUSED(1);
2268                   REQUEST_LENGTH();
2269                   COLORMAP(cmap);
2270                   CARD16(red);
2271                   CARD16(green);
2272                   CARD16(blue);
2273                   UNUSED(2);
2274                   break;
2275
2276                 case 85: /* AllocNamedColor */
2277                   UNUSED(1);
2278                   REQUEST_LENGTH();
2279                   COLORMAP(cmap);
2280                   v16 = FIELD16(name_length);
2281                   UNUSED(2);
2282                   STRING8(name, v16);
2283                   PAD();
2284                   break;
2285
2286                 case 86: /* AllocColorCells */
2287                   BOOL(contiguous);
2288                   REQUEST_LENGTH();
2289                   COLORMAP(cmap);
2290                   CARD16(colors);
2291                   CARD16(planes);
2292                   break;
2293
2294                 case 87: /* AllocColorPlanes */
2295                   BOOL(contiguous);
2296                   REQUEST_LENGTH();
2297                   COLORMAP(cmap);
2298                   CARD16(colors);
2299                   CARD16(reds);
2300                   CARD16(greens);
2301                   CARD16(blues);
2302                   break;
2303
2304                 case 88: /* FreeColors */
2305                   UNUSED(1);
2306                   v16 = REQUEST_LENGTH();
2307                   COLORMAP(cmap);
2308                   CARD32(plane_mask);
2309                   LISTofCARD32(pixels, v16 - 12);
2310                   break;
2311
2312                 case 89: /* StoreColors */
2313                   UNUSED(1);
2314                   v16 = REQUEST_LENGTH();
2315                   COLORMAP(cmap);
2316                   LISTofCOLORITEM(color_items, v16 - 8);
2317                   break;
2318
2319                 case 90: /* StoreNamedColor */
2320                   COLOR_FLAGS(color);
2321                   REQUEST_LENGTH();
2322                   COLORMAP(cmap);
2323                   CARD32(pixel);        
2324                   v16 = FIELD16(name_length);
2325                   UNUSED(2);
2326                   STRING8(name, v16);
2327                   PAD();
2328                   break;
2329
2330                 case 91: /* QueryColors */
2331                   UNUSED(1);
2332                   v16 = REQUEST_LENGTH();
2333                   COLORMAP(cmap);
2334                   LISTofCARD32(pixels, v16 - 8);
2335                   break;
2336
2337                 case 92: /* LookupColor */
2338                   UNUSED(1);
2339                   REQUEST_LENGTH();
2340                   COLORMAP(cmap);
2341                   v16 = FIELD16(name_length);
2342                   UNUSED(2);
2343                   STRING8(name, v16);
2344                   PAD();
2345                   break;
2346
2347                 case 93: /* CreateCursor */
2348                   UNUSED(1);
2349                   REQUEST_LENGTH();
2350                   CURSOR(cid);
2351                   PIXMAP(source_pixmap);
2352                   PIXMAP(mask);
2353                   CARD16(fore_red);
2354                   CARD16(fore_green);
2355                   CARD16(fore_blue);
2356                   CARD16(back_red);
2357                   CARD16(back_green);
2358                   CARD16(back_blue);
2359                   CARD16(x);
2360                   CARD16(y);
2361                   break;
2362
2363                 case 94: /* CreateGlyphCursor */
2364                   UNUSED(1);
2365                   REQUEST_LENGTH();
2366                   CURSOR(cid);
2367                   FONT(source_font);
2368                   FONT(mask_font);
2369                   CARD16(source_char);
2370                   CARD16(mask_char);
2371                   CARD16(fore_red);
2372                   CARD16(fore_green);
2373                   CARD16(fore_blue);
2374                   CARD16(back_red);
2375                   CARD16(back_green);
2376                   CARD16(back_blue);
2377                   break;
2378
2379                 case 95: /* FreeCursor */
2380                   UNUSED(1);
2381                   REQUEST_LENGTH();
2382                   CURSOR(cursor);
2383                   break;
2384
2385                 case 96: /* RecolorCursor */
2386                   UNUSED(1);
2387                   REQUEST_LENGTH();
2388                   CURSOR(cursor);
2389                   CARD16(fore_red);
2390                   CARD16(fore_green);
2391                   CARD16(fore_blue);
2392                   CARD16(back_red);
2393                   CARD16(back_green);
2394                   CARD16(back_blue);
2395                   break;
2396
2397                 case 97: /* QueryBestSize */
2398                   ENUM8(class);
2399                   REQUEST_LENGTH();
2400                   DRAWABLE(drawable);
2401                   CARD16(width);
2402                   CARD16(height);
2403                   break;
2404
2405                 case 98: /* QueryExtension */
2406                   UNUSED(1);
2407                   REQUEST_LENGTH();
2408                   v16 = FIELD16(name_length);
2409                   UNUSED(2);
2410                   STRING8(name, v16);
2411                   PAD();
2412                   break;
2413
2414                 case 99: /* ListExtensions */
2415                   UNUSED(1);
2416                   REQUEST_LENGTH();
2417                   break;
2418
2419                 case 100: /* ChangeKeyboardMapping */
2420                   v8 = FIELD8(keycode_count);
2421                   REQUEST_LENGTH();
2422                   KEYCODE(first_keycode);
2423                   v8_2 = FIELD8(keysyms_per_keycode);
2424                   UNUSED(2);
2425                   LISTofKEYSYM(keysyms, v8, v8_2);
2426                   break;
2427
2428                 case 101: /* GetKeyboardMapping */
2429                   UNUSED(1);
2430                   REQUEST_LENGTH();
2431                   KEYCODE(first_keycode);
2432                   FIELD8(count);
2433                   UNUSED(2);
2434                   break;
2435
2436                 case 102: /* ChangeKeyboardControl */
2437                   UNUSED(1);
2438                   REQUEST_LENGTH();
2439                   BITMASK32(keyboard_value);
2440                   BITFIELD(INT8, keyboard_value_mask, key_click_percent);
2441                   BITFIELD(INT8, keyboard_value_mask, bell_percent);
2442                   BITFIELD(INT16, keyboard_value_mask, bell_pitch);
2443                   BITFIELD(INT16, keyboard_value_mask, bell_duration);
2444                   BITFIELD(INT16, keyboard_value_mask, led);
2445                   BITFIELD(ENUM8, keyboard_value_mask, led_mode);
2446                   BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
2447                   BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
2448                   ENDBITMASK;
2449                   break;
2450
2451                 case 103: /* GetKeyboardControl */
2452                   UNUSED(1);
2453                   REQUEST_LENGTH();
2454                   break;
2455
2456                 case 104: /* Bell */
2457                   INT8(percent);
2458                   REQUEST_LENGTH();
2459                   break;
2460
2461                 case 105: /* ChangePointerControl */
2462                   UNUSED(1);
2463                   REQUEST_LENGTH();
2464                   INT16(acceleration_numerator);
2465                   INT16(acceleration_denominator);
2466                   INT16(threshold);
2467                   BOOL(do_acceleration);
2468                   BOOL(do_threshold);
2469                   break;
2470
2471                 case 106: /* GetPointerControl */
2472                   UNUSED(1);
2473                   REQUEST_LENGTH();
2474                   break;
2475
2476                 case 107: /* SetScreenSaver */
2477                   UNUSED(1);
2478                   REQUEST_LENGTH();
2479                   INT16(timeout);
2480                   INT16(interval);
2481                   ENUM8(prefer_blanking);
2482                   ENUM8(allow_exposures);
2483                   UNUSED(2);
2484                   break;
2485
2486                 case 108: /* GetScreenSaver */
2487                   UNUSED(1);
2488                   REQUEST_LENGTH();
2489                   break;
2490
2491                 case 109: /* ChangeHosts */
2492                   ENUM8(change_host_mode);
2493                   REQUEST_LENGTH();
2494                   ENUM8(family);
2495                   UNUSED(1);
2496                   v16 = CARD16(address_length);
2497                   LISTofCARD8(address, v16);
2498                   break;
2499
2500                 case 110: /* ListHosts */
2501                   UNUSED(1);
2502                   REQUEST_LENGTH();
2503                   break;
2504
2505                 case 111: /* SetAccessControl */
2506                   ENUM8(access_mode);
2507                   REQUEST_LENGTH();
2508                   break;
2509
2510                 case 112: /* SetCloseDownMode */
2511                   ENUM8(close_down_mode);
2512                   REQUEST_LENGTH();
2513                   break;
2514
2515                 case 113: /* KillClient */
2516                   UNUSED(1);
2517                   REQUEST_LENGTH();
2518                   CARD32(resource);
2519                   break;
2520
2521                 case 114: /* RotateProperties */
2522                   UNUSED(1);
2523                   v16 = REQUEST_LENGTH();
2524                   WINDOW(window);
2525                   CARD16(property_number);
2526                   INT16(delta);
2527                   LISTofATOM(properties, (v16 - 12));
2528                   break;
2529
2530                 case 115: /* ForceScreenSaver */
2531                   ENUM8(screen_saver_mode);
2532                   REQUEST_LENGTH();
2533                   break;
2534
2535                 case 116: /* SetPointerMapping */
2536                   v8 = FIELD8(map_length);
2537                   REQUEST_LENGTH();
2538                   LISTofCARD8(map, v8);
2539                   PAD();
2540                   break;
2541
2542                 case 117: /* GetPointerMapping */
2543                   UNUSED(1);
2544                   REQUEST_LENGTH();
2545                   break;
2546
2547                 case 118: /* SetModifierMapping */
2548                   v8 = FIELD8(keycodes_per_modifier);
2549                   REQUEST_LENGTH();
2550                   LISTofKEYCODE(keycodes, v8);
2551                   break;
2552
2553                 case 119: /* GetModifierMapping */
2554                   UNUSED(1);
2555                   REQUEST_LENGTH();
2556                   break;
2557                   
2558                 case 127: /* NoOperation */
2559                   UNUSED(1);
2560                   REQUEST_LENGTH();
2561                   break;
2562             }
2563             if (*offsetp < next_offset)
2564                   proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp, next_offset - *offsetp, little_endian);
2565             *offsetp = next_offset;
2566             left = nextLeft;
2567       }
2568
2569       return left;
2570 }
2571
2572 /************************************************************************
2573  ***                                                                  ***
2574  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2575  ***                                                                  ***
2576  ************************************************************************/
2577
2578 static GTree *byte_ordering_cache = NULL;
2579 static GMemChunk *address_chunk = NULL;
2580 static GMemChunk *ipv4_chunk = NULL;
2581 static GMemChunk *ipv6_chunk = NULL;
2582
2583 static gint compareAddresses(gconstpointer aa, gconstpointer bb)
2584 {
2585       const address *a = (const address *)aa;
2586       const address *b = (const address *)bb;
2587       int c = b -> type - a -> type;
2588       if (c) return c;
2589       c = b -> len - a -> len;
2590       if (c) return c;
2591       return memcmp(b -> data, a -> data, a -> len);
2592 }
2593
2594 /* If we can't guess, we return TRUE (that is little_endian), cause
2595    I'm developing on a Linux box :-). The (non-)guess isn't cached
2596    however, so we may have more luck next time. I'm quite conservative
2597    in my assertions, cause once it's cached, it's stay in cache, and
2598    we may be fooled up by a packet starting with the end of a request
2599    started in a previous packet...
2600 */
2601
2602 int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2603
2604 int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2605 {
2606       int res = 0;
2607       while(maskLength--) {
2608             int c = tvb_get_guint8(tvb, offset);
2609             offset++;
2610             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2611       }
2612       return res;
2613 }
2614
2615 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2616 {
2617       if (listLength > length) return FALSE;
2618       while(listLength--) {
2619             int l;
2620             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2621             l = tvb_get_guint8(tvb, offset);
2622             if (!l) break;
2623             l++;
2624             if (l > length) return FALSE;
2625             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2626             offset += l;
2627             length -= l;
2628       }
2629       if (length > 3) return FALSE;
2630       return TRUE;
2631 }
2632
2633 static int rounded4(int n)
2634 {
2635       int remainder = n % 4;
2636       int res = n / 4;
2637       if (remainder) res++;
2638       return res;
2639 }
2640
2641 /* We assume the order to be consistent, until proven wrong. */
2642
2643 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2644 {
2645       switch(tvb_get_guint8(tvb, offset)) {
2646           case 1: /* CreateWindow */
2647             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2648
2649           case 2: /* ChangeWindowAttributes */
2650           case 56: /* ChangeGC */
2651             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2652
2653           case 3: /* GetWindowAttributes */
2654           case 4: /* DestroyWindow */
2655           case 5: /* DestroySubwindows */
2656           case 6: /* ChangeSaveSet */
2657           case 8: /* MapWindow */
2658           case 9: /* MapSubWindow */
2659           case 10: /* UnmapWindow */
2660           case 11: /* UnmapSubwindows */
2661           case 13: /* CirculateWindow */
2662           case 14: /* GetGeometry */
2663           case 15: /* QueryTree */
2664           case 17: /* GetAtomName */
2665           case 21: /* ListProperties */
2666           case 23: /* GetSelectionOwner */
2667           case 27: /* UngrabPointer */
2668           case 32: /* UngrabKeyboard */
2669           case 35: /* AllowEvents */
2670           case 38: /* QueryPointer */
2671           case 46: /* CloseFont */
2672           case 47: /* QueryFont */
2673           case 54: /* FreePixmap */
2674           case 60: /* FreeGC */
2675           case 79: /* FreeColormap */
2676           case 81: /* InstallColormap */
2677           case 82: /* UninstallColormap */
2678           case 83: /* ListInstalledColormaps */
2679           case 95: /* FreeCursor */
2680           case 101: /* GetKeyboardMapping */
2681           case 113: /* KillClient */
2682             return length == 2;
2683
2684           case 7: /* ReparentWindow */
2685           case 22: /* SetSelectionOwner */
2686           case 30: /* ChangeActivePointerGrab */
2687           case 31: /* GrabKeyboard */
2688           case 33: /* GrabKey */
2689           case 39: /* GetMotionEvents */
2690           case 40: /* TranslateCoordinates */
2691           case 53: /* CreatePixmap */
2692           case 57: /* CopyGC */
2693           case 61: /* ClearArea */
2694           case 78: /* CreateColormap */
2695           case 84: /* AllocColor */
2696           case 87: /* AllocColorPlanes */
2697             return length == 4;
2698
2699           case 12: /* ConfigureWindow */
2700             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2701
2702           case 16: /* InternAtom */
2703           case 98: /* QueryExtension */
2704             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2705
2706           case 18: /* ChangeProperty */
2707             {
2708                   int multiplier, type;
2709                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2710                   type = tvb_get_guint8(tvb, 16);
2711                   if (type != 8 && type != 16 && type != 32) return FALSE;
2712                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2713                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2714                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2715             }
2716
2717           case 19: /* DeleteProperty */
2718           case 29: /* UngrabButton */
2719           case 34: /* UngrabKey */
2720           case 42: /* SetInputFocus */
2721           case 80: /* CopyColormapAndFree */
2722           case 86: /* AllocColorCells */
2723           case 97: /* QueryBestSize */
2724           case 105: /* ChangePointerControl */
2725           case 107: /* SetScreenSaver */
2726             return length == 3;
2727
2728           case 20: /* GetProperty */
2729           case 24: /* ConvertSelection */
2730           case 26: /* GrabPointer */
2731           case 28: /* GrabButton */
2732           case 41: /* WarpPointer */
2733             return length == 6;
2734
2735           case 25: /* SendEvent */
2736             return length == 11;
2737
2738           case 36: /* GrabServer */
2739           case 37: /* UngrabServer */
2740           case 43: /* GetInputFocus */
2741           case 44: /* QueryKeymap */
2742           case 52: /* GetFontPath */
2743           case 99: /* ListExtensions */
2744           case 103: /* GetKeyboardControl */
2745           case 104: /* Bell */
2746           case 106: /* GetPointerControl */
2747           case 108: /* GetScreenSaver */
2748           case 110: /* ListHosts */
2749           case 111: /* SetAccessControl */
2750           case 112: /* SetCloseDownMode */
2751           case 115: /* ForceScreenSaver */
2752           case 117: /* GetPointerMapping */
2753           case 119: /* GetModifierMapping */
2754             return length == 1;
2755
2756           case 45: /* OpenFont */
2757           case 85: /* AllocNamedColor */
2758           case 92: /* LookupColor */
2759             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2760
2761           case 48: /* QueryTextExtents */
2762             return length >= 2;
2763
2764           case 49: /* ListFonts */
2765           case 50: /* ListFontsWithInfo */
2766           case 109: /* ChangeHosts */
2767             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2768
2769           case 51: /* SetFontPath */
2770             if (length < 2) return FALSE;
2771             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2772             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2773
2774           case 55: /* CreateGC */
2775             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2776
2777           case 58: /* SetDashes */
2778             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2779
2780           case 59: /* SetClipRectangles */
2781           case 66: /* PolySegment */
2782           case 67: /* PolyRectangle */
2783           case 70: /* PolyFillRectangle */
2784             return length >= 3 && (length - 3) % 2 == 0;
2785
2786           case 62: /* CopyArea */
2787             return length == 7;
2788
2789           case 63: /* CopyPlane */
2790           case 93: /* CreateCursor */
2791           case 94: /* CreateGlyphCursor */
2792             return length == 8;
2793
2794           case 64: /* PolyPoint */
2795           case 65: /* PolyLine */
2796           case 88: /* FreeColors */
2797             return length >= 3;
2798
2799           case 68: /* PolyArc */
2800           case 71: /* PolyFillArc */
2801             return length >= 3 && (length - 3) % 3 == 0;
2802
2803           case 69: /* FillPoly */
2804           case 76: /* ImageText8 */
2805             return length >= 4;
2806
2807           case 72: /* PutImage */
2808             return length >= 6;
2809
2810           case 73: /* GetImage */
2811           case 96: /* RecolorCursor */
2812             return length == 5;
2813
2814           case 74: /* PolyText8 */
2815             if (length < 4) return FALSE;
2816             return TRUE; /* We don't perform many controls on this one */
2817
2818           case 75: /* PolyText16 */
2819             if (length < 4) return FALSE;
2820             return TRUE; /* We don't perform many controls on this one */
2821
2822           case 77: /* ImageText16 */
2823             return length >= 4;
2824
2825           case 89: /* StoreColors */
2826             return length > 2 && (length - 2) % 3 == 0;
2827
2828           case 90: /* StoreNamedColor */
2829             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2830
2831           case 91: /* QueryColors */
2832             return length >= 2;
2833
2834           case 100: /* ChangeKeyboardMapping */
2835             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2836
2837           case 102: /* ChangeKeyboardControl */
2838             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2839
2840           case 114: /* RotateProperties */
2841             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2842
2843           case 116: /* SetPointerMapping */
2844             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2845
2846           case 118: /* SetModifierMapping */
2847             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2848             
2849           case 127: /* NoOperation */
2850             return length >= 1;
2851
2852           default:
2853             return TRUE;
2854       }
2855 }
2856
2857 /* -1 means doesn't match, +1 means match, 0 means don't know */
2858
2859 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2860 {
2861       int offset, nextoffset;
2862       int atLeastOne = 0;
2863
2864       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2865             int length;
2866             length = v16(tvb, offset + 2);
2867             if (!length) return -1;
2868             nextoffset = offset + length * 4;
2869             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2870             atLeastOne = 1;
2871       }
2872       return atLeastOne;
2873 }
2874
2875 static gboolean
2876 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
2877 {
2878       /* With X the client gives the byte ordering for the protocol,
2879          and the port on the server tells us we're speaking X. */
2880
2881       int le, be, decision, decisionToCache;
2882
2883       gboolean is_reply = (pinfo->srcport == pinfo->match_port);
2884       address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
2885       gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
2886       if (cache) return cache > 0 ? TRUE : FALSE;
2887       if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
2888
2889       le = x_endian_match(tvb, tvb_get_letohs);
2890       be = x_endian_match(tvb, tvb_get_ntohs);
2891
2892       /* remember that "decision" really means "little_endian". */
2893       if (le == be) {
2894             /* We have no reason to believe it's little- rather than
2895                big-endian, so we guess the shortest length is the
2896                right one.
2897             */
2898             if (!tvb_bytes_exist(tvb, 0, 4))
2899                   /* Not even a way to get the length. We're biased
2900                      toward little endianness here (essentially the
2901                      x86 world right now). Decoding won't go very far
2902                      anyway.
2903                   */
2904                   decision = TRUE;
2905             else
2906                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2907       } else
2908           decision = le >= be;
2909
2910       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2911       if (decisionToCache) {
2912             /* We encode the decision as 1 for TRUE and -1 for FALSE
2913                to be able to distinguish between FALSE and no value in
2914                the cache when recalling the value.
2915             */
2916             int address_length;
2917             char *address_data;
2918             address *cached;
2919             if (addr -> type == AT_IPv4) {
2920                   address_length = 4;
2921                   address_data = g_mem_chunk_alloc(ipv4_chunk);
2922             } else if (addr -> type == AT_IPv6) {
2923                   address_length = 16;
2924                   address_data = g_mem_chunk_alloc(ipv6_chunk);
2925             } else {
2926                   address_length = addr -> len;
2927                   address_data = g_malloc(address_length);
2928             }
2929             cached = g_mem_chunk_alloc(address_chunk);
2930             memcpy(address_data, addr -> data, address_length);
2931             SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
2932             g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
2933       }
2934             
2935       /*
2936       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n", 
2937               pinfo->fd -> num, le, be, decision, decisionToCache);
2938       */
2939       return decision;
2940 }
2941
2942 /************************************************************************
2943  ***                                                                  ***
2944  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
2945  ***                                                                  ***
2946  ************************************************************************/
2947
2948 static void
2949 dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2950 {
2951 /* Set up structures we will need to add the protocol subtree and manage it */
2952       proto_item *ti;
2953       proto_tree *x11_tree;
2954       int offset;
2955       int left;
2956         
2957 /* This field shows up as the "Info" column in the display; you should make
2958    it, if possible, summarize what's in the packet, so that a user looking
2959    at the list of packets can tell what type of packet it is. */
2960       if (check_col(pinfo->cinfo, COL_INFO)) 
2961             col_set_str(pinfo->cinfo, COL_INFO, "X11 request");
2962
2963 /* In the interest of speed, if "tree" is NULL, don't do any work not
2964    necessary to generate protocol tree items. */
2965       if (!tree) return;
2966       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2967       x11_tree = proto_item_add_subtree(ti, ett_x11);
2968
2969       offset = 0;
2970       little_endian = guess_byte_ordering(tvb, pinfo);
2971       left = dissect_x11_request_loop(tvb, &offset, x11_tree);
2972       if (left)
2973             call_dissector(data_handle, tvb_new_subset(tvb, offset,-1, tvb_reported_length_remaining(tvb, offset)), pinfo, x11_tree);
2974 }
2975
2976 static void
2977 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2978 {
2979 /* Set up structures we will need to add the protocol subtree and manage it */
2980       proto_item *ti;
2981       proto_tree *x11_tree;
2982         
2983 /* This field shows up as the "Info" column in the display; you should make
2984    it, if possible, summarize what's in the packet, so that a user looking
2985    at the list of packets can tell what type of packet it is. */
2986       if (check_col(pinfo->cinfo, COL_INFO)) 
2987             col_set_str(pinfo->cinfo, COL_INFO, "X11 event");
2988
2989 /* In the interest of speed, if "tree" is NULL, don't do any work not
2990    necessary to generate protocol tree items. */
2991       if (tree) {
2992             ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2993             x11_tree = proto_item_add_subtree(ti, ett_x11);
2994
2995 /* Code to process the packet goes here */
2996
2997             call_dissector(data_handle,tvb, pinfo, x11_tree);
2998       }
2999 }
3000
3001 static void
3002 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
3003 {
3004       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
3005             col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
3006     
3007       if (pinfo->match_port == pinfo->destport)
3008             dissect_x11_request(tvb, pinfo, tree);
3009       else
3010             dissect_x11_event(tvb, pinfo, tree);
3011 }
3012
3013 /* Register the protocol with Ethereal */
3014 void proto_register_x11(void)
3015 {                 
3016
3017 /* Setup list of header fields */
3018       static hf_register_info hf[] = {
3019 /*
3020   { &hf_x11_FIELDABBREV,
3021   { "FIELDNAME",           "x11.FIELDABBREV",
3022   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,          
3023   "FIELDDESCR", HFILL }
3024   },
3025 */
3026 #include "x11-register-info.h"
3027       };
3028
3029 /* Setup protocol subtree array */
3030       static gint *ett[] = {
3031             &ett_x11,
3032             &ett_x11_request,
3033             &ett_x11_color_flags,
3034             &ett_x11_list_of_arc,
3035             &ett_x11_arc,
3036             &ett_x11_list_of_atom,
3037             &ett_x11_list_of_card32,
3038             &ett_x11_list_of_color_item,
3039             &ett_x11_color_item,
3040             &ett_x11_list_of_keycode,
3041             &ett_x11_list_of_keysyms,
3042             &ett_x11_keysym,
3043             &ett_x11_list_of_point,
3044             &ett_x11_point,
3045             &ett_x11_list_of_rectangle,
3046             &ett_x11_rectangle,
3047             &ett_x11_list_of_segment,
3048             &ett_x11_segment,
3049             &ett_x11_list_of_string8,
3050             &ett_x11_list_of_text_item,
3051             &ett_x11_text_item,
3052             &ett_x11_gc_value_mask,
3053             &ett_x11_event_mask,
3054             &ett_x11_do_not_propagate_mask,
3055             &ett_x11_set_of_key_mask,
3056             &ett_x11_pointer_event_mask,
3057             &ett_x11_window_value_mask,
3058             &ett_x11_configure_window_mask,
3059             &ett_x11_keyboard_value_mask,
3060       };
3061
3062 /* Register the protocol name and description */
3063       proto_x11 = proto_register_protocol("X11", "X11", "x11");
3064
3065 /* Required function calls to register the header fields and subtrees used */
3066       proto_register_field_array(proto_x11, hf, array_length(hf));
3067       proto_register_subtree_array(ett, array_length(ett));
3068
3069       byte_ordering_cache = g_tree_new(compareAddresses);
3070       address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address), 
3071                                       sizeof(address) * 128, G_ALLOC_ONLY);
3072       ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
3073       ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
3074 };
3075
3076
3077 void
3078 proto_reg_handoff_x11(void)
3079 {
3080   dissector_handle_t x11_handle;
3081
3082   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
3083   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
3084   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
3085   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
3086   data_handle = find_dissector("data");
3087 }