/*************************************************************
 * WebMailFolder                                             *
 * COPYRIGHT 1998 by Norbert Kuemin <norbert.kuemin@gmx.net> *
 *************************************************************/
   
#define INDEX_FILE
#include "wmf.h"

struct {
    int Messages;
    time_t First;
    time_t Last;
    int Thread;
    int Subject;
    int Author;
} stats;

int WriteThreadLine(struct MAILHEAD *mh, int page, int page_counter, int level);

void DelHeader (struct MAILHEAD *mh) {

    if (config.DebugLevel & 1) printf(".DelHeader(%s)\n",mh->FileName);
    if (mh->Subject != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free Subject (%s)\n",mh->Subject);
	freechar(mh->Subject);
	mh->Subject = NULL;
    }
    if (mh->SendName != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free SendName (%s)\n",mh->SendName);
	freechar(mh->SendName);
	mh->SendName = NULL;
    }
    if (mh->SendAddress != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free SendAddress (%s)\n",mh->SendAddress);
	freechar(mh->SendAddress);
	mh->SendAddress = NULL;
    }
    if (mh->ReceiveName != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free ReceiveName (%s)\n",mh->ReceiveName);
	freechar(mh->ReceiveName);
	mh->ReceiveName = NULL;
    }
    if (mh->ReceiveAddress != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free ReceiveAddress (%s)\n",mh->ReceiveAddress);
	freechar(mh->ReceiveAddress);
	mh->ReceiveAddress = NULL;
    }
    if (mh->SentDate != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free SentDate (%s)\n",mh->SentDate);
	freechar(mh->SentDate);
	mh->SentDate = NULL;
    }
    if (mh->MsgId != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free MsgId (%s)\n",mh->MsgId);
	freechar(mh->MsgId);
	mh->MsgId = NULL;
    }
    if (mh->Reference != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free Reference (%s)\n",mh->Reference);
	freechar(mh->Reference);
	mh->Reference = NULL;
    }
    if (mh->Xface != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free Xface (%s)\n",mh->Xface);
	freechar(mh->Xface);
	mh->Xface = NULL;
    }
    if (mh->HomePage != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free HomePage (%s)\n",mh->HomePage);
	freechar(mh->HomePage);
	mh->HomePage = NULL;
    }
    if (mh->ssort != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free ssort (%s)\n",mh->ssort);
	freechar(mh->ssort);
	mh->ssort = NULL;
    }
    if (mh->FileName != NULL) {
	if (config.DebugLevel & 2)
	    printf("..free FileName (%s)\n",mh->FileName);
	freechar(mh->FileName);
	mh->FileName = NULL;
    }
}


void CleanAllHeader (struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;

    if (mh != NULL) {
	tmp_mh = mh->Next;
	while(tmp_mh != NULL) {
	    DelHeader(tmp_mh->Prev);
	    if (tmp_mh->Next == NULL) {
	        DelHeader(tmp_mh);
		if (config.DebugLevel & 2)
		    printf("..free mh\n");
		free(tmp_mh);
	        tmp_mh = NULL;
	    } else {
	        tmp_mh = tmp_mh->Next;
	    }
	}
	DelHeader(mh);
    }
}


struct MAILHEAD *ReadHtmlHeader (void) {
    FILE *fd;
    DIR *dd;
    struct dirent *DirEntry;
    char *FileName;
    char *HtmlVersion;
    char *VarName, *VarValue;
    char line[BUFSIZ];
    struct MAILHEAD *mh;
    struct MAILHEAD *last_mh;
    struct MAILHEAD *return_mh;
    time_t tmptime;
                    
    if (config.DebugLevel & 1) printf(".ReadHtmlHeader\n");
    mh = NULL;
    last_mh = NULL;
    return_mh = NULL;
    HtmlVersion = NULL;
    AppendFile("","");
    dd = opendir(config.Directory);
    DirEntry = readdir(dd);
    while (DirEntry != NULL) {
        if ((strncmp(DirEntry->d_name,"date",4) != 0) &&
            (strncmp(DirEntry->d_name,"subject",7) != 0) &&
            (strncmp(DirEntry->d_name,"thread",6) != 0) &&
            (strncmp(DirEntry->d_name,"author",6) != 0) &&
            (strncmp(DirEntry->d_name,"stats",5) != 0) &&
            (strncmp(DirEntry->d_name,"index",5) != 0) &&
            (strcmp(DirEntry->d_name,".") != 0) &&
            (strcmp(DirEntry->d_name,"..") != 0) &&
            (strstr(DirEntry->d_name,config.Extension) != NULL)) {
            FileName = newchar(strlen(config.Directory)
                + strlen(DirEntry->d_name) + 2);
            sprintf(FileName,"%s/%s",config.Directory,DirEntry->d_name);
	    fd = fopen(FileName,"r");
	    if (fd != NULL) {
		if (config.DebugLevel & 2) printf("..read %s\n",FileName);

	        /* a new entry */
		mh = (struct MAILHEAD *) malloc(sizeof(*mh));

		/* init the values */
                mh->Next = NULL;
		mh->Subject = NULL;
		mh->SendName = NULL;
		mh->SendAddress = NULL;
		mh->ReceiveName = NULL;
		mh->ReceiveAddress = NULL;
		mh->SentDate = NULL;
		mh->MsgId = NULL;
		mh->Reference = NULL;
		mh->Xface = NULL;
		mh->HomePage = NULL;
		mh->ssort = NULL;
		mh->isort = 0;
		mh->Printed = FALSE;
		
		/* connection to other headers */
                mh->Prev = last_mh;
                if (last_mh != NULL) last_mh->Next = mh; 

		/* save filename */
		mh->FileName = dupchar(DirEntry->d_name);

		last_mh = mh;
	        while(fgets(line,BUFSIZ,fd) != NULL) {
		    if (config.DebugLevel & 8)
			printf("....read line \"%s\"\n",line);
		    if (strncmp(line,"<HEAD>",6) == 0) break;
		    VarName = ReadHtmlVarname(line);
		    if (strlen(VarName) > 0) {
			VarValue = ReadHtmlValue(line);
		    } else {
			VarValue = dupchar("\0");
		    }
		    if ((strcmp(VarName,"EmailData") == 0) &&
		        (strcmp(VarValue,"End") == 0)) {
			/* End mark for HTML Version 1.1 */
			freechar(VarName);
			freechar(VarValue);
			break;
		    }
		    if (config.DebugLevel & 2)
			printf("..readhtmlvar %s=\"%s\"\n",VarName,VarValue);
		    if (strncmp(VarName,"Version",7) == 0) {
		        HtmlVersion = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"Subject",7) == 0) {
		        mh->Subject = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"FromName",8) == 0) {
		        mh->SendName = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"FromEmail",9) == 0) {
		        mh->SendAddress = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"ToName",6) == 0) {
		        mh->ReceiveName = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"ToEmail",7) == 0) {
		        mh->ReceiveAddress = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"Date",4) == 0) {
		        mh->SentDate = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"Id",2) == 0) {
		        mh->MsgId = VarValue;
		        VarValue = NULL;
		    }
		    if (strncmp(VarName,"Reference",9) == 0) {
		        mh->Reference = VarValue;
		        VarValue = NULL;
		    }
 		    if (strncmp(VarName,"X-Face",6) == 0) {
 		        mh->Xface = VarValue;
		        VarValue = NULL;
		    }
 		    if (strncmp(VarName,"X-URL",5) == 0) {
 		        mh->HomePage = VarValue;
		        VarValue = NULL;
		    }
		    freechar(VarName);
		    VarName = NULL;
		    if (VarValue != NULL) {
			freechar(VarValue);
			VarValue = NULL;
		    }
	        }
	        if (mh->Subject == NULL) {
	            mh->Subject = dupchar("\0");
	        }
	        if (mh->SendName == NULL) {
	            mh->SendName = dupchar("\0");
	        }
	        if (mh->SendAddress == NULL) {
	            mh->SendAddress = dupchar("\0");
	        }
	        if (mh->ReceiveName == NULL) {
	            mh->ReceiveName = dupchar("\0");
	        }
	        if (mh->ReceiveAddress == NULL) {
	            mh->ReceiveAddress = dupchar("\0");
	        }
	        if (mh->SentDate == NULL) {
	            mh->SentDate = dupchar("\0");
	        }
	        if (mh->MsgId == NULL) {
	            mh->MsgId = dupchar("\0");
	        }
	        if (mh->Reference == NULL) {
	            mh->Reference = dupchar("\0");
	        }
	        if (mh->Xface == NULL) {
	            mh->Xface = dupchar("\0");
	        }
	        if (mh->HomePage == NULL) {
	            mh->HomePage = dupchar("\0");
	        }
	        if (mh->ssort == NULL) {
	            mh->ssort = dupchar("\0");
	        }
	        if (strlen(mh->Subject) == 0) {
	            freechar(mh->Subject);
	            mh->Subject = dupchar(WMF_NOSUBJECT);
	        }
	        fclose(fd);
                if (HtmlVersion != NULL) {
                    freechar(HtmlVersion);
                    HtmlVersion = NULL;
                }	
		if (return_mh == NULL) return_mh = mh;
	        if ((mh != NULL) && (config.ListLimit > 0)) {
		    tmptime = getutc(mh->SentDate);
		    if (tmptime < config.ListLimit) {
			last_mh = mh->Prev;
			if (last_mh != NULL) last_mh->Next = NULL;
		        if (return_mh == mh) {
			    return_mh = NULL;
			}
		        DelHeader(mh);
			mh = NULL;
		    }
	        }
	    }
	    freechar(FileName);
	    FileName = NULL;
        }
        DirEntry = readdir(dd);
    }
    if ((mh != NULL) && (config.ListLimit > 0)) {
	tmptime = getutc(mh->SentDate);
	if (tmptime < config.ListLimit) {
	    if (return_mh == mh) return_mh = NULL;
	    last_mh = mh->Prev;
	    DelHeader(mh);
	    if (return_mh == mh) {
		return_mh = NULL;
		last_mh = NULL;
		mh = NULL;
	    }
	}
    }
    closedir(dd);
    return return_mh;
}


