/*==============================================================================
Microsoft Denali

Microsoft Confidential.
Copyright 1996-1999 Microsoft Corporation. All Rights Reserved.

File:			templcap.h
Maintained by:	DaveK
Component:		include file for CTemplate 'captive' classes
				'captive' == only used internally within CTemplate
	
==============================================================================*/

// forward refs
class CBuffer;
class CFileMap;
class DIR_MONTIOR_ENTRY;

/*	============================================================================
	Enum type:	SOURCE_SEGMENT
	Synopsis:	A contiguous segment of a source template, e.g. primary script, html, etc.
*/
enum SOURCE_SEGMENT
	{
	ssegHTML,
	ssegPrimaryScript,
	ssegTaggedScript,
	ssegObject,
	ssegInclude,
	ssegMetadata,
	ssegHTMLComment,
        ssegFPBot,
	};

/*	****************************************************************************
	Class:		CSourceInfo
	Synopsis:	Info on the source of an output

	NOTE: The target offsets are strictly increasing, so it is binary
	      searchable.  (This is good because this is the search key
	      used by the debugger workhorse API, GetSourceContextOfPosition)
	      Beware, however, that source offsets and line #s are not, in
	      general, binary searchable because of #include files being thrown
	      into the mix.

		TODO DBCS:
	      Both the corresponding byte AND character offsets for the source are
	      stored in this table.  Character offsets are used by all of the API
	      interfaces, but the GetText() API must know what byte offset corresponds
	      to a character offset.  To figure this out, GetText() looks for the
	      closest character offset in the file and uses that as its base for
	      figuring out the byte offset.
*/
class CSourceInfo
	{
	public:
		CFileMap *		m_pfilemap;			// filemap to source file
		unsigned		m_cchTargetOffset;	// target offset (target line # implicit)
		unsigned		m_cchSourceOffset;	// character offset of the source line
		unsigned		m_cchSourceText;	// # of characters in the source statement
		unsigned		m_idLine:31;		// line number in source file
		unsigned		m_fIsHTML:1;		// line number is start of HTML block

		// UNSAFE if virtual functions ever added to this class!
		CSourceInfo() { memset(this, 0, sizeof(*this)); }
	};

/*	****************************************************************************
	Class:		CTargetOffsetOrder
	Synopsis:	provides ordering function for GetBracketingPair() based on
	            target offsets in the CSourceInfo array
*/
class CTargetOffsetOrder
	{
	public:
		BOOL operator()(const CSourceInfo &si, ULONG ul)
			{ return si.m_cchTargetOffset < ul; }

		BOOL operator()(ULONG ul, const CSourceInfo &si)
			{ return ul < si.m_cchTargetOffset; }
	};

/*	****************************************************************************
	Class:		CBuffer
	Synopsis:	A self-sizing memory buffer
*/
class CBuffer
	{
	private:
		CByteRange*	m_pItems;		// ptr to items (i.e. byte ranges)
		USHORT		m_cSlots;		// count of item slots allocated
		USHORT		m_cItems;		// count of items actually stored
		BYTE*		m_pbData;		// ptr to local data storage for items
		ULONG		m_cbData;		// size of local data storage for items
		ULONG		m_cbDataUsed;	// amount of local data storage actually used

	public:
		CBuffer();
		~CBuffer();
		void		Init(USHORT cItems, ULONG cbData);
		USHORT		Count()	{	return m_cItems;	}
		USHORT		CountSlots()	{	return m_cSlots;	}
		void		GetItem(UINT i, CByteRange& br);
		CByteRange* operator[](UINT i) { return &m_pItems[i]; }
		void		SetItem(UINT i, const CByteRange& br, BOOL fLocal, UINT idSequence, CFileMap *pfilemap, BOOL fLocalString = FALSE);
		void		Append(const CByteRange& br, BOOL fLocal, UINT idSequence, CFileMap *pfilemap, BOOL fLocalString = FALSE);
		LPSTR		PszLocal(UINT i);

        // Cache on per-class basis
        // ACACHE_INCLASS_DEFINITIONS()
	};

