
/***************************************************************************
 *   Copyright (C) 1997 to 2004 by Jonathan Duddington                     *
 *   email: jonsd@users.sourceforge.net                                    *
 *                                                                         *
 *   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 3 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 see:                           *
 *               <http://www.gnu.org/licenses/>.                           *
 ***************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>


#include "kernel.h"

#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "event.h"
#include "baricon.h"
#include "res.h"
#include "resspr.h"
#include "menu.h"
#include "template.h"
#include "dbox.h"
#include "saveas.h"
#include "xferrecv.h"
#include "werr.h"
#include "font.h"
#include "bbc.h"
#include "help.h"
#include "msgs.h"
#include "flex.h"
#include "os.h"
#include "time.h"
#include "locale.h"

#include "narc.h"
#include "hdrs.h"
#include "regexmod.h"

#include "dboxtcol.h"

#ifdef MemCheck
#include "MemCheck:MemCheck.h"
#endif
#ifdef MemCheck
#include "MemCheck:Flex.h"
#endif


extern unsigned int *ixlist_article;     /* card sorted by article address */
extern FOLDREC list_fr[N_LISTS];


static char *Version_String = "3.06 (09.04.13)";

char *mailer_name = "Pluto/3.06";


extern void init_menu(void);
extern void init_options(void);
extern void init_fold(void);
extern void init_cats(void);
extern void init_display(void);
extern void init_article(void);
extern void init_cards(void);
extern void init_text(void);
extern void init_reply(void);
extern void init_speak(void);
extern void init_search(void);
extern void init_import(void);
extern void init_blist(void);
extern void init_addr(void);
extern void init_textextra(void);
extern void init_spell(void);
extern void init_pgp(void);
extern void init_newsg(void);

extern void OLE_close_window(wimp_w w);
extern void OLE_started(wimp_eventdata *d,int ok);
extern void OLE_changed(wimp_eventdata *d);
extern void OLE_close(wimp_eventdata *d);


extern void display_field_selected(int *hits);
extern void options_font_selected(int *hits);
void attach_menu1(int on);
void call_event_process(int count);


extern int page_width;  /* ???? TEST */
extern OPTIONS options;
extern BLIST boxlist;
extern FOLDREC *search_cancel_flag;
extern int select_user_flag;
extern int speak_loaded;
int  regex_err = 0;
static int browser_fail_count = 0;

FILE *f_log=NULL;

void (*menu_expected)(int *) = NULL;
int  menu_expected_persist;
int  dbox_menu_field = 0;   /* field which has menu attached */
static wimp_menustr *current_menu;
static int current_menu_x;
static int current_menu_y;

char *pluto_path = "<Pluto$Dir>.";
char pluto_articles[128];
char *path_choices = "<Pluto$Dir>.Choices";
char *path_choices2 = "<Choices$Write>.Pluto";
int  using_ramfs;

int  null_event_map = 0;
int  window_open = 0;

int scroll_bar_width = 0;
int scroll_bar_height = 0;
int x_screen_dim;
int y_screen_dim;
int n_screen_colrs;
int min_extent;

int slotsize_msgs=0;  /* TEST */
int  os_version;
char os_version_string[8] = {0};

static int no_window=0;
static char *query_button2 = NULL;
static char *query_button3 = NULL;
menu menu_main;
menu menu_prefs;
int  pluto_slave=0;    /* 1 = don't allow changes to preferences and boxes */
int  pluto_lock=0;     /* 1 = use !Pluto.Articles.Lock to ensure only one copy can access articles */



static int system_shutdown = 0;
char *pluto_name="Pluto";
char *wipe_command = "Wipe <Wimp$ScrapDir>.Pluto.* ~C ~V";
char *msg_not_implemented = "Not implemented in this version";
int lock_expiry = 0;



int preserve_iconbar()
/******************/
/* Do we need to avoid hiding the iconbar */
{
	int  location=28;
	int  value;

	os_byte(161,&location,&value);
	if(value & 0x10)
		return(160);   /* icon bar height */
	else
		return(0);
}   /* end of preserve_iconbar */




int is_keypressed(int key)
/************************/
/* Check with internel code of key, see PRM 1-849 */
{
	os_regset regs;

	regs.r[0] = 129;   /* OS_Byte 129  Read keyboard for information */
	regs.r[1] = key ^ 0xff;
	regs.r[2] = 0xff;
	os_swix(0x06,&regs);
	return(regs.r[1]);
}   /* end of is_keypressed */




int read_os_variable(char *name,char *output,int max_length)
/**********************************************************/
{
	os_error *error;
	os_regset regs;

	output[0] = 0;

	regs.r[0] = (int)name;
	regs.r[1] = (int)output;
	regs.r[2] = -1;
	regs.r[3] = 0;
	regs.r[4] = 0;
	os_swix(0x23,&regs);     /* OS_ReadVarVal */

	if(regs.r[2] == 0)
		return(1);   /* not found */

	regs.r[2] = - regs.r[2];
	if(regs.r[2] > max_length)
		return(2);   /* too long */

	regs.r[0] = (int)name;
	regs.r[3] = 0;
	error = os_swix(0x23,&regs);
	if(error)
		return(3);

	output[regs.r[2]] = 0;   /* string terminator */
	return(0);
}   /* end of read_os_variable */





int read_os_variable2(char *name,char *output,int max_length)
/******************************************************/
/* Read OS variable and convert to canonical form */
{
	int  i;
	os_regset regs;
	char buf[200];

	i = read_os_variable(name,buf,sizeof(buf));
	if(i != 0)
		return(i);

	regs.r[0] = 37;         /* convert pathname to cononical form */
	regs.r[1] = (int)buf;
	regs.r[2] = (int)output;
	regs.r[3] = 0;
	regs.r[4] = 0;
	regs.r[5] = max_length;
	os_swix(0x29,&regs);     /* OS_FSControl 37 */
	return(0);
}   /* end of read_os_variable2 */




void set_os_variable(char *name, char *value)
/***************************************/
{
	os_regset regs;

	regs.r[0] = (int)name;
	regs.r[1] = (int)value;
	regs.r[2] = strlen(value);
	regs.r[3] = 0;
	regs.r[4] = 0;
	os_swix(0x24,&regs);
}   /* end of set_os_variable */


int get_task_handle(char *name)
/*****************************/
{
	os_regset regs;

	struct {
		int handle;
		char *name;
		int size;
		int flags;
	} buf;

	regs.r[0] = 0;
	for(;;)
	{
		regs.r[1] = (int)&buf;
		regs.r[2] = sizeof(buf);
		os_swi(0x42681,&regs);   /* TaskManager_EnumerateTasks */
		if(strcmp(name,buf.name)==0)
		{
			return(buf.handle);
		}

		if(regs.r[0] < 0)
			break;
	}
	return(0);
}   /* end of get_task_handle */



