#ifndef APP_AttrList_H
#define APP_AttrList_H
/******************************************************************************
 **
 **	C++ Class Library for the Amiga© system software.
 **
 **	Copyright (C) 1994 by Armin Vogt  **  EMail: armin@uni-paderborn.de
 **	All Rights Reserved.
 **
 **	$VER: apphome:APlusPlus/intuition/AttrList.h 1.04 (04.05.94) $
 **	
 ******************************************************************************/

extern "C" {
#include <utility/tagitem.h>
#ifdef __GNUG__
#include <inline/utility.h>
#endif

#ifdef __SASC
#include <proto/utility.h>
#endif
}
#include <iostream.h>
#include <APlusPlus/environment/APPObject.h>


/******************************************************************************

		AttrList class 
	
	This class handles Amiga® TagItem lists (arrays) for the uniform usage 
	throughout the A++ Library.
	
	Common terms for understanding TagItem lists:
	A 'tag list' is an array of 'tag items' each consisting of a 'tag value' indicating 
	the 'type' of the tag (therefore called 'TagValue' or 'TagType', sometimes 'Tag') 
	and a 'tag data' describing the 'data value' of the tag (refered to as 'DataValue' 
	or 'TagData').

 ******************************************************************************/

typedef struct TagItem *TagList;
// pointer to the first TagItem element of a TagItem array terminated with {TAG_END,0}
// divided into several array chunks that are linked with {TAG_MORE,<TagList>}.
	
class AttrIterator;
class AttrList
{
	friend AttrIterator;
	friend ostream& operator << (ostream& OS,const AttrList& attrlist);
	
	private:
		static struct TagItem *tmp;	// temporary taglist memory for temporary AttList objects
		static AttrList *tmpUser;		
		static int tmpMaxLength;	
		
		struct TagItem *copyTagItems(struct TagItem *tlist);
		void freeTagItems(struct TagItem *tlist);
		
	protected:
		struct TagItem *taglist;
				  		  	
	public:
		AttrList(struct TagItem *tl=NULL);
		AttrList(LONG tag1Type,...);
		AttrList(const AttrList& from);
		~AttrList();
		  	
		AttrList& operator=(const AttrList& from);	// assignment is copying
				
		operator struct TagItem*() const { return taglist; }
		  
		BOOL addAttrs(const AttrList& attrlist);
		AttrList& operator += (const AttrList&	add) { addAttrs(add); return *this; }
		BOOL updateAttrs(const AttrList& attrlist);
      // tags in 'this' that are present in both 'this' and 'attrlist' are updated to
      // the tag data value found in 'attrlist'.
		
		LONG getTagData(Tag tag,LONG defaultValue=0) const { 
		  	return (LONG)GetTagData(tag,defaultValue,taglist); }
			
		ULONG mapAttrs(AttrList& mapAt);
		ULONG filterAttrs(AttrList& filterAt);
		
		ULONG mapAttrs(struct TagItem *mapList);
		ULONG filterAttrs(struct TagItem *filterList);

		ULONG mapAttrs(Tag tag1Type,...) { return mapAttrs((struct TagItem*)&tag1Type); }
		ULONG filterAttrs(Tag tag1Type,...) { return filterAttrs((struct TagItem*)&tag1Type); }


		
};

inline AttrList operator + (const AttrList& op1,const AttrList& op2)
{
	AttrList tmp(op1);
	return tmp.addAttrs(op2);
}

ostream& operator << (ostream& OS,struct TagItem *tl);

class AttrIterator
{
	protected:
		const AttrList *al;
		struct TagItem *tstate,*atTag;	
		
	public:
		AttrIterator(const AttrList& alist) { al = &alist; atTag = tstate = alist.taglist; }
		  
		BOOL operator () () { return ((atTag = NextTagItem(&tstate))!=NULL); }
		void reset() { atTag = tstate = al->taglist; }
		  
		BOOL findTagItem(Tag tagVal);
		// find next occurancy of 'tagVal' tag item and set iterator to its position
		// if 'tagVal' could not be found the iterator remains at its position and the method returns FALSE.
		  
		Tag tag() { return atTag->ti_Tag; }
		LONG data() { return atTag->ti_Data; } 
};

class AttrManipulator : public AttrIterator
{
	public:
		AttrManipulator(AttrList& calist) : AttrIterator((const AttrList&)calist) {}
		
		void writeTag(Tag tagValue) { atTag->ti_Tag = tagValue; }
		void writeData(LONG tagData) { atTag->ti_Data = tagData; }   
		
};

#endif
