/*
 * This file is part of the FEddi package
 *
 * Personal use allowed under the terms of the
 *
 *              GNU GENERAL PUBLIC LICENSE Version 2
 *              (see LICENSE for the complete text)
 *
 *-------------------------------------------------------------------
 *
 *    ENTER AT YOUR OWN RISK !!
 *
 * This source is without any documentation and can drive you mad.
 * In case of sudden epileptic seizures please call your doctor.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <ncurses.h>
#include <dirent.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include "regex.h"
#include "proc.h" 
#include "functs.h"
#include "mbnl.h"
#include "textedit.h"
#include "template.h"
#include "mbhelp.h"
#include "charset.h"
#include "colors.h"
#include "mbsearch.h"
#include "request.h"
#include "mbutil.h"
#include "flags.h"
#include "inout.h"

#define toggle(n) n=1-n
#define togglebit(n,m) n=n^(1<<m)

static char Flags[16][11]={
"Priv ", "Crash ", "Recv ", "Sent ", "File ", "Trans ",
"Orph ", "Kill/Sent ", "Local ", "Hold ", "?unused? ", "FileReq ",
"RRReq ", "IRRec ", "Audit ", "FUReq "};

static char _REPLYREG[80]="[rR]{1}[eE]{1}(\\^[[:digit:]]+)?[[:space:]]*:";

LineListType *MsgTxt, *Kludges, *DispKludges;
int curLine, MsgLines, KludgeLines, DispKludgeLines;

WINDOW *wHdr, *wTxt, *wTop, *wHlp;

FolderType *Folder;
int maxFld=0, curFld=0, widFld=0, reFld=0;
int curMsg=0, ende=0, help=0;
int MBSFIN=0;
int pseudoEmpty=0, TotalRecs;
int SimpleLink=0, TreeMode=0;

char ExportFile[PATH_MAX];

char **Names=NULL, **ShortNames=NULL;
int NameNum=0;

GroupType *Groups=NULL, TempGroup={"",0,NULL,NULL};
int numGroups=0, tmpGroup=0;

MsgHdrType *MsgHdr;

sig_atomic_t show_time_now=0;
sigset_t allmask;

int init();
void initscrs();
int initmb();
void initsig();
void initnames();
void initgroups();
int comp(const void *e1, const void *e2);
void showmsg();
void showfld();
void showhdr();
void nextmsg();
void prevmsg();
void metakey();
void showtxt(int shift);
void loadtxt(int);
void showflags(MsgHdrType *a);
int inputstat(MsgHdrType *a);
void showtime();
void replymsg(int pernm, int sender);
int savemsg(MsgHdrType *mh, int, int);
void lastline(char *);
void firstline(char *);
void reinit();
void nextSubject();
void prevSubject();
void Mother();
void Child();
void nextBrother();
void prevBrother();
void findundel();
void nextmarked();
void prevmarked();
void nextpersonal();
void prevpersonal();
void nextprotected();
void prevprotected();
void nextfolder();
void prevfolder();
void renumberfld();
int rescanfld();
void savefolder();
int inputaddr(WINDOW *, int, int, MsgHdrType *, int, int);
void chooseAka();
int editorcall(char *, int, int, int, MsgHdrType *, MsgHdrType *, int);
int getfolder();
void folderinfo(int fld);
void quitsig(int);
int changeFolder();
int listMsgs();
void FolderListShell(int);
int importFolders(int);
int UseThisGroup(GroupType *, char *);
int BuildTempGroup();
void clearmarks(int msg);

#include "mbedit.h"
#include "mbmenu.h"

int main(int argc, char **argv)
{
	int in;
	strcpy(ProgName,"fmbedit");
	if (argc==3)
	{
		if (strcmp(argv[1],"--config")==0 || strcmp(argv[1],"-c")==0)
			strcpy(ConfigName,argv[2]);
		else
		{
			printERR("Unknown param '%s'!\n",argv[1]);
			exit(EXIT_FAILURE);
		}
	} else
		if (argc!=1)
		{
			printERR("Illegal number of params!\n");
			exit(EXIT_FAILURE);
		}
	if (loadrc(1))
	{
		Log("*FEddi running Editor");
		if (init())
		{
			if (reFld)
				changeFolder();
			do
			{
				sigprocmask(SIG_UNBLOCK,&allmask,NULL);
				if (show_time_now) showtime();
				in=getchn();
				if (show_time_now) showtime();
				sigprocmask(SIG_BLOCK,&allmask,NULL);
				if (in==0x1b) metakey();
				else switch((char)in)
				{
					case 1: killmenu(); changeShowAll(); break;
					case 4: killmenu(); redrawScreen(); break;
					case 6: killmenu(); forward(); break;
					case 7: killmenu(); requestFilesfromAddr(); break;
					case 8: killmenu(); changeCharset(); break;
					case 12: killmenu(); toggleLink(); break;
					case 13: killmenu(); toggleClearMarks(); break;
					case 14: killmenu(); netreplyDest(); break;
					case 15: killmenu(); toggleReadOnly(); break;
					case 18: killmenu(); replyDest(); break;
					case 0x7f: killmenu(); deleteThread(); break;
					case 0x9: killmenu(); showtree(); break;

					case '5':
						if (menuarrow(ARROW_NIL))
							toggleMark();
						break;
					case '0':
						if (menuarrow(ARROW_NIL))
							toggleProtect();
						break;
					case '6':
						if (menuarrow(ARROW_NIL))
						{
							if (SimpleLink)
								nextSubject();
							else
								nextBrother();
						}
						break;
					case '4':
						if (menuarrow(ARROW_NIL))
						{
							if (SimpleLink)
								prevSubject();
							else
								prevBrother();
						}
						break;
					case '8':
						if (menuarrow(ARROW_NIL))
							if (!SimpleLink) Mother();
						break;
					case '2':
						if (menuarrow(ARROW_NIL))
							if (!SimpleLink) Child();
						break;
					case '9': if (menuarrow(ARROW_NIL)) nextmarked(); break;
					case '7': if (menuarrow(ARROW_NIL)) prevmarked(); break;
					case '3': if (menuarrow(ARROW_NIL)) nextpersonal(); break;
					case '1': if (menuarrow(ARROW_NIL)) prevpersonal(); break;
					case '+': if (menuarrow(ARROW_NIL)) nextprotected(); break;
					case '-': if (menuarrow(ARROW_NIL)) prevprotected(); break;
					case '/': if (menuarrow(ARROW_NIL)) prevfolder(); break;
					case '*': if (menuarrow(ARROW_NIL)) nextfolder(); break;
					case 0xa: if (menuarrow(ARROW_CLICK)) ListShell(); break;

					case 'a' ... 'z':
					case 'A' ... 'Z':
					case 32:
						menukey(in);
						break;
				}
			} while (!ende);
			savemsghdr(&MsgHdr);
			MsgData.LastRead=curMsg;
			closearea();
			savefolder();
			sigprocmask(SIG_BLOCK,&allmask,NULL);
			curs_set(CURSOR_ON);
			endwin();
			Log("*Leaving Editor\n");
			EndLog();
		} else
		{
			closearea();
			sigprocmask(SIG_BLOCK,&allmask,NULL);
			if (stdscr) endwin();
			Log("!Error while starting fmbedit");
			Log("*Leaving Editor\n");
			EndLog();
			return EXIT_FAILURE;
		}
	} else
	{
		printERR("\nError while processing ~/.feddirc\n");
		return EXIT_FAILURE;
	}
	return EXIT_SUCCESS;
}

void metakey()
{
	int in;
	in=getchn();
	switch (in)
	{
		case 0x1b: menukey(32); break;
		case '1': killmenu(); showGlobalHelp(); break;
		case '2': killmenu(); showKeyboardHelp(); break;
		case '3': killmenu(); showNumblockHelp(); break;
		case '4': killmenu(); showFolderHelp(); break;
		case '5': killmenu(); showMessageHelp(); break;
		case '6': killmenu(); showTreeHelp(); break;
		case '7': killmenu(); showRequestHelp(); break;
		case '8': killmenu(); showSearchHelp(); break;
		case '9': killmenu(); showRegexHelp(); break;
		case '0': killmenu(); showEditorHelp(); break;

		case 'a': killmenu(); cycleAka(); break;
		case 'b': killmenu(); changeFrom(); break;
		case 'c': killmenu(); crosspost(); break;
		case 'd': killmenu(); changeTo(); break;
		case 'e': killmenu(); exportMsg(); break;
		case 'f': killmenu(); FolderShell(); break;
		case 'g': killmenu(); requestFiles(); break;
		case 'h': killmenu(); showKeyboardHelp(); break;
		case 'i': killmenu(); folderInfo(); break;
		case 'j': killmenu(); changeSubj(); break;
		case 'k': killmenu(); showKludges(); break;
		case 'l':	killmenu(); ListShell(); break;

		case 'n': killmenu(); netreplyMsg(); break;
		case 'o': killmenu(); chooseOrigin(); break;
		case 'p': killmenu(); printMsg(); break;

		case 'r': killmenu(); replyMsg(); break;
		case 's': killmenu(); startSearch(); break;
		case 't': killmenu(); changeText(); break;
		case 'u': killmenu(); callUtility(); break;

		case 'w': killmenu(); showAbout(); break;
		case 'x': killmenu(); quitFEddi(); break;
		case 'y': killmenu(); changeFlags(); break;

		case 0x5b: in=getchn();
							switch(in)
							{
								case 0x41:
									if (menuarrow(ARROW_UP))
										showtxt(-1);
									break;
								case 0x42:
									if (menuarrow(ARROW_DOWN))
										showtxt(1);
									break;
								case 0x43:
									if (menuarrow(ARROW_RIGHT))
										nextmsg();
									break;
								case 0x44:
									if (menuarrow(ARROW_LEFT))
										prevmsg();
									break;
								case 0x35:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										curLine-=(LINES-9);
										if (curLine<0) curLine=0;
										showtxt(0);
									}
									break;
								case 0x36:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										if (MsgLines>LINES-8)
										{
											curLine+=(LINES-9);
											if (curLine>MsgLines-LINES+8)
												curLine=MsgLines-LINES+8;
											showtxt(0);
										}
									}
									break;
								case 0x31:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										curLine=0;
										showtxt(0);
									}
									break;
								case 0x34:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										if (MsgLines>LINES-8)
											curLine=MsgLines-LINES+8;
										showtxt(0);
									}
									break;
								case 0x32:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										touchwin(wTxt);
										wrefresh(wTxt);
										enterMsg();
									}
									break;
								case 0x33:
									getch();
									if (menuarrow(ARROW_NIL))
									{
										touchwin(wTxt);
										wrefresh(wTxt);
										deleteMsg();
									}
									break;
							}
							break;
	}
}

int init()
{
	MsgTxt=Kludges=DispKludges=NULL;
	MsgHdr=NULL;
	stdscr=NULL;
	srand(time(NULL));
	Aka=Profile.Aka;
	if (!initmb())
	{
		printERR("\nNo messagebase!\n\n");
		return 0;
	} else
	{
		initquote();
		initnames();
		initgroups();
 		initutils();
		initscrs();
		initsig();
		showtime();
		return 1;
	}
}

void quitsig(int sig)
{
	char log[80];
	savemsghdr(&MsgHdr);
	MsgData.LastRead=curMsg;
	closearea();
	savefolder();
	curs_set(CURSOR_ON);
	endwin();
	strcpy(log,"End by Signal ");
	switch (sig)
	{
		case 3: strcat(log,"QUIT"); break;
		case 7: strcat(log,"SEVEN"); break;
		case 15: strcat(log,"TERM"); break;
	}
	Log("!%s",log);
	Log("*Leaving fmbedit\n");
	EndLog();
	exit(0);
}

void sigshowtime(int sig)
{
	show_time_now=1;
}

void initsig()
{
	struct sigaction sa;
	sigemptyset(&allmask);
	sigaddset(&allmask,SIGALRM);
	sigprocmask(SIG_BLOCK,&allmask,NULL);
	sa.sa_handler=sigshowtime;
	sigfillset(&sa.sa_mask);
	sa.sa_flags=SA_RESTART;
	sigaction(SIGALRM,&sa,NULL);
	
/*	sa.sa_handler=quitsig;
	sigfillset(&sa.sa_mask);
	sa.sa_flags=SA_RESTART;
	sigaction(SIGQUIT,&sa,NULL);
	sigaction(SIGTERM,&sa,NULL);*/
	
	sa.sa_handler=SIG_IGN;
	sigfillset(&sa.sa_mask);
	sa.sa_flags=SA_RESTART;
	sigaction(SIGINT,&sa,NULL);
	sigaction(SIGTSTP,&sa,NULL);
	sigaction(SIGQUIT,&sa,NULL);
	sigaction(SIGTERM,&sa,NULL);
}

void initnames()
{
	FILE *f;
	char line[PATH_MAX], *d1;
	sprintf(line,"%snames",BasePath);
	Names=addhistory(Names,NameNum,"");
	ShortNames=addhistory(ShortNames,NameNum++,"");
	if ((f=fopen(line,"rt"))!=NULL)
	{
		while (fgets(line,PATH_MAX,f))
		{
			if ((d1=strchr(line,0xa))) *d1=0;
			if (line[0])
			{
				if (line[0]=='*')
				{
					if ((d1=strchr(line,',')))
						*d1++=0;
					else
						continue;
					Names=addhistory(Names,NameNum,d1);
					ShortNames=addhistory(ShortNames,NameNum++,line);
				} else
				{
					Names=addhistory(Names,NameNum,line);
					ShortNames=addhistory(ShortNames,NameNum++,"");
				}
			}
		}
		fclose(f);
	}
}

void initgroups()
{
	char line[PATH_MAX], *d1, *d2, *d3;
	FILE *f;
	int i;
	sprintf(line,"%sgroups",BasePath);
	if ((f=fopen(line,"rt")))
	{
		while (fgets(line,PATH_MAX,f))
		{
			if ((d1=strchr(line,'\n'))) *d1=0;
			if (line[0]=='!')
			{
				numGroups++;
				Groups=(GroupType *)realloc(Groups,GroupSize*numGroups);
				line[19]=0;
				strcpy(Groups[numGroups-1].Label,line);
				Groups[numGroups-1].numNames=0;
				Groups[numGroups-1].Names=NULL;
				Groups[numGroups-1].Addr=NULL;
				Groups[numGroups-1].Subj=NULL;
				Groups[numGroups-1].Attrib=NULL;
				continue;
			}
			if (numGroups)
			{
				if ((d1=strchr(line,',')))
				{
					*d1++=0;
	 				Groups[numGroups-1].numNames++;
					Groups[numGroups-1].Names=(char **)realloc(
							Groups[numGroups-1].Names,
							Groups[numGroups-1].numNames*sizeof(char *));
					Groups[numGroups-1].Addr=(Addr4dType *)realloc(
							Groups[numGroups-1].Addr,
							Groups[numGroups-1].numNames*Addr4dSize);
					Groups[numGroups-1].Subj=(char **)realloc(
							Groups[numGroups-1].Subj,
							Groups[numGroups-1].numNames*sizeof(char *));
					Groups[numGroups-1].Attrib=(word *)realloc(
							Groups[numGroups-1].Attrib,
							Groups[numGroups-1].numNames*sizeof(word));
					Groups[numGroups-1].Names[Groups[numGroups-1].numNames-1]=(char *)
							malloc(strlen(line)+1);
					strcpy(Groups[numGroups-1].Names[Groups[numGroups-1].numNames-1],
							line);
					Groups[numGroups-1].Attrib[Groups[numGroups-1].numNames-1]=0;
					if ((d2=strchr(d1,',')))
					{
						*d2++=0;
						if ((d3=strchr(d2,',')))
						{
							for (*d3++=0; *d3; d3+=2)
								for (i=0; i<16; i++)
									if (strncasecmp(d3,NAMEFLAG[i],2)==0)
									{
										Groups[numGroups-1].Attrib
												[Groups[numGroups-1].numNames-1]|=(1<<i);
										break;
									}
						}
						Groups[numGroups-1].Subj[Groups[numGroups-1].numNames-1]=(char *)
								malloc(strlen(d2)+1);
						strcpy(Groups[numGroups-1].Subj[Groups[numGroups-1].numNames-1],
								d2);
					} else
					{
						Groups[numGroups-1].Subj[Groups[numGroups-1].numNames-1]=(char *)
								malloc(1);
						strcpy(Groups[numGroups-1].Subj[Groups[numGroups-1].numNames-1],
								"");
					}
					if (Str2Addr(d1,
							&(Groups[numGroups-1].Addr[Groups[numGroups-1].numNames-1])))
					{
						free(Groups[numGroups-1].Names[Groups[numGroups-1].numNames-1]);
						free(Groups[numGroups-1].Subj[Groups[numGroups-1].numNames-1]);
						Groups[numGroups-1].numNames--;
					}
				}
			}
		}
		fclose(f);
	}
}

void initscrs()
{
	if (!initscr()) raise(SIGTRAP);
	if (LINES<10 || COLS <20)
	{
		printERR("\nTerminal is to small!\n\n");
		endwin();
		exit(1);
	}
	if (has_colors())
	{
		start_color();
		COLON=1;
	}
	initFEddiColors();
	cbreak();
	noecho();
	curs_set(CURSOR_OFF);
	WordWrap=COLS-8;
	wTop=newwin(1,0,0,0);
	wHdr=newwin(6,0,1,0);
	wTxt=newwin(LINES-8,0,7,0);
	wHlp=newwin(1,0,LINES-1,0);
	meta(wHdr,TRUE);
	meta(wTxt,TRUE);
	meta(stdscr,TRUE);
	wcolon(stdscr,COL_NormalText);
	erase();
	refresh();
	wcolon(wTop,COL_StatusLine);
	werase(wTop);
	mvwprintw(wTop,0,1,"%s(%s)@%u:%u/%u.%u(%s)",\
						Profile.UserName,Profile.UserLogin,\
						Aka->UserZone,Aka->UserNet,Aka->UserNode,Aka->UserPoint,\
						Aka->NetName);
	wcoloff(wTop);
	wrefresh(wTop);
	initmenu();
	showmsg();
}

int initmb()
{
	FILE *areas;
	char *d1, name[PATH_MAX], line[PATH_MAX];
	struct stat st;
	maxFld=1;
	Folder=(FolderType *)malloc(sizeof(FolderType));
	memset(&(Folder[0]),0,FolderSize);
	strcpy(Folder[0].name,"NETMAIL");
	Folder[0].num=0;
	strcpy(name,BasePath);
	strcat(name,"areas");
	if ((areas=fopen(name,"rt"))!=NULL)
	{
		while (fgets(line,80,areas)!=NULL)
		{
			if ((d1=strchr(line,0xa))) *d1=0;
			if (line[0]==0) continue;
			Folder=(FolderType *)realloc((void *)Folder,\
					sizeof(FolderType)*(maxFld+1));
			memset(&(Folder[maxFld]),0,FolderSize);
			if (line[0]!='-')
			{
				if ((d1=strchr(line,32)))
				{
					*d1++=0;
					extendhome(d1);
					mksl(d1);
					if (!stat(d1,&st))
					{
						Folder[maxFld].path=(char *)malloc(strlen(d1)+1);
						strcpy(Folder[maxFld].path,d1);
					} else
					{
						Log("!Can't stat %s",d1);
						continue;
					}
				}
				upperstr(line);
			}
			strncpy(Folder[maxFld].name,line,39);
			Folder[maxFld].name[strlen(line)]=0;
			if (strlen(Folder[maxFld].name)>widFld)
				widFld=strlen(Folder[maxFld].name);
			maxFld++;
		}
		fclose(areas);
	} else Log("!Can't stat area-file");
	reFld=rescanfld();
	renumberfld();
	if (reFld) curFld=maxFld-reFld;
	TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
	loadmsghdr(&MsgHdr);
	loadalias(Folder[curFld].name);
	loadorig(Folder[curFld].name);
	curMsg=MsgData.LastRead;
	findundel();
	return 1;
}