void dbox_hidefield (dbox d, dbox_field f)
{

	/* set shaded bit in iconflags */
	wimpt_noerr(wimp_set_icon_state (dbox_syshandle(d), dbox__fieldtoicon(f),
									 wimp_IDELETED, wimp_IDELETED));
}




void dbox_fade_list(dbox d, char *list, int fade)
/***********************************************/
{
	int  i;

	while((i = *list++) != 0)
	{
		if(fade)
			dbox_fadefield(d,i);
		else
			dbox_unfadefield(d,i);
	}
}   /* end of dbox_fade_list */





void dirlist_open(char *path,char *flags)
/***************************************/
{
	wimp_mousestr m;
	char command[256];

	wimp_get_point_info(&m);
	sprintf(command,"Filer_OpenDir %s %s",path,flags);
	os_cli(command);
	return;

}   /* end of dirlist_open */





void set_colour(unsigned int colour,int fground,int action)
/********************************************************/
{
	os_swi6(0x40743,colour,0,0,fground,action,0);  /* ColourTrans_SetGCOL */
}



void set_focus(wimp_w w)
/**********************/
{
	wimp_caretstr caret;

	if(w == NULL)
		return;

	/* set input focus, but invisible caret */
	caret.w = w;
	caret.i = -1;
	caret.x = 0;
	caret.y = 0;
	caret.height = 0x1000000;   /* invisible */
	caret.index = 0;
	wimp_set_caret_pos(&caret);
}   /* end of set_focus */




void set_input_focus(wimp_w w, int icon, int index)
/********************************************/
{
	wimp_caretstr caretstr;

	caretstr.w = w;
	caretstr.i = icon;
	caretstr.x = 0;
	caretstr.y = 0;
	if(icon == -1)
		caretstr.height = 0x2000000;    /* invisible */
	else
		caretstr.height = -1;    /* set from icon */
	caretstr.index = index;
	wimp_set_caret_pos(&caretstr);
}   /* end of set_input_focus */



void icon_set_caret_pos(wimp_w w, int field, int end)
/**********************************************/
{
	wimp_caretstr caretstr;

	memset(&caretstr,0,sizeof(caretstr));
	caretstr.w = w;
	caretstr.i = field;
	caretstr.height = -1;
	if(end)
		caretstr.index = 512;

	wimp_set_caret_pos(&caretstr);
}   /* end of icon_set_caret_pos */






void set_icon_state(wimp_w w, int icon, int state)
/************************************************/
{
	if(state != 0)
		state = wimp_ISELECTED;
	wimp_set_icon_state(w,icon,state,wimp_ISELECTED);

}   /* end of set_icon_state */



void wimp_hide_window(wimp_w w)
/**************************/
/* Hide behind the background, don't change position */
{
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);
	wstate.o.behind = -3;
	wimp_open_wind(&wstate.o);
}   /* end of wimp_hide_window */




void set_dbox_at_pointer(dbox d)
/******************************/
/* Set screen coordinates of dbox so it is by the pointer */
{
	wimp_w w;
	int  x_size;
	int  y_size;
	wimp_mousestr m;
	wimp_wstate wstate;

	wimp_get_point_info(&m);

	w = dbox_syshandle(d);

	wimp_get_wind_state(w,&wstate);
	x_size = wstate.o.box.x1 - wstate.o.box.x0;
	y_size = wstate.o.box.y1 - wstate.o.box.y0;

	/* ensure that the dbox is completely on the screen */
	if((m.x + x_size) > x_screen_dim)
		wstate.o.box.x0 = x_screen_dim - x_size;
	else
		wstate.o.box.x0 = m.x+20;
	wstate.o.box.x1 = wstate.o.box.x0 + x_size;

	if((m.y - y_size) < 0)
		wstate.o.box.y1 = y_size;
	else
		wstate.o.box.y1 = m.y;
	wstate.o.box.y0 = m.y - y_size;

	wimp_open_wind(&wstate.o);
}   /* end of set_dbox_at_pointer */



void dbox_menu(wimp_menustr *wmenu,void(*proc)(int *),wimp_mousestr *mouse)
/*************************************************************************/
/* Display menu and call 'proc' when a selection is made */
{
	wimp_mousestr mouse_str;

	if(mouse == NULL)
	{
		wimp_get_point_info(&mouse_str);
		mouse = &mouse_str;
	}
	current_menu = wmenu;
	current_menu_x = mouse->x - 40;
	current_menu_y = mouse->y + 20;

	event_clear_current_menu();
	wimp_create_menu(current_menu,current_menu_x,current_menu_y);
	menu_expected = proc;
	menu_expected_persist = 0;
}   /* dbox_menu */



int dbox_range_check(int value, int lower, int upper)
/***************************************************/
{
	if(value < lower)
	{
		beep();
		return(lower);
	}
	if(value > upper)
	{
		beep();
		return(upper);
	}
	return(value);
}   /* end of dbox_range_check */





int search_regex_compile(char *string, int case_sensitive)
/***************************************************/
{
	static int  handle = 0;
	static int default_syntax = -1;

	os_error *error;
	os_regset regs;

	error = os_swix(REGX_GetDefaultSyntax,&regs);
	if(error && (error->errnum == 486))
	{
		regex_load();
		error = os_swix(REGX_GetDefaultSyntax,&regs);
	}

	if(error == NULL)
	{
		default_syntax = regs.r[0];
	}

	if(error == NULL)
	{
		regs.r[0] = handle;
		regs.r[1] = (int)string;
		regs.r[3] = 0;

		if(case_sensitive == 0)
			regs.r[2] = default_syntax | RE_CASE_INSENSITIVE;
		else
			regs.r[2] = default_syntax & ~RE_CASE_INSENSITIVE;

		error = os_swix(REGX_CompileExtendedPattern,&regs);
	}

	if(error)
	{
		werr(0,"REGEX:  %s",error->errmess);
		search_cancel_flag = NULL;
		regex_err = 1;
		return(-1);
	}

	handle = regs.r[0];
	return(handle);
}   /* end of search_regex_compile */




int search_regex(char *string, int length, char **anchor, int from, int len,
				 int case_sensitive, int regex, int *found_len)
