|
|
DataMuseum.dkPresents historical artifacts from the history of: Rational R1000/400 Tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Rational R1000/400 Tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: B T
Length: 41197 (0xa0ed)
Types: TextFile
Names: »B«
└─⟦85b835f43⟧ Bits:30000549 8mm tape, Rational 1000, Xlib rev 6.00
└─⟦0c20f784e⟧ »DATA«
└─⟦1abbe589f⟧
└─⟦059497ac5⟧
└─⟦this⟧
with Xlbt_Arithmetic;
use Xlbt_Arithmetic;
with Xlbt_Basic;
use Xlbt_Basic;
with Xlbt_Display2;
use Xlbt_Display2;
with Xlbt_Error3;
use Xlbt_Error3;
with Xlbt_Event3;
use Xlbt_Event3;
with Xlbt_Exceptions;
use Xlbt_Exceptions;
with Xlbt_Extension3;
use Xlbt_Extension3;
with Xlbt_Proc_Var;
use Xlbt_Proc_Var;
with Xlbt_Reply;
use Xlbt_Reply;
with Xlbt_Request;
use Xlbt_Request;
with Xlbt_String;
use Xlbt_String;
with Xlbp_Error;
use Xlbp_Error;
with Xlbp_Proc_Var;
use Xlbp_Proc_Var;
with Xlbit_Library3;
use Xlbit_Library3;
with Xlbip_Internal;
use Xlbip_Internal;
with Xlbip_Wire_Converters;
use Xlbip_Wire_Converters;
with Xlbmt_Network_Types;
use Xlbmt_Network_Types;
with Xlbmp_Internal;
use Xlbmp_Internal;
with Xlbmp_Network_Interface;
use Xlbmp_Network_Interface;
package body Xlbmp_Get is
------------------------------------------------------------------------------
-- X Library X Server Get Routines
--
-- Xlbmp_Get - Receive info from 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.
------------------------------------------------------------------------------
--\f
------------------------------------------------------------------------------
-- Length of any Event/Error that we can receive from the X server. They are
-- all the same size.
------------------------------------------------------------------------------
Event_Length : constant X_Raw_Data_Index := X_Button_Event'Size / 8;
--\f
procedure Get_Reply_Generic (Display : X_Display;
Code : X_Request_Code;
Reply : out Reply_Record;
Extra : S_Natural;
Discard : Boolean;
Status : out X_Status) is
------------------------------------------------------------------------------
-- Display - the display to read from
-- Code - the code for the request indicates the format of the reply
-- Reply - where to put the reply; if one is received
-- Extra - many replies receive extra data; we require at least this
-- much extra to be present or we regard it as an I/O error
-- Discard - TRUE to discard any extra extra data that may appear with the
-- reply
-- Status - Failed if we got an Error instead of a Reply
--
-- Read a reply to a request out of the network connection. You should only
-- request multiples of 4 bytes.
--
-- The Wire_To_Reply procedure has these arguments.
--
-- Code - Specifies the X_Request_Code of the reply
-- Raw - Specifies the raw 32-bytes of data representing the reply
-- Send_Event - Specifies TRUE if this reply was not sent by the server
-- Reply - Receives the converted reply record
-- Length - Specifies the number of additions words (groups of 4 bytes)
-- that make up the rest of the reply; including all variable
-- length data.
------------------------------------------------------------------------------
Rec_Next : X_Raw_Data_Index := 1;
Rec_Len : X_Raw_Data_Index := 0;
New_Next_M1 : X_Raw_Data_Index;
Copy_Amt : S_Natural;
Client_Sent : Boolean;
Sequence_No : U_Short;
Event_Code : X_Event_Code;
Er : X_Error_Contents;
Ret : Boolean := False;
Ret_Code : X_Status;
Ev : X_Event;
Len : S_Natural;
Ext : X_Extension;
Queue_It : X_Status;
----Pull out the serial number now, so that (currently illegal) requests
-- generated by an error handler don't confuse us.
Cur_Request : S_Long := Display.Request;
begin
----If we have gotten an I/O error then don't do more I/O.
if Display.Flags (Xlib_Display_Io_Error) then
return;
end if;
----Flush any pending output (such as the request whose reply we desire).
Internal_X_Flush_Display (Display);
----If there is any pending input in Display.Input then put that into our buffer
-- and add new information to it.
if Display.Input.Used < Display.Input.Data'Last then
if Display.Input.Used > 0 then
Receive_Maybe
(Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data
(Display.Input.Used + 1 .. Display.Input.Data'Last),
Rec_Len);
Display.Input.Used := Display.Input.Used + Rec_Len;
else
Receive_Must
(Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Event_Length),
Rec_Len);
Display.Input.Used := Rec_Len;
end if;
----See if our Receive had an error. Timed_Out is fine.
if Display.Network.Fd_Error /= Ok and then
Display.Network.Fd_Error /= Timed_Out then
Report_Io_Error (Display, "Receive");
end if;
end if;
----Loop until we've received a reply and we've used up all of the data in
-- our buffer that we can use up.
loop
----We can assume here that all Event/Error packets are the same size. However
-- we know that Reply packets are of differing lengths. This is
-- currently true. X11.V4 3/6/90. Calculate the end of the record.
--/ if Raw_Is_Unsigned then
if Display.Input.Data (Rec_Next) > 127 then
Client_Sent := True;
Event_Code := X_Event_Code'Val
(Display.Input.Data (Rec_Next) - 128);
else
Client_Sent := False;
Event_Code := X_Event_Code'Val (Display.Input.Data (Rec_Next));
end if;
--/ else
--// if Display.Input.Data (Rec_Next) < 0 then
--// Client_Sent := True;
--// Event_Code := X_Event_Code'Val
--// ((Display.Input.Data (Rec_Next) + 127) + 1);
--// else
--// Client_Sent := False;
--// Event_Code := X_Event_Code'Val (Display.Input.Data (Rec_Next));
--// end if;
--/ end if;
Sequence_No := U_Short (Display.Input.Data (Rec_Next + 2)) * 256 +
U_Short (Display.Input.Data (Rec_Next + 3));
Display.Input.Data (Rec_Next) := X_Event_Code'Pos (Event_Code);
if Event_Code = Reply_Event then
if Display.Reply_Size (Code) = 0 then
-- All replyable requests should have non-zero in there.
-- A zero value represents a bug; in us or in the server.
raise X_Library_Confusion;
end if;
New_Next_M1 := Rec_Next + Display.Reply_Size (Code) - 1;
else
New_Next_M1 := Rec_Next + Event_Length - 1;
end if;
----If there isn't enough data in the buffer to make up the next record then
-- we'll read in some more data. We watch to make sure that we don't overflow
-- the buffer.
if New_Next_M1 > Display.Input.Used then
if New_Next_M1 > Display.Input.Data'Last then
New_Next_M1 := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Rec_Next + 1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Rec_Next .. New_Next_M1);
Rec_Next := 1;
if Event_Code = Reply_Event then
New_Next_M1 := Display.Reply_Size (Code);
else
New_Next_M1 := Event_Length;
end if;
end if;
Receive_Maybe
(Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data
(Display.Input.Used + 1 .. Display.Input.Data'Last),
Rec_Len);
Display.Input.Used := Display.Input.Used + Rec_Len;
----If we timed out and there still isn't enough data to process then do a
-- receive of exactly the right amount of data and wait forever if we have to.
-- Check for errors as well.
if Display.Network.Fd_Error /= Ok and then
Display.Network.Fd_Error /= Timed_Out then
Report_Io_Error (Display, "Receive");
end if;
if New_Next_M1 > Display.Input.Used then
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data
(Display.Input.Used + 1 .. New_Next_M1),
Rec_Len);
Display.Input.Used := Display.Input.Used + Rec_Len;
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
end if;
end if;
----Take the next record and convert it appropriately.
case Event_Code is
----Error are converted and immediately reported except when they pertain to
-- the reply we were expecting. Do not call Display.X_Lib.Error on "no such
-- font", "can't allocate", and "can't grab" failures.
when Error_Event =>
Internal_Wire_To_Error
(Display,
Display.Input.Data (Rec_Next .. New_Next_M1),
Client_Sent,
Er);
----For each error type; see if the Sequence_Number is the same as the request
-- we just made. If so then see if we want to suppress this error.
if Er.Serial = Cur_Request then
case Er.Kind is
when Bad_Name =>
case Er.Nothing.Major_Opcode is
when Open_Font |
Lookup_Color |
Alloc_Named_Color =>
Status := Failed;
Rec_Next := Display.Input.Used;
Display.Input.Used :=
Display.Input.Used - New_Next_M1;
Display.Input.Data
(1 .. Display.Input.Used) :=
Display.Input.Data
(New_Next_M1 + 1 .. Rec_Next);
return;
when others =>
null;
end case;
when Bad_Alloc | Bad_Access =>
Status := Failed;
Rec_Next := Display.Input.Used;
Display.Input.Used :=
Display.Input.Used - New_Next_M1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data
(New_Next_M1 + 1 .. Rec_Next);
return;
when Bad_Font =>
if Er.Resource.Major_Opcode = Query_Font then
Status := Failed;
Rec_Next := Display.Input.Used;
Display.Input.Used :=
Display.Input.Used - New_Next_M1;
Display.Input.Data
(1 .. Display.Input.Used) :=
Display.Input.Data
(New_Next_M1 + 1 .. Rec_Next);
return;
end if;
when others =>
null;
end case;
----The error made it this far; this error pertains to this request so
-- see if some Extension wants to suppress it.
Ext := Display.Ext_Procs;
while Ext /= null loop
if Ext.Error /= None_X_Procedure_Variable then
Proc_Var_X_Error_Extension.Call
(Proc_Var_X_Error_Extension.To_Pv
(Ext.Error),
Display, Er, Ext.Codes, Ret_Code, Ret);
end if;
if Ret then
Status := Ret_Code;
Rec_Next := Display.Input.Used;
Display.Input.Used :=
Display.Input.Used - New_Next_M1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data
(New_Next_M1 + 1 .. Rec_Next);
return;
end if;
Ext := Ext.Next;
end loop;
Ret := True;
end if;
----An unsinkable error; report it and then return failure if it pertains to
-- the current request.
declare
Proc : X_Procedure_Variable;
begin
X_Lib.Get_Error (Display, Proc);
Proc_Var_X_Error_Function.Call
(Proc_Var_X_Error_Function.To_Pv (Proc),
Display, Er);
end;
if Er.Serial = Cur_Request then
Status := Failed;
Rec_Next := Display.Input.Used;
Display.Input.Used := Display.Input.Used - New_Next_M1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (New_Next_M1 + 1 .. Rec_Next);
return;
end if;
----We got a reply. It had better be the one we've been waiting for. Convert
-- the bytes into a real reply and compute the number of extra bytes sent.
when Reply_Event =>
if Sequence_No = U_Short (Cur_Request mod 16#1_0000#) then
Display.Last_Request_Read := Cur_Request;
else
Cur_Request := Internal_X_Set_Last_Request_Read
(Display, Event_Code, Sequence_No);
end if;
Wire_To_Reply (Code,
Display.Input.Data (Rec_Next .. New_Next_M1),
Client_Sent,
Reply,
Len);
----Len is in words, 4 bytes per word, add this to get the total length of the
-- server's reply.
Len := Len * 4
+ S_Natural (Event_Length)
- S_Natural (New_Next_M1 - Rec_Next + 1);
----Get rid of any extra data a) if there is some; b) he wanted that.
-- Otherwise we return and we assume that our caller will eat it later.
if Discard then
Copy_Amt := Len;
if Copy_Amt <= S_Natural (Display.Input.Used -
New_Next_M1) then
New_Next_M1 := New_Next_M1 +
X_Raw_Data_Index (Copy_Amt);
else
Copy_Amt := Copy_Amt -
S_Natural (Display.Input.Used -
New_Next_M1);
loop
if Copy_Amt >
S_Natural (Display.Input.Data'Last) then
Rec_Next := Display.Input.Data'Last;
else
Rec_Next := X_Raw_Data_Index (Copy_Amt);
end if;
Receive_Must
(Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Rec_Next),
Rec_Len);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
Copy_Amt := Copy_Amt - S_Natural (Rec_Len);
if Copy_Amt = 0 then
exit;
end if;
end loop;
New_Next_M1 := Display.Input.Used;
end if;
end if;
Rec_Next := Display.Input.Used;
Display.Input.Used := Display.Input.Used - New_Next_M1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (New_Next_M1 + 1 .. Rec_Next);
----See if the reply was shorter then we expected. This constitutes an I/O
-- error.
if Extra > Len then
declare
Proc : X_Procedure_Variable;
begin
X_Lib.Get_Io_Error (Display, Proc);
Err (Display.Last_Error,
X_Get_Error_String
("XlibError", "ReplyShort",
"Reply shorter than was requested."));
Proc_Var_X_Io_Error_Function.Call
(Proc_Var_X_Io_Error_Function.To_Pv (Proc),
Display);
raise X_Network_Io_Error;
end;
end if;
Status := Successful;
return;
----Everything else is assumed to be an Event.
when others =>
Proc_Var_X_Wire_Event.Call
(Proc_Var_X_Wire_Event.To_Pv
(Display.Event_Vec (Event_Code)),
Display,
Display.Input.Data (Rec_Next .. New_Next_M1),
Client_Sent,
Ev,
Queue_It);
if Queue_It = Successful then
Internal_X_Enq (Display, Ev);
end if;
end case;
----Advance to the next record from the input (make sure there IS one). If
-- there isn't a next record then we must get one. They are all at least
-- Event_Length in length so require that we get at least that many and wait
-- forever if we have to.
Rec_Next := New_Next_M1 + 1;
if Rec_Next > Display.Input.Used then
Display.Input.Used :=
0; -- May as well reset buffer position.
Rec_Next := 1;
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Event_Length),
Rec_Len);
Display.Input.Used := Rec_Len;
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
end if;
end loop;
end Get_Reply_Generic;
--\f
procedure Get_Data_Private (Display : X_Display;
D : out Original) is
------------------------------------------------------------------------------
-- For Discrete and ordinary Private types.
--
-- Read some data from the network connection. Typically only called when
-- you've previously called Get_Reply or some such and you now want to read
-- data that you know is there.
-- 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
-- From_Raw - converts the data to X_Raw_Data
-- Display - display to receive the request
-- D - the data to send
------------------------------------------------------------------------------
Data_Length : X_Raw_Data_Index;
Point : X_Raw_Data_Index;
begin
----If there's data in the input buffer to satisfy the request then use that.
-- Copy remaining data at end-of-buffer down to beginning-of-buffer. We do
-- this kind of thing instead of having a begin-data/end-data pointer pair
-- because the amount of data in the buffer will typically be exactly right
-- and the copy becomes a no-op.
if Display.Input.Used >= Original_Size then
From_Raw (D, Display.Input.Data (1 .. Original_Size));
Point := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Original_Size;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Original_Size + 1 .. Point);
return;
end if;
----We need more data. If Original_Size will fit into the Display buffer then
-- read it into there.
if Original_Size <= Display.Input.Data'Last then
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data
(Display.Input.Used + 1 .. Original_Size),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D, Display.Input.Data (1 .. Original_Size));
Display.Input.Used := 0;
return;
end if;
----Create a buffer area that's big-enough; we won't assume that the type he's
-- receiving will fit into Display.Input.Data. Copy the old data in and
-- Receive however much new data we require. Then do the conversion.
declare
Raw : X_Raw_Data_List;
begin
Raw := new X_Raw_Data_Array (1 .. Original_Size);
Point := Display.Input.Used + 1;
Raw (1 .. Display.Input.Used) :=
Display.Input.Data (1 .. Display.Input.Used);
Display.Input.Used := 0;
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Raw (Point .. Original_Size),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D, Raw.all);
Free_X_Raw_Data_List (Raw);
end;
end Get_Data_Private;
--\f
procedure Get_Large_Data_1d (Display : X_Display;
D : out 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.
--
-- Read some data from the network connection. Typically only called when
-- you've previously called Get_Reply or some such and you now want to read
-- data that you know is there.
-- 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
-- Index - this is the index type for the array type
-- Original_Array - this is the array type
-- From_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;
Data_Length : X_Raw_Data_Index;
Point1 : X_Raw_Data_Index;
Point2 : X_Raw_Data_Index;
Next : S_Long;
Incr : S_Long;
begin
----If there's data in the input buffer to satisfy the request then use that.
-- Copy remaining data at end-of-buffer down to beginning-of-buffer. We do
-- this kind of thing instead of having a begin-data/end-data pointer pair
-- because the amount of data in the buffer will typically be exactly right
-- and the copy becomes a no-op.
if S_Natural (Display.Input.Used) >= Total_Size then
From_Raw (D, Display.Input.Data (1 ..
X_Raw_Data_Index (Total_Size)));
Point1 := X_Raw_Data_Index (Total_Size);
Point2 := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Point1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Point1 + 1 .. Point2);
return;
end if;
----We need more data. If Total_Size will fit into the Display buffer then
-- read it into there.
if Total_Size <= S_Natural (Display.Input.Data'Last) then
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (Display.Input.Used + 1 ..
X_Raw_Data_Index (Total_Size)),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D, Display.Input.Data (1 ..
X_Raw_Data_Index (Total_Size)));
Display.Input.Used := 0;
return;
end if;
----Read the array elements a few at a time.
Next := S_Long (D'First);
Incr := S_Long (Display.Input.Data'Last / Original_Size);
Point1 := Original_Size * X_Raw_Data_Index (Incr);
----First we read them one complete Display.Input.Data buffer-full at a time.
while S_Long (D'Last) - Next >= Incr loop
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (Display.Input.Used + 1 .. Point1),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D (Index (Next) .. Index (Next + Incr - 1)),
Display.Input.Data (1 .. Point1));
Next := Next + Incr;
end loop;
----Finally we read whatever is left to read.
if Next <= S_Long (D'Last) then
Point1 := Original_Size * X_Raw_Data_Index
(S_Long (D'Last) - Next + 1);
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Point1),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D (Index (Next) .. D'Last),
Display.Input.Data (1 .. Point1));
end if;
Display.Input.Used := 0;
end Get_Large_Data_1d;
--\f
procedure Get_Small_Data_1d (Display : X_Display;
D : out 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 probably not 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 greater than 32.
--
-- Read some data from the network connection. Typically only called when
-- you've previously called Get_Reply or some such and you now want to read
-- data that you know is there.
-- 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
-- Index - this is the index type for the array type
-- Original_Array - this is the array type
-- From_Raw - converts the data to X_Raw_Data
-- Display - display to receive the request
-- D - the data to send
------------------------------------------------------------------------------
Total_Data_Size : S_Natural := S_Natural (Original_Size) * D'Length;
Total_Xfer_Size : S_Natural := (Total_Data_Size + 3) / 4 * 4;
Data_Length : X_Raw_Data_Index;
Point1 : X_Raw_Data_Index;
Point2 : X_Raw_Data_Index;
Next : S_Long;
Incr : S_Long;
begin
----If there's data in the input buffer to satisfy the request then use that.
-- Copy remaining data at end-of-buffer down to beginning-of-buffer. We do
-- this kind of thing instead of having a begin-data/end-data pointer pair
-- because the amount of data in the buffer will typically be exactly right
-- and the copy becomes a no-op.
if S_Natural (Display.Input.Used) >= Total_Xfer_Size then
From_Raw
(D,
Display.Input.Data (1 .. X_Raw_Data_Index (Total_Data_Size)));
Point1 := X_Raw_Data_Index (Total_Xfer_Size);
Point2 := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Point1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Point1 + 1 .. Point2);
return;
end if;
----We need more data. If Total_Xfer_Size will fit into the Display buffer then
-- read it into there.
if Total_Xfer_Size <= S_Natural (Display.Input.Data'Last) then
Point1 := X_Raw_Data_Index (Total_Xfer_Size);
Point2 := X_Raw_Data_Index (Total_Data_Size);
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (Display.Input.Used + 1 .. Point1),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D, Display.Input.Data (1 .. Point2));
Display.Input.Used := 0;
return;
end if;
----Read the array elements a few at a time.
Next := S_Long (D'First);
Incr := S_Long (Display.Input.Data'Last / Original_Size);
Point1 := Original_Size * X_Raw_Data_Index (Incr);
Point2 := Point1;
----First we read them one complete Display.Input.Data buffer-full at a time.
while Total_Xfer_Size >= S_Natural (Point1) loop
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (Display.Input.Used + 1 .. Point1),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
if S_Long (D'Last) - Next + 1 < Incr then
Incr := S_Long (D'Last) - Next + 1;
Point2 := Original_Size * X_Raw_Data_Index (Incr);
end if;
if Incr > 0 then
From_Raw (D (Index (Next) .. Index (Next + Incr - 1)),
Display.Input.Data (1 .. Point2));
Next := Next + Incr;
end if;
Total_Xfer_Size := Total_Xfer_Size - S_Natural (Point1);
end loop;
----Finally we read whatever is left to read.
if Total_Xfer_Size > 0 then
Point1 := X_Raw_Data_Index (Total_Xfer_Size);
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Point1),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
if S_Long (D'Last) - Next + 1 < Incr then
Incr := S_Long (D'Last) - Next + 1;
Point2 := Original_Size * X_Raw_Data_Index (Incr);
end if;
if Incr > 0 then
From_Raw (D (Index (Next) .. Index (Next + Incr - 1)),
Display.Input.Data (1 .. Point2));
end if;
end if;
Display.Input.Used := 0;
end Get_Small_Data_1d;
--\f
procedure Get_Data_2d (Display : X_Display;
D : out Original_Array) is
------------------------------------------------------------------------------
-- For two-dimensional array types.
--
-- Read some data from the network connection. Typically only called when
-- you've previously called Get_Reply or some such and you now want to read
-- data that you know is there.
-- 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
-- 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
-- From_Raw - converts the data to X_Raw_Data
-- Display - display to receive the request
-- D - the data to send
------------------------------------------------------------------------------
Total_Size : X_Raw_Data_Index :=
Original_Size * D'Length (1) * D'Length (2);
Data_Length : X_Raw_Data_Index;
Point : X_Raw_Data_Index;
begin
----If there's data in the input buffer to satisfy the request then use that.
-- Copy remaining data at end-of-buffer down to beginning-of-buffer. We do
-- this kind of thing instead of having a begin-data/end-data pointer pair
-- because the amount of data in the buffer will typically be exactly right
-- and the copy becomes a no-op.
if Display.Input.Used >= Total_Size then
From_Raw (D, Display.Input.Data (1 .. Total_Size));
Point := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Total_Size;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Total_Size + 1 .. Point);
return;
end if;
----We need more data. If Total_Size will fit into the Display buffer then
-- read it into there.
if Total_Size <= Display.Input.Data'Last then
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data
(Display.Input.Used + 1 .. Total_Size),
Data_Length);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
From_Raw (D, Display.Input.Data (1 .. Total_Size));
Display.Input.Used := 0;
return;
end if;
----Read the array elements one at a time. You can't slice a 2-D array.
declare
procedure Get_Data is
new Get_Data_Private (Original, From_Raw);
begin
for I in D'Range (1) loop
for J in D'Range (2) loop
Get_Data (Display, D (I, J));
end loop;
end loop;
end;
end Get_Data_2d;
--\f
procedure Eat_Data_Raw (Display : X_Display;
Amount : S_Natural) is
------------------------------------------------------------------------------
-- Read some data from the network connection. Typically only called when
-- you've previously called Get_Reply or some such and you now want to read
-- data that you know is there.
------------------------------------------------------------------------------
Data_Length : S_Natural;
Point1 : X_Raw_Data_Index;
Point2 : X_Raw_Data_Index;
begin
----Always eat full words.
Data_Length := (Amount + 3) / 4 * 4;
----If there's data in the input buffer to satisfy the request then use that.
-- Copy remaining data at end-of-buffer down to beginning-of-buffer. We do
-- this kind of thing instead of having a begin-data/end-data pointer pair
-- because the amount of data in the buffer will typically be exactly right
-- and the copy becomes a no-op.
if S_Natural (Display.Input.Used) >= Data_Length then
Point1 := X_Raw_Data_Index (Data_Length);
Point2 := Display.Input.Used;
Display.Input.Used := Display.Input.Used - Point1;
Display.Input.Data (1 .. Display.Input.Used) :=
Display.Input.Data (Point1 + 1 .. Point2);
return;
end if;
----Eliminate as much data as we have. Then do a/some Receive(s) for the rest.
Data_Length := Data_Length - S_Natural (Display.Input.Used);
Display.Input.Used := 0;
while Data_Length > 0 loop
if Data_Length > S_Natural (Display.Input.Data'Last) then
Point1 := Display.Input.Data'Last;
else
Point1 := X_Raw_Data_Index (Data_Length);
end if;
Receive_Must (Display.Network.Fd,
Display.Network.Fd_Error,
Display.Input.Data (1 .. Point1),
Point2);
if Display.Network.Fd_Error /= Ok then
Report_Io_Error (Display, "Receive");
end if;
Data_Length := Data_Length - S_Natural (Point2);
end loop;
end Eat_Data_Raw;
--\f
end Xlbmp_Get;