#include <math.h>
#include <string.h>
#include <ctype.h>
#include <stream.h>
#include <fstream.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>
#include <stdlib.h>
#include "menstck.h"
#include "menu.h"
#include <InterViews/color.h>
#include <InterViews/brush.h>
#include <InterViews/font.h>

#include "plotfile.h"
#include "portable.h"
#include "xdrv.h"
#include "netdescg.h"
#include <InterViews/leave-scope.h>
#include <Dispatch/leave-scope.h>
#include "dsp_app.h"
#include "menmgr.h"
#include "mkstr.h"
#include "remcom.h"
#include "menucmdg.h"

#include "arthtyp.h"
#include "cgidbg.h"
#include "newaloc.h"
#include "playback.h"
#include <stdio.h>
#include "dyntextg.h"
#include "sysconst.h"
#include "com_input.h"
#include "xgui.h"
#include "help.h"
#include "helpwin.h"
#include "environ.h"
		// for OpenFileMode

#include "xk_tab.h"

static RootMenuView * TheRootWindow = 0 ;
int DspApplication::spacer_l = 0 ;
static const ivBrush *narrow_brush = 0 ;
static const ivColor * cyan_color = 0 ;
static const ivColor * white_color = 0 ;
static const ivColor * black_color = 0 ;
static const ivColor * rosy_brown_color = 0 ;
static const ivFont * standard_font = 0 ;
static const ivFont * the_tty_font = 0 ;
static const char * spacer =
"\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040\040" ;
// backslashes are to guard against replacing 4 blanks in a row with tabs

int DspApplication::spacer_length()
{
	if (!spacer_l) spacer_l = strlen(spacer());
	return spacer_l ;
}

ivWindow * DspApplication::menu_window()
{
	return root_window()->get_menu_window();
}

RootMenuView * DspApplication::root_window()
{
	return TheRootWindow ;
}

const char * DspApplication::spacer()
{
	return ::spacer ;
}



void DspApplication::enable_remote_com()
{
	root_window()->enable_remote_com();
}

void DspApplication::disable_remote_com()
{
	root_window()->disable_remote_com();
}


int DspApplication::size_of(ArithType::ArithTypes type)
{
	switch (type) {
default:
case ArithType::ArithTypeUndefined:
			DbgError("DspApplication::size_of","bad type");
case ArithType::ArithDouble:
			return sizeof(double);
case ArithType::ArithInt16:
			return sizeof(int16);
case ArithType::ArithInt32:
			return sizeof(int32);
case ArithType::ArithFloat:
			return sizeof(float);
	}
}

ivCanvas * DspApplication::canvas()
{
	return root_window()->canvas();
}

ivDisplay * DspApplication::display()
{
	return root_window()->display();
}

static int nan_total = 0 ;
static int infinity_total = 0 ;
static int gave_warning = 0 ;

void DspApplication::plot_err_display()
{
	char * msgs[4] ;
	int i = 0 ;
	msgs[i++] = Concatenate(
		"The following refer to values in all plot data streams.\n");
	msgs[i++] = Concatenate("Total values that are not a number (NAN): ",
		dec(nan_total),".\n");
	msgs[i++] = Concatenate("Total values that are infinity: ",
		dec(infinity_total),"\n") ;
	msgs[i++] = 0 ;
	for (const char ** pt = msgs ; *pt ; pt++) *Output + OutputCppHelp <<
		*pt ;
	root_window()->replace_page(msgs);
	
}

static void check_warning()
{
	if (gave_warning) return ;
	StringList list ;
	const char * msgs [] = {
		"There are non numeric IEEE floating values (NAN or infinity)",
		"in the plot data stream. These have been set to 0.",
		"Select `plot err' under `state' in the menu data base to see",
		"the total errors from all plots.\n",
		0
	};
	DspApplication::warn_info_window(1.5*4*72.0,72.,msgs);
	gave_warning = 1 ;
}

int DspApplication::nan_count()
{
	return nan_total ;
}

int DspApplication::infinity_count()
{
	return infinity_total ;
}

