/*------------------------------------------------------------------------------*
 *	File Name:      llist.h		                                                *
 *	Purpose:        Link list management macros		                            *
 *	Creation:		1/1/89, by Dr. C. P. Yang                                   * 
 *	Copyright Microcal Software Inc. 1989-1995									*
 *	Modification log	                                                        *
 *	CPY v3.8 6/24/95 CPP_MENUS, convert to C++ compatible, add extern C			*
 *	sth v4.12 7/23/96 SAFE_EACH_LIST											*
 *	sth v4.133 9/20/96 GENERIC_LINK_LIST_SUPPORT								*
 *	sth v4.93 2/28/97 RENAMEING_SAFE_EACH_LIST									*
 *	ML 2/25/98 TEMPORARY_FRAME_FOR_PLOT_DETAILS_DLG								*
 *------------------------------------------------------------------------------*/

#ifdef __cplusplus  ///CPY v3.8 6/24/95 CPP_MENUS
extern "C" {            /* Assume C declarations for C++ */
#endif	/* __cplusplus */


///sth v4.133 9/20/96 GENERIC_LINK_LIST_SUPPORT
#define GENERIC_LINK_LIST_SUPORT
///end GENERIC_LINK_LIST_SUPPORT

///sth v4.12 7/23/96 SAFE_EACH_LIST
///sth v4.93 2/28/97 RENAMEING_SAFE_EACH_LIST
//this macro was designed spefically for recursive labtalk commands (over all windows etc)
//it was named incorectly as safe,here it has been re named AND made safer, i.e checks p before getting p->next
//#define EACH_LIST_ELEMENT_SAFE(head,p,pp)	for ( (p) = (head),(pp) = (p)->next ; (p) != NULL; (p) = (pp), (pp) = (p) != NULL ? (p)->next : NULL )
#define EACH_LIST_ELEMENT_RECURSIVE_LABTALK(head,p,pp)	for ( (p) = (head),(pp) = (p) != NULL ? (p)->next : NULL ; (p) != NULL; (p) = (pp), (pp) = (p) != NULL ? (p)->next : NULL )
///end RENAMEING_SAFE_EACH_LIST
///end SAFE_EACH_LIST

///sth v4.133 9/20/96 GENERIC_LINK_LIST_SUPPORT
#ifdef GENERIC_LINK_LIST_SUPORT

	#define GENERIC_EACH_LIST_ELEMENT(head,p,nextfield)	for ( (p) = (head); (p) != NULL; (p) = (p)->nextfield)

	/// ML 2/25/98 TEMPORARY_FRAME_FOR_PLOT_DETAILS_DLG
	#define	GENERIC_EACH_PAIR_LISTS_ELEMENTS(head1, p1, next1, head2, p2, next2)	for ( (p1) = (head1), (p2) = (head2); (p1) != NULL && (p2) != NULL; (p1) = (p1)->next1, (p2) = (p2)->next2)
	/// end TEMPORARY_FRAME_FOR_PLOT_DETAILS_DLG


	#define GENERIC_REMOVE_LIST_ELEMENT(head,pi,p,nextfield) 		{(p) = (head);	\
			if( (p) == (pi) ) {(head) = (pi)->nextfield;}							\
			else GENERIC_EACH_LIST_ELEMENT(head,p,nextfield)						\
			{ if( (p)->nextfield == (pi) ) 											\
					{(p)->nextfield = (pi)->nextfield;break;}						\
			}}

	#define GENERIC_ADD_LIST_ELEMENT(head,pi,p,nextfield)	{(pi)->nextfield = NULL;\
		if( (head) == NULL ) {(head) = (pi);}										\
		else																		\
		GENERIC_EACH_LIST_ELEMENT(head,p,nextfield) 								\
		{	if( (p)->nextfield == NULL ) 											\
			{ (p)->nextfield = pi;break; }											\
		}}

	#define GENERIC_LIST_ELEMENT(head,i,p,nextfield) { int indx = 0;				\
		GENERIC_EACH_LIST_ELEMENT((head),p,nextfield)								\
		{ if ( indx++ == (i) )	break; } }
	
	//sth 2/10/95
	//ps=search pointer, pt=temp pointer, head = list, past = where you wish the past pointer to be placed
	#define	GENERIC_PREVIOS_POINTER(head,ps,pt,past,nextfield) 						\
		{																			\
		if (head == ps)																\
			past = NULL;															\
		else																		\
			GENERIC_EACH_LIST_ELEMENT(head,pt,nextfield)                            \
			{																		\
				if (pt->nextfield == ps)											\
				{																	\
					past = pt;														\
					break;															\
				}                                      								\
			}																		\
		}	
	//

	#define	GENERIC_DELETE_LIST(head,p,nextfield)	while ( p = head ) {GENERIC_POP_LIST(head,,nextfield);DisposPtr(p);}

	#define GENERIC_POP_LIST(head,nextfield)	(head) = (head)->nextfield
	#define GENERIC_PUSH_LIST(head,p,nextfield) {(p)->nextfield = head;head = (p);}

	#define GENERIC_COUNT_LIST(head,p,n,nextfield) { n = 0; GENERIC_EACH_LIST_ELEMENT(head,p,nextfield) n++; }

	#define	GENERIC_LIST_INDEX(head,pi,p,n,nextfield) {n=0;GENERIC_EACH_LIST_ELEMENT(head,p,nextfield) {if (p == pi) break;n++;}}

	#define	GENERIC_REVERS_LIST(head,plast,p1,p2,new,nextfield) {p1=head;new=plast;	\
		while((p2 = p1) != plast) {GENERIC_POP_LIST(p1,nextfield);GENERIC_PUSH_LIST(new,p2,nextfield)};	\
		head=new;}

	#define GENERIC_INSERT_LIST_ELEMENT(head,pi,pnext,p,nextfield) 		{(p) = (head);	\
			if( (p) == (pnext) ) {(pi)->nextfield=(p);(head) = (pi);}					\
			else GENERIC_EACH_LIST_ELEMENT(head,p,nextfield) 							\
			{ if( (p)->nextfield == (pnext) ) 											\
					{(p)->nextfield = (pi);(pi)->nextfield=(pnext);break;}				\
			}}

	////
	#define EACH_LIST_ELEMENT(head,p)				GENERIC_EACH_LIST_ELEMENT(head,p,next)

	/// ML 2/25/98 TEMPORARY_FRAME_FOR_PLOT_DETAILS_DLG
	#define	EACH_PAIR_LISTS_ELEMENTS(head1, p1, head2, p2)	GENERIC_EACH_PAIR_LISTS_ELEMENTS(head1, p1, next, head2, p2, next)
	/// end TEMPORARY_FRAME_FOR_PLOT_DETAILS_DLG
	
	#define REMOVE_LIST_ELEMENT(head,pi,p)			GENERIC_REMOVE_LIST_ELEMENT(head,pi,p,next)

	#define ADD_LIST_ELEMENT(head,pi,p)				GENERIC_ADD_LIST_ELEMENT(head,pi,p,next)

	#define LIST_ELEMENT(head,i,p)					GENERIC_LIST_ELEMENT(head,i,p,next)

	#define	PREVIOS_POINTER(head,ps,pt,past)		GENERIC_PREVIOS_POINTER(head,ps,pt,past,next)

	#define	DELETE_LIST(head,p)						GENERIC_DELETE_LIST(head,p,next)

	#define POP_LIST(head)							GENERIC_POP_LIST(head,next)
	
	#define PUSH_LIST(head,p)						GENERIC_PUSH_LIST(head,p,next)

	#define COUNT_LIST(head,p,n)					GENERIC_COUNT_LIST(head,p,n,next)

	#define	LIST_INDEX(head,pi,p,n)					GENEIRC_LIST_INDEX(head,pi,p,n,next)

	#define	REVERS_LIST(head,plast,p1,p2,new)		GENERIC_REVERS_LIST(head,plast,p1,p2,new,next)

	#define INSERT_LIST_ELEMENT(head,pi,pnext,p)	GENERIC_INSERT_LIST_ELEMENT(head,pi,pnext,p,next)
	
