On Windows, include "capture-wpcap.h", to define "has_wpcap".
[obnox/wireshark/wip.git] / packet-x11.c
index a43e4383a7aa7270003c632d31cb649ee7b38a30..197f805c132a77d315a446b33b6c213506f5c5c0 100644 (file)
@@ -2,10 +2,10 @@
  * Routines for X11 dissection
  * Copyright 2000, Christophe Tronche <ch.tronche@computer.org>
  *
- * $Id: packet-x11.c,v 1.12 2000/11/19 02:48:24 guy Exp $
+ * $Id: packet-x11.c,v 1.41 2002/04/17 08:33:08 guy Exp $
  *
  * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@unicom.net>
+ * By Gerald Combs <gerald@ethereal.com>
  * Copyright 1998 Gerald Combs
  *
  * Copied from README.developer
 
 /* TODO (in no particular order):
  *
- * - keep track of Atom creation by server to be able to display non predefined atoms
+ * - keep track of Atom creation by server to be able to display
+ *   non-predefined atoms
  * - Idem for keysym <-> keycode ???
  * - Idem for fonts 
- * - Subtree the request ids (that is x11.create-window.window and x11.change-window.window should be 
- *   distinct), and add hidden fields (so we still have x11.window).
- * - add hidden fields so we can have x11.circulate-window in addition to x11.opcode == 13
+ * - Subtree the request ids (that is x11.create-window.window and
+ *   x11.change-window.window should be  distinct), and add hidden fields
+ *   (so we still have x11.window).
+ * - add hidden fields so we can have x11.circulate-window in addition to
+ *   x11.opcode == 13 (but you could match on x11.opcode == "CirculateWindow"
+ *   now)
  * - add hidden fields so we have x11.listOfStuff.length
  * - use a faster scheme that linear list searching for the opcode.
- * - correct display of unicode chars.
- * - Not everything is homogeneous, in particular the handling of items in list is a total mess.
+ * - correct display of Unicode chars.
+ * - Not everything is homogeneous, in particular the handling of items in
+ *   list is a total mess.
  */
 
 /* By the way, I wrote a program to generate every request and test
 
 #include <string.h>
 #include <glib.h>
-#include "packet.h"
+#include <epan/packet.h>
+#include <epan/conversation.h>
+
+#include "prefs.h"
+#include "packet-frame.h"
 
 #define cVALS(x) (const value_string*)(x)
 
 /* Initialize the protocol and registered fields */
 static int proto_x11 = -1;
 
-#include "packet-x11-declarations.h"
+#include "x11-declarations.h"
 
 /* Initialize the subtree pointers */
 static gint ett_x11 = -1;
-static gint ett_x11_request = -1;
+static gint ett_x11_color_flags = -1;
+static gint ett_x11_list_of_arc = -1;
+static gint ett_x11_arc = -1;
+static gint ett_x11_list_of_atom = -1;
+static gint ett_x11_list_of_card32 = -1;
+static gint ett_x11_list_of_color_item = -1;
+static gint ett_x11_color_item = -1;
+static gint ett_x11_list_of_keycode = -1;
+static gint ett_x11_list_of_keysyms = -1;
+static gint ett_x11_keysym = -1;
+static gint ett_x11_list_of_point = -1;
+static gint ett_x11_point = -1;
+static gint ett_x11_list_of_rectangle = -1;
+static gint ett_x11_rectangle = -1;
+static gint ett_x11_list_of_segment = -1;
+static gint ett_x11_segment = -1;
+static gint ett_x11_list_of_string8 = -1;
+static gint ett_x11_list_of_text_item = -1;
+static gint ett_x11_text_item = -1;
+static gint ett_x11_gc_value_mask = -1;
+static gint ett_x11_event_mask = -1;
+static gint ett_x11_do_not_propagate_mask = -1;
+static gint ett_x11_set_of_key_mask = -1;
+static gint ett_x11_pointer_event_mask = -1;
+static gint ett_x11_window_value_mask = -1;
+static gint ett_x11_configure_window_mask = -1;
+static gint ett_x11_keyboard_value_mask = -1;
+
+/* desegmentation of X11 messages */
+static gboolean x11_desegment = TRUE;
+
+static dissector_handle_t data_handle;
 
 #define TCP_PORT_X11                   6000
 #define TCP_PORT_X11_2                 6001
 #define TCP_PORT_X11_3                 6002
 
+/*
+ * Round a length to a multiple of 4 bytes.
+ */
+#define ROUND_LENGTH(n)        ((((n) + 3)/4) * 4)
+
 /************************************************************************
  ***                                                                  ***
  ***         E N U M   T A B L E S   D E F I N I T I O N S            ***
  ***                                                                  ***
  ************************************************************************/
 
+static const value_string byte_order_vals[] = {
+     { 'B', "Big-endian" },
+     { 'l', "Little-endian" },
+     { 0,   NULL }
+};
+
 static const value_string access_mode_vals[] = {
       { 0, "Disable" },
       { 1, "Enable" },
@@ -253,10 +304,14 @@ static const value_string direction_vals[] = {
       { 0, NULL }
 };
 
+#define FAMILY_INTERNET        0
+#define FAMILY_DECNET  1
+#define FAMILY_CHAOS   2
+
 static const value_string family_vals[] = {
-      { 0, "Internet" },
-      { 1, "DECnet" },
-      { 2, "Chaos" },
+      { FAMILY_INTERNET, "Internet" },
+      { FAMILY_DECNET,   "DECnet" },
+      { FAMILY_CHAOS,    "Chaos" },
       { 0, NULL }
 };
 
@@ -575,17 +630,7 @@ static const value_string zero_is_none_vals[] = {
  ***                                                                  ***
  ************************************************************************/
 
-static int cur_offset;         /* The current offset in the frame */
-static int next_offset = 0; /* Offset of the next request in the frame */    
 static gboolean little_endian = TRUE;
-static proto_tree *t = NULL;
-
-static struct maskStruct {
-      guint32 _value;
-      int _offset;
-      int _zone;
-      proto_tree *_tree;
-} lastMask = { 0, 0, 0, NULL };
 
 /************************************************************************
  ***                                                                  ***
@@ -597,43 +642,61 @@ static struct maskStruct {
 #define VALUE16(tvb, offset) (little_endian ? tvb_get_letohs(tvb, offset) : tvb_get_ntohs(tvb, offset))
 #define VALUE32(tvb, offset) (little_endian ? tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset))
 
-#define FIELD8(name)  (field8(tvb, hf_x11_##name))
-#define FIELD16(name) (field16(tvb, hf_x11_##name))
-#define FIELD32(name) (field32(tvb, hf_x11_##name))
+#define FIELD8(name)  (field8(tvb, offsetp, t, hf_x11_##name))
+#define FIELD16(name) (field16(tvb, offsetp, t, hf_x11_##name))
+#define FIELD32(name) (field32(tvb, offsetp, t, hf_x11_##name))
 
 #define BITFIELD(TYPE, position, name) {\
-  if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
-       int unused;\
-       int save = cur_offset;\
-       proto_tree_add_item(lastMask._tree, hf_x11_##position##_##name, tvb, lastMask._offset, \
-                           lastMask._zone, little_endian); \
+  int unused;\
+  int save = *offsetp;\
+  proto_tree_add_item(bitmask_tree, hf_x11_##position##_##name, tvb, bitmask_offset, \
+                      bitmask_size, little_endian); \
+  if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_##name) -> bitmask) {\
        TYPE(name);\
-       unused = save + 4 - cur_offset;\
+       unused = save + 4 - *offsetp;\
        if (unused)\
-           proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, unused, little_endian);\
-       cur_offset = save + 4;\
+           proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp, unused, little_endian);\
+       *offsetp = save + 4;\
  }\
 }
 
 #define FLAG(position, name) {\
-  if (lastMask._value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
-       proto_tree_add_boolean(lastMask._tree, hf_x11_##position##_mask##_##name, tvb, lastMask._offset, lastMask._zone, lastMask._value); }
-
-#define ATOM(name)     { atom(tvb, t, hf_x11_##name); }
-#define BITGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Forget"); }
-#define BITMASK8(name) { bitmask(tvb, hf_x11_##name##_mask, 1); }
-#define BITMASK16(name) { bitmask(tvb, hf_x11_##name##_mask, 2); }
-#define BITMASK32(name)  { bitmask(tvb, hf_x11_##name##_mask, 4); }
-#define BOOL(name)     (add_boolean(tvb, #name, hf_x11_##name))
+       proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
+
+#define FLAG_IF_NONZERO(position, name) {\
+  if (bitmask_value & proto_registrar_get_nth(hf_x11_##position##_mask##_##name) -> bitmask)\
+       proto_tree_add_boolean(bitmask_tree, hf_x11_##position##_mask##_##name, tvb, bitmask_offset, bitmask_size, bitmask_value); }
+
+#define ATOM(name)     { atom(tvb, offsetp, t, hf_x11_##name); }
+#define BITGRAVITY(name) { gravity(tvb, offsetp, t, #name, hf_x11_##name, "Forget"); }
+#define BITMASK(name, size) {\
+      proto_item *ti; \
+      guint32 bitmask_value; \
+      int bitmask_offset; \
+      int bitmask_size; \
+      proto_tree *bitmask_tree; \
+      bitmask_value = ((size == 1) ? VALUE8(tvb, *offsetp) : \
+                      ((size == 2) ? VALUE16(tvb, *offsetp) : \
+                                     VALUE32(tvb, *offsetp))); \
+      bitmask_offset = *offsetp; \
+      bitmask_size = size; \
+      ti = proto_tree_add_uint(t, hf_x11_##name##_mask, tvb, *offsetp, size, bitmask_value); \
+      bitmask_tree = proto_item_add_subtree(ti, ett_x11_##name##_mask); \
+      *offsetp += size;
+#define ENDBITMASK     }
+#define BITMASK8(name) BITMASK(name, 1);
+#define BITMASK16(name)        BITMASK(name, 2);
+#define BITMASK32(name) BITMASK(name, 4);
+#define BOOL(name)     (add_boolean(tvb, offsetp, t, hf_x11_##name))
 #define BUTTON(name)   { FIELD8(name); }
 #define CARD8(name)    { FIELD8(name); }
 #define CARD16(name)   (FIELD16(name))
 #define CARD32(name)   (FIELD32(name))
-#define COLOR_FLAGS(name) { colorFlags(tvb, t); }
+#define COLOR_FLAGS(name) { colorFlags(tvb, offsetp, t); }
 #define COLORMAP(name) { FIELD32(name); }
 #define CURSOR(name)   { FIELD32(name); }
 #define DRAWABLE(name) { FIELD32(name); }
-#define ENUM8(name)    { FIELD8(name); }
+#define ENUM8(name)    (FIELD8(name))
 #define ENUM16(name)   { FIELD16(name); }
 #define FONT(name)     { FIELD32(name); }
 #define FONTABLE(name) { FIELD32(name); }
@@ -641,40 +704,40 @@ static struct maskStruct {
 #define INT8(name)     { FIELD8(name); }
 #define INT16(name)    { FIELD16(name); }
 #define KEYCODE(name)  { FIELD8(name); }
-#define LISTofARC(name) { listOfArc(tvb, hf_x11_##name, (next_offset - cur_offset) / 12); }
-#define LISTofATOM(name, length) { listOfAtom(tvb, hf_x11_##name, (length) / 4); }
-#define LISTofBYTE(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
-#define LISTofCARD8(name, length) { listOfByte(tvb, hf_x11_##name, (length)); }
-#define LISTofCARD32(name, length) { listOfCard32(tvb, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
-#define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, hf_x11_##name, (length) / 12); }
-#define LISTofKEYCODE(name, length) { listOfKeycode(tvb, hf_x11_##name, (length)); }
+#define LISTofARC(name) { listOfArc(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 12); }
+#define LISTofATOM(name, length) { listOfAtom(tvb, offsetp, t, hf_x11_##name, (length) / 4); }
+#define LISTofBYTE(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length)); }
+#define LISTofCARD8(name, length) { listOfByte(tvb, offsetp, t, hf_x11_##name, (length)); }
+#define LISTofCARD32(name, length) { listOfCard32(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (length) / 4); }
+#define LISTofCOLORITEM(name, length) { listOfColorItem(tvb, offsetp, t, hf_x11_##name, (length) / 12); }
+#define LISTofKEYCODE(name, length) { listOfKeycode(tvb, offsetp, t, hf_x11_##name, (length)); }
 #define LISTofKEYSYM(name, keycode_count, keysyms_per_keycode) { \
-      listOfKeysyms(tvb, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
-#define LISTofPOINT(name, length) { listOfPoint(tvb, hf_x11_##name, (length) / 4); }
-#define LISTofRECTANGLE(name) { listOfRectangle(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
-#define LISTofSEGMENT(name) { listOfSegment(tvb, hf_x11_##name, (next_offset - cur_offset) / 8); }
-#define LISTofSTRING8(name, length) { listOfString8(tvb, hf_x11_##name, hf_x11_##name##_string, (length)); }
-#define LISTofTEXTITEM8(name) { listOfTextItem(tvb, hf_x11_##name, FALSE); }
-#define LISTofTEXTITEM16(name) { listOfTextItem(tvb, hf_x11_##name, TRUE); }
+      listOfKeysyms(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_item, (keycode_count), (keysyms_per_keycode)); }
+#define LISTofPOINT(name, length) { listOfPoint(tvb, offsetp, t, hf_x11_##name, (length) / 4); }
+#define LISTofRECTANGLE(name) { listOfRectangle(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
+#define LISTofSEGMENT(name) { listOfSegment(tvb, offsetp, t, hf_x11_##name, (next_offset - *offsetp) / 8); }
+#define LISTofSTRING8(name, length) { listOfString8(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_string, (length)); }
+#define LISTofTEXTITEM8(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, FALSE, next_offset); }
+#define LISTofTEXTITEM16(name) { listOfTextItem(tvb, offsetp, t, hf_x11_##name, TRUE, next_offset); }
 #define OPCODE()       { opcode = FIELD8(opcode); }
 #define PIXMAP(name)   { FIELD32(name); }
-#define REQUEST_LENGTH() (requestLength(tvb))
-#define SETofEVENT(name) { setOfEvent(tvb); }
-#define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb);}
-#define SETofKEYMASK(name) { setOfKeyMask(tvb); }
-#define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb); }
-#define STRING8(name, length)  { string8(tvb, #name, hf_x11_##name, length); }
-#define STRING16(name, length)  { string16(tvb, hf_x11_##name, hf_x11_##name##_bytes, length); }
-#define TIMESTAMP(name){ timestamp(tvb, #name, hf_x11_##name); }
-#define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset,  x, little_endian); p += x; }
-#define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset,  x, little_endian); cur_offset += x; }
-#define PAD()          { if (next_offset - cur_offset > 0) proto_tree_add_item(t, hf_x11_unused, tvb, cur_offset, next_offset - cur_offset, little_endian); cur_offset = next_offset; }
+#define REQUEST_LENGTH() (requestLength(tvb, offsetp, t))
+#define SETofEVENT(name) { setOfEvent(tvb, offsetp, t); }
+#define SETofDEVICEEVENT(name) { setOfDeviceEvent(tvb, offsetp, t);}
+#define SETofKEYMASK(name) { setOfKeyMask(tvb, offsetp, t); }
+#define SETofPOINTEREVENT(name) { setOfPointerEvent(tvb, offsetp, t); }
+#define STRING8(name, length)  { string8(tvb, offsetp, t, #name, hf_x11_##name, length); }
+#define STRING16(name, length)  { string16(tvb, offsetp, t, hf_x11_##name, hf_x11_##name##_bytes, length); }
+#define TIMESTAMP(name){ timestamp(tvb, offsetp, t, #name, hf_x11_##name); }
+#define UNDECODED(x)   { proto_tree_add_item(t, hf_x11_undecoded, tvb, *offsetp,  x, little_endian); *offsetp += x; }
+#define UNUSED(x)      { proto_tree_add_item(t, hf_x11_unused, tvb, *offsetp,  x, little_endian); *offsetp += x; }
+#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; }
 #define WINDOW(name)   { FIELD32(name); }
-#define WINGRAVITY(name) { gravity(tvb, #name, hf_x11_##name, "Unmap"); }
+#define WINGRAVITY(name) { gravity(tvb, offsetp, t, #name, hf_x11_##name, "Unmap"); }
 
-#define VISUALID(name) { gint32 v = VALUE32(tvb, cur_offset); \
-    proto_tree_add_uint_format(t, hf_x11_##name, tvb, cur_offset, 4, v, "Visualid: 0x%08x%s", v, \
-                              v ? "" : " (CopyFromParent)"); cur_offset += 4; }
+#define VISUALID(name) { gint32 v = VALUE32(tvb, *offsetp); \
+    proto_tree_add_uint_format(t, hf_x11_##name, tvb, *offsetp, 4, v, "Visualid: 0x%08x%s", v, \
+                              v ? "" : " (CopyFromParent)"); *offsetp += 4; }
 
 /************************************************************************
  ***                                                                  ***
@@ -682,46 +745,38 @@ static struct maskStruct {
  ***                                                                  ***
  ************************************************************************/
 
-static void atom(tvbuff_t *tvb, proto_tree *t, int hf)
+static void atom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
 {
       const char *interpretation = NULL;
 
-      guint32 v = VALUE32(tvb, cur_offset);
+      guint32 v = VALUE32(tvb, *offsetp);
       if (v >= 1 && v < array_length(atom_predefined_interpretation))
            interpretation = atom_predefined_interpretation[v];
       else if (v)
            interpretation = "Not a predefined atom";
       else {
-           struct header_field_info *hfi = proto_registrar_get_nth(hf);
+           header_field_info *hfi = proto_registrar_get_nth(hf);
            if (hfi -> strings)
                  interpretation = match_strval(v, cVALS(hfi -> strings));
       }
       if (!interpretation) interpretation = "error in Xlib client program ?";
-      proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: %d (%s)", 
+      proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, "%s: %u (%s)", 
                                 proto_registrar_get_nth(hf) -> name, v, interpretation);
-      cur_offset += 4;
-}
-
-static void bitmask(tvbuff_t *tvb, int hf, int size)
-{
-      lastMask._value = size == 2 ? VALUE16(tvb, cur_offset) : VALUE32(tvb, cur_offset);
-      lastMask._offset = cur_offset;
-      lastMask._zone = size;
-      lastMask._tree = proto_tree_add_uint(t, hf, tvb, cur_offset, size, lastMask._value);
-      cur_offset += size; 
+      *offsetp += 4;
 }
 
-static guint32 add_boolean(tvbuff_t *tvb, const char *nameAsChar, int hf)
+static guint32 add_boolean(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
 {
-      guint32 v = VALUE8(tvb, cur_offset);
-      proto_tree_add_boolean(t, hf, tvb, cur_offset, 1, v);
-      cur_offset += 1;
+      guint32 v = VALUE8(tvb, *offsetp);
+      proto_tree_add_boolean(t, hf, tvb, *offsetp, 1, v);
+      *offsetp += 1;
       return v;
 }
 
-static void colorFlags(tvbuff_t *tvb, proto_tree *t)
+static void colorFlags(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      unsigned do_red_green_blue = VALUE8(tvb, cur_offset);
+      unsigned do_red_green_blue = VALUE8(tvb, *offsetp);
+      proto_item *ti;
       proto_tree *tt;
       
       if (do_red_green_blue) {
@@ -751,101 +806,107 @@ static void colorFlags(tvbuff_t *tvb, proto_tree *t)
                  sprintf(bp, "trash");
            }
 
-           tt = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
+           ti = proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
                                            "%s", buffer);
+           tt = proto_item_add_subtree(ti, ett_x11_color_flags);
            if (do_red_green_blue & 0x1)
-                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, cur_offset, 1, 
+                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_red, tvb, *offsetp, 1, 
                                         do_red_green_blue & 0x1);
            if (do_red_green_blue & 0x2)
-                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, cur_offset, 1, 
+                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_green, tvb, *offsetp, 1, 
                                         do_red_green_blue & 0x2);
            if (do_red_green_blue & 0x4)
