[comp.sources.amiga] v02i075: gimme.lib - misc library routines, Part02/07

page@swan.ulowell.edu (Bob Page) (12/02/88)

Submitted-by: oscvax!jan@uunet.UU.NET (Jan Sven Trabandt)
Posting-number: Volume 2, Issue 75
Archive-name: libraries/gimme.2

#	This is a shell archive.
#	Remove everything above and including the cut line.
#	Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar:    Shell Archiver
#	Run the following text with /bin/sh to create:
#	DOCS.part2
# This archive created: Thu Dec  1 19:44:31 1988
cat << \SHAR_EOF > DOCS.part2
 *		short err;
 *
 * INPUTS:	struct IOStdReq *ioreq;     ioreq returned by addInputHandler
 *
 * DESCRIPTION: Remove an input handler to the system (previously added by
 *		addInputHandler).
 *
 *		Note: the contents of the ioreq must be unchanged since the
 *		preceding addInputHandler call.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	addInputHandler
 */

/*
 * NAME:	gimmeBorder
 *
 * SYNOPSIS:	border = gimmeBorder( memheadptr, xsize, ysize );
 *		struct Border *border;
 *
 * INPUTS:	void	**memheadptr;	pointer to chained-memory head
 *		SHORT	xsize;		total width in pixels
 *		SHORT	ysize;		total height in pixels
 *
 * DESCRIPTION: Allocate and initialize a Border structure.
 *		If xsize and ysize are both strictly positive, the five
 *		coordinates for the border are set up as well.
 *
 *		Note: the draw mode and colours are set to JAM1 and 1, 0.
 *
 *		If memheadptr is non-NULL, chainAllocMem is used and you
 *		should use chainFreeMem eventually to free the memory;
 *		otherwise AllocMem is used and you must FreeMem on each
 *		separately allocated component.
 *
 * RESULTS:	Returns pointer to Border, or NULL.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem
 */

/*
 * NAME:	gimmeImage
 *
 * SYNOPSIS:	image = gimmeImage( memheadptr, depth, width, height );
 *		struct Image *image;
 *
 * INPUTS:	void	**memheadptr;	    pointer to chained-memory head
 *		SHORT	depth;		    number of bit-planes for image
 *		SHORT	width;		    width of image in pixels
 *		SHORT	height; 	    height of image in pixels
 *
 * DESCRIPTION: Allocate and initialize an Image structure.
 *		If depth, width and height are all non-zero, sufficient
 *		contiguous chip memory is allocated for the image data;
 *		the pointer is stored in the image's ImageData field.
 *
 *		If memheadptr is non-NULL, chainAllocMem is used and you
 *		should use chainFreeMem eventually to free the memory;
 *		otherwise AllocMem is used and you must FreeMem on each
 *		separately allocated component.
 *
 * RESULTS:	Returns pointer to Image, or NULL.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem
 */

/*
 * NAME:	gimmeIntuiText
 *
 * SYNOPSIS:	itext = gimmeIntuiText( memheadptr, s, textattr, width );
 *		struct IntuiText *itext;
 *
 * INPUTS:	void	**memheadptr;	    pointer to chained-memory head
 *		UBYTE	*s;		    text string
 *		struct TextAttr *textattr;  pointer to font, or NULL
 *		SHORT	width;		    total width; for optional centering
 *
 * DESCRIPTION: Allocate and initialize a IntuiText structure.
 *		The textattr can be NULL to use the default font.
 *
 *		NOTE: width is "optional":
 *		if width is positive, then the string is centered in the
 *		field that is width pixels wide.
 *
 *		Note: the draw mode and colours are set to JAM2 and 1, 0.
 *
 *		If memheadptr is non-NULL, chainAllocMem is used and you
 *		should use chainFreeMem eventually to free the memory;
 *		otherwise AllocMem is used and you must FreeMem on each
 *		separately allocated component.
 *
 * RESULTS:	Returns pointer to IntuiText, or NULL.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem
 */

/*
 * NAME:	deadKeyConvert
 *
 * REQUISITES:	struct ConsoleDevice *ConsoleDevice;	properly initialized
 *
 * SYNOPSIS:	len = deadKeyConvert( imsg, buf, bufsize, keymap );
 *		SHORT len;
 *
 * INPUTS:	struct IntuiMessage *imsg;	pointer to Intuition message
 *		UBYTE	*buf;			address of a buffer
 *		USHORT	bufsize;		size of the buffer "buf"
 *		struct KeyMap	*keymap;	pointer to a KeyMap, or NULL
 *
 * DESCRIPTION: Takes an Intuition RAWKEY message and processes it.
 *		The result will be "cooked" keys and key conversions placed
 *		in the buffer "buf".
 *
 *		NOTE: you must have a global variable named ConsoleDevice,
 *		declared as a "struct ConsoleDevice *", already initialized by
 *		extracting the "library" pointer from the console.device
 *		with code similar to the following:
 *		    struct IOStdReq ioreq;
 *		    err = OpenDevice("console.device", <unit-no>, &ioreq, 0L);
 *		    { check for error }
 *		    ConsoleDevice = (struct ConsoleDevice *) ioreq.io_Device;
 *
 *		Also, some versions of the Axtec C "functions.h" file have
 *		a bug: it declares the function "ConsoleDevice()" which
 *		is non-existant and that line should be deleted.
 *		Note: this is *very* similar to the DeadKeyConvert() function
 *		from the Amiga Enhancer Manual.
 *
 * RESULTS:	Returns the actual number of characters put into the buffer
 *		or -1 if the buffer overflowed
 *		or -2 if the IntuiMessage is not of class RAWKEY
 *		or -3 if parameters are invalid (if checking is done)
 */

/*
 * NAME:	chainAllocMem
 *
 * SYNOPSIS:	memptr = chainAllocMem( headptr, size, type );
 *		void *memptr;
 *
 * INPUTS:	void	**headptr;	ptr to the memory-chain head
 *		ULONG	size;		size of desired memory
 *		ULONG	flags;		type of memory ala AllocMem()
 *
 * DESCRIPTION: Allocate requested memory and possibly chain it to *headptr.
 *
 *		NOTE: if headptr is non-NULL, the chain head pointer MUST be
 *		initialized to NULL before its first use, and
 *		the memory returned must be freed by chainFreeMem only!!
 *
 *		NOTE: if headptr is NULL, then a normal AllocMem() is done
 *		and absolutely no chaining occurs and you are responsible
 *		for freeing the memory with a FreeMem(),
 *
 * RESULTS:	Returns pointer to requested chunk of memory, or NULL.
 *		Note that *headptr is updated if headptr is a valid pointer.
 *
 * SEE ALSO:	chainFreeMem, AllocMem, linkChainMem
 */

/*
 * NAME:	chainFreeMem
 *
 * SYNOPSIS:	chainFreeMem( head );
 *
 * INPUTS:	void	*head;		    head of memory-chain to be freed
 *
 * DESCRIPTION: Free all memory chained to this head (including the head)
 *
 *		NOTE: head must be NULL or altered by chainAllocMem only!
 *
 * SEE ALSO:	chainAllocMem, pluckChainMem
 */

/*
 * NAME:	linkChainMem
 *
 * SYNOPSIS:	err = linkChainMem( headptr, head );
 *		short err;
 *
 * INPUTS:	void	**headptr;	    ptr to memory-chain head
 *		void	*head;		    secondary chain head
 *
 * DESCRIPTION: Link secondary chain (pointed at by head) to the front of the
 *		memory-chain (pointed at by *headptr), updating *headptr.
 *
 *		NOTE: head and the head pointed at by headptr must be NULL or
 *		altered by chainAllocMem only!
 *
 * RESULTS:	Non-zero on error. Note that *headptr may be updated.
 *
 * SEE ALSO:	chainAllocMem
 */

