/*
 *   Copyright (C) 1991-2000 by Jonathan Naylor HB9DRD/G4KLX
 *
 *   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 2 of the License, 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.
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <sys/stat.h>

#include <gtk/gtk.h>

#include "global.h"

#define	ERROR_BOX	0
#define	WARNING_BOX	1
#define	MESSAGE_BOX	2
#define	INFO_BOX	3
#define	YN_BOX		4
#define	EXIT_BOX	5

char *Files_Path              = VARDIR;

GSList *Sat_List              = NULL;
struct Sat_Struct *Sat_Chosen = NULL;

GSList *Loc_List              = NULL;

struct User_Struct User_Data = {
	"G4KLX",
	53.05,
	1.55,
	100.0,
	2,
	2,
	0,
	8,		/* World Map */
	{
	{0, 0, 0, 65535},
	{0, 65535, 65535, 65535},
	{0, 65535, 0, 0},
	{0, 0, 0, 0},
	{0, 65535, 0, 0},
	{0, 65535, 65535, 0}
	},
	"",		/* Startup Satellite */
	DATE_FORMAT_DDMMYYYY
};

static void FileCb(GtkWidget *, gpointer);
static void EditCb(GtkWidget *, gpointer);

GtkWidget *MapArea;
GtkWidget *MapText;

static GtkWidget *List_Ask_Entry[4];
static void ListAskCb(GtkWidget *, GtkWidget *);

static void Exit_Box(void);
static void ExitCb(GtkWidget *, GtkWidget *);

static gint TimeoutCb(gpointer);

static void Track_Sat(struct Sat_Struct *);
static void List_Sat(void);

static int Time_Offset;

static void General_Box(char *, char *, int);

static void YesCb(GtkWidget *, GtkWidget *);
static void NoCb(GtkWidget *, GtkWidget *);
static void (*Question_Yes)(void);
static void (*Question_No)(void);

static GtkItemFactoryEntry Menu_Items[] = {
	{"/_File",                      NULL,      NULL,     0, "<Branch>"},
	{"/File/New",                   NULL,      FileCb,   0, NULL},
	{"/File/sep",                   NULL,      NULL,     0, "<Separator>"},
	{"/File/Tracking Table",        NULL,      FileCb,   1, NULL},
	{"/File/Updated Elements",      NULL,      FileCb,   2, NULL},
	{"/File/Visibility",            NULL,      FileCb,   3, NULL},
	{"/File/sep",                   NULL,      NULL,     0, "<Separator>"},
	{"/File/Exit",                  NULL,      FileCb,   4, NULL},
	{"/_Edit",                      NULL,      NULL,     0, "<Branch>"},
	{"/Edit/Satellite",             NULL,      NULL,     0, "<Branch>"},
	{"/Edit/Satellite/Add",         NULL,      EditCb,   0, NULL},
	{"/Edit/Satellite/Delete",      NULL,      EditCb,   1, NULL},
	{"/Edit/Satellite/Modify",      NULL,      EditCb,   2, NULL},
	{"/Edit/Satellite/Import TLE",  NULL,      EditCb,   3, NULL},
	{"/Edit/Locations",             NULL,      NULL,     0, "<Branch>"},
	{"/Edit/Locations/Add",         NULL,      EditCb,   4, NULL},
	{"/Edit/Locations/Delete",      NULL,      EditCb,   5, NULL},
	{"/Edit/Locations/Modify",      NULL,      EditCb,   6, NULL},
	{"/Edit/Preferences",           NULL,      EditCb,   7, NULL},
	{"/Edit/Colours",               NULL,      NULL,     0, "<Branch>"},
	{"/Edit/Colours/Background",    NULL,      ColourCb, COLOUR_BACKGROUND, NULL},
	{"/Edit/Colours/Cities",        NULL,      ColourCb, COLOUR_CITIES, NULL},
	{"/Edit/Colours/Footprint",     NULL,      ColourCb, COLOUR_FOOTPRINT, NULL},
	{"/Edit/Colours/Land",          NULL,      ColourCb, COLOUR_LAND, NULL},
	{"/Edit/Colours/Satellite",     NULL,      ColourCb, COLOUR_SATELLITE, NULL},
	{"/Edit/Colours/User",          NULL,      ColourCb, COLOUR_USER, NULL},
	{"/_Map",                       NULL,      NULL,     0, "<Branch>"},
	{"/Map/Africa",                 NULL,      MapCb,    0, NULL},
	{"/Map/Asia",                   NULL,      MapCb,    1, NULL},
	{"/Map/Australasia",            NULL,      MapCb,    2, NULL},
	{"/Map/Europe",                 NULL,      MapCb,    3, NULL},
	{"/Map/N America",              NULL,      MapCb,    4, NULL},
	{"/Map/Pacific",                NULL,      MapCb,    5, NULL},
	{"/Map/S America",              NULL,      MapCb,    6, NULL},
	{"/Map/USA",                    NULL,      MapCb,    7, NULL},
	{"/Map/World",                  NULL,      MapCb,    8, NULL},
	{"/_Help",                      NULL,      NULL,     0, "<LastBranch>"},
	{"/Help/Mtrack Help",           NULL,      HelpCb,   1, NULL},
	{"/Help/Contents and Index",    NULL,      HelpCb,   0, NULL},
	{"/Help/sep",                   NULL,      NULL,     0, "<Separator>"},
	{"/Help/About Mtrack",          NULL,      AboutCb,  0, NULL}
};

