XView Selection Package 
/**/# @(#)sel_api.txt	1.5 28 Jun 1993 SMI


1.  Abstract

   This document details the new selection service  specification.  It  
   describes the new application programmer interface, and  provides some 
   examples.  It assumes the reader is familiar with principles of  X11 
   inter-client communication protocol.


2.  Introduction

   The Selection Service package provides for  flexible communication among 
   window applications. It is concerned with the aspects of the selection[s] 
   the user has made, and with the status of the user interface which may affect 
   those selections. Selections communicate between an "owner" client and a 
   "requestor" client. The "owner" has the data representing the selected value 
   and the "requestor" wants that data.


3.  XView Selection API

   The new selection package is intended as a cleaner/simpler method for
   XView inter-client communication.  Selections should be XView objects. 
   One should be able to use xv_create to create the selection object, use 
   xv_get and xv_set to manipulate the object.

   3.1.  Class Hierarchy

       The new package name for the selection will be "SELECTION". 
       "SELECTION" is sub-classed from  the XView generic object. 
       Sub-classed from the "SELECTION" object are, "SELECTION_OWNER" and 
       "SELECTION_REQUESTOR".
   	
       "SELECTION_ITEM" is also sub-classed from the XView generic object. 

       The "SELECTION" package is an example of a hidden class. It  cannot be
       instantiated independently from the "SELECTION_OWNER" and 
       "SELECTION_REQUESTOR".
       "SELECTION" package will contain attributes that are common between the
       "SELECTION_OWNER" and "SELECTION_REQUESTOR".

				    ---------------
				    |   GENERIC   |
				    ---------------
				      |	 	 |
			    -- -- -- -- ---	--------------------
			    |  SELECTION  |	|  SELECTION_ITEM  |
			    -- -- -- -- ---	--------------------
			       |	|
		-------------------   -----------------------
		| SELECTION_OWNER |   | SELECTION_REQUESTOR |
		-------------------   -----------------------

    3.2. Object Ownership

				    ------
				    WINDOW
				    ------
				     |   |
			---------------  -------------------
			SELECTION_OWNER  SELECTION_REQUESTOR
			---------------  -------------------
			       |
			--------------
			SELECTION_ITEM
			--------------


    3.3. SELECTION Object Attributes

	Attribute           Type        Default           Procs     
	--------------------------------------------------------------------
	SEL_RANK            Atom       XA_PRIMARY         create/get/set

	Specifies the selection atom. Pre-defined atoms are XA_PRIMARY, 
	XA_SECONDARY and CLIPBOARD. The client should set the SEL_RANK to 
	the atom representing the selection.


	SEL_RANK_NAME      *char     "XA_PRIMARY"        create/get/set

	Specifies the selection name. The package will intern the selection
	atom using this name.


	SEL_TIMEOUT_VALUE  unsigned int "Selection.Timeout" create/set/get

	Selection timeout value. This value indicates the number of seconds 
	that a requestor or a selection owner waits for a response.


	SEL_TIME     struct timeval *  "Last event time"   create/set/get

	Specifies the timestamp of the event triggering the acquisition or
	the request attempt. 



    3.4. Selection Owner

     The "SELECTION_OWNER" package is sub-classed from the "SELECTION".
     It will allow the clients to become the owners of a particular selection
     rank.
     It is the owner's responsibility to convert the data to the format 
     required by the requestor and to transfer transfer the converted 
     data to the requestor.

     3.4.1. SELECTION_OWNER Attributes


	Attribute           Type             Default             Procs     
	--------------------------------------------------------------------

	SEL_CONVERT_PROC  Pointer to a func  sel_convert_proc  create/set/get

	Specifies the procedure that is to be called whenever a client requests 
	the current value of the selection. For more info refer to 3.4.2.
	

	SEL_DONE_PROC      Pointer to a func     NULL          create/set/get
	
	Specifies the procedure that is  called after the requestor has 
	received the selection or NULL if the owner is not interested in being 
	called back. For more info refer to 3.4.3.


	SEL_LOSE_PROC      Pointer to a func     NULL         create/set/get

	Specifies the procedure that is to be called whenever the selection 
	owner has lost selection or NULL if the owner is not interested in being 
	called back. For more info refer to 3.4.4.


	SEL_OWN               boolean            FALSE        create/set/get
	
	Setting SEL_OWN causes the selection to be acquired (True) or lost 
	(False). Owning a selection without an external convert proc or any 
	Selection Owner items will generate a NULL-data reply.


	SEL_FIRST_ITEM       Selection_item     N/A           get

	Returns a selection item.


	SEL_NEXT_ITEM       Selection_item      N/A           get

	Returns a selection item.


	SEL_PROP_INFO	    Sel_prop_info *     N/A	      get

	Returns the property data.
	This attribute should be used from a convert_proc. It returns the
	data that has been set on the SelectionNotify's property by the
	requestor client.


     3.4.2.  convert_proc

	This user defined procedure is called by the SELECTION_OWNER package to 
	convert	the value of a selection to a given type.
	The return value should be set to "TRUE" if the owner has successfully 
	converted the selection to the target type and "FALSE" otherwise.

	The owner can choose to send the data in increments by constructing
	an "INCR" message as follow:
	
		- "replyType" to INCR.
		- "replyBuff" to an integer, representing a lower bound on the
		  number of bytes of data in the selection.
		- "length" to 1.
		- "format" to 32.

	It should then return "TRUE". The selection package will send the
	"INCR" message to the requestor and calls the "convert_proc"
	repeatedly until "length" is set to zero. This will indicate the
	end of data transfer.

	Clients are required by ICCCM to convert to "TARGETS" type. 
	"convert_proc" should include the code necessary to convert to this 
	atom type. 

	This routine is designed for the advanced users. It could be used in
	situations that needs special processing (e.g. sending large data in
	increments).

	"convert_proc" is called with "length" set to server's 
	maximum_request_size. If the owner has chosen to send the selection
	data in increments, the size of each increments should be less than
	or equal to "length".


	"convert_proc" is called with "format" set to "SEL_BEGIN_MULTIPLE" to 
	indicate the beginning of a "MULTIPLE" request and to "SEL_END_MULTIPLE" 
	to indicate the end of a "MULTIPLE" request.


	int  (*convert_proc)( seln, &replyType, &replyBuff, &length, 
						&format );

	Argument   Type        Description
	------------------------------------------------------------------------
	seln Selection_owner  Selection object.

	replyType  *Atom      Specifies the type of the selection that has been
			      requested. It should be set to an atom which 
			      describes the converted type of the selection 
			      (For example TEXT might have the property type of 
			      XA_STRING).  This routine is called with 

	replyBuff *Xv_opaque  A pointer to a buffer address which contains the 
			      converted data. 

	length    *unsigned long  Specifies a pointer to the number of elements in 
			      the  property. "sel_convert_proc" is called with 
			      "length" set to the max allowed buffer size. 

	format     *int      Specifies a pointer to the data format ( 8-bit, 
			     16-bit or  32-bit).


        3.4.2.1.  sel_convert_proc

		"sel_convert_proc" is a public procedure. This procedure is the
		package default convert proc.

	            sel_convert_proc( seln, &replyBuff, &length, &format, &incr );


     3.4.3.  done_proc


	This user defined procedure is called by the SELECTION_OWNER package when 
	a selection request has successfully been completed.  It is called once 
	following each successful transfer of  data to the requestor. This 
	procedure can be used to deallocate the selection data.
	If an "alloc" error occurs during storing the selection data, the
	done_proc will be called with "target" set to "SEL_FAILED".

	void  (*done_proc)( seln, replyBuff, target );

	Argument          Type        Description
	-----------------------------------------------------------------------
	seln         Selection_owner  Selection object.

	replyBuff    Xv_opaque        Buffer which contains  the converted data.

	target		 Atom             Specifies the requested data type.

			    

     3.4.4.  lose_proc

	This user defined procedure is called by the SELECTION_OWNER package to 
	inform the client that it has lost the ownership of  the given selection.
	One example of "lose_proc" usage is unhighlighting (normal video)
	the selected text in textsw.	


	void  (*lose_proc)( seln );


	Argument     Type              Description
	--------------------------------------------------------------------
	seln         Selection_owner   Selection object.


    3.5. Selection Requestor

     The "SELECTION_REQUESTOR" package is sub-classed from the "SELECTION".
     It will allow the clients to obtain the value of a selection in a 
     particular form.

     3.5.1.  SELECTION_REQUESTOR Object Attributes

	
	Attribute            Type        Default        Procs     
	--------------------------------------------------------------------

	SEL_DATA             Xv_opaque    N/A            get

	It will initiate a  blocking selection request. The arguments
	to this attribute are, a pointer to a "long" which will be set
	to the number of elements in the returned buffer and a pointer to 
	an "integer" which will be set to the data format.
	"xv_get" returns a pointer to the selection data. clients should 
	free the returned buffer .

	If the requestor client has not registered a  "reply_proc" with the
	selection package and requesting for MULTIPLE or INCR, the call will
	return with "length" set to "SEL_ERROR" and format set to zero.

	If the requestor client has registered a  "reply_proc" with the
	selection package and requesting for MULTIPLE or INCR, the package
	will call the client's reply_proc with the converted data. "xv_get"
	returns after the transaction has completed with "length" set to
	XV_OK and format set to the returned data format. 

	If the request fails the "xv_get" will return with "length" set to
	"SEL_ERROR" and format set to zero.

	data = (char *) xv_get(sel_requestor, SEL_DATA, &length, &format);


	SEL_TYPE             Atoms        XA_STRING      create/set/get

	Specifies an atom type that the client is requesting. 

	SEL_TYPES          List of Atoms  "XA_STRING,0"   create/set/get

	Specifies a NULL-terminated list of atom types that the client is
	requesting. The effect will be as if a sequence of "SelectionRequest" 
	events is delivered to the selection owner, one for each atom.
	This attribute will initiate a multiple request. For more info refer 
	to 4.2.2.

	SEL_TYPE_NAME        *char         "STRING"       create/set/get

	Same as SEL_TYPE except that the argument is the name of the 
	requested selection type. The Package will intern the requested
	atom type.


	SEL_TYPE_NAMES     List of string   "STRING", 0    create/set/get

	Specifies a NULL-terminated list of atom type names that the client 
	is requesting. 


	SEL_APPEND_TYPES     List of Atoms       N/A         create/set

	Same as SEL_TYPES except that the new list is appended to the 
	previously set type list.


	SEL_APPEND_TYPE_NAMES  List of string  N/A           create/set

	Same as SEL_TYPE_NAMES except that the new list is appended to the 
	previously set type list.


	SEL_REPLY_PROC      "Pointer to a func"  NULL     creat/set/get

	Specifies the procedure that is to be called when the selection value 
	has been obtained. See 3.5.2.


	SEL_TYPE_INDEX	    int			N/A	  create/set

	Specifies an index to the SEL_TYPES or SEL_TYPE list. This attr is
	used in conjunction with the following five attributes to associate
	data to a property used by the requestor.


	Multiple:

		xv_set( sel_req, SEL_TYPES, XA_STRING, INSERT_SELECTION, 0,
					SEL_TYPE_INDEX, 1,
						SEL_PROP_DATA, dataPointer,
						SEL_PROP_LENGTH, 20,
					0 );


	Single Request:

		xv_set( sel_req, SEL_TYPE, XA_STRING,
					SEL_TYPE_INDEX, 0,
						SEL_PROP_DATA, dataPointer,
						SEL_PROP_LENGTH, 20,
					0 );


	SEL_PROP_DATA       Xv_opaque		NULL	  create/set

	Specifies the data associated to a property.


	SEL_PROP_LENGTH	   unsigned long	0	  create/set

	Specifies the length of the data associated to a property.


	SEL_PROP_FORMAT    int			8	  create/set

	Specifies the format of the data associated to a property.


	SEL_PROP_TYPE	   Atom			XA_STRING  create/set

	Specifies the type of the data associated to a property.


	SEL_PROP_TYPE_NAME *char  		"STRING"   create/set

	Specifies the type name of the data associated to a property.


    3.5.2. reply_proc

	void  (*reply_proc)( sel_req, type, replyValue, length, format );

	Argument               Type       Description
	------------------------------------------------------------------------
	Selection_requestor   sel_req     Selection requestor object.

	target				  Atom        Specifies the requested data type.

	type		      Atom        Specifies the converted data type.

	replyValue            Xv_opaque   Specifies a pointer to the converted 
					  data. 

	length                unsigned long  Specifies the actual number of 8, 16,
	  				  or 32-bit items return in replyValue.

	format	     	      int         Specifies the actual data type of the 
	  				  returned  data.


	This routine is used as a communication mechanism between the selection
	package and the selection client.

	If the selection content is larger than the server's maximum_request_size
	or if the selection owner has decided to transfer the selection data in
	increments the selection package will send the data to the requestor in
	chunks.
	The package starts the data transfer by first calling this routine with
	"type" set to "INCR" and "replyValue" set to a lower bound on the number
	of bytes of data in the selection.
	The "reply_proc" will then be called repeatedly until all the selection
	data has been transferred.
	The "reply_proc" is called once more with "length" set to zero and
	"replyValue" set to NULL to indicate the end of incremental data
	transfer.
	If one of the MULTIPLE's target is being transferred incrementally,
	"target" is set to "MULTIPLE".

	If the selection conversion fails, this routine is called with 
	"replyValue" set to an error code, "length" set to SEL_ERROR. 

	The error codes are:

	  SEL_TIMEDOUT -       Selection timedout.

	  SEL_BAD_WIN_ID -     The SelectionNotify requestor ID does not  match 
 	    	   	       the  package requestor ID.

	  SEL_BAD_TIME -       The SelectionNotify time does not match the 
			       package  time value.

	  SEL_BAD_CONVERSION - If the "property" field is None, the conversion 
			       has been refused.  This can mean that there is 
			       no owner for the selection, that the owner does 
			       not support the conversion implied by "target",
			       or that the  server did not have sufficient 
			       space.


     3.5.3. Non-blocking Selection Request

	"sel_post_req" is a public procedure used to initiate a non-blocking 
	request. Users "reply_proc" is called by the package to transfer the 
	data to	the requestor client. It returns XV_OK or XV_ERROR.  If no reply 
	procedure is defined, XV_ERROR is returned.

	sel_post_req( sel_req )
	  Selection_requestor    sel_req


    3.6. Selection Items

       3.6.1. SELECTION_ITEM Object Attributes


	Attribute            Type        Default        Procs     
	--------------------------------------------------------------------

	SEL_COPY             Boolean     True           create/set/get

	SEL_COPY indicates whether or not to copy the data.


	SEL_DATA             Xv_opaque   NULL           create/set/get

	Specifies  a pointer to the selection data.


	SEL_FORMAT           Xv_opaque    8             create/set/get
	  
	Specifies the data format.


	SEL_LENGTH           unsined long Type-dependent    create/set/get

	Specifies the number of  8, 16, 32-bit elements. If the type is
	either "STRING", "FILENAME" or "HOSTNAME", the default value
	is set to "strlen(data)".


	SEL_TYPE             Atom         XA_STRING     create/set/get

	Specifies the type that the package will convert to.


	SEL_TYPE_NAME        char *       "STRING"      create/set/get

	Specifies the type name that the package will convert to.