/*	****************************************************************************
	Class:		CScriptStore
	Synopsis:	Working storage for script segments during compilation.

	Terminology
	-----------
	Engine		== a particular script engine (VBScript, JavaScript, etc)
	Segment		== a contiguous chunk of script text in the source file
*/
class CScriptStore
	{
public:
	CBuffer**		m_ppbufSegments;	// ptr to array of ptrs to script segment buffers, one per engine
	UINT			m_cSegmentBuffers;	// count of script segment buffers
	CBuffer			m_bufEngineNames;	// buffer of engine names, one per engine
	PROGLANG_ID* 	m_rgProgLangId;		// array of prog lang ids, one per engine
	
	CScriptStore(): m_ppbufSegments(NULL), m_cSegmentBuffers(0), m_rgProgLangId(NULL) {}
	~CScriptStore();
	HRESULT	Init(LPCSTR szDefaultScriptLanguage, CLSID *pCLSIDDefaultEngine);
	USHORT 	CountPreliminaryEngines() { return m_bufEngineNames.Count(); }
	HRESULT	AppendEngine(CByteRange& brEngine, PROGLANG_ID*	pProgLangId, UINT idSequence);
	USHORT 	IdEngineFromBr(CByteRange& brEngine, UINT idSequence);
	void	AppendScript(CByteRange& brScript, CByteRange& brEngine, BOOLB fPrimary, UINT idSequence, CFileMap* pfilemap);

	};

/*	****************************************************************************
	Class:		CObjectInfo
	Synopsis:	Information about an object which can be determined at compile time
*/
class CObjectInfo
	{
public:
	CLSID	    m_clsid;	// clsid
	CompScope	m_scope;	// scope: application, session, page
	CompModel	m_model;	// threading model: single, apt, free
	};

/*	****************************************************************************
	Class:		CObjectInfoStore
	Synopsis:	Working storage for object-infos during compilation.
*/
class CObjectInfoStore
	{
public:
	CObjectInfo*	m_pObjectInfos;		// array of object infos
	CBuffer			m_bufObjectNames;	// buffer of object names

	CObjectInfoStore(): m_pObjectInfos(NULL) {}
	~CObjectInfoStore();
	void	Init();
	void	AppendObject(CByteRange& brObjectName, CLSID clsid, CompScope scope, CompModel model, UINT idSequence);
	USHORT	Count() { return m_bufObjectNames.Count(); }

	};

/*	****************************************************************************
	Class:		CWorkStore
	Synopsis:	Working storage for template components
*/
class CWorkStore
	{
public:
	CBuffer				m_bufHTMLSegments;	// buffer of HTML segments
	CObjectInfoStore	m_ObjectInfoStore;	// object-infos store
	CScriptStore		m_ScriptStore;		// script store
	UINT				m_idCurSequence;	// sequence number for current segment
	CByteRange			m_brCurEngine;		// current script engine
	BOOLB				m_fPageCommandsExecuted;	// have we executed page-level @ commands yet?
	BOOLB				m_fPageCommandsAllowed;		// are we allowed to execute page-level @ commands?
													// (will be true iff we have not yet compiled any line of script)
	LPSTR				m_szWriteBlockOpen;			// open  for Response.WriteBlock() equivalent
	LPSTR				m_szWriteBlockClose;		// close for Response.WriteBlock() equivalent
	LPSTR				m_szWriteOpen;				// open  for Response.Write() equivalent
	LPSTR				m_szWriteClose;				// close for Response.Write() equivalent

	
	
	
			CWorkStore();
			~CWorkStore();
	void 	Init();
	USHORT 	CRequiredScriptEngines(BOOL	fGlobalAsa);
	BOOLB 	FScriptEngineRequired(USHORT idEnginePrelim, BOOL	fGlobalAsa);

	};

/*	****************************************************************************
	Class:		COffsetInfo
	Synopsis:	map byte offsets to character offsets (different for DBCS)
				on line boundaries

	Each CFileMap has an array of these COffsetInfo structures at each line boundary.
	It stores these at the same offsets in the CSourceInfo array so that a simple
	binary search is all that's needed to convert offsets.
*/
class COffsetInfo
	{
	public:
		unsigned		m_cchOffset;		// character offset in file
		unsigned		m_cbOffset;			// byte offset in file

		// UNSAFE if virtual functions ever added to this class!
		COffsetInfo() { memset(this, 0, sizeof(*this)); }
	};

