/*
 * $Source: $
 * $Revision: $
 * $Date: $
 * $State: $
 * $Author: $
 *
 *
 * $Log: $
 *
 */

/*-----------------------------------------------------------------------------------------
#
#	Apple Macintosh Developer Technical Support
#
#	Collection of Utilities for DTS Sample code
#
#	Program:	Utilities.c.o
#	File:		Utilities.h	-	Header for C Source
#
#	Copyright © 1988-1990 Apple Computer, Inc.
#	All rights reserved.
#
-----------------------------------------------------------------------------------------*/

#ifndef __UTILITIES__
#define __UTILITIES__

#ifdef applec

#	ifndef __TYPES__
#		include <Types.h>
#	endif

#	ifndef __QUICKDRAW__
#		include <QuickDraw.h>
#	endif

#	ifndef __DIALOGS__
#		include <Dialogs.h>
#	endif

#	ifndef __FILES__
#		include <Files.h>
#	endif

#	ifndef __MEMORY__
#		include <Memory.h>
#	endif

#	ifndef __OSUTILS__
#		include <OSUtils.h>
#	endif

#	ifndef __WINDOWS__
#		include <Windows.h>
#	endif

/*
 *	If we are using MPW 3.2 or later, GestaltEqu.h is included, otherwise we use
 *	GestaltEqu31.h included in ::SC.025.Utilities:
 */
#	ifndef __GESTALTEQU__
#		ifdef MPW32
#			include <GestaltEqu.h>
#		else
#			include "GestaltEqu31.h"
#		endif
#	endif

/*
 *	If we are using MPW 3.2 or later, Folders.h is included, otherwise we use
 *	definitions included in ::SC.025.Utilities:
 */
#	ifndef __FOLDERS__
#		ifdef MPW32
#			include <Folders.h>
#		else
#			include "Folders31.h"
#		endif
#	endif

#endif

#include "UtilitiesCommon.h"

/*-----------------------------------------------------------------------------------------
	Global constants
-----------------------------------------------------------------------------------------*/
#ifndef applec
#define nil						0L
#define _WaitNextEvent					0xA860
#define _InitGraf						0xA86E
#define _Unimplemented					0xA89F
#define screenActive			15
#endif

#define	kOSEvent				app4Evt		/* event used by MultiFinder */
#define	kSuspendResumeMessage	1			/* high byte of suspend/resume event message */
#define	kResumeMask				1			/* bit of message field for resume vs. suspend */
#define	kMouseMovedMessage		0xFA		/* high byte of mouse-moved event message */
#define	kNoEvents				0			/* no events mask */

#define kDelayTime				8			/* For the delay time when flashing the
											   menubar and highlighting a button.
											   8/60ths of a second*/

#define kStartPtH				2			/* offset from the left of the screen */
#define kStartPtV				2			/* offset from the top of the screen */
#define kStaggerH				16			/* staggering amounts for new windows */
#define kStaggerV				22

#define chBackspace				'\b'		/* ASCII code for Backspace character */
#define chClear					'\033'		/* ASCII code for Clear key (aka ESC) */
#define chDown					'\037'		/* ASCII code for down arrow */
#define chEnd					'\004'		/* ASCII code for the End key */
#define chEnter					'\003'		/* ASCII code for Enter character */
#define chEscape				'\033'		/* ASCII code for Escape (aka Clear) key */
#define chFunction				'\020'		/* ASCII code for any function key */
#define chFwdDelete				'\177'		/* ASCII code for forward delete */
#define chHelp					'\005'		/* ASCII code for Help key */
#define chHome					'\001'		/* ASCII code for the Home key */
#define chLeft					'\034'		/* ASCII code for left arrow */
#define chPageDown				'\f'		/* ASCII code for Page Down key */
#define chPageUp				'\013'		/* ASCII code for Page Up key */
#define chReturn				'\n'		/* ASCII code for Return character */
#define chRight					'\035'		/* ASCII code for right arrow */
#define chSpace					' '			/* ASCII code for Space character */
#define chTab					'\t'		/* ASCII code for Tab character */
#define chUp					'\036'		/* ASCII code for up arrow */

enum { kQDOriginal = 0, kQD8Bit, kQD32Bit };	/* For use with gQDVersion */

/*-----------------------------------------------------------------------------------------
	Types
-----------------------------------------------------------------------------------------*/

typedef int *IntegerPtr, **IntegerHandle;

typedef long *LongintPtr, **LongintHandle;

typedef Boolean *BooleanPtr, **BooleanHandle;

