GTRequest.txt doc

(C) Copyright 1993 Justin Miller
      This file may be freely distributed with IntuiGen 2.0.
      All Other Rights Reserved.
      The Author makes no warranties, express or implied, as to
	the accuracy or suitability of the material contained herein.

What is GTRequest
GTRequest refers to the set of functions found in the GTRequest.c file
which manage an IntuiGen generated requester under GadTools.  This file
documents these functions, their use, and the structures that drive them.



GTRequest
GTRequest is a function in the GTRequest.c file which opens your window,
displays your IntuiGen generated requester, handles user input, calls
user-defined functions, copies values between the requester gadgets and a
structure, implements keyboard commands, and more.  To use GTRequest,
simply set up your requester in IntuiGen, generate code for it using the
GadTools Code and IG/GTRequest code options, (you may want to generate a
window listing too), and then call GTRequest from within your program
somewhere, like this:

main()
{
	LONG x;
	...
	x=GTRequest(&MyRequest);
	/*
		if x=0 GTRequest failed due to inadequate or unavailable
		system resources

		Otherwise x=MyRequest.Terminate
		if x>0, then the associated data structure was filled from the
			user-entered info in the gadgets
		if x<0, then the data structure was not filled
		>0 usually corresponds to OK-type ending
		<0 usually corresponds to Cancel-type ending
	*/
	...
}



Simulating User Input
GTRequest includes several functions that can be called while a GTRequest
is active which simulate User Input.  These functions are:

__far void SetControlAttrs (GTRequest *req,struct GTControl *gtc,Tag
    tag1,...);

__far BOOL GTKeyClick (struct GTRequest *req,UBYTE *keyinfo,UBYTE key);

__far void SetIntControl (struct GTRequest *req,struct GTControl *gtc,LONG
    number);

__far void SetStringControl (struct GTRequest *req,struct GTControl
    *gtc,UBYTE *string);

__far BOOL GTGadgetClick (struct GTRequest *req,struct Gadget *gadg);

#define GTControlClick(r,g) GTGadgetClick(r,(g)->Gadget)



GTBlock/UnBlockInput
GTBlockInput Function opens an blank intuition requester on top
of an GTRequest, thereby blocking it from receiving input, making all
of its Gadgets/Controls unselectable and unusable.

__far void GTBlockInput(struct GTRequest *req);

GTUnBlockInput closes blank requester opened by GTBlockInput, thereby
permitting messages to come through again.  Calls to GTBlock/UnBlockIGInput
can be nested; a nesting depth count is kept.  Only when the number of
calls to GTUnBlockInput equal the number of calls to GTBlockInput will the
requester be unblocked.

__far void GTUnBlockInput(struct GTRequest *req);



InitFunctions
In the GTRequest structure is a field called InitFunction.  This field
points to a function to be called as soon as the requester is open, and its
imagery displayed, immediately before message processing begins.  If you
need to algorithmically draw any additional imagery, initialize any lists,
Remember keys, etc. that couldn't be initialized before GTRequest or
ProcessReqSet was called, you can do this in the InitFunction.	To set up
an InitFunction, simply write a function which uses the following
prototype:

	void   (*InitFunction) (struct GTRequest *);

After doing this, enter the functions name in the InitFunction field in the
GTRequest structure.  Your function will then be called when the requester
is run.



Simultaneous Requests
There may be times when you wish to have several GTRequests open at once.
There are two ways that these requesters could behave.

The first way is that the second requester is a sub-requester of the first,
and all input to the first request is blocked until the second request is
ended.	To do this, use a code segment as per below:

main()
{
	...
	GTRequest(&MyRequest1);
	/* MyRequest1 contains a gadget called SomeGadget which has
been
		linked to the function SomeGagdetGUpFunc();
	*/
	...
}

SomeGadgetGUpFunc(struct GTRequest *req, struct IntuiMessage *msg,
	struct GTControl *gtc, struct MessageHandler *mh)
{
	...
	GTBlockInput(req);
	GTRequest(&MyRequest2);
	GTUnBlockInput(req);
	...
}

The second way that the two requesters could behave is as if they belonged
to two separate tasks, each one interacting with the user independently of
the other, with the user free to switch back and forth at will.  Though
these requester may behave as if they belonged to two separate tasks, they
really don't.  An example of this is the Workbench.  You can open several
windows, and then click in any of them you choose and have Workbench
respond to your mouseclick.  To set this up, write code as per below:

main()
{
	struct GTReqSet reqset;
	...

	InitReqSet(&reqset);

	AddGTRequest(&reqset,&MyRequest1);
	AddGTRequest(&reqset,&MyRequest2);

	ProcessReqSet(&reqset);
	...
}

Note that regardless of which of the two methods you use for your
requesters, you cannot display the same requester more than once
simultaneously.  If you would like to open several identical requesters
using either of the above methods, use the DuplicateRequest function to
create a new requester identical to the first.




Creating New MessageClasses
If you would like to establish a new MessageClass to which MessageHandlers
can belong for your requester, you must do the following things:

1) Write an IsType function.  The IsType function should use the following
    argument template:

	 BOOL  (*IsType) (struct GTRequest *,struct IntuiMessage *,
		struct GTControl *,struct MessageHandler *mh);

If struct GTControl * is NULL, then IsType should determine whether the
message has taken place in the requester or for any of the requesters
controls.  If GTControl * is not NULL, then IsType should determine whether
the message kind has taken place for the specific control.  IsType should
return 1 if the message has taken place, otherwise it should return 0.