/************************************************************************************************/
/* regex= 0 no regex, -1 regex on string, other: precompiled regex handle */
{
	int *result;
	int *r_starts;
	int *r_ends;
	os_error *error;
	os_regset regs;

	if(regex == 0)
	{
		if(found_len != NULL)
			*found_len = strlen(string);
		return(search_string(string,length,anchor,from,len,case_sensitive));
	}

	if(regex == -1)
	{
		regs.r[0] = search_regex_compile(string, case_sensitive);
	}
	else
	{
		regs.r[0] = regex;   /* precompiled */
	}

	regs.r[1] = (int)(*anchor);
	regs.r[2] = from+len;
	regs.r[3] = from;
	regs.r[4] = -1;
	error = os_swix(REGX_Search,&regs);

	if(error)
	{
		werr(0,"REGEX:  %s",error->errmess);
		search_cancel_flag = NULL;
		regex_err = 1;
		return(-1);
	}

	if(regs.r[5] >= 0)
	{
		result = (int *)regs.r[6];
		r_starts = (int *)result[1];
		r_ends = (int *)result[2];

		if(found_len != NULL)
			*found_len = r_ends[0] - r_starts[0];
		return(r_starts[0]);
	}
	return(-1);
}   /* end of search_regex */






int query_dcs(char *text)
/***********************/
/* Display  Cancel  Save   RISC OS 3.5 and later only */
{
	os_regset regs;
	os_error error;

	error.errnum = 201;
	strcpy(error.errmess,text);

	regs.r[0] = (int)&error;
	regs.r[1] = 0x900;
	regs.r[2] = (int)"Pluto";
	regs.r[3] = 0;
	regs.r[4] = 1;
	regs.r[5] = (int)"Save,Cancel,Discard";

	os_swi(0x400df,&regs);   /* wimp report error */

	return(regs.r[1]);

}   /* end of query_dcs */



int query(char *text, char *button)
/*********************************/
/* Answers 1 for YES */
{
	dbox d;
	int  beeping = 0x90;  /* 0x90 = no beep, 0x00 = beep */

	int answer=0;
	os_regset regs;
	os_error error;
	char buttons[32];

	if(os_version >= 0xa5)
	{
		error.errnum = 201;
		strcpy(error.errmess,text);


		regs.r[0] = (int)&error;
		regs.r[1] = 0x903 + beeping;
		regs.r[2] = (int)"Pluto";
		regs.r[3] = (int)"";
		regs.r[4] = 1;
		regs.r[5] = 0;

		if(button != NULL)
		{
			if(query_button2 == NULL)
				sprintf(buttons,"%s,Cancel",button);
			else
			{
				sprintf(buttons,"%s,%s",button,query_button2);
				if(query_button3 != NULL)
					sprintf(buttons,"%s,%s,%s",button,query_button2,query_button3);
			}

			regs.r[1] = 0x900 + beeping;
			regs.r[5] = (int)buttons;
		}

		query_button2 = NULL;
		query_button3 = NULL;
		os_swi(0x400df,&regs);   /* wimp report error */

		if((regs.r[1] == 4) || (regs.r[1] == 2))
			return(0);
		if(regs.r[1] == 5)
			return(2);
		else
			return(1);
	}

	d = dbox_new("Query");
	dbox_setfield(d,3,text);
	if(button != NULL)
		dbox_setfield(d,0,button);

	if(query_button2 != NULL)
	{
		dbox_setfield(d,1,query_button2);
	}

	if(query_button3 != NULL)
	{
		dbox_setfield(d,2,query_button3);
	}
	else
	{
		wimp_set_icon_state(dbox_syshandle(d),2,wimp_IDELETED,wimp_IDELETED);
	}
	query_button2 = NULL;
	query_button3 = NULL;

	dbox_show(d);

	answer = dbox_fillin(d);
	if(answer == 0)
		answer = 1;
	else if(answer == 1)
		answer = 0;
	dbox_dispose(&d);
	return(answer);
}   /* end of query */


int query2(char *text, char *button, char *button2)
/*************************************************/
{
	query_button2 = button2;
	return(query(text,button));
}   /* end of query2 */


int query3(char *text, char *button, char *button2, char *button3)
/****************************************************************/
/* Return: 0=button2, 1=button, 2=button3 */
{
	query_button3 = button3;
	return(query2(text,button,button2));
}   /* end of query3 */



int user_message(char *text)
/**************************/
/* Display a message in a dialogue box */
{
	dbox d;
	int answer=0;

	d = dbox_new("Message");
	if(d != NULL)
	{
		dbox_setfield(d,0,"OK");
		dbox_setfield(d,1,text);
		dbox_show(d);

		dbox_fillin(d);
		dbox_dispose(&d);
	}
	return(answer);
}   /* end of user_message */




int get_button_state(wimp_w w, int icon)
/**********************************/
{
	wimp_icon  icon_info;

	wimp_get_icon_info(w,icon,&icon_info);
	return((icon_info.flags & wimp_ISELECTED) >> 21);
}   /* end of get_button_state */





void set_button_state(wimp_w w, int icon, int state, int flag)
/*******************************************************/
/* 'state' is 1 or 0 for set or unset */
{
	int  i = 0;

	if(state)
		i = flag;
	wimp_set_icon_state(w,icon,i,flag);
}   /* end of set_button_state */




void null_events(int type, int on)
/********************************/
/* type=1 speech,  2=drags  4=expire  8=articles->find_fault */
{
	if(on)
		null_event_map |= type;
	else
		null_event_map &= ~type;

	if(null_event_map == 0)
		event_setmask(0x01);    /* null events off */
	else
		event_setmask(0x00);    /* null events on */

}   /* end of null_events */



void reopen_window(wimp_w w, int behind)
/**************************************/
/* Re-open a window, if it is already open */
{
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);

	if(behind != 0)
		wstate.o.behind = behind;

	if(wstate.flags & wimp_WOPEN)
		wimp_open_wind(&wstate.o);

}   /* end of reopen_text_window */




char *get_leaf_name(char *fname)
/******************************/
{
	int  i;

	for(i=strlen(fname)-2; i>=0; i--)
	{
		if(fname[i] == '.')
			return(&fname[i+1]);
	}
	return(fname);
}   /* end of get_leaf_name */



int get_filelength(char *fname)
/*****************************/
{
	int length=0;
	int type;
	os_error *error;

	error = os_swi6r(0x20008,5,(int)fname,0,0,0,0, &type,NULL,NULL,NULL,&length,NULL);
	if(error)
		return(0);

	if((type!=1) && (type!=3))
		return(0);   /* not a file */

	return(length);
}   /* end of get_filelength */



int get_filetype(char *fname)
/**************************/
{
	os_error *error;
	os_regset regs;

	regs.r[0] = 23;
	regs.r[1] = (int)fname;
	error = os_swix(0x8,&regs);
	if(error)
		return(-1);
	return(regs.r[6]);
}   /* end of get_filetype */