typedef Rect *RectPtr, **RectHandle;

struct	WindowTemplate	{					/*template to a WIND resource*/
	Rect	boundsRect;
	short	procID;
	Boolean	visible;
	Boolean	filler1;
	Boolean	goAwayFlag;
	Boolean	filler2;
	long	refCon;
	Str255	title;
};
typedef	struct	WindowTemplate	WindowTemplate;
typedef			WindowTemplate	*WindowTPtr, **WindowTHndl;

/* following is here to account for lapses in the THINK C headers */

#ifndef applec
typedef unsigned char TrapType;
struct NumVersion {
	unsigned char majorRev; 		/*1st part of version number in BCD*/
	unsigned int minorRev : 4;		/*2nd part is 1 nibble in BCD*/
	unsigned int bugFixRev : 4; 	/*3rd part is 1 nibble in BCD*/
	unsigned char stage;			/*stage code: dev, alpha, beta, final*/
	unsigned char nonRelRev;		/*revision level of non-released version*/
};

typedef struct NumVersion NumVersion;
/* Numeric version part of 'vers' resource */
struct VersRec {
	NumVersion numericVersion;		/*encoded version number*/
	short countryCode;				/*country code from intl utilities*/
	Str255 shortVersion;			/*version number string - worst case*/
	Str255 reserved;				/*longMessage string packed after shortVersion*/
};

typedef struct VersRec VersRec;
typedef VersRec *VersRecPtr, **VersRecHndl;

typedef WStateData *WStateDataPtr, **WStateDataHandle;

#endif


/*-----------------------------------------------------------------------------------------
	Handy Macros/inlines
-----------------------------------------------------------------------------------------*/
#ifdef __cplusplus

inline long abs(val)
{	return ((val < 0) ? (-val) : (val)); }			/* Absolute value */

inline short pStrLength(str)
{	return (*str); }								/* Length of a Pascal string */

inline void PStrCopy(dest, src)						/* Pascal string copy */
{	BlockMove (src, dest, (*(char *)(src))+1); }

inline Point* TopLeft(Rect& r)						/* provide access to rect.topLeft  */
{	return (Point*)(&r.top); }

inline Point* BotRight(Rect& r)						/* provide access to rect.botRight  */
{	return (Point*)(&r.bottom); }

inline short HiWrd(long aLong)						/* return the hi word of a long */
{	return ((aLong >> 16) & 0xFFFF); }

inline short LoWrd(long aLong)						/* return the lo word of a long */
{	return (aLong & 0xFFFF); }

inline void SETPT(Point *pt,short h,short v)
{	(*pt).h = h; (*pt).v = v); }

inline void SETRECT(Rect *r,short left,short top,short right,short bottom)
{	SETPT(TopLeft(*r), left, top); SETPT(BotRight(*r), right, bottom); }

/*
 *	Useful functions for testing gestalt attribute responses
 *
 *	BTstBool returns a true boolean value (0 or 1), but is slower than:
 *	BTstQ which simply returns a non-zero value if the bit is set which
 *	means the result could get lost if assigned to a short, for example.
 *
 *	arg is any integer value, bitnbr is the number of the bit to be tested.
 *	bitnbr = 0 is the least significant bit.
 */
inline short BTstBool(arg, bitnbr)
{	return ((arg >> bitnbr) & 1); }

inline long BTstQ(arg, bitnbr)
{	return (arg & (1 << bitnbr)); }

#else

/* define our own abs() so we don't need StdLib */
#define abs(val) ((val < 0) ? (-val) : (val))
#define pStrLength(str) (*str)								/* Length of a Pascal string */
/* Pascal string copy */
#define PStrCopy(dest, src)	(BlockMove (src, dest, (*(char *)(src))+1))
#define TopLeft(r)		(* (Point *) &(r).top)
#define BotRight(r)		(* (Point *) &(r).bottom)
#define HiWrd(aLong)	(((aLong) >> 16) & 0xFFFF)
#define LoWrd(aLong)	((aLong) & 0xFFFF)
#define SETPT(pt, x, y)	(*(pt)).h = (x); (*(pt)).v = (y)
#define SETRECT(r, left, top, right, bottom)	\
						SETPT(&TopLeft(*(r)), (left), (top)); \
						SETPT(&BotRight(*(r)), (right), (bottom))
/*
 *	Useful macros for testing gestalt attribute responses
 *
 *	BTstBool returns a true boolean value (0 or 1), but is slower than:
 *	BTstQ which simply returns a non-zero value if the bit is set which
 *	means the result could get lost if assigned to a short, for example.
 *
 *	arg is any integer value, bitnbr is the number of the bit to be tested.
 *	bitnbr = 0 is the least significant bit.
 */