-                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, cur_offset, 1, 
+                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_do_blue, tvb, *offsetp, 1, 
                                         do_red_green_blue & 0x4);
            if (do_red_green_blue & 0xf8)
-                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, cur_offset, 1, 
+                 proto_tree_add_boolean(tt, hf_x11_coloritem_flags_unused, tvb, *offsetp, 1, 
                                         do_red_green_blue & 0xf8);
       } else
-           proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, cur_offset, 1, do_red_green_blue,
+           proto_tree_add_uint_format(t, hf_x11_coloritem_flags, tvb, *offsetp, 1, do_red_green_blue,
                                       "flags: none");
-      cur_offset++;
+      *offsetp += 1;
 }
 
-static void gravity(tvbuff_t *tvb, const char *nameAsChar, int hf, const char *nullInterpretation)
+static void gravity(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+    const char *nameAsChar, int hf, const char *nullInterpretation)
 {
-      guint8 v = VALUE8(tvb, cur_offset);
+      guint8 v = VALUE8(tvb, *offsetp);
       if (!v)
-           proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: 0 (%s)", nameAsChar, 
+           proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v, "%s: 0 (%s)", nameAsChar, 
                                       nullInterpretation);
       else
-           proto_tree_add_uint(t, hf, tvb, cur_offset, 1, v);
-      cur_offset += 1;
+           proto_tree_add_uint(t, hf, tvb, *offsetp, 1, v);
+      *offsetp += 1;
 }
 
-static void listOfArc(tvbuff_t *tvb, int hf, int length)
+static void listOfArc(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_arc);
       while(length--) {
-           gint16 x = VALUE16(tvb, cur_offset);
-           gint16 y = VALUE16(tvb, cur_offset + 2);
-           guint16 width = VALUE16(tvb, cur_offset + 4);
-           guint16 height = VALUE16(tvb, cur_offset + 6);
-           gint16 angle1 = VALUE16(tvb, cur_offset + 8);
-           gint16 angle2 = VALUE16(tvb, cur_offset + 10);
-
-           proto_tree *ttt = proto_tree_add_protocol_format(tt, hf_x11_arc, tvb, cur_offset, 12, 
-                                                            "arc: %dx%d+%d+%d, angle %d -> %d (%f° -> %f°)",
+           gint16 x = VALUE16(tvb, *offsetp);
+           gint16 y = VALUE16(tvb, *offsetp + 2);
+           guint16 width = VALUE16(tvb, *offsetp + 4);
+           guint16 height = VALUE16(tvb, *offsetp + 6);
+           gint16 angle1 = VALUE16(tvb, *offsetp + 8);
+           gint16 angle2 = VALUE16(tvb, *offsetp + 10);
+
+           proto_item *tti = proto_tree_add_none_format(tt, hf_x11_arc, tvb, *offsetp, 12, 
+                                                            "arc: %dx%d+%d+%d, angle %d -> %d (%f degrees -> %f degrees)",
                                                             width, height, x, y, angle1, angle2,
                                                             angle1 / 64.0, angle2 / 64.0);
-           proto_tree_add_int(ttt, hf_x11_arc_x, tvb, cur_offset, 2, x); cur_offset += 2;
-           proto_tree_add_int(ttt, hf_x11_arc_y, tvb, cur_offset, 2, y); cur_offset += 2;
-           proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, cur_offset, 2, y); cur_offset += 2;
-           proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, cur_offset, 2, y); cur_offset += 2;
-           proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, cur_offset, 2, y); cur_offset += 2;
-           proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, cur_offset, 2, y); cur_offset += 2;
+           proto_tree *ttt = proto_item_add_subtree(tti, ett_x11_arc);
+           proto_tree_add_int(ttt, hf_x11_arc_x, tvb, *offsetp, 2, x);
+           *offsetp += 2;
+           proto_tree_add_int(ttt, hf_x11_arc_y, tvb, *offsetp, 2, y);
+           *offsetp += 2;
+           proto_tree_add_uint(ttt, hf_x11_arc_width, tvb, *offsetp, 2, y);
+           *offsetp += 2;
+           proto_tree_add_uint(ttt, hf_x11_arc_height, tvb, *offsetp, 2, y);
+           *offsetp += 2;
+           proto_tree_add_int(ttt, hf_x11_arc_angle1, tvb, *offsetp, 2, y);
+           *offsetp += 2;
+           proto_tree_add_int(ttt, hf_x11_arc_angle2, tvb, *offsetp, 2, y);
+           *offsetp += 2;
       }
 }
 
-static void listOfAtom(tvbuff_t *tvb, int hf, int length)
+static void listOfAtom(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
-      while(length--) {
-           if (cur_offset + 4 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           atom(tvb, tt, hf_x11_properties_item);
-      }
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_atom);
+      while(length--)
+           atom(tvb, offsetp, tt, hf_x11_properties_item);
 }
 
-static void listOfByte(tvbuff_t *tvb, int hf, int length)
+static void listOfByte(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      if (cur_offset + length > next_offset) {
-           /* List runs past end of message. */
-           length = next_offset -  cur_offset;
-      }
       if (length <= 0) length = 1;
-      proto_tree_add_bytes(t, hf, tvb, cur_offset, length, tvb_get_ptr(tvb, cur_offset, length));
-      cur_offset += length;
+      proto_tree_add_item(t, hf, tvb, *offsetp, length, little_endian);
+      *offsetp += length;
 }
 
-static void listOfCard32(tvbuff_t *tvb, int hf, int hf_item, int length)
+static void listOfCard32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int hf_item, int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_card32);
       while(length--) {
-           if (cur_offset + 4 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           proto_tree_add_uint(tt, hf_item, tvb, cur_offset, 4, VALUE32(tvb, cur_offset));
-           cur_offset += 4;
+           proto_tree_add_uint(tt, hf_item, tvb, *offsetp, 4, VALUE32(tvb, *offsetp));
+           *offsetp += 4;
       }
 }
 
-static void listOfColorItem(tvbuff_t *tvb, int hf, int length)
+static void listOfColorItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_color_item);
       while(length--) {
+           proto_item *tti;
            proto_tree *ttt;
            unsigned do_red_green_blue;
            guint16 red, green, blue;
@@ -853,28 +914,37 @@ static void listOfColorItem(tvbuff_t *tvb, int hf, int length)
            char *bp;
            const char *sep;
 
-           if (cur_offset + 12 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           red = VALUE16(tvb, cur_offset + 4);
-           green = VALUE16(tvb, cur_offset + 6);
-           blue = VALUE16(tvb, cur_offset + 8);
-           do_red_green_blue = VALUE8(tvb, cur_offset + 10);
+           red = VALUE16(tvb, *offsetp + 4);
+           green = VALUE16(tvb, *offsetp + 6);
+           blue = VALUE16(tvb, *offsetp + 8);
+           do_red_green_blue = VALUE8(tvb, *offsetp + 10);
 
            bp = buffer + sprintf(buffer, "colorItem: ");
            sep = "";
-           if (do_red_green_blue & 0x1) { bp += sprintf(bp, "red = %d", red); sep = ", "; }
-           if (do_red_green_blue & 0x2) { bp += sprintf(bp, "%sgreen = %d", sep, green); sep = ", "; }
-           if (do_red_green_blue & 0x4) bp += sprintf(bp, "%sblue = %d", sep, blue);
-
-           ttt = proto_tree_add_protocol_format(tt, hf_x11_coloritem, tvb, cur_offset, 12, "%s", buffer);
-           proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, cur_offset, 4, little_endian); cur_offset += 4;
-           proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           colorFlags(tvb, ttt);
-           proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, cur_offset, 1, little_endian); cur_offset++;
+           if (do_red_green_blue & 0x1) {
+               bp += sprintf(bp, "red = %d", red);
+               sep = ", ";
+           }
+           if (do_red_green_blue & 0x2) {
+               bp += sprintf(bp, "%sgreen = %d", sep, green);
+               sep = ", ";
+           }
+           if (do_red_green_blue & 0x4)
+               bp += sprintf(bp, "%sblue = %d", sep, blue);
+
+           tti = proto_tree_add_none_format(tt, hf_x11_coloritem, tvb, *offsetp, 12, "%s", buffer);
+           ttt = proto_item_add_subtree(tti, ett_x11_color_item);
+           proto_tree_add_item(ttt, hf_x11_coloritem_pixel, tvb, *offsetp, 4, little_endian);
+           *offsetp += 4;
+           proto_tree_add_item(ttt, hf_x11_coloritem_red, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           proto_tree_add_item(ttt, hf_x11_coloritem_green, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           proto_tree_add_item(ttt, hf_x11_coloritem_blue, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           colorFlags(tvb, offsetp, ttt);
+           proto_tree_add_item(ttt, hf_x11_coloritem_unused, tvb, *offsetp, 1, little_endian);
+           *offsetp += 1;
       }
 }
 
@@ -903,127 +973,129 @@ static const char *keysymString(guint32 v)
 
 static const char *modifiers[] = { "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
 
-static void listOfKeycode(tvbuff_t *tvb, int hf, int length)
+static void listOfKeycode(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
       char buffer[1024];
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keycode);
 
       while(length--) {
            char *bp = buffer;
            const char **m;
            int i;
 
-           if (cur_offset + 8 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
            for(i = 8, m = modifiers; i; i--, m++) {
-                 u_char c = tvb_get_guint8(tvb, cur_offset);
-                 cur_offset++;
-                 if (c) bp += sprintf(bp, "  %s=%d", *m, c);
+               u_char c = tvb_get_guint8(tvb, *offsetp);
+               *offsetp += 1;
+               if (c)
+                   bp += sprintf(bp, "  %s=%d", *m, c);
            }
 
-           proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, cur_offset - 8, 8, tvb_get_ptr(tvb, cur_offset - 8, 8),  "item: %s", buffer);
+           proto_tree_add_bytes_format(tt, hf_x11_keycodes_item, tvb, *offsetp - 8, 8, tvb_get_ptr(tvb, *offsetp - 8, 8),      "item: %s", buffer);
       }
 }
 
-static void listOfKeysyms(tvbuff_t *tvb, int hf, int hf_item, int keycode_count, int keysyms_per_keycode)
+static void listOfKeysyms(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int hf_item, int keycode_count, int keysyms_per_keycode)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, keycode_count * keysyms_per_keycode * 4, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, keycode_count * keysyms_per_keycode * 4, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_keysyms);
+      proto_item *tti;
       proto_tree *ttt;
       int i;