2)  Establish a class name for this message class.  The class name can be
any string; note that class names are case sensitive.

3)  Create a NULL-terminated MessageClass array for your requester.  This
array will look like this:

	struct MessageClass MyClassList[] = {
		{ MyIsType1, "MyClassName1" },
		{ MyIsType2, "MyClassName2" },
		{ 0, 0 }
	};

4)  Finally, you need to set the LocalMsgClassList field of your IGRequest
structure to point to the above array.

Any MessageHandler in your GTRequest can now use the new
MessageClass, simply by specifying the MessageClass's name.

Before creating a MessageClass, you should check to insure that:
	1)  The class you intend to create isn't already available in the
		GTRequest.c global class list (used by default for all
		requesters).
	2)  The name for you class doesn't conflict with the names of
		any global MessageClass, or any of your other message
		classes.




Linking Toggle Buttons To Structures
Often, you will have a series of on/off type options which lend themselves
to CheckBox_Kind or Toggle Button controls.  You can link CheckBox_Kind
buttons to any field in your structure through IntuiGen, but what if you
want to link them to a particular bit of a field.  In this case, use the
BOOLBIT field type from within IntuiGen.  You will then have to manually
specify the bit of the field to which the control is to be linked, as will
be described shortly.

There are no provisions in IntuiGen for linking Toggle buttons to fields,
much less bits of a field.  This must be done manually.

To link Toggle buttons to a bit of a given field follow these steps.  To
link CheckBox_Kind buttons to a bit of a given field, if you specified the
field name and BOOLBIT field type in IntuiGen, start at step 3.  Otherwise
start at step 1.  Note that when using the BOOLBIT field type, the field in
which the bit that you are linking to exists must be of type ULONG.

1)  Enter FLD_BOOLBIT in the FieldType field of the Control

2)  Enter offsetof(struct StructureTypeNameHere, FieldNameHere) in the
     FieldOffset field of the Control

3)  Enter the bit number (between 0 and 31) of the bit to use in the FieldBit
     field of the Control



CloseWindow Messages
To have a user-defined function called on receipt of a CloseWindow message,
enter the following MessageHandler:

	struct MessageHandler MyRequestCloseWindowMH = {
		NULL,
		"CloseWindow",
		NULL,
		MyCloseWindowFunction
	};

You will then have to append this MessageHandler to you GTRequest's
MessageHandler list.  To do this, find the last MessageHandler in the list
(the first one reading from top to bottom in the code) which is connected
to your GTRequest (comes after all GTControl structures and before the
GTRequest structure).  Change the first field in this structure to read
&MyRequestCloseWindowMH.  If you can't find any request MessageHandlers,
look at the MsgHandlerList field of your GTRequest structure.  If this
field is NULL, there currently aren't any request MessageHandlers.  In this
case, enter &MyRequestCloseWindowMH into this field.

MyCloseWindowFunction will now be called when the user closes the window.



Global Message Classes
The following is a list of all the global message classes you can use in
your programs.	All but the last five correspond to IDCMP messages of
similar names.

	GadgetUp
	GadgetDown
	MouseButtons
	MouseMove
	DeltaMove
	RawKey
	IntuiTicks
	DiskInserted
	DiskRemoved
	MenuVerify
	MenuPick
	SizeVerify
	NewSize
	ReqVerify
	ReqSet
	ReqClear
	ActiveWindow
	InactiveWindow
	RefreshWindow
	NewPrefs
	CloseWindow

These last five classes are unique to GTRequest and therefore warrant
explanation.
	EndGadgetUp
		If you use this message class for a Gadget,
		if that gadget receives a GadgetUp message, EndGTRequest
		will automatically be called with a termination value of -1
		before the HandlerFunction, if any, is called.

	EndFillGadgetUp
		Identical to above, except Terminate = 1

	LimitStringContents
		Use this message Handler to limit string contents to those
		characters not contained in the string associated with the
		GTCT_STRING_INVALIDCHARS control tag.

	VerifyIntLimits
		Use this message handler to limit a string or integer
		Gadget's contents to the digits 0-9, negative sign, and a
		decimal point. Further, allows restrictions to be placed on
		the entered number specifying that it falls within a
		certain range.	The restrictions are set with the tags
		GTCT_INT_MIN and GTCT_INT_MAX.

	StringDSelected
		This message is sent to string gadgets and integer gadgets
		any time the user clicks on another gadget, or hits return.
		Like GadgetUp for strings, but always takes place.




Pseudokinds
Below are the pseudokinds included with GTRequest.  But for the EditList
kind, these can all be used without adding a pseudokind class list to your
GTRequest (the other kinds are in the default pseudokind class list and are
always linked in).  As EditList is in a separate file, and the additional
code it requires is not always linked in, you must add a pseudokind class
list entry to any GTRequest structure which makes use of it.  To learn how
to do this, click the EditList button.

ToggleSelect
	This class creates a BUTTON_KIND-like gadget, except it is
	ToggleSelect.  Supports all the tags BUTTON_KIND supports
	and adds GTPK_Toggled.

ImageButton
	This class creates a Boolean gadget, optionally ToggleSelect,
	which is based on Images.  Uses the following tags with it:

    GTPK_Image
	ti_Data = struct Image *
    GTPK_Toggleselect
	ti_Data = T/F
    GTPK_SelectedImage
	ti_Data = struct Image *
		If not specified, GADGHCOMP used
    GTPK_Toggled
	ti_Data = T/F