4.  Large Data Transfer
   
	Selections can get large, and this poses the following problems:
	  - Transferring large amount of data to the server is expensive.
	  - All servers have limits on the amount of data that can be stored in 
	    the property.

	The  SELECTION_OWNER  package will compare the size of the data 
	describing the selection with the XMaxRequestSize. If the selection data
	is larger than the XMaxRequestSize the selection owner will use the 
	INCR property mechanism to  transfer the selection data.
	The SELECTION_OWNER package will process "alloc" errors in property 
	change requests by using the XView XIO error handler.
	If an "alloc" error occurs during storing the selection data, all 
	properties stored for this selection will be deleted and an error will
	be sent back to the requestor by calling the requestor's "done_proc"
	with the appropriate error code. For more information refer to 3.4.3.

  
5.  General features

	5.1.  Giving up the selection ownership

	     The SELECTION package provides a method for selection owners to 
	     gracefully give up the selection ownership. 
	     (see 3.4.1. SEL_OWN)

	5.2.  Atom management

	     The SELECTION package contains atom management routines. It reuses
	     Atoms that are not currently being used.

	5.3.  Incremental data transfer

	     The SELECTION package will support incremental replies if it is 
	     asked to do so. (see 3.4.2 "convert_proc")

	5.4.  Inter-operation

	     The clients using the new SELECTION package will be able to 
	     communicate  with clients linked with the old package.
	     The only type supported is "XA_STRING".

	5.5.  Timeout value

	     The SELECTION package uses the resources "Selection.Timeout" to  get 
	     the default selection timeout value.  This value indicates the number 
	     of seconds that a requestor or a selection owner waits for a response.

	     If the requestor client times out while waiting for a response from
	     the selection owner; the package calls the requestor 
	     reply proc with an  error code of SEL_TIMEDOUT.

	     If the selection owner client times out while waiting for a 
	     response from the requestor; the package calls the selection owner 
	     done proc, if it exists.

	     The default is set for 3 sec.

	5.6.  Local client

	     It will include the ability to treat the clients that are both the
	     owner of the selection and the requestor more efficiently.
	     I am planning to utilize a shared memory scheme for local 
	     connections in the next version of the selection package.