struct MAILHEAD *TopOfList(struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;

    if (config.DebugLevel & 4) printf("...TopOfList\n");
    if (mh == NULL) return mh;
    tmp_mh = mh;
    while (tmp_mh->Prev != NULL) {
        tmp_mh = tmp_mh->Prev;
    }
    return tmp_mh;
}


struct MAILHEAD *BottomOfList(struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;

    if (config.DebugLevel & 4) printf("...BottomOfList\n");
    if (mh == NULL) return mh;
    tmp_mh = mh;
    while (tmp_mh->Next != NULL) {
        tmp_mh = tmp_mh->Next;
    }
    return tmp_mh;
}


int MessageCount(struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;
    int tmp_count;

    if (config.DebugLevel & 1) printf(".MessageCount\n");
    tmp_count = 0;
    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
        tmp_mh = tmp_mh->Next;
        tmp_count++;
    }
    return tmp_count;
}


void Exchange(struct MAILHEAD *mh1, struct MAILHEAD *mh2) {

    if (config.DebugLevel & 4) printf("...Exchange\n");

    /* Setting new place in the list */
    if (mh1->Prev != NULL) mh1->Prev->Next = mh2;
    if (mh2->Next != NULL) mh2->Next->Prev = mh1;
    
    /* Exchange previous pointer */
    mh2->Prev = mh1->Prev;
    mh1->Prev = mh2;

    /* Exchange next pointer */
    mh1->Next = mh2->Next;
    mh2->Next = mh1;
}


void int_sort(struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;
    int entry_count,m,n;

    if (config.DebugLevel & 1) printf(".int_sort\n");
    if (mh == NULL) return;
    tmp_mh = TopOfList(mh);
    entry_count = 0;
    /* count entries */
    while (tmp_mh!= NULL) {
	entry_count++;
	tmp_mh = tmp_mh->Next;
    }
    if (config.DebugLevel & 2) printf("..entries = %d\n",entry_count);
    /* sorting */
    for (m=1;m<entry_count;m++) {
	tmp_mh = TopOfList(mh);
	for (n=1;n<=(entry_count-m);n++) {
	    if (config.SortOrder == SORT_REVERSE) {
		if (tmp_mh->isort < tmp_mh->Next->isort) {
		    Exchange(tmp_mh,tmp_mh->Next);
		} else {
		    tmp_mh = tmp_mh->Next;
		}
	    } else {
		if (tmp_mh->isort > tmp_mh->Next->isort) {
		    Exchange(tmp_mh,tmp_mh->Next);
		} else {
		    tmp_mh = tmp_mh->Next;
		}
	    }
	}
    }
}


void strint_sort(struct MAILHEAD *mh) {
    struct MAILHEAD *tmp_mh;
    int entry_count,m,n;

    if (config.DebugLevel & 1) printf(".strint_sort\n");
    if (mh == NULL) return;
    tmp_mh = TopOfList(mh);
    entry_count = 0;
    /* count entries */
    while (tmp_mh!= NULL) {
	entry_count++;
	tmp_mh = tmp_mh->Next;
    }
    if (config.DebugLevel & 2) printf("..entries = %d\n",entry_count);
    /* sorting */
    for (m=1;m<entry_count;m++) {
	tmp_mh = TopOfList(mh);
	for (n=1;n<=(entry_count-m);n++) {
	    if (strcmp(tmp_mh->ssort,tmp_mh->Next->ssort) > 0) {
		Exchange(tmp_mh,tmp_mh->Next);
	    } else {
		if (strcmp(tmp_mh->ssort,tmp_mh->Next->ssort) < 0) {
		    tmp_mh = tmp_mh->Next;
		} else {
		    if (strcmp(tmp_mh->ssort,tmp_mh->Next->ssort) == 0) {
			if (config.SortOrder == SORT_REVERSE) {
			    if (tmp_mh->isort < tmp_mh->Next->isort) {
				Exchange(tmp_mh,tmp_mh->Next);
			    } else {
				tmp_mh = tmp_mh->Next;
			    }
			} else {
			    if (tmp_mh->isort > tmp_mh->Next->isort) {
				Exchange(tmp_mh,tmp_mh->Next);
			    } else {
				tmp_mh = tmp_mh->Next;
			    }
			}
		    }
		}
	    }
	}
    }
    if (config.DebugLevel & 2) printf("..strint_sort_Return\n");
}

char *GetMainSubject(char *Subject) {

    int loop, i, length;
    char *tmpstr, *retstr;

    if (config.DebugLevel & 1) printf(".GetMainSubject(%s)\n",Subject);
    tmpstr = Subject;
    loop = TRUE;
    while(loop) {
	loop = FALSE;
	for(i=0;reply_prefix[i] != NULL;i++) {
	    if (strncmp(reply_prefix[i],tmpstr,strlen(reply_prefix[i])) == 0) {
		tmpstr = tmpstr + strlen(reply_prefix[i]);
		while(tmpstr[0] == ' ') tmpstr++;
		loop = TRUE;
		break; /* stop the for */
	    }
	}
    }
    length = strlen(tmpstr);
    while(tmpstr[length-1] == ' ') length--;
    if (length > 0) {
	retstr = newchar(length+1);
	strncpy(retstr,tmpstr,length);
	retstr[length] = '\0';
    } else {
	retstr = dupchar(WMF_NOSUBJECT);
    }
    if (config.DebugLevel & 2) printf("..GetMainSubject_return(%s)\n",retstr);
    return retstr;
}