int comp(const void *s1, const void *s2)
{
	return (strcmp(((FolderType *)s1)->name,((FolderType *)s2)->name));
}

void showmsg()
{
	loadtxt(0);
	if (TotalMsgs && !pseudoEmpty)
	{
		if (AutoDelEmpty && !MsgLines && !MsgHdr[curMsg].Deleted)
		{
			MsgHdr[curMsg].Deleted=1;
			MsgData.Deleted++;
			if (MsgHdr[curMsg].Marked)
				MsgData.Marked--;
		}
		if (MsgHdr[curMsg].New)
		{
			MsgHdr[curMsg].New=0;
			MsgData.New--;
		}
		if (MsgHdr[curMsg].NewPersonal)
		{
			MsgHdr[curMsg].NewPersonal=0;
			MsgData.NewPersonal--;
		}
	}
	showhdr();
	showtxt(0);
}

void showfld()
{
	int i;
	wcolon(wHdr,COL_Header);
	wmove(wHdr,5,0);
	for (i=0; i<COLS; i++)
		waddch(wHdr,ACS_HLINE);
	if (curFld>0)
		mvwprintw(wHdr,5,1,"<%u:%u/%u>",MsgData.RouteZone,MsgData.RouteNet,\
				MsgData.RouteNode);
	if (MsgData.ReadOnly)
		waddstr(wHdr,"<RD>");
	mvwprintw(wHdr,5,COLS-3-strlen(Folder[curFld].name),"[%s]",\
			Folder[curFld].name);
	wcoloff(wHdr);
}

void showhdr()
{
	int ok;
	char addr[40], *d1;
	NLentryType ent;
	wcolon(wHdr,COL_HeaderText);
	werase(wHdr);
	showfld();
	if (TotalMsgs==0 || pseudoEmpty)
	{
		wcolon(wHdr,COL_Warning);
		mvwaddstr(wHdr,2,10,"NO MESSAGES IN THIS FOLDER");
		touchwin(wHdr);
		wrefresh(wHdr);
		return;
	}
	wcolon(wHdr,COL_Header);
	mvwaddch(wHdr,0,0,'[');
	mvwaddstr(wHdr,1,0,"By:");
	mvwaddstr(wHdr,2,0,"To:");
	mvwaddstr(wHdr,3,0,"Re:");
	mvwaddstr(wHdr,4,0,"St:");
	wcolon(wHdr,COL_HeaderText);
  mvwprintw(wHdr,0,1,"%u/%u",curMsg+1,TotalMsgs);
  wcolon(wHdr,COL_Header);
  waddch(wHdr,']');
  wcolon(wHdr,COL_HeaderText);
  wprintw(wHdr," %s",MsgHdr[curMsg].DateTime);
  if (MsgData.NetMail &&  MsgHdr[curMsg].Recvdt[0])
  {
		wcolon(wHdr,COL_ReceivedDT);
		wprintw(wHdr,"  Recv: %s",MsgHdr[curMsg].Recvdt);
		wcolon(wHdr,COL_HeaderText);
	}
	if (MsgHdr[curMsg].Personal)
		wcolon(wHdr,COL_PrivateFlag);
	if (MsgHdr[curMsg].Attribute&256)
		wcolon(wHdr,COL_LocalMessage);
	mvwaddstru(wHdr,1,4,MsgHdr[curMsg].WhoFrom);
	wcolon(wHdr,COL_HeaderText);
	if (MBSActualField==1 && MBSFoundMsg==curMsg)
	{
		wcolon(wHdr,COL_FoundText);
		mvwaddstru(wHdr,1,4+MBSStringPosX,MBSFoundString);
		wcolon(wHdr,COL_HeaderText);
	}
	if (MsgData.NetMail || ShowAllAddr==2)
	{
		sprintf(addr,"%u:%u/%u.%u",MsgHdr[curMsg].OrigZone,
				MsgHdr[curMsg].OrigNet,MsgHdr[curMsg].OrigNode,
				MsgHdr[curMsg].OrigPoint);
		if ((ok=keyentry(addr,&ent)) && MsgHdr[curMsg].OrigPoint)
		{
			d1=strchr(addr,'.');
			*d1=0;
			ok=keyentry(addr,&ent);
		}
		mvwprintw(wHdr,1,4+strlen(MsgHdr[curMsg].WhoFrom),
				", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,
				MsgHdr[curMsg].OrigZone,MsgHdr[curMsg].OrigNet,
				MsgHdr[curMsg].OrigNode,MsgHdr[curMsg].OrigPoint);
	} else
		if (ShowAllAddr)
			mvwprintw(wHdr,1,4+strlen(MsgHdr[curMsg].WhoFrom)," (%u:%u/%u.%u)",
					MsgHdr[curMsg].OrigZone,MsgHdr[curMsg].OrigNet,
					MsgHdr[curMsg].OrigNode,MsgHdr[curMsg].OrigPoint);
	if (MsgHdr[curMsg].Personal)
		wcolon(wHdr,COL_PrivateFlag);
	if (MsgHdr[curMsg].Attribute&256)
		wcolon(wHdr,COL_LocalMessage);
	mvwaddstru(wHdr,2,4,MsgHdr[curMsg].WhoTo);
	wcolon(wHdr,COL_HeaderText);
	if (MBSActualField==2 && MBSFoundMsg==curMsg)
	{
		wcolon(wHdr,COL_FoundText);
		mvwaddstru(wHdr,2,4+MBSStringPosX,MBSFoundString);
		wcolon(wHdr,COL_HeaderText);
	}
	if (MsgData.NetMail)
	{
		sprintf(addr,"%u:%u/%u.%u",MsgHdr[curMsg].DestZone,
				MsgHdr[curMsg].DestNet,MsgHdr[curMsg].DestNode,
				MsgHdr[curMsg].DestPoint);
		if ((ok=keyentry(addr,&ent)) && MsgHdr[curMsg].DestPoint)
		{
			d1=strchr(addr,'.');
			*d1=0;
			ok=keyentry(addr,&ent);
		}
		mvwprintw(wHdr,2,4+strlen(MsgHdr[curMsg].WhoTo),
				", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,
				MsgHdr[curMsg].DestZone,MsgHdr[curMsg].DestNet,
				MsgHdr[curMsg].DestNode,MsgHdr[curMsg].DestPoint);
	}
	if (MsgHdr[curMsg].Personal)
		wcolon(wHdr,COL_PrivateFlag);
	if (MsgHdr[curMsg].Attribute&256)
		wcolon(wHdr,COL_LocalMessage);
	mvwaddstru(wHdr,3,4,MsgHdr[curMsg].Subj);
	wcolon(wHdr,COL_HeaderText);
	if (MBSActualField==3 && MBSFoundMsg==curMsg)
	{
		wcolon(wHdr,COL_FoundText);
		mvwaddstru(wHdr,3,4+MBSStringPosX,MBSFoundString);
		wcolon(wHdr,COL_HeaderText);
	}
	showflags(&MsgHdr[curMsg]);
	if (MsgHdr[curMsg].Personal)
	{
		wcolon(wHdr,COL_PrivateFlag);
		mvwaddstr(wHdr,0,COLS-12,"PRS");
	}
	if (MsgHdr[curMsg].Protected)
	{
		wcolon(wHdr,COL_ProtectedFlag);
		mvwaddstr(wHdr,0,COLS-8,"PRT");
	}
	if (MsgHdr[curMsg].Marked)
	{
		wcolon(wHdr,COL_MarkedFlag);
		mvwaddstr(wHdr,0,COLS-4,"MRK");
	}
	wcoloff(wHdr);
	if (MsgHdr[curMsg].NumRecs>MaxMsgLength)
	{
		wcolon(wHdr,COL_Warning);
		mvwaddstr(wHdr,2,COLS-17," WARNING ");
		mvwprintw(wHdr,3,COLS-17,"  %3uK   ",MsgHdr[curMsg].NumRecs/4+1);
		wcoloff(wHdr);
	}
	if (SimpleLink)
	{
		wcolon(wHdr,COL_Link);
		if (MsgHdr[curMsg].prevSubject!=65535)
			mvwprintw(wHdr,2,COLS-8,"<-%5u",MsgHdr[curMsg].prevSubject+1);
		if (MsgHdr[curMsg].nextSubject!=65535)
			mvwprintw(wHdr,3,COLS-8,"->%5u",MsgHdr[curMsg].nextSubject+1);
		wcoloff(wHdr);
	} else
	{
		wcolon(wHdr,COL_Link);
		if (MsgHdr[curMsg].Mother!=65535)
			mvwprintw(wHdr,1,COLS-8,"^-%5u",MsgHdr[curMsg].Mother+1);
		if (MsgHdr[curMsg].prevBrother!=65535)
			mvwprintw(wHdr,2,COLS-8,"<-%5u",MsgHdr[curMsg].prevBrother+1);
		if (MsgHdr[curMsg].nextBrother!=65535)
			mvwprintw(wHdr,3,COLS-8,"->%5u",MsgHdr[curMsg].nextBrother+1);
		if (MsgHdr[curMsg].Child!=65535)
			mvwprintw(wHdr,4,COLS-8,"v-%5u",MsgHdr[curMsg].Child+1);
		wcoloff(wHdr);
	}
	touchwin(wHdr);
	wrefresh(wHdr);
}

void nextmsg()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg<TotalMsgs-1)
	{
		for (i=curMsg+1; MsgHdr[i].Deleted && i<TotalMsgs; i++);
		if (i!=TotalMsgs)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	if (AutoNextFolder)
	{
		findundel();
		FolderShell();
		return;
	}
	Beep();
}