#define BTstBool(arg, bitnbr)	((arg >> bitnbr) & 1)
#define BTstQ(arg, bitnbr)		(arg & (1 << bitnbr))

#endif

/*-----------------------------------------------------------------------------------------
	Global variables
-----------------------------------------------------------------------------------------*/
/*	The following global variables are initialized by StardardInitialization to
 *	define the environnment.  This used to be a single SysEnvRec, but now,
 *	all those variables defined in a SysEnvRec can be returned by Gestalt
 *	(except sysVRefNum; see FindSysFolder).  Note that all the variables
 *	below will be correctly initialized whether Gestalt is available or not;
 *	the Gestalt glue handles this.
 */
extern int				gMachineType;			/* which machine this is */
extern int				gSystemVersion;			/* System version number */
extern int				gProcessorType;			/* which CPU this is */
extern Boolean			gHasFPU;				/* true if machine has an FPU */
extern int				gQDVersion;				/* major QD version #; 0 for original,
													1 for color QD, 2 for 32-bit QD */
extern int				gKeyboardType;			/* which type of keyboard is present */
extern int				gAppleTalkVersion;		/* AppleTalk version number */

/*	These are also handled by Gestalt. gHasPMMU has no corresponding SysEnvRec
 *	field, but it is handled by the glue, so we include it here for completeness.
 *	gAUXVersion will be initialized with Gestalt if present, but correctly
 *	set even if Gestalt is not available
 */
extern Boolean			gHasPMMU;				/* true if machine has a PMMU or equivalent */
extern int				gAUXVersion;			/* major A/UX version number (0 if not present) */

/*
 *	gHasWaitNextEvent is set to TRUE if the Macintosh we are running on has
 *	WaitNextEvent implemented. We can use this in our main event loop to
 *	determine whether to call WaitNextEvent or GetNextEvent.
 */
extern Boolean			gHasWaitNextEvent;

/*
 *	gAppResRef is the applicationÕs resource file reference. I need to save
 *	this since I can open other resource files. The current resource file is
 *	always gAppResRef unless I momentarily set it to another file to read its
 *	resources, and then immediately restore it back.
 */
extern short			gAppResRef;

/*
 *	gInBackground is maintained by our osEvent handling routines. Any part of
 *	the program can check it to find out if it is currently in the background.
 */
extern Boolean			gInBackground;			/* maintained by StandardInitialization
													  and DoEvent */

/*
 *	gAppName holds the name of the application that's running. You can use if
 *	for any purpose you'd like. It is also used by StandardAbout if it can't
 *	find a string to use for the application name in a resource, so make sure
 *	you call InitForStandardAbout if you are going to call StandardAbout. If you
 *	call StandardInitialization, this is done for you.
 */
extern Str255			gAppName;

/*
 *	gSignature holds the creator signature for the running application. It follows the
 *	same rules as those for gAppName.
 */
extern OSType			gSignature;

/*
 *	Initial values of these global variables are set to zero or FALSE by MPW's
 *	runtime initialization routines.  If the Utilities initialization routines
 *	have been properly called, then gUtilitiesInited will be true.  If it is
 *	not true, then the values of the above global variables are invalid.
 */
extern Boolean			gUtilitiesInited;

/*-----------------------------------------------------------------------------------------
	Interface to routines
-----------------------------------------------------------------------------------------*/

