/*
 *  xdrv.h from ObjectProDSP 0.2
 *  Copyright (C) 1994 1995, Mountain Math Software. All rights reserved.
 *  
 *  This file is part of ObjectProDSP, a tool for Digital Signal
 *  Processing design, development and implementation. It is free
 *  software provided you use and distribute it under the terms of
 *  version 2 of the GNU General Public License as published
 *  by the Free Software Foundation. You may NOT distribute it or
 *  works derived from it or code that it generates under ANY
 *  OTHER terms.  In particular NONE of the ObjectProDSP system is
 *  licensed for use under the GNU General Public LIBRARY License.
 *  Mountain Math Software plans to offer a commercial version of
 *  ObjectProDSP for a fee. That version will allow redistribution
 *  of generated code under standard commercial terms.
 *  
 *  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 version 2 of the GNU General
 *  Public License along with this program. See file COPYING. If not
 *  or if you wish information on commercial versions and licensing
 *  write Mountain Math Software, P. O. Box 2124, Saratoga, CA 95070,
 *  USA, or send us e-mail at: support@mtnmath.com.
 *  
 *  You may also obtain the GNU General Public License by writing the
 *  Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
 *  USA.  However if you received a copy of this program without the
 *  file COPYING or without a copyright notice attached to all text
 *  files, libraries and executables please inform Mountain Math Software.
 *  
 *  ObjectProDSP is a trademark of Mountain Math Software.
 */
#ifndef XDRV_DOT_H
#define XDRV_DOT_H
#include "slist.h"
#include "usriotyp.h"
#include "callback.h"
#include "arthtyp.h"
#include "com_input.h"

#include "usrprompt.h"
#include <InterViews/coord.h>
#include <InterViews/style.h>
#include <InterViews/glyph.h>
#include <InterViews/leave-scope.h>
#include <Dispatch/leave-scope.h>
#include "menstck.h"

class ivCanvas ;
class ivDisplay ;
class ivDeck ;
class ivPatch ;
class ivMonoGlyph ;
class ivGlyph ;
class ivSession ;
class ivEvent ;
class ivLabel ;
class ivStyle ;
class ivButton ;
class ivWidgetKit ;
class ivLayoutKit ;
class ivManagedWindow ;
class ivWindow ;
class ivFileChooser ;
class ivFieldEditor ;
class ivTopLevelWindow ;

class TextWindowView ;
class TxtWindow ;
class HotButton ;
class UserPrompt ;
class Menu ;
class MenuLine ;
class MenuView ;
class MenuViewList ;
class HotButton ;
class PromptImpl ;
class InformationImpl ;
class StackMenu ;
class StackMenuBase ;
class DataPlot ;
class FocusSelector ;
class MenuTreeTraverseObject ;
class MenuKeyboard ;

class MenuViewLine {
	MenuView& menu_window ;
	ivDeck& deck ;
	Menu& menu ;
	ivPatch * patch ;
	ivPatch * base_gl ;
	StackMenu * stack_menu ;
	ivGlyphIndex index ;
	int active_menu ;
	HotButton * active_button ;
	HotButton ** the_hot_buttons ;
	ivGlyph * button_glyph ;
	char * unique_name ; // this is only so we can delete it

	HotButton * hot_button(MenuLine& item, int index, int is_down=0);
	void display_help_text(const char ** text);
public:
	MenuViewLine(MenuView& window, Menu& men,int down_index= -1);
	virtual ~MenuViewLine();

	void append_to_menu_glyph();
	
	Menu& get_menu() {return menu;}
	const char * get_command(ivGlyphIndex index);
	const char * get_unique_name(ivGlyphIndex index);
	inline ivWidgetKit& kit() ;
	inline const ivLayoutKit& layout() const ;
	inline ivSession& session() const ;
	inline ivGlyph& menu_glyph() ;
	int is_visible() const {return base_gl != 0;}
	void you_are_invisible() ;
	void become_visible() ;
	ivPatch * base_glyph() const {return base_gl;}

	ivGlyph& make_button_glyph(const MenuLine& item) const ;
	ivButton& push_button(const MenuLine& item) const ;
	ivButton& push_button_menu(const MenuLine& item) const ;
	
	void execute_enter(int ix);
	void execute_push(int ix);
	virtual void release(const ivEvent& e);
	enum release_return {execute_release_null=0,
		execute_stay_in=1,execute_release_moved=2} ;
	void press(int index, const ivEvent& e, HotButton *b);

	release_return execute_release(int ix,const ivEvent& e, HotButton *);
	release_return execute_release_kernel(int ix,int help_flg, HotButton *);
	void execute_restore(int ix,int help_flg, HotButton *);

	HotButton * button(ivGlyphIndex ix) const ;
	ivGlyphIndex number_buttons() const ;
	ivGlyphIndex button_index(HotButton * check); // returns -1 if not found
	void execute_leave(int ix);

	void control_execute(int ix) ;