void WriteListHead (char *Title, char *FileName, int PageNr, int MsgCount) {
    time_t BuildTime;
    char *tmpstr;

    if (config.DebugLevel & 1) printf(".WriteListHead\n");

    InitHtml(FileName);
    if (config.DocStartFile != NULL) {
	IncludeFile(FileName,config.DocStartFile);
    } else {
	AppendFile(FileName,"<HEAD>\n");
	AppendFile(FileName,Title);
	AppendFile(FileName,"</HEAD>\n");
	if (HtmlCmd.BodyStart == NULL)
	    AppendFile(FileName,HTMLCMD_BODY_START);
	else
	    AppendFile(FileName,HtmlCmd.BodyStart);
	AppendFile(FileName,"\n");

	if (config.FrameSupport == FALSE) {
	    WriteIndexNavigation(FileName);
	    if (HtmlCmd.HrStart == NULL)
		AppendFile(FileName,HTMLCMD_HR_START);
	    else
		AppendFile(FileName,HtmlCmd.HrStart);
	    AppendFile(FileName,"\n");
	}
    }

    if (PageNr > 0) {
        tmpstr = newchar(255);
        sprintf(tmpstr,"<H3 ALIGN=RIGHT>Page:%d</H3>\n",PageNr);
        AppendFile(FileName,tmpstr);
        freechar(tmpstr);
        tmpstr = NULL;
    }
    if (config.FrameSupport == FALSE) {
	if (config.ListStart > 0) {
	    AppendFile(FileName,"<H2 ALIGN=LEFT>Date</H2>\n");
	    tmpstr = newchar(71); /* 50 for date */
	    if (config.SortOrder == SORT_REVERSE) {
		strftime(tmpstr,67,"First message: %a, %d. %b %Y %H:%M:%S<BR>\n",
		  localtime(&config.ListEnd));
	    } else {
		strftime(tmpstr,67,"First message: %a, %d. %b %Y %H:%M:%S<BR>\n",
		  localtime(&config.ListStart));
	    }
	    AppendFile(FileName,tmpstr);
	    freechar(tmpstr);
	    tmpstr = NULL;
	}
	if (config.ListEnd > 0) {
	    tmpstr = newchar(70); /* 50 for date */
	    if (config.SortOrder == SORT_REVERSE) {
		strftime(tmpstr,67,"Last message: %a, %d. %b %Y %H:%M:%S<BR>\n",
		  localtime(&config.ListStart));
	    } else {
		strftime(tmpstr,67,"Last message: %a, %d. %b %Y %H:%M:%S<BR>\n",
		  localtime(&config.ListEnd));
	    }
	    AppendFile(FileName,tmpstr);
	    freechar(tmpstr);
	    tmpstr = NULL;
	}
	if (config.ListLimit > 0) {
	    tmpstr = newchar(70); /* 50 for date */
	    strftime(tmpstr,66,"List limit: %a, %d. %b %Y %H:%M:%S<BR>\n",
	      localtime(&config.ListLimit));
	    AppendFile(FileName,tmpstr);
	    freechar(tmpstr);
	    tmpstr = NULL;
	}
	tmpstr = newchar(70); /* 50 for date */
	BuildTime = time(NULL);
	strftime(tmpstr,67,"Index build: %a, %d. %b %Y %H:%M:%S<BR>\n",
          localtime(&BuildTime));
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	tmpstr = NULL;
	if (MsgCount != WMF_NOVALUE) {
	    tmpstr = newchar(36); /* 20 for number */
	    sprintf(tmpstr,"Messages: %d<BR>\n",MsgCount);
	    AppendFile(FileName,tmpstr);
	    freechar(tmpstr);
	    tmpstr = NULL;
	}

	AppendFile(FileName,"<H2 ALIGN=LEFT>Index</H2>\n");
    }
}


void WriteListEnd (char *FileName, int PageNr, struct MAILHEAD *mh,
    char *ListType) {
    char *tmpstr;
    
    if (config.DebugLevel & 1) printf(".WriteListEnd\n");
    if (HtmlCmd.HrStart == NULL)
	AppendFile(FileName,HTMLCMD_HR_START);
    else
	AppendFile(FileName,HtmlCmd.HrStart);
    AppendFile(FileName,"\n");
    if (config.FrameSupport == FALSE) {
	WriteIndexNavigation(FileName);
    }
    if ((PageNr > 1) || ((PageNr == 1) && (mh != NULL)))
	AppendFile(FileName,"<B>Page:</B>\n");
    if (PageNr > 1) {
        if (PageNr == 2) {
	    if (config.FrameSupport == TRUE) {
		tmpstr = newchar(strlen(ListType)+strlen(config.Extension)+
		  strlen(config.FrameNameIndex)+37);
		sprintf(tmpstr,"[<A HREF=\"%s%s\" TARGET=\"%s\">previous</A>]\n",
	          ListType,config.Extension,config.FrameNameIndex);
	    } else {
		tmpstr = newchar(strlen(ListType)+strlen(config.Extension)+27);
		sprintf(tmpstr,"[<A HREF=\"%s%s\">previous</A>]\n",
	          ListType,config.Extension);
	    }
        } else {
	    if (config.FrameSupport == TRUE) {
		tmpstr = newchar(strlen(ListType)+
		  strlen(config.FrameNameIndex)+strlen(config.Extension)+38);
		sprintf(tmpstr,"[<A HREF=\"%s_%d%s\" TARGET=\"%s\">previous</A>]\n",
	          ListType,(PageNr-1),config.Extension,config.FrameNameIndex);
	    } else {
		tmpstr = newchar(strlen(ListType)+strlen(config.Extension)+28);
		sprintf(tmpstr,"[<A HREF=\"%s_%d%s\">previous</A>]\n",
	          ListType,(PageNr-1),config.Extension);
	    }
        }
        AppendFile(FileName,tmpstr);
        freechar(tmpstr);
        tmpstr = NULL;
    }
    if ((PageNr > 0) && (mh != NULL)) {
	if (config.FrameSupport == TRUE) {
	    tmpstr = newchar(strlen(ListType)+strlen(config.FrameNameIndex)+
	      strlen(config.Extension)+45);
	    sprintf(tmpstr,"[<A HREF=\"%s_%d%s\" TARGET=\"%s\">next</A>]\n",
	      ListType,(PageNr+1),config.Extension,config.FrameNameIndex);
	} else {
	    tmpstr = newchar(strlen(ListType)+strlen(config.Extension)+35);
	    sprintf(tmpstr,"[<A HREF=\"%s_%d%s\">next</A>]\n",
	      ListType,(PageNr+1),config.Extension);
	}
        AppendFile(FileName,tmpstr);
        freechar(tmpstr);
        tmpstr = NULL;
    }
    AppendFile(FileName,"<P>\n");
    if (config.FrameSupport == TRUE) {
	tmpstr = newchar(strlen(HREF)+strlen(NAME)+strlen(VERSION)+38);
	sprintf(tmpstr,"<A HREF=\"%s\" TARGET=_top>%s</A> version %s\n",HREF,NAME,VERSION);
    } else {
	tmpstr = newchar(strlen(HREF)+strlen(NAME)+strlen(VERSION)+26);
	sprintf(tmpstr,"<A HREF=\"%s\">%s</A> version %s\n",HREF,NAME,VERSION);
    }
    AppendFile(FileName,tmpstr);
    freechar(tmpstr);
    tmpstr = NULL;
    if (config.DocEndFile != NULL) {
	IncludeFile(FileName,config.DocEndFile);
    } else {
	if (HtmlCmd.BodyEnd == NULL)
	    AppendFile(FileName,HTMLCMD_BODY_END);
	else
	    AppendFile(FileName,HtmlCmd.BodyEnd);
	AppendFile(FileName,"\n");
    }
    EndHtml(FileName);
}


struct MAILHEAD *FindId(struct MAILHEAD *mh, char *Id) {
    struct MAILHEAD *tmp_mh;
    
    if (config.DebugLevel & 1) printf(".FindId(%s)\n",Id);
    tmp_mh = mh;
    while(tmp_mh != NULL) {
	if (strcmp(tmp_mh->MsgId,Id) == 0) break;
	tmp_mh = tmp_mh->Next;
    }
    return tmp_mh;
}


struct MAILHEAD *FindMainSubject(struct MAILHEAD *mh, char *Subject, char *RefID) {

    struct MAILHEAD *tmp_mh, *tmpLastMh, *tmpNextMh;
    char *tmpRefId, *tmpSubject, *tmpstr;

