/** EggUtils.c

	© 1992 CoSA

**/
#ifndef _H_EggUtils
#define _H_EggUtils

#include <BEE.h>
#include <LIST.h>
#include "DaveUtils.h"

class CNumText;

typedef enum {
	kNoMatteInfo = 0,
	kIgnored,
	kMatted,
	kUnmatted
} MatteInfo;

/** Failure containment macros

	use TRY/CATCH/ENDTRY _or_ START/END
	
	no mixing, CATCH isn't optional between TRY & ENDTRY

	DONT_FAIL_START/{failing code}/DONT_FAIL_END

	DONT_FAIL_TRY/{failing code}/DONT_FAIL_CATCH/{non-failing code}/DONT_FAIL_ENDTRY
	
	NOTE: there are some double braces {{ to avoid mismatching try/endtry without catch
*/

#define		DONT_FAIL_TRY(ERR)							\
	TRY_MULTIPLE {{
	
#define		DONT_FAIL_CATCH(ERR)						\
	}} CATCH {											\
		NO_PROPAGATE									\
		ERR = gLastError ? gLastError : Err_GENERIC;	\
		if (gLastError != kSilentErr)					\
			ErrorAlert(gLastError, gLastMessage);

#define		DONT_FAIL_ENDTRY(ERR)						\
	} ENDTRY

/* ---------------------------------------------------- */

#define		DONT_FAIL_START(ERR)						\
	DONT_FAIL_TRY(ERR) {

#define		DONT_FAIL_END(ERR)							\
	} DONT_FAIL_CATCH(ERR) {							\
	} DONT_FAIL_ENDTRY(ERR)

/* ---------------------------------------------------- */

#define		CODE_CALLBACK_TRY(ERR)						\
	++G_inCoDE;											\
	DONT_FAIL_TRY(ERR) {{

#define		CODE_CALLBACK_CATCH(ERR)					\
	}} DONT_FAIL_CATCH(ERR) {

#define		CODE_CALLBACK_ENDTRY(ERR)					\
	} DONT_FAIL_ENDTRY(ERR);							\
	--G_inCoDE;											\
	U_ASSERT(G_inCoDE > 0)

/* ---------------------------------------------------- */			

#define		CODE_CALLBACK_START(ERR)					\
	CODE_CALLBACK_TRY(ERR) {

#define		CODE_CALLBACK_END(ERR)						\
	} CODE_CALLBACK_CATCH(ERR) {						\
	} CODE_CALLBACK_ENDTRY(ERR)


/* ---------------------------------------------------- */			
#define		FEE_LIST_FOR_EACH(LIST, INDEX, PTR, ERR)			\
	LIST_FOR_EACH(LIST, INDEX, PTR, ERR)						\
		DONT_FAIL_START(ERR)

#define		FEE_LIST_END_EACH(LIST, ERR)						\
		DONT_FAIL_END(ERR);										\
	LIST_END_EACH(LIST, ERR)

/**/
#define		FEE_LIST_FOR_EACH_REVERSE(LIST, INDEX, PTR, ERR)	\
	LIST_FOR_EACH_REVERSE(LIST, INDEX, PTR, ERR)				\
		DONT_FAIL_START(ERR)

#define		FEE_LIST_END_EACH_REVERSE(LIST, ERR)				\
		DONT_FAIL_END(ERR);										\
	LIST_END_EACH(LIST, ERR)

/**/
#define		FEE_BEE_FOR_EACH_SELECTED_LAYER(SELH, LAYH, ERR)	\
	BEE_FOR_EACH_SELECTED_LAYER(SELH, LAYH, ERR)				\
		DONT_FAIL_START(ERR)

#define		FEE_BEE_END_EACH_SELECTED_LAYER(SELH, ERR)			\
		DONT_FAIL_END(ERR);										\
	BEE_END_EACH_SELECTED_LAYER(SELH, ERR)

/**/
#define		FEE_BEE_FOR_EACH_SELECTED_STREAM(TYPE, ERR)			\
	BEE_FOR_EACH_SELECTED_STREAM(TYPE, ERR)						\
		DONT_FAIL_START(ERR)

#define		FEE_BEE_END_EACH_SELECTED_STREAM(ERR)				\
		DONT_FAIL_END(ERR);										\
	BEE_END_EACH_SELECTED_STREAM(ERR)

/**/
#define		FEE_BEE_FOR_EACH_SELECTED_KEYFRAME(KEY_IDX, ERR)	\
	BEE_FOR_EACH_SELECTED_KEYFRAME(KEY_IDX, ERR)				\
		DONT_FAIL_START(ERR)

