/*	TResDocument.h
 *
 *		Resource document object; this mediates access to the internal database
 *	for resource document objects
 */

/*  YAAF Constructor - Rapid application development for YAAF
 *  Copyright (C) 1998 William Edward Woody
 *  
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
 *  02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#ifndef PandaWave_TRESDOCUMENT
#define PandaWave_TRESDOCUMENT

#include <stdio.h>
#include <stdlib.h>
#include <XDialog.h>
#include <XDocument.h>
#include <XHandle.h>
#include <XDynArray.h>
#include "TFile.h"

/************************************************************************/
/*																		*/
/*	Forwards															*/
/*																		*/
/************************************************************************/

class XGWindow;

/************************************************************************/
/*																		*/
/*	Internal Messages													*/
/*																		*/
/************************************************************************/

#define	KRevertDoc				'REVd'
#define KChangeSelect			'CHsl'

/*	ChangeSelect
 *
 *		Change selection record
 */

struct ChangeSelect {
	short						type;
	long						index;
};

/************************************************************************/
/*																		*/
/*	Predefine Types														*/
/*																		*/
/************************************************************************/

/*	PredefValue
 *
 *		Predefined value
 */

struct PredefValue {
	char						*value;
};

/*	PredefValueRecord
 *
 *		The thing to scan for the predefined values
 */

struct PredefValueRecord {
	long						viewType;
	PredefValue					*viewValue;
};

extern PredefValueRecord		GPredefValues[];

/*	PredefDeclaration
 *
 *		Predefined type declaration
 */

struct PredefDeclaration {
	unsigned char				type;
	char						*name;
};

/*	PredefTypeRecord
 *
 *		Predefined type record
 */

struct PredefTypeRecord {
	long						viewType;
	long						viewChild;
	char						*className;
	PredefDeclaration			*declList;
};

extern PredefTypeRecord			GPredefTypes[];

/************************************************************************/
/*																		*/
/*	Description Objects													*/
/*																		*/
/************************************************************************/

/*	ViewTypeRecord
 *
 *		How a view type declaration
 */

struct ViewTypeRecord {
	XGWindow					*window;

	bool						noDelete;			// unable to delete?
	bool						mark;				// Used internally
	long						viewType;
	ViewTypeRecord				*childPtr;			// child decl ptr
	char						className[256];		// name of this thing
	XGStringList				*declaration;		// declaration of this
		
	/*
	 *	Support methods
	 */
	
	long						LenDeclaration();	// # elements in decl
	short						GetDeclItem(long);	// Decl item
	void						GetDeclText(long,char *);
};

/*	ViewItemDeclaration
 *
 *		How a view is itself declared
 */

struct ViewItemDeclaration {
	long						viewType;
	struct ViewItemDeclaration	*child;
	struct ViewItemDeclaration	*sibling;			// sibling to this view
	
	XGStringList				*data;				// data in this thing as strings
};

/*	ViewDeclaration
 *
 *		How a view is declared
 */

struct ViewDeclaration {
	short						viewResID;
	char						viewResName[256];
	
	ViewItemDeclaration			*view;
	XGWindow					*window;
};

/*	ErrorDeclaration
 *
 *		How error messages are declared
 */

struct ErrorDeclaration {
	short						errorResID;
	char						errorResName[256];
	
	XGStringList				*smsg;
	XGStringList				*lmsg;
	XGWindow					*window;
};

/*	FontDeclaration
 *
 *		How fonts are declared
 */

struct FontDeclaration {
	short						fontResID;
	char						fontResName[256];
	
	short						flags;
	short						size;
	char						fontName[256];
};

/*	ResInfoRecord
 *
 *		Resource information
 */

struct ResInfoRecord {
	class TResDocument			*doc;
	short						type;
	long						index;
	char						name[256];
	
	union {
		short					resID;
		struct {
			long				classID;
			long				baseID;
		}						t;
	};
};

/************************************************************************/
/*																		*/
/*	Support																*/
/*																		*/
/************************************************************************/

extern void To4Char(char *out, long in);
extern long From4Char(char *in);

/************************************************************************/
/*																		*/
/*	Classes																*/
/*																		*/
/************************************************************************/

/*	TResDocument
 *
 *		The resource document. This is the resource database object which
 *	stores information about the view, string, menu and other resources
 */

class TResDocument : public XGDocument {
	public:
								TResDocument();
		virtual					~TResDocument();
		
		/*
		 *	Document construction
		 */
		
		static TResDocument		*NewDocument();
		static TResDocument		*OpenDocument();
#if OPT_MACOS
		static TResDocument		*OpenDocument(FSSpec *);
#endif

#if OPT_WINOS || OPT_XWIN
		static TResDocument		*OpenDocument(char *);
#endif

		/*
		 *	Document save/restore hooks
		 */
		