    if (config.DebugLevel & 1) printf(".FindMainSubject(%s,%s)\n",Subject,RefID);
    if (config.ThreadNewSubject != TRUE) {
        /* Thread all */
	tmp_mh = mh;
	tmpRefId = RefID;
	tmpLastMh = NULL;
	tmpSubject = Subject;

	/* Walk back until no more Reference */
	if (config.DebugLevel & 2) printf("..Walk back (Reference)\n");
	while ((tmp_mh != NULL) && (strlen(tmpRefId) > 0)) {
	    tmp_mh = FindId(mh,tmpRefId);
	    if (tmp_mh != NULL) {
		tmpLastMh = tmp_mh;
		tmpRefId = tmp_mh->Reference;
		tmpSubject = tmp_mh->Subject;
	    }
	}

	/* Already the top one ? */
	if (tmpLastMh != NULL) {
	    tmpstr = GetMainSubject(tmpLastMh->Subject);
	    if (config.DebugLevel & 2) {
		printf("..TopOneRef ('%s','%s','%s')\n",
		  tmpLastMh->Subject,tmpstr,tmpLastMh->Reference);
	    }
	    if ((strcmp(tmpLastMh->Subject,tmpstr) == 0) &&
	      (strlen(tmpLastMh->Reference) == 0)) {
		freechar(tmpstr);
		tmpstr = NULL;
		return tmpLastMh;
	    }
	    freechar(tmpstr);
	    tmpstr = NULL;
	}

	tmp_mh = mh;
	if (config.DebugLevel & 2) printf("..Walk back (Subject)\n");

	while (tmp_mh != NULL) {
	    if (strcmp(tmp_mh->Subject,tmpSubject) == 0) {
		if(strlen(tmp_mh->Reference) == 0) {
		    break;
		} else {
		    tmpNextMh = FindId(mh,tmp_mh->Reference);
		    if (tmpNextMh != NULL)
			if(strcmp(tmpNextMh->ssort,tmp_mh->ssort) != 0) break;
		}
	    }
	    tmp_mh = tmp_mh->Next;
	}

	if (tmp_mh != NULL) {
	    tmpstr = GetMainSubject(tmp_mh->Subject);
	    if (config.DebugLevel & 2) printf("..TopOneSub ('%s','%s','%s')\n",
		tmp_mh->Subject,tmpstr,tmp_mh->Reference);
	    if (strlen(tmp_mh->Reference) != 0)
		tmp_mh = FindMainSubject(mh,tmpstr,tmp_mh->Reference);
	    freechar(tmpstr);
	    tmpstr = NULL;
	    return tmp_mh;
	} else {
	    return tmpLastMh;
	}
    } else {
        /* Thread until main subject */
	tmp_mh = mh;
	if (config.DebugLevel & 2) printf("..Walk back (Subject)\n");

	while (tmp_mh != NULL) {
	    if (strcmp(tmp_mh->Subject,Subject) == 0) {
		break;
	    }
	    tmp_mh = tmp_mh->Next;
	}
	return tmp_mh;
    }
}


int WriteThreadLineEx(struct MAILHEAD *mh, int page, int page_counter, int level) {
    struct MAILHEAD *tmp_mh;
    char *tmpstr, *tmpName, *FileName, *tmpTitle, *ls_subject;
    int tmpCount, li_firstflag;
     
    if (config.DebugLevel & 1) printf(".WriteThreadLine\n");

    li_firstflag = TRUE;
    tmpCount = page_counter;
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+26);
        sprintf(tmpTitle,"<TITLE>%s threaded</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Threaded</TITLE>\n");
    }

    if (page > 1) {
	FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+19);
	sprintf(FileName,"%s/thread_%d%s",config.Directory,page,config.Extension);
    } else {
	FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+8);
	sprintf(FileName,"%s/thread%s",config.Directory,config.Extension);
    }

    tmpName = Email2Html(mh);
    ls_subject = Text_2_Html(mh->Subject);
    if (config.FrameSupport == TRUE) {
	tmpstr = newchar(strlen(mh->FileName)+strlen(ls_subject)+
	  strlen(config.FrameNameMail)+strlen(tmpName)+42);
	sprintf(tmpstr,"<LI> <A HREF=\"%s\" TARGET=\"%s\">%s</A> <I>(%s)</I>\n",
	  mh->FileName,config.FrameNameMail,ls_subject,tmpName);
    } else {
	tmpstr = newchar(strlen(mh->FileName)+strlen(ls_subject)+
	  strlen(tmpName)+32);
	sprintf(tmpstr,"<LI> <A HREF=\"%s\">%s</A> <I>(%s)</I>\n",mh->FileName,
	  ls_subject,tmpName);
    }
    freechar(ls_subject);
    ls_subject = NULL;
    AppendFile(FileName,tmpstr);
    freechar(tmpName);
    tmpName = NULL;
    freechar(tmpstr);
    tmpstr = NULL;
    mh->Printed = TRUE;
    tmpCount++;
    
    /* Looking for childs (Ref)*/
    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
	if ((strlen(mh->MsgId) > 0) &&
	    (strcmp(mh->MsgId,tmp_mh->Reference)==0)) {
	    if (tmp_mh->Printed == FALSE) {
		if (li_firstflag == TRUE) {
		    li_firstflag = FALSE;
		    if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
			AppendFile(FileName,"<UL>\n");
		}
		tmpCount = WriteThreadLineEx(tmp_mh,page,tmpCount,level+1);
	    }
	}
	tmp_mh = tmp_mh->Next;
    }

    /* Looking for childs (Sub)*/
    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
	if ((strlen(mh->MsgId) > 0) &&
	    (strcmp(mh->ssort,tmp_mh->ssort)==0) &&
	    (strlen(tmp_mh->Reference) == 0)) {
	    if (tmp_mh->Printed == FALSE) {
		if (li_firstflag == TRUE) {
		    li_firstflag = FALSE;
		    if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
			AppendFile(FileName,"<UL>\n");
		}
		tmpCount = WriteThreadLine(tmp_mh,page,tmpCount,level+1);
	    }
	}
	tmp_mh = tmp_mh->Next;
    }

    if (li_firstflag == FALSE) {
	if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
	    AppendFile(FileName,"</UL>\n");
    }

    /* Do a little cleanup */
    freechar(FileName);
    FileName = NULL;
    freechar(tmpTitle);
    tmpTitle = NULL;

    return tmpCount;
}