#define		FEE_BEE_END_EACH_SELECTED_KEYFRAME(ERR)				\
		DONT_FAIL_END(ERR);										\
	BEE_END_EACH_SELECTED_KEYFRAME(ERR)
	
/**/
#define		FEE_BEE_FOR_EACH_SELECTED_KEYFRAME_REVERSE(KEY_IDX, ERR)	\
	BEE_FOR_EACH_SELECTED_KEYFRAME_REVERSE(KEY_IDX, ERR)				\
		DONT_FAIL_START(ERR)

#define		FEE_BEE_END_EACH_SELECTED_KEYFRAME_REVERSE(ERR)		\
		DONT_FAIL_END(ERR);										\
	BEE_END_EACH_SELECTED_KEYFRAME_REVERSE(ERR)
/* ---------------------------------------------------- */			


typedef struct {
	char	dimensions[32];
	char	duration[32];
	char	framerate[32];
	char	color_depth[50];
	char	audio[32];
	char	deinterlace[32];
	char	pulldown[32];
} ItemInfoStrs;

enum	{
	kUniqueItemName, 
	kUniqueLayerName, 
	kUniqueRenderSettingsName, 
	kUniqueOutputModuleName
};
typedef short EGG_UniqueNameType;

enum	{
	kResHigh = 1, kResMedium, kResThird, kResLow, kResSeparator, kResCustom
};

class	CDirProjItem;
class	CPanoProjItem;

void	SetAppResFileRefNum(short resRefNum);
short	GetAppResFileRefNum(void);
void	UseAppResFile(void);

typedef enum {
	FEE_ItemIcon_UNKNOWN, 
	FEE_ItemIcon_PICT, 
	FEE_ItemIcon_VIDEO, 
	FEE_ItemIcon_COMP, 
	FEE_ItemIcon_AUDIO, 
	FEE_ItemIcon_AV, 
	FEE_ItemIcon_SOLID, 
	FEE_ItemIcon_RENDER, 
	FEE_ItemIcon_FOLDER, 
	FEE_ItemIcon_SEQUENCE, 
	FEE_ItemIcon_VECTOR
} FEE_ItemIconType;

FEE_ItemIconType	GetBEEItemIcon(BEE_ItemH itemH);

short	MenuItemToDSF(short menuItem);
short	DsfToMenuItem(BEE_Dsf dsf);
long	DsfMenuItemToCommand(short menuItem);

void	SetGlobalTimeLinkage(long linkage);
void	SeekItemToTime(BEE_ItemH item, const TDB_TimeRecord *timeRec);

void	MakeUniqueName(	EGG_UniqueNameType type, 		//		>>	what type (comp, solid etc)
						void *data, 					//		>>	any necessary data
						char *name);					//		<>	default name in, unique name out

void	GetStreamText(	BEE_LayerH			theLayer, 
						BEE_StrmType		streamType, 
						BEE_StreamValue		*streamValue, 
						char				*streamText);

void			NullBeeCommand(void);

void			SetStreamToNotVary(BEE_LayerH layerH, BEE_StrmType streamType);

short			GetStreamTemporalDimension(TDB_StreamH streamH);

void			GetNudgeValue(long cmd, long modifiers, short *dx, short *dy);
void			CaptureWindowState(void);

class			CDirProject;
void			RestoreWindowState(CDirProject *theSupervisor);

void			DoGotoTime(BEE_ItemH theItem);


typedef enum {
	kFormatTime, kFormatDuration
} TimeFormatType;



typedef struct _TimeFormatInfo {
	Boolean			use_timecode;		// otherwise, frames or feet/frames
	Boolean			nondrop30;
	Boolean			spare1, spare2;
	long			timecode_framemax;	// usually 24, 25, or 30
	long			frames_per_foot;	// zero means just do frames, usually 0, 16, or 40
	long			starting_frame;		// for frame times only
} TimeFormatInfo;


typedef struct {
	Boolean		negative;				// zero for non-timecode
	Boolean		pad1, pad2, pad3;
	long		hours, mins, secs;		// zero for non-timecode
	long		feet;					// zero for timecode or frames_per_foot == 0
	long		frames;					// interpreted by TFI.fps but NOT TFI.starting_frame
} TimeComponents;


void			TimeToComponents(const TDB_TimeRecord *tr,
								const TimeFormatInfo *tfi0,		// if NULL, uses Std
								TimeFormatType format_type,
								M_Fixed underlying_fps0,
								TimeComponents *tc);			/* << */