EditList
	An EditList is a list with an Editable ShowSelect STRING_KIND gadget, and
	Add and Remove gadgets so that additional entries may be added to the list
	by the user.  It uses the following tags, of which the first two MUST be
	specified:

    GTPK_Remember
	ti_Data = struct Remember **
		All user-added list entries are allocated on this key
		You must free it
    GTPK_List
	ti_Data = struct List *
		This is the list which is displayed and to which entries
		are added.  GTLV_Labels is an acceptable synonym
		for this.
    GTPK_Alpha
	ti_Data = T/F
		Keep the list alphabetized?

    GTPK_NodeSize
	ti_Data = ULONG
		This is the size of each list node to be allocated. Defaults
		to sizeof(struct Node).  If your nodes are custom
		structures, you must set this.

    GTPK_SetList
	ti_Data = void (*SetList) (GTRequest *, GTControl *, List *);

		This function should Attach/disattach list to all controls
		associated with this list, so changes will showup in all
		ListView gadgets.  Need only be set if the list is being
		used by several ListView Gadgets at once.

An edit list has a custom set of messages that it will send out, for which
you can establish MessageHandlers.  The name of the message is the class to
use in the MessageHandler's name.

ChangedEntry
    msg->IAddress = ENTRY (a struct Node *)
	Sent when a Node is changed.

AddedEntry
    msg->IAddress = NEWENTRY (a struct Node *)
	Sent when an entry is added.

ChangedList
    msg->IAddress = LIST
	Sent when the list or one of its nodes is changed in any way.

DeletedEntry
    msg->IAddress = DELETEDENTRY
	Sent when an entry is deleted.	Note that deleted entries are
	Not freed; they remain allocated on your Remember key and
	are freed with all the other entries when you free the Remember
	key.

GadgetUp
    msg->Code = Entry's ord. #
    msg->IAddress = ENTRY
	Sent when the user selects an entry (just like a LISTVIEW_KIND).
	Note that standard LISTVIEW_KINDs don't place the selected
	node's address in msg->IAddress.



EditLists
For an explanation of what an EditList is, see Pseudokinds.  For pointers
on how to use IntuiGen to ease the process of creating the necessary
structures for an EditList, click on the IntuiGen button.  This section
describes what files must be compiled and linked into the program to use
EditLists, and how to set up a Pseudokind class list allowing EditLists to
be used in a particular request.

To use EditLists, you will have to compile and link in the following files:
	GTRequest.c
	EditList.c
	ListViewKind.c

You will then have to define a Pseudokind class list.  Your pseudokind
class list will look something like this:

struct GTPKind MyPKindList[] = {
    { "EditList",CreateEditListKind,0 },
    { 0,0,0 }
};

You will then have to link this class list into your GTRequest structure by
typing MyPKindList into the GTRequest's LocalPKindClassList field.  You can
now use EditList controls in this requester.



Bit Field Macros
These are defined in GTRequest.h:

#define FLAGOFF(x,flag) ((x)&=0xffffffff^(flag))
#define FLAGON(x,flag) ((x)|=(flag))

#define SETFLAG(x,flag,onoff) (onoff ? ((x)|=(flag)) : ((x)&=0xffffffff^(flag)) )

#define ISFLAGON(x,flag) ((x) & (flag))
#define ISFLAGOFF(x,flag) (!((x) & (flag)))
#define GETFLAG(x,flag) ((x) & flag)



GTRequest Tags
These are defined in GTRequest.h:

/**************************************************************************/
/*		   GTRequest/Control Tags				  */
/**************************************************************************/

#define TAG_GTR_BASE (TAG_USER | (1<<16))

/**************************************************************************/
/*			Prefixes for Tags				  */
/**************************************************************************/
/* GTRT is a Request Tag						  */
/*	It should be placed in list pointed to by Request->RequestTags	  */
/*									  */
/* GTCT is a Control Tag						  */
/*	It should be placed in list pointed to by Control->ControlTags	  */
/*									  */
/* GTPK is a Gadget Tag for pseudo kind 				  */
/*	It should be placed in list pointed to by Control->GadgetTags	  */
/*									  */
/* GTGT is a Gadget Tag for GadTools kind which is intercepted by
GTRequest */
/*	It should be placed in list pointed to by Control->GadgetTags	  */
/**************************************************************************/


/**************************************************************************/
/*	These tags are for String_Kind controls 			  */
/*	  They are used to set minimum, maximum limits, and illegal chars */
/**************************************************************************/

#define GTCT_INT_MIN (TAG_GTR_BASE + 1)
#define GTCT_INT_MAX (TAG_GTR_BASE + 2)
#define GTCT_STRING_INVALIDCHARS (TAG_GTR_BASE + 3)

/**************************************************************************/
/*		Don't use these next two                                  */
/**************************************************************************/

#define GTCT_TOGGLED (TAG_GTR_BASE + 4)  /* These 2 really aren't control
tags */
#define GTCT_NEXTDATATOGADGETADDRESS (TAG_GTR_BASE +4) /* use
synonyms def'd
							    below */

