[mod.mac.sources] FakeAlert.c - configurable resourceless alert

dubois@uwmacc.UUCP (Paul DuBois) (09/29/86)

Here's some code for doing an alert without resources.  There
are some examples of use at the end.

The tabwidth should be set to 4.
----

/*
	FakeAlert - routines to do a resourceless alert with a message
	and either 1, 2 or 3 buttons.  Default (bold) button may be
	specified.


			Paul DuBois
			Wisconsin Regional Primate Research Center
			1220 Capital Court
			Madison WI  53706  USA

	UUCP:	{allegra,ihnp4,seismo}!uwvax!uwmacc!dubois
	ARPA:	dubois@rhesus
			dubois@rhesus.primate.wisc.edu
			dubois@unix.macc.wisc.edu

	Written for LightspeedC, which is a trademark of:

			THINK Technologies, Inc
			420 Bedford Street  Suite 350
			Lexington, MA  02173


	Thanks to Erik Kilk and Jason Haines.  Some of the stuff to do
	this is modified from code they wrote.
*/

# include	<DialogMgr.h>


# define	nil		(0L)


/*
	In-memory item list for dialog with four items:

	1	"^0^1^2^3" (static text)
	2	Button 1
	3	Button 2
	4	Button 3

	The caller of FakeAlert passes the four strings that are to be
	substituted into the first item, the number of buttons that
	should be used, and the titles to put into each button.
	A copy of the item list is hacked to use the right number of
	buttons.
*/


static int	itemList [] =
{
	3,					/* max number of items - 1 */

/*
	statText item
*/
	0, 0,				/* reserve a long for item handle */
	10, 27, 61, 225,	/* display rectangle */
	((8+128) << 8) | 8,	/* 8 + 128 = statText (disabled), title 8 bytes long */
	0x5e30, 0x5e31,		/* ^0^1^2^3 */
	0x5e32, 0x5e33,

/*
	first button
*/

	0, 0,				/* reserve a long for item handle */
	104, 140, 124, 210,	/* display rectangle */
	(4 << 8) | 0,		/* 4 = pushButton, title is 0 bytes long*/

/*
	second button
*/

	0, 0,				/* reserve a long for item handle */
	104, 30, 124, 100,	/* display rectangle */
	(4 << 8) | 0,		/* 4 = pushButton, title is 0 bytes long */

/*
	third button
*/

	0, 0,				/* reserve a long for item handle */
	72, 30, 92, 100,	/* display rectangle */
	(4 << 8) | 0		/* 4 = pushButton, title is 0 bytes long */
};


/*
	Set dialog button title and draw bold outline if makeBold true.
	This must be done after the window is shown or else the bold
	outline won't show up (which is probably the wrong way to do it).
*/

static SetDControl (theDialog, itemNo, title, makeBold)
DialogPtr	theDialog;
int			itemNo;
StringPtr	title;
Boolean		makeBold;
{
Handle		itemHandle;
int			itemType;
Rect		itemRect;
PenState	pState;

	GetDItem (theDialog, itemNo, &itemType, &itemHandle, &itemRect);
	SetCTitle (itemHandle, title);
	if (makeBold)
	{
		GetPenState (&pState);
		PenNormal ();
		PenSize (3, 3);
		InsetRect (&itemRect, -4, -4);
		FrameRoundRect (&itemRect, 16, 16);
		SetPenState (&pState);
	}
}


/*
	Fake an alert, using an in-memory window and item list.
	The message to be presented is constructed from the first
	four arguments.  nButtons is the number of buttons to use,
	defButton is the default button, the next three args are
	the titles to put into the buttons.  The return value is
	the button number (1..nButtons).  This must be interpreted
	by the caller, since the buttons may be given arbitrary
	titles.

	nButtons should be between 1 and 3, inclusive.
	defButton should be between 1 and nButtons, inclusive.
*/


static FakeAlert (s1, s2, s3, s4, nButtons, defButton, t1, t2, t3)
StringPtr	s1, s2, s3, s4;
int			nButtons;
int			defButton;
StringPtr	t1, t2, t3;
{
GrafPtr		savePort;
register DialogPtr	theDialog;
register Handle		iListHandle;
Rect		bounds;
int			itemHit;

	InitCursor ();
	GetPort (&savePort);
	iListHandle = NewHandle (512L);
	HLock (iListHandle);
	BlockMove (&itemList, *iListHandle, 512L);

/*
	Set the number of buttons
*/
	((int *) *iListHandle)[0] = nButtons;

	SetRect (&bounds, 115, 80, 355, 220);
	theDialog = NewDialog (nil, &bounds, "\p", false, dBoxProc, -1L,
							false, 0L, iListHandle);

	ParamText (s1, s2, s3, s4);		/* construct message */

	SetPort (theDialog);
	ShowWindow (theDialog);

	switch (nButtons)				/* set button titles */
	{
		case 3:
			SetDControl (theDialog, 4, t3, defButton == 3);
			/* fall through... */
		case 2:
			SetDControl (theDialog, 3, t2, defButton == 2);
			/* fall through... */
		case 1:
			SetDControl (theDialog, 2, t1, defButton == 1);
	}

/*
	ModalDialog returns 1 if return/enter hit, which,
	since the statText item is first, can be unambiguously
	interpreted as "choose default button".
*/

	ModalDialog (nil, &itemHit);
	itemHit = (itemHit == 1 ? defButton : itemHit - 1);
	HUnlock (iListHandle);
	/*HPurge (iListHandle);*/
	DisposDialog (theDialog);
	SetPort (savePort);
	return (itemHit);
}

--- end FakeAlert.c ---

Here are some examples of ways to use FakeAlert:

/*
	Present single-string error message.
*/

ErrMesg (s)
StringPtr	s;
{
	(void) FakeAlert (s, "\p", "\p", "\p", 1, 1, "\pOK", "\p", "\p");
}


/*
	Ask about reverting to disk version of file.  Default is Cancel.
*/

AskAboutRevert (fileName)
StringPtr	fileName;
{
	return (FakeAlert ("\p\"", fileName,
				"\p\" has been changed.  Really revert?", "\p",
				2, 1, "\pCancel", "\pRevert", "\p"));
}


/*
	Ask about saving to disk.  Default is Save.
*/

AskAboutSave (fileName)
StringPtr	fileName;
{
	return (FakeAlert ("\pSave changes to \"", fileName, "\p\"?", "\p",
						3, 3, "\pCancel", "\pDiscard", "\pSave"));
}
--- end of posting ---