double DspApplication::convert_to_double(const char * value,
	ArithType::ArithTypes type)
{
	double temp ;
	int change = 0 ;
	MoveNBytes((char *) &temp, value, size_of(type));
	switch (type) {
default:
case ArithType::ArithTypeUndefined:
			DbgError("DspApplication::convert_to_double","bad type");
case ArithType::ArithDouble:
			if (isnan(temp)) {
				nan_total++ ;
				change = 1 ;
			}
			if (isinf(temp)) {
				infinity_total++ ;
				change = 1 ;
			}
			if (change) {
				check_warning();
				return 0. ;
			}
			return temp ;
case ArithType::ArithInt16:
			return *(int16*) &temp ;
case ArithType::ArithInt32:
			return *(int32*) &temp ;
case ArithType::ArithFloat:
			if (isnan(*(float*) &temp)) {
				nan_total++ ;
				change = 1 ;
			}
			if (isinf(*(float*) &temp)) {
				infinity_total++ ;
				change= 1 ;
			}
			if (change) {
				check_warning();
				return 0 ;
			}
			return *(float*) &temp ;
	}
}


void DspApplication::set_root_window(RootMenuView& root)
{
	TheRootWindow = &root ;
}

static NetworkDisplayManager * network_display_manager = 0 ;

static void check_network_manager_exists()
{
	if (! network_display_manager) network_display_manager = new
		NetworkDisplayManager ;
}

NetworkDisplayManager * DspApplication::network_manager()
{
	check_network_manager_exists();
	return network_display_manager ;
}

void DspApplication::network_display(int id,int size,const char *data)
{
	check_network_manager_exists();
	network_display_manager->network_display(id,size,data);
}

void DspApplication::network_edit(int id,int size,const char *data)
{
	check_network_manager_exists();
	network_display_manager->network_edit(id,size,data);
}


const ivBrush* DspApplication::brush()
{
	if (!narrow_brush) {
		narrow_brush = new ivBrush(0.0);
		ivResource::ref(narrow_brush);
	}
	return narrow_brush ;
}

const ivColor* DspApplication::cyan()
{
	if (!cyan_color) {
		cyan_color = ivColor::lookup(display(),"cyan");
		ivResource::ref(cyan_color);
	}
	return cyan_color ;
}

const ivColor* DspApplication::white()
{
	if (!white_color) {
		white_color = ivColor::lookup(display(),"white");
		ivResource::ref(white_color);
	}
	return white_color ;
}

const ivColor* DspApplication::black()
{
	if (!black_color) {
		black_color = ivColor::lookup(display(),"black");
		ivResource::ref(black_color);
	}
	return black_color ;
}

const ivColor* DspApplication::rosy_brown()
{
	if (!rosy_brown_color) {
		rosy_brown_color = ivColor::lookup(display(),"RosyBrown");
		ivResource::ref(rosy_brown_color);
	}
	return rosy_brown_color ;
}

const ivFont* DspApplication::tty_font()
{
	if (!the_tty_font) {
		the_tty_font = ivFont::lookup("*fixed-medium-r-normal-*14*");
		ivResource::ref(the_tty_font);
	}
	if (!the_tty_font) DbgError("DspApplication::font","no font");
	return the_tty_font ;
}
const ivFont* DspApplication::font()
{
	if (!standard_font) {
		standard_font = ivFont::lookup("*helvetica-medium-r-normal--12*");
		ivResource::ref(standard_font);
	}
	if (!standard_font) DbgError("DspApplication::font","no font");
	return standard_font ;
}


void DspApplication::dimensions(ivGlyph * g, ivCoord& x, ivCoord&y)
{
		x = y = 0.0 ;
		if (!g) return ;	
		ivRequisition Temp ;
		g->request(Temp);
		x = Temp.x_requirement().natural() ;
		y = Temp.y_requirement().natural() ;
}

ivCoord DspApplication::x_req(ivGlyph *g)
{
	if (!g) return 0.0 ;
	ivRequisition Temp ;
	g->request(Temp);
	return Temp.x_requirement().natural() ;
}