int WriteThreadLine(struct MAILHEAD *mh, int page, int page_counter, int level) {
    struct MAILHEAD *tmp_mh;
    char *tmpstr, *tmpName, *FileName, *tmpTitle, *ls_subject;
    int tmpCount, li_firstflag;
     
    if (config.DebugLevel & 1) printf(".WriteThreadLine\n");

    li_firstflag = TRUE;
    tmpCount = page_counter;
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+26);
        sprintf(tmpTitle,"<TITLE>%s threaded</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Threaded</TITLE>\n");
    }

    if (page > 1) {
	FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+19);
	sprintf(FileName,"%s/thread_%d%s",config.Directory,page,config.Extension);
    } else {
	FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+8);
	sprintf(FileName,"%s/thread%s",config.Directory,config.Extension);
    }

    tmpName = Email2Html(mh);
    ls_subject = Text_2_Html(mh->Subject);
    if (config.FrameSupport == TRUE) {
	tmpstr = newchar(strlen(mh->FileName)+strlen(ls_subject)+
	  strlen(config.FrameNameMail)+strlen(tmpName)+42);
	sprintf(tmpstr,"<LI> <A HREF=\"%s\" TARGET=\"%s\">%s</A> <I>(%s)</I>\n",
	  mh->FileName,config.FrameNameMail,ls_subject,tmpName);
    } else {
	tmpstr = newchar(strlen(mh->FileName)+strlen(ls_subject)+
	  strlen(tmpName)+32);
	sprintf(tmpstr,"<LI> <A HREF=\"%s\">%s</A> <I>(%s)</I>\n",mh->FileName,
	  ls_subject,tmpName);
    }
    freechar(ls_subject);
    ls_subject = NULL;
    AppendFile(FileName,tmpstr);
    freechar(tmpName);
    tmpName = NULL;
    freechar(tmpstr);
    tmpstr = NULL;
    mh->Printed = TRUE;
    tmpCount++;
    
    /* Looking for childs (Ref)*/
    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
	if (config.ThreadNewSubject == TRUE) {
    	    if ((strlen(mh->MsgId) > 0) &&
		(strcmp(mh->MsgId,tmp_mh->Reference)==0) &&
		(strcmp(mh->ssort,tmp_mh->ssort)==0)) {
		if (tmp_mh->Printed == FALSE) {
		    if (li_firstflag == TRUE) {
			li_firstflag = FALSE;
			if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
			    AppendFile(FileName,"<UL>\n");
		    }
	            tmpCount = WriteThreadLine(tmp_mh,page,tmpCount,level+1);
		}
	    }
	} else {
    	    if ((strlen(mh->MsgId) > 0) &&
		(strcmp(mh->MsgId,tmp_mh->Reference)==0)) {
		if (tmp_mh->Printed == FALSE) {
		    if (li_firstflag == TRUE) {
			li_firstflag = FALSE;
			if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
			    AppendFile(FileName,"<UL>\n");
		    }
		    if(strcmp(mh->ssort,tmp_mh->ssort) != 0) {
			tmpCount = WriteThreadLineEx(tmp_mh,page,tmpCount,level+1);
		    } else {
			tmpCount = WriteThreadLine(tmp_mh,page,tmpCount,level+1);
		    }
		}
	    }
	}
	tmp_mh = tmp_mh->Next;
    }
    if (li_firstflag == FALSE) {
	if ((config.ThreadLevelLimit == 0) || (level < config.ThreadLevelLimit))
	    AppendFile(FileName,"</UL>\n");
    }

    /* Do a little cleanup */
    freechar(FileName);
    FileName = NULL;
    freechar(tmpTitle);
    tmpTitle = NULL;

    return tmpCount;
}


void WriteThread (struct MAILHEAD *mh, int MsgCount) {
    struct MAILHEAD *tmp_mh, *scan_mh, *parent_mh;
    char *FileName, *tmpstr, *tmpName, *tmpTitle, *ls_subject, *ls_subject2;
    int page, page_counter, li_firstflag, i;
               
    if (config.DebugLevel & 1) printf(".WriteThread\n");
    tmp_mh = TopOfList(mh);
    
    page_counter = 0;
    stats.Thread = 0;

    /* Fill sort-field */
    while (tmp_mh != NULL) {
	tmp_mh->isort = getutc(tmp_mh->SentDate);
	if (tmp_mh->ssort != NULL) freechar(tmp_mh->ssort);
	tmp_mh->ssort = GetMainSubject(tmp_mh->Subject);
	if (config.ThreadCaseSort == FALSE) {
	    /* Convert to uppercase */
	    for (i=0;i<strlen(tmp_mh->ssort);i++)
		tmp_mh->ssort[i] = toupper(tmp_mh->ssort[i]);
	}
	tmp_mh = tmp_mh->Next;
    }

    int_sort(TopOfList(mh));

    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+8);
    sprintf(FileName,"%s/thread%s",config.Directory,config.Extension);
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+26);
        sprintf(tmpTitle,"<TITLE>%s threaded</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Threaded</TITLE>\n");
    }
    
    if (config.PageSize > 0) {
        page = 1;
	page_counter = 1;
    } else {
        page = 0;
    }

    WriteListHead(tmpTitle,FileName,page,MsgCount);
    AppendFile(FileName,"<UL>\n");

    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
        if (tmp_mh->Printed == FALSE) {
            tmpstr = GetMainSubject(tmp_mh->Subject);
            parent_mh = FindMainSubject(TopOfList(mh),tmpstr,tmp_mh->Reference);
            freechar(tmpstr);
            tmpstr = NULL;
	    if (config.PageSize > 0) {
	        if ((page_counter >= config.PageSize) && (tmp_mh != NULL)) {
		    AppendFile(FileName,"</UL>\n");
	 	    WriteListEnd(FileName,page,tmp_mh,"thread");
		    page_counter = 0;
		    page++;
		    freechar(FileName);
		    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+19);
		    sprintf(FileName,"%s/thread_%d%s",config.Directory,page,config.Extension);
		    WriteListHead(tmpTitle,FileName,page,MsgCount);
		    AppendFile(FileName,"<UL>\n");
	        }
	        page_counter++;
	    }
            if (parent_mh == NULL) {
		ls_subject = GetMainSubject(tmp_mh->Subject);
		tmpstr = newchar(strlen(ls_subject)+7);
		sprintf(tmpstr,"<LI> %s\n",ls_subject);
		freechar(ls_subject);
		ls_subject = NULL;
		AppendFile(FileName,tmpstr);
		freechar(tmpstr);
		tmpstr = NULL;
	        AppendFile(FileName,"<UL>\n");
	        stats.Thread++;

		if (strcmp(tmp_mh->ssort,WMF_NOSUBJECT) != 0) {
		    /* print all threaded with subject and no RefId */
		    scan_mh = tmp_mh;
		    while (scan_mh != NULL) {
			if ((strcmp(scan_mh->ssort,tmp_mh->ssort) == 0) &&
			  (strlen(scan_mh->Reference) == 0))
			    if (scan_mh->Printed == FALSE)
				page_counter = WriteThreadLine(scan_mh,page,page_counter,1);
			scan_mh = scan_mh->Next;
		    }

		    /* print all threaded with subject and unknown RefId */
		    scan_mh = tmp_mh;
		    while (scan_mh != NULL) {
			if ((strcmp(scan_mh->ssort,tmp_mh->ssort) == 0) &&
			  (FindId(tmp_mh,scan_mh->Reference) == NULL))
			    if (scan_mh->Printed == FALSE)
				page_counter = WriteThreadLine(scan_mh,page,page_counter,1);
			scan_mh = scan_mh->Next;
		    }
 		} else {
		    tmpName = Email2Html(tmp_mh);
		    ls_subject2 = Text_2_Html(tmp_mh->Subject);
	            if (config.FrameSupport == TRUE) {
			tmpstr = newchar(strlen(tmp_mh->FileName)+
			  strlen(ls_subject2)+strlen(tmpName)+
			  strlen(config.FrameNameMail)+35);
			sprintf(tmpstr,"<LI> <A HREF=\"%s\" TARGET=\"%s\">%s</A> (%s)\n",
			  tmp_mh->FileName,config.FrameNameMail,
			  ls_subject2,tmpName);
		    } else {
			tmpstr = newchar(strlen(tmp_mh->FileName)+
			  strlen(ls_subject2)+strlen(tmpName)+25);
			sprintf(tmpstr,"<LI> <A HREF=\"%s\">%s</A> (%s)\n",
			  tmp_mh->FileName,ls_subject2,tmpName);
		    }
		    AppendFile(FileName,tmpstr);
		    freechar(ls_subject2);
		    ls_subject2 = NULL;
		    freechar(tmpstr);
		    tmpstr = NULL;
		    freechar(tmpName);
		    tmpName = NULL;
		    tmp_mh->Printed = TRUE;
 		}
 		AppendFile(FileName,"</UL>\n");
            } else {
		li_firstflag = TRUE;
		tmpName = Email2Html(parent_mh);
		ls_subject = Text_2_Html(parent_mh->Subject);
	        if (config.FrameSupport == TRUE) {
		    tmpstr = newchar(strlen(parent_mh->FileName)+
		      strlen(ls_subject)+strlen(tmpName)+
		      strlen(config.FrameNameMail)+35);
		    sprintf(tmpstr,"<LI> <A HREF=\"%s\" TARGET=\"%s\">%s</A> (%s)\n",
		      parent_mh->FileName,config.FrameNameMail,ls_subject,tmpName);
		} else {
		    tmpstr = newchar(strlen(parent_mh->FileName)+
		      strlen(ls_subject)+strlen(tmpName)+25);
		    sprintf(tmpstr,"<LI> <A HREF=\"%s\">%s</A> (%s)\n",
		      parent_mh->FileName,ls_subject,tmpName);
		}
		AppendFile(FileName,tmpstr);
		freechar(ls_subject);
		ls_subject = NULL;
		freechar(tmpstr);
		tmpstr = NULL;
		freechar(tmpName);
		tmpName = NULL;
		parent_mh->Printed = TRUE;
	        stats.Thread++;

		if (strlen(parent_mh->MsgId) > 0) {
		    /* print all threaded with ref */
		    if (config.DebugLevel & 2)
			printf("..Scanning for MsgId=\"%s\"\n",parent_mh->MsgId);

		    scan_mh = tmp_mh;
		    while (scan_mh != NULL) {
			if (strcmp(scan_mh->Reference,parent_mh->MsgId) == 0)
		            if (scan_mh->Printed == FALSE) {
				if (config.DebugLevel & 2)
				    printf("..Found RefId in MsgId=\"%s\"\n",scan_mh->MsgId);
				if (li_firstflag == TRUE) {
				    li_firstflag = FALSE;
				    AppendFile(FileName,"<UL>\n");
				}
				page_counter = WriteThreadLine(scan_mh,page,page_counter,1);
			    }
			scan_mh = scan_mh->Next;
		    }
		}

		if (strcmp(tmp_mh->ssort,WMF_NOSUBJECT) != 0) {
		    /* print all threaded with subject and no RefId */
		    if (config.DebugLevel & 2)
			printf("..Scanning for Subject=\"%s\"\n",parent_mh->ssort);
		    scan_mh = tmp_mh;
		    while (scan_mh != NULL) {
			if ((strcmp(scan_mh->ssort,parent_mh->ssort) == 0) &&
			  (strlen(scan_mh->Reference) == 0))
		    	    if (scan_mh->Printed == FALSE) {
				if (config.DebugLevel & 2)
				    printf("..Found Subject in MsgId=\"%s\"\n",scan_mh->MsgId);
				if (li_firstflag == TRUE) {
				    li_firstflag = FALSE;
				    AppendFile(FileName,"<UL>\n");
				}
				page_counter = WriteThreadLine(scan_mh,page,page_counter,1);
			    }
			scan_mh = scan_mh->Next;
		    }

		    /* print all threaded with subject and unknown RefId */
		    scan_mh = tmp_mh;
		    while (scan_mh != NULL) {
			if ((strcmp(scan_mh->ssort,parent_mh->ssort) == 0) &&
			  (FindId(tmp_mh,scan_mh->Reference) == NULL))
			    if (scan_mh->Printed == FALSE) {
				if (li_firstflag == TRUE) {
				    li_firstflag = FALSE;
				    AppendFile(FileName,"<UL>\n");
				}
				page_counter = WriteThreadLine(scan_mh,page,page_counter,1);
			    }
			scan_mh = scan_mh->Next;
		    }
		}
		if (li_firstflag == FALSE)
                    AppendFile(FileName,"</UL>\n");
            }
        } /* end of if */
	tmp_mh = tmp_mh->Next;
    } /* end of while */
    AppendFile(FileName,"</UL>\n");
    WriteListEnd(FileName,page,tmp_mh,"thread");

    /* Do a little cleanup */
    freechar(FileName);
    FileName = NULL;
    freechar(tmpTitle);
    tmpTitle = NULL;
}