/*
 * NAME:	pluckChainMem
 *
 * SYNOPSIS:	err = pluckChainMem( headptr, mem );
 *		short err;
 *
 * INPUTS:	void	**headptr;	    ptr to memory-chain head
 *		void	*mem;		    actual pointer to memory chunk
 *
 * DESCRIPTION: Search for the "mem" entry in the memory-chain list pointed at
 *		by headptr; if it is in the list, unlink it and free the memory,
 *		otherwise it will not be freed so that memory lists are not
 *		corrupted.
 *		NOTE: mem must be a "real" pointer returned by chainAllocMem.
 *
 *		NOTE: the head pointed at by headptr must be NULL or
 *		altered by chainAllocMem only!
 *
 * RESULTS:	Non-zero on error, eg. headptr is NULL.
 *		Note that *headptr may be updated.
 *		If successful, the memory "mem" is freed and therefore unusable.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem
 */

/*
 * NAME:	gimmeMenu
 *
 * SYNOPSIS:	menu = gimmeMenu( memheadptr, left, width, name, flags );
 *		struct Menu *menu;
 *
 * INPUTS:	void	**memheadptr;	pointer to chained-memory head
 *		SHORT	left;		left offset in pixels
 *		SHORT	width;		total width in pixels, or -1
 *		UBYTE	*name;		name for menu
 *		ULONG	flags;		Menu flags
 *
 * DESCRIPTION: Allocate and initialize a Menu structure.
 *		Width should include room for a checkmark if necessary.
 *		If width is -1 (negative), a feeble attempt at calculating
 *		a width is made (9 pixels per character).
 *
 *		If memheadptr is non-NULL, chainAllocMem is used and you
 *		should use chainFreeMem eventually to free the memory;
 *		otherwise AllocMem is used and you must FreeMem on each
 *		separately allocated component.
 *
 * RESULTS:	Returns pointer to Menu, or NULL.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem, gimmeMenuItem
 */

/*
 * NAME:	gimmeMenuItem
 *
 * REQUISITES:	struct GfxBase *GfxBase;    properly initialized - but only if
 *					      text && height == -1  && !textattr
 *
 * SYNOPSIS:	item = gimmeMenuItem( memheadptr, left, width, height,
 *					command, name, textattr, flags );
 *		struct MenuItem *item;
 *
 * INPUTS:	void	**memheadptr;	    pointer to chained-memory head
 *		SHORT	left;		    left offset in pixels
 *		SHORT	width;		    total width in pixels, or -1
 *		SHORT	height; 	    total height in pixels, or -1
 *		BYTE	command;	    Command byte, if COMMSEQ flag set
 *		UBYTE	*name;		    name for menu item
 *		struct TextAttr *textattr;  pointer to font, or NULL
 *		ULONG	flags;		    MenuItem flags
 *
 * DESCRIPTION: Allocate and initialize a MenuItem structure.
 *		If ITEMTEXT flag set, then an IntuiText structure is created
 *		using the name and textattr (using INVERSVID drawing mode);
 *		otherwise:
 *		    treat "(struct Image *)name" as primary image
 *		    if HIGHIMAGE set, then treat
 *			"(struct Image *)textattr" as secondary image
 *		In either case, if width (and/or height) is -1 (negative)
 *		a suitable width (and/or height) is calculated. Further,
 *		if the CHECKIT or COMMSEQ flags are set, then CHECKWIDTH or
 *		COMMWIDTH respectively is added in to the calculated width
 *		(not LOWCHECKWIDTH nor LOWCOMMWIDTH since I can't tell the
 *		resolution and besides, no one really uses lo-res do they? :-)
 *
 *		NOTE: chainAllocMem is used and you
 *		should use chainFreeMem eventually to free the memory;
 *
 * RESULTS:	Returns pointer to MenuItem, or NULL.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem, gimmeMenu
 */

/*
 * NAME:	addMenuItem
 *
 * SYNOPSIS:	menucode = addMenuItem( menu, item, positem, possub,
 *					    numitem, myflags );
 *		ULONG menucode;
 *
 * INPUTS:	struct Menu	*menu;	    menu to which to add MenuItem
 *		struct MenuItem *item;	    item (or subitem) to add
 *		SHORT		positem;    position of item, or -1
 *		SHORT		possub;     position of subitem, or -1
 *		SHORT		numitem;    number of (sub)items to add, or -1
 *		ULONG		myflags;    flags for this routine
 *
 * DESCRIPTION: Add a (list of) MenuItem to a Menu as an item or a subitem,
 *		depending on the flags.
 *		If the subitem-flag is set in myflags, then positem is used to
 *		locate a MenuItem to which "item" is to be added as a subitem;
 *		 NOTE: in this case a MenuItem must already exist in the menu.
 *
 *		Actually add numitem MenuItems from a list starting with "item",
 *		where a numitem of -1 means all the MenuItems in the list.
 *		Either positem or possub may be -1 (ie. negative) which means
 *		the end of the list; otherwise use normal menu(item) position
 *		numbers, ie. 0 means the first one, 1 means the second, etc.
 *
 *		The flags (see gimmelib/menustuff.h) dictate other options,
 *		such as automatic adjusting of top edges to compensate visually
 *		for the insertion of the menuitems (visually) in the middle or
 *		at the end of the menu.
 *		Note: the Intuition menucode depends on the physical position
 *		of the menuitem in the menu's chain (not the visual position).
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns menucode corresponding to position of (sub)item,
 *		or MENUNULL on error.
 *
 * SEE ALSO:	gimmeMenuItem, gimmeMenu, addMenu
 */

/*
 * NAME:	addMenu
 *
 * SYNOPSIS:	menucode = addMenu( menuptr, menu, posmenu, nummenu, myflags );
 *		ULONG menucode;
 *
 * INPUTS:	struct Menu	**menuptr;  pointer to menu ptr on which to add
 *		struct Menu	*menu;	    menu to add
 *		SHORT		posmenu;    position of menu, or -1
 *		SHORT		nummenu;    number of menus to add, or -1
 *		ULONG		myflags;    flags for this routine
 *
 * DESCRIPTION: Add nummenu Menus to a menustrip starting with "menu",
 *		where a nummenu of -1 means all the Menus in the list.
 *
 *		A posmenu of -1 (ie. negative) means the end of the list;
 *		otherwise use normal menu position numbers, ie. 0 means the
 *		first one, 1 means the second, etc.
 *
 *		NOTE: menuptr can point at a NULL pointer (ie *menuptr == NULL)
 *		which means that a "new" menu is begun with "menu".
 *
 *		The flags (see gimmelib/menustuff.h) dictate other options,
 *		such as automatic adjusting of left edges to compensate for
 *		the insertion of the menus (visually) in the middle or at the
 *		end of the menustrip.
 *		Note: the Intuition menucode depends on the physical position
 *		of the menu in the menustrip's chain (not the visual position).
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns menucode corresponding to position of menu,
 *		or MENUNULL on error.
 *
 * SEE ALSO:	gimmeMenu, gimmeMenuItem, addMenuItem
 */

/*
 * NAME:	removeMenuItem
 *
 * SYNOPSIS:	item = removeMenuItem( menu, item, positem, possub,
 *					    numitem, myflags );
 *		strut MenuItem *item;
 *
 * INPUTS:	struct Menu	*menu;	    menu from which to remove MenuItem
 *		struct MenuItem *item;	    item (or subitem) to remove, or NULL
 *		SHORT		positem;    position of item, or -1
 *		SHORT		possub;     position of subitem, or -1
 *		SHORT		numitem;    #(sub)items to remove, or -1
 *		ULONG		myflags;    flags for this routine
 *
 * DESCRIPTION: Remove a (list of) MenuItem to a Menu as an item or a subitem,
 *		depending on the flags.
 *		If the subitem-flag is set in myflags, then positem is used to
 *		locate a MenuItem from which "item" is to be removed as a
 *		subitem; NOTE: in this case a MenuItem must already exist in
 *		the menu.
 *
 *		If item is non-NULL (ie. you have an actual MenuItem address):
 *		actually remove numitem MenuItems from a list starting with
 *		"item", where numitem of -1 means all the MenuItems in the list;
 *		in this case, positem and possub are ignored.
 *
 *		Otherwise (if item is NULL):
 *		find the appropriate item [as specified by positem, and possub
 *		if the subitem-flag is set] and then actually remove numitem
 *		MenuItems starting with the found item, where numitem of -1
 *		means all the MenuItems in the list.
 *		Either positem or possub may be -1 (ie. negative) which means
 *		the end of the list; otherwise use normal menu(item) position
 *		numbers, ie. 0 means the first one, 1 means the second, etc.
 *
 *		The flags (see gimmelib/menustuff.h) dictate other options,
 *		such as automatic adjusting of top edges to compensate for the
 *		removal of the menuitems (effects visual offsets in the menu).
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns pointer to the (list of) MenuItem removed,
 *		or NULL on error.
 *
 * SEE ALSO:	addMenuItem, addMenu, removeMenu
 */