-      char buffer[128];
-      char *bp;
 
       while(keycode_count--) {
-           if (cur_offset + keysyms_per_keycode * 4 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           bp = buffer + sprintf(buffer, "keysyms:");
-           for(i = 0; i < keysyms_per_keycode; i++) {
-                 bp += sprintf(bp, " %s", keysymString(VALUE32(tvb, cur_offset + i * 4)));
-           }
-           *bp = '\0';
-           ttt = proto_tree_add_protocol_format(tt, hf_item, tvb, cur_offset, keysyms_per_keycode * 4,
-                                                "%s", buffer);
+           tti = proto_tree_add_none_format(tt, hf_item, tvb, *offsetp, keysyms_per_keycode * 4,
+                                                "keysyms:");
+           ttt = proto_item_add_subtree(tti, ett_x11_keysym);
            for(i = keysyms_per_keycode; i; i--) {
-                 guint32 v = VALUE32(tvb, cur_offset);
-                 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, cur_offset, 4, v,
+                 guint32 v = VALUE32(tvb, *offsetp);
+                 proto_item_append_text(tti, " %s", keysymString(v));
+                 proto_tree_add_uint_format(ttt, hf_x11_keysyms_item_keysym, tvb, *offsetp, 4, v,
                                             "keysym: 0x%08x (%s)", v, keysymString(v));
-                 cur_offset += 4;
+                 *offsetp += 4;
            }
       }
 }
 
-static void listOfPoint(tvbuff_t *tvb, int hf, int length)
+static void listOfPoint(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf, int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 4, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 4, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_point);
       while(length--) {
            gint16 x, y;
+           proto_item *tti;
            proto_tree *ttt;
 
-           if (cur_offset + 4 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           x = VALUE16(tvb, cur_offset);
-           y = VALUE16(tvb, cur_offset + 2);
+           x = VALUE16(tvb, *offsetp);
+           y = VALUE16(tvb, *offsetp + 2);
 
-           ttt = proto_tree_add_protocol_format(tt, hf_x11_point, tvb, cur_offset, 4, "point: (%d,%d)", x, y);
-           proto_tree_add_int(ttt, hf_x11_point_x, tvb, cur_offset, 2, x); cur_offset += 2;
-           proto_tree_add_int(ttt, hf_x11_point_y, tvb, cur_offset, 2, y); cur_offset += 2;
+           tti = proto_tree_add_none_format(tt, hf_x11_point, tvb, *offsetp, 4, "point: (%d,%d)", x, y);
+           ttt = proto_item_add_subtree(tti, ett_x11_point);
+           proto_tree_add_int(ttt, hf_x11_point_x, tvb, *offsetp, 2, x);
+           *offsetp += 2;
+           proto_tree_add_int(ttt, hf_x11_point_y, tvb, *offsetp, 2, y);
+           *offsetp += 2;
       }
 }
 
-static void listOfRectangle(tvbuff_t *tvb, int hf, int length)
+static void listOfRectangle(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_rectangle);
       while(length--) {
            gint16 x, y;
            unsigned width, height;
+           proto_item *tti;
            proto_tree *ttt;
 
-           if (cur_offset + 8 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           x = VALUE16(tvb, cur_offset);
-           y = VALUE16(tvb, cur_offset + 2);
-           width = VALUE16(tvb, cur_offset + 4);
-           height = VALUE16(tvb, cur_offset + 6);
+           x = VALUE16(tvb, *offsetp);
+           y = VALUE16(tvb, *offsetp + 2);
+           width = VALUE16(tvb, *offsetp + 4);
+           height = VALUE16(tvb, *offsetp + 6);
 
-           ttt = proto_tree_add_protocol_format(tt, hf_x11_rectangle, tvb, cur_offset, 8, 
+           tti = proto_tree_add_none_format(tt, hf_x11_rectangle, tvb, *offsetp, 8, 
                                                 "rectangle: %dx%d+%d+%d", width, height, x, y);
-           proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, cur_offset, 2, x); cur_offset += 2;
-           proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, cur_offset, 2, y); cur_offset += 2;
-           proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, cur_offset, 2, width); cur_offset += 2;
-           proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, cur_offset, 2, height); cur_offset += 2;
+           ttt = proto_item_add_subtree(tti, ett_x11_rectangle);
+           proto_tree_add_int(ttt, hf_x11_rectangle_x, tvb, *offsetp, 2, x);
+           *offsetp += 2;
+           proto_tree_add_int(ttt, hf_x11_rectangle_y, tvb, *offsetp, 2, y);
+           *offsetp += 2;
+           proto_tree_add_uint(ttt, hf_x11_rectangle_width, tvb, *offsetp, 2, width);
+           *offsetp += 2;
+           proto_tree_add_uint(ttt, hf_x11_rectangle_height, tvb, *offsetp, 2, height);
+           *offsetp += 2;
       }
 }
 
-static void listOfSegment(tvbuff_t *tvb, int hf, int length)
+static void listOfSegment(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int length)
 {
-      proto_tree *tt = proto_tree_add_item(t, hf, tvb, cur_offset, length * 8, little_endian);
+      proto_item *ti = proto_tree_add_item(t, hf, tvb, *offsetp, length * 8, little_endian);
+      proto_tree *tt = proto_item_add_subtree(ti, ett_x11_list_of_segment);
       while(length--) {
            gint16 x1, y1, x2, y2;
+           proto_item *tti;
            proto_tree *ttt;
 
-           if (cur_offset + 8 > next_offset) {
-               /* List runs past end of message. */
-               return;
-           }
-           x1 = VALUE16(tvb, cur_offset);
-           y1 = VALUE16(tvb, cur_offset + 2);
-           x2 = VALUE16(tvb, cur_offset + 4);
-           y2 = VALUE16(tvb, cur_offset + 6);
+           x1 = VALUE16(tvb, *offsetp);
+           y1 = VALUE16(tvb, *offsetp + 2);
+           x2 = VALUE16(tvb, *offsetp + 4);
+           y2 = VALUE16(tvb, *offsetp + 6);
 
-           ttt = proto_tree_add_protocol_format(tt, hf_x11_segment, tvb, cur_offset, 8, 
+           tti = proto_tree_add_none_format(tt, hf_x11_segment, tvb, *offsetp, 8, 
                                                 "segment: (%d,%d)-(%d,%d)", x1, y1, x2, y2);
-           proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
-           proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, cur_offset, 2, little_endian); cur_offset += 2;
+           ttt = proto_item_add_subtree(tti, ett_x11_segment);
+           proto_tree_add_item(ttt, hf_x11_segment_x1, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           proto_tree_add_item(ttt, hf_x11_segment_y1, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           proto_tree_add_item(ttt, hf_x11_segment_x2, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
+           proto_tree_add_item(ttt, hf_x11_segment_y2, tvb, *offsetp, 2, little_endian);
+           *offsetp += 2;
       }
 }
 
@@ -1040,37 +1112,50 @@ static void stringCopy(char *dest, const char *source, int length)
       *dest++ = '\0';
 }
 
-static void listOfString8(tvbuff_t *tvb, int hf, int hf_item, int length)
+static void listOfString8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int hf_item, int length)
 {
       char *s = NULL;
-      int allocated = 0;
+      guint allocated = 0;
+      proto_item *ti;
       proto_tree *tt;
       int i;
 
       /* Compute total length */
       
-      int scanning_offset = cur_offset; /* Scanning pointer */
+      int scanning_offset = *offsetp; /* Scanning pointer */
       int l;
       for(i = length; i; i--) {
            l = tvb_get_guint8(tvb, scanning_offset);
            scanning_offset += 1 + l;
       }
 
-      tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
+      ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
+      tt = proto_item_add_subtree(ti, ett_x11_list_of_string8);
+
+      /*
+       * In case we throw an exception, clean up whatever stuff we've
+       * allocated (if any).
+       */
+      CLEANUP_PUSH(g_free, s);
 
       while(length--) {
-           unsigned l = VALUE8(tvb, cur_offset);
-           if (allocated < l + 1) {
+           unsigned l = VALUE8(tvb, *offsetp);
+           if (allocated < (l + 1)) {
                  /* g_realloc doesn't work ??? */
                  g_free(s);
                  s = g_malloc(l + 1);
                  allocated = l + 1;
            }
-           stringCopy(s, tvb_get_ptr(tvb, cur_offset + 1, l), l); /* Nothing better for now. We need a better string handling API. */
-           proto_tree_add_string_format(tt, hf_item, tvb, cur_offset, l + 1, s, "\"%s\"", s);
-           cur_offset += l + 1;
+           stringCopy(s, tvb_get_ptr(tvb, *offsetp + 1, l), l); /* Nothing better for now. We need a better string handling API. */
+           proto_tree_add_string_format(tt, hf_item, tvb, *offsetp, l + 1, s, "\"%s\"", s);
+           *offsetp += l + 1;
       }
-      g_free(s);
+
+      /*
+       * Call the cleanup handler to free the string and pop the handler.
+       */
+      CLEANUP_CALL_AND_POP;
 }
 
 #define STRING16_MAX_DISPLAYED_LENGTH 150
@@ -1078,8 +1163,8 @@ static void listOfString8(tvbuff_t *tvb, int hf, int hf_item, int length)
 static int stringIsActuallyAn8BitString(tvbuff_t *tvb, int offset, unsigned length)
 {
       if (length > STRING16_MAX_DISPLAYED_LENGTH) length = STRING16_MAX_DISPLAYED_LENGTH;
-      for(; length > 0; cur_offset += 2, length--) {
-           if (tvb_get_guint8(tvb, cur_offset))
+      for(; length > 0; offset += 2, length--) {
+           if (tvb_get_guint8(tvb, offset))
                return FALSE;
       }
       return TRUE;
@@ -1103,7 +1188,7 @@ static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
                  truncated = TRUE;
                  l = STRING16_MAX_DISPLAYED_LENGTH;
            }
-           if (*sLength < l + 3) {
+           if (*sLength < (int) l + 3) {
                  g_free(*s);
                  *s = g_malloc(l + 3);
                  *sLength = l + 3;
@@ -1126,20 +1211,22 @@ static void string16_with_buffer_preallocated(tvbuff_t *tvb, proto_tree *t,
            proto_tree_add_string_format(t, hf, tvb, offset, length, tvb_get_ptr(tvb, offset, length), "%s: %s", 
                                        proto_registrar_get_nth(hf) -> name, *s);
       } else
-           proto_tree_add_bytes(t, hf_bytes, tvb, offset, length, tvb_get_ptr(tvb, offset, length));
+           proto_tree_add_item(t, hf_bytes, tvb, offset, length, little_endian);
 
 }
 
-static void listOfTextItem(tvbuff_t *tvb, int hf, int sizeIs16)
+static void listOfTextItem(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int sizeIs16, int next_offset)
 {
       int allocated = 0;
       char *s = NULL;
+      proto_item *ti;
       proto_tree *tt;
       guint32 fid;
 
       /* Compute total length */
       
-      int scanning_offset = cur_offset; /* Scanning pointer */
+      int scanning_offset = *offsetp; /* Scanning pointer */
       int l;                            /* Length of an individual item */
       int n = 0;                        /* Number of items */
 
@@ -1151,88 +1238,105 @@ static void listOfTextItem(tvbuff_t *tvb, int hf, int sizeIs16)
            scanning_offset += l == 255 ? 4 : l + (sizeIs16 ? l : 0) + 1;
       }
 
-      tt = proto_tree_add_item(t, hf, tvb, cur_offset, scanning_offset - cur_offset, little_endian);
+      ti = proto_tree_add_item(t, hf, tvb, *offsetp, scanning_offset - *offsetp, little_endian);
+      tt = proto_item_add_subtree(ti, ett_x11_list_of_text_item);
+
+      /*
+       * In case we throw an exception, clean up whatever stuff we've
+       * allocated (if any).
+       */
+      CLEANUP_PUSH(g_free, s);
 
       while(n--) {
-           unsigned l = VALUE8(tvb, cur_offset);
+           unsigned l = VALUE8(tvb, *offsetp);
            if (l == 255) { /* Item is a font */
-                 fid = tvb_get_ntohl(tvb, cur_offset + 1);
-                 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, cur_offset, 5, fid);
-                 cur_offset += 5;
+                 fid = tvb_get_ntohl(tvb, *offsetp + 1);
+                 proto_tree_add_uint(tt, hf_x11_textitem_font, tvb, *offsetp, 5, fid);
+                 *offsetp += 5;
            } else { /* Item is a string */
+                 proto_item *tti;
                  proto_tree *ttt;
-                 gint8 delta = VALUE8(tvb, cur_offset + 1);
+                 gint8 delta = VALUE8(tvb, *offsetp + 1);
                  if (sizeIs16) l += l;
-                 if (allocated < l + 1) {
+                 if ((unsigned) allocated < l + 1) {
                        /* g_realloc doesn't work ??? */
                        g_free(s);
                        s = g_malloc(l + 1);
                        allocated = l + 1;
                  }
-                 stringCopy(s, tvb_get_ptr(tvb, cur_offset + 2, l), l);
-                 ttt = proto_tree_add_protocol_format(tt, hf_x11_textitem_string, tvb, cur_offset, l + 2,
+                 stringCopy(s, tvb_get_ptr(tvb, *offsetp + 2, l), l);
+                 tti = proto_tree_add_none_format(tt, hf_x11_textitem_string, tvb, *offsetp, l + 2,
                                                       "textitem (string): delta = %d, \"%s\"",
                                                       delta, s);
-                 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, cur_offset + 1, 1, little_endian);
+                 ttt = proto_item_add_subtree(tti, ett_x11_text_item);
+                 proto_tree_add_item(ttt, hf_x11_textitem_string_delta, tvb, *offsetp + 1, 1, little_endian);
                  if (sizeIs16)
                        string16_with_buffer_preallocated(tvb, ttt, hf_x11_textitem_string_string16, 
                                                          hf_x11_textitem_string_string16_bytes,
-                                                         cur_offset + 2, l,
+                                                         *offsetp + 2, l,
                                                           &s, &allocated);
                  else
                        proto_tree_add_string_format(ttt, hf_x11_textitem_string_string8, tvb, 
-                                                    cur_offset + 2, l, s, "\"%s\"", s);
-                 cur_offset += l + 2;
+                                                    *offsetp + 2, l, s, "\"%s\"", s);
+                 *offsetp += l + 2;
            }
       }
-      g_free(s);
+
+      /*
+       * Call the cleanup handler to free the string and pop the handler.
+       */
+      CLEANUP_CALL_AND_POP;
 }
 
-static guint32 field8(tvbuff_t *tvb, int hf)
+static guint32 field8(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
 {
-      guint32 v = VALUE8(tvb, cur_offset);
-      struct header_field_info *hfi = proto_registrar_get_nth(hf);
+      guint32 v = VALUE8(tvb, *offsetp);
+      header_field_info *hfi = proto_registrar_get_nth(hf);
       gchar *enumValue = NULL;
       gchar *nameAsChar = hfi -> name;
 
       if (hfi -> strings)
            enumValue = match_strval(v, cVALS(hfi -> strings));
       if (enumValue)
-           proto_tree_add_uint_format(t, hf, tvb, cur_offset, 1, v, "%s: %d (%s)", nameAsChar, v, enumValue);
+           proto_tree_add_uint_format(t, hf, tvb, *offsetp, 1, v,
+                                      hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%02x (%s)",
+                                      nameAsChar, v, enumValue);
       else
-           proto_tree_add_item(t, hf, tvb, cur_offset, 1, little_endian);
-      cur_offset += 1;
+           proto_tree_add_item(t, hf, tvb, *offsetp, 1, little_endian);
+      *offsetp += 1;
       return v;
 }
 
-static guint32 field16(tvbuff_t *tvb, int hf)
+static guint32 field16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
 {
-      guint32 v = VALUE16(tvb, cur_offset);
-      proto_tree_add_item(t, hf, tvb, cur_offset, 2, v);
-      cur_offset += 2;
+      guint32 v = VALUE16(tvb, *offsetp);
+      proto_tree_add_item(t, hf, tvb, *offsetp, 2, little_endian);
+      *offsetp += 2;
       return v;
 }
 
-static guint32 field32(tvbuff_t *tvb, int hf)
+static guint32 field32(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf)
 {
-      guint32 v = VALUE32(tvb, cur_offset);
-      struct header_field_info *hfi = proto_registrar_get_nth(hf);
+      guint32 v = VALUE32(tvb, *offsetp);
+      header_field_info *hfi = proto_registrar_get_nth(hf);
       gchar *enumValue = NULL;
       gchar *nameAsChar = hfi -> name;
 
       if (hfi -> strings)
            enumValue = match_strval(v, cVALS(hfi -> strings));
       if (enumValue)
-           proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, "%s: 0x%08x (%s)", nameAsChar, v, enumValue);
+           proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v,
+                                      hfi -> display == BASE_DEC ? "%s: %u (%s)" : "%s: 0x%08x (%s)",
+                                      nameAsChar, v, enumValue);
       else
-           proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, v, 
-                                      hfi -> display == BASE_DEC ? "%s: %d" : "%s : 0x%08x",
+           proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, v, 
+                                      hfi -> display == BASE_DEC ? "%s: %u" : "%s: 0x%08x",
                                       nameAsChar, v);
-      cur_offset += 4;
+      *offsetp += 4;
       return v;
 }
 