int main(int argc, char **argv)
{
	GtkWidget *window;
	GtkWidget *menubar;
	GtkWidget *vbox;
	GtkWidget *separator;
	GtkItemFactory *item_factory;
	GtkAccelGroup *accel_group;
	struct Sat_Struct *Sat_Data;
	int nmenu_items = sizeof(Menu_Items) / sizeof(Menu_Items[0]);
	char *s;

	gtk_init(&argc, &argv);

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_main_quit), &window);

	gtk_window_set_title(GTK_WINDOW(window), "mtrack");
	gtk_container_set_border_width(GTK_CONTAINER(window), 0);

	vbox = gtk_vbox_new(FALSE, 1);
	gtk_container_border_width(GTK_CONTAINER(vbox), 1);
	gtk_container_add(GTK_CONTAINER(window), vbox);

	accel_group = gtk_accel_group_new();
	item_factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", accel_group);
	gtk_item_factory_create_items(item_factory, nmenu_items, Menu_Items, NULL);
	gtk_accel_group_attach(accel_group, GTK_OBJECT(window));

	menubar = gtk_item_factory_get_widget(item_factory, "<main>");
	gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
	gtk_widget_show(menubar);

	MapArea = gtk_drawing_area_new();
	gtk_drawing_area_size(GTK_DRAWING_AREA(MapArea), MAP_WIDTH, MAP_HEIGHT);
	gtk_signal_connect(GTK_OBJECT(MapArea), "expose_event", (GtkSignalFunc)MapAreaCb, NULL);
	gtk_box_pack_start(GTK_BOX(vbox), MapArea, FALSE, TRUE, 0);
	gtk_widget_show(MapArea);

	separator = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, TRUE, 0);
	gtk_widget_show(separator);

	MapText = gtk_drawing_area_new();
	gtk_drawing_area_size(GTK_DRAWING_AREA(MapText), MAP_WIDTH, MAP_TEXT_HEIGHT);
	gtk_signal_connect(GTK_OBJECT(MapText), "expose_event", (GtkSignalFunc)MapTextCb, NULL);
	gtk_box_pack_start(GTK_BOX(vbox), MapText, FALSE, TRUE, 0);
	gtk_widget_show(MapText);

	gtk_widget_show(vbox);

	if ((s = getenv("MTRACK_PATH")) != NULL)
		Files_Path = s;

	Read_Sat_Data();

	Read_Loc_Data();

	Read_User_Data();

	if ((Sat_Data = Find_Satellite_Name(User_Data.Startup)) != NULL)
		Track_Sat(Sat_Data);

	gtk_timeout_add(User_Data.Time_Interval * 1000L, TimeoutCb, NULL);

	gtk_widget_show(window);

	gtk_main();

	return 0;
}

static gint TimeoutCb(gpointer data)
{
	time_t Time_Now;
	struct tm *Tm_Time_Now;

	if (Sat_Chosen != NULL) {
		time(&Time_Now);
		Tm_Time_Now = gmtime(&Time_Now);
		Time_Now    = mktime(Tm_Time_Now);
		
		Track_Satellite(Time_Now + Time_Offset);
	}

	return TRUE;
}