void set_filetype(char *filename, int ftype)
/******************************************/
{
	os_filestr filestr;

	filestr.action = 18;   /* set filetype */
	filestr.name = filename;
	filestr.loadaddr = ftype;   /* text */
	os_file(&filestr);
}   /* end of set_filetype */



void file_ensure_exists(char *fname)
/**********************************/
{
	FILE *f;

	f = fopen(fname,"a");
	if(f != NULL)
		fclose(f);    /* ensure the file exists */
}   /* end of file_ensure_exists */



void dataopen(char *fname, int ftype)
/***********************************/
{
	wimp_msgstr msg;

	if(ftype >= 0)
		set_filetype(fname,ftype);

	msg.data.dataopen.w = -1;
	msg.data.dataopen.i = -1;
	msg.data.dataopen.x = 0;
	msg.data.dataopen.y = 0;
	msg.data.dataopen.size = get_filelength(fname);
	msg.data.dataopen.type = ftype;
	strcpy(msg.data.dataopen.name,fname);

	msg.hdr.size = (strlen(msg.data.dataopen.name) + 44 + 4) & ~3;
	msg.hdr.your_ref = 0;
	msg.hdr.action = wimp_MDATAOPEN;

	file_ensure_exists(fname);

	wimp_sendmessage(wimp_ESENDWANTACK,&msg,0);
}   /* end of dataopen */



void err_internal(int number, int value)
/**************************************/
{
	werr(0,"Pluto internal error:  number %d  value &%x",number,value);
}   /* end of err_internal */


void err_please_run(char *app)
/****************************/
{
	werr(0,"Please run !%s to set system variables, and repeat",app);
}   /* end of err_please_run */




int pointer_sanity_check(int number, void *ptr)
/*********************************************/
{
	if(((int)ptr & ~0x1fff) == 0)
	{
		err_internal(number,(int)ptr);
		return(-1);
	}
	return(0);
}   /* end of pointer_sanity_check */



void malloc_err_string(int number, char *string)
/**********************************************/
{
	werr(0,"Failed (%d) to allocate memory %s",number,string);
}   /* end of malloc_err_string */




void malloc_err(int number)
/*************************/
{
	char *extra;

	switch(number >> 8)
	{
	case 1:
		extra = "for Text";
		break;
	case 2:
		extra = "for Attachment";
		break;
	default:
		extra = "";
		break;
	}
	malloc_err_string(number,extra);
}   /* end of malloc_err */





void *malloc_dont_budge(int size)
/*******************************/
/* Try to malloc without letting the heap expand.
   If it can't allocate the required memory, then let it expand */
{
	void *p;

//   _kernel_register_slotextend(flex_dont_budge);
	p = malloc(size);
//   _kernel_register_slotextend(flex_budge);

	if(p != NULL)
		return(p);

	return(malloc(size));
}   /* end of malloc_dont_budge */




BOOL help_handler(void *event, int id)
/************************************/
{
	int  icon;
	int  window;
	wimp_eventstr *ev;
	wimp_msgstr *msg;
	char *p;
	char help_id[12];

	ev = (wimp_eventstr *)event;

	if(ev->e == wimp_ESENDWANTACK)
	{
		msg = &ev->data.msg;

		if(msg->hdr.action == wimp_MHELPREQUEST)
		{
			p = NULL;
			icon = msg->data.helprequest.m.i;
			window = msg->data.helprequest.m.w;

			if(icon < 0)
				icon = 99;

			switch(id)
			{
			}

			sprintf(help_id,"%c%d:",id,icon);
			p = msgs_lookup(help_id);

			if(p != NULL)
			{
				if(p[0] == 0)
					return(FALSE);

				help_reply(p);
				return(TRUE);
			}
			return(TRUE);
		}
	}
	return(FALSE);

}   /* end of help_handler */



BOOL dbox_help_handler(dbox d, void *event, void *handle)
/********************************************************/
{
	return(help_handler(event,(int)handle));
}   /* end of dbox_help_handler */






int check_mode()
/*************/
/* Get screen dimensions from current mode.
   Return whether they have changed from previous values */
{
	int  x;
	int  y;
	int  changed = 0;
	static int vdu_read_block[] = {4,5,11,12,3,-1};

	struct {
		int  XEigFactor;
		int  YEigFactor;
		int  XWindLimit;
		int  YWindLimit;
		int  NColour;
	}  vdu_values;

	/* OS_ReadVduVariables */
	os_swi2(0x31,(int)vdu_read_block,(int)&vdu_values);

	x = vdu_values.XWindLimit << vdu_values.XEigFactor;
	y = vdu_values.YWindLimit << vdu_values.YEigFactor;

	if((x != x_screen_dim) || (y != y_screen_dim))
		changed = 1;

	x_screen_dim = x;
	y_screen_dim = y;
	n_screen_colrs = vdu_values.NColour+1;
	if(n_screen_colrs==0)
		n_screen_colrs=0x10000;

	min_extent = y_screen_dim - 160;

	return(changed);
}   /* end of check_mode */





void scroll_window(wimp_eventdata *d)
/***********************************/
{
	int  window_width;
	int  window_height;
	wimp_openstr *s;

	s = &d->scroll.o;
	window_width = s->box.x1 - s->box.x0;
	window_height = s->box.y1 - s->box.y0 - 40;

	/* switch on button type */
	switch(d->scroll.y)
	{
	case 1:
		s->y += 40;
		break;

	case 2:
		s->y += window_height;
		break;

	case -1:
		s->y -= 40;
		break;

	case -2:
		s->y -= window_height;
		break;
	}

	switch(d->scroll.x)
	{
	case 1:
		s->x += 40;
		break;

	case 2:
		s->x += window_width;
		break;

	case -1:
		s->x -= 40;
		break;

	case -2:
		s->x -= window_width;
		break;
	}
	wimp_open_wind(s);

}   /* end of scroll_window */




int scroll_page(wimp_w w, int up)
/*******************************/
{
	int  window_height;
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);
	window_height =wstate.o.box.y1 - wstate.o.box.y0 - 40;
	wstate.o.y += (window_height * up);
	wimp_open_wind(&wstate.o);
	return(wstate.o.y);
}   /* end of scroll_page */


void scroll_to_top(wimp_w w, int up)
/**********************************/
{
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);

	if(up==1)
		wstate.o.y = -0x7fffffff;
	else
		wstate.o.y = 0;
	wimp_open_wind(&wstate.o);
}   /* end of scroll_to_top */






