/*
 *   Copyright 1992, 1993, 1994 John Melton (G0ORX/N6LYT)
 *              All Rights Reserved
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 1, or (at your option)
 *   any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

/*
	message.c

	Prepare a PacSat message for uploading

	John Melton
	G0ORX, N6LYT

	4 Charlwoods Close
	Copthorne
	West Sussex
	RH10 3QZ
	England

	INTERNET:	g0orx@amsat.org
			n6lyt@amsat.org
			john@images.demon.co.uk
			J.D.Melton@slh0613.icl.wins.co.uk

	History:

	0.1	initial version.					G0ORX
	0.2	fixed file length in header.				G0ORX
	0.3	converted to Xaw.					G4KLX
		removed size restriction on message and banner.
	0.4	restructured screen and code.				G4KLX
	0.5	added quoting of original message.			G4KLX
*/

#define INSERTCRLF

#define VERSION_STRING "message (version 0.5 by g0orx/n6lyt/g4klx)"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <dirent.h>
#include <time.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Cardinals.h>
#include <X11/Xaw/Form.h>
#include <X11/Xaw/Text.h>
#include <X11/Xaw/AsciiText.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/MenuButton.h>

#include "xawutils.h"
#include "header.h"
#include "ftl0.h"

Display *dpy;

XtAppContext app_context;

typedef struct
{
	XFontStruct *bold_font, *button_font, *menu_font, *label_font, *text_font;
}
Resources;

Resources  resources;

Widget toplevel, compwindow, quitbutton, preparebutton, bannerbutton,
	quotebutton, fromlabel, fromtext, tolabel, totext, titlelabel,
	titletext, keywordslabel, keywordstext, filetypebutton, filetypelabel,
	filetypetext, comptypebutton, comptypelabel, comptypetext, mesgsrclabel,
	mesgsrcbutton, mesgsrctext, datawindow;

static XtResource resource_list[] =
{
	{"boldFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
		XtOffsetOf(Resources, bold_font), XtRString, XtDefaultFont},
	{"buttonFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
		XtOffsetOf(Resources, button_font), XtRString, XtDefaultFont},
	{"menuFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
		XtOffsetOf(Resources, menu_font), XtRString, XtDefaultFont},
	{"labelFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
		XtOffsetOf(Resources, label_font), XtRString, XtDefaultFont},
	{"textFont", XtCFont, XtRFontStruct, sizeof(XFontStruct *),
		XtOffsetOf(Resources, text_font), XtRString, XtDefaultFont}
};

static Arg shell_args[] =
{
	{XtNtitle,		(XtArgVal)NULL}
};

static Arg form_args[] =
{
	{XtNdefaultDistance,	(XtArgVal)0}
};

static Arg label_args[] =
{
	{XtNfromVert,		(XtArgVal)NULL},
	{XtNlabel,		(XtArgVal)NULL},
	{XtNwidth,		(XtArgVal)0},
	{XtNfont,		(XtArgVal)NULL},
	{XtNborderWidth,	(XtArgVal)0},
	{XtNresize,		False},
	{XtNjustify,		XtJustifyLeft},
	{XtNvertDistance,	(XtArgVal)6},
	{XtNhorizDistance,	(XtArgVal)8},
	{XtNtop,		XtChainTop},
	{XtNbottom,		XtChainTop},
	{XtNleft,		XtChainLeft},
	{XtNright,		XtChainLeft}
};

static Arg button_args[] =
{
	{XtNcallback,		(XtArgVal)NULL},
	{XtNlabel,		(XtArgVal)NULL},
	{XtNfont,		(XtArgVal)NULL},
	{XtNfromHoriz,		(XtArgVal)NULL},
	{XtNvertDistance,	(XtArgVal)6},
	{XtNhorizDistance,	(XtArgVal)8},
	{XtNresize,		False},
	{XtNtop,		XtChainTop},
	{XtNbottom,		XtChainTop},
	{XtNleft,		XtChainLeft},
	{XtNright,		XtChainLeft}
};