/**************************************************************************/
/* If the ti_Data for a tag should be the Gadget Address of a created	  */
/*  GadTools Gadget (i.e. To get an editable ListView ShowSelected        */
/*  String_Kind, you have to pass it the address of an already created	  */
/*  String_Kind), use GTGT_NEXTDATATOGADGETADDRESS.  The data value of
*/
/*  the next tag is assumed to be a pointer to a GTControl.  This	  */
/*  GTControl is created first, and the address of the resulting gadget   */
/*  returned by GadTools is placed in place of the GTControl pointer.	  */
/*  The GTGT_NEXTDATATOGADGETADDRESS tag is turned into a
TAG_IGNORE.	  */
/*  These changes are actually performed on a duplicate of the TagList,   */
/*  so the original taglist is unmodified for future calls to GTRequest.  */
/**************************************************************************/

#define GTGT_NEXTDATATOGADGETADDRESS
GTCT_NEXTDATATOGADGETADDRESS

/**************************************************************************/
/*  For ImageButton PseudoKind						  */
/**************************************************************************/

#define GTPK_Image (TAG_GTR_BASE + 5)         /* Arg = struct Image * */
#define GTPK_Toggleselect (TAG_GTR_BASE + 6)  /* Arg = T/F */
#define GTPK_SelectedImage (TAG_GTR_BASE + 7) /* Arg = struct Image * */
					      /* If not specified, GADGHCOMP
						    used */
#define GTPK_Toggled GTCT_TOGGLED	      /* Arg = T/F */


/************************************************************************/
/****			   Info for EditList PseudoKind 	     ****/
/************************************************************************/

#define GTPK_Remember (TAG_GTR_BASE + 5) /* Arg = struct Remember **
*/
#define GTPK_List     GTLV_Labels	 /* Arg = struct List * */
#define GTPK_Alpha    (TAG_GTR_BASE + 7) /* Arg = T/F */
#define GTPK_NodeSize (TAG_GTR_BASE + 8) /* Arg = ULONG */
#define GTPK_SetList  (TAG_GTR_BASE * 9) /* Arg =
						void (*SetList)
						    (GTRequest *,
						     GTControl *,
						     List *);

					    This should Attach/disattach
					    list to all controls associated
					    with list, so changes will show
					    up in all ListView gadgets.
					  */



Control Flags
These are defined in GTRequest.h:

/**************************************************************************/
/*	    These are flags for Control->Flags				  */
/**************************************************************************/

#define GTC_ATTROVERRIDESSTRING 8
    /* This indicates that control->Attribute should be used
	instead of converting the contents of a string gadgets
	buffer to the appropriate type and using this value.
    */
#define GTC_PSEUDOKIND 16
    /* Specify this, and the control is assumed to be of a user type.
       GTControl->Kind should point to a string which gives the class
       of this control.  The local custom control class list, and then
       the global list are searched to find the function to create this
       type.  See struct {"GTPKind" LINK GTPKindStructure} for more info.
    */


#define GTC_INTERNALCONTROL 32	     /* If Pseudo controls need to
add
					      other controls to the requester
					      They should call AllocControl
					      to do so and then set one of these
					      2 flags.	The first marks
					      this as a pseudo control which
					      will be removed from the control
					      list when the request is ended
					      and freed.
					      The second indicates the same
					      thing, but in addition tells
					      GTRequest not to take any action
					      to initialize this control.
					      (It's Gadget will not be
					       created; it is assumed to have
					       already been created)
					    */
#define GTC_INTERNALCONTROLIGNORE 64


#define GTC_INITFROMDATA 2
#define GTC_STOREDATA 4



Request Flags
These are defined in GTRequest.h:

/**************************************************************************/
/*		These flags are for use in Request->Flags		  */
/**************************************************************************/

#define GT_INITFROMDATA 2
#define GT_STOREDATA	4


/**************************************************************************/
/*		Synonyms for above flags, can be used in either 	  */
/*		    Control->Flags or Request->Flags			  */
/**************************************************************************/

#define INITFROMDATA GT_INITFROMDATA
#define STOREDATA GT_STOREDATA



Control Field Types
These are defined in GTRequest.h:

/**************************************************************************/
/* These are the data types that can be copied between struct fields and
*/
/*	    Controls.							  */
/**************************************************************************/

#define FLD_NONE  0  /* No data is copied to or from structure */
#define FLD_SHORT 1
#define FLD_LONG 2
#define FLD_FLOAT 3  /* This uses GTFLOAT typedef, must be 4 bytes in length
*/
		     /* It is assumed you are using a STRING_KIND control for
			adjusting floats.  If you are not, you will need to
			override default setting/reading code in the particular
			control
		     */
#define FLD_BYTE   4
#define FLD_POINTER 5

/* The Bit field storage types require that the field given be of type
    ULONG!!
*/
#define FLD_BOOLBIT 6 /* SETFLAG(field,1<<control->Bit,control->Attribute) */
#define FLD_ATTRBIT 7 /* field=1<<control->Attribute */
		      /* The above (ATTRBIT) is especially useful for
			 LISTVIEWS, MX_KINDS, etc, where you are given
			 an ordinal position and you wish to encode it
			 a ULONG
		      */

/*  These next 2 can be written into the data structure,
    but they can't be written into the gadgets without special code
    specified for the appropriate control.  You probably won't use them.   */

#define FLD_ORATTR  8 /* field|=control->Attribute */
#define FLD_ORATTRBIT 9 /* field|=1<<control->Attribute */


#define FLD_STRINGINSTRUCT 10 /* if your structure looks like this:
				    struct mystruct {
					type1 field1;
					type2 field2;
					...
					UBYTE TheField[X];
					type3 field4;
					type4 field5;
					...
				    };
				  Then use this flag to store data in
				  TheField
			       */