static void FileCb(GtkWidget *w, gpointer data)
{
	int n = (int)data;
	
	switch (n) {
		case 0:
			Choose_Satellite(Track_Sat);
			break;
		case 1:
			if (Sat_Chosen != NULL)
				List_Sat();
			else
				Warning_Box("No satellite selected yet");
			break;
		case 2:
			if (Sat_Chosen != NULL)
				Show_Elements();
			else
				Warning_Box("No satellite selected yet");
			break;
		case 3:
			if (Sat_Chosen != NULL)
				Show_Locations();
			else
				Warning_Box("No satellite selected yet");
			break;
		case 4:
			Exit_Box();
			break;
		default:
			break;
	}
}

static void Track_Sat(struct Sat_Struct *Sat)
{
	Sat_Chosen = Sat;

	Time_Offset = User_Data.Time_Offset * 3600;
}

static void EditCb(GtkWidget *w, gpointer data)
{
	int n = (int)data;

	switch (n) {
		case 0:
			Add_Sat_Data();
			break;
		case 1:
			Delete_Sat_Data();
			break;
		case 2:
			Update_Sat_Data();
			break;
		case 3:
			Import_Sat_Data();
			break;
		case 4:
			Add_Loc_Data();
			break;
		case 5:
			Delete_Loc_Data();
			break;
		case 6:
			Update_Loc_Data();
			break;
		case 7:
			Update_User_Data();
			break;
		default:
			break;
	}	
}

