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