/*
 * NAME:	removeMenu
 *
 * SYNOPSIS:	menu = removeMenu( menuptr, menu, posmenu, nummenu, myflags );
 *		struct Menu *menu;
 *
 * INPUTS:	struct Menu	**menuptr;  pointer to menu ptr on which to add
 *		struct Menu	*menu;	    menu to remove, or NULL
 *		SHORT		posmenu;    position of menu, or -1
 *		SHORT		nummenu;    number of menus to remove, or -1
 *		ULONG		myflags;    flags for this routine
 *
 * DESCRIPTION: Remove a (list of) Menu from a menustrip.
 *
 *		If menu is non-NULL (ie. you have an actual Menu address):
 *		actually remove nummenu Menus from a list starting with
 *		"menu", where nummenu of -1 means all the Menus in the list;
 *		in this case, posmenu is ignored.
 *
 *		Otherwise (if menu is NULL):
 *		find the appropriate menu [as specified by posmenu], and then
 *		actually remove nummenu Menus starting with the found menu,
 *		where nummenu of -1 means all the Menus in the list.
 *		A posmenu of -1 (ie. negative) means the end of the list;
 *		otherwise use normal menu(item) position numbers,
 *		ie. 0 means the first one, 1 means the second, etc.
 *
 *		The flags (see gimmelib/menustuff.h) dictate other options,
 *		such as automatic adjusting of left edges to compensate for
 *		the removal of the menus (visually) in the middle or at the
 *		end of the menustrip.
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns pointer to the (list of) MenuItem removed,
 *		or NULL on error.
 *
 * SEE ALSO:	addMenu, addMenuItem, removeMenuItem
 */

/*
 * NAME:	adjustMenuItems
 *
 * SYNOPSIS:	err = adjustMenuItems( item, stop, topedge, mepos, myflags );
 *		short err;
 *
 * INPUTS:	struct MenuItem *item;	    item at which to start
 *		struct MenuItem *stop;	    first item not to alter, or NULL
 *		SHORT		topedge;    topedge for first menu item
 *		SHORT		mepos;	    pos of 1st item (for MutualExclude)
 *		ULONG		myflags;    flags for this routine
 *
 * DESCRIPTION: Adjust the TopEdge and/or MutualExclude fields of a list of
 *		MenuItems, depending on the flags.
 *
 *		Starting with "item" the adjustment is done for the entire list,
 *		OR until (but not including) "stop" is reached,
 *		OR only from "stop" until the end of the list
 *		-- all according to the flags (see gimmelib/menustuff.h).
 *
 *		The topedge and mutualexlude options are independant (and have
 *		separate flags), so you can mix and match when either one is
 *		done in a single call [eg. adjust topedges until "past" and
 *		mutualexcludes only from "past" onwards].
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeMenuItem, addMenuItem, gimmeMenu, addMenu
 */

/*
 * NAME:	adjustMenuLefts
 *
 * SYNOPSIS:	err = adjustMenuLefts( menu, stop, leftedge, myflags );
 *		short err;
 *
 * INPUTS:	struct Menu *menu;	menu at which to start
 *		struct Menu *stop;	first menu not to alter, or NULL
 *		SHORT	    leftedge;	leftedge for first menu given
 *		ULONG	    myflags;	flags for this routine
 *
 * DESCRIPTION: Adjust the LeftEdge field of a list of Menus, starting with
 *		leftedge and incremented using the widths of the menus.
 *
 *		Starting with "menu" the adjustment is done for the entire list,
 *		OR until (but not including) "stop" is reached -- according to
 *		the flags (see gimmelib/menustuff.h).
 *
 *		NOTE: this routine should only be used on a menustrip that is
 *		not attached to a window or guaranteed not to be actively used
 *		by Intuition (eg. by using the MENUVERIFY flag).
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeMenuItem, addMenuItem, gimmeMenu, addMenu
 */

/*
 * NAME:	gimmeMessage
 *
 * SYNOPSIS:	msg = gimmeMessage( size, replyport );
 *		struct Message *msg;
 *
 * INPUTS:	ULONG		size;		size of your message struct
 *		struct MsgPort	*replyport;	ptr to a reply port, or NULL
 *
 * DESCRIPTION: Allocate memory for an [extended] message struct,
 *		initializing the Node, Length and ReplyPort [enough to
 *		do a PutMsg() immediately].
 *		Node type set to NT_FREEMSG for consistency.
 *
 *		NOTE: size must be passed as a ULONG, *not* a short.
 *
 * RESULTS:	Returns pointer to an [extended] message struct of the
 *		specified size, or NULL on failure.
 *
 * SEE ALSO:	getRidOfMessage
 */

/*
 * NAME:	getRidOfMessage
 *
 * SYNOPSIS:	err = getRidOfMessage( msg );
 *		short err;
 *
 * INPUTS:	struct Message	*msg;	    pointer to initialized Message
 *
 * DESCRIPTION: Free the [extended] message struct, using its Length field.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeMessage
 */

/*
 * NAME:	gimmePicture
 *
 *		#include <gimmelib/picture.h>
 *
 * SYNOPSIS:	pic = gimmePicture( filename, myflags );
 *		PICTURE *pic;
 *
 * INPUTS:	UBYTE	*filename;	    name of iff ilbm file
 *		ULONG	myflags;	    flags for the routine
 *
 * DESCRIPTION: Read a picture (IFF/ILBM) from the specified file.
 *		Create and initialize a PICTURE structure for the picture.
 *		The flags specify whether chip memory for the bitplanes
 *		should be allocated contiguously or sequentially or either;
 *		these flags are the same as those used by gimmeBitPlanes,
 *		and are defined in <gimmelib/bitplane.h>.
 *		If possible, an error message is printed if anything goes
 *		wrong -- it is safe to call this function from a (sub)task
 *		that has no CLI window.
 *
 *		Note: all allocated memory, including the PICTURE struct itself,
 *		is chained and the header is stored in the PICTURE's memhead
 *		field, which is used by getRidOfPicture to deallocate memory.
 *		You should use getRidOfPicture to free all the memory allocated
 *		by this routine.
 *
 * RESULTS:	Returns pointer to an initialized PICTURE, or NULL on error.
 *
 * SEE ALSO:	getRidOfPicture
 */

/*
 * NAME:	getRidOfPicture
 *
 * SYNOPSIS:	err = getRidOfPicture( picture );
 *		short err;
 *
 * INPUTS:	PICTURE   *picture;	    pointer to PICTURE
 *
 * DESCRIPTION: De-allocate a PICTURE structure that was dynamically
 *		allocated by gimmePicture.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmePicture
 */

/*
 * NAME:	positionPicture
 *
 * SYNOPSIS:	err = positionPicture( rp, myflags, pic, minterm, x, y );
 *		short err;
 *
 * INPUTS:	struct RastPort *rp;		rastport in which to place it
 *		ULONG		myflags;	flags for the routine
 *		PICTURE 	*pic;		picture to be placed/removed
 *		SHORT		minterm;	how to blit the picture
 *		SHORT		x, y;		offsets for placing picture
 *
 * DESCRIPTION: Position a picture's image into a rastport using the blitter.
 *		The rastport should NOT be a window's rastport, because of
 *		layers associated with windows that are bypassed here.
 *		The flags modify the interpretation of the x and y coordinates
 *		so that the x and y values can specify the centre or any corner
 *		pixel positions; see gimmelib/postext.h for the actual flags.
 *		The minterm determines how the picture's image (bitmap) will
 *		be blitted into the screen's rastport; see gimmelib/minterm.h
 *		for some common minterms.
 *
 *		NOTE: clipping is done so that you can safely position part or
 *		all of the picture outside of the rastport's boundaries so that
 *		the remaining portion (if any) is visible.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmePicture, getRidOfPicture
 */