static void General_Box(char *title, char *message, int type)
{
	GtkWidget *window;
	GtkWidget *vbox;
	GtkWidget *bbox;
	GtkWidget *label;
	GtkWidget *separator;
	GtkWidget *button[2];

	window = gtk_window_new(GTK_WINDOW_DIALOG);

	gtk_window_set_title(GTK_WINDOW(window), title);
	gtk_container_set_border_width(GTK_CONTAINER(window), BORDER_WIDTH);

	vbox = gtk_vbox_new(FALSE, BORDER_WIDTH);
	gtk_container_add(GTK_CONTAINER(window), vbox);

	label = gtk_label_new(message);
	gtk_box_pack_start(GTK_BOX(vbox), label, TRUE, TRUE, 0);

	separator = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(vbox), separator, TRUE, TRUE, 0);

	bbox = gtk_hbutton_box_new();
	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_SPREAD);
	gtk_box_pack_end(GTK_BOX(vbox), bbox, TRUE, TRUE, 0);

	switch (type) {
		case ERROR_BOX:
			button[0] = gtk_button_new_with_label("OK");
			gtk_container_add(GTK_CONTAINER(bbox), button[0]);
			gtk_signal_connect(GTK_OBJECT(button[0]), "clicked", ExitCb, window);
			GTK_WIDGET_SET_FLAGS(button[0], GTK_CAN_DEFAULT);
			gtk_widget_grab_default(button[0]);
			gtk_widget_show(button[0]);
			break;
		case WARNING_BOX:
		case MESSAGE_BOX:
		case INFO_BOX:
			button[0] = gtk_button_new_with_label("OK");
			gtk_container_add(GTK_CONTAINER(bbox), button[0]);
			gtk_signal_connect_object(GTK_OBJECT(button[0]), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
			GTK_WIDGET_SET_FLAGS(button[0], GTK_CAN_DEFAULT);
			gtk_widget_grab_default(button[0]);
			gtk_widget_show(button[0]);
			break;
		case YN_BOX:
			button[0] = gtk_button_new_with_label("Yes");
			button[1] = gtk_button_new_with_label("No");
			gtk_container_add(GTK_CONTAINER(bbox), button[0]);
			gtk_container_add(GTK_CONTAINER(bbox), button[1]);
			gtk_signal_connect(GTK_OBJECT(button[0]), "clicked", GTK_SIGNAL_FUNC(YesCb), window);
			gtk_signal_connect(GTK_OBJECT(button[1]), "clicked", GTK_SIGNAL_FUNC(NoCb), window);
			GTK_WIDGET_SET_FLAGS(button[0], GTK_CAN_DEFAULT);
			GTK_WIDGET_SET_FLAGS(button[1], GTK_CAN_DEFAULT);
			gtk_widget_grab_default(button[0]);
			gtk_widget_show(button[0]);
			gtk_widget_show(button[1]);
			break;
		case EXIT_BOX:
			button[0] = gtk_button_new_with_label("OK");
			button[1] = gtk_button_new_with_label("Cancel");
			gtk_container_add(GTK_CONTAINER(bbox), button[0]);
			gtk_container_add(GTK_CONTAINER(bbox), button[1]);
			gtk_signal_connect(GTK_OBJECT(button[0]), "clicked", ExitCb, window);
			gtk_signal_connect_object(GTK_OBJECT(button[1]), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
			GTK_WIDGET_SET_FLAGS(button[0], GTK_CAN_DEFAULT);
			GTK_WIDGET_SET_FLAGS(button[1], GTK_CAN_DEFAULT);
			gtk_widget_grab_default(button[0]);
			gtk_widget_show(button[0]);
			gtk_widget_show(button[1]);
			break;
		default:
			g_error("mtrack: unknown box type %d\n", type);
			break;
	}

	gtk_widget_show(label);
	gtk_widget_show(separator);
	gtk_widget_show(bbox);
	gtk_widget_show(vbox);
	gtk_widget_show(window);
}

void Error_Box(char *message)
{
	General_Box("Error from Mtrack", message, ERROR_BOX);
}

void Warning_Box(char *message)
{
	General_Box("Warning from Mtrack", message, WARNING_BOX);
}

void Message_Box(char *message)
{
	General_Box("Message from Mtrack", message, MESSAGE_BOX);
}

void Info_Box(char *message)
{
	General_Box("Information about Mtrack", message, INFO_BOX);
}

void YN_Box(char *message, void (*Yes)(void), void (*No)(void))
{
	Question_Yes = Yes;
	Question_No  = No;

	General_Box("Question from Mtrack", message, YN_BOX);
}

static void YesCb(GtkWidget *widget, GtkWidget *window)
{
	gtk_widget_destroy(window);
	
	if (Question_Yes != (void (*)(void))NULL)
		(*Question_Yes)();
}

static void NoCb(GtkWidget *widget, GtkWidget *window)
{
	gtk_widget_destroy(window);
	
	if (Question_No != (void (*)(void))NULL)
		(*Question_No)();
}

void Exit_Box(void)
{
	General_Box("Exit Mtrack", "Leave Mtrack ?", EXIT_BOX);
}

static void ExitCb(GtkWidget *widget, GtkWidget *window)
{
	Write_User_Data();

	gtk_widget_destroy(window);

	gtk_main_quit();
}

static void List_Sat(void)
{
	GtkWidget *window;
	GtkWidget *hbox;
	GtkWidget *table;
	GtkWidget *label[4];
	GtkWidget *button[3];
	GtkWidget *frame;
	GtkWidget *bbox;
	char Buffer[21];
	time_t Time_Now;
	struct tm *tm;
	int i;
	
	time(&Time_Now);
	tm = gmtime(&Time_Now);

	window = gtk_window_new(GTK_WINDOW_DIALOG);

	gtk_window_set_title(GTK_WINDOW(window), "Track List");
	gtk_container_set_border_width(GTK_CONTAINER(window), BORDER_WIDTH);

	hbox = gtk_hbox_new(FALSE, BORDER_WIDTH);
	gtk_container_add(GTK_CONTAINER(window), hbox);

	frame = gtk_frame_new(NULL);
	gtk_box_pack_start(GTK_BOX(hbox), frame, TRUE, TRUE, 0);

	table = gtk_table_new(4, 2, FALSE);
	gtk_container_add(GTK_CONTAINER(frame), table);

	label[0] = gtk_label_new("Start Date/Time");
	label[1] = gtk_label_new("End Date/Time");
	label[2] = gtk_label_new("Time Step");
	label[3] = gtk_label_new("Min Elevation");

	List_Ask_Entry[0] = gtk_entry_new_with_max_length(19);
	List_Ask_Entry[1] = gtk_entry_new_with_max_length(19);
	List_Ask_Entry[2] = gtk_entry_new_with_max_length(19);
	List_Ask_Entry[3] = gtk_entry_new_with_max_length(19);

	gtk_table_attach(GTK_TABLE(table), label[0], 0, 1, 0, 1,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), label[1], 0, 1, 1, 2,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), label[2], 0, 1, 2, 3,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), label[3], 0, 1, 3, 4,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), List_Ask_Entry[0], 1, 2, 0, 1,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), List_Ask_Entry[1], 1, 2, 1, 2,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), List_Ask_Entry[2], 1, 2, 2, 3,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);
	gtk_table_attach(GTK_TABLE(table), List_Ask_Entry[3], 1, 2, 3, 4,
		GTK_FILL | GTK_EXPAND, GTK_FILL | GTK_EXPAND, BORDER_ITEM, BORDER_ITEM);

	bbox = gtk_vbutton_box_new();
	gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_START);
	gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
	gtk_box_pack_end(GTK_BOX(hbox), bbox, TRUE, TRUE, 0);

	button[0] = gtk_button_new_with_label("OK");
	button[1] = gtk_button_new_with_label("Cancel");
	button[2] = gtk_button_new_with_label("Help");

	gtk_container_add(GTK_CONTAINER(bbox), button[0]);
	gtk_container_add(GTK_CONTAINER(bbox), button[1]);
	gtk_container_add(GTK_CONTAINER(bbox), button[2]);

	gtk_signal_connect(GTK_OBJECT(button[0]), "clicked", GTK_SIGNAL_FUNC(ListAskCb), window);
	gtk_signal_connect_object(GTK_OBJECT(button[1]), "clicked", GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
	gtk_signal_connect(GTK_OBJECT(button[2]), "clicked", GTK_SIGNAL_FUNC(HelpCb), (gpointer)7);

	GTK_WIDGET_SET_FLAGS(button[0], GTK_CAN_DEFAULT);
	GTK_WIDGET_SET_FLAGS(button[1], GTK_CAN_DEFAULT);
	GTK_WIDGET_SET_FLAGS(button[2], GTK_CAN_DEFAULT);
	gtk_widget_grab_default(button[0]);

	switch (User_Data.Date_Format) {
		case DATE_FORMAT_DDMMYYYY:
			sprintf(Buffer, "%02d-%02d-%04d %02d:%02d:%02d", 
					tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year,
					tm->tm_hour, tm->tm_min,     tm->tm_sec);
			break;
		case DATE_FORMAT_MMDDYYYY:
			sprintf(Buffer, "%02d/%02d/%04d %02d:%02d:%02d", 
					tm->tm_mon + 1, tm->tm_mday, 1900 + tm->tm_year,
					tm->tm_hour,    tm->tm_min,  tm->tm_sec);
			break;
		default:
			g_error("mtrack: unknown date format %d\n", User_Data.Date_Format);
			break;
	}

	gtk_entry_set_text(GTK_ENTRY(List_Ask_Entry[0]), Buffer);

	switch (User_Data.Date_Format) {
		case DATE_FORMAT_DDMMYYYY:
			sprintf(Buffer, "%02d-%02d-%04d 23:59:59", 
					tm->tm_mday, tm->tm_mon + 1, 1900 + tm->tm_year);
			break;
		case DATE_FORMAT_MMDDYYYY:
			sprintf(Buffer, "%02d/%02d/%04d 23:59:59", 
					tm->tm_mon + 1, tm->tm_mday, 1900 + tm->tm_year);
			break;
		default:
			g_error("mtrack: unknown date format %d\n", User_Data.Date_Format);
			break;
	}

	gtk_entry_set_text(GTK_ENTRY(List_Ask_Entry[1]), Buffer);

	sprintf(Buffer, "%d", User_Data.List_Interval);
	gtk_entry_set_text(GTK_ENTRY(List_Ask_Entry[2]), Buffer);

	gtk_entry_set_text(GTK_ENTRY(List_Ask_Entry[3]), "-5");

	for (i = 0; i < 4; i++) {
		gtk_widget_show(label[i]);
		gtk_widget_show(List_Ask_Entry[i]);
	}

	for (i = 0; i < 3; i++)
		gtk_widget_show(button[i]);

	gtk_widget_show(table);
	gtk_widget_show(bbox);
	gtk_widget_show(hbox);
	gtk_widget_show(frame);
	gtk_widget_show(window);
}