ivCoord DspApplication::y_req(ivGlyph *g)
{
	if (!g) return 0.0 ;
	ivRequisition Temp ;
	g->request(Temp);
	return Temp.y_requirement().natural() ;
}

const char * DspApplication::int_string(int v)
{
	const buf_size = 20 ;
	static char buf[buf_size];
	for (int i = 0 ; i < buf_size;i++) buf[0] ='\0' ;
	sprintf(buf,"%d",v);
	// LogOut << "DspApplication::int_string(" << v << "), buf `" << buf << "'\n" ;
	return buf ;
}

static GuiDynamicTextControl * the_dynamic_text_controller = 0 ;

GuiDynamicTextControl * DspApplication::dynamic_text_controller()
{
	if (!the_dynamic_text_controller) the_dynamic_text_controller =
		new GuiDynamicTextControl ;
	return the_dynamic_text_controller ;
}

HelpControl * DspApplication::help_control()
{
	return &HelpDo ;
}

void DspApplication::dynamic_text(
		OutputType type,const char *str,OutputType nxt)
{
	dynamic_text_controller()->append(type,str,nxt);
}

ivStyle& DspApplication::style()
{
	return *(root_window()->style());
}

ivWidgetKit& DspApplication::kit()
{
	return root_window()->kit();
}

const ivLayoutKit& DspApplication::layout()
{
	return root_window()->layout();
}

static int BaseOpenFile(const char * Name)
{
	return open(Name, O_RDWR | O_CREAT | O_EXCL,OpenFileMode) ;
}

static const char * TempFileDirectoryName = 0 ;
static const char * BaseFileName = "dsp.XXXXXX" ;

char * DspApplication::make_file_name()
{
	if (!TempFileDirectoryName) {
		const char * tmp = Environment::get("OPD_TEMP");
		if (!tmp) DbgError("DspApplication::make_file_name","no default /tmp");
		if (tmp[strlen(tmp)-1] != '/') tmp = Concatenate(tmp,"/");
		TempFileDirectoryName = tmp ;
	}
	char * Name = strcpy(new char[strlen(BaseFileName)+
		strlen(TempFileDirectoryName)+1],TempFileDirectoryName);
	strcat (Name,BaseFileName);
	mktemp(Name);
	return Name ;
}

char * DspApplication::open_file(int& TheFile)
{
	char * Name = make_file_name();
	TheFile = BaseOpenFile(Name);
	if (TheFile < 0) {
		TheLog << Name << "\n" ;
		DbgError("TextFile::OpenFile cannot create ",Name);
	}
	return Name ;
}

const char * DspApplication::temp_file_directory()
{
	return TempFileDirectoryName ;
}

void DspApplication::remove_control(char *str)
{
	// LogOut << "DspApplication::remove_control(`" << str << "')\n" ;
	if (str) for (;*str;str++) if (!isprint(*str)) *str = ' ' ;
}

DspProcessState * DspApplication::state()
{
	return DspState ;
}

static int child_id = 0 ;

void DspApplication::child_id(int c)
{
	::child_id = c ;
}

int DspApplication::child_id()
{
	return ::child_id ;
}

void DspApplication::write_help_info()
{
	root_window()->write_help_info();
}

void DspApplication::flush_help_info()
{
	root_window()->write_help_info();
}

int DspApplication::execute_menu_command(const char * cmd, const char * h1,
		const char * h2, const char * h3, const char * h4,
		const char * h5, const char * h6, const char * h7)
{
	return execute_menu_command((Menu *) 0,cmd,h1,h2,h3,h4,h5,h6,h7);
}

int DspApplication::execute_menu_command(Menu * menu,const char * cmd,
		const char * h1,
		const char * h2, const char * h3, const char * h4,
		const char * h5, const char * h6, const char * h7)
{
	ConstStringList * lst = 0 ;
	if (h1) {
		lst = new ConstStringList ;
		lst->Append(h1);
		if (h2) lst->Append(h2);
		if (h3) lst->Append(h3);
		if (h4) lst->Append(h4);
		if (h5) lst->Append(h5);
		if (h6) lst->Append(h6);
		if (h7) lst->Append(h7);
	}
	execute_menu_command(cmd,lst,menu);
}