#define FLD_STRINGPOINTEDTOINSTRUCT 11 /* if your structure looks like this:
					      struct mystruct {
						  type1 field1;
						  ...
						  UBYTE *TheField;
						  typeX FieldX;
						  ...
					      };
					   Then use this flag to copy the
					   string to the buffer pointed to
					   by TheField
				       */

#define FLD_STRINGPTR 12  /* if your structure looks like the one above
			     (for STRINGPOINTEDTOINSTRUCT) and you
			     want to set TheField=control->Attribute
			     (without performing a strcpy)
			     use this.
			  */



MessageClass Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		    MessageClass structure				  */
/**************************************************************************/
/*  Use this to set up handling routines for classes of messages or	  */
/*  sequences of messages not supported by IGRequest.  (Shift Click,      */
/*  Triple Click, etc.) 						  */
/**************************************************************************/

struct MessageClass {
    UBYTE *Name; /* Name of this message class, case significant */
    BOOL  (*IsType) (struct GTRequest *,struct IntuiMessage *,struct GTControl
*,struct MessageHandler *mh);
	/* Called on every message.  Should return 1 if the message
	    constitutes the correct type, 0 otherwise */
};



MessageHandler Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		    MessageHandler structure				  */
/**************************************************************************/

struct MessageHandler {
    struct MessageHandler *Next;
    UBYTE *Name; /* Name of class to which this handler belongs. */

    BOOL (*IsType) (struct GTRequest *,struct IntuiMessage *,
		    struct GTControl *,struct MessageHandler *);

	/* if this is a member of a class (Name!=NULL) and GTRequest can find
	    the MessageClass struct for this class, (either in its global list,
	    or its GTRequest list) this will be initialized; hence it can be
	    left NULL.	If this Handler is unique, and doesn't belong to
	    a class, or you would like to override the class default IsType
	    function, enter a function pointer here.
	*/

    void (*HandlerFunction) (struct GTRequest *,struct IntuiMessage *,
			      struct GTControl *,struct MessageHandler *);
	/* If IsType () returns 1, this is called */

	/* The address of this structure is passed to the HandlerFunction.
	   Hence, you can make custom structures embedding this one
	   to pass additional data to this function if you like
	*/
};



GTControl Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		    GTControl structure 				  */
/**************************************************************************/

struct GTControl {
    struct GTControl *Next;
    ULONG  Kind;
    ULONG  Flags;
    struct TagList *GadgetTags;
    struct TagList *ControlTags;
    struct NewGadget *NewGadget;
    struct Gadget    *Gadget;
    struct MessageHandler *MsgHandlerList;

    USHORT  ASCIICommand;   /* do not use qualified characters here */
			    /* use Qualifier below  */

    USHORT  RawKeyCommand;  /* Will automatically be filled in (using
current
				keymap) if ASCIICommand is filled in */
    USHORT  Qualifier;
    UBYTE   Pad1;
    UBYTE   Pad2;

    BOOL (*HandleKeyCommand) (struct GTRequest *,struct GTControl
*,struct IntuiMessage *);
	/*  If this is non-zero, it is called everytime a RAWKEY message is
	    received to check if the RAWKEY message is a keyboard command
	    for this control, and if so to take whatever action is necessary.
	    If it is not present, default processing is done based on the
	    above vaules.
	    Return True if this was a valid Keyboard command for your control,
	    False otherwise.
	*/

    USHORT  FieldOffset;
    USHORT  FieldType;
    USHORT  FieldSize;
    UBYTE   FieldBit;
    UBYTE   Pad3;
    ULONG   Attribute; /* Except for Kinds STRING_KIND and INTEGER_KIND
			   message processing functions
			   Should Cause this to contain the value
			   of the GTGadget to be stored to the data structure */

    ULONG   AttributeTag; /* Used in setting Gadget Attribute from data struct
info */

    void (*SetGadgetFromData) (struct GTRequest *,struct GTControl *,APTR);
	/*  If this is non-NULL, it is called to initialize the control from
	    information given in GTRequest->DataStruct.  APTR points to the
	    field within DataStruct which this control is associated with.
	    If not specified (NULL), default processing is used (assuming
	    INITFROMDATA flag is set) */

    void (*SetDataFromGadget) (struct GTRequest *,struct GTControl *,APTR);
	/* If this is non-NULL, it is called to copy the data represented
	   by the control into the data structure.  The arguments are the
	   same as above.  Again, if not specified, default processing is
	   used (assuming STOREDATA flag is set)
	*/

    void (*GUpUpdateControl) (struct GTRequest *,struct GTControl *,struct
IntuiMessage *);
    void (*GDownUpdateControl) (struct GTRequest *,struct GTControl *,struct
IntuiMessage *);
	   /* If either of these is non-null, they will be called every time
	      this control recieves either a GadgetUp or GadgetDown message.
	      They should update the GTControl->Attribute field as required
	      by the contents of the passed message.  If these values are null,
	      defaults are supplied for:
		    CHECKBOX_KIND, MX_KIND, CYCLE_KIND, SCROLLER_KIND,
		    SLIDER_KIND, LISTVIEW_KIND, PALETTE_KIND,
		    STRING_KIND, and INTEGER_KIND
	      If these values are 0xffffffff (-1L) no function is called
	      at all for this control.
	    */