void			ComponentsToTime(const TimeComponents *tc,
								const TimeFormatInfo *tfi0,		// if NULL, uses Std
								TimeFormatType format_type,
								M_Fixed underlying_fps0,
								TDB_TimeRecord *tr);

char *			GeneralFormatTime(const TDB_TimeRecord *tr,
								const TimeFormatInfo *tfi,
								TimeFormatType format_type,
								M_Fixed underlying_fps0,
								char *str);

void			SetStdTimeFormat(const TimeFormatInfo *tfi);
void			GetStdTimeFormat(TimeFormatInfo *tfi);

char *			FormatTime(const TDB_TimeRecord *tr, M_Fixed underlying_fps0, char *str);
char *			FormatDuration(const TDB_TimeRecord *tr, M_Fixed underlying_fps0, char *str);
								
char *			FormatItemTime(const TDB_TimeRecord *tr, BEE_ItemH itemH, char *str);
char *			FormatItemDuration(const TDB_TimeRecord *tr, BEE_ItemH itemH, char *str);

typedef enum {
	NIM_LayerOrigin_COMP, 
	NIM_LayerOrigin_FOOTAGE
} NIM_LayerOriginType;

M_Fixed			GetItemUnderlyingFPS(BEE_ItemH itemH);
M_Fixed			GetLayerUnderlyingFPS(BEE_LayerH layerH, NIM_LayerOriginType origin);

long			CountDeepFolderItems(BEE_ItemH folderH);


Boolean		GetTimeDialog(
				const char		*dialogTitle0, 
				TDB_TimeRecord	*tr, 
				M_Fixed			underlying_fps0);

Boolean		DoCoolTimeDialog(
				const char		*title0, 
				Boolean			allowNeg, 
				TDB_TimeRecord	*minTime0, 
				TDB_TimeRecord	*maxTime0, 
				TDB_TimeRecord	*timeRec, 
				M_Fixed			underlying_fps0);


Boolean			CouldEditFileExternally(BEE_ItemH itemH);
void			ShowFrameFileName(BEE_ItemH itemH, const TDB_TimeRecord *tr);
void			EditFileExternally(BEE_ItemH itemH, const TDB_TimeRecord *tr);

Boolean			StreamIsPointControl(BEE_LayerH theLayer, BEE_StrmType streamType);

void			SetValue2Digits(CNumText *t, short v);

char			*GetDepthString(PIN_AlphaType alphaType, short depth, char *buf);
void			ConvertDepthToString(short depth, MatteInfo matte_info, char *str);

void			GetItemInfoStrings(BEE_ItemH itemH, PIN_SeqSpecH pinH0, BEE_ItemInfo *info0, ItemInfoStrs *strs);
void			GetItemInfoStringsFromCompSettings(const BEE_CompSettings *cs, BEE_Dsf dsf, ItemInfoStrs *strs);

PIN_OptionsInfoH	GetPINOptionsPref(PIN_ModuleSignature sig);
void				DisposePINOptionsPref(PIN_OptionsInfoH *optionsH);
void				SavePINOptionsPref(PIN_ModuleSignature sig, PIN_OptionsInfoH optionsH);

void				StorePINOptions(PIN_OutSpecH pinoutH);

void 				GetMemoryString(Boolean purge_all, char *str);

void				RefreshCompWindows(
							BEE_ItemH	compItemH, 
							Boolean		compToo, 
							short		flags);

void				RefreshEffectsWindowsOfComp(BEE_ItemH compItemH, Boolean compToo);
void				RefreshLayerWindowsOfComp(BEE_ItemH compItemH, Boolean compToo);

void				SetLastDSF(BEE_Dsf dsf);
void				SetLastZoom(short zoom);
BEE_Dsf				GetDefaultDsf(void);
short				GetDefaultZoom(void);

Boolean				RealtimeUpdate(void);
Boolean				DelayedRealtimeUpdate(void);

//	note: on other platforms/compliers, bitfields may be reversed, 
//	so we must test them to see what order they come in
typedef struct {
	Rect		pos;
	unsigned	short	window_open	: 1;	//	hi bit
	unsigned	short	spare		: 7;	//	low seven bits
	unsigned	short	zoom_factor	: 8;	//	next byte (mac, metrowerks)
	void		*extra;
} FEE_BEE_WindowPos;

#define		FEE_WindowPos(ITEM)		(*(FEE_BEE_WindowPos *)&(DH(ITEM)->wind_pos))