	int is_menu_select(int) const ;
	ivGlyph * label_glyph(const char *);
	ivGlyph * build_menu(ivCoord lim);
	ivGlyphIndex glyph_index() const {return index;}
	void dec_glyph_index(int dec=1) {index -= dec;}
	void redraw();
	StackMenu * get_stack_menu() const { return stack_menu;}
	void set_stack_menu(StackMenu * menu) {stack_menu = menu;}
	boolean is_other();
	int level();
	int execute(int index, const char * cmd);
	MenuViewLine::release_return modifier_execute(const ivEvent& event,
		int index);
	MenuView& get_menu_window() {return menu_window;}
	void replace_button(HotButton * to_replace);
	void release_button();
	void set_mouse_selection(HotButton * selected);
	void clear_mouse_selection();

	void peel_off_menu(int index);
	void raise_windows(int index);
	void create_default(int index);
	void create_instance(int index);

	void do_command(int index);
	void help_paragraph(int index);
	void cond_help_paragraph(int index);
	void help_file(int index);
	
	HotButton * find_selection(const char * sel);
	void set_active(HotButton *b, int ix= -1)
		{active_button = b ; active_menu = ix;}
};

class RootMenuView ;
class WindowMenuView ;

class MenuView : public DspActiveHandler {
friend MenuViewLine ;
	int init ;
	StackMenuList menu_stack ;
	int the_stack_offset ;
	void pop(int to_pop);
	int stack_base_size ;
	HotButton * the_selection ;
	HotButton * the_mouse_selection ;
	int prefer_mouse ;
	char * the_fail_select ;
	int action_failed ;
	
protected:
	ivPatch * menu_patch ;
	Menu& top_menu ;
	ivCoord max_height ;
	ivSession& session ;
	ivWidgetKit& the_kit;
	const ivLayoutKit& the_layout;
	ivGlyph& menu_glyph ;
	RootMenuView& root_window ;
	MenuViewLine * root_menu_window_line ;
	MenuViewLine * active_line ;
	WindowMenuView * keyboard_interface ;

	MenuKeyboard * the_menu_keyboard ;

	void init_push(MenuViewLine*, const char*, int index);
	void push(MenuViewLine*, const char*, int index);
	inline void replace_page(const char ** str) ;
	ivMonoGlyph *  first_menu_init(MenuKeyboard *k=0);
	void map() ;
	void set_active(MenuViewLine *);

	void prefer_mouse_selection() {prefer_mouse=1;}
	void prefer_keyboard_selection() {prefer_mouse=0;}
public:
	MenuView(ivStyle * sty, Menu& menu, ivSession& s, const char * command,
		RootMenuView& root, StackMenuBaseList *b=0,int lim= -1);

	virtual ~MenuView();

	MenuView *  new_menu(Menu& menu, const char * command,
		StackMenuBaseList *b=0, int lim= -1);

	virtual void enter();
	virtual void leave();
	virtual void press(const ivEvent& e);
	virtual void release(const ivEvent& e);

	void resize() ;
	void control_execute(const char* cmd,int level, Menu&);
	void control_execute(StackMenu *, int index, int level) ;
	inline ivCoord width() const ;
	inline void scroll(const char *) ;
	void repair();
	void patch_redraw();
	RootMenuView& root() {return root_window;}
	MenuViewLine * active() const {return active_line;}
	void visible_pop();
	int all_visible();
	const ivLayoutKit& layout(){return the_layout;}
	ivWidgetKit& kit() {return the_kit;}
	ivWindow* get_window() const {return window();}
	int visible_levels();
	int stack_size();
	const StackMenuList& get_menu_stack() const {return menu_stack ;}
	void display_help_file(const char * name, const char * win_name=0);
	MenuViewLine * root_line() const { return root_menu_window_line;}
	virtual void exit_window();
	void stack_offset(int offset) {the_stack_offset = offset ;}
	int stack_offset() const {return the_stack_offset;}
	int about_to_change_menu(Menu *) ; // return 1 MenuView should be deleted

	MenuKeyboard * build_menu_keyboard(ivWidgetKit& kit,
		const ivLayoutKit& layout, ivStyle * style, MenuView&) ;
	MenuKeyboard * menu_keyboard() const {return the_menu_keyboard;}
	virtual int base_keystroke(const ivEvent& e, FocusSelector * sel);

	void set_selection(HotButton * selected);
	void new_selection(HotButton * selected);
	HotButton * selection(int record_action_or_fail = 0 );

	void set_mouse_selection(HotButton * selected);
	void clear_mouse_selection() {the_mouse_selection = 0;}

	void select_home();
	void select_end();
	void select_left();
	void select_right();
	void select_up();
	void select_down();
	void select_none();		// clears keyboard
	void clear_selected(); // clears mouse and keyboard

	void peel_off_menu();
	void raise_windows();
	void create_default();
	void create_instance();

	void do_command();
	void help_paragraph();
	void cond_help_paragraph();
	void help_file();