		bool					IsDocumentNamed();
		bool					IsDocumentDirty();
		void					GetDocumentName(char *);
		bool					DoDocumentSave();
		bool					DoDocumentSaveAs();
		void					DoDocumentRevert();
		
		/*
		 *	Resource export
		 */
		
		void					ExportMacintosh();
		void					ExportWindows();
		void					ExportUnix();
		
		/*
		 *	Mark dirty flag
		 */
		
		void					MarkDirty()
									{
										fDirty = true;
										DocumentChanged();
									}
		
		/*
		 *	View type declaration
		 */
		
		long					GetNumViewType()
									{
										return fViewType.Length();
									}
									
		ViewTypeRecord			*GetViewTypeByIndex(long index)
									{
										return fViewType[index];
									}
		ViewTypeRecord			*GetViewTypeByType(long);
		long					NewViewType(void);
		void					DeleteViewType(long);
		
		/*
		 *	View declaration
		 */
		
		long					GetNumViews()
									{
										return fViewDecl.Length();
									}
		ViewDeclaration			*GetViewDeclaration(long index)
									{
										return fViewDecl[index];
									}
		long					NewViewDeclaration(short resID);
		void					DeleteViewDeclaration(long);
		
		/*
		 *	View declaration support
		 */
		
		void					ConvertToHandle(ViewItemDeclaration *, XGHandle &);
		void					ConvertResource(ViewItemDeclaration *, XGHandle &);
		void					GetViewResource(long index, XGHandle &);

		/*
		 *	Error declaration
		 */
		
		long					GetNumErrors()
									{
										return fErrorDecl.Length();
									}
		ErrorDeclaration		*GetErrorDeclaration(long index)
									{
										return fErrorDecl[index];
									}
		long					NewErrorDeclaration(short resID);
		void					DeleteErrorDeclaration(long);
		void					GetErrorResource(long index, XGHandle &);
		
		/*
		 *	Font declaration
		 */
		
		long					GetNumFonts()
									{
										return fFontDecl.Length();
									}
		FontDeclaration			*GetFontDeclaration(long index)
									{
										return fFontDecl[index];
									}
		long					NewFontDeclaration(short resID);
		void					DeleteFontDeclaration(long);
		void					GetFontResource(long index, XGHandle &);
		
		/*
		 *	Resource editing support
		 */
		
		void					DoCreateResource(void);
		void					DoEditResource(short type, long index);
		void					DoGetResInfo(short type, long index);
		void					DoDeleteResource(short type, long index);

		/*
		 *	Events
		 */
		
		DECLAREDISPATCH
		long					DoMenuCommand(long, void *);
		long					DoGetMenuStatus(long, void *);
	private:
		bool					DoOpenDialog();
		bool					DoSaveDialog();
		TFile					*DoSaveExtension(const char *ext);
		void					DeleteAll();
		
		void					AddChecksum();
		bool					VerifyChecksum();
		
		bool					fDirty;
		char					fName[256];
		TFile					*fFile;
		
		/*
		 *	Verify tree
		 */
		
		void					DoDeleteByType(long type);
		bool					VerifyDelete(long index);
		bool					VerifyAdd(long type, long base);
		bool					VerifyChange(long index, long type, long base);
		
		/*
		 *	High level save/load
		 */
		
		void					WriteHandle(long type, XGHandle &data);
		void					ReadHandle(long *type, XGHandle &data);
		
		/*
		 *	Low level conversion
		 */
		
		void					ToHandle(ViewTypeRecord *v, XGHandle &data);
		void					ToHandle(ViewDeclaration *v, XGHandle &data);
		void					ToHandle(ErrorDeclaration *v, XGHandle &data);
		void					ToHandle(FontDeclaration *v, XGHandle &data);
		
		void					InsertViewType(XGHandle &data);
		void					InsertViewDeclaration(XGHandle &data);
		void					InsertErrorDeclaration(XGHandle &data);
		void					InsertFontDeclaration(XGHandle &data);
		
		long					AppendHandle(ViewItemDeclaration *, XGHandle &data);
		ViewItemDeclaration		*GetItemFromHandle(XGHandle &data, long pos);
		void					DeleteViewItem(ViewItemDeclaration *);
		
		static long				CreateResourceDialog(XGDialog *, void *, long, long, void *);
		
		/*
		 *	Edit font specification
		 */
		
		static long				EditFontDialog(XGDialog *, void *, long, long, void *);
		void					EditFont(long index);
		
		/*
		 *	Resource sort
		 */
		
		void					SortResArray(long len, void *array);

		XGPDynArray<ViewTypeRecord>		fViewType;
		XGPDynArray<ViewDeclaration>	fViewDecl;
		XGPDynArray<ErrorDeclaration>	fErrorDecl;
		XGPDynArray<FontDeclaration>	fFontDecl;
};

#endif // PandaWave_TRESDOCUMENT