-static void gcAttributes(tvbuff_t *tvb)
+static void gcAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
       BITMASK32(gc_value);
       BITFIELD(ENUM8,  gc_value_mask, function);
@@ -1258,9 +1362,10 @@ static void gcAttributes(tvbuff_t *tvb)
       BITFIELD(CARD16, gc_value_mask, dash_offset);
       BITFIELD(CARD8,  gc_value_mask, gc_dashes);
       BITFIELD(ENUM8,  gc_value_mask, arc_mode);
+      ENDBITMASK;
 }
 
-static void gcMask(tvbuff_t *tvb)
+static void gcMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
       BITMASK32(gc_value);
       FLAG(gc_value, function);
@@ -1286,19 +1391,19 @@ static void gcMask(tvbuff_t *tvb)
       FLAG(gc_value, dash_offset);
       FLAG(gc_value, gc_dashes);
       FLAG(gc_value, arc_mode);
+      ENDBITMASK;
 }
 
-static guint32 requestLength(tvbuff_t *tvb)
+static guint32 requestLength(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      guint32 res = VALUE16(tvb, cur_offset) * 4;
-      proto_tree_add_uint(t, hf_x11_request_length, tvb, cur_offset, 2, res);
-      cur_offset += 2;
+      guint32 res = VALUE16(tvb, *offsetp) * 4;
+      proto_tree_add_uint(t, hf_x11_request_length, tvb, *offsetp, 2, res);
+      *offsetp += 2;
       return res;
 }
 
-static void setOfEvent(tvbuff_t *tvb)
+static void setOfEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      struct maskStruct save = lastMask;
       BITMASK32(event);
       FLAG(event, KeyPress);
       FLAG(event, KeyRelease);
@@ -1325,13 +1430,12 @@ static void setOfEvent(tvbuff_t *tvb)
       FLAG(event, PropertyChange);
       FLAG(event, ColormapChange);
       FLAG(event, OwnerGrabButton);
-      FLAG(event, erroneous_bits);
-      lastMask = save;
+      FLAG_IF_NONZERO(event, erroneous_bits);
+      ENDBITMASK;
 }
 
-static void setOfDeviceEvent(tvbuff_t *tvb)
+static void setOfDeviceEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      struct maskStruct save = lastMask;
       BITMASK32(do_not_propagate);
       FLAG(do_not_propagate, KeyPress);
       FLAG(do_not_propagate, KeyRelease);
@@ -1344,22 +1448,28 @@ static void setOfDeviceEvent(tvbuff_t *tvb)
       FLAG(do_not_propagate, Button4Motion);
       FLAG(do_not_propagate, Button5Motion);
       FLAG(do_not_propagate, ButtonMotion);
-      FLAG(do_not_propagate, erroneous_bits);
-      lastMask = save;
+      FLAG_IF_NONZERO(do_not_propagate, erroneous_bits);
+      ENDBITMASK;
 }
 
-static void setOfKeyMask(tvbuff_t *tvb)
+static void setOfKeyMask(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      struct maskStruct save = lastMask;
-      lastMask._value = VALUE16(tvb, cur_offset);
-      lastMask._offset = cur_offset;
-      lastMask._zone = 2;
-      if (lastMask._value == 0x8000)
-           proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, cur_offset, 2, 0x8000,
+      proto_item *ti;
+      guint32 bitmask_value;
+      int bitmask_offset;
+      int bitmask_size;
+      proto_tree *bitmask_tree;
+
+      bitmask_value = VALUE16(tvb, *offsetp);
+      bitmask_offset = *offsetp;
+      bitmask_size = 2;
+      if (bitmask_value == 0x8000)
+           proto_tree_add_uint_format(t, hf_x11_modifiers_mask_AnyModifier, tvb, *offsetp, 2, 0x8000,
                                       "modifiers-masks: 0x8000 (AnyModifier)");
       else {
-           lastMask._tree = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, cur_offset, 2, 
-                                                lastMask._value);
+           ti = proto_tree_add_uint(t, hf_x11_modifiers_mask, tvb, *offsetp, 2, 
+                                                bitmask_value);
+           bitmask_tree = proto_item_add_subtree(ti, ett_x11_set_of_key_mask);
            FLAG(modifiers, Shift);
            FLAG(modifiers, Lock);
            FLAG(modifiers, Control);
@@ -1368,15 +1478,13 @@ static void setOfKeyMask(tvbuff_t *tvb)
            FLAG(modifiers, Mod3);
            FLAG(modifiers, Mod4);
            FLAG(modifiers, Mod5);
-           FLAG(modifiers, erroneous_bits);
+           FLAG_IF_NONZERO(modifiers, erroneous_bits);
       }
-      lastMask = save;
-      cur_offset += 2; 
+      *offsetp += 2; 
 }
 
-static void setOfPointerEvent(tvbuff_t *tvb)
+static void setOfPointerEvent(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
-      struct maskStruct save = lastMask;
       BITMASK16(pointer_event);
       FLAG(pointer_event, ButtonPress);
       FLAG(pointer_event, ButtonRelease);
@@ -1391,42 +1499,69 @@ static void setOfPointerEvent(tvbuff_t *tvb)
       FLAG(pointer_event, Button5Motion);
       FLAG(pointer_event, ButtonMotion);
       FLAG(pointer_event, KeymapState);
-      FLAG(pointer_event, erroneous_bits);
-      lastMask = save;
+      FLAG_IF_NONZERO(pointer_event, erroneous_bits);
+      ENDBITMASK;
 }
 
-static void string8(tvbuff_t *tvb, const char *nameAsChar, int hf, unsigned length)
+static void string8(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+    const char *nameAsChar, int hf, unsigned length)
 {
       char *s = g_malloc(length + 1);
-      stringCopy(s, tvb_get_ptr(tvb, cur_offset, length), length);
-      proto_tree_add_string_format(t, hf, tvb, cur_offset, length, s, "%s: %s", nameAsChar, s);
-      g_free(s);
-      cur_offset += length;
+
+      /*
+       * In case we throw an exception, clean up whatever stuff we've
+       * allocated (if any).
+       */
+      CLEANUP_PUSH(g_free, s);
+
+      stringCopy(s, tvb_get_ptr(tvb, *offsetp, length), length);
+      proto_tree_add_string_format(t, hf, tvb, *offsetp, length, s, "%s: %s", nameAsChar, s);
+
+      /*
+       * Call the cleanup handler to free the string and pop the handler.
+       */
+      CLEANUP_CALL_AND_POP;
+
+      *offsetp += length;
 }
 
 /* The length is the length of the _byte_zone_ (twice the length of the string) */
 
-static void string16(tvbuff_t *tvb, int hf, int hf_bytes, unsigned length)
+static void string16(tvbuff_t *tvb, int *offsetp, proto_tree *t, int hf,
+    int hf_bytes, unsigned length)
 {
       char *s = NULL;
       unsigned l = 0;
+
+      /*
+       * In case we throw an exception, clean up whatever stuff we've
+       * allocated (if any).
+       */
+      CLEANUP_PUSH(g_free, s);
+
       length += length;
-      string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, cur_offset, length, &s, &l);
-      g_free(s);
-      cur_offset += length;
+      string16_with_buffer_preallocated(tvb, t, hf, hf_bytes, *offsetp, length, &s, &l);
+
+      /*
+       * Call the cleanup handler to free the string and pop the handler.
+       */
+      CLEANUP_CALL_AND_POP;
+
+      *offsetp += length;
 }
 