/*	****************************************************************************
	Class:		CByteOffsetOrder
	Synopsis:	provides ordering function for GetBracketingPair() based on
				byte offsets in the COffsetInfo array
*/
class CByteOffsetOrder
	{
	public:
		BOOL operator()(const COffsetInfo &oi, ULONG ul)
			{ return oi.m_cbOffset < ul; }

		BOOL operator()(ULONG ul, const COffsetInfo &oi)
			{ return ul < oi.m_cbOffset; }
	};

/*	****************************************************************************
	Class:		CCharOffsetOrder
	Synopsis:	provides ordering function for GetBracketingPair() based on
				character offsets in the COffsetInfo array
*/
class CCharOffsetOrder
	{
	public:
		BOOL operator()(const COffsetInfo &oi, ULONG ul)
			{ return oi.m_cchOffset < ul; }

		BOOL operator()(ULONG ul, const COffsetInfo &oi)
			{ return ul < oi.m_cchOffset; }
	};

/*	****************************************************************************
	Class:		CFileMap
	Synopsis:	A memory-mapping of a file

	NOTE: We store an incfile-template dependency by storing an incfile ptr in m_pIncFile.
	This is efficient but ***will break if we ever change Denali to move its memory around***
*/
class CFileMap
	{
public:
	TCHAR *					m_szPathInfo;			// file's virtual path (from www root)
	TCHAR *					m_szPathTranslated;		// file's actual file system path
	union {											// NOTE: m_fHasSibling is used to disambiguate these two
		CFileMap*			m_pfilemapParent;		// ptr to filemap of parent file
		CFileMap*			m_pfilemapSibling;		// ptr to next filemap in same level of hierarchy
	};
	CFileMap*				m_pfilemapChild;		// index of first filemap in next lower level of hierarchy
	HANDLE					m_hFile;				// file handle
	HANDLE					m_hMap;					// file map handle
	BYTE*					m_pbStartOfFile;		// ptr to start of file
	CIncFile*				m_pIncFile;				// ptr to inc-file object
	PSECURITY_DESCRIPTOR	m_pSecurityDescriptor;	// ptr to file's security descriptor
	unsigned long			m_dwSecDescSize:30;		// size of security descriptor
	unsigned long			m_fHasSibling:1;		// Does a sibling exist for this node?
	unsigned long			m_fHasVirtPath:1;		// Is m_szPathInfo the virtual or physical path?
	FILETIME	            m_ftLastWriteTime;		// last time the file was written to
	DWORD					m_cChars;				// # of characters in the file
	vector<COffsetInfo>		m_rgByte2DBCS;			// line-by-line map of byte offsets to DBCS
	CDirMonitorEntry*		m_pDME;				// pointer to directory monitor entry for this file

				CFileMap();
				~CFileMap();
	void 		MapFile(LPCTSTR szFileSpec, LPCTSTR szApplnPath, CFileMap* pfilemapParent, BOOL fVirtual, CHitObj* pRequest, BOOL fGlobalAsp);
	void		RemapFile();
	void 		UnmapFile();

	CFileMap*	GetParent();
	void		SetParent(CFileMap *);

	void		AddSibling(CFileMap *);
	CFileMap*	NextSibling() { return m_fHasSibling? m_pfilemapSibling : NULL; }

	BOOL		FIsMapped()
					{ return m_pbStartOfFile != NULL; }

	BOOL		FHasVirtPath() 
					{ return m_fHasVirtPath; }

	BOOL		FCyclicInclude(LPCTSTR szPathTranslated);
	BOOL		GetSecurityDescriptor();
	DWORD       GetSize() { return GetFileSize(m_hFile, NULL); }		// return # of bytes
	DWORD		CountChars(WORD wCodePage);							// return # of chars

	// implementation of debugging iterface - CTemplate & CIncFile eventually delegate to this function
	HRESULT		GetText(WORD wCodePage, ULONG cchSourceOffset, WCHAR *pwchText, SOURCE_TEXT_ATTR *pTextAttr, ULONG *pcChars, ULONG cMaxChars);

	// Cache on per-class basis
	ACACHE_INCLASS_DEFINITIONS()
	};