int scroll_to_y2(wimp_w w,int y1, int y2)
/***************************************/
/* Scroll the window to ensure the specified coordinate is on the screen */
{
	int  dy;
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);
	dy = wstate.o.box.y1 - wstate.o.box.y0;    /* window height */
	if(y1 > (wstate.o.y - 40))
	{
		wstate.o.y = y1 + 40;     /* scroll by this amount */
		wimp_open_wind(&wstate.o);
	}
	else if(y2 < (wstate.o.y - dy))
	{
		wstate.o.y = y2 + dy;
		wimp_open_wind(&wstate.o);
	}
	return(wstate.o.y);
}   /* end of scroll_to_y2 */


int scroll_to_y(wimp_w w, int y)
/******************************/
{
	return(scroll_to_y2(w,y,y));
}   /* end of scroll_to_y */



int scroll_by_y(wimp_w w, int by)
/*******************************/
{
	wimp_wstate wstate;

	wimp_get_wind_state(w,&wstate);
	wstate.o.y += by;
	wimp_open_wind(&wstate.o);
	return(wstate.o.y);
}   /* end of scroll_by_y */




void open_main_window()
/*********************/
{
}   /* end of open_main_window */



char wimpscrap_leafname[31];



char *wimpscrap_check(char *filename)
/***********************************/
{
	if((strcmp_lc(filename,"<wimp$scrap>")==0) && (wimpscrap_leafname[0] != 0))
		return(wimpscrap_leafname);
	else
		return(filename);
}   /* end of xferrecv_check_wimpscrap */




void wimpscrap_check_clear()
/**************************/
{
	wimpscrap_leafname[0] = 0;
}   /* end of wimpscrap_check_clear */




void xferrecv_wimpscrap(wimp_eventstr *e)
/***************************************/
{
	wimp_msgstr xferrecv_ack ;
	wimp_t sendertask;

	/* remember leafname for when we get the Dataload message */
	strncpy0(wimpscrap_leafname,e->data.msg.data.datasave.leaf,sizeof(wimpscrap_leafname));

	/* reply with DataSaveAck */
	xferrecv_ack.hdr.size = sizeof(wimp_msghdr) + sizeof(wimp_msgdatasaveok) ;
	sendertask = e->data.msg.hdr.task ;
	xferrecv_ack.hdr.your_ref = e->data.msg.hdr.my_ref ;
	xferrecv_ack.hdr.action = wimp_MDATASAVEOK ;
	xferrecv_ack.data.datasaveok.w = e->data.msg.data.datasave.w ;
	xferrecv_ack.data.datasaveok.i = e->data.msg.data.datasave.i ;
	xferrecv_ack.data.datasaveok.x = e->data.msg.data.datasave.x ;
	xferrecv_ack.data.datasaveok.y = e->data.msg.data.datasave.y ;
	xferrecv_ack.data.datasaveok.estsize = -1 ;
	xferrecv_ack.data.datasaveok.type = e->data.msg.data.datasave.type ;
	strcpy(xferrecv_ack.data.datasaveok.name,"<Wimp$Scrap>");
	wimp_sendmessage(wimp_ESEND, &xferrecv_ack, sendertask);
}   /* end of xferrecv_wimpscrap */






void icon_load_handler(wimp_eventstr *e, void *handle)
/****************************************************/
/* Event handler for the Icon */
{
	int filetype;
	char *filename;

	/* Deal with event */
	switch (e->e)
	{
	case wimp_ENULL:
		if(null_event_map & 1)
			speak_text_continue();

		if(null_event_map & 2)
			drag_continue();

		if(null_event_map & 4)
			expire_articles(0);

		if(null_event_map & 8)
			article_files_search_fault(0);

		break;

	case wimp_ECLOSE:  /* Pass on close request */
		wimpt_noerr(wimp_close_wind(e->data.o.w));
		window_open = FALSE;
		break;

	case wimp_ESEND:
	case wimp_ESENDWANTACK:
		switch(e->data.msg.hdr.action)
		{
		case wimp_MDATASAVE:     /* import data */
			xferrecv_wimpscrap(e);
			break;

		case wimp_MDATALOAD:     /* insert data */
			filetype = xferrecv_checkinsert(&filename);

			load_article(filename,filetype,1,-1,NULL,0);
			xferrecv_insertfileok();
			break;

		}
		break;

	case wimp_EACK:
		break;

	default:   /* Ignore any other event */
		break;
	}
}  /* end of icon_load_handler */






static void info_about_program(void)
/**********************************/
{
	dbox  d;  /* Dialogue box handle */

	/* Create the dialogue box */
	d = dbox_new("ProgInfo");
	if(d != NULL)
	{
		/* Fill in the version number */
		dbox_setfield(d, 0, Version_String);

		/* Show the dialogue box */
		dbox_show(d);

		/* Keep it on the screen as long as needed */
		dbox_fillin(d);

		/* Dispose of the dialogue box */
		dbox_dispose(&d);
	}
}   /* end of info_about_program */



static void pre_quit(wimp_eventdata *d)
/*************************************/
{
	int sender;
	int flags;

	struct {
		wimp_caretstr c;
		int chcode;
	} key;

	sender = d->msg.hdr.task;
	wimp_get_caret_pos(&key.c);

	if(d->msg.hdr.size > 20)
		flags = d->msg.data.words[0];
	else
		flags = 0;

	if(text_record_check_changed()==0)
	{
		system_shutdown = 1;
		return;   /* no unsaved data */
	}

	if(query("Text window contains unsaved data","Quit")==0)
	{
		/* send ack to prevent the shutdown */
		d->msg.hdr.your_ref = d->msg.hdr.my_ref;
		wimp_sendmessage(wimp_EACK,&d->msg,sender);
		return;
	}

	system_shutdown = 1;

	if(flags & 1)
	{
		return;   /* just quit this task */
	}

	return;
	/* The following code causes an error in RISC OS
	   abort on data transfer: &21d37e8 */

	key.chcode = 0x1fc;   /* CTRL-SHIFT-F12 */

	/* restart shutdown sequence by sending CTRL-SHIFT-F12 key to task manager */
	wimp_sendmessage(8,(wimp_msgstr *)&key,sender);
}   /* end of pre_quit */



void proc_iconclick(wimp_i icon)
/******************************/
/* Event handler for left click on the Icon */
{
	if(check_lock_lists(1)!=0)
		return;   /* remaking index */

	boxlist_click_open(0);
}   /* end of proc_iconclick */