	void set_fail_select(const char * set);
	void clear_fail_select();

	
	void act_select(const char * sel);
	void act_deselect();
	int do_command(const char * cmd);
	void create_default(const char * cmd);
	void create_instance(const char * cmd);
	int test_clear_action_failed() ;
	void reset_action_failed() {action_failed=0;}
	void set_action_failed() {action_failed=1;}
	
};

class PromptStringList : public StringList {
public:
	PromptStringList():StringList(){}
	Append(char * item);
};
	

class RootMenuView : public MenuView {
	StringList help_strings ;
	PromptStringList prompt_strings ;
	StringList info_strings ;
	StringList edit_info_strings ;
	TextWindowView * help_display ;
	TxtWindow * menu_txt_window ;
	TxtWindow * cpp_txt_window ;
	ivPatch * help_patch ;
	MenuView * active_menu ;
	char * read_file_name ;
	int overwrite_flag ;
	int init_return_id ;
	PromptImpl * prompt ;
	InformationImpl * info ;
	StackMenuBaseList * direct_command ;

	ivTopLevelWindow * the_help_window ;

	ivWindow * the_cursor_window ;
	ivWindow * to_unmap ;
	HotButton * button_to_leave ;
	int network_edit_mode ;
	int wait_for_dsp_flag ;

	void select_setup() ;
	void window_setup(ivGlyph * glyph);
	void init_prompt();
	void init_info();
	int disallow_check_remote ;
	int freeze_flag;
	int hard_freeze_flag ;

	int read_action_file_mode ;

	const char * prompt_response ;
	const char * pending_prompt_response ;
	int prompt_buf_length ;
	char * prompt_buf ;

	void new_help_page();
public:
	RootMenuView(ivStyle *sty, Menu& menu, ivSession& s);
	virtual ~RootMenuView();
	int run();
	void replace_page(const char ** str) ;
	ivCoord width() const ;
	void scroll(const char * string);
	void cpp_scroll(const char * string);
	void help_info_string(const char * string);
	void flush_help_info();
	void write_help_info();
	
	void window_init();
	void RemoteServer(OutputType type,const char * msg,OutputType next);
	void process_help_strings();
	const char * menu_stack_name(int ix);
	void set_active(MenuView * to_set) {active_menu = to_set;}
	MenuView * get_active() const {return active_menu;}
	const char * get_file_name(const char * prompt, const char*the_default=0,
		const char * pattern=0,int check_suffix=0, ivWindow * win = 0) ;
	void read_state(int, const char * file_name=0);
	void ReadStateCompletion(CallBackStatus status, char * Name=0,
		int Lines= -1);
	PromptStatus InputPost(UserPrompt * Prompt, const char * AbortMessage=0,
		StringList *  message=0, ivWindow * win=0) ;
	void information_complete();
	void information(const char * str, ivWindow * win,int force=0);
	void information(StringList& list, ivWindow *win,int force=0);
	int check_remote() const {return !disallow_check_remote;}
	void create_plot(DataPlot * plt);
	ivCanvas *canvas() const ;
	ivDisplay * display() const ;
	void disable_remote_com();
	void enable_remote_com();
	int do_menu_command(const char * cmd);
	void remote_prompt(const char * str);
	void not_busy() const ;
	void hard_freeze();
	void freeze();
	void clear_hard_freeze();
	void thaw();
	int is_frozen() const {return freeze_flag;}
	int is_frozen_hard() const {return hard_freeze_flag;}
	void cursor_window(ivWindow * win) {the_cursor_window = win;}
	ivWindow * cursor_window() {return the_cursor_window;}
	void new_cursor();
	void set_button_to_leave(HotButton *);
	void set_window_to_unmap(ivWindow * win) ;
	ivTopLevelWindow * help_window() const {return the_help_window;}
	TextWindowView * get_help_display() const {return help_display;}
	void no_cpp_entry();
	virtual int input_allowed(const ivInputHandler *) ;
	void network_edit_command(const char * cmd);
	void read_request_active() ;
	void ReadyForInitFileRead();
	ivWindow* get_menu_window();
	void execute_menu_command(MenuTreeTraverseObject& obj);

	int set_prompt_response(const char * resp);
	void action_read_on();
	void action_read_off();

	int process_event(ivEvent& e);
	int event_check();
	int event_wait();
	
	void set_wait_for_dsp();
	void check_wait_for_dsp();

	void focus_clear();
	void focus_dpp();
    void focus_menu();
    void focus_buttons();

	int reading_action_file() const {return read_action_file_mode;}

	void statement_history();
	void append_statement_history();
	void command_history();
	virtual void edit_init();
	int remote_com_disallowed() const {return disallow_check_remote;}
};

inline ivCoord MenuView::width() const {return root_window.width();}
	void pop(int to_pop);

inline void MenuView::replace_page(const char ** str) 
	{root_window.replace_page(str);}

inline void MenuView::scroll(const char * str) {root_window.scroll(str);}

#include <OS/leave-scope.h>
#include <OS/enter-scope.h>
#include <InterViews/enter-scope.h>
#include <Dispatch/enter-scope.h>


#endif /* #ifdef XDRV_DOT_H */