///end GENERIC_LINK_LIST_SUPPORT
#else ///GENERIC_LINK_LIST_SUPPORT
	#define EACH_LIST_ELEMENT(head,p)	for ( (p) = (head); (p) != NULL; (p) = (p)->next)

	#define REMOVE_LIST_ELEMENT(head,pi,p) 		{(p) = (head);	\
			if( (p) == (pi) ) {(head) = (pi)->next;}			\
			else EACH_LIST_ELEMENT(head,p) 						\
			{ if( (p)->next == (pi) ) 							\
					{(p)->next = (pi)->next;break;}				\
			}}

	#define ADD_LIST_ELEMENT(head,pi,p)	{(pi)->next = NULL;		\
		if( (head) == NULL ) {(head) = (pi);}					\
		else													\
		EACH_LIST_ELEMENT(head,p) 								\
		{	if( (p)->next == NULL ) 							\
			{ (p)->next = pi;break; }							\
		}}

	#define LIST_ELEMENT(head,i,p) { int indx = 0;					\
		EACH_LIST_ELEMENT((head),p)								\
		{ if ( indx++ == (i) )	break; } }

	//sth 2/10/95
	//ps=search pointer, pt=temp pointer, head = list, past = where you wish the past pointer to be placed
	#define	PREVIOS_POINTER(head,ps,pt,past) 				\
		{								\
		if (head == ps)                                                 \
			past = NULL;                                            \
		else                                                            \
			EACH_LIST_ELEMENT(head,pt)                              \
			{                                                       \
				if (pt->next == ps)                             \
				{                                               \
					past = pt;                              \
					break;                                  \
				}                                      		\
			}                                                       \
		}	
	//

	#define	DELETE_LIST(head,p)	while ( p = head ) {POP_LIST(head);DisposPtr(p);}

	#define POP_LIST(head)	(head) = (head)->next
	#define PUSH_LIST(head,p) {(p)->next = head;head = (p);}

	#define COUNT_LIST(head,p,n) { n = 0; EACH_LIST_ELEMENT(head,p) n++; }

	#define	LIST_INDEX(head,pi,p,n) {n=0;EACH_LIST_ELEMENT(head,p) {if (p == pi) break;n++;}}

	#define	REVERS_LIST(head,plast,p1,p2,new) {p1=head;new=plast;	\
		while((p2 = p1) != plast) {POP_LIST(p1);PUSH_LIST(new,p2)};	\
		head=new;}

	#define INSERT_LIST_ELEMENT(head,pi,pnext,p) 		{(p) = (head);	\
			if( (p) == (pnext) ) {(pi)->next=(p);(head) = (pi);}		\
			else EACH_LIST_ELEMENT(head,p) 								\
			{ if( (p)->next == (pnext) ) 								\
					{(p)->next = (pi);(pi)->next=(pnext);break;}		\
			}}

	////

#endif ///GENERIC_LINK_LIST_SUPPORT


#ifdef __cplusplus
}
#endif	/* __cplusplus */
///CPY v3.8 6/24/95 CPP_MENUS
