packet-x11.c(1780) : warning C4090: 'function' : different 'const' qualifiers
[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  * Ethereal - Network traffic analyzer
9  * By Gerald Combs <gerald@ethereal.com>
10  * Copyright 1998 Gerald Combs
11  *
12  * Copied from README.developer
13  *
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /* TODO (in no particular order):
30  *
31  * - keep track of Atom creation by server to be able to display
32  *   non-predefined atoms
33  * - Idem for keysym <-> keycode ???
34  * - Idem for fonts
35  * - Subtree the request ids (that is x11.create-window.window and
36  *   x11.change-window.window should be  distinct), and add hidden fields
37  *   (so we still have x11.window).
38  * - add hidden fields so we can have x11.circulate-window in addition to
39  *   x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
40  *   now)
41  * - add hidden fields so we have x11.listOfStuff.length
42  * - use a faster scheme that linear list searching for the opcode.
43  * - correct display of Unicode chars.
44  * - Not everything is homogeneous, in particular the handling of items in
45  *   list is a total mess.
46  */
47
48 /* By the way, I wrote a program to generate every request and test
49  * that stuff. If you're interested, you can get it at
50  * http://tronche.com/gui/x/
51  */
52
53 #ifdef HAVE_CONFIG_H
54 # include "config.h"
55 #endif
56
57 #include <assert.h>
58 #include <ctype.h>
59 #include <stdio.h>
60 #include <stdlib.h>
61
62 #include <string.h>
63 #include <glib.h>
64 #include <epan/packet.h>
65 #include <epan/conversation.h>
66
67 #include <epan/prefs.h>
68 #include "packet-frame.h"
69 #include "packet-x11-keysymdef.h"
70
71 #define cVALS(x) (const value_string*)(x)
72
73 /*
74  * Data structure associated with a conversation; keeps track of the
75  * request for which we're expecting a reply, the frame number of
76  * the initial connection request, and the byte order of the connection.
77  *
78  * An opcode of -3 means we haven't yet seen any requests yet.
79  * An opcode of -2 means we're not expecting a reply (unused).
80  * An opcode of -1 means we're waiting for a reply to the initial
81  * connection request.
82  * An opcode of 0  means the request was not seen (or unknown).
83  * Other values are the opcode of the request for which we're expecting
84  * a reply.
85  *
86  */
87 #define NOTHING_SEEN            -3
88 #define NOTHING_EXPECTED        -2
89 #define INITIAL_CONN            -1
90 #define UNKNOWN_OPCODE           0
91
92 #define MAX_OPCODES             (255 + 1) /* 255 + INITIAL_CONN */
93
94 #define BYTE_ORDER_BE           0
95 #define BYTE_ORDER_LE           1
96 #define BYTE_ORDER_UNKNOWN      -1
97
98 static const char *modifiers[] = {
99     "Shift",
100     "Lock",
101     "Control",
102     "Mod1",
103     "Mod2",
104     "Mod3",
105     "Mod4",
106     "Mod5"
107 };
108
109 /* Keymasks.  From <X11/X.h>. */
110 #define ShiftMask               (1<<0)
111 #define LockMask                (1<<1)
112 #define ControlMask             (1<<2)
113 #define Mod1Mask                (1<<3)
114 #define Mod2Mask                (1<<4)
115 #define Mod3Mask                (1<<5)
116 #define Mod4Mask                (1<<6)
117 #define Mod5Mask                (1<<7)
118
119 static const int modifiermask[] = { ShiftMask, LockMask, ControlMask,
120 Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
121
122 /* from <X11/X.h> */
123 #define NoSymbol             0L /* special KeySym */
124
125 typedef struct _x11_conv_data {
126       struct _x11_conv_data *next;
127       GHashTable *seqtable;     /* hashtable of sequencenumber <-> opcode. */
128       GHashTable *valtable;/* hashtable of sequencenumber <-> &opcode_vals */
129       /* major opcodes including extensions (NULL terminated) */
130       value_string opcode_vals[MAX_OPCODES+1]; 
131       int       sequencenumber; /* sequencenumber of current packet.       */
132       guint32   iconn_frame;    /* frame # of initial connection request   */
133       guint32   iconn_reply;    /* frame # of initial connection reply     */
134       int       byte_order;     /* byte order of connection */
135       gboolean  resync;  /* resynchronization of sequence number performed */
136
137       int       *keycodemap[256]; /* keycode to keysymvalue map. */
138       int       keysyms_per_keycode;
139       int       first_keycode;
140       int       *modifiermap[array_length(modifiers)];/* modifier to keycode.*/
141       int       keycodes_per_modifier;
142
143       union {
144         struct {
145                 int     first_keycode;
146         } GetKeyboardMapping;
147       } request;
148 } x11_conv_data_t;
149
150 static GMemChunk *x11_state_chunk = NULL;
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[512];
1312             char *bp = buffer + sprintf(buffer, "flags: ");
1313
1314             if (do_red_green_blue & 0x1) {
1315                   bp += sprintf(bp, "DoRed");
1316                   sep = TRUE;
1317             }
1318
1319             if (do_red_green_blue & 0x2) {
1320                   if (sep) bp += sprintf(bp, " | ");
1321                   bp += sprintf(bp, "DoGreen");
1322                   sep = TRUE;
1323             }
1324
1325             if (do_red_green_blue & 0x4) {
1326                   if (sep) bp += sprintf(bp, " | ");
1327                   bp += sprintf(bp, "DoBlue");
1328                   sep = TRUE;
1329             }
1330
1331             if (do_red_green_blue & 0xf8) {
1332                   if (sep) bp += sprintf(bp, " + ");
1333                   sprintf(bp, "trash");
1334             }
1335
1336             ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1337                                             "%s", buffer);
1338             tt = proto_item_add_subtree(ti, ett_x11_color_flags);
1339             if (do_red_green_blue & 0x1)
1340                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1,
1341                                          do_red_green_blue & 0x1);
1342             if (do_red_green_blue & 0x2)
1343                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1,
1344                                          do_red_green_blue & 0x2);
1345             if (do_red_green_blue & 0x4)
1346                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1,
1347                                          do_red_green_blue & 0x4);
1348             if (do_red_green_blue & 0xf8)
1349                   proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1,
1350                                          do_red_green_blue & 0xf8);
1351       } else
1352             proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
1353                                        "flags: none");
1354       *offsetp += 1;
1355 }
1356
1357 static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
1358     int hf, const char *nullInterpretation)
1359 {
1360       guint8 v = VALUE8(tvb, *offsetp);
1361
1362       if (!v)
1363             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)",
1364                                        proto_registrar_get_nth(hf) -> name,
1365                                        nullInterpretation);
1366       else
1367             proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
1368       *offsetp += 1;
1369 }
1370
1371 static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1372                       int length, gboolean little_endian)
1373 {
1374       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1375       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
1376       while(length--) {
1377             gint16 x = VALUE16(tvb, *offsetp);
1378             gint16 y = VALUE16(tvb, *offsetp + 2);
1379             guint16 width = VALUE16(tvb, *offsetp + 4);
1380             guint16 height = VALUE16(tvb, *offsetp + 6);
1381             gint16 angle1 = VALUE16(tvb, *offsetp + 8);
1382             gint16 angle2 = VALUE16(tvb, *offsetp + 10);
1383
1384             proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12,
1385                                                              "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
1386                                                              width, height, x, y, angle1, angle2,
1387                                                              angle1 / 64.0, angle2 / 64.0);
1388             proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
1389             proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
1390             *offsetp += 2;
1391             proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
1392             *offsetp += 2;
1393             proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
1394             *offsetp += 2;
1395             proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
1396             *offsetp += 2;
1397             proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
1398             *offsetp += 2;
1399             proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
1400             *offsetp += 2;
1401       }
1402 }
1403
1404 static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1405                        int length, gboolean little_endian)
1406 {
1407       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1408       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
1409       while(length--)
1410             atom(tvb, offsetp, tt, hf_x11_properties_item, little_endian);
1411 }
1412
1413 static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1414                        int length, gboolean little_endian)
1415 {
1416       if (length <= 0) length = 1;
1417       proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
1418       *offsetp += length;
1419 }
1420
1421 static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1422                          int hf_item, int length, gboolean little_endian)
1423 {
1424       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1425       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
1426       while(length--) {
1427             proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
1428             *offsetp += 4;
1429       }
1430 }
1431
1432 static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1433                             int length, gboolean little_endian)
1434 {
1435       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1436       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
1437       while(length--) {
1438             proto_item *tti;
1439             proto_tree *ttt;
1440             unsigned do_red_green_blue;
1441             guint16 red, green, blue;
1442             char buffer[1024];
1443             char *bp;
1444             const char *sep;
1445
1446             red = VALUE16(tvb, *offsetp + 4);
1447             green = VALUE16(tvb, *offsetp + 6);
1448             blue = VALUE16(tvb, *offsetp + 8);
1449             do_red_green_blue = VALUE8(tvb, *offsetp + 10);
1450
1451             bp = buffer + sprintf(buffer, "colorItem: ");
1452             sep = "";
1453             if (do_red_green_blue & 0x1) {
1454                 bp += sprintf(bp, "red = %d", red);
1455                 sep = ", ";
1456             }
1457             if (do_red_green_blue & 0x2) {
1458                 bp += sprintf(bp, "%sgreen = %d", sep, green);
1459                 sep = ", ";
1460             }
1461             if (do_red_green_blue & 0x4)
1462                 bp += sprintf(bp, "%sblue = %d", sep, blue);
1463
1464             tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
1465             ttt = proto_item_add_subtree(tti, ett_x11_color_item);
1466             proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
1467             *offsetp += 4;
1468             proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
1469             *offsetp += 2;
1470             proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
1471             *offsetp += 2;
1472             proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
1473             *offsetp += 2;
1474             colorFlags(tvb, offsetp, ttt);
1475             proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
1476             *offsetp += 1;
1477       }
1478 }
1479
1480 static GTree *keysymTable = NULL;
1481
1482 static gint compareGuint32(gconstpointer a, gconstpointer b)
1483 {
1484       return GPOINTER_TO_INT(b) - GPOINTER_TO_INT(a);
1485 }
1486
1487 static void
1488 XConvertCase(register int sym, int *lower, int *upper)
1489 {
1490     *lower = sym;
1491     *upper = sym;
1492     switch(sym >> 8) {
1493     case 0: /* Latin 1 */
1494         if ((sym >= XK_A) && (sym <= XK_Z))
1495             *lower += (XK_a - XK_A);
1496         else if ((sym >= XK_a) && (sym <= XK_z))
1497             *upper -= (XK_a - XK_A);
1498         else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis))
1499             *lower += (XK_agrave - XK_Agrave);
1500         else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis))
1501             *upper -= (XK_agrave - XK_Agrave);
1502         else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn))
1503             *lower += (XK_oslash - XK_Ooblique);
1504         else if ((sym >= XK_oslash) && (sym <= XK_thorn))
1505             *upper -= (XK_oslash - XK_Ooblique);
1506         break;
1507     case 1: /* Latin 2 */
1508         /* Assume the KeySym is a legal value (ignore discontinuities) */
1509         if (sym == XK_Aogonek)
1510             *lower = XK_aogonek;
1511         else if (sym >= XK_Lstroke && sym <= XK_Sacute)
1512             *lower += (XK_lstroke - XK_Lstroke);
1513         else if (sym >= XK_Scaron && sym <= XK_Zacute)
1514             *lower += (XK_scaron - XK_Scaron);
1515         else if (sym >= XK_Zcaron && sym <= XK_Zabovedot)
1516             *lower += (XK_zcaron - XK_Zcaron);
1517         else if (sym == XK_aogonek)
1518             *upper = XK_Aogonek;
1519         else if (sym >= XK_lstroke && sym <= XK_sacute)
1520             *upper -= (XK_lstroke - XK_Lstroke);
1521         else if (sym >= XK_scaron && sym <= XK_zacute)
1522             *upper -= (XK_scaron - XK_Scaron);
1523         else if (sym >= XK_zcaron && sym <= XK_zabovedot)
1524             *upper -= (XK_zcaron - XK_Zcaron);
1525         else if (sym >= XK_Racute && sym <= XK_Tcedilla)
1526             *lower += (XK_racute - XK_Racute);
1527         else if (sym >= XK_racute && sym <= XK_tcedilla)
1528             *upper -= (XK_racute - XK_Racute);
1529         break;
1530     case 2: /* Latin 3 */
1531         /* Assume the KeySym is a legal value (ignore discontinuities) */
1532         if (sym >= XK_Hstroke && sym <= XK_Hcircumflex)
1533             *lower += (XK_hstroke - XK_Hstroke);
1534         else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex)
1535             *lower += (XK_gbreve - XK_Gbreve);
1536         else if (sym >= XK_hstroke && sym <= XK_hcircumflex)
1537             *upper -= (XK_hstroke - XK_Hstroke);
1538         else if (sym >= XK_gbreve && sym <= XK_jcircumflex)
1539             *upper -= (XK_gbreve - XK_Gbreve);
1540         else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex)
1541             *lower += (XK_cabovedot - XK_Cabovedot);
1542         else if (sym >= XK_cabovedot && sym <= XK_scircumflex)
1543             *upper -= (XK_cabovedot - XK_Cabovedot);
1544         break;
1545     case 3: /* Latin 4 */
1546         /* Assume the KeySym is a legal value (ignore discontinuities) */
1547         if (sym >= XK_Rcedilla && sym <= XK_Tslash)
1548             *lower += (XK_rcedilla - XK_Rcedilla);
1549         else if (sym >= XK_rcedilla && sym <= XK_tslash)
1550             *upper -= (XK_rcedilla - XK_Rcedilla);
1551         else if (sym == XK_ENG)
1552             *lower = XK_eng;
1553         else if (sym == XK_eng)
1554             *upper = XK_ENG;
1555         else if (sym >= XK_Amacron && sym <= XK_Umacron)
1556             *lower += (XK_amacron - XK_Amacron);
1557         else if (sym >= XK_amacron && sym <= XK_umacron)
1558             *upper -= (XK_amacron - XK_Amacron);
1559         break;
1560     case 6: /* Cyrillic */
1561         /* Assume the KeySym is a legal value (ignore discontinuities) */
1562         if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE)
1563             *lower -= (XK_Serbian_DJE - XK_Serbian_dje);
1564         else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze)
1565             *upper += (XK_Serbian_DJE - XK_Serbian_dje);
1566         else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN)
1567             *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu);
1568         else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign)
1569             *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu);
1570         break;
1571     case 7: /* Greek */
1572         /* Assume the KeySym is a legal value (ignore discontinuities) */
1573         if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent)
1574             *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1575         else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent &&
1576                  sym != XK_Greek_iotaaccentdieresis &&
1577                  sym != XK_Greek_upsilonaccentdieresis)
1578             *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent);
1579         else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA)
1580             *lower += (XK_Greek_alpha - XK_Greek_ALPHA);
1581         else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega &&
1582                  sym != XK_Greek_finalsmallsigma)
1583             *upper -= (XK_Greek_alpha - XK_Greek_ALPHA);
1584         break;
1585     }
1586 }
1587
1588 static const char *
1589 keycode2keysymString(int *keycodemap[256], int first_keycode,
1590                      int keysyms_per_keycode, 
1591                      int *modifiermap[array_length(modifiers)],
1592                      int keycodes_per_modifier,
1593                      guint32 keycode, guint32 bitmask)
1594 {
1595         static char buf[32];
1596         int *syms;
1597         int groupmodkc, numlockkc, numlockmod, groupmod;
1598         int lockmod_is_capslock = 0, lockmod_is_shiftlock = 0;
1599         int lockmod_is_nosymbol = 1;
1600         int modifier, kc, keysym;
1601
1602         if ((syms = keycodemap[keycode]) == NULL)
1603                 return "<Unknown>";
1604
1605         for (kc = first_keycode, groupmodkc = numlockkc = -1; kc < 256; ++kc)
1606                 for (keysym = 0; keysym < keysyms_per_keycode; ++keysym) {
1607                         if (keycodemap[kc] == NULL)
1608                                 return "<Unknown>";
1609                         switch (keycodemap[kc][keysym]) {
1610                                 case 0xff7e:
1611                                         groupmodkc = kc;
1612                                         break;
1613
1614                                 case 0xff7f:
1615                                         numlockkc = kc;
1616                                         break;
1617
1618                                 case 0xffe5:
1619                                         lockmod_is_capslock = kc;
1620                                         break;
1621
1622                                 case 0xffe6:
1623                                         lockmod_is_shiftlock = kc;
1624                                         break;
1625                         }
1626                 }
1627
1628
1629         /*
1630          * If we have not seen the modifiermap we don't know what the
1631          * keycode translates to, but we do know it's one of the keys 
1632          * in syms (give or take a case-conversion), so we could in 
1633          * theory list them all.
1634          */
1635         if (modifiermap[array_length(modifiers) - 1] == NULL) /* all or none */
1636                 return "<Unknown>";
1637
1638         /* find out what the numlockmodifer and groupmodifier is. */
1639         for (modifier = 0, numlockmod = groupmod = -1;
1640             modifier < (int)array_length(modifiers) && numlockmod == -1;
1641             ++modifier)
1642                 for (kc = 0; kc < keycodes_per_modifier; ++kc)
1643                         if (modifiermap[modifier][kc] == numlockkc)
1644                                 numlockmod = modifier;
1645                         else if (modifiermap[modifier][kc] == groupmodkc)
1646                                 groupmod = modifier;
1647
1648         /*
1649          * ... and what the lockmodifier is interpreted as.
1650          * (X11v4r6 ref, keyboard and pointers section.)
1651          */
1652         for (kc = 0; kc < keycodes_per_modifier; ++kc)
1653                 if (modifiermap[1][kc] == lockmod_is_capslock) {
1654                         lockmod_is_shiftlock = lockmod_is_nosymbol = 0;
1655                         break;
1656                 }
1657                 else if (modifiermap[0][kc] == lockmod_is_shiftlock) {
1658                         lockmod_is_capslock = lockmod_is_nosymbol = 0;
1659                         break;
1660                 }
1661
1662 #if 0 
1663         /* 
1664          * This is (how I understand) the X11v4R6 protocol description given
1665          * in A. Nye's book.  It is quite different from the
1666          * code in _XTranslateKey() in the file 
1667          * "$XConsortium: KeyBind.c /main/55 1996/02/02 14:08:55 kaleb $"
1668          * as shipped with XFree, and doesn't work correctly, nor do I see
1669          * how it could (e.g. the case of lower/uppercase-letters).
1670          * -- Michael Shuldman
1671          */
1672
1673         if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1674             && ((syms[1] >= 0xff80
1675              && syms[1] <= 0xffbd)
1676              || (syms[1] >= 0x11000000
1677               && syms[1] <= 0x1100ffff))) {
1678                 if ((bitmask & ShiftMask) || lockmod_is_shiftlock)
1679                         return keysymString(syms[groupmod + 0]);
1680                 else
1681                         if (syms[groupmod + 1] == NoSymbol)
1682                                 return keysymString(syms[groupmod + 0]);
1683                         else
1684                                 return keysymString(syms[groupmod + 1]);
1685         }
1686         else if (!(bitmask & ShiftMask) && !(bitmask & LockMask))
1687                 return keysymString(syms[groupmod + 0]);
1688         else if (!(bitmask & ShiftMask)
1689             && ((bitmask & LockMask) && lockmod_is_capslock))
1690                 if (islower(syms[groupmod + 0]))
1691 /*                      return toupper(keysymString(syms[groupmod + 0])); */
1692                         return "Uppercase"; /* XXX */
1693                 else
1694                         return keysymString(syms[groupmod + 0]);
1695
1696         else if ((bitmask & ShiftMask) 
1697             && ((bitmask & LockMask) && lockmod_is_capslock))
1698                 if (islower(syms[groupmod + 1]))
1699 /*                      return toupper(keysymString(syms[groupmod + 1])); */
1700                         return "Uppercase"; /* XXX */
1701                 else
1702                         return keysymString(syms[groupmod + 1]);
1703
1704         else if ((bitmask & ShiftMask) 
1705             ||  ((bitmask & LockMask) && lockmod_is_shiftlock))
1706                         return keysymString(syms[groupmod + 1]);
1707 #else /* _XTranslateKey() based code. */
1708
1709         while (keysyms_per_keycode > 2
1710             && keycodemap[keysyms_per_keycode - 1] == NoSymbol)
1711                 --keysyms_per_keycode;
1712         if (keysyms_per_keycode > 2
1713             && (groupmod >= 0 && (modifiermask[groupmod] & bitmask))) {
1714                 syms += 2;
1715                 keysyms_per_keycode -= 2;
1716         }
1717         
1718         if (numlockmod >= 0 && (bitmask & modifiermask[numlockmod])
1719             && keysyms_per_keycode > 1
1720             && ((syms[1] >= 0xff80 && syms[1] <= 0xffbd)
1721              || (syms[1] >= 0x11000000 && syms[1] <= 0x1100ffff))) {
1722                 if ((bitmask & ShiftMask)
1723                     || (bitmask & LockMask && lockmod_is_shiftlock))
1724                         keysym = syms[0];
1725                 else
1726                         keysym = syms[1];
1727         }
1728         else if (!(bitmask & ShiftMask)
1729             && (!(bitmask & LockMask) || lockmod_is_nosymbol)) {
1730                 if (keysyms_per_keycode == 1
1731                     || (keysyms_per_keycode > 1 && syms[1] == NoSymbol)) {
1732                         int usym;
1733
1734                         XConvertCase(syms[0], &keysym, &usym);
1735                 }
1736                 else
1737                         keysym = syms[0];
1738         }
1739         else if (!(bitmask & LockMask) || !lockmod_is_capslock) {
1740                 int lsym, usym;
1741
1742                 if (keysyms_per_keycode == 1
1743                     || (keysyms_per_keycode > 1 && (usym = syms[1]) == NoSymbol))
1744                         XConvertCase(syms[0], &lsym, &usym);
1745                 keysym = usym;
1746         }
1747         else {
1748                 int lsym, usym;
1749
1750                 if (keysyms_per_keycode == 1
1751                     || (keysyms_per_keycode > 1 && syms[1] == NoSymbol))
1752                         keysym = syms[0];
1753
1754                 XConvertCase(keysym, &lsym, &usym);
1755
1756                 if (!(bitmask & ShiftMask) && keysym != syms[0]
1757                 && ((keysym != usym) || (lsym == usym)))
1758                         XConvertCase(syms[0], &lsym, &usym);
1759                 keysym = usym;
1760         }
1761         
1762         if (keysym == XK_VoidSymbol)
1763                 keysym = NoSymbol;
1764
1765         sprintf(buf, "%d, \"%s\"", keysym, keysymString(keysym));
1766         return buf;
1767 #endif
1768 }
1769
1770 static const char *keysymString(guint32 v)
1771 {
1772       gpointer res;
1773       if (!keysymTable) {
1774
1775             /* This table is so big that we built it only if necessary */
1776
1777             const value_string *p = keysym_vals_source;
1778             keysymTable = g_tree_new(compareGuint32);
1779             for(; p -> strptr; p++)
1780                   g_tree_insert(keysymTable, GINT_TO_POINTER(p -> value), (gpointer) (p -> strptr) );
1781       }
1782       res = g_tree_lookup(keysymTable, GINT_TO_POINTER(v));
1783       return res ? res : "<Unknown>";
1784 }
1785
1786 static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1787                           int *modifiermap[], int keycodes_per_modifier,
1788                           gboolean little_endian)
1789 {
1790       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp,
1791         array_length(modifiers) * keycodes_per_modifier, little_endian);
1792       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
1793       size_t m;
1794
1795       for (m = 0; m < array_length(modifiers);
1796         ++m, *offsetp += keycodes_per_modifier) {
1797             const guint8 *p;
1798             proto_item *tikc;
1799             int i;
1800
1801             p = tvb_get_ptr(tvb, *offsetp, keycodes_per_modifier);
1802             modifiermap[m] =
1803                 g_malloc(sizeof(*modifiermap[m]) * keycodes_per_modifier);
1804
1805             tikc = proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb,
1806                 *offsetp, keycodes_per_modifier, p, "item: ");
1807             for(i = 0; i < keycodes_per_modifier; ++i) {
1808                 guchar c = p[i];
1809
1810                 if (c)
1811                     proto_item_append_text(tikc, " %s=%d", modifiers[m], c);
1812
1813                 modifiermap[m][i] = c;
1814             }
1815       }
1816 }
1817
1818 static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1819                           int hf_item, int *keycodemap[256],
1820                           int keycode_first, int keycode_count,
1821                           int keysyms_per_keycode, gboolean little_endian)
1822 {
1823       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
1824       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
1825       proto_item *tti;
1826       proto_tree *ttt;
1827       int i, keycode;
1828
1829       DISSECTOR_ASSERT(keycode_first >= 0);
1830       DISSECTOR_ASSERT(keycode_count >= 0);
1831
1832       for (keycode = keycode_first; keycode_count > 0;
1833            ++keycode, --keycode_count) {
1834             if (keycode >= 256) {
1835                 proto_tree_add_text(tt, tvb, *offsetp, 4 * keysyms_per_keycode,
1836                     "keycode value %d is out of range", keycode);
1837                 *offsetp += 4 * keysyms_per_keycode;
1838                 continue;
1839             }
1840             tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp,
1841                 4 * keysyms_per_keycode, "keysyms (keycode %d):", keycode);
1842
1843             ttt = proto_item_add_subtree(tti, ett_x11_keysym);
1844
1845             tvb_ensure_bytes_exist(tvb, *offsetp, 4 * keysyms_per_keycode);
1846             keycodemap[keycode]
1847                 = g_malloc(sizeof(*keycodemap[keycode]) * keysyms_per_keycode);
1848
1849             for(i = 0; i < keysyms_per_keycode; ++i) {
1850                   /* keysymvalue = byte3 * 256 + byte4. */
1851                   guint32 v = VALUE32(tvb, *offsetp);
1852
1853                   proto_item_append_text(tti, " %s", keysymString(v));
1854                   proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym,
1855                       tvb, *offsetp, 4, v,
1856                       "keysym (keycode %d): 0x%08x (%s)",
1857                       keycode, v, keysymString(v));
1858
1859                   keycodemap[keycode][i] = v;
1860                   *offsetp += 4;
1861             }
1862         
1863             for (i = 1; i < keysyms_per_keycode; ++i)
1864                 if (keycodemap[keycode][i] != NoSymbol)
1865                         break;
1866
1867             if (i == keysyms_per_keycode) {
1868                 /* all but (possibly) first were NoSymbol. */
1869                 if (keysyms_per_keycode == 4) {
1870                         keycodemap[keycode][1] = NoSymbol;
1871                         keycodemap[keycode][2] = keycodemap[keycode][0];
1872                         keycodemap[keycode][3] = NoSymbol;
1873                 }
1874
1875                 continue;
1876             }
1877
1878             for (i = 2; i < keysyms_per_keycode; ++i)
1879                 if (keycodemap[keycode][i] != NoSymbol)
1880                         break;
1881             if (i == keysyms_per_keycode) {
1882                 /* all but (possibly) first two were NoSymbol. */
1883                 if (keysyms_per_keycode == 4) {
1884                         keycodemap[keycode][2] = keycodemap[keycode][0];
1885                         keycodemap[keycode][3] =  keycodemap[keycode][1];
1886                 }
1887
1888                 continue;
1889             }
1890       }
1891 }
1892
1893 static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1894                         int length, gboolean little_endian)
1895 {
1896       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
1897       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
1898       while(length--) {
1899             gint16 x, y;
1900             proto_item *tti;
1901             proto_tree *ttt;
1902
1903             x = VALUE16(tvb, *offsetp);
1904             y = VALUE16(tvb, *offsetp + 2);
1905
1906             tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
1907             ttt = proto_item_add_subtree(tti, ett_x11_point);
1908             proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
1909             *offsetp += 2;
1910             proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
1911             *offsetp += 2;
1912       }
1913 }
1914
1915 static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1916                             int length, gboolean little_endian)
1917 {
1918       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1919       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
1920       while(length--) {
1921             gint16 x, y;
1922             unsigned width, height;
1923             proto_item *tti;
1924             proto_tree *ttt;
1925
1926             x = VALUE16(tvb, *offsetp);
1927             y = VALUE16(tvb, *offsetp + 2);
1928             width = VALUE16(tvb, *offsetp + 4);
1929             height = VALUE16(tvb, *offsetp + 6);
1930
1931             tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8,
1932                                                  "rectangle: %dx%d+%d+%d", width, height, x, y);
1933             ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
1934             proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
1935             *offsetp += 2;
1936             proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
1937             *offsetp += 2;
1938             proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
1939             *offsetp += 2;
1940             proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
1941             *offsetp += 2;
1942       }
1943 }
1944
1945 static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1946                           int length, gboolean little_endian)
1947 {
1948       proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
1949       proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
1950       while(length--) {
1951             gint16 x1, y1, x2, y2;
1952             proto_item *tti;
1953             proto_tree *ttt;
1954
1955             x1 = VALUE16(tvb, *offsetp);
1956             y1 = VALUE16(tvb, *offsetp + 2);
1957             x2 = VALUE16(tvb, *offsetp + 4);
1958             y2 = VALUE16(tvb, *offsetp + 6);
1959
1960             tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8,
1961                                                  "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
1962             ttt = proto_item_add_subtree(tti, ett_x11_segment);
1963             proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
1964             *offsetp += 2;
1965             proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
1966             *offsetp += 2;
1967             proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
1968             *offsetp += 2;
1969             proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
1970             *offsetp += 2;
1971       }
1972 }
1973
1974 /* XXX - the protocol tree code should handle non-printable characters.
1975    Note that "non-printable characters" may depend on your locale.... */
1976 static void stringCopy(char *dest, const char *source, int length)
1977 {
1978       guchar c;
1979       while(length--) {
1980             c = *source++;
1981             if (!isgraph(c) && c != ' ') c = '.';
1982             *dest++ = c;
1983       }
1984       *dest++ = '\0';
1985 }
1986
1987 static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
1988                           int hf_item, int length, gboolean little_endian)
1989 {
1990       char *s = NULL;
1991       guint allocated = 0;
1992       proto_item *ti;
1993       proto_tree *tt;
1994       int i;
1995
1996       /* Compute total length */
1997
1998       int scanning_offset = *offsetp; /* Scanning pointer */
1999       int l;
2000       for(i = length; i; i--) {
2001             l = tvb_get_guint8(tvb, scanning_offset);
2002             scanning_offset += 1 + l;
2003       }
2004
2005       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2006       tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
2007
2008       /*
2009        * In case we throw an exception, clean up whatever stuff we've
2010        * allocated (if any).
2011        */
2012       CLEANUP_PUSH(g_free, s);
2013
2014       while(length--) {
2015             unsigned l = VALUE8(tvb, *offsetp);
2016             if (allocated < (l + 1)) {
2017                   /* g_realloc doesn't work ??? */
2018                   g_free(s);
2019                   s = g_malloc(l + 1);
2020                   allocated = l + 1;
2021             }
2022             stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
2023             proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
2024             *offsetp += l + 1;
2025       }
2026
2027       /*
2028        * Call the cleanup handler to free the string and pop the handler.
2029        */
2030       CLEANUP_CALL_AND_POP;
2031 }
2032
2033 #define STRING16_MAX_DISPLAYED_LENGTH 150
2034
2035 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
2036 {
2037       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
2038       for(; length > 0; offset += 2, length--) {
2039             if (tvb_get_guint8(tvb, offset))
2040                 return FALSE;
2041       }
2042       return TRUE;
2043 }
2044
2045 /* length is the length of the _byte_zone_ (that is, twice the length of the string) */
2046
2047 static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
2048                                               int hf, int hf_bytes,
2049                                               int offset, unsigned length,
2050                                               char **s, int *sLength,
2051                                               gboolean little_endian)
2052 {
2053       int truncated = FALSE;
2054       unsigned l = length / 2;
2055
2056       if (stringIsActuallyAn8BitString(tvb, offset, l)) {
2057             char *dp;
2058             int soffset = offset;
2059
2060             if (l > STRING16_MAX_DISPLAYED_LENGTH) {
2061                   truncated = TRUE;
2062                   l = STRING16_MAX_DISPLAYED_LENGTH;
2063             }
2064             if (*sLength < (int) l + 3) {
2065                   g_free(*s);
2066                   *s = g_malloc(l + 3);
2067                   *sLength = l + 3;
2068             }
2069             dp = *s;
2070             *dp++ = '"';
2071             if (truncated) l -= 3;
2072
2073             while(l--) {
2074                   soffset++;
2075                   *dp++ = tvb_get_guint8(tvb, soffset);
2076                   soffset++;
2077             }
2078             *dp++ = '"';
2079
2080             /* If truncated, add an ellipsis */
2081             if (truncated) { *dp++ = '.'; *dp++ = '.'; *dp++ = '.'; }
2082
2083             *dp++ = '\0';
2084             proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s",
2085                                         proto_registrar_get_nth(hf) -> name, *s);
2086       } else
2087             proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
2088
2089 }
2090
2091 static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2092     int sizeIs16, int next_offset, gboolean little_endian)
2093 {
2094       int allocated = 0;
2095       char *s = NULL;
2096       proto_item *ti;
2097       proto_tree *tt;
2098       guint32 fid;
2099
2100       /* Compute total length */
2101
2102       int scanning_offset = *offsetp; /* Scanning pointer */
2103       int l;                            /* Length of an individual item */
2104       int n = 0;                        /* Number of items */
2105
2106       while(scanning_offset < next_offset) {
2107             l = tvb_get_guint8(tvb, scanning_offset);
2108             scanning_offset++;
2109             if (!l) break;
2110             n++;
2111             scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
2112       }
2113
2114       ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
2115       tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
2116
2117       /*
2118        * In case we throw an exception, clean up whatever stuff we've
2119        * allocated (if any).
2120        */
2121       CLEANUP_PUSH(g_free, s);
2122
2123       while(n--) {
2124             unsigned l = VALUE8(tvb, *offsetp);
2125             if (l == 255) { /* Item is a font */
2126                   fid = tvb_get_ntohl(tvb, *offsetp + 1);
2127                   proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
2128                   *offsetp += 5;
2129             } else { /* Item is a string */
2130                   proto_item *tti;
2131                   proto_tree *ttt;
2132                   gint8 delta = VALUE8(tvb, *offsetp + 1);
2133                   if (sizeIs16) l += l;
2134                   if ((unsigned) allocated < l + 1) {
2135                         /* g_realloc doesn't work ??? */
2136                         g_free(s);
2137                         s = g_malloc(l + 1);
2138                         allocated = l + 1;
2139                   }
2140                   stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
2141                   tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
2142                                                        "textitem (string): delta = %d, \"%s\"",
2143                                                        delta, s);
2144                   ttt = proto_item_add_subtree(tti, ett_x11_text_item);
2145                   proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
2146                   if (sizeIs16)
2147                         string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16,
2148                                                           hf_x11_textitem_string_string16_bytes,
2149                                                           *offsetp + 2, l,
2150                                                           &s, &allocated,
2151                                                           little_endian);
2152                   else
2153                         proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb,
2154                                                      *offsetp + 2, l, s, "\"%s\"", s);
2155                   *offsetp += l + 2;
2156             }
2157       }
2158
2159       /*
2160        * Call the cleanup handler to free the string and pop the handler.
2161        */
2162       CLEANUP_CALL_AND_POP;
2163 }
2164
2165 static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2166                       gboolean little_endian)
2167 {
2168       guint32 v = VALUE8(tvb, *offsetp);
2169       header_field_info *hfi = proto_registrar_get_nth(hf);
2170       gchar *enumValue = NULL;
2171
2172       if (hfi -> strings)
2173             enumValue = match_strval(v, cVALS(hfi -> strings));
2174       if (enumValue)
2175             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
2176             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2177             hfi -> name, v, enumValue);
2178       else
2179             proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
2180       *offsetp += 1;
2181       return v;
2182 }
2183
2184 static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2185                        gboolean little_endian)
2186 {
2187       guint32 v = VALUE16(tvb, *offsetp);
2188       header_field_info *hfi = proto_registrar_get_nth(hf);
2189       gchar *enumValue = NULL;
2190
2191       if (hfi -> strings)
2192             enumValue = match_strval(v, cVALS(hfi -> strings));
2193       if (enumValue)
2194             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 2, v,
2195             hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
2196             hfi -> name, v, enumValue);
2197       else
2198             proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
2199       *offsetp += 2;
2200       return v;
2201 }
2202
2203 static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2204                        gboolean little_endian)
2205 {
2206       guint32 v = VALUE32(tvb, *offsetp);
2207       header_field_info *hfi = proto_registrar_get_nth(hf);
2208       gchar *enumValue = NULL;
2209       const gchar *nameAsChar = hfi -> name;
2210
2211       if (hfi -> strings)
2212             enumValue = match_strval(v, cVALS(hfi -> strings));
2213       if (enumValue)
2214             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2215                                        hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
2216                                        nameAsChar, v, enumValue);
2217       else
2218             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
2219                                        hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
2220                                        nameAsChar, v);
2221       *offsetp += 4;
2222       return v;
2223 }
2224
2225 static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2226                          gboolean little_endian)
2227 {
2228       BITMASK32(gc_value);
2229       BITFIELD(ENUM8,  gc_value_mask, function);
2230       BITFIELD(CARD32, gc_value_mask, plane_mask);
2231       BITFIELD(CARD32, gc_value_mask, foreground);
2232       BITFIELD(CARD32, gc_value_mask, background);
2233       BITFIELD(CARD16, gc_value_mask, line_width);
2234       BITFIELD(ENUM8,  gc_value_mask, line_style);
2235       BITFIELD(ENUM8,  gc_value_mask, cap_style);
2236       BITFIELD(ENUM8,  gc_value_mask, join_style);
2237       BITFIELD(ENUM8,  gc_value_mask, fill_style);
2238       BITFIELD(ENUM8,  gc_value_mask, fill_rule);
2239       BITFIELD(PIXMAP, gc_value_mask, tile);
2240       BITFIELD(PIXMAP, gc_value_mask, stipple);
2241       BITFIELD(INT16,  gc_value_mask, tile_stipple_x_origin);
2242       BITFIELD(INT16,  gc_value_mask, tile_stipple_y_origin);
2243       BITFIELD(FONT,   gc_value_mask, font);
2244       BITFIELD(ENUM8,  gc_value_mask, subwindow_mode);
2245       BITFIELD(BOOL,   gc_value_mask, graphics_exposures);
2246       BITFIELD(INT16,  gc_value_mask, clip_x_origin);
2247       BITFIELD(INT16,  gc_value_mask, clip_y_origin);
2248       BITFIELD(PIXMAP, gc_value_mask, clip_mask);
2249       BITFIELD(CARD16, gc_value_mask, dash_offset);
2250       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
2251       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
2252       ENDBITMASK;
2253 }
2254
2255 static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2256                    gboolean little_endian)
2257 {
2258       BITMASK32(gc_value);
2259       FLAG(gc_value, function);
2260       FLAG(gc_value, plane_mask);
2261       FLAG(gc_value, foreground);
2262       FLAG(gc_value, background);
2263       FLAG(gc_value, line_width);
2264       FLAG(gc_value, line_style);
2265       FLAG(gc_value, cap_style);
2266       FLAG(gc_value, join_style);
2267       FLAG(gc_value, fill_style);
2268       FLAG(gc_value, fill_rule);
2269       FLAG(gc_value, tile);
2270       FLAG(gc_value, stipple);
2271       FLAG(gc_value, tile_stipple_x_origin);
2272       FLAG(gc_value, tile_stipple_y_origin);
2273       FLAG(gc_value, font);
2274       FLAG(gc_value, subwindow_mode);
2275       FLAG(gc_value, graphics_exposures);
2276       FLAG(gc_value, clip_x_origin);
2277       FLAG(gc_value, clip_y_origin);
2278       FLAG(gc_value, clip_mask);
2279       FLAG(gc_value, dash_offset);
2280       FLAG(gc_value, gc_dashes);
2281       FLAG(gc_value, arc_mode);
2282       ENDBITMASK;
2283 }
2284
2285 static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2286                              gboolean little_endian)
2287 {
2288       guint32 res = VALUE16(tvb, *offsetp);
2289       proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
2290       *offsetp += 2;
2291       return res * 4;
2292 }
2293
2294 static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2295                        gboolean little_endian)
2296 {
2297       BITMASK32(event);
2298       FLAG(event, KeyPress);
2299       FLAG(event, KeyRelease);
2300       FLAG(event, ButtonPress);
2301       FLAG(event, ButtonRelease);
2302       FLAG(event, EnterWindow);
2303       FLAG(event, LeaveWindow);
2304       FLAG(event, PointerMotion);
2305       FLAG(event, PointerMotionHint);
2306       FLAG(event, Button1Motion);
2307       FLAG(event, Button2Motion);
2308       FLAG(event, Button3Motion);
2309       FLAG(event, Button4Motion);
2310       FLAG(event, Button5Motion);
2311       FLAG(event, ButtonMotion);
2312       FLAG(event, KeymapState);
2313       FLAG(event, Exposure);
2314       FLAG(event, VisibilityChange);
2315       FLAG(event, StructureNotify);
2316       FLAG(event, ResizeRedirect);
2317       FLAG(event, SubstructureNotify);
2318       FLAG(event, SubstructureRedirect);
2319       FLAG(event, FocusChange);
2320       FLAG(event, PropertyChange);
2321       FLAG(event, ColormapChange);
2322       FLAG(event, OwnerGrabButton);
2323       FLAG_IF_NONZERO(event, erroneous_bits);
2324       ENDBITMASK;
2325 }
2326
2327 static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2328                              gboolean little_endian)
2329 {
2330       BITMASK32(do_not_propagate);
2331       FLAG(do_not_propagate, KeyPress);
2332       FLAG(do_not_propagate, KeyRelease);
2333       FLAG(do_not_propagate, ButtonPress);
2334       FLAG(do_not_propagate, ButtonRelease);
2335       FLAG(do_not_propagate, PointerMotion);
2336       FLAG(do_not_propagate, Button1Motion);
2337       FLAG(do_not_propagate, Button2Motion);
2338       FLAG(do_not_propagate, Button3Motion);
2339       FLAG(do_not_propagate, Button4Motion);
2340       FLAG(do_not_propagate, Button5Motion);
2341       FLAG(do_not_propagate, ButtonMotion);
2342       FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
2343       ENDBITMASK;
2344 }
2345
2346
2347 static void setOfKeyButMask(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2348                          gboolean little_endian, gboolean butmask)
2349 {
2350       proto_item *ti;
2351       guint32 bitmask_value;
2352       int bitmask_offset;
2353       int bitmask_size;
2354       proto_tree *bitmask_tree;
2355
2356       bitmask_value = VALUE16(tvb, *offsetp);
2357       bitmask_offset = *offsetp;
2358       bitmask_size = 2;
2359
2360       if (!butmask && bitmask_value == 0x8000)
2361             proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
2362                                        "modifiers-masks: 0x8000 (AnyModifier)");
2363       else {
2364             ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2,
2365                                                  bitmask_value);
2366             bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
2367             FLAG(modifiers, Shift);
2368             FLAG(modifiers, Lock);
2369             FLAG(modifiers, Control);
2370             FLAG(modifiers, Mod1);
2371             FLAG(modifiers, Mod2);
2372             FLAG(modifiers, Mod3);
2373             FLAG(modifiers, Mod4);
2374             FLAG(modifiers, Mod5);
2375
2376             if (butmask) {
2377                     FLAG(modifiers, Button1);
2378                     FLAG(modifiers, Button2);
2379                     FLAG(modifiers, Button3);
2380                     FLAG(modifiers, Button4);
2381                     FLAG(modifiers, Button5);
2382             }
2383
2384             if (butmask)
2385                     FLAG_IF_NONZERO(keybut, erroneous_bits);
2386             else
2387                     FLAG_IF_NONZERO(modifiers, erroneous_bits);
2388       }
2389       *offsetp += 2;
2390 }
2391
2392 static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2393                               gboolean little_endian)
2394 {
2395       BITMASK16(pointer_event);
2396       FLAG(pointer_event, ButtonPress);
2397       FLAG(pointer_event, ButtonRelease);
2398       FLAG(pointer_event, EnterWindow);
2399       FLAG(pointer_event, LeaveWindow);
2400       FLAG(pointer_event, PointerMotion);
2401       FLAG(pointer_event, PointerMotionHint);
2402       FLAG(pointer_event, Button1Motion);
2403       FLAG(pointer_event, Button2Motion);
2404       FLAG(pointer_event, Button3Motion);
2405       FLAG(pointer_event, Button4Motion);
2406       FLAG(pointer_event, Button5Motion);
2407       FLAG(pointer_event, ButtonMotion);
2408       FLAG(pointer_event, KeymapState);
2409       FLAG_IF_NONZERO(pointer_event, erroneous_bits);
2410       ENDBITMASK;
2411 }
2412
2413 static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2414     int hf, unsigned length)
2415 {
2416       const guint8 *p;
2417       char *s;
2418
2419       p = tvb_get_ptr(tvb, *offsetp, length);
2420       s = g_malloc(length + 1);
2421       stringCopy(s, p, length);
2422       proto_tree_add_string(t, hf, tvb, *offsetp, length, s);
2423       g_free(s);
2424       *offsetp += length;
2425 }
2426
2427 /* The length is the length of the _byte_zone_ (twice the length of the string) */
2428
2429 static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2430     int hf_bytes, unsigned length, gboolean little_endian)
2431 {
2432       char *s = NULL;
2433       unsigned l = 0;
2434
2435       /*
2436        * In case we throw an exception, clean up whatever stuff we've
2437        * allocated (if any).
2438        */
2439       CLEANUP_PUSH(g_free, s);
2440
2441       length += length;
2442       string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length,
2443                                         &s, &l, little_endian);
2444
2445       /*
2446        * Call the cleanup handler to free the string and pop the handler.
2447        */
2448       CLEANUP_CALL_AND_POP;
2449
2450       *offsetp += length;
2451 }
2452
2453 static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
2454                       gboolean little_endian)
2455 {
2456       guint32 v = VALUE32(tvb, *offsetp);
2457
2458       if (!v)
2459             proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)",
2460                 proto_registrar_get_nth(hf) -> name);
2461       else
2462             proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
2463       *offsetp += 4;
2464 }
2465
2466 static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t,
2467                              gboolean little_endian)
2468 {
2469       BITMASK32(window_value);
2470       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
2471       BITFIELD(CARD32, window_value_mask, background_pixel);
2472       BITFIELD(PIXMAP, window_value_mask, border_pixmap);
2473       BITFIELD(CARD32, window_value_mask, border_pixel);
2474       BITFIELD(BITGRAVITY, window_value_mask, bit_gravity);
2475       BITFIELD(WINGRAVITY, window_value_mask, win_gravity);
2476       BITFIELD(ENUM8, window_value_mask, backing_store);
2477       BITFIELD(CARD32, window_value_mask, backing_planes);
2478       BITFIELD(CARD32, window_value_mask, backing_pixel);
2479       BITFIELD(BOOL,   window_value_mask, override_redirect);
2480       BITFIELD(BOOL,   window_value_mask, save_under);
2481       BITFIELD(SETofEVENT, window_value_mask, event_mask);
2482       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
2483       BITFIELD(COLORMAP, window_value_mask, colormap);
2484       BITFIELD(CURSOR, window_value_mask, cursor);
2485       ENDBITMASK;
2486 }
2487
2488 static void x11_init_protocol(void)
2489 {
2490       x11_conv_data_t *state;
2491
2492       for (state = x11_conv_data_list; state != NULL; state = state->next) {
2493             g_hash_table_destroy(state->seqtable);
2494             g_hash_table_destroy(state->valtable);
2495       }
2496       x11_conv_data_list = NULL;
2497       if (x11_state_chunk != NULL)
2498             g_mem_chunk_destroy(x11_state_chunk);
2499
2500       x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
2501                                         sizeof (x11_conv_data_t),
2502                                         128 * sizeof (x11_conv_data_t),
2503                                         G_ALLOC_ONLY);
2504 }
2505
2506 /************************************************************************
2507  ***                                                                  ***
2508  ***         G U E S S I N G   T H E   B Y T E   O R D E R I N G      ***
2509  ***                                                                  ***
2510  ************************************************************************/
2511
2512 /* If we can't guess, we return TRUE (that is little_endian), cause
2513    I'm developing on a Linux box :-). The (non-)guess isn't cached
2514    however, so we may have more luck next time. I'm quite conservative
2515    in my assertions, cause once it's cached, it's stay in cache, and
2516    we may be fooled up by a packet starting with the end of a request
2517    started in a previous packet...
2518 */
2519
2520 static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
2521
2522 static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
2523 {
2524       int res = 0;
2525       while(maskLength--) {
2526             int c = tvb_get_guint8(tvb, offset);
2527             offset++;
2528             res += numberOfBitSetTable[c & 0xf] + numberOfBitSetTable[c >> 4];
2529       }
2530       return res;
2531 }
2532
2533 static int listOfStringLengthConsistent(tvbuff_t *tvb, int offset, int length, int listLength)
2534 {
2535       if (listLength > length) return FALSE;
2536       while(listLength--) {
2537             int l;
2538             if (!tvb_bytes_exist(tvb, offset, 1)) return TRUE;
2539             l = tvb_get_guint8(tvb, offset);
2540             if (!l) break;
2541             l++;
2542             if (l > length) return FALSE;
2543             if (!tvb_bytes_exist(tvb, offset, l)) return TRUE;
2544             offset += l;
2545             length -= l;
2546       }
2547       if (length > 3) return FALSE;
2548       return TRUE;
2549 }
2550
2551 static int rounded4(int n)
2552 {
2553       int remainder = n % 4;
2554       int res = n / 4;
2555       if (remainder) res++;
2556       return res;
2557 }
2558
2559 /* We assume the order to be consistent, until proven wrong. */
2560
2561 static gboolean consistentWithOrder(int length, tvbuff_t *tvb, int offset, guint16 (*v16)(tvbuff_t *, gint))
2562 {
2563       switch(tvb_get_guint8(tvb, offset)) {
2564           case X_CreateWindow:
2565             return !tvb_bytes_exist(tvb, offset, 32) || length == 8 + numberOfBitSet(tvb, offset + 7 * 4, 4);
2566
2567           case X_ChangeWindowAttributes:
2568           case X_ChangeGC:
2569             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + numberOfBitSet(tvb, offset + 8, 4);
2570
2571           case X_GetWindowAttributes:
2572           case X_DestroyWindow:
2573           case X_DestroySubwindows:
2574           case X_ChangeSaveSet:
2575           case X_MapWindow:
2576           case X_MapSubwindows:
2577           case X_UnmapWindow:
2578           case X_UnmapSubwindows:
2579           case X_CirculateWindow:
2580           case X_GetGeometry:
2581           case X_QueryTree:
2582           case X_GetAtomName:
2583           case X_ListProperties:
2584           case X_GetSelectionOwner:
2585           case X_UngrabPointer:
2586           case X_UngrabKeyboard:
2587           case X_AllowEvents:
2588           case X_QueryPointer:
2589           case X_CloseFont:
2590           case X_QueryFont:
2591           case X_FreePixmap:
2592           case X_FreeGC:
2593           case X_FreeColormap:
2594           case X_InstallColormap:
2595           case X_UninstallColormap:
2596           case X_ListInstalledColormaps:
2597           case X_FreeCursor:
2598           case X_GetKeyboardMapping:
2599           case X_KillClient:
2600             return length == 2;
2601
2602           case X_ReparentWindow:
2603           case X_SetSelectionOwner:
2604           case X_ChangeActivePointerGrab:
2605           case X_GrabKeyboard:
2606           case X_GrabKey:
2607           case X_GetMotionEvents:
2608           case X_TranslateCoords:
2609           case X_CreatePixmap:
2610           case X_CopyGC:
2611           case X_ClearArea:
2612           case X_CreateColormap:
2613           case X_AllocColor:
2614           case X_AllocColorPlanes:
2615             return length == 4;
2616
2617           case X_ConfigureWindow:
2618             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + numberOfBitSet(tvb, offset + 8, 2);
2619
2620           case X_InternAtom:
2621           case X_QueryExtension:
2622             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + rounded4(v16(tvb, offset + 4));
2623
2624           case X_ChangeProperty:
2625             {
2626                   int multiplier, type;
2627                   if (!tvb_bytes_exist(tvb, offset, 17)) return TRUE;
2628                   type = tvb_get_guint8(tvb, 16);
2629                   if (type != 8 && type != 16 && type != 32) return FALSE;
2630                   multiplier = type == 8 ? 1 : type == 16 ? 2 : 4;
2631                   if (!tvb_bytes_exist(tvb, offset, 24)) return TRUE;
2632                   return length == 6 + rounded4((v16 == tvb_get_letohs ? tvb_get_letohl : tvb_get_ntohl)(tvb, offset + 20) * multiplier);
2633             }
2634
2635           case X_DeleteProperty:
2636           case X_UngrabButton:
2637           case X_UngrabKey:
2638           case X_SetInputFocus:
2639           case X_CopyColormapAndFree:
2640           case X_AllocColorCells:
2641           case X_QueryBestSize:
2642           case X_ChangePointerControl:
2643           case X_SetScreenSaver:
2644             return length == 3;
2645
2646           case X_GetProperty:
2647           case X_ConvertSelection:
2648           case X_GrabPointer:
2649           case X_GrabButton:
2650           case X_WarpPointer:
2651             return length == 6;
2652
2653           case X_SendEvent:
2654             return length == 11;
2655
2656           case X_GrabServer:
2657           case X_UngrabServer:
2658           case X_GetInputFocus:
2659           case X_QueryKeymap:
2660           case X_GetFontPath:
2661           case X_ListExtensions:
2662           case X_GetKeyboardControl:
2663           case X_Bell:
2664           case X_GetPointerControl:
2665           case X_GetScreenSaver:
2666           case X_ListHosts:
2667           case X_SetAccessControl:
2668           case X_SetCloseDownMode:
2669           case X_ForceScreenSaver:
2670           case X_GetPointerMapping:
2671           case X_GetModifierMapping:
2672             return length == 1;
2673
2674           case X_OpenFont:
2675           case X_AllocNamedColor:
2676           case X_LookupColor:
2677             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + rounded4(v16(tvb, offset + 8));
2678
2679           case X_QueryTextExtents:
2680             return length >= 2;
2681
2682           case X_ListFonts:
2683           case X_ListFontsWithInfo:
2684           case X_ChangeHosts:
2685             return !tvb_bytes_exist(tvb, offset, 8) || length == 2 + rounded4(v16(tvb, offset + 6));
2686
2687           case X_SetFontPath:
2688             if (length < 2) return FALSE;
2689             if (!tvb_bytes_exist(tvb, offset, 8)) return TRUE;
2690             return listOfStringLengthConsistent(tvb, offset + 8, (length - 2) * 4, v16(tvb, offset + 4));
2691
2692           case X_CreateGC:
2693             return !tvb_bytes_exist(tvb, offset, 16) || length == 4 + numberOfBitSet(tvb, offset + 12, 4);
2694
2695           case X_SetDashes:
2696             return !tvb_bytes_exist(tvb, offset, 12) || length == 3 + rounded4(v16(tvb, offset + 10));
2697
2698           case X_SetClipRectangles:
2699           case X_PolySegment:
2700           case X_PolyRectangle:
2701           case X_PolyFillRectangle:
2702             return length >= 3 && (length - 3) % 2 == 0;
2703
2704           case X_CopyArea:
2705             return length == 7;
2706
2707           case X_CopyPlane:
2708           case X_CreateCursor:
2709           case X_CreateGlyphCursor:
2710             return length == 8;
2711
2712           case X_PolyPoint:
2713           case X_PolyLine:
2714           case X_FreeColors:
2715             return length >= 3;
2716
2717           case X_PolyArc:
2718           case X_PolyFillArc:
2719             return length >= 3 && (length - 3) % 3 == 0;
2720
2721           case X_FillPoly:
2722           case X_ImageText8:
2723             return length >= 4;
2724
2725           case X_PutImage:
2726             return length >= 6;
2727
2728           case X_GetImage:
2729           case X_RecolorCursor:
2730             return length == 5;
2731
2732           case X_PolyText8:
2733             if (length < 4) return FALSE;
2734             return TRUE; /* We don't perform many controls on this one */
2735
2736           case X_PolyText16:
2737             if (length < 4) return FALSE;
2738             return TRUE; /* We don't perform many controls on this one */
2739
2740           case X_ImageText16:
2741             return length >= 4;
2742
2743           case X_StoreColors:
2744             return length > 2 && (length - 2) % 3 == 0;
2745
2746           case X_StoreNamedColor:
2747             return !tvb_bytes_exist(tvb, offset, 14) || length == 4 + rounded4(v16(tvb, offset + 12));
2748
2749           case X_QueryColors:
2750             return length >= 2;
2751
2752           case X_ChangeKeyboardMapping:
2753             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + tvb_get_guint8(tvb, 1) * tvb_get_guint8(tvb, 5);
2754
2755           case X_ChangeKeyboardControl:
2756             return !tvb_bytes_exist(tvb, offset, 6) || length == 2 + numberOfBitSet(tvb, offset + 4, 2);
2757
2758           case X_RotateProperties:
2759             return !tvb_bytes_exist(tvb, offset, 10) || length == 3 + v16(tvb, offset + 8);
2760
2761           case X_SetPointerMapping:
2762             return length == 1 + rounded4(tvb_get_guint8(tvb, 1));
2763
2764           case X_SetModifierMapping:
2765             return length == 1 + tvb_get_guint8(tvb, 1) * 2;
2766
2767           case X_NoOperation:
2768             return length >= 1;
2769
2770           default:
2771             return TRUE;
2772       }
2773 }
2774
2775 /* -1 means doesn't match, +1 means match, 0 means don't know */
2776
2777 static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
2778 {
2779       int offset, nextoffset;
2780       int atLeastOne = 0;
2781
2782       for(offset = 0; tvb_bytes_exist(tvb, offset, 4); offset = nextoffset) {
2783             int length;
2784             length = v16(tvb, offset + 2);
2785             if (!length) return -1;
2786             nextoffset = offset + length * 4;
2787             if (!consistentWithOrder(length, tvb, offset, v16)) return -1;
2788             atLeastOne = 1;
2789       }
2790       return atLeastOne;
2791 }
2792
2793 static gboolean
2794 guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
2795                     x11_conv_data_t *state)
2796 {
2797       /* With X the client gives the byte ordering for the protocol,
2798          and the port on the server tells us we're speaking X. */
2799
2800       int le, be, decision, decisionToCache;
2801
2802       if (state->byte_order == BYTE_ORDER_BE)
2803             return FALSE;       /* known to be big-endian */
2804       else if (state->byte_order == BYTE_ORDER_LE)
2805             return TRUE;        /* known to be little-endian */
2806
2807       if (pinfo->srcport == pinfo->match_port) {
2808             /*
2809              * This is a reply or event; we don't try to guess the
2810              * byte order on it for now.
2811              */
2812             return TRUE;
2813       }
2814
2815       le = x_endian_match(tvb, tvb_get_letohs);
2816       be = x_endian_match(tvb, tvb_get_ntohs);
2817
2818       /* remember that "decision" really means "little_endian". */
2819       if (le == be) {
2820             /* We have no reason to believe it's little- rather than
2821                big-endian, so we guess the shortest length is the
2822                right one.
2823             */
2824             if (!tvb_bytes_exist(tvb, 0, 4))
2825                   /* Not even a way to get the length. We're biased
2826                      toward little endianness here (essentially the
2827                      x86 world right now). Decoding won't go very far
2828                      anyway.
2829                   */
2830                   decision = TRUE;
2831             else
2832                   decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
2833       } else
2834           decision = le >= be;
2835
2836       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
2837       if (decisionToCache) {
2838             /*
2839              * Remember the decision.
2840              */
2841             state->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
2842       }
2843
2844       /*
2845       fprintf(stderr, "packet %d\tle %d\tbe %d\tlittle_endian %d\tcache %d\n",
2846               pinfo->fd -> num, le, be, decision, decisionToCache);
2847       */
2848       return decision;
2849 }
2850
2851 /************************************************************************
2852  ***                                                                  ***
2853  ***              D E C O D I N G   O N E   P A C K E T               ***
2854  ***                                                                  ***
2855  ************************************************************************/
2856
2857 /*
2858  * Decode an initial connection request.
2859  */
2860 static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
2861     proto_tree *tree, x11_conv_data_t *state, gboolean little_endian)
2862 {
2863       int offset = 0;
2864       int *offsetp = &offset;
2865       proto_item *ti;
2866       proto_tree *t;
2867       guint16 auth_proto_name_length, auth_proto_data_length;
2868       gint left;
2869
2870       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2871       proto_item_append_text(ti, ", Request, Initial connection request");
2872       t = proto_item_add_subtree(ti, ett_x11);
2873
2874       CARD8(byte_order);
2875       UNUSED(1);
2876       CARD16(protocol_major_version);
2877       CARD16(protocol_minor_version);
2878       auth_proto_name_length = CARD16(authorization_protocol_name_length);
2879       auth_proto_data_length = CARD16(authorization_protocol_data_length);
2880       UNUSED(2);
2881
2882       if (auth_proto_name_length != 0) {
2883             STRING8(authorization_protocol_name, auth_proto_name_length);
2884             offset = ROUND_LENGTH(offset);
2885       }
2886
2887       if (auth_proto_data_length != 0) {
2888             STRING8(authorization_protocol_data, auth_proto_data_length);
2889             offset = ROUND_LENGTH(offset);
2890       }
2891
2892       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2893                 proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left,
2894                 little_endian);
2895
2896       /*
2897        * This is the initial connection request...
2898        */
2899       state->iconn_frame = pinfo->fd->num;
2900
2901       /*
2902        * ...and we're expecting a reply to it.
2903        */
2904       state->sequencenumber = 0;
2905       g_hash_table_insert(state->seqtable, GINT_TO_POINTER(state->sequencenumber),
2906                           (int *)INITIAL_CONN);
2907 }
2908
2909 static void dissect_x11_initial_reply(tvbuff_t *tvb, packet_info *pinfo,
2910     proto_tree *tree, const char _U_ *sep, x11_conv_data_t *volatile state,
2911     gboolean little_endian)
2912 {
2913         int offset = 0, *offsetp = &offset, left;
2914         unsigned char success;
2915         int length_of_vendor;
2916         int length_of_reason;
2917         proto_item *ti;
2918         proto_tree *t;
2919
2920         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2921         proto_item_append_text(ti, ", Reply, Initial connection reply");
2922         t = proto_item_add_subtree(ti, ett_x11);
2923
2924         state->iconn_reply = pinfo->fd->num;
2925         success = INT8(success);
2926         if (success) {
2927                 UNUSED(1);
2928                 length_of_reason = 0;
2929         }
2930         else {
2931                 length_of_reason = INT8(length_of_reason);
2932         }
2933
2934         INT16(protocol_major_version);
2935         INT16(protocol_minor_version);
2936         INT16(replylength);
2937         if (success) {
2938                 INT32(release_number);
2939                 INT32(resource_id_base);
2940                 INT32(resource_id_mask);
2941                 INT32(motion_buffer_size);
2942                 length_of_vendor = INT16(length_of_vendor);
2943                 INT16(maximum_request_length);
2944                 INT8(number_of_screens_in_roots);
2945                 INT8(number_of_formats_in_pixmap_formats);
2946                 INT8(image_byte_order);
2947                 INT8(bitmap_format_bit_order);
2948                 INT8(bitmap_format_scanline_unit);
2949                 INT8(bitmap_format_scanline_pad);
2950                 INT8(min_keycode);
2951                 INT8(max_keycode);
2952                 UNUSED(4);
2953                 STRING8(vendor, length_of_vendor);
2954         } else {
2955                 STRING8(reason, length_of_reason);
2956         }
2957
2958         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
2959             UNDECODED(left);
2960
2961 }
2962
2963 static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
2964     proto_tree *tree, const char *sep, x11_conv_data_t *state,
2965     gboolean little_endian)
2966 {
2967       int offset = 0;
2968       int *offsetp = &offset;
2969       int next_offset;
2970       proto_item *ti;
2971       proto_tree *t;
2972       int length, opcode, i;
2973       guint8 v8, v8_2, v8_3;
2974       guint16 v16;
2975       guint32 v32;
2976       gint left;
2977       gchar *name;
2978
2979       length = VALUE16(tvb, 2) * 4;
2980
2981       if (length < 4) {
2982             /* Bogus message length? */
2983             return;
2984       }
2985
2986       next_offset = offset + length;
2987
2988       ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
2989       t = proto_item_add_subtree(ti, ett_x11);
2990
2991       if (PACKET_IS_NEW(pinfo))
2992             ++state->sequencenumber;
2993
2994       OPCODE();
2995
2996       if (check_col(pinfo->cinfo, COL_INFO))
2997           col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
2998                           val_to_str(opcode, state->opcode_vals, 
2999                                      "<Unknown opcode %d>"));
3000
3001       proto_item_append_text(ti, ", Request, opcode: %d (%s)", 
3002                              opcode, val_to_str(opcode, state->opcode_vals,
3003                                                 "<Unknown opcode %d>"));
3004
3005       /*
3006        * Does this request expect a reply?
3007        */
3008       switch(opcode) {
3009
3010       case X_QueryExtension:
3011
3012                 /* necessary processing even if tree == NULL */
3013
3014                 v16 = VALUE16(tvb, 4);
3015                 name = g_malloc(v16 + 1);
3016                 stringCopy(name, tvb_get_ptr(tvb, 8, v16), v16);
3017
3018                 /* store string of extension, opcode will be set at reply */
3019                 i = 0;
3020                 while(i < MAX_OPCODES) {
3021                         if (state->opcode_vals[i].strptr == NULL) {
3022                                 state->opcode_vals[i].strptr = name;
3023                                 g_hash_table_insert(state->valtable,
3024                                                     GINT_TO_POINTER(state->sequencenumber), 
3025                                                     (int *)&state->opcode_vals[i]);
3026                                 break;
3027                         } else if (strcmp(state->opcode_vals[i].strptr,
3028                                           name) == 0) {
3029                                 g_hash_table_insert(state->valtable,
3030                                                     GINT_TO_POINTER(state->sequencenumber), 
3031                                                     (int *)&state->opcode_vals[i]);
3032                                 break;
3033                         }
3034                         i++;
3035                 }
3036
3037                 /* QueryExtension expects a reply, fall through */
3038
3039       case X_AllocColor:
3040       case X_AllocColorCells:
3041       case X_AllocColorPlanes:
3042       case X_AllocNamedColor:
3043       case X_GetAtomName:
3044       case X_GetFontPath:
3045       case X_GetGeometry:
3046       case X_GetImage:
3047       case X_GetInputFocus:
3048       case X_GetKeyboardControl:
3049       case X_GetKeyboardMapping:
3050       case X_GetModifierMapping:
3051       case X_GetMotionEvents:
3052       case X_GetPointerControl:
3053       case X_GetPointerMapping:
3054       case X_GetProperty:
3055       case X_GetScreenSaver:
3056       case X_GetSelectionOwner:
3057       case X_GetWindowAttributes:
3058       case X_GrabKeyboard:
3059       case X_GrabPointer:
3060       case X_InternAtom:
3061       case X_ListExtensions:
3062       case X_ListFonts:
3063       case X_ListFontsWithInfo:
3064       case X_ListHosts:
3065       case X_ListInstalledColormaps:
3066       case X_ListProperties:
3067       case X_LookupColor:
3068       case X_QueryBestSize:
3069       case X_QueryColors:
3070       case X_QueryFont:
3071       case X_QueryKeymap:
3072       case X_QueryPointer:
3073       case X_QueryTextExtents:
3074       case X_QueryTree:
3075       case X_SetModifierMapping:
3076       case X_SetPointerMapping:
3077       case X_TranslateCoords:
3078                 /*
3079                  * Those requests expect a reply.
3080                  */
3081                 g_hash_table_insert(state->seqtable,
3082                                     GINT_TO_POINTER(state->sequencenumber), 
3083                                     GINT_TO_POINTER(opcode));
3084
3085                 break;
3086
3087       default:
3088                 /* 
3089                  * With Extension, we don't know, so assume there could be one
3090                  */
3091                 if (opcode >= X_FirstExtension && opcode <= X_LastExtension) {
3092                         g_hash_table_insert(state->seqtable,
3093                                             GINT_TO_POINTER(state->sequencenumber), 
3094                                             GINT_TO_POINTER(opcode));
3095                 }
3096
3097                 /*
3098                  * No reply is expected from any other request.
3099                  */
3100                 break;
3101       }
3102
3103       if (tree == NULL)
3104          return; 
3105
3106       switch(opcode) {
3107
3108       case X_CreateWindow:
3109             CARD8(depth);
3110             REQUEST_LENGTH();
3111             WINDOW(wid);
3112             WINDOW(parent);
3113             INT16(x);
3114             INT16(y);
3115             CARD16(width);
3116             CARD16(height);
3117             CARD16(border_width);
3118             ENUM16(window_class);
3119             VISUALID(visual);
3120             windowAttributes(tvb, offsetp, t, little_endian);
3121             break;
3122
3123       case X_ChangeWindowAttributes:
3124             UNUSED(1);
3125             REQUEST_LENGTH();
3126             WINDOW(window);
3127             windowAttributes(tvb, offsetp, t, little_endian);
3128             break;
3129
3130       case X_GetWindowAttributes:
3131       case X_DestroyWindow:
3132       case X_DestroySubwindows:
3133             UNUSED(1);
3134             REQUEST_LENGTH();
3135             WINDOW(window);
3136             break;
3137
3138       case X_ChangeSaveSet:
3139             ENUM8(save_set_mode);
3140             REQUEST_LENGTH();
3141             WINDOW(window);
3142             break;
3143
3144       case X_ReparentWindow:
3145             UNUSED(1);
3146             REQUEST_LENGTH();
3147             WINDOW(window);
3148             WINDOW(parent);
3149             INT16(x);
3150             INT16(y);
3151             break;
3152
3153       case X_MapWindow:
3154       case X_MapSubwindows:
3155       case X_UnmapWindow:
3156       case X_UnmapSubwindows:
3157             UNUSED(1);
3158             REQUEST_LENGTH();
3159             WINDOW(window);
3160             break;
3161
3162       case X_ConfigureWindow:
3163             UNUSED(1);
3164             REQUEST_LENGTH();
3165             WINDOW(window);
3166             BITMASK16(configure_window);
3167             UNUSED(2);
3168             BITFIELD(INT16,  configure_window_mask, x);
3169             BITFIELD(INT16,  configure_window_mask, y);
3170             BITFIELD(CARD16, configure_window_mask, width);
3171             BITFIELD(CARD16, configure_window_mask, height);
3172             BITFIELD(CARD16, configure_window_mask, border_width);
3173             BITFIELD(WINDOW, configure_window_mask, sibling);
3174             BITFIELD(ENUM8,  configure_window_mask, stack_mode);
3175             ENDBITMASK;
3176             PAD();
3177             break;
3178
3179       case X_CirculateWindow:
3180             ENUM8(direction);
3181             REQUEST_LENGTH();
3182             WINDOW(window);
3183             break;
3184
3185       case X_GetGeometry:
3186       case X_QueryTree:
3187             UNUSED(1);
3188             REQUEST_LENGTH();
3189             DRAWABLE(drawable);
3190             break;
3191
3192       case X_InternAtom:
3193             BOOL(only_if_exists);
3194             REQUEST_LENGTH();
3195             v16 = FIELD16(name_length);
3196             UNUSED(2);
3197             STRING8(name, v16);
3198             PAD();
3199             break;
3200
3201       case X_GetAtomName:
3202             UNUSED(1);
3203             REQUEST_LENGTH();
3204             ATOM(atom);
3205             break;
3206
3207       case X_ChangeProperty:
3208             ENUM8(mode);
3209             REQUEST_LENGTH();
3210             WINDOW(window);
3211             ATOM(property);
3212             ATOM(type);
3213             CARD8(format);
3214             UNUSED(3);
3215             v32 = CARD32(data_length);
3216             LISTofBYTE(data, v32);
3217             PAD();
3218             break;
3219
3220       case X_DeleteProperty:
3221             UNUSED(1);
3222             REQUEST_LENGTH();
3223             WINDOW(window);
3224             ATOM(property);
3225             break;
3226
3227       case X_GetProperty:
3228             BOOL(delete);
3229             REQUEST_LENGTH();
3230             WINDOW(window);
3231             ATOM(property);
3232             ATOM(get_property_type);
3233             CARD32(long_offset);
3234             CARD32(long_length);
3235             break;
3236
3237       case X_ListProperties:
3238             UNUSED(1);
3239             REQUEST_LENGTH();
3240             WINDOW(window);
3241             break;
3242
3243       case X_SetSelectionOwner:
3244             UNUSED(1);
3245             REQUEST_LENGTH();
3246             WINDOW(owner);
3247             ATOM(selection);
3248             TIMESTAMP(time);
3249             break;
3250
3251       case X_GetSelectionOwner:
3252             UNUSED(1);
3253             REQUEST_LENGTH();
3254             ATOM(selection);
3255             break;
3256
3257       case X_ConvertSelection:
3258             UNUSED(1);
3259             REQUEST_LENGTH();
3260             WINDOW(requestor);
3261             ATOM(selection);
3262             ATOM(target);
3263             ATOM(property);
3264             TIMESTAMP(time);
3265             break;
3266
3267       case X_SendEvent:
3268             BOOL(propagate);
3269             REQUEST_LENGTH();
3270             WINDOW(destination);
3271             SETofEVENT(event_mask);
3272             UNDECODED(32);
3273             break;
3274
3275       case X_GrabPointer:
3276             BOOL(owner_events);
3277             REQUEST_LENGTH();
3278             WINDOW(grab_window);
3279             SETofPOINTEREVENT(pointer_event_mask);
3280             ENUM8(pointer_mode);
3281             ENUM8(keyboard_mode);
3282             WINDOW(confine_to);
3283             CURSOR(cursor);
3284             TIMESTAMP(time);
3285             break;
3286
3287       case X_UngrabPointer:
3288             UNUSED(1);
3289             REQUEST_LENGTH();
3290             TIMESTAMP(time);
3291             break;
3292
3293       case X_GrabButton:
3294             BOOL(owner_events);
3295             REQUEST_LENGTH();
3296             WINDOW(grab_window);
3297             SETofPOINTEREVENT(event_mask);
3298             ENUM8(pointer_mode);
3299             ENUM8(keyboard_mode);
3300             WINDOW(confine_to);
3301             CURSOR(cursor);
3302             BUTTON(button);
3303             UNUSED(1);
3304             SETofKEYMASK(modifiers);
3305             break;
3306
3307       case X_UngrabButton:
3308             BUTTON(button);
3309             REQUEST_LENGTH();
3310             WINDOW(grab_window);
3311             SETofKEYMASK(modifiers);
3312             UNUSED(2);
3313             break;
3314
3315       case X_ChangeActivePointerGrab:
3316             UNUSED(1);
3317             REQUEST_LENGTH();
3318             CURSOR(cursor);
3319             TIMESTAMP(time);
3320             SETofPOINTEREVENT(event_mask);
3321             UNUSED(2);
3322             break;
3323
3324       case X_GrabKeyboard:
3325             BOOL(owner_events);
3326             REQUEST_LENGTH();
3327             WINDOW(grab_window);
3328             TIMESTAMP(time);
3329             ENUM8(pointer_mode);
3330             ENUM8(keyboard_mode);
3331             UNUSED(2);
3332             break;
3333
3334       case X_UngrabKeyboard:
3335             UNUSED(1);
3336             REQUEST_LENGTH();
3337             TIMESTAMP(time);
3338             break;
3339
3340       case X_GrabKey:
3341             BOOL(owner_events);
3342             REQUEST_LENGTH();
3343             WINDOW(grab_window);
3344             SETofKEYMASK(modifiers);
3345             KEYCODE(key);
3346             ENUM8(pointer_mode);
3347             ENUM8(keyboard_mode);
3348             UNUSED(3);
3349             break;
3350
3351       case X_UngrabKey:
3352             KEYCODE(key);
3353             REQUEST_LENGTH();
3354             WINDOW(grab_window);
3355             SETofKEYMASK(modifiers);
3356             UNUSED(2);
3357             break;
3358
3359       case X_AllowEvents:
3360             ENUM8(allow_events_mode);
3361             REQUEST_LENGTH();
3362             TIMESTAMP(time);
3363             break;
3364
3365       case X_GrabServer:
3366             UNUSED(1);
3367             REQUEST_LENGTH();
3368             break;
3369
3370       case X_UngrabServer:
3371             UNUSED(1);
3372             REQUEST_LENGTH();
3373             break;
3374
3375       case X_QueryPointer:
3376             UNUSED(1);
3377             REQUEST_LENGTH();
3378             WINDOW(window);
3379             break;
3380
3381       case X_GetMotionEvents:
3382             UNUSED(1);
3383             REQUEST_LENGTH();
3384             WINDOW(window);
3385             TIMESTAMP(start);
3386             TIMESTAMP(stop);
3387             break;
3388
3389       case X_TranslateCoords:
3390             UNUSED(1);
3391             REQUEST_LENGTH();
3392             WINDOW(src_window);
3393             WINDOW(dst_window);
3394             INT16(src_x);
3395             INT16(src_y);
3396             break;
3397
3398       case X_WarpPointer:
3399             UNUSED(1);
3400             REQUEST_LENGTH();
3401             WINDOW(warp_pointer_src_window);
3402             WINDOW(warp_pointer_dst_window);
3403             INT16(src_x);
3404             INT16(src_y);
3405             CARD16(src_width);
3406             CARD16(src_height);
3407             INT16(dst_x);
3408             INT16(dst_y);
3409             break;
3410
3411       case X_SetInputFocus:
3412             ENUM8(revert_to);
3413             REQUEST_LENGTH();
3414             WINDOW(focus);
3415             TIMESTAMP(time);
3416             break;
3417
3418       case X_GetInputFocus:
3419             UNUSED(1);
3420             REQUEST_LENGTH();
3421             break;
3422
3423       case X_QueryKeymap:
3424             UNUSED(1);
3425             REQUEST_LENGTH();
3426             break;
3427
3428       case X_OpenFont:
3429             UNUSED(1);
3430             REQUEST_LENGTH();
3431             FONT(fid);
3432             v16 = FIELD16(name_length);
3433             UNUSED(2);
3434             STRING8(name, v16);
3435             PAD();
3436             break;
3437
3438       case X_CloseFont:
3439             UNUSED(1);
3440             REQUEST_LENGTH();
3441             FONT(font);
3442             break;
3443
3444       case X_QueryFont:
3445             UNUSED(1);
3446             REQUEST_LENGTH();
3447             FONTABLE(font);
3448             break;
3449
3450       case X_QueryTextExtents:
3451             v8 = BOOL(odd_length);
3452             REQUEST_LENGTH();
3453             FONTABLE(font);
3454             STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
3455             PAD();
3456             break;
3457
3458       case X_ListFonts:
3459             UNUSED(1);
3460             REQUEST_LENGTH();
3461             CARD16(max_names);
3462             v16 = FIELD16(pattern_length);
3463             STRING8(pattern, v16);
3464             PAD();
3465             break;
3466
3467       case X_ListFontsWithInfo:
3468             UNUSED(1);
3469             REQUEST_LENGTH();
3470             CARD16(max_names);
3471             v16 = FIELD16(pattern_length);
3472             STRING8(pattern, v16);
3473             PAD();
3474             break;
3475
3476       case X_SetFontPath:
3477             UNUSED(1);
3478             REQUEST_LENGTH();
3479             v16 = CARD16(str_number_in_path);
3480             UNUSED(2);
3481             LISTofSTRING8(path, v16);
3482             PAD();
3483             break;
3484
3485       case X_GetFontPath:
3486             UNUSED(1);
3487             REQUEST_LENGTH();
3488             break;
3489
3490       case X_CreatePixmap:
3491             CARD8(depth);
3492             REQUEST_LENGTH();
3493             PIXMAP(pid);
3494             DRAWABLE(drawable);
3495             CARD16(width);
3496             CARD16(height);
3497             break;
3498
3499       case X_FreePixmap:
3500             UNUSED(1);
3501             REQUEST_LENGTH();
3502             PIXMAP(pixmap);
3503             break;
3504
3505       case X_CreateGC:
3506             UNUSED(1);
3507             REQUEST_LENGTH();
3508             GCONTEXT(cid);
3509             DRAWABLE(drawable);
3510             gcAttributes(tvb, offsetp, t, little_endian);
3511             break;
3512
3513       case X_ChangeGC:
3514             UNUSED(1);
3515             REQUEST_LENGTH();
3516             GCONTEXT(gc);
3517             gcAttributes(tvb, offsetp, t, little_endian);
3518             break;
3519
3520       case X_CopyGC:
3521             UNUSED(1);
3522             REQUEST_LENGTH();
3523             GCONTEXT(src_gc);
3524             GCONTEXT(dst_gc);
3525             gcMask(tvb, offsetp, t, little_endian);
3526             break;
3527
3528       case X_SetDashes:
3529             UNUSED(1);
3530             REQUEST_LENGTH();
3531             GCONTEXT(gc);
3532             CARD16(dash_offset);
3533             v16 = FIELD16(dashes_length);
3534             LISTofCARD8(dashes, v16);
3535             PAD();
3536             break;
3537
3538       case X_SetClipRectangles:
3539             ENUM8(ordering);
3540             REQUEST_LENGTH();
3541             GCONTEXT(gc);
3542             INT16(clip_x_origin);
3543             INT16(clip_y_origin);
3544             LISTofRECTANGLE(rectangles);
3545             break;
3546
3547       case X_FreeGC:
3548             UNUSED(1);
3549             REQUEST_LENGTH();
3550             GCONTEXT(gc);
3551             break;
3552
3553       case X_ClearArea:
3554             BOOL(exposures);
3555             REQUEST_LENGTH();
3556             WINDOW(window);
3557             INT16(x);
3558             INT16(y);
3559             CARD16(width);
3560             CARD16(height);
3561             break;
3562
3563       case X_CopyArea:
3564             UNUSED(1);
3565             REQUEST_LENGTH();
3566             DRAWABLE(src_drawable);
3567             DRAWABLE(dst_drawable);
3568             GCONTEXT(gc);
3569             INT16(src_x);
3570             INT16(src_y);
3571             INT16(dst_x);
3572             INT16(dst_y);
3573             CARD16(width);
3574             CARD16(height);
3575             break;
3576
3577       case X_CopyPlane:
3578             UNUSED(1);
3579             REQUEST_LENGTH();
3580             DRAWABLE(src_drawable);
3581             DRAWABLE(dst_drawable);
3582             GCONTEXT(gc);
3583             INT16(src_x);
3584             INT16(src_y);
3585             INT16(dst_x);
3586             INT16(dst_y);
3587             CARD16(width);
3588             CARD16(height);
3589             CARD32(bit_plane);
3590             break;
3591
3592       case X_PolyPoint:
3593             ENUM8(coordinate_mode);
3594             v16 = REQUEST_LENGTH();
3595             DRAWABLE(drawable);
3596             GCONTEXT(gc);
3597             LISTofPOINT(points, v16 - 12);
3598             break;
3599
3600       case X_PolyLine:
3601             ENUM8(coordinate_mode);
3602             v16 = REQUEST_LENGTH();
3603             DRAWABLE(drawable);
3604             GCONTEXT(gc);
3605             LISTofPOINT(points, v16 - 12);
3606             break;
3607
3608       case X_PolySegment:
3609             UNUSED(1);
3610             REQUEST_LENGTH();
3611             DRAWABLE(drawable);
3612             GCONTEXT(gc);
3613             LISTofSEGMENT(segments);
3614             break;
3615
3616       case X_PolyRectangle:
3617             UNUSED(1);
3618             REQUEST_LENGTH();
3619             DRAWABLE(drawable);
3620             GCONTEXT(gc);
3621             LISTofRECTANGLE(rectangles);
3622             break;
3623
3624       case X_PolyArc:
3625             UNUSED(1);
3626             REQUEST_LENGTH();
3627             DRAWABLE(drawable);
3628             GCONTEXT(gc);
3629             LISTofARC(arcs);
3630             break;
3631
3632       case X_FillPoly:
3633             UNUSED(1);
3634             v16 = REQUEST_LENGTH();
3635             DRAWABLE(drawable);
3636             GCONTEXT(gc);
3637             ENUM8(shape);
3638             ENUM8(coordinate_mode);
3639             UNUSED(2);
3640             LISTofPOINT(points, v16 - 16);
3641             break;
3642
3643       case X_PolyFillRectangle:
3644             UNUSED(1);
3645             REQUEST_LENGTH();
3646             DRAWABLE(drawable);
3647             GCONTEXT(gc);
3648             LISTofRECTANGLE(rectangles);
3649             break;
3650
3651       case X_PolyFillArc:
3652             UNUSED(1);
3653             REQUEST_LENGTH();
3654             DRAWABLE(drawable);
3655             GCONTEXT(gc);
3656             LISTofARC(arcs);
3657             break;
3658
3659       case X_PutImage:
3660             ENUM8(image_format);
3661             v16 = REQUEST_LENGTH();
3662             DRAWABLE(drawable);
3663             GCONTEXT(gc);
3664             CARD16(width);
3665             CARD16(height);
3666             INT16(dst_x);
3667             INT16(dst_y);
3668             CARD8(left_pad);
3669             CARD8(depth);
3670             UNUSED(2);
3671             LISTofBYTE(data, v16 - 24);
3672             PAD();
3673             break;
3674
3675       case X_GetImage:
3676             ENUM8(image_pixmap_format);
3677             REQUEST_LENGTH();
3678             DRAWABLE(drawable);
3679             INT16(x);
3680             INT16(y);
3681             CARD16(width);
3682             CARD16(height);
3683             CARD32(plane_mask);
3684             break;
3685
3686       case X_PolyText8:
3687             UNUSED(1);
3688             v16 = REQUEST_LENGTH();
3689             DRAWABLE(drawable);
3690             GCONTEXT(gc);
3691             INT16(x);
3692             INT16(y);
3693             LISTofTEXTITEM8(items);
3694             PAD();
3695             break;
3696
3697       case X_PolyText16:
3698             UNUSED(1);
3699             v16 = REQUEST_LENGTH();
3700             DRAWABLE(drawable);
3701             GCONTEXT(gc);
3702             INT16(x);
3703             INT16(y);
3704             LISTofTEXTITEM16(items);
3705             PAD();
3706             break;
3707
3708       case X_ImageText8:
3709             v8 = FIELD8(string_length);
3710             REQUEST_LENGTH();
3711             DRAWABLE(drawable);
3712             GCONTEXT(gc);
3713             INT16(x);
3714             INT16(y);
3715             STRING8(string, v8);
3716             PAD();
3717             break;
3718
3719       case X_ImageText16:
3720             v8 = FIELD8(string_length);
3721             REQUEST_LENGTH();
3722             DRAWABLE(drawable);
3723             GCONTEXT(gc);
3724             INT16(x);
3725             INT16(y);
3726             STRING16(string16, v8);
3727             PAD();
3728             break;
3729
3730       case X_CreateColormap:
3731             ENUM8(alloc);
3732             REQUEST_LENGTH();
3733             COLORMAP(mid);
3734             WINDOW(window);
3735             VISUALID(visual);
3736             break;
3737
3738       case X_FreeColormap:
3739             UNUSED(1);
3740             REQUEST_LENGTH();
3741             COLORMAP(cmap);
3742             break;
3743
3744       case X_CopyColormapAndFree:
3745             UNUSED(1);
3746             REQUEST_LENGTH();
3747             COLORMAP(mid);
3748             COLORMAP(src_cmap);
3749             break;
3750
3751       case X_InstallColormap:
3752             UNUSED(1);
3753             REQUEST_LENGTH();
3754             COLORMAP(cmap);
3755             break;
3756
3757       case X_UninstallColormap:
3758             UNUSED(1);
3759             REQUEST_LENGTH();
3760             COLORMAP(cmap);
3761             break;
3762
3763       case X_ListInstalledColormaps:
3764             UNUSED(1);
3765             REQUEST_LENGTH();
3766             WINDOW(window);
3767             break;
3768
3769       case X_AllocColor:
3770             UNUSED(1);
3771             REQUEST_LENGTH();
3772             COLORMAP(cmap);
3773             CARD16(red);
3774             CARD16(green);
3775             CARD16(blue);
3776             UNUSED(2);
3777             break;
3778
3779       case X_AllocNamedColor:
3780             UNUSED(1);
3781             REQUEST_LENGTH();
3782             COLORMAP(cmap);
3783             v16 = FIELD16(name_length);
3784             UNUSED(2);
3785             STRING8(name, v16);
3786             PAD();
3787             break;
3788
3789       case X_AllocColorCells:
3790             BOOL(contiguous);
3791             REQUEST_LENGTH();
3792             COLORMAP(cmap);
3793             CARD16(colors);
3794             CARD16(planes);
3795             break;
3796
3797       case X_AllocColorPlanes:
3798             BOOL(contiguous);
3799             REQUEST_LENGTH();
3800             COLORMAP(cmap);
3801             CARD16(colors);
3802             CARD16(reds);
3803             CARD16(greens);
3804             CARD16(blues);
3805             break;
3806
3807       case X_FreeColors:
3808             UNUSED(1);
3809             v16 = REQUEST_LENGTH();
3810             COLORMAP(cmap);
3811             CARD32(plane_mask);
3812             LISTofCARD32(pixels, v16 - 12);
3813             break;
3814
3815       case X_StoreColors:
3816             UNUSED(1);
3817             v16 = REQUEST_LENGTH();
3818             COLORMAP(cmap);
3819             LISTofCOLORITEM(color_items, v16 - 8);
3820             break;
3821
3822       case X_StoreNamedColor:
3823             COLOR_FLAGS(color);
3824             REQUEST_LENGTH();
3825             COLORMAP(cmap);
3826             CARD32(pixel);
3827             v16 = FIELD16(name_length);
3828             UNUSED(2);
3829             STRING8(name, v16);
3830             PAD();
3831             break;
3832
3833       case X_QueryColors:
3834             UNUSED(1);
3835             v16 = REQUEST_LENGTH();
3836             COLORMAP(cmap);
3837             LISTofCARD32(pixels, v16 - 8);
3838             break;
3839
3840       case X_LookupColor:
3841             UNUSED(1);
3842             REQUEST_LENGTH();
3843             COLORMAP(cmap);
3844             v16 = FIELD16(name_length);
3845             UNUSED(2);
3846             STRING8(name, v16);
3847             PAD();
3848             break;
3849
3850       case X_CreateCursor:
3851             UNUSED(1);
3852             REQUEST_LENGTH();
3853             CURSOR(cid);
3854             PIXMAP(source_pixmap);
3855             PIXMAP(mask);
3856             CARD16(fore_red);
3857             CARD16(fore_green);
3858             CARD16(fore_blue);
3859             CARD16(back_red);
3860             CARD16(back_green);
3861             CARD16(back_blue);
3862             CARD16(x);
3863             CARD16(y);
3864             break;
3865
3866       case X_CreateGlyphCursor:
3867             UNUSED(1);
3868             REQUEST_LENGTH();
3869             CURSOR(cid);
3870             FONT(source_font);
3871             FONT(mask_font);
3872             CARD16(source_char);
3873             CARD16(mask_char);
3874             CARD16(fore_red);
3875             CARD16(fore_green);
3876             CARD16(fore_blue);
3877             CARD16(back_red);
3878             CARD16(back_green);
3879             CARD16(back_blue);
3880             break;
3881
3882       case X_FreeCursor:
3883             UNUSED(1);
3884             REQUEST_LENGTH();
3885             CURSOR(cursor);
3886             break;
3887
3888       case X_RecolorCursor:
3889             UNUSED(1);
3890             REQUEST_LENGTH();
3891             CURSOR(cursor);
3892             CARD16(fore_red);
3893             CARD16(fore_green);
3894             CARD16(fore_blue);
3895             CARD16(back_red);
3896             CARD16(back_green);
3897             CARD16(back_blue);
3898             break;
3899
3900       case X_QueryBestSize:
3901             ENUM8(class);
3902             REQUEST_LENGTH();
3903             DRAWABLE(drawable);
3904             CARD16(width);
3905             CARD16(height);
3906             break;
3907
3908       case X_QueryExtension:
3909             UNUSED(1);
3910             REQUEST_LENGTH();
3911             v16 = FIELD16(name_length);
3912             UNUSED(2);
3913             STRING8(name, v16);
3914             PAD();
3915             break;
3916
3917       case X_ListExtensions:
3918             UNUSED(1);
3919             REQUEST_LENGTH();
3920             break;
3921
3922       case X_ChangeKeyboardMapping:
3923             v8 = FIELD8(keycode_count);
3924             REQUEST_LENGTH();
3925             v8_2 = KEYCODE(first_keycode);
3926             v8_3 = FIELD8(keysyms_per_keycode);
3927             UNUSED(2);
3928             LISTofKEYSYM(keysyms, state->keycodemap, v8_2, v8, v8_3);
3929             break;
3930
3931       case X_GetKeyboardMapping:
3932             UNUSED(1);
3933             REQUEST_LENGTH();
3934             state->request.GetKeyboardMapping.first_keycode
3935             = KEYCODE(first_keycode);
3936             FIELD8(count);
3937             UNUSED(2);
3938             break;
3939
3940       case X_ChangeKeyboardControl:
3941             UNUSED(1);
3942             REQUEST_LENGTH();
3943             BITMASK32(keyboard_value);
3944             BITFIELD(INT8, keyboard_value_mask, key_click_percent);
3945             BITFIELD(INT8, keyboard_value_mask, bell_percent);
3946             BITFIELD(INT16, keyboard_value_mask, bell_pitch);
3947             BITFIELD(INT16, keyboard_value_mask, bell_duration);
3948             BITFIELD(INT16, keyboard_value_mask, led);
3949             BITFIELD(ENUM8, keyboard_value_mask, led_mode);
3950             BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
3951             BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
3952             ENDBITMASK;
3953             break;
3954
3955       case X_GetKeyboardControl:
3956             UNUSED(1);
3957             REQUEST_LENGTH();
3958             break;
3959
3960       case X_Bell:
3961             INT8(percent);
3962             REQUEST_LENGTH();
3963             break;
3964
3965       case X_ChangePointerControl:
3966             UNUSED(1);
3967             REQUEST_LENGTH();
3968             INT16(acceleration_numerator);
3969             INT16(acceleration_denominator);
3970             INT16(threshold);
3971             BOOL(do_acceleration);
3972             BOOL(do_threshold);
3973             break;
3974
3975       case X_GetPointerControl:
3976             UNUSED(1);
3977             REQUEST_LENGTH();
3978             break;
3979
3980       case X_SetScreenSaver:
3981             UNUSED(1);
3982             REQUEST_LENGTH();
3983             INT16(timeout);
3984             INT16(interval);
3985             ENUM8(prefer_blanking);
3986             ENUM8(allow_exposures);
3987             UNUSED(2);
3988             break;
3989
3990       case X_GetScreenSaver:
3991             UNUSED(1);
3992             REQUEST_LENGTH();
3993             break;
3994
3995       case X_ChangeHosts:
3996             ENUM8(change_host_mode);
3997             REQUEST_LENGTH();
3998             v8 = ENUM8(family);
3999             UNUSED(1);
4000             v16 = CARD16(address_length);
4001             if (v8 == FAMILY_INTERNET && v16 == 4) {
4002                   /*
4003                    * IPv4 addresses.
4004                    * XXX - what about IPv6?  Is that a family of
4005                    * FAMILY_INTERNET (0) with a length of 16?
4006                    */
4007                   LISTofIPADDRESS(ip_address, v16);
4008             } else
4009                   LISTofCARD8(address, v16);
4010             break;
4011
4012       case X_ListHosts:
4013             UNUSED(1);
4014             REQUEST_LENGTH();
4015             break;
4016
4017       case X_SetAccessControl:
4018             ENUM8(access_mode);
4019             REQUEST_LENGTH();
4020             break;
4021
4022       case X_SetCloseDownMode:
4023             ENUM8(close_down_mode);
4024             REQUEST_LENGTH();
4025             break;
4026
4027       case X_KillClient:
4028             UNUSED(1);
4029             REQUEST_LENGTH();
4030             CARD32(resource);
4031             break;
4032
4033       case X_RotateProperties:
4034             UNUSED(1);
4035             v16 = REQUEST_LENGTH();
4036             WINDOW(window);
4037             CARD16(property_number);
4038             INT16(delta);
4039             LISTofATOM(properties, (v16 - 12));
4040             break;
4041
4042       case X_ForceScreenSaver:
4043             ENUM8(screen_saver_mode);
4044             REQUEST_LENGTH();
4045             break;
4046
4047       case X_SetPointerMapping:
4048             v8 = FIELD8(map_length);
4049             REQUEST_LENGTH();
4050             LISTofCARD8(map, v8);
4051             PAD();
4052             break;
4053
4054       case X_GetPointerMapping:
4055             UNUSED(1);
4056             REQUEST_LENGTH();
4057             break;
4058
4059       case X_SetModifierMapping:
4060             v8 = FIELD8(keycodes_per_modifier);
4061             REQUEST_LENGTH();
4062             LISTofKEYCODE(state->modifiermap, keycodes, v8);
4063             break;
4064
4065       case X_GetModifierMapping:
4066             UNUSED(1);
4067             REQUEST_LENGTH();
4068             break;
4069
4070       case X_NoOperation:
4071             UNUSED(1);
4072             REQUEST_LENGTH();
4073             break;
4074       }
4075
4076       if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4077             UNDECODED(left);
4078 }
4079
4080 static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
4081     proto_tree *tree)
4082 {
4083       volatile int offset = 0;
4084       int length_remaining;
4085       volatile gboolean little_endian;
4086       guint8 opcode;
4087       volatile int plen;
4088       proto_item *ti;
4089       proto_tree *t;
4090       volatile gboolean is_initial_creq;
4091       guint16 auth_proto_len, auth_data_len;
4092       const char *volatile sep = NULL;
4093       conversation_t *conversation;
4094       x11_conv_data_t *volatile state;
4095       int length;
4096       tvbuff_t *next_tvb;
4097
4098       while (tvb_reported_length_remaining(tvb, offset) != 0) {
4099             /*
4100              * We use "tvb_ensure_length_remaining()" to make sure there
4101              * actually *is* data remaining.
4102              *
4103              * This means we're guaranteed that "length_remaining" is
4104              * positive.
4105              */
4106             length_remaining = tvb_ensure_length_remaining(tvb, offset);
4107
4108             /*
4109              * Can we do reassembly?
4110              */
4111             if (x11_desegment && pinfo->can_desegment) {
4112                   /*
4113                    * Yes - is the X11 request header split across
4114                    * segment boundaries?
4115                    */
4116                   if (length_remaining < 4) {
4117                         /*
4118                          * Yes.  Tell the TCP dissector where the data
4119                          * for this message starts in the data it handed
4120                          * us, and how many more bytes we need, and return.
4121                          */
4122                         pinfo->desegment_offset = offset;
4123                         pinfo->desegment_len = 4 - length_remaining;
4124                         return;
4125                   }
4126             }
4127
4128             /*
4129              * Get the state for this conversation; create the conversation
4130              * if we don't have one, and create the state if we don't have
4131              * any.
4132              */
4133             conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4134                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4135             if (conversation == NULL) {
4136                   /*
4137                    * No - create one.
4138                    */
4139                   conversation = conversation_new(pinfo->fd->num, &pinfo->src,
4140                         &pinfo->dst, pinfo->ptype, pinfo->srcport,
4141                         pinfo->destport, 0);
4142             }
4143
4144             /*
4145              * Is there state attached to this conversation?
4146              */
4147             if ((state = conversation_get_proto_data(conversation, proto_x11))
4148             == NULL)
4149                 state = x11_stateinit(conversation);
4150
4151             /*
4152              * Guess the byte order if we don't already know it.
4153              */
4154             little_endian = guess_byte_ordering(tvb, pinfo, state);
4155
4156             /*
4157              * Get the opcode and length of the putative X11 request.
4158              */
4159             opcode = VALUE8(tvb, 0);
4160             plen = VALUE16(tvb, offset + 2);
4161
4162             if (plen == 0) {
4163                   /*
4164                    * This can't be 0, as it includes the header length.
4165                    * A different choice of byte order wouldn't have
4166                    * helped.
4167                    * Give up.
4168                    */
4169                   ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1,
4170                   FALSE);
4171                   t = proto_item_add_subtree(ti, ett_x11);
4172                   proto_tree_add_text(t, tvb, offset, -1,
4173                   "Bogus request length (0)");
4174                   return;
4175             }
4176
4177             if (state->iconn_frame == pinfo->fd->num ||
4178                 (g_hash_table_lookup(state->seqtable,
4179                 GINT_TO_POINTER(state->sequencenumber)) == (int *)NOTHING_SEEN &&
4180                  (opcode == 'B' || opcode == 'l') &&
4181                  (plen == 11 || plen == 2816))) {
4182                   /*
4183                    * Either
4184                    *
4185                    *    we saw this on the first pass and this is
4186                    *    it again
4187                    *
4188                    * or
4189                    *    we haven't already seen any requests, the first
4190                    *    byte of the message is 'B' or 'l', and the 16-bit
4191                    *    integer 2 bytes into the data stream is either 11
4192                    *    or a byte-swapped 11.
4193                    *
4194                    * This means it's probably an initial connection
4195                    * request, not a message.
4196                    *
4197                    * 'B' is decimal 66, which is the opcode for a
4198                    * PolySegment request; unfortunately, 11 is a valid
4199                    * length for a PolySegment request request, so we
4200                    * might mis-identify that request.  (Are there any
4201                    * other checks we can do?)
4202                    *
4203                    * 'l' is decimal 108, which is the opcode for a
4204                    * GetScreenSaver request; the only valid length
4205                    * for that request is 1.
4206                    */
4207                   is_initial_creq = TRUE;
4208
4209                   /*
4210                    * We now know the byte order.  Override the guess.
4211                    */
4212                   if (state->byte_order == BYTE_ORDER_UNKNOWN) {
4213                         if (opcode == 'B') {
4214                               /*
4215                                * Big-endian.
4216                                */
4217                               state->byte_order = BYTE_ORDER_BE;
4218                               little_endian = FALSE;
4219                         } else {
4220                               /*
4221                                * Little-endian.
4222                                */
4223                               state->byte_order = BYTE_ORDER_LE;
4224                               little_endian = TRUE;
4225                         }
4226                   }
4227
4228                   /*
4229                    * Can we do reassembly?
4230                    */
4231                   if (x11_desegment && pinfo->can_desegment) {
4232                         /*
4233                          * Yes - is the fixed-length portion of the
4234                          * initial connection header split across
4235                          * segment boundaries?
4236                          */
4237                         if (length_remaining < 10) {
4238                               /*
4239                                * Yes.  Tell the TCP dissector where the
4240                                * data for this message starts in the data
4241                                * it handed us, and how many more bytes we
4242                                * need, and return.
4243                                */
4244                               pinfo->desegment_offset = offset;
4245                               pinfo->desegment_len = 10 - length_remaining;
4246                               return;
4247                         }
4248                   }
4249
4250                   /*
4251                    * Get the lengths of the authorization protocol and
4252                    * the authorization data.
4253                    */
4254                   auth_proto_len = VALUE16(tvb, offset + 6);
4255                   auth_data_len = VALUE16(tvb, offset + 8);
4256                   plen = 12 + ROUND_LENGTH(auth_proto_len) +
4257                         ROUND_LENGTH(auth_data_len);
4258             } else {
4259                   /*
4260                    * This is probably an ordinary request.
4261                    */
4262                   is_initial_creq = FALSE;
4263
4264                   /*
4265                    * The length of a request is in 4-byte words.
4266                    */
4267                   plen *= 4;
4268             }
4269
4270             /*
4271              * Can we do reassembly?
4272              */
4273             if (x11_desegment && pinfo->can_desegment) {
4274                   /*
4275                    * Yes - is the X11 request split across segment
4276                    * boundaries?
4277                    */
4278                   if (length_remaining < plen) {
4279                         /*
4280                          * Yes.  Tell the TCP dissector where the data
4281                          * for this message starts in the data it handed
4282                          * us, and how many more bytes we need, and return.
4283                          */
4284                         pinfo->desegment_offset = offset;
4285                         pinfo->desegment_len = plen - length_remaining;
4286                         return;
4287                   }
4288             }
4289
4290             /*
4291              * Construct a tvbuff containing the amount of the payload
4292              * we have available.  Make its reported length the
4293              * amount of data in the X11 request.
4294              *
4295              * XXX - if reassembly isn't enabled. the subdissector
4296              * will throw a BoundsError exception, rather than a
4297              * ReportedBoundsError exception.  We really want a tvbuff
4298              * where the length is "length", the reported length is "plen",
4299              * and the "if the snapshot length were infinite" length is the
4300              * minimum of the reported length of the tvbuff handed to us
4301              * and "plen", with a new type of exception thrown if the offset
4302              * is within the reported length but beyond that third length,
4303              * with that exception getting the "Unreassembled Packet" error.
4304              */
4305             length = length_remaining;
4306             if (length > plen)
4307                   length = plen;
4308             next_tvb = tvb_new_subset(tvb, offset, length, plen);
4309
4310             /*
4311              * Set the column appropriately.
4312              */
4313             if (is_initial_creq) {
4314                   if (check_col(pinfo->cinfo, COL_INFO))
4315                         col_set_str(pinfo->cinfo, COL_INFO,
4316                         "Initial connection request");
4317             } else {
4318                   if (sep == NULL) {
4319                         /*
4320                          * We haven't set the column yet; set it.
4321                          */
4322                         if (check_col(pinfo->cinfo, COL_INFO))
4323                               col_add_str(pinfo->cinfo, COL_INFO, "Requests");
4324
4325                         /*
4326                          * Initialize the separator.
4327                          */
4328                         sep = ":";
4329                   }
4330             }
4331
4332             /*
4333              * Dissect the X11 request.
4334              *
4335              * Catch the ReportedBoundsError exception; if this
4336              * particular message happens to get a ReportedBoundsError
4337              * exception, that doesn't mean that we should stop
4338              * dissecting X11 requests within this frame or chunk of
4339              * reassembled data.
4340              *
4341              * If it gets a BoundsError, we can stop, as there's nothing
4342              * more to see, so we just re-throw it.
4343              */
4344             TRY {
4345                   if (is_initial_creq) {
4346                         dissect_x11_initial_conn(next_tvb, pinfo, tree,
4347                             state, little_endian);
4348                   } else {
4349                         dissect_x11_request(next_tvb, pinfo, tree, sep,
4350                             state, little_endian);
4351                   }
4352             }
4353             CATCH(BoundsError) {
4354                   RETHROW;
4355             }
4356             CATCH(ReportedBoundsError) {
4357                   show_reported_bounds_error(tvb, pinfo, tree);
4358             }
4359             ENDTRY;
4360
4361             /*
4362              * Skip the X11 message.
4363              */
4364             offset += plen;
4365
4366             sep = ",";
4367       }
4368 }
4369
4370 static x11_conv_data_t *
4371 x11_stateinit(conversation_t *conversation)
4372 {
4373         x11_conv_data_t *state;
4374         static x11_conv_data_t stateinit;
4375         int i = 0;
4376
4377         state = g_mem_chunk_alloc(x11_state_chunk);
4378         *state = stateinit; 
4379         state->next = x11_conv_data_list;
4380         x11_conv_data_list = state;
4381
4382         /* initialise opcodes */
4383         while (1) {
4384           if (opcode_vals[i].strptr == NULL) break;
4385           state->opcode_vals[i].value = opcode_vals[i].value;
4386           state->opcode_vals[i].strptr = opcode_vals[i].strptr;
4387           i++;
4388         }
4389         while (i <= MAX_OPCODES) {
4390           state->opcode_vals[i].value = 0;
4391           state->opcode_vals[i].strptr = NULL;
4392           i++;
4393         }       
4394
4395         state->seqtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4396         state->valtable = g_hash_table_new(g_direct_hash, g_direct_equal);
4397         g_hash_table_insert(state->seqtable, (int *)0, (int *)NOTHING_SEEN);
4398         state->byte_order = BYTE_ORDER_UNKNOWN; /* don't know yet*/
4399         conversation_add_proto_data(conversation, proto_x11, state);
4400         return state;
4401 }
4402
4403
4404 static void
4405 dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4406 {
4407 /* Set up structures we will need to add the protocol subtree and manage it */
4408         volatile int offset, plen;
4409         tvbuff_t * volatile next_tvb;
4410         conversation_t *conversation;
4411         x11_conv_data_t *volatile state;
4412         gboolean little_endian;
4413         int length_remaining;
4414         const char *volatile sep = NULL;
4415
4416
4417         /*
4418         * Get the state for this conversation; create the conversation
4419         * if we don't have one, and create the state if we don't have
4420         * any.
4421         */
4422         conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4423         pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4424         if (conversation == NULL) {
4425                 /*
4426                  * No - create one.
4427                 */
4428                 conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst,
4429                 pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
4430         }
4431
4432         /*
4433          * Is there state attached to this conversation?
4434         */
4435         if ((state = conversation_get_proto_data(conversation, proto_x11))
4436         == NULL) {
4437                 /*
4438                  * No - create a state structure and attach it.
4439                  */
4440                 state = x11_stateinit(conversation);
4441         }
4442
4443         /*
4444          * Guess the byte order if we don't already know it.
4445          */
4446         little_endian = guess_byte_ordering(tvb, pinfo, state);
4447
4448         offset = 0;
4449         while (tvb_reported_length_remaining(tvb, offset) != 0) {
4450                 /*
4451                  * We use "tvb_ensure_length_remaining()" to make sure there
4452                  * actually *is* data remaining.
4453                  *
4454                  * This means we're guaranteed that "length_remaining" is
4455                  * positive.
4456                  */
4457                 length_remaining = tvb_ensure_length_remaining(tvb, offset);
4458
4459                 /*
4460                 * Can we do reassembly?
4461                 */
4462                 if (x11_desegment && pinfo->can_desegment) {
4463                           /*
4464                            * Yes - is the X11 reply header split across
4465                            * segment boundaries?
4466                            */
4467                           if (length_remaining < 8) {
4468                                 /*
4469                                  * Yes.  Tell the TCP dissector where the data
4470                                  * for this message starts in the data it handed
4471                                  * us, and how many more bytes we need, and
4472                                  * return.
4473                                  */
4474                                 pinfo->desegment_offset = offset;
4475                                 pinfo->desegment_len = 4 - length_remaining;
4476                                 return;
4477                         }
4478                 }
4479
4480                 /*
4481                  * Find out what kind of a reply it is.
4482                  * There are four possible:
4483                  *      - reply to initial connection
4484                  *      - errorreply (a request generated an error)
4485                  *      - requestreply (reply to a request)
4486                  *      - event (some event occured)
4487                  */
4488                 if (g_hash_table_lookup(state->seqtable,
4489                     GINT_TO_POINTER(state->sequencenumber)) == (int *)INITIAL_CONN 
4490                     || (state->iconn_reply == pinfo->fd->num)) {
4491                         /*
4492                          * Either the connection is in the "initial
4493                          * connection" state, or this frame is known
4494                          * to have the initial connection reply.
4495                          * That means this is the initial connection
4496                          * reply.
4497                          */
4498                         plen = 8 + VALUE16(tvb, offset + 6) * 4;
4499
4500                         HANDLE_REPLY(plen, length_remaining,
4501                             "Initial connection reply", 
4502                             dissect_x11_initial_reply); 
4503                 } else {
4504                         /*
4505                          * This isn't an initial connection reply
4506                          * (XXX - unless we missed the initial
4507                          * connection request).  Look at the first
4508                          * byte to determine what it is; errors
4509                          * start with a byte of 0, replies start
4510                          * with a byte of 1, events start with
4511                          * a byte with of 2 or greater.
4512                          */
4513                         switch (tvb_get_guint8(tvb, offset)) {
4514
4515                         case 0:
4516                                 plen = 32;
4517                                 HANDLE_REPLY(plen, length_remaining,
4518                                     "Error", dissect_x11_error); 
4519                                 break;
4520
4521                         case 1:
4522                                 /* replylength is in units of four. */
4523                                 plen = 32 + VALUE32(tvb, offset + 4) * 4;
4524
4525                                 HANDLE_REPLY(plen, length_remaining,
4526                                     "Reply", dissect_x11_reply); 
4527                                 break;
4528
4529                         default:
4530                                 /* Event */
4531                                 plen = 32;
4532                                 HANDLE_REPLY(plen, length_remaining,
4533                                     "Event", dissect_x11_event);
4534                                 break;
4535                         }
4536                 }
4537
4538                 offset += plen;
4539         }
4540
4541         return;
4542 }
4543
4544 static void
4545 dissect_x11_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4546                   const char *volatile sep, x11_conv_data_t *volatile state,
4547                   gboolean little_endian)
4548 {
4549         int offset = 0, *offsetp = &offset, length, left, opcode;
4550         int major_opcode, sequence_number;
4551         value_string *vals_p;
4552         proto_item *ti;
4553         proto_tree *t;
4554         
4555         ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
4556                                  tvb_reported_length_remaining(tvb, offset),
4557                                  FALSE);
4558         t = proto_item_add_subtree(ti, ett_x11);
4559
4560
4561         /*
4562          * XXX - this doesn't work correctly if either
4563          *
4564          *      1) the request sequence number wraps in the lower 16
4565          *         bits;
4566          *
4567          *      2) we don't see the initial connection request and the
4568          *         resynchronization of sequence number fails and thus
4569          *         don't have the right sequence numbers 
4570          *
4571          *      3) we don't have all the packets in the capture and
4572          *         get out of sequence.
4573          *
4574          * We might, instead, want to assume that a reply is a reply to
4575          * the most recent not-already-replied-to request in the same
4576          * connection.  That also might mismatch replies to requests if
4577          * packets are lost, but there's nothing you can do to fix that.
4578          */
4579
4580         sequence_number = VALUE16(tvb, offset + 2);
4581         opcode = GPOINTER_TO_INT(g_hash_table_lookup(state->seqtable,
4582                                           GINT_TO_POINTER(sequence_number)));
4583
4584         if (state->iconn_frame == 0 &&  state->resync == FALSE) {
4585
4586                 /*
4587                  * We don't see the initial connection request and no
4588                  * resynchronization has been performed yet (first reply),
4589                  * set the current sequence number to the one of the 
4590                  * current reply (this is only performed once).
4591                  */
4592                 state->sequencenumber = sequence_number;
4593                 state->resync = TRUE;
4594         }
4595
4596         if (opcode == UNKNOWN_OPCODE) {
4597                 if (check_col(pinfo->cinfo, COL_INFO))
4598                         col_append_fstr(pinfo->cinfo, COL_INFO, 
4599                                         "%s to unknown request", sep);
4600                 proto_item_append_text(ti, ", Reply to unknown request");
4601         } else {
4602                 if (check_col(pinfo->cinfo, COL_INFO))
4603                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4604                                         sep,
4605                                         val_to_str(opcode, state->opcode_vals, 
4606                                                    "<Unknown opcode %d>"));
4607
4608                 proto_item_append_text(ti, ", Reply, opcode: %d (%s)", 
4609                                        opcode, val_to_str(opcode, 
4610                                                           state->opcode_vals,
4611                                                           "<Unknown opcode %d>"));
4612         }
4613
4614         switch (opcode) {
4615
4616                 /*
4617                  * Replies that need special processing outside tree
4618                  */
4619
4620                 case X_QueryExtension:    
4621
4622                         /* 
4623                          * if extension is present and request is known:
4624                          * store opcode of extension in value_string of
4625                          * opcodes
4626                          */
4627                         if (!VALUE8(tvb, offset + 8)) {
4628                                 /* not present */
4629                                 break;
4630                         }
4631
4632                         vals_p = g_hash_table_lookup(state->valtable,
4633                                                      GINT_TO_POINTER(sequence_number));
4634                         if (vals_p != NULL) {
4635                                 major_opcode = VALUE8(tvb, offset + 9);
4636                                 vals_p->value = major_opcode;
4637                                 g_hash_table_remove(state->valtable,
4638                                                     GINT_TO_POINTER(sequence_number));
4639                         }
4640                         break;
4641
4642                 default:
4643                         break;
4644         }
4645
4646         if (tree == NULL)
4647                 return; 
4648
4649         switch (opcode) {
4650                 /*
4651                  * Requests that expect a reply.
4652                  */
4653
4654                 case X_GetWindowAttributes:
4655                         REPLYCONTENTS_COMMON();
4656                         break; 
4657
4658                 case X_GetGeometry:
4659                         REPLY(reply);
4660                         CARD8(depth);
4661                         SEQUENCENUMBER_REPLY(sequencenumber);
4662                         REPLYLENGTH(replylength);
4663                         WINDOW(rootwindow);
4664                         INT16(x);
4665                         INT16(y);
4666                         CARD16(width);
4667                         CARD16(height);
4668                         CARD16(border_width);
4669                         UNUSED(10);
4670                         break;
4671
4672                 case X_QueryTree:
4673                         REPLYCONTENTS_COMMON();
4674                         break; 
4675
4676                 case X_InternAtom:
4677                         REPLY(reply);
4678                         UNUSED(1);
4679                         SEQUENCENUMBER_REPLY(sequencenumber);
4680                         REPLYLENGTH(replylength);
4681                         ATOM(atom);
4682                         UNUSED(20);
4683                         break;
4684
4685                 case X_GetAtomName:
4686                         REPLYCONTENTS_COMMON();
4687                         break; 
4688
4689                 case X_GetProperty:
4690                         REPLY(reply);
4691                         CARD8(format);
4692                         SEQUENCENUMBER_REPLY(sequencenumber);
4693                         length = REPLYLENGTH(replylength);
4694                         ATOM(get_property_type);
4695                         CARD32(bytes_after);
4696                         CARD32(valuelength);
4697                         UNUSED(12);
4698                         break;
4699
4700                 case X_ListProperties:
4701                         REPLY(reply);
4702                         UNUSED(1);
4703                         SEQUENCENUMBER_REPLY(sequencenumber);
4704                         REPLYLENGTH(replylength);
4705                         length = CARD16(property_number);
4706                         UNUSED(22);
4707                         LISTofATOM(properties, length*4);
4708                         break;
4709
4710                 case X_GetSelectionOwner:
4711                         REPLY(reply);
4712                         UNUSED(1);
4713                         SEQUENCENUMBER_REPLY(sequencenumber);
4714                         REPLYLENGTH(replylength);
4715                         WINDOW(owner);
4716                         UNUSED(20);
4717                         break;
4718
4719                 case X_GrabPointer:
4720                 case X_GrabKeyboard:
4721                         REPLY(reply);
4722                         ENUM8(grab_status);
4723                         SEQUENCENUMBER_REPLY(sequencenumber);
4724                         REPLYLENGTH(replylength);
4725                         UNUSED(24);
4726                         break;
4727
4728                 case X_QueryPointer:
4729                         REPLY(reply);
4730                         BOOL(same_screen);
4731                         SEQUENCENUMBER_REPLY(sequencenumber);
4732                         REPLYLENGTH(replylength);
4733                         WINDOW(rootwindow);
4734                         WINDOW(childwindow);
4735                         INT16(root_x);
4736                         INT16(root_y);
4737                         INT16(win_x);
4738                         INT16(win_y);
4739                         SETofKEYBUTMASK(mask);
4740                         UNUSED(6);
4741                         break; 
4742
4743                 case X_GetMotionEvents:
4744                         REPLYCONTENTS_COMMON();
4745                         break; 
4746
4747                 case X_TranslateCoords:
4748                         REPLY(reply);
4749                         BOOL(same_screen);
4750                         SEQUENCENUMBER_REPLY(sequencenumber);
4751                         REPLYLENGTH(replylength);
4752                         WINDOW(childwindow);
4753                         INT16(dst_x);
4754                         INT16(dst_y);
4755                         UNUSED(16);
4756                         break; 
4757                         
4758                 case X_GetInputFocus:
4759                         REPLY(reply);
4760                         ENUM8(revert_to);
4761                         SEQUENCENUMBER_REPLY(sequencenumber);
4762                         REPLYLENGTH(replylength);
4763                         WINDOW(focus);
4764                         UNUSED(20);
4765                         break;
4766
4767                 case X_QueryKeymap:
4768                         REPLY(reply);
4769                         UNUSED(1);
4770                         SEQUENCENUMBER_REPLY(sequencenumber);
4771                         REPLYLENGTH(replylength);
4772                         LISTofCARD8(keys, 32);
4773                         break;
4774
4775                 case X_QueryFont:
4776                 case X_QueryTextExtents:
4777                 case X_ListFonts:
4778                 case X_GetImage:
4779                 case X_ListInstalledColormaps:
4780                         REPLYCONTENTS_COMMON();
4781                         break;
4782
4783                 case X_AllocColor:
4784                         REPLY(reply);
4785                         UNUSED(1);
4786                         SEQUENCENUMBER_REPLY(sequencenumber);
4787                         REPLYLENGTH(replylength);
4788                         CARD16(red);
4789                         CARD16(green);
4790                         CARD16(blue);
4791                         UNUSED(2);
4792                         CARD32(pixel);
4793                         UNUSED(12);
4794                         break;
4795
4796                 case X_QueryColors:
4797                         REPLYCONTENTS_COMMON();
4798                         break;
4799
4800                 case X_LookupColor:
4801                         REPLY(reply);
4802                         UNUSED(1);
4803                         SEQUENCENUMBER_REPLY(sequencenumber);
4804                         REPLYLENGTH(replylength);
4805                         CARD16(exact_red);
4806                         CARD16(exact_green);
4807                         CARD16(exact_blue);
4808                         CARD16(visual_red);
4809                         CARD16(visual_green);
4810                         CARD16(visual_blue);
4811                         UNUSED(12);
4812                         break;
4813
4814                 case X_QueryBestSize:
4815                         REPLY(reply);
4816                         UNUSED(1);
4817                         SEQUENCENUMBER_REPLY(sequencenumber);
4818                         REPLYLENGTH(replylength);
4819                         CARD16(width);
4820                         CARD16(height);
4821                         UNUSED(20);
4822                         break;
4823
4824                 case X_QueryExtension:
4825                         REPLY(reply);
4826                         UNUSED(1);
4827                         SEQUENCENUMBER_REPLY(sequencenumber);
4828                         REPLYLENGTH(replylength);
4829                         BOOL(present);
4830                         CARD8(major_opcode);
4831                         CARD8(first_event);
4832                         CARD8(first_error);
4833                         UNUSED(20);
4834                         break;
4835                   
4836                 case X_ListExtensions:
4837                         REPLYCONTENTS_COMMON();
4838                         break; 
4839
4840                 case X_GetKeyboardMapping:
4841                         state->first_keycode =
4842                                 state->request.GetKeyboardMapping.first_keycode;
4843                         REPLY(reply);
4844                         state->keysyms_per_keycode =
4845                                 FIELD8(keysyms_per_keycode);
4846                         SEQUENCENUMBER_REPLY(sequencenumber);
4847                         length = REPLYLENGTH(replylength);
4848                         UNUSED(24);
4849                         LISTofKEYSYM(keysyms, state->keycodemap,
4850                                      state->request.GetKeyboardMapping.first_keycode, 
4851                                      length / state->keysyms_per_keycode,
4852                                      state->keysyms_per_keycode);
4853                         break; 
4854
4855                 case X_GetKeyboardControl:
4856                         REPLYCONTENTS_COMMON();
4857                         break; 
4858
4859                 case X_GetPointerControl:
4860                         REPLY(reply);
4861                         UNUSED(1);
4862                         SEQUENCENUMBER_REPLY(sequencenumber);
4863                         REPLYLENGTH(replylength);
4864                         CARD16(acceleration_numerator);
4865                         CARD16(acceleration_denominator);
4866                         CARD16(threshold);
4867                         UNUSED(18);
4868                         break;
4869
4870                 case X_GetScreenSaver:
4871                         REPLY(reply);
4872                         UNUSED(1);
4873                         SEQUENCENUMBER_REPLY(sequencenumber);
4874                         REPLYLENGTH(replylength);
4875                         CARD16(timeout);
4876                         CARD16(interval);
4877                         ENUM8(prefer_blanking);
4878                         ENUM8(allow_exposures);
4879                         UNUSED(18);
4880                         break;
4881
4882                 case X_ListHosts:
4883                 case X_SetPointerMapping:
4884                 case X_GetPointerMapping:
4885                 case X_SetModifierMapping:
4886                         REPLYCONTENTS_COMMON();
4887                         break; 
4888
4889                 case X_GetModifierMapping:
4890                         REPLY(reply);
4891                         state->keycodes_per_modifier =
4892                                 FIELD8(keycodes_per_modifier);
4893                         SEQUENCENUMBER_REPLY(sequencenumber);
4894                         REPLYLENGTH(replylength);
4895                         UNUSED(24);
4896                         LISTofKEYCODE(state->modifiermap, keycodes,
4897                                       state->keycodes_per_modifier);
4898                         break; 
4899
4900                 default:
4901                         REPLYCONTENTS_COMMON();
4902         }
4903
4904         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
4905             UNDECODED(left);
4906 }
4907
4908 static void
4909 same_screen_focus(tvbuff_t *tvb, int *offsetp, proto_tree *t)
4910 {
4911       proto_item *ti;
4912       guint32 bitmask_value;
4913       int bitmask_offset;
4914       int bitmask_size;
4915       proto_tree *bitmask_tree;
4916
4917       bitmask_value = VALUE8(tvb, *offsetp);
4918       bitmask_offset = *offsetp;
4919       bitmask_size = 1;
4920
4921       ti = proto_tree_add_uint(t, hf_x11_same_screen_focus_mask, tvb, *offsetp, 1,
4922                                                  bitmask_value);
4923       bitmask_tree = proto_item_add_subtree(ti, ett_x11_same_screen_focus);
4924       FLAG(same_screen_focus, focus);
4925       FLAG(same_screen_focus, same_screen);
4926
4927       *offsetp += 1;
4928 }
4929
4930 static void
4931 dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4932                   const char *volatile sep, x11_conv_data_t *volatile state,
4933                   gboolean little_endian)
4934 {
4935         int offset = 0, *offsetp = &offset, left;
4936         unsigned char eventcode;
4937         proto_item *ti;
4938         proto_tree *t;
4939
4940         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
4941         t = proto_item_add_subtree(ti, ett_x11);
4942
4943         eventcode = tvb_get_guint8(tvb, offset);
4944
4945         if (check_col(pinfo->cinfo, COL_INFO))
4946                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
4947                                 sep, val_to_str(eventcode, eventcode_vals,
4948                                 "<Unknown eventcode %u>"));
4949
4950         proto_tree_add_uint_format(t, hf_x11_eventcode, tvb, offset, 1,
4951                                    eventcode, 
4952                                    "eventcode: %d (%s)",
4953                                    eventcode, 
4954                                    val_to_str(eventcode, eventcode_vals,
4955                                    "<Unknown eventcode %u>"));
4956         ++offset;
4957
4958         proto_item_append_text(ti, ", Event, eventcode: %d (%s)", 
4959                               eventcode, val_to_str(eventcode, eventcode_vals,
4960                               "<Unknown eventcode %u>"));
4961
4962         if (tree == NULL)
4963                 return; 
4964
4965         switch (eventcode) {
4966                 case KeyPress:
4967                 case KeyRelease: {
4968                         int code, mask;
4969
4970                         /* need to do some prefetching here ... */
4971                         code = VALUE8(tvb, offset);
4972                         mask = VALUE16(tvb, 28);
4973
4974                         KEYCODE_DECODED(keycode, code, mask);
4975                         CARD16(event_sequencenumber);
4976                         EVENTCONTENTS_COMMON();
4977                         BOOL(same_screen);
4978                         UNUSED(1);
4979                         break;
4980                 }
4981
4982                 case ButtonPress:
4983                 case ButtonRelease:
4984                         BUTTON(eventbutton);
4985                         CARD16(event_sequencenumber);
4986                         EVENTCONTENTS_COMMON();
4987                         BOOL(same_screen);
4988                         UNUSED(1);
4989                         break;
4990
4991                 case MotionNotify:
4992                         CARD8(detail);
4993                         CARD16(event_sequencenumber);
4994                         EVENTCONTENTS_COMMON();
4995                         BOOL(same_screen);
4996                         UNUSED(1);
4997                         break;
4998
4999                 case EnterNotify:
5000                 case LeaveNotify:
5001                         ENUM8(event_detail);
5002                         CARD16(event_sequencenumber);
5003                         EVENTCONTENTS_COMMON();
5004                         ENUM8(grab_mode);
5005                         same_screen_focus(tvb, offsetp, t);
5006                         break;
5007
5008                 case FocusIn:
5009                 case FocusOut:
5010                         ENUM8(focus_detail);
5011                         CARD16(event_sequencenumber);
5012                         WINDOW(eventwindow);
5013                         ENUM8(focus_mode);
5014                         UNUSED(23);
5015                         break;
5016
5017                 case KeymapNotify:
5018                         break;
5019
5020                 case Expose:
5021                         UNUSED(1);
5022                         CARD16(event_sequencenumber);
5023                         WINDOW(eventwindow);
5024                         INT16(x);
5025                         INT16(y);
5026                         CARD16(width);
5027                         CARD16(height);
5028                         CARD16(count);
5029                         UNUSED(14);
5030                         break;
5031
5032                 case GraphicsExpose:
5033                         UNUSED(1);
5034                         CARD16(event_sequencenumber);
5035                         DRAWABLE(drawable);
5036                         CARD16(x);
5037                         CARD16(y);
5038                         CARD16(width);
5039                         CARD16(height);
5040                         CARD16(minor_opcode);
5041                         CARD16(count);
5042                         CARD8(major_opcode);
5043                         UNUSED(11);
5044                         break;
5045
5046                 case NoExpose:
5047                         UNUSED(1);
5048                         CARD16(event_sequencenumber);
5049                         DRAWABLE(drawable);
5050                         CARD16(minor_opcode);
5051                         CARD8(major_opcode);
5052                         UNUSED(21);
5053                         break;
5054
5055                 case VisibilityNotify:
5056                         UNUSED(1);
5057                         CARD16(event_sequencenumber);
5058                         WINDOW(eventwindow);
5059                         ENUM8(visibility_state);
5060                         UNUSED(23);
5061                         break;
5062
5063                 case CreateNotify:
5064                         UNUSED(1);
5065                         CARD16(event_sequencenumber);
5066                         WINDOW(parent);
5067                         WINDOW(eventwindow);
5068                         INT16(x);
5069                         INT16(y);
5070                         CARD16(width);
5071                         CARD16(height);
5072                         CARD16(border_width);
5073                         BOOL(override_redirect);
5074                         UNUSED(9);
5075                         break;
5076
5077                 case DestroyNotify:
5078                         UNUSED(1);
5079                         CARD16(event_sequencenumber);
5080                         WINDOW(eventwindow);
5081                         WINDOW(window);
5082                         UNUSED(20);
5083                         break;
5084
5085                 case UnmapNotify:
5086                         UNUSED(1);
5087                         CARD16(event_sequencenumber);
5088                         WINDOW(eventwindow);
5089                         WINDOW(window);
5090                         BOOL(from_configure);
5091                         UNUSED(19);
5092                         break;
5093
5094                 case MapNotify:
5095                         UNUSED(1);
5096                         CARD16(event_sequencenumber);
5097                         WINDOW(eventwindow);
5098                         WINDOW(window);
5099                         BOOL(override_redirect);
5100                         UNUSED(19);
5101                         break;
5102
5103                 case MapRequest:
5104                         UNUSED(1);
5105                         CARD16(event_sequencenumber);
5106                         WINDOW(parent);
5107                         WINDOW(eventwindow);
5108                         UNUSED(20);
5109                         break;
5110
5111                 case ReparentNotify:
5112                         UNUSED(1);
5113                         CARD16(event_sequencenumber);
5114                         WINDOW(eventwindow);
5115                         WINDOW(window);
5116                         WINDOW(parent);
5117                         INT16(x);
5118                         INT16(y);
5119                         BOOL(override_redirect);
5120                         UNUSED(11);
5121                         break;
5122
5123                 case ConfigureNotify:
5124                         UNUSED(1);
5125                         CARD16(event_sequencenumber);
5126                         WINDOW(eventwindow);
5127                         WINDOW(window);
5128                         WINDOW(above_sibling);
5129                         INT16(x);
5130                         INT16(y);
5131                         CARD16(width);
5132                         CARD16(height);
5133                         CARD16(border_width);
5134                         BOOL(override_redirect);
5135                         UNUSED(5);
5136                         break;
5137
5138                 case ConfigureRequest:
5139                         break;
5140
5141                 case GravityNotify:
5142                         UNUSED(1);
5143                         CARD16(event_sequencenumber);
5144                         WINDOW(eventwindow);
5145                         WINDOW(window);
5146                         INT16(x);
5147                         INT16(y);
5148                         UNUSED(16);
5149                         break;
5150
5151                 case ResizeRequest:
5152                         UNUSED(1);
5153                         CARD16(event_sequencenumber);
5154                         WINDOW(eventwindow);
5155                         CARD16(width);
5156                         CARD16(height);
5157                         UNUSED(20);
5158                         break;
5159
5160                 case CirculateNotify:
5161                         UNUSED(1);
5162                         CARD16(event_sequencenumber);
5163                         WINDOW(eventwindow);
5164                         WINDOW(window);
5165                         UNUSED(4);
5166                         ENUM8(place);
5167                         UNUSED(15);
5168                         break;
5169
5170                 case CirculateRequest:
5171                         UNUSED(1);
5172                         CARD16(event_sequencenumber);
5173                         WINDOW(parent);
5174                         WINDOW(eventwindow);
5175                         UNUSED(4);
5176                         ENUM8(place);
5177                         UNUSED(15);
5178                         break;
5179
5180                 case PropertyNotify:
5181                         UNUSED(1);
5182                         CARD16(event_sequencenumber);
5183                         WINDOW(eventwindow);
5184                         ATOM(atom);
5185                         TIMESTAMP(time);
5186                         ENUM8(property_state);
5187                         UNUSED(15);
5188                         break;
5189
5190                 case SelectionClear:
5191                         UNUSED(1);
5192                         CARD16(event_sequencenumber);
5193                         TIMESTAMP(time);
5194                         WINDOW(owner);
5195                         ATOM(selection);
5196                         UNUSED(16);
5197                         break;
5198
5199                 case SelectionRequest:
5200                         UNUSED(1);
5201                         CARD16(event_sequencenumber);
5202                         TIMESTAMP(time);
5203                         WINDOW(owner);
5204                         WINDOW(requestor);
5205                         ATOM(selection);
5206                         ATOM(target);
5207                         ATOM(property);
5208                         UNUSED(4);
5209                         break;
5210
5211                 case SelectionNotify:
5212                         UNUSED(1);
5213                         CARD16(event_sequencenumber);
5214                         TIMESTAMP(time);
5215                         WINDOW(requestor);
5216                         ATOM(selection);
5217                         ATOM(target);
5218                         ATOM(property);
5219                         UNUSED(8);
5220                         break;
5221
5222                 case ColormapNotify:
5223                         UNUSED(1);
5224                         CARD16(event_sequencenumber);
5225                         WINDOW(eventwindow);
5226                         COLORMAP(cmap);
5227                         BOOL(new);
5228                         ENUM8(colormap_state);
5229                         UNUSED(18);
5230                         break;
5231
5232                 case ClientMessage:
5233                         CARD8(format);
5234                         CARD16(event_sequencenumber);
5235                         WINDOW(eventwindow);
5236                         ATOM(type);
5237                         LISTofBYTE(data, 20);
5238                         break;
5239
5240                 case MappingNotify:
5241                 default:
5242                         break;
5243         }
5244
5245         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0) 
5246             UNDECODED(left);
5247
5248         return;
5249 }
5250
5251 static void
5252 dissect_x11_error(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
5253                   const char *volatile sep, x11_conv_data_t *volatile state _U_,
5254                   gboolean little_endian)
5255 {
5256         int offset = 0, *offsetp = &offset, left;
5257         unsigned char errorcode, error;
5258         proto_item *ti;
5259         proto_tree *t;
5260
5261         ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
5262         t = proto_item_add_subtree(ti, ett_x11);
5263
5264         error = tvb_get_guint8(tvb, offset);
5265         CARD8(error);
5266
5267         errorcode = tvb_get_guint8(tvb, offset);
5268         if (check_col(pinfo->cinfo, COL_INFO))
5269                 col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s",
5270                 sep, val_to_str(errorcode, errorcode_vals, "<Unknown errorcode %u>"));
5271
5272         proto_tree_add_uint_format(t, hf_x11_errorcode, tvb, offset, 1,
5273                                    errorcode, 
5274                                    "errorcode: %d (%s)",
5275                                    errorcode, 
5276                                    val_to_str(errorcode, errorcode_vals,
5277                                    "<Unknown errocode %u>"));
5278         ++offset;
5279
5280         proto_item_append_text(ti, ", Error, errorcode: %d (%s)", 
5281                               errorcode, val_to_str(errorcode, errorcode_vals,
5282                               "<Unknown errorcode %u>"));
5283
5284         if (tree == NULL)
5285                 return; 
5286
5287         CARD16(error_sequencenumber);
5288
5289         switch (errorcode) {
5290                 case BadValue:
5291                         CARD32(error_badvalue);
5292                         break;
5293
5294                 default:
5295                         UNDECODED(4);
5296         }
5297
5298         CARD16(minor_opcode);
5299         CARD8(major_opcode);
5300
5301         if ((left = tvb_reported_length_remaining(tvb, offset)) > 0)
5302             UNDECODED(left);
5303 }
5304
5305                         
5306
5307 /************************************************************************
5308  ***                                                                  ***
5309  ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
5310  ***                                                                  ***
5311  ************************************************************************/
5312
5313 static void
5314 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
5315 {
5316         if (check_col(pinfo->cinfo, COL_PROTOCOL))
5317                 col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
5318
5319         if (pinfo->match_port == pinfo->srcport)
5320                 dissect_x11_replies(tvb, pinfo, tree);
5321         else
5322                 dissect_x11_requests(tvb, pinfo, tree);
5323 }
5324
5325 /* Register the protocol with Ethereal */
5326 void proto_register_x11(void)
5327 {
5328
5329 /* Setup list of header fields */
5330       static hf_register_info hf[] = {
5331 #include "x11-register-info.h"
5332       };
5333
5334 /* Setup protocol subtree array */
5335       static gint *ett[] = {
5336             &ett_x11,
5337             &ett_x11_color_flags,
5338             &ett_x11_list_of_arc,
5339             &ett_x11_arc,
5340             &ett_x11_list_of_atom,
5341             &ett_x11_list_of_card32,
5342             &ett_x11_list_of_color_item,
5343             &ett_x11_color_item,
5344             &ett_x11_list_of_keycode,
5345             &ett_x11_list_of_keysyms,
5346             &ett_x11_keysym,
5347             &ett_x11_list_of_point,
5348             &ett_x11_point,
5349             &ett_x11_list_of_rectangle,
5350             &ett_x11_rectangle,
5351             &ett_x11_list_of_segment,
5352             &ett_x11_segment,
5353             &ett_x11_list_of_string8,
5354             &ett_x11_list_of_text_item,
5355             &ett_x11_text_item,
5356             &ett_x11_gc_value_mask,
5357             &ett_x11_event_mask,
5358             &ett_x11_do_not_propagate_mask,
5359             &ett_x11_set_of_key_mask,
5360             &ett_x11_pointer_event_mask,
5361             &ett_x11_window_value_mask,
5362             &ett_x11_configure_window_mask,
5363             &ett_x11_keyboard_value_mask,
5364             &ett_x11_same_screen_focus,
5365       };
5366       module_t *x11_module;
5367
5368 /* Register the protocol name and description */
5369       proto_x11 = proto_register_protocol("X11", "X11", "x11");
5370
5371 /* Required function calls to register the header fields and subtrees used */
5372       proto_register_field_array(proto_x11, hf, array_length(hf));
5373       proto_register_subtree_array(ett, array_length(ett));
5374
5375       register_init_routine(x11_init_protocol);
5376
5377       x11_module = prefs_register_protocol(proto_x11, NULL);
5378       prefs_register_bool_preference(x11_module, "desegment",
5379             "Reassemble X11 messages spanning multiple TCP segments",
5380             "Whether the X11 dissector should reassemble messages spanning multiple TCP segments. "
5381             "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5382             &x11_desegment);
5383 }
5384
5385 void
5386 proto_reg_handoff_x11(void)
5387 {
5388   dissector_handle_t x11_handle;
5389
5390   x11_handle = create_dissector_handle(dissect_x11, proto_x11);
5391   dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
5392   dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
5393   dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
5394   data_handle = find_dissector("data");
5395 }
5396