    void (*SetAttrs) (struct GTRequest *,struct GTControl *,struct TagItem *);
	/* If this is Non-Null this is called instead of GT_SetGadgetAttrs
	   to set an attribute.  It will (and should) usually pass its
	   data on to GT_SetGadgetAttrs. Particularly useful for pseudo-
	   controls.
	*/
    APTR   UserData;
};



GTPKind Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		    GTPKind structure					  */
/*			Used for setting up additional pseudokinds	  */
/**************************************************************************/

struct GTPKind {
    UBYTE *Name;
    struct Gadget * (*Create) (struct GTPKind *,struct Gadget *,struct
GTControl *,struct GTRequest *,struct VisualInfo *);
    void (*Destroy) (struct GTPKind *,struct GTControl *,struct GTRequest *);
};



GTMenuInfo Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		  GTMenuInfo structure					  */
/*		   Used for linking menu events to functions to be called */
/**************************************************************************/

struct GTMenuInfo {
    USHORT Code;
    void (*Function) (struct GTRequest *,struct IntuiMessage *);
};



GTReqSet Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*			GTReqSet structure				  */
/*			  Used for opening many requesters simultaneously */
/**************************************************************************/

struct GTReqSet {
    struct List List;
    struct MsgPort *MsgPort;
};



GTRequest Structure
This is defined in GTRequest.h:

/**************************************************************************/
/*		    GTRequest structure 				  */
/* This is the top level structure which contains pointers to all the	  */
/*  others' lists.  A pointer to one of these structures is passed to     */
/*  GTRequest.								  */
/**************************************************************************/

struct GTRequest {
    struct TagList *NewWindowTags; /* pointer to NewWindow to open */
				 /* pointer to opened window will be
				    placed in IGRequest->Window field */
    struct Window *Window; /* Pointer to already opened window
			       If you would like GTRequest to use a window
				you open, place a pointer to it here,
				and leave NewWindowTags NULL
			   */
    struct NewMenu *Menus;
    struct GTMenuInfo *MenuInfo;
    struct GTControl *Controls; /* pointer to first control in requester to use */
    ULONG Flags;
    struct TagItem *RequestTags;
    struct Border *Borders;  /* pointer to Border list to draw into window */
    struct Image *Images;    /* pointer to Image list to draw into window */
    struct IntuiText *ITexts; /* pointer to IntuiText list to write into window */
    void   (*InitFunction) (struct IGRequest *); /* function to call when
requester first opened */

    LONG Terminate; /* Can be set by outside routines to */
		 /* force request to end, >0==FillStruct, <0==!FillStruct */

    struct MsgPort *IComPort; /* Internal use only.  Initialize to 0 */

    APTR DataStruct;
    void (*EndFunction) (struct IGRequest *,struct IntuiMessage *);
     /* To be called when requester ends.
      * This is called after any EndList EndFunction */

    void (*LoopFunction) (struct IGRequest *);
			     /* This function is called repeatedly
			      * while there is not a message at the
			      * Window port and while CallLoop!=0
			     */

    ULONG CallLoop;
    ULONG LoopBitsUsed;

    ULONG AdditionalSignals; /* Additional signals to Wait on */
    BOOL  (*SignalFunction) (struct GTRequest *,ULONG);

	/* Called before IGRequest goes into wait state.  Use this to test
	    Ports that you are waiting on through AdditionalSignals for messages.
	    Process one message at a time.  Return 0 if IGRequest can go
	    into a wait state, 1 if you require further processing time,
	    in which case your function will be called again (after checking
	    the window port, calling the loopfunction, etc.)


	     SignalFunction (IGRequest,Signals);
	*/


    struct MessageClass *LocalMsgClassList; /* Must be NULL terminated array
*/
    struct GTPKind *LocalPKindClassList; /* Must be NULL terminated array */

    struct MessageHandler *MsgHandlerList;

    ULONG  AppIDCMP; /* Internal use only! */
    struct IntuiMessage *LastGadgetEvent;  /* For use by GTRequest, Message
Handlers */
    struct IntuiMessage *BeforeLastGadgetEvent;
    struct Remember *GTKey; /* Internal use. Do not free (will be freed
				    on exit from GTRequest) */
    struct GTControl *ActiveControl;
    APTR InternalData; /* Internal use only, init to zero */
    struct GTControl *EndControl; /* Pointer to control that caused requester
					to terminate */
    struct MessageHandler *EndMsgHandler; /* Pointer to MsgHandler that
						caused requester to
						terminate
					  */
    APTR UserData;
};



EndGTRequest Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*  Call this to end requester */

__far void EndGTRequest(struct GTRequest *req,LONG terminate,
		   struct MessageHandler *mh,struct GTControl *gtc);



GTSendIntuiMsg Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   This function sends a simulated IntuiMessage to a GTRequest.
    GTRequest will normally take care of freeing the message.
*/

__far BOOL GTSendIntuiMsg (struct GTRequest *req,ULONG Class,ULONG
Code,
		    USHORT Qualifier,APTR IAddress);

#define FreeIntuiMsg(x) FreeMem(x,sizeof(struct IntuiMessage))



GTKeyClickFunction
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   This function simulates a user keypress to the requester
*/

__far BOOL GTKeyClick (struct GTRequest *req,UBYTE *keyinfo,UBYTE key);



SetIntControl Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   This function will set an Integer_Kind control to the given number,
    and will simulate appropriate messages, making it appear to the program
    as if the user entered the new number
*/

__far void SetIntControl (struct GTRequest *req,struct GTControl *gtc,LONG
number);



SetStringControl Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   This function will set a String_Kind control to the given string,
    and will simulate appropriate messages, making it appear to the program
    as if the user entered the new string
