DataMuseum.dk

Presents historical artifacts from the history of:

Rational R1000/400

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Rational R1000/400

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦00a2fb873⟧ Ada Source

    Length: 67584 (0x10800)
    Types: Ada Source
    Notes: 03_class, FILE, Long Ada Source, R1k_Segment, e3_tag, package body Xlbmp_Put, seg_004f0f

Derivation

└─⟦8527c1e9b⟧ Bits:30000544 8mm tape, Rational 1000, Arrival backup of disks in PAM's R1000
    └─ ⟦cfc2e13cd⟧ »Space Info Vol 2« 
        └─⟦this⟧ 

E3 Source Code



with Xlbt_Arithmetic;  
use Xlbt_Arithmetic;  
with Xlbt_Basic;  
use Xlbt_Basic;  
with Xlbt_Exceptions;  
use Xlbt_Exceptions;
with Xlbt_Request;
use Xlbt_Request;

with Xlbip_Internal;  
use Xlbip_Internal;

with Xlbmt_Network_Types;  
use Xlbmt_Network_Types;

with Xlbmp_Internal;  
use Xlbmp_Internal;

package body Xlbmp_Put is
------------------------------------------------------------------------------
-- X Library X Server Put Routines
--
-- Xlbmp_Put - Send info to the X Server
------------------------------------------------------------------------------
-- Copyright 1989 - 1991 by Rational, Santa Clara, California.
--
--                  All Rights Reserved.
--
-- Permission to use, copy, modify, and distribute this software and its
-- documentation for any purpose and without fee is hereby granted,
-- provided that the above copyright notice(s) appear in all copies and that
-- both that copyright notice(s) and this permission notice appear in
-- supporting documentation, and that the name of Rational not be used in
-- advertising or publicity pertaining to distribution of the software
-- without specific, written prior permission.
--
-- Rational disclaims all warranties with regard to this software, including
-- all implied warranties of merchantability and fitness, in no event shall
-- Rational be liable for any special, indirect or consequential damages or
-- any damages whatsoever resulting from loss of use, data or profits, whether
-- in an action of contract, negligence or other tortious action, arising out
-- of or in connection with the use or performance of this software.
------------------------------------------------------------------------------

--\x0c
    procedure Put_Request (Display : X_Display;  
                           Req     : Request) is
------------------------------------------------------------------------------
-- For X_Request's only.  Do not use for ordinary private types.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Request         - this is the type of data that needs to be sent
--  Request_Size    - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  Cvt             - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  Req             - the request to send
------------------------------------------------------------------------------
        Last_Byte : X_Raw_Data_Index;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

--/ if DEBUG then

        if Request_Size rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        end if;

--/ end if;

----If there is a request in the Display.Last_Req buffer then he must be flushed
--  before we can be placed.

        if Display.Last_Request.Kind /= Invalid_Request then  
            Internal_X_Flush_Last_Request (Display);  
        end if;

----If this request will not fit in the buffer then flush the buffer.

        Last_Byte := Display.Output.Used + Request_Size;  
        if Last_Byte > Display.Output.Data'Last then  
            Internal_X_Flush_Display (Display);  
            Last_Byte := Request_Size;  
        end if;