6.  Examples

    6.1.  Becoming The Primary Selection Owner 

     	6.1.1.

		char               *highlighted_selection;
		Selection_owner     sel_owner;
		Selection_item      sel_item;

		main()
		{
		    :
			sel_owner = xv_create(window, SELECTION_OWNER, 0);
			sel_item = xv_create(sel_owner, SELECTION_ITEM, 0);
			:
                 }
			 
                 window_event_handler(..., event, ...)
                 :
                 Event          *event;
                 :
                 {
                                  :
                	 switch (event_action(event) {
			   case ACTION_COPY:
			   xv_set(sel_item, SEL_DATA, highlighted_selection, 0);
			   xv_set(sel_owner, SEL_OWN, TRUE, 0);
			   break;
			:
		}
											
        6.1.2.  Becoming the Primary Selection owner (using explicit convert
		procedure).

		Selection_owner  seln_owner;

		main()
		{
			.............
			.............
			/* Create a selection object */
			seln_owner = xv_create( window, SELECTION_OWNER, 
						SEL_CONVERT_PROC, CvtProc, 
						NULL );
	
			xv_main_loop( frame );
		}

		CvtProc( seln_owner,type,replyBuff,length, format )
		Selection_owner        seln_owner;
		Atom                   *type;
		char                   **replyBuff;
		unsigned long          *length;
		int                    *format;
		{
		    int  len;
	
		    Atom   selection;
		    char   str[50];

		    selection = (Atom) xv_get( seln_owner, SEL_RANK );
		

	        strcpy( str,"Primary selection content!!\n");

		    if ( type == TARGETS )  {
				/* Support target conversion here. */
				return( TRUE );
		    }
		    if ((selection == XA_PRIMARY ) && ( type == XA_STRING )) {
				*format = 8;
				*length = strlen( *str ) + 1 ;
				*type = type;
				*replyBuff = (char *) *str;
				return(TRUE);
		    }
		    return(FALSE);
		}



    6.2.  Requesting The Primary Selection Value 
    
      6.2.1.  Blocking 

	Selection_requestor sel_requestor;
 
	main()
	{
		:
		sel_requestor = xv_create(window, SELECTION_REQUESTOR, 0);
		:
	}
	      
	window_event_handler(..., event, ...)
	:
	Event          *event;
	:
	{
		char           *data;
		int             format;     /* size of data element: 8, 16 or 32
						bits */
		unsigned long  length;     /* nbr of data elements */
		:
		switch (event_action(event) {
		  case ACTION_PASTE:
		    /* Initiate a blocking request, and get the data */
		    data = (char *) xv_get(sel_requestor, SEL_DATA, 
						&length, &format);
		:
	}
									 

      6.2.2.  Non-blocking

	long  *file_buffer;        /* contents of selected file */
	long  file_buffer_size;   /* # of long's in file_buffer */
	Selection_requestor sel_requestor;
 
	void
	reply_proc(sel_requestor, type, data, length, format)
	Selection_requestor sel_requestor;
	Atom           type;
	long           *data;       /* buffer address */
	unsigned long  length;     /* nbr of data elements */
	int             format;     /* size of data element: 8, 16 or 32
					bits */
	{
		int             i;
		long           *lptr;
	
		if (length == SEL_ERROR) {
			xv_error(sel_requestor,
				ERROR_LAYER, ERROR_PROGRAM,
				ERROR_SEL_ERROR, *data,
				0);
			return;
		}   
		if (format != sizeof(long)) {
			xv_error(sel_requestor,
				ERROR_LAYER, ERROR_PROGRAM,
				ERROR_STRING, "Incorrect format returned",
				0);
			return;
		}   
		file_buffer = (long *) malloc(length * 4);
		file_buffer_size = length;
		lptr = file_buffer;
		for (i = 1; i <= length; i++)
			*lptr++ = *data++;
	}
	main()
	{
		:
		sel_requestor = xv_create(window, SELECTION_REQUESTOR,
				SEL_REPLY_PROC, reply_proc,
				0);
		:
	}
	 
	window_event_handler(..., event, ...)
	:
	Event          *event;
	:
	{
		:
		switch (event_action(event) {
		case ACTION_PASTE:
		  sel_post_req(sel_requestor);  /* initiate non-blocking 
							request */
		:
	}

7. References

	Inter-Client Communication Conventions Manual (Version 1.0)
	   David S.H. Rosenthal 
	   Sun Microsystems, Inc.