/*	****************************************************************************
	Class:		CTokenList
	Synopsis:	A list of tokens.
*/
class CTokenList
{
public:
	/*	========================================================================
	Enum type:	TOKEN
	Synopsis:	Token type.
				NOTE: keep sync'ed with CTokenList::Init()
	*/
	enum TOKEN
	{
		//======== Opener tokens ==================================
		tknOpenPrimaryScript,	// open primary script segment
		tknOpenTaggedScript,	// open tagged script segment
		tknOpenObject,			// open object segment
		tknOpenHTMLComment,		// open HTML comment
		
		//======== Non-opener tokens ==============================
		tknNewLine,				// new line

		tknClosePrimaryScript,	// close primary script segment
		tknCloseTaggedScript,	// close primary script segment
		tknCloseObject,			// close object segment
		tknCloseHTMLComment,	// close HTML comment
		tknEscapedClosePrimaryScript,	// escaped close-primary-script symbol

		tknCloseTag,			// close object or script tag

		tknCommandINCLUDE,		// server-side include (SSI) INCLUDE command
		
		tknTagRunat,			// RUNAT script/object attribute
		tknTagLanguage,			// LANGUAGE tag: page-level compiler directive or script block attribute
		tknTagCodePage,			// CODEPAGE tag: page-level compiler directive
		tknTagLCID,				// LCID tag: page-level compiler directive
		tknTagTransacted,		// TRANSACTED tag: page-level compiler directive
		tknTagSession,		    // SESSION tag: page-level compiler directive
		tknTagID,				// ID object attribute
		tknTagClassID,			// CLASSID object attribute
		tknTagProgID,			// PROGID object attribute
		tknTagScope,			// SCOPE object attribute
		tknTagVirtual,			// VIRTUAL include file attribute
		tknTagFile,				// FILE include file attribute
		tknTagMETADATA,			// METADATA tag - used by IStudio
//		tknTagSetPriScriptLang,	// sets primary script language, as in <% @ LANGUAGE = VBScript %>
        tknTagName,             // NAME inside METADATA
		tknValueTypeLib,        // TypeLib inside METADATA (has to be before TYPE in the list)
        tknTagType,             // TYPE inside METADATA
        tknTagUUID,             // UUID inside METADATA
        tknTagVersion,          // VERSION inside METADATA
        tknTagStartspan,        // STARTSPAN inside METADATA
        tknTagEndspan,          // ENDSPAN inside METADATA
        tknValueCookie,         // TYPE=Cookie inside METADATA
        tknTagSrc,              // SRC= inside METADATA
		
		tknValueServer,			// Server value - e.g. RUNAT=Server
		tknValueApplication,	// SCOPE=Application
		tknValueSession,		// SCOPE=Session
		tknValuePage,			// SCOPE=Page

		tknVBSCommentSQuote,	// VBS comment symbol
		tknVBSCommentRem,		// VBS comment symbol (alternate)

        tknTagFPBot,            // Front Page webbot tag
		
		tknEOF,					// end-of-file pseudo-token

		tkncAll					// pseudo-token: count of all tokens
	};

	void		Init();
	CByteRange* operator[](UINT i) { return m_bufTokens[i]; }
	CByteRange* operator[](TOKEN tkn) { return operator[]((UINT) tkn); }
	void		AppendToken(TOKEN	tkn, char* psz);
	TOKEN		NextOpenToken(CByteRange& brSearch, TOKEN* rgtknOpeners, UINT ctknOpeners, BYTE** ppbToken, LONG lCodePage);
	void		MovePastToken(TOKEN tkn, BYTE* pbToken, CByteRange& brSearch);
	BYTE*		GetToken(TOKEN tkn, CByteRange& brSearch, LONG lCodePage);

public:
	CBuffer		m_bufTokens;	// tokens buffer
};

/*	****************************************************************************
	Class:		CDocNodeElem
	Synopsis:	contains a pair of document nodes & application it belongs to
*/
class CDocNodeElem : public CDblLink
{
public:
	CAppln                *m_pAppln;
//	IDebugApplicationNode *m_pFileRoot;					// root of directory hierarchy
	IDebugApplicationNode *m_pDocRoot;					// root of template document hierarchy

	// ctor
	CDocNodeElem(CAppln *pAppln, /*IDebugApplicationNode *pFileRoot,*/ IDebugApplicationNode *pDocRoot);

	// dtor
	~CDocNodeElem();
};