Use "tvb_get_string()" instead of allocating a (len+1)-sized buffer,
[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  * Copyright 2003, Michael Shuldman
5  *
6  * $Id: packet-x11.c,v 1.54 2004/02/25 09:31:07 guy Exp $
7  *
8  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from README.developer
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /* TODO (in no particular order):
30  *
31  * - keep track of Atom creation by server to be able to display
32  *   non-predefined atoms
33  * - Idem for keysym <-> keycode ???
34  * - Idem for fonts
35  * - Subtree the request ids (that is x11.create-window.window and
36  *   x11.change-window.window should be  distinct), and add hidden fields
37  *   (so we still have x11.window).
38  * - add hidden fields so we can have x11.circulate-window in addition to
39  *   x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
40  *   now)
41  * - add hidden fields so we have x11.listOfStuff.length
42  * - use a faster scheme that linear list searching for the opcode.
43  * - correct display of Unicode chars.
44  * - Not everything is homogeneous, in particular the handling of items in
45  *   list is a total mess.
46  */
47
48 /* By the way, I wrote a program to generate every request and test
49  * that stuff. If you're interested, you can get it at
50  * http://tronche.com/gui/x/
51  */
52
53 #ifdef HAVE_CONFIG_H
54 # include "config.h"
55 #endif
56
57 #include <assert.h>
58 #include <ctype.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61
62 #include <string.h>
63 #include <glib.h>
64 #include <epan/packet.h>
65 #include <epan/conversation.h>
66
67 #include "prefs.h"
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
70
71 #define cVALS(x) (const value_string*)(x)
72
73 /*
74  * Data structure associated with a conversation; keeps track of the
75  * request for which we're expecting a reply, the frame number of
76  * the initial connection request, and the byte order of the connection.
77  *
78  * An opcode of -3 means we haven't yet seen any requests yet.
79  * An opcode of -2 means we're not expecting a reply.
80  * An opcode of -1 means means we're waiting for a reply to the initial
81  * connection request.
82  * Other values are the opcode of the request for which we're expecting
83  * a reply.
84  *
85  */
86 #define NOTHING_SEEN            -3
87 #define NOTHING_EXPECTED        -2
88 #define INITIAL_CONN            -1
89
90 #define BYTE_ORDER_BE           0
91 #define BYTE_ORDER_LE           1
92 #define BYTE_ORDER_UNKNOWN      -1
93
94 static const char *modifiers[] = {
95     "Shift",
96     "Lock",
97     "Control",
98     "Mod1",
99     "Mod2",
100     "Mod3",
101     "Mod4",
102     "Mod5"
103 };
104
105 /* Keymasks.  From <X11/X.h>. */
106 #define ShiftMask               (1<<0)
107 #define LockMask                (1<<1)
108 #define ControlMask             (1<<2)
109 #define Mod1Mask                (1<<3)
110 #define Mod2Mask                (1<<4)
111 #define Mod3Mask                (1<<5)
112 #define Mod4Mask                (1<<6)
113 #define Mod5Mask                (1<<7)
114
115 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
116 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
117
118 /* from <X11/X.h> */
119 #define NoSymbol             0L /* special KeySym */
120
121 typedef struct {
122       GHashTable *seqtable;     /* hashtable of sequncenumber <-> opcode.  */   
123       int       sequencenumber; /* sequencenumber of current packet.       */
124       guint32   iconn_frame;    /* frame # of initial connection request   */
125       guint32   iconn_reply;    /* frame # of initial connection reply     */
126       int       byte_order;     /* byte order of connection */
127
128       int       *keycodemap[256]; /* keycode to keysymvalue map. */
129       int       keysyms_per_keycode;
130       int       first_keycode;
131       int       *modifiermap[array_length(modifiers)];/* modifier to keycode. */
132       int       keycodes_per_modifier;
133
134       union {
135         struct {
136                 int     first_keycode;
137         } GetKeyboardMapping;
138       } request;
139 } x11_conv_data_t;
140
141 static GMemChunk *x11_state_chunk = NULL;
142
143
144 /* Initialize the protocol and registered fields */
145 static int proto_x11 = -1;
146
147 #include "x11-declarations.h"
148
149 /* Initialize the subtree pointers */
150 static gint ett_x11 = -1;
151 static gint ett_x11_color_flags = -1;
152 static gint ett_x11_list_of_arc = -1;
153 static gint ett_x11_arc = -1;
154 static gint ett_x11_list_of_atom = -1;
155 static gint ett_x11_list_of_card32 = -1;
156 static gint ett_x11_list_of_color_item = -1;
157 static gint ett_x11_color_item = -1;
158 static gint ett_x11_list_of_keycode = -1;
159 static gint ett_x11_list_of_keysyms = -1;
160 static gint ett_x11_keysym = -1;
161 static gint ett_x11_list_of_point = -1;
162 static gint ett_x11_point = -1;
163 static gint ett_x11_list_of_rectangle = -1;
164 static gint ett_x11_rectangle = -1;
165 static gint ett_x11_list_of_segment = -1;
166 static gint ett_x11_segment = -1;
167 static gint ett_x11_list_of_string8 = -1;
168 static gint ett_x11_list_of_text_item = -1;
169 static gint ett_x11_text_item = -1;
170 static gint ett_x11_gc_value_mask = -1;
171 static gint ett_x11_event_mask = -1;
172 static gint ett_x11_do_not_propagate_mask = -1;
173 static gint ett_x11_set_of_key_mask = -1;
174 static gint ett_x11_pointer_event_mask = -1;
175 static gint ett_x11_window_value_mask = -1;
176 static gint ett_x11_configure_window_mask = -1;
177 static gint ett_x11_keyboard_value_mask = -1;
178
179 /* desegmentation of X11 messages */
180 static gboolean x11_desegment = TRUE;
181
182 static dissector_handle_t data_handle;
183
184 #define TCP_PORT_X11                    6000
185 #define TCP_PORT_X11_2                  6001
186 #define TCP_PORT_X11_3                  6002
187
188 /*
189  * Round a length to a multiple of 4 bytes.
190  */
191 #define ROUND_LENGTH(n) ((((n) + 3)/4) * 4)
192
193 /************************************************************************
194  ***                                                                  ***
195  ***         E N U M   T A B L E S   D E F I N I T I O N S            ***
196  ***                                                                  ***
197  ************************************************************************/
198
199 static const value_string byte_order_vals[] = {
200      { 'B', "Big-endian" },
201      { 'l', "Little-endian" },
202      { 0,   NULL }
203 };
204
205 static const value_string image_byte_order_vals[] = {
206      { 0, "LSBFirst" },
207      { 1, "MSBFirst" },
208      { 0,   NULL }
209 };
210
211 static const value_string access_mode_vals[] = {
212       { 0, "Disable" },
213       { 1, "Enable" },
214       { 0, NULL }
215 };
216
217 static const value_string all_temporary_vals[] = {
218       { 0, "AllTemporary" },
219       { 0, NULL }
220 };
221
222 static const value_string alloc_vals[] = {
223       { 0, "None" },
224       { 1, "All" },
225       { 0, NULL }
226 };
227
228 static const value_string allow_events_mode_vals[] = {
229       { 0, "AsyncPointer" },
230       { 1, "SyncPointer" },
231       { 2, "ReplayPointer" },
232       { 3, "AsyncKeyboard" },
233       { 4, "SyncKeyboard" },
234       { 5, "ReplayKeyboard" },
235       { 6, "AsyncBoth" },
236       { 7, "SyncBoth" },
237       { 0, NULL }
238 };
239
240 static const value_string arc_mode_vals[] = {
241       { 0, "Chord" },
242       { 1, "PieSlice" },
243       { 0, NULL }
244 };
245
246 static const char *atom_predefined_interpretation[] = {
247       "<error>",
248       "PRIMARY",
249       "SECONDARY",
250       "ARC",
251       "ATOM",
252       "BITMAP",
253       "CARDINAL",
254       "COLORMAP",
255       "CURSOR",
256       "CUT_BUFFER0",
257       "CUT_BUFFER1",
258       "CUT_BUFFER2",
259       "CUT_BUFFER3",
260       "CUT_BUFFER4",
261       "CUT_BUFFER5",
262       "CUT_BUFFER6",
263       "CUT_BUFFER7",
264       "DRAWABLE",
265       "FONT",
266       "INTEGER",
267       "PIXMAP",
268       "POINT",
269       "RECTANGLE",
270       "RESOURCE_MANAGER",
271       "RGB_COLOR_MAP",
272       "RGB_BEST_MAP",
273       "RGB_BLUE_MAP",
274       "RGB_DEFAULT_MAP",
275       "RGB_GRAY_MAP",
276       "RGB_GREEN_MAP",
277       "RGB_RED_MAP",
278       "STRING",
279       "VISUALID",
280       "WINDOW",
281       "WM_COMMAND",
282       "WM_HINTS",
283       "WM_CLIENT_MACHINE",
284       "WM_ICON_NAME",
285       "WM_ICON_SIZE",
286       "WM_NAME",
287       "WM_NORMAL_HINTS",
288       "WM_SIZE_HINTS",
289       "WM_ZOOM_HINTS",
290       "MIN_SPACE",
291       "NORM_SPACE",
292       "MAX_SPACE",
293       "END_SPACE",
294       "SUPERSCRIPT_X",
295       "SUPERSCRIPT_Y",
296       "SUBSCRIPT_X",
297       "SUBSCRIPT_Y",
298       "UNDERLINE_POSITION",
299       "UNDERLINE_THICKNESS",
300       "STRIKEOUT_ASCENT",
301       "STRIKEOUT_DESCENT",
302       "ITALIC_ANGLE",
303       "X_HEIGHT",
304       "QUAD_WIDTH",
305       "WEIGHT",
306       "POINT_SIZE",
307       "RESOLUTION",
308       "COPYRIGHT",
309       "NOTICE",
310       "FONT_NAME",
311       "FAMILY_NAME",
312       "FULL_NAME",
313       "CAP_HEIGHT",
314       "WM_CLASS",
315       "WM_TRANSIENT_FOR",
316 };
317
318 static const value_string auto_repeat_mode_vals[] = {
319       { 0, "Off" },
320       { 1, "On" },
321       { 2, "Default" },
322       { 0, NULL }
323 };
324
325 static const value_string background_pixmap_vals[] = {
326       { 0, "None" },
327       { 1, "ParentRelative" },
328       { 0, NULL }
329 };
330
331 static const value_string backing_store_vals[] = {
332       { 0, "NotUseful" },
333       { 1, "WhenMapped" },
334       { 2, "Always" },
335       { 0, NULL }
336 };
337
338 static const value_string border_pixmap_vals[] = {
339       { 0, "CopyFromParent" },
340       { 0, NULL }
341 };
342
343 static const value_string button_vals[] = {
344       { 0x8000, "AnyButton" },
345       { 0, NULL }
346 };
347
348 static const value_string cap_style_vals[] = {
349       { 0, "NotLast" },
350       { 1, "Butt" },
351       { 2, "Round" },
352       { 3, "Projecting" },
353       { 0, NULL }
354 };
355
356 static const value_string class_vals[] = {
357       { 0, "Cursor" },
358       { 1, "Tile" },
359       { 2, "Stipple" },
360       { 0, NULL }
361 };
362
363 static const value_string close_down_mode_vals[] = {
364       { 0, "Destroy" },
365       { 1, "RetainPermanent" },
366       { 2, "RetainTemporary" },
367       { 0, NULL }
368 };
369
370 static const value_string coordinate_mode_vals[] = {
371       { 0, "Origin" },
372       { 1, "Previous" },
373       { 0, NULL }
374 };
375
376 static const value_string direction_vals[] = {
377       { 0, "RaiseLowest" },
378       { 1, "LowerHighest" },
379       { 0, NULL }
380 };
381
382 #define FAMILY_INTERNET 0
383 #define FAMILY_DECNET   1
384 #define FAMILY_CHAOS    2
385
386 static const value_string family_vals[] = {
387       { FAMILY_INTERNET, "Internet" },
388       { FAMILY_DECNET,   "DECnet" },
389       { FAMILY_CHAOS,    "Chaos" },
390       { 0, NULL }
391 };
392
393 static const value_string fill_rule_vals[] = {
394       { 0, "EvenOdd" },
395       { 1, "Winding" },
396       { 0, NULL }
397 };
398
399 static const value_string fill_style_vals[] = {
400       { 0, "Solid" },
401       { 1, "Tiled" },
402       { 2, "Stippled" },
403       { 3, "OpaqueStippled" },
404       { 0, NULL }
405 };
406
407 static const value_string focus_vals[] = {
408       { 0, "None" },
409       { 1, "PointerRoot" },
410       { 0, NULL }
411 };
412
413 static const value_string function_vals[] = {
414       {  0, "Clear" },
415       {  1, "And" },
416       {  2, "AndReverse" },
417       {  3, "Copy" },
418       {  4, "AndInverted" },
419       {  5, "NoOp" },
420       {  6, "Xor" },
421       {  7, "Or" },
422       {  8, "Nor" },
423       {  9, "Equiv" },
424       { 10, "Invert" },
425       { 11, "OrReverse" },
426       { 12, "CopyInverted" },
427       { 13, "OrInverted" },
428       { 14, "Nand" },
429       { 15, "Set" },
430       {  0, NULL }
431 };
432
433 static const value_string gravity_vals[] = {
434       {  1, "NorthWest" },
435       {  2, "North" },
436       {  3, "NorthEast" },
437       {  4, "West" },
438       {  5, "Center" },
439       {  6, "East" },
440       {  7, "SouthWest" },
441       {  8, "South" },
442       {  9, "SouthEast" },
443       { 10, "Static" },
444       {  0, NULL }
445 };
446
447 static const value_string image_format_vals[] = {
448       { 0, "Bitmap" },
449       { 1, "XYPixmap" },
450       { 2, "ZPixmap" },
451       { 0, NULL }
452 };
453
454 static const value_string image_pixmap_format_vals[] = {
455       { 1, "XYPixmap" },
456       { 2, "ZPixmap" },
457       { 0, NULL }
458 };
459
460 static const value_string join_style_vals[] = {
461       { 0, "Miter" },
462       { 1, "Round" },
463       { 2, "Bevel" },
464       { 0, NULL }
465 };
466
467 static const value_string key_vals[] = {
468       { 0, "AnyKey" },
469       { 0, NULL }
470 };
471
472 #include "packet-x11-keysym.h"
473
474 static const value_string line_style_vals[] = {
475       { 0, "Solid" },
476       { 1, "OnOffDash" },
477       { 2, "DoubleDash" },
478       { 0, NULL }
479 };
480
481 static const value_string mode_vals[] = {
482       { 0, "Replace" },
483       { 1, "Prepend" },
484       { 2, "Append" },
485       { 0, NULL }
486 };
487
488 static const value_string on_off_vals[] = {
489       { 0, "Off" },
490       { 1, "On" },
491       { 0, NULL }
492 };
493
494 /* Requestcodes.  From <X11/Xproto.h>. */
495 #define X_CreateWindow                  1              
496 #define X_ChangeWindowAttributes        2        
497 #define X_GetWindowAttributes           3     
498 #define X_DestroyWindow                 4
499 #define X_DestroySubwindows             5   
500 #define X_ChangeSaveSet                 6
501 #define X_ReparentWindow                7
502 #define X_MapWindow                     8
503 #define X_MapSubwindows                 9
504 #define X_UnmapWindow                  10
505 #define X_UnmapSubwindows              11  
506 #define X_ConfigureWindow              12  
507 #define X_CirculateWindow              13  
508 #define X_GetGeometry                  14
509 #define X_QueryTree                    15
510 #define X_InternAtom                   16
511 #define X_GetAtomName                  17
512 #define X_ChangeProperty               18 
513 #define X_DeleteProperty               19 
514 #define X_GetProperty                  20
515 #define X_ListProperties               21 
516 #define X_SetSelectionOwner            22    
517 #define X_GetSelectionOwner            23    
518 #define X_ConvertSelection             24   
519 #define X_SendEvent                    25
520 #define X_GrabPointer                  26
521 #define X_UngrabPointer                27
522 #define X_GrabButton                   28
523 #define X_UngrabButton                 29
524 #define X_ChangeActivePointerGrab      30          
525 #define X_GrabKeyboard                 31
526 #define X_UngrabKeyboard               32 
527 #define X_GrabKey                      33
528 #define X_UngrabKey                    34
529 #define X_AllowEvents                  35       
530 #define X_GrabServer                   36      
531 #define X_UngrabServer                 37        
532 #define X_QueryPointer                 38        
533 #define X_GetMotionEvents              39           
534 #define X_TranslateCoords              40                
535 #define X_WarpPointer                  41       
536 #define X_SetInputFocus                42         
537 #define X_GetInputFocus                43         
538 #define X_QueryKeymap                  44       
539 #define X_OpenFont                     45    
540 #define X_CloseFont                    46     
541 #define X_QueryFont                    47
542 #define X_QueryTextExtents             48     
543 #define X_ListFonts                    49  
544 #define X_ListFontsWithInfo            50 
545 #define X_SetFontPath                  51 
546 #define X_GetFontPath                  52 
547 #define X_CreatePixmap                 53        
548 #define X_FreePixmap                   54      
549 #define X_CreateGC                     55    
550 #define X_ChangeGC                     56    
551 #define X_CopyGC                       57  
552 #define X_SetDashes                    58     
553 #define X_SetClipRectangles            59             
554 #define X_FreeGC                       60  
555 #define X_ClearArea                    61             
556 #define X_CopyArea                     62    
557 #define X_CopyPlane                    63     
558 #define X_PolyPoint                    64     
559 #define X_PolyLine                     65    
560 #define X_PolySegment                  66       
561 #define X_PolyRectangle                67         
562 #define X_PolyArc                      68   
563 #define X_FillPoly                     69    
564 #define X_PolyFillRectangle            70             
565 #define X_PolyFillArc                  71       
566 #define X_PutImage                     72    
567 #define X_GetImage                     73 
568 #define X_PolyText8                    74     
569 #define X_PolyText16                   75      
570 #define X_ImageText8                   76      
571 #define X_ImageText16                  77       
572 #define X_CreateColormap               78          
573 #define X_FreeColormap                 79        
574 #define X_CopyColormapAndFree          80               
575 #define X_InstallColormap              81           
576 #define X_UninstallColormap            82             
577 #define X_ListInstalledColormaps       83                  
578 #define X_AllocColor                   84      
579 #define X_AllocNamedColor              85           
580 #define X_AllocColorCells              86           
581 #define X_AllocColorPlanes             87            
582 #define X_FreeColors                   88      
583 #define X_StoreColors                  89       
584 #define X_StoreNamedColor              90           
585 #define X_QueryColors                  91       
586 #define X_LookupColor                  92       
587 #define X_CreateCursor                 93        
588 #define X_CreateGlyphCursor            94             
589 #define X_FreeCursor                   95      
590 #define X_RecolorCursor                96         
591 #define X_QueryBestSize                97         
592 #define X_QueryExtension               98          
593 #define X_ListExtensions               99          
594 #define X_ChangeKeyboardMapping        100
595 #define X_GetKeyboardMapping           101
596 #define X_ChangeKeyboardControl        102                
597 #define X_GetKeyboardControl           103             
598 #define X_Bell                         104
599 #define X_ChangePointerControl         105
600 #define X_GetPointerControl            106
601 #define X_SetScreenSaver               107          
602 #define X_GetScreenSaver               108          
603 #define X_ChangeHosts                  109       
604 #define X_ListHosts                    110     
605 #define X_SetAccessControl             111               
606 #define X_SetCloseDownMode             112
607 #define X_KillClient                   113 
608 #define X_RotateProperties             114
609 #define X_ForceScreenSaver             115
610 #define X_SetPointerMapping            116
611 #define X_GetPointerMapping            117
612 #define X_SetModifierMapping           118
613 #define X_GetModifierMapping           119
614 #define X_NoOperation                  127
615
616 static const value_string opcode_vals[] = {
617       { INITIAL_CONN,                   "Initial connection request" },
618       { X_CreateWindow,                 "CreateWindow" },
619       { X_ChangeWindowAttributes,       "ChangeWindowAttributes" },
620       { X_GetWindowAttributes,          "GetWindowAttributes" },
621       { X_DestroyWindow,                "DestroyWindow" },
622       { X_DestroySubwindows,            "DestroySubwindows" },
623       { X_ChangeSaveSet,                "ChangeSaveSet" },
624       { X_ReparentWindow,               "ReparentWindow" },
625       { X_MapWindow,                    "MapWindow" },
626       { X_MapSubwindows,                "MapSubwindows" },
627       { X_UnmapWindow,                  "UnmapWindow" },
628       { X_UnmapSubwindows,              "UnmapSubwindows" },
629       { X_ConfigureWindow,              "ConfigureWindow" },
630       { X_CirculateWindow,              "CirculateWindow" },
631       { X_GetGeometry,                  "GetGeometry" },
632       { X_QueryTree,                    "QueryTree" },
633       { X_InternAtom,                   "InternAtom" },
634       { X_GetAtomName,                  "GetAtomName" },
635       { X_ChangeProperty,               "ChangeProperty" },
636       { X_DeleteProperty,               "DeleteProperty" },
637       { X_GetProperty,                  "GetProperty" },
638       { X_ListProperties,               "ListProperties" },
639       { X_SetSelectionOwner,            "SetSelectionOwner" },
640       { X_GetSelectionOwner,            "GetSelectionOwner" },
641       { X_ConvertSelection,             "ConvertSelection" },
642       /* { X_SendEvent,                   "SendEvent" }, */
643       { X_GrabPointer,                  "GrabPointer" },
644       { X_UngrabPointer,                "UngrabPointer" },
645       { X_GrabButton,                   "GrabButton" },
646       { X_UngrabButton,                 "UngrabButton" },
647       { X_ChangeActivePointerGrab,      "ChangeActivePointerGrab" },
648       { X_GrabKeyboard,                 "GrabKeyboard" },
649       { X_UngrabKeyboard,               "UngrabKeyboard" },
650       { X_GrabKey,                      "GrabKey" },
651       { X_UngrabKey,                    "UngrabKey" },
652       { X_AllowEvents,                  "AllowEvents" },
653       { X_GrabServer,                   "GrabServer" },
654       { X_UngrabServer,                 "UngrabServer" },
655       { X_QueryPointer,                 "QueryPointer" },
656       { X_GetMotionEvents,              "GetMotionEvents" },
657       { X_TranslateCoords,              "TranslateCoordinates" },
658       { X_WarpPointer,                  "WarpPointer" },
659       { X_SetInputFocus,                "SetInputFocus" },
660       { X_GetInputFocus,                "GetInputFocus" },
661       { X_QueryKeymap,                  "QueryKeymap" },
662       { X_OpenFont,                     "OpenFont" },
663       { X_CloseFont,                    "CloseFont" },
664       { X_QueryFont,                    "QueryFont" },
665       { X_QueryTextExtents,             "QueryTextExtents" },
666       { X_ListFonts,                    "ListFonts" },
667       { X_ListFontsWithInfo,            "ListFontsWithInfo" },
668       { X_SetFontPath,                  "SetFontPath" },
669       { X_GetFontPath,                  "GetFontPath" },
670       { X_CreatePixmap,                 "CreatePixmap" },
671       { X_FreePixmap,                   "FreePixmap" },
672       { X_CreateGC,                     "CreateGC" },
673       { X_ChangeGC,                     "ChangeGC" },
674       { X_CopyGC,                       "CopyGC" },
675       { X_SetDashes,                    "SetDashes" },
676       { X_SetClipRectangles,            "SetClipRectangles" },
677       { X_FreeGC,                       "FreeGC" },
678       { X_ClearArea,                    "ClearArea" },
679       { X_CopyArea,                     "CopyArea" },
680       { X_CopyPlane,                    "CopyPlane" },
681       { X_PolyPoint,                    "PolyPoint" },
682       { X_PolyLine,                     "PolyLine" },
683       { X_PolySegment,                  "PolySegment" },
684       { X_PolyRectangle,                "PolyRectangle" },
685       { X_PolyArc,                      "PolyArc" },
686       { X_FillPoly,                     "FillPoly" },
687       { X_PolyFillRectangle,            "PolyFillRectangle" },
688       { X_PolyFillArc,                  "PolyFillArc" },
689       { X_PutImage,                     "PutImage" },
690       { X_GetImage,                     "GetImage" },
691       { X_PolyText8,                    "PolyText8" },
692       { X_PolyText16,                   "PolyText16" },
693       { X_ImageText8,                   "ImageText8" },
694       { X_ImageText16,                  "ImageText16" },
695       { X_CreateColormap,               "CreateColormap" },
696       { X_FreeColormap,                 "FreeColormap" },
697       { X_CopyColormapAndFree,          "CopyColormapAndFree" },
698       { X_InstallColormap,              "InstallColormap" },
699       { X_UninstallColormap,            "UninstallColormap" },
700       { X_ListInstalledColormaps,       "ListInstalledColormaps" },
701       { X_AllocColor,                   "AllocColor" },
702       { X_AllocNamedColor,              "AllocNamedColor" },
703       { X_AllocColorCells,              "AllocColorCells" },
704       { X_AllocColorPlanes,             "AllocColorPlanes" },
705       { X_FreeColors,                   "FreeColors" },
706       { X_StoreColors,                  "StoreColors" },
707       { X_StoreNamedColor,              "StoreNamedColor" },
708       { X_QueryColors,                  "QueryColors" },
709       { X_LookupColor,                  "LookupColor" },
710       { X_CreateCursor,                 "CreateCursor" },
711       { X_CreateGlyphCursor,            "CreateGlyphCursor" },
712       { X_FreeCursor,                   "FreeCursor" },
713       { X_RecolorCursor,                "RecolorCursor" },
714       { X_QueryBestSize,                "QueryBestSize" },
715       { X_QueryExtension,               "QueryExtension" },
716       { X_ListExtensions,               "ListExtensions" },
717       { X_ChangeKeyboardMapping,        "ChangeKeyboardMapping" },
718       { X_GetKeyboardMapping,           "GetKeyboardMapping" },
719       { X_ChangeKeyboardControl,        "ChangeKeyboardControl" },
720       { X_GetKeyboardControl,           "GetKeyboardControl" },
721       { X_Bell,                         "Bell" },
722       { X_ChangePointerControl,         "ChangePointerControl" },
723       { X_GetPointerControl,            "GetPointerControl" },
724       { X_SetScreenSaver,               "SetScreenSaver" },
725       { X_GetScreenSaver,               "GetScreenSaver" },
726       { X_ChangeHosts,                  "ChangeHosts" },
727       { X_ListHosts,                    "ListHosts" },
728       { X_SetAccessControl,             "SetAccessControl" },
729       { X_SetCloseDownMode,             "SetCloseDownMode" },
730       { X_KillClient,                   "KillClient" },
731       { X_RotateProperties,             "RotateProperties" },
732       { X_ForceScreenSaver,             "ForceScreenSaver" },
733       { X_SetPointerMapping,            "SetPointerMapping" },
734       { X_GetPointerMapping,            "GetPointerMapping" },
735       { X_SetModifierMapping,           "SetModifierMapping" },
736       { X_GetModifierMapping,           "GetModifierMapping" },
737       { X_NoOperation,                  "NoOperation" },
738       { 0,                              NULL }
739 };
740
741 /* Eventscodes.  From <X11/X.h>. */
742 #define KeyPress                2
743 #define KeyRelease              3
744 #define ButtonPress             4
745 #define ButtonRelease           5
746 #define MotionNotify            6
747 #define EnterNotify             7
748 #define LeaveNotify             8
749 #define FocusIn                 9
750 #define FocusOut                10
751 #define KeymapNotify            11
752 #define Expose                  12
753 #define GraphicsExpose          13
754 #define NoExpose                14
755 #define VisibilityNotify        15
756 #define CreateNotify            16
757 #define DestroyNotify           17
758 #define UnmapNotify             18
759 #define MapNotify               19
760 #define MapRequest              20
761 #define ReparentNotify          21
762 #define ConfigureNotify         22
763 #define ConfigureRequest        23
764 #define GravityNotify           24
765 #define ResizeRequest           25
766 #define CirculateNotify         26
767 #define CirculateRequest        27
768 #define PropertyNotify          28
769 #define SelectionClear          29
770 #define SelectionRequest        30
771 #define SelectionNotify         31
772 #define ColormapNotify          32
773 #define ClientMessage           33
774 #define MappingNotify           34
775
776 static const value_string eventcode_vals[] = {
777         { KeyPress,          "KeyPress" },
778         { KeyRelease,        "KeyRelease" },
779         { ButtonPress,       "ButtonPress" },
780         { ButtonRelease,     "ButtonRelease" },
781         { MotionNotify,      "MotionNotify" },
782         { EnterNotify,       "EnterNotify" },
783         { LeaveNotify,       "LeaveNotify" },
784         { FocusIn,           "FocusIn" },
785         { FocusOut,          "FocusOut" },
786         { KeymapNotify,      "KeymapNotify" },
787         { Expose,            "Expose" },
788         { GraphicsExpose,    "GraphicsExpose" },
789         { NoExpose,          "NoExpose" },
790         { VisibilityNotify,  "VisibilityNotify" },
791         { CreateNotify,      "CreateNotify" },
792         { DestroyNotify,     "DestroyNotify" },
793         { UnmapNotify,       "UnmapNotify" },
794         { MapNotify,         "MapNotify" },
795         { MapRequest,        "MapRequest" },
796         { ReparentNotify,    "ReparentNotify" },
797         { ConfigureNotify,   "ConfigureNotify" },
798         { ConfigureRequest,  "ConfigureRequest" },
799         { GravityNotify,     "GravityNotify" },
800         { ResizeRequest,     "ResizeRequest" },
801         { CirculateNotify,   "CirculateNotify" },
802         { CirculateRequest,  "CirculateRequest" },
803         { PropertyNotify,    "PropertyNotify" },
804         { SelectionClear,    "SelectionClear" },
805         { SelectionRequest,  "SelectionRequest" },
806         { SelectionNotify,   "SelectionNotify" },
807         { ColormapNotify,    "ColormapNotify" },
808         { ClientMessage,     "ClientMessage" },
809         { MappingNotify,     "MappingNotify" },
810         { 0,                 NULL }
811 };
812
813 /* Errorcodes.  From <X11/X.h> */
814 #define Success                 0       /* everything's okay */
815 #define BadRequest              1       /* bad request code */
816 #define BadValue                2       /* int parameter out of range */
817 #define BadWindow               3       /* parameter not a Window */
818 #define BadPixmap               4       /* parameter not a Pixmap */
819 #define BadAtom                 5       /* parameter not an Atom */
820 #define BadCursor               6       /* parameter not a Cursor */
821 #define BadFont                 7       /* parameter not a Font */
822 #define BadMatch                8       /* parameter mismatch */
823 #define BadDrawable             9       /* parameter not a Pixmap or Window */
824 #define BadAccess               10      /* depending on context:
825                                          - key/button already grabbed
826                                          - attempt to free an illegal 
827                                            cmap entry 
828                                         - attempt to store into a read-only 
829                                            color map entry.
830                                         - attempt to modify the access control
831                                            list from other than the local host.
832                                         */
833 #define BadAlloc                11      /* insufficient resources */
834 #define BadColor                12      /* no such colormap */
835 #define BadGC                   13      /* parameter not a GC */
836 #define BadIDChoice             14      /* choice not in range or already used */
837 #define BadName                 15      /* font or color name doesn't exist */
838 #define BadLength               16      /* Request length incorrect */
839 #define BadImplementation       17      /* server is defective */
840
841 #define FirstExtensionError     128
842 #define LastExtensionError      255
843
844 static const value_string errorcode_vals[] = {
845         { Success,               "Success" },
846         { BadRequest,            "BadRequest" },
847         { BadValue,              "BadValue" },
848         { BadWindow,             "BadWindow" },
849         { BadPixmap,             "BadPixmap" },
850         { BadAtom,               "BadAtom" },
851         { BadCursor,             "BadCursor" },
852         { BadFont,               "BadFont" },
853         { BadMatch,              "BadMatch" },
854         { BadDrawable,           "BadDrawable" },
855         { BadAccess,             "BadAccess" },
856         { BadAlloc,              "BadAlloc" },
857         { BadColor,              "BadColor" },
858         { BadGC,                 "BadGC" },
859         { BadIDChoice,           "BadIDChoice" },
860         { BadName,               "BadName" },
861         { BadLength,             "BadLength" },
862         { BadImplementation,     "BadImplementation" },
863         { FirstExtensionError,   "FirstExtensionError" },
864         { LastExtensionError,    "LastExtensionError" },
865         { 0,                     NULL }
866 };
867
868 static const value_string ordering_vals[] = {
869       { 0, "UnSorted" },
870       { 1, "YSorted" },
871       { 2, "YXSorted" },
872       { 3, "YXBanded" },
873       { 0, NULL }
874 };
875
876 static const value_string plane_mask_vals[] = {
877       { 0xFFFFFFFF, "AllPlanes" },
878       { 0, NULL }
879 };
880
881 static const value_string pointer_keyboard_mode_vals[] = {
882       { 0, "Synchronous" },
883       { 1, "Asynchronous" },
884       { 0, NULL }
885 };
886
887 static const value_string revert_to_vals[] = {
888       { 0, "None" },
889       { 1, "PointerRoot" },
890       { 2, "Parent" },
891       { 0, NULL }
892 };
893
894 static const value_string insert_delete_vals[] = {
895       { 0, "Insert" },
896       { 1, "Delete" },
897       { 0, NULL }
898 };
899
900 static const value_string screen_saver_mode_vals[] = {
901       { 0, "Reset" },
902       { 1, "Activate" },
903       { 0, NULL }
904 };
905
906 static const value_string shape_vals[] = {
907       { 0, "Complex" },
908       { 1, "Nonconvex" },
909       { 2, "Convex" },
910       { 0, NULL }
911 };
912
913 static const value_string stack_mode_vals[] = {
914       { 0, "Above" },
915       { 1, "Below" },
916       { 2, "TopIf" },
917       { 3, "BottomIf" },
918       { 4, "Opposite" },
919       { 0, NULL }
920 };
921
922 static const value_string subwindow_mode_vals[] = {
923       { 0, "ClipByChildren" },
924       { 1, "IncludeInferiors" },
925       { 0, NULL }
926 };
927
928 static const value_string window_class_vals[] = {
929       { 0, "CopyFromParent" },
930       { 1, "InputOutput" },
931       { 2, "InputOnly" },
932       { 0, NULL }
933 };
934
935 static const value_string yes_no_default_vals[] = {
936       { 0, "No" },
937       { 1, "Yes" },
938       { 2, "Default" },
939       { 0, NULL }
940 };
941
942 static const value_string zero_is_any_property_type_vals[] = {
943       { 0, "AnyPropertyType" },
944       { 0, NULL }
945 };
946
947 static const value_string zero_is_none_vals[] = {
948       { 0, "None" },
949       { 0, NULL }
950 };
951
952 /* we have not seen packet before. */
953 #define PACKET_IS_NEW(pinfo) \
954         (!((pinfo)->fd->flags.visited))
955
956 /************************************************************************
957  ***                                                                  ***
958  ***           F I E L D   D E C O D I N G   M A C R O S              ***
959  ***                                                                  ***
960  ************************************************************************/
961
962 #define VALUE8(tvb, offset) (tvb_get_guint8(tvb, offset))
963 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
964 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
965
966 #define FIELD8(name)  (field8(tvb, offsetp, t, hf_x11_##name, little_endian))
967 #define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name, little_endian))
968 #define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name, little_endian))
969
970 #define BITFIELD(TYPE, position, name) {\
971   int unused;\
972   int save = *offsetp;\
973   proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
974                       bitmask_size, little_endian); \
975   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
976        TYPE(name);\
977        unused = save + 4 - *offsetp;\
978        if (unused)\
979            proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
980        *offsetp = save + 4;\
981  }\
982 }
983
984 #define FLAG(position, name) {\
985        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
986
987 #define FLAG_IF_NONZERO(position, name) do {\
988   if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
989        proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); } while (0)
990
991 #define ATOM(name)     { atom(tvb, offsetp, t, hf_x11_##name, little_endian); }
992 #define BITGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Forget"); }
993 #define BITMASK(name, size) {\
994       proto_item *ti; \
995       guint32 bitmask_value; \
996       int bitmask_offset; \
997       int bitmask_size; \
998       proto_tree *bitmask_tree; \
999       bitmask_value = ((size == 1) ? (guint32)VALUE8(tvb, *offsetp) : \
1000                        ((size == 2) ? (guint32)VALUE16(tvb, *offsetp) : \
1001                                       (guint32)VALUE32(tvb, *offsetp))); \
1002       bitmask_offset = *offsetp; \
1003       bitmask_size = size; \
1004       ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
1005       bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
1006       *offsetp += size;
1007 #define ENDBITMASK      }
1008 #define BITMASK8(name)  BITMASK(name, 1);
1009 #define BITMASK16(name) BITMASK(name, 2);
1010 #define BITMASK32(name) BITMASK(name, 4);
1011 #define BOOL(name)     (add_boolean(tvb, offsetp, t, hf_x11_##name))
1012 #define BUTTON(name)   FIELD8(name)
1013 #define CARD8(name)    FIELD8(name)
1014 #define CARD16(name)   (FIELD16(name))
1015 #define CARD32(name)   (FIELD32(name))
1016 #define COLOR_FLAGS(name) colorFlags(tvb, offsetp, t)
1017 #define COLORMAP(name) FIELD32(name)
1018 #define CURSOR(name)   FIELD32(name)
1019 #define DRAWABLE(name) FIELD32(name)
1020 #define ENUM8(name)    (FIELD8(name))
1021 #define ENUM16(name)   (FIELD16(name))
1022 #define FONT(name)     FIELD32(name)
1023 #define FONTABLE(name) FIELD32(name)
1024 #define GCONTEXT(name) FIELD32(name)
1025 #define INT8(name)     FIELD8(name)
1026 #define INT16(name)    FIELD16(name)
1027 #define INT32(name)    FIELD32(name)
1028 #define KEYCODE(name)  FIELD8(name)
1029 #define KEYCODE_DECODED(name, keycode, mask)  do {                      \
1030         proto_tree_add_uint_format(t, hf_x11_##name, tvb, offset, 1,    \
1031         keycode, "keycode: %d (%s)",                            \
1032         keycode,  keycode2keysymString(state->keycodemap,               \
1033         state->first_keycode, state->keysyms_per_keycode,               \
1034         state->modifiermap, state->keycodes_per_modifier,               \
1035         keycode, mask));                                                \
1036         ++offset;                                                       \
1037 } while (0)
1038
1039 #define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12, little_endian); }
1040 #define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1041 #define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1042 #define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length), little_endian); }
1043 #define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4, little_endian); }
1044 #define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12, little_endian); }
1045 #define LISTofKEYCODE(map, name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, map, (length), little_endian); }
1046 #define LISTofKEYSYM(name, map, keycode_first, keycode_count, \
1047 keysyms_per_keycode) {\
1048       listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, map, (keycode_first), (keycode_count), (keysyms_per_keycode), little_endian); }
1049 #define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4, little_endian); }
1050 #define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1051 #define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8, little_endian); }
1052 #define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length), little_endian); }
1053 #define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset, little_endian); }
1054 #define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset, little_endian); }
1055 #define OPCODE()       { opcode = FIELD8(opcode); }
1056 #define PIXMAP(name)   { FIELD32(name); }
1057 #define REQUEST_LENGTH() (requestLength(tvb, offsetp, t, little_endian))
1058 #define SETofEVENT(name) { setOfEvent(tvb, offsetp, t, little_endian); }
1059 #define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t, little_endian);}
1060 #define SETofKEYMASK(name) { setOfKeyButMask(tvb, offsetp, t, little_endian, 0); }
1061 #define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t, little_endian); }
1062 #define STRING8(name, length)  { string8(tvb, offsetp, t, hf_x11_##name, length); }
1063 #define STRING16(name, length)  { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length, little_endian); }
1064 #define TIMESTAMP(name){ timestamp(tvb, offsetp, t, hf_x11_##name, little_endian); }
1065 #define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp,  x, little_endian); *offsetp += x; }
1066 #define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp,  x, little_endian); *offsetp += x; }
1067 #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; }
1068 #define WINDOW(name)   { FIELD32(name); }
1069 #define WINGRAVITY(name) { gravity(tvb, offsetp, t, hf_x11_##name, "Unmap"); }
1070
1071 #define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
1072     proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
1073                                v ? "" : " (CopyFromParent)"); *offsetp += 4; }
1074 #define REPLY(name)       FIELD8(name);
1075 #define REPLYLENGTH(name) FIELD32(name);
1076
1077 #define EVENTCONTENTS_COMMON() do {                                          \
1078                         TIMESTAMP(time);                                     \
1079                         WINDOW(rootwindow);                                  \
1080                         WINDOW(eventwindow);                                 \
1081                         WINDOW(childwindow);                                 \
1082                         INT16(root_x);                                       \
1083                         INT16(root_y);                                       \
1084                         INT16(event_x);                                      \
1085                         INT16(event_y);                                      \
1086                         setOfKeyButMask(tvb, offsetp, t, little_endian, 1);  \
1087 } while (0)
1088
1089 #define SEQUENCENUMBER_REPLY(name) do {                                 \
1090         guint16 seqno;                                                  \
1091                                                                         \
1092         seqno = VALUE16(tvb, *offsetp);                                 \
1093         proto_tree_add_uint_format(t, hf_x11_reply_##name, tvb,         \
1094         *offsetp, sizeof(seqno), seqno,                                 \
1095         "sequencenumber: %d (%s)",                                      \
1096         (int)seqno,                                                     \
1097         val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));                \
1098         *offsetp += sizeof(seqno);                                      \
1099 } while (0) 
1100
1101 #define REPLYCONTENTS_COMMON() do {                                     \
1102         REPLY(reply);                                                   \
1103         proto_tree_add_item(t, hf_x11_undecoded, tvb, offset,           \
1104         1, little_endian);                                              \
1105         ++offset;                                                       \
1106         SEQUENCENUMBER_REPLY(sequencenumber);                           \
1107         REPLYLENGTH(replylength);                                       \
1108         proto_tree_add_item(t, hf_x11_undecoded, tvb, offset,           \
1109         tvb_reported_length_remaining(tvb, offset), little_endian);     \
1110         offset += tvb_reported_length_remaining(tvb, offset);           \
1111 } while (0)
1112
1113
1114 #define HANDLE_REPLY(plen, length_remaining, str, func) do {            \
1115         if (length_remaining < plen) {                                  \
1116                 if (x11_desegment && pinfo->can_desegment) {            \
1117                         pinfo->desegment_offset = offset;               \
1118                         pinfo->desegment_len    = plen - length_remaining;\
1119                         return;                                         \
1120                 } else {                                                \
1121                         ; /* XXX yes, what then?  Need to skip/join. */ \
1122                 }                                                       \
1123         }                                                               \
1124         if (length_remaining > plen)                                    \
1125                 length_remaining = plen;                                \
1126         next_tvb = tvb_new_subset(tvb, offset, length_remaining, plen); \
1127                                                                         \
1128         if (sep == NULL) {                                              \
1129            if (check_col(pinfo->cinfo, COL_INFO))                       \
1130                    col_add_str(pinfo->cinfo, COL_INFO, str);            \
1131            sep = ":";                                                   \
1132         }                                                               \
1133                                                                         \
1134         TRY {                                                           \
1135                 func(next_tvb, pinfo, tree, sep, state, little_endian); \
1136         }                                                               \
1137                                                                         \
1138         CATCH(BoundsError) {                                            \
1139                 RETHROW;                                                \
1140         }                                                               \
1141         CATCH(ReportedBoundsError) {                                    \
1142                 show_reported_bounds_error(next_tvb, pinfo, tree);      \
1143         }                                                               \
1144         ENDTRY;                                                         \
1145                                                                         \
1146         sep = ",";                                                      \
1147 } while (0)     
1148
1149 static void
1150 dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1151                   const char *sep, x11_conv_data_t *volatile state,
1152                   gboolean little_endian);
1153
1154 static void
1155 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1156                   const char *volatile sep, x11_conv_data_t *volatile state,
1157                   gboolean little_endian);
1158
1159 static void
1160 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1161                   const char *volatile sep, x11_conv_data_t *volatile state,
1162                   gboolean little_endian);
1163
1164 static void
1165 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1166                   const char *volatile sep, x11_conv_data_t *volatile state,
1167                   gboolean little_endian);
1168
1169 static void
1170 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation);
1171
1172 static const char *
1173 keysymString(guint32 v);
1174
1175
1176 /************************************************************************
1177  ***                                                                  ***
1178  ***                  D E C O D I N G   F I E L D S                   ***
1179  ***                                                                  ***
1180  ************************************************************************/
1181
1182 static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1183                  gboolean little_endian)
1184 {
1185       const char *interpretation = NULL;
1186
1187       guint32 v = VALUE32(tvb, *offsetp);
1188       if (v >= 1 && v < array_length(atom_predefined_interpretation))
1189             interpretation = atom_predefined_interpretation[v];
1190       else if (v)
1191             interpretation = "Not a predefined atom";
1192       else {
1193             header_field_info *hfi = proto_registrar_get_nth(hf);
1194             if (hfi -> strings)
1195                   interpretation = match_strval(v, cVALS(hfi -> strings));
1196       }
1197       if (!interpretation) interpretation = "error in Xlib client program ?";
1198       proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)",
1199                                  proto_registrar_get_nth(hf) -> name, v, interpretation);
1200       *offsetp += 4;
1201 }
1202
1203 static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
1204 {
1205       guint32 v = VALUE8(tvb, *offsetp);
1206       proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
1207       *offsetp += 1;
1208       return v;
1209 }
1210
1211 static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
1212 {
1213       unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
1214       proto_item *ti;
1215       proto_tree *tt;
1216
1217       if (do_red_green_blue) {
1218             int sep = FALSE;
1219             char buffer[512];
1220             char *bp = buffer + sprintf(buffer, "flags: ");
1221
1222             if (do_red_green_blue & 0x1) {
1223                   bp += sprintf(bp, "DoRed");
1224                   sep = TRUE;
1225             }
1226
1227             if (do_red_green_blue & 0x2) {
1228                   if (sep) bp += sprintf(bp, " | ");
1229                   bp += sprintf(bp, "DoGreen");
1230                   sep = TRUE;
1231             }
1232
1233             if (do_red_green_blue & 0x4) {
1234                   if (sep) bp += sprintf(bp, " | ");
1235                   bp += sprintf(bp, "DoBlue");
1236                   sep = TRUE;
1237             }
1238
1239             if (do_red_green_blue & 0xf8) {
1240                   if (sep) bp += sprintf(bp, " + ");
1241                   sprintf(bp, "trash");
1242             }
1243
1244             ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1245                                             "%s", buffer);
1246             tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1247             if (do_red_green_blue & 0x1)
1248                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1249                                          do_red_green_blue & 0x1);
1250             if (do_red_green_blue & 0x2)
1251                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1252                                          do_red_green_blue & 0x2);
1253             if (do_red_green_blue & 0x4)
1254                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1255                                          do_red_green_blue & 0x4);
1256             if (do_red_green_blue & 0xf8)
1257                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1258                                          do_red_green_blue & 0xf8);
1259       } else
1260             proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1261                                        "flags: none");
1262       *offsetp += 1;
1263 }
1264
1265 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1266     int hf, const char *nullInterpretation)
1267 {
1268       guint8 v = VALUE8(tvb, *offsetp);
1269
1270       if (!v)
1271             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1272                                        proto_registrar_get_nth(hf) -> name,
1273                                        nullInterpretation);
1274       else
1275             proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1276       *offsetp += 1;
1277 }
1278
1279 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1280                       int length, gboolean little_endian)
1281 {
1282       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1283       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1284       while(length--) {
1285             gint16 x = VALUE16(tvb, *offsetp);
1286             gint16 y = VALUE16(tvb, *offsetp + 2);
1287             guint16 width = VALUE16(tvb, *offsetp + 4);
1288             guint16 height = VALUE16(tvb, *offsetp + 6);
1289             gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1290             gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1291
1292             proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1293                                                              "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1294                                                              width, height, x, y, angle1, angle2,
1295                                                              angle1 / 64.0, angle2 / 64.0);
1296             proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1297             proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1298             *offsetp += 2;
1299             proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1300             *offsetp += 2;
1301             proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1302             *offsetp += 2;
1303             proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1304             *offsetp += 2;
1305             proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1306             *offsetp += 2;
1307             proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1308             *offsetp += 2;
1309       }
1310 }
1311
1312 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1313                        int length, gboolean little_endian)
1314 {
1315       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1316       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1317       while(length--)
1318             atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1319 }
1320
1321 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1322                        int length, gboolean little_endian)
1323 {
1324       if (length <= 0) length = 1;
1325       proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1326       *offsetp += length;
1327 }
1328
1329 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1330                          int hf_item, int length, gboolean little_endian)
1331 {
1332       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1333       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1334       while(length--) {
1335             proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1336             *offsetp += 4;
1337       }
1338 }
1339
1340 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1341                             int length, gboolean little_endian)
1342 {
1343       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1344       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1345       while(length--) {
1346             proto_item *tti;
1347             proto_tree *ttt;
1348             unsigned do_red_green_blue;
1349             guint16 red, green, blue;
1350             char buffer[1024];
1351             char *bp;
1352             const char *sep;
1353
1354             red = VALUE16(tvb, *offsetp + 4);
1355             green = VALUE16(tvb, *offsetp + 6);
1356             blue = VALUE16(tvb, *offsetp + 8);
1357             do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1358
1359             bp = buffer + sprintf(buffer, "colorItem: ");
1360             sep = "";
1361             if (do_red_green_blue & 0x1) {
1362                 bp += sprintf(bp, "red = %d", red);
1363                 sep = ", ";
1364             }
1365             if (do_red_green_blue & 0x2) {
1366                 bp += sprintf(bp, "%sgreen = %d", sep, green);
1367                 sep = ", ";
1368             }
1369             if (do_red_green_blue & 0x4)
1370                 bp += sprintf(bp, "%sblue = %d", sep, blue);
1371
1372             tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1373             ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1374             proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1375             *offsetp += 4;
1376             proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1377             *offsetp += 2;
1378             proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1379             *offsetp += 2;
1380             proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1381             *offsetp += 2;
1382             colorFlags(tvb, offsetp, ttt);
1383             proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1384             *offsetp += 1;
1385       }
1386 }
1387
1388 static GTree *keysymTable = NULL;
1389
1390 static gint compareGuint32(gconstpointer a, gconstpointer b)
1391 {
1392       return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1393 }
1394
1395 static void
1396 XConvertCase(register int sym, int *lower, int *upper)
1397 {
1398     *lower = sym;
1399     *upper = sym;
1400     switch(sym >> 8) {
1401     case 0: /* Latin 1 */
1402         if ((sym >= XK_A) && (sym <= XK_Z))
1403             *lower += (XK_a - XK_A);
1404         else if ((sym >= XK_a) && (sym <= XK_z))
1405             *upper -= (XK_a - XK_A);
1406         else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1407             *lower += (XK_agrave - XK_Agrave);
1408         else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1409             *upper -= (XK_agrave - XK_Agrave);
1410         else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1411             *lower += (XK_oslash - XK_Ooblique);
1412         else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1413             *upper -= (XK_oslash - XK_Ooblique);
1414         break;
1415     case 1: /* Latin 2 */
1416         /* Assume the KeySym is a legal value (ignore discontinuities) */
1417         if (sym == XK_Aogonek)
1418             *lower = XK_aogonek;
1419         else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1420             *lower += (XK_lstroke - XK_Lstroke);
1421         else if (sym >= XK_Scaron && sym <= XK_Zacute)
1422             *lower += (XK_scaron - XK_Scaron);
1423         else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1424             *lower += (XK_zcaron - XK_Zcaron);
1425         else if (sym == XK_aogonek)
1426             *upper = XK_Aogonek;
1427         else if (sym >= XK_lstroke && sym <= XK_sacute)
1428             *upper -= (XK_lstroke - XK_Lstroke);
1429         else if (sym >= XK_scaron && sym <= XK_zacute)
1430             *upper -= (XK_scaron - XK_Scaron);
1431         else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1432             *upper -= (XK_zcaron - XK_Zcaron);
1433         else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1434             *lower += (XK_racute - XK_Racute);
1435         else if (sym >= XK_racute && sym <= XK_tcedilla)
1436             *upper -= (XK_racute - XK_Racute);
1437         break;
1438     case 2: /* Latin 3 */
1439         /* Assume the KeySym is a legal value (ignore discontinuities) */
1440         if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1441             *lower += (XK_hstroke - XK_Hstroke);
1442         else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1443             *lower += (XK_gbreve - XK_Gbreve);
1444         else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1445             *upper -= (XK_hstroke - XK_Hstroke);
1446         else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1447             *upper -= (XK_gbreve - XK_Gbreve);
1448         else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1449             *lower += (XK_cabovedot - XK_Cabovedot);
1450         else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1451             *upper -= (XK_cabovedot - XK_Cabovedot);
1452         break;
1453     case 3: /* Latin 4 */
1454         /* Assume the KeySym is a legal value (ignore discontinuities) */
1455         if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1456             *lower += (XK_rcedilla - XK_Rcedilla);
1457         else if (sym >= XK_rcedilla && sym <= XK_tslash)
1458             *upper -= (XK_rcedilla - XK_Rcedilla);
1459         else if (sym == XK_ENG)
1460             *lower = XK_eng;
1461         else if (sym == XK_eng)
1462             *upper = XK_ENG;
1463         else if (sym >= XK_Amacron && sym <= XK_Umacron)
1464             *lower += (XK_amacron - XK_Amacron);
1465         else if (sym >= XK_amacron && sym <= XK_umacron)
1466             *upper -= (XK_amacron - XK_Amacron);
1467         break;
1468     case 6: /* Cyrillic */
1469         /* Assume the KeySym is a legal value (ignore discontinuities) */
1470         if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1471             *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1472         else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1473             *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1474         else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1475             *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1476         else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1477             *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1478         break;
1479     case 7: /* Greek */
1480         /* Assume the KeySym is a legal value (ignore discontinuities) */
1481         if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1482             *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1483         else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1484                  sym != XK_Greek_iotaaccentdieresis &&
1485                  sym != XK_Greek_upsilonaccentdieresis)
1486             *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1487         else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1488             *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1489         else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1490                  sym != XK_Greek_finalsmallsigma)
1491             *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1492         break;
1493     }
1494 }
1495
1496 static const char *
1497 keycode2keysymString(int *keycodemap[256], int first_keycode,
1498                      int keysyms_per_keycode, 
1499                      int *modifiermap[array_length(modifiers)],
1500                      int keycodes_per_modifier,
1501                      guint32 keycode, guint32 bitmask)
1502 {
1503         static char buf[32];
1504         int *syms;
1505         int groupmodkc, numlockkc, numlockmod, groupmod;
1506         int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1507         int lockmod_is_nosymbol = 1;
1508         int modifier, kc, keysym;
1509
1510         if ((syms = keycodemap[keycode]) == NULL)
1511                 return "<Unknown>";
1512
1513         for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1514                 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym)
1515                         switch (keycodemap[kc][keysym]) {
1516                                 case 0xff7e:
1517                                         groupmodkc = kc;
1518                                         break;
1519
1520                                 case 0xff7f:
1521                                         numlockkc = kc;
1522                                         break;
1523
1524                                 case 0xffe5:
1525                                         lockmod_is_capslock = kc;
1526                                         break;
1527
1528                                 case 0xffe6:
1529                                         lockmod_is_shiftlock = kc;
1530                                         break;
1531                         }
1532
1533
1534         /*
1535          * If we have not seen the modifiermap we don't know what the
1536          * keycode translates to, but we do know it's one of the keys 
1537          * in syms (give or take a case-conversion), so we could in 
1538          * theory list them all.
1539          */
1540         if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1541                 return "<Unknown>";
1542
1543         /* find out what the numlockmodifer and groupmodifier is. */
1544         for (modifier = 0, numlockmod = groupmod = -1;
1545         modifier < (int)array_length(modifiers) && numlockmod == -1;
1546         ++modifier)
1547                 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1548                         if (modifiermap[modifier][kc] == numlockkc)
1549                                 numlockmod = modifier;
1550                         else if (modifiermap[modifier][kc] == groupmodkc)
1551                                 groupmod = modifier;
1552
1553         /*
1554          * ... and what the lockmodifier is interpreted as.
1555          * (X11v4r6 ref, keyboard and pointers section.)
1556          */
1557         for (kc = 0; kc < keycodes_per_modifier; ++kc)
1558                 if (modifiermap[1][kc] == lockmod_is_capslock) {
1559                         lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1560                         break;
1561                 }
1562                 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1563                         lockmod_is_capslock = lockmod_is_nosymbol = 0;
1564                         break;
1565                 }
1566
1567 #if 0 
1568         /* 
1569          * This is (how I understand) the X11v4R6 protocol description given
1570          * in A. Nye's book.  It is quite different from the
1571          * code in _XTranslateKey() in the file 
1572          * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1573          * as shipped with XFree, and doesn't work correctly, nor do I see
1574          * how it could (e.g. the case of lower/uppercase-letters).
1575          * -- Michael Shuldman
1576          */
1577
1578         if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1579         && ((keycodemap[keycode][1] >= 0xff80
1580          && keycodemap[keycode][1] <= 0xffbd)
1581          || (keycodemap[keycode][1] >= 0x11000000
1582          && keycodemap[keycode][1] <= 0x1100ffff))) {
1583                 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1584                         return keysymString(keycodemap[keycode][groupmod + 0]);
1585                 else
1586                         if (keycodemap[keycode][groupmod + 1] == NoSymbol)
1587                                 return keysymString(keycodemap[keycode]
1588                                 [groupmod + 0]);
1589                         else
1590                                 return keysymString(keycodemap[keycode]
1591                                 [groupmod + 1]);
1592         }
1593         else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1594                 return keysymString(keycodemap[keycode][groupmod + 0]);
1595         else if (!(bitmask & ShiftMask)
1596         && ((bitmask & LockMask) && lockmod_is_capslock))
1597                 if (islower(keycodemap[keycode][groupmod + 0]))
1598 /*                      return toupper(keysymString(keycodemap[keycode][groupmod + 0])); */
1599                         return "Uppercase"; /* XXX */
1600                 else
1601                         return keysymString(keycodemap[keycode][groupmod + 0]);
1602
1603         else if ((bitmask & ShiftMask) 
1604         && ((bitmask & LockMask) && lockmod_is_capslock))
1605                 if (islower(keycodemap[keycode][groupmod + 1]))
1606 /*                      return toupper(keysymString(keycodemap[keycode][groupmod + 1])); */
1607                         return "Uppercase"; /* XXX */
1608                 else
1609                         return keysymString(keycodemap[keycode][groupmod + 1]);
1610
1611         else if ((bitmask & ShiftMask) 
1612         ||  ((bitmask & LockMask) && lockmod_is_shiftlock))
1613                         return keysymString(keycodemap[keycode][groupmod + 1]);
1614 #else /* _XTranslateKey() based code. */
1615
1616         while (keysyms_per_keycode > 2
1617         && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1618                 --keysyms_per_keycode;
1619         if (keysyms_per_keycode > 2
1620         && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1621                 syms += 2;
1622                 keysyms_per_keycode -= 2;
1623         }
1624         
1625         if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1626         && keysyms_per_keycode > 1 && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1627          || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1628                 if ((bitmask & ShiftMask)
1629                 || (bitmask & LockMask && lockmod_is_shiftlock))
1630                         keysym = syms[0];
1631                 else
1632                         keysym = syms[1];
1633         }
1634         else if (!(bitmask & ShiftMask)
1635         && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1636                 if (keysyms_per_keycode == 1
1637                 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1638                         int usym;
1639
1640                         XConvertCase(syms[0], &keysym, &usym);
1641                 }
1642                 else
1643                         keysym = syms[0];
1644         }
1645         else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1646                 int lsym, usym;
1647
1648                 if (keysyms_per_keycode == 1
1649                 || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1650                         XConvertCase(syms[0], &lsym, &usym);
1651                 keysym = usym;
1652         }
1653         else {
1654                 int lsym, usym;
1655
1656                 if (keysyms_per_keycode == 1
1657                 || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1658                         keysym = syms[0];
1659
1660                 XConvertCase(keysym, &lsym, &usym);
1661
1662                 if (!(bitmask & ShiftMask) && keysym != syms[0]
1663                 && ((keysym != usym) || (lsym == usym)))
1664                         XConvertCase(syms[0], &lsym, &usym);
1665                 keysym = usym;
1666         }
1667         
1668         if (keysym == XK_VoidSymbol)
1669                 keysym = NoSymbol;
1670
1671         sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1672         return buf;
1673 #endif
1674 }
1675
1676 static const char *keysymString(guint32 v)
1677 {
1678       gpointer res;
1679       if (!keysymTable) {
1680
1681             /* This table is so big that we built it only if necessary */
1682
1683             const value_string *p = keysym_vals_source;
1684             keysymTable = g_tree_new(compareGuint32);
1685             for(; p -> strptr; p++)
1686                   g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), p -> strptr);
1687       }
1688       res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1689       return res ? res : "<Unknown>";
1690 }
1691
1692 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1693                           int *modifiermap[], int keycodes_per_modifier,
1694                           gboolean little_endian)
1695 {
1696       char buffer[1024];
1697       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1698       array_length(modifiers) * keycodes_per_modifier, little_endian);
1699
1700       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1701       size_t m;
1702
1703       for (m = 0; m < array_length(modifiers);
1704       ++m, *offsetp += keycodes_per_modifier) {
1705             const guint8 *p;
1706             char *bp = buffer;
1707             int i;
1708
1709             p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1710             modifiermap[m] = g_malloc(keycodes_per_modifier);
1711
1712             for(i = 0; i < keycodes_per_modifier; ++i) {
1713                 guchar c = p[i];
1714
1715                 if (c)
1716                     bp += sprintf(bp, " %s=%d", modifiers[m], c);
1717
1718                 modifiermap[m][i] = c;
1719             }
1720
1721             proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1722                 *offsetp, keycodes_per_modifier, p,
1723                 "item: %s", buffer);
1724       }
1725 }
1726
1727 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1728                           int hf_item, int *keycodemap[256],
1729                           int keycode_first, int keycode_count,
1730                           int keysyms_per_keycode, gboolean little_endian)
1731 {
1732       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1733       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1734       proto_item *tti;
1735       proto_tree *ttt;
1736       int i, keycode;
1737
1738       g_assert(keycode_first >= 0);
1739       g_assert(keycode_count >= 0);
1740       g_assert((size_t)(keycode_first + keycode_count) <= 256);
1741
1742
1743       for (keycode = keycode_first; keycode_count > 0;
1744       ++keycode, --keycode_count) {
1745             tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1746             keysyms_per_keycode * 4, "keysyms (keycode %d):", keycode);
1747
1748             ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1749
1750             keycodemap[keycode]
1751             = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1752
1753             for(i = 0; i < keysyms_per_keycode; ++i) {
1754                   /* keysymvalue = byte3 * 256 + byte4. */
1755                   guint32 v = VALUE32(tvb, *offsetp);
1756
1757                   proto_item_append_text(tti, " %s", keysymString(v));
1758                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1759                   tvb, *offsetp, 4, v,
1760                   "keysym (keycode %d): 0x%08x (%s)",
1761                   keycode, v, keysymString(v));
1762
1763                   keycodemap[keycode][i] = v;
1764                   *offsetp += 4;
1765             }
1766         
1767             for (i = 1; i < keysyms_per_keycode; ++i)
1768                 if (keycodemap[keycode][i] != NoSymbol)
1769                         break;
1770
1771             if (i == keysyms_per_keycode) {
1772                 /* all but (possibly) first were NoSymbol. */
1773                 if (keysyms_per_keycode == 4) {
1774                         keycodemap[keycode][1] = NoSymbol;
1775                         keycodemap[keycode][2] = keycodemap[keycode][0];
1776                         keycodemap[keycode][3] = NoSymbol;
1777                 }
1778
1779                 continue;
1780             }
1781
1782             for (i = 2; i < keysyms_per_keycode; ++i)
1783                 if (keycodemap[keycode][i] != NoSymbol)
1784                         break;
1785             if (i == keysyms_per_keycode) {
1786                 /* all but (possibly) first two were NoSymbol. */
1787                 if (keysyms_per_keycode == 4) {
1788                         keycodemap[keycode][2] = keycodemap[keycode][0];
1789                         keycodemap[keycode][3] =  keycodemap[keycode][1];
1790                 }
1791
1792                 continue;
1793             }
1794       }
1795 }
1796
1797 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1798                         int length, gboolean little_endian)
1799 {
1800       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1801       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1802       while(length--) {
1803             gint16 x, y;
1804             proto_item *tti;
1805             proto_tree *ttt;
1806
1807             x = VALUE16(tvb, *offsetp);
1808             y = VALUE16(tvb, *offsetp + 2);
1809
1810             tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1811             ttt = proto_item_add_subtree(tti, ett_x11_point);
1812             proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1813             *offsetp += 2;
1814             proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1815             *offsetp += 2;
1816       }
1817 }
1818
1819 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1820                             int length, gboolean little_endian)
1821 {
1822       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1823       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1824       while(length--) {
1825             gint16 x, y;
1826             unsigned width, height;
1827             proto_item *tti;
1828             proto_tree *ttt;
1829
1830             x = VALUE16(tvb, *offsetp);
1831             y = VALUE16(tvb, *offsetp + 2);
1832             width = VALUE16(tvb, *offsetp + 4);
1833             height = VALUE16(tvb, *offsetp + 6);
1834
1835             tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1836                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1837             ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1838             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1839             *offsetp += 2;
1840             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1841             *offsetp += 2;
1842             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1843             *offsetp += 2;
1844             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1845             *offsetp += 2;
1846       }
1847 }
1848
1849 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1850                           int length, gboolean little_endian)
1851 {
1852       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1853       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1854       while(length--) {
1855             gint16 x1, y1, x2, y2;
1856             proto_item *tti;
1857             proto_tree *ttt;
1858
1859             x1 = VALUE16(tvb, *offsetp);
1860             y1 = VALUE16(tvb, *offsetp + 2);
1861             x2 = VALUE16(tvb, *offsetp + 4);
1862             y2 = VALUE16(tvb, *offsetp + 6);
1863
1864             tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1865                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1866             ttt = proto_item_add_subtree(tti, ett_x11_segment);
1867             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1868             *offsetp += 2;
1869             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1870             *offsetp += 2;
1871             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1872             *offsetp += 2;
1873             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1874             *offsetp += 2;
1875       }
1876 }
1877
1878 /* XXX - the protocol tree code should handle non-printable characters.
1879    Note that "non-printable characters" may depend on your locale.... */
1880 static void stringCopy(char *dest, const char *source, int length)
1881 {
1882       guchar c;
1883       while(length--) {
1884             c = *source++;
1885             if (!isgraph(c) && c != ' ') c = '.';
1886             *dest++ = c;
1887       }
1888       *dest++ = '\0';
1889 }
1890
1891 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1892                           int hf_item, int length, gboolean little_endian)
1893 {
1894       char *s = NULL;
1895       guint allocated = 0;
1896       proto_item *ti;
1897       proto_tree *tt;
1898       int i;
1899
1900       /* Compute total length */
1901
1902       int scanning_offset = *offsetp; /* Scanning pointer */
1903       int l;
1904       for(i = length; i; i--) {
1905             l = tvb_get_guint8(tvb, scanning_offset);
1906             scanning_offset += 1 + l;
1907       }
1908
1909       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1910       tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1911
1912       /*
1913        * In case we throw an exception, clean up whatever stuff we've
1914        * allocated (if any).
1915        */
1916       CLEANUP_PUSH(g_free, s);
1917
1918       while(length--) {
1919             unsigned l = VALUE8(tvb, *offsetp);
1920             if (allocated < (l + 1)) {
1921                   /* g_realloc doesn't work ??? */
1922                   g_free(s);
1923                   s = g_malloc(l + 1);
1924                   allocated = l + 1;
1925             }
1926             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1927             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1928             *offsetp += l + 1;
1929       }
1930
1931       /*
1932        * Call the cleanup handler to free the string and pop the handler.
1933        */
1934       CLEANUP_CALL_AND_POP;
1935 }
1936
1937 #define STRING16_MAX_DISPLAYED_LENGTH 150
1938
1939 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1940 {
1941       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1942       for(; length > 0; offset += 2, length--) {
1943             if (tvb_get_guint8(tvb, offset))
1944                 return FALSE;
1945       }
1946       return TRUE;
1947 }
1948
1949 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1950
1951 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1952                                               int hf, int hf_bytes,
1953                                               int offset, unsigned length,
1954                                               char **s, int *sLength,
1955                                               gboolean little_endian)
1956 {
1957       int truncated = FALSE;
1958       unsigned l = length / 2;
1959
1960       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1961             char *dp;
1962             int soffset = offset;
1963
1964             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1965                   truncated = TRUE;
1966                   l = STRING16_MAX_DISPLAYED_LENGTH;
1967             }
1968             if (*sLength < (int) l + 3) {
1969                   g_free(*s);
1970                   *s = g_malloc(l + 3);
1971                   *sLength = l + 3;
1972             }
1973             dp = *s;
1974             *dp++ = '"';
1975             if (truncated) l -= 3;
1976
1977             while(l--) {
1978                   soffset++;
1979                   *dp++ = tvb_get_guint8(tvb, soffset);
1980                   soffset++;
1981             }
1982             *dp++ = '"';
1983
1984             /* If truncated, add an ellipsis */
1985             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1986
1987             *dp++ = '\0';
1988             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1989                                         proto_registrar_get_nth(hf) -> name, *s);
1990       } else
1991             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1992
1993 }
1994
1995 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1996     int sizeIs16, int next_offset, gboolean little_endian)
1997 {
1998       int allocated = 0;
1999       char *s = NULL;
2000       proto_item *ti;
2001       proto_tree *tt;
2002       guint32 fid;
2003
2004       /* Compute total length */
2005
2006       int scanning_offset = *offsetp; /* Scanning pointer */
2007       int l;                            /* Length of an individual item */
2008       int n = 0;                        /* Number of items */
2009
2010       while(scanning_offset < next_offset) {
2011             l = tvb_get_guint8(tvb, scanning_offset);
2012             scanning_offset++;
2013             if (!l) break;
2014             n++;
2015             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2016       }
2017
2018       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2019       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2020
2021       /*
2022        * In case we throw an exception, clean up whatever stuff we've
2023        * allocated (if any).
2024        */
2025       CLEANUP_PUSH(g_free, s);
2026
2027       while(n--) {
2028             unsigned l = VALUE8(tvb, *offsetp);
2029             if (l == 255) { /* Item is a font */
2030                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
2031                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2032                   *offsetp += 5;
2033             } else { /* Item is a string */
2034                   proto_item *tti;
2035                   proto_tree *ttt;
2036                   gint8 delta = VALUE8(tvb, *offsetp + 1);
2037                   if (sizeIs16) l += l;
2038                   if ((unsigned) allocated < l + 1) {
2039                         /* g_realloc doesn't work ??? */
2040                         g_free(s);
2041                         s = g_malloc(l + 1);
2042                         allocated = l + 1;
2043                   }
2044                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2045                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2046                                                        "textitem (string): delta = %d, \"%s\"",
2047                                                        delta, s);
2048                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2049                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2050                   if (sizeIs16)
2051                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2052                                                           hf_x11_textitem_string_string16_bytes,
2053                                                           *offsetp + 2, l,
2054                                                           &s, &allocated,
2055                                                           little_endian);
2056                   else
2057                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2058                                                      *offsetp + 2, l, s, "\"%s\"", s);
2059                   *offsetp += l + 2;
2060             }
2061       }
2062
2063       /*
2064        * Call the cleanup handler to free the string and pop the handler.
2065        */
2066       CLEANUP_CALL_AND_POP;
2067 }
2068
2069 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2070                       gboolean little_endian)
2071 {
2072       guint32 v = VALUE8(tvb, *offsetp);
2073       header_field_info *hfi = proto_registrar_get_nth(hf);
2074       gchar *enumValue = NULL;
2075
2076       if (hfi -> strings)
2077             enumValue = match_strval(v, cVALS(hfi -> strings));
2078       if (enumValue)
2079             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2080             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2081             hfi -> name, v, enumValue);
2082       else
2083             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2084       *offsetp += 1;
2085       return v;
2086 }
2087
2088 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2089                        gboolean little_endian)
2090 {
2091       guint32 v = VALUE16(tvb, *offsetp);
2092       header_field_info *hfi = proto_registrar_get_nth(hf);
2093       gchar *enumValue = NULL;
2094
2095       if (hfi -> strings)
2096             enumValue = match_strval(v, cVALS(hfi -> strings));
2097       if (enumValue)
2098             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2099             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2100             hfi -> name, v, enumValue);
2101       else
2102             proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2103       *offsetp += 2;
2104       return v;
2105 }
2106
2107 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2108                        gboolean little_endian)
2109 {
2110       guint32 v = VALUE32(tvb, *offsetp);
2111       header_field_info *hfi = proto_registrar_get_nth(hf);
2112       gchar *enumValue = NULL;
2113       gchar *nameAsChar = hfi -> name;
2114
2115       if (hfi -> strings)
2116             enumValue = match_strval(v, cVALS(hfi -> strings));
2117       if (enumValue)
2118             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2119                                        hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2120                                        nameAsChar, v, enumValue);
2121       else
2122             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2123                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2124                                        nameAsChar, v);
2125       *offsetp += 4;
2126       return v;
2127 }
2128
2129 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2130                          gboolean little_endian)
2131 {
2132       BITMASK32(gc_value);
2133       BITFIELD(ENUM8,  gc_value_mask, function);
2134       BITFIELD(CARD32, gc_value_mask, plane_mask);
2135       BITFIELD(CARD32, gc_value_mask, foreground);
2136       BITFIELD(CARD32, gc_value_mask, background);
2137       BITFIELD(CARD16, gc_value_mask, line_width);
2138       BITFIELD(ENUM8,  gc_value_mask, line_style);
2139       BITFIELD(ENUM8,  gc_value_mask, cap_style);
2140       BITFIELD(ENUM8,  gc_value_mask, join_style);
2141       BITFIELD(ENUM8,  gc_value_mask, fill_style);
2142       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
2143       BITFIELD(PIXMAP, gc_value_mask, tile);
2144       BITFIELD(PIXMAP, gc_value_mask, stipple);
2145       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
2146       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
2147       BITFIELD(FONT,   gc_value_mask, font);
2148       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
2149       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
2150       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
2151       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
2152       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2153       BITFIELD(CARD16, gc_value_mask, dash_offset);
2154       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
2155       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
2156       ENDBITMASK;
2157 }
2158
2159 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2160                    gboolean little_endian)
2161 {
2162       BITMASK32(gc_value);
2163       FLAG(gc_value, function);
2164       FLAG(gc_value, plane_mask);
2165       FLAG(gc_value, foreground);
2166       FLAG(gc_value, background);
2167       FLAG(gc_value, line_width);
2168       FLAG(gc_value, line_style);
2169       FLAG(gc_value, cap_style);
2170       FLAG(gc_value, join_style);
2171       FLAG(gc_value, fill_style);
2172       FLAG(gc_value, fill_rule);
2173       FLAG(gc_value, tile);
2174       FLAG(gc_value, stipple);
2175       FLAG(gc_value, tile_stipple_x_origin);
2176       FLAG(gc_value, tile_stipple_y_origin);
2177       FLAG(gc_value, font);
2178       FLAG(gc_value, subwindow_mode);
2179       FLAG(gc_value, graphics_exposures);
2180       FLAG(gc_value, clip_x_origin);
2181       FLAG(gc_value, clip_y_origin);
2182       FLAG(gc_value, clip_mask);
2183       FLAG(gc_value, dash_offset);
2184       FLAG(gc_value, gc_dashes);
2185       FLAG(gc_value, arc_mode);
2186       ENDBITMASK;
2187 }
2188
2189 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2190                              gboolean little_endian)
2191 {
2192       guint32 res = VALUE16(tvb, *offsetp);
2193       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2194       *offsetp += 2;
2195       return res * 4;
2196 }
2197
2198 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2199                        gboolean little_endian)
2200 {
2201       BITMASK32(event);
2202       FLAG(event, KeyPress);
2203       FLAG(event, KeyRelease);
2204       FLAG(event, ButtonPress);
2205       FLAG(event, ButtonRelease);
2206       FLAG(event, EnterWindow);
2207       FLAG(event, LeaveWindow);
2208       FLAG(event, PointerMotion);
2209       FLAG(event, PointerMotionHint);
2210       FLAG(event, Button1Motion);
2211       FLAG(event, Button2Motion);
2212       FLAG(event, Button3Motion);
2213       FLAG(event, Button4Motion);
2214       FLAG(event, Button5Motion);
2215       FLAG(event, ButtonMotion);
2216       FLAG(event, KeymapState);
2217       FLAG(event, Exposure);
2218       FLAG(event, VisibilityChange);
2219       FLAG(event, StructureNotify);
2220       FLAG(event, ResizeRedirect);
2221       FLAG(event, SubstructureNotify);
2222       FLAG(event, SubstructureRedirect);
2223       FLAG(event, FocusChange);
2224       FLAG(event, PropertyChange);
2225       FLAG(event, ColormapChange);
2226       FLAG(event, OwnerGrabButton);
2227       FLAG_IF_NONZERO(event, erroneous_bits);
2228       ENDBITMASK;
2229 }
2230
2231 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2232                              gboolean little_endian)
2233 {
2234       BITMASK32(do_not_propagate);
2235       FLAG(do_not_propagate, KeyPress);
2236       FLAG(do_not_propagate, KeyRelease);
2237       FLAG(do_not_propagate, ButtonPress);
2238       FLAG(do_not_propagate, ButtonRelease);
2239       FLAG(do_not_propagate, PointerMotion);
2240       FLAG(do_not_propagate, Button1Motion);
2241       FLAG(do_not_propagate, Button2Motion);
2242       FLAG(do_not_propagate, Button3Motion);
2243       FLAG(do_not_propagate, Button4Motion);
2244       FLAG(do_not_propagate, Button5Motion);
2245       FLAG(do_not_propagate, ButtonMotion);
2246       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2247       ENDBITMASK;
2248 }
2249
2250
2251 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2252                          gboolean little_endian, gboolean butmask)
2253 {
2254       proto_item *ti;
2255       guint32 bitmask_value;
2256       int bitmask_offset;
2257       int bitmask_size;
2258       proto_tree *bitmask_tree;
2259
2260       bitmask_value = VALUE16(tvb, *offsetp);
2261       bitmask_offset = *offsetp;
2262       bitmask_size = 2;
2263
2264       if (!butmask && bitmask_value == 0x8000)
2265             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2266                                        "modifiers-masks: 0x8000 (AnyModifier)");
2267       else {
2268             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2269                                                  bitmask_value);
2270             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2271             FLAG(modifiers, Shift);
2272             FLAG(modifiers, Lock);
2273             FLAG(modifiers, Control);
2274             FLAG(modifiers, Mod1);
2275             FLAG(modifiers, Mod2);
2276             FLAG(modifiers, Mod3);
2277             FLAG(modifiers, Mod4);
2278             FLAG(modifiers, Mod5);
2279
2280             if (butmask) {
2281                     FLAG(modifiers, Button1);
2282                     FLAG(modifiers, Button2);
2283                     FLAG(modifiers, Button3);
2284                     FLAG(modifiers, Button4);
2285                     FLAG(modifiers, Button5);
2286             }
2287
2288             if (butmask)
2289                     FLAG_IF_NONZERO(keybut, erroneous_bits);
2290             else
2291                     FLAG_IF_NONZERO(modifiers, erroneous_bits);
2292       }
2293       *offsetp += 2;
2294 }
2295
2296
2297 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2298                               gboolean little_endian)
2299 {
2300       BITMASK16(pointer_event);
2301       FLAG(pointer_event, ButtonPress);
2302       FLAG(pointer_event, ButtonRelease);
2303       FLAG(pointer_event, EnterWindow);
2304       FLAG(pointer_event, LeaveWindow);
2305       FLAG(pointer_event, PointerMotion);
2306       FLAG(pointer_event, PointerMotionHint);
2307       FLAG(pointer_event, Button1Motion);
2308       FLAG(pointer_event, Button2Motion);
2309       FLAG(pointer_event, Button3Motion);
2310       FLAG(pointer_event, Button4Motion);
2311       FLAG(pointer_event, Button5Motion);
2312       FLAG(pointer_event, ButtonMotion);
2313       FLAG(pointer_event, KeymapState);
2314       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2315       ENDBITMASK;
2316 }
2317
2318 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2319     int hf, unsigned length)
2320 {
2321       const guint8 *p;
2322       char *s;
2323
2324       p = tvb_get_ptr(tvb, *offsetp, length);
2325       s = g_malloc(length + 1);
2326       stringCopy(s, p, length);
2327       proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2328       g_free(s);
2329       *offsetp += length;
2330 }
2331
2332 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2333
2334 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2335     int hf_bytes, unsigned length, gboolean little_endian)
2336 {
2337       char *s = NULL;
2338       unsigned l = 0;
2339
2340       /*
2341        * In case we throw an exception, clean up whatever stuff we've
2342        * allocated (if any).
2343        */
2344       CLEANUP_PUSH(g_free, s);
2345
2346       length += length;
2347       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2348                                         &s, &l, little_endian);
2349
2350       /*
2351        * Call the cleanup handler to free the string and pop the handler.
2352        */
2353       CLEANUP_CALL_AND_POP;
2354
2355       *offsetp += length;
2356 }
2357
2358 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2359                       gboolean little_endian)
2360 {
2361       guint32 v = VALUE32(tvb, *offsetp);
2362
2363       if (!v)
2364             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2365                 proto_registrar_get_nth(hf) -> name);
2366       else
2367             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2368       *offsetp += 4;
2369 }
2370
2371 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2372                              gboolean little_endian)
2373 {
2374       BITMASK32(window_value);
2375       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2376       BITFIELD(CARD32, window_value_mask, background_pixel);
2377       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2378       BITFIELD(CARD32, window_value_mask, border_pixel);
2379       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2380       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2381       BITFIELD(ENUM8, window_value_mask, backing_store);
2382       BITFIELD(CARD32, window_value_mask, backing_planes);
2383       BITFIELD(CARD32, window_value_mask, backing_pixel);
2384       BITFIELD(BOOL,   window_value_mask, override_redirect);
2385       BITFIELD(BOOL,   window_value_mask, save_under);
2386       BITFIELD(SETofEVENT, window_value_mask, event_mask);
2387       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2388       BITFIELD(COLORMAP, window_value_mask, colormap);
2389       BITFIELD(CURSOR, window_value_mask, cursor);
2390       ENDBITMASK;
2391 }
2392
2393 static void x11_init_protocol(void)
2394 {
2395       if (x11_state_chunk != NULL)
2396             g_mem_chunk_destroy(x11_state_chunk);
2397
2398       x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2399                                         sizeof (x11_conv_data_t),
2400                                         128 * sizeof (x11_conv_data_t),
2401                                         G_ALLOC_ONLY);
2402 }
2403
2404 /************************************************************************
2405  ***                                                                  ***
2406  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2407  ***                                                                  ***
2408  ************************************************************************/
2409
2410 /* If we can't guess, we return TRUE (that is little_endian), cause
2411    I'm developing on a Linux box :-). The (non-)guess isn't cached
2412    however, so we may have more luck next time. I'm quite conservative
2413    in my assertions, cause once it's cached, it's stay in cache, and
2414    we may be fooled up by a packet starting with the end of a request
2415    started in a previous packet...
2416 */
2417
2418 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2419
2420 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2421 {
2422       int res = 0;
2423       while(maskLength--) {
2424             int c = tvb_get_guint8(tvb, offset);
2425             offset++;
2426             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2427       }
2428       return res;
2429 }
2430
2431 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2432 {
2433       if (listLength > length) return FALSE;
2434       while(listLength--) {
2435             int l;
2436             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2437             l = tvb_get_guint8(tvb, offset);
2438             if (!l) break;
2439             l++;
2440             if (l > length) return FALSE;
2441             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2442             offset += l;
2443             length -= l;
2444       }
2445       if (length > 3) return FALSE;
2446       return TRUE;
2447 }
2448
2449 static int rounded4(int n)
2450 {
2451       int remainder = n % 4;
2452       int res = n / 4;
2453       if (remainder) res++;
2454       return res;
2455 }
2456
2457 /* We assume the order to be consistent, until proven wrong. */
2458
2459 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2460 {
2461       switch(tvb_get_guint8(tvb, offset)) {
2462           case X_CreateWindow:
2463             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2464
2465           case X_ChangeWindowAttributes:
2466           case X_ChangeGC:
2467             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2468
2469           case X_GetWindowAttributes:
2470           case X_DestroyWindow:
2471           case X_DestroySubwindows:
2472           case X_ChangeSaveSet:
2473           case X_MapWindow:
2474           case X_MapSubwindows:
2475           case X_UnmapWindow:
2476           case X_UnmapSubwindows:
2477           case X_CirculateWindow:
2478           case X_GetGeometry:
2479           case X_QueryTree:
2480           case X_GetAtomName:
2481           case X_ListProperties:
2482           case X_GetSelectionOwner:
2483           case X_UngrabPointer:
2484           case X_UngrabKeyboard:
2485           case X_AllowEvents:
2486           case X_QueryPointer:
2487           case X_CloseFont:
2488           case X_QueryFont:
2489           case X_FreePixmap:
2490           case X_FreeGC:
2491           case X_FreeColormap:
2492           case X_InstallColormap:
2493           case X_UninstallColormap:
2494           case X_ListInstalledColormaps:
2495           case X_FreeCursor:
2496           case X_GetKeyboardMapping:
2497           case X_KillClient:
2498             return length == 2;
2499
2500           case X_ReparentWindow:
2501           case X_SetSelectionOwner:
2502           case X_ChangeActivePointerGrab:
2503           case X_GrabKeyboard:
2504           case X_GrabKey:
2505           case X_GetMotionEvents:
2506           case X_TranslateCoords:
2507           case X_CreatePixmap:
2508           case X_CopyGC:
2509           case X_ClearArea:
2510           case X_CreateColormap:
2511           case X_AllocColor:
2512           case X_AllocColorPlanes:
2513             return length == 4;
2514
2515           case X_ConfigureWindow:
2516             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2517
2518           case X_InternAtom:
2519           case X_QueryExtension:
2520             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2521
2522           case X_ChangeProperty:
2523             {
2524                   int multiplier, type;
2525                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2526                   type = tvb_get_guint8(tvb, 16);
2527                   if (type != 8 && type != 16 && type != 32) return FALSE;
2528                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2529                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2530                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2531             }
2532
2533           case X_DeleteProperty:
2534           case X_UngrabButton:
2535           case X_UngrabKey:
2536           case X_SetInputFocus:
2537           case X_CopyColormapAndFree:
2538           case X_AllocColorCells:
2539           case X_QueryBestSize:
2540           case X_ChangePointerControl:
2541           case X_SetScreenSaver:
2542             return length == 3;
2543
2544           case X_GetProperty:
2545           case X_ConvertSelection:
2546           case X_GrabPointer:
2547           case X_GrabButton:
2548           case X_WarpPointer:
2549             return length == 6;
2550
2551           case X_SendEvent:
2552             return length == 11;
2553
2554           case X_GrabServer:
2555           case X_UngrabServer:
2556           case X_GetInputFocus:
2557           case X_QueryKeymap:
2558           case X_GetFontPath:
2559           case X_ListExtensions:
2560           case X_GetKeyboardControl:
2561           case X_Bell:
2562           case X_GetPointerControl:
2563           case X_GetScreenSaver:
2564           case X_ListHosts:
2565           case X_SetAccessControl:
2566           case X_SetCloseDownMode:
2567           case X_ForceScreenSaver:
2568           case X_GetPointerMapping:
2569           case X_GetModifierMapping:
2570             return length == 1;
2571
2572           case X_OpenFont:
2573           case X_AllocNamedColor:
2574           case X_LookupColor:
2575             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2576
2577           case X_QueryTextExtents:
2578             return length >= 2;
2579
2580           case X_ListFonts:
2581           case X_ListFontsWithInfo:
2582           case X_ChangeHosts:
2583             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2584
2585           case X_SetFontPath:
2586             if (length < 2) return FALSE;
2587             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2588             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2589
2590           case X_CreateGC:
2591             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2592
2593           case X_SetDashes:
2594             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2595
2596           case X_SetClipRectangles:
2597           case X_PolySegment:
2598           case X_PolyRectangle:
2599           case X_PolyFillRectangle:
2600             return length >= 3 && (length - 3) % 2 == 0;
2601
2602           case X_CopyArea:
2603             return length == 7;
2604
2605           case X_CopyPlane:
2606           case X_CreateCursor:
2607           case X_CreateGlyphCursor:
2608             return length == 8;
2609
2610           case X_PolyPoint:
2611           case X_PolyLine:
2612           case X_FreeColors:
2613             return length >= 3;
2614
2615           case X_PolyArc:
2616           case X_PolyFillArc:
2617             return length >= 3 && (length - 3) % 3 == 0;
2618
2619           case X_FillPoly:
2620           case X_ImageText8:
2621             return length >= 4;
2622
2623           case X_PutImage:
2624             return length >= 6;
2625
2626           case X_GetImage:
2627           case X_RecolorCursor:
2628             return length == 5;
2629
2630           case X_PolyText8:
2631             if (length < 4) return FALSE;
2632             return TRUE; /* We don't perform many controls on this one */
2633
2634           case X_PolyText16:
2635             if (length < 4) return FALSE;
2636             return TRUE; /* We don't perform many controls on this one */
2637
2638           case X_ImageText16:
2639             return length >= 4;
2640
2641           case X_StoreColors:
2642             return length > 2 && (length - 2) % 3 == 0;
2643
2644           case X_StoreNamedColor:
2645             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2646
2647           case X_QueryColors:
2648             return length >= 2;
2649
2650           case X_ChangeKeyboardMapping:
2651             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2652
2653           case X_ChangeKeyboardControl:
2654             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2655
2656           case X_RotateProperties:
2657             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2658
2659           case X_SetPointerMapping:
2660             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2661
2662           case X_SetModifierMapping:
2663             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2664
2665           case X_NoOperation:
2666             return length >= 1;
2667
2668           default:
2669             return TRUE;
2670       }
2671 }
2672
2673 /* -1 means doesn't match, +1 means match, 0 means don't know */
2674
2675 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2676 {
2677       int offset, nextoffset;
2678       int atLeastOne = 0;
2679
2680       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2681             int length;
2682             length = v16(tvb, offset + 2);
2683             if (!length) return -1;
2684             nextoffset = offset + length * 4;
2685             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2686             atLeastOne = 1;
2687       }
2688       return atLeastOne;
2689 }
2690
2691 static gboolean
2692 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2693                     x11_conv_data_t *state)
2694 {
2695       /* With X the client gives the byte ordering for the protocol,
2696          and the port on the server tells us we're speaking X. */
2697
2698       int le, be, decision, decisionToCache;
2699
2700       if (state->byte_order == BYTE_ORDER_BE)
2701             return FALSE;       /* known to be big-endian */
2702       else if (state->byte_order == BYTE_ORDER_LE)
2703             return TRUE;        /* known to be little-endian */
2704
2705       if (pinfo->srcport == pinfo->match_port) {
2706             /*
2707              * This is a reply or event; we don't try to guess the
2708              * byte order on it for now.
2709              */
2710             return TRUE;
2711       }
2712
2713       le = x_endian_match(tvb, tvb_get_letohs);
2714       be = x_endian_match(tvb, tvb_get_ntohs);
2715
2716       /* remember that "decision" really means "little_endian". */
2717       if (le == be) {
2718             /* We have no reason to believe it's little- rather than
2719                big-endian, so we guess the shortest length is the
2720                right one.
2721             */
2722             if (!tvb_bytes_exist(tvb, 0, 4))
2723                   /* Not even a way to get the length. We're biased
2724                      toward little endianness here (essentially the
2725                      x86 world right now). Decoding won't go very far
2726                      anyway.
2727                   */
2728                   decision = TRUE;
2729             else
2730                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2731       } else
2732           decision = le >= be;
2733
2734       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2735       if (decisionToCache) {
2736             /*
2737              * Remember the decision.
2738              */
2739             state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2740       }
2741
2742       /*
2743       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2744               pinfo->fd -> num, le, be, decision, decisionToCache);
2745       */
2746       return decision;
2747 }
2748
2749 /************************************************************************
2750  ***                                                                  ***
2751  ***              D E C O D I N G   O N E   P A C K E T               ***
2752  ***                                                                  ***
2753  ************************************************************************/
2754
2755 /*
2756  * Decode an initial connection request.
2757  */
2758 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2759     proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2760 {
2761       int offset = 0;
2762       int *offsetp = &offset;
2763       proto_item *ti;
2764       proto_tree *t;
2765       guint16 auth_proto_name_length, auth_proto_data_length;
2766       gint left;
2767
2768       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2769       proto_item_append_text(ti, ", Request, Initial connection request");
2770       t = proto_item_add_subtree(ti, ett_x11);
2771
2772       CARD8(byte_order);
2773       UNUSED(1);
2774       CARD16(protocol_major_version);
2775       CARD16(protocol_minor_version);
2776       auth_proto_name_length = CARD16(authorization_protocol_name_length);
2777       auth_proto_data_length = CARD16(authorization_protocol_data_length);
2778       UNUSED(2);
2779
2780       if (auth_proto_name_length != 0) {
2781             STRING8(authorization_protocol_name, auth_proto_name_length);
2782             offset = ROUND_LENGTH(offset);
2783       }
2784
2785       if (auth_proto_data_length != 0) {
2786             STRING8(authorization_protocol_data, auth_proto_data_length);
2787             offset = ROUND_LENGTH(offset);
2788       }
2789
2790       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2791                 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2792                 little_endian);
2793
2794       /*
2795        * This is the initial connection request...
2796        */
2797       state->iconn_frame = pinfo->fd->num;
2798
2799       /*
2800        * ...and we're expecting a reply to it.
2801        */
2802       state->sequencenumber = 0;
2803       g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
2804       (int *)INITIAL_CONN);
2805 }
2806
2807 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2808     proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2809     gboolean little_endian)
2810 {
2811         int offset = 0, *offsetp = &offset, left;
2812         unsigned char success;
2813         int length_of_vendor;
2814         int length_of_reason;
2815         proto_item *ti;
2816         proto_tree *t;
2817
2818         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2819         proto_item_append_text(ti, ", Reply, Initial connection reply");
2820         t = proto_item_add_subtree(ti, ett_x11);
2821
2822         state->iconn_reply = pinfo->fd->num;
2823         success = INT8(success);
2824         if (success) {
2825                 UNUSED(1);
2826                 length_of_reason = 0;
2827         }
2828         else {
2829                 length_of_reason = INT8(length_of_reason);
2830         }
2831
2832         INT16(protocol_major_version);
2833         INT16(protocol_minor_version);
2834         INT16(replylength);
2835         if (success) {
2836                 INT32(release_number);
2837                 INT32(resource_id_base);
2838                 INT32(resource_id_mask);
2839                 INT32(motion_buffer_size);
2840                 length_of_vendor = INT16(length_of_vendor);
2841                 INT16(maximum_request_length);
2842                 INT8(number_of_screens_in_roots);
2843                 INT8(number_of_formats_in_pixmap_formats);
2844                 INT8(image_byte_order);
2845                 INT8(bitmap_format_bit_order);
2846                 INT8(bitmap_format_scanline_unit);
2847                 INT8(bitmap_format_scanline_pad);
2848                 INT8(min_keycode);
2849                 INT8(max_keycode);
2850                 UNUSED(4);
2851                 STRING8(vendor, length_of_vendor);
2852         } else {
2853                 STRING8(reason, length_of_reason);
2854         }
2855
2856         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2857             UNDECODED(left);
2858
2859 }
2860
2861 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2862     proto_tree *tree, const char *sep, x11_conv_data_t *state,
2863     gboolean little_endian)
2864 {
2865       int offset = 0;
2866       int *offsetp = &offset;
2867       int next_offset;
2868       proto_item *ti;
2869       proto_tree *t;
2870       int length, opcode;
2871       guint8 v8, v8_2, v8_3;
2872       guint16 v16;
2873       guint32 v32;
2874       gint left;
2875
2876       length = VALUE16(tvb, 2) * 4;
2877
2878       if (length < 4) {
2879             /* Bogus message length? */
2880             return;
2881       }
2882
2883       next_offset = offset + length;
2884
2885       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2886       t = proto_item_add_subtree(ti, ett_x11);
2887
2888       if (PACKET_IS_NEW(pinfo))
2889             ++state->sequencenumber;
2890
2891       OPCODE();
2892
2893       if (check_col(pinfo->cinfo, COL_INFO))
2894           col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2895                           val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
2896
2897       proto_item_append_text(ti, ", Request, opcode: %d (%s)", 
2898                             opcode, val_to_str(opcode, opcode_vals,
2899                             "<Unknown opcode %d>"));
2900
2901       /*
2902        * Does this request expect a reply?
2903        */
2904       switch(opcode) {
2905       case X_AllocColor:
2906       case X_AllocColorCells:
2907       case X_AllocColorPlanes:
2908       case X_AllocNamedColor:
2909       case X_GetAtomName:
2910       case X_GetFontPath:
2911       case X_GetGeometry:
2912       case X_GetImage:
2913       case X_GetInputFocus:
2914       case X_GetKeyboardControl:
2915       case X_GetKeyboardMapping:
2916       case X_GetModifierMapping:
2917       case X_GetMotionEvents:
2918       case X_GetPointerControl:
2919       case X_GetPointerMapping:
2920       case X_GetProperty:
2921       case X_GetScreenSaver:
2922       case X_GetSelectionOwner:
2923       case X_GetWindowAttributes:
2924       case X_GrabKeyboard:
2925       case X_GrabPointer:
2926       case X_InternAtom:
2927       case X_ListExtensions:
2928       case X_ListFonts:
2929       case X_ListFontsWithInfo:
2930       case X_ListHosts:
2931       case X_ListInstalledColormaps:
2932       case X_ListProperties:
2933       case X_LookupColor:
2934       case X_QueryBestSize:
2935       case X_QueryColors:
2936       case X_QueryExtension:
2937       case X_QueryFont:
2938       case X_QueryKeymap:
2939       case X_QueryPointer:
2940       case X_QueryTextExtents:
2941       case X_QueryTree:
2942       case X_SetModifierMapping:
2943       case X_SetPointerMapping:
2944       case X_TranslateCoords:
2945                 /*
2946                  * Those requests expect a reply.
2947                  */
2948
2949                 g_hash_table_insert(state->seqtable,
2950                 (int *)state->sequencenumber, (int *)opcode);
2951
2952                 break;
2953
2954       default:
2955                 /*
2956                  * No reply is expected from any other request.
2957                  */
2958                 break;
2959       }
2960
2961       if (tree == NULL)
2962          return; 
2963
2964       switch(opcode) {
2965
2966       case X_CreateWindow:
2967             CARD8(depth);
2968             REQUEST_LENGTH();
2969             WINDOW(wid);
2970             WINDOW(parent);
2971             INT16(x);
2972             INT16(y);
2973             CARD16(width);
2974             CARD16(height);
2975             CARD16(border_width);
2976             ENUM16(window_class);
2977             VISUALID(visual);
2978             windowAttributes(tvb, offsetp, t, little_endian);
2979             break;
2980
2981       case X_ChangeWindowAttributes:
2982             UNUSED(1);
2983             REQUEST_LENGTH();
2984             WINDOW(window);
2985             windowAttributes(tvb, offsetp, t, little_endian);
2986             break;
2987
2988       case X_GetWindowAttributes:
2989       case X_DestroyWindow:
2990       case X_DestroySubwindows:
2991             UNUSED(1);
2992             REQUEST_LENGTH();
2993             WINDOW(window);
2994             break;
2995
2996       case X_ChangeSaveSet:
2997             ENUM8(save_set_mode);
2998             REQUEST_LENGTH();
2999             WINDOW(window);
3000             break;
3001
3002       case X_ReparentWindow:
3003             UNUSED(1);
3004             REQUEST_LENGTH();
3005             WINDOW(window);
3006             WINDOW(parent);
3007             INT16(x);
3008             INT16(y);
3009             break;
3010
3011       case X_MapWindow:
3012       case X_MapSubwindows:
3013       case X_UnmapWindow:
3014       case X_UnmapSubwindows:
3015             UNUSED(1);
3016             REQUEST_LENGTH();
3017             WINDOW(window);
3018             break;
3019
3020       case X_ConfigureWindow:
3021             UNUSED(1);
3022             REQUEST_LENGTH();
3023             WINDOW(window);
3024             BITMASK16(configure_window);
3025             UNUSED(2);
3026             BITFIELD(INT16,  configure_window_mask, x);
3027             BITFIELD(INT16,  configure_window_mask, y);
3028             BITFIELD(CARD16, configure_window_mask, width);
3029             BITFIELD(CARD16, configure_window_mask, height);
3030             BITFIELD(CARD16, configure_window_mask, border_width);
3031             BITFIELD(WINDOW, configure_window_mask, sibling);
3032             BITFIELD(ENUM8,  configure_window_mask, stack_mode);
3033             ENDBITMASK;
3034             PAD();
3035             break;
3036
3037       case X_CirculateWindow:
3038             ENUM8(direction);
3039             REQUEST_LENGTH();
3040             WINDOW(window);
3041             break;
3042
3043       case X_GetGeometry:
3044       case X_QueryTree:
3045             UNUSED(1);
3046             REQUEST_LENGTH();
3047             DRAWABLE(drawable);
3048             break;
3049
3050       case X_InternAtom:
3051             BOOL(only_if_exists);
3052             REQUEST_LENGTH();
3053             v16 = FIELD16(name_length);
3054             UNUSED(2);
3055             STRING8(name, v16);
3056             PAD();
3057             break;
3058
3059       case X_GetAtomName:
3060             UNUSED(1);
3061             REQUEST_LENGTH();
3062             ATOM(atom);
3063             break;
3064
3065       case X_ChangeProperty:
3066             ENUM8(mode);
3067             REQUEST_LENGTH();
3068             WINDOW(window);
3069             ATOM(property);
3070             ATOM(type);
3071             CARD8(format);
3072             UNUSED(3);
3073             v32 = CARD32(data_length);
3074             LISTofBYTE(data, v32);
3075             PAD();
3076             break;
3077
3078       case X_DeleteProperty:
3079             UNUSED(1);
3080             REQUEST_LENGTH();
3081             WINDOW(window);
3082             ATOM(property);
3083             break;
3084
3085       case X_GetProperty:
3086             BOOL(delete);
3087             REQUEST_LENGTH();
3088             WINDOW(window);
3089             ATOM(property);
3090             ATOM(get_property_type);
3091             CARD32(long_offset);
3092             CARD32(long_length);
3093             break;
3094
3095       case X_ListProperties:
3096             UNUSED(1);
3097             REQUEST_LENGTH();
3098             WINDOW(window);
3099             break;
3100
3101       case X_SetSelectionOwner:
3102             UNUSED(1);
3103             REQUEST_LENGTH();
3104             WINDOW(owner);
3105             ATOM(selection);
3106             TIMESTAMP(time);
3107             break;
3108
3109       case X_GetSelectionOwner:
3110             UNUSED(1);
3111             REQUEST_LENGTH();
3112             ATOM(selection);
3113             break;
3114
3115       case X_ConvertSelection:
3116             UNUSED(1);
3117             REQUEST_LENGTH();
3118             WINDOW(requestor);
3119             ATOM(selection);
3120             ATOM(target);
3121             ATOM(property);
3122             TIMESTAMP(time);
3123             break;
3124
3125       case X_GrabPointer:
3126             BOOL(owner_events);
3127             REQUEST_LENGTH();
3128             WINDOW(grab_window);
3129             SETofPOINTEREVENT(pointer_event_mask);
3130             ENUM8(pointer_mode);
3131             ENUM8(keyboard_mode);
3132             WINDOW(confine_to);
3133             CURSOR(cursor);
3134             TIMESTAMP(time);
3135             break;
3136
3137       case X_UngrabPointer:
3138             UNUSED(1);
3139             REQUEST_LENGTH();
3140             TIMESTAMP(time);
3141             break;
3142
3143       case X_GrabButton:
3144             BOOL(owner_events);
3145             REQUEST_LENGTH();
3146             WINDOW(grab_window);
3147             SETofPOINTEREVENT(event_mask);
3148             ENUM8(pointer_mode);
3149             ENUM8(keyboard_mode);
3150             WINDOW(confine_to);
3151             CURSOR(cursor);
3152             BUTTON(button);
3153             UNUSED(1);
3154             SETofKEYMASK(modifiers);
3155             break;
3156
3157       case X_UngrabButton:
3158             BUTTON(button);
3159             REQUEST_LENGTH();
3160             WINDOW(grab_window);
3161             SETofKEYMASK(modifiers);
3162             UNUSED(2);
3163             break;
3164
3165       case X_ChangeActivePointerGrab:
3166             UNUSED(1);
3167             REQUEST_LENGTH();
3168             CURSOR(cursor);
3169             TIMESTAMP(time);
3170             SETofPOINTEREVENT(event_mask);
3171             UNUSED(2);
3172             break;
3173
3174       case X_GrabKeyboard:
3175             BOOL(owner_events);
3176             REQUEST_LENGTH();
3177             WINDOW(grab_window);
3178             TIMESTAMP(time);
3179             ENUM8(pointer_mode);
3180             ENUM8(keyboard_mode);
3181             UNUSED(2);
3182             break;
3183
3184       case X_UngrabKeyboard:
3185             UNUSED(1);
3186             REQUEST_LENGTH();
3187             TIMESTAMP(time);
3188             break;
3189
3190       case X_GrabKey:
3191             BOOL(owner_events);
3192             REQUEST_LENGTH();
3193             WINDOW(grab_window);
3194             SETofKEYMASK(modifiers);
3195             KEYCODE(key);
3196             ENUM8(pointer_mode);
3197             ENUM8(keyboard_mode);
3198             UNUSED(3);
3199             break;
3200
3201       case X_UngrabKey:
3202             KEYCODE(key);
3203             REQUEST_LENGTH();
3204             WINDOW(grab_window);
3205             SETofKEYMASK(modifiers);
3206             UNUSED(2);
3207             break;
3208
3209       case X_AllowEvents:
3210             ENUM8(allow_events_mode);
3211             REQUEST_LENGTH();
3212             TIMESTAMP(time);
3213             break;
3214
3215       case X_GrabServer:
3216             UNUSED(1);
3217             REQUEST_LENGTH();
3218             break;
3219
3220       case X_UngrabServer:
3221             UNUSED(1);
3222             REQUEST_LENGTH();
3223             break;
3224
3225       case X_QueryPointer:
3226             UNUSED(1);
3227             REQUEST_LENGTH();
3228             WINDOW(window);
3229             break;
3230
3231       case X_GetMotionEvents:
3232             UNUSED(1);
3233             REQUEST_LENGTH();
3234             WINDOW(window);
3235             TIMESTAMP(start);
3236             TIMESTAMP(stop);
3237             break;
3238
3239       case X_TranslateCoords:
3240             UNUSED(1);
3241             REQUEST_LENGTH();
3242             WINDOW(src_window);
3243             WINDOW(dst_window);
3244             INT16(src_x);
3245             INT16(src_y);
3246             break;
3247
3248       case X_WarpPointer:
3249             UNUSED(1);
3250             REQUEST_LENGTH();
3251             WINDOW(warp_pointer_src_window);
3252             WINDOW(warp_pointer_dst_window);
3253             INT16(src_x);
3254             INT16(src_y);
3255             CARD16(src_width);
3256             CARD16(src_height);
3257             INT16(dst_x);
3258             INT16(dst_y);
3259             break;
3260
3261       case X_SetInputFocus:
3262             ENUM8(revert_to);
3263             REQUEST_LENGTH();
3264             WINDOW(focus);
3265             TIMESTAMP(time);
3266             break;
3267
3268       case X_GetInputFocus:
3269             UNUSED(1);
3270             REQUEST_LENGTH();
3271             break;
3272
3273       case X_QueryKeymap:
3274             UNUSED(1);
3275             REQUEST_LENGTH();
3276             break;
3277
3278       case X_OpenFont:
3279             UNUSED(1);
3280             REQUEST_LENGTH();
3281             FONT(fid);
3282             v16 = FIELD16(name_length);
3283             UNUSED(2);
3284             STRING8(name, v16);
3285             PAD();
3286             break;
3287
3288       case X_CloseFont:
3289             UNUSED(1);
3290             REQUEST_LENGTH();
3291             FONT(font);
3292             break;
3293
3294       case X_QueryFont:
3295             UNUSED(1);
3296             REQUEST_LENGTH();
3297             FONTABLE(font);
3298             break;
3299
3300       case X_QueryTextExtents:
3301             v8 = BOOL(odd_length);
3302             REQUEST_LENGTH();
3303             FONTABLE(font);
3304             STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3305             PAD();
3306             break;
3307
3308       case X_ListFonts:
3309             UNUSED(1);
3310             REQUEST_LENGTH();
3311             CARD16(max_names);
3312             v16 = FIELD16(pattern_length);
3313             STRING8(pattern, v16);
3314             PAD();
3315             break;
3316
3317       case X_ListFontsWithInfo:
3318             UNUSED(1);
3319             REQUEST_LENGTH();
3320             CARD16(max_names);
3321             v16 = FIELD16(pattern_length);
3322             STRING8(pattern, v16);
3323             PAD();
3324             break;
3325
3326       case X_SetFontPath:
3327             UNUSED(1);
3328             REQUEST_LENGTH();
3329             v16 = CARD16(str_number_in_path);
3330             UNUSED(2);
3331             LISTofSTRING8(path, v16);
3332             PAD();
3333             break;
3334
3335       case X_GetFontPath:
3336             UNUSED(1);
3337             REQUEST_LENGTH();
3338             break;
3339
3340       case X_CreatePixmap:
3341             CARD8(depth);
3342             REQUEST_LENGTH();
3343             PIXMAP(pid);
3344             DRAWABLE(drawable);
3345             CARD16(width);
3346             CARD16(height);
3347             break;
3348
3349       case X_FreePixmap:
3350             UNUSED(1);
3351             REQUEST_LENGTH();
3352             PIXMAP(pixmap);
3353             break;
3354
3355       case X_CreateGC:
3356             UNUSED(1);
3357             REQUEST_LENGTH();
3358             GCONTEXT(cid);
3359             DRAWABLE(drawable);
3360             gcAttributes(tvb, offsetp, t, little_endian);
3361             break;
3362
3363       case X_ChangeGC:
3364             UNUSED(1);
3365             REQUEST_LENGTH();
3366             GCONTEXT(gc);
3367             gcAttributes(tvb, offsetp, t, little_endian);
3368             break;
3369
3370       case X_CopyGC:
3371             UNUSED(1);
3372             REQUEST_LENGTH();
3373             GCONTEXT(src_gc);
3374             GCONTEXT(dst_gc);
3375             gcMask(tvb, offsetp, t, little_endian);
3376             break;
3377
3378       case X_SetDashes:
3379             UNUSED(1);
3380             REQUEST_LENGTH();
3381             GCONTEXT(gc);
3382             CARD16(dash_offset);
3383             v16 = FIELD16(dashes_length);
3384             LISTofCARD8(dashes, v16);
3385             PAD();
3386             break;
3387
3388       case X_SetClipRectangles:
3389             ENUM8(ordering);
3390             REQUEST_LENGTH();
3391             GCONTEXT(gc);
3392             INT16(clip_x_origin);
3393             INT16(clip_y_origin);
3394             LISTofRECTANGLE(rectangles);
3395             break;
3396
3397       case X_FreeGC:
3398             UNUSED(1);
3399             REQUEST_LENGTH();
3400             GCONTEXT(gc);
3401             break;
3402
3403       case X_ClearArea:
3404             BOOL(exposures);
3405             REQUEST_LENGTH();
3406             WINDOW(window);
3407             INT16(x);
3408             INT16(y);
3409             CARD16(width);
3410             CARD16(height);
3411             break;
3412
3413       case X_CopyArea:
3414             UNUSED(1);
3415             REQUEST_LENGTH();
3416             DRAWABLE(src_drawable);
3417             DRAWABLE(dst_drawable);
3418             GCONTEXT(gc);
3419             INT16(src_x);
3420             INT16(src_y);
3421             INT16(dst_x);
3422             INT16(dst_y);
3423             CARD16(width);
3424             CARD16(height);
3425             break;
3426
3427       case X_CopyPlane:
3428             UNUSED(1);
3429             REQUEST_LENGTH();
3430             DRAWABLE(src_drawable);
3431             DRAWABLE(dst_drawable);
3432             GCONTEXT(gc);
3433             INT16(src_x);
3434             INT16(src_y);
3435             INT16(dst_x);
3436             INT16(dst_y);
3437             CARD16(width);
3438             CARD16(height);
3439             CARD32(bit_plane);
3440             break;
3441
3442       case X_PolyPoint:
3443             ENUM8(coordinate_mode);
3444             v16 = REQUEST_LENGTH();
3445             DRAWABLE(drawable);
3446             GCONTEXT(gc);
3447             LISTofPOINT(points, v16 - 12);
3448             break;
3449
3450       case X_PolyLine:
3451             ENUM8(coordinate_mode);
3452             v16 = REQUEST_LENGTH();
3453             DRAWABLE(drawable);
3454             GCONTEXT(gc);
3455             LISTofPOINT(points, v16 - 12);
3456             break;
3457
3458       case X_PolySegment:
3459             UNUSED(1);
3460             REQUEST_LENGTH();
3461             DRAWABLE(drawable);
3462             GCONTEXT(gc);
3463             LISTofSEGMENT(segments);
3464             break;
3465
3466       case X_PolyRectangle:
3467             UNUSED(1);
3468             REQUEST_LENGTH();
3469             DRAWABLE(drawable);
3470             GCONTEXT(gc);
3471             LISTofRECTANGLE(rectangles);
3472             break;
3473
3474       case X_PolyArc:
3475             UNUSED(1);
3476             REQUEST_LENGTH();
3477             DRAWABLE(drawable);
3478             GCONTEXT(gc);
3479             LISTofARC(arcs);
3480             break;
3481
3482       case X_FillPoly:
3483             UNUSED(1);
3484             v16 = REQUEST_LENGTH();
3485             DRAWABLE(drawable);
3486             GCONTEXT(gc);
3487             ENUM8(shape);
3488             ENUM8(coordinate_mode);
3489             UNUSED(2);
3490             LISTofPOINT(points, v16 - 16);
3491             break;
3492
3493       case X_PolyFillRectangle:
3494             UNUSED(1);
3495             REQUEST_LENGTH();
3496             DRAWABLE(drawable);
3497             GCONTEXT(gc);
3498             LISTofRECTANGLE(rectangles);
3499             break;
3500
3501       case X_PolyFillArc:
3502             UNUSED(1);
3503             REQUEST_LENGTH();
3504             DRAWABLE(drawable);
3505             GCONTEXT(gc);
3506             LISTofARC(arcs);
3507             break;
3508
3509       case X_PutImage:
3510             ENUM8(image_format);
3511             v16 = REQUEST_LENGTH();
3512             DRAWABLE(drawable);
3513             GCONTEXT(gc);
3514             CARD16(width);
3515             CARD16(height);
3516             INT16(dst_x);
3517             INT16(dst_y);
3518             CARD8(left_pad);
3519             CARD8(depth);
3520             UNUSED(2);
3521             LISTofBYTE(data, v16 - 24);
3522             PAD();
3523             break;
3524
3525       case X_GetImage:
3526             ENUM8(image_pixmap_format);
3527             REQUEST_LENGTH();
3528             DRAWABLE(drawable);
3529             INT16(x);
3530             INT16(y);
3531             CARD16(width);
3532             CARD16(height);
3533             CARD32(plane_mask);
3534             break;
3535
3536       case X_PolyText8:
3537             UNUSED(1);
3538             v16 = REQUEST_LENGTH();
3539             DRAWABLE(drawable);
3540             GCONTEXT(gc);
3541             INT16(x);
3542             INT16(y);
3543             LISTofTEXTITEM8(items);
3544             PAD();
3545             break;
3546
3547       case X_PolyText16:
3548             UNUSED(1);
3549             v16 = REQUEST_LENGTH();
3550             DRAWABLE(drawable);
3551             GCONTEXT(gc);
3552             INT16(x);
3553             INT16(y);
3554             LISTofTEXTITEM16(items);
3555             PAD();
3556             break;
3557
3558       case X_ImageText8:
3559             v8 = FIELD8(string_length);
3560             REQUEST_LENGTH();
3561             DRAWABLE(drawable);
3562             GCONTEXT(gc);
3563             INT16(x);
3564             INT16(y);
3565             STRING8(string, v8);
3566             PAD();
3567             break;
3568
3569       case X_ImageText16:
3570             v8 = FIELD8(string_length);
3571             REQUEST_LENGTH();
3572             DRAWABLE(drawable);
3573             GCONTEXT(gc);
3574             INT16(x);
3575             INT16(y);
3576             STRING16(string16, v8);
3577             PAD();
3578             break;
3579
3580       case X_CreateColormap:
3581             ENUM8(alloc);
3582             REQUEST_LENGTH();
3583             COLORMAP(mid);
3584             WINDOW(window);
3585             VISUALID(visual);
3586             break;
3587
3588       case X_FreeColormap:
3589             UNUSED(1);
3590             REQUEST_LENGTH();
3591             COLORMAP(cmap);
3592             break;
3593
3594       case X_CopyColormapAndFree:
3595             UNUSED(1);
3596             REQUEST_LENGTH();
3597             COLORMAP(mid);
3598             COLORMAP(src_cmap);
3599             break;
3600
3601       case X_InstallColormap:
3602             UNUSED(1);
3603             REQUEST_LENGTH();
3604             COLORMAP(cmap);
3605             break;
3606
3607       case X_UninstallColormap:
3608             UNUSED(1);
3609             REQUEST_LENGTH();
3610             COLORMAP(cmap);
3611             break;
3612
3613       case X_ListInstalledColormaps:
3614             UNUSED(1);
3615             REQUEST_LENGTH();
3616             WINDOW(window);
3617             break;
3618
3619       case X_AllocColor:
3620             UNUSED(1);
3621             REQUEST_LENGTH();
3622             COLORMAP(cmap);
3623             CARD16(red);
3624             CARD16(green);
3625             CARD16(blue);
3626             UNUSED(2);
3627             break;
3628
3629       case X_AllocNamedColor:
3630             UNUSED(1);
3631             REQUEST_LENGTH();
3632             COLORMAP(cmap);
3633             v16 = FIELD16(name_length);
3634             UNUSED(2);
3635             STRING8(name, v16);
3636             PAD();
3637             break;
3638
3639       case X_AllocColorCells:
3640             BOOL(contiguous);
3641             REQUEST_LENGTH();
3642             COLORMAP(cmap);
3643             CARD16(colors);
3644             CARD16(planes);
3645             break;
3646
3647       case X_AllocColorPlanes:
3648             BOOL(contiguous);
3649             REQUEST_LENGTH();
3650             COLORMAP(cmap);
3651             CARD16(colors);
3652             CARD16(reds);
3653             CARD16(greens);
3654             CARD16(blues);
3655             break;
3656
3657       case X_FreeColors:
3658             UNUSED(1);
3659             v16 = REQUEST_LENGTH();
3660             COLORMAP(cmap);
3661             CARD32(plane_mask);
3662             LISTofCARD32(pixels, v16 - 12);
3663             break;
3664
3665       case X_StoreColors:
3666             UNUSED(1);
3667             v16 = REQUEST_LENGTH();
3668             COLORMAP(cmap);
3669             LISTofCOLORITEM(color_items, v16 - 8);
3670             break;
3671
3672       case X_StoreNamedColor:
3673             COLOR_FLAGS(color);
3674             REQUEST_LENGTH();
3675             COLORMAP(cmap);
3676             CARD32(pixel);
3677             v16 = FIELD16(name_length);
3678             UNUSED(2);
3679             STRING8(name, v16);
3680             PAD();
3681             break;
3682
3683       case X_QueryColors:
3684             UNUSED(1);
3685             v16 = REQUEST_LENGTH();
3686             COLORMAP(cmap);
3687             LISTofCARD32(pixels, v16 - 8);
3688             break;
3689
3690       case X_LookupColor:
3691             UNUSED(1);
3692             REQUEST_LENGTH();
3693             COLORMAP(cmap);
3694             v16 = FIELD16(name_length);
3695             UNUSED(2);
3696             STRING8(name, v16);
3697             PAD();
3698             break;
3699
3700       case X_CreateCursor:
3701             UNUSED(1);
3702             REQUEST_LENGTH();
3703             CURSOR(cid);
3704             PIXMAP(source_pixmap);
3705             PIXMAP(mask);
3706             CARD16(fore_red);
3707             CARD16(fore_green);
3708             CARD16(fore_blue);
3709             CARD16(back_red);
3710             CARD16(back_green);
3711             CARD16(back_blue);
3712             CARD16(x);
3713             CARD16(y);
3714             break;
3715
3716       case X_CreateGlyphCursor:
3717             UNUSED(1);
3718             REQUEST_LENGTH();
3719             CURSOR(cid);
3720             FONT(source_font);
3721             FONT(mask_font);
3722             CARD16(source_char);
3723             CARD16(mask_char);
3724             CARD16(fore_red);
3725             CARD16(fore_green);
3726             CARD16(fore_blue);
3727             CARD16(back_red);
3728             CARD16(back_green);
3729             CARD16(back_blue);
3730             break;
3731
3732       case X_FreeCursor:
3733             UNUSED(1);
3734             REQUEST_LENGTH();
3735             CURSOR(cursor);
3736             break;
3737
3738       case X_RecolorCursor:
3739             UNUSED(1);
3740             REQUEST_LENGTH();
3741             CURSOR(cursor);
3742             CARD16(fore_red);
3743             CARD16(fore_green);
3744             CARD16(fore_blue);
3745             CARD16(back_red);
3746             CARD16(back_green);
3747             CARD16(back_blue);
3748             break;
3749
3750       case X_QueryBestSize:
3751             ENUM8(class);
3752             REQUEST_LENGTH();
3753             DRAWABLE(drawable);
3754             CARD16(width);
3755             CARD16(height);
3756             break;
3757
3758       case X_QueryExtension:
3759             UNUSED(1);
3760             REQUEST_LENGTH();
3761             v16 = FIELD16(name_length);
3762             UNUSED(2);
3763             STRING8(name, v16);
3764             PAD();
3765             break;
3766
3767       case X_ListExtensions:
3768             UNUSED(1);
3769             REQUEST_LENGTH();
3770             break;
3771
3772       case X_ChangeKeyboardMapping:
3773             v8 = FIELD8(keycode_count);
3774             REQUEST_LENGTH();
3775             v8_2 = KEYCODE(first_keycode);
3776             v8_3 = FIELD8(keysyms_per_keycode);
3777             UNUSED(2);
3778             LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3779             break;
3780
3781       case X_GetKeyboardMapping:
3782             UNUSED(1);
3783             REQUEST_LENGTH();
3784             state->request.GetKeyboardMapping.first_keycode
3785             = KEYCODE(first_keycode);
3786             FIELD8(count);
3787             UNUSED(2);
3788             break;
3789
3790       case X_ChangeKeyboardControl:
3791             UNUSED(1);
3792             REQUEST_LENGTH();
3793             BITMASK32(keyboard_value);
3794             BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3795             BITFIELD(INT8, keyboard_value_mask, bell_percent);
3796             BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3797             BITFIELD(INT16, keyboard_value_mask, bell_duration);
3798             BITFIELD(INT16, keyboard_value_mask, led);
3799             BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3800             BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3801             BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3802             ENDBITMASK;
3803             break;
3804
3805       case X_GetKeyboardControl:
3806             UNUSED(1);
3807             REQUEST_LENGTH();
3808             break;
3809
3810       case X_Bell:
3811             INT8(percent);
3812             REQUEST_LENGTH();
3813             break;
3814
3815       case X_ChangePointerControl:
3816             UNUSED(1);
3817             REQUEST_LENGTH();
3818             INT16(acceleration_numerator);
3819             INT16(acceleration_denominator);
3820             INT16(threshold);
3821             BOOL(do_acceleration);
3822             BOOL(do_threshold);
3823             break;
3824
3825       case X_GetPointerControl:
3826             UNUSED(1);
3827             REQUEST_LENGTH();
3828             break;
3829
3830       case X_SetScreenSaver:
3831             UNUSED(1);
3832             REQUEST_LENGTH();
3833             INT16(timeout);
3834             INT16(interval);
3835             ENUM8(prefer_blanking);
3836             ENUM8(allow_exposures);
3837             UNUSED(2);
3838             break;
3839
3840       case X_GetScreenSaver:
3841             UNUSED(1);
3842             REQUEST_LENGTH();
3843             break;
3844
3845       case X_ChangeHosts:
3846             ENUM8(change_host_mode);
3847             REQUEST_LENGTH();
3848             v8 = ENUM8(family);
3849             UNUSED(1);
3850             v16 = CARD16(address_length);
3851             if (v8 == FAMILY_INTERNET && v16 == 4) {
3852                   /*
3853                    * IPv4 addresses.
3854                    * XXX - what about IPv6?  Is that a family of
3855                    * FAMILY_INTERNET (0) with a length of 16?
3856                    */
3857                   LISTofCARD8(ip_address, v16);
3858             } else
3859                   LISTofCARD8(address, v16);
3860             break;
3861
3862       case X_ListHosts:
3863             UNUSED(1);
3864             REQUEST_LENGTH();
3865             break;
3866
3867       case X_SetAccessControl:
3868             ENUM8(access_mode);
3869             REQUEST_LENGTH();
3870             break;
3871
3872       case X_SetCloseDownMode:
3873             ENUM8(close_down_mode);
3874             REQUEST_LENGTH();
3875             break;
3876
3877       case X_KillClient:
3878             UNUSED(1);
3879             REQUEST_LENGTH();
3880             CARD32(resource);
3881             break;
3882
3883       case X_RotateProperties:
3884             UNUSED(1);
3885             v16 = REQUEST_LENGTH();
3886             WINDOW(window);
3887             CARD16(property_number);
3888             INT16(delta);
3889             LISTofATOM(properties, (v16 - 12));
3890             break;
3891
3892       case X_ForceScreenSaver:
3893             ENUM8(screen_saver_mode);
3894             REQUEST_LENGTH();
3895             break;
3896
3897       case X_SetPointerMapping:
3898             v8 = FIELD8(map_length);
3899             REQUEST_LENGTH();
3900             LISTofCARD8(map, v8);
3901             PAD();
3902             break;
3903
3904       case X_GetPointerMapping:
3905             UNUSED(1);
3906             REQUEST_LENGTH();
3907             break;
3908
3909       case X_SetModifierMapping:
3910             v8 = FIELD8(keycodes_per_modifier);
3911             REQUEST_LENGTH();
3912             LISTofKEYCODE(state->modifiermap, keycodes, v8);
3913             break;
3914
3915       case X_GetModifierMapping:
3916             UNUSED(1);
3917             REQUEST_LENGTH();
3918             break;
3919
3920       case X_NoOperation:
3921             UNUSED(1);
3922             REQUEST_LENGTH();
3923             break;
3924       }
3925
3926       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3927             UNDECODED(left);
3928 }
3929
3930 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
3931     proto_tree *tree)
3932 {
3933       volatile int offset = 0;
3934       int length_remaining;
3935       volatile gboolean little_endian;
3936       guint8 opcode;
3937       volatile int plen;
3938       proto_item *ti;
3939       proto_tree *t;
3940       volatile gboolean is_initial_creq;
3941       guint16 auth_proto_len, auth_data_len;
3942       const char *volatile sep = NULL;
3943       conversation_t *conversation;
3944       x11_conv_data_t *state;
3945       int length;
3946       tvbuff_t *next_tvb;
3947
3948       while (tvb_reported_length_remaining(tvb, offset) != 0) {
3949             /*
3950              * We use "tvb_ensure_length_remaining()" to make sure there
3951              * actually *is* data remaining.
3952              *
3953              * This means we're guaranteed that "length_remaining" is
3954              * positive.
3955              */
3956             length_remaining = tvb_ensure_length_remaining(tvb, offset);
3957
3958             /*
3959              * Can we do reassembly?
3960              */
3961             if (x11_desegment && pinfo->can_desegment) {
3962                   /*
3963                    * Yes - is the X11 request header split across
3964                    * segment boundaries?
3965                    */
3966                   if (length_remaining < 4) {
3967                         /*
3968                          * Yes.  Tell the TCP dissector where the data
3969                          * for this message starts in the data it handed
3970                          * us, and how many more bytes we need, and return.
3971                          */
3972                         pinfo->desegment_offset = offset;
3973                         pinfo->desegment_len = 4 - length_remaining;
3974                         return;
3975                   }
3976             }
3977
3978             /*
3979              * Get the state for this conversation; create the conversation
3980              * if we don't have one, and create the state if we don't have
3981              * any.
3982              */
3983             conversation = find_conversation(&pinfo->src, &pinfo->dst,
3984                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3985             if (conversation == NULL) {
3986                   /*
3987                    * No - create one.
3988                    */
3989                   conversation = conversation_new(&pinfo->src,
3990                         &pinfo->dst, pinfo->ptype, pinfo->srcport,
3991                         pinfo->destport, 0);
3992             }
3993
3994             /*
3995              * Is there state attached to this conversation?
3996              */
3997             if ((state = conversation_get_proto_data(conversation, proto_x11))
3998             == NULL)
3999                 x11_stateinit(&state, conversation);
4000
4001             /*
4002              * Guess the byte order if we don't already know it.
4003              */
4004             little_endian = guess_byte_ordering(tvb, pinfo, state);
4005
4006             /*
4007              * Get the opcode and length of the putative X11 request.
4008              */
4009             opcode = VALUE8(tvb, 0);
4010             plen = VALUE16(tvb, offset + 2);
4011
4012             if (plen == 0) {
4013                   /*
4014                    * This can't be 0, as it includes the header length.
4015                    * A different choice of byte order wouldn't have
4016                    * helped.
4017                    * Give up.
4018                    */
4019                   ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4020                   FALSE);
4021                   t = proto_item_add_subtree(ti, ett_x11);
4022                   proto_tree_add_text(t, tvb, offset, -1,
4023                   "Bogus request length (0)");
4024                   return;
4025             }
4026
4027             if (state->iconn_frame == pinfo->fd->num ||
4028                 (g_hash_table_lookup(state->seqtable,
4029                 (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
4030                  (opcode == 'B' || opcode == 'l') &&
4031                  (plen == 11 || plen == 2816))) {
4032                   /*
4033                    * Either
4034                    *
4035                    *    we saw this on the first pass and this is
4036                    *    it again
4037                    *
4038                    * or
4039                    *    we haven't already seen any requests, the first
4040                    *    byte of the message is 'B' or 'l', and the 16-bit
4041                    *    integer 2 bytes into the data stream is either 11
4042                    *    or a byte-swapped 11.
4043                    *
4044                    * This means it's probably an initial connection
4045                    * request, not a message.
4046                    *
4047                    * 'B' is decimal 66, which is the opcode for a
4048                    * PolySegment request; unfortunately, 11 is a valid
4049                    * length for a PolySegment request request, so we
4050                    * might mis-identify that request.  (Are there any
4051                    * other checks we can do?)
4052                    *
4053                    * 'l' is decimal 108, which is the opcode for a
4054                    * GetScreenSaver request; the only valid length
4055                    * for that request is 1.
4056                    */
4057                   is_initial_creq = TRUE;
4058
4059                   /*
4060                    * We now know the byte order.  Override the guess.
4061                    */
4062                   if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4063                         if (opcode == 'B') {
4064                               /*
4065                                * Big-endian.
4066                                */
4067                               state->byte_order = BYTE_ORDER_BE;
4068                               little_endian = FALSE;
4069                         } else {
4070                               /*
4071                                * Little-endian.
4072                                */
4073                               state->byte_order = BYTE_ORDER_LE;
4074                               little_endian = TRUE;
4075                         }
4076                   }
4077
4078                   /*
4079                    * Can we do reassembly?
4080                    */
4081                   if (x11_desegment && pinfo->can_desegment) {
4082                         /*
4083                          * Yes - is the fixed-length portion of the
4084                          * initial connection header split across
4085                          * segment boundaries?
4086                          */
4087                         if (length_remaining < 10) {
4088                               /*
4089                                * Yes.  Tell the TCP dissector where the
4090                                * data for this message starts in the data
4091                                * it handed us, and how many more bytes we
4092                                * need, and return.
4093                                */
4094                               pinfo->desegment_offset = offset;
4095                               pinfo->desegment_len = 10 - length_remaining;
4096                               return;
4097                         }
4098                   }
4099
4100                   /*
4101                    * Get the lengths of the authorization protocol and
4102                    * the authorization data.
4103                    */
4104                   auth_proto_len = VALUE16(tvb, offset + 6);
4105                   auth_data_len = VALUE16(tvb, offset + 8);
4106                   plen = 12 + ROUND_LENGTH(auth_proto_len) +
4107                         ROUND_LENGTH(auth_data_len);
4108             } else {
4109                   /*
4110                    * This is probably an ordinary request.
4111                    */
4112                   is_initial_creq = FALSE;
4113
4114                   /*
4115                    * The length of a request is in 4-byte words.
4116                    */
4117                   plen *= 4;
4118             }
4119
4120             /*
4121              * Can we do reassembly?
4122              */
4123             if (x11_desegment && pinfo->can_desegment) {
4124                   /*
4125                    * Yes - is the X11 request split across segment
4126                    * boundaries?
4127                    */
4128                   if (length_remaining < plen) {
4129                         /*
4130                          * Yes.  Tell the TCP dissector where the data
4131                          * for this message starts in the data it handed
4132                          * us, and how many more bytes we need, and return.
4133                          */
4134                         pinfo->desegment_offset = offset;
4135                         pinfo->desegment_len = plen - length_remaining;
4136                         return;
4137                   }
4138             }
4139
4140             /*
4141              * Construct a tvbuff containing the amount of the payload
4142              * we have available.  Make its reported length the
4143              * amount of data in the X11 request.
4144              *
4145              * XXX - if reassembly isn't enabled. the subdissector
4146              * will throw a BoundsError exception, rather than a
4147              * ReportedBoundsError exception.  We really want a tvbuff
4148              * where the length is "length", the reported length is "plen",
4149              * and the "if the snapshot length were infinite" length is the
4150              * minimum of the reported length of the tvbuff handed to us
4151              * and "plen", with a new type of exception thrown if the offset
4152              * is within the reported length but beyond that third length,
4153              * with that exception getting the "Unreassembled Packet" error.
4154              */
4155             length = length_remaining;
4156             if (length > plen)
4157                   length = plen;
4158             next_tvb = tvb_new_subset(tvb, offset, length, plen);
4159
4160             /*
4161              * Set the column appropriately.
4162              */
4163             if (is_initial_creq) {
4164                   if (check_col(pinfo->cinfo, COL_INFO))
4165                         col_set_str(pinfo->cinfo, COL_INFO,
4166                         "Initial connection request");
4167             } else {
4168                   if (sep == NULL) {
4169                         /*
4170                          * We haven't set the column yet; set it.
4171                          */
4172                         if (check_col(pinfo->cinfo, COL_INFO))
4173                               col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4174
4175                         /*
4176                          * Initialize the separator.
4177                          */
4178                         sep = ":";
4179                   }
4180             }
4181
4182             /*
4183              * Dissect the X11 request.
4184              *
4185              * Catch the ReportedBoundsError exception; if this
4186              * particular message happens to get a ReportedBoundsError
4187              * exception, that doesn't mean that we should stop
4188              * dissecting X11 requests within this frame or chunk of
4189              * reassembled data.
4190              *
4191              * If it gets a BoundsError, we can stop, as there's nothing
4192              * more to see, so we just re-throw it.
4193              */
4194             TRY {
4195                   if (is_initial_creq) {
4196                         dissect_x11_initial_conn(next_tvb, pinfo, tree,
4197                             state, little_endian);
4198                   } else {
4199                         dissect_x11_request(next_tvb, pinfo, tree, sep,
4200                             state, little_endian);
4201                   }
4202             }
4203             CATCH(BoundsError) {
4204                   RETHROW;
4205             }
4206             CATCH(ReportedBoundsError) {
4207                   show_reported_bounds_error(tvb, pinfo, tree);
4208             }
4209             ENDTRY;
4210
4211             /*
4212              * Skip the X11 message.
4213              */
4214             offset += plen;
4215
4216             sep = ",";
4217       }
4218 }
4219
4220 static void
4221 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4222 {
4223         static x11_conv_data_t stateinit;
4224
4225         *state = g_mem_chunk_alloc(x11_state_chunk);
4226         **state = stateinit; 
4227
4228         (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4229         g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4230         (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4231         conversation_add_proto_data(conversation, proto_x11, *state);
4232 }
4233
4234
4235 static void
4236 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4237 {
4238 /* Set up structures we will need to add the protocol subtree and manage it */
4239         volatile int offset, plen;
4240         tvbuff_t * volatile next_tvb;
4241         conversation_t *conversation;
4242         x11_conv_data_t *state;
4243         gboolean little_endian;
4244         int length_remaining;
4245         const char *volatile sep = NULL;
4246
4247
4248         /*
4249         * Get the state for this conversation; create the conversation
4250         * if we don't have one, and create the state if we don't have
4251         * any.
4252         */
4253         conversation = find_conversation(&pinfo->src, &pinfo->dst,
4254         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4255         if (conversation == NULL) {
4256                 /*
4257                  * No - create one.
4258                 */
4259                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4260                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4261         }
4262
4263         /*
4264          * Is there state attached to this conversation?
4265         */
4266         if ((state = conversation_get_proto_data(conversation, proto_x11))
4267         == NULL) {
4268                 /*
4269                  * No - create a state structure and attach it.
4270                  */
4271                 x11_stateinit(&state, conversation);
4272         }
4273
4274         /*
4275          * Guess the byte order if we don't already know it.
4276          */
4277         little_endian = guess_byte_ordering(tvb, pinfo, state);
4278
4279         offset = 0;
4280         while (tvb_reported_length_remaining(tvb, offset) != 0) {
4281                 /*
4282                  * We use "tvb_ensure_length_remaining()" to make sure there
4283                  * actually *is* data remaining.
4284                  *
4285                  * This means we're guaranteed that "length_remaining" is
4286                  * positive.
4287                  */
4288                 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4289
4290                 /*
4291                 * Can we do reassembly?
4292                 */
4293                 if (x11_desegment && pinfo->can_desegment) {
4294                           /*
4295                            * Yes - is the X11 reply header split across
4296                            * segment boundaries?
4297                            */
4298                           if (length_remaining < 8) {
4299                                 /*
4300                                  * Yes.  Tell the TCP dissector where the data
4301                                  * for this message starts in the data it handed
4302                                  * us, and how many more bytes we need, and
4303                                  * return.
4304                                  */
4305                                 pinfo->desegment_offset = offset;
4306                                 pinfo->desegment_len = 4 - length_remaining;
4307                                 return;
4308                         }
4309                 }
4310
4311                 /*
4312                  * Find out what kind of a reply it is.
4313                  * There are four possible:
4314                  *      - reply to initial connection
4315                  *      - errorreply (a request generated an error)
4316                  *      - requestreply (reply to a request)
4317                  *      - event (some event occured)
4318                  */
4319                 if (g_hash_table_lookup(state->seqtable,
4320                     (int *)state->sequencenumber) == (int *)INITIAL_CONN 
4321                     || (state->iconn_reply == pinfo->fd->num)) {
4322                         /*
4323                          * Either the connection is in the "initial
4324                          * connection" state, or this frame is known
4325                          * to have the initial connection reply.
4326                          * That means this is the initial connection
4327                          * reply.
4328                          */
4329                         plen = 8 + VALUE16(tvb, offset + 6) * 4;
4330
4331                         HANDLE_REPLY(plen, length_remaining,
4332                             "Initial connection reply", 
4333                             dissect_x11_initial_reply); 
4334                 } else {
4335                         /*
4336                          * This isn't an initial connection reply
4337                          * (XXX - unless we missed the initial
4338                          * connection request).  Look at the first
4339                          * byte to determine what it is; errors
4340                          * start with a byte of 0, replies start
4341                          * with a byte of 1, events start with
4342                          * a byte with of 2 or greater.
4343                          */
4344                         switch (tvb_get_guint8(tvb, offset)) {
4345
4346                         case 0:
4347                                 plen = 32;
4348                                 HANDLE_REPLY(plen, length_remaining,
4349                                     "Error", dissect_x11_error); 
4350                                 break;
4351
4352                         case 1:
4353                                 /* replylength is in units of four. */
4354                                 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4355
4356                                 HANDLE_REPLY(plen, length_remaining,
4357                                     "Reply", dissect_x11_reply); 
4358                                 break;
4359
4360                         default:
4361                                 /* Event */
4362                                 plen = 32;
4363                                 HANDLE_REPLY(plen, length_remaining,
4364                                     "Event", dissect_x11_event);
4365                                 break;
4366                         }
4367                 }
4368
4369                 offset += plen;
4370         }
4371
4372         return;
4373 }
4374
4375 static void
4376 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4377                   const char *volatile sep, x11_conv_data_t *volatile state,
4378                   gboolean little_endian)
4379 {
4380         int offset = 0, *offsetp = &offset, length, left, opcode;
4381         proto_item *ti;
4382         proto_tree *t;
4383         
4384         ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4385                                  tvb_reported_length_remaining(tvb, offset),
4386                                  FALSE);
4387         t = proto_item_add_subtree(ti, ett_x11);
4388
4389
4390         /*
4391          * XXX - this doesn't work correctly if either
4392          *
4393          *      1) the request sequence number wraps in the lower 16
4394          *         bits;
4395          *
4396          *      2) we don't see the initial connection request and thus
4397          *         don't have the right sequence numbers;
4398          *
4399          *      3) we don't have all the packets in the capture and
4400          *         get out of sequence.
4401          *
4402          * We might, instead, want to assume that a reply is a reply to
4403          * the most recent not-already-replied-to request in the same
4404          * connection.  That also might mismatch replies to requests if
4405          * packets are lost, but there's nothing you can do to fix that.
4406          *
4407          * XXX - if "opcode" is 0, we shouldn't say "Unknown opcode",
4408          * we should say that we don't have the request for the reply.
4409          */
4410         opcode = (int)g_hash_table_lookup(state->seqtable,
4411         (int *)VALUE16(tvb, offset + 2));
4412
4413         if (check_col(pinfo->cinfo, COL_INFO))
4414                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4415                                 sep,
4416                                 /* 
4417                                  * don't print opcode value since if it's
4418                                  * unknown, we didn't know to save the
4419                                  * request opcode.
4420                                  */
4421                                 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
4422
4423         proto_item_append_text(ti, ", Reply, opcode: %d (%s)", 
4424                               opcode, val_to_str(opcode, opcode_vals,
4425                               "<Unknown opcode %d>"));
4426
4427         if (tree == NULL)
4428                 return; 
4429
4430         switch (opcode) {
4431                 /*
4432                  * Requests that expect a reply.
4433                 */
4434
4435                 case X_GetWindowAttributes:
4436                 case X_GetGeometry:
4437                 case X_QueryTree:
4438                 case X_InternAtom:
4439                 case X_GetAtomName:
4440                         REPLYCONTENTS_COMMON();
4441                         break; 
4442
4443                 case X_GetProperty:
4444                         REPLY(reply);
4445                         CARD8(format);
4446                         SEQUENCENUMBER_REPLY(sequencenumber);
4447                         length = REPLYLENGTH(replylength);
4448                         ATOM(get_property_type);
4449                         CARD32(bytes_after);
4450                         CARD32(valuelength);
4451                         UNUSED(12);
4452                         break;
4453
4454                 case X_ListProperties:
4455                 case X_GetSelectionOwner:
4456                 case X_GrabPointer:
4457                 case X_GrabKeyboard:
4458                 case X_QueryPointer:
4459                 case X_GetMotionEvents:
4460                 case X_TranslateCoords:
4461                         REPLYCONTENTS_COMMON();
4462                         break; 
4463
4464                 case X_QueryKeymap:
4465                 case X_QueryFont:
4466                 case X_QueryTextExtents:
4467                 case X_ListFonts:
4468                 case X_GetImage:
4469                 case X_ListInstalledColormaps:
4470                 case X_AllocColor:
4471                 case X_QueryColors:
4472                 case X_LookupColor:
4473                 case X_QueryBestSize:
4474                 case X_QueryExtension:
4475                 case X_ListExtensions:
4476                         REPLYCONTENTS_COMMON();
4477                         break; 
4478
4479                 case X_GetKeyboardMapping:
4480                         state->first_keycode
4481                         = state->request.GetKeyboardMapping.first_keycode, 
4482                         REPLY(reply);
4483                         state->keysyms_per_keycode
4484                         = FIELD8(keysyms_per_keycode);
4485                         SEQUENCENUMBER_REPLY(sequencenumber);
4486                         length = REPLYLENGTH(replylength);
4487                         UNUSED(24);
4488                         LISTofKEYSYM(keysyms, state->keycodemap,
4489                         state->request.GetKeyboardMapping.first_keycode, 
4490                         length / state->keysyms_per_keycode,
4491                         state->keysyms_per_keycode);
4492                         break; 
4493
4494                 case X_GetKeyboardControl:
4495                 case X_GetPointerControl:
4496                 case X_GetScreenSaver:
4497                 case X_ListHosts:
4498                 case X_SetPointerMapping:
4499                 case X_GetPointerMapping:
4500                 case X_SetModifierMapping:
4501                         REPLYCONTENTS_COMMON();
4502                         break; 
4503
4504                 case X_GetModifierMapping:
4505                         REPLY(reply);
4506                         state->keycodes_per_modifier
4507                         = FIELD8(keycodes_per_modifier);
4508                         SEQUENCENUMBER_REPLY(sequencenumber);
4509                         REPLYLENGTH(replylength);
4510                         UNUSED(24);
4511                         LISTofKEYCODE(state->modifiermap, keycodes,
4512                         state->keycodes_per_modifier);
4513                         break; 
4514
4515                 default:
4516                         REPLYCONTENTS_COMMON();
4517         }
4518
4519         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4520             UNDECODED(left);
4521 }
4522
4523 static void
4524 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4525                   const char *volatile sep, x11_conv_data_t *volatile state,
4526                   gboolean little_endian)
4527 {
4528         int offset = 0, *offsetp = &offset, left;
4529         unsigned char eventcode;
4530         proto_item *ti;
4531         proto_tree *t;
4532
4533         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4534         t = proto_item_add_subtree(ti, ett_x11);
4535
4536         eventcode = tvb_get_guint8(tvb, offset);
4537
4538         if (check_col(pinfo->cinfo, COL_INFO))
4539                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4540                                 sep, val_to_str(eventcode, eventcode_vals,
4541                                 "<Unknown eventcode %u>"));
4542
4543         proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4544                                    eventcode, 
4545                                    "eventcode: %d (%s)",
4546                                    eventcode, 
4547                                    val_to_str(eventcode, eventcode_vals,
4548                                    "<Unknown eventcode %u>"));
4549         ++offset;
4550
4551         proto_item_append_text(ti, ", Event, eventcode: %d (%s)", 
4552                               eventcode, val_to_str(eventcode, eventcode_vals,
4553                               "<Unknown eventcode %u>"));
4554
4555         if (tree == NULL)
4556                 return; 
4557
4558         switch (eventcode) {
4559                 case KeyPress:
4560                 case KeyRelease: {
4561                         int code, mask;
4562
4563                         /* need to do some prefetching here ... */
4564                         code = VALUE8(tvb, offset);
4565                         mask = VALUE16(tvb, 28);
4566
4567                         KEYCODE_DECODED(keycode, code, mask);
4568                         CARD16(event_sequencenumber);
4569                         EVENTCONTENTS_COMMON();
4570                         BOOL(same_screen);
4571                         UNUSED(1);
4572                         break;
4573                 }
4574
4575                 case ButtonPress:
4576                 case ButtonRelease:
4577                         BUTTON(eventbutton);
4578                         CARD16(event_sequencenumber);
4579                         EVENTCONTENTS_COMMON();
4580                         BOOL(same_screen);
4581                         UNUSED(1);
4582                         break;
4583
4584                 case MotionNotify:
4585                         CARD8(detail);
4586                         CARD16(event_sequencenumber);
4587                         EVENTCONTENTS_COMMON();
4588                         BOOL(same_screen);
4589                         UNUSED(1);
4590                         break;
4591
4592                 case EnterNotify:
4593                 case LeaveNotify:
4594                         CARD8(detail);
4595                         CARD16(event_sequencenumber);
4596                         EVENTCONTENTS_COMMON();
4597                         CARD8(same_screen);
4598                         break;
4599
4600                 case FocusIn:
4601                 case FocusOut:
4602                 case KeymapNotify:
4603                 case Expose:
4604                 case GraphicsExpose:
4605                 case NoExpose:
4606                 case VisibilityNotify:
4607                 case CreateNotify:
4608                 case DestroyNotify:
4609                 case UnmapNotify:
4610                 case MapNotify:
4611                 case MapRequest:
4612                 case ReparentNotify:
4613                 case ConfigureNotify:
4614                 case ConfigureRequest:
4615                 case GravityNotify:
4616                 case ResizeRequest:
4617                 case CirculateNotify:
4618                 case CirculateRequest:
4619                 case PropertyNotify:
4620                 case SelectionClear:
4621                 case SelectionRequest:
4622                 case SelectionNotify:
4623                 case ColormapNotify:
4624                 case ClientMessage:
4625                 case MappingNotify:
4626                 default:
4627                         break;
4628         }
4629
4630         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0) 
4631             UNDECODED(left);
4632
4633         return;
4634 }
4635
4636 static void
4637 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4638                   const char *volatile sep, x11_conv_data_t *volatile state _U_,
4639                   gboolean little_endian)
4640 {
4641         int offset = 0, *offsetp = &offset, left;
4642         unsigned char errorcode, error;
4643         proto_item *ti;
4644         proto_tree *t;
4645
4646         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4647         t = proto_item_add_subtree(ti, ett_x11);
4648
4649         error = tvb_get_guint8(tvb, offset);
4650         CARD8(error);
4651
4652         errorcode = tvb_get_guint8(tvb, offset);
4653         if (check_col(pinfo->cinfo, COL_INFO))
4654                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4655                 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
4656
4657         proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
4658                                    errorcode, 
4659                                    "errorcode: %d (%s)",
4660                                    errorcode, 
4661                                    val_to_str(errorcode, errorcode_vals,
4662                                    "<Unknown errocode %u>"));
4663         ++offset;
4664
4665         proto_item_append_text(ti, ", Error, errorcode: %d (%s)", 
4666                               errorcode, val_to_str(errorcode, errorcode_vals,
4667                               "<Unknown errorcode %u>"));
4668
4669         if (tree == NULL)
4670                 return; 
4671
4672         CARD16(error_sequencenumber);
4673
4674         switch (errorcode) {
4675                 case BadValue:
4676                         CARD32(error_badvalue);
4677                         break;
4678
4679                 default:
4680                         UNDECODED(4);
4681         }
4682
4683         CARD16(minor_opcode);
4684         CARD8(major_opcode);
4685
4686         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4687             UNDECODED(left);
4688 }
4689
4690                         
4691
4692 /************************************************************************
4693  ***                                                                  ***
4694  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
4695  ***                                                                  ***
4696  ************************************************************************/
4697
4698 static void
4699 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4700 {
4701         if (check_col(pinfo->cinfo, COL_PROTOCOL))
4702                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
4703
4704         if (pinfo->match_port == pinfo->srcport)
4705                 dissect_x11_replies(tvb, pinfo, tree);
4706         else
4707                 dissect_x11_requests(tvb, pinfo, tree);
4708 }
4709
4710 /* Register the protocol with Ethereal */
4711 void proto_register_x11(void)
4712 {
4713
4714 /* Setup list of header fields */
4715       static hf_register_info hf[] = {
4716 /*
4717   { &hf_x11_FIELDABBREV,
4718   { "FIELDNAME",           "x11.FIELDABBREV",
4719   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
4720   "FIELDDESCR", HFILL }
4721   },
4722 */
4723 #include "x11-register-info.h"
4724       };
4725
4726 /* Setup protocol subtree array */
4727       static gint *ett[] = {
4728             &ett_x11,
4729             &ett_x11_color_flags,
4730             &ett_x11_list_of_arc,
4731             &ett_x11_arc,
4732             &ett_x11_list_of_atom,
4733             &ett_x11_list_of_card32,
4734             &ett_x11_list_of_color_item,
4735             &ett_x11_color_item,
4736             &ett_x11_list_of_keycode,
4737             &ett_x11_list_of_keysyms,
4738             &ett_x11_keysym,
4739             &ett_x11_list_of_point,
4740             &ett_x11_point,
4741             &ett_x11_list_of_rectangle,
4742             &ett_x11_rectangle,
4743             &ett_x11_list_of_segment,
4744             &ett_x11_segment,
4745             &ett_x11_list_of_string8,
4746             &ett_x11_list_of_text_item,
4747             &ett_x11_text_item,
4748             &ett_x11_gc_value_mask,
4749             &ett_x11_event_mask,
4750             &ett_x11_do_not_propagate_mask,
4751             &ett_x11_set_of_key_mask,
4752             &ett_x11_pointer_event_mask,
4753             &ett_x11_window_value_mask,
4754             &ett_x11_configure_window_mask,
4755             &ett_x11_keyboard_value_mask,
4756       };
4757       module_t *x11_module;
4758
4759 /* Register the protocol name and description */
4760       proto_x11 = proto_register_protocol("X11", "X11", "x11");
4761
4762 /* Required function calls to register the header fields and subtrees used */
4763       proto_register_field_array(proto_x11, hf, array_length(hf));
4764       proto_register_subtree_array(ett, array_length(ett));
4765
4766       register_init_routine(x11_init_protocol);
4767
4768       x11_module = prefs_register_protocol(proto_x11, NULL);
4769       prefs_register_bool_preference(x11_module, "desegment",
4770             "Desegment all X11 messages spanning multiple TCP segments",
4771             "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
4772             &x11_desegment);
4773 }
4774
4775 void
4776 proto_reg_handoff_x11(void)
4777 {
4778   dissector_handle_t x11_handle;
4779
4780   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
4781   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
4782   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
4783   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
4784   data_handle = find_dissector("data");
4785 }
4786