*/

__far void SetStringControl (struct GTRequest *req,struct GTControl
*gtc,UBYTE *string);



GTGadgetClickFunction
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   This function will simulate a user mouse press over the given gadget
    The corresponding macro simulates a user mouse press over a control
*/

__far BOOL GTGadgetClick(struct GTRequest *req,struct Gadget *gadg);

#define GTControlClick(r,g) GTGadgetClick(r,(g)->Gadget)



GTBlockInput Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    GTBlockInput Function opens an blank intuition requester on top
    of an IGRequest, thereby blocking it from receiving input
*/
__far void GTBlockInput(struct GTRequest *req);



GTUnBlockInput Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    GTUnBlockInput closes blank requester opened by GTBlockInput, thereby
    permitting messages to come through again
    Calls to GTBlock/UnBlockIGInput can be nested; a nesting depth count
							is kept
*/
__far void GTUnBlockInput(struct GTRequest *req);



GTReqModifyIDCMP Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* You must use this instead of ModifyIDCMP!! */

__far void GTReqModifyIDCMP(struct GTRequest *req,ULONG IDCMP);



SetControlAttrsA Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* You must use this instead of GT_SetGadgetAttrsA */

__far void SetControlAttrsA (struct GTRequest *req,struct GTControl
*gtc,struct TagItem *ti);



SetControlAttrs Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* You must use this instead of GT_SetGadgetAttrsA */

__far void SetControlAttrs(struct GTRequest *req,struct GTControl *gtc,Tag
tag1,...);



SendMessageToControl Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function searches through a GTControl's MessageHandler list
	for a MessageHandler of the given class, and then calls that
	MessageHandler's HandlerFunction.  IsType isn't called;
	the message is by definition of the given type.
	This allows you to set up additional classes of messages
	for controls and Pseudocontrols, as a class can be named
	anything you would like.  The EditList pseudokind uses
	this stategy.
*/

__far void SendMessageToControl(struct GTRequest *req,struct GTControl
*gtc,struct IntuiMessage *msg, UBYTE *class);



AddInternalControl Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function adds an internal Control to a GTRequest's control list.
    An internal control is one that is created by a pseudokind and is removed
    from the list when the requester is terminated.  EditList kind uses this
    function.
*/

__far void AddInternalControl(struct GTRequest *req,struct GTControl
*parent,struct GTControl *gtc,ULONG type);



AllocNewGadgetFunction
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function allocates a NewGadget structure on the Request's ReqKey,
	which is automatically freed.  Used for creating internal controls.
	Used by EditList PKind.
*/

__far struct NewGadget *AllocNewGadget(struct GTRequest *req,struct
NewGadget *sg,
					    LONG x,LONG y,LONG w,LONG h);



Termination Info Macros
These are defined in GTRequest.h:

#define GetTerminate(req) ((req)->Terminate)
#define GetEndControl(req) ((req)->EndControl)
#define GetEndMsgHandler(req) ((req)->EndMsgHandler)



FindGadgetControl Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    Takes pointer to linked list of controls, and finds and returns
    the one that is related to the given gadget
*/
__far struct GTControl *FindGadgetControl(struct GTControl *gtc,struct
Gadget *g);



RawKeyToAscii Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
  Takes RAWKEY code and qualifier (from an IntuiMessage) and returns
   ASCII equivalent
*/
__far UBYTE RawKeyToAscii (USHORT code,USHORT qual);



ASCIIToRawKey Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* Takes ASCII char and returns Rawkey code.  ASCII code must correspond
to
   letter painted on keyboard keycap (the unqualified value).  Qualifier
   must be determined as follows (Under IGRequest which does not
   differentiate between right and left):

	SHIFT =  1
	ALT   = 16
	CTRL  =  8
	AMIGA = 64

   Returns -1 error.
*/

__far SHORT ASCIIToRawKey (char c);



ClearWindow Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    ClearWindow Function, clears inside of window to background (0)
    Used by GTRequest on exit if it doesn't close the window.
*/
__far void ClearWindow (struct Window *w);



FirstItem Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function returns a pointer to the first item in an exec list,
	or NULL if the list is empty
*/

struct Node *FirstItem(struct List *l);



NextItem Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function returns a pointer to the next node in an exec list,
	or NULL if the given node is the last valid node
*/
struct Node *NextItem(struct Node *n);



NodeValid Macro
This is defined in GTRequest.h:

/*
    This macro determines whether a node is valid (contains data or is
	part of the ListHead structure)
*/
#define NodeValid(n) ((n)->ln_Succ->ln_Succ)



cismember Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function returns the ordinal position +1 of c in set.
     If c isn't in set, it returns 0.  set is a string (NULL delimited).
*/
__far int cismember (char c,char *set);



delchars Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* deletes n chars starting at position p from string s */

__far void delchars (char *s,USHORT p,USHORT n);



strelim Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
   when k is true, only chars in elim allowed, otherwise,
    only chars not in elim allowed
*/
__far BOOL strelim (char *s,char *elim,BOOL k);



MakeBox Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
  Generates the necessary structures and SHORT values for a two pixel thick,
   two color box.  Returns pointer to first of two Border structures.  All
   information is allocated on the Remember key
*/

__far struct Border *MakeBox (USHORT w,USHORT h,UBYTE c1,UBYTE c2,struct
Remember **key);



DetachUserPort Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function will detach the UserPort from a window so that
	the window may be closed without closing the UserPort,
	important if several windows are sharing a UserPort.