void WriteSubject (struct MAILHEAD *mh, int MsgCount) {
    struct MAILHEAD *tmp_mh;
    char *FileName, *tmpstr, *tmpSubject, *tmpTitle, *tmpEmail, *ls_subject;
    int page, page_counter, i;
           
    if (config.DebugLevel & 1) printf(".WriteSubject\n");

    page_counter = 0;
    tmpSubject = NULL;
    tmp_mh = TopOfList(mh);
    stats.Subject = 0;

    /* Fill sort-field */
    while (tmp_mh != NULL) {
	if (tmp_mh->ssort != NULL) freechar(tmp_mh->ssort);
	tmp_mh->isort = getutc(tmp_mh->SentDate);
	tmp_mh->ssort = GetMainSubject(tmp_mh->Subject);
	if (config.SubjectCaseSort == FALSE) {
	    /* Convert to uppercase */
	    for (i=0;i<strlen(tmp_mh->ssort);i++)
		tmp_mh->ssort[i] = toupper(tmp_mh->ssort[i]);
	}
	tmp_mh = tmp_mh->Next;
    }

    strint_sort(TopOfList(mh));

    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+9);
    sprintf(FileName,"%s/subject%s",config.Directory,config.Extension);
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+35);
        sprintf(tmpTitle,"<TITLE>%s sorted by subject</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Sorted by subject</TITLE>\n");
    }
    
    if (config.PageSize > 0) {
        page = 1;
	page_counter = 1;
    } else {
        page = 0;
    }

    WriteListHead(tmpTitle,FileName,page,MsgCount);

    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
	if (tmpSubject == NULL) {
	    tmpstr = GetMainSubject(tmp_mh->Subject);
	    ls_subject = Text_2_Html(tmpstr);
	    freechar(tmpstr);
	    tmpstr = newchar(strlen(ls_subject)+11);
	    sprintf(tmpstr,"<H3>%s</H3>\n",ls_subject);
            AppendFile(FileName,tmpstr);
            freechar(ls_subject);
            ls_subject = NULL;
	    freechar(tmpstr);
	    tmpstr = NULL;
            tmpSubject = dupchar(tmp_mh->ssort);
            stats.Subject = 1;
	} else {
	    if (strcmp(tmp_mh->ssort,tmpSubject) != 0) {
		tmpstr = GetMainSubject(tmp_mh->Subject);
		ls_subject = Text_2_Html(tmpstr);
		freechar(tmpstr);
	        tmpstr = newchar(strlen(ls_subject)+11);
	        sprintf(tmpstr,"<H3>%s</H3>\n",ls_subject);
		AppendFile(FileName,tmpstr);
		freechar(ls_subject);
		ls_subject = NULL;
		freechar(tmpstr);
		tmpstr = NULL;
		freechar(tmpSubject);
		tmpSubject = dupchar(tmp_mh->ssort);
		stats.Subject++;
	    }
	}
	tmpEmail = Email2Html(tmp_mh);
        if (config.FrameSupport == TRUE) {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+strlen(tmpEmail)+
	      strlen(tmp_mh->SentDate)+strlen(config.FrameNameMail)+34);
	    sprintf(tmpstr,"<A HREF=\"%s\" TARGET=\"%s\">%s</A> (%s)<BR>\n",
	      tmp_mh->FileName,config.FrameNameMail,tmp_mh->SentDate,tmpEmail);
	} else {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+
	      strlen(tmpEmail)+strlen(tmp_mh->SentDate)+24);
	    sprintf(tmpstr,"<A HREF=\"%s\">%s</A> (%s)<BR>\n",
	      tmp_mh->FileName,tmp_mh->SentDate,tmpEmail);
	}
        AppendFile(FileName,tmpstr);
        freechar(tmpstr);
        tmpstr = NULL;
        freechar(tmpEmail);
        tmpEmail = NULL;
	tmp_mh = tmp_mh->Next;
	if (config.PageSize > 0) {
	    if ((page_counter >= config.PageSize) && (tmp_mh != NULL)) {
		WriteListEnd(FileName,page,tmp_mh,"subject");
		page_counter = 0;
        	page++;
        	freechar(FileName);
		FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+20);
		sprintf(FileName,"%s/subject_%d%s",config.Directory,page,config.Extension);
		WriteListHead(tmpTitle,FileName,page,MsgCount);
	    }
	    page_counter++;
	}
    }
    WriteListEnd(FileName,page,tmp_mh,"author");

    /* Do a little cleanup */
    if (tmpSubject != NULL) {
	freechar(tmpSubject);
	tmpSubject = NULL;
    }
    if (FileName != NULL) {
	freechar(FileName);
	FileName = NULL;
    }
    if (tmpTitle != NULL) {
	freechar(tmpTitle);
	tmpTitle = NULL;
    }
}