int DspApplication::execute_menu_command(const char * cmd,
	ConstStringList * lst, Menu* menu)
{
	MenuTreeTraverseObject obj(cmd,lst,menu, menu!= 0);
	int Return = TheCurrentMenus->execute_command(obj);
	if (lst) lst->Clear();
	delete lst ;
	return Return ;
}

int DspApplication::execute_menu_command(const char * cmd,
	const char ** const l)
{
	ConstStringList * lst = 0 ;
	if (l) {
		lst = new ConstStringList ;
		for (const char ** pt = l ; *pt; pt++) lst->Append(*pt);
	}
	execute_menu_command(cmd,lst);
}
	

static MenuViewList * all_menu_views = 0 ;
MenuViewList & DspApplication::menu_manager()
{
	if (!all_menu_views) all_menu_views = new MenuViewList ;
	return *all_menu_views ;
}

void DspApplication::prompt(const char  *msg, SuspendedRead client,
	const char * def_val, void * obj, ivWindow * win)
{
	StringList strings;
	strings.Append(Concatenate(msg));
	prompt(strings,client,def_val,obj,win);
}
void DspApplication::prompt(StringList& msg, SuspendedRead client,
	const char * def_val,void * obj,ivWindow * win)
{
	UserPrompt prompt(0,client,obj,1,1,InputPrompt, def_val);
	root_window()->InputPost(&prompt,0,&msg,win);
}

uint32 DspApplication::xk_alias(uint32 c)
{
	return X_Character::table().alias_of(c);
}

const char * DspApplication::xk_name_of_char(uint32 c)
{
	return X_Character::table().name(c);
}

void DspApplication::display_help_file(const char * name)
{
	root_window()->display_help_file(name);
}

static char * add_quote(const char * text)
{
	if (!text) return 0 ;
	int count = 0 ;
	for (const char * pt = text; *pt; pt++) if (*pt =='"') count++ ;
	if (!count) return 0 ;
	char * ret = new char [strlen(text)+count+1] ;
	char * dest = ret ;
	for (pt = text; *pt; pt++) {
		if (*pt =='"') *dest++ = '\\' ;
		*dest++ = *pt ;
	}
	*dest ='\0' ;
	return ret ;
}

class Record {
	ostream * the_file ;
	const char * the_name ;
	int recording ;

	void abort(const char * msg);
public:
	Record();
	~Record();
	void start(const char * file_name =0);
	void stop();
	void close();
	
	void prompt(const char * str);
	void mouse(uint32 action, const char * selected, const char *window);
	void key(uint32 action, const char * selected, const char *window);
	void action(ivGlyphIndex index, const char * selected, const char * win,
		const char * comment);
	void menu_text(const char * text);
	void dpp_text(const char * text);
	const char * name() const {return the_name;}
	void record_menu_state(StackMenuList& list,Menu &men);
	void record_menu_state(const char ** const state);
} recorder ;

Record::Record():
	the_file(0),
	the_name(0),
	recording(0)
{
}

Record::~Record()
{
	// LogOut << "deleteing the_file\n" ;
	delete the_file ;
}

void Record::abort(const char * msg)
{
	DspApplication::information(msg,
		DspApplication::menu_window());
	the_name = 0 ;
	the_file = 0 ;
	recording = 0 ;
}

void Record::start(const char * file_name)
{
	recording = 1 ;
	if (file_name) {
		if (the_name) if (!strcmp(file_name,the_name)) if (the_file) return ;
		the_name = file_name ;
	} else {
		if (the_name) {if (the_file) return ;}
		else {
			char * temp = Concatenate("No file specified. Recording aborted.");
			abort(temp);
			delete temp ;
			return ;
		}
	}
	the_file = new ofstream(the_name);
	if (the_file) if (the_file->good()) {
		DspApplication::command_record_state();
		return ;
	}
	char * temp = Concatenate("Cannot create recording file `",
			the_name, "'. Recording aborted.");
	abort(temp);
	delete temp ;
}

