Make sure the keysym list is present before allocating a buffer to hold
[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.55 2004/02/25 23:12:49 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             tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1751             keycodemap[keycode]
1752                 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1753
1754             for(i = 0; i < keysyms_per_keycode; ++i) {
1755                   /* keysymvalue = byte3 * 256 + byte4. */
1756                   guint32 v = VALUE32(tvb, *offsetp);
1757
1758                   proto_item_append_text(tti, " %s", keysymString(v));
1759                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1760                       tvb, *offsetp, 4, v,
1761                       "keysym (keycode %d): 0x%08x (%s)",
1762                       keycode, v, keysymString(v));
1763
1764                   keycodemap[keycode][i] = v;
1765                   *offsetp += 4;
1766             }
1767         
1768             for (i = 1; i < keysyms_per_keycode; ++i)
1769                 if (keycodemap[keycode][i] != NoSymbol)
1770                         break;
1771
1772             if (i == keysyms_per_keycode) {
1773                 /* all but (possibly) first were NoSymbol. */
1774                 if (keysyms_per_keycode == 4) {
1775                         keycodemap[keycode][1] = NoSymbol;
1776                         keycodemap[keycode][2] = keycodemap[keycode][0];
1777                         keycodemap[keycode][3] = NoSymbol;
1778                 }
1779
1780                 continue;
1781             }
1782
1783             for (i = 2; i < keysyms_per_keycode; ++i)
1784                 if (keycodemap[keycode][i] != NoSymbol)
1785                         break;
1786             if (i == keysyms_per_keycode) {
1787                 /* all but (possibly) first two were NoSymbol. */
1788                 if (keysyms_per_keycode == 4) {
1789                         keycodemap[keycode][2] = keycodemap[keycode][0];
1790                         keycodemap[keycode][3] =  keycodemap[keycode][1];
1791                 }
1792
1793                 continue;
1794             }
1795       }
1796 }
1797
1798 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1799                         int length, gboolean little_endian)
1800 {
1801       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1802       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1803       while(length--) {
1804             gint16 x, y;
1805             proto_item *tti;
1806             proto_tree *ttt;
1807
1808             x = VALUE16(tvb, *offsetp);
1809             y = VALUE16(tvb, *offsetp + 2);
1810
1811             tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1812             ttt = proto_item_add_subtree(tti, ett_x11_point);
1813             proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1814             *offsetp += 2;
1815             proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1816             *offsetp += 2;
1817       }
1818 }
1819
1820 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1821                             int length, gboolean little_endian)
1822 {
1823       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1824       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1825       while(length--) {
1826             gint16 x, y;
1827             unsigned width, height;
1828             proto_item *tti;
1829             proto_tree *ttt;
1830
1831             x = VALUE16(tvb, *offsetp);
1832             y = VALUE16(tvb, *offsetp + 2);
1833             width = VALUE16(tvb, *offsetp + 4);
1834             height = VALUE16(tvb, *offsetp + 6);
1835
1836             tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1837                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1838             ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1839             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1840             *offsetp += 2;
1841             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1842             *offsetp += 2;
1843             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1844             *offsetp += 2;
1845             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1846             *offsetp += 2;
1847       }
1848 }
1849
1850 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1851                           int length, gboolean little_endian)
1852 {
1853       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1854       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1855       while(length--) {
1856             gint16 x1, y1, x2, y2;
1857             proto_item *tti;
1858             proto_tree *ttt;
1859
1860             x1 = VALUE16(tvb, *offsetp);
1861             y1 = VALUE16(tvb, *offsetp + 2);
1862             x2 = VALUE16(tvb, *offsetp + 4);
1863             y2 = VALUE16(tvb, *offsetp + 6);
1864
1865             tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1866                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1867             ttt = proto_item_add_subtree(tti, ett_x11_segment);
1868             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1869             *offsetp += 2;
1870             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1871             *offsetp += 2;
1872             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1873             *offsetp += 2;
1874             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1875             *offsetp += 2;
1876       }
1877 }
1878
1879 /* XXX - the protocol tree code should handle non-printable characters.
1880    Note that "non-printable characters" may depend on your locale.... */
1881 static void stringCopy(char *dest, const char *source, int length)
1882 {
1883       guchar c;
1884       while(length--) {
1885             c = *source++;
1886             if (!isgraph(c) && c != ' ') c = '.';
1887             *dest++ = c;
1888       }
1889       *dest++ = '\0';
1890 }
1891
1892 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1893                           int hf_item, int length, gboolean little_endian)
1894 {
1895       char *s = NULL;
1896       guint allocated = 0;
1897       proto_item *ti;
1898       proto_tree *tt;
1899       int i;
1900
1901       /* Compute total length */
1902
1903       int scanning_offset = *offsetp; /* Scanning pointer */
1904       int l;
1905       for(i = length; i; i--) {
1906             l = tvb_get_guint8(tvb, scanning_offset);
1907             scanning_offset += 1 + l;
1908       }
1909
1910       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
1911       tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
1912
1913       /*
1914        * In case we throw an exception, clean up whatever stuff we've
1915        * allocated (if any).
1916        */
1917       CLEANUP_PUSH(g_free, s);
1918
1919       while(length--) {
1920             unsigned l = VALUE8(tvb, *offsetp);
1921             if (allocated < (l + 1)) {
1922                   /* g_realloc doesn't work ??? */
1923                   g_free(s);
1924                   s = g_malloc(l + 1);
1925                   allocated = l + 1;
1926             }
1927             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
1928             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
1929             *offsetp += l + 1;
1930       }
1931
1932       /*
1933        * Call the cleanup handler to free the string and pop the handler.
1934        */
1935       CLEANUP_CALL_AND_POP;
1936 }
1937
1938 #define STRING16_MAX_DISPLAYED_LENGTH 150
1939
1940 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
1941 {
1942       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
1943       for(; length > 0; offset += 2, length--) {
1944             if (tvb_get_guint8(tvb, offset))
1945                 return FALSE;
1946       }
1947       return TRUE;
1948 }
1949
1950 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
1951
1952 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
1953                                               int hf, int hf_bytes,
1954                                               int offset, unsigned length,
1955                                               char **s, int *sLength,
1956                                               gboolean little_endian)
1957 {
1958       int truncated = FALSE;
1959       unsigned l = length / 2;
1960
1961       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
1962             char *dp;
1963             int soffset = offset;
1964
1965             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
1966                   truncated = TRUE;
1967                   l = STRING16_MAX_DISPLAYED_LENGTH;
1968             }
1969             if (*sLength < (int) l + 3) {
1970                   g_free(*s);
1971                   *s = g_malloc(l + 3);
1972                   *sLength = l + 3;
1973             }
1974             dp = *s;
1975             *dp++ = '"';
1976             if (truncated) l -= 3;
1977
1978             while(l--) {
1979                   soffset++;
1980                   *dp++ = tvb_get_guint8(tvb, soffset);
1981                   soffset++;
1982             }
1983             *dp++ = '"';
1984
1985             /* If truncated, add an ellipsis */
1986             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
1987
1988             *dp++ = '\0';
1989             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
1990                                         proto_registrar_get_nth(hf) -> name, *s);
1991       } else
1992             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
1993
1994 }
1995
1996 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1997     int sizeIs16, int next_offset, gboolean little_endian)
1998 {
1999       int allocated = 0;
2000       char *s = NULL;
2001       proto_item *ti;
2002       proto_tree *tt;
2003       guint32 fid;
2004
2005       /* Compute total length */
2006
2007       int scanning_offset = *offsetp; /* Scanning pointer */
2008       int l;                            /* Length of an individual item */
2009       int n = 0;                        /* Number of items */
2010
2011       while(scanning_offset < next_offset) {
2012             l = tvb_get_guint8(tvb, scanning_offset);
2013             scanning_offset++;
2014             if (!l) break;
2015             n++;
2016             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2017       }
2018
2019       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2020       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2021
2022       /*
2023        * In case we throw an exception, clean up whatever stuff we've
2024        * allocated (if any).
2025        */
2026       CLEANUP_PUSH(g_free, s);
2027
2028       while(n--) {
2029             unsigned l = VALUE8(tvb, *offsetp);
2030             if (l == 255) { /* Item is a font */
2031                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
2032                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2033                   *offsetp += 5;
2034             } else { /* Item is a string */
2035                   proto_item *tti;
2036                   proto_tree *ttt;
2037                   gint8 delta = VALUE8(tvb, *offsetp + 1);
2038                   if (sizeIs16) l += l;
2039                   if ((unsigned) allocated < l + 1) {
2040                         /* g_realloc doesn't work ??? */
2041                         g_free(s);
2042                         s = g_malloc(l + 1);
2043                         allocated = l + 1;
2044                   }
2045                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2046                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2047                                                        "textitem (string): delta = %d, \"%s\"",
2048                                                        delta, s);
2049                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2050                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2051                   if (sizeIs16)
2052                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2053                                                           hf_x11_textitem_string_string16_bytes,
2054                                                           *offsetp + 2, l,
2055                                                           &s, &allocated,
2056                                                           little_endian);
2057                   else
2058                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2059                                                      *offsetp + 2, l, s, "\"%s\"", s);
2060                   *offsetp += l + 2;
2061             }
2062       }
2063
2064       /*
2065        * Call the cleanup handler to free the string and pop the handler.
2066        */
2067       CLEANUP_CALL_AND_POP;
2068 }
2069
2070 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2071                       gboolean little_endian)
2072 {
2073       guint32 v = VALUE8(tvb, *offsetp);
2074       header_field_info *hfi = proto_registrar_get_nth(hf);
2075       gchar *enumValue = NULL;
2076
2077       if (hfi -> strings)
2078             enumValue = match_strval(v, cVALS(hfi -> strings));
2079       if (enumValue)
2080             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2081             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2082             hfi -> name, v, enumValue);
2083       else
2084             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2085       *offsetp += 1;
2086       return v;
2087 }
2088
2089 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2090                        gboolean little_endian)
2091 {
2092       guint32 v = VALUE16(tvb, *offsetp);
2093       header_field_info *hfi = proto_registrar_get_nth(hf);
2094       gchar *enumValue = NULL;
2095
2096       if (hfi -> strings)
2097             enumValue = match_strval(v, cVALS(hfi -> strings));
2098       if (enumValue)
2099             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2100             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2101             hfi -> name, v, enumValue);
2102       else
2103             proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2104       *offsetp += 2;
2105       return v;
2106 }
2107
2108 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2109                        gboolean little_endian)
2110 {
2111       guint32 v = VALUE32(tvb, *offsetp);
2112       header_field_info *hfi = proto_registrar_get_nth(hf);
2113       gchar *enumValue = NULL;
2114       gchar *nameAsChar = hfi -> name;
2115
2116       if (hfi -> strings)
2117             enumValue = match_strval(v, cVALS(hfi -> strings));
2118       if (enumValue)
2119             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2120                                        hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2121                                        nameAsChar, v, enumValue);
2122       else
2123             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2124                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2125                                        nameAsChar, v);
2126       *offsetp += 4;
2127       return v;
2128 }
2129
2130 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2131                          gboolean little_endian)
2132 {
2133       BITMASK32(gc_value);
2134       BITFIELD(ENUM8,  gc_value_mask, function);
2135       BITFIELD(CARD32, gc_value_mask, plane_mask);
2136       BITFIELD(CARD32, gc_value_mask, foreground);
2137       BITFIELD(CARD32, gc_value_mask, background);
2138       BITFIELD(CARD16, gc_value_mask, line_width);
2139       BITFIELD(ENUM8,  gc_value_mask, line_style);
2140       BITFIELD(ENUM8,  gc_value_mask, cap_style);
2141       BITFIELD(ENUM8,  gc_value_mask, join_style);
2142       BITFIELD(ENUM8,  gc_value_mask, fill_style);
2143       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
2144       BITFIELD(PIXMAP, gc_value_mask, tile);
2145       BITFIELD(PIXMAP, gc_value_mask, stipple);
2146       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
2147       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
2148       BITFIELD(FONT,   gc_value_mask, font);
2149       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
2150       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
2151       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
2152       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
2153       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2154       BITFIELD(CARD16, gc_value_mask, dash_offset);
2155       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
2156       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
2157       ENDBITMASK;
2158 }
2159
2160 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2161                    gboolean little_endian)
2162 {
2163       BITMASK32(gc_value);
2164       FLAG(gc_value, function);
2165       FLAG(gc_value, plane_mask);
2166       FLAG(gc_value, foreground);
2167       FLAG(gc_value, background);
2168       FLAG(gc_value, line_width);
2169       FLAG(gc_value, line_style);
2170       FLAG(gc_value, cap_style);
2171       FLAG(gc_value, join_style);
2172       FLAG(gc_value, fill_style);
2173       FLAG(gc_value, fill_rule);
2174       FLAG(gc_value, tile);
2175       FLAG(gc_value, stipple);
2176       FLAG(gc_value, tile_stipple_x_origin);
2177       FLAG(gc_value, tile_stipple_y_origin);
2178       FLAG(gc_value, font);
2179       FLAG(gc_value, subwindow_mode);
2180       FLAG(gc_value, graphics_exposures);
2181       FLAG(gc_value, clip_x_origin);
2182       FLAG(gc_value, clip_y_origin);
2183       FLAG(gc_value, clip_mask);
2184       FLAG(gc_value, dash_offset);
2185       FLAG(gc_value, gc_dashes);
2186       FLAG(gc_value, arc_mode);
2187       ENDBITMASK;
2188 }
2189
2190 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2191                              gboolean little_endian)
2192 {
2193       guint32 res = VALUE16(tvb, *offsetp);
2194       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2195       *offsetp += 2;
2196       return res * 4;
2197 }
2198
2199 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2200                        gboolean little_endian)
2201 {
2202       BITMASK32(event);
2203       FLAG(event, KeyPress);
2204       FLAG(event, KeyRelease);
2205       FLAG(event, ButtonPress);
2206       FLAG(event, ButtonRelease);
2207       FLAG(event, EnterWindow);
2208       FLAG(event, LeaveWindow);
2209       FLAG(event, PointerMotion);
2210       FLAG(event, PointerMotionHint);
2211       FLAG(event, Button1Motion);
2212       FLAG(event, Button2Motion);
2213       FLAG(event, Button3Motion);
2214       FLAG(event, Button4Motion);
2215       FLAG(event, Button5Motion);
2216       FLAG(event, ButtonMotion);
2217       FLAG(event, KeymapState);
2218       FLAG(event, Exposure);
2219       FLAG(event, VisibilityChange);
2220       FLAG(event, StructureNotify);
2221       FLAG(event, ResizeRedirect);
2222       FLAG(event, SubstructureNotify);
2223       FLAG(event, SubstructureRedirect);
2224       FLAG(event, FocusChange);
2225       FLAG(event, PropertyChange);
2226       FLAG(event, ColormapChange);
2227       FLAG(event, OwnerGrabButton);
2228       FLAG_IF_NONZERO(event, erroneous_bits);
2229       ENDBITMASK;
2230 }
2231
2232 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2233                              gboolean little_endian)
2234 {
2235       BITMASK32(do_not_propagate);
2236       FLAG(do_not_propagate, KeyPress);
2237       FLAG(do_not_propagate, KeyRelease);
2238       FLAG(do_not_propagate, ButtonPress);
2239       FLAG(do_not_propagate, ButtonRelease);
2240       FLAG(do_not_propagate, PointerMotion);
2241       FLAG(do_not_propagate, Button1Motion);
2242       FLAG(do_not_propagate, Button2Motion);
2243       FLAG(do_not_propagate, Button3Motion);
2244       FLAG(do_not_propagate, Button4Motion);
2245       FLAG(do_not_propagate, Button5Motion);
2246       FLAG(do_not_propagate, ButtonMotion);
2247       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2248       ENDBITMASK;
2249 }
2250
2251
2252 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2253                          gboolean little_endian, gboolean butmask)
2254 {
2255       proto_item *ti;
2256       guint32 bitmask_value;
2257       int bitmask_offset;
2258       int bitmask_size;
2259       proto_tree *bitmask_tree;
2260
2261       bitmask_value = VALUE16(tvb, *offsetp);
2262       bitmask_offset = *offsetp;
2263       bitmask_size = 2;
2264
2265       if (!butmask && bitmask_value == 0x8000)
2266             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2267                                        "modifiers-masks: 0x8000 (AnyModifier)");
2268       else {
2269             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2270                                                  bitmask_value);
2271             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2272             FLAG(modifiers, Shift);
2273             FLAG(modifiers, Lock);
2274             FLAG(modifiers, Control);
2275             FLAG(modifiers, Mod1);
2276             FLAG(modifiers, Mod2);
2277             FLAG(modifiers, Mod3);
2278             FLAG(modifiers, Mod4);
2279             FLAG(modifiers, Mod5);
2280
2281             if (butmask) {
2282                     FLAG(modifiers, Button1);
2283                     FLAG(modifiers, Button2);
2284                     FLAG(modifiers, Button3);
2285                     FLAG(modifiers, Button4);
2286                     FLAG(modifiers, Button5);
2287             }
2288
2289             if (butmask)
2290                     FLAG_IF_NONZERO(keybut, erroneous_bits);
2291             else
2292                     FLAG_IF_NONZERO(modifiers, erroneous_bits);
2293       }
2294       *offsetp += 2;
2295 }
2296
2297
2298 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2299                               gboolean little_endian)
2300 {
2301       BITMASK16(pointer_event);
2302       FLAG(pointer_event, ButtonPress);
2303       FLAG(pointer_event, ButtonRelease);
2304       FLAG(pointer_event, EnterWindow);
2305       FLAG(pointer_event, LeaveWindow);
2306       FLAG(pointer_event, PointerMotion);
2307       FLAG(pointer_event, PointerMotionHint);
2308       FLAG(pointer_event, Button1Motion);
2309       FLAG(pointer_event, Button2Motion);
2310       FLAG(pointer_event, Button3Motion);
2311       FLAG(pointer_event, Button4Motion);
2312       FLAG(pointer_event, Button5Motion);
2313       FLAG(pointer_event, ButtonMotion);
2314       FLAG(pointer_event, KeymapState);
2315       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2316       ENDBITMASK;
2317 }
2318
2319 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2320     int hf, unsigned length)
2321 {
2322       const guint8 *p;
2323       char *s;
2324
2325       p = tvb_get_ptr(tvb, *offsetp, length);
2326       s = g_malloc(length + 1);
2327       stringCopy(s, p, length);
2328       proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2329       g_free(s);
2330       *offsetp += length;
2331 }
2332
2333 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2334
2335 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2336     int hf_bytes, unsigned length, gboolean little_endian)
2337 {
2338       char *s = NULL;
2339       unsigned l = 0;
2340
2341       /*
2342        * In case we throw an exception, clean up whatever stuff we've
2343        * allocated (if any).
2344        */
2345       CLEANUP_PUSH(g_free, s);
2346
2347       length += length;
2348       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2349                                         &s, &l, little_endian);
2350
2351       /*
2352        * Call the cleanup handler to free the string and pop the handler.
2353        */
2354       CLEANUP_CALL_AND_POP;
2355
2356       *offsetp += length;
2357 }
2358
2359 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2360                       gboolean little_endian)
2361 {
2362       guint32 v = VALUE32(tvb, *offsetp);
2363
2364       if (!v)
2365             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2366                 proto_registrar_get_nth(hf) -> name);
2367       else
2368             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2369       *offsetp += 4;
2370 }
2371
2372 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2373                              gboolean little_endian)
2374 {
2375       BITMASK32(window_value);
2376       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2377       BITFIELD(CARD32, window_value_mask, background_pixel);
2378       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2379       BITFIELD(CARD32, window_value_mask, border_pixel);
2380       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2381       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2382       BITFIELD(ENUM8, window_value_mask, backing_store);
2383       BITFIELD(CARD32, window_value_mask, backing_planes);
2384       BITFIELD(CARD32, window_value_mask, backing_pixel);
2385       BITFIELD(BOOL,   window_value_mask, override_redirect);
2386       BITFIELD(BOOL,   window_value_mask, save_under);
2387       BITFIELD(SETofEVENT, window_value_mask, event_mask);
2388       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2389       BITFIELD(COLORMAP, window_value_mask, colormap);
2390       BITFIELD(CURSOR, window_value_mask, cursor);
2391       ENDBITMASK;
2392 }
2393
2394 static void x11_init_protocol(void)
2395 {
2396       if (x11_state_chunk != NULL)
2397             g_mem_chunk_destroy(x11_state_chunk);
2398
2399       x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2400                                         sizeof (x11_conv_data_t),
2401                                         128 * sizeof (x11_conv_data_t),
2402                                         G_ALLOC_ONLY);
2403 }
2404
2405 /************************************************************************
2406  ***                                                                  ***
2407  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2408  ***                                                                  ***
2409  ************************************************************************/
2410
2411 /* If we can't guess, we return TRUE (that is little_endian), cause
2412    I'm developing on a Linux box :-). The (non-)guess isn't cached
2413    however, so we may have more luck next time. I'm quite conservative
2414    in my assertions, cause once it's cached, it's stay in cache, and
2415    we may be fooled up by a packet starting with the end of a request
2416    started in a previous packet...
2417 */
2418
2419 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2420
2421 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2422 {
2423       int res = 0;
2424       while(maskLength--) {
2425             int c = tvb_get_guint8(tvb, offset);
2426             offset++;
2427             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2428       }
2429       return res;
2430 }
2431
2432 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2433 {
2434       if (listLength > length) return FALSE;
2435       while(listLength--) {
2436             int l;
2437             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2438             l = tvb_get_guint8(tvb, offset);
2439             if (!l) break;
2440             l++;
2441             if (l > length) return FALSE;
2442             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2443             offset += l;
2444             length -= l;
2445       }
2446       if (length > 3) return FALSE;
2447       return TRUE;
2448 }
2449
2450 static int rounded4(int n)
2451 {
2452       int remainder = n % 4;
2453       int res = n / 4;
2454       if (remainder) res++;
2455       return res;
2456 }
2457
2458 /* We assume the order to be consistent, until proven wrong. */
2459
2460 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2461 {
2462       switch(tvb_get_guint8(tvb, offset)) {
2463           case X_CreateWindow:
2464             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2465
2466           case X_ChangeWindowAttributes:
2467           case X_ChangeGC:
2468             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2469
2470           case X_GetWindowAttributes:
2471           case X_DestroyWindow:
2472           case X_DestroySubwindows:
2473           case X_ChangeSaveSet:
2474           case X_MapWindow:
2475           case X_MapSubwindows:
2476           case X_UnmapWindow:
2477           case X_UnmapSubwindows:
2478           case X_CirculateWindow:
2479           case X_GetGeometry:
2480           case X_QueryTree:
2481           case X_GetAtomName:
2482           case X_ListProperties:
2483           case X_GetSelectionOwner:
2484           case X_UngrabPointer:
2485           case X_UngrabKeyboard:
2486           case X_AllowEvents:
2487           case X_QueryPointer:
2488           case X_CloseFont:
2489           case X_QueryFont:
2490           case X_FreePixmap:
2491           case X_FreeGC:
2492           case X_FreeColormap:
2493           case X_InstallColormap:
2494           case X_UninstallColormap:
2495           case X_ListInstalledColormaps:
2496           case X_FreeCursor:
2497           case X_GetKeyboardMapping:
2498           case X_KillClient:
2499             return length == 2;
2500
2501           case X_ReparentWindow:
2502           case X_SetSelectionOwner:
2503           case X_ChangeActivePointerGrab:
2504           case X_GrabKeyboard:
2505           case X_GrabKey:
2506           case X_GetMotionEvents:
2507           case X_TranslateCoords:
2508           case X_CreatePixmap:
2509           case X_CopyGC:
2510           case X_ClearArea:
2511           case X_CreateColormap:
2512           case X_AllocColor:
2513           case X_AllocColorPlanes:
2514             return length == 4;
2515
2516           case X_ConfigureWindow:
2517             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2518
2519           case X_InternAtom:
2520           case X_QueryExtension:
2521             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2522
2523           case X_ChangeProperty:
2524             {
2525                   int multiplier, type;
2526                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2527                   type = tvb_get_guint8(tvb, 16);
2528                   if (type != 8 && type != 16 && type != 32) return FALSE;
2529                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2530                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2531                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2532             }
2533
2534           case X_DeleteProperty:
2535           case X_UngrabButton:
2536           case X_UngrabKey:
2537           case X_SetInputFocus:
2538           case X_CopyColormapAndFree:
2539           case X_AllocColorCells:
2540           case X_QueryBestSize:
2541           case X_ChangePointerControl:
2542           case X_SetScreenSaver:
2543             return length == 3;
2544
2545           case X_GetProperty:
2546           case X_ConvertSelection:
2547           case X_GrabPointer:
2548           case X_GrabButton:
2549           case X_WarpPointer:
2550             return length == 6;
2551
2552           case X_SendEvent:
2553             return length == 11;
2554
2555           case X_GrabServer:
2556           case X_UngrabServer:
2557           case X_GetInputFocus:
2558           case X_QueryKeymap:
2559           case X_GetFontPath:
2560           case X_ListExtensions:
2561           case X_GetKeyboardControl:
2562           case X_Bell:
2563           case X_GetPointerControl:
2564           case X_GetScreenSaver:
2565           case X_ListHosts:
2566           case X_SetAccessControl:
2567           case X_SetCloseDownMode:
2568           case X_ForceScreenSaver:
2569           case X_GetPointerMapping:
2570           case X_GetModifierMapping:
2571             return length == 1;
2572
2573           case X_OpenFont:
2574           case X_AllocNamedColor:
2575           case X_LookupColor:
2576             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2577
2578           case X_QueryTextExtents:
2579             return length >= 2;
2580
2581           case X_ListFonts:
2582           case X_ListFontsWithInfo:
2583           case X_ChangeHosts:
2584             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2585
2586           case X_SetFontPath:
2587             if (length < 2) return FALSE;
2588             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2589             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2590
2591           case X_CreateGC:
2592             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2593
2594           case X_SetDashes:
2595             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2596
2597           case X_SetClipRectangles:
2598           case X_PolySegment:
2599           case X_PolyRectangle:
2600           case X_PolyFillRectangle:
2601             return length >= 3 && (length - 3) % 2 == 0;
2602
2603           case X_CopyArea:
2604             return length == 7;
2605
2606           case X_CopyPlane:
2607           case X_CreateCursor:
2608           case X_CreateGlyphCursor:
2609             return length == 8;
2610
2611           case X_PolyPoint:
2612           case X_PolyLine:
2613           case X_FreeColors:
2614             return length >= 3;
2615
2616           case X_PolyArc:
2617           case X_PolyFillArc:
2618             return length >= 3 && (length - 3) % 3 == 0;
2619
2620           case X_FillPoly:
2621           case X_ImageText8:
2622             return length >= 4;
2623
2624           case X_PutImage:
2625             return length >= 6;
2626
2627           case X_GetImage:
2628           case X_RecolorCursor:
2629             return length == 5;
2630
2631           case X_PolyText8:
2632             if (length < 4) return FALSE;
2633             return TRUE; /* We don't perform many controls on this one */
2634
2635           case X_PolyText16:
2636             if (length < 4) return FALSE;
2637             return TRUE; /* We don't perform many controls on this one */
2638
2639           case X_ImageText16:
2640             return length >= 4;
2641
2642           case X_StoreColors:
2643             return length > 2 && (length - 2) % 3 == 0;
2644
2645           case X_StoreNamedColor:
2646             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2647
2648           case X_QueryColors:
2649             return length >= 2;
2650
2651           case X_ChangeKeyboardMapping:
2652             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2653
2654           case X_ChangeKeyboardControl:
2655             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2656
2657           case X_RotateProperties:
2658             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2659
2660           case X_SetPointerMapping:
2661             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2662
2663           case X_SetModifierMapping:
2664             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2665
2666           case X_NoOperation:
2667             return length >= 1;
2668
2669           default:
2670             return TRUE;
2671       }
2672 }
2673
2674 /* -1 means doesn't match, +1 means match, 0 means don't know */
2675
2676 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2677 {
2678       int offset, nextoffset;
2679       int atLeastOne = 0;
2680
2681       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2682             int length;
2683             length = v16(tvb, offset + 2);
2684             if (!length) return -1;
2685             nextoffset = offset + length * 4;
2686             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2687             atLeastOne = 1;
2688       }
2689       return atLeastOne;
2690 }
2691
2692 static gboolean
2693 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2694                     x11_conv_data_t *state)
2695 {
2696       /* With X the client gives the byte ordering for the protocol,
2697          and the port on the server tells us we're speaking X. */
2698
2699       int le, be, decision, decisionToCache;
2700
2701       if (state->byte_order == BYTE_ORDER_BE)
2702             return FALSE;       /* known to be big-endian */
2703       else if (state->byte_order == BYTE_ORDER_LE)
2704             return TRUE;        /* known to be little-endian */
2705
2706       if (pinfo->srcport == pinfo->match_port) {
2707             /*
2708              * This is a reply or event; we don't try to guess the
2709              * byte order on it for now.
2710              */
2711             return TRUE;
2712       }
2713
2714       le = x_endian_match(tvb, tvb_get_letohs);
2715       be = x_endian_match(tvb, tvb_get_ntohs);
2716
2717       /* remember that "decision" really means "little_endian". */
2718       if (le == be) {
2719             /* We have no reason to believe it's little- rather than
2720                big-endian, so we guess the shortest length is the
2721                right one.
2722             */
2723             if (!tvb_bytes_exist(tvb, 0, 4))
2724                   /* Not even a way to get the length. We're biased
2725                      toward little endianness here (essentially the
2726                      x86 world right now). Decoding won't go very far
2727                      anyway.
2728                   */
2729                   decision = TRUE;
2730             else
2731                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2732       } else
2733           decision = le >= be;
2734
2735       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2736       if (decisionToCache) {
2737             /*
2738              * Remember the decision.
2739              */
2740             state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2741       }
2742
2743       /*
2744       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2745               pinfo->fd -> num, le, be, decision, decisionToCache);
2746       */
2747       return decision;
2748 }
2749
2750 /************************************************************************
2751  ***                                                                  ***
2752  ***              D E C O D I N G   O N E   P A C K E T               ***
2753  ***                                                                  ***
2754  ************************************************************************/
2755
2756 /*
2757  * Decode an initial connection request.
2758  */
2759 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2760     proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2761 {
2762       int offset = 0;
2763       int *offsetp = &offset;
2764       proto_item *ti;
2765       proto_tree *t;
2766       guint16 auth_proto_name_length, auth_proto_data_length;
2767       gint left;
2768
2769       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2770       proto_item_append_text(ti, ", Request, Initial connection request");
2771       t = proto_item_add_subtree(ti, ett_x11);
2772
2773       CARD8(byte_order);
2774       UNUSED(1);
2775       CARD16(protocol_major_version);
2776       CARD16(protocol_minor_version);
2777       auth_proto_name_length = CARD16(authorization_protocol_name_length);
2778       auth_proto_data_length = CARD16(authorization_protocol_data_length);
2779       UNUSED(2);
2780
2781       if (auth_proto_name_length != 0) {
2782             STRING8(authorization_protocol_name, auth_proto_name_length);
2783             offset = ROUND_LENGTH(offset);
2784       }
2785
2786       if (auth_proto_data_length != 0) {
2787             STRING8(authorization_protocol_data, auth_proto_data_length);
2788             offset = ROUND_LENGTH(offset);
2789       }
2790
2791       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2792                 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2793                 little_endian);
2794
2795       /*
2796        * This is the initial connection request...
2797        */
2798       state->iconn_frame = pinfo->fd->num;
2799
2800       /*
2801        * ...and we're expecting a reply to it.
2802        */
2803       state->sequencenumber = 0;
2804       g_hash_table_insert(state->seqtable, (int *)state->sequencenumber,
2805       (int *)INITIAL_CONN);
2806 }
2807
2808 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2809     proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2810     gboolean little_endian)
2811 {
2812         int offset = 0, *offsetp = &offset, left;
2813         unsigned char success;
2814         int length_of_vendor;
2815         int length_of_reason;
2816         proto_item *ti;
2817         proto_tree *t;
2818
2819         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2820         proto_item_append_text(ti, ", Reply, Initial connection reply");
2821         t = proto_item_add_subtree(ti, ett_x11);
2822
2823         state->iconn_reply = pinfo->fd->num;
2824         success = INT8(success);
2825         if (success) {
2826                 UNUSED(1);
2827                 length_of_reason = 0;
2828         }
2829         else {
2830                 length_of_reason = INT8(length_of_reason);
2831         }
2832
2833         INT16(protocol_major_version);
2834         INT16(protocol_minor_version);
2835         INT16(replylength);
2836         if (success) {
2837                 INT32(release_number);
2838                 INT32(resource_id_base);
2839                 INT32(resource_id_mask);
2840                 INT32(motion_buffer_size);
2841                 length_of_vendor = INT16(length_of_vendor);
2842                 INT16(maximum_request_length);
2843                 INT8(number_of_screens_in_roots);
2844                 INT8(number_of_formats_in_pixmap_formats);
2845                 INT8(image_byte_order);
2846                 INT8(bitmap_format_bit_order);
2847                 INT8(bitmap_format_scanline_unit);
2848                 INT8(bitmap_format_scanline_pad);
2849                 INT8(min_keycode);
2850                 INT8(max_keycode);
2851                 UNUSED(4);
2852                 STRING8(vendor, length_of_vendor);
2853         } else {
2854                 STRING8(reason, length_of_reason);
2855         }
2856
2857         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2858             UNDECODED(left);
2859
2860 }
2861
2862 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2863     proto_tree *tree, const char *sep, x11_conv_data_t *state,
2864     gboolean little_endian)
2865 {
2866       int offset = 0;
2867       int *offsetp = &offset;
2868       int next_offset;
2869       proto_item *ti;
2870       proto_tree *t;
2871       int length, opcode;
2872       guint8 v8, v8_2, v8_3;
2873       guint16 v16;
2874       guint32 v32;
2875       gint left;
2876
2877       length = VALUE16(tvb, 2) * 4;
2878
2879       if (length < 4) {
2880             /* Bogus message length? */
2881             return;
2882       }
2883
2884       next_offset = offset + length;
2885
2886       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2887       t = proto_item_add_subtree(ti, ett_x11);
2888
2889       if (PACKET_IS_NEW(pinfo))
2890             ++state->sequencenumber;
2891
2892       OPCODE();
2893
2894       if (check_col(pinfo->cinfo, COL_INFO))
2895           col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2896                           val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
2897
2898       proto_item_append_text(ti, ", Request, opcode: %d (%s)", 
2899                             opcode, val_to_str(opcode, opcode_vals,
2900                             "<Unknown opcode %d>"));
2901
2902       /*
2903        * Does this request expect a reply?
2904        */
2905       switch(opcode) {
2906       case X_AllocColor:
2907       case X_AllocColorCells:
2908       case X_AllocColorPlanes:
2909       case X_AllocNamedColor:
2910       case X_GetAtomName:
2911       case X_GetFontPath:
2912       case X_GetGeometry:
2913       case X_GetImage:
2914       case X_GetInputFocus:
2915       case X_GetKeyboardControl:
2916       case X_GetKeyboardMapping:
2917       case X_GetModifierMapping:
2918       case X_GetMotionEvents:
2919       case X_GetPointerControl:
2920       case X_GetPointerMapping:
2921       case X_GetProperty:
2922       case X_GetScreenSaver:
2923       case X_GetSelectionOwner:
2924       case X_GetWindowAttributes:
2925       case X_GrabKeyboard:
2926       case X_GrabPointer:
2927       case X_InternAtom:
2928       case X_ListExtensions:
2929       case X_ListFonts:
2930       case X_ListFontsWithInfo:
2931       case X_ListHosts:
2932       case X_ListInstalledColormaps:
2933       case X_ListProperties:
2934       case X_LookupColor:
2935       case X_QueryBestSize:
2936       case X_QueryColors:
2937       case X_QueryExtension:
2938       case X_QueryFont:
2939       case X_QueryKeymap:
2940       case X_QueryPointer:
2941       case X_QueryTextExtents:
2942       case X_QueryTree:
2943       case X_SetModifierMapping:
2944       case X_SetPointerMapping:
2945       case X_TranslateCoords:
2946                 /*
2947                  * Those requests expect a reply.
2948                  */
2949
2950                 g_hash_table_insert(state->seqtable,
2951                 (int *)state->sequencenumber, (int *)opcode);
2952
2953                 break;
2954
2955       default:
2956                 /*
2957                  * No reply is expected from any other request.
2958                  */
2959                 break;
2960       }
2961
2962       if (tree == NULL)
2963          return; 
2964
2965       switch(opcode) {
2966
2967       case X_CreateWindow:
2968             CARD8(depth);
2969             REQUEST_LENGTH();
2970             WINDOW(wid);
2971             WINDOW(parent);
2972             INT16(x);
2973             INT16(y);
2974             CARD16(width);
2975             CARD16(height);
2976             CARD16(border_width);
2977             ENUM16(window_class);
2978             VISUALID(visual);
2979             windowAttributes(tvb, offsetp, t, little_endian);
2980             break;
2981
2982       case X_ChangeWindowAttributes:
2983             UNUSED(1);
2984             REQUEST_LENGTH();
2985             WINDOW(window);
2986             windowAttributes(tvb, offsetp, t, little_endian);
2987             break;
2988
2989       case X_GetWindowAttributes:
2990       case X_DestroyWindow:
2991       case X_DestroySubwindows:
2992             UNUSED(1);
2993             REQUEST_LENGTH();
2994             WINDOW(window);
2995             break;
2996
2997       case X_ChangeSaveSet:
2998             ENUM8(save_set_mode);
2999             REQUEST_LENGTH();
3000             WINDOW(window);
3001             break;
3002
3003       case X_ReparentWindow:
3004             UNUSED(1);
3005             REQUEST_LENGTH();
3006             WINDOW(window);
3007             WINDOW(parent);
3008             INT16(x);
3009             INT16(y);
3010             break;
3011
3012       case X_MapWindow:
3013       case X_MapSubwindows:
3014       case X_UnmapWindow:
3015       case X_UnmapSubwindows:
3016             UNUSED(1);
3017             REQUEST_LENGTH();
3018             WINDOW(window);
3019             break;
3020
3021       case X_ConfigureWindow:
3022             UNUSED(1);
3023             REQUEST_LENGTH();
3024             WINDOW(window);
3025             BITMASK16(configure_window);
3026             UNUSED(2);
3027             BITFIELD(INT16,  configure_window_mask, x);
3028             BITFIELD(INT16,  configure_window_mask, y);
3029             BITFIELD(CARD16, configure_window_mask, width);
3030             BITFIELD(CARD16, configure_window_mask, height);
3031             BITFIELD(CARD16, configure_window_mask, border_width);
3032             BITFIELD(WINDOW, configure_window_mask, sibling);
3033             BITFIELD(ENUM8,  configure_window_mask, stack_mode);
3034             ENDBITMASK;
3035             PAD();
3036             break;
3037
3038       case X_CirculateWindow:
3039             ENUM8(direction);
3040             REQUEST_LENGTH();
3041             WINDOW(window);
3042             break;
3043
3044       case X_GetGeometry:
3045       case X_QueryTree:
3046             UNUSED(1);
3047             REQUEST_LENGTH();
3048             DRAWABLE(drawable);
3049             break;
3050
3051       case X_InternAtom:
3052             BOOL(only_if_exists);
3053             REQUEST_LENGTH();
3054             v16 = FIELD16(name_length);
3055             UNUSED(2);
3056             STRING8(name, v16);
3057             PAD();
3058             break;
3059
3060       case X_GetAtomName:
3061             UNUSED(1);
3062             REQUEST_LENGTH();
3063             ATOM(atom);
3064             break;
3065
3066       case X_ChangeProperty:
3067             ENUM8(mode);
3068             REQUEST_LENGTH();
3069             WINDOW(window);
3070             ATOM(property);
3071             ATOM(type);
3072             CARD8(format);
3073             UNUSED(3);
3074             v32 = CARD32(data_length);
3075             LISTofBYTE(data, v32);
3076             PAD();
3077             break;
3078
3079       case X_DeleteProperty:
3080             UNUSED(1);
3081             REQUEST_LENGTH();
3082             WINDOW(window);
3083             ATOM(property);
3084             break;
3085
3086       case X_GetProperty:
3087             BOOL(delete);
3088             REQUEST_LENGTH();
3089             WINDOW(window);
3090             ATOM(property);
3091             ATOM(get_property_type);
3092             CARD32(long_offset);
3093             CARD32(long_length);
3094             break;
3095
3096       case X_ListProperties:
3097             UNUSED(1);
3098             REQUEST_LENGTH();
3099             WINDOW(window);
3100             break;
3101
3102       case X_SetSelectionOwner:
3103             UNUSED(1);
3104             REQUEST_LENGTH();
3105             WINDOW(owner);
3106             ATOM(selection);
3107             TIMESTAMP(time);
3108             break;
3109
3110       case X_GetSelectionOwner:
3111             UNUSED(1);
3112             REQUEST_LENGTH();
3113             ATOM(selection);
3114             break;
3115
3116       case X_ConvertSelection:
3117             UNUSED(1);
3118             REQUEST_LENGTH();
3119             WINDOW(requestor);
3120             ATOM(selection);
3121             ATOM(target);
3122             ATOM(property);
3123             TIMESTAMP(time);
3124             break;
3125
3126       case X_GrabPointer:
3127             BOOL(owner_events);
3128             REQUEST_LENGTH();
3129             WINDOW(grab_window);
3130             SETofPOINTEREVENT(pointer_event_mask);
3131             ENUM8(pointer_mode);
3132             ENUM8(keyboard_mode);
3133             WINDOW(confine_to);
3134             CURSOR(cursor);
3135             TIMESTAMP(time);
3136             break;
3137
3138       case X_UngrabPointer:
3139             UNUSED(1);
3140             REQUEST_LENGTH();
3141             TIMESTAMP(time);
3142             break;
3143
3144       case X_GrabButton:
3145             BOOL(owner_events);
3146             REQUEST_LENGTH();
3147             WINDOW(grab_window);
3148             SETofPOINTEREVENT(event_mask);
3149             ENUM8(pointer_mode);
3150             ENUM8(keyboard_mode);
3151             WINDOW(confine_to);
3152             CURSOR(cursor);
3153             BUTTON(button);
3154             UNUSED(1);
3155             SETofKEYMASK(modifiers);
3156             break;
3157
3158       case X_UngrabButton:
3159             BUTTON(button);
3160             REQUEST_LENGTH();
3161             WINDOW(grab_window);
3162             SETofKEYMASK(modifiers);
3163             UNUSED(2);
3164             break;
3165
3166       case X_ChangeActivePointerGrab:
3167             UNUSED(1);
3168             REQUEST_LENGTH();
3169             CURSOR(cursor);
3170             TIMESTAMP(time);
3171             SETofPOINTEREVENT(event_mask);
3172             UNUSED(2);
3173             break;
3174
3175       case X_GrabKeyboard:
3176             BOOL(owner_events);
3177             REQUEST_LENGTH();
3178             WINDOW(grab_window);
3179             TIMESTAMP(time);
3180             ENUM8(pointer_mode);
3181             ENUM8(keyboard_mode);
3182             UNUSED(2);
3183             break;
3184
3185       case X_UngrabKeyboard:
3186             UNUSED(1);
3187             REQUEST_LENGTH();
3188             TIMESTAMP(time);
3189             break;
3190
3191       case X_GrabKey:
3192             BOOL(owner_events);
3193             REQUEST_LENGTH();
3194             WINDOW(grab_window);
3195             SETofKEYMASK(modifiers);
3196             KEYCODE(key);
3197             ENUM8(pointer_mode);
3198             ENUM8(keyboard_mode);
3199             UNUSED(3);
3200             break;
3201
3202       case X_UngrabKey:
3203             KEYCODE(key);
3204             REQUEST_LENGTH();
3205             WINDOW(grab_window);
3206             SETofKEYMASK(modifiers);
3207             UNUSED(2);
3208             break;
3209
3210       case X_AllowEvents:
3211             ENUM8(allow_events_mode);
3212             REQUEST_LENGTH();
3213             TIMESTAMP(time);
3214             break;
3215
3216       case X_GrabServer:
3217             UNUSED(1);
3218             REQUEST_LENGTH();
3219             break;
3220
3221       case X_UngrabServer:
3222             UNUSED(1);
3223             REQUEST_LENGTH();
3224             break;
3225
3226       case X_QueryPointer:
3227             UNUSED(1);
3228             REQUEST_LENGTH();
3229             WINDOW(window);
3230             break;
3231
3232       case X_GetMotionEvents:
3233             UNUSED(1);
3234             REQUEST_LENGTH();
3235             WINDOW(window);
3236             TIMESTAMP(start);
3237             TIMESTAMP(stop);
3238             break;
3239
3240       case X_TranslateCoords:
3241             UNUSED(1);
3242             REQUEST_LENGTH();
3243             WINDOW(src_window);
3244             WINDOW(dst_window);
3245             INT16(src_x);
3246             INT16(src_y);
3247             break;
3248
3249       case X_WarpPointer:
3250             UNUSED(1);
3251             REQUEST_LENGTH();
3252             WINDOW(warp_pointer_src_window);
3253             WINDOW(warp_pointer_dst_window);
3254             INT16(src_x);
3255             INT16(src_y);
3256             CARD16(src_width);
3257             CARD16(src_height);
3258             INT16(dst_x);
3259             INT16(dst_y);
3260             break;
3261
3262       case X_SetInputFocus:
3263             ENUM8(revert_to);
3264             REQUEST_LENGTH();
3265             WINDOW(focus);
3266             TIMESTAMP(time);
3267             break;
3268
3269       case X_GetInputFocus:
3270             UNUSED(1);
3271             REQUEST_LENGTH();
3272             break;
3273
3274       case X_QueryKeymap:
3275             UNUSED(1);
3276             REQUEST_LENGTH();
3277             break;
3278
3279       case X_OpenFont:
3280             UNUSED(1);
3281             REQUEST_LENGTH();
3282             FONT(fid);
3283             v16 = FIELD16(name_length);
3284             UNUSED(2);
3285             STRING8(name, v16);
3286             PAD();
3287             break;
3288
3289       case X_CloseFont:
3290             UNUSED(1);
3291             REQUEST_LENGTH();
3292             FONT(font);
3293             break;
3294
3295       case X_QueryFont:
3296             UNUSED(1);
3297             REQUEST_LENGTH();
3298             FONTABLE(font);
3299             break;
3300
3301       case X_QueryTextExtents:
3302             v8 = BOOL(odd_length);
3303             REQUEST_LENGTH();
3304             FONTABLE(font);
3305             STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3306             PAD();
3307             break;
3308
3309       case X_ListFonts:
3310             UNUSED(1);
3311             REQUEST_LENGTH();
3312             CARD16(max_names);
3313             v16 = FIELD16(pattern_length);
3314             STRING8(pattern, v16);
3315             PAD();
3316             break;
3317
3318       case X_ListFontsWithInfo:
3319             UNUSED(1);
3320             REQUEST_LENGTH();
3321             CARD16(max_names);
3322             v16 = FIELD16(pattern_length);
3323             STRING8(pattern, v16);
3324             PAD();
3325             break;
3326
3327       case X_SetFontPath:
3328             UNUSED(1);
3329             REQUEST_LENGTH();
3330             v16 = CARD16(str_number_in_path);
3331             UNUSED(2);
3332             LISTofSTRING8(path, v16);
3333             PAD();
3334             break;
3335
3336       case X_GetFontPath:
3337             UNUSED(1);
3338             REQUEST_LENGTH();
3339             break;
3340
3341       case X_CreatePixmap:
3342             CARD8(depth);
3343             REQUEST_LENGTH();
3344             PIXMAP(pid);
3345             DRAWABLE(drawable);
3346             CARD16(width);
3347             CARD16(height);
3348             break;
3349
3350       case X_FreePixmap:
3351             UNUSED(1);
3352             REQUEST_LENGTH();
3353             PIXMAP(pixmap);
3354             break;
3355
3356       case X_CreateGC:
3357             UNUSED(1);
3358             REQUEST_LENGTH();
3359             GCONTEXT(cid);
3360             DRAWABLE(drawable);
3361             gcAttributes(tvb, offsetp, t, little_endian);
3362             break;
3363
3364       case X_ChangeGC:
3365             UNUSED(1);
3366             REQUEST_LENGTH();
3367             GCONTEXT(gc);
3368             gcAttributes(tvb, offsetp, t, little_endian);
3369             break;
3370
3371       case X_CopyGC:
3372             UNUSED(1);
3373             REQUEST_LENGTH();
3374             GCONTEXT(src_gc);
3375             GCONTEXT(dst_gc);
3376             gcMask(tvb, offsetp, t, little_endian);
3377             break;
3378
3379       case X_SetDashes:
3380             UNUSED(1);
3381             REQUEST_LENGTH();
3382             GCONTEXT(gc);
3383             CARD16(dash_offset);
3384             v16 = FIELD16(dashes_length);
3385             LISTofCARD8(dashes, v16);
3386             PAD();
3387             break;
3388
3389       case X_SetClipRectangles:
3390             ENUM8(ordering);
3391             REQUEST_LENGTH();
3392             GCONTEXT(gc);
3393             INT16(clip_x_origin);
3394             INT16(clip_y_origin);
3395             LISTofRECTANGLE(rectangles);
3396             break;
3397
3398       case X_FreeGC:
3399             UNUSED(1);
3400             REQUEST_LENGTH();
3401             GCONTEXT(gc);
3402             break;
3403
3404       case X_ClearArea:
3405             BOOL(exposures);
3406             REQUEST_LENGTH();
3407             WINDOW(window);
3408             INT16(x);
3409             INT16(y);
3410             CARD16(width);
3411             CARD16(height);
3412             break;
3413
3414       case X_CopyArea:
3415             UNUSED(1);
3416             REQUEST_LENGTH();
3417             DRAWABLE(src_drawable);
3418             DRAWABLE(dst_drawable);
3419             GCONTEXT(gc);
3420             INT16(src_x);
3421             INT16(src_y);
3422             INT16(dst_x);
3423             INT16(dst_y);
3424             CARD16(width);
3425             CARD16(height);
3426             break;
3427
3428       case X_CopyPlane:
3429             UNUSED(1);
3430             REQUEST_LENGTH();
3431             DRAWABLE(src_drawable);
3432             DRAWABLE(dst_drawable);
3433             GCONTEXT(gc);
3434             INT16(src_x);
3435             INT16(src_y);
3436             INT16(dst_x);
3437             INT16(dst_y);
3438             CARD16(width);
3439             CARD16(height);
3440             CARD32(bit_plane);
3441             break;
3442
3443       case X_PolyPoint:
3444             ENUM8(coordinate_mode);
3445             v16 = REQUEST_LENGTH();
3446             DRAWABLE(drawable);
3447             GCONTEXT(gc);
3448             LISTofPOINT(points, v16 - 12);
3449             break;
3450
3451       case X_PolyLine:
3452             ENUM8(coordinate_mode);
3453             v16 = REQUEST_LENGTH();
3454             DRAWABLE(drawable);
3455             GCONTEXT(gc);
3456             LISTofPOINT(points, v16 - 12);
3457             break;
3458
3459       case X_PolySegment:
3460             UNUSED(1);
3461             REQUEST_LENGTH();
3462             DRAWABLE(drawable);
3463             GCONTEXT(gc);
3464             LISTofSEGMENT(segments);
3465             break;
3466
3467       case X_PolyRectangle:
3468             UNUSED(1);
3469             REQUEST_LENGTH();
3470             DRAWABLE(drawable);
3471             GCONTEXT(gc);
3472             LISTofRECTANGLE(rectangles);
3473             break;
3474
3475       case X_PolyArc:
3476             UNUSED(1);
3477             REQUEST_LENGTH();
3478             DRAWABLE(drawable);
3479             GCONTEXT(gc);
3480             LISTofARC(arcs);
3481             break;
3482
3483       case X_FillPoly:
3484             UNUSED(1);
3485             v16 = REQUEST_LENGTH();
3486             DRAWABLE(drawable);
3487             GCONTEXT(gc);
3488             ENUM8(shape);
3489             ENUM8(coordinate_mode);
3490             UNUSED(2);
3491             LISTofPOINT(points, v16 - 16);
3492             break;
3493
3494       case X_PolyFillRectangle:
3495             UNUSED(1);
3496             REQUEST_LENGTH();
3497             DRAWABLE(drawable);
3498             GCONTEXT(gc);
3499             LISTofRECTANGLE(rectangles);
3500             break;
3501
3502       case X_PolyFillArc:
3503             UNUSED(1);
3504             REQUEST_LENGTH();
3505             DRAWABLE(drawable);
3506             GCONTEXT(gc);
3507             LISTofARC(arcs);
3508             break;
3509
3510       case X_PutImage:
3511             ENUM8(image_format);
3512             v16 = REQUEST_LENGTH();
3513             DRAWABLE(drawable);
3514             GCONTEXT(gc);
3515             CARD16(width);
3516             CARD16(height);
3517             INT16(dst_x);
3518             INT16(dst_y);
3519             CARD8(left_pad);
3520             CARD8(depth);
3521             UNUSED(2);
3522             LISTofBYTE(data, v16 - 24);
3523             PAD();
3524             break;
3525
3526       case X_GetImage:
3527             ENUM8(image_pixmap_format);
3528             REQUEST_LENGTH();
3529             DRAWABLE(drawable);
3530             INT16(x);
3531             INT16(y);
3532             CARD16(width);
3533             CARD16(height);
3534             CARD32(plane_mask);
3535             break;
3536
3537       case X_PolyText8:
3538             UNUSED(1);
3539             v16 = REQUEST_LENGTH();
3540             DRAWABLE(drawable);
3541             GCONTEXT(gc);
3542             INT16(x);
3543             INT16(y);
3544             LISTofTEXTITEM8(items);
3545             PAD();
3546             break;
3547
3548       case X_PolyText16:
3549             UNUSED(1);
3550             v16 = REQUEST_LENGTH();
3551             DRAWABLE(drawable);
3552             GCONTEXT(gc);
3553             INT16(x);
3554             INT16(y);
3555             LISTofTEXTITEM16(items);
3556             PAD();
3557             break;
3558
3559       case X_ImageText8:
3560             v8 = FIELD8(string_length);
3561             REQUEST_LENGTH();
3562             DRAWABLE(drawable);
3563             GCONTEXT(gc);
3564             INT16(x);
3565             INT16(y);
3566             STRING8(string, v8);
3567             PAD();
3568             break;
3569
3570       case X_ImageText16:
3571             v8 = FIELD8(string_length);
3572             REQUEST_LENGTH();
3573             DRAWABLE(drawable);
3574             GCONTEXT(gc);
3575             INT16(x);
3576             INT16(y);
3577             STRING16(string16, v8);
3578             PAD();
3579             break;
3580
3581       case X_CreateColormap:
3582             ENUM8(alloc);
3583             REQUEST_LENGTH();
3584             COLORMAP(mid);
3585             WINDOW(window);
3586             VISUALID(visual);
3587             break;
3588
3589       case X_FreeColormap:
3590             UNUSED(1);
3591             REQUEST_LENGTH();
3592             COLORMAP(cmap);
3593             break;
3594
3595       case X_CopyColormapAndFree:
3596             UNUSED(1);
3597             REQUEST_LENGTH();
3598             COLORMAP(mid);
3599             COLORMAP(src_cmap);
3600             break;
3601
3602       case X_InstallColormap:
3603             UNUSED(1);
3604             REQUEST_LENGTH();
3605             COLORMAP(cmap);
3606             break;
3607
3608       case X_UninstallColormap:
3609             UNUSED(1);
3610             REQUEST_LENGTH();
3611             COLORMAP(cmap);
3612             break;
3613
3614       case X_ListInstalledColormaps:
3615             UNUSED(1);
3616             REQUEST_LENGTH();
3617             WINDOW(window);
3618             break;
3619
3620       case X_AllocColor:
3621             UNUSED(1);
3622             REQUEST_LENGTH();
3623             COLORMAP(cmap);
3624             CARD16(red);
3625             CARD16(green);
3626             CARD16(blue);
3627             UNUSED(2);
3628             break;
3629
3630       case X_AllocNamedColor:
3631             UNUSED(1);
3632             REQUEST_LENGTH();
3633             COLORMAP(cmap);
3634             v16 = FIELD16(name_length);
3635             UNUSED(2);
3636             STRING8(name, v16);
3637             PAD();
3638             break;
3639
3640       case X_AllocColorCells:
3641             BOOL(contiguous);
3642             REQUEST_LENGTH();
3643             COLORMAP(cmap);
3644             CARD16(colors);
3645             CARD16(planes);
3646             break;
3647
3648       case X_AllocColorPlanes:
3649             BOOL(contiguous);
3650             REQUEST_LENGTH();
3651             COLORMAP(cmap);
3652             CARD16(colors);
3653             CARD16(reds);
3654             CARD16(greens);
3655             CARD16(blues);
3656             break;
3657
3658       case X_FreeColors:
3659             UNUSED(1);
3660             v16 = REQUEST_LENGTH();
3661             COLORMAP(cmap);
3662             CARD32(plane_mask);
3663             LISTofCARD32(pixels, v16 - 12);
3664             break;
3665
3666       case X_StoreColors:
3667             UNUSED(1);
3668             v16 = REQUEST_LENGTH();
3669             COLORMAP(cmap);
3670             LISTofCOLORITEM(color_items, v16 - 8);
3671             break;
3672
3673       case X_StoreNamedColor:
3674             COLOR_FLAGS(color);
3675             REQUEST_LENGTH();
3676             COLORMAP(cmap);
3677             CARD32(pixel);
3678             v16 = FIELD16(name_length);
3679             UNUSED(2);
3680             STRING8(name, v16);
3681             PAD();
3682             break;
3683
3684       case X_QueryColors:
3685             UNUSED(1);
3686             v16 = REQUEST_LENGTH();
3687             COLORMAP(cmap);
3688             LISTofCARD32(pixels, v16 - 8);
3689             break;
3690
3691       case X_LookupColor:
3692             UNUSED(1);
3693             REQUEST_LENGTH();
3694             COLORMAP(cmap);
3695             v16 = FIELD16(name_length);
3696             UNUSED(2);
3697             STRING8(name, v16);
3698             PAD();
3699             break;
3700
3701       case X_CreateCursor:
3702             UNUSED(1);
3703             REQUEST_LENGTH();
3704             CURSOR(cid);
3705             PIXMAP(source_pixmap);
3706             PIXMAP(mask);
3707             CARD16(fore_red);
3708             CARD16(fore_green);
3709             CARD16(fore_blue);
3710             CARD16(back_red);
3711             CARD16(back_green);
3712             CARD16(back_blue);
3713             CARD16(x);
3714             CARD16(y);
3715             break;
3716
3717       case X_CreateGlyphCursor:
3718             UNUSED(1);
3719             REQUEST_LENGTH();
3720             CURSOR(cid);
3721             FONT(source_font);
3722             FONT(mask_font);
3723             CARD16(source_char);
3724             CARD16(mask_char);
3725             CARD16(fore_red);
3726             CARD16(fore_green);
3727             CARD16(fore_blue);
3728             CARD16(back_red);
3729             CARD16(back_green);
3730             CARD16(back_blue);
3731             break;
3732
3733       case X_FreeCursor:
3734             UNUSED(1);
3735             REQUEST_LENGTH();
3736             CURSOR(cursor);
3737             break;
3738
3739       case X_RecolorCursor:
3740             UNUSED(1);
3741             REQUEST_LENGTH();
3742             CURSOR(cursor);
3743             CARD16(fore_red);
3744             CARD16(fore_green);
3745             CARD16(fore_blue);
3746             CARD16(back_red);
3747             CARD16(back_green);
3748             CARD16(back_blue);
3749             break;
3750
3751       case X_QueryBestSize:
3752             ENUM8(class);
3753             REQUEST_LENGTH();
3754             DRAWABLE(drawable);
3755             CARD16(width);
3756             CARD16(height);
3757             break;
3758
3759       case X_QueryExtension:
3760             UNUSED(1);
3761             REQUEST_LENGTH();
3762             v16 = FIELD16(name_length);
3763             UNUSED(2);
3764             STRING8(name, v16);
3765             PAD();
3766             break;
3767
3768       case X_ListExtensions:
3769             UNUSED(1);
3770             REQUEST_LENGTH();
3771             break;
3772
3773       case X_ChangeKeyboardMapping:
3774             v8 = FIELD8(keycode_count);
3775             REQUEST_LENGTH();
3776             v8_2 = KEYCODE(first_keycode);
3777             v8_3 = FIELD8(keysyms_per_keycode);
3778             UNUSED(2);
3779             LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3780             break;
3781
3782       case X_GetKeyboardMapping:
3783             UNUSED(1);
3784             REQUEST_LENGTH();
3785             state->request.GetKeyboardMapping.first_keycode
3786             = KEYCODE(first_keycode);
3787             FIELD8(count);
3788             UNUSED(2);
3789             break;
3790
3791       case X_ChangeKeyboardControl:
3792             UNUSED(1);
3793             REQUEST_LENGTH();
3794             BITMASK32(keyboard_value);
3795             BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3796             BITFIELD(INT8, keyboard_value_mask, bell_percent);
3797             BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3798             BITFIELD(INT16, keyboard_value_mask, bell_duration);
3799             BITFIELD(INT16, keyboard_value_mask, led);
3800             BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3801             BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3802             BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3803             ENDBITMASK;
3804             break;
3805
3806       case X_GetKeyboardControl:
3807             UNUSED(1);
3808             REQUEST_LENGTH();
3809             break;
3810
3811       case X_Bell:
3812             INT8(percent);
3813             REQUEST_LENGTH();
3814             break;
3815
3816       case X_ChangePointerControl:
3817             UNUSED(1);
3818             REQUEST_LENGTH();
3819             INT16(acceleration_numerator);
3820             INT16(acceleration_denominator);
3821             INT16(threshold);
3822             BOOL(do_acceleration);
3823             BOOL(do_threshold);
3824             break;
3825
3826       case X_GetPointerControl:
3827             UNUSED(1);
3828             REQUEST_LENGTH();
3829             break;
3830
3831       case X_SetScreenSaver:
3832             UNUSED(1);
3833             REQUEST_LENGTH();
3834             INT16(timeout);
3835             INT16(interval);
3836             ENUM8(prefer_blanking);
3837             ENUM8(allow_exposures);
3838             UNUSED(2);
3839             break;
3840
3841       case X_GetScreenSaver:
3842             UNUSED(1);
3843             REQUEST_LENGTH();
3844             break;
3845
3846       case X_ChangeHosts:
3847             ENUM8(change_host_mode);
3848             REQUEST_LENGTH();
3849             v8 = ENUM8(family);
3850             UNUSED(1);
3851             v16 = CARD16(address_length);
3852             if (v8 == FAMILY_INTERNET && v16 == 4) {
3853                   /*
3854                    * IPv4 addresses.
3855                    * XXX - what about IPv6?  Is that a family of
3856                    * FAMILY_INTERNET (0) with a length of 16?
3857                    */
3858                   LISTofCARD8(ip_address, v16);
3859             } else
3860                   LISTofCARD8(address, v16);
3861             break;
3862
3863       case X_ListHosts:
3864             UNUSED(1);
3865             REQUEST_LENGTH();
3866             break;
3867
3868       case X_SetAccessControl:
3869             ENUM8(access_mode);
3870             REQUEST_LENGTH();
3871             break;
3872
3873       case X_SetCloseDownMode:
3874             ENUM8(close_down_mode);
3875             REQUEST_LENGTH();
3876             break;
3877
3878       case X_KillClient:
3879             UNUSED(1);
3880             REQUEST_LENGTH();
3881             CARD32(resource);
3882             break;
3883
3884       case X_RotateProperties:
3885             UNUSED(1);
3886             v16 = REQUEST_LENGTH();
3887             WINDOW(window);
3888             CARD16(property_number);
3889             INT16(delta);
3890             LISTofATOM(properties, (v16 - 12));
3891             break;
3892
3893       case X_ForceScreenSaver:
3894             ENUM8(screen_saver_mode);
3895             REQUEST_LENGTH();
3896             break;
3897
3898       case X_SetPointerMapping:
3899             v8 = FIELD8(map_length);
3900             REQUEST_LENGTH();
3901             LISTofCARD8(map, v8);
3902             PAD();
3903             break;
3904
3905       case X_GetPointerMapping:
3906             UNUSED(1);
3907             REQUEST_LENGTH();
3908             break;
3909
3910       case X_SetModifierMapping:
3911             v8 = FIELD8(keycodes_per_modifier);
3912             REQUEST_LENGTH();
3913             LISTofKEYCODE(state->modifiermap, keycodes, v8);
3914             break;
3915
3916       case X_GetModifierMapping:
3917             UNUSED(1);
3918             REQUEST_LENGTH();
3919             break;
3920
3921       case X_NoOperation:
3922             UNUSED(1);
3923             REQUEST_LENGTH();
3924             break;
3925       }
3926
3927       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
3928             UNDECODED(left);
3929 }
3930
3931 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
3932     proto_tree *tree)
3933 {
3934       volatile int offset = 0;
3935       int length_remaining;
3936       volatile gboolean little_endian;
3937       guint8 opcode;
3938       volatile int plen;
3939       proto_item *ti;
3940       proto_tree *t;
3941       volatile gboolean is_initial_creq;
3942       guint16 auth_proto_len, auth_data_len;
3943       const char *volatile sep = NULL;
3944       conversation_t *conversation;
3945       x11_conv_data_t *state;
3946       int length;
3947       tvbuff_t *next_tvb;
3948
3949       while (tvb_reported_length_remaining(tvb, offset) != 0) {
3950             /*
3951              * We use "tvb_ensure_length_remaining()" to make sure there
3952              * actually *is* data remaining.
3953              *
3954              * This means we're guaranteed that "length_remaining" is
3955              * positive.
3956              */
3957             length_remaining = tvb_ensure_length_remaining(tvb, offset);
3958
3959             /*
3960              * Can we do reassembly?
3961              */
3962             if (x11_desegment && pinfo->can_desegment) {
3963                   /*
3964                    * Yes - is the X11 request header split across
3965                    * segment boundaries?
3966                    */
3967                   if (length_remaining < 4) {
3968                         /*
3969                          * Yes.  Tell the TCP dissector where the data
3970                          * for this message starts in the data it handed
3971                          * us, and how many more bytes we need, and return.
3972                          */
3973                         pinfo->desegment_offset = offset;
3974                         pinfo->desegment_len = 4 - length_remaining;
3975                         return;
3976                   }
3977             }
3978
3979             /*
3980              * Get the state for this conversation; create the conversation
3981              * if we don't have one, and create the state if we don't have
3982              * any.
3983              */
3984             conversation = find_conversation(&pinfo->src, &pinfo->dst,
3985                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
3986             if (conversation == NULL) {
3987                   /*
3988                    * No - create one.
3989                    */
3990                   conversation = conversation_new(&pinfo->src,
3991                         &pinfo->dst, pinfo->ptype, pinfo->srcport,
3992                         pinfo->destport, 0);
3993             }
3994
3995             /*
3996              * Is there state attached to this conversation?
3997              */
3998             if ((state = conversation_get_proto_data(conversation, proto_x11))
3999             == NULL)
4000                 x11_stateinit(&state, conversation);
4001
4002             /*
4003              * Guess the byte order if we don't already know it.
4004              */
4005             little_endian = guess_byte_ordering(tvb, pinfo, state);
4006
4007             /*
4008              * Get the opcode and length of the putative X11 request.
4009              */
4010             opcode = VALUE8(tvb, 0);
4011             plen = VALUE16(tvb, offset + 2);
4012
4013             if (plen == 0) {
4014                   /*
4015                    * This can't be 0, as it includes the header length.
4016                    * A different choice of byte order wouldn't have
4017                    * helped.
4018                    * Give up.
4019                    */
4020                   ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4021                   FALSE);
4022                   t = proto_item_add_subtree(ti, ett_x11);
4023                   proto_tree_add_text(t, tvb, offset, -1,
4024                   "Bogus request length (0)");
4025                   return;
4026             }
4027
4028             if (state->iconn_frame == pinfo->fd->num ||
4029                 (g_hash_table_lookup(state->seqtable,
4030                 (int *)state->sequencenumber) == (int *)NOTHING_SEEN &&
4031                  (opcode == 'B' || opcode == 'l') &&
4032                  (plen == 11 || plen == 2816))) {
4033                   /*
4034                    * Either
4035                    *
4036                    *    we saw this on the first pass and this is
4037                    *    it again
4038                    *
4039                    * or
4040                    *    we haven't already seen any requests, the first
4041                    *    byte of the message is 'B' or 'l', and the 16-bit
4042                    *    integer 2 bytes into the data stream is either 11
4043                    *    or a byte-swapped 11.
4044                    *
4045                    * This means it's probably an initial connection
4046                    * request, not a message.
4047                    *
4048                    * 'B' is decimal 66, which is the opcode for a
4049                    * PolySegment request; unfortunately, 11 is a valid
4050                    * length for a PolySegment request request, so we
4051                    * might mis-identify that request.  (Are there any
4052                    * other checks we can do?)
4053                    *
4054                    * 'l' is decimal 108, which is the opcode for a
4055                    * GetScreenSaver request; the only valid length
4056                    * for that request is 1.
4057                    */
4058                   is_initial_creq = TRUE;
4059
4060                   /*
4061                    * We now know the byte order.  Override the guess.
4062                    */
4063                   if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4064                         if (opcode == 'B') {
4065                               /*
4066                                * Big-endian.
4067                                */
4068                               state->byte_order = BYTE_ORDER_BE;
4069                               little_endian = FALSE;
4070                         } else {
4071                               /*
4072                                * Little-endian.
4073                                */
4074                               state->byte_order = BYTE_ORDER_LE;
4075                               little_endian = TRUE;
4076                         }
4077                   }
4078
4079                   /*
4080                    * Can we do reassembly?
4081                    */
4082                   if (x11_desegment && pinfo->can_desegment) {
4083                         /*
4084                          * Yes - is the fixed-length portion of the
4085                          * initial connection header split across
4086                          * segment boundaries?
4087                          */
4088                         if (length_remaining < 10) {
4089                               /*
4090                                * Yes.  Tell the TCP dissector where the
4091                                * data for this message starts in the data
4092                                * it handed us, and how many more bytes we
4093                                * need, and return.
4094                                */
4095                               pinfo->desegment_offset = offset;
4096                               pinfo->desegment_len = 10 - length_remaining;
4097                               return;
4098                         }
4099                   }
4100
4101                   /*
4102                    * Get the lengths of the authorization protocol and
4103                    * the authorization data.
4104                    */
4105                   auth_proto_len = VALUE16(tvb, offset + 6);
4106                   auth_data_len = VALUE16(tvb, offset + 8);
4107                   plen = 12 + ROUND_LENGTH(auth_proto_len) +
4108                         ROUND_LENGTH(auth_data_len);
4109             } else {
4110                   /*
4111                    * This is probably an ordinary request.
4112                    */
4113                   is_initial_creq = FALSE;
4114
4115                   /*
4116                    * The length of a request is in 4-byte words.
4117                    */
4118                   plen *= 4;
4119             }
4120
4121             /*
4122              * Can we do reassembly?
4123              */
4124             if (x11_desegment && pinfo->can_desegment) {
4125                   /*
4126                    * Yes - is the X11 request split across segment
4127                    * boundaries?
4128                    */
4129                   if (length_remaining < plen) {
4130                         /*
4131                          * Yes.  Tell the TCP dissector where the data
4132                          * for this message starts in the data it handed
4133                          * us, and how many more bytes we need, and return.
4134                          */
4135                         pinfo->desegment_offset = offset;
4136                         pinfo->desegment_len = plen - length_remaining;
4137                         return;
4138                   }
4139             }
4140
4141             /*
4142              * Construct a tvbuff containing the amount of the payload
4143              * we have available.  Make its reported length the
4144              * amount of data in the X11 request.
4145              *
4146              * XXX - if reassembly isn't enabled. the subdissector
4147              * will throw a BoundsError exception, rather than a
4148              * ReportedBoundsError exception.  We really want a tvbuff
4149              * where the length is "length", the reported length is "plen",
4150              * and the "if the snapshot length were infinite" length is the
4151              * minimum of the reported length of the tvbuff handed to us
4152              * and "plen", with a new type of exception thrown if the offset
4153              * is within the reported length but beyond that third length,
4154              * with that exception getting the "Unreassembled Packet" error.
4155              */
4156             length = length_remaining;
4157             if (length > plen)
4158                   length = plen;
4159             next_tvb = tvb_new_subset(tvb, offset, length, plen);
4160
4161             /*
4162              * Set the column appropriately.
4163              */
4164             if (is_initial_creq) {
4165                   if (check_col(pinfo->cinfo, COL_INFO))
4166                         col_set_str(pinfo->cinfo, COL_INFO,
4167                         "Initial connection request");
4168             } else {
4169                   if (sep == NULL) {
4170                         /*
4171                          * We haven't set the column yet; set it.
4172                          */
4173                         if (check_col(pinfo->cinfo, COL_INFO))
4174                               col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4175
4176                         /*
4177                          * Initialize the separator.
4178                          */
4179                         sep = ":";
4180                   }
4181             }
4182
4183             /*
4184              * Dissect the X11 request.
4185              *
4186              * Catch the ReportedBoundsError exception; if this
4187              * particular message happens to get a ReportedBoundsError
4188              * exception, that doesn't mean that we should stop
4189              * dissecting X11 requests within this frame or chunk of
4190              * reassembled data.
4191              *
4192              * If it gets a BoundsError, we can stop, as there's nothing
4193              * more to see, so we just re-throw it.
4194              */
4195             TRY {
4196                   if (is_initial_creq) {
4197                         dissect_x11_initial_conn(next_tvb, pinfo, tree,
4198                             state, little_endian);
4199                   } else {
4200                         dissect_x11_request(next_tvb, pinfo, tree, sep,
4201                             state, little_endian);
4202                   }
4203             }
4204             CATCH(BoundsError) {
4205                   RETHROW;
4206             }
4207             CATCH(ReportedBoundsError) {
4208                   show_reported_bounds_error(tvb, pinfo, tree);
4209             }
4210             ENDTRY;
4211
4212             /*
4213              * Skip the X11 message.
4214              */
4215             offset += plen;
4216
4217             sep = ",";
4218       }
4219 }
4220
4221 static void
4222 x11_stateinit(x11_conv_data_t **state, conversation_t *conversation)
4223 {
4224         static x11_conv_data_t stateinit;
4225
4226         *state = g_mem_chunk_alloc(x11_state_chunk);
4227         **state = stateinit; 
4228
4229         (*state)->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4230         g_hash_table_insert((*state)->seqtable, (int *)0, (int *)NOTHING_SEEN);
4231         (*state)->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4232         conversation_add_proto_data(conversation, proto_x11, *state);
4233 }
4234
4235
4236 static void
4237 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4238 {
4239 /* Set up structures we will need to add the protocol subtree and manage it */
4240         volatile int offset, plen;
4241         tvbuff_t * volatile next_tvb;
4242         conversation_t *conversation;
4243         x11_conv_data_t *state;
4244         gboolean little_endian;
4245         int length_remaining;
4246         const char *volatile sep = NULL;
4247
4248
4249         /*
4250         * Get the state for this conversation; create the conversation
4251         * if we don't have one, and create the state if we don't have
4252         * any.
4253         */
4254         conversation = find_conversation(&pinfo->src, &pinfo->dst,
4255         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4256         if (conversation == NULL) {
4257                 /*
4258                  * No - create one.
4259                 */
4260                 conversation = conversation_new(&pinfo->src, &pinfo->dst,
4261                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4262         }
4263
4264         /*
4265          * Is there state attached to this conversation?
4266         */
4267         if ((state = conversation_get_proto_data(conversation, proto_x11))
4268         == NULL) {
4269                 /*
4270                  * No - create a state structure and attach it.
4271                  */
4272                 x11_stateinit(&state, conversation);
4273         }
4274
4275         /*
4276          * Guess the byte order if we don't already know it.
4277          */
4278         little_endian = guess_byte_ordering(tvb, pinfo, state);
4279
4280         offset = 0;
4281         while (tvb_reported_length_remaining(tvb, offset) != 0) {
4282                 /*
4283                  * We use "tvb_ensure_length_remaining()" to make sure there
4284                  * actually *is* data remaining.
4285                  *
4286                  * This means we're guaranteed that "length_remaining" is
4287                  * positive.
4288                  */
4289                 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4290
4291                 /*
4292                 * Can we do reassembly?
4293                 */
4294                 if (x11_desegment && pinfo->can_desegment) {
4295                           /*
4296                            * Yes - is the X11 reply header split across
4297                            * segment boundaries?
4298                            */
4299                           if (length_remaining < 8) {
4300                                 /*
4301                                  * Yes.  Tell the TCP dissector where the data
4302                                  * for this message starts in the data it handed
4303                                  * us, and how many more bytes we need, and
4304                                  * return.
4305                                  */
4306                                 pinfo->desegment_offset = offset;
4307                                 pinfo->desegment_len = 4 - length_remaining;
4308                                 return;
4309                         }
4310                 }
4311
4312                 /*
4313                  * Find out what kind of a reply it is.
4314                  * There are four possible:
4315                  *      - reply to initial connection
4316                  *      - errorreply (a request generated an error)
4317                  *      - requestreply (reply to a request)
4318                  *      - event (some event occured)
4319                  */
4320                 if (g_hash_table_lookup(state->seqtable,
4321                     (int *)state->sequencenumber) == (int *)INITIAL_CONN 
4322                     || (state->iconn_reply == pinfo->fd->num)) {
4323                         /*
4324                          * Either the connection is in the "initial
4325                          * connection" state, or this frame is known
4326                          * to have the initial connection reply.
4327                          * That means this is the initial connection
4328                          * reply.
4329                          */
4330                         plen = 8 + VALUE16(tvb, offset + 6) * 4;
4331
4332                         HANDLE_REPLY(plen, length_remaining,
4333                             "Initial connection reply", 
4334                             dissect_x11_initial_reply); 
4335                 } else {
4336                         /*
4337                          * This isn't an initial connection reply
4338                          * (XXX - unless we missed the initial
4339                          * connection request).  Look at the first
4340                          * byte to determine what it is; errors
4341                          * start with a byte of 0, replies start
4342                          * with a byte of 1, events start with
4343                          * a byte with of 2 or greater.
4344                          */
4345                         switch (tvb_get_guint8(tvb, offset)) {
4346
4347                         case 0:
4348                                 plen = 32;
4349                                 HANDLE_REPLY(plen, length_remaining,
4350                                     "Error", dissect_x11_error); 
4351                                 break;
4352
4353                         case 1:
4354                                 /* replylength is in units of four. */
4355                                 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4356
4357                                 HANDLE_REPLY(plen, length_remaining,
4358                                     "Reply", dissect_x11_reply); 
4359                                 break;
4360
4361                         default:
4362                                 /* Event */
4363                                 plen = 32;
4364                                 HANDLE_REPLY(plen, length_remaining,
4365                                     "Event", dissect_x11_event);
4366                                 break;
4367                         }
4368                 }
4369
4370                 offset += plen;
4371         }
4372
4373         return;
4374 }
4375
4376 static void
4377 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4378                   const char *volatile sep, x11_conv_data_t *volatile state,
4379                   gboolean little_endian)
4380 {
4381         int offset = 0, *offsetp = &offset, length, left, opcode;
4382         proto_item *ti;
4383         proto_tree *t;
4384         
4385         ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4386                                  tvb_reported_length_remaining(tvb, offset),
4387                                  FALSE);
4388         t = proto_item_add_subtree(ti, ett_x11);
4389
4390
4391         /*
4392          * XXX - this doesn't work correctly if either
4393          *
4394          *      1) the request sequence number wraps in the lower 16
4395          *         bits;
4396          *
4397          *      2) we don't see the initial connection request and thus
4398          *         don't have the right sequence numbers;
4399          *
4400          *      3) we don't have all the packets in the capture and
4401          *         get out of sequence.
4402          *
4403          * We might, instead, want to assume that a reply is a reply to
4404          * the most recent not-already-replied-to request in the same
4405          * connection.  That also might mismatch replies to requests if
4406          * packets are lost, but there's nothing you can do to fix that.
4407          *
4408          * XXX - if "opcode" is 0, we shouldn't say "Unknown opcode",
4409          * we should say that we don't have the request for the reply.
4410          */
4411         opcode = (int)g_hash_table_lookup(state->seqtable,
4412         (int *)VALUE16(tvb, offset + 2));
4413
4414         if (check_col(pinfo->cinfo, COL_INFO))
4415                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4416                                 sep,
4417                                 /* 
4418                                  * don't print opcode value since if it's
4419                                  * unknown, we didn't know to save the
4420                                  * request opcode.
4421                                  */
4422                                 val_to_str(opcode, opcode_vals, "<Unknown opcode %d>"));
4423
4424         proto_item_append_text(ti, ", Reply, opcode: %d (%s)", 
4425                               opcode, val_to_str(opcode, opcode_vals,
4426                               "<Unknown opcode %d>"));
4427
4428         if (tree == NULL)
4429                 return; 
4430
4431         switch (opcode) {
4432                 /*
4433                  * Requests that expect a reply.
4434                 */
4435
4436                 case X_GetWindowAttributes:
4437                 case X_GetGeometry:
4438                 case X_QueryTree:
4439                 case X_InternAtom:
4440                 case X_GetAtomName:
4441                         REPLYCONTENTS_COMMON();
4442                         break; 
4443
4444                 case X_GetProperty:
4445                         REPLY(reply);
4446                         CARD8(format);
4447                         SEQUENCENUMBER_REPLY(sequencenumber);
4448                         length = REPLYLENGTH(replylength);
4449                         ATOM(get_property_type);
4450                         CARD32(bytes_after);
4451                         CARD32(valuelength);
4452                         UNUSED(12);
4453                         break;
4454
4455                 case X_ListProperties:
4456                 case X_GetSelectionOwner:
4457                 case X_GrabPointer:
4458                 case X_GrabKeyboard:
4459                 case X_QueryPointer:
4460                 case X_GetMotionEvents:
4461                 case X_TranslateCoords:
4462                         REPLYCONTENTS_COMMON();
4463                         break; 
4464
4465                 case X_QueryKeymap:
4466                 case X_QueryFont:
4467                 case X_QueryTextExtents:
4468                 case X_ListFonts:
4469                 case X_GetImage:
4470                 case X_ListInstalledColormaps:
4471                 case X_AllocColor:
4472                 case X_QueryColors:
4473                 case X_LookupColor:
4474                 case X_QueryBestSize:
4475                 case X_QueryExtension:
4476                 case X_ListExtensions:
4477                         REPLYCONTENTS_COMMON();
4478                         break; 
4479
4480                 case X_GetKeyboardMapping:
4481                         state->first_keycode
4482                         = state->request.GetKeyboardMapping.first_keycode, 
4483                         REPLY(reply);
4484                         state->keysyms_per_keycode
4485                         = FIELD8(keysyms_per_keycode);
4486                         SEQUENCENUMBER_REPLY(sequencenumber);
4487                         length = REPLYLENGTH(replylength);
4488                         UNUSED(24);
4489                         LISTofKEYSYM(keysyms, state->keycodemap,
4490                         state->request.GetKeyboardMapping.first_keycode, 
4491                         length / state->keysyms_per_keycode,
4492                         state->keysyms_per_keycode);
4493                         break; 
4494
4495                 case X_GetKeyboardControl:
4496                 case X_GetPointerControl:
4497                 case X_GetScreenSaver:
4498                 case X_ListHosts:
4499                 case X_SetPointerMapping:
4500                 case X_GetPointerMapping:
4501                 case X_SetModifierMapping:
4502                         REPLYCONTENTS_COMMON();
4503                         break; 
4504
4505                 case X_GetModifierMapping:
4506                         REPLY(reply);
4507                         state->keycodes_per_modifier
4508                         = FIELD8(keycodes_per_modifier);
4509                         SEQUENCENUMBER_REPLY(sequencenumber);
4510                         REPLYLENGTH(replylength);
4511                         UNUSED(24);
4512                         LISTofKEYCODE(state->modifiermap, keycodes,
4513                         state->keycodes_per_modifier);
4514                         break; 
4515
4516                 default:
4517                         REPLYCONTENTS_COMMON();
4518         }
4519
4520         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4521             UNDECODED(left);
4522 }
4523
4524 static void
4525 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4526                   const char *volatile sep, x11_conv_data_t *volatile state,
4527                   gboolean little_endian)
4528 {
4529         int offset = 0, *offsetp = &offset, left;
4530         unsigned char eventcode;
4531         proto_item *ti;
4532         proto_tree *t;
4533
4534         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4535         t = proto_item_add_subtree(ti, ett_x11);
4536
4537         eventcode = tvb_get_guint8(tvb, offset);
4538
4539         if (check_col(pinfo->cinfo, COL_INFO))
4540                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4541                                 sep, val_to_str(eventcode, eventcode_vals,
4542                                 "<Unknown eventcode %u>"));
4543
4544         proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4545                                    eventcode, 
4546                                    "eventcode: %d (%s)",
4547                                    eventcode, 
4548                                    val_to_str(eventcode, eventcode_vals,
4549                                    "<Unknown eventcode %u>"));
4550         ++offset;
4551
4552         proto_item_append_text(ti, ", Event, eventcode: %d (%s)", 
4553                               eventcode, val_to_str(eventcode, eventcode_vals,
4554                               "<Unknown eventcode %u>"));
4555
4556         if (tree == NULL)
4557                 return; 
4558
4559         switch (eventcode) {
4560                 case KeyPress:
4561                 case KeyRelease: {
4562                         int code, mask;
4563
4564                         /* need to do some prefetching here ... */
4565                         code = VALUE8(tvb, offset);
4566                         mask = VALUE16(tvb, 28);
4567
4568                         KEYCODE_DECODED(keycode, code, mask);
4569                         CARD16(event_sequencenumber);
4570                         EVENTCONTENTS_COMMON();
4571                         BOOL(same_screen);
4572                         UNUSED(1);
4573                         break;
4574                 }
4575
4576                 case ButtonPress:
4577                 case ButtonRelease:
4578                         BUTTON(eventbutton);
4579                         CARD16(event_sequencenumber);
4580                         EVENTCONTENTS_COMMON();
4581                         BOOL(same_screen);
4582                         UNUSED(1);
4583                         break;
4584
4585                 case MotionNotify:
4586                         CARD8(detail);
4587                         CARD16(event_sequencenumber);
4588                         EVENTCONTENTS_COMMON();
4589                         BOOL(same_screen);
4590                         UNUSED(1);
4591                         break;
4592
4593                 case EnterNotify:
4594                 case LeaveNotify:
4595                         CARD8(detail);
4596                         CARD16(event_sequencenumber);
4597                         EVENTCONTENTS_COMMON();
4598                         CARD8(same_screen);
4599                         break;
4600
4601                 case FocusIn:
4602                 case FocusOut:
4603                 case KeymapNotify:
4604                 case Expose:
4605                 case GraphicsExpose:
4606                 case NoExpose:
4607                 case VisibilityNotify:
4608                 case CreateNotify:
4609                 case DestroyNotify:
4610                 case UnmapNotify:
4611                 case MapNotify:
4612                 case MapRequest:
4613                 case ReparentNotify:
4614                 case ConfigureNotify:
4615                 case ConfigureRequest:
4616                 case GravityNotify:
4617                 case ResizeRequest:
4618                 case CirculateNotify:
4619                 case CirculateRequest:
4620                 case PropertyNotify:
4621                 case SelectionClear:
4622                 case SelectionRequest:
4623                 case SelectionNotify:
4624                 case ColormapNotify:
4625                 case ClientMessage:
4626                 case MappingNotify:
4627                 default:
4628                         break;
4629         }
4630
4631         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0) 
4632             UNDECODED(left);
4633
4634         return;
4635 }
4636
4637 static void
4638 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4639                   const char *volatile sep, x11_conv_data_t *volatile state _U_,
4640                   gboolean little_endian)
4641 {
4642         int offset = 0, *offsetp = &offset, left;
4643         unsigned char errorcode, error;
4644         proto_item *ti;
4645         proto_tree *t;
4646
4647         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4648         t = proto_item_add_subtree(ti, ett_x11);
4649
4650         error = tvb_get_guint8(tvb, offset);
4651         CARD8(error);
4652
4653         errorcode = tvb_get_guint8(tvb, offset);
4654         if (check_col(pinfo->cinfo, COL_INFO))
4655                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4656                 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
4657
4658         proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
4659                                    errorcode, 
4660                                    "errorcode: %d (%s)",
4661                                    errorcode, 
4662                                    val_to_str(errorcode, errorcode_vals,
4663                                    "<Unknown errocode %u>"));
4664         ++offset;
4665
4666         proto_item_append_text(ti, ", Error, errorcode: %d (%s)", 
4667                               errorcode, val_to_str(errorcode, errorcode_vals,
4668                               "<Unknown errorcode %u>"));
4669
4670         if (tree == NULL)
4671                 return; 
4672
4673         CARD16(error_sequencenumber);
4674
4675         switch (errorcode) {
4676                 case BadValue:
4677                         CARD32(error_badvalue);
4678                         break;
4679
4680                 default:
4681                         UNDECODED(4);
4682         }
4683
4684         CARD16(minor_opcode);
4685         CARD8(major_opcode);
4686
4687         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4688             UNDECODED(left);
4689 }
4690
4691                         
4692
4693 /************************************************************************
4694  ***                                                                  ***
4695  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
4696  ***                                                                  ***
4697  ************************************************************************/
4698
4699 static void
4700 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4701 {
4702         if (check_col(pinfo->cinfo, COL_PROTOCOL))
4703                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
4704
4705         if (pinfo->match_port == pinfo->srcport)
4706                 dissect_x11_replies(tvb, pinfo, tree);
4707         else
4708                 dissect_x11_requests(tvb, pinfo, tree);
4709 }
4710
4711 /* Register the protocol with Ethereal */
4712 void proto_register_x11(void)
4713 {
4714
4715 /* Setup list of header fields */
4716       static hf_register_info hf[] = {
4717 /*
4718   { &hf_x11_FIELDABBREV,
4719   { "FIELDNAME",           "x11.FIELDABBREV",
4720   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,
4721   "FIELDDESCR", HFILL }
4722   },
4723 */
4724 #include "x11-register-info.h"
4725       };
4726
4727 /* Setup protocol subtree array */
4728       static gint *ett[] = {
4729             &ett_x11,
4730             &ett_x11_color_flags,
4731             &ett_x11_list_of_arc,
4732             &ett_x11_arc,
4733             &ett_x11_list_of_atom,
4734             &ett_x11_list_of_card32,
4735             &ett_x11_list_of_color_item,
4736             &ett_x11_color_item,
4737             &ett_x11_list_of_keycode,
4738             &ett_x11_list_of_keysyms,
4739             &ett_x11_keysym,
4740             &ett_x11_list_of_point,
4741             &ett_x11_point,
4742             &ett_x11_list_of_rectangle,
4743             &ett_x11_rectangle,
4744             &ett_x11_list_of_segment,
4745             &ett_x11_segment,
4746             &ett_x11_list_of_string8,
4747             &ett_x11_list_of_text_item,
4748             &ett_x11_text_item,
4749             &ett_x11_gc_value_mask,
4750             &ett_x11_event_mask,
4751             &ett_x11_do_not_propagate_mask,
4752             &ett_x11_set_of_key_mask,
4753             &ett_x11_pointer_event_mask,
4754             &ett_x11_window_value_mask,
4755             &ett_x11_configure_window_mask,
4756             &ett_x11_keyboard_value_mask,
4757       };
4758       module_t *x11_module;
4759
4760 /* Register the protocol name and description */
4761       proto_x11 = proto_register_protocol("X11", "X11", "x11");
4762
4763 /* Required function calls to register the header fields and subtrees used */
4764       proto_register_field_array(proto_x11, hf, array_length(hf));
4765       proto_register_subtree_array(ett, array_length(ett));
4766
4767       register_init_routine(x11_init_protocol);
4768
4769       x11_module = prefs_register_protocol(proto_x11, NULL);
4770       prefs_register_bool_preference(x11_module, "desegment",
4771             "Desegment all X11 messages spanning multiple TCP segments",
4772             "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
4773             &x11_desegment);
4774 }
4775
4776 void
4777 proto_reg_handoff_x11(void)
4778 {
4779   dissector_handle_t x11_handle;
4780
4781   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
4782   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
4783   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
4784   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
4785   data_handle = find_dissector("data");
4786 }
4787