/*
 * NAME:	usePictureColors
 *
 * SYNOPSIS:	err = usePictureColors( pic, screen );
 *		short err;
 *
 * INPUTS:	PICTURE 	*pic;		use this picture's colors
 *		struct Screen	*screen;	screen to be affected
 *
 * DESCRIPTION: Set a screen's colors to those of a picture.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmePicture, getRidOfPicture
 */

/*
 * NAME:	positionText
 *
 * SYNOPSIS:	maxrastlen = positionText( rp, myflags, s, num, x, y );;
 *		SHORT maxrastlen;
 *
 * INPUTS:	struct RastPort *rp;	pointer to rastport to draw into
 *		ULONG	myflags;	routine flags controlling position
 *		UBYTE	*s;		pointer to string to display, or NULL
 *		LONG	num;		number to display (or 0L if not used)
 *		SHORT	x, y;		coordinates used in displaying text,
 *					  interpreted according to flags
 *
 * DESCRIPTION: Displays a string using the coordinates (x, y).
 *		The string displayed is: if s is NULL, "num" is converted
 *		to a string, otherwise the string "s" is used.
 *		The current font, pen colours and draw-mode of the rastport
 *		are used.
 *		The type of coordinates can be specified in the <flags>
 *		individually for x/y (see gimmelib/postext.h for flag names):
 *		- flags for x: left, right and centre.
 *		- flags for y: top, bottom, centre, baseline, centrebase.
 *		For example, specifying the centre-x flag will cause the
 *		x coordinate to be used as the centre of the text to be
 *		displayed.
 *		NOTE: centre-y means the centre of the character's height,
 *		whereas centrebase-y means the centre of the top of the
 *		character to its baseline. Since most of a character
 *		appears above the baseline, this may be more desirable than
 *		centre-y on certain fonts.
 *
 *		Note: normally when text is displayed using the system's
 *		Text() function, the coordinates specified are the LEFT-x
 *		and BASELINE-y.
 *
 *		If the y-upwards or y-downwards control flags are specified,
 *		then the text is written vertically (eg. a label for a y-axis).
 *		Note "upwards" means rotated 90 degrees counter-clockwise,
 *		similarly "downwards" is clockwise (as viewed from your seat).
 *		In these 2 cases, the meaning of the flags are changed slightly:
 *		the x-flags are applied to the y-coordinate, and the y-flags are
 *		applied to the x-coordinate. The way to picture this is like so:
 *		if you look at your vertical text so that is horizontal (normal)
 *		then how would you apply the flags? But since the vertical text
 *		does get rotated 90 degrees, the x and y coordinates really
 *		apply to the y and x coordinates relative to the normal text.
 *		eg. the baseline of the text is now an offset in the x-direction
 *		because the text is sideways.
 *		NOTE: currently any portion of vertical text (JAM2 or otherwise)
 *		that is colour 0 does NOT get rendered in the rastport.
 *		Note: the x-thicken control flag only works in conjunction with
 *		vertical text.
 *		Note: vertical text does NOT take layers into account.
 *
 * RESULTS:	Returns the maximum possible length in pixels that the
 *		number/string could occupy in the current given rastport,
 *		or a negative number on error (eg. incorrect parameters).
 */

/*
 * NAME:	gimmeAutoRequest
 *
 * SYNOPSIS:	result = gimmeAutoRequest( window, s, textattr );
 *		SHORT result;
 *
 * INPUTS:	struct Window	*window;    window, or NULL for default screen
 *		UBYTE		*s;	    main text string for requester
 *		struct TextAttr *textattr;  pointer to font type, or NULL
 *
 * DESCRIPTION: Put up an auto requester in the window (or screen if window
 *		is NULL).
 *		Use default font if textattr is NULL.
 *
 *		Note: If you wish to change the default positive/negative
 *		gadgets' text, you can alter the pointers which are extern'd in
 *		gimmelib/requester.h, to which you are referred.
 *		The defaults can be restored by assigning GAR_POSTEXT and
 *		GAR_NEGTEXT to the respective pointers.
 *		Caution: if you play around with these pointers in your program,
 *		you must not have more than one task within the same process
 *		space manipulating these pointers simultaneously.
 *
 * RESULTS:	Returns TRUE or FALSE, ala AutoRequest(), according to the
 *		user's selection.
 */

/*
 * NAME:	gimmeRequester
 *
 * SYNOPSIS:	req = gimmeRequester( memheadptr, left, top, width, height,
 *					backfill, gplist, s, textattr, flags );
 *		struct Requester *req;
 *
 * INPUTS:	void	**memheadptr;	    pointer to chained-memory head
 *		SHORT	left;		    left offset in pixels
 *		SHORT	top;		    top offset in pixels
 *		SHORT	width;		    total width in pixels, or -1
 *		SHORT	height; 	    total height in pixels, or -1
 *		UBYTE	backfill;	    color to fill in back of requester
 *		struct Gadget	*gplist;    first of a list of gadgets
 *		UBYTE	*s;		    main text string, or NULL
 *		struct TextAttr *textattr;  pointer to font, or NULL
 *		ULONG	flags;		    Requester flags
 *
 * DESCRIPTION: Allocate and initialize a Requester structure,
 *		including a border just inside the edge of the requester
 *		in the complement of the backfill colour.
 *		Note: this routine succeeds even if no border was allocated
 *		(check gp->GadgetRender for a non-NULL value if you want to
 *		be sure that a border was allocated).
 *		If you want to remove the border, do something similar to this:
 *			pluckChainMem( memheadptr, req->ReqBorder );
 *			req->ReqBorder = NULL;
 *
 *		The requester background is filled with the backfill color.
 *		The main text string pointed at by "s" is put in its own
 *		(allocated) IntuiText struct.
 *		If width is non-positive, then a suitable width is calculated
 *		based on the given text, font and gadgets.
 *		If height is non-positive, then a suitable height is calculated
 *		based on the given text, font and gadgets.
 *		Note: in either of these cases, gadget Borders or alternate
 *		images are not checked in calculating sufficient sizes.
 *
 *		The textattr can be NULL to use the default font.
 *		The linked list of gadget(s) is attached to the requester;
 *		remember that at least one gadget must have the ENDGADGET flag
 *		set so that the requester can be made to go away.
 *		Note that you might have to adjust the gadgets' back colours
 *		to match the backfill colour yourself if JAM2 modes are used.
 *		The flags are set in the requester's Flags field.
 *
 *		The allocated memory is chained to the memory chain pointed
 *		at by memheadptr using chainAllocMem.
 *		Eventually chainFreeMem should be called on the memhead.
 *
 * RESULTS:	Returns pointer to requester, or NULL.
 *		Note: the requester is NOT added to a window.
 *
 * SEE ALSO:	chainAllocMem, chainFreeMem, gimmeStringInfo
 */

/*
 * NAME:	gimmeNewScreen
 *
 * SYNOPSIS:	ns = gimmeNewScreen( modes, type, depth, title, textattr );
 *		struct NewScreen *ns;
 *
 * INPUTS:	ULONG	modes;		    new screen ViewMode flags
 *		ULONG	type;		    new screen Type (eg CUSTOMSCREEN)
 *		SHORT	depth;		    depth to make screen
 *		UBYTE	*title; 	    title string
 *		struct TextAttr *textattr;  pointer to font, or NULL
 *
 * DESCRIPTION: Allocate and initialize a NewScreen structure.
 *		Width and height taken from WorkBench screen (however, if
 *		you want to find out the height, eg for windows, you must
 *		wait until you open the screen and then check the Height
 *		field in the Screen structure).
 *		Note: this routine assumes an upper width limit of 350 for
 *		lo-res screens, and adjusts the width taken from GfxBase
 *		accordingly.
 *
 *		You can customize the NewScreen structure before opening
 *		the screen.
 *
 * RESULTS:	Returns pointer to NewScreen structure, or NULL on error.
 *
 * SEE ALSO:	getRidOfNewScreen, gimmeScreen, getRidOfScreen
 */