void Record::stop()
{
	if (recording) {
		if (HelpDo.Confirm()) HelpOut << "Recording stopped.\n" ;
		recording = 0 ;
	} else if (HelpDo.Confirm())
		HelpOut << "Cannot stop recording. Recording is not on.\n" ;
}

void Record::close()
{
	if (!recording && !the_file) {
	    if (HelpDo.Confirm()) 
			HelpOut << "Cannot flush recording. There is no active recording file.\n" ;
			return ;
	}
	delete the_file ;
	the_file = 0 ;
	the_name = 0 ;
	recording = 0 ;
	if (HelpDo.Confirm()) HelpOut << "Recording flushed.\n" ;
}


const always_flush = 1 ;

static const char * convert_control(const char * str)
{
	if (!str) return 0 ;
	if (!*str) return str ;
	static char * buf = 0 ;
	static int buf_size = 0 ;
	const min_size = 128 ;
	int control_count = 0 ;
	for (const char * ptr = str ; *ptr; ptr++) if (iscntrl(*ptr)) control_count++ ;
	if (!control_count) return str ;
	int len = strlen(str);
	int needed = len + control_count + 1 ;
	if (needed > buf_size) {
		delete buf ;
		buf_size = min_size ;
		if (buf_size < needed) buf_size = needed ;
		buf = new char[buf_size] ;
	}
	char * dest = buf ;
	for (ptr = str ; *ptr; ptr++) if (!iscntrl(*ptr)) *dest++ = *ptr ;
	else {
		*dest++ = '^' ;
		*dest++ = 'A' + *ptr ;
		
	}
	*dest = '\0' ;
	return buf ;
}

void Record::record_menu_state(StackMenuList& list,Menu& men)
{
	if (!recording) return ;
	*the_file << "MenuState " ;
	list.record_menu_state(*the_file,men);
	*the_file << "\n" ;
}

void Record::record_menu_state(const char ** const state)
{
	if (!recording) return ;
	*the_file << "MenuState " ;
	for (const char ** pt = state; *pt ; pt++)
		*the_file << " \"" << *pt << "\"" ;
	*the_file << "\n" ;
}

void Record::prompt(const char * str)
{
	ManagedKeyboards::manager()->set_action_recorded();
	if (!recording) return ;
	// LogOut << "Record::Prompt \"" << str << "\"\n" ;
	*the_file << "Prompt \"" << str << "\"\n" ;
	if (always_flush) the_file->flush();
}

void Record::mouse(uint32 action, const char * selected, const char *window)
{
	if (!recording) return ;
/*
 *	LogOut << "Record::Mouse 0x" << hex << action << dec << " \"" <<
 *		selected << "\" \"" << window << "\"\n" ;
 */
	*the_file << "Mouse " << action << " \"" << selected << "\" \"" <<
		window << "\"\n" ;
	if (always_flush) the_file->flush();
}

void Record::key(uint32 action, const char * selected, const char *window)
{
	if (!recording) return ;
/*
 *	LogOut  << "Record::Key " << action << " \"" << selected << "\" \"" <<
 *		window << "\"\n" ;
 */
	*the_file << "Key 0x" << hex << action << dec << " \"" << selected <<
		"\" \"" << window << "\"\n" ;
	if (always_flush) the_file->flush();
}

void Record::action(ivGlyphIndex index, const char * selected,
	const char * win, const char * comment)
{
	ManagedKeyboards::manager()->set_action_recorded();
/*
 *	LogOut << "Record::action 0x" << hex << index << dec <<
 *		" \"" << selected << "\" \"" << win << "\"\n" ;
 */
	if (!recording) return ;
	*the_file << "Action 0x" << hex <<  index << dec << " \"" << selected << "\" \"" 
		<<  win << "\"";
	if (comment) *the_file << " # " << comment ;
	*the_file << "\n" ;
	if (always_flush) the_file->flush();
}