-static void timestamp(tvbuff_t *tvb, const char *nameAsChar, int hf)
+static void timestamp(tvbuff_t *tvb, int *offsetp, proto_tree *t,
+    const char *nameAsChar, int hf)
 {
-      guint32 v = VALUE32(tvb, cur_offset);
+      guint32 v = VALUE32(tvb, *offsetp);
       if (!v)
-           proto_tree_add_uint_format(t, hf, tvb, cur_offset, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
+           proto_tree_add_uint_format(t, hf, tvb, *offsetp, 4, 0, "%s: 0 (CurrentTime)", nameAsChar);
       else
-           proto_tree_add_uint(t, hf, tvb, cur_offset, 4, v);
-      cur_offset += 4;
+           proto_tree_add_uint(t, hf, tvb, *offsetp, 4, v);
+      *offsetp += 4;
 }
 
-static void windowAttributes(tvbuff_t *tvb)
+static void windowAttributes(tvbuff_t *tvb, int *offsetp, proto_tree *t)
 {
       BITMASK32(window_value);
       BITFIELD(PIXMAP, window_value_mask, background_pixmap);
@@ -1444,1018 +1579,49 @@ static void windowAttributes(tvbuff_t *tvb)
       BITFIELD(SETofDEVICEEVENT, window_value_mask, do_not_propagate_mask);
       BITFIELD(COLORMAP, window_value_mask, colormap);
       BITFIELD(CURSOR, window_value_mask, cursor);
+      ENDBITMASK;
 }
 
-/************************************************************************
- ***                                                                  ***
- ***              D E C O D I N G   O N E   P A C K E T               ***
- ***                                                                  ***
- ************************************************************************/
+/*
+ * Data structure associated with a conversation; keeps track of the
+ * request for which we're expecting a reply, the frame number of
+ * the initial connection request, and the byte order of the connection.
+ *
+ * An opcode of -3 means we haven't yet seen any requests yet.
+ * An opcode of -2 means we're not expecting a reply.
+ * An opcode of -1 means means we're waiting for a reply to the initial
+ * connection request.
+ * Other values are the opcode of the request for which we're expecting
+ * a reply.
+ *
+ * XXX - assumes only one outstanding request is awaiting a reply,
+ * which should always be the case.
+ */
+#define NOTHING_SEEN           -3
+#define NOTHING_EXPECTED       -2
+#define INITIAL_CONN           -1
 
-static int dissect_x11_request_loop(tvbuff_t *tvb, proto_tree *root)
-{
-      int left = tvb_reported_length(tvb), nextLeft;
-      proto_item *ti;
-      guint8 v8, v8_2;
-      guint16 v16;
-      guint32 v32;
+#define BYTE_ORDER_BE          0
+#define BYTE_ORDER_LE          1
+#define BYTE_ORDER_UNKNOWN     -1
 
-      /* The X11 data stream to the server is just a sequence of requests,
-         each of which contains a length; for now, we dissect all the
-        requests in this frame until we run out of data in the frame.
-        Eventually, we should handle requests that cross frame
-        boundaries.
-
-        Note that "in this frame" refers to everything in the frame
-        as it appeared in the wire, not as it was captured; we want
-        an exception to be thrown if we go past the end of the
-        captured data in the frame without going past the end of the
-        data in the frame. */
-      for(;;) {
-           int length, opcode;
-           
-           /* fprintf(stderr, "Starting loop, left = %d, cur_offset = %d\n", left, cur_offset); */
-           if (left < 4) {
-               /* We ran out of data - we don't have enough data in
-                  the frame to get the length of this request. */
-               break;
-           }
-           length = VALUE16(tvb, cur_offset + 2) * 4;
-           /*      fprintf(stderr, "length = %d\n", length);*/
-           if (left < length) {
-               /* We ran out of data - we don't have enough data in
-                  the frame for the full request. */
-               break;
-           }
-           if (length < 4) {
-               /* Bogus message length? */
-               break;
-           }
+typedef struct {
+      int      opcode;         /* opcode for which we're awaiting a reply */
+      guint32  iconn_frame;    /* frame # of initial connection request */
+      int      byte_order;     /* byte order of connection */
+} x11_conv_data_t;
 
-           next_offset = cur_offset + length;
-           nextLeft = left - length;
-
-           ti = proto_tree_add_uint(root, hf_x11_request, tvb, cur_offset, length, tvb_get_guint8(tvb, cur_offset));
-           t = proto_item_add_subtree(ti, ett_x11_request);
-
-           OPCODE();
-
-           switch(opcode) {
-               case 1: /* CreateWindow */
-                 CARD8(depth);
-                 REQUEST_LENGTH();
-                 WINDOW(wid);
-                 WINDOW(parent);
-                 INT16(x);
-                 INT16(y);
-                 CARD16(width);
-                 CARD16(height);
-                 CARD16(border_width);
-                 ENUM16(window_class);
-                 VISUALID(visual);
-                 windowAttributes(tvb);
-                 break;
-
-               case 2: /* ChangeWindowAttributes */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 windowAttributes(tvb);
-                 break;
-
-               case 3: /* GetWindowAttributes */
-               case 4: /* DestroyWindow */
-               case 5: /* DestroySubwindows */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 6: /* ChangeSaveSet */
-                 ENUM8(save_set_mode);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 7: /* ReparentWindow */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 WINDOW(parent);
-                 INT16(x);
-                 INT16(y);
-                 break;
-
-               case 8: /* MapWindow */
-               case 9: /* MapSubWindow */
-               case 10: /* UnmapWindow */
-               case 11: /* UnmapSubwindows */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 12: /* ConfigureWindow */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 BITMASK16(configure_window);
-                 UNUSED(2); 
-                 BITFIELD(INT16,  configure_window_mask, x);
-                 BITFIELD(INT16,  configure_window_mask, y);
-                 BITFIELD(CARD16, configure_window_mask, width);
-                 BITFIELD(CARD16, configure_window_mask, height);
-                 BITFIELD(CARD16, configure_window_mask, border_width);
-                 BITFIELD(WINDOW, configure_window_mask, sibling);
-                 BITFIELD(ENUM8,  configure_window_mask, stack_mode);
-                 PAD();
-                 break;
-
-               case 13: /* CirculateWindow */
-                 ENUM8(direction);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 14: /* GetGeometry */
-               case 15: /* QueryTree */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 break;
-
-               case 16: /* InternAtom */
-                 BOOL(only_if_exists);
-                 REQUEST_LENGTH();
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 17: /* GetAtomName */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 ATOM(atom);
-                 break;
-
-               case 18: /* ChangeProperty */
-                 ENUM8(mode);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 ATOM(property);
-                 ATOM(type);
-                 CARD8(format);
-                 UNUSED(3);
-                 v32 = CARD32(data_length);
-                 LISTofBYTE(data, v32);
-                 PAD();
-                 break;
-
-               case 19: /* DeleteProperty */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 ATOM(property);
-                 break;
-
-               case 20: /* GetProperty */
-                 BOOL(delete);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 ATOM(property);
-                 ATOM(get_property_type);
-                 CARD32(long_offset);
-                 CARD32(long_length);
-                 break;
-
-               case 21: /* ListProperties */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 22: /* SetSelectionOwner */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(owner);
-                 ATOM(selection);
-                 TIMESTAMP(time);
-                 break;
-
-               case 23: /* GetSelectionOwner */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 ATOM(selection);
-                 break;
-
-               case 24: /* ConvertSelection */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(requestor);
-                 ATOM(selection);
-                 ATOM(target);
-                 ATOM(property);
-                 TIMESTAMP(time);
-                 break;
-
-               case 26: /* GrabPointer */
-                 BOOL(owner_events);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 SETofPOINTEREVENT(pointer_event_mask);
-                 ENUM8(pointer_mode);
-                 ENUM8(keyboard_mode);
-                 WINDOW(confine_to);
-                 CURSOR(cursor);
-                 TIMESTAMP(time);
-                 break;
-
-               case 27: /* UngrabPointer */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 TIMESTAMP(time);
-                 break;
-
-               case 28: /* GrabButton */
-                 BOOL(owner_events);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 SETofPOINTEREVENT(event_mask);
-                 ENUM8(pointer_mode);
-                 ENUM8(keyboard_mode);
-                 WINDOW(confine_to);
-                 CURSOR(cursor);
-                 BUTTON(button);
-                 UNUSED(1);
-                 SETofKEYMASK(modifiers);
-                 break;
-
-               case 29: /* UngrabButton */
-                 BUTTON(button);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 SETofKEYMASK(modifiers);
-                 UNUSED(2);
-                 break;
-
-               case 30: /* ChangeActivePointerGrab */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CURSOR(cursor);
-                 TIMESTAMP(time);
-                 SETofPOINTEREVENT(event_mask);
-                 UNUSED(2);
-                 break;
-
-               case 31: /* GrabKeyboard */
-                 BOOL(owner_events);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 TIMESTAMP(time);
-                 ENUM8(pointer_mode);
-                 ENUM8(keyboard_mode);
-                 UNUSED(2);
-                 break;
-
-               case 32: /* UngrabKeyboard */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 TIMESTAMP(time);
-                 break;
-
-               case 33: /* GrabKey */
-                 BOOL(owner_events);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 SETofKEYMASK(modifiers);
-                 KEYCODE(key);
-                 ENUM8(pointer_mode);
-                 ENUM8(keyboard_mode);
-                 UNUSED(3);
-                 break;
-
-               case 34: /* UngrabKey */
-                 KEYCODE(key);
-                 REQUEST_LENGTH();
-                 WINDOW(grab_window);
-                 SETofKEYMASK(modifiers);
-                 UNUSED(2);
-                 break;
-
-               case 35: /* AllowEvents */
-                 ENUM8(allow_events_mode);
-                 REQUEST_LENGTH();
-                 TIMESTAMP(time);
-                 break;
-
-               case 36: /* GrabServer */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 37: /* UngrabServer */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 38: /* QueryPointer */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 39: /* GetMotionEvents */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 TIMESTAMP(start);
-                 TIMESTAMP(stop);
-                 break;
-
-               case 40: /* TranslateCoordinates */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(src_window);
-                 WINDOW(dst_window);
-                 INT16(src_x);
-                 INT16(src_y);
-                 break;
-
-               case 41: /* WarpPointer */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(warp_pointer_src_window);
-                 WINDOW(warp_pointer_dst_window);
-                 INT16(src_x);
-                 INT16(src_y);
-                 CARD16(src_width);
-                 CARD16(src_height);
-                 INT16(dst_x);
-                 INT16(dst_y);
-                 break;
-
-               case 42: /* SetInputFocus */
-                 ENUM8(revert_to);
-                 REQUEST_LENGTH();
-                 WINDOW(focus);
-                 TIMESTAMP(time);
-                 break;
-
-               case 43: /* GetInputFocus */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 44: /* QueryKeymap */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 45: /* OpenFont */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 FONT(fid);
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 46: /* CloseFont */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 FONT(font);
-                 break;
-
-               case 47: /* QueryFont */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 FONTABLE(font);
-                 break;
-
-               case 48: /* QueryTextExtents */
-                 v8 = BOOL(odd_length);
-                 REQUEST_LENGTH();
-                 FONTABLE(font);
-                 STRING16(string16, (next_offset - cur_offset - (v8 ? 2 : 0)) / 2);
-                 PAD();
-                 break;
-
-               case 49: /* ListFonts */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CARD16(max_names);
-                 v16 = FIELD16(pattern_length);
-                 STRING8(pattern, v16);
-                 PAD();
-                 break;
-
-               case 50: /* ListFontsWithInfo */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CARD16(max_names);
-                 v16 = FIELD16(pattern_length);
-                 STRING8(pattern, v16);
-                 PAD();
-                 break;
-
-               case 51: /* SetFontPath */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 v16 = CARD16(str_number_in_path);
-                 UNUSED(2);
-                 LISTofSTRING8(path, v16);
-                 PAD();
-                 break;
-
-               case 52: /* GetFontPath */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 53: /* CreatePixmap */
-                 CARD8(depth);
-                 REQUEST_LENGTH();
-                 PIXMAP(pid);
-                 DRAWABLE(drawable);
-                 CARD16(width);
-                 CARD16(height);
-                 break;
-
-               case 54: /* FreePixmap */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 PIXMAP(pixmap);
-                 break;
-
-               case 55: /* CreateGC */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 GCONTEXT(cid);
-                 DRAWABLE(drawable);
-                 gcAttributes(tvb);
-                 break;
-
-               case 56: /* ChangeGC */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 GCONTEXT(gc);
-                 gcAttributes(tvb);
-                 break;
-
-               case 57: /* CopyGC */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 GCONTEXT(src_gc);
-                 GCONTEXT(dst_gc);
-                 gcMask(tvb);
-                 break;
-
-               case 58: /* SetDashes */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 GCONTEXT(gc);
-                 CARD16(dash_offset);
-                 v16 = FIELD16(dashes_length);
-                 LISTofCARD8(dashes, v16);
-                 PAD();
-                 break;
-
-               case 59: /* SetClipRectangles */
-                 ENUM8(ordering);
-                 REQUEST_LENGTH();
-                 GCONTEXT(gc);
-                 INT16(clip_x_origin);
-                 INT16(clip_y_origin);
-                 LISTofRECTANGLE(rectangles);
-                 break;
-
-               case 60: /* FreeGC */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 GCONTEXT(gc);
-                 break;
-
-               case 61: /* ClearArea */
-                 BOOL(exposures);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 INT16(x);
-                 INT16(y);
-                 CARD16(width);
-                 CARD16(height);
-                 break;
-
-               case 62: /* CopyArea */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(src_drawable);
-                 DRAWABLE(dst_drawable);
-                 GCONTEXT(gc);
-                 INT16(src_x);
-                 INT16(src_y);
-                 INT16(dst_x);
-                 INT16(dst_y);
-                 CARD16(width);
-                 CARD16(height);
-                 break;
-
-               case 63: /* CopyPlane */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(src_drawable);
-                 DRAWABLE(dst_drawable);
-                 GCONTEXT(gc);
-                 INT16(src_x);
-                 INT16(src_y);
-                 INT16(dst_x);
-                 INT16(dst_y);
-                 CARD16(width);
-                 CARD16(height);
-                 CARD32(bit_plane);
-                 break;
-
-               case 64: /* PolyPoint */
-                 ENUM8(coordinate_mode);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofPOINT(points, v16 - 12);
-                 break;
-
-               case 65: /* PolyLine */
-                 ENUM8(coordinate_mode);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofPOINT(points, v16 - 12);
-                 break;
-
-               case 66: /* PolySegment */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofSEGMENT(segments);
-                 break;
-
-               case 67: /* PolyRectangle */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofRECTANGLE(rectangles);
-                 break;
-
-               case 68: /* PolyArc */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofARC(arcs);
-                 break;
-
-               case 69: /* FillPoly */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 ENUM8(shape);
-                 ENUM8(coordinate_mode);
-                 UNUSED(2);
-                 LISTofPOINT(points, v16 - 16);
-                 break;
-
-               case 70: /* PolyFillRectangle */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofRECTANGLE(rectangles);
-                 break;
-
-               case 71: /* PolyFillArc */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 LISTofARC(arcs);
-                 break;
-
-               case 72: /* PutImage */
-                 ENUM8(image_format);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 CARD16(width);
-                 CARD16(height);
-                 INT16(dst_x);
-                 INT16(dst_y);
-                 CARD8(left_pad);
-                 CARD8(depth);
-                 UNUSED(2);
-                 LISTofBYTE(data, v16 - 24);
-                 PAD();
-                 break;
-
-               case 73: /* GetImage */
-                 ENUM8(image_pixmap_format);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 INT16(x);
-                 INT16(y);
-                 CARD16(width);
-                 CARD16(height);
-                 CARD32(plane_mask);
-                 break;
-
-               case 74: /* PolyText8 */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 INT16(x);
-                 INT16(y);
-                 LISTofTEXTITEM8(items);
-                 PAD();
-                 break;
-
-               case 75: /* PolyText16 */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 INT16(x);
-                 INT16(y);
-                 LISTofTEXTITEM16(items);
-                 PAD();
-                 break;
-
-               case 76: /* ImageText8 */
-                 v8 = FIELD8(string_length);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 INT16(x);
-                 INT16(y);
-                 STRING8(string, v8);
-                 PAD();
-                 break;
-
-               case 77: /* ImageText16 */
-                 v8 = FIELD8(string_length);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 GCONTEXT(gc);
-                 INT16(x);
-                 INT16(y);
-                 STRING16(string16, v8);
-                 PAD();
-                 break;
-
-               case 78: /* CreateColormap */
-                 ENUM8(alloc);
-                 REQUEST_LENGTH();
-                 COLORMAP(mid);
-                 WINDOW(window);
-                 VISUALID(visual);
-                 break;
-
-               case 79: /* FreeColormap */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 break;
-
-               case 80: /* CopyColormapAndFree */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(mid);
-                 COLORMAP(src_cmap);
-                 break;
-
-               case 81: /* InstallColormap */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 break;
-
-               case 82: /* UninstallColormap */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 break;
-
-               case 83: /* ListInstalledColormaps */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 WINDOW(window);
-                 break;
-
-               case 84: /* AllocColor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 CARD16(red);
-                 CARD16(green);
-                 CARD16(blue);
-                 UNUSED(2);
-                 break;
-
-               case 85: /* AllocNamedColor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 86: /* AllocColorCells */
-                 BOOL(contiguous);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 CARD16(colors);
-                 CARD16(planes);
-                 break;
-
-               case 87: /* AllocColorPlanes */
-                 BOOL(contiguous);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 CARD16(colors);
-                 CARD16(reds);
-                 CARD16(greens);
-                 CARD16(blues);
-                 break;
-
-               case 88: /* FreeColors */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 CARD32(plane_mask);
-                 LISTofCARD32(pixels, v16 - 12);
-                 break;
-
-               case 89: /* StoreColors */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 LISTofCOLORITEM(color_items, v16 - 8);
-                 break;
-
-               case 90: /* StoreNamedColor */
-                 COLOR_FLAGS(color);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 CARD32(pixel);        
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 91: /* QueryColors */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 LISTofCARD32(pixels, v16 - 8);
-                 break;
-
-               case 92: /* LookupColor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 COLORMAP(cmap);
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 93: /* CreateCursor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CURSOR(cid);
-                 PIXMAP(source_pixmap);
-                 PIXMAP(mask);
-                 CARD16(fore_red);
-                 CARD16(fore_green);
-                 CARD16(fore_blue);
-                 CARD16(back_red);
-                 CARD16(back_green);
-                 CARD16(back_blue);
-                 CARD16(x);
-                 CARD16(y);
-                 break;
-
-               case 94: /* CreateGlyphCursor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CURSOR(cid);
-                 FONT(source_font);
-                 FONT(mask_font);
-                 CARD16(source_char);
-                 CARD16(mask_char);
-                 CARD16(fore_red);
-                 CARD16(fore_green);
-                 CARD16(fore_blue);
-                 CARD16(back_red);
-                 CARD16(back_green);
-                 CARD16(back_blue);
-                 break;
-
-               case 95: /* FreeCursor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CURSOR(cursor);
-                 break;
-
-               case 96: /* RecolorCursor */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CURSOR(cursor);
-                 CARD16(fore_red);
-                 CARD16(fore_green);
-                 CARD16(fore_blue);
-                 CARD16(back_red);
-                 CARD16(back_green);
-                 CARD16(back_blue);
-                 break;
-
-               case 97: /* QueryBestSize */
-                 ENUM8(class);
-                 REQUEST_LENGTH();
-                 DRAWABLE(drawable);
-                 CARD16(width);
-                 CARD16(height);
-                 break;
-
-               case 98: /* QueryExtension */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 v16 = FIELD16(name_length);
-                 UNUSED(2);
-                 STRING8(name, v16);
-                 PAD();
-                 break;
-
-               case 99: /* ListExtensions */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 100: /* ChangeKeyboardMapping */
-                 v8 = FIELD8(keycode_count);
-                 REQUEST_LENGTH();
-                 KEYCODE(first_keycode);
-                 v8_2 = FIELD8(keysyms_per_keycode);
-                 UNUSED(2);
-                 LISTofKEYSYM(keysyms, v8, v8_2);
-                 break;
-
-               case 101: /* GetKeyboardMapping */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 KEYCODE(first_keycode);
-                 FIELD8(count);
-                 UNUSED(2);
-                 break;
-
-               case 102: /* ChangeKeyboardControl */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 BITMASK32(keyboard_value);
-                 BITFIELD(INT8, keyboard_value_mask, key_click_percent);
-                 BITFIELD(INT8, keyboard_value_mask, bell_percent);
-                 BITFIELD(INT16, keyboard_value_mask, bell_pitch);
-                 BITFIELD(INT16, keyboard_value_mask, bell_duration);
-                 BITFIELD(INT16, keyboard_value_mask, led);
-                 BITFIELD(ENUM8, keyboard_value_mask, led_mode);
-                 BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
-                 BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
-                 break;
-
-               case 103: /* GetKeyboardControl */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 104: /* Bell */
-                 INT8(percent);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 105: /* ChangePointerControl */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 INT16(acceleration_numerator);
-                 INT16(acceleration_denominator);
-                 INT16(threshold);
-                 BOOL(do_acceleration);
-                 BOOL(do_threshold);
-                 break;
-
-               case 106: /* GetPointerControl */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 107: /* SetScreenSaver */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 INT16(timeout);
-                 INT16(interval);
-                 ENUM8(prefer_blanking);
-                 ENUM8(allow_exposures);
-                 UNUSED(2);
-                 break;
-
-               case 108: /* GetScreenSaver */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 109: /* ChangeHosts */
-                 ENUM8(change_host_mode);
-                 REQUEST_LENGTH();
-                 ENUM8(family);
-                 UNUSED(1);
-                 v16 = CARD16(address_length);
-                 LISTofCARD8(address, v16);
-                 break;
-
-               case 110: /* ListHosts */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 111: /* SetAccessControl */
-                 ENUM8(access_mode);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 112: /* SetCloseDownMode */
-                 ENUM8(close_down_mode);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 113: /* KillClient */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 CARD32(resource);
-                 break;
-
-               case 114: /* RotateProperties */
-                 UNUSED(1);
-                 v16 = REQUEST_LENGTH();
-                 WINDOW(window);
-                 CARD16(property_number);
-                 INT16(delta);
-                 LISTofATOM(properties, (v16 - 12));
-                 break;
-
-               case 115: /* ForceScreenSaver */
-                 ENUM8(screen_saver_mode);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 116: /* SetPointerMapping */
-                 v8 = FIELD8(map_length);
-                 REQUEST_LENGTH();
-                 LISTofCARD8(map, v8);
-                 PAD();
-                 break;
-
-               case 117: /* GetPointerMapping */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-
-               case 118: /* SetModifierMapping */
-                 v8 = FIELD8(keycodes_per_modifier);
-                 REQUEST_LENGTH();
-                 LISTofKEYCODE(keycodes, v8);
-                 break;
-
-               case 119: /* GetModifierMapping */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-                 
-               case 127: /* NoOperation */
-                 UNUSED(1);
-                 REQUEST_LENGTH();
-                 break;
-           }
-           if (cur_offset < next_offset)
-                 proto_tree_add_item(t, hf_x11_undecoded, tvb, cur_offset, next_offset - cur_offset, little_endian);
-           cur_offset = next_offset;
-           left = nextLeft;
-      }
+static GMemChunk *x11_state_chunk = NULL;
 
-      return left;
+static void x11_init_protocol(void)
+{
+      if (x11_state_chunk != NULL)
+           g_mem_chunk_destroy(x11_state_chunk);
+
+      x11_state_chunk = g_mem_chunk_new("x11_state_chunk",
+                                       sizeof (x11_conv_data_t),
+                                       128 * sizeof (x11_conv_data_t),
+                                       G_ALLOC_ONLY);
 }
 
 /************************************************************************
@@ -2464,22 +1630,6 @@ static int dissect_x11_request_loop(tvbuff_t *tvb, proto_tree *root)
  ***                                                                  ***
  ************************************************************************/
 
-static GTree *byte_ordering_cache = NULL;
-static GMemChunk *address_chunk = NULL;
-static GMemChunk *ipv4_chunk = NULL;
-static GMemChunk *ipv6_chunk = NULL;
-
-static gint compareAddresses(gconstpointer aa, gconstpointer bb)
-{
-      const address *a = (const address *)aa;
-      const address *b = (const address *)bb;
-      int c = b -> type - a -> type;
-      if (c) return c;
-      c = b -> len - a -> len;
-      if (c) return c;
-      return memcmp(b -> data, a -> data, a -> len);
-}
-
 /* If we can't guess, we return TRUE (that is little_endian), cause
    I'm developing on a Linux box :-). The (non-)guess isn't cached
    however, so we may have more luck next time. I'm quite conservative
@@ -2488,9 +1638,9 @@ static gint compareAddresses(gconstpointer aa, gconstpointer bb)
    started in a previous packet...
 */
 
-int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+static int numberOfBitSetTable[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
 
-int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
+static int numberOfBitSet(tvbuff_t *tvb, int offset, int maskLength)
 {
       int res = 0;
       while(maskLength--) {
@@ -2762,18 +1912,26 @@ static int x_endian_match(tvbuff_t *tvb, guint16 (*v16)(tvbuff_t *, gint))
 }
 
 static gboolean
-guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
+guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo,
+                   x11_conv_data_t *state_info)
 {
       /* With X the client gives the byte ordering for the protocol,
         and the port on the server tells us we're speaking X. */
 
       int le, be, decision, decisionToCache;
 
-      gboolean is_reply = (pinfo->srcport == pinfo->match_port);
-      address *addr = is_reply ? &pinfo->net_dst : &pinfo->net_src;
-      gint32 cache = GPOINTER_TO_INT(g_tree_lookup(byte_ordering_cache, addr));
-      if (cache) return cache > 0 ? TRUE : FALSE;
-      if (is_reply) return TRUE; /* We don't try to guess on a reply / event for now */
+      if (state_info->byte_order == BYTE_ORDER_BE)
+           return FALSE;       /* known to be big-endian */
+      else if (state_info->byte_order == BYTE_ORDER_LE)
+           return TRUE;        /* known to be little-endian */
+
+      if (pinfo->srcport == pinfo->match_port) {
+           /*
+            * This is a reply or event; we don't try to guess the
+            * byte order on it for now.
+            */
+           return TRUE;
+      }
 
       le = x_endian_match(tvb, tvb_get_letohs);
       be = x_endian_match(tvb, tvb_get_ntohs);
@@ -2785,11 +1943,11 @@ guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
               right one.
            */
            if (!tvb_bytes_exist(tvb, 0, 4))
-                         /* Not even a way to get the length. We're biased
-                            toward little endianness here (essentially the
-                            x86 world right now). Decoding won't go very far
-                            anyway.
-                         */
+                 /* Not even a way to get the length. We're biased
+                    toward little endianness here (essentially the
+                    x86 world right now). Decoding won't go very far
+                    anyway.
+                 */
                  decision = TRUE;
            else
                  decision = tvb_get_letohs(tvb, 2) <= tvb_get_ntohs(tvb, 2);
@@ -2798,27 +1956,10 @@ guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
 
       decisionToCache = (le < 0 && be > 0) || (le > 0 && be < 0);
       if (decisionToCache) {
-           /* We encode the decision as 1 for TRUE and -1 for FALSE
-              to be able to distinguish between FALSE and no value in
-              the cache when recalling the value.
-           */
-           int address_length;
-           char *address_data;
-           address *cached;
-           if (addr -> type == AT_IPv4) {
-                 address_length = 4;
-                 address_data = g_mem_chunk_alloc(ipv4_chunk);
-           } else if (addr -> type == AT_IPv6) {
-                 address_length = 16;
-                 address_data = g_mem_chunk_alloc(ipv6_chunk);
-           } else {
-                 address_length = addr -> len;
-                 address_data = g_malloc(address_length);
-           }
-           cached = g_mem_chunk_alloc(address_chunk);
-           memcpy(address_data, addr -> data, address_length);
-           SET_ADDRESS(cached, addr -> type, addr -> len, address_data);
-           g_tree_insert(byte_ordering_cache, cached, GINT_TO_POINTER(decision ? 1 : -1));
+           /*
+            * Remember the decision.
+            */
+           state_info->byte_order = decision ? BYTE_ORDER_LE : BYTE_ORDER_BE;
       }
            
       /*
@@ -2830,83 +1971,1437 @@ guess_byte_ordering(tvbuff_t *tvb, packet_info *pinfo)
 
 /************************************************************************
  ***                                                                  ***
- ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
+ ***              D E C O D I N G   O N E   P A C K E T               ***
  ***                                                                  ***
  ************************************************************************/
 
-static void
-dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+/*
+ * Decode an initial connection request.
+ */
+static void dissect_x11_initial_conn(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree, x11_conv_data_t *state_info)
 {
-/* Set up structures we will need to add the protocol subtree and manage it */
+      int offset = 0;
+      int *offsetp = &offset;
       proto_item *ti;
-      proto_tree *x11_tree;
-      int left;
-       
-/* Make entries in Protocol column and Info column on summary display */
-      if (check_col(pinfo->fd, COL_PROTOCOL)) 
-           col_add_str(pinfo->fd, COL_PROTOCOL, "X11");
-    
-/* This field shows up as the "Info" column in the display; you should make
-   it, if possible, summarize what's in the packet, so that a user looking
-   at the list of packets can tell what type of packet it is. */
-      if (check_col(pinfo->fd, COL_INFO)) 
-           col_add_str(pinfo->fd, COL_INFO, "X11 request");
+      proto_tree *t;
+      guint16 auth_proto_name_length, auth_proto_data_length;
+      gint left;
+
+      ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+      t = proto_item_add_subtree(ti, ett_x11);
+
+      CARD8(byte_order);
+      UNUSED(1);
+      CARD16(protocol_major_version);
+      CARD16(protocol_minor_version);
+      auth_proto_name_length = CARD16(authorization_protocol_name_length);
+      auth_proto_data_length = CARD16(authorization_protocol_data_length);
+      UNUSED(2);
+      if (auth_proto_name_length != 0) {
+           STRING8(authorization_protocol_name, auth_proto_name_length);
+           offset = ROUND_LENGTH(offset);
+      }
+      if (auth_proto_data_length != 0) {
+           STRING8(authorization_protocol_data, auth_proto_data_length);
+           offset = ROUND_LENGTH(offset);
+      }
+      left = tvb_length_remaining(tvb, offset);
+      if (left)
+           proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
+
+      /*
+       * This is the initial connection request...
+       */
+      state_info->iconn_frame = pinfo->fd->num;
+
+      /*
+       * ...and we're expecting a reply to it.
+       */
+      state_info->opcode = INITIAL_CONN;
+}
+
+static void dissect_x11_request(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree, const char *sep, x11_conv_data_t *state_info)
+{
+      int offset = 0;
+      int *offsetp = &offset;
+      int next_offset;
+      proto_item *ti;
+      proto_tree *t;
+      int length, opcode;
+      guint8 v8, v8_2;
+      guint16 v16;
+      guint32 v32;
+      gint left;
+
+      length = VALUE16(tvb, 2) * 4;
+
+      if (length < 4) {
+           /* Bogus message length? */
+           return;
+      }
+
+      next_offset = offset + length;
+
+      ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+      t = proto_item_add_subtree(ti, ett_x11);
+
+      OPCODE();
+
+      if (check_col(pinfo->cinfo, COL_INFO)) 
+         col_append_fstr(pinfo->cinfo, COL_INFO, "%s %s", sep,
+                         val_to_str(opcode, opcode_vals, "Unknown (%u)"));
+
+      /*
+       * Does this request expect a reply?
+       */
+      switch(opcode) {
+
+      case 3: /* GetWindowAttributes */
+      case 14: /* GetGeometry */
+      case 15: /* QueryTree */
+      case 16: /* InternAtom */
+      case 17: /* GetAtomName */
+      case 20: /* GetProperty */
+      case 21: /* ListProperties */
+      case 23: /* GetSelectionOwner */
+      case 26: /* GrabPointer */
+      case 31: /* GrabKeyboard */
+      case 38: /* QueryPointer */
+      case 39: /* GetMotionEvents */
+      case 40: /* TranslateCoordinates */
+      case 44: /* QueryKeymap */
+      case 47: /* QueryFont */
+      case 48: /* QueryTextExtents */
+      case 49: /* ListFonts */
+      case 73: /* GetImage */
+      case 83: /* ListInstalledColormaps */
+      case 84: /* AllocColor */
+      case 91: /* QueryColors */
+      case 92: /* LookupColor */
+      case 97: /* QueryBestSize */
+      case 98: /* QueryExtension */
+      case 99: /* ListExtensions */
+      case 101: /* GetKeyboardMapping */
+      case 103: /* GetKeyboardControl */
+      case 106: /* GetPointerControl */
+      case 108: /* GetScreenSaver */
+      case 110: /* ListHosts */
+      case 116: /* SetPointerMapping */
+      case 117: /* GetPointerMapping */
+      case 118: /* SetModifierMapping */
+      case 119: /* GetModifierMapping */
+           /*
+            * Those requests expect a reply.
+            */
+           state_info->opcode = opcode;
+           break;
+
+      default:
+           /*
+            * No reply is expected from any other request.
+            */
+           state_info->opcode = NOTHING_EXPECTED;
+           break;
+      }
 
-/* In the interest of speed, if "tree" is NULL, don't do any work not
-   necessary to generate protocol tree items. */
       if (!tree) return;
-      ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
-                              tvb_length(tvb), FALSE);
-      x11_tree = proto_item_add_subtree(ti, ett_x11);
 
-      cur_offset = 0;
-      little_endian = guess_byte_ordering(tvb, pinfo);
-      left = dissect_x11_request_loop(tvb, x11_tree);
+      switch(opcode) {
+
+      case 1: /* CreateWindow */
+           CARD8(depth);
+           REQUEST_LENGTH();
+           WINDOW(wid);
+           WINDOW(parent);
+           INT16(x);
+           INT16(y);
+           CARD16(width);
+           CARD16(height);
+           CARD16(border_width);
+           ENUM16(window_class);
+           VISUALID(visual);
+           windowAttributes(tvb, offsetp, t);
+           break;
+
+      case 2: /* ChangeWindowAttributes */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           windowAttributes(tvb, offsetp, t);
+           break;
+
+      case 3: /* GetWindowAttributes */
+      case 4: /* DestroyWindow */
+      case 5: /* DestroySubwindows */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 6: /* ChangeSaveSet */
+           ENUM8(save_set_mode);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 7: /* ReparentWindow */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           WINDOW(parent);
+           INT16(x);
+           INT16(y);
+           break;
+
+      case 8: /* MapWindow */
+      case 9: /* MapSubWindow */
+      case 10: /* UnmapWindow */
+      case 11: /* UnmapSubwindows */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 12: /* ConfigureWindow */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           BITMASK16(configure_window);
+           UNUSED(2); 
+           BITFIELD(INT16,  configure_window_mask, x);
+           BITFIELD(INT16,  configure_window_mask, y);
+           BITFIELD(CARD16, configure_window_mask, width);
+           BITFIELD(CARD16, configure_window_mask, height);
+           BITFIELD(CARD16, configure_window_mask, border_width);
+           BITFIELD(WINDOW, configure_window_mask, sibling);
+           BITFIELD(ENUM8,  configure_window_mask, stack_mode);
+           ENDBITMASK;
+           PAD();
+           break;
+
+      case 13: /* CirculateWindow */
+           ENUM8(direction);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 14: /* GetGeometry */
+      case 15: /* QueryTree */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           break;
+
+      case 16: /* InternAtom */
+           BOOL(only_if_exists);
+           REQUEST_LENGTH();
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 17: /* GetAtomName */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           ATOM(atom);
+           break;
+
+      case 18: /* ChangeProperty */
+           ENUM8(mode);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           ATOM(property);
+           ATOM(type);
+           CARD8(format);
+           UNUSED(3);
+           v32 = CARD32(data_length);
+           LISTofBYTE(data, v32);
+           PAD();
+           break;
+
+      case 19: /* DeleteProperty */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           ATOM(property);
+           break;
+
+      case 20: /* GetProperty */
+           BOOL(delete);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           ATOM(property);
+           ATOM(get_property_type);
+           CARD32(long_offset);
+           CARD32(long_length);
+           break;
+
+      case 21: /* ListProperties */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 22: /* SetSelectionOwner */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(owner);
+           ATOM(selection);
+           TIMESTAMP(time);
+           break;
+
+      case 23: /* GetSelectionOwner */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           ATOM(selection);
+           break;
+
+      case 24: /* ConvertSelection */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(requestor);
+           ATOM(selection);
+           ATOM(target);
+           ATOM(property);
+           TIMESTAMP(time);
+           break;
+
+      case 26: /* GrabPointer */
+           BOOL(owner_events);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           SETofPOINTEREVENT(pointer_event_mask);
+           ENUM8(pointer_mode);
+           ENUM8(keyboard_mode);
+           WINDOW(confine_to);
+           CURSOR(cursor);
+           TIMESTAMP(time);
+           break;
+
+      case 27: /* UngrabPointer */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           TIMESTAMP(time);
+           break;
+
+      case 28: /* GrabButton */
+           BOOL(owner_events);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           SETofPOINTEREVENT(event_mask);
+           ENUM8(pointer_mode);
+           ENUM8(keyboard_mode);
+           WINDOW(confine_to);
+           CURSOR(cursor);
+           BUTTON(button);
+           UNUSED(1);
+           SETofKEYMASK(modifiers);
+           break;
+
+      case 29: /* UngrabButton */
+           BUTTON(button);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           SETofKEYMASK(modifiers);
+           UNUSED(2);
+           break;
+
+      case 30: /* ChangeActivePointerGrab */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CURSOR(cursor);
+           TIMESTAMP(time);
+           SETofPOINTEREVENT(event_mask);
+           UNUSED(2);
+           break;
+
+      case 31: /* GrabKeyboard */
+           BOOL(owner_events);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           TIMESTAMP(time);
+           ENUM8(pointer_mode);
+           ENUM8(keyboard_mode);
+           UNUSED(2);
+           break;
+
+      case 32: /* UngrabKeyboard */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           TIMESTAMP(time);
+           break;
+
+      case 33: /* GrabKey */
+           BOOL(owner_events);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           SETofKEYMASK(modifiers);
+           KEYCODE(key);
+           ENUM8(pointer_mode);
+           ENUM8(keyboard_mode);
+           UNUSED(3);
+           break;
+
+      case 34: /* UngrabKey */
+           KEYCODE(key);
+           REQUEST_LENGTH();
+           WINDOW(grab_window);
+           SETofKEYMASK(modifiers);
+           UNUSED(2);
+           break;
+
+      case 35: /* AllowEvents */
+           ENUM8(allow_events_mode);
+           REQUEST_LENGTH();
+           TIMESTAMP(time);
+           break;
+
+      case 36: /* GrabServer */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 37: /* UngrabServer */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 38: /* QueryPointer */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 39: /* GetMotionEvents */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           TIMESTAMP(start);
+           TIMESTAMP(stop);
+           break;
+
+      case 40: /* TranslateCoordinates */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(src_window);
+           WINDOW(dst_window);
+           INT16(src_x);
+           INT16(src_y);
+           break;
+
+      case 41: /* WarpPointer */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(warp_pointer_src_window);
+           WINDOW(warp_pointer_dst_window);
+           INT16(src_x);
+           INT16(src_y);
+           CARD16(src_width);
+           CARD16(src_height);
+           INT16(dst_x);
+           INT16(dst_y);
+           break;
+
+      case 42: /* SetInputFocus */
+           ENUM8(revert_to);
+           REQUEST_LENGTH();
+           WINDOW(focus);
+           TIMESTAMP(time);
+           break;
+
+      case 43: /* GetInputFocus */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 44: /* QueryKeymap */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 45: /* OpenFont */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           FONT(fid);
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 46: /* CloseFont */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           FONT(font);
+           break;
+
+      case 47: /* QueryFont */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           FONTABLE(font);
+           break;
+
+      case 48: /* QueryTextExtents */
+           v8 = BOOL(odd_length);
+           REQUEST_LENGTH();
+           FONTABLE(font);
+           STRING16(string16, (next_offset - offset - (v8 ? 2 : 0)) / 2);
+           PAD();
+           break;
+
+      case 49: /* ListFonts */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CARD16(max_names);
+           v16 = FIELD16(pattern_length);
+           STRING8(pattern, v16);
+           PAD();
+           break;
+
+      case 50: /* ListFontsWithInfo */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CARD16(max_names);
+           v16 = FIELD16(pattern_length);
+           STRING8(pattern, v16);
+           PAD();
+           break;
+
+      case 51: /* SetFontPath */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           v16 = CARD16(str_number_in_path);
+           UNUSED(2);
+           LISTofSTRING8(path, v16);
+           PAD();
+           break;
+
+      case 52: /* GetFontPath */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 53: /* CreatePixmap */
+           CARD8(depth);
+           REQUEST_LENGTH();
+           PIXMAP(pid);
+           DRAWABLE(drawable);
+           CARD16(width);
+           CARD16(height);
+           break;
+
+      case 54: /* FreePixmap */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           PIXMAP(pixmap);
+           break;
+
+      case 55: /* CreateGC */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           GCONTEXT(cid);
+           DRAWABLE(drawable);
+           gcAttributes(tvb, offsetp, t);
+           break;
+
+      case 56: /* ChangeGC */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           GCONTEXT(gc);
+           gcAttributes(tvb, offsetp, t);
+           break;
+
+      case 57: /* CopyGC */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           GCONTEXT(src_gc);
+           GCONTEXT(dst_gc);
+           gcMask(tvb, offsetp, t);
+           break;
+
+      case 58: /* SetDashes */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           GCONTEXT(gc);
+           CARD16(dash_offset);
+           v16 = FIELD16(dashes_length);
+           LISTofCARD8(dashes, v16);
+           PAD();
+           break;
+
+      case 59: /* SetClipRectangles */
+           ENUM8(ordering);
+           REQUEST_LENGTH();
+           GCONTEXT(gc);
+           INT16(clip_x_origin);
+           INT16(clip_y_origin);
+           LISTofRECTANGLE(rectangles);
+           break;
+
+      case 60: /* FreeGC */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           GCONTEXT(gc);
+           break;
+
+      case 61: /* ClearArea */
+           BOOL(exposures);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           INT16(x);
+           INT16(y);
+           CARD16(width);
+           CARD16(height);
+           break;
+
+      case 62: /* CopyArea */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(src_drawable);
+           DRAWABLE(dst_drawable);
+           GCONTEXT(gc);
+           INT16(src_x);
+           INT16(src_y);
+           INT16(dst_x);
+           INT16(dst_y);
+           CARD16(width);
+           CARD16(height);
+           break;
+
+      case 63: /* CopyPlane */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(src_drawable);
+           DRAWABLE(dst_drawable);
+           GCONTEXT(gc);
+           INT16(src_x);
+           INT16(src_y);
+           INT16(dst_x);
+           INT16(dst_y);
+           CARD16(width);
+           CARD16(height);
+           CARD32(bit_plane);
+           break;
+
+      case 64: /* PolyPoint */
+           ENUM8(coordinate_mode);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofPOINT(points, v16 - 12);
+           break;
+
+      case 65: /* PolyLine */
+           ENUM8(coordinate_mode);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofPOINT(points, v16 - 12);
+           break;
+
+      case 66: /* PolySegment */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofSEGMENT(segments);
+           break;
+
+      case 67: /* PolyRectangle */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofRECTANGLE(rectangles);
+           break;
+
+      case 68: /* PolyArc */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofARC(arcs);
+           break;
+
+      case 69: /* FillPoly */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           ENUM8(shape);
+           ENUM8(coordinate_mode);
+           UNUSED(2);
+           LISTofPOINT(points, v16 - 16);
+           break;
+
+      case 70: /* PolyFillRectangle */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofRECTANGLE(rectangles);
+           break;
+
+      case 71: /* PolyFillArc */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           LISTofARC(arcs);
+           break;
+
+      case 72: /* PutImage */
+           ENUM8(image_format);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           CARD16(width);
+           CARD16(height);
+           INT16(dst_x);
+           INT16(dst_y);
+           CARD8(left_pad);
+           CARD8(depth);
+           UNUSED(2);
+           LISTofBYTE(data, v16 - 24);
+           PAD();
+           break;
+
+      case 73: /* GetImage */
+           ENUM8(image_pixmap_format);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           INT16(x);
+           INT16(y);
+           CARD16(width);
+           CARD16(height);
+           CARD32(plane_mask);
+           break;
+
+      case 74: /* PolyText8 */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           INT16(x);
+           INT16(y);
+           LISTofTEXTITEM8(items);
+           PAD();
+           break;
+
+      case 75: /* PolyText16 */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           INT16(x);
+           INT16(y);
+           LISTofTEXTITEM16(items);
+           PAD();
+           break;
+
+      case 76: /* ImageText8 */
+           v8 = FIELD8(string_length);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           INT16(x);
+           INT16(y);
+           STRING8(string, v8);
+           PAD();
+           break;
+
+      case 77: /* ImageText16 */
+           v8 = FIELD8(string_length);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           GCONTEXT(gc);
+           INT16(x);
+           INT16(y);
+           STRING16(string16, v8);
+           PAD();
+           break;
+
+      case 78: /* CreateColormap */
+           ENUM8(alloc);
+           REQUEST_LENGTH();
+           COLORMAP(mid);
+           WINDOW(window);
+           VISUALID(visual);
+           break;
+
+      case 79: /* FreeColormap */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           break;
+
+      case 80: /* CopyColormapAndFree */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(mid);
+           COLORMAP(src_cmap);
+           break;
+
+      case 81: /* InstallColormap */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           break;
+
+      case 82: /* UninstallColormap */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           break;
+
+      case 83: /* ListInstalledColormaps */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           WINDOW(window);
+           break;
+
+      case 84: /* AllocColor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           CARD16(red);
+           CARD16(green);
+           CARD16(blue);
+           UNUSED(2);
+           break;
+
+      case 85: /* AllocNamedColor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 86: /* AllocColorCells */
+           BOOL(contiguous);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           CARD16(colors);
+           CARD16(planes);
+           break;
+
+      case 87: /* AllocColorPlanes */
+           BOOL(contiguous);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           CARD16(colors);
+           CARD16(reds);
+           CARD16(greens);
+           CARD16(blues);
+           break;
+
+      case 88: /* FreeColors */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           COLORMAP(cmap);
+           CARD32(plane_mask);
+           LISTofCARD32(pixels, v16 - 12);
+           break;
+
+      case 89: /* StoreColors */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           COLORMAP(cmap);
+           LISTofCOLORITEM(color_items, v16 - 8);
+           break;
+
+      case 90: /* StoreNamedColor */
+           COLOR_FLAGS(color);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           CARD32(pixel);      
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 91: /* QueryColors */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           COLORMAP(cmap);
+           LISTofCARD32(pixels, v16 - 8);
+           break;
+
+      case 92: /* LookupColor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           COLORMAP(cmap);
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 93: /* CreateCursor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CURSOR(cid);
+           PIXMAP(source_pixmap);
+           PIXMAP(mask);
+           CARD16(fore_red);
+           CARD16(fore_green);
+           CARD16(fore_blue);
+           CARD16(back_red);
+           CARD16(back_green);
+           CARD16(back_blue);
+           CARD16(x);
+           CARD16(y);
+           break;
+
+      case 94: /* CreateGlyphCursor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CURSOR(cid);
+           FONT(source_font);
+           FONT(mask_font);
+           CARD16(source_char);
+           CARD16(mask_char);
+           CARD16(fore_red);
+           CARD16(fore_green);
+           CARD16(fore_blue);
+           CARD16(back_red);
+           CARD16(back_green);
+           CARD16(back_blue);
+           break;
+
+      case 95: /* FreeCursor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CURSOR(cursor);
+           break;
+
+      case 96: /* RecolorCursor */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CURSOR(cursor);
+           CARD16(fore_red);
+           CARD16(fore_green);
+           CARD16(fore_blue);
+           CARD16(back_red);
+           CARD16(back_green);
+           CARD16(back_blue);
+           break;
+
+      case 97: /* QueryBestSize */
+           ENUM8(class);
+           REQUEST_LENGTH();
+           DRAWABLE(drawable);
+           CARD16(width);
+           CARD16(height);
+           break;
+
+      case 98: /* QueryExtension */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           v16 = FIELD16(name_length);
+           UNUSED(2);
+           STRING8(name, v16);
+           PAD();
+           break;
+
+      case 99: /* ListExtensions */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 100: /* ChangeKeyboardMapping */
+           v8 = FIELD8(keycode_count);
+           REQUEST_LENGTH();
+           KEYCODE(first_keycode);
+           v8_2 = FIELD8(keysyms_per_keycode);
+           UNUSED(2);
+           LISTofKEYSYM(keysyms, v8, v8_2);
+           break;
+
+      case 101: /* GetKeyboardMapping */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           KEYCODE(first_keycode);
+           FIELD8(count);
+           UNUSED(2);
+           break;
+
+      case 102: /* ChangeKeyboardControl */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           BITMASK32(keyboard_value);
+           BITFIELD(INT8, keyboard_value_mask, key_click_percent);
+           BITFIELD(INT8, keyboard_value_mask, bell_percent);
+           BITFIELD(INT16, keyboard_value_mask, bell_pitch);
+           BITFIELD(INT16, keyboard_value_mask, bell_duration);
+           BITFIELD(INT16, keyboard_value_mask, led);
+           BITFIELD(ENUM8, keyboard_value_mask, led_mode);
+           BITFIELD(KEYCODE, keyboard_value_mask, keyboard_key);
+           BITFIELD(ENUM8, keyboard_value_mask, auto_repeat_mode);
+           ENDBITMASK;
+           break;
+
+      case 103: /* GetKeyboardControl */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 104: /* Bell */
+           INT8(percent);
+           REQUEST_LENGTH();
+           break;
+
+      case 105: /* ChangePointerControl */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           INT16(acceleration_numerator);
+           INT16(acceleration_denominator);
+           INT16(threshold);
+           BOOL(do_acceleration);
+           BOOL(do_threshold);
+           break;
+
+      case 106: /* GetPointerControl */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 107: /* SetScreenSaver */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           INT16(timeout);
+           INT16(interval);
+           ENUM8(prefer_blanking);
+           ENUM8(allow_exposures);
+           UNUSED(2);
+           break;
+
+      case 108: /* GetScreenSaver */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 109: /* ChangeHosts */
+           ENUM8(change_host_mode);
+           REQUEST_LENGTH();
+           v8 = ENUM8(family);
+           UNUSED(1);
+           v16 = CARD16(address_length);
+           if (v8 == FAMILY_INTERNET && v16 == 4) {
+                 /*
+                  * IPv4 addresses.
+                  * XXX - what about IPv6?  Is that a family of
+                  * FAMILY_INTERNET (0) with a length of 16?
+                  */
+                 LISTofCARD8(ip_address, v16);
+           } else
+                 LISTofCARD8(address, v16);
+           break;
+
+      case 110: /* ListHosts */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 111: /* SetAccessControl */
+           ENUM8(access_mode);
+           REQUEST_LENGTH();
+           break;
+
+      case 112: /* SetCloseDownMode */
+           ENUM8(close_down_mode);
+           REQUEST_LENGTH();
+           break;
+
+      case 113: /* KillClient */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           CARD32(resource);
+           break;
+
+      case 114: /* RotateProperties */
+           UNUSED(1);
+           v16 = REQUEST_LENGTH();
+           WINDOW(window);
+           CARD16(property_number);
+           INT16(delta);
+           LISTofATOM(properties, (v16 - 12));
+           break;
+
+      case 115: /* ForceScreenSaver */
+           ENUM8(screen_saver_mode);
+           REQUEST_LENGTH();
+           break;
+
+      case 116: /* SetPointerMapping */
+           v8 = FIELD8(map_length);
+           REQUEST_LENGTH();
+           LISTofCARD8(map, v8);
+           PAD();
+           break;
+
+      case 117: /* GetPointerMapping */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+
+      case 118: /* SetModifierMapping */
+           v8 = FIELD8(keycodes_per_modifier);
+           REQUEST_LENGTH();
+           LISTofKEYCODE(keycodes, v8);
+           break;
+
+      case 119: /* GetModifierMapping */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+           
+      case 127: /* NoOperation */
+           UNUSED(1);
+           REQUEST_LENGTH();
+           break;
+      }
+      left = tvb_length_remaining(tvb, offset);
       if (left)
-           dissect_data(tvb, cur_offset, pinfo, x11_tree);
+           proto_tree_add_item(t, hf_x11_undecoded, tvb, offset, left, little_endian);
+}
+
+static void dissect_x11_requests(tvbuff_t *tvb, packet_info *pinfo,
+    proto_tree *tree)
+{
+      volatile int offset = 0;
+      int length_remaining;
+      guint8 opcode;
+      volatile int plen;
+      proto_item *ti;
+      proto_tree *t;
+      volatile gboolean is_initial_creq;
+      guint16 auth_proto_len, auth_data_len;
+      const char *volatile sep = NULL;
+      conversation_t *conversation;
+      x11_conv_data_t *volatile state_info;
+      int byte_order;
+      int length;
+      tvbuff_t *next_tvb;
+
+      while (tvb_reported_length_remaining(tvb, offset) != 0) {
+           length_remaining = tvb_length_remaining(tvb, offset);
+
+           /*
+            * Can we do reassembly?
+            */
+           if (x11_desegment && pinfo->can_desegment) {
+                 /*
+                  * Yes - is the X11 request header split across
+                  * segment boundaries?
+                  */
+                 if (length_remaining < 4) {
+                       /*
+                        * Yes.  Tell the TCP dissector where the data
+                        * for this message starts in the data it handed
+                        * us, and how many more bytes we need, and return.
+                        */
+                       pinfo->desegment_offset = offset;
+                       pinfo->desegment_len = 4 - length_remaining;
+                       return;
+                 }
+           }
+
+           /*
+            * Get the state for this conversation; create the conversation
+            * if we don't have one, and create the state if we don't have
+            * any.
+            */
+           conversation = find_conversation(&pinfo->src, &pinfo->dst,
+               pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
+           if (conversation == NULL) {
+                 /*
+                  * No - create one.
+                  */
+                 conversation = conversation_new(&pinfo->src,
+                       &pinfo->dst, pinfo->ptype, pinfo->srcport,
+                       pinfo->destport, 0);
+           }
+
+           /*
+            * Is there state attached to this conversation?
+            */
+           state_info = conversation_get_proto_data(conversation, proto_x11);
+           if (state_info == NULL) {
+                 /*
+                  * No - create a state structure and attach it.
+                  */
+                 state_info = g_mem_chunk_alloc(x11_state_chunk);
+                 state_info->opcode = NOTHING_SEEN;    /* nothing seen yet */
+                 state_info->iconn_frame = 0;  /* don't know it yet */
+                 state_info->byte_order = BYTE_ORDER_UNKNOWN;  /* don't know it yet */
+                 conversation_add_proto_data(conversation, proto_x11,
+                       state_info);
+           }
+
+           /*
+            * Guess the byte order if we don't already know it.
+            */
+           little_endian = guess_byte_ordering(tvb, pinfo, state_info);
+
+           /*
+            * Get the opcode and length of the putative X11 request.
+            */
+           opcode = VALUE8(tvb, 0);
+           plen = VALUE16(tvb, offset + 2);
+
+           if (plen == 0) {
+                 /*
+                  * This can't be 0, as it includes the header length.
+                  * A different choice of byte order wouldn't have
+                  * helped.
+                  * Give up.
+                  */
+                 ti = proto_tree_add_item(tree, proto_x11, tvb, offset, -1, FALSE);
+                 t = proto_item_add_subtree(ti, ett_x11);
+                 proto_tree_add_text(t, tvb, offset, -1, "Bogus request length (0)");
+                 return;
+           }
+
+           if (state_info->iconn_frame == pinfo->fd->num ||
+               (state_info->opcode == NOTHING_SEEN &&
+                (opcode == 'B' || opcode == 'l') &&
+                (plen == 11 || plen == 2816))) {
+                 /*
+                  * Either
+                  *
+                  *    we saw this on the first pass and this is
+                  *    it again
+                  *
+                  * or
+                  *    we haven't already seen any requests, the first
+                  *    byte of the message is 'B' or 'l', and the 16-bit
+                  *    integer 2 bytes into the data stream is either 11
+                  *    or a byte-swapped 11.
+                  *
+                  * This means it's probably an initial connection
+                  * request, not a message.
+                  *
+                  * 'B' is decimal 66, which is the opcode for a
+                  * PolySegment request; unfortunately, 11 is a valid
+                  * length for a PolySegment request request, so we
+                  * might mis-identify that request.  (Are there any
+                  * other checks we can do?)
+                  *
+                  * 'l' is decimal 108, which is the opcode for a
+                  * GetScreenSaver request; the only valid length
+                  * for that request is 1.
+                  */
+                 is_initial_creq = TRUE;
+
+                 /*
+                  * We now know the byte order.  Override the guess.
+                  */
+                 if (state_info->byte_order == BYTE_ORDER_UNKNOWN) {
+                       if (opcode == 'B') {
+                             /*
+                              * Big-endian.
+                              */
+                             state_info->byte_order = BYTE_ORDER_BE;
+                             little_endian = FALSE;
+                       } else {
+                             /*
+                              * Little-endian.
+                              */
+                             state_info->byte_order = BYTE_ORDER_LE;
+                             little_endian = TRUE;
+                       }
+                 }
+
+                 /*
+                  * Can we do reassembly?
+                  */
+                 if (x11_desegment && pinfo->can_desegment) {
+                       /*
+                        * Yes - is the fixed-length portion of the
+                        * initial connection header split across
+                        * segment boundaries?
+                        */
+                       if (length_remaining < 10) {
+                             /*
+                              * Yes.  Tell the TCP dissector where the
+                              * data for this message starts in the data
+                              * it handed us, and how many more bytes we
+                              * need, and return.
+                              */
+                             pinfo->desegment_offset = offset;
+                             pinfo->desegment_len = 10 - length_remaining;
+                             return;
+                       }
+                 }
+
+                 /*
+                  * Get the lengths of the authorization protocol and
+                  * the authorization data.
+                  */
+                 auth_proto_len = VALUE16(tvb, offset + 6);
+                 auth_data_len = VALUE16(tvb, offset + 8);
+                 plen = 12 + ROUND_LENGTH(auth_proto_len) +
+                       ROUND_LENGTH(auth_data_len);
+           } else {
+                 /*
+                  * This is probably an ordinary request.
+                  */
+                 is_initial_creq = FALSE;
+
+                 /*
+                  * The length of a request is in 4-byte words.
+                  */
+                 plen *= 4;
+           }
+
+           /*
+            * Can we do reassembly?
+            */
+           if (x11_desegment && pinfo->can_desegment) {
+                 /*
+                  * Yes - is the X11 request split across segment
+                  * boundaries?
+                  */
+                 if (length_remaining < plen) {
+                       /*
+                        * Yes.  Tell the TCP dissector where the data
+                        * for this message starts in the data it handed
+                        * us, and how many more bytes we need, and return.
+                        */
+                       pinfo->desegment_offset = offset;
+                       pinfo->desegment_len = plen - length_remaining;
+                       return;
+                 }
+           }
+
+           /*
+            * Construct a tvbuff containing the amount of the payload
+            * we have available.  Make its reported length the
+            * amount of data in the X11 request.
+            *
+            * XXX - if reassembly isn't enabled. the subdissector
+            * will throw a BoundsError exception, rather than a
+            * ReportedBoundsError exception.  We really want a tvbuff
+            * where the length is "length", the reported length is "plen",
+            * and the "if the snapshot length were infinite" length is the
+            * minimum of the reported length of the tvbuff handed to us
+            * and "plen", with a new type of exception thrown if the offset
+            * is within the reported length but beyond that third length,
+            * with that exception getting the "Unreassembled Packet" error.
+            */
+           length = length_remaining;
+           if (length > plen)
+                 length = plen;
+           next_tvb = tvb_new_subset(tvb, offset, length, plen);
+
+           /*
+            * Set the column appropriately.
+            */
+           if (is_initial_creq) {
+                 if (check_col(pinfo->cinfo, COL_INFO)) 
+                       col_set_str(pinfo->cinfo, COL_INFO, "Initial connection request");
+           } else {
+                 if (sep == NULL) {
+                       /*
+                        * We haven't set the column yet; set it.
+                        */
+                       if (check_col(pinfo->cinfo, COL_INFO)) 
+                             col_add_str(pinfo->cinfo, COL_INFO, "Requests");
+
+                       /*
+                        * Initialize the separator.
+                        */
+                       sep = ":";
+                 }
+           }
+
+           /*
+            * Dissect the X11 request.
+            *
+            * Catch the ReportedBoundsError exception; if this
+            * particular message happens to get a ReportedBoundsError
+            * exception, that doesn't mean that we should stop
+            * dissecting X11 requests within this frame or chunk of
+            * reassembled data.
+            *
+            * If it gets a BoundsError, we can stop, as there's nothing
+            * more to see, so we just re-throw it.
+            */
+           TRY {
+                 if (is_initial_creq) {
+                       dissect_x11_initial_conn(next_tvb, pinfo, tree,
+                           state_info);
+                 } else {
+                       dissect_x11_request(next_tvb, pinfo, tree, sep,
+                           state_info);
+                 }
+           }
+           CATCH(BoundsError) {
+                 RETHROW;
+           }
+           CATCH(ReportedBoundsError) {
+                 show_reported_bounds_error(tvb, pinfo, tree);
+           }
+           ENDTRY;
+
+           /*
+            * Skip the X11 message.
+            */
+           offset += plen;
+
+           sep = ",";
+      }
 }
 
 static void
-dissect_x11_event(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_x11_replies(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
 /* Set up structures we will need to add the protocol subtree and manage it */
       proto_item *ti;
       proto_tree *x11_tree;
        
-/* Make entries in Protocol column and Info column on summary display */
-      if (check_col(pinfo->fd, COL_PROTOCOL)) 
-           col_add_str(pinfo->fd, COL_PROTOCOL, "X11");
-    
 /* This field shows up as the "Info" column in the display; you should make
    it, if possible, summarize what's in the packet, so that a user looking
    at the list of packets can tell what type of packet it is. */
-      if (check_col(pinfo->fd, COL_INFO)) 
-           col_add_str(pinfo->fd, COL_INFO, "X11 event");
+      if (check_col(pinfo->cinfo, COL_INFO)) 
+           col_set_str(pinfo->cinfo, COL_INFO, "Replies/events");
 
 /* In the interest of speed, if "tree" is NULL, don't do any work not
    necessary to generate protocol tree items. */
-      if (tree) {
-           ti = proto_tree_add_item(tree, proto_x11, tvb, 0,
-               tvb_length(tvb), FALSE);
-           x11_tree = proto_item_add_subtree(ti, ett_x11);
-
-/* Code to process the packet goes here */
+      if (!tree) return;
+      ti = proto_tree_add_item(tree, proto_x11, tvb, 0, -1, FALSE);
+      x11_tree = proto_item_add_subtree(ti, ett_x11);
 
-           dissect_data(tvb, 0, pinfo, x11_tree);
-      }
+      /*
+       * XXX - dissect these in a loop, like the requests.
+       */
+      call_dissector(data_handle,tvb, pinfo, x11_tree);
 }
 
+/************************************************************************
+ ***                                                                  ***
+ ***         I N I T I A L I Z A T I O N   A N D   M A I N            ***
+ ***                                                                  ***
+ ************************************************************************/
+
 static void
 dissect_x11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-
-      CHECK_DISPLAY_AS_DATA(proto_x11, tvb, pinfo, tree);
-
-      pinfo->current_proto = "X11";
+      if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
+           col_set_str(pinfo->cinfo, COL_PROTOCOL, "X11");
+    
       if (pinfo->match_port == pinfo->destport)
-           dissect_x11_request(tvb, pinfo, tree);
+           dissect_x11_requests(tvb, pinfo, tree);
       else
-           dissect_x11_event(tvb, pinfo, tree);
+           dissect_x11_replies(tvb, pinfo, tree);
 }
 
 /* Register the protocol with Ethereal */
@@ -2919,37 +3414,69 @@ void proto_register_x11(void)
   { &hf_x11_FIELDABBREV,
   { "FIELDNAME",           "x11.FIELDABBREV",
   FIELDTYPE, FIELDBASE, FIELDCONVERT, BITMASK,          
-  "FIELDDESCR" }
+  "FIELDDESCR", HFILL }
   },
 */
-#include "packet-x11-register-info.h"
+#include "x11-register-info.h"
       };
 
 /* Setup protocol subtree array */
       static gint *ett[] = {
            &ett_x11,
-           &ett_x11_request,
+           &ett_x11_color_flags,
+           &ett_x11_list_of_arc,
+           &ett_x11_arc,
+           &ett_x11_list_of_atom,
+           &ett_x11_list_of_card32,
+           &ett_x11_list_of_color_item,
+           &ett_x11_color_item,
+           &ett_x11_list_of_keycode,
+           &ett_x11_list_of_keysyms,
+           &ett_x11_keysym,
+           &ett_x11_list_of_point,
+           &ett_x11_point,
+           &ett_x11_list_of_rectangle,
+           &ett_x11_rectangle,
+           &ett_x11_list_of_segment,
+           &ett_x11_segment,
+           &ett_x11_list_of_string8,
+           &ett_x11_list_of_text_item,
+           &ett_x11_text_item,
+           &ett_x11_gc_value_mask,
+           &ett_x11_event_mask,
+           &ett_x11_do_not_propagate_mask,
+           &ett_x11_set_of_key_mask,
+           &ett_x11_pointer_event_mask,
+           &ett_x11_window_value_mask,
+           &ett_x11_configure_window_mask,
+           &ett_x11_keyboard_value_mask,
       };
+      module_t *x11_module;
 
 /* Register the protocol name and description */
-      proto_x11 = proto_register_protocol("X11", "x11");
+      proto_x11 = proto_register_protocol("X11", "X11", "x11");
 
 /* Required function calls to register the header fields and subtrees used */
       proto_register_field_array(proto_x11, hf, array_length(hf));
       proto_register_subtree_array(ett, array_length(ett));
 
-      byte_ordering_cache = g_tree_new(compareAddresses);
-      address_chunk = g_mem_chunk_new("x11 byte ordering address cache", sizeof(address), 
-                                     sizeof(address) * 128, G_ALLOC_ONLY);
-      ipv4_chunk = g_mem_chunk_new("x11 byte ordering ipv4 address cache", 4, 4 * 128, G_ALLOC_ONLY);
-      ipv6_chunk = g_mem_chunk_new("x11 byte ordering ipv6 address cache", 16, 16 * 128, G_ALLOC_ONLY);
-};
+      register_init_routine(x11_init_protocol);
 
+      x11_module = prefs_register_protocol(proto_x11, NULL);
+      prefs_register_bool_preference(x11_module, "desegment",
+           "Desegment all X11 messages spanning multiple TCP segments",
+           "Whether the X11 dissector should desegment all messages spanning multiple TCP segments",
+           &x11_desegment);
+}
 
 void
 proto_reg_handoff_x11(void)
 {
-  dissector_add("tcp.port", TCP_PORT_X11, dissect_x11);
-  dissector_add("tcp.port", TCP_PORT_X11_2, dissect_x11);
-  dissector_add("tcp.port", TCP_PORT_X11_3, dissect_x11);
+  dissector_handle_t x11_handle;
+
+  x11_handle = create_dissector_handle(dissect_x11, proto_x11);
+  dissector_add("tcp.port", TCP_PORT_X11, x11_handle);
+  dissector_add("tcp.port", TCP_PORT_X11_2, x11_handle);
+  dissector_add("tcp.port", TCP_PORT_X11_3, x11_handle);
+  data_handle = find_dissector("data");
 }