void WriteAuthor (struct MAILHEAD *mh, int MsgCount) {
    struct MAILHEAD *tmp_mh;
    char *FileName, *tmpstr, *tmpAuthor, *tmpTitle, *tmpEmail, *tmpName, *ls_subject;
    int page, page_counter, n;
           
    if (config.DebugLevel & 1) printf(".WriteAuthor\n");

    page_counter = 0;
    tmpAuthor = NULL;
    tmp_mh = TopOfList(mh);
    stats.Author = 0;

    /* Fill sort-field */
    while (tmp_mh != NULL) {
        if (tmp_mh->ssort != NULL) freechar(tmp_mh->ssort);
        tmp_mh->isort = getutc(tmp_mh->SentDate);
	if ((strlen(tmp_mh->SendName) == 0) || (config.AuthorEmailSort == TRUE)) {
	    tmp_mh->ssort = dupchar(tmp_mh->SendAddress);
	} else {
	    tmp_mh->ssort = dupchar(tmp_mh->SendName);
	}
	if (config.AuthorCaseSort == FALSE) {
	    /* Convert to uppercase */
	    for (n=0;n<strlen(tmp_mh->ssort);n++)
		tmp_mh->ssort[n] = toupper(tmp_mh->ssort[n]);
	}
	tmp_mh = tmp_mh->Next;
    }
    strint_sort(TopOfList(mh));

    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+8);
    sprintf(FileName,"%s/author%s",config.Directory,config.Extension);
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+34);
        sprintf(tmpTitle,"<TITLE>%s sorted by author</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Sorted by author</TITLE>\n");
    }
    
    if (config.PageSize > 0) {
        page = 1;
	page_counter = 1;
    } else {
        page = 0;
    }

    WriteListHead(tmpTitle,FileName,page,MsgCount);

    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
	if (strlen(tmp_mh->SendName) == 0)
	    tmpName = dupchar(tmp_mh->SendName);
	else
	    tmpName = Text_2_Html(tmp_mh->SendName);
    	if (config.MailCommand != NULL) {
	    tmpEmail = newchar(strlen(config.MailCommand)+
		strlen(tmp_mh->SendAddress)*2+16);
	    sprintf(tmpEmail,"<A HREF=\"%s%s\">%s</A>",config.MailCommand,
		tmp_mh->SendAddress,tmp_mh->SendAddress);
    	} else {
    	    tmpEmail = dupchar(tmp_mh->SendAddress);
    	}
	if (tmpAuthor == NULL) {
	    if(strlen(tmp_mh->SendName) == 0) {
	        tmpstr = newchar(strlen(tmpEmail)+11);
	        sprintf(tmpstr,"<H3>%s</H3>\n",tmpEmail);
	    } else {
	        tmpstr = newchar(strlen(tmpName)+strlen(tmpEmail)+14);
	        sprintf(tmpstr,"<H3>%s (%s)</H3>\n",tmpName,tmpEmail);
	    }
            AppendFile(FileName,tmpstr);
	    freechar(tmpstr);
	    tmpstr = NULL;
            tmpAuthor = dupchar(tmp_mh->ssort);
            stats.Author = 1;
	} else {
	    if (strcmp(tmp_mh->ssort,tmpAuthor) != 0) {
	        if(strlen(tmp_mh->SendName) == 0) {
	            tmpstr = newchar(strlen(tmpEmail)+11);
	            sprintf(tmpstr,"<H3>%s</H3>\n",tmpEmail);
	        } else {
	            tmpstr = newchar(strlen(tmpName)+strlen(tmpEmail)+14);
	            sprintf(tmpstr,"<H3>%s (%s)</H3>\n",tmpName,tmpEmail);
	        }
		AppendFile(FileName,tmpstr);
		freechar(tmpstr);
		tmpstr = NULL;
		freechar(tmpAuthor);
		tmpAuthor = dupchar(tmp_mh->ssort);
                stats.Author++;
	    }
	}
	freechar(tmpEmail);
	tmpEmail = NULL;
	freechar(tmpName);
	tmpName = NULL;
	ls_subject = Text_2_Html(tmp_mh->Subject);
        if (config.FrameSupport == TRUE) {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+strlen(tmp_mh->SentDate)+
	      strlen(ls_subject)+ strlen(config.FrameNameMail)+39);
	    sprintf(tmpstr,"<A HREF=\"%s\" TARGET=\"%s\">%s</A> <I>%s</I><BR>\n",
	      tmp_mh->FileName,config.FrameNameMail,ls_subject,
	      tmp_mh->SentDate);
	} else {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+strlen(tmp_mh->SentDate)+
	      strlen(ls_subject)+29);
	    sprintf(tmpstr,"<A HREF=\"%s\">%s</A> <I>%s</I><BR>\n",
	      tmp_mh->FileName, ls_subject, tmp_mh->SentDate);
	}
        AppendFile(FileName,tmpstr);
        freechar(ls_subject);
        ls_subject = NULL;
        freechar(tmpstr);
        tmpstr = NULL;
	tmp_mh = tmp_mh->Next;
	if (config.PageSize > 0) {
	    if ((page_counter >= config.PageSize) && (tmp_mh != NULL)) {
		WriteListEnd(FileName,page,tmp_mh,"author");
		page_counter = 0;
        	page++;
        	freechar(FileName);
		FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+19);
		sprintf(FileName,"%s/author_%d%s",config.Directory,page,config.Extension);
		WriteListHead(tmpTitle,FileName,page,MsgCount);
	    }
	    page_counter++;
	}
    }
    WriteListEnd(FileName,page,tmp_mh,"author");

    /* Do a little cleanup */
    tmp_mh = TopOfList(mh);
    if (tmpAuthor != NULL) {
	freechar(tmpAuthor);
	tmpAuthor = NULL;
    }
    freechar(FileName);
    FileName = NULL;
    freechar(tmpTitle);
    tmpTitle = NULL;
}



void WriteDate (struct MAILHEAD *mh, int MsgCount) {
    struct MAILHEAD *tmp_mh;
    char *FileName, *tmpstr, *tmpName, *tmpTitle, *ls_subject, *ls_hellbender;
    int page, page_counter;
           
    if (config.DebugLevel & 1) printf(".WriteDate\n");

    ls_hellbender = newchar(1024);
    page_counter = 0;
    tmp_mh = TopOfList(mh);

    /* Fill sort-field */
    while (tmp_mh != NULL) {
	tmp_mh->isort = getutc(tmp_mh->SentDate);
	tmp_mh = tmp_mh->Next;
    }
    int_sort(TopOfList(mh));

    if (config.SortOrder == SORT_REVERSE) {
	tmp_mh = BottomOfList(mh);
	if (tmp_mh != NULL) {
	    config.ListEnd = tmp_mh->isort;
	} else {
	    config.ListEnd = 0;
	}
	stats.First = config.ListEnd;
	tmp_mh = TopOfList(mh);
	if (tmp_mh != NULL) {
	    config.ListStart = tmp_mh->isort;
	} else {
	    config.ListStart = 0;
	}
	stats.Last = config.ListStart;
    } else {
	tmp_mh = TopOfList(mh);
	if (tmp_mh != NULL) {
	    config.ListStart = tmp_mh->isort;
	} else {
	    config.ListStart = 0;
	}
	stats.First = config.ListStart;
	tmp_mh = BottomOfList(mh);
	if (tmp_mh != NULL) {
	    config.ListEnd = tmp_mh->isort;
	} else {
	    config.ListEnd = 0;
	}
	stats.Last = config.ListEnd;
    }
    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+6);
    sprintf(FileName,"%s/date%s",config.Directory,config.Extension);
    if (config.Name != NULL) {
        tmpTitle = newchar(strlen(config.Name)+32);
        sprintf(tmpTitle,"<TITLE>%s sorted by date</TITLE>\n",config.Name);
    } else {
        tmpTitle = dupchar("<TITLE>Sorted by date</TITLE>\n");
    }
    
    if (config.PageSize > 0) {
        page = 1;
	page_counter = 1;
    } else {
        page = 0;
    }

    WriteListHead(tmpTitle,FileName,page,MsgCount);

    tmp_mh = TopOfList(mh);
    while (tmp_mh != NULL) {
        tmpName = Email2Html(tmp_mh);
        ls_subject = Text_2_Html(tmp_mh->Subject);
        if (config.FrameSupport == TRUE) {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+strlen(ls_subject)+
	      strlen(tmpName)+strlen(config.FrameNameMail)+
	      strlen(tmp_mh->SentDate)+42);
	    sprintf(tmpstr,"<A HREF=\"%s\" TARGET=\"%s\">%s</A> (%s) <I>%s</I><BR>\n",
	      tmp_mh->FileName,config.FrameNameMail,ls_subject,tmpName,tmp_mh->SentDate);
        } else {
	    tmpstr = newchar(strlen(tmp_mh->FileName)+strlen(ls_subject)+
	      strlen(tmpName)+strlen(tmp_mh->SentDate)+32);
	    sprintf(tmpstr,"<A HREF=\"%s\">%s</A> (%s) <I>%s</I><BR>\n",
	      tmp_mh->FileName,ls_subject,tmpName,tmp_mh->SentDate);
        }
        AppendFile(FileName,tmpstr);
        freechar(ls_subject);
        ls_subject = NULL;
        freechar(tmpstr);
        tmpstr = NULL;
        freechar(tmpName);
        tmpName = NULL;
	tmp_mh = tmp_mh->Next;
	if (config.PageSize > 0) {
	    if ((page_counter >= config.PageSize) && (tmp_mh != NULL)) {
		WriteListEnd(FileName,page,tmp_mh,"date");
		page_counter = 0;
		page++;
        	freechar(FileName);
		FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+17);
		sprintf(FileName,"%s/date_%d%s",config.Directory,page,config.Extension);
		WriteListHead(tmpTitle,FileName,page,MsgCount);
	    }
	    page_counter++;
	}
    }
    WriteListEnd(FileName,page,tmp_mh,"date");
    freechar(FileName);
    FileName = NULL;
    freechar(tmpTitle);
    tmpTitle = NULL;
}