void Record::menu_text(const char * text)
{
	ManagedKeyboards::manager()->set_action_recorded();
	if (!recording) return ;
	*the_file << "MenuText " << " \"" << text << "\"\n" ;
}

void Record::dpp_text(const char * text)
{
	ManagedKeyboards::manager()->set_action_recorded();
	if (!recording) return ;
	char * rep = add_quote(text);
	if (rep) text = rep ;
	*the_file << "DppText " << " \"" << text << "\"\n" ;
	delete rep ;
}

const char * DspApplication::record_file_name()
{
	return recorder.name();
}


void DspApplication::command_record_state()
{
	DspApplication::root_window()->do_command("state");
	DspApplication::root_window()->do_command("session");
}

void DspApplication::record_prompt(const char * str)
{
	if (HelpDo.All()) root_window()->cpp_scroll(str);
	recorder.prompt(str);
}

void DspApplication::record_on(const char * file_name)
{
	recorder.start(file_name);
}

void DspApplication::record_off()
{
	recorder.stop();
}

void DspApplication::record_close()
{
	recorder.close();
}

void DspApplication::record_mouse(uint32 action, const char * selected,
		const char *window)
{
	recorder.mouse(action,selected,window);
}

void DspApplication::record_key(uint32 action, const char * selected,
		const char *window)
{
	recorder.key(action,selected,window);
}

void DspApplication::record_menu_state(const char ** const state)
{
	recorder.record_menu_state(state);
}

void DspApplication::record_menu_state(StackMenuList& list,MenuViewLine &line)
{
	recorder.record_menu_state(list,line.get_menu());
}

void DspApplication::record_action(ivGlyphIndex index, const char * selected,
	const char * win, const char * comment)
{
	recorder.action(index,selected,win,comment);
}

void DspApplication::record_menu_text(const char * str)
{
	recorder.menu_text(str);
}


static char * remove_quote(const char * str)
{
	if (!str) return 0 ;
	int count = 0 ;
	for (const char * pt = str ; * pt ; pt++)
		if (*pt == '\\') if (pt[1] == '"') count ++ ;
	if (!count) return 0 ;
	char * ret = new char[strlen(pt) - count + 1] ;
	char * dest = ret ;
	for (pt = str ; * pt ; pt++) {
        if (*pt == '\\') if (pt[1] == '"') {
			*dest++ = *++pt ;
			pt++ ;
		}
		else *dest++ = *pt ;
	}
	*dest = '\0' ;
	return ret ;
}

void DspApplication::record_dpp_text(const char * str)
{
	const char * text = str ;
	char * to_delete = remove_quote(str)  ;
	if (to_delete) text = to_delete ;
	recorder.dpp_text(text);
	delete to_delete ;
}


void DspApplication::information(const char * msg,ivWindow * win,int f)
{
	root_window()->information(msg,win,f);
}

void DspApplication::information(StringList & msg,ivWindow * win,int f)
{
	root_window()->information(msg,win,f);
}

const char * DspApplication::get_file_name(const char * prompt,const char * def,
	const char * pattern,ivWindow * win)
{
	return root_window()->get_file_name(prompt,def,pattern,0,win);
}

int DspApplication::set_prompt_response(const char * resp)
{
	return root_window()->set_prompt_response(resp);
}

void DspApplication::action_read_on()
{
	root_window()->action_read_on();
}

void DspApplication::action_read_off()
{
	root_window()->action_read_off();
}

int DspApplication::action_read_line()
{
	return ManagedKeyboards::manager()->read_line();	
}

int DspApplication::cond_check_packet_read()
{
	if (!root_window()->check_remote()) return 0 ;
	return check_packet_read();
}

int DspApplication::check_packet_read()
{
	return ReadSeg->CheckPacketRead();
}

DspProcessState * DspApplication::dsp_state()
{
	return DspState ;
}

int DspApplication::is_busy()
{
	return dsp_state()->IsBusy();
}

