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