/*
 *
 *  AM --- AmigaMail
 *  (C) 1991, 1992 by Christian Riede
 *
 *  AM is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY.  No author or distributor accepts responsibility to anyone
 *  for the consequences of using it or for whether it serves any
 *  particular purpose or works at all, unless he says so in writing.
 *  Refer to the GNU General Public License, Version 1, for full details.
 *  
 *  Everyone is granted permission to copy, modify and redistribute AM,
 *  but only under the conditions described in the GNU General Public
 *  License, Version 1.  A copy of this license is supposed to have been 
 *  given to you along with AM so you can know your rights and responsi-
 *  bilities.  It should be in a file named COPYING.  Among other things,
 *  the copyright notice and this notice must be preserved on all copies.
 *
 *  
 *
 */

#include "am.h"

#define addrcmp(s,t) strcmp(s,t)

#if 0
static int addrcmp(char *s,char *t)
{
	char a[MAIL_FIELDLENGTH],b[MAIL_FIELDLENGTH];

	GetUsername(s,a,MAIL_FIELDLENGTH);
	GetUsername(t,b,MAIL_FIELDLENGTH);

	s=a;
	t=b;

	while (*s)
	{
		if (toupper((int)*s)<toupper((int)*t))
			return(-1);
		if (toupper((int)*s)>toupper((int)*t))
			return(1);
		s++;
		t++;
	}
	return(0);

}
#endif

/* return pointer to first real subject character */
/* after cutting Re: like prefixes */
static char *stripre(char *s)
{
again:

	if (s[0]) if (isspace((int)s[0]))
	{
		s++;
		goto again;
	}

	if (s[0]) if (s[0]=='R')
		if (s[1]) if (s[1]=='E')
			if (s[2]) if (s[2]==':')
			{
				s+=3;
				goto again;
			}

	if (s[0]) if (s[0]=='A')
		if (s[1]) if (s[1]==':')
		{
			s+=2;
			goto again;
		}

	return(s);
}

#define subjcmp(s,t) strcmp(stripre(s),stripre(t))

#if 0
static int subjcmp(char *s,char *t)
{
	char a[160],b[160];
	strncpy(a,s,160);
	strncpy(b,t,160);

	/* change case to upper */
	s=a; while (*s) {*s=toupper((int)*s); s++;}
	s=b; while (*s) {*s=toupper((int)*s); s++;}
	
	return(strcmp(stripre(a),stripre(b)));
}
#endif

void InsertByNumber(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail))
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
		if (Scan->Number < Mail->Number)
			break;

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}

void InsertByFrom(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;
	int cmp;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail))
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
	{
		cmp = addrcmp(Scan->From,Mail->From);
		if (cmp>0 || (cmp==0 && Mail->Date>Scan->Date))
			break;
	}

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}

void InsertByTo(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;
	int cmp;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail))
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
	{
		cmp = addrcmp(Scan->To,Mail->To);
		if (cmp>0 || (cmp==0 && Mail->Date>Scan->Date))
			break;
	}

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}

void InsertBySubject(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;
	int cmp;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail))
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
	{
		cmp = subjcmp(Scan->Subject,Mail->Subject);
		if (cmp>0 || (cmp==0 && Mail->Date>Scan->Date))
			break;
	}

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}

void InsertByDate(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail))
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
		if (Scan->Date < Mail->Date)
			break;

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}

void InsertByInReplyTo(struct List *Selected,struct Mail *Mail)
{
	struct Mail *Scan;

	if (Selected->lh_Head == (struct Node *)&(Selected->lh_Tail) || !*Mail->MsgId)
	{
		AddHead(Selected,&(Mail->m_SelectNode));
		return;
	}

	for (Scan=(struct Mail *)((char *)Selected->lh_Head-sizeof(struct Node));
		Scan->m_SelectNode.ln_Succ;
		Scan=(struct Mail *) ((char *)Scan->m_SelectNode.ln_Succ-sizeof(struct Node)))
	{
		if (strstr(Scan->MsgId,Mail->MsgId))
			break;
		if (!strcmp(Scan->MsgId,Mail->InReplyTo))
			break;
	}

	Insert(Selected,&(Mail->m_SelectNode),Scan->m_SelectNode.ln_Pred);
}
