PreviousUpNext

15.4.1680  src/lib/x-kit/xclient/src/wire/wire-to-value-pith.pkg

## wire-to-value-pith.pkg
#
# Translation from X server network bytestring format
# to internal Mythryl datastructure format.
#
# This package gets wrapped by the exception-reporting
# logic in:
#
#     src/lib/x-kit/xclient/src/wire/wire-to-value.pkg 
#
# Every package reading from the X server needs to call us:
#
#     src/lib/x-kit/xclient/src/wire/display-old.pkg
#     src/lib/x-kit/xclient/src/wire/xsocket-old.pkg
#     src/lib/x-kit/xclient/src/iccc/atom-old.pkg
#     src/lib/x-kit/xclient/src/iccc/atom-imp-old.pkg
#     src/lib/x-kit/xclient/src/iccc/window-property-old.pkg
#     src/lib/x-kit/xclient/src/window/window-old.pkg
#     src/lib/x-kit/xclient/src/window/selection-imp-old.pkg
#     src/lib/x-kit/xclient/src/window/font-imp-old.pkg
#     src/lib/x-kit/xclient/src/window/draw-types-old.pkg
#     src/lib/x-kit/xclient/src/window/color-spec.pkg
#     src/lib/x-kit/xclient/src/window/keymap-imp-old.pkg
#     src/lib/x-kit/xclient/src/window/cs-pixmap-old.pkg

# Compiled by:
#     src/lib/x-kit/xclient/xclient-internals.sublib




#
# TODO
#   events
#     decodeKeymapNotify
#   replies
#     decodeAllocColorCellsReply
#     decodeAllocColorPlanesReply
#     decodeGetPointerMappingReply
#     decodeListExtensionsReply
#     decodeQueryExtensionReply
#     decodeQueryKeymapReply


stipulate
    package w8  =  one_byte_unt;
    package w8v =  vector_of_one_byte_unts;
    package g2d =  geometry2d;                                          # geometry2d            is from   src/lib/std/2d/geometry2d.pkg
    package xt  =  xtypes;                                              # xtypes                is from   src/lib/x-kit/xclient/src/wire/xtypes.pkg
    package xet =  xevent_types;                                        # xevent_types          is from   src/lib/x-kit/xclient/src/wire/xevent-types.pkg
    package ts  =  xserver_timestamp;                                   # xserver_timestamp     is from   src/lib/x-kit/xclient/src/wire/xserver-timestamp.pkg
    package xe  =  xerrors;                                             # xerrors               is from   src/lib/x-kit/xclient/src/wire/xerrors.pkg
    package xtr =  xlogger;                                             # xlogger               is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