/*
 * NAME:	getRidOfNewScreen
 *
 * SYNOPSIS:	err = getRidOfNewScreen( ns );
 *		short err;
 *
 * INPUTS:	struct NewScreen    *ns;	pointer to NewScreen structure
 *
 * DESCRIPTION: De-allocates a NewScreen structure that was dynamically
 *		allocated by gimmeNewScreen.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeNewScreen, gimmeScreen, gimmeScreenLazy, getRidOfScreen
 */

/*
 * NAME:	gimmeScreen
 *
 * SYNOPSIS:	screen = gimmeScreen( ns, windowptr, depth, IDCMPflags,
 *					winflags );
 *		struct Screen *screen;
 *
 * INPUTS:	struct NewScreen    *ns;	    ptr to initialized NewScreen
 *		struct Window	    **windowptr;    ptr to window ptr
 *		SHORT		    depth;	    depth for window
 *		ULONG		    IDCMPflags;     IDCMP flags for window
 *		ULONG		    winflags;	    flags for window
 *
 * DESCRIPTION: Open an Intuition screen.
 *		If the NewScreen pointer "ns" in NULL, then a default NewScreen
 *		structure is temporarily created, used and deleted.
 *		If windowptr is non-NULL, a window with the given IDCMP and
 *		window flags is opened on the screen; the pointer to this window
 *		is placed where windowptr points to. The screen's titlebar will
 *		be hidden behind the window if it is a backdrop window.
 *		The window, if opened, will be the same width as the screen,
 *		but one pixel shorter and placed down one pixel so that the
 *		screen's titlebar is still accessible.
 *		Note that the screen's titlebar may be partially visible.
 *
 *		Note: the depth parameter is only used if no NewScreen is
 *		given, ie. if "ns" is NULL.
 *
 *		Note: when you close the screen with getRidOfScreen, you must
 *		either close the window using getRidOfWindow on the window ptr
 *		placed in *windowptr, OR pass this window ptr along to the
 *		getRidOfScreen routine.
 *
 *		Note: this routine will fail if a window is asked for but
 *		cannot be opened even though the screen opened (any allocated
 *		memory will be freed and the screen closed before returning).
 *
 * RESULTS:	Returns a pointer to an open Intuition screen, or NULL if
 *		anything went wrong. If windowptr is non-NULL, *windowptr will
 *		be updated to contain a pointer to a window.
 *
 * SEE ALSO:	getRidOfNewScreen, gimmeScreenLazy, getRidOfScreen
 */

/*
 * NAME:	gimmeScreenLazy
 *
 * SYNOPSIS:	screen = gimmeScreenLazy( ns, windowptr, depth );
 *		struct Screen *screen;
 *
 * INPUTS:	struct NewScreen    *ns;	    ptr to initialized NewScreen
 *		struct Window	    **windowptr;    ptr to window ptr
 *		SHORT		    depth;	    depth for window
 *
 * DESCRIPTION: Open an Intuition screen, and possibly a window.
 *		This routine is a shortcut for using gimmeScreen, using
 *		default IDCMP and window flags (see gimmelib/window.h) for
 *		a backdrop window if windowptr in non-NULL.
 *		Note that the screen titlebar may be partially visible.
 *
 *		Note: this routine will fail if a window is asked for but
 *		cannot be opened even though the screen opened (any allocated
 *		memory will be freed and the screen closed before returning).
 *
 * RESULTS:	Returns a pointer to an open Intuition screen, or NULL if
 *		anything went wrong. If windowptr is non-NULL, *windowptr will
 *		be updated to contain a pointer to a window.
 *
 * SEE ALSO:	gimmeNewScreen, gimmeScreen, getRidOfScreen
 */

/*
 * NAME:	getRidOfScreen
 *
 * SYNOPSIS:	err = getRidOfScreen( screen, window );
 *		short err;
 *
 * INPUTS:	struct Screen	*screen;	pointer to Intuition screen
 *		struct Window	*window;	pointer to window -- see note
 *
 * DESCRIPTION: Close a screen.
 *		If window is non-NULL, close the window first.
 *		NOTE: if window is specified, it SHOULD be the window ptr
 *		returned by gimmeScreen where the window-ptr parameter
 *		pointed to.
 *
 *		Note: does NOT call ClearMenuStrip() on the window.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeNewScreen, getRidOfNewScreen, gimmeScreen
 */

/*
 * NAME:	lowerScreen
 *
 * SYNOPSIS:	err = lowerScreen( screen, toheight );
 *		short err;
 *
 * INPUTS:	struct Screen	*screen;    pointer to Intuition screen
 *		SHORT	toheight;	    height in pixels from top of view
 *
 * DESCRIPTION: Slide the screen down until top of screen is at the
 *		desired height from the top of the viewing area.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	raiseScreen
 */

/*
 * NAME:	raiseScreen
 *
 * SYNOPSIS:	err = raiseScreen( screen, toheight );
 *		short err;
 *
 * INPUTS:	struct Screen	*screen;    pointer to Intuition screen
 *		SHORT	toheight;	    height in pixels from top of view
 *
 * DESCRIPTION: Slides the screen up until top of screen is at the
 *		desired height from the top of the viewing area.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	lowerScreen
 */

/*
 * NAME:	gimmeOneScroll
 *
 * SYNOPSIS:	gp = gimmeOneScroll( window, id, dirflags, myflags );
 *		struct Gadget *gp;
 *
 * INPUTS:	struct Window	*window;    window for gadget, or NULL
 *		USHORT		id;	    non-zero id for gadget
 *		ULONG		dirflags;   direction flags as per PropInfo
 *					      can be FREEVERT or FREEHORIZ
 *		ULONG		myflags;    flags for routine
 *
 * DESCRIPTION: Creates an initialized scroll-button (vertical or horizontal)
 *		placed near the corners of a window,
 *		leaving room for the sizing gadget (whether or not it is there).
 *		These are often used at the top/left and bottom/right ends
 *		of a scroll-bar to be used for incremental scrolling.
 *		If window is non-NULL, the gadget is further customized for
 *		the window (eg checks for GIMMEZEROZERO).
 *
 *		If all goes well, the head pointer to chained memory for the
 *		gadget and its other required structures is stored in the
 *		gp->UserData field. You must preserve this pointer!!
 *		If you need to use the UserData yourself, be sure to save
 *		gp->UserData somewhere safe after calling gimmeOneScroll.
 *		When you are done with the gadget you must ensure that the
 *		chained memory head pointer is restored into gp->UserData
 *		before you call getRidOfGadget.
 *
 * RESULTS:	Returns pointer to requested type of Gadget, or NULL.
 *		Note: The gadget is NOT added to the window.
 *
 * SEE ALSO:	getRidOfGadgets, gimmeScrollBar, gimmeFullScrollBar
 */

/*
 * NAME:	gimmeScrollBar
 *
 * SYNOPSIS:	gp = gimmeScrollBar( window, id, dirflags, propflags );
 *		struct Gadget *gp;
 *
 * INPUTS:	struct Window	*window;    window for gadget, or NULL
 *		USHORT		id;	    non-zero id for gadget
 *		ULONG		propflags;  flags for PropInfo
 *		ULONG		myflags;    flags for routine
 *
 * DESCRIPTION: Creates an initialized scroll-bar (vertical or horizontal only),
 *		leaving room for the sizing gadget (whether or not it is there)
 *		to be placed in a window.
 *		If window is non-NULL, the gadget is further customized for
 *		the window (eg checks for GIMMEZEROZERO and calculates
 *		the PropInfo's HorizBody and VertBody), also the FgPen and BgPen
 *		colours of the window's rastport are used (see gimmePropGadget).
 *		The propflags are used by gimmePropInfo to set up the PropInfo
 *		structure for the scrollbar.
 *		Note: if you wish to change the knob imagery to your own, do
 *		something similar to the following after this routine:
 *		    gp->GadgetRender = (APTR) <your image or border>;
 *		    ((struct PropInfo *)gp->SpecialInfo)->Flags &= ~AUTOKNOB;
 *		    gp->Flags &= ~GADGIMAGE;	;; ONLY if you want a BORDER
 *
 *
 *		If all goes well, the head pointer to chained memory for the
 *		gadget and its other required structures is stored in the
 *		gp->UserData field. You must preserve this pointer!!
 *		If you need to use the UserData yourself, be sure to save
 *		gp->UserData somewhere safe after calling gimmeScrollBar.
 *		When you are done with the gadget you must ensure that the
 *		chained memory head pointer is restored into gp->UserData
 *		before you call getRidOfGadget.
 *
 * RESULTS:	Returns pointer to requested type of Gadget, or NULL.
 *		Note: The gadget is NOT added to the window.
 *
 * SEE ALSO:	getRidOfGadgets, gimmeFullScrollBar, gimmeOneScroll
 */