----Put the data into the buffer.

        To_Raw  
           (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), Req);  
        Display.Output.Used := Last_Byte;  
        begin  
            Display.Request := Display.Request + 1;  
        exception  
            when Constraint_Error =>  
                Display.Request := (Display.Request - 16#7F00_0000#) + 1;  
                Display.Last_Request_Read :=  
                   Display.Last_Request_Read - 16#7F00_0000#;  
        end;

    end Put_Request;

--\x0c
    procedure Put_Request_Extra (Display : X_Display;  
                                 Req     : Request;  
                                 Extra   : S_Natural) is
------------------------------------------------------------------------------
-- For Discrete and ordinary Private types.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Request         - this is the type of data that needs to be sent
--  Request_Size    - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  Req             - the request to send
--  Extra           - We are making a request to the server and we need the
--                    buffer space for this Request object plus we will need
--                    Extra bytes in the same buffer for data that follows
--                    and is part of the request.
------------------------------------------------------------------------------
        Extra_Bytes : X_Raw_Data_Index :=  
           X_Raw_Data_Index ((Extra + 3) / 4 * 4);  
        Last_Byte   : X_Raw_Data_Index;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

        if Request_Size rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        end if;

----If there is a request in the Display.Last_Req buffer then he must be flushed
--  before we can be placed.

        if Display.Last_Request.Kind /= Invalid_Request then  
            Internal_X_Flush_Last_Request (Display);  
        end if;

----If this request will not fit in the buffer then flush the buffer.

        Last_Byte := Display.Output.Used + Request_Size;  
        if Last_Byte + Extra_Bytes > Display.Output.Data'Last then  
            Internal_X_Flush_Display (Display);  
            Last_Byte := Request_Size;  
        end if;

----Put the data into the buffer.  The Extra data is placed later.

        To_Raw  
           (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), Req);  
        Display.Output.Used := Last_Byte;  
        begin  
            Display.Request := Display.Request + 1;  
        exception  
            when Constraint_Error =>  
                Display.Request := (Display.Request - 16#7F00_0000#) + 1;  
                Display.Last_Request_Read :=  
                   Display.Last_Request_Read - 16#7F00_0000#;  
        end;

    end Put_Request_Extra;

--\x0c
    procedure Put_Data_Private (Display : X_Display;  
                                D       : Original) is
------------------------------------------------------------------------------
-- For Discrete and ordinary Private types.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Original_Size   - all X protocol requests are 32 bytes long, this value
--                    corresponds to the number of X_Raw_Data items; always
--                    a multiple of 4 bytes.
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Last_Byte : X_Raw_Data_Index;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

        if Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        end if;

----If this request will fit into the buffer (usual case) then just place it
--  there.

        Last_Byte := Display.Output.Used + Original_Size;  
        if Last_Byte <= Display.Output.Data'Last then  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);

----This request will not fit in the buffer; flush the buffer.

        else  
            Internal_X_Flush_Display (Display);

----If this request will fit into the buffer now (usual case) then just do that.

            if Original_Size <= Display.Output.Data'Last then  
                Last_Byte := Original_Size;  
                To_Raw (Display.Output.Data (1 .. Last_Byte), D);

----The caller is shipping something very large.  Allocate some heap to use
--  as a buffer (we don't want to rely upon the stack being large enough; there
--  is a Storage_Error exception but there is no Stack_Overflow exception).

            else  
                declare  
                    Raw  : X_Raw_Data_List;  
                    Rawi : X_Raw_Data_Index := 1;  
                begin

----Convert the data into Raw form and put it out a bit at a time.

                    Raw := new X_Raw_Data_Array (1 .. Original_Size);  
                    To_Raw (Raw.all, D);  
                    for I in reverse  
                       1 .. Originl_Size / Display.Output.Data'Last loop  
                        Display.Output.Data :=  
                           Raw (Rawi .. Rawi - 1 + Display.Output.Data'Last);  
                        Display.Output.Used := Display.Output.Data'Last;  
                        Internal_X_Flush_Display (Display);  
                        Rawi := Rawi + Display.Output.Data'Last;  
                    end loop;

----Put out the last piece of data and return.

                    Last_Byte := Original_Size - Rawi + 1;  
                    Display.Output.Data (1 .. Last_Byte) :=  
                       Raw (Rawi .. Original_Size);  
                    Free_X_Raw_Data_List (Raw);  
                end;  
            end if;  
        end if;  
        Display.Output.Used := Last_Byte;

    end Put_Data_Private;

--\x0c
    procedure Put_Data_Private_Unaligned (Display : X_Display; D : Original) is
------------------------------------------------------------------------------
-- For Discrete and ordinary Private types.
--
-- Put data into the buffer going to a particular display.  This is only used
-- for those portions of some requests where we must create the requests
-- piecemeal out of pieces that are not multiples of 4-bytes in length.
-- If the data does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Last_Byte : X_Raw_Data_Index;  
        Unal      : X_Raw_Data_Array (1 .. 4);  
        Unali     : X_Raw_Data_Index;  
    begin

----If our caller is following the rules then the space required for this data
--  was "allocated" (allowed for) by a call on Put_Request_Extra.  Just stuff
--  the data into the buffer.  Of course, the buffer may be smaller than the
--  total request...

----If this request will fit into the buffer (usual case) then just place it
--  there.

        if Original_Size <= Display.Output.Data'Last - Display.Output.Used then  
            Last_Byte := Display.Output.Used + X_Raw_Data_Index (Original_Size);  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----This request will not fit in the buffer; flush the buffer.  Only flush
--  a multiple of 4 bytes.

        Unali               := Display.Output.Used rem 4;  
        Display.Output.Used := Display.Output.Used - Unali;  
        Unal (1 .. Unali)   := Display.Output.Data  
                                  (Display.Output.Used + 1 ..  
                                      Display.Output.Used + Unali);  
        Internal_X_Flush_Display (Display);

----If the request will fit into the buffer now (usual case) then just do that.

        Last_Byte := Unali + X_Raw_Data_Index (Original_Size);  
        if Last_Byte <= Display.Output.Data'Last then  
            Display.Output.Data (1 .. Unali) := Unal (1 .. Unali);  
            To_Raw (Display.Output.Data (Unali + 1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----The caller is shipping something very large.  Allocate some heap to use
--  as a buffer (we don't want to rely upon the stack being large enough; there
--  is a Storage_Error exception but there is no Stack_Overflow exception).
--  Note: We cannot ship something whose Original_Size > X_Raw_Data_Index'Last.
--  We can expect that to be at lease 32*1024 bytes so we won't worry about it
--  until it bites us.  A workaround for the caller would be to convert to
--  a u_char_array first and then transmit that.

        declare  
            Raw  : X_Raw_Data_List;  
            Rawi : X_Raw_Data_Index := 1;  
        begin

----Convert the data into Raw form and put it out a bit at a time.

            Raw              := new X_Raw_Data_Array (1 .. Last_Byte);  
            Raw (1 .. Unali) := Unal (1 .. Unali);  
            To_Raw (Raw (Unali + 1 .. Last_Byte), D);  
            for I in reverse 1 .. Last_Byte / Display.Output.Data'Last loop  
                Display.Output.Data :=  
                   Raw (Rawi .. Rawi + Display.Output.Data'Last - 1);  
                Display.Output.Used := Display.Output.Data'Last;  
                Internal_X_Flush_Display (Display);  
                Rawi := Rawi + Display.Output.Data'Last;  
            end loop;

----Put out the last piece of data and return.

            Last_Byte := Last_Byte - Rawi + 1;  
            Display.Output.Data (1 .. Last_Byte) := Raw (Rawi .. Raw'Last);  
            Display.Output.Used := Last_Byte;  
            Free_X_Raw_Data_List (Raw);  
            return;

        exception  
            when others =>  
                Free_X_Raw_Data_List (Raw);  
                raise;  
        end;

    end Put_Data_Private_Unaligned;

--\x0c
    procedure Put_Large_Data_1d (Display : X_Display;  
                                 D       : Original_Array) is
------------------------------------------------------------------------------
-- For one-dimensional array types where the element type is "large".  A
-- "large" type is any type whose 'Size is a multiple of 32 bits.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*32.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  Index           - this is the index type for the array type
--  Original_Array  - this is the array type
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Total_Size : S_Natural := S_Natural (Original_Size) * D'Length;  
        Last_Byte  : X_Raw_Data_Index;  
        Next       : S_Long;  
        Incr       : S_Long;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

--/ if DEBUG then

        if Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Total_Size = 0 then  
            return;  
        end if;

--/ end if;

----If this request will fit into the buffer (usual case) then just place it
--  there.

        if S_Long (Display.Output.Data'Last - Display.Output.Used) >=  
           Total_Size then  
            Last_Byte := Display.Output.Used + X_Raw_Data_Index (Total_Size);  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----This request will not fit in the buffer; flush the buffer.

        Internal_X_Flush_Display (Display);

----If this request will fit into the buffer now (usual case) then just do that.

        if Total_Size <= S_Long (Display.Output.Data'Last) then  
            Last_Byte := X_Raw_Data_Index (Total_Size);  
            To_Raw (Display.Output.Data (1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----The caller is shipping something very large.  Put out the array elements
--  a few at a time.

        Next      := S_Long (D'First);  
        Incr      := S_Long (Display.Input.Data'Last / Original_Size);  
        Last_Byte := Original_Size * X_Raw_Data_Index (Incr);

----First we write them as complete Display.Input.Data buffer-fulls at a time.

        while S_Long (D'Last) - Next >= Incr loop  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. Index (Next + Incr - 1)));  
            Display.Output.Used := Last_Byte;  
            Internal_X_Flush_Display (Display);  
            Next := Next + Incr;  
        end loop;

----Finally we write whatever is left to write.

        if Next <= S_Long (D'Last) then  
            Last_Byte := Original_Size * X_Raw_Data_Index  
                                            (S_Long (D'Last) - Next + 1);  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. D'Last));  
            Display.Output.Used := Last_Byte;  
        end if;

    end Put_Large_Data_1d;

--\x0c
    procedure Put_Small_Data_1d (Display : X_Display;  
                                 D       : Original_Array) is
------------------------------------------------------------------------------
-- For one-dimensional array types where the element type is "small".  A
-- "small" type is any type whose 'Size is less than 32 bits.  This is
-- expected to be used for 8 and 16 bit data types.  Other sizes of
-- data will not probably work properly.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*32.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  Index           - this is the index type for the array type
--  Original_Array  - this is the array type
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Total_Size : S_Natural := S_Natural (Original_Size) * D'Length;  
        Last_Byte  : X_Raw_Data_Index;  
        Next       : S_Long;  
        Incr       : S_Long;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

        if Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Total_Size = 0 then  
            return;  
        end if;

----If this request will fit into the buffer (usual case) then just place it
--  there.

        if S_Long (Display.Output.Data'Last - Display.Output.Used) >=  
           Total_Size then  
            Last_Byte := Display.Output.Used + X_Raw_Data_Index (Total_Size);  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);  
            goto Modulo_4;  
        end if;

----This request will not fit in the buffer; flush the buffer.

        Internal_X_Flush_Display (Display);

----If this request will fit into the buffer now (usual case) then just do that.

        if Total_Size <= S_Long (Display.Output.Data'Last) then  
            Last_Byte := X_Raw_Data_Index (Total_Size);  
            To_Raw (Display.Output.Data (1 .. Last_Byte), D);  
            goto Modulo_4;  
        end if;

----The caller is shipping something very large.  Put out the array elements
--  a few at a time.

        Next      := S_Long (D'First);  
        Incr      := S_Long (Display.Input.Data'Last / Original_Size);  
        Last_Byte := Original_Size * X_Raw_Data_Index (Incr);

----First we write them as complete Display.Input.Data buffer-fulls at a time.

        while S_Long (D'Last) - Next >= Incr loop  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. Index (Next + Incr - 1)));  
            Display.Output.Used := Last_Byte;  
            Internal_X_Flush_Display (Display);  
            Next := Next + Incr;  
        end loop;

----Finally we write whatever is left to write.

        if Next <= S_Long (D'Last) then  
            Last_Byte := Original_Size * X_Raw_Data_Index  
                                            (S_Long (D'Last) - Next + 1);  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. D'Last));  
        else  
            Last_Byte := 0;  
        end if;

----Pad the output buffer to a modulo-4 boundary.

        <<Modulo_4>> null;  
        case Last_Byte rem 4 is  
            when 1 =>  
                Last_Byte := Last_Byte + 3;  
                Display.Output.Data (Last_Byte - 2) := 0;  
                Display.Output.Data (Last_Byte - 1) := 0;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when 2 =>  
                Last_Byte := Last_Byte + 2;  
                Display.Output.Data (Last_Byte - 1) := 0;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when 3 =>  
                Last_Byte := Last_Byte + 1;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when others =>  
                null;  
        end case;  
        Display.Output.Used := Last_Byte;

    end Put_Small_Data_1d;

--\x0c
    procedure Put_Small_Data_1d_Unaligned (Display : X_Display;  
                                           D       : Original_Array) is
------------------------------------------------------------------------------
-- For one-dimensional array types where the element type is "small".  A
-- "small" type is any type whose 'Size is less than 32 bits.  This is
-- expected to be used for 8 and 16 bit data types.  Other sizes of
-- data will not probably work properly.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*32.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  This routine does
-- not preserve that 4-byte alignment requirement.  Callers of this routine
-- are required to make their request a multiple of 4-bytes when they are
-- finished.  If the data does not fit into the buffer then the buffer is
-- flushed first.  Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Index           - this is the index type for the array type
--  Original_Array  - this is the array type
--  To_Raw          - converts the data to X_Raw_Data
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items required
--                    to represent a single Original item
--  Less_Than_32    - causes Constraint_Error if Original is of an inappropriate
--                    'Size
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Total_Size : S_Natural := S_Natural (Original_Size) * D'Length;  
        Last_Byte  : X_Raw_Data_Index;  
        Next       : S_Long;  
        Incr       : S_Long;  
    begin

----If this request will fit into the buffer (usual case) then just place it
--  there.

        if Total_Size = 0 then  
            return;  
        elsif S_Long (Display.Output.Data'Last - Display.Output.Used) >=  
              Total_Size then  
            Last_Byte := Display.Output.Used + X_Raw_Data_Index (Total_Size);  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----This request will not fit in the buffer; flush the buffer.

        Internal_X_Flush_Display (Display);

----If this request will fit into the buffer now (usual case) then just do that.

        if Total_Size <= S_Long (Display.Output.Data'Last) then  
            Last_Byte := X_Raw_Data_Index (Total_Size);  
            To_Raw (Display.Output.Data (1 .. Last_Byte), D);  
            Display.Output.Used := Last_Byte;  
            return;  
        end if;

----The caller is shipping something very large.  Put out the array elements
--  a few at a time.  Note: This only works if Original_Size is not larger
--  than X_Raw_Data_Index'Last.  In a case like that the caller can always
--  convert to a U_Char_Array and then transmit that.

        Next      := S_Long (D'First);  
        Incr      := S_Long (Display.Input.Data'Last / Original_Size);  
        Last_Byte := Original_Size * X_Raw_Data_Index (Incr);

----First we write them as complete Display.Input.Data buffer-fulls at a time.

        while S_Long (D'Last) - Next >= Incr loop  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. Index (Next + Incr - 1)));  
            Display.Output.Used := Last_Byte;  
            Internal_X_Flush_Display (Display);  
            Next := Next + Incr;  
        end loop;

----Finally we write whatever is left to write.

        if Next <= S_Long (D'Last) then  
            Last_Byte := Original_Size * X_Raw_Data_Index  
                                            (S_Long (D'Last) - Next + 1);  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. D'Last));  
        else  
            Last_Byte := 0;  
        end if;  
        Display.Output.Used := Last_Byte;

    end Put_Small_Data_1d_Unaligned;

--\x0c
    procedure Put_Data_2d (Display : X_Display;  
                           D       : Original_Array) is
------------------------------------------------------------------------------
-- For two-dimensional array types where the element type is 8, 16, or N*32
-- bits in length.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*8.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items
--  Index1          - this is the first index type for the array type
--  Index2          - this is the second index type for the array type
--  Original_Array  - this is the array type
--  To_Raw          - converts the data to X_Raw_Data
--  Display         - display to receive the request
--  D               - the data to send
------------------------------------------------------------------------------
        Last_Byte  : X_Raw_Data_Index;  
        Total_Size : S_Long : S_Long (Original_Size) *  
                                  D'Length (1) * D'Length (2);  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

        if Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Total_Size = 0 then  
            return;  
        end if;

----If this request will fit into the buffer (usual case) then just place it
--  there.

        if Total_Size <= S_Long (Display.Output.Data'Last -  
                                 Display.Output.Used) then  
            Last_Byte := Display.Output.Used + X_Raw_Data_Index (Total_Size);  
            To_Raw  
               (Display.Output.Data (Display.Output.Used + 1 .. Last_Byte), D);  
            goto Modulo_4;  
        end if;

----This request will not fit in the buffer; flush the buffer.

        Internal_X_Flush_Display (Display);
----If this request will fit into the buffer now (usual case) then just do that.

        if Total_Size <= S_Long (Display.Output.Data'Last) then  
            Last_Byte := X_Raw_Data_Index (Total_Size);  
            To_Raw (Display.Output.Data (1 .. Last_Byte), D);  
            goto Modulo_4;  
        end if;

----The caller is shipping something very large.  Put out the array elements
--  one at a time; you can't slice a 2-D array in Ada.

        declare  
            Raw      : X_Raw_Data_Array (1 .. Original_Size);  
            Raw_Tmp  : X_Raw_Data_Array (1 .. 3);  
            Raw_Tmpi : X_Raw_Data_Index;  
        begin  
            Last_Byte := 0;  
            for I in D'Range (1) loop  
                for J in D'Range (2) loop  
                    To_Raw (Raw, D (I, J));  
                    if Display.Output.Data'Last - Last_Byte < Original_Size then

----When we must flush the buffer, make sure we flush multiples of 4 bytes.

                        Raw_Tmpi                := Last_Byte rem 4;  
                        Display.Output.Used     := Last_Byte - Raw_Tmpi;  
                        Raw_Tmp (1 .. Raw_Tmpi) :=  
                           Display.Output.Data  
                              (Display.Output.Used + 1 ..  
                                  Display.Output.Used + Raw_Tmpi);  
                        Internal_X_Flush_Display (Display);  
                        Display.Output.Data (1 .. Raw_Tmpi) :=  
                           Raw_Tmp (1 .. Raw_Tmpi);  
                        Last_Byte := Raw_Tmpi;  
                    end if;

----Put the next element into the buffer.

                    Display.Output.Data  
                       (Last_Byte + 1 .. Last_Byte + Original_Size) := Raw;  
                    Last_Byte := Last_Byte + Original_Size;  
                end loop;  
            end loop;  
        end;

----Pad the output buffer to a modulo-4 boundary.

        <<Modulo_4>> null;  
        case Last_Byte rem 4 is  
            when 1 =>  
                Last_Byte := Last_Byte + 3;  
                Display.Output.Data (Last_Byte - 2) := 0;  
                Display.Output.Data (Last_Byte - 1) := 0;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when 2 =>  
                Last_Byte := Last_Byte + 2;  
                Display.Output.Data (Last_Byte - 1) := 0;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when 3 =>  
                Last_Byte := Last_Byte + 1;  
                Display.Output.Data (Last_Byte - 0) := 0;  
            when others =>  
                null;  
        end case;  
        Display.Output.Used := Last_Byte;

    end Put_Data_2d;

--\x0c
    procedure Reserve_Request_Large_1d (Display     :     X_Display;  
                                        Max_Spaces  :     S_Natural;
                                        Req         :     Request;  
                                        D           :     Original_Array;
                                        Reservation : out X_Raw_Data_Index;  
                                        Spaces_Left : out S_Natural) is
------------------------------------------------------------------------------
-- For Poly X_Request's with one dimensional array arguments only.
-- Do not use this for ordinary private types or for arrays of "small" types.
--
-- Called in an attempt to a) reserve space for a request record and b) to
-- begin placing the array data into the output buffer.  Allocates space in
-- the Display.Output buffer for the request and then allocates space in the
-- buffer for the array data.  The array data is copied into the buffer.  The
-- request is not copied.  Use the Place_Reserved_Request generic to do that.
-- This is for the use of the various Poly requests where adjacent requests may
-- be joined together to form a smaller number of longer requests.
--
-- Returns the reserved position for the request and the maximum number of
-- further array elements that can be placed into the buffer.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*32.
--
-- Put data into the buffer going to a particular display.  All X requests
-- are always a multiple of 32 bits (4 bytes) in length.  If the data
-- does not fit into the buffer then the buffer is flushed first.
-- Display.Last_Req is not set; that is up to the caller.
--  Original        - this is the type of data that needs to be sent
--  Index           - this is the index type for the array type
--  Original_Array  - this is the array type
--  Request         - this is the type of data that needs to be sent
--  To_Raw          - converts the data to X_Raw_Data
--  To_Raw          - converts the data to X_Raw_Data
--  Request_Size    - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items required
--                    to represent the Request
--  Multiple_Of_32  - causes Constraint_Error if Request is of an inappropriate
--                    'Size
--  Original_Size   - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items required
--                    to represent a single Original item
--  Original_Multiple_Of_32  - causes Constraint_Error if Original is of an
--                    inappropriate 'Size
--  Display         - display to receive the request
--  Req             - the X_Request to send
------------------------------------------------------------------------------
        Total_Size : S_Natural := S_Natural (Original_Size) * D'Length;  
        Last_Byte  : X_Raw_Data_Index;  
        Next       : S_Long;  
        Incr       : S_Long;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.
--  We only reserve requests that fit into the buffer.

--/ if DEBUG then

        if Request_Size rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Max_Spaces <= D'Length then
            raise X_Library_Confusion;
        end if;

--/ end if;

----If there is a request in the Display.Last_Req buffer then he must be flushed
--  before we can be placed.

        if Display.Last_Request.Kind /= Invalid_Request then  
            Internal_X_Flush_Last_Request (Display);  
        end if;

----If this request will fit into the buffer then shove it in and return.

        if Total_Size <= S_Long (Display.Output.Data'Last  
                                  - Display.Output.Used  
                                  - Request_Size) then

----Calculate the last byte that will be used.  Then calculate the number
--  of spaces that remain in the buffer for new array elements.

            Last_Byte   := Display.Output.Used + Request_Size +
                              X_Raw_Data_Index (Total_Size);  
            Incr        := S_Long (Display.Output.Data'Last -
                                   Last_Byte / Original_Size);
            Incr        := Min (Max_Spaces - D'Length, Incr);
            Spaces_Left := Incr;

----If there are no more spaces left then shove the request into the buffer.

            if Incr = 0 then
                To_Raw
                   (Display.Output.Data (Display.Output.Used + 1 ..
                                            Display.Output.Used + Request_Size),  
                    Req);
                Reservation := 0;
            else
                Reservation := Display.Output.Used + 1;
            end if;

----Copy the array into the buffer.

            To_Raw (Display.Output.Data  
                       (Display.Output.Used + Request_Size + 1 .. Last_Byte),  
                    D);  
            Display.Output.Used := Last_Byte;  
            return;
        end if;

----This request will not fit in the buffer space available; flush the buffer.

        Internal_X_Flush_Display (Display);

----If this request will fit into the buffer now (usual case) then just do that.

        if Total_Size <= S_Long (Display.Output.Data'Last - Request_Size) then

----Calculate the last byte that will be used.  Then calculate the number
--  of spaces that remain in the buffer for new array elements.

            Last_Byte   := Request_Size + X_Raw_Data_Index (Total_Size);  
            Incr        := S_Long (Display.Output.Data'Last -
                                   Last_Byte / Original_Size);
            Incr        := Min (Max_Spaces - D'Length, Incr);
            Spaces_Left := Incr;

----If there are no more spaces left then shove the request into the buffer.

            if Incr = 0 then
                To_Raw (Display.Output.Data (1 .. Request_Size),  
                        Req);
                Reservation := 0;
            else
                Reservation := Display.Output.Used + 1;
            end if;

----Copy the array into the buffer.

            To_Raw (Display.Output.Data (Request_Size + 1 .. Last_Byte),  
                    D);  
            Display.Output.Used := Last_Byte;  
            return;
        end if;

----The caller is shipping something very large.  Put out the request and we
--  will follow it with the array elements.

        Reservation := 0;
        Spaces_Left := 0;
        To_Raw (Display.Output.Data (1 .. Request_Size),  
                Req);

----Put out the array elements a few at a time.

        Next      := S_Long (D'First);  
        Incr      := S_Long ((Display.Input.Data'Last - Request_Size) /  
                             Original_Size);  
        Last_Byte := Original_Size * X_Raw_Data_Index (Incr);

----Put out the first few elements.

        To_Raw (Display.Output.Data (Request_Size + 1 .. Last_Byte),  
                D (Index (Next) .. Index (Next + Incr - 1)));  
        Display.Output.Used := Last_Byte;  
        Internal_X_Flush_Display (Display);  
        Next := Next + Incr;

----Prepare to put out full size chunks.

        Incr      := S_Long (Display.Input.Data'Last / Original_Size);
        Last_Byte := Original_Size * X_Raw_Data_Index (Incr);

----First we write them as complete Display.Input.Data buffer-fulls at a time.

        while S_Long (D'Last) - Next >= Incr loop  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. Index (Next + Incr - 1)));  
            Display.Output.Used := Last_Byte;  
            Internal_X_Flush_Display (Display);  
            Next := Next + Incr;  
        end loop;

----Finally we write whatever is left to write.

        if Next <= S_Long (D'Last) then  
            Last_Byte := Original_Size * X_Raw_Data_Index  
                                            (S_Long (D'Last) - Next + 1);  
            To_Raw (Display.Output.Data (1 .. Last_Byte),  
                    D (Index (Next) .. D'Last));  
            Display.Output.Used := Last_Byte;  
        end if;

    end Reserve_Request_Large_1d;

--\x0c
    procedure Place_Reserved_Request (Display     : X_Display;  
                                      Req         : Request;  
                                      Reservation : X_Raw_Data_Index) is
------------------------------------------------------------------------------
-- For X_Request's only.  Do not use this for ordinary private types.
--
-- If you get a Constraint_Error when elaborating this generic then you have
-- tried to instantiate it with a type whose 'Size is not N*32.
--
-- Put data into a reserved place within the buffer going to a particular
-- display.  All X requests are always a multiple of 32 bits (4 bytes) in
-- length.  Display.Last_Req is not set; that is up to the caller.
--  Request         - this is the type of data that needs to be sent
--  To_Raw          - converts the data to X_Raw_Data
--  Request_Size    - all X protocol requests are 4*N bytes long, this value
--                    corresponds to the number of X_Raw_Data items required
--                    to represent the Request
--  Multiple_Of_32  - causes Constraint_Error if Request is of an inappropriate
--                    'Size
--  Display         - display to receive the request
--  Req             - the X_Request to send
------------------------------------------------------------------------------
        Last_Byte : X_Raw_Data_Index;  
    begin

----If this fails then the previous request left the buffer on a non-word
--  boundary.  That would mean that we are harboring a bug somewhere.

--/ if DEBUG then

        if Request_Size rem 4 /= 0 then  
            raise X_Library_Confusion;  
        elsif Display.Output.Used rem 4 /= 0 then  
            raise X_Library_Confusion;  
        end if;

--/ end if;

----Put the data into the buffer.

        To_Raw  
           (Display.Output.Data (Reservation .. Reservation + Request_Size - 1),  
            Req);  
        begin  
            Display.Request := Display.Request + 1;  
        exception  
            when Constraint_Error =>  
                Display.Request := (Display.Request - 16#7F00_0000#) + 1;  
                Display.Last_Request_Read :=  
                   Display.Last_Request_Read - 16#7F00_0000#;  
        end;

    end Place_Reserved_Request;

--\x0c
end Xlbmp_Put;  

E3 Meta Data

    nblk1=41
    nid=0
    hdr6=82
        [0x00] rec0=21 rec1=00 rec2=01 rec3=068
        [0x01] rec0=11 rec1=00 rec2=02 rec3=06a
        [0x02] rec0=15 rec1=00 rec2=03 rec3=044
        [0x03] rec0=1d rec1=00 rec2=04 rec3=06a
        [0x04] rec0=16 rec1=00 rec2=05 rec3=074
        [0x05] rec0=14 rec1=00 rec2=06 rec3=00c
        [0x06] rec0=00 rec1=00 rec2=41 rec3=004
        [0x07] rec0=1b rec1=00 rec2=07 rec3=012
        [0x08] rec0=14 rec1=00 rec2=08 rec3=080
        [0x09] rec0=1a rec1=00 rec2=09 rec3=012
        [0x0a] rec0=18 rec1=00 rec2=0a rec3=044
        [0x0b] rec0=00 rec1=00 rec2=40 rec3=002
        [0x0c] rec0=17 rec1=00 rec2=0b rec3=094
        [0x0d] rec0=12 rec1=00 rec2=0c rec3=004
        [0x0e] rec0=00 rec1=00 rec2=3f rec3=00e
        [0x0f] rec0=17 rec1=00 rec2=0d rec3=05e
        [0x10] rec0=01 rec1=00 rec2=3e rec3=00c
        [0x11] rec0=12 rec1=00 rec2=3d rec3=084
        [0x12] rec0=00 rec1=00 rec2=0e rec3=00c
        [0x13] rec0=18 rec1=00 rec2=0f rec3=03c
        [0x14] rec0=00 rec1=00 rec2=3c rec3=01c
        [0x15] rec0=19 rec1=00 rec2=10 rec3=050
        [0x16] rec0=13 rec1=00 rec2=11 rec3=01e
        [0x17] rec0=00 rec1=00 rec2=3b rec3=01a
        [0x18] rec0=1e rec1=00 rec2=12 rec3=082
        [0x19] rec0=1a rec1=00 rec2=13 rec3=02a
        [0x1a] rec0=00 rec1=00 rec2=3a rec3=014
        [0x1b] rec0=16 rec1=00 rec2=14 rec3=02a
        [0x1c] rec0=11 rec1=00 rec2=15 rec3=012
        [0x1d] rec0=02 rec1=00 rec2=39 rec3=010
        [0x1e] rec0=1a rec1=00 rec2=16 rec3=06a
        [0x1f] rec0=1a rec1=00 rec2=17 rec3=00a
        [0x20] rec0=00 rec1=00 rec2=38 rec3=014
        [0x21] rec0=17 rec1=00 rec2=18 rec3=06a
        [0x22] rec0=16 rec1=00 rec2=19 rec3=064
        [0x23] rec0=10 rec1=00 rec2=1a rec3=01a
        [0x24] rec0=1b rec1=00 rec2=1b rec3=014
        [0x25] rec0=00 rec1=00 rec2=37 rec3=01a
        [0x26] rec0=15 rec1=00 rec2=1c rec3=02c
        [0x27] rec0=00 rec1=00 rec2=36 rec3=014
        [0x28] rec0=1a rec1=00 rec2=1d rec3=05e
        [0x29] rec0=11 rec1=00 rec2=1e rec3=03a
        [0x2a] rec0=00 rec1=00 rec2=35 rec3=002
        [0x2b] rec0=1b rec1=00 rec2=1f rec3=000
        [0x2c] rec0=19 rec1=00 rec2=20 rec3=010
        [0x2d] rec0=00 rec1=00 rec2=34 rec3=00c
        [0x2e] rec0=17 rec1=00 rec2=21 rec3=010
        [0x2f] rec0=00 rec1=00 rec2=33 rec3=026
        [0x30] rec0=19 rec1=00 rec2=22 rec3=014
        [0x31] rec0=0f rec1=00 rec2=23 rec3=018
        [0x32] rec0=11 rec1=00 rec2=24 rec3=014
        [0x33] rec0=12 rec1=00 rec2=25 rec3=082
        [0x34] rec0=01 rec1=00 rec2=32 rec3=004
        [0x35] rec0=1c rec1=00 rec2=26 rec3=048
        [0x36] rec0=19 rec1=00 rec2=27 rec3=004
        [0x37] rec0=00 rec1=00 rec2=31 rec3=032
        [0x38] rec0=19 rec1=00 rec2=28 rec3=006
        [0x39] rec0=00 rec1=00 rec2=30 rec3=02e
        [0x3a] rec0=1d rec1=00 rec2=29 rec3=052
        [0x3b] rec0=00 rec1=00 rec2=2f rec3=01e
        [0x3c] rec0=1b rec1=00 rec2=2a rec3=036
        [0x3d] rec0=00 rec1=00 rec2=2e rec3=00a
        [0x3e] rec0=15 rec1=00 rec2=2b rec3=056
        [0x3f] rec0=15 rec1=00 rec2=2c rec3=018
        [0x40] rec0=19 rec1=00 rec2=2d rec3=000
    tail 0x21700652a819780775c97 0x42a00088462063203