herein


    package   wire_to_value_pith
    :         Wire_To_Value
    {
        Font_Query_Reply =    { all_chars_exist:  Bool, 
                                char_infos:       List(xt::Char_Info), 
                                default_char:     Int,
                                draw_dir:         xt::Font_Drawing_Direction, 
                                #
                                font_ascent:      Int,
                                font_descent:     Int, 
                                #
                                max_bounds:  xt::Char_Info,
                                min_bounds:  xt::Char_Info,
                                #
                                max_byte1:   Int, 
                                min_byte1:   Int,
                                #
                                min_char:    Int, 
                                max_char:    Int,
                                #
                                properties: List(xt::Font_Prop)
                              };

        trace =  xtr::log_if  xtr::io_logging  0;                       # Conditionally write strings to tracing.log or whatever.

        stipulate

            my (&) = large_unt::bitwise_and;
            my (|) = large_unt::bitwise_or;

            # infix my & | ;

            fun is_set (x, i)
                =
                (x & large_unt::(<<) (0u1, i)) != 0u0;

            fun pad n
                =
                case (unt::bitwise_and (unt::from_int n, 0u3))
                    #
                    0u0 =>  n;
                    r   =>  n + (4 - unt::to_int_x r);
                esac;


            fun get_string (bv, i, n)
                =
                byte::unpack_string_vector (vector_slice_of_one_byte_unts::make_slice (bv, i, THE n));

            get8 = w8::to_large_unt o w8v::get;

            fun get_word8   arg =  unt::from_large_unt (w8::to_large_unt (w8v::get arg));
            fun get_int8    arg =  w8::to_int (w8v::get arg);
            fun get_signed8 arg =  w8::to_int_x (w8v::get arg);

            fun get16        (s, i) =  pack_big_endian_unt16::get_vec (s, i / 2);
            fun get_word16   (s, i) =  unt::from_large_unt (get16 (s, i));
            fun get_int16    (s, i) =  large_unt::to_int (get16 (s, i));
            fun get_signed16 (s, i) =  large_unt::to_int_x (pack_big_endian_unt16::get_vec_x (s, i / 2));

            fun get32 (s, i)
                =
                one_word_unt::from_large_unt (pack_big_endian_unt1::get_vec (s, i / 4));

            fun get_signed32 (s, i)
                =
                one_word_int::from_multiword_int (large_unt::to_multiword_int (pack_big_endian_unt1::get_vec_x (s, i / 4)));

            fun get_word (s, i)
                =
                unt::from_large_unt (get32 (s, i));

            fun get_int (s, i)
                =
                large_unt::to_int_x (pack_big_endian_unt1::get_vec_x (s, i / 4));

            w8vextract
                =
                vector_slice_of_one_byte_unts::to_vector  o  vector_slice_of_one_byte_unts::make_slice;

            fun wrap_fn name f (s, i)
                =
                f (s, i)
                except
                    ex = {   xlogger::err_trace {. cat ["**** ", name, "(", int::to_string (w8v::length s), ", ",       int::to_string i, ")\n"]; };
                             raise exception ex;
                         };

            get8         = wrap_fn "get8" get8;
            get_word8    = wrap_fn "getWord8" get_word8;
            get_int8     = wrap_fn "getInt8" get_int8;
            get_signed8  = wrap_fn "getSigned8" get_signed8;

            get16        = wrap_fn "get16" get16;
            get_word16   = wrap_fn "getWord16" get_word16;
            get_int16    = wrap_fn "getInt16" get_int16;
            get_signed16 = wrap_fn "getSigned16" get_signed16;

            get32        = wrap_fn "get32" get32;
            get_signed32 = wrap_fn "getSigned32" get_signed32;
            get_word     = wrap_fn "getWord" get_word;
            get_int      = wrap_fn "getInt" get_int;

            fun get_list (f, size:  Int) (buf, i, n)
                =
                {
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_list/TOP";  }; result =
                    get (i, n, []);
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_list/BOT";  }; result;
                }
                where
                    fun get (_, 0, l) =>  list::reverse l;
                        get (i, n, l) =>  get (i+size, n - 1, f (buf, i) ! l);
                    end;
                end;

            # Get a list of strings, where each string is preceded by a one-byte length
            # field.
            #
            fun get_string_list (buf, i, n)
                =
                get (i, n, [])
                where 
                    fun get (_, 0, l)
                            =>
                            list::reverse l;

                        get (i, n, l)
                            =>
                            {   len = get_int8 (buf, i);
                                j = i+1;

                                get (j+len, n - 1, get_string (buf, j, len) ! l);
                            };
                    end;
                end;

            get_xatom =  xt::XATOM o get_word;

            fun get_xatom_option arg
                =
                case (get_word  arg)
                    #
                    0u0 => NULL;
                    x   => THE (xt::XATOM x);
                esac;


            fun get_xid arg
                =
                xt::xid_from_unt  (get_word  arg);

            fun get_xid_option arg
                =
                case (get_word  arg)
                    #
                    0u0 => NULL;
                    x   => THE (xt::xid_from_unt  x);
                esac;

            get_event_mask =  xt::EVENT_MASK o get_word;
            get_visual_id  =  xt::VISUAL_ID o get_word;

            fun get_visual_id_option  arg
                =
                case (get_word  arg)
                    #
                    0u0 => NULL;
                    x   => THE (xt::VISUAL_ID x);
                esac;


            get_rgb8 =  rgb8::rgb8_from_int  o  get_int;

            #  Are time values signed???  XXX BUGGO FIXME (X server timestamp values wrap around every 49.7 days)

            fun get_xs_timestamp (s, i)
                =
                ts::XSERVER_TIMESTAMP (get32 (s, i));

            fun get_xt_timestamp (s, i)
                =
                case (get32 (s, i))
                    #
                    0u0 => xt::CURRENT_TIME;
                    t   => xt::TIMESTAMP (ts::XSERVER_TIMESTAMP t);
                esac;


            fun get_bool arg
                =
                case (w8v::get arg)
                    #
                    0u0 => FALSE;
                    _   => TRUE;
                esac;


            fun get_pt   (s, i)
                =
                { col => get_signed16 (s, i),
                  row => get_signed16 (s, i+2)
                };

            fun get_size (s, i)
                =
                { wide => get_int16 (s, i),
                  high => get_int16 (s, i+2)
                };

            fun get_box (s, i)
                =
                { col  =>  get_signed16 (s, i),
                  row  =>  get_signed16 (s, i+2),
                  #
                  wide =>  get_int16 (s, i+4),
                  high =>  get_int16 (s, i+6)
                };

            fun get_wgeom (s, i)
                =
                { upperleft    => get_pt    (s, i  ),
                  size         => get_size  (s, i+4),
                  border_thickness => get_int16 (s, i+8)
                }
                : g2d::Window_Site;

            get_key_code =  xt::KEYCODE o get_int8;

            fun get_stk_pos arg
                =
                case (w8v::get arg)
                    #
                    0u0 => xt::PLACE_ON_TOP;
                    _   => xt::PLACE_ON_BOTTOM;
                esac;


            fun get_focus_mode (s, i)
                =
                case (w8v::get (s, i))
                    #
                    0u0 => xt::FOCUS_NORMAL;
                    0u1 => xt::FOCUS_GRAB;
                    0u2 => xt::FOCUS_UNGRAB;
                    0u3 => xt::FOCUS_WHILE_GRABBED;
                    _   => xgripe::impossible "bad focus mode";
                esac;

            fun get_focus_detail (s, i)
                =
                case (w8v::get (s, i))
                    #
                    0u0 => xt::FOCUS_ANCESTOR;
                    0u1 => xt::FOCUS_VIRTUAL;
                    0u2 => xt::FOCUS_INFERIOR;
                    0u3 => xt::FOCUS_NONLINEAR;
                    0u4 => xt::FOCUS_NONLINEAR_VIRTUAL;
                    0u5 => xt::FOCUS_POINTER;
                    0u6 => xt::FOCUS_POINTER_ROOT;
                    0u7 => xt::FOCUS_NONE;
                   _    => xgripe::impossible "bad focus detail";
                esac;

            fun get_key_but_set (s, i)
                =
                {   m = get_word16 (s, i);

                    ( xt::MKSTATE (unt::bitwise_and (m, 0uxFF)),
                      xt::MOUSEBUTTON_STATE (unt::bitwise_and (m, 0ux1F00))
                    );
                };

            fun get_rgb (buf, i)
                =
                {   red   = get_word16 (buf, i  );
                    green = get_word16 (buf, i+2);
                    blue  = get_word16 (buf, i+4);
                    #
                    rgb::rgb_from_unts (red, green, blue);
                };

            fun get_bs (buf, i)
                =
                case (w8v::get (buf, i))
                    #
                    0u0 => xt::BS_NOT_USEFUL;
                    0u1 => xt::BS_WHEN_MAPPED;
                    _   => xt::BS_ALWAYS;
                esac;


            fun get_font_dir (buf, i)
                =
                case (w8v::get (buf, i))
                    #
                    0u0 => xt::DRAW_FONT_LEFT_TO_RIGHT;
                    0u1 => xt::DRAW_FONT_RIGHT_TO_LEFT;
                    _   => xgripe::impossible "bad font direction";
                esac;

            get_xid_list   = get_list (get_xid,   4);
            get_xatom_list = get_list (get_xatom, 4);

            stipulate

                  fun to_gravity (0u1:  one_byte_unt::Unt) => THE xt::NORTHWEST_GRAVITY;
                      to_gravity 0u2 => THE xt::NORTH_GRAVITY;
                      to_gravity 0u3 => THE xt::NORTHEAST_GRAVITY;
                      to_gravity 0u4 => THE xt::WEST_GRAVITY;
                      to_gravity 0u5 => THE xt::CENTER_GRAVITY;
                      to_gravity 0u6 => THE xt::EAST_GRAVITY;
                      to_gravity 0u7 => THE xt::SOUTHWEST_GRAVITY;
                      to_gravity 0u8 => THE xt::SOUTH_GRAVITY;
                      to_gravity 0u9 => THE xt::SOUTHEAST_GRAVITY;
                      to_gravity 0u10 => THE xt::STATIC_GRAVITY;
                      to_gravity _ => NULL;
                  end;

            herein

                fun get_bit_gravity arg
                    =
                    case (to_gravity (w8v::get arg))
                        #
                        NULL  => xt::FORGET_GRAVITY;
                        THE g => g;
                    esac;


                fun get_window_gravity arg
                    =
                    case (to_gravity (w8v::get arg))
                        #
                        NULL => xt::UNMAP_GRAVITY;
                        THE g => g;
                    esac;
            end;

            fun get_raw_format arg
                =
                case (w8v::get arg)
                    #
                     0u8 =>  xt::RAW08;
                    0u16 =>  xt::RAW16;
                    0u32 =>  xt::RAW32;
                    _    =>  xgripe::impossible "[getRawFormat: bad ClientMessage]";
                esac;

        herein

            # Get the reply from a connection request:
            #
            stipulate

                prefix_size = 8;

                fun get_order (buf, i)
                    =
                    case (get8 (buf, i))
                        #
                        0u0 => xt::LSBFIRST;
                        _   => xt::MSBFIRST;
                    esac;

                fun get_pixmap_format (buf, i)
                    =
                    xt::FORMAT {
                      depth          => get_int8 (buf, i), 
                      bits_per_pixel => get_int8 (buf, i+1), 
                      scanline_pad   => get_raw_format (buf, i+2)
                    };

                fun get_visual_depth (buf, i, depth)
                    =
                    xt::VISUAL
                      {
                        visual_id    => get_visual_id (buf, i),
                        depth,

                        bits_per_rgb => get_int8 (buf, i+5),
                        cmap_entries => get_int16 (buf, i+6),

                        red_mask     => get_word (buf, i+8),
                        green_mask   => get_word (buf, i+12),
                        blue_mask    => get_word (buf, i+16),

                        ilk =>  case (w8v::get (buf, i+4))
                                    #
                                    0u0 => xt::STATIC_GRAY;  0u1 => xt::GRAY_SCALE;
                                    0u2 => xt::STATIC_COLOR;  0u3 => xt::PSEUDO_COLOR;
                                    0u4 => xt::TRUE_COLOR;  0u5 => xt::DIRECT_COLOR;
                                    _   => xgripe::impossible "bad visual depth";
                                esac

                      };

                fun get_visual_depth_list (buf, i, ndepths)
                    =
                    get_depths (ndepths, i, [])
                    where
                        fun get_depths (0, i, l)
                                =>
                                (list::reverse l, i);

                            get_depths (ndepths, i, l)
                                =>
                                {   depth = get_int8 (buf, i);

                                    case (get_int16 (buf, i+2))
                                        #
                                        0         =>  get_depths  (ndepths - 1, i+8, (xt::NO_VISUAL_FOR_THIS_DEPTH depth) ! l);
                                        n_visuals =>  get_visuals (ndepths - 1, depth, n_visuals, i+8, l);
                                    esac;
                                };
                        end 

                        also
                        fun get_visuals (ndepths, _, 0, i, l)
                                =>
                                get_depths (ndepths, i, l);

                            get_visuals (ndepths, depth, k, i, l)
                                =>
                                get_visuals (ndepths, depth, k - 1, i+24, get_visual_depth (buf, i, depth) ! l);
                        end;
                    end;

                fun get_screen (buf, i)
                    =
                    {   my (visuals, next)
                            =
                            get_visual_depth_list (buf, i+40, get_int8 (buf, i+39));

                        ( { root_window         => get_xid (buf, i),
                            default_colormap    => get_xid (buf, i+4),

                            white_rgb8          => get_rgb8  (buf, i+8),
                            black_rgb8          => get_rgb8  (buf, i+12),

                            input_masks         => get_event_mask (buf, i+16),

                            pixels_wide         => get_int16 (buf, i+20),
                            pixels_high         => get_int16 (buf, i+22),

                            millimeters_wide    => get_int16 (buf, i+24),
                            millimeters_high    => get_int16 (buf, i+26),

                            installed_colormaps => { min => get_int16 (buf, i+28), max => get_int16 (buf, i+30) },

                            root_visualid       => get_visual_id (buf, i+32),

                            backing_store       => get_bs (buf, i+36),
                            save_unders         => get_bool (buf, i+37),

                            root_depth          => get_int8 (buf, i+38),
                            visuals
                          },

                          next
                       );
                  };

                fun get_pixmap_formats (buf, i, n)
                    =
                    {
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_pixmap_formats/TOP";  }; result =
                        get_list (get_pixmap_format, 8) (buf, i, n);
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_pixmap_formats/BOT";  }; result;
                    };

                fun get_screens (buf, i, nscreens)
                    =
                    {
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_screens/TOP";  }; result =
                        get (nscreens, i, []);
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply: get_screens/BOT";  }; result;
                    }
                    where
                        fun get (0, _, l)
                                =>
                                list::reverse l;

                            get (n, i, l)
                                =>
                                {   my (screen, next) = get_screen (buf, i);

                                    get (n - 1, next, screen ! l);
                                };
                        end;
                    end;
            herein

                fun decode_connect_request_reply (prefix, msg)
                    =
                    {
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/TOP";  };
                        vendor_len    =  get_int16               (msg, 16);

trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/AAA";  };
                        nscreens      =  get_int8                (msg, 20);
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/BBB";  };
                        nformats      =  get_int8                (msg, 21);

trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/CCC";  };
                        format_offset =  pad (32 + vendor_len);
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/DDD";  };
                        screen_offset =  format_offset + 8*nformats;
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/EEE";  };
result =
                        { protocol_version => { major => get_int16 (prefix, 2),
                                                minor => get_int16 (prefix, 4)
                                              },

                          release_number     => get_int          (msg,  0),
                          xid_base           => get_word         (msg,  4),
                          xid_mask           => get_word         (msg,  8),

                          motion_buf_size    => get_int          (msg, 12),
                          max_request_length => get_int16        (msg, 18),

                          image_byte_order   => get_order        (msg, 22),
                          bitmap_order       => get_order        (msg, 23),

                          bitmap_scanline_unit => get_raw_format (msg, 24),
                          bitmap_scanline_pad  => get_raw_format (msg, 25),

                          min_keycode => get_key_code            (msg, 26),
                          max_keycode => get_key_code            (msg, 27),

                          vendor => get_string                   (msg, 32, vendor_len),

                          pixmap_formats => get_pixmap_formats   (msg, format_offset, nformats),
                          screens        => get_screens          (msg, screen_offset, nscreens)
                        };
trace  {.  "wire-to-value-pith.pkg: decode_connect_request_reply/BOTTOM";  };
result;
                    };
            end;                        # stipulate


            # Decode event messages

            stipulate

                fun get_key_xevent buf
                    =
                    {   my (mks, mbs) = get_key_but_set    (buf, 28);

                        { keycode         => get_key_code      (buf,  1),
                          timestamp       => get_xs_timestamp  (buf,  4),
                          root_window_id  => get_xid           (buf,  8),
                          event_window_id => get_xid           (buf, 12),
                          child_window_id => get_xid_option    (buf, 16),
                          root_point      => get_pt                (buf, 20),
                          event_point     => get_pt                (buf, 24),
                          #
                          modifier_keys_state   => mks,
                          mousebuttons_state    => mbs,
                          same_screen           => get_bool(buf, 30)
                        };
                    };

                fun get_button_xevent buf
                    =
                    {   my (mks, mbs)
                            =
                            get_key_but_set                        (buf, 28);

                        { mouse_button    => xt::MOUSEBUTTON (get_int8 (buf,  1)),
                          timestamp       => get_xs_timestamp          (buf,  4),
                          root_window_id  => get_xid                   (buf,  8),
                          event_window_id => get_xid                   (buf, 12),
                          child_window_id => get_xid_option            (buf, 16),
                          root_point      => get_pt                    (buf, 20),
                          event_point     => get_pt                    (buf, 24),
                          #
                          modifier_keys_state  => mks,
                          mousebuttons_state   => mbs,
                          same_screen          => get_bool             (buf, 30)
                       };
                    };

                fun decode_motion_notify buf
                    =
                    {   my (mks, mbs)
                            =
                            get_key_but_set                 (buf, 28);

                        xet::x::MOTION_NOTIFY
                          {
                            hint            => get_bool          (buf,  1),
                            timestamp       => get_xs_timestamp  (buf,  4),

                            root_window_id  => get_xid           (buf,  8),
                            event_window_id => get_xid           (buf, 12),
                            child_window_id => get_xid_option    (buf, 16),

                            root_point      => get_pt            (buf, 20),
                            event_point     => get_pt            (buf, 24),

                            modifier_keys_state  => mks,
                            mousebuttons_state   => mbs,

                            same_screen     => get_bool          (buf, 30)
                          };
                    };

                fun get_enter_leave_xevent buf
                    =
                    {   my (mks, mbs)
                            =
                            get_key_but_set                   (buf, 28);

                        flags = get8                          (buf, 31);

                        { detail          => get_focus_detail (buf,  1),
                          timestamp       => get_xs_timestamp (buf,  4),
                          #
                          root_window_id  => get_xid          (buf,  8),
                          event_window_id => get_xid          (buf, 12),
                          child_window_id => get_xid_option   (buf, 16),

                          root_point      => get_pt           (buf, 20),
                          event_point     => get_pt           (buf, 24),

                          modifier_keys_state => mks,
                          mousebuttons_state  => mbs,

                          mode  =>     get_focus_mode        (buf, 30),
                          focus => is_set (flags, 0u0),

                          same_screen => is_set (flags, 0u1)
                        };
                    };

                fun get_focus_xevent buf
                    =
                    {   detail           => get_focus_detail (buf, 1),
                        event_window_id  => get_xid          (buf, 4),
                        mode             => get_focus_mode   (buf, 8)
                    };

                fun decode_keymap_notify buf
                    =
                    xet::x::KEYMAP_NOTIFY { };     # * NOTE: no seqn #    # FIX *

                fun decode_expose buf
                    =
                    xet::x::EXPOSE
                      {
                        exposed_window_id =>   get_xid   (buf,  4),
                        boxes             => [ get_box   (buf,  8) ],
                        count             =>   get_int16 (buf, 16)
                      };

                fun decode_graphics_expose buf
                    =
                    xet::x::GRAPHICS_EXPOSE
                      { drawable     => get_xid    (buf,  4),
                        box          => get_box    (buf,  8),
                        minor_opcode => get_word16 (buf, 16),
                        count        => get_int16  (buf, 18),
                        major_opcode => get_word16 (buf, 20)
                      };

                fun decode_no_expose buf
                    =
                    xet::x::NO_EXPOSE
                    {
                      drawable     => get_xid    (buf,  4),

                      minor_opcode => get_word16 (buf,  8),
                      major_opcode => get_word16 (buf, 10)
                    };

                fun decode_visibility_notify buf
                    =
                    xet::x::VISIBILITY_NOTIFY
                      {
                        changed_window_id =>  get_xid (buf, 4),

                        state  => case (w8v::get (buf, 8))
                                      #
                                      0u0 => xt::VISIBILITY_UNOBSCURED;
                                      0u1 => xt::VISIBILITY_PARTIALLY_OBSCURED;
                                      0u2 => xt::VISIBILITY_FULLY_OBSCURED;
                                      _   => xgripe::impossible "bad VisibilityNotify";
                                  esac
                      };

                fun decode_create_notify buf
                    =
                    xet::x::CREATE_NOTIFY
                      {
                        parent_window_id  =>  get_xid   (buf,  4),
                        created_window_id =>  get_xid   (buf,  8),

                        box               =>  get_box   (buf, 12),

                        border_wid        =>  get_int16 (buf, 20),
                        override_redirect =>  get_bool  (buf, 21)
                      };

                fun decode_destroy_notify buf
                    =
                    xet::x::DESTROY_NOTIFY
                      { event_window_id     =>  get_xid (buf, 4),
                        destroyed_window_id =>  get_xid (buf, 8)
                      };

                fun decode_unmap_notify buf
                    =
                    xet::x::UNMAP_NOTIFY
                      {
                        event_window_id    =>  get_xid  (buf,  4),
                        unmapped_window_id =>  get_xid  (buf,  8),
                        from_config        =>  get_bool (buf, 12)
                      };

                fun decode_map_notify buf
                    =
                    xet::x::MAP_NOTIFY
                      {
                        event_window_id    =>  get_xid  (buf,  4),
                        mapped_window_id   =>  get_xid  (buf,  8),
                        #
                        override_redirect  =>  get_bool (buf, 12)
                      };

                fun decode_map_request buf
                    =
                    xet::x::MAP_REQUEST
                      {
                        parent_window_id   =>  get_xid (buf,  4),
                        mapped_window_id   =>  get_xid (buf,  8)
                      };

                fun decode_reparent_notify buf
                    =
                    xet::x::REPARENT_NOTIFY
                      {
                        event_window_id    =>  get_xid             (buf,  4),
                        parent_window_id   =>  get_xid             (buf,  8),
                        rerooted_window_id =>  get_xid             (buf, 12),   # I suspect this should be "reparented_window_id"
                        #
                        upperleft_corner   =>  get_pt              (buf, 16),
                        override_redirect  =>  get_bool            (buf, 20)
                      };

                fun decode_configure_notify buf
                    =
                    xet::x::CONFIGURE_NOTIFY
                    {
                      event_window_id      =>  get_xid             (buf,  4),
                      configured_window_id =>  get_xid             (buf,  8),
                      sibling_window_id    =>  get_xid_option      (buf, 12),
                      # 
                      box                  =>  get_box             (buf, 16),
                      border_wid           =>  get_int16           (buf, 20),
                      override_redirect    =>  get_bool            (buf, 22)
                    };

                fun decode_configure_request buf
                    =
                    {   mask = get16 (buf, 26);

                        fun the_else get_fn (i, j)
                            = 
                            is_set (mask, i)  ??  THE (get_fn (buf, j))
                                              ::  NULL;

                        xet::x::CONFIGURE_REQUEST
                          {
                            stack_mode => if (not (is_set (mask, 0u6)))
                                               NULL;
                                          else
                                               case (w8v::get (buf, 1))
                                                   #
                                                   0u0 => THE xt::ABOVE;
                                                   0u1 => THE xt::BELOW;
                                                   0u2 => THE xt::TOP_IF;
                                                   0u3 => THE xt::BOTTOM_IF;
                                                   0u4 => THE xt::OPPOSITE;
                                                   _ => xgripe::impossible "bad ConfigureRequest";
                                                esac;
                                          fi,


                            parent_window_id    =>  get_xid               (buf,  4),
                            configure_window_id =>  get_xid               (buf,  8),
                            sibling_window_id   =>  get_xid_option        (buf, 12),
                            #
                            x                   =>  the_else get_signed16 (0u0, 16),
                            y                   =>  the_else get_signed16 (0u1, 18),
                            wide                =>  the_else get_int16    (0u2, 20),
                            high                =>  the_else get_int16    (0u3, 22),
                            border_wid          =>  the_else get_int16    (0u4, 24)
                          };
                    };

                fun decode_gravity_notify buf
                    =
                    xet::x::GRAVITY_NOTIFY
                      {
                        event_window_id  =>  get_xid (buf,  4),
                        moved_window_id  =>  get_xid (buf,  8),
                        #
                        upperleft_corner =>  get_pt  (buf, 12)
                      };

                fun decode_resize_request buf
                    =
                    xet::x::RESIZE_REQUEST
                      {
                        resize_window_id  =>  get_xid  (buf, 4),
                        req_size          =>  get_size (buf, 8)
                      };

                fun decode_circulate_notify buf
                    =
                    xet::x::CIRCULATE_NOTIFY
                      {
                        event_window_id      =>  get_xid     (buf,  4),
                        circulated_window_id =>  get_xid     (buf,  8),
                        parent_window_id     =>  get_xid     (buf, 12),
                        #
                        place                =>  get_stk_pos (buf, 16)
                      };

                fun decode_circulate_request buf
                    =
                    xet::x::CIRCULATE_REQUEST
                      {
                        parent_window_id     =>  get_xid     (buf,  4),
                        circulate_window_id  =>  get_xid     (buf,  8),
                        place                =>  get_stk_pos (buf, 12)
                      };

                fun decode_property_notify buf
                    =
                    xet::x::PROPERTY_NOTIFY
                      {
                        changed_window_id    =>  get_xid          (buf,  4),
                        atom                 =>  get_xatom        (buf,  8),
                        timestamp            =>  get_xs_timestamp (buf, 12),
                        deleted              =>  get_bool         (buf, 16)        
                      };

                fun decode_selection_clear buf
                    =
                    xet::x::SELECTION_CLEAR
                    {
                      timestamp              =>  get_xs_timestamp (buf,  4),
                      owning_window_id       =>  get_xid          (buf,  8),
                      selection              =>  get_xatom        (buf, 12)
                    };

                fun decode_selection_request buf
                    =
                    xet::x::SELECTION_REQUEST
                      {
                        timestamp            =>  get_xt_timestamp (buf,  4),
                        owning_window_id     =>  get_xid          (buf,  8),
                        requesting_window_id =>  get_xid          (buf, 12),
                        selection            =>  get_xatom        (buf, 16),
                        target               =>  get_xatom        (buf, 20),
                        property             =>  get_xatom_option (buf, 24)
                      };

                fun decode_selection_notify buf
                    =
                    xet::x::SELECTION_NOTIFY
                      {
                        timestamp            =>  get_xt_timestamp (buf,  4),
                        requesting_window_id =>  get_xid          (buf,  8),
                        selection            =>  get_xatom        (buf, 12),
                        target               =>  get_xatom        (buf, 16),
                        property             =>  get_xatom_option (buf, 20)
                      };

                fun decode_colormap_notify buf
                    =
                    xet::x::COLORMAP_NOTIFY
                      {
                        window_id           =>  get_xid           (buf,  4),
                        cmap                =>  get_xid_option    (buf,  8),
                        new                 =>  get_bool          (buf, 12),
                        installed           =>  get_bool          (buf, 13)
                      };

                # ClientMessage is documented on pages 88 and 158 of:
                #
                #     http://mythryl.org/pub/exene/X-protocol-R6.pdf
                #
                fun decode_client_message buf
                    = 
                    xet::x::CLIENT_MESSAGE
                      {
                        window_id           =>  get_xid           (buf,  4),
                        type                =>  get_xatom         (buf,  8),
                        #
                        value  => xt::RAW_DATA
                                    {
                                      format =>  get_raw_format   (buf,  1),
                                      data   =>  w8vextract       (buf, 12, THE 20)
                                    }
                      };

                # MappingNotify is document on page 88 (see also 68, 69, 72, 158) of:
                #
                #     http://mythryl.org/pub/exene/X-protocol-R6.pdf
                #
                fun decode_mapping_notify buf
                    =
                    case (w8v::get (buf, 4))
                        #
                        0u0 => xet::x::MODIFIER_MAPPING_NOTIFY;

                        0u1 => xet::x::KEYBOARD_MAPPING_NOTIFY
                                 {
                                   first_keycode => get_key_code (buf, 5),
                                   count         => get_int8     (buf, 6)
                                 };

                        0u2 => xet::x::POINTER_MAPPING_NOTIFY;
                        _   => xgripe::impossible "bad MappingNotify";
                    esac;

            herein

                # Page numbers below are for   http://mythryl.org/pub/exene/X-protocol-R6.pdf
                #
                # Page 1 comments that
                #
                #    "Every event contains an 8-bit type code.
                #     The most-significant bit in this code
                #     is set if the event was generated by a
                #     SendEvent request."
                #
                # The "type code" must be byte 0, 'code' below.
                #
                # Individual X event layouts are documented
                # starting on page 150.

                fun decode_xpacket (code: one_byte_unt::Unt,  buf)
                    =
                    {
                        n = w8::bitwise_and (code, 0ux7f);

                        xevent = case n
                                     #
                                     0u2  => xet::x::KEY_PRESS          (get_key_xevent    buf);
                                     0u3  => xet::x::KEY_RELEASE        (get_key_xevent    buf);
                                     0u4  => xet::x::BUTTON_PRESS       (get_button_xevent buf);
                                     0u5  => xet::x::BUTTON_RELEASE     (get_button_xevent buf);
                                     0u6  => decode_motion_notify       buf;
                                     0u7  => xet::x::ENTER_NOTIFY       (get_enter_leave_xevent buf);
                                     0u8  => xet::x::LEAVE_NOTIFY       (get_enter_leave_xevent buf);
                                     0u9  => xet::x::FOCUS_IN           (get_focus_xevent buf);
                                     0u10 => xet::x::FOCUS_OUT          (get_focus_xevent buf);
                                     0u11 => decode_keymap_notify       buf;
                                     0u12 => decode_expose              buf;
                                     0u13 => decode_graphics_expose     buf;
                                     0u14 => decode_no_expose           buf;
                                     0u15 => decode_visibility_notify   buf;
                                     0u16 => decode_create_notify       buf;
                                     0u17 => decode_destroy_notify      buf;
                                     0u18 => decode_unmap_notify        buf;
                                     0u19 => decode_map_notify          buf;
                                     0u20 => decode_map_request         buf;
                                     0u21 => decode_reparent_notify     buf;
                                     0u22 => decode_configure_notify    buf;
                                     0u23 => decode_configure_request   buf;
                                     0u24 => decode_gravity_notify      buf;
                                     0u25 => decode_resize_request      buf;
                                     0u26 => decode_circulate_notify    buf;
                                     0u27 => decode_circulate_request   buf;
                                     0u28 => decode_property_notify     buf;
                                     0u29 => decode_selection_clear     buf;
                                     0u30 => decode_selection_request   buf;
                                     0u31 => decode_selection_notify    buf;
                                     0u32 => decode_colormap_notify     buf;
                                     0u33 => decode_client_message      buf;
                                     0u34 => decode_mapping_notify      buf;
                                     _ => xgripe::impossible "bad event code";
                                 esac;

                        ( code == n,            # FALSE means that this event was faked via SendEvent request.
                          xevent
                        );
                  };

                # We export the decode functions
                # for reporting graphics exposures 
                #
                decode_graphics_expose = decode_graphics_expose;
                decode_no_expose = decode_no_expose;

            end;                        # stipulate


            # Decode error messages:
            #
            stipulate


                fun get_error (kind, buf)
                    =
                    xe::XERROR
                      {
                        kind,
                        minor_op => get_word16 (buf,  8),
                        major_op => w8v::get   (buf, 10)
                      };
            herein

                fun decode_error buf
                    =
                    case (w8v::get (buf, 1))
                        #
                        0u1  => get_error (xe::BAD_REQUEST,                           buf);
                        0u2  => get_error (xe::BAD_VALUE    (get_string (buf, 4, 4)), buf);
                        0u3  => get_error (xe::BAD_WINDOW   (get_xid    (buf, 4)),    buf);
                        0u4  => get_error (xe::BAD_PIXMAP   (get_xid    (buf, 4)),    buf);
                        0u5  => get_error (xe::BAD_ATOM     (get_xid    (buf, 4)),    buf);
                        0u6  => get_error (xe::BAD_CURSOR   (get_xid    (buf, 4)),    buf);
                        0u7  => get_error (xe::BAD_FONT     (get_xid    (buf, 4)),    buf);
                        0u8  => get_error (xe::BAD_MATCH,                             buf);
                        0u9  => get_error (xe::BAD_DRAWABLE (get_xid    (buf, 4)),    buf);
                        0u10 => get_error (xe::BAD_ACCESS,                            buf);
                        0u11 => get_error (xe::BAD_ALLOC,                             buf);
                        0u12 => get_error (xe::BAD_COLOR    (get_xid    (buf, 4)),    buf);
                        0u13 => get_error (xe::BAD_GC       (get_xid    (buf, 4)),    buf);
                        0u14 => get_error (xe::BAD_IDCHOICE (get_xid    (buf, 4)),    buf);
                        0u15 => get_error (xe::BAD_NAME,                              buf);
                        0u16 => get_error (xe::BAD_LENGTH,                            buf);
                        0u17 => get_error (xe::BAD_IMPLEMENTATION,                    buf);
                        #
                        _ => xgripe::impossible "bad error number";
                    esac;
            end;


            # Decode reply messages.
            #
            fun decode_get_window_attributes_reply msg
                =
                {
                  backing_store => get_bs                      (msg,  1),
                  visual => get_visual_id                      (msg,  8),

                  input_only => case (get16                    (msg, 12))
                                    #
                                    0u1 => FALSE;
                                    0u2 => TRUE;
                                    _   => xgripe::impossible "bad GetWindowAttributes reply";
                                esac,

                  bit_gravity => get_bit_gravity               (msg, 14),
                  window_gravity => get_window_gravity         (msg, 15),

                  backing_planes   => xt::PLANEMASK (get_word  (msg, 16)),
                  backing_pixel    => get_rgb8                (msg, 20),
                  save_under       => get_bool                 (msg, 24),
                  map_is_installed => get_bool                 (msg, 25),

                  map_state => case (w8v::get                  (msg, 26))
                                   #
                                   0u0 => xt::WINDOW_IS_UNMAPPED;
                                   0u1 => xt::WINDOW_IS_UNVIEWABLE;
                                   0u2 => xt::WINDOW_IS_VIEWABLE;
                                   _   => xgripe::impossible "bad GetWindowAttributes reply";
                               esac,

                  override_redirect => get_bool                (msg, 27),
                  colormap          => get_xid_option          (msg, 28),

                  all_event_mask    => get_event_mask          (msg, 32),
                  event_mask        => get_event_mask          (msg, 36),
                  do_not_propagate  => get_event_mask          (msg, 40)
                };

            fun decode_alloc_color_cells_reply msg
                =
                { err => xgripe::impossible "unimplemented" # ** FIX ** XXX BUGGO FIXME
                };

            fun decode_alloc_color_planes_reply msg
                =
                { err => xgripe::impossible "unimplemented" # ** FIX ** XXX BUGGO FIXME
                };

            fun decode_alloc_color_reply msg
                =
                { visual_rgb => get_rgb  (msg,  8),
                  pixel      => get_rgb8 (msg, 16)
                };

            fun decode_alloc_named_color_reply msg
                =
                { pixel      => get_rgb8 (msg,  8),
                  exact_rgb  => get_rgb  (msg, 12),
                  visual_rgb => get_rgb  (msg, 18)
                };

            fun decode_get_atom_name_reply msg
                =
               get_string (msg, 32, get_int16 (msg, 8));

            fun decode_get_font_path_reply msg
                =
                get_string_list (msg, 32, get_int16 (msg, 8));

            fun decode_get_geometry_reply msg
                =
                { depth     =>  get_int8  (msg,  1),
                  root      =>  get_xid   (msg,  8),
                  geometry  =>  get_wgeom (msg, 12)
                };

            fun decode_get_image_reply  msg
                =
                { depth    =>  get_int8             (msg,  1),
                  visualid =>  get_visual_id_option (msg,  8),
                  data     =>  w8vextract           (msg, 32, THE (4*get_int (msg, 4)))
                };

            fun decode_get_input_focus_reply msg
                =
                {   revert_to => case (w8v::get (msg, 1))
                                     #
                                     0u0 =>  xt::REVERT_TO_NONE;
                                     0u1 =>  xt::REVERT_TO_POINTER_ROOT;
                                     _   =>  xt::REVERT_TO_PARENT;
                                 esac,

                    focus =>     case (get_word (msg, 8))
                                    #
                                    0u0 =>  xt::INPUT_FOCUS_NONE;
                                    0u1 =>  xt::INPUT_FOCUS_POINTER_ROOT;
                                    w   =>  xt::INPUT_FOCUS_WINDOW (xt::xid_from_unt w);
                                esac

                  };

            fun decode_get_keyboard_control_reply msg
                =
                {
                  glob_auto_repeat =>  get_bool   (msg,  1),
                  led_mask         =>  get32      (msg,  8),
                  key_click_pct    =>  get_int8   (msg, 12),
                  bell_pct         =>  get_int8   (msg, 13),
                  bell_pitch       =>  get_int16  (msg, 14),
                  bell_duration    =>  get_int16  (msg, 16),
                  auto_repeats     =>  w8vextract (msg, 20, THE 32)
                };

            fun decode_get_keyboard_mapping_reply msg
                =
                {
                    syms_per_code =  get_int8 (msg, 1);
                    n_key_codes   =  get_int  (msg, 4) / syms_per_code;

                    # Get the keysyms bound to a given keycode;
                    # Discard trailing NoSymbols,
                    # but include intermediate ones.
                    #
                    fun clean_tl (xt::NO_SYMBOL ! r) =>  clean_tl r;
                        clean_tl l                   =>  reverse l;
                    end;

                    fun get_syms (i, 0, l) =>   clean_tl l;
                        #
                        get_syms (i, j, l) =>   case (get_int (msg, i))
                                                    #
                                                    0 =>  get_syms (i+4, j - 1,  xt::NO_SYMBOL ! l);
                                                    k =>  get_syms (i+4, j - 1, (xt::KEYSYM k) ! l);
                                                esac;
                    end;

                    get_list
                      ( \\ (_, i) =  get_syms (i, syms_per_code, []),
                        syms_per_code * 4
                      )

                    (msg, 32, n_key_codes);
                };

            fun decode_get_modifier_mapping_reply msg
                =
                { shift_keycodes =>  get_syms 0,
                  lock_keycodes  =>  get_syms 1,
                  cntl_keycodes  =>  get_syms 2,
                  mod1_keycodes  =>  get_syms 3,
                  mod2_keycodes  =>  get_syms 4,
                  mod3_keycodes  =>  get_syms 5,
                  mod4_keycodes  =>  get_syms 6,
                  mod5_keycodes  =>  get_syms 7
                }
                where
                    codes_per_mod =  get_int8 (msg, 1);
                    #
                    fun get_syms k
                        =
                        get (32 + codes_per_mod*k, codes_per_mod)
                        where
                            fun get (i, 0) =>   [];
                                #
                                get (i, j) =>   case (get_int8 (msg, i))
                                                    #
                                                    0 => get (i+1, j - 1);                      #  0 == unused 
                                                    k => (xt::KEYCODE k) ! get (i+1, j - 1);
                                                esac;
                             end;
                        end;
                end;

            stipulate
                #
                get_events =    get_list
                                  ( \\ (buf, i) =  { timestamp => get_xt_timestamp (buf, i  ),
                                                     coord     => get_pt           (buf, i+4)
                                                   },
                                    8
                                  );

            herein
                #
                fun decode_get_motion_events_reply msg
                    =
                    get_events (msg, 32, get_int16 (msg, 8));
            end;

            fun decode_get_pointer_control_reply msg
                =
                { acceleration_numerator   =>  get16 (msg,  8),
                  acceleration_denominator =>  get16 (msg, 10),
                  threshold                =>  get16 (msg, 12)
                };

            fun decode_get_pointer_mapping_reply msg
                =
                { err => xgripe::impossible "unimplemented"             # XXX SUCKO FIXME
                };

            fun decode_get_property_reply msg
                =
                case (get_word (msg, 8))
                    #
                    0u0 => NULL;

                    t   =>  {   nitems =  get_int (msg, 16);
                                #
                                my (fmt, nbytes)
                                    =
                                    case (w8v::get (msg, 1))
                                        #
                                        0u8  =>  (xt::RAW08,   nitems);
                                        0u16 =>  (xt::RAW16, 2*nitems);
                                        0u32 =>  (xt::RAW32, 4*nitems);
                                        #
                                        _    =>  xgripe::impossible "bad GetProperty reply";
                                    esac;


                                THE { type        => xt::XATOM t,
                                      bytes_after => get_int (msg, 12),
                                      value       => xt::RAW_DATA { format => fmt,
                                                                    data => w8vextract (msg, 32, THE nbytes)
                                                                   }
                                    };
                            };
                esac;

            fun decode_get_screen_saver_reply msg
                =
                { timeout         =>  get16    (msg,  8),
                  interval        =>  get16    (msg, 10),
                  prefer_blanking =>  get_bool (msg, 12),
                  allow_exposures =>  get_bool (msg, 13)
                };

            fun decode_get_selection_owner_reply msg
                =
                get_xid_option (msg, 8);

            stipulate
                #
                fun decode_grab_reply msg
                    =
                    case (w8v::get (msg, 1))
                        #
                        0u0 =>  xt::GRAB_SUCCESS;
                        0u1 =>  xt::ALREADY_GRABBED;
                        0u2 =>  xt::GRAB_INVALID_TIME;
                        0u3 =>  xt::GRAB_NOT_VIEWABLE;
                        _   =>  xt::GRAB_FROZEN;
                    esac;

            herein
                decode_grab_keyboard_reply =  decode_grab_reply;
                decode_grab_pointer_reply  =  decode_grab_reply;
            end;

            fun decode_intern_atom_reply msg
                =
                get_xatom (msg, 8);

            fun decode_list_extensions_reply msg
                =
                get_string_list (msg, 32, get_int8 (msg, 1));

            fun decode_list_fonts_reply msg
                =
                get_string_list (msg, 32, get_int16 (msg, 8));

            stipulate
                #
                fun get_host_list (buf, n)
                    =
                    get (32, n, [])
                    where
                        fun get (_, 0, l)
                                =>
                                l;

                            get (i, n, l)
                                =>
                                {   addr_len = get_int16  (buf, i+2);
                                    address  = get_string (buf, i+4, addr_len);

                                    host     = case (w8v::get (buf, i))
                                                   #
                                                   0u0 => xt::INTERNET_HOST address;
                                                   0u1 => xt::DECNET_HOST address;
                                                   0u2 => xt::CHAOS_HOST address;
                                                   _   => raise exception (xgripe::xerror "unknown host family");
                                               esac;

                                    get (i+(pad addr_len)+4, n - 1, host ! l);
                                };
                        end;
                    end;
            herein

                fun decode_list_hosts_reply msg
                    =
                    {   enabled =>  get_bool (msg, 1),
                        hosts   =>  get_host_list (msg, get_int16 (msg, 8))
                    };
            end;                # stipulate


            fun decode_list_installed_colormaps_reply msg
                =
                get_xid_list (msg, 32, get_int16 (msg, 8));


            fun decode_list_properties_reply msg
                =
                get_xatom_list (msg, 32, get_int16 (msg, 8));


            fun decode_lookup_color_reply msg
                =
                {   exact_rgb  =>  get_rgb (msg,  8),
                    visual_rgb =>  get_rgb (msg, 14)
                };

            fun decode_query_best_size_reply msg
                =
                {   wide =>  get_int16 (msg,  8),
                    high =>  get_int16 (msg, 10)
                };



            stipulate
                #
                get_rgblist = get_list (get_rgb, 8);

            herein
                #
                fun decode_query_colors_reply msg
                    =
                    get_rgblist (msg, 32, get_int16 (msg, 8));

            end;



            fun decode_query_extension_reply msg
                =
                { err => xgripe::impossible "unimplemented"             # XXX BUGGO FIXME
                };

            stipulate
                #
                get_props = get_list
                              ( \\ (buf, i) =  xt::FONT_PROP  { name  =>  get_xatom (buf, i  ),
                                                                value =>  get32     (buf, i+4)
                                                              },
                                8
                              );

                fun get_char_info (buf, i)
                    =
                    xt::CHAR_INFO
                      {
                        left_bearing  =>  get_signed16 (buf, i),
                        right_bearing =>  get_signed16 (buf, i+2),
                        char_width    =>  get_signed16 (buf, i+4),
                        ascent        =>  get_signed16 (buf, i+6),
                        descent       =>  get_signed16 (buf, i+8),
                        attributes    =>  get_word16   (buf, i+10)
                      };

                get_char_info_list
                    =
                    get_list (get_char_info, 12);

                fun get_info buf                                                                # For background here see p38 and p131 in   http://mythryl.org/pub/exene/X-protocol-R7.pdf
                    =                                                                           #
                    {   n_props = get_int16            (buf, 46);
                        #
                        { min_bounds => get_char_info  (buf,  8),
                          max_bounds => get_char_info  (buf, 24),

                          min_char   => get_int16      (buf, 40),                               # "min-char-or-byte2" in protocol doc.
                          max_char   => get_int16      (buf, 42),                               # "max-char-or-byte2" in protocol doc.

                          default_char => get_int16    (buf, 44),
                          draw_dir     => get_font_dir (buf, 48),

                          min_byte1 => get_int8        (buf, 49),
                          max_byte1 => get_int8        (buf, 50),

                          all_chars_exist => get_bool  (buf, 51),
                          font_ascent     => get_int16 (buf, 52),
                          font_descent    => get_int16 (buf, 54),
                          n_props,

                          properties => get_props (buf, 60, n_props)
                       };
                    };
            herein

        /****** THIS GENERATES MULTIPLE REPLIES ****
          #  this gets a list of font name/info replies 
            fun decodeListFontsWithInfoReply msg = let
              fun getList l = let
                my (msg, extra) = getReply (connection, sizeOfListFontsWithInfoReply)
                name_len = get8 (msg, 1)
                in
                  if (name_len == 0)
                then #  this is the last in a series of replies 
                  (reverse l)
                else let
                  info = getInfo (msg, extra)
                  reply = {
                      min_bounds = info.min_bounds,
                      max_bounds = info.max_bounds,
                      min_char = info.min_char,
                      max_char = info.max_char,
                      default_char = info.default_char,
                      draw_dir = info.draw_dir,
                      min_byte1 = info.min_byte1,
                      max_byte1 = info.max_byte1,
                      all_chars_exist = info.all_chars_exist,
                      font_ascent = info.font_ascent,
                      font_descent = info.font_descent,
                      replies_hint = get32 (msg, 56),
                      properties = info.properties,
                      name = get_string (extra, 8*info.n_props, name_len)
                    }
                  in
                    getList (reply ! l)
                  end
                end #  getList 
              in
                getList []
              end #  getListFontsWithInfoReply 
        *********/

            fun decode_query_font_reply  msg
                =
                {   info =  get_info  msg;
                    #
                    { min_bounds => info.min_bounds,
                      max_bounds => info.max_bounds,

                      min_char   => info.min_char,
                      max_char   => info.max_char,

                      default_char => info.default_char,

                      draw_dir  => info.draw_dir,

                      min_byte1 => info.min_byte1,
                      max_byte1 => info.max_byte1,

                      all_chars_exist => info.all_chars_exist,

                      font_ascent  => info.font_ascent,
                      font_descent => info.font_descent,

                      properties => info.properties,
                      char_infos => get_char_info_list (msg, 60+8*info.n_props, get_int (msg, 56))
                    };
                };
            end;                        # stipulate

            fun decode_query_keymap_reply  msg
                =
                { err => xgripe::impossible "unimplemented" # ** FIX **
                };

            fun decode_query_pointer_reply  msg
                =
                {   (get_key_but_set (msg, 24))
                        ->
                        (mks, mbs);

                    { same_screen    => get_bool       (msg,  1),
                      root           => get_xid        (msg,  8),
                      child          => get_xid_option (msg, 12),
                      root_point     => get_pt         (msg, 16),
                      window_point   => get_pt         (msg, 20),
                      modifier_keys_state => mks,
                      mousebuttons_state  => mbs
                    };
                };

            fun decode_query_text_extents_reply  msg
                =
                { draw_direction  => get_font_dir (msg,  1),
                  font_ascent     => get16        (msg,  8),
                  font_descent    => get16        (msg, 10),
                  overall_ascent  => get16        (msg, 12),
                  overall_descent => get16        (msg, 14),
                  overall_width   => get16        (msg, 16),
                  overall_left    => get16        (msg, 18),
                  overall_right   => get16        (msg, 20)
                };

            fun decode_query_tree_reply  msg
                =
                { root     => get_xid        (msg,  8),
                  parent   => get_xid_option (msg, 12),
                  children => get_xid_list   (msg, 32, get_int16 (msg, 16)) 
                };

            stipulate
                #
                fun get_set_mapping_reply msg
                    =
                    case (get8 (msg, 1))
                        #
                        0u0 => xt::MAPPING_SUCCESS;
                        0u1 => xt::MAPPING_BUSY;
                        _   => xt::MAPPING_FAILED;
                    esac;

            herein
                decode_set_modifier_mapping_reply = get_set_mapping_reply;
                decode_set_pointer_mapping_reply  = get_set_mapping_reply;
            end;

            fun decode_translate_coordinates_reply  msg
                =
                { child    =>  get_xid_option (msg,  8),
                  to_point =>  get_pt         (msg, 12)
                };


        end;                    # stipulate

    };                          # package wire_to_value
end;


Comments and suggestions to: bugs@mythryl.org

PreviousUpNext