/*
 * NAME:	gimmeFullScrollBar
 *
 * SYNOPSIS:	gp = gimmeFullScrollBar( window, id, propflags, myflags,
 *					    id1, id2 );
 *		struct Gadget *gp;
 *
 * INPUTS:	struct Window	*window;    window for gadget, or NULL
 *		USHORT		id;	    non-zero id for gadget
 *		ULONG		propflags;  flags for PropInfo
 *		ULONG		myflags;    flags for routine
 *		USHORT		id1;	    id for left/up one-scroll gadget
 *		USHORT		id2;	    id for right/down one-scroll gadget
 *
 * DESCRIPTION: Creates an initialized scroll-bar (vertical or horizontal)
 *		along with two one-scroll button gadgets at the ends of the
 *		scroll bar (hence the "full" designation),
 *		leaving room for the sizing gadget (whether or not it is there).
 *		If window is non-NULL, the gadget is further customized for
 *		the window (eg checks for GIMMEZEROZERO and calculates
 *		the PropInfo's HorizBody and VertBody).
 *		The propflags are used by gimmePropInfo to set up the PropInfo
 *		structure for the scrollbar.
 *
 *		Note: since the gadgets are linked together (with the scrollbar
 *		gadget first), be careful when using the gadget pointer returned
 *		by this function -- use addGadgets to add the list of gadgets,
 *		or follow the NextGadget pointers before chaining other gadgets
 *		to the end of these gadgets.
 *
 *		If all goes well, the head pointer to chained memory for the
 *		gadget and its other required structures is stored in the
 *		gp->UserData field. You must preserve this pointer!!
 *		If you need to use the UserData yourself, be sure to save
 *		gp->UserData somewhere safe after calling gimmeScrollBar.
 *		When you are done with the gadget you must ensure that the
 *		chained memory head pointer is restored into gp->UserData
 *		before you call getRidOfGadget.
 *
 * RESULTS:	Returns pointer to scroll-bar Gadget, to which the two
 *		one-scroll gadgets are linked, or NULL.
 *		Note: The gadgets are NOT added to the window.
 *
 * SEE ALSO:	getRidOfGadgets, gimmeScrollBar, gimmeOneScroll, addGadgets
 */

/*
 * NAME:	gimmeSound
 *
 *		#include <gimmelib/sound.h>
 *
 * SYNOPSIS:	snd = gimmeSound( filename );
 *		SOUND *snd;
 *
 * INPUTS:	UBYTE	*filename;		name of iff sound file
 *
 * DESCRIPTION: Read a sound sample from the specified file.
 *		Create and initialize a SOUND structure for the sound sample.
 *		If possible, an error message is printed if anything goes
 *		wrong -- it is safe to call this function from a (sub)task
 *		that has no CLI window.
 *
 *		Note: all allocated memory, including the SOUND struct itself,
 *		is chained and the header is stored in the SOUND's memhead
 *		field, which is used by getRidOfSound to deallocate memory.
 *
 * RESULTS:	Returns pointer to an initialized SOUND, or NULL on error.
 *
 * SEE ALSO:	getRidOfSound
 */

/*
 * NAME:	getRidOfSound
 *
 * SYNOPSIS:	err = getRidOfSound( sound );
 *		short err;
 *
 * INPUTS:	SOUND	*sound; 	pointer to SOUND
 *
 * DESCRIPTION: De-allocate a SOUND structure that was dynamically
 *		allocated by gimmeSound.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeSound
 */

/*
 * NAME:	gimmeStdStuff
 *
 * SYNOPSIS:	error = gimmeStdStuff( myflags, revision );
 *		ULONG error;
 *
 * INPUTS:	ULONG	myflags;	flags for libraries/devices to open
 *		SHORT	revision;	revision number to use for OpenDevice()
 *
 * DESCRIPTION: Open standard libraries and devices and other things
 *		specified by the given myflags, using the given revision number.
 *		Pointers are stored in global variables in gimme.lib
 *		See gimmelib/stdstuff.h for the flags and variable names
 *		in order to find out what you can open with this routine.
 *
 *		Things are opened or initialized in the same order as the flags
 *		are listed (ie. in order of increasing importance!)
 *		except the special things (indicated by special bits).
 *
 *		NOTE: this routine is NOT reentrant; it can only be safely used
 *		by one task.
 *
 *		NOTE: it is not recommended to use any of the global variables
 *		associated with this routine for use without this routine and
 *		getRidOfStdStuff.
 *
 * RESULTS:	Returns zero if ok, otherwise flag corresponding to library
 *		or device that could not be opened.
 *		NOTE: returns on the first failure to open something.
 *
 * SEE ALSO:	getRidOfStdStuff
 */

/*
 * NAME:	getRidOfStdStuff
 *
 * SYNOPSIS:	error = getRidOfStdStuff( myflags );
 *		ULONG error;
 *
 * INPUTS:	ULONG	myflags;	special flags for closing devices
 *
 * DESCRIPTION: Close the standard libraries/devices/things opened by
 *		gimmeStdStuff.
 *		See gimmelib/stdstuff.h for the global variable names used.
 *		The myflags specify control flags, esp. with regard to handling
 *		errors encountered when closing devices.
 *
 *		Things are closed or reset in the *reverse* order as the flags
 *		are listed (ie. in order of decreasing importance!)
 *		except the special things (corresponding to the special bits).
 *
 *		NOTE: this routine is NOT reentrant; it can only be safely used
 *		by one task.
 *
 * RESULTS:	Returns zero if ok, otherwise flag corresponding to library
 *		or device that could not be closed.
 *		NOTE: returns on the first failure to close something.
 *
 * SEE ALSO:	getRidOfStdStuff
 */

/*
 * NAME:	gimmeSubTask
 *
 * SYNOPSIS:	task = gimmeSubTask( countptr, portptr, stacksize, datasize,
 *							    myportptr );
 *		struct Task *task;
 *
 * INPUTS:	SHORT		*countptr;  pointer to counter variable, or NULL
 *		struct MsgPort	**portptr;  pointer to a MsgPort ptr, or NULL
 *		LONG		stacksize;  size of stack for subtask
 *		LONG		datasize;   size of a startup data area for
 *					      the subtask, or 0L if none needed
 *		struct MsgPort **myportptr; pointer to a pointer where subtask
 *					      is to put its MsgPort ptr, or NULL
 *
 * DESCRIPTION: Set everything up to launch a subtask via startSubTask.
 *		It creates (and allocates memory) for the following:
 *		- a Task struct
 *		- a <stacksize>-byte stack
 *		    - minimum approx 90 bytes used if <stacksize> is smaller
 *		- a <datasize>-byte data area
 *		    - ONLY IF <datasize> is strictly positive
 *		    - pointer to this data area stored in task->tc_UserData
 *		    - pointer to this area will be passed as the single
 *		      parameter to the subtask by startSubTask.
 *		- a special Message struct
 *		    ONLY IF portptr and myportptr are non-NULL
 *		    NOTE: when your subtask returns "normally" (ie you don't
 *		    kill it), the default auto-clean-up routine will send
 *		    a special "I'm dying" message to your task-monitoring port
 *		    (indirectly pointed at by portptr) and *wait* for a reply
 *		    (on the port it created for itself; see myportptr)
 *		    before decrementing the subtask counter and removing
 *		    itself from the system.
 *		    Before your subtask exits, it should empty its message
 *		    port and then (safely) NULL its port pointer (since a
 *		    copy is kept by the subtasking "library") before it exits,
 *		    so that (hopefully) other tasks will no longer put messages
 *		    on its port (this will also help the auto-cleanup-routine).
 *		- a message port
 *		    - ONLY IF myportptr is non-NULL
 *		    - NOTE: the message port isn't actually created until
 *		      the subtask starts running after you call startSubTask.
 *		    - see note below.
 *
 *		Note: if myportptr is non-NULL, a non-public message port
 *		will be automagically created when the subtask starts
 *		*running* [after it has been started via startSubTask]
 *		and the pointer to this message port will be stored in what
 *		myportptr points to. Thus the port will exist and the pointer
 *		pointed at by myportptr will be valid when the actual code
 *		of the subtask starts (called by the subtask startup code).
 *		If at that time the message port cannot be created, the
 *		subtask will exit gracefully without ever entering your
 *		initial subtask code.
 *
 *		This function should be followed by initialization of the data
 *		area (if any) for the child task, then startSubTask
 *		OR use undoGimmeSubTask if you change your mind and don't
 *		want to start the subtask to free any allocated memory.
 *
 *		Use getRidOfTask to cleanly kill a subtask, or allow the
 *		default task-completion code for the subtask to clean up
 *		everything.
 *
 *		Note: countptr should be the same as was passed to
 *		initSubTasker, and portptr should be NULL or the same as
 *		passed to initSubTasker.
 *
 * RESULTS:	Returns a pointer to the Task struct,
 *		with task->tc_UserData pointing to the data area (if any)
 *		which is automatically passed as the only parameter to your
 *		subtask by startSubTask.
 *
 * SEE ALSO:	startSubTask, undoGimmeSubTask, getRidOfTask
 */