void prevmsg()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg>0)
	{
		for (i=curMsg-1; MsgHdr[i].Deleted && i>=0; i--);
		if (i>=0)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void showtxt(int shift)
{
	int i,j;
	if (!shift)
	{
		wcolon(wTxt,COL_NormalText);
		werase(wTxt);
		for (i=curLine, j=0; j<LINES-8 && i<MsgLines; j++, i++)
		{
			wcolon(wTxt,
					MsgTxt[i].Quote?
							(MsgTxt[i].Quote==1?COL_FirstQuoteText:COL_QuoteText)
							:(MsgTxt[i].CutOrigin?COL_CutOriginText:COL_NormalText));
			mvwaddstru(wTxt,i-curLine,0,MsgTxt[i].line);
			if (MBSActualField==4 && MBSFoundMsg==curMsg && i==MBSStringPosY)
			{
				wcolon(wTxt,COL_FoundText);
				mvwaddstru(wTxt,i-curLine,MBSStringPosX,MBSFoundString);
			}
		}
	} else
	{
		if (curLine+shift>=0 && curLine+shift<MsgLines-LINES+9)
		{
			scrollok(wTxt,TRUE);
			wscrl(wTxt,shift);
			scrollok(wTxt,FALSE);
			curLine+=shift;
			i=(shift>0)?curLine+(LINES-8-shift):curLine;
			wcolon(wTxt,
					MsgTxt[i].Quote?
							(MsgTxt[i].Quote==1?COL_FirstQuoteText:COL_QuoteText)
							:(MsgTxt[i].CutOrigin?COL_CutOriginText:COL_NormalText));
			mvwaddstru(wTxt,i-curLine,0,MsgTxt[i].line);
			wclrtoeolu(wTxt);
			if (MBSActualField==4 && MBSFoundMsg==curMsg && i==MBSStringPosY)
			{
				wcolon(wTxt,COL_FoundText);
				mvwaddstru(wTxt,i-curLine,MBSStringPosX,MBSFoundString);
			}
		} else
		{
			Beep();
			return;
		}
	}
	wrefresh(wTxt);
}

void loadtxt(int shift)
{
	curLine=0;
	if (TotalMsgs==0 || pseudoEmpty)
	{
		killTextOfMsg(&MsgLines,&MsgTxt,
				&KludgeLines,&Kludges,
				&DispKludgeLines,&DispKludges);
		return;
	}
	loadTextOfMsg(shift?shift:COLS,&(MsgHdr[curMsg]),
			&MsgLines,&MsgTxt,
			&KludgeLines,&Kludges,
			&DispKludgeLines,&DispKludges);
	if (MBSFIN)
	{
		MBSFIN=0;
		if (MBSFoundMsg==curMsg && MBSActualField==4)
			if (MsgLines-LINES+8>0)
			{
				curLine=MBSStringPosY;
				if (curLine>MsgLines-LINES+8)
					curLine=MsgLines-LINES+8;
			}
	}
}

void changeFrom()
{
	char line[36];
	if (TotalMsgs && !pseudoEmpty)
		if (MsgHdr[curMsg].Attribute&256)
		{
			wcolon(wHdr,COL_InputText);
			strcpy(line,MsgHdr[curMsg].WhoFrom);
			strcpy(Alias[0],MsgHdr[curMsg].WhoFrom);
			wmove(wHdr,1,4);
			wclrnumn(wHdr,COLS-12);
			if (!inputline(wHdr,wHlp,1,4,35,line,Alias,Aliases,0))
				strcpy(MsgHdr[curMsg].WhoFrom,line);
			wcoloff(wHdr);
			MatchAddr(&MsgHdr[curMsg],0);
			showhdr();
			return;
		}
	Beep();
}

void changeTo()
{
	MsgHdrType new;
	if (TotalMsgs && !pseudoEmpty)
		if (MsgHdr[curMsg].Attribute&256)
		{
			wcolon(wHdr,COL_InputText);
			new=MsgHdr[curMsg];
			wmove(wHdr,2,4);
			wclrnumn(wHdr,COLS-12);
			if (!inputaddr(wHdr,2,4,&new,0,0))
				MsgHdr[curMsg]=new;
			wcoloff(wHdr);
			MatchAddr(&MsgHdr[curMsg],0);
			showhdr();
			return;
		}
	Beep();
}

void changeSubj()
{
	if (TotalMsgs && !pseudoEmpty)
		if (MsgHdr[curMsg].Attribute&256)
		{
			wcolon(wHdr,COL_InputText);
			inputline(wHdr,wHlp,3,4,71,MsgHdr[curMsg].Subj,NULL,0,1);
			wcoloff(wHdr);
			showhdr();
			return;
		}
	Beep();
}

void changeFlags()
{
	if (TotalMsgs && !pseudoEmpty)
		if (MsgHdr[curMsg].Attribute&256)
		{
			inputstat(&MsgHdr[curMsg]);
			showhdr();
			return;
		}
	Beep();
}

void showflags(MsgHdrType *a)
{
	int i;
	wmove(wHdr,4,4);
	for (i=4; i<COLS; i++) waddch(wHdr,32);
	wmove(wHdr,4,4);
	for (i=0; i<16; i++)
		if (a->Attribute&(1<<i))
			waddstr(wHdr,(char *)Flags[i]);
	if (a->TruncSent) waddstr(wHdr,"Trunc/Sent ");
	if (a->DeleteSent) waddstr(wHdr,"Del/Sent ");
	if (a->Direct) waddstr(wHdr,"Direct ");
	wrefresh(wHdr);
}

void deleteMsg()
{
	if (TotalMsgs && !pseudoEmpty && !MsgHdr[curMsg].Protected)
	{
		if (!MsgHdr[curMsg].Deleted)
		{
			MsgHdr[curMsg].Deleted=1;
			MsgData.Deleted++;
			if (MsgHdr[curMsg].New)
				MsgData.New--;
			if (MsgHdr[curMsg].NewPersonal)
				MsgData.NewPersonal--;
			if (MsgHdr[curMsg].Marked)
				MsgData.Marked--;
		}
		findundel();
		showmsg();
	}
}

void toggleMark()
{
	if (TotalMsgs && !pseudoEmpty)
	{
		toggle(MsgHdr[curMsg].Marked);
		if (MsgHdr[curMsg].Marked)
			MsgData.Marked++;
		else
			MsgData.Marked--;
		showhdr();
	}
}

void toggleProtect()
{
	if (TotalMsgs && !pseudoEmpty)
	{
		toggle(MsgHdr[curMsg].Protected);
		showhdr();
	}
}

int inputstat(MsgHdrType *a)
{
	WINDOW *stat;
	int in=0;
	if (MsgData.NetMail)
	{
		stat=newwin(14,15,6,1);
		wcolon(stat,COL_Menu);
		werase(stat);
		box(stat,0,0);
		mvwaddstr(stat,1,1,"p Private");
		mvwaddstr(stat,2,1,"f FileAttach");
		mvwaddstr(stat,3,1,"u UpdateReq");
		mvwaddstr(stat,4,1,"k Kill/Sent");
		mvwaddstr(stat,5,1,"t Trunc/Sent");
		mvwaddstr(stat,6,1,"d Delete/Sent");
		mvwaddstr(stat,7,1,"s Sent");
		mvwaddstr(stat,8,1,"c Crash");
		mvwaddstr(stat,9,1,"h Hold");
		mvwaddstr(stat,10,1,"i Direct");
		mvwaddstr(stat,11,1,"z No Status");
		mvwaddstr(stat,12,1,"y Standard");
	} else
	{
		stat=newwin(7,13,6,1);
		wcolon(stat,COL_Menu);
		werase(stat);
		box(stat,0,0);
		mvwaddstr(stat,1,1,"p Private");
		mvwaddstr(stat,2,1,"s Sent");
		mvwaddstr(stat,3,1,"h Hold");
		mvwaddstr(stat,4,1,"z No Status");
		mvwaddstr(stat,5,1,"y Standard");
	}
	move(0,0);
	wrefresh(stat);
	wcolon(wHdr,COL_InputText);
	showflags(a);
	while (in!=27 && in!=10)
	{
		in=getchn();
		switch (in)
		{
			case 'p': togglebit(a->Attribute,0); showflags(a); break;
			case 's': togglebit(a->Attribute,3); showflags(a); break;
			case 'z': a->Attribute=0; 
								a->TruncSent=a->DeleteSent=a->Direct=0;
								showflags(a); break;
			case 'y': a->Attribute=StandardFlags; 
								a->TruncSent=a->DeleteSent=a->Direct=0;
								showflags(a); break;
			case 'h': togglebit(a->Attribute,9); showflags(a); break;
		}
		if (MsgData.NetMail)
			switch (in)
			{
				case 'f':
					togglebit(a->Attribute,4);
					if (!(a->Attribute&2))
						togglebit(a->Attribute,1);
					if (!(a->Attribute&128))
						togglebit(a->Attribute,7);
					showflags(a);
					break;
				case 'k': togglebit(a->Attribute,7); showflags(a); break;
				case 't': toggle(a->TruncSent); showflags(a); break;
				case 'd': toggle(a->DeleteSent); showflags(a); break;
				case 'u': togglebit(a->Attribute,15); showflags(a); break;
				case 'c': togglebit(a->Attribute,1); showflags(a); break;
				case 'i': toggle(a->Direct); showflags(a); break;
			}
	}
	delwin(stat);
	wcoloff(wHdr);
	touchwin(wTxt);
	wrefresh(wTxt);
	touchwin(wHdr);
	wrefresh(wHdr);
	if (in==10) return 1; else return 0;
}

void showtime()
{
	time_t timer;
	struct tm *tblock;
	timer=time(NULL);
	tblock=localtime(&timer);
	alarm(60-tblock->tm_sec);
	wcolon(wTop,COL_StatusLine);
	mvwprintw(wTop,0,COLS-19,"%02u.%02u.19%02u  %02u:%02u",\
						tblock->tm_mday,tblock->tm_mon+1,tblock->tm_year,\
						tblock->tm_hour,tblock->tm_min);
	wcoloff(wTop);
	wrefresh(wTop);
	show_time_now=0;
}

int exportask()
{
	int ret=0;
	WINDOW *ask=NULL;
	if ((ask=openask(ClearMarks?7:5,ClearMarks?34:21,LINES/2-(ClearMarks?1:0),
			COLS/2-(ClearMarks?17:10),"Export",COL_Menu))!=NULL)
	{
		mvwaddstr(ask,1,ClearMarks?9:2,"<M>arked messages");
		mvwaddstr(ask,2,ClearMarks?9:2,"<T>his message");
		mvwaddstr(ask,3,ClearMarks?9:2,"<ESC>^2 to abort");
		if (ClearMarks)
			mvwaddstr(ask,5,2,"WARNING: Marks will be cleared");
		wrefresh(ask);
		for (;;)
		{
			switch (getchn())
			{
				case 0x1b: getch(); break;
				case 'm':
				case 'M':
					ret=2;
					break;
				case 't':
				case 'T':
					ret=1;
					break;
				default: continue;
			}
			break;
		}
		delwin(ask);
		touchwin(wTxt);
		wrefresh(wTxt);
	} else
		Beep();
	return ret;
}

void exportMsg()
{
	struct stat st;
	FILE *rp, *wp;
	char fname[PATH_MAX], mode[4]="", **args, *d1, *d2=NULL, path[PATH_MAX];
	int in, pid, which=1, o, i, lines=0;
	LineListType *status=NULL;
	WINDOW *inp;
	if (!TotalMsgs)
	{
		Beep();
		return;
	}
	if (MsgData.Marked)
		if (!(which=exportask()))
		{
			Beep();
			return;
		}
	inp=openask(4,80,LINES/2+4,0,
			(which==1?"Export Message to":"Export Messages to"),COL_Menu);
	newcommand:
	while ((in=inputline(inp,wHlp,1,1,78,ExportFile,NULL,0,1))==-1);
	if (!in)
	{
		if (ExportFile[0]=='|')
		{
			for (d1=ExportFile+1; *d1==32; d1++);
			if ((d2=strchr(d1,32))) *d2=0;
			strcpy(fname,d1);
			if (d2) *d2++=32;
			if (!findfile(fname,path))
			{
				mvwaddstr(inp,2,2,"Command not found!");
				goto newcommand;
			}
			strcpy(mode,"cal");
		} else
		{
			extendhome(ExportFile);
			strcpy(fname,ExportFile);
			if (stat(fname,&st)==0)
			{
				mvwaddstr(inp,2,2,"File exists!!! (oVERWRITE/aPPEND/cANCEL)");
				wrefresh(inp);
				for (;;)
				{
					in=getchn();
					if (in=='o') {strcpy(mode,"new"); break;}
					if (in=='a') {strcpy(mode,"app"); break;}
					if (in=='c' || in==0x1b) {mode[0]=0; break;}
				}
			} else strcpy(mode,"new");
		}
		if (mode[0])
		{
			if (mode[0]=='c')
			{
				args=(char **)malloc(2*sizeof(char *));
				args[0]=(char *)malloc(strlen(fname)+strlen(path)+1);
				strcpy(args[0],path);
				strcat(args[0],fname);
				args[1]=strdup(args[0]);
				for (i=1; d2; i++, d2=d1)
				{
					if ((d1=strchr(d2,32))) *d1++=0;
					args=(char **)realloc(args,(i+2)*sizeof(char *));
					args[i+1]=strdup(d2);
				}
				args=(char **)realloc(args,(i+2)*sizeof(char *));
				args[i+1]=NULL;
			} else
			{
				args=(char **)malloc(4*sizeof(char *));
				args[0]=strdup(ExportMsg);
				args[1]=strdup(mode);
				args[2]=strdup(fname);
				args[3]=NULL;
			}
			if ((pid=pipecall(args[0],args,&rp,&wp))>0)
			{
				if (which==1)
				{
					outputMsg(wp,curMsg,Folder[curFld].name,&(MsgHdr[curMsg]),
							MsgLines,&MsgTxt,KludgeLines,&Kludges);
					if (ClearMarks) clearmarks(curMsg);
				}
				else
				{
					for (o=curMsg, in=0; in<TotalMsgs; in++)
						if (MsgHdr[in].Marked)
						{
							curMsg=in;
							loadtxt(0);
							outputMsg(wp,in,Folder[curFld].name,&(MsgHdr[in]),
									MsgLines,&MsgTxt,KludgeLines,&Kludges);
							if (ClearMarks) clearmarks(in);
						}
					curMsg=o;
					loadtxt(0);
				}
				fclose(wp);
				inputMsg(rp,COLS,&i,path,NULL,NULL,NULL,NULL,NULL,&lines,&status);
				while (waitpid(pid,&in,WNOHANG)!=pid);
				if (lines)
				{
					scrolltext(status,lines,"Export result",0);
					for (i=0; i<lines; i++) free(status[i].line);
					free(status);
				}
			}
			for (i=0; args[i]; i++) free(args[i]);
			free(args);
		}
	}
	delwin(inp);
	touchwin(wTxt);
	wrefresh(wTxt);
}

void printMsg()
{
	FILE *rp, *wp;
	char **args;
	int pid, i;
	if (TotalMsgs && !pseudoEmpty)
	{
		args=(char **)malloc(2*sizeof(char *));
		args[0]=strdup(PrintMsg);
		args[1]=NULL;
		if ((pid=pipecall(PrintMsg,args,&rp,&wp))>0)
		{
			fclose(rp);
			outputMsg(wp,curMsg,Folder[curFld].name,&(MsgHdr[curMsg]),
					MsgLines,&MsgTxt,KludgeLines,&Kludges);
			fclose(wp);
			while (waitpid(pid,&i,WNOHANG)!=pid);
		}
		free(args[0]);
		free(args);
		return;
	}
	Beep();
}

void enterMsg()
{
	MsgHdrType NewMsg;
	char addr[25], *d1, line[80], origsubj[80];
	NLentryType ent;
	LineListType *otxt=NULL;
	GroupType ThisGroup;
	int ok, group, l, i, j, oldmsg, nsj=0, nat=0;
	word origattr=0;
	wcolon(wHdr,COL_Header);
	mvwaddstr(wHdr,1,0,"By:");
	wclrtoeoln(wHdr);
	mvwaddstr(wHdr,2,0,"To:");
	wclrtoeoln(wHdr);
	mvwaddstr(wHdr,3,0,"Re:");
	wclrtoeoln(wHdr);
	mvwaddstr(wHdr,4,0,"St:");
	wclrtoeoln(wHdr);
	wcolon(wHdr,COL_InputText);
	mvwaddstr(wHdr,0,0,"New Message");
	wclrtoeoln(wHdr);
	NewMsg.OrigZone=Aka->UserZone;
	NewMsg.OrigNet=Aka->UserNet;
	NewMsg.OrigNode=Aka->UserNode;
	NewMsg.OrigPoint=Aka->UserPoint;
	NewMsg.DestZone=NewMsg.DestNet=NewMsg.DestNode=NewMsg.DestPoint=0;
	NewMsg.Attribute=StandardFlags;
	NewMsg.Mother=NewMsg.nextBrother=NewMsg.prevBrother=NewMsg.Child=\
	NewMsg.nextSubject=NewMsg.prevSubject=65535;
	NewMsg.Personal=NewMsg.Deleted=NewMsg.New=NewMsg.Marked=\
	NewMsg.TruncSent=NewMsg.DeleteSent=NewMsg.Direct=\
	NewMsg.Protected=NewMsg.NewPersonal=0;
	strcpy(NewMsg.WhoTo,"");
	strcpy(NewMsg.Subj,"");
	if (AskForOrigName)
	{
		strcpy(line,Profile.UserName);
		strcpy(Alias[0],Profile.UserName);
		if (!inputline(wHdr,wHlp,1,4,35,line,Alias,Aliases,0))
			strcpy(NewMsg.WhoFrom,line);
		else
			goto ende;
	} else
		strcpy(NewMsg.WhoFrom,Profile.UserName);
	mvwaddstr(wHdr,1,4,NewMsg.WhoFrom);
	if (MsgData.NetMail)
	{
		sprintf(addr,"%u:%u/%u.%u",Aka->UserZone,Aka->UserNet,
				Aka->UserNode,Aka->UserPoint);
		if ((ok=keyentry(addr,&ent)) && Aka->UserPoint)
		{
			d1=strchr(addr,'.');
			*d1=0;
			ok=keyentry(addr,&ent);
		}
		wprintw(wHdr,", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,
				Aka->UserZone,Aka->UserNet,\
				Aka->UserNode,Aka->UserPoint);
	}
	wclrtoeoln(wHdr);
	if ((group=inputaddr(wHdr,2,4,&NewMsg,1,1))<0)
	{
		Beep();
		goto ende;
	}
	oldmsg=TotalMsgs;
	if (group==0)
	{
		MatchAddr(&NewMsg,0);
		mvwaddstr(wHdr,1,4,NewMsg.WhoFrom);
		if (MsgData.NetMail)
		{
			sprintf(addr,"%u:%u/%u.%u",NewMsg.OrigZone,NewMsg.OrigNet,
					NewMsg.OrigNode,NewMsg.OrigPoint);
			if ((ok=keyentry(addr,&ent)) && NewMsg.OrigPoint)
			{
				d1=strchr(addr,'.');
				*d1=0;
				ok=keyentry(addr,&ent);
			}
			wprintw(wHdr,", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,
					NewMsg.OrigZone,NewMsg.OrigNet,
					NewMsg.OrigNode,NewMsg.OrigPoint);
		}
		wclrtoeoln(wHdr);
		if (inputline(wHdr,wHlp,3,4,71,NewMsg.Subj,NULL,0,1)!=-2)
		{
			if (MsgData.NetMail)
			{
				NewMsg.Attribute|=1;
				inputstat(&NewMsg);
				touchwin(wHdr);
				touchwin(wTxt);
				wrefresh(wHdr);
				wrefresh(wTxt);      /* kill Status win */
			}
			showflags(&NewMsg);
			for (i=0; i<KludgeLines; i++) free(Kludges[i].line);
			free(Kludges);
			Kludges=NULL;
			KludgeLines=0;
			editorcall("new",0,1,0,&NewMsg,&NewMsg,curFld);
			if (TotalMsgs!=oldmsg) curMsg=TotalMsgs-1;
		}
	} else
	{
		if (group==1)
			ThisGroup=TempGroup;
		else
			ThisGroup=Groups[group-2];
		for (i=0; i<ThisGroup.numNames; i++)
		{
			if (ThisGroup.Subj[i][0]==0) nsj=1;
			if (ThisGroup.Attrib[i]==0) nat=1;
		}
		if (MsgData.NetMail)
		{
			if (nsj)
			{
				if (inputline(wHdr,wHlp,3,4,71,NewMsg.Subj,NULL,0,1)==-2)
				{
					Beep();
					goto ende;
				}
				strcpy(origsubj,NewMsg.Subj);
			} else
			{
				mvwaddstru(wHdr,3,4,ThisGroup.Subj[0]);
				wclrtoeoln(wHdr);
			}
			NewMsg.Attribute|=1;
			if (nat)
			{
				inputstat(&NewMsg);
				origattr=NewMsg.Attribute;
			} else
				NewMsg.Attribute=ThisGroup.Attrib[0];
			touchwin(wHdr);
			touchwin(wTxt);
			wrefresh(wHdr);
			wrefresh(wTxt);
			showflags(&NewMsg);
			for (i=0; i<KludgeLines; i++) free(Kludges[i].line);
			free(Kludges);
			Kludges=NULL;
			KludgeLines=0;
			if (!editorcall("cc",-1,0,0,&NewMsg,&NewMsg,curFld))
			{
				for (l=0; l<MsgLines; l++)
					if (strcmp(MsgTxt[l].line,"$%&PUT-CROSSPOST-INFO-HERE&%$")==0)
						break;
				if (l!=MsgLines)
				{
					MsgTxt[l].CR=1;
					MsgTxt[l].Quote=0;
					MsgTxt[l].CutOrigin=0;
					MsgTxt[l].line[0]=0;
					free(MsgTxt[l].line);
					MsgTxt[l].line=(char *)malloc(4096);
					memset(MsgTxt[l].line,64,4095);
					MsgTxt[l].line[4095]=0;
				}
				otxt=(LineListType *)malloc(LineListSize*MsgLines);
				for (i=0; i<MsgLines; i++)
				{
					otxt[i].CR=MsgTxt[i].CR;
					otxt[i].Quote=MsgTxt[i].Quote;
					otxt[i].CutOrigin=MsgTxt[i].CutOrigin;
					otxt[i].line=(char *)malloc(strlen(MsgTxt[i].line)+1);
					strcpy(otxt[i].line,MsgTxt[i].line);
				}
				for (i=0; i<ThisGroup.numNames; i++)
				{
					for (j=0; j<MsgLines; j++)
					{
						MsgTxt[j].CR=otxt[j].CR;
						MsgTxt[j].Quote=otxt[j].Quote;
						MsgTxt[j].CutOrigin=otxt[j].CutOrigin;
						free(MsgTxt[j].line);
						MsgTxt[j].line=(char *)malloc(strlen(otxt[j].line)+1);
						strcpy(MsgTxt[j].line,otxt[j].line);
					}
					if (l!=MsgLines)
					{
						strcpy(MsgTxt[l].line,"Cc: ");
						for (j=0; j<ThisGroup.numNames; j++)
							if (j!=i)
							{
								strcat(MsgTxt[l].line,ThisGroup.Names[j]);
								strcat(MsgTxt[l].line,", ");
							}
						MsgTxt[l].line[strlen(MsgTxt[l].line)-2]=0;
					}
					strcpy(NewMsg.WhoTo,ThisGroup.Names[i]);
					NewMsg.DestZone=ThisGroup.Addr[i].Zone;
					NewMsg.DestNet=ThisGroup.Addr[i].Net;
					NewMsg.DestNode=ThisGroup.Addr[i].Node;
					NewMsg.DestPoint=ThisGroup.Addr[i].Point;
					if (ThisGroup.Subj[i][0])
						strcpy(NewMsg.Subj,ThisGroup.Subj[i]);
					else
						strcpy(NewMsg.Subj,origsubj);
					if (ThisGroup.Attrib[i])
						NewMsg.Attribute=ThisGroup.Attrib[i];
					else
						NewMsg.Attribute=origattr;
					MatchAddr(&NewMsg,0);
					AfterTextTemplate(NewMsg);
					savemsg(&NewMsg,0,1);
				}
				for (i=0; i<MsgLines; i++) free(otxt[i].line);
				free(otxt);
				if (TotalMsgs!=oldmsg) curMsg=TotalMsgs-1;
			} else
				Beep();
		}
	}
	ende:
	tmpGroup=0;
	findundel();
	showmsg();
}

void replymsg(int pernm, int dest)
{
	UserAkaType *aka, *oAka;
	Addr4dType *route;
	MsgHdrType NewMsg, old;
	struct re_pattern_buffer regex;
	struct re_registers regs;
	NLentryType ent;
	int i, renr=-1;
	char line[100], *d1;
	aka=NULL;
	route=NULL;
	if (!MsgData.NetMail && !pernm)
	{
		for (aka=Profile.Aka; aka; aka=aka->next)
			if (aka->UserZone==MsgData.RouteZone &&
					aka->UserNet==MsgData.RouteNet &&
					aka->UserNode==MsgData.RouteNode) break;
	} else
		for (aka=Profile.Aka; aka; aka=aka->next)
		{
			for (route=aka->Route; route; route=route->next)
				if (route->Zone==MsgHdr[curMsg].OrigZone) break;
			if (route && route->Zone==MsgHdr[curMsg].OrigZone) break;
		}
	oAka=Aka;
	Aka=aka;
	if (!TotalMsgs || aka==NULL)
	{
		Beep();
		return;
	}
	strcpy(NewMsg.Subj,MsgHdr[curMsg].Subj);
	if (ReplySubject)
	{
		memset(&regex.buffer,0,sizeof(struct re_pattern_buffer));
		re_set_syntax(RE_SYNTAX_POSIX_EGREP);
		if (!re_compile_pattern(_REPLYREG,strlen(_REPLYREG),&regex))
		{
			regs.num_regs=0;
			regs.start=0;
			regs.end=0;
			if (re_match(&regex,NewMsg.Subj,strlen(NewMsg.Subj),0,&regs)>=0)
			{
				if (regs.num_regs)
				{
					renr=atoi(NewMsg.Subj+regs.start[1]+1);
					if (renr==0) renr=1;
				} else
					renr=1;
				strcpy(line,NewMsg.Subj+regs.end[0]);
				for (d1=line; *d1==32; d1++);
				strcpy(NewMsg.Subj,d1);
			}
			free(regs.start);
			free(regs.end);
		}
		free(regex.buffer);
		if (renr==-1)
			strcpy(line,"Re: ");
		else
			sprintf(line,"Re^%u: ",renr+1);
		strcat(line,NewMsg.Subj);
		line[71]=0;
		strcpy(NewMsg.Subj,line);
	}
	wcolon(wHdr,COL_Header);
	mvwaddstr(wHdr,1,0,"By:");
	wclrtoeoln(wHdr);
	mvwaddstr(wHdr,2,0,"To:");
	mvwaddstr(wHdr,3,0,"Re:");
	mvwaddstr(wHdr,4,0,"St:");
	wclrtoeoln(wHdr);
	wcolon(wHdr,COL_InputText);
	NewMsg.OrigZone=Aka->UserZone;
	NewMsg.OrigNet=Aka->UserNet;
	NewMsg.OrigNode=Aka->UserNode;
	NewMsg.OrigPoint=Aka->UserPoint;
	mvwaddstru(wHdr,2,4,dest?MsgHdr[curMsg].WhoTo:MsgHdr[curMsg].WhoFrom);
	if (MsgData.NetMail || pernm)
	{
		if (dest)
		{
			if (nameentry(MsgHdr[curMsg].WhoTo,&ent))
			{
				Beep();
				return;
			}
			NewMsg.DestZone=ent.ad.Zone;
			NewMsg.DestNet=ent.ad.Net;
			NewMsg.DestNode=ent.ad.Node;
			NewMsg.DestPoint=ent.ad.Point;
			MatchAddr(&NewMsg,1);
		} else
		{
			NewMsg.DestZone=MsgHdr[curMsg].OrigZone;
			NewMsg.DestNet=MsgHdr[curMsg].OrigNet;
			NewMsg.DestNode=MsgHdr[curMsg].OrigNode;
			NewMsg.DestPoint=MsgHdr[curMsg].OrigPoint;
		}
	  wprintw(wHdr,", (%u:%u/%u.%u)",NewMsg.DestZone,
	  		NewMsg.DestNet,NewMsg.DestNode,NewMsg.DestPoint);
	} else NewMsg.DestZone=NewMsg.DestNet=NewMsg.DestNode=NewMsg.DestPoint=0;
	wclrtoeoln(wHdr);
	mvwaddstru(wHdr,3,4,NewMsg.Subj);
	wclrtoeoln(wHdr);
	mvwaddstr(wHdr,0,0,"Replying Message");
	if (pernm)
		waddstr(wHdr," per Netmail");
	wclrtoeoln(wHdr);
	NewMsg.Attribute=StandardFlags+((MsgData.NetMail || pernm)?1:0);
	NewMsg.Mother=NewMsg.prevBrother=\
	NewMsg.nextBrother=NewMsg.Child=\
	NewMsg.nextSubject=NewMsg.prevSubject=65535;
	NewMsg.Personal=NewMsg.Deleted=NewMsg.New=NewMsg.Marked=\
	NewMsg.TruncSent=NewMsg.DeleteSent=NewMsg.Direct=\
	NewMsg.Protected=NewMsg.NewPersonal=0;
	if (AskForOrigName)
	{
		for (i=1; i<Aliases; i++)
			if (strcmp(Alias[i],MsgHdr[curMsg].WhoTo)==0) break;
		strcpy(line,i<Aliases?Alias[i]:Profile.UserName);
		strcpy(Alias[0],line);
		if (!inputline(wHdr,wHlp,1,4,35,line,Alias,Aliases,0))
			strcpy(NewMsg.WhoFrom,line);
		else
			goto ende;
	} else
		strcpy(NewMsg.WhoFrom,Profile.UserName);
	mvwaddstru(wHdr,1,4,NewMsg.WhoFrom);
	wprintw(wHdr,", (%u:%u/%u.%u)",NewMsg.OrigZone,NewMsg.OrigNet,
			NewMsg.OrigNode,NewMsg.OrigPoint);
	wclrtoeoln(wHdr);
	strcpy(NewMsg.WhoTo,dest?MsgHdr[curMsg].WhoTo:MsgHdr[curMsg].WhoFrom);
	old=MsgHdr[curMsg];
	if (inputline(wHdr,wHlp,3,4,71,NewMsg.Subj,NULL,0,1)!=-2)
	{
		if (MsgData.NetMail || pernm)
			if (!inputstat(&NewMsg))
				goto ende;
		editorcall(dest?
				(pernm?"netreplydest":"replydest"):
				(pernm?"netreply":"reply"),1,1,pernm,
				&old,&NewMsg,pernm?0:curFld);
	}
	ende:
	Aka=oAka;
	findundel();
	showmsg();
}

int savemsg(MsgHdrType *mh, int reply, int savehdr)
{
	int tend, count, i;
	char line[256], help[80], *d1;
	if (!MsgData.NetMail)
	{
		for (i=0; i<MsgLines; i++)
		{
			if (strncmp(MsgTxt[i].line," * Origin:",10)==0 ||
					strncmp(MsgTxt[i].line,"--- ",4)==0 ||
					strcmp(MsgTxt[i].line,"---")==0)
			{
				free(MsgTxt[i].line);
				memmove(&MsgTxt[i],&MsgTxt[i+1],(MsgLines-i-1)*LineListSize);
				MsgLines--;
				i--;
			}
		}
		for (i=MsgLines-1; i>=0 && MsgTxt[i].line[0]==0; i--)
		{
			free(MsgTxt[i].line);
			MsgTxt=(LineListType *)realloc(MsgTxt,i*sizeof(LineListType));
			MsgLines--;
		}
		lastline("");
		sprintf(line,CUTline,VERSION,Mailer?"BinkleyTerm":"ifcico");
		lastline(line);
		sprintf(help," (%u:%u/%u.%u)",\
				mh->OrigZone,mh->OrigNet,mh->OrigNode,mh->OrigPoint);
		sprintf(line," * Origin: %s",\
				(Origchoose==-1)?
					(Origlines?OrigLine[rand()%Origlines].line:StandardOrig):
					(OrigLine[Origchoose].line));
		if (strlen(help)+strlen(line)>78)
			line[79-strlen(help)]=0;
		strcat(line,help);
		lastline(line);
	}
	if (reply==2)
	{
		for (i=KludgeLines-1; i>=0; i--)
			if (strncasecmp(Kludges[i].line,"SEEN-BY:",8)!=0 && \
					strncasecmp(Kludges[i].line,"\001PATH:",6)!=0)
				firstline(Kludges[i].line);
		for (i=0; i<KludgeLines; i++)
			if (strncasecmp(Kludges[i].line,"SEEN-BY:",8)==0 || \
					strncasecmp(Kludges[i].line,"\001PATH:",6)==0)
				lastline(Kludges[i].line);
	} else
		if (!(mh->Attribute&2048))
		{
			if (reply)
			{
				for (i=0; i<KludgeLines; i++)
					if (strncmp(Kludges[i].line,"\001MSGID:",7)==0) break;
				if (i!=KludgeLines)
				{
					d1=strchr(Kludges[i].line,':');
					strcpy(line,"\001REPLY");
					strcat(line,d1);
					firstline(line);
				}
			}
		}
	MsgTxt[MsgLines-1].CR=1;
	getsizes(Folder[curFld].name,Folder[curFld].path,&count,&tend);
	fseek(mtf,tend*256,SEEK_SET);
	for (i=0, count=0; i<MsgLines; i++)
	{
		if (strlen(MsgTxt[i].line)) fputs(MsgTxt[i].line,mtf);
		if (MsgTxt[i].CR)
		{
			fputc((char)13,mtf);
			count++;
		} else
			if (MsgTxt[i].line[strlen(MsgTxt[i].line)-1]!=32)
			{
				fputc((char)32,mtf);
				count++;
			}
		count+=strlen(MsgTxt[i].line);
	}
	fputc((char)0,mtf);
	count++;
	for (; count%256; count++) fputc((char)0,mtf);
	fflush(mtf);
	mh->StartRec=tend;
	mh->NumRecs=count/256;
	if (savehdr)
	{
		fseek(mhf,TotalMsgs*MsgHdrSize,SEEK_SET);
		fwrite(mh,MsgHdrSize,1,mhf);
		fflush(mhf);
		if (savehdr==1)
		{
			TotalMsgs++;
			MsgHdr=(MsgHdrType *)realloc(MsgHdr,MsgHdrSize*TotalMsgs);
			MsgHdr[TotalMsgs-1]=*mh;
		}
	}
	return 1;
}

void cycleAka()
{
	sigset_t wait;
	Aka=Aka->next;
	if (!Aka)
		Aka=Profile.Aka;
	wcolon(wTop,COL_StatusLine);
	werase(wTop);
	mvwprintw(wTop,0,1,"%s(%s)@%u:%u/%u.%u(%s)",\
						Profile.UserName,Profile.UserLogin,\
						Aka->UserZone,Aka->UserNet,Aka->UserNode,Aka->UserPoint,\
						Aka->NetName);
	wcoloff(wTop);
	wrefresh(wTop);
	alarm(0);
	sigpending(&wait);
	if (!sigismember(&wait,SIGALRM))
		raise(SIGALRM);
	if (!MsgData.NetMail)
	{
		MsgData.RouteZone=Aka->UserZone;
		MsgData.RouteNet=Aka->UserNet;
		MsgData.RouteNode=Aka->UserNode;
		savemsgdata();
		showhdr();
		Beep();
	}
}

void lastline(char *s)
{
	MsgTxt=(LineListType *)realloc(MsgTxt,(MsgLines+1)*sizeof(LineListType));
	MsgTxt[MsgLines].line=(char *)malloc(strlen(s)+1);
	strcpy(MsgTxt[MsgLines].line,s);
	MsgTxt[MsgLines].Quote=MsgTxt[MsgLines].CutOrigin=0;
	MsgTxt[MsgLines].CR=MsgTxt[MsgLines-1].CR=1;
	MsgLines++;
}

void firstline(char *s)
{
	MsgTxt=(LineListType *)realloc(MsgTxt,(MsgLines+1)*sizeof(LineListType));
	memmove(&MsgTxt[1],&MsgTxt[0],sizeof(LineListType)*MsgLines);
	MsgTxt[0].line=(char *)malloc(strlen(s)+1);
	strcpy(MsgTxt[0].line,s);
	MsgTxt[0].Quote=MsgTxt[0].CutOrigin=0;
	MsgTxt[0].CR=1;
	MsgLines++;
}

void reinit()
{
	sigset_t wait;
	initscr();
	if (has_colors())
	{
		start_color();
		COLON=1;
	} else
		COLON=0;
	initFEddiColors();
	cbreak();
	noecho();
	WordWrap=COLS-8;
	meta(wHdr,TRUE);
	meta(wTxt,TRUE);
	meta(stdscr,TRUE);
	wcolon(stdscr,COL_NormalText);
	erase();
	refresh();
	wcolon(wTop,COL_StatusLine);
	werase(wTop);
	mvwprintw(wTop,0,1,"%s(%s)@%u:%u/%u.%u(%s)",\
						Profile.UserName,Profile.UserLogin,\
						Aka->UserZone,Aka->UserNet,Aka->UserNode,Aka->UserPoint,\
						Aka->NetName);
	wcoloff(wTop);
	wrefresh(wTop);
	sigpending(&wait);
	if (!sigismember(&wait,SIGALRM))
		raise(SIGALRM);
	initnames();
	initgroups();
	initutils();
	initsig();
	initmenu();
}

void showFld(WINDOW *win, int f, char *form1, char *form2, int move)
{
	int y, yy, Kategorie=0;
	yy=(LINES-4)/2-f-1;
	for (y=0; yy<0; yy++, y++)
		if (Folder[y].num==-1)
			Kategorie=Folder[y].marked;
	for (y=0; y<yy; y++)
		mvwprintw(win,1+y,1,form2,32,"");
	for (; y<LINES-4; y++)
	{
		mvwprintw(win,1+y,1,form2,32,"");
		if (f-(LINES-4)/2+1+y<maxFld)
		{
			if (f-(LINES-4)/2+1+y==f)
			{
				if (Folder[f-(LINES-4)/2+1+y].path)
					wcolon(win,COL_ImportAreaHigh);
				else
					wcolon(win,COL_MenuHigh);
			} else
				if (Folder[f-(LINES-4)/2+1+y].path)
					wcolon(win,COL_ImportArea);
			if (Folder[f-(LINES-4)/2+1+y].num>=0)
				mvwprintw(win,1+y,1,form1,\
						Folder[f-(LINES-4)/2+1+y].Marked?'M':32,
						Folder[f-(LINES-4)/2+1+y].Personal?
								(Folder[f-(LINES-4)/2+1+y].Personal<10?
								Folder[f-(LINES-4)/2+1+y].Personal+'0':'P'):32,
						Folder[f-(LINES-4)/2+1+y].unread?'*':32,
						Folder[f-(LINES-4)/2+1+y].num,
						(Kategorie || Folder[f-(LINES-4)/2+1+y].marked)?'+':32,
						Folder[f-(LINES-4)/2+1+y].name);
			else
				mvwprintw(win,1+y,1,form2,\
						Folder[f-(LINES-4)/2+1+y].marked?'+':32,
						Folder[f-(LINES-4)/2+1+y].name);
			if (Folder[f-(LINES-4)/2+1+y].num==-1)
				Kategorie=Folder[f-(LINES-4)/2+1+y].marked;
			if (f-(LINES-4)/2+1+y==f || Folder[f-(LINES-4)/2+1+y].path)
				wcolon(win,COL_Menu);
		}
	}
	if (!move)
	{
		wmove(win,LINES-3,2);
		for (y=0; y<widFld+5; y++) waddch(win,ACS_HLINE);
	}
	wrefresh(win);
}

int sortfld(const struct dirent * const *e1, const struct dirent * const *e2)
{
	return (strcmp((*e1)->d_name,(*e2)->d_name));
}

int selectfld(const struct dirent *e)
{
	int i;
	if (e->d_name[0]!='+') return 0;
	for (i=0; i<maxFld; i++)
		if (strcmp(Folder[i].name,e->d_name+1)==0) return 0;
	return 1;
}

int rescanfld()
{
	struct dirent **ents;
	int new, i;
	MsgDataType md;
	new=scandir(BasePath,&ents,selectfld,sortfld);
	if (new>0)
	{
		Folder=(FolderType *)realloc(Folder,FolderSize*(maxFld+new+1));
		strcpy(Folder[maxFld].name,"-Rescan-Result:");
		for (i=0; i<new; i++)
		{
			memset(&(Folder[maxFld+1+i]),0,FolderSize);
			strncpy(Folder[maxFld+1+i].name,ents[i]->d_name+1,39);
			Folder[maxFld+1+i].name[39]=0;
		}
		maxFld+=new+1;
	}
	for (i=0, widFld=0; i<maxFld; i++)
	{
		if (Folder[i].name[0]!='-')
		{
			md=getmsgdata(Folder[i].name,Folder[i].path);
			Folder[i].unread=(md.New!=0);
			Folder[i].Personal=md.NewPersonal;
			Folder[i].Marked=md.Marked;
		}
		Folder[i].marked=0;
		if (strlen(Folder[i].name)>widFld)
			widFld=strlen(Folder[i].name);
	}
	freedirentries(&ents,new);
	return new;
}

void renumberfld()
{
	int i, n;
	for (i=0, widFld=0, n=0; i<maxFld; i++)
	{
		Folder[i].num=(Folder[i].name[0]!='-')?n++:-1;
		if (strlen(Folder[i].name)>widFld)
			widFld=strlen(Folder[i].name);
	}
}

void movefld(int m, int f)
{
	FolderType buf;
	if (m==curFld)
		curFld=f;
	else
		if (f==curFld)
			curFld=m;
	buf=Folder[m];
	memmove(&(Folder[m]),&(Folder[m+1]),\
			FolderSize*(maxFld-m-1));
	memmove(&(Folder[f+1]),&(Folder[f]),\
			FolderSize*(maxFld-f));
	Folder[f]=buf;
	renumberfld();
}

int changeFolder()
{
	WINDOW *wFld=NULL, *inp=NULL;
	int fld, in=0, moveit=0, i, a=0, ende=0, j, m;
	char f1[20],f2[20], file[PATH_MAX], area[40], dummy[40];
	FolderType buf;
	fld=curFld;
	area[0]=0;
	sigprocmask(SIG_BLOCK,&allmask,NULL);
	if ((wFld=openask(LINES-2,12+widFld,1,COLS/2-6-widFld/2,"Change Folder",
			COL_Menu))!=NULL)
	{
		werase(wHlp);
		mvwaddstr(wHlp,0,1,bhelp_changefld);
		wrefresh(wHlp);
		Folder[curFld].unread=(MsgData.New!=0);
		Folder[curFld].Personal=MsgData.NewPersonal;
		Folder[curFld].Marked=MsgData.Marked;
		sprintf(f1," %%c%%c%%c %%3u%%c%%-%us ",widFld);
		sprintf(f2,"        %%c%%-%us ",widFld);
		showFld(wFld,fld,f1,f2,0);
		while (!ende)
		{
			sigprocmask(SIG_UNBLOCK,&allmask,NULL);
			if (show_time_now) showtime();
			in=getchn();
			if (show_time_now) showtime();
			sigprocmask(SIG_BLOCK,&allmask,NULL);
			switch (in)
			{
				case 9:
					if (Folder[fld].num!=-1)
					{
						folderinfo(fld);
						touchwin(wFld);
						wrefresh(wFld);
					} else
						Beep();
					break;
				case 32:
					for (i=fld-1; i>=0 && Folder[i].num!=-1; i--);
					if ((j=i)>0)
					{
						if (Folder[i].marked)
						{
							Folder[i].marked=0;
							for (i++; i<maxFld && Folder[i].num!=-1; i++)
								Folder[i].marked=1;
						}
						toggle(Folder[fld].marked);
						for (i=j+1, m=1; i<maxFld && Folder[i].num!=-1; i++)
							if (!Folder[i].marked) m=0;
						if (m)
						{
							Folder[j].marked=1;
							for (i=j+1; i<maxFld && Folder[i].num!=-1; i++)
								Folder[i].marked=0;
						}
					} else
						toggle(Folder[fld].marked);
					if (Folder[fld].num==-1 && !Folder[fld].marked)
						for (i=fld+1; i<maxFld && Folder[i].num!=-1; i++)
							Folder[i].marked=0;
					showFld(wFld,fld,f1,f2,moveit);
					break;
				case 25:
					if (!moveit)
					{
						a=fld=0;
						area[0]=0;
						showFld(wFld,fld,f1,f2,moveit);
						mvwaddstr(wFld,LINES-3,2,Folder[fld].name);
						wrefresh(wFld);
					}
					break;
				case 127:
					if (!moveit)
					{
						a--;
						area[a]=0;
						goto matchit;
					}
					break;
				case '.':
				case '_':
				case '-':
				case 48 ... 57:
				case 97 ... 122:
					if (!moveit)
					{
						area[a++]=tolower(in);
						area[a]=0;
matchit:
						for (i=0; i<maxFld && strncasecmp(Folder[i].name,area,a)!=0; i++);
						if (i!=maxFld)
						{
							fldlm(area,dummy);
							fld=i;
							showFld(wFld,fld,f1,f2,moveit);
						} else
						{
							Beep();
							a--;
							area[a]=0;
							showFld(wFld,fld,f1,f2,moveit);
						}
						mvwaddstr(wFld,LINES-3,2,Folder[fld].name);
						mvwaddstr(wFld,LINES-3,2,area);
						wrefresh(wFld);
					}
					break;
				case 0xa:
					if (moveit)
					{
						wmove(wFld,LINES-3,2);
						for (in=0; in<widFld+5; in++) waddch(wFld,ACS_HLINE);
						mvwaddstr(wFld,LINES-3,2,area);
						wrefresh(wFld);
						in=moveit=0;
					} else
						if (Folder[fld].num==-1)
						{
							in=0;
							if ((inp=openask(3,42,LINES/2+1,COLS/2-21,"Change Seperator",\
									COL_Menu))!=NULL)
							{
								buf=Folder[fld];
								if (!inputline(inp,wHlp,1,1,39,buf.name,NULL,0,0))
								{
									if (buf.name[0]=='-') Folder[fld]=buf;
									renumberfld();
									sprintf(f1," %%c%%c%%c %%3u%%c%%-%us ",widFld);
									sprintf(f2,"        %%c%%-%us ",widFld);
									delwin(wFld);
									if ((wFld=openask(LINES-2,12+widFld,1,COLS/2-6-widFld/2,\
											"Change Folder",COL_Menu))==NULL)
										raise (SIGABRT);
								}
								werase(wHlp);
								mvwaddstr(wHlp,0,1,bhelp_changefld);
								wrefresh(wHlp);
								delwin(inp);
							}
							touchwin(wTxt);
							touchwin(wHdr);
							touchwin(wFld);
							wrefresh(wTxt);
							wrefresh(wHdr);
							a=0;
							area[0]=0;
							showFld(wFld,fld,f1,f2,moveit);
						} else
							ende=2;
					break;
				case 0x1b:
					switch ((in=getchn()))
					{
						case 'h': showFolderHelp(); touchwin(wFld); wrefresh(wFld); break;
						case 'i':
							fld=importFolders(fld);
							touchwin(wTxt);
							touchwin(wHdr);
							wrefresh(wTxt);
							wrefresh(wHdr);
							werase(wHlp);
							mvwaddstr(wHlp,0,1,bhelp_changefld);
							wrefresh(wHlp);
							sprintf(f1," %%c%%c%%c %%3u%%c%%-%us ",widFld);
							sprintf(f2,"        %%c%%-%us ",widFld);
							delwin(wFld);
							if ((wFld=openask(LINES-2,12+widFld,1,COLS/2-6-widFld/2,\
									"Change Folder",COL_Menu))==NULL)
								raise (SIGABRT);
							showFld(wFld,fld,f1,f2,moveit);
							break;
						case 'm':
							if (fld>0)
							{
								moveit=fld;
								mvwprintw(wFld,LINES-3,2,"Move  %s",Folder[fld].name);
								wrefresh(wFld);
								a=0;
								area[0]=0;
							}
							else
								Beep();
							break;
						case 0x1b:
							ende=1;
							break;
						case 0x5b:
							switch (getchn())
							{
								case 0x41: if (fld>0)
													{
														if (moveit)
														{
															if (fld>1)
															{
																fld--;
																movefld(moveit,fld);
																moveit=fld;
															} else Beep();
														} else
															fld--;
														a=0;
														area[0]=0;
														showFld(wFld,fld,f1,f2,moveit);
													} else Beep();
													break;
								case 0x42: if (fld<maxFld-1)
													{
														fld++;
														if (moveit)
														{
															movefld(moveit,fld);
															moveit=fld;
														}
														a=0;
														area[0]=0;
														showFld(wFld,fld,f1,f2,moveit);
													} else Beep();
													break;
								case 0x43:
									if (!moveit && Folder[fld].num!=-1)
										ende=3;
									else
										Beep();
									break;
								case 0x35: getch();
													if (fld==0 || (moveit && fld==1)) Beep();
													else
													{
														if (fld>0) fld--;
														for (; fld>0; fld--)
															if (Folder[fld].num!=-1) break;
														for (; fld>0; fld--)
															if (Folder[fld].num==-1) break;
														for (; fld<maxFld; fld++)
															if (Folder[fld].num!=-1) break;
														if (moveit)
														{
															if (fld<1) fld=1;
															movefld(moveit,fld);
															moveit=fld;
														} else
															if (fld<0) fld=0;
														a=0;
														area[0]=0;
														showFld(wFld,fld,f1,f2,moveit);
													} break;
								case 0x36: getch();
													if (fld==maxFld-1) Beep();
													else
													{
														for (; fld<maxFld; fld++)
															if (Folder[fld].num==-1) break;
														for (; fld<maxFld; fld++)
															if (Folder[fld].num!=-1) break;
														if (fld==maxFld) fld--;
														if (moveit)
														{
															movefld(moveit,fld);
															moveit=fld;
														}
														a=0;
														area[0]=0;
														showFld(wFld,fld,f1,f2,moveit);
													} break;
								case 0x31: getch();
													if (moveit)
													{
														movefld(moveit,1);
														fld=moveit=1;
													} else
														fld=0;
													a=0;
													area[0]=0;
													showFld(wFld,fld,f1,f2,moveit);
													break;
								case 0x34: getch();
													fld=maxFld-1;
													if (moveit)
													{
														movefld(moveit,fld);
														moveit=fld;
													}
													a=0;
													area[0]=0;
													showFld(wFld,fld,f1,f2,moveit);
													break;
								case 0x32:
									getch();
									if (fld>0)
									{
										memset(&buf,0,FolderSize);
										if ((inp=openask(3,42,LINES/2+1,COLS/2-21,"New Folder",\
												COL_Menu))!=NULL)
										{
											if (!inputline(inp,wHlp,1,1,39,buf.name,NULL,0,0))
											{
												if (buf.name[0]!='-') upperstr(buf.name);
												maxFld++;
												Folder=(FolderType *)realloc(Folder,FolderSize*maxFld);
												memmove(&(Folder[fld+1]),&(Folder[fld]),\
														FolderSize*(maxFld-fld-1));
												Folder[fld]=buf;
												renumberfld();
												if (Folder[fld].name[0]!='-')
													newarea(Folder[fld].name,Aka);
												if (fld<=curFld) curFld++;
												sprintf(f1," %%c%%c%%c %%3u%%c%%-%us ",widFld);
												sprintf(f2,"        %%c%%-%us ",widFld);
												delwin(wFld);
												if ((wFld=openask(LINES-2,12+widFld,1,COLS/2-6-widFld/2,\
														"Change Folder",COL_Menu))==NULL)
													raise (SIGABRT);
											}
											werase(wHlp);
											mvwaddstr(wHlp,0,1,bhelp_changefld);
											wrefresh(wHlp);
											delwin(inp);
										}
										touchwin(wTxt);
										touchwin(wHdr);
										touchwin(wFld);
										wrefresh(wTxt);
										wrefresh(wHdr);
										a=0;
										area[0]=0;
										showFld(wFld,fld,f1,f2,moveit);
									} else Beep();
									break;
								case 0x33:
									getch();
									if (fld>0)
									{
										if (Folder[fld].name[0]!='-')
										{
											if ((inp=openask(3,16,LINES/2+1,COLS/2-8,
													Folder[fld].path?"Del Area ?":"Kill Area ?",
													COL_MenuHigh))!=NULL)
											{
												mvwaddstr(inp,1,1,"Y|y to confirm");
												wrefresh(inp);
												in=getchn();
												if (in==0x1b) getch();
												delwin(inp);
												touchwin(wTxt);
												touchwin(wFld);
												wrefresh(wTxt);
												wrefresh(wFld);
												if (in!='y' && in!='Y')
												{
													in=0;
													break;
												}
											}
											if (fld==curFld) closearea();
											if (!Folder[fld].path)
											{
												sprintf(file,"rm -r -f \"%s+%s\" >&/dev/null",\
														BasePath,Folder[fld].name);
												system(file);
											} else
												free(Folder[fld].path);
										}
										memmove(&(Folder[fld]),&(Folder[fld+1]),\
												FolderSize*(maxFld-fld-1));
										maxFld--;
										Folder=(FolderType *)realloc(Folder,FolderSize*maxFld);
										renumberfld();
										if (fld==curFld)
										{
											if (curFld==maxFld) curFld--;
											for (; Folder[curFld].num==-1; curFld--);
											TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
											curMsg=MsgData.LastRead;
											loadmsghdr(&MsgHdr);
											loadalias(Folder[curFld].name);
											loadorig(Folder[curFld].name);
										}
										if (fld<curFld) curFld--;
										if (fld==maxFld) fld--;
										a=0;
										area[0]=0;
										showFld(wFld,fld,f1,f2,moveit);
									} else Beep();
									break;
							}
							break;
					}
					break;
			}
		}
		if ((ende==2 || ende==3) && curFld!=fld)
		{
			savemsghdr(&MsgHdr);
			curFld=fld;
			MsgData.LastRead=curMsg;
			TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
			curMsg=MsgData.LastRead;
			loadmsghdr(&MsgHdr);
			loadalias(Folder[curFld].name);
			loadorig(Folder[curFld].name);
			Folder[curFld].unread=(MsgData.New!=0);
			findundel();
			chooseAka();
		}
		delwin(wFld);
		initmenu();
		showmsg();
	}
	if (ende==1 || ende==2) return -1;
	return 1;
}

void replyMsg()
{
	replymsg(0,0);
}

void netreplyMsg()
{
	replymsg(1,0);
}

void replyDest()
{
	if (!MsgData.NetMail)
		replymsg(0,1);
	else
		Beep();
}

void netreplyDest()
{
	if (!MsgData.NetMail)
		replymsg(1,1);
	else
		Beep();
}

void quitFEddi()
{
	ende=1;
}

void listmsgs(WINDOW *win, int msg, MsgHdrType *amh, int cutNames,
		int cutSubject, int mode)
{
	int y, yy;
	char a[36],b[36],c[72],d[20];
	yy=(LINES-9)/2-msg-1;
	if (yy<0) yy=0;
	wcolon(win,COL_Menu);
	werase(win);
	wcolon(win,COL_StatusLine);
	wmove(win,0,0);
	waddstr(win,"DMPN     # From");
	for (y=cutNames-3; y; y--) waddch(win, 32);
	waddstr(win,mode?"Subject":"To     ");
	for (y=cutNames-6; y; y--) waddch(win, 32);
	waddstr(win,mode?"       ":"Subject");
	for (y=cutSubject-6; y; y--) waddch(win, 32);
	waddstr(win,"Date  ");
	wcolon(win,COL_Menu);
	for (y=yy; y<LINES-9; y++)
	{
		if (msg-(LINES-9)/2+y<TotalMsgs)
		{
			if ((LINES-9)/2==y)
			{
				if (amh[msg-(LINES-9)/2+y].Personal)
					wcolon(win,COL_PrivateMsgListHigh);
				else
					wcolon(win,COL_MenuHigh);
			} else
				if (amh[msg-(LINES-9)/2+y].Personal)
					wcolon(win,COL_PrivateMsgList);
			strcpy(a,amh[msg-(LINES-9)/2+y].WhoFrom);
			a[cutNames]=0;
			strcpy(b,amh[msg-(LINES-9)/2+y].WhoTo);
			b[cutNames]=0;
			strcpy(c,amh[msg-(LINES-9)/2+y].Subj);
			if (ListMode)
				c[cutNames+(cutSubject>71?71:cutSubject)+1]=0;
			else
				c[(cutSubject>71?71:cutSubject)]=0;
			strcpy(d,amh[msg-(LINES-9)/2+y].DateTime);
			d[6]=0;
			mvwprintw(win,y+1,0,"%c%c%c%c%c%5u",
													amh[msg-(LINES-9)/2+y].Deleted?'D':32,
													amh[msg-(LINES-9)/2+y].Marked?'M':32,
													amh[msg-(LINES-9)/2+y].Protected?'P':32,
													amh[msg-(LINES-9)/2+y].New?'N':32,
													(amh[msg-(LINES-9)/2+y].Mother==65535 &&
													 amh[msg-(LINES-9)/2+y].nextBrother==65535 &&
													 amh[msg-(LINES-9)/2+y].prevBrother==65535 &&
													 amh[msg-(LINES-9)/2+y].Child!=65535)?'>':32,
													1+msg-(LINES-9)/2+y);
			wclrtoeoln(win);
			mvwaddstru(win,y+1,11,a);
			if (ListMode)
				mvwaddstru(win,y+1,12+cutNames,c);
			else
			{
				mvwaddstru(win,y+1,12+cutNames,b);
				mvwaddstru(win,y+1,13+2*cutNames,c);
			}
			mvwaddstru(win,y+1,14+2*cutNames+cutSubject,d);
			if ((LINES-9)/2==y || amh[msg-(LINES-9)/2+y].Personal)
				wcolon(win,COL_Menu);
		}
	}
	wrefresh(win);
	y=curMsg;
	curMsg=msg;
	showhdr();
	curMsg=y;
}

int listMsgs()
{
	int msg, in=0, i, cutNames, cutSubject, ende=0;
	sigprocmask(SIG_BLOCK,&allmask,NULL);
	if (!TotalMsgs || COLS<80)
	{
		Beep();
		return -1;
	}
	cutNames=COLS/5+4;
	if (cutNames>35) cutNames=35;
	cutSubject=COLS-2*cutNames-20;
	werase(wHlp);
	wcolon(wHlp,COL_StatusLine);
	mvwaddstr(wHlp,0,1,bhelp_changemsg);
	wrefresh(wHlp);
	msg=curMsg;
	listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
	while (!ende)
	{
		sigprocmask(SIG_UNBLOCK,&allmask,NULL);
		if (show_time_now) showtime();
		in=getchn();
		if (show_time_now) showtime();
		sigprocmask(SIG_BLOCK,&allmask,NULL);
		if (in==0x1b)
		{
			switch ((in=getchn()))
			{
				case 'h':
					showMessageHelp();
					break;
				case 's':
					ListMode=1-ListMode;
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case 0x1b:
					ende=1;
					break;
				case 0x5b:
					switch (getchn())
					{
						case 0x41: if (msg>0)
											{
												msg--;
												listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											} else Beep();
											break;
						case 0x42: if (msg<TotalMsgs-1)
											{
												msg++;
												listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											} else Beep();
											break;
						case 0x43:
							ende=2;
							break;
						case 0x44:
							ende=3;
							break;
						case 0x35: getch();
											if (msg==0) Beep();
											else
											{
												msg=msg-(LINES-9)/2;
												if (msg<0) msg=0;
												listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											} break;
						case 0x36: getch();
											if (msg==TotalMsgs-1) Beep();
											else
											{
												msg=msg+(LINES-9)/2;
												if (msg>=TotalMsgs) msg=TotalMsgs-1;
												listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											} break;
						case 0x31: getch();
											if (SkipDeleted)
											{
												i=curMsg;
												curMsg=0;
												findundel();
												msg=curMsg;
												curMsg=i;
											} else
												msg=0;
											listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											break;
						case 0x34: getch();
											if (SkipDeleted)
											{
												i=curMsg;
												curMsg=TotalMsgs-1;
												findundel();
												msg=curMsg;
												curMsg=i;
											} else
												msg=TotalMsgs-1;
											listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
											break;
						case 0x33:
							getch();
							if (!MsgHdr[msg].Deleted)
							{
								MsgHdr[msg].Deleted=1;
								if (MsgHdr[msg].New)
									MsgData.New--;
								if (MsgHdr[msg].NewPersonal)
									MsgData.NewPersonal--;
								if (MsgHdr[msg].Marked)
									MsgData.Marked--;
								MsgData.Deleted++;
							}
							else
							{
								MsgHdr[msg].Deleted=0;
								if (MsgHdr[msg].New)
									MsgData.New++;
								if (MsgHdr[msg].NewPersonal)
									MsgData.NewPersonal++;
								if (MsgHdr[msg].Marked)
									MsgData.Marked++;
								MsgData.Deleted--;
							}
							if (msg<TotalMsgs-1) msg++;
							listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
							break;
					}
					break;
			}
		} else
			switch ((char)in)
			{
				case 10:
					ende=2;
					break;
				case 32:
					toggle(MsgHdr[msg].Marked);
					if (!MsgHdr[msg].Deleted)
					{
						if (MsgHdr[msg].Marked)
							MsgData.Marked++;
						else
							MsgData.Marked--;
					}
					if (msg<TotalMsgs-1) msg++;
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case '5':
					toggle(MsgHdr[msg].Marked);
					if (!MsgHdr[msg].Deleted)
					{
						if (MsgHdr[msg].Marked)
							MsgData.Marked++;
						else
							MsgData.Marked--;
					}
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case '0':
					toggle(MsgHdr[msg].Protected);
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case 's':
					for (i=0; i<TotalMsgs; i++) MsgHdr[i].Marked=1;
					MsgData.Marked=TotalMsgs-MsgData.Deleted;
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case 'c':
					for (i=0; i<TotalMsgs; i++) MsgHdr[i].Marked=0;
					MsgData.Marked=0;
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case '*':
					for (i=0; i<TotalMsgs; i++)
					{
						toggle(MsgHdr[i].Marked);
						if (!MsgHdr[i].Deleted)
						{
							if (MsgHdr[i].Marked)
								MsgData.Marked++;
							else
								MsgData.Marked--;
						}
					}
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case 'N':
					for (i=0; i<TotalMsgs; i++) MsgHdr[i].New=MsgHdr[i].NewPersonal=0;
					MsgData.New=MsgData.NewPersonal=0;
					listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					break;
				case '7':
					for (i=msg-1; !MsgHdr[i].Marked && i>=0; i--);
					if (i>=0)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '9':
					for (i=msg+1; !MsgHdr[i].Marked && i<TotalMsgs; i++);
					if (i!=TotalMsgs)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '1':
					for (i=msg-1; !MsgHdr[i].Personal && i>=0; i--);
					if (i>=0)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '3':
					for (i=msg+1; !MsgHdr[i].Personal && i<TotalMsgs; i++);
					if (i!=TotalMsgs)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '-':
					for (i=msg-1; !MsgHdr[i].Protected && i>=0; i--);
					if (i>=0)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '+':
					for (i=msg+1; !MsgHdr[i].Protected && i<TotalMsgs; i++);
					if (i!=TotalMsgs)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '8':
					for (i=msg-1; i>=0 &&
							!(MsgHdr[i].Mother==65535 &&
							MsgHdr[i].nextBrother==65535 &&
							MsgHdr[i].prevBrother==65535 &&
							MsgHdr[i].Child!=65535); i--);
					if (i>=0)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
				case '2':
					for (i=msg+1; i<TotalMsgs &&
							!(MsgHdr[i].Mother==65535 &&
							MsgHdr[i].nextBrother==65535 &&
							MsgHdr[i].prevBrother==65535 &&
							MsgHdr[i].Child!=65535); i++);
					if (i!=TotalMsgs)
					{
						msg=i;
						listmsgs(wTxt,msg,MsgHdr,cutNames,cutSubject,ListMode);
					} else
						Beep();
					break;
			}
	}
	if (ende>=2)
	{
		curMsg=msg;
		if (MsgHdr[msg].Deleted && ende==2)
		{
			MsgHdr[msg].Deleted=0;
			if (MsgHdr[msg].New)
				MsgData.New++;
			if (MsgHdr[msg].NewPersonal)
				MsgData.NewPersonal++;
			if (MsgHdr[msg].Marked)
				MsgData.Marked++;
			MsgData.Deleted--;
		}
		findundel();
	}
	pseudoEmpty=0;
	showmsg();
	initmenu();
	if (ende==1 || ende==2) return -1;
	return 0;
}

void showKludges()
{
	if (DispKludgeLines==1)
	{
		scrolltext(DispKludges,DispKludgeLines,"Kludge Line",0);
		touchwin(wTxt);
		wrefresh(wTxt);
	}
	else
		if (Kludges)
		{
			scrolltext(DispKludges,DispKludgeLines,"Kludge Lines",0);
			touchwin(wTxt);
			wrefresh(wTxt);
		}
}

void findundel()
{
	int i;
	if (TotalMsgs)
	{
		for (i=curMsg; MsgHdr[i].Deleted && i<TotalMsgs; i++);
		if (i==TotalMsgs)
			for (i=curMsg-1; MsgHdr[i].Deleted && i>=0; i--);
		if (i>=0 && i<TotalMsgs)
		{
			curMsg=i;
			pseudoEmpty=0;
		} else
			pseudoEmpty=1;
	}
}

void folderInfo()
{
	folderinfo(curFld);
}

void folderinfo(int fld)
{
	WINDOW *win=NULL;
	char line[80];
	int i;
	MsgDataType md;
	dword tm, tr;
	if (fld==curFld)
	{
		md=MsgData;
		tm=TotalMsgs;
		tr=TotalRecs;
	} else
	{
		md=getmsgdata(Folder[fld].name,Folder[fld].path);
		getsizes(Folder[fld].name,Folder[fld].path,&tm,&tr);
		loadorig(Folder[fld].name);
	}
	if (Origchoose!=-1)
	{
		strcpy(line,BaseOrig?"BASE--> ":"AREA--> ");
		strcat(line,OrigLine[Origchoose].line);
	} else
		switch (Origlines)
		{
			case 0:
				strcpy(line,StandardOrig);
				break;
			case 1:
				strcpy(line,BaseOrig?"BASE--> ":"AREA--> ");
				strcat(line,OrigLine[0].line);
				break;
			default:
				sprintf(line,BaseOrig?"BASE--> RANDOM[%u]":
						"AREA--> RANDOM[%u]",Origlines);
				break;
		}
	i=strlen(line);
	if (i<50) i=50;
	if ((win=openask(17,i+4,7,COLS/2-2-i/2,"Folder Info",COL_MenuHigh))!=NULL)
	{
		mvwprintw(win,2,2,"Folder Name: %s",Folder[fld].name);
		mvwprintw(win,3,2,"Owner      : %s",md.Owner);
		mvwprintw(win,4,2,"MsgBase    : %s",
				Folder[fld].path?Folder[fld].path:BasePath);
		mvwprintw(win,5,2,"TotalMsgs  : %u",tm);
		mvwprintw(win,6,2,"NewPersonal: %u",md.NewPersonal);
		mvwprintw(win,7,2,"New        : %u",md.New);
		mvwprintw(win,8,2,"Marked     : %u",md.Marked);
		mvwprintw(win,9,2,"Deleted    : %u",md.Deleted);
		mvwprintw(win,10,2,"Linked     : %s",md.Linked?"Yes":"No");
		mvwprintw(win,11,2,"Size       : %u kB",\
				(tm*MsgHdrSize+tr*256+sizeof(MsgDataType))/1024+1);
		mvwprintw(win,12,2,"Charset    : %s",CHRSETS[md.CharSet][0]);
		if (!md.NetMail)
		{
			mvwaddstr(win,13,2,"Originline :");
			mvwaddstr(win,14,2,line);
		}
		mvwaddstr(win,16,i-11,"<CR> to leave");
		wrefresh(win);
		while (getchn()!=0xa);
		delwin(win);
		touchwin(wTxt);
		wrefresh(wTxt);
	}
	if (fld!=curFld)
		loadorig(Folder[curFld].name);
}

void toggleLink()
{
	if (TotalMsgs || !pseudoEmpty)
	{
		toggle(SimpleLink);
		mvwaddstr(wHlp,0,COLS-8,SimpleLink?"1D-link":"2D-link");
		wrefresh(wHlp);
		showmsg();
	}
}

void toggleClearMarks()
{
	toggle(ClearMarks);
	Beep();
}

void nextSubject()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].nextSubject!=65535)
	{
		for (i=MsgHdr[curMsg].nextSubject;\
				MsgHdr[i].Deleted && MsgHdr[i].nextSubject!=65535;\
				i=MsgHdr[i].nextSubject);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void prevSubject()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].prevSubject!=65535)
	{
		for (i=MsgHdr[curMsg].prevSubject;\
				MsgHdr[i].Deleted && MsgHdr[i].prevSubject!=65535;\
				i=MsgHdr[i].prevSubject);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void Mother()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].Mother!=65535)
	{
		for (i=MsgHdr[curMsg].Mother;\
				MsgHdr[i].Deleted && MsgHdr[i].Mother!=65535;\
				i=MsgHdr[i].Mother);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void Child()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].Child!=65535)
	{
		for (i=MsgHdr[curMsg].Child;\
				MsgHdr[i].Deleted && MsgHdr[i].Child!=65535;\
				i=MsgHdr[i].Child);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void nextBrother()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].nextBrother!=65535)
	{
		for (i=MsgHdr[curMsg].nextBrother;\
				MsgHdr[i].Deleted && MsgHdr[i].nextBrother!=65535;\
				i=MsgHdr[i].nextBrother);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void prevBrother()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && MsgHdr[curMsg].prevBrother!=65535)
	{
		for (i=MsgHdr[curMsg].prevBrother;\
				MsgHdr[i].Deleted && MsgHdr[i].prevBrother!=65535;\
				i=MsgHdr[i].prevBrother);
		if (!MsgHdr[i].Deleted)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void drawtree(char **tree, word *treenum, word n, int cm, int mode, int y)
{
	char line[4096];
	int x, sl;
	sl=(LINES-9)/2-cm;
	if (sl<0) sl=0;
	wcolon(wTxt,COL_Menu);
	werase(wTxt);
	wmove(wTxt,0,0);
	for (x=0; x<COLS; x++) waddch(wTxt,ACS_HLINE);
	mvwprintw(wTxt,0,COLS/2-6,"2D-Linktree");
	for (x=sl; x<LINES-9; x++)
	{
		if (cm-(LINES-9)/2+x==n) break;
		if ((LINES-9)/2==x)
			wcolon(wTxt,COL_MenuHigh);
		switch (mode)
		{
			case 0:
				sprintf(line,"%s%u",tree[cm-(LINES-9)/2+x],
						treenum[cm-(LINES-9)/2+x]+1);
				break;
			case 1:
				sprintf(line,"%s%s",tree[cm-(LINES-9)/2+x],
						MsgHdr[treenum[cm-(LINES-9)/2+x]].WhoFrom);
				break;
			case 2:
				sprintf(line,"%s%s",tree[cm-(LINES-9)/2+x],
						MsgHdr[treenum[cm-(LINES-9)/2+x]].WhoTo);
				break;
			case 3:
				sprintf(line,"%s%s",tree[cm-(LINES-9)/2+x],
						MsgHdr[treenum[cm-(LINES-9)/2+x]].Subj);
				break;
		}
		line[y+COLS]=0;
		if (strlen(line)>y)
			mvwaddstru(wTxt,1+x,0,line+y);
		if ((LINES-9)/2==x)
			wcolon(wTxt,COL_Menu);
	}
	wrefresh(wTxt);
}

void treewalk(word **treen, word **treer, word i, int *n, word *e)
{
	word nb;
	(*n)++;
	*treen=(word *)realloc(*treen,sizeof(word)*(*n));
	*treer=(word *)realloc(*treer,sizeof(word)*(*n));
	treen[0][*n-1]=i;
	treer[0][*n-1]=*e;
	nb=*e;
	if (MsgHdr[i].Child!=65535)
	{
		(*e)++;
		treewalk(treen,treer,MsgHdr[i].Child,n,e);
	}
	if (MsgHdr[i].nextBrother!=65535)
		treewalk(treen,treer,MsgHdr[i].nextBrother,n,&nb);
	if (nb>*e) *e=nb;
}

void showtree()
{
	int n=0, p, x, y=0, maxy=0, tab, pos, lineflag;
	char in=0;
	word *treenum=NULL, *treer=NULL, e=1, ee;
	char **tree=NULL;
	if (TotalMsgs && !pseudoEmpty && !SimpleLink &&\
			(MsgHdr[curMsg].Mother!=65535 ||\
			 MsgHdr[curMsg].Child!=65535 ||\
			 MsgHdr[curMsg].prevBrother!=65535 ||\
			 MsgHdr[curMsg].nextBrother!=65535))
	{
		werase(wHlp);
		mvwaddstr(wHlp,0,1,bhelp_tree);
		switch (TreeMode)
		{
			case 0:
				mvwaddstr(wHlp,0,COLS-8," Number");
				break;
			case 1:
				mvwaddstr(wHlp,0,COLS-8,"   From");
				break;
			case 2:
				mvwaddstr(wHlp,0,COLS-8,"     To");
				break;
			case 3:
				mvwaddstr(wHlp,0,COLS-8,"Subject");
				break;
		}
		wrefresh(wHlp);
		for (p=curMsg; MsgHdr[p].Mother!=65535; p=MsgHdr[p].Mother);
		treewalk(&treenum,&treer,p,&n,&e);
		for (tab=8; (e+1)*tab>COLS && tab>4; tab--);
		if (n>1)
		{
			tree=(char **)malloc(sizeof(char *)*n);
			for (x=0; x<n; x++)
			{
				tree[x]=(char *)malloc(tab*e+1);
				memset(tree[x],32,tab*treer[x]);
				tree[x][tab*treer[x]]=0;
			}
			for (lineflag=0, ee=1; ee<e; ee++)
				for (x=0; x<n; x++)
				{
					if (treer[x]==ee+1)
					{
						lineflag=(MsgHdr[treenum[x]].nextBrother!=65535);
						tree[x][ee*tab]='+';
						memset(&tree[x][ee*tab+1],'-',tab-1);
					} else
						if (lineflag)
							tree[x][ee*tab]='|';
					if (maxy<strlen(tree[x])) maxy=strlen(tree[x]);
				}
			p=curMsg;
			for (x=0; x<n; x++)
				if (treenum[x]==curMsg) break;
			pos=x;
			drawtree(tree,treenum,n,pos,TreeMode,y);
			while (in!=10 && in!=27)
			{
				sigprocmask(SIG_UNBLOCK,&allmask,NULL);
				if (show_time_now) showtime();
				in=getchn();
				if (show_time_now) showtime();
				sigprocmask(SIG_BLOCK,&allmask,NULL);
				switch (in)
				{
					case 9:
						TreeMode++;
						if (TreeMode==4) TreeMode=0;
						drawtree(tree,treenum,n,pos,TreeMode,y);
						switch (TreeMode)
						{
							case 0:
								mvwaddstr(wHlp,0,COLS-5," NUM");
								break;
							case 1:
								mvwaddstr(wHlp,0,COLS-5,"FROM");
								break;
							case 2:
								mvwaddstr(wHlp,0,COLS-5,"  TO");
								break;
							case 3:
								mvwaddstr(wHlp,0,COLS-5,"SUBJ");
								break;
						}
						wrefresh(wHlp);
						break;
					case '8':
						if (MsgHdr[curMsg].Mother!=65535)
						{
							curMsg=MsgHdr[curMsg].Mother;
							for (pos=0; pos<n && curMsg!=treenum[pos]; pos++);
							showhdr();
							drawtree(tree,treenum,n,pos,TreeMode,y);
						} else Beep();
						break;
					case '2':
						if (MsgHdr[curMsg].Child!=65535)
						{
							curMsg=MsgHdr[curMsg].Child;
							for (pos=0; pos<n && curMsg!=treenum[pos]; pos++);
							showhdr();
							drawtree(tree,treenum,n,pos,TreeMode,y);
						} else Beep();
						break;
					case '4':
						if (MsgHdr[curMsg].prevBrother!=65535)
						{
							curMsg=MsgHdr[curMsg].prevBrother;
							for (pos=0; pos<n && curMsg!=treenum[pos]; pos++);
							showhdr();
							drawtree(tree,treenum,n,pos,TreeMode,y);
						} else Beep();
						break;
					case '6':
						if (MsgHdr[curMsg].nextBrother!=65535)
						{
							curMsg=MsgHdr[curMsg].nextBrother;
							for (pos=0; pos<n && curMsg!=treenum[pos]; pos++);
							showhdr();
							drawtree(tree,treenum,n,pos,TreeMode,y);
						} else Beep();
						break;
					case 0x1b:
						switch ((in=getchn()))
						{
							case 'h':
								showTreeHelp();
								drawtree(tree,treenum,n,pos,TreeMode,y);
								break;
							case 0x5b:
								switch ((in=getchn()))
								{
									case 0x41:
										if (pos>0)
										{	
											pos--;
											curMsg=treenum[pos];
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
									case 0x42:
										if (pos<n-1)
										{
											pos++;
											curMsg=treenum[pos];
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
									case 0x44:
										if (y>0)
										{	
											y-=tab;
											if (y<0) y=0;
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
									case 0x43:
										if (y<maxy)
										{	
											y+=tab;
											if (y>maxy) y=maxy;
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
									case 0x35:
										getch();
										if (pos>0)
										{
											pos-=((LINES-9)/2);
											if (pos<0) pos=0;
											curMsg=treenum[pos];
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else
											Beep();
										break;
									case 0x36:
										getch();
										if (pos<n-1)
										{
											pos+=((LINES-9)/2);
											if (pos>n-1) pos=n-1;
											curMsg=treenum[pos];
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else
											Beep();
										break;
									case 0x31:
										getch();
										if (MsgHdr[curMsg].Mother!=65535)
										{
											while (MsgHdr[curMsg].Mother!=65535)
												curMsg=MsgHdr[curMsg].Mother;
											for (pos=0; pos<n && curMsg!=treenum[pos]; pos++);
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
									case 0x34:
										getch();
										if (MsgHdr[curMsg].Child!=65535)
										{
											while (MsgHdr[curMsg].Child!=65535)
												curMsg=MsgHdr[curMsg].Child;
											for (pos=0; pos<n && curMsg!=treenum[pos]; pos++); 
											showhdr();
											drawtree(tree,treenum,n,pos,TreeMode,y);
										} else Beep();
										break;
								} break;
							case 0x1b:
								curMsg=p;
								showhdr();
								break;
						}
				}
			}
			if (in==10 && MsgHdr[curMsg].Deleted)
			{
				MsgData.Deleted--;
				MsgHdr[curMsg].Deleted=0;
			}
			wcoloff(wTxt);
			showmsg();
		} else Beep();
		free(treenum);
		free(treer);
		if (tree) for (x=0; x<n; x++) free(tree[x]);
		free(tree);
		initmenu();
	} else Beep();
}

void nextmarked()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg<TotalMsgs-1)
	{
		for (i=curMsg+1; i<TotalMsgs; i++)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Marked) break;
		if (i!=TotalMsgs)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void prevmarked()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg>0)
	{
		for (i=curMsg-1; i>=0; i--)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Marked) break;
		if (i>=0)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void nextpersonal()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg<TotalMsgs-1)
	{
		for (i=curMsg+1; i<TotalMsgs; i++)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Personal) break;
		if (i!=TotalMsgs)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void prevpersonal()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg>0)
	{
		for (i=curMsg-1; i>=0; i--)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Personal) break;
		if (i>=0)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void nextprotected()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg<TotalMsgs-1)
	{
		for (i=curMsg+1; i<TotalMsgs; i++)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Protected) break;
		if (i!=TotalMsgs)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void prevprotected()
{
	int i;
	if (TotalMsgs && !pseudoEmpty && curMsg>0)
	{
		for (i=curMsg-1; i>=0; i--)
			if (!MsgHdr[i].Deleted && MsgHdr[i].Protected) break;
		if (i>=0)
		{
			curMsg=i;
			showmsg();
			return;
		}
	}
	Beep();
}

void nextfolder()
{
	int last;
	if (curFld<maxFld-1)
	{
		Folder[curFld].unread=(MsgData.New!=0);
		Folder[curFld].Personal=MsgData.NewPersonal;
		Folder[curFld].Marked=MsgData.Marked;
		for (last=curFld, curFld++; Folder[curFld].num==-1 && curFld<maxFld; \
				curFld++);
		if (curFld==maxFld)
		{
			curFld=last;
			Beep();
			return;
		}
		savemsghdr(&MsgHdr);
		MsgData.LastRead=curMsg;
		TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
		curMsg=MsgData.LastRead;
		loadmsghdr(&MsgHdr);
		loadalias(Folder[curFld].name);
		loadorig(Folder[curFld].name);
		findundel();
		chooseAka();
		showmsg();
		return;
	}
	Beep();
}

void prevfolder()
{
	if (curFld>0)
	{
		Folder[curFld].unread=(MsgData.New!=0);
		Folder[curFld].Personal=MsgData.NewPersonal;
		Folder[curFld].Marked=MsgData.Marked;
		savemsghdr(&MsgHdr);
		MsgData.LastRead=curMsg;
		for (curFld--; Folder[curFld].num==-1; curFld--);
		TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
		curMsg=MsgData.LastRead;
		loadmsghdr(&MsgHdr);
		loadalias(Folder[curFld].name);
		loadorig(Folder[curFld].name);
		Folder[curFld].unread=(MsgData.New!=0);
		findundel();
		chooseAka();
		showmsg();
		return;
	}
	Beep();
}

void savefolder()
{
	FILE *f;
	char name[256];
	int i;
	strcpy(name,BasePath);
	strcat(name,"areas");
	if ((f=fopen(name,"wt"))!=NULL)
	{
		for (i=1; i<maxFld; i++)
			if (Folder[i].path)
				fprintf(f,"%s %s\n",Folder[i].name,Folder[i].path);
			else
				fprintf(f,"%s\n",Folder[i].name);
		fclose(f);
		chmod(name,FIDO_MOD);
		chown(name,-1,FIDO_GID);
	}
}

int inputaddr(WINDOW *win, int y, int x, MsgHdrType *nm, int subj, int group)
{
	char Destination[COLS], *d1, *d2, *d3, addr[25];
	int found=-2, ok=0, i;
	Addr4dType ad;
	NLentryType ent;
	UserAkaType *aka;
	strcpy(Destination,nm->WhoTo);
	while (!(ok=inputline(win,wHlp,y,x,COLS-20,Destination,Names,NameNum,0)))
	{
		if (Destination[0]==0) continue;
		if (group)
		{
			for (i=0; i<numGroups; i++)
				if (strcmp(Destination,Groups[i].Label)==0)
				{
					if (tmpGroup)
						return i+2;
					if (UseThisGroup(&(Groups[i]),"Use this group?"))
						return i+2;
					Beep();
					break;
				}
			if (i!=numGroups) continue;
			if (strcmp(Destination,"!")==0)
				if (BuildTempGroup())
					return 1;
				else
				{
					Beep();
					continue;
				}
		}
		for (i=1; i<NameNum; i++)
			if (strcmp(Destination,ShortNames[i])==0)
			{
				strcpy(Destination,Names[i]);
				break;
			}
		if (MsgData.NetMail)
		{
			d1=strchr(Destination,',');
			if (d1)
			{
				*d1++=0;
				while (*d1==32) d1++;
				d2=strchr(d1,',');
				if (d2)
				{
					*d2++=0;
					if (subj)
					{
						while (*d2==32) d2++;
						d3=strchr(d2,',');
						if (d3) *d3++=0;
						strcpy(nm->Subj,d2);
					} else
					{
						d3=strchr(d2,',');
						if (d3) *d3++=0;
					}
					if (d3)
						for (; *d3; d3+=2)
							for (i=0; i<16; i++)
								if (strncasecmp(d3,NAMEFLAG[i],2)==0)
								{
									nm->Attribute|=(1<<i);
									break;
								}
				}
				strcpy(addr,d1);
				if (Str2Addr(addr,&ad))
				{
					Beep();
					continue;
				}
				nm->DestZone=ad.Zone;
				nm->DestNet=ad.Net;
				nm->DestNode=ad.Node;
				nm->DestPoint=ad.Point;
				found=0;
				break;
			} else
			{
				if (!Str2Addr(Destination,&ad))
				{
					sprintf(addr,"%u:%u/%u.%u",ad.Zone,ad.Net,ad.Node,ad.Point);
					if (keyentry(addr,&ent))
					{
						aka=Aka;
						for (Aka=Profile.Aka; Aka; Aka=Aka->next)
						{
							if (aka!=Aka && !Str2Addr(Destination,&ad))
							{
								sprintf(addr,"%u:%u/%u.%u",ad.Zone,ad.Net,ad.Node,ad.Point);
								if (!keyentry(addr,&ent)) break;
							}
						}
						if (!Aka)
						{
							Aka=aka;
							Beep();
							continue;
						}
						Aka=aka;
					}
				} else
					if (nameentry(Destination,&ent))
					{
						strcat(Destination,",");
						Beep();
						continue;
					}
				d1=strchr(ent.Sysop,32);
				if (d1)
				{
					*d1++=0;
					strcpy(Destination,d1);
					strcat(Destination," ");
					strcat(Destination,ent.Sysop);
				} else strcpy(Destination,ent.Sysop);
				nm->DestZone=ent.ad.Zone;
				nm->DestNet=ent.ad.Net;
				nm->DestNode=ent.ad.Node;
				nm->DestPoint=ent.ad.Point;
				freeentry(&ent);
				found=0;
				break;
			}
		} else
		{
			d1=strchr(Destination,',');
			if (d1) *d1=0;
			found=0;
			break;
		}
	}
	if (!found)
	{
		strncpy(nm->WhoTo,Destination,35);
		nm->WhoTo[35]=0;
		wmove(wHdr,2,4);
		mvwaddstru(wHdr,2,4,nm->WhoTo);
		if (MsgData.NetMail)
		{
			sprintf(addr,"%u:%u/%u.%u",
					nm->DestZone,nm->DestNet,nm->DestNode,nm->DestPoint);
			if ((ok=keyentry(addr,&ent)) && nm->DestPoint)
			{
				d1=strchr(addr,'.');
				*d1=0;
				ok=keyentry(addr,&ent);
			}
			wprintw(wHdr,", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,
					nm->DestZone,nm->DestNet,nm->DestNode,nm->DestPoint);
		}
		wclrtoeoln(wHdr);
	}
	if (ok==-1) return -1;
	return found;
}

void chooseAka()
{
	sigset_t wait;
	UserAkaType *ra, *la;
	if (Aka->UserZone!=MsgData.RouteZone && \
			Aka->UserNet!=MsgData.RouteNet && \
			Aka->UserNode!=MsgData.RouteNode && \
			!MsgData.NetMail)
	{
		la=Aka;
		for (ra=Profile.Aka; ra; ra=ra->next)
			if (ra->UserZone==MsgData.RouteZone && \
					ra->UserNet==MsgData.RouteNet && \
					ra->UserNode==MsgData.RouteNode) break;
		wcolon(wTop,COL_StatusLine);
		werase(wTop);
		if (ra)
		{
			Aka=ra;
			mvwprintw(wTop,0,1,"%s(%s)@%u:%u/%u.%u(%s)",\
								Profile.UserName,Profile.UserLogin,\
								Aka->UserZone,Aka->UserNet,Aka->UserNode,Aka->UserPoint,\
								Aka->NetName);
		} else
		{
			Aka=la;
			mvwprintw(wTop,0,1,"%s(%s) No matching Profile",\
								Profile.UserName,Profile.UserLogin);
		}
		wcoloff(wTop);
		wrefresh(wTop);
		alarm(0);
		sigpending(&wait);
		if (!sigismember(&wait,SIGALRM))
			raise(SIGALRM);
	}
	if (MsgData.NetMail)
	{
		wcolon(wTop,COL_StatusLine);
		werase(wTop);
		mvwprintw(wTop,0,1,"%s(%s)@%u:%u/%u.%u(%s)",\
							Profile.UserName,Profile.UserLogin,\
							Aka->UserZone,Aka->UserNet,Aka->UserNode,Aka->UserPoint,\
							Aka->NetName);
		wcoloff(wTop);
		wrefresh(wTop);
		alarm(0);
		sigpending(&wait);
		if (!sigismember(&wait,SIGALRM))
			raise(SIGALRM);
	}
}

void changeText()
{
	MsgHdrType NewMsg;
	if (TotalMsgs && !pseudoEmpty)
		if (MsgHdr[curMsg].Attribute&256)
		{
			NewMsg=MsgHdr[curMsg];
			NewMsg.StartRec=0;
			NewMsg.NumRecs=0;
			editorcall(NULL,2,0,0,&NewMsg,&NewMsg,curFld);
			showmsg();
			return;
		}
	Beep();
}

void deltree(int i)
{
	if (!MsgHdr[i].Deleted)
	{
		MsgData.Deleted++;
		MsgHdr[i].Deleted=1;
		if (MsgHdr[i].New)
			MsgData.New--;
		if (MsgHdr[i].NewPersonal)
			MsgData.NewPersonal--;
		if (MsgHdr[i].Marked)
			MsgData.Marked--;
	}
	if (MsgHdr[i].nextBrother!=65535)
		deltree(MsgHdr[i].nextBrother);
	if (MsgHdr[i].Child!=65535)
		deltree(MsgHdr[i].Child);
}

void deleteThread()
{
	WINDOW *inp;
	int i, in;
	if (TotalMsgs && !pseudoEmpty && !SimpleLink)
		if ((inp=openask(3,16,LINES/2+1,COLS/2-8,"Kill Thread ?",\
				COL_MenuHigh))!=NULL)
		{
			mvwaddstr(inp,1,1,"Y/y to Confirm");
			wrefresh(inp);
			in=getchn();
			if (in==0x1b) getch();
			delwin(inp);
			touchwin(wTxt);
			wrefresh(wTxt);
			if (in!='y' && in!='Y') return;
			if (MsgHdr[curMsg].Mother==65535 && \
					MsgHdr[curMsg].Child==65535 && \
					MsgHdr[curMsg].nextBrother==65535 && \
					MsgHdr[curMsg].prevBrother==65535)
				deleteMsg();
			else
			{
				for (i=curMsg; MsgHdr[i].Mother!=65535; i=MsgHdr[i].Mother);
				deltree(i);
			}
			findundel();
			showmsg();
			return;
		}
	Beep();
}

void toggleReadOnly()
{
	if (!MsgData.NetMail)
	{
		toggle(MsgData.ReadOnly);
		showhdr();
	} else
		Beep();
}

int editorcall(char *tmpl, int mode, int savehdr, int pernm,
		MsgHdrType *OldMsg, MsgHdrType *NewMsg, int area)
{
	char sys[PATH_MAX], group[100]="NETMAIL", tempm[100];
	FILE *temp;
	int x=0, y=0, oldFld=-1, exit=1, i;
	for (i=area; i>=0; i--)
		if (Folder[i].num==-1)
		{
			strcpy(group,Folder[i].name);
			break;
		}
	if (Editor[0]==0)
	{
		DateTime(NewMsg->DateTime);
		if (mode<2) strcpy(NewMsg->Recvdt,"");
		if (tmpl)
			TextTemplate(Folder[curFld].name,Folder[area].name,group,tmpl,
					*OldMsg,*NewMsg,&x,&y);
		if (area!=curFld)
		{
			MsgData.LastRead=curMsg;
			savemsghdr(&MsgHdr);
			openarea(Folder[area].name,Folder[area].path);
			loadmsghdr(&MsgHdr);
			loadalias(Folder[area].name);
			loadorig(Folder[area].name);
			curMsg=MsgData.LastRead;
			oldFld=curFld;
			curFld=area;
			showfld();
		}
		if (!textedit(wTxt,wHlp,&MsgTxt,&MsgLines,x,y))
		{
			ExeShellCommand(Folder[curFld].name);
			if (mode!=-1) savemsg(NewMsg,mode,savehdr);
			if (mode==2) MsgHdr[curMsg]=*NewMsg;
			exit=0;
		} else
			EndTemplate();
		if (oldFld!=-1)
		{
			MsgData.LastRead=curMsg;
			savemsghdr(&MsgHdr);
			curFld=oldFld;
			TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
			loadmsghdr(&MsgHdr);
			loadalias(Folder[curFld].name);
			loadorig(Folder[curFld].name);
			curMsg=MsgData.LastRead;
			showfld();
		}
		initmenu();
	} else
	{
		sprintf(tempm,TEMPMSG".%u",getpid());
		if (mode>0)
		{
			if (tmpl)
				TextTemplate(Folder[curFld].name,Folder[area].name,group,tmpl,
						*OldMsg,*NewMsg,&x,&y);
			temp=fopen(tempm,"wt");
			if (temp)
			{
				outputMsg(temp,0,Folder[curFld].name,NewMsg,MsgLines,&MsgTxt,0,NULL);
				fclose(temp);
			}
		}
		sprintf(sys,Editor,tempm);
		endwin();
		system(sys);
		reinit();
		redrawScreen();
		if (area!=curFld)
		{
			MsgData.LastRead=curMsg;
			savemsghdr(&MsgHdr);
			openarea(Folder[area].name,Folder[area].path);
			loadmsghdr(&MsgHdr);
			loadalias(Folder[area].name);
			loadorig(Folder[area].name);
			curMsg=MsgData.LastRead;
			oldFld=curFld;
			curFld=area;
		}
		temp=fopen(tempm,"rt");
		if (temp)
		{
			if (inputMsg(temp,COLS,&x,sys,NewMsg,&MsgLines,&MsgTxt,NULL,NULL,NULL,NULL))
			{
				ExeShellCommand(Folder[curFld].name);
				DateTime(NewMsg->DateTime);
				if (mode<2) strcpy(NewMsg->Recvdt,"");
				if (mode!=-1) savemsg(NewMsg,mode,savehdr);
				if (mode==2) MsgHdr[curMsg]=*NewMsg;
				remove(tempm);
				exit=0;
			}
			fclose(temp);
			EndTemplate();
		}
		if (oldFld!=-1)
		{
			MsgData.LastRead=curMsg;
			savemsghdr(&MsgHdr);
			curFld=oldFld;
			TotalRecs=openarea(Folder[curFld].name,Folder[curFld].path);
			loadmsghdr(&MsgHdr);
			loadalias(Folder[curFld].name);
			loadorig(Folder[curFld].name);
			curMsg=MsgData.LastRead;
			showfld();
		}
	}
	return exit;
}

int getfolder()
{
	int i, j, l=0;
	LineListType *lines=NULL;
	for (i=0; i<maxFld; i++)
		if (Folder[i].num!=-1)
		{
			l++;
			lines=(LineListType *)realloc(lines,l*LineListSize);
			lines[l-1].line=(char *)malloc(strlen(Folder[i].name)+10);
			sprintf(lines[l-1].line," %3u %s ",Folder[i].num,Folder[i].name);
			lines[l-1].Quote=i;
		}
	j=scrollchoice(lines,l,"Forward to Area",NULL);
	i=lines[j].Quote;
	touchwin(wTxt);
	wrefresh(wTxt);
	for (j=0; j<l; j++) free(lines[j].line);
	free(lines);
	return i;
}

void crosspost()
{
	int i, j, fl, l, fld, CrossLine=0;
	LineListType *folder=NULL;
	MsgHdrType NewMsg;
	char line[80];
	for (fl=j=0, i=1; i<maxFld; i++)
	{
		if (Folder[i].num==-1) j=0;
		if (Folder[i].num==-1 && Folder[i].marked) j=1;
		if (Folder[i].num!=-1 && (j || Folder[i].marked))
		{
			fl++;
			folder=(LineListType *)realloc(folder,LineListSize*fl);
			folder[fl-1].line=(char *)malloc(strlen(Folder[i].name)+1);
			strcpy(folder[fl-1].line,Folder[i].name);
			folder[fl-1].CR=i;
		}
	}
	if (fl<2)
	{
		for (i=0; i<fl; i++) free(folder[i].line);
		free(folder);
		folder=(LineListType *)malloc(LineListSize*2);
		folder[0].line=(char *)malloc(20);
		strcpy(folder[0].line,"Not enough folders marked!");
		folder[1].line=(char *)malloc(20);
		strcpy(folder[1].line,"     Use M-f to mark");
		scrolltext(folder,2,"Warning",0);
		free(folder[0].line);
		free(folder[1].line);
		free(folder);
		touchwin(wTxt);
		wrefresh(wTxt);
		return;
	} else
	{
		if (scrolltext(folder,fl,"Crosspost to this folders?",1))
		{
			touchwin(wTxt);
			wrefresh(wTxt);
			fld=curFld;
			MsgData.LastRead=curMsg;
			savemsghdr(&MsgHdr);
			openarea(Folder[folder[0].CR].name,Folder[folder[0].CR].path);
			loadmsghdr(&MsgHdr);
			loadalias(folder[0].line);
			loadorig(folder[0].line);
			curMsg=MsgData.LastRead;
			curFld=folder[0].CR;
			showfld();
			wcolon(wHdr,COL_Header);
			mvwaddstr(wHdr,1,0,"By:");
			wclrtoeoln(wHdr);
			mvwaddstr(wHdr,2,0,"To:");
			wclrtoeoln(wHdr);
			mvwaddstr(wHdr,3,0,"Re:");
			wclrtoeoln(wHdr);
			mvwaddstr(wHdr,4,0,"St:");
			wclrtoeoln(wHdr);
			wcolon(wHdr,COL_InputText);
			mvwaddstr(wHdr,0,0,"Crosspost Message");
			wclrtoeoln(wHdr);
			NewMsg.OrigZone=Aka->UserZone;
			NewMsg.OrigNet=Aka->UserNet;
			NewMsg.OrigNode=Aka->UserNode;
			NewMsg.OrigPoint=Aka->UserPoint;
			NewMsg.DestZone=NewMsg.DestNet=NewMsg.DestNode=NewMsg.DestPoint=0;
			NewMsg.Attribute=StandardFlags;
			NewMsg.Mother=NewMsg.nextBrother=NewMsg.prevBrother=NewMsg.Child=\
			NewMsg.nextSubject=NewMsg.prevSubject=65535;
			NewMsg.Personal=NewMsg.Deleted=NewMsg.New=NewMsg.Marked=\
			NewMsg.TruncSent=NewMsg.DeleteSent=NewMsg.Direct=\
			NewMsg.Protected=NewMsg.NewPersonal=0;
			strcpy(NewMsg.WhoTo,"");
			strcpy(NewMsg.Subj,"");
			if (AskForOrigName)
			{
				strcpy(line,Profile.UserName);
				strcpy(Alias[0],Profile.UserName);
				if (!inputline(wHdr,wHlp,1,4,35,line,Alias,Aliases,0))
					strcpy(NewMsg.WhoFrom,line);
				else
					goto ende;
			} else
				strcpy(NewMsg.WhoFrom,Profile.UserName);
			mvwaddstr(wHdr,1,4,NewMsg.WhoFrom);
			wclrtoeoln(wHdr);
			if (!inputaddr(wHdr,2,4,&NewMsg,1,0))
			{
				if (!inputline(wHdr,wHlp,3,4,71,NewMsg.Subj,NULL,0,1))
				{
					showflags(&NewMsg);
					if (!editorcall("crosspost",-1,0,0,&NewMsg,&NewMsg,curFld))
					{
						for (l=0; l<MsgLines; l++)
							if (strcmp(MsgTxt[l].line,"$%&PUT-CROSSPOST-INFO-HERE&%$")==0)
							{
								CrossLine=1;
								break;
							}
						if (CrossLine)
						{
							MsgTxt[l].CR=1;
							MsgTxt[l].Quote=MsgTxt[l].CutOrigin=0;
							MsgTxt[l].line[0]=0;
							free(MsgTxt[l].line);
							MsgTxt[l].line=(char *)malloc(4096);
						}
						for (i=0; i<fl; i++)
						{
							if (CrossLine)
							{
								strcpy(MsgTxt[l].line,"Crossposted to: ");
								for (j=0; j<fl; j++)
									if (j!=i)
									{
										strcat(MsgTxt[l].line,folder[j].line);
										strcat(MsgTxt[l].line,", ");
									}
								MsgTxt[l].line[strlen(MsgTxt[l].line)-2]=0;
							}
							MsgData.LastRead=curMsg;
							savemsghdr(&MsgHdr);
							openarea(Folder[folder[i].CR].name,Folder[folder[i].CR].path);
							loadmsghdr(&MsgHdr);
							loadalias(folder[i].line);
							loadorig(folder[i].line);
							curMsg=MsgData.LastRead;
							curFld=folder[i].CR;
							MatchAddr(&NewMsg,0);
							savemsg(&NewMsg,0,1);
						}
						curFld=fld;
						MsgData.LastRead=curMsg;
						savemsghdr(&MsgHdr);
						openarea(Folder[curFld].name,Folder[curFld].path);
						loadmsghdr(&MsgHdr);
						loadalias(Folder[curFld].name);
						loadorig(Folder[curFld].name);
						curMsg=MsgData.LastRead;
					} else
						Beep();
				}
			}
			ende:
			for (i=0; i<fl; i++) free(folder[i].line);
			free(folder);
			showmsg();
			return;
		}
	}
	for (i=0; i<fl; i++) free(folder[i].line);
	free(folder);
	touchwin(wTxt);
	wrefresh(wTxt);
	Beep();
}

void forward()
{
	int fld, ok;
	NLentryType ent;
	MsgHdrType head, old;
	char line[80], *d1;
	MsgDataType data;
	UserAkaType *oAka;
	if ((fld=getfolder())>=0)
	{
		data=MsgData;
		MsgData=getmsgdata(Folder[fld].name,Folder[fld].path);
		oAka=Aka;
		chooseAka();
		old=head=MsgHdr[curMsg];
		strcpy(head.WhoFrom,Profile.UserName);
		head.WhoTo[0]=0;
		head.OrigZone=MsgData.NetMail?Aka->UserZone:MsgData.RouteZone;
		head.OrigNet=MsgData.NetMail?Aka->UserNet:MsgData.RouteNet;
		head.OrigNode=MsgData.NetMail?Aka->UserNode:MsgData.RouteNode;
		head.OrigPoint=MsgData.NetMail?Aka->UserPoint:0;
		head.DestZone=head.DestNet=head.DestNode=head.DestPoint=0;
		head.Attribute=StandardFlags|(fld==0?1:0);
		head.Mother=head.nextBrother=head.prevBrother=head.Child=
		head.nextSubject=head.prevSubject=65535;
		head.Personal=head.Deleted=head.New=head.Marked=
		head.TruncSent=head.DeleteSent=head.Direct=
		head.Protected=head.NewPersonal=0;
		wcolon(wHdr,COL_InputText);
		mvwaddstr(wHdr,0,0,"Forward Message");
		wclrtoeoln(wHdr);
		mvwaddstr(wHdr,1,4,Profile.UserName);
		if (MsgData.NetMail)
		{
			sprintf(line,"%u:%u/%u.%u",Aka->UserZone,Aka->UserNet,\
					Aka->UserNode,Aka->UserPoint);
			if ((ok=keyentry(line,&ent)) && Aka->UserPoint)
			{
				d1=strchr(line,'.');
				*d1=0;
				ok=keyentry(line,&ent);
			}
			wprintw(wHdr,", %s (%u:%u/%u.%u)",ok?"-Unlisted-":ent.Box,\
					Aka->UserZone,Aka->UserNet,\
					Aka->UserNode,Aka->UserPoint);
		}
		wclrtoeoln(wHdr);
		if (!inputaddr(wHdr,2,4,&head,0,0))
		{
			MatchAddr(&head,0);
			mvwaddstru(wHdr,3,4,head.Subj);
			wrefresh(wHdr);
			editorcall("forward",0,1,0,&old,&head,fld);
		}
		MsgData=data;
		Aka=oAka;
		chooseAka();
		showmsg();
		return;
	}
	Beep();
}

void changeCharset()
{
	WINDOW *win=NULL;
	char in=0;
	int cs=MsgData.CharSet;
	if ((win=openask(3,20,LINES/2+3,COLS/2-10,"Charset",COL_Menu))!=NULL)
	{
		mvwaddstr(win,1,10-strlen(CHRSETS[cs][0])/2,(char *)CHRSETS[cs][0]);
		mvwaddstr(win,2,8,"<SPC>/<CR>");
		wrefresh(win);
		while (in!=10 && in!=27)
		{
			in=getchn();
			if (in==32)
			{
				cs++;
				if (cs==MAXCHRS) cs=0;
				mvwaddstr(win,1,1,"                  ");
				mvwaddstr(win,1,10-strlen(CHRSETS[cs][0])/2,(char *)CHRSETS[cs][0]);
				wrefresh(win);
			}
		}
		if (in==10)
		{
			MsgData.CharSet=cs;
			savemsgdata();
		}
		touchwin(wTxt);
		wrefresh(wTxt);		
		delwin(win);
	}
}

void changeShowAll()
{
	ShowAllAddr++;
	if (ShowAllAddr==3) ShowAllAddr=0;
	showhdr();
}

void requestFiles()
{
	if (TotalMsgs && !pseudoEmpty)
	{
		request(&(MsgHdr[curMsg]),wHlp,0);
		touchwin(wTxt);
		wrefresh(wTxt);
		initmenu();
	} else Beep();
}

void requestFilesfromAddr()
{
	MsgHdrType dmh;
	memset(&dmh,0,MsgHdrSize);
	request(&dmh,wHlp,1);
	touchwin(wTxt);
	wrefresh(wTxt);
	initmenu();
}

void startSearch()
{
	int i, ocm;
	WINDOW *win;
	if (startsearch())
	{
		ocm=curMsg;
		if ((i=searchnext(curMsg,1))==-1)
			if ((i=searchprev(curMsg,1))==-1)
				Beep();
		if (i!=-1)
		{
			curMsg=i;
			MBSFIN=1;
			showmsg();
			werase(wHlp);
			mvwaddstr(wHlp,0,1,bhelp_search);
			wrefresh(wHlp);
		} else
		{
			if ((win=openask(3,20,LINES/2-2,COLS/2-10,"Search",COL_Menu))!=NULL)
			{
				mvwaddstr(win,1,2,"Text not found!");
				mvwaddstr(win,2,5,"<CR> to leave");
				wrefresh(win);
				while (getchn()!=10);
				touchwin(wTxt);
				touchwin(wHdr);
			}
		}
		while (i>-1)
		{
			i=-1;
			while (i==-1)
			{
				switch (getchn())
				{
					case '+':
						if (curMsg<TotalMsgs-1)
						{
							curMsg++;
							i=searchnext(curMsg,1);
							if (i==-1) Beep();
							else
							{
								curMsg=i;
								MBSFIN=1;
								showmsg();
							}
						}
						break;
					case '-':
						if (curMsg>0)
						{
							curMsg--;
							i=searchprev(curMsg,1);
							if (i==-1) Beep();
							else
							{
								curMsg=i;
								MBSFIN=1;
								showmsg();
							}
						}
						break;
					case 10:
						i=-3;
						break;
					case '5':
						toggleMark();
						break;
					case '0':
						toggleProtect();
						break;
					case 0x1b:
						switch (getchn())
						{
							case 'h':
								showSearchHelp();
								break;
							case 0x1b:
								i=-2;
								break;
							case 0x5b:
								switch (getchn())
								{
									case 0x31:
										curMsg=0;
										i=searchnext(curMsg,1);
										if (i==-1) Beep();
										else
										{
											curMsg=i;
											MBSFIN=1;
											showmsg();
										}
										break;
									case 0x34:
										curMsg=TotalMsgs-1;
										i=searchprev(curMsg,1);
										if (i==-1) Beep();
										else
										{
											curMsg=i;
											MBSFIN=1;
											showmsg();
										}
										break;
									case 0x35:
										getch();
										curLine-=(LINES-9);
										if (curLine<0) curLine=0;
										showtxt(0);
										break;
									case 0x36:
										getch();
										if (MsgLines>LINES-8)
										{
											curLine+=(LINES-9);
											if (curLine>MsgLines-LINES+8)
												curLine=MsgLines-LINES+8;
											showtxt(0);
										}
										break;
									case 0x41:
										showtxt(-1);
										break;
									case 0x42:
										showtxt(1);
										break;
									case 0x43:
										i=searchnext(curMsg,0);
										if (i==-1) Beep();
										else
										{
											curMsg=i;
											MBSFIN=1;
											showmsg();
										}
										break;
									case 0x44:
										i=searchprev(curMsg,0);
										if (i==-1) Beep();
										else
										{
											curMsg=i;
											MBSFIN=1;
											showmsg();
										}
										break;
								}
								break;
						}
						break;
				}
			}
		}
		donesearch();
		initmenu();
		if (i==-2) curMsg=ocm;
	}
	showmsg();
}

void FolderShell()
{
	FolderListShell(0);
}

void ListShell()
{
	FolderListShell(1);
}

void FolderListShell(int mode)
{
	while (mode!=-1)
		if (mode==0)
			mode=changeFolder();
		else
			mode=listMsgs();
}

void redrawScreen()
{
	wclear(stdscr);
	touchwin(stdscr);
	refresh();
	touchwin(wTop);
	touchwin(wHdr);
	touchwin(wTxt);
	touchwin(wHlp);
	wrefresh(wTop);
	wrefresh(wHdr);
	wrefresh(wTxt);
	wrefresh(wHlp);
	curs_set(CURSOR_OFF);
}

int importFolders(int fld)
{
	WINDOW *win=NULL;
	char path[PATH_MAX], name[PATH_MAX], *d1;
	FILE *f;
	int i;
	if ((win=openask(3,0,LINES/2-1,0,"Import areas (enter MsgBasePath)",
			COL_Menu)))
	{
		path[0]=0;
		if (!inputline(win,wHlp,1,1,78,path,NULL,0,1))
		{
			extendhome(path);
			mksl(path);
			sprintf(name,"%sareas",path);
			if ((f=fopen(name,"rt")))
			{
				Folder=(FolderType *)realloc(Folder,FolderSize*(maxFld+1));
				memset(&(Folder[maxFld]),0,FolderSize);
				strcpy(Folder[maxFld].name,"-Import-Result:");
				fld=maxFld++;
				while (fgets(name,PATH_MAX,f))
				{
					if ((d1=strchr(name,0xa))) *d1=0;
					if (name[0]!='-')
						if ((d1=strchr(name,32)))
							continue;
					for (i=0; i<maxFld; i++) if (strcmp(Folder[i].name,name)==0) break;
					if (i==maxFld)
					{
						Folder=(FolderType *)realloc(Folder,FolderSize*(maxFld+1));
						memset(&(Folder[maxFld]),0,FolderSize);
						strcpy(Folder[maxFld].name,name);
						if (name[0]!='-')
						{
							Folder[maxFld].path=(char *)malloc(strlen(path)+1);
							strcpy(Folder[maxFld].path,path);
						}
						maxFld++;
					}
				}
				fclose(f);
				renumberfld();
			}
		}
		delwin(win);
	}
	return fld;
}

void callUtility()
{
	int u;
	if ((u=chooseUtility())!=-1)
	{
		touchwin(wTxt);
		wrefresh(wTxt);
		if (execUtility(u))
			savemsg(&MsgHdr[curMsg],0,0);
	}
	showhdr();
	showtxt(0);
	initmenu();
}

int UseThisGroup(GroupType *group, char *title)
{
	int ende=0, l=0;
	LineListType *list;
	char line[PATH_MAX], d[100];
	list=(LineListType *)malloc(LineListSize*group->numNames);
	for (l=0; l<group->numNames; l++)
	{
		strcpy(line,group->Names[l]);
		memset(line+strlen(line),32,36-strlen(line));
		line[36]=0;
		sprintf(d,"%u:%u/%u%c%u",
				group->Addr[l].Zone,group->Addr[l].Net,group->Addr[l].Node,
				group->Addr[l].Point?'.':0,group->Addr[l].Point);
		strcat(line,d);
		list[l].line=(char *)malloc(strlen(line)+1);
		strcpy(list[l].line,line);
	}
	ende=scrolltext(list,l,title,1);
	for (l=0; l<group->numNames; l++) free(list[l].line);
	free(list);
	touchwin(wTxt);
	wrefresh(wTxt);
	return ende;
}

int BuildTempGroup()
{
	WINDOW *ask;
	int ende=0, i, j, k, shift=0;
	MsgHdrType mh;
	char line[PATH_MAX];
	FILE *f;
	if (tmpGroup) return 0;
	tmpGroup=1;
	for (i=0; i<TempGroup.numNames; i++)
	{
		free(TempGroup.Names[i]);
		free(TempGroup.Subj[i]);
	}
	TempGroup.Label[0]=0;
	TempGroup.numNames=0;
	free(TempGroup.Names);
	TempGroup.Names=NULL;
	free(TempGroup.Addr);
	TempGroup.Addr=NULL;
	strcpy(mh.WhoTo,"");
	free(TempGroup.Subj);
	TempGroup.Subj=NULL;
	free(TempGroup.Attrib);
	TempGroup.Attrib=NULL;
	strcpy(mh.WhoTo,"");
	strcpy(mh.Subj,"");
	mh.DestZone=mh.DestNet=mh.DestNode=mh.DestPoint=0;
	mh.Attribute=0;
	if ((ask=openask(17,0,7,0,"Build Temp Group",COL_Menu)))
	{
		mvwaddstr(ask,2,2,"Please enter an address or a blank line to exit");
		while (!ende)
		{
			ende=inputaddr(ask,1,1,&mh,0,1);
			if (ende>0)
			{
				for (j=0; j<Groups[ende-2].numNames; j++)
				{
					for (i=0; i<TempGroup.numNames; i++)
						if (strcmp(TempGroup.Names[i],Groups[ende-2].Names[j])==0 &&
								TempGroup.Addr[i].Zone==Groups[ende-2].Addr[j].Zone &&
								TempGroup.Addr[i].Net==Groups[ende-2].Addr[j].Net &&
								TempGroup.Addr[i].Node==Groups[ende-2].Addr[j].Node &&
								TempGroup.Addr[i].Point==Groups[ende-2].Addr[j].Point)
							break;
					if (i==TempGroup.numNames)
					{
						TempGroup.numNames++;
						TempGroup.Names=(char **)realloc(TempGroup.Names,
								TempGroup.numNames*sizeof(char *));
						TempGroup.Addr=(Addr4dType *)realloc(TempGroup.Addr,
								Addr4dSize*TempGroup.numNames);
						TempGroup.Subj=(char **)realloc(TempGroup.Subj,
								TempGroup.numNames*sizeof(char *));
						TempGroup.Attrib=(word *)realloc(TempGroup.Attrib,
								TempGroup.numNames*sizeof(word));
						TempGroup.Names[TempGroup.numNames-1]=(char *)
								malloc(strlen(Groups[ende-2].Names[j])+1);
						strcpy(TempGroup.Names[TempGroup.numNames-1],
								Groups[ende-2].Names[j]);
						TempGroup.Addr[TempGroup.numNames-1].Zone=
								Groups[ende-2].Addr[j].Zone;
						TempGroup.Addr[TempGroup.numNames-1].Net=
								Groups[ende-2].Addr[j].Net;
						TempGroup.Addr[TempGroup.numNames-1].Node=
								Groups[ende-2].Addr[j].Node;
						TempGroup.Addr[TempGroup.numNames-1].Point=
								Groups[ende-2].Addr[j].Point;
						TempGroup.Subj[TempGroup.numNames-1]=(char *)
								malloc(strlen(Groups[ende-2].Subj[j])+1);
						strcpy(TempGroup.Subj[TempGroup.numNames-1],
								Groups[ende-2].Subj[j]);
						TempGroup.Attrib[TempGroup.numNames-1]=
								Groups[ende-2].Attrib[j];
						if (TempGroup.numNames%13==0 && TempGroup.numNames)
						{
							shift++;
							for (k=0; k<13; k++)
							{
								wmove(ask,3+k,2);
								wclrtoeoln(ask);
							}
						}
						mvwaddstru(ask,3+TempGroup.numNames-shift*13,2,
								Groups[ende-2].Names[j]);
						mvwprintw(ask,3+TempGroup.numNames-shift*13,40,"%u:%u/%u%c%u",
								Groups[ende-2].Addr[j].Zone,
								Groups[ende-2].Addr[j].Net,
								Groups[ende-2].Addr[j].Node,
								Groups[ende-2].Addr[j].Point?'.':0,
								Groups[ende-2].Addr[j].Point);
					} else
						Beep();
				}
				strcpy(mh.WhoTo,"");
				strcpy(mh.Subj,"");
				mh.DestZone=mh.DestNet=mh.DestNode=mh.DestPoint=0;
				mh.Attribute=0;
				touchwin(ask);
				wrefresh(ask);
				ende=0;
				continue;
			}
			if (ende==0)
			{
				for (i=0; i<TempGroup.numNames; i++)
					if (strcmp(TempGroup.Names[i],mh.WhoTo)==0 &&
							TempGroup.Addr[i].Zone==mh.DestZone &&
							TempGroup.Addr[i].Net==mh.DestNet &&
							TempGroup.Addr[i].Node==mh.DestNode &&
							TempGroup.Addr[i].Point==mh.DestPoint)
						break;
				if (i==TempGroup.numNames)
				{
					TempGroup.numNames++;
					TempGroup.Names=(char **)realloc(TempGroup.Names,
							TempGroup.numNames*sizeof(char *));
					TempGroup.Addr=(Addr4dType *)realloc(TempGroup.Addr,
							Addr4dSize*TempGroup.numNames);
					TempGroup.Subj=(char **)realloc(TempGroup.Subj,
							TempGroup.numNames*sizeof(char *));
					TempGroup.Attrib=(word *)realloc(TempGroup.Attrib,
							TempGroup.numNames*sizeof(word));
					TempGroup.Names[TempGroup.numNames-1]=(char *)
							malloc(strlen(mh.WhoTo)+1);
					strcpy(TempGroup.Names[TempGroup.numNames-1],mh.WhoTo);
					TempGroup.Addr[TempGroup.numNames-1].Zone=mh.DestZone;
					TempGroup.Addr[TempGroup.numNames-1].Net=mh.DestNet;
					TempGroup.Addr[TempGroup.numNames-1].Node=mh.DestNode;
					TempGroup.Addr[TempGroup.numNames-1].Point=mh.DestPoint;
					TempGroup.Subj[TempGroup.numNames-1]=(char *)
							malloc(strlen(mh.Subj)+1);
					strcpy(TempGroup.Subj[TempGroup.numNames-1],mh.Subj);
					TempGroup.Attrib[TempGroup.numNames-1]=mh.Attribute;
					if (TempGroup.numNames%13==0 && TempGroup.numNames)
					{
						shift++;
						for (k=0; k<13; k++)
						{
							wmove(ask,3+k,2);
							wclrtoeoln(ask);
						}
					}
					mvwaddstru(ask,3+TempGroup.numNames-shift*13,2,mh.WhoTo);
					mvwprintw(ask,3+TempGroup.numNames-shift*13,40,"%u:%u/%u%c%u",
							mh.DestZone,mh.DestNet,mh.DestNode,mh.DestPoint?'.':0,
							mh.DestPoint);
				} else
					Beep();
				strcpy(mh.WhoTo,"");
				strcpy(mh.Subj,"");
				mh.DestZone=mh.DestNet=mh.DestNode=mh.DestPoint=0;
				mh.Attribute=0;
			}
			touchwin(ask);
			wrefresh(ask);
		}
		delwin(ask);
		touchwin(wTxt);
		wrefresh(wTxt);
		if (ende==-1 && TempGroup.numNames>1)
		{
			if (UseThisGroup(&TempGroup,"Save Temp Group?"))
			{
				if ((ask=openask(3,22,LINES/2-1,COLS/2-11,"Enter a Groupname",COL_Menu)))
				{
					if (!inputline(ask,wHlp,1,1,19,TempGroup.Label,NULL,0,0))
					{
						sprintf(line,"%sgroups",BasePath);
						if ((f=fopen(line,"at")))
						{
							if (TempGroup.Label[0]!='!') fputc('!',f);
							fprintf(f,"%s\n",TempGroup.Label);
							for (i=0; i<TempGroup.numNames; i++)
							{
								sprintf(line,"%s,%u:%u/%u.%u%c%s",TempGroup.Names[i],
										TempGroup.Addr[i].Zone,TempGroup.Addr[i].Net,
										TempGroup.Addr[i].Node,TempGroup.Addr[i].Point,
										TempGroup.Subj[i][0]?',':0,TempGroup.Subj[i]);
								fputs(line,f);
								if (TempGroup.Attrib)
								{
									strcpy(line,"");
									for (j=0; j<16; j++)
										if (TempGroup.Attrib[i]&(1<<j))
											strcat(line,NAMEFLAG[j]);
									if (TempGroup.Subj[i][0]==0)
										fputc(',',f);
									fprintf(f,",%s",line);
								}
								fputc('\n',f);
							}
							fclose(f);
							for (i=0; i<numGroups; i++)
							{
								for (j=0; j<Groups[i].numNames; j++)
								{
									free(Groups[i].Names[j]);
									free(Groups[i].Subj[j]);
								}
								free(Groups[i].Names);
								free(Groups[i].Addr);
								free(Groups[i].Subj);
								free(Groups[i].Attrib);
							}
							free(Groups);
							Groups=NULL;
							numGroups=0;
							initgroups();
						} else
						{
							Log("!Could not write to groups");
							Beep();
						}
					} else
					{
						delwin(ask);
						goto ende;
					}
					delwin(ask);
					touchwin(wTxt);
					wrefresh(wTxt);
					mvwaddch(wHdr,2,4,'!');
					mvwaddstru(wHdr,2,5,TempGroup.Label);
					wclrtoeoln(wHdr);
					return 1;
				} else
					Beep();
			}
			ende:
			touchwin(wTxt);
			wrefresh(wTxt);
			mvwaddstr(wHdr,2,4,"!TEMP-GROUP");
			wclrtoeoln(wHdr);
			return 1;
		}
	}
	tmpGroup=0;
	return 0;
}

void chooseOrigin()
{
	if (!MsgData.NetMail)
	{
		Origchoose=scrollchoice(OrigLine,Origlines,"Choose Origline",NULL);
		touchwin(wTxt);
		wrefresh(wTxt);
	} else
		Beep();
}

void clearmarks(int msg)
{
	if (MsgHdr[msg].Marked)
	{
		MsgHdr[msg].Marked=0;
		MsgData.Marked--;
	}
	if (MsgHdr[msg].New)
	{
		MsgHdr[msg].New=0;
		MsgData.New--;
	}
	if (MsgHdr[msg].NewPersonal)
	{
		MsgHdr[msg].NewPersonal=0;
		MsgData.NewPersonal--;
	}
}