void WriteStats (struct MAILHEAD *mh) {
    char *tmpstr, *FileName;
    time_t BuildTime;

    if (stats.Messages == WMF_NOVALUE) stats.Messages = MessageCount(mh);
    FileName = newchar(strlen(config.Directory)+strlen(config.Extension)+7);
    sprintf(FileName,"%s/stats%s",config.Directory,config.Extension);

    if (config.Name != NULL) {
        tmpstr = newchar(strlen(config.Name)+32);
        sprintf(tmpstr,"<TITLE>%s statistics</TITLE>\n",config.Name);
    } else {
        tmpstr = dupchar("<TITLE>Statistics</TITLE>\n");
    }

    InitHtml(FileName);
    if (config.DocStartFile != NULL) {
	IncludeFile(FileName,config.DocStartFile);
    } else {
	AppendFile(FileName,"<HEAD>\n");
	AppendFile(FileName,tmpstr);
	AppendFile(FileName,"</HEAD>\n");
	if (HtmlCmd.BodyStart == NULL)
	    AppendFile(FileName,HTMLCMD_BODY_START);
	else
	    AppendFile(FileName,HtmlCmd.BodyStart);
	AppendFile(FileName,"\n");
    }
    freechar(tmpstr);
    tmpstr = NULL;
    if (config.FrameSupport == FALSE) {
	WriteIndexNavigation(FileName);
	if (HtmlCmd.HrStart == NULL)
	    AppendFile(FileName,HTMLCMD_HR_START);
	else
	    AppendFile(FileName,HtmlCmd.HrStart);
    }

    AppendFile(FileName,"<H2>Statistics</H2>\n");
    tmpstr = newchar(75); /* 50 for date */
    BuildTime = time(NULL);
    strftime(tmpstr,67,"Statistics build: %a, %d. %b %Y %H:%M:%S<P>\n",
          localtime(&BuildTime));
    AppendFile(FileName,tmpstr);
    freechar(tmpstr);
    AppendFile(FileName,"<TABLE>\n");

    if (stats.Messages != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>Messages:</TH><TD>");
	tmpstr = newchar(10); /* 10 for amount of messages */
	sprintf(tmpstr,"%d",stats.Messages);
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }
    
    if (stats.First != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>First message:</TH><TD>");
	tmpstr = newchar(50); /* 50 for date */
	strftime(tmpstr,50,"%a, %d. %b %Y %H:%M:%S",
	  localtime(&stats.First));
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }

    if (stats.Last != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>Last message:</TH><TD>");
	tmpstr = newchar(50); /* 50 for date */
	strftime(tmpstr,50,"%a, %d. %b %Y %H:%M:%S",
	  localtime(&stats.Last));
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }

    if (stats.Author != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>Authors:</TH><TD>");
	tmpstr = newchar(10); /* 10 for amount of messages */
	sprintf(tmpstr,"%d",stats.Author);
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }
    
    if (stats.Subject != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>Subjects:</TH><TD>");
	tmpstr = newchar(10); /* 10 for amount of messages */
	sprintf(tmpstr,"%d",stats.Subject);
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }
    
    if (stats.Thread != WMF_NOVALUE) {
	AppendFile(FileName,"<TR><TH ALIGN=LEFT>Threads:</TH><TD>");
	tmpstr = newchar(10); /* 10 for amount of messages */
	sprintf(tmpstr,"%d",stats.Thread);
	AppendFile(FileName,tmpstr);
	freechar(tmpstr);
	AppendFile(FileName,"</TD></TR>\n");
    }
    
    AppendFile(FileName,"</TABLE>\n");

    if (HtmlCmd.HrStart == NULL)
	AppendFile(FileName,HTMLCMD_HR_START);
    else
	AppendFile(FileName,HtmlCmd.HrStart);
    AppendFile(FileName,"\n");
    if (config.FrameSupport == FALSE) {
	WriteIndexNavigation(FileName);
    }
    AppendFile(FileName,"<P>\n");
    if (config.FrameSupport == TRUE) {
	tmpstr = newchar(strlen(HREF)+strlen(NAME)+strlen(VERSION)+38);
	sprintf(tmpstr,"<A HREF=\"%s\" TARGET=_top>%s</A> version %s\n",HREF,NAME,VERSION);
    } else {
	tmpstr = newchar(strlen(HREF)+strlen(NAME)+strlen(VERSION)+26);
	sprintf(tmpstr,"<A HREF=\"%s\">%s</A> version %s\n",HREF,NAME,VERSION);
    }
    AppendFile(FileName,tmpstr);
    freechar(tmpstr);
    tmpstr = NULL;
    if (config.DocEndFile != NULL) {
	IncludeFile(FileName,config.DocEndFile);
    } else {
	if (HtmlCmd.BodyEnd == NULL)
	    AppendFile(FileName,HTMLCMD_BODY_END);
	else
	    AppendFile(FileName,HtmlCmd.BodyEnd);
	AppendFile(FileName,"\n");
    }
    EndHtml(FileName);
    freechar(FileName);
    
}


void CreateIndex () {
    struct MAILHEAD *mh;
    int MsgCount;
    
    if (config.DebugLevel & 1) printf(".CreateIndex\n");

    /* Init stats var*/
    stats.Messages = WMF_NOVALUE;
    stats.First = WMF_NOVALUE;
    stats.Last = WMF_NOVALUE;
    stats.Thread = WMF_NOVALUE;
    stats.Subject = WMF_NOVALUE;
    stats.Author = WMF_NOVALUE;

    /* remove existing index-file */
    DelIndexFiles();
    mh = ReadHtmlHeader();
    if (config.CountMessages == TRUE) {
	MsgCount = MessageCount(mh);
    } else {
	MsgCount = WMF_NOVALUE;
    }
    stats.Messages = MsgCount;
    if (config.IndexDate == TRUE) WriteDate(mh,MsgCount);
    if (config.IndexAuthor == TRUE) WriteAuthor(mh,MsgCount);
    if (config.IndexSubject == TRUE) WriteSubject(mh,MsgCount);
    if (config.IndexThread == TRUE) WriteThread(mh,MsgCount);
    if (config.Statistics == TRUE) WriteStats(mh);
    CleanAllHeader(TopOfList(mh));
 }