int DspApplication::event_wait()
{
	return root_window()->event_wait();
}

int DspApplication::event_check()
{
	return root_window()->event_check();
}

int DspApplication::check_processing()
{
	int Return = 0 ;
	while (event_check()) Return = 1 ;
	while (DspApplication::check_packet_read()) Return = 1;
	while (is_busy()) {
		while(event_check()) Return = 1;
		while(DspApplication::check_packet_read()) Return = 1;
	}
	return Return ;
}

void DspApplication::set_wait_for_dsp()
{
	root_window()->set_wait_for_dsp();
}

void DspApplication::check_wait_for_dsp()
{
	root_window()->check_wait_for_dsp();
}

void DspApplication::wait_for_dsp()
{
	while(is_busy()) {
		ReadSeg->ReadPacket();
		while(ReadSeg->CheckPacketRead());
	}
}

void DspApplication::process_help_strings()
{
	root_window()->process_help_strings() ;
}

int DspApplication::user_input_allowed(int warn)
{
	if (!root_window()) return 0 ;
	if (FocusSelector::currently_printing(warn)) return 0 ;
	if (Master.wait_remote_execute()) return 0 ;
	if (!root_window()->reading_action_file()) return 1 ;
	if (warn) {
		StringList strings ;
		strings.Append(Concatenate("Most user input is disallowed while reading an action file."));
		strings.Append(Concatenate("Type `ctrl-delete' in the main window to abort the action file."));
		information(strings,menu_window(),1);
	}
	return 0 ;
}

ShiftTable& DspApplication::shift_table()
{
	return X_Character::shift_table ;
}


void DspApplication::cpp_scroll(const char * str)
{
	root_window()->cpp_scroll(str);
}

void DspApplication::menu_scroll(const char * str)
{
	root_window()->scroll(str);
}

void DspApplication::read_plot()
{
	const char * name = get_file_name("Enter saved plot file:","plot.plt",
		"*.plt");
	if (!name) return ;
	if (!*name) return ;
	ThePlotFileManager.ReadPlot(name);
}

int command_waiting_on_dsp_flag = 0 ;
void DspApplication::set_waiting_on_dsp()
{
	command_waiting_on_dsp_flag = 1 ;
	root_window()->new_cursor();
}

void DspApplication::clear_waiting_on_dsp()
{
	command_waiting_on_dsp_flag = 0 ;
	root_window()->new_cursor();
}

int DspApplication::waiting_on_dsp()
{
	return command_waiting_on_dsp_flag  ;
}


void DspApplication::check_rebuild()
{
	network_manager()->check_rebuild();
}

void DspApplication::new_cursor()
{
	root_window()->new_cursor();
}

TextWindowView * DspApplication::help_display()
{
	return root_window()->get_help_display()  ;
}

void DspApplication::do_menu_command(const char * str)
{
	DspApplication::root_window()->do_command(str);
}

void DspApplication::warn_info_window(ivCoord X_dim, ivCoord Y_dim,
        const char ** str)
{
	TextWindowKit::warn_info_window(X_dim, Y_dim, str);
}

void DspApplication::create_default(const char * cmd)
{
	if (execute_menu_command("create default",cmd)) {
		root_window()->scroll("create default");
		return ;
	}
    if (execute_menu_command( "Edit","exec",cmd)) {
        root_window()->scroll("Edit");
        return ;
    }
    if (execute_menu_command( "AssignToEdit","exec",cmd))
        root_window()->scroll("AssignToEdit");
}



void DspApplication::create_instance(const char * cmd)
{
	if (execute_menu_command("create",cmd)) {
		root_window()->scroll("create");
		return ;
	}
}

int is_prompt_active = 0 ;

int DspApplication::prompt_active()
{
	return is_prompt_active ;
}

void DspApplication::prompt_active(int set_to)
{
	is_prompt_active = set_to ;
}


const char * DspApplication::main_window_prefix = "ObjectProDSP " ;
const char * DspApplication::info_window = "ObjectProDSP information" ;