#ifdef __cplusplus
extern "C" {
#endif

short		CenteredAlert(short alertID);
			/* Given an Alert ID, this routine will center the alertÕs rectangle before
			   showing it on the main screen. This follows the Apple Human Interface
			   Guidelines for where to place a centered window on the screen. If the Alert
			   is closely associated with another window, considerations should be given to
			   what the window is located. If this other window is on a screen other then
			   the main monitor, then it would be best to center the Alert on that other
			   monitor. */

void		CenterTwoRects (Rect outerRect, Rect *innerRect);
			/* Given two rectangles, this routine centers the second one within the first. */

void		CenterWindowRect (short procID, Rect *theRect);
			/*	Given a windowÕs portRect, this routine will center the rectangle on the
			  	main device within the desktop region. This excludes the menu bar area. It
			  	follows the Apple Human Interface Guidelines for where to place a window
			  	centered on the screen. That is, 1/3th of the desktop shows above the window
			  	and 2/3ths below it. It returns a new rectangle set to the centered
			  	position. The top and left of this rectangle can be used with MoveWindow.
			  	This routine only considers the main device. CenterWindowRect could take a
			  	GDevice as a parameter to center the VAR rect with. This would also allow
			  	Alerts or dialogs that are closely associated with a document window to be
			  	centered relative to the monitor that contains that document. This is also
			  	one of the Human Interface Guidelines. MacApp 2.0 has a utility
			  	CalcScreenRect that you can borrow from to include this.

			 	WARNING: This routine may move or purge memory. */

void		CenterWindowRectTo(short procID, Rect screenRect, Rect *theRect);

void		CenterWindowRectToMaxIntersectedDevice(short procID, Rect *theRect);

void		CloseAnyWindow(WindowPtr window);
			/* Closes the indicated window. Does the right thing, taking into account that
			   the window may belong to a DA. */

void		DeathAlert(short errResID, short errStringIndex);
			/* Display an alert that tells the user an error occurred, then exit the
			   program. This routine is used as an ultimate bail-out for serious errors
			   that prohibit the continuation of the application. */

void		DeathAlertMessage(short errResID, short errStringIndex, short message);

void		ErrorAlert(short errResID, short errStringIndex);

void		ErrorAlertMessage(short errResID, short errStringIndex, short message);

OSErr		FindSysFolder (short *foundVRefNum, long *foundDirID);
			/*
			 *	FindSysFolder returns the (real) vRefNum, and the DirID of the current
			 *	system folder.  It uses the Folder Manager if present, otherwise
			 *	it falls back to SysEnvirons.  It returns zero on success, otherwise
			 *	a standard system error.
			 */

Handle		GetAppResource(ResType theType,short theID);
			/* GetAppResource gets a resource from the application's res file by resource ID */

Handle		GetAppIndResource(ResType theType,short index);
			/* GetAppIndResource gets a resource from the application's res file by index */

Handle		GetAppNamedResource(ResType theType,const Str255 name);
			/* GetAppNamedResource gets a resource from the application's res file by name */

short		GetAUXVersion ( void );
			/*
			 *	getAUXVersion -- Checks for the presence of A/UX by whatever means is
			 *	appropriate.  Returns the major version number of A/UX (i.e. 0 if A/UX
			 *	is not present, 1 for any 1.x.x version 2 for any 2.x version, etc.
			 *
			 *	This code should work for all past, present and future A/UX systems.
			 */

DialogPtr	GetCenteredDialog(short id,Ptr p,WindowPtr behind);
			/* 	Given a dialog ID, this routine will center the dialogÕs rectangle before
			  	showing it on the main screen. This follows the Apple Human Interface
			  	Guidelines for where to place a centered window on the screen. If the
			  	dialog is closely associated with another window, considerations should be
			  	given to what the window is located. If this other window is on a screen
			  	other then the main monitor, then it would be best to center the dialog on
			  	that other monitor. */

WindowPtr	GetCenteredWindow(short id,Ptr p,WindowPtr behind);
			/*  Given a window ID, this routine will center the windowÕs rectangle before
			  	showing it on the main screen. This follows the Apple Human Interface
			  	Guidelines for where to place a centered window on the screen. If the
			  	window is closely associated with another window, considerations should be
			  	given to where that other window is located. If this other window is on a
			  	screen other then the main monitor, then it would be best to center the
			  	window on that other monitor. */

Boolean 	GetCheckOrRadio(DialogPtr dlgPtr, short ChkItem);

long		GetGestaltResult (OSType gestaltSelector);
			/*
			 *	GetGestaltResult returns the result value from Gestalt for the specified
			 *	selector.  If Gestalt returned an error GetGestaltResult returns zero.  Use
			 *	of this function is only cool if we don't care whether Gestalt returned an
			 *	error.  In many casesyou may need to know the exact Gestalt error code so
			 *	then this routine would be inappropriate.
			 */

Point		GetGlobalMouse(void);
			/* Returns the location of the mouse in local coordinates. It does this by
			   calling OSEventAvail(). */

Point		GetGlobalTopLeft(WindowPtr window);
			/* 	Given a window, this will return the top left point of the windowÕs port in
			  	global coordinates. Something this doesnÕt include, is the windowÕs drag
			  	region (or title bar). This returns the top left point of the windowÕs
			  	content area only. */

long		GetKFreeSpace(short vRefNum);

Rect		GetMainScreenRect(void);

GDHandle	GetMaxIntersectedDevice(Rect globalRect);

TrapType	GetTrapType(short theTrap);
			/* Returns the type (OSType or ToolType) of the trap. It does this by checking
			   the bits of the trap word. */

void		GetWindowStrucRect(short procID, Rect boundsRect, Rect *strucRect);
			/* This procedure is used to get the rectangle that surrounds the entire structure of a
			   window, given the rectangle that would be used for the portRect. It does this by
			   temporarily creating a window way offscreen, and getting the rgnBBox of its strucRgn.
			   The window is disposed of afterwards, and the port set back to the original port. */

#if 0
short		GetWindowTitleHeight(short procID);
			/* Try and determine the windowÕs title bar height. This is assumed to be the
			   difference between the tops of the content region and structure region of
			   the window. */
#endif

void		GlobalToLocalRect(Rect *aRect);

void		InitToolBox(void);

void		InitUtilities(void);
			/* This sets up some global variables for use by the utilities package.  If you call
			   StandardInitialization, you don't need to call this, as it will do it for you. */

Boolean		IsAppWindow(WindowPtr window);
			/* Returns TRUE if the windowKind of the window is greater than or equal to
			   userKind. If it is less, or the window is NIL, then return FALSE. */

Boolean		IsDAWindow(WindowPtr window);
			/* Returns TRUE if the windowKind of the window is less than zero. If not, or
			   the window is NIL, then return FALSE. */

void		LocalToGlobalRect(Rect *aRect);

void		LockHandleHigh(Handle theHandle);

WindowPtr	NewStackedWindow(short windID, Ptr windStorage);

WindowPtr	NewStaggeredWindow(short windID, Ptr windStorage, WindowPtr behind, Boolean forColor);

short		NumToolboxTraps(void);
			/* Determines the size of the Tool trap table. It does this by sampling a
			   couple of trap locations and seeing which, if any are Unimplemented. */

void		OutlineControl(ControlHandle button);

void 		OutlineDialogItem(DialogPtr dlgPtr, short item);

void		PositionTwoRects(Rect outerRect, Rect *innerRect, Fixed horzRatio, Fixed vertRatio);
			/* Given two rectangles, this routine positions the second within the first one
			   so that the it maintains the spacing specified the the horzRatio and vertRatio
			   parameters. In other words, to center an inner rectangle hoizontally, but
			   have its center be 1/3 from the top of the outer rectangle, call this
			   routine with horzRatio = FixRatio (1, 2), vertRatio = FixRatio (1, 3). */

void		PullApplicationToFront(void);

void		PStrConcat (Str255 targetStr, Str255 appendStr);
			/* Concatenate a Pascal string onto another. */

void		SelectButton(ControlHandle button);
			/* Given the button control handle, this will cause the button to look as if it
			   has been clicked in. This is nice to do for the user if they type return or
			   enter to select the default item. */

void		SetCheckOrRadioButton(DialogPtr dlgPtr, short itemNo, short state);

void		StaggerThisWindow(WindowPtr theWindow, short procID);

void		StandardAbout(short appNameStringID);
			/* Shows a standard about box with the name of the application, its version
			   number, a copyright notice, and DTS credits. Most of this information is
			   taking from a standard DITL and the applicationÕs 'vers' resource. The name
			   of the application is taken either from the 'STR ' resource passed in to
			   this routine, or from GetAppParms() if that resource doesnÕt exist, or you
			   pass in -1. */

void		StandardInitialization(short callsToMoreMasters);
			/* Initializes ÒgInBackGroundÓ to FALSE. Makes the following InitXXX calls:
			   InitGraf(), InitFonts(), InitWindows(), InitMenus(), TEInit(),
			   InitDialogs(), InitCursor(). Brings application to front with 3 EventAvail
			   calls. Calls SysEnvirons to initialize ÒgMacÓ. Calls TrapExists() to
			   initialize ÒgHasWaitNextEventÓ. */

void		StandardMenuSetup(short MBARID, short AppleMenuID);
			/* Installs and draws the menus indicated by 'MBAR'(MBARID). Adds DAÕs to the
			   menu indicated by AppleMenuID by calling AddResMenu. If the menuBar cannot
			   be created, the alert specified by rDeathAlert is displayed. */

void 		ToggleCheck(DialogPtr dlgPtr, short cChkItem);

Boolean		TrapExists(short theTrap);
			/* Returns TRUE if the trap exists (i.e., itÕs callable without getting DS
			   error 12) */

void 		TruncateString (int widthNeeded, StringPtr Str);

void		ZoomToMaxIntersectedDevice(WindowPtr theWindow, short zoomDir, Boolean front);

#ifdef __cplusplus
}
#endif

#endif