[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference bulova::decw_jan-89_to_nov-90

Title:DECWINDOWS 26-JAN-89 to 29-NOV-90
Notice:See 1639.0 for VMS V5.3 kit; 2043.0 for 5.4 IFT kit
Moderator:STAR::VATNE
Created:Mon Oct 30 1989
Last Modified:Mon Dec 31 1990
Last Successful Update:Fri Jun 06 1997
Number of topics:3726
Total number of notes:19516

781.0. "Ada and DECwindows problems" by 8899::DIX (I guess I do windows now...) Sun May 14 1989 17:36

    I'm having some problems in the use of the change_property and/or the
    get_window_property procedure calls for DECwindows from Ada.  This note 
    will be posted in both the DECwindows conference and the Ada conference.
    The following is a brief description of the problem I'm running into.

    I've overloaded the change_property procedure to allow a record data
    structure to be written to the property, but strange things are
    happening (twighlight zone music please....)  The record structure
    consists of 2 elements, both of which are strings.  If I initialize
    the strings to some initial value (upon declaration of the record), then
    change them before calling the change_property procedure, what I end up
    with is the initial values that were assigned.  If I don't give initial
    values when I declare the record, then change the values before calling
    the change_property procedure I get out the values that I changed them to.

    This probably makes no sense at all, so I've included the code (such the
    nice person I am) for anyone to take a look at.  This is a baffling
    problem, but I'm sure someone out there will be able to arrive at a
    solution.

    For those interested in attempting to run the program, you can select the
    area starting with the --++ through the end of the file, write it out to
    a file and compile it all at once.  To link, the two main programs are
    get_property and write_property.  The write_property will bring up a 
    push button.  The get_property procedure will create some output stating
    what values were retrieved from the get_window_property call.

			Thanks in advance for any help,
				Sandy

--++
--
--  This first package contains the overloaded procedure for the change_property
--  call, the "more correct" version of the get_window_property procedure
--  call (there is a known problem with the Ada interface declaration), and
--  the declaration of the record structure.
--
--++
WITH x; USE x;
WITH system; USE system;