void browser_not_running(wimp_msgstr *msg)
/****************************************/
/* "Ack" wimp message (wimp_M_URL) received in response to our attempt to pass URL to
   Fresco.  This means that Fresco is not running. */
{
	int  done;
	char *p;
	os_error *error;
	char buf[256];

	static char browsers[] = {0,X_WEBVOYAGE,X_ARCWEB,X_FRESCO,X_WEBVOYAGE,0,0};

	/* could try running the browser and re-trying, if we knew how */
	done = 1;
	if(read_os_variable("Alias$URLopen_HTTP",buf,sizeof(buf)) == 0)
	{
		/* we can use this to start Fresco running */

		p = msg->data.chars;

		if(strlen(p) > 128)
			p = "http:\\";

		sprintf(buf,"URLopen_HTTP %s",p);

		error = os_swi1(0x400de + os_X,(int)buf);   /* Wimp_StartTask */
		return;
	}


	{
		switch(browsers[options.mail_transport])
		{
		case X_WEBVOYAGE:
			read_os_variable("VTiInternet$Dir",buf,sizeof(buf));
			if(buf[0] == 0)
			{
				werr(0,"Voyager is not running");
				return;
			}

			sprintf(buf,"Run <VTiInternet$Dir>.Apps.Web.!Run");
			break;

		case X_FRESCO:
			read_os_variable("Fresco$Dir",buf,sizeof(buf));
			if(buf[0] == 0)
			{
				werr(0,"Fresco has not been seen by filer");
				return;
			}

			sprintf(buf,"Run <Fresco$Dir>.!Run");
			break;

		case X_ARCWEB:
			read_os_variable("ArcWeb$Dir",buf,sizeof(buf));
			if(buf[0] == 0)
			{
				werr(0,"ArcWeb has not been seen by filer");
				return;
			}

			sprintf(buf,"Run <ArcWeb$Dir>.!Run");
			break;

		default:
			done = 0;
		}
	}

	if(done)
	{
		error = os_swi1(0x400de + os_X,(int)buf);   /* Wimp_StartTask */
	}

	if(done && !error && (browser_fail_count == 0))
	{
		browser_fail_count = 1;
		os_swi3(0x400e7,18,(int)msg,0);    /* Wimp_SendMessage, return ACK if not acknowledged */
	}
	else
	{
		werr(0,"Web browser is not running");
	}

}   /* end of browser_not_running */




BOOL unknown_event_handler(wimp_eventstr *e, void *handle)
/********************************************************/
/* Event handler for the Icon */
{
	int  dealt_with = FALSE;
	int *hits;
	wimp_msgstr *m;
	char *fname;
	char buf[24];
	char buf2[1];


	/* Deal with event */
	switch (e->e)
	{
	case wimp_ENULL:
		if(null_event_map & 1)
			speak_text_continue();

		if(null_event_map & 2)
			drag_continue();
		break;

	case wimp_EUSERDRAG:
		null_events(2,0);     /* turn off for drag */
		drag_complete();
		return(TRUE);

	case wimp_ESEND:
	case wimp_ESENDWANTACK:
		m = &e->data.msg;

		switch(e->data.msg.hdr.action)
		{
		case wimp_MPREQUIT:   /* 8  Message_PreQuit */
			pre_quit(&e->data);
			break;

		case wimp_MMODECHANGE:  // 0x400c1
			if(check_mode())
				change_display_mode2();
			break;

		case wimp_MSLOTCHANGE:  // 0x400c4  Slot size has altered
			slotsize_msgs++;
			break;

		case 0x400c9:  /* Message_MenusDeleted */
			blist_menu_deleted(e->data.msg.data.words[0]);
			break;

		case 0x400cc:  /* Message_Windowinf  - from Pinboard */
			iconise_aviewer(e->data.msg.data.words[0]);
			break;

		case 15:    /* Message_ClaimEntity */
			claim_entity_request(&e->data);
			break;

		case 16:    /* Message_DataRequest */
			clipboard_request(&e->data);
			break;

		case 17:    /* Message_Dragging */
			dragdrop_request(&e->data);
			break;

		case 18:    /* Message_DragClaim */
			dragdrop_claim(&e->data);
			break;

		case wimp_MPrintFile:
			return(FALSE);

		case wimp_MDATASAVEOK:
			if(print_datasaveack(&e->data))
				return(TRUE);
			return(clipboard_send(&e->data));

		case wimp_M_URL:
			reply_M_URL(&e->data,1);   /* ANT URI request */
			return(TRUE);

		case 0x4e382:   /* Acorn URI_Request */
			reply_M_URL(&e->data,0);
			return(TRUE);

		case message_OLEOpenSessionAck:
			OLE_started(&e->data,1);
			return(TRUE);

		case message_OLEFileChanged:
			OLE_changed(&e->data);
			return(TRUE);

		case message_OLECloseSession:
			OLE_close(&e->data);
			return(TRUE);

		case 0x4ad90:
			pluto_wimp_message(e->data.msg.data.words[0],e->data.msg.data.words[1],(char *)(&e->data.msg.data.words[2]));
			break;

		case 0x4ad91:
			newsg_wimp_message(e->data);
			break;

		case wimp_MDATALOAD:     /* insert data */
		case wimp_MDATAOPEN:
		default:
			break;
		}
		break;

	case wimp_EACK:
		switch(e->data.msg.hdr.action)
		{
		case wimp_MDATAOPEN:
			/* dataopen message not acknowledged, run file */
			fname = e->data.msg.data.dataopen.name;
			if((e->data.msg.data.dataopen.type == 0xfff) &&
					(memcmp_lc("<wimp$scrapdir>",fname,15)==0))
			{
				set_filetype(fname,0xfff);
			}
			sprintf(buf,"Alias$@RunType_%.3x",e->data.msg.data.dataopen.type);
			if(read_os_variable(buf,buf2,0) != 1)
				wimp_starttask(fname);
			else
				werr(0,"Can't run this file type");
			break;

		case wimp_M_URL:
			browser_not_running(&e->data.msg);
			break;

		case message_OLEOpenSession:    /* failed to open OLE session */
			OLE_started(&e->data,0);
			break;
		}
		break;

	case wimp_EMENU:
		hits = e->data.menu;

		if(menu_expected != NULL)
		{
			menu_expected(hits);

			if(dbox_persist())
			{
				wimp_create_menu(current_menu,current_menu_x,current_menu_y);
			}
			else if(menu_expected_persist == 0)
			{
				menu_expected = NULL;
			}
			dealt_with = TRUE;
		}
		else
		{
			dealt_with = FALSE;
		}
		break;

	default:   /* Ignore any other event */
		break;
	}

	return(dealt_with);
}  /* end of unknown_event_handler */