static Arg menu_button_args[] =
{
	{XtNlabel,		(XtArgVal)NULL},
	{XtNfromHoriz,		(XtArgVal)NULL},
	{XtNfromVert,		(XtArgVal)NULL},
	{XtNwidth,		(XtArgVal)0},
	{XtNfont,		(XtArgVal)NULL},
	{XtNresize,		False},
	{XtNvertDistance,	(XtArgVal)6},
	{XtNhorizDistance,	(XtArgVal)8},
	{XtNtop,		XtChainTop},
	{XtNbottom,		XtChainTop},
	{XtNleft,		XtChainLeft},
	{XtNright,		XtChainLeft},
	{XtNjustify,		XtJustifyCenter}
};

static Arg text_args[] =
{
	{XtNfromHoriz,		(XtArgVal)NULL},
	{XtNfromVert,		(XtArgVal)NULL},
	{XtNlength,		(XtArgVal)255},
	{XtNwidth,		(XtArgVal)500},
	{XtNstring,		(XtArgVal)NULL},
	{XtNfont,		(XtArgVal)NULL},
	{XtNbackground,		(XtArgVal)NULL},
	{XtNvertDistance,	(XtArgVal)6},
	{XtNhorizDistance,	(XtArgVal)8},
	{XtNtop,		XtChainTop},
	{XtNbottom,		XtChainTop},
	{XtNleft,		XtChainLeft},
	{XtNright,		XtChainLeft},
	{XtNeditType,		XawtextEdit},
	{XtNtype,		XawAsciiString},
	{XtNresize,		False},
	{XtNuseStringInPlace,	True}
};

static Arg window_args[] =
{
	{XtNfromVert,		(XtArgVal)NULL},
	{XtNbackground,		(XtArgVal)NULL},
	{XtNfont,		(XtArgVal)NULL},
	{XtNwidth,		(XtArgVal)600},
	{XtNheight,		(XtArgVal)200},
	{XtNvertDistance,	(XtArgVal)10},
	{XtNhorizDistance,	(XtArgVal)0},
	{XtNtop,		XtChainTop},
	{XtNbottom,		XtChainBottom},
	{XtNleft,		XtChainLeft},
	{XtNright,		XtChainRight},
	{XtNeditType,		XawtextEdit},
	{XtNtype,		XawAsciiString},
	{XtNwrap,		XawtextWrapWord},
	{XtNscrollVertical,	XawtextScrollAlways}
};

MenuEntry comp_type_menu[] =
{
	{"Not Compressed",	"comptype1",	0},
	{"PKARC",		"comptype2",	1},
	{"PKZIP",		"comptype3",	2},
	{"LHARC",		"comptype4",	3},
	{"Other -->",		"comptype5",	255}
};

MenuEntry mesg_src_menu[] =
{
	{"Inline Text",		"mesgsrc1",	0},
	{"File -->",		"mesgsrc2",	1}
};

MenuEntry file_type_menu[] =
{
	{"ASCII text",			"filetype1",	0},
	{"RLI/MBL message (single)",	"filetype2",	1},
	{"RLI/MBL message (multiple)",	"filetype3",	2},
	{"MS/PC-DOS .exe",		"filetype4",	6},
	{"MS/PC-DOS .com",		"filetype5",	7},
	{"Keps (NASA 2-line)",		"filetype6",	8},
	{"Keps (AMSAT)",		"filetype7",	9},
	{"Multiple messages",		"filetype8",	12},
	{"Multiple messages (ASCII)",	"filetype9",	13},
	{"GIF image",			"filetype10",	14},
	{"PCX image",			"filetype11",	15},
	{"JPEG image",			"filetype12",	16},
	{"Other -->",			"filetype13",	255}
};

char *fileName = NULL;

HEADER *pHeader;

int filetype = 0;
int comptype = 0;
int mesgsrc  = 0;

char satelliteId[16];

char myCall[256]        = "";
char toCall[256]        = "";
char title[256]         = "";
char keywords[256]      = "";
char filetype_text[256] = "";
char comptype_text[256] = "";
char mesgsrc_text[256]  = "";

char banner[256];

#define MAXHEADER 2048

unsigned char header[MAXHEADER];
int nHeader = 0;

int PrepareFile(unsigned char *);

void QuitCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	XtDestroyApplicationContext(app_context);

	exit(0);
}

void BannerCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	FILE *fp;
	static char text[1000];
	int bytes;
	XawTextPosition pos, oldpos;
	XawTextBlock tt;
	Arg args[1];
	String string;
	
	if ((fp = fopen(banner, "r")) != NULL)
	{
		XtSetArg(args[0], XtNstring, &string);
		XtGetValues(datawindow, args, 1);
		pos = strlen(string);

		oldpos = XawTextGetInsertionPoint(datawindow);
	
		while ((bytes = fread(text, 1, 1000, fp)) > 0)
		{
			XawTextSetInsertionPoint(datawindow, pos);
		
			tt.firstPos = 0;
			tt.ptr      = text;
			tt.length   = bytes;
			tt.format   = FMT8BIT;

			XawTextReplace(datawindow, pos, pos, &tt);
			pos += bytes;
		}
		
		fclose(fp);

		XawTextSetInsertionPoint(datawindow, oldpos);
	}
}

void ExtractDetails(void)
{
	char *pBuffer;
	FILE *hFile;
	int headerSize;
	int nBytes;
	
	/* open the file */
	if ((hFile = fopen(fileName, "r")) == NULL)
	{
		MessageBox("Cannot open input file");
		return;
	}

	pBuffer = XtMalloc(1024);

	/* read in the header */
	nBytes = fread(pBuffer, 1, 1024, hFile);

	/* extracting the header */
	if ((pHeader = ExtractHeader(pBuffer, nBytes, &headerSize)) == NULL)
	{
		MessageBox("Cannot extract PACSAT header");
		XtFree(pBuffer);
		fclose(hFile);
		return;
	}

	strcpy(toCall, pHeader->source);
	sprintf(title, "Re: %s", pHeader->title);

	XtFree(pBuffer);
	fclose(hFile);
}

void QuoteCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	char *pBuffer, *pOutBuffer;
	FILE *hFile;
	FILE *hOut;
	int nBytes, nOutBytes;
	int status, i;
	XawTextPosition pos = 0;
	XawTextBlock tt;
	char command[40];
	char compFile[20], viewFile[20];
	time_t t;
	
	/* open the file */
	if ((hFile = fopen(fileName, "r")) == NULL)
	{
		MessageBox("Cannot open input file");
		return;
	}

	pBuffer = XtMalloc(1024);

	if (pHeader->compression != 0 && pHeader->compression != 255)
	{
		time(&t);
	
		sprintf(compFile, "%x.comp", (int)t);
		sprintf(viewFile, "%x.view", (int)t);
	
		fseek(hFile, pHeader->bodyOffset, SEEK_SET);

		if ((hOut = fopen(compFile, "w")) == NULL)
		{
			MessageBox("Cannot open output file");
			return;
		}

		while ((nBytes = fread(pBuffer, 1, 1024, hFile)) > 0)
			fwrite(pBuffer, 1, nBytes, hOut);

		fclose(hFile);
		fclose(hOut);
	
		switch (pHeader->compression)
		{
		case 2:
			sprintf(command, "unzip -p %s > %s", compFile, viewFile);
			break;
		case 3:
			sprintf(command, "lha -pq %s > %s", compFile, viewFile);
			break;
		default:
			break;
		}

		status = system(command);

		if (status == 127 || status < 0)
		{
			unlink(compFile);
			MessageBox("Cannot run unzip/lha");
			return;
		}

		if ((hFile = fopen(viewFile, "r")) == NULL)
		{
			unlink(compFile);
			MessageBox("Cannot open input file");
			return;
		}
	}
	
	/* now copy in the text */
	if (pHeader->compression == 0)
		fseek(hFile, pHeader->bodyOffset, SEEK_SET);

	pOutBuffer = XtMalloc(2048);

	pOutBuffer[0] = '>';
	pOutBuffer[1] = ' ';
	nOutBytes     = 2;

	while ((nBytes = fread(pBuffer, 1, 1024, hFile)) > 0)
	{
		for (i = 0; i < nBytes; i++)
		{
			if (pBuffer[i] >= ' ' && pBuffer[i] <= '~')
				pOutBuffer[nOutBytes++] = pBuffer[i];
				
			if (pBuffer[i] == '\n')
			{
				pOutBuffer[nOutBytes++] = '\n';
				pOutBuffer[nOutBytes++] = '>';
				pOutBuffer[nOutBytes++] = ' ';
			}
		}

		tt.firstPos = 0;
		tt.ptr      = pOutBuffer;
		tt.length   = nOutBytes;
		tt.format   = FMT8BIT;

		XawTextReplace(datawindow, pos, pos, &tt);

		pos += nOutBytes;

		nOutBytes = 0;
	}

	fclose(hFile);

	if (pHeader->compression != 0)
	{
		unlink(compFile);
		unlink(viewFile);
	}

	XtFree(pBuffer);
	XtFree(pOutBuffer);
}

void PrepareCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	unsigned char *src;
	Arg args[1];

	XtSetArg(args[0], XtNstring, &src);
	XtGetValues(datawindow, args, 1);

#ifdef INSERTCRLF
	{
		int  length;
		unsigned char *dest, *text;

		length = strlen(src);

		for (dest = src; *dest != '\0'; dest++)
			if (*dest == '\n')
				length++;

		if ((text = XtMalloc(length + 1)) == NULL)
		{
			MessageBox("Out of memory");
			return;
		}

		dest = text;

		while (*src)
		{
			if (*src == '\n') *dest++ = '\r';
			*dest++ = *src++;
		}

		*dest++ = '\0';

		/* prepare the header and the data */
		PrepareFile(text);

		XtFree(text);
	}
#else
	/* prepare the header and the data */
	PrepareFile(src);
#endif
}

void HeaderOut(int v)
{
	if (nHeader < MAXHEADER)
	{
		header[nHeader] = v;
		nHeader++;
	}
}

void Header(unsigned int id, char *string, int length)
{
	int i;

	HeaderOut(id % 256);
	HeaderOut(id / 256);
	HeaderOut(length);

	for (i = 0; i < length; i++)
		HeaderOut(string[i]);
}

int PrepareFile(unsigned char *text)
{
	time_t uploadSeq;
	FILE *fpin, *fpout;
	char OutFile[20], InFile[20];
	int i, Bytes;
	int updateFileSize, updateBodyChecksum, updateHeaderChecksum;
	int updateBodyOffset, savedHeaderOffset;
	unsigned char buffer[512];
	unsigned char  int8  = 0;
	unsigned short int16 = 0;
	unsigned long  int32 = 0;
	unsigned short HeaderChecksum = 0;
	unsigned short BodyChecksum   = 0;
	unsigned int   FileSize       = 0;
	unsigned short BodyOffset     = 0;

	time(&uploadSeq);

	if (mesgsrc == 0)
		sprintf(InFile, "%x.txt", (int)uploadSeq);

	sprintf(OutFile, "%x.upl", (int)uploadSeq);

	nHeader = 0;

	HeaderOut(0xAA);
	HeaderOut(0x55);

	Header(0x01, (char *)&int32, 4);
	Header(0x02, (char *)"        ", 8);
	Header(0x03, (char *)"   ", 3);
	updateFileSize = nHeader;

	Header(0x04, (char *)&int32, 4);
	Header(0x05, (char *)&int32, 4);
	Header(0x06, (char *)&int32, 4);
	Header(0x07, (char *)&int8, 1);

	int8 = filetype;
	Header(0x08, (char *)&int8, 1);
	updateBodyChecksum = nHeader;

	Header(0x09, (char *)&int16, 2);
	updateHeaderChecksum = nHeader;

	Header(0x0A, (char *)&int16, 2);
	updateBodyOffset = nHeader;

	int8 = 0;
	Header(0x0B, (char *)&int16, 2);
	Header(0x10, (char *)myCall, strlen(myCall));
	Header(0x11, (char *)"      ", 6);
	Header(0x12, (char *)&int32, 4);
	Header(0x13, (char *)&int8, 1);
	Header(0x14, (char *)toCall, strlen(toCall));
	Header(0x15, (char *)"      ", 6);
	Header(0x16, (char *)&int32, 4);
	Header(0x17, (char *)&int32, 4);
	Header(0x18, (char *)&int8, 1);

	int8 = comptype;
	Header(0x19, (char *)&int8, 1);

	Header(0x22, title, strlen(title));

	if (strlen(keywords) != 0)
		Header(0x23, keywords, strlen(keywords));

	if (filetype == 255)
		Header(0x24, filetype_text, strlen(filetype_text));

	if (comptype == 255)
		Header(0x25, comptype_text, strlen(comptype_text));

	if (mesgsrc == 0)
		Header(0x26, InFile, strlen(InFile));
	else
		Header(0x26, mesgsrc_text, strlen(mesgsrc_text));

	HeaderOut(0x00);
	HeaderOut(0x00);
	HeaderOut(0x00);
	savedHeaderOffset = nHeader;

	BodyOffset = nHeader;

	nHeader = updateBodyOffset;
	Header(0x0B, (char *)&BodyOffset, 2);

	nHeader = savedHeaderOffset;

	FileSize = nHeader;

	if (mesgsrc == 0)
	{
		if ((fpout = fopen(OutFile, "w")) == NULL)
		{
			MessageBox("Cannot open output file");
			return(FALSE);
		}

		fseek(fpout, BodyOffset, SEEK_SET);

		fwrite(text, 1, strlen(text), fpout);

		for (i = 0; i < strlen(text); i++)
			BodyChecksum += (unsigned int)text[i];

		FileSize = nHeader + strlen(text);
	}
	else
	{
		if ((fpin = fopen(mesgsrc_text, "r")) == NULL)
		{
			MessageBox("Cannot open input file");
			return(FALSE);
		}

		if ((fpout = fopen(OutFile, "w")) == NULL)
		{
			fclose(fpin);
			MessageBox("Cannot open output file");
			return(FALSE);
		}

		fseek(fpout, BodyOffset, SEEK_SET);

		while ((Bytes = fread(buffer, 1, sizeof(buffer), fpin)) > 0)
		{
			FileSize += Bytes;

			fwrite(buffer, 1, Bytes, fpout);

			for (i = 0; i < Bytes; i++)
				BodyChecksum += (unsigned int)buffer[i];
		}

		fclose(fpin);
	}

	savedHeaderOffset = nHeader;

	nHeader = updateBodyChecksum;
	Header(0x09, (char *)&BodyChecksum, 2);

	nHeader = savedHeaderOffset;
	savedHeaderOffset = nHeader;

	nHeader = updateFileSize;
	Header(0x04, (char *)&FileSize, 4);

	nHeader = savedHeaderOffset;
	for (i = 0; i < nHeader; i++)
		HeaderChecksum += (unsigned int)header[i];
	savedHeaderOffset = nHeader;

	nHeader = updateHeaderChecksum;
	Header(0x0A, (char *)&HeaderChecksum, 2);

	nHeader = savedHeaderOffset;

	fseek(fpout, 0L, SEEK_SET);

	fwrite(header, 1, nHeader, fpout);

	fclose(fpout);

	sprintf(buffer, "Message prepared: file %x.upl", (int)uploadSeq);
	MessageBox(buffer);

	return(TRUE);
}

void CompTypeCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	int i = 0;

	comptype = (int)client_data;

	for (;;)
	{
		if (comp_type_menu[i].Value == comptype)
		{
			XtVaSetValues(comptypebutton, XtNlabel, comp_type_menu[i].Label, NULL);
			return;
		}

		i++;
	}
}

void MesgSrcCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	int i = 0;

	mesgsrc = (int)client_data;

	for (;;)
	{
		if (mesg_src_menu[i].Value == mesgsrc)
		{
			XtVaSetValues(mesgsrcbutton, XtNlabel, mesg_src_menu[i].Label, NULL);
			return;
		}

		i++;
	}
}

void FileTypeCb(Widget w, XtPointer client_data, XtPointer call_data)
{
	int i = 0;

	filetype = (int)client_data;

	for (;;)
	{
		if (file_type_menu[i].Value == filetype)
		{
			XtVaSetValues(filetypebutton, XtNlabel, file_type_menu[i].Label, NULL);
			return;
		}

		i++;
	}
}

int main(int argc, char **argv)
{
	static XtCallbackRec callback[2];
	char *s;

	if ((s = getenv("SATELLITE")) == NULL)
	{
		printf("SATELLITE environment variable not set.\n");
		return(1);
	}

	strcpy(satelliteId, s);

	if ((s = getenv("MYCALL")) == NULL)
	{
		printf("MYCALL environment variable not set.\n");
		return(1);
	}

	strcpy(myCall, s);

	if ((s = getenv("BANNER")) == NULL)
	{
		if ((s = getenv("HOME")) != NULL)
		{
			strcpy(banner, s);
			strcat(banner, "/.sig");
		}
		else
		{
			strcpy(banner, ".sig");
		}
	}
	else
		strcpy(banner, s);

	if (argc > 1)
	{
		fileName = argv[1];
		ExtractDetails();
	}

	toplevel = XtAppInitialize(&app_context, "Xpb", NULL, 0, &argc, argv,
				NULL, shell_args, XtNumber(shell_args));
	XtVaSetValues(toplevel, XtNtitle, VERSION_STRING, NULL);

	dpy  = XtDisplay(toplevel);

	XtGetApplicationResources(toplevel, &resources,
				resource_list, XtNumber(resource_list),
				NULL, ZERO);

	compwindow = XtCreateManagedWidget("appForm", formWidgetClass,
				toplevel, form_args, XtNumber(form_args));

	callback[0].callback = QuitCb;
	callback[0].closure  = toplevel;
	button_args[0].value = (XtArgVal)callback;
	button_args[1].value = (XtArgVal)"Quit";
	button_args[2].value = (XtArgVal)resources.button_font;
	quitbutton = XtCreateManagedWidget("quitButton", commandWidgetClass,
				compwindow, button_args, XtNumber(button_args));

	callback[0].callback = PrepareCb;
	callback[0].closure  = toplevel;
	button_args[0].value = (XtArgVal)callback;
	button_args[1].value = (XtArgVal)"Prepare";
	button_args[3].value = (XtArgVal)quitbutton;
	preparebutton = XtCreateManagedWidget("prepareButton", commandWidgetClass,
				compwindow, button_args, XtNumber(button_args));

	callback[0].callback = BannerCb;
	callback[0].closure  = toplevel;
	button_args[0].value = (XtArgVal)callback;
	button_args[1].value = (XtArgVal)"Append Banner";
	button_args[3].value = (XtArgVal)preparebutton;
	bannerbutton = XtCreateManagedWidget("appendButton", commandWidgetClass,
				compwindow, button_args, XtNumber(button_args));

	if (fileName != NULL)
	{
		callback[0].callback = QuoteCb;
		callback[0].closure  = toplevel;
		button_args[0].value = (XtArgVal)callback;
		button_args[1].value = (XtArgVal)"Quote";
		button_args[3].value = (XtArgVal)bannerbutton;
		quotebutton = XtCreateManagedWidget("quoteButton", commandWidgetClass,
				compwindow, button_args, XtNumber(button_args));
	}

	label_args[0].value = (XtArgVal)quitbutton;
	label_args[1].value = (XtArgVal)"From:";
	label_args[2].value = (XtArgVal)75;
	label_args[3].value = (XtArgVal)resources.label_font;
	fromlabel = XtCreateManagedWidget("fromLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)fromlabel;
	label_args[1].value = (XtArgVal)"To:";
	tolabel = XtCreateManagedWidget("toLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)tolabel;
	label_args[1].value = (XtArgVal)"Title:";
	titlelabel = XtCreateManagedWidget("titleLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)titlelabel;
	label_args[1].value = (XtArgVal)"Key Words:";
	keywordslabel = XtCreateManagedWidget("keywordsLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)keywordslabel;
	label_args[1].value = (XtArgVal)"File Type";
	filetypelabel = XtCreateManagedWidget("filetypeLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)filetypelabel;
	label_args[1].value = (XtArgVal)"Compression Type";
	label_args[2].value = (XtArgVal)120;
	comptypelabel = XtCreateManagedWidget("comptypeLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	label_args[0].value = (XtArgVal)comptypelabel;
	label_args[1].value = (XtArgVal)"Message Source";
	mesgsrclabel = XtCreateManagedWidget("mesgsrcLabel", labelWidgetClass,
				compwindow, label_args, XtNumber(label_args));

	window_args[0].value = (XtArgVal)mesgsrclabel;
	window_args[1].value = (XtArgVal)WhitePixel(dpy, DefaultScreen(dpy));
	window_args[2].value = (XtArgVal)resources.text_font;
	datawindow = XtCreateManagedWidget("messageText", asciiTextWidgetClass,
				compwindow, window_args, XtNumber(window_args));

	text_args[0].value = (XtArgVal)fromlabel;
	text_args[1].value = (XtArgVal)quitbutton;
	text_args[4].value = (XtArgVal)myCall;
	text_args[5].value = (XtArgVal)resources.button_font;
	text_args[6].value = (XtArgVal)WhitePixel(dpy, DefaultScreen(dpy));
	fromtext = XtCreateManagedWidget("fromText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	text_args[0].value = (XtArgVal)tolabel;
	text_args[1].value = (XtArgVal)fromlabel;
	text_args[4].value = (XtArgVal)toCall;
	totext = XtCreateManagedWidget("toText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	text_args[0].value = (XtArgVal)titlelabel;
	text_args[1].value = (XtArgVal)tolabel;
	text_args[4].value = (XtArgVal)title;
	titletext = XtCreateManagedWidget("titleText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	text_args[0].value = (XtArgVal)keywordslabel;
	text_args[1].value = (XtArgVal)titlelabel;
	text_args[4].value = (XtArgVal)keywords;
	keywordstext = XtCreateManagedWidget("keywordsText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	menu_button_args[0].value = (XtArgVal)file_type_menu[0].Label;
	menu_button_args[1].value = (XtArgVal)filetypelabel;
	menu_button_args[2].value = (XtArgVal)keywordslabel;
	menu_button_args[3].value = (XtArgVal)175;
	menu_button_args[4].value = (XtArgVal)resources.button_font;
	filetypebutton = XtCreateManagedWidget("filetypeButton", menuButtonWidgetClass,
				compwindow, menu_button_args, XtNumber(menu_button_args));

	createMenuPopup(filetypebutton, resources.menu_font, file_type_menu,
				XtNumber(file_type_menu), FileTypeCb);

	text_args[0].value = (XtArgVal)filetypebutton;
	text_args[1].value = (XtArgVal)keywordslabel;
	text_args[3].value = (XtArgVal)317;
	text_args[4].value = (XtArgVal)filetype_text;
	filetypetext = XtCreateManagedWidget("filetypeText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	menu_button_args[0].value = (XtArgVal)comp_type_menu[0].Label;
	menu_button_args[1].value = (XtArgVal)comptypelabel;
	menu_button_args[2].value = (XtArgVal)filetypelabel;
	menu_button_args[3].value = (XtArgVal)130;
	comptypebutton = XtCreateManagedWidget("comptypeButton", menuButtonWidgetClass,
				compwindow, menu_button_args, XtNumber(menu_button_args));

	createMenuPopup(comptypebutton, resources.menu_font, comp_type_menu,
				XtNumber(comp_type_menu), CompTypeCb);

	text_args[0].value = (XtArgVal)comptypebutton;
	text_args[1].value = (XtArgVal)filetypelabel;
	text_args[4].value = (XtArgVal)comptype_text;
	comptypetext = XtCreateManagedWidget("comptypeText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	menu_button_args[0].value = (XtArgVal)mesg_src_menu[0].Label;
	menu_button_args[1].value = (XtArgVal)mesgsrclabel;
	menu_button_args[2].value = (XtArgVal)comptypelabel;
	mesgsrcbutton = XtCreateManagedWidget("mesgsrcButton", menuButtonWidgetClass,
				compwindow, menu_button_args, XtNumber(menu_button_args));

	createMenuPopup(mesgsrcbutton, resources.menu_font, mesg_src_menu,
				XtNumber(mesg_src_menu), MesgSrcCb);

	text_args[0].value = (XtArgVal)mesgsrcbutton;
	text_args[1].value = (XtArgVal)comptypelabel;
	text_args[4].value = (XtArgVal)mesgsrc_text;
	mesgsrctext = XtCreateManagedWidget("mesgsrcText", asciiTextWidgetClass,
				compwindow, text_args, XtNumber(text_args));

	createMessagePopup(resources.bold_font, resources.button_font);

	XawTextSetInsertionPoint(fromtext,  strlen(myCall));
	XawTextSetInsertionPoint(totext,    strlen(toCall));
	XawTextSetInsertionPoint(titletext, strlen(title));

	XtRealizeWidget(toplevel);
				
	XtAppMainLoop(app_context);
	
	return(0);
}