/*
 * NAME:	undoGimmeSubTask
 *
 * SYNOPSIS:	undoGimmeSubTask( task );
 *
 * INPUTS:	struct Task *task;	    pointer to task struct
 *
 * DESCRIPTION: Free memory allocated for this subtask-in-the-making
 *		by gimmeSubTask.
 *
 *		NOTE: this is a "cancel!" function to be used after
 *		gimmeSubTask but before the task is actually
 *		started by startSubTask if you no longer want to submit
 *		the subtask.
 *
 * RESULTS:	The task pointer becomes invalid.
 *
 * SEE ALSO:	gimmeSubTask, killSubTask, startSubTask
 */

/*
 * NAME:	killSubTask
 *
 * SYNOPSIS:	killSubTask( countptr, portptr, task )
 *
 * INPUTS:	SHORT		*countptr;	ptr to counter variable, or NULL
 *		struct MsgPort	**portptr;	ptr to a MsgPort ptr, or NULL
 *		struct Task	*task;		ptr to an existing task
 *
 * DESCRIPTION: Remove the specified subtask from the system.
 *		Delete the port (if any) pointed at by what portptr points to.
 *		Note that the countptr and portptr parameters should be
 *		the same as was passed to initSubTasker.
 *
 * SEE ALSO:	gimmeSubTask, undoGimmeSubTask, startSubTask
 */

/*
 * NAME:	startSubTask
 *
 * SYNOPSIS:	error =  startSubTask( task, name, pri, initialpc, finalpc );
 *		short error;
 *
 *		struct Task *task;		pointer to task struct
 *		char	    *name;		name for subtask
 *		BYTE	    pri;		priority of subtask
 *		void	    (*initialpc)();     address of routine for subtask
 *		void	    (*finalpc)();       NULL - see note below
 *
 * DESCRIPTION: Start a subtask, ie. add it to the system.
 *		The task pointer must be the result of gimmeSubTask.
 *		Initialization of the data (if any) for the new task should
 *		already have been done before this routine.
 *		Note: regarding finalpc:
 *		- a value of NULL will cause the default cleanup
 *		  routine getRidOfMyself to be used, which will
 *		  handle things very nicely and cleanly.
 *		- Use your own finalpc routine AT YOUR OWN RISK!!!
 *		NOTE: the subtask counter [see countptr parameter for
 *		initSubTasker] gets incremented by the subtask itself
 *		once the subtask starts *running*!!!
 *
 *		WARNING: do NOT try to write to stdout or stderr
 *		(unless they are a file ??)
 *		or do a Write() to Output() from the subtask
 *		since it can be very bad for your health!!
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	gimmeSubTask, undoGimmeSubTask, killSubTask
 */

/*
 * NAME:	initSubTasker
 *
 * SYNOPSIS:	error = initSubTasker( countptr, portptr );
 *		short error;
 *
 * INPUTS:	SHORT		*countptr;	ptr to counter variable, or NULL
 *		struct MsgPort	**portptr;	ptr to a MsgPort ptr, or NULL
 *
 * DESCRIPTION: Initialize the sub-tasking "library" mechanism by:
 *		- setting the counter to zero (pointed at by countptr).
 *		- if portptr is non-NULL, a message port is created, pointed
 *		  at by what portptr points to.
 *		Note that the countptr and portptr parameters should be
 *		passed to certain other sub-tasking routines, such as:
 *		doneSubTasker, getRidOfSubTask and
 *		handleSpecialSubTaskMsg.
 *		A message port is only necessary if you use the dying-task-
 *		messages-its-parent or printf'ing from a subtask features;
 *		if you do not need these, portptr can be NULL and a message
 *		port will *not* be created.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	doneSubTasker, gimmeSubTask
 */

/*
 * NAME:	doneSubTasker
 *
 * SYNOPSIS:	error = doneSubTasker( countptr, portptr )
 *		short error;
 *
 * INPUTS:	SHORT		*countptr;	ptr to counter variable, or NULL
 *		struct MsgPort	**portptr;	ptr to a MsgPort ptr, or NULL
 *
 * DESCRIPTION: Finish access to the sub-tasking "library" mechanism by:
 *		- checking for outstanding subtasks via the counter variable
 *		  pointed at by countptr (returns error if there are)
 *		- deletes message port (if any) created by initSubTasker and
 *		  pointed at by what portptr points to.
 *		Note: the message port (if any) is *not* deleted if an error
 *		occurred.
 *		Note that the countptr and portptr parameters should be
 *		the same as was passed to initSubTasker.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	initSubTasker
 */

/*
 * NAME:	doPrintf
 *
 * SYNOPSIS:	error = doPrintf( port, replyport, s, p1, p2, p3, p4 )
 *		short error;
 *
 * INPUTS:	struct MsgPort	*port;		ptr to a Dos process' port
 *		struct MsgPort	*replyport;	your replyport or NULL
 *		UBYTE		*s;		a format string ala printf
 *		LONG		p1, p2; 	4 parms for printf
 *		double		p3, p4; 	see note below
 *
 * DESCRIPTION: Sends a message to a DOS process to print something.
 *		The DOS process in question must use handleSpecialSubTaskMsg
 *		to receive the print message.
 *		If replyport is NULL, doPrintf will not Wait() for a reply
 *		and the messaged process must do the FreeMem().
 *
 *		NOTE: The final string to be printed (ie. after processing
 *		by printf) should be no longer than 163 characters (which is
 *		approximately 2 full lines plus newlines) not including the
 *		final null character.
 *
 *		NOTE: the 4 printf parms (p1, p2, p3 and p4) do NOT have
 *		to match the long and double types exactly. This routine
 *		passes 4 parameters [ total size PARMS_SIZE calculated as:
 *		  2 * sizeof(LONG) + 2 * sizeof(double)  ] to printf,
 *		which will only use what is required by the format
 *		string "s". This makes it possible to pass as printf parms
 *		the equivalent in size to 6 longwords. If this space isn't
 *		sufficient, several doPrintf's will be required.
 *		==> This means that you can pass as many parameters as you
 *		want to doPrintf, but only up to the first PARMS_SIZE bytes
 *		will be used. This isn't exactly ANSI standard, but then
 *		again neither is the compiler.
 *
 *		NOTE: use synchronous printing VERY cautiously:
 *		the DOS process must be able to accept the message right
 *		away so you do not wait forever for a reply, and the first
 *		message on your replyport must be the reply to your print
 *		message (otherwise you screw up what arrives on your port).
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	handleSpecialSubTaskMsg
 */