*/

void DetachUserPort(struct Window *win);



GTAllocCLBit Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* Allocates and returns a CallLoop Bit for a GTRequester */
BYTE GTAllocCLBit (struct GTRequest *req);



GTFreeCLBit Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/* Frees a CallLoop Bit for a GTRequester */
void GTFreeCLBit (struct GTRequest *req,UBYTE bit);



InitReqSet Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function initializes a ReqSet structure.  It must be called
	before any requests are added to the ReqSet.
*/

void InitReqSet(struct GTReqSet *rs);



EndAllRequests Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function calls EndGTRequest for each requester in a ReqSet,
	Causing them all to end as soon as ProcessReqSet is called/returned to
*/

void EndAllRequests(struct GTReqSet *rs,LONG terminate,struct
MessageHandler *mh, struct GTControl *gtc);



AddGTRequest Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    This function opens a requester, allocates the gadgets, displays imagery,
	etc, and adds the requester to the ReqSet
*/

LONG AddGTRequest(struct GTReqSet *rs,struct GTRequest *gtr);



ProcessReqSet Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    Call This function to process messages sent to all requesters in
	the given ReqSet.  Each requester will work just as if it
	had been opened by GTRequest and was running by itself.
	More requesters can be added to the set while ProcessReqSet is
	running.  ProcessReqSet returns only when all requesters in the
	ReqSet have terminated.
*/
__far void ProcessReqSet (struct GTReqSet *set);



DuplicateRequest Function
This is defined in GTRequest.c and prototyped in GTRequest.h:

/*
    You cannot call AddGTRequest and add the same requester to a ReqSet
	twice.	You must duplicate the Requester and add the duplicate
	to the ReqSet.	The below function does this.  When the request
	is finished, free the key to recover memory.
*/

struct Request *DuplicateRequest (struct Remember **key,struct GTRequest
*req);



CreateEditListKind Function
/***********************************************************************/
/*  Set a GTPKind's Create field to this function to establish a       */
/*  Edit List pseudokind.					       */
/***********************************************************************/

__far struct Gadget *CreateEditListKind(struct GTPKind *kclass,struct Gadget *gad,
				  struct GTControl *gtc,struct GTRequest *req,
				  struct VisualInfo *vinfo);



AddNodeAlpha Function
/***********************************************************************/
/*  This function adds a node to a list in alphabetical order by       */
/*  Node->ln_Name.  If NODUPLICATES flag is specified, node will not   */
/*  be added if another node with the same name is already in the      */
/*  list.  1 is returned if the node is added, 0 otherwise.	       */
/***********************************************************************/

#define NODUPLICATES 1
LONG AddNodeAlpha(struct List *l,struct Node *n,ULONG flags);




CountNodesInList Function
/***********************************************************************/
/* CountNodesInList returns the number of nodes in the given list.     */
/***********************************************************************/

ULONG CountNodesInList(struct List *l);




AddNamedNodeToList Function
/***********************************************************************/
/* AddNamedNodeToList allocates a node on the given key, allocates a   */
/* string big enough for the given name on the given key, and adds the */
/* new node to the list.  If the ALPHA flag is specified the Node is   */
/* added in alphabetical order					       */
/***********************************************************************/

#define ALPHA 1
struct Node *AddNamedNodeToList(struct Remember **key,struct List *l,UBYTE *name,
    ULONG size,ULONG flags);




ChangeNodesName Function
/***********************************************************************/
/* ChangeNodesName allocates enough room on the given key for the      */
/* new name, and assigns the node->ln_Name to the newly allocated      */
/* memory.  It then copies the given name into the newly allocated     */
/* memory.							       */
/***********************************************************************/

UBYTE ChangeNodesName(struct Remember **key,struct GTRequest *req,
    struct GTControl *gtc,struct List *l,struct Node *n,UBYTE *newname);




AddEntryToListBox Function
/***********************************************************************/
/* AddEntryToListBox calls AddNamedNodeToList to add a node with the   */
/* given name to a list box.  It also detaches the list from the list  */
/* box before beginning, and reattaches it when its done.	       */
/***********************************************************************/

struct Node *AddEntryToListBox(struct Remember **key,struct GTRequest *req,
    struct GTControl *gtc,struct List *l,UBYTE *name,ULONG size,ULONG flags);




RemoveEntryFromListBox Function
/***********************************************************************/
/*  RemoveEntryFromListBox detaches the given list from the list box,  */
/*  removes the given node from the list, and reattaches the list to   */
/*  the list box.  It does not free the node.			       */
/***********************************************************************/

UBYTE RemoveEntryFromListBox(struct GTRequest *req,struct GTControl *gtc,
    struct List *l,struct Node *n);




NodeToOrd Function
/***********************************************************************/
/*  NodeToOrd returns a node's ordinal position in the list.  The      */
/*  first node in the list is 0, the second 1, and so on.	       */
/*  Convenient if you want to set a ListBox's selected attribute to    */
/*  a given node, but know only a node address and not its ordinal     */
/*  position, which Intuition requires. 			       */
/***********************************************************************/

ULONG NodeToOrd(struct List *l,struct Node *n);




OrdToNode Function
/***********************************************************************/
/*  OrdToNode returns a node address from an ordinal position in the   */
/*  list (like what you get out of msg->Code or Control->Attribute     */
/*  when dealing with a ListView_Kind). 			       */
/***********************************************************************/

struct Node *OrdToNode(struct List *l,ULONG ord);