typedef enum {
	FontStyle_NONE = -1,	// sentinel
	FontStyle_SYS = 0,		// system font, system size, system style (0, 0, 0)
	FontStyle_SMALL,		// U.S.: Geneva 9 -- usually small annotation text
	FontStyle_SMALL_BOLD,	// U.S.: Geneva 9 Bold -- more important small annotations
	FontStyle_SMALL_ITALIC,	// U.S.: Geneva 9 Italic -- missing things, etc.
	FontStyle_MED,			// U.S.: Geneva 10 -- times in in/out panels
	FontStyle_MED_BOLD,		// U.S.: Geneva 10 Bold
	FontStyle_APP,			// U.S.: Geneva 12
	FontStyle_APP_BOLD,		// U.S.: Geneva 12 Bold -- time in TL window
	FontStyle_APP_ITALIC,	// U.S.: Geneva 12 Italic
	FontStyle_UNUSED1,
	FontStyle_UNUSED2
} FontStyleSheet;

typedef struct {
	short	txFont;
	Style	txFace;
	short	txMode;
	short	txSize;
} FEE_FontInfoRec;

void		SaveFontInfo(FEE_FontInfoRec *fontRec);
void		RestoreFontInfo(FEE_FontInfoRec *fontRec);

void		GetFontStyleSheet(FontStyleSheet sheet,				/* >> */
					short *font0, short *size0, short *style0);	/* << */

void		SetFontSizeStyleFromSheet(FontStyleSheet sheet);	/* >> */

void		NewDashItems(MenuHandle theMenu, int firstItem, int lastItem, long itemFlags);

MenuHandle	FindMenu(short menuID, Boolean genevaNine);
long		PopUpSmallMenuSelect(MenuRef menu, short top, short left, short popUpItem);
long		PopUpSmallFixedWidthMenuSelect(MenuRef menu, short fixed_width0,
											short top, short left, short popUpItem);

void		StepBack(BEE_ItemH compItemH, TDB_TimeRecord *timeRec);
char *		SecsToDate(u_long secs, char *buf);
char *		FormatSeconds(long secs, char *buf);

#define IS_2997_FPS(FIXED_RATE)		(M_ABS(M_FLOAT2FIX(29.97) - (FIXED_RATE)) < 2)

Boolean		GeneralAlert(short alert_id, const char *string);
Boolean		OkCancelAlert(const char *string);

void		InstallExtraXFerModes(void);
short		DoPopupMenu(MenuHandle theMenu, short menuItem, Point thePoint);

typedef	enum {
	FEE_MenuCheckMark_NONE, 
	
	FEE_MenuCheckMark_CHECK,
	FEE_MenuCheckMark_BULLET, 
	FEE_MenuCheckMark_DASH, 
	
	FEE_MenuCheckMark_NUMTYPES
} FEE_MenuCheckMarkType;

void	GetMenuCheckMarkChar(
	FEE_MenuCheckMarkType	markType, 
	FontStyleSheet			styleSheet, 
	char					*returnChar);

typedef enum {
	kFirstKeyTableID = 128,
	
	kCSwitchboardKeyTableID = kFirstKeyTableID,
	kCEggAppKeyTableID,
	kCEggAppToolKeyTableID,
	kCCompTimeKeyTableID,
	kCCompCmdKeyTableID,
	kCCompPanoCmdKeyTableID,
	kCCompCCompCmdKeyTableID,
	kCCompMarkerCmdKeyTableID,
	kCDirProjItemTimeKeyTableID,
	kCDirWindowKeyTableID,
	kCItemKeyTableID,
	kCPanoECOutlineKeyTableID,
	kCPanoProjFootageKeyTableID,
	kCPanoProjItemKeyTableID,
	kCPanoProjLayerKeyTableID,
	kCPanoProjLayerPanoKeyTableID,
	kCPanoRenderKeyTableID,
	kCPanoSequencerKeyTableID,

	kLastPlusOneKeyTableID,
	kLastKeyTableID = kLastPlusOneKeyTableID - 1,
	kNumTableEntries = kLastPlusOneKeyTableID - kFirstKeyTableID
} KeyTableID;


void		SetupOverrideKeytables(void);

void		SetupWriteKeytablesToResources(void);

long		NewTranslateKeyToCommand(KeyTableID unique_id,
				const KeyCmd *kc,
				const EventRecord *evt);

void		NewAddTableShortcutsToMenus(KeyTableID unique_id,
				const KeyCmd *table);


#endif