/*
 * NAME:	handleSpecialSubTaskMsg
 *
 * SYNOPSIS:	numdied = handleSpecialSubTaskMsg( countptr, portptr )
 *		SHORT numdied;
 *
 * INPUTS:	SHORT		*countptr;	ptr to counter variable, or NULL
 *		struct MsgPort	**portptr;	ptr to a MsgPort ptr
 *
 * DESCRIPTION: Handles special messages from subtasks, in particular
 *		"print" and "done" messages.
 *		If printing messages (say, from subtasks),
 *		this routine must be called from a DOS process, not a subtask
 *		otherwise nothing will get printed.
 *
 * RESULTS:	The number of "I'm dying" messages received from subtasks.
 *
 * SEE ALSO:	initSubTasker, doneSubTasker, doPrintf
 */

/*
 * NAME:	accessTimer
 *
 * REQUISITES:	struct Device *TimerBase;
 *
 * SYNOPSIS:	tr = accessTimer( unit, portptr );
 *		struct timerequest *tr;
 *
 * INPUTS:	ULONG	unit;			timer device unit
 *		struct MsgPort	**portptr;	pointer to a MsgPort ptr
 *
 * DESCRIPTION: Open the timer device.
 *		Allocates memory for a "master" time-request and initializes
 *		it for use with the timer device.
 *		The "unit" must be either UNIT_VBLANK or UNIT_MICROHZ.
 *		If portptr is non-NULL:
 *		- if the pointer that portptr points to is non-NULL,
 *		  the time-request will use that port as a reply port.
 *		- otherwise a reply port is created and a pointer to it is
 *		  stuffed into what portptr points at.
 *		If portptr is NULL, a message port will be created but you
 *		would have to snoop around the time-request struct to find
 *		a pointer to it.
 *		NOTE: make sure what portptr points to is NULL if it is not
 *		a valid pointer (ie initialize it).
 *
 *		NOTE: you must end any and all "slave" time-requests
 *		you create [via gimmeTimeRequest] by using
 *		getRidOfTimeRequest on each "slave" before releasing access
 *		to the timer via releaseTimer on the "master" time-request.
 *
 *		Note: you must have declared a global variable as follows:
 *		    struct Device *TimerBase = NULL;
 *		The actual pointer will be stored in the TimerBase variable
 *		by this routine [after opening the timer device].
 *
 * RESULTS:	Returns a pointer to a "master" time-request, or NULL.
 *
 * SEE ALSO:	releaseTimer, gimmeTimeRequest, getRidOfTimeRequest
 */

/*
 * NAME:	releaseTimer
 *
 * SYNOPSIS:	error = releaseTimer( tr, saveport );
 *		LONG error;
 *
 * INPUTS:	struct timerequest  *tr;	ptr to "master" time-request
 *		struct MsgPort	    *saveport;	ptr to msgport to save, or NULL
 *
 * DESCRIPTION: Close the timer device and free the memory of the "master"
 *		time-request.
 *		If saveport is NULL, the port associated with the given
 *		"master" time-request will be deleted (not necessarily the
 *		same one as the saveport specified in the parameters).
 *		If saveport is non-NULL, no message port will be deleted.
 *
 *		NOTE: you must have ended any and all "slave" time-requests
 *		you created [via gimmeTimeRequest] by using
 *		getRidOfTimeRequest on each "slave" BEFORE calling this
 *		function.
 *
 * RESULTS:	Returns non-zero ala AbortIO() on error.
 *
 * SEE ALSO:	accessTimer, gimmeTimeRequest, getRidOfTimeRequest
 */

/*
 * NAME:	gimmeTimeRequest
 *
 * SYNOPSIS:	tr = gimmeTimeRequest( trmaster );
 *		struct timerequest *tr;
 *
 * INPUTS:	struct timerequest  *trmaster;	    ptr to "master" time-request
 *
 * DESCRIPTION: Allocate memory for a "slave" time-request and initializes
 *		it from the "master" time-request.
 *		This "slave" timerequest will use the same timer unit
 *		(either UNIT_VBLANK or UNIT_MICROHZ) and reply port
 *		as the "master" time-request.
 *		NOTE: you must end all "slave" time-requests
 *		via getRidOfTimeRequest before releasing access to the
 *		timer via releaseTimer using the "master" time-request.
 *
 * RESULTS:	Returns a pointer to a "slave" time-request, or NULL.
 *
 * SEE ALSO:	accessTimer, getRidOfTimeRequest, releaseTimer
 */

/*
 * NAME:	getRidOfTimeRequest
 *
 * SYNOPSIS:	error = getRidOfTimeRequest( tr );
 *		LONG error;
 *
 * INPUTS:	struct timerequest  *tr;    pointer to "slave" time-request,
 *					      as returned by gimmeTimeRequest
 *
 * DESCRIPTION: Free memory taken by the "slave" time-request, rendering
 *		the pointer <tr> invalid.
 *		The time-request will be aborted if it is currently in
 *		progress.
 *
 * RESULTS:	Returns zero if ok, or non-zero ala AbortIO() on error.
 *		Either way, the time-request gets freed and <tr> becomes
 *		an invalid pointer.
 *
 * SEE ALSO:	gimmeTimeRequest, accessTimer, releaseTimer
 */

/*
 * NAME:	timeDelay
 *
 * SYNOPSIS:	error = timeDelay( secs, micros, unit, mytr );
 *		LONG error;
 *
 * INPUTS:	ULONG		    secs;	number of seconds to delay
 *		ULONG		    micros;	number of microseconds to delay
 *		ULONG		    unit;	timer device unit
 *		struct timerequest  *mytr;	ptr to a time-request, or NULL
 *
 * DESCRIPTION: Delay a specified amount of time using Synchronous IO.
 *		If mytr is non-NULL, that time-request is used, otherwise a
 *		"master" timerequest" is created via accessTimer.
 *		The unit must be either UNIT_VBLANK or UNIT_MICROHZ,
 *		but is ignored if myptr is non-NULL.
 *		The "tv" parameter should point to a timeval struct which
 *		contains the number of seconds and microseconds to wait.
 *
 *		Note: this function can be used completely stand-alone if
 *		the "mytr" parameter is NULL, or in conjunction with other
 *		timer routines such as accessTimer and gimmeTimeRequest.
 *
 * RESULTS:	Returns non-zero on error.
 *
 * SEE ALSO:	accessTimer, releaseTimer
 */

/*
 * NAME:	timeDelayAsync
 *
 * SYNOPSIS:	tr = timeDelayAsync( secs, micros, unit, mytr );
 *		struct timerequest *tr;
 *
 * INPUTS:	ULONG		    secs;	number of seconds to delay
 *		ULONG		    micros;	number of microseconds to delay
 *		ULONG		    unit;	timer device unit
 *		struct timerequest  *mytr;	ptr to a time-request, or NULL
 *
 * DESCRIPTION: Send a delay request using Asynchronous IO.
 *		If mytr is non-NULL, that time-request is used, otherwise
 *		a "master" time request with no reply port is created via
 *		accessTimer.
 *		The unit must be either UNIT_VBLANK or UNIT_MICROHZ,
 *		but is ignored if myptr is non-NULL.
 *		The "tv" parameter should point to a timeval struct which
 *		contains the number of seconds and microseconds to wait.
 *
 *		Note: if mytr is NULL, you must remove the time-request via
 *		releaseTimer when you are signalled that it is done.
 *
 * RESULTS:	Returns a pointer to a time-request (either the same one
 *		passed as a parameter or a new "master" time-request),
 *		or NULL on error.
 *
 * SEE ALSO:	accessTimer, releaseTimer
 */

/*
 * NAME:	waitTimer
 *
 * SYNOPSIS:	error = waitTimer( tr );
 *		LONG error;
 *
 * INPUTS:	struct timerequest  *tr;	time-request to wait for
 *
 * DESCRIPTION: Wait for the specified time-request to complete.
 *		Usually used after an Asynchronous time delay,
 *		eg. using timeDelayAsync.
 *
 * RESULTS:	Returns non-zero on error, ala WaitIO().
 *
 * SEE ALSO:	accessTimer, releaseTimer, gimmeTimeRequest, timeDelayAsync
 */

/*
 * NAME:	killTimeDelay
 *
 * SYNOPSIS:	error = killTimeDelay( tr );
 *		LONG error;
SHAR_EOF
#	End of shell archive
exit 0
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.