static void ListAskCb(GtkWidget *widget, GtkWidget *window)
{
	struct tm tm;
	time_t Start;
	time_t End;
	int    Step;
	double Elevation;
	char *s;
	int    Day, Month, Year;
	int    Hours, Minutes, Seconds;

	s = gtk_entry_get_text(GTK_ENTRY(List_Ask_Entry[0]));
	switch (User_Data.Date_Format) {
		case DATE_FORMAT_DDMMYYYY:
			if (sscanf(s, "%d-%d-%d %d:%d:%d", &Day, &Month, &Year, &Hours, &Minutes, &Seconds) != 6) {
				Warning_Box("Start Date/Time is in an\ninvalid format");
				return;
			}
			break;
		case DATE_FORMAT_MMDDYYYY:
			if (sscanf(s, "%d/%d/%d %d:%d:%d", &Month, &Day, &Year, &Hours, &Minutes, &Seconds) != 6) {
				Warning_Box("Start Date/Time is in an\ninvalid format");
				return;
			}
			break;
		default:
			g_error("mtrack: unknown date format %d\n", User_Data.Date_Format);
			break;
	}
	if (Day < 1 || Day > 31) {
		Warning_Box("Start Day is invalid");
		return;
	}
	if (Month < 1 || Month > 12) {
		Warning_Box("Start Month is invalid");
		return;
	}
	if (Year < 1990 || Year > 2010) {
		Warning_Box("Start Year is invalid");
		return;
	}
	if (Hours < 0 || Hours > 23) {
		Warning_Box("Start Hours is invalid");
		return;
	}
	if (Minutes < 0 || Minutes > 59) {
		Warning_Box("Start Minutes is invalid");
		return;
	}
	if (Seconds < 0 || Seconds > 59) {
		Warning_Box("Start Seconds is invalid");
		return;
	}
	tm.tm_mday = Day;
	tm.tm_mon  = Month - 1;
	tm.tm_year = Year - 1900;
	tm.tm_hour = Hours;
	tm.tm_min  = Minutes;
	tm.tm_sec  = Seconds;
	tm.tm_isdst= FALSE;
	Start = mktime(&tm);

	s = gtk_entry_get_text(GTK_ENTRY(List_Ask_Entry[1]));
	switch (User_Data.Date_Format) {
		case DATE_FORMAT_DDMMYYYY:
			if (sscanf(s, "%d-%d-%d %d:%d:%d", &Day, &Month, &Year, &Hours, &Minutes, &Seconds) != 6) {
				Warning_Box("End Date/Time is in an\ninvalid format");
				return;
			}
			break;
		case DATE_FORMAT_MMDDYYYY:
			if (sscanf(s, "%d/%d/%d %d:%d:%d", &Month, &Day, &Year, &Hours, &Minutes, &Seconds) != 6) {
				Warning_Box("End Date/Time is in an\ninvalid format");
				return;
			}
			break;
		default:
			g_error("mtrack: unknown date format %d\n", User_Data.Date_Format);
			break;
	}
	if (Day < 1 || Day > 31) {
		Warning_Box("End Day is invalid");
		return;
	}
	if (Month < 1 || Month > 12) {
		Warning_Box("End Month is invalid");
		return;
	}
	if (Year < 1990 || Year > 2010) {
		Warning_Box("End Year is invalid");
		return;
	}
	if (Hours < 0 || Hours > 23) {
		Warning_Box("End Hours is invalid");
		return;
	}
	if (Minutes < 0 || Minutes > 59) {
		Warning_Box("End Minutes is invalid");
		return;
	}
	if (Seconds < 0 || Seconds > 59) {
		Warning_Box("End Seconds is invalid");
		return;
	}
	tm.tm_mday = Day;
	tm.tm_mon  = Month - 1;
	tm.tm_year = Year - 1900;
	tm.tm_hour = Hours;
	tm.tm_min  = Minutes;
	tm.tm_sec  = Seconds;
	tm.tm_isdst= FALSE;
	End = mktime(&tm);

	if (Start >= End) {
		Warning_Box("End Time must be later than the\nStart Time");
		return;
	}

	s = gtk_entry_get_text(GTK_ENTRY(List_Ask_Entry[2]));
	Step = atoi(s) * 60;
	if (Step < 60) {
		Warning_Box("Time Step must be greater than zero");
		return;
	}

	s = gtk_entry_get_text(GTK_ENTRY(List_Ask_Entry[3]));
	Elevation = atof(s);
	if (Elevation < -90.0 || Elevation > 90.0) {
		Warning_Box("Min Elevation must be between\n+-90 degrees");
		return;
	}

	gtk_widget_destroy(window);

	List_Satellite(Start, End, Step, Elevation);
}