void options_menu_proc(char *hits)
/********************************/
{
	switch(hits[1])
	{
	case 1:
		options_news();
		break;

	case 2:
		options_delivery();
		break;

	case 3:
		options_misc();
		break;

	case 4:
		options_fonts();
		break;

	case 5:  /* Sorting */
		display_called(hits[2],NULL,1);
		break;

	case 6:
		options_speak();
		break;

	case 7:
		options_filters();
		break;

	case 8:
		options_colours();
		break;

	case 9:
		if(hits[2]==1)
			options_spellcheck();
		break;

	case 10:
		set_window_positions();
		break;
	}
}   /* end of options_menu_proc */





static void main_menuproc(void *handle, char *hit)
/************************************************/
/* Event handler for main menu */
{
	int  hit1;
	char buf[128];

	/* Find which menu item was hit and take action as appropriate */
	hit1 = hit[1];

	switch (hit[0])
	{
	case 1:   /* Info */
		if(hit1==1)
			info_about_program();
		break;

	case 2:
		if(check_lock_lists(1) != 0)
			break;

		switch(hit1)
		{
		case 1:
			addrlist_open(0);
			break;

		case 2:
			open_cats_window();
			break;

		case 3:   /* distribution lists */
			sprintf(buf,"%s.Maillists",path_choices);
			dirlist_open(buf,"-si");
			break;

		case 4:
			kill_open();
			break;

		case 5:
			newsg_open(1);
			break;

		case 6:
			newsg_open(0);
			break;

		case 7:
			pgp_list_keys(1);
			break;

		case 8:   /* signatures */
			sprintf(buf,"%s.Signatures",path_choices);
			dirlist_open(buf,"-si");
			break;

		case 9:
			open_srcs_window();
			break;

		case 10:
			options_users();
			break;
		}
		break;

	case 3:   /* Preferences */
		options_menu_proc(hit);
		break;

	case 4:   /* Articles */
		if(check_lock_lists(0xffff) != 0)
			break;

		switch(hit1)
		{
		case 1:
			article_files_repair(0,0);
			break;

		case 2:
			/* compact all articles files */
			article_file_compact_all();
			break;

		case 3:
			visdelay2_begin();
			cardfile_save(0,1);
			visdelay2_end();
			break;

		case 4:
			article_files_search_fault(1);
			break;

		case 5:
			expire_articles(2);
			break;

		case 6:
			article_delete_duplicates();
			break;

		case 7:
			cardfile_new_to_unread(-1);
			break;

		case 8:
			article_file_ressurrect(0);  /* unhide deleted articles */
			break;
		}
		break;


	case 5:   /* Backups */
		sprintf(buf,"%sBackup",pluto_path);
		dirlist_open(buf,"-fi");
		break;

	case 6:   /* New document */
		if(check_lock_lists(1) != 0)
			break;

		new_file();
		break;

	case 7:  /* Statistics */
		if(hit1==1)
			artfile_statistics(0);
		break;

	case 8:   /* Misc */
		if(check_lock_lists(1) != 0)
			break;

		switch(hit1)
		{
		case 1:
			article_file_set_references();
			break;

		case 2:
			argo_import();
			break;
		}
		break;

	default:   /* Quit */
		if(text_exit_check() < 0)
			break;
		exit(0);
	}
}   /* end of main_menuproc */




void attach_menu1(int on)
/*********************/
{
	menu m;

	if(on)
		m = menu_main;
	else
		m = 0;

	event_attachmenu(win_ICONBAR, m, main_menuproc, 0);
}   /* attach_menu1 */




void get_scroll_bar_size()
/************************/
{
	wimp_redrawstr r;
	wimp_wstate wstate;

	/* determine size of window furniture */

	wimp_get_wind_state(boxlist.w_list,&wstate);
	wstate.o.behind = -3;
	wimp_open_wind(&wstate.o);

	wimp_get_wind_state(boxlist.w_list,&wstate);
	r.w = boxlist.w_list;
	wimp_getwindowoutline(&r);

	scroll_bar_height = wstate.o.box.y0 - r.box.y0;
	scroll_bar_width = r.box.x1 - wstate.o.box.x1;
}   /* end of get_scroll_bar_size */



void pass_url_to_browser(char *url)
/******************************/
{
	char *p;
	int  length;
	os_error *error;
	os_regset regs;
	int  blk[64];  /* for wimp message */
	char buf[410];

	if(strstr(url,"://") == NULL)
	{
		if(memcmp(url,"ftp.",4)==0)
			sprintf(buf,"ftp://%s",url);
		else
			sprintf(buf,"http://%s",url);
		url = buf;
	}

	if(options.browser_type == 0)
	{
		/* try the Acorn URI_dispatch SWI first, then the Fresco protocol */
		regs.r[0] = 0;
		regs.r[1] = (int)url;
		regs.r[2] = 0;
		error = os_swix(0x4e381,&regs);   /* Acorn URI_dispatch */

		if((error==NULL) && ((regs.r[0] & 1)==0))
			return;   /* successful */
	}

	/* Now try the Fresco protocol */
	length = 20 + strlen(url) + 1;
	length = (length + 3) & ~3;
	if(length > 256) length = 256;

	blk[0] = length;
	blk[1] = 0;
	blk[2] = 0;
	blk[3] = 0;
	blk[4] = wimp_M_URL;

	p = (char *)&blk[5];
	strncpy0(p,url,256-20);

	browser_fail_count = 0;
	os_swi3(0x400e7,18,(int)blk,0);    /* Wimp_SendMessage, return ACK if not acknowledged */
}   /* end of pass_url_to_browser */




void call_event_process(int count)
/********************************/
/* Count=0: check multi-task option */
{
	int  i;
	clock_t t1;
	static clock_t t2=0;

	if(system_shutdown == 1)
	{
		/* don't multi-task during system shutdown */
		return;
	}

	if(count == 0)
	{
		if(options.multi_task==0)
			return;

		t1 = clock();

		/* poll less frequently for RISC OS 3.6 and earlier because
		   of greater task swapping overheads */
		if((os_version < 0xa7) && ((t1-t2) < 20))
			return;

		if((t1 - t2) < 10)
			return;   /* less than 100mS since the last call */

		t2 = t1;

		count = 1;
	}

	null_events(0x8000,1);
	for(i=0; i<count; i++)
		event_process();
	null_events(0x8000,0);
}   /* end of call_event_process */




void terminate()
/**************/
/* Actions to be taken at program termination */
{

	blist_exit();      /* must be before article_exit */
	article_exit();    /* saves the card file */
	display_exit();
	killfile_exit();
	OLE_close_window(NULL);
	os_cli(wipe_command);
	if(using_ramfs)
	{
		os_cli("Wipe Mem::Sprites.$.Pluto R ~C ~V");
	}

	if(speak_loaded)
		os_swi1(SWI_SPEAK+2,2);  /* de-register user */

}   /* end of terminate */