PACKAGE new_x IS

      --
      --=====================================================================
      --  The first element has not been initialized in order to demonstrate
      --  the problems I'm having.  When the program is run, the values are
      --  changed as this:
      --    element_1(1) := 'A';
      --    element_2(1) := 'B';
      --  The results that get printed out when the property is retrieved
      --  are:
      --    element_1(1) => A
      --    element_2(1) => 2
      --=====================================================================
      --  
    TYPE record_512_type IS
	RECORD
	    element_1 : string(1..256);
	    element_2 : string(1..256) := (others => '2');
        END RECORD;

      --
      --================================================================
      --  There are some known problems with the Ada interface for the
      --  GET_WINDOW_PROPERTY procedure call, this (to the best of my
      --  knowledge) is a correct version of the procedure call.
      --================================================================
      --  
    procedure GET_WINDOW_PROPERTY (
	RESULT		          : out INTEGER;
	DISPLAY		          : in  DISPLAY_TYPE;
	WINDOW_ID	          : in  WINDOW_ID_TYPE;
	PROPERTY_ID	          : in  PROPERTY_ID_TYPE;
	LONG_OFFSET	          : in  INTEGER;
	LONG_LEN	          : in  INTEGER;
	DELETE		          : in  UNSIGNED_LONGWORD;
	REQUESTED_TYPE	          : in  UNSIGNED_LONGWORD;
	ACTUAL_TYPE_RETURN	  : out UNSIGNED_LONGWORD;
	ACTUAL_FORMAT_RETURN	  : out INTEGER;
        NUM_ITEMS_RETURN          : out INTEGER;
	BYTES_AFTER_RETURN	  : out INTEGER;
	PROPERTY_DATA_RETURN	  : out ADDRESS;
	PROPERTY_DATA_LEN	  : in  INTEGER := INTEGER'NULL_PARAMETER;
	PROPERTY_DATA_BUFF_RETURN : in  UNSIGNED_LONGWORD_ARRAY :=
                                   UNSIGNED_LONGWORD_ARRAY'NULL_PARAMETER;
	NUM_ELEMENTS_RETURN       : in  INTEGER := INTEGER'NULL_PARAMETER );

    pragma INTERFACE (EXTERNAL, GET_WINDOW_PROPERTY);
 
    pragma IMPORT_VALUED_PROCEDURE 
     (GET_WINDOW_PROPERTY, "x$get_window_property",
	(INTEGER, DISPLAY_TYPE, WINDOW_ID_TYPE, PROPERTY_ID_TYPE, INTEGER, 
	 INTEGER, UNSIGNED_LONGWORD, UNSIGNED_LONGWORD,	UNSIGNED_LONGWORD, 
	 INTEGER, INTEGER, INTEGER, ADDRESS, INTEGER, UNSIGNED_LONGWORD_ARRAY,
	 INTEGER),
	(VALUE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, 
	 REFERENCE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, 
	 REFERENCE, REFERENCE, REFERENCE, REFERENCE));


      --
      --======================================================================
      --  The CHANGE_PROPERTY procedure call has been overloaded in order to
      --  be able to write a record structure to the property for a specified
      --  window.
      --======================================================================
      --  
    PROCEDURE CHANGE_PROPERTY(
	DISPLAY       : IN DISPLAY_TYPE;
	WINDOW_ID     : IN WINDOW_ID_TYPE;
	PROPERTY_ID   : IN PROPERTY_ID_TYPE;
	TYPE_ID       : IN TYPE_ID_TYPE;
	FORMAT        : IN INTEGER;
	CHANGE_MODE   : IN UNSIGNED_LONGWORD;
	PROP_DATA     : IN RECORD_512_TYPE;
	NUM_ELEMENTS  : IN INTEGER );

    PRAGMA INTERFACE (EXTERNAL, CHANGE_PROPERTY);

    PRAGMA IMPORT_PROCEDURE
       (CHANGE_PROPERTY, "X$CHANGE_PROPERTY",
          (DISPLAY_TYPE, WINDOW_ID_TYPE, PROPERTY_ID_TYPE, TYPE_ID_TYPE,
	   INTEGER, UNSIGNED_LONGWORD, RECORD_512_TYPE, INTEGER),
	  (REFERENCE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, REFERENCE, 
	   REFERENCE, REFERENCE));

end new_x;

--############################################################################--

--++
--
--  The client_procedures package contains the procedure to be executed durring
--  the callback of the write_property procedure.
--
--++
WITH dwt;

PACKAGE Client_Procedures IS

    PROCEDURE Send_512_Record( WIDGET : IN dwt.widget_type;
                               TAG    : IN INTEGER;
			       REASON : IN INTEGER );
      --
      --================================================
      --  Export the procedure for use in the callbacks
      --================================================
      --  
    PRAGMA EXPORT_PROCEDURE( Send_512_Record );

END Client_Procedures;


WITH text_io;
WITH new_x;
WITH x;
WITH system;
WITH dwt;

PACKAGE BODY Client_Procedures IS

    PROCEDURE Send_512_Record( WIDGET : IN dwt.widget_type;
                               TAG    : IN INTEGER;
			       REASON : IN INTEGER ) IS

	Test_Record   : new_x.record_512_type;
	Display       : dwt.display_type;
	Screen        : system.unsigned_longword;
	Root_Window   : x.window_id_type;
	Atom_512      : x.atom_id_type;
	Num_Elements  : integer;

    BEGIN
	  --
	  --=============================================================
	  --  Get the display_id of the window in order to determine the
	  --  root window for which the property is to be changed
	  --=============================================================
	  --  
	dwt.xt_display( result => display,
	                widget => widget );

	x.default_screen_of_display( result  => screen,
	                             display => display );

	x.root_window_of_screen( result    => Root_Window,
	                         screen_id => screen );
	  --
	  --=================================================================
	  --  Use the atom name "atom_512" to identify the atom being changed
	  --=================================================================
	  --  
	x.intern_atom( result         => atom_512,
	               display        => display,
		       atom_name      => "atom_512",
		       only_if_exists => false );

	Num_Elements := new_x.record_512_type'size / 32;
	  --
	  --======================================================
	  --  Now change the values before changing the property
	  --======================================================
	  --  
	Test_Record.element_1(1) := 'A';
	Test_Record.element_2(1) := 'B';
	  --
	  --==================================================================
	  --  The change property procedure is called, followed by a flush to
	  --  be sure the event is being handled by the server.
	  --==================================================================
	  --  
	new_x.change_property( display      => display,
	                       window_id    => root_window,
			       property_id  => atom_512,
			       type_id      => x.c_xa_string,
			       format       => 32,
			       change_mode  => x.c_prop_mode_replace,
			       prop_data    => Test_Record,
			       num_elements => Num_Elements );

	x.flush( display => display );

    END Send_512_Record;

END Client_Procedures;

--############################################################################--

--++
--
--  The get_property procedure handles the retrieval of the property and
--  conversion of the address back into the record structure
--
--++
with x;
with system;
with text_io;
with new_x;

procedure get_property is

    display		: x.display_type;
    name_of_display	: constant string := "DECW$DISPLAY";
    screen		: system.unsigned_longword;
    depth		: integer; 
    visual		: x.visual_type := x.visual_type_init;
    attribute_mask	: x.window_masks_type := x.window_masks_type_init;
    window_attributes	: x.set_win_attributes_type :=
                              x.set_win_attributes_type_init;
    window_height	: constant system.unsigned_longword := 280;
    window_width	: constant system.unsigned_longword := 360;
    window_x		: constant integer := 25;
    window_y		: constant integer := 100;
    root_window		: x.window_id_type;
    main_window		: x.window_id_type;
    event		: x.event_type;
    value		: string(1..132);
    length		: natural;
    status		: integer;
    ret_type		: system.unsigned_longword;
    ret_fmt_type	: integer;
    nitems		: integer;
    nremaining		: integer;
    data_string		: system.address;
    record_512_value    : new_x.record_512_type;
    atom_512		: x.atom_id_type;

      --
      --========================================================================
      --  This procedure uses the address passed back by the get_window_property
      --  procedure as the location for the data and returns the data at that
      --  address.
      --========================================================================
      --  
    procedure address_to_record( location : in  system.address;
                                 value    : out new_x.record_512_type ) is
	rec_val : new_x.record_512_type;
	for rec_val use at location;
    begin
	value := rec_val;
    end address_to_record;


begin
    x.open_display( result        => display,
                    display_name  => name_of_display );

    x.default_screen_of_display( result   => screen,
                                 display  => display );

    x.default_depth_of_screen( result     => depth,
                               screen_id  => screen );

    x.default_visual_of_screen( screen_id      => screen,
                                visual_return  => visual );

    x.root_window_of_screen( result     => root_window,
                             screen_id  => screen );
      --
      --======================================================================
      --  Use the same atom name as specified in the changing of the property
      --  in order to retrieve the correct property.
      --======================================================================
      --  
    x.intern_atom( result         => atom_512,
                   display        => display,
		   atom_name      => "atom_512",
		   only_if_exists => false );

    x.create_window( result           => main_window,
                     display          => display,
		     parent_id        => root_window,
		     x_coord          => window_x,
		     y_coord          => window_y,
		     width            => window_width,
		     height           => window_height,
		     border_width     => 3,
		     depth            => depth,
		     class            => x.c_copy_from_parent,
		     visual_struc     => visual,
		     attributes_mask  => attribute_mask,
		     attributes       => window_attributes );
      --
      --=====================================================================
      --  Set up an interest in a property change event for the root window
      --=====================================================================
      --  
    attribute_mask.cw_event_mask := true;
    window_attributes.swda_event_mask := x.m_property_change;
    x.change_window_attributes( display         => display,
                                window_id       => root_window,
				attributes_mask => attribute_mask,
				attributes      => window_attributes );

    x.map_window( display   => display,
                  window_id => main_window );
      --
      --======================================================================
      --  Loop through retrieving events and getting the property if the event
      --  is a property notify for the atom_512.
      --======================================================================
      --  
    loop
	x.next_event( display      => display,
	              event_return => event );

	if event.evnt_type = x.c_property_notify then

	  if system."=" (event.ppev_atom, atom_512) then
            NEW_X.GET_WINDOW_PROPERTY (
                   RESULT                     => status,
                   DISPLAY                    => Display,
                   WINDOW_ID                  => Root_Window,
                   PROPERTY_ID                => atom_512,
                   LONG_OFFSET                => 0,
                   LONG_LEN                   => 128,
                   DELETE                     => 0,
                   REQUESTED_TYPE             => X.C_XA_STRING,
                   ACTUAL_TYPE_RETURN         => Ret_Type,
                   ACTUAL_FORMAT_RETURN       => Ret_Fmt_type,
		   NUM_ITEMS_RETURN           => nitems,
                   BYTES_AFTER_RETURN         => nremaining,
                   PROPERTY_DATA_RETURN       => data_string );
	      --
	      --=======================================================
	      --  Convert the address returned into a record_512_type
	      --=======================================================
	      --  
	    address_to_record( location => data_string,
	                       value    => record_512_value );
	      --
	      --============================================================
	      --  Write out what was received in order to determine if the
	      --  change_property and the get_property worked properly.
	      --============================================================
	      --  
	    text_io.put_line("Element 1 => " & record_512_value.element_1(1) );
	    text_io.put_line("Element 2 => " & record_512_value.element_2(1) );

	    x.free( buff_ptr => data_string,
	            buff_len => 512 );

	  end if;
	end if;
    end loop;

end get_property;

--############################################################################--

--++
--
--  The write_property procedure creates a push button and uses callbacks to
--  execute the changing of the property.
--
--++
with x;
with dwt;
with system;
with text_io;
with client_procedures;
    use client_procedures;

procedure write_property is

    main_widget		: dwt.widget_type;
    top_level_widget	: dwt.widget_type;
    push_button_512	: dwt.widget_type;
    top_level_name	: constant string := "T";
    button_512_name	: constant string := "512 Button";
    top_level_class	: constant string := "C";
    argument_count	: dwt.cardinal_type := 0;
    argument_list	: dwt.arg_array_type( 0..5 ) :=
                            (others => dwt.arg_type_init);
    comp_string		: dwt.comp_string_type;
    return_status	: integer;
    callback_arg_list	: dwt.callback_array_type( 0..1 ) :=
			    ( 0 =>
			      ( callback_proc => send_512_record'address,
			        callback_tag  => 0 ),
			      1 => dwt.callback_type_init );

begin

    dwt.xt_initialize( widget      => top_level_widget,
                       name        => top_level_name,
		       class_name  => top_level_class,
		       urlist      => 
		            system.unsigned_longword_array'NULL_PARAMETER,
		       num_urlist  => 0,
		       argcount    => argument_count,
		       argvalue    => dwt.address_array'NULL_PARAMETER );

    dwt.vms_set_arg( arg        => 340,
                     arglist    => argument_list,
		     argnumber  => 0,
		     argname    => dwt.c_nx );

    dwt.vms_set_arg( arg        => 280,
                     arglist    => argument_list,
		     argnumber  => 1,
		     argname    => dwt.c_ny );

    dwt.vms_set_arg( arg        => 1,
                     arglist    => argument_list,
		     argnumber  => 2,
		     argname    => dwt.c_nallow_shell_resize );
      --
      --======================================================================
      --  Set the values for the top_level_widget to specify the X/Y location
      --  as well as allowing the shell to resize
      --======================================================================
      --  
    dwt.xt_set_values( widget   => top_level_widget,
                       arglist  => argument_list,
		       argcount => 3 );

    dwt.dialog_box_create( widget            => main_widget,
                           parent_widget     => top_level_widget,
			   name	             => " ",
			   override_arglist  => 
			       dwt.arg_array_type'null_parameter,
			   override_argcount => 0 );
    dwt.xt_manage_child( widget => main_widget );
      --
      --=========================================================
      --  Set up the callback array and create the push button
      --=========================================================
      --  
    dwt.vms_set_callback_arg( callback_arg => callback_arg_list,
                              arglist      => argument_list,
			      argnum       => 0,
			      argname      => dwt.c_nactivate_callback );

    dwt.push_button_create( widget            => push_button_512,
                            parent_widget     => main_widget,
			    name              => button_512_name,
			    override_arglist  => argument_list,
			    override_argcount => 1 );

    dwt.xt_manage_child( widget => push_button_512 );

    dwt.xt_realize_widget( widget => top_level_widget );

    dwt.xt_main_loop;

end write_property;

T.RTitleUserPersonal
Name
DateLines
781.1Customer needs a response8899::DIXI guess I do windows now...Fri May 19 1989 17:199

	One thing I forgot to mention in the first note is that the
	use of X events and properties is a major design issue on a
	very large project for a customer I'm working with.  If I
	don't get a response I'll assume the engineering people should
	be notified via an SPR.


781.2PSW::WINALSKIPaul S. WinalskiFri May 19 1989 21:426
If it's a major and important problem, you should be escalating it through the
official support channels as well as looking for quick answers in notes
conferences.

--PSW

781.3Solution to the problem....8899::DIXI guess I do windows now...Thu May 25 1989 10:3364
	For anyone wishing to know the solution to this dilema, it was
	answered in the Ada notes conference and I shall place it here
	as well....

                 <<< TURRIS::NOTE$:[NOTES$LIBRARY]ADA.NOTE;2 >>>
                                -< DIGITAL Ada >-
================================================================================
Note 1383.5                Ada and DECwindows problem                     5 of 6
TLE::MORRIS                                          50 lines  24-MAY-1989 18:57
                      -< Be careful with address clauses >-
--------------------------------------------------------------------------------
Hi!
    I'm pretty certain I know what the problem is.  I believe the problem comes
about from the use of an address clause to overlay storage in the procedure 
address_to_record.

From the LRM section 13.5:

    An address clause specifies a required address in storage for an entity.

The code from package new_x:

    TYPE record_512_type IS
	RECORD
	    element_1 : string(1..256);
	    element_2 : string(1..256) := (others => '2');
        END RECORD;

The code from procedure get_property:

    procedure address_to_record( location : in  system.address;
                                 value    : out new_x.record_512_type ) is
	rec_val : new_x.record_512_type;
	for rec_val use at location;
    begin
	value := rec_val;
    end address_to_record;

The location passed in is used as the address for storage of rec_val as 
the programmer intended, but remember THAT IS ALL THE ADDRESS CLAUSE DOES.
So just as if it was not present, the implicit initialization given in 
the type declaration for the record new_x.record_512_type is then executed 
writing over the data that the programmer was trying to fetch.

One way to avoid this problem would be to use the generic procedure
defined in system for fetching data given an address as follows:

    procedure address_to_record( location : in  system.address;
                                 value    : out new_x.record_512_type ) is

        function fetch_record_512 is new 
	    system.fetch_from_address (target => new_x.record_512_type);

    begin
	value := fetch_record_512(location);
    end address_to_record;

I made this change and get_property seemed to function correctly.
Sorry I wasn't able to look at this sooner.

	Greg