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