BOOL initialise(int run_options,int control2, char *run_option_data)
/******************************************************************/
{
	static char *flex_dummy;

	initialise2();      /* in options.c */

	/* initialise data */
	init_menu();        /* must come before init_display */
	init_options();
	setup_read();       /* before init_article and others */

	init_blist();
	init_cats();
	init_display();     /* before init_cards */
	init_article();     /* before init_cards */
	init_cards();       /* in setup.c */
	init_reply();       /* initialised text_data_records, before init_text */
	init_text();
	init_newsg();
	init_addr();
	init_spell();

	os_cli("If \"<OLEServer$Type_fff>\"=\"\" Then RMEnsure OLESupport 0.22 RMLoad System:Modules.OLESupport");
	os_cli("If \"<OLEServer$Type_fff>\"=\"\" Then RMEnsure OLESupport 0.22 RMLoad <Pluto$Dir>.Resources.RMStore.OLESupport");

	os_cli("cdir <Wimp$ScrapDir>.Pluto");

	text_set_colours();
	make_display_menu();
	atexit(terminate);


	if(cardfile_load(0) < 0)
		exit(8);

	init_killfile();

	call_event_process(8);

	/* allocate a flex block, so that kernal_dont_budge will have an effect */
	flex_alloc((flex_ptr)&flex_dummy,1);


	if(run_options != 5)
	{
		expire_articles(1);
	}
	else
	{
		sort_msgids();
	}

	if(run_options)
	{
		pluto_wimp_message(run_options,control2,run_option_data);
	}

	expire_killfile();

	get_scroll_bar_size();

	if(no_window==0)
		boxlist_click_open(1);

	return(TRUE);
}   /* end of initialise */



os_error * wimp_taskinit2(char *name)
/***********************************/
{
	os_regset r;
	os_error *e;

	r.r[0] = 200;
	r.r[1] = 'T' +
			 ('A' << 8) +
			 ('S' << 16) +
			 ('K' << 24);
	r.r[2] = (int) name;
	e = os_swix(0x400c0, &r);
	return(e);
}


extern int lock_lists;

void pluto_wimp_message(int control, int control2, char *data)
/******************************************************/
{
	int  no_window;
	int  announce;

	if((lock_expiry!=0) || (lock_lists!=0))
	{
		/* wait until expiry or lists operation has finished */
		pluto_run_options = control;
		pluto_run_options2 = control2;
		return;
	}
	pluto_run_options = 0;


	switch(control & 0xff)
	{
	case 5:   /* run expiry */
		expire_articles(2);
		break;

	case 6:   /* debatch mail */
	case 7:   /* debatch news */
	case 8:   /* mail and news */
	case 0:   /* neither */
		if(control2 & 1)
			no_window = 0x100;
		else
			no_window = 0;

		if(control2 & 2)
			announce = 0x200;
		else
			announce = 1;

		if(control==0)
			control=5;

		if(read_raw_news(control-5,announce + no_window) == 0)
		{
			/* no messages debatched, but still open boxlist window */
			if(no_window == 0)
				set_boxlist_extent(0x43);  /* open boxlist window */
		}
		break;

	case 9:   /* import box */
		if(data != NULL)
		{
			boxlist_import(data,0x2000);
		}
		break;

	case 10:  /* save index file */
		cardfile_save(0,0);
		break;

	case 11:  /* quit */
		exit(0);
		break;
	}
}   /* end of pluto_wimp_message */




int main(int argc, char **argv)
/*******************************/
{
	int run_options = 0;
	char *run_option_data = "";
	int task;
	int *block;
	char *mailto = NULL;
	int  control2 = 0;


#ifdef MemCheck
	MemCheck_Init();
	MemCheck_InterceptSCLStringFunctions();
	/*   MemCheck_SetStoreMallocFunctions( 1); */
	MemCheck_RedirectToFilename("MCOut");
#endif

	while(argc > 1)
	{
		if(strcmp(argv[1],"-url")==0)
		{
			/* this must be a mailto: */
			if(argc > 2)
			{
				mailto = argv[2];
				argc--;
				argv++;
			}
		}
		else if(strcmp(argv[1],"-expire")==0)
		{
			run_options = 5;
		}
		else if(strcmp(argv[1],"-fetch")==0)
		{
			run_options = 8;
		}
		else if(strcmp(argv[1],"-mail")==0)
		{
			run_options = 6;
		}
		else if(strcmp(argv[1],"-news")==0)
		{
			run_options = 7;
		}
		else if(strcmp(argv[1],"-nowindow")==0)
		{
			no_window=1;   /* don't open window when started */
			select_user_flag = 2;
		}
		else if(strcmp(argv[1],"-quiet")==0)
		{
			control2 |= 2;
		}
		else if(strcmp(argv[1],"-box")==0)
		{
			run_options = 9;
			run_option_data = argv[2];
			argv++;
			argc--;
		}
		else if(strcmp(argv[1],"-saveindex")==0)
		{
			run_options = 10;
		}
		else if(strcmp(argv[1],"-slave")==0)
		{
			pluto_slave = 1;
		}
		else if(strcmp(argv[1],"-lock")==0)
		{
			pluto_lock = 1;
		}
		else if(strcmp(argv[1],"-quit")==0)
		{
			run_options = 11;;
		}
#ifdef deleted
		else
		{
			run_options = atoi(argv[1]);
			if(run_options==1)
				run_options = 8;
		}
#endif
		argv++;
		argc--;
	}

	if((task = get_task_handle("Pluto")) != 0)
	{
		wimp_taskinit2("Pluto2");

		block = malloc(256);

		if(mailto)
		{
			block[0] = (24 + strlen(mailto)) & ~3;
			block[3] = 0;
			block[4] = wimp_M_URL;
			strcpy((char *)(&block[5]),mailto);
		}
		else
		{
			block[3] = 0;
			block[4] = 0x4ad90;
			block[5] = run_options;
			block[6] = no_window + control2;
			strncpy0((char *)(&block[7]),run_option_data,228);
			block[0] = (32 + strlen((char *)(&block[7]))) & ~3;
		}
		wimp_sendmessage(17,(wimp_msgstr *)block,task);
		wimp_closedown();
		exit(9);
	}

	initialise(run_options,control2,run_option_data);
	check_ramfs();

	if(mailto)
	{
		new_reply(NULL,mailto,NULL,NULL,0,NULL);
	}

	/* The main event loop */
	while (TRUE)
	{
		event_process();
	}
	return 0;
}
