/*
 * MindTool
 *
 * This program provides a window based interface to the mind program.
 *
 * James Blake
 * Yale University
 * Department of Chemistry
 * jim@doctor.chem.yale.edu
 *
 * Permission to use, copy, and distribute this software and its 
 * documentation for any purpose without fee is hereby granted,  
 * provided that the above notice appear in all copies.
 *
 */

#define		MAX_FILENAME_LEN	256

#include <stdio.h>
#include <signal.h>
#include <suntool/sunview.h>
#include <suntool/panel.h>
#include <suntool/tty.h>
#include <suntool/textsw.h>
#include <suntool/seln.h>
#include <suntool/alert.h>
#include <suntool/icon_load.h>

#include "help.c"

static char window_label[] = "Yale Univ. LCC MindTool 2.4 - [";
static char raster_file[] = "raster_file";
static char mind_icon_file[MAX_FILENAME_LEN] = MINDTOOL_ICON;
static char *cwd, *getcwd();
static char display_buf[MAX_FILENAME_LEN];
static char present_file[MAX_FILENAME_LEN];

static FILE	*fptest;	    /* fp to test file existence */
static FILE	*fp_tochild;	    /* fp of pipe to child (write data) */
static FILE	*fp_fromchild;	    /* fp of pipe from child (read data */
static FILE     *fpras;             /* name of raster file */

static int to_child;		    /* associated file descriptors to & from*/
static int from_child;
static int childpid;		    /* pid of child process */
static int child_is_dead = FALSE;   /* flag for a dying child */ 
static int first_time = TRUE;	    /* flag for initial entry */

/* 
 * Window, menus, fonts, and panel items.
 */
Frame		base_frame, tty;
Panel		button_panel, command_panel, message_panel;
Pixfont		*screen_font, *screen_font_bold;
Menu		menu, line_menu, width_menu, strings_menu, font_menu; 
Menu		pos_angle_menu, neg_angle_menu, main_angle_menu;	
Menu		stereo_menu;	
Panel_item	command_item, slider_item, projection_item;
Panel_item	slider_item_x, slider_item_y, slider_item_z;
Panel_item	model_item, label_item, message_item, arrow_item;
Panel_item	distance_item, angle_item, torsion_item;
Panel_item	partial_item, hide_item, hidenone_item, delete_item;
Panel_item	redraw_item, bond_item, limits_item, complete_item;
Panel_item	plot_item, zoom_item, pan_item, more_item;
Panel_item	add_label_item, move_label_item, delete_label_item;
Panel_item	add_arc_item, add_line_item, delete_line_item;
Panel_item	bond_type_item, number_item, dump_label_item;
Panel_item	stereo_item, main_help_item;

/*
 * Processes called by the notifier
 */
static void	pipe_data_proc(), write_file(), cd_proc(), style_proc();
static void	execute_proc(), quit_proc(), read_file(), plot_file();
static void	turn_proc_x(), turn_proc_y(), turn_proc_z(), save_proc();
static void	turn_proc_mx(), turn_proc_my(), turn_proc_mz(), text_proc();
static void	perspective_proc(), model_proc(), label_proc(), font_proc();
static void	load_icon(), yes_no_ok(), add_proc(), scale_proc();
static void	bond_proc(), pipe_menu_proc(), get_selection(), Mind_Help();
static void	dumpregion(), stereo_proc(), hbonds_proc();

static Icon mindtool_icon;
static struct pixrect *mind_pr;

/*
 * Handlers to take care of ugly situations
 */
static Notify_value mind_interposer(), mind_handler();
static Notify_value pipe_reader(), dead_child();

main(argc, argv)
int     argc;
char  **argv;
{
    int     next = 1;
    screen_font = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.r.16");
    screen_font_bold = pf_open("/usr/lib/fonts/fixedwidthfonts/screen.b.16");
/*
 *  Define a base frame and all of the associated panels.
 */
    base_frame = window_create(NULL, FRAME,
			       FRAME_NO_CONFIRM, TRUE,
			       WIN_X, 15, WIN_Y, 15,
			       FRAME_LABEL, window_label, 0);
    tty = window_create(base_frame, TTY,
			TTY_ARGV, TTY_ARGV_DO_NOT_FORK,
			TTY_QUIT_ON_CHILD_DEATH, FALSE,
			WIN_WIDTH, 800, WIN_HEIGHT, 800, 0);

    button_panel = window_create(base_frame, PANEL,
				 WIN_RIGHT_OF, tty,
				 WIN_Y, 0,
				 WIN_COLUMNS, 20,
				 WIN_FONT, screen_font,
				 WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
				 WIN_ROW_GAP, 7,
				 WIN_KBD_FOCUS, TRUE, 0);
    message_panel = window_create(base_frame, PANEL,
				  WIN_BELOW, tty, WIN_X, 0,
				  WIN_FONT, screen_font,
				  WIN_WIDTH, 800, WIN_ROWS, 1, 0);

/*
 *  Create menus, panels, and icons.
 */
    create_tty_menu();
    load_icon(argc, argv, &next);
    create_panel_items();
    window_fit(base_frame);
/*
 *  start the child process and tell the notifier about it
 */
    start_mind();
/*
 *  note that notify_set_input_func takes a file descriptor, not a file
 *  pointer used by the standard I/O library
 */
    (void) notify_set_input_func(base_frame, pipe_reader, from_child);
    (void) notify_interpose_event_func(base_frame, mind_interposer,
				       NOTIFY_SAFE);
    (void) notify_set_wait3_func(base_frame, dead_child, childpid);
    (void) notify_set_signal_func(base_frame, mind_handler, SIGHUP,
				  NOTIFY_ASYNC);
    if ((cwd = getcwd((char *) NULL, 64)) == NULL) {
	perror("pwd");
	exit(1);
    }
    if (argc >= 2 && argc != next) {
	panel_set_value(command_item, argv[next]);
	read_file();
    } else {
	get_selection();
	if (strlen(present_file) == 0) {
	    display_buf[0] = '\0';
	    sprintf(display_buf, "%s%s], dir: %s", window_label, present_file, cwd);
	    window_set(base_frame, FRAME_LABEL, display_buf, 0);
	} else {
	    panel_set_value(command_item, present_file);
	    read_file();
	}
    }
/*
 *  Pass control to the notifier and do a little hack to prevent the window
 *  from being repainted twice on initial entry.
 */
    first_time = FALSE;
/*
 * create a help window frame used for displaying bitmaps.
 */
    create_help_popup(base_frame);
    add_help_button(main_help_item, BITMAPS);

    window_main_loop(base_frame);
    exit(0);
}

create_tty_menu()
{
    line_menu = menu_create(MENU_ITEM,
			    	MENU_STRING, "Dashed line",
			    	MENU_FONT, screen_font,
			    	MENU_NOTIFY_PROC, style_proc,
			    	MENU_CLIENT_DATA, "1", 0,
			    MENU_ITEM,
			    	MENU_STRING, "Solid line",
			    	MENU_FONT, screen_font_bold,
			    	MENU_NOTIFY_PROC, style_proc,
			    	MENU_CLIENT_DATA, "0", 0, 0);

    font_menu = menu_create(MENU_ITEM,
			     	MENU_STRING, "Times-Roman",
			     	MENU_FONT, screen_font_bold,
			     	MENU_NOTIFY_PROC, font_proc,
			     	MENU_CLIENT_DATA, "0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "Helvetica",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, font_proc,
			     	MENU_CLIENT_DATA, "4", 0, 0);

    width_menu = menu_create(MENU_ITEM,
			     	MENU_STRING, "1",
			     	MENU_FONT, screen_font_bold,
			     	MENU_NOTIFY_PROC, style_proc,
			     	MENU_CLIENT_DATA, "11", 0,
			     MENU_ITEM,
			     	MENU_STRING, "3",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, style_proc,
			     	MENU_CLIENT_DATA, "12", 0,
			     MENU_ITEM,
			     	MENU_STRING, "5",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, style_proc,
			     	MENU_CLIENT_DATA, "13", 0,
			     MENU_ITEM,
			     	MENU_STRING, "7",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, style_proc,
			     	MENU_CLIENT_DATA, "14", 0, 0);

    strings_menu = menu_create(MENU_ITEM,
			       	MENU_STRING, "0.050",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.050", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.075",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.075", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.100",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.100", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.125",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.125", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.150",
			       	MENU_FONT, screen_font_bold,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.150", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.175",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.175", 0,
			       MENU_ITEM,
			       	MENU_STRING, "0.200",
			       	MENU_FONT, screen_font,
			       	MENU_NOTIFY_PROC, text_proc,
			       	MENU_CLIENT_DATA, "0.200", 0, 0);

    pos_angle_menu = menu_create(MENU_ITEM,
			     	MENU_STRING, "0.0",
			     	MENU_FONT, screen_font_bold,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "0.01", 0,
			     MENU_ITEM,
			     	MENU_STRING, "15.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "15.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "30.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "30.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "45.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "45.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "60.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "60.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "75.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "75.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "90.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "90.0", 0, 0);

    neg_angle_menu = menu_create(MENU_ITEM,
			     	MENU_STRING, "0.0",
			     	MENU_FONT, screen_font_bold,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "0.01", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-15.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-15.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-30.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-30.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-45.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-45.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-60.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-60.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-75.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-75.0", 0,
			     MENU_ITEM,
			     	MENU_STRING, "-90.0",
			     	MENU_FONT, screen_font,
			     	MENU_NOTIFY_PROC, text_proc,
			     	MENU_CLIENT_DATA, "-90.0", 0, 0);

    main_angle_menu = menu_create(MENU_ITEM,
					MENU_STRING, "Positive",
					MENU_FONT, screen_font,
					MENU_PULLRIGHT, pos_angle_menu, 0,
				  MENU_ITEM,
					MENU_STRING, "Negative",
					MENU_FONT, screen_font,
					MENU_PULLRIGHT, neg_angle_menu, 0, 0);

    menu = menu_create(MENU_ITEM,
		       	MENU_STRING, "Line/Arc Styles",
		       	MENU_FONT, screen_font,
		       	MENU_PULLRIGHT, line_menu, 0,
		       MENU_ITEM,
		       	MENU_STRING, "Line/Arc Widths",
		       	MENU_FONT, screen_font,
		       	MENU_PULLRIGHT, width_menu, 0,
		       MENU_ITEM,
		       	MENU_STRING, "Text Heights",
		       	MENU_FONT, screen_font,
		       	MENU_PULLRIGHT, strings_menu, 0,
		       MENU_ITEM,
		       	MENU_STRING, "Text Angles",
		       	MENU_FONT, screen_font,
		       	MENU_PULLRIGHT, main_angle_menu, 0,
		       MENU_ITEM,
		       	MENU_STRING, "Font Styles",
		       	MENU_FONT, screen_font,
		       	MENU_PULLRIGHT, font_menu, 0,
		       MENU_ITEM,
		       	MENU_STRING, "Draw Arc",
		       	MENU_FONT, screen_font,
		       	MENU_NOTIFY_PROC, pipe_menu_proc,
		       	MENU_CLIENT_DATA, "add arc", 0,
		       MENU_ITEM,
		       	MENU_STRING, "Draw Line",
		       	MENU_FONT, screen_font,
		       	MENU_NOTIFY_PROC, pipe_menu_proc,
		       	MENU_CLIENT_DATA, "add line", 0,
		       MENU_ITEM,
		       	MENU_STRING, "Draw Arrowhead",
		       	MENU_FONT, screen_font,
		       	MENU_NOTIFY_PROC, pipe_menu_proc,
		       	MENU_CLIENT_DATA, "add head", 0, 0);

    stereo_menu = menu_create(MENU_STRINGS,
				"Viewing (reduced)",
				"Publication (enlarged)",0,0);

    window_set(tty, WIN_MENU, menu, 0);

}

create_panel_items()
{
    message_item = panel_create_item(message_panel, PANEL_MESSAGE,
				     PANEL_LABEL_STRING,
    "Enter a file name at the File: prompt and hit the Read button.", 0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Quit", 0, 0),
		      PANEL_NOTIFY_PROC, quit_proc,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Exit the program immediately", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Save", 0, 0),
		      PANEL_NOTIFY_PROC, save_proc,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Save the screen as displayed", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "More", 0, 0),
		      PANEL_NOTIFY_PROC, pipe_data_proc,
		      PANEL_CLIENT_DATA, "more",
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Display the next structure in the file", 0,
		      0);

    redraw_item = panel_create_item(button_panel, PANEL_BUTTON,
				    PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Redraw", 0, 0),
				    PANEL_NOTIFY_PROC, pipe_data_proc,
				    PANEL_CLIENT_DATA, "draw",
				    PANEL_SHOW_MENU, TRUE,
				    PANEL_MENU_CHOICE_STRINGS,
				    "Redraw the current display", 0,
				    0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, " cd ", 0, 0),
		      PANEL_NOTIFY_PROC, cd_proc,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(1),
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Change to the default directory at the prompt", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Read", 0, 0),
		      PANEL_NOTIFY_PROC, read_file,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Read the file at the prompt", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Write", 0, 0),
		      PANEL_NOTIFY_PROC, write_file,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Write the coordinates as displayed", 0,
		      0);

    main_help_item = panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Help", 0, 0),
		      PANEL_NOTIFY_PROC, help_proc,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "General help", 0,
		      0);

    plot_item = panel_create_item(button_panel, PANEL_BUTTON,
				  PANEL_LABEL_IMAGE,
			  panel_button_image(button_panel, "Plot", 0, 0),
				  PANEL_ITEM_X, ATTR_COL(0),
				  PANEL_ITEM_Y, ATTR_ROW(2),
				  PANEL_NOTIFY_PROC, plot_file,
				  PANEL_SHOW_MENU, TRUE,
				  PANEL_MENU_CHOICE_STRINGS,
				  "Plot the display as shown", 0,
				  0);

    zoom_item = panel_create_item(button_panel, PANEL_BUTTON,
				  PANEL_LABEL_IMAGE,
			  panel_button_image(button_panel, "Zoom", 0, 0),
				  PANEL_NOTIFY_PROC, pipe_data_proc,
				  PANEL_CLIENT_DATA, "zoom",
				  PANEL_SHOW_MENU, TRUE,
				  PANEL_MENU_CHOICE_STRINGS,
				  "Zoom on a portion of the display", 0,
				  0);

    pan_item = panel_create_item(button_panel, PANEL_BUTTON,
				 PANEL_LABEL_IMAGE,
			   panel_button_image(button_panel, "Pan", 0, 0),
				 PANEL_NOTIFY_PROC, pipe_data_proc,
				 PANEL_CLIENT_DATA, "pan",
				 PANEL_SHOW_MENU, TRUE,
				 PANEL_MENU_CHOICE_STRINGS,
				 "Return display to full view", 0,
				 0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Scale", 0, 0),
		      PANEL_NOTIFY_PROC, scale_proc,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Scale the display by the amount given.", 0,
		      0);

    hide_item = panel_create_item(button_panel, PANEL_BUTTON,
				  PANEL_LABEL_IMAGE,
			  panel_button_image(button_panel, "Hide", 0, 0),
				  PANEL_ITEM_X, ATTR_COL(0),
				  PANEL_ITEM_Y, ATTR_ROW(3),
				  PANEL_NOTIFY_PROC, pipe_data_proc,
				  PANEL_CLIENT_DATA, "hide",
				  PANEL_SHOW_MENU, TRUE,
				  PANEL_MENU_CHOICE_STRINGS,
			    "Hide atom(s) and its bonds from display", 0,
				  0);

    hidenone_item = panel_create_item(button_panel, PANEL_BUTTON,
				      PANEL_LABEL_IMAGE,
		     panel_button_image(button_panel, "Hide None", 0, 0),
				      PANEL_NOTIFY_PROC, pipe_data_proc,
				      PANEL_CLIENT_DATA, "hide none",
				      PANEL_SHOW_MENU, TRUE,
				      PANEL_MENU_CHOICE_STRINGS,
				      "Display all atoms", 0,
				      0);

    complete_item = panel_create_item(button_panel, PANEL_BUTTON,
				      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Complete", 0, 0),
				      PANEL_NOTIFY_PROC, pipe_data_proc,
				      PANEL_CLIENT_DATA, "complete",
				      PANEL_SHOW_MENU, TRUE,
				      PANEL_MENU_CHOICE_STRINGS,
				      "Display connected-hidden atoms", 0,
				      0);

    dump_label_item = panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(4),
					  PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Dump", 0, 0),
				       PANEL_NOTIFY_PROC, dumpregion,
					  PANEL_SHOW_MENU, TRUE,
					  PANEL_MENU_CHOICE_STRINGS,
			       "Dump the display as a raster file", 0,
					  0);

    panel_create_item(button_panel, PANEL_BUTTON,
                                  PANEL_LABEL_IMAGE,
                          panel_button_image(button_panel, "Stereo", 0, 0),
                                  PANEL_NOTIFY_PROC, stereo_proc,
                                  PANEL_SHOW_MENU, TRUE,
                                PANEL_MENU_CHOICE_STRINGS,
                            "Create a stereo plot of the display", 0,
                                  0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Grid", 0, 0),
		      PANEL_NOTIFY_PROC, pipe_data_proc,
		      PANEL_CLIENT_DATA, "grid",
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Draw a regular grid for aligning text.", 0,
		      0);

    panel_create_item(button_panel, PANEL_MESSAGE,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(6),
		      PANEL_LABEL_BOLD, TRUE,
		      PANEL_LABEL_STRING,
		      "Bonds", 0);

    bond_item = panel_create_item(button_panel, PANEL_BUTTON,
				  PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Add Full", 0, 0),
				  PANEL_ITEM_X, ATTR_COL(0),
				  PANEL_ITEM_Y, ATTR_ROW(7),
				  PANEL_NOTIFY_PROC, pipe_data_proc,
				  PANEL_CLIENT_DATA, "add bond",
				  PANEL_SHOW_MENU, TRUE,
				  PANEL_MENU_CHOICE_STRINGS,
			    "Add a full bond between a pair of atoms", 0,
				  0);

    partial_item = panel_create_item(button_panel, PANEL_BUTTON,
				     PANEL_LABEL_IMAGE,
		   panel_button_image(button_panel, "Add Partial", 0, 0),
				     PANEL_NOTIFY_PROC, pipe_data_proc,
				     PANEL_CLIENT_DATA, "add partial",
				     PANEL_SHOW_MENU, TRUE,
				     PANEL_MENU_CHOICE_STRINGS,
			 "Add a partial bond between a pair of atoms", 0,
				     0);

    delete_item = panel_create_item(button_panel, PANEL_BUTTON,
				    PANEL_LABEL_IMAGE,
		   panel_button_image(button_panel, "Delete Bond", 0, 0),
				    PANEL_ITEM_X, ATTR_COL(0),
				    PANEL_ITEM_Y, ATTR_ROW(8),
				    PANEL_NOTIFY_PROC, pipe_data_proc,
				    PANEL_CLIENT_DATA, "delete bond",
				    PANEL_SHOW_MENU, TRUE,
				    PANEL_MENU_CHOICE_STRINGS,
			    "Delete any bond between a pair of atoms", 0,
				    0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "H-Bonds", 0, 0),
		      PANEL_NOTIFY_PROC, hbonds_proc,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		      "Toggle H-bonds on or off.", 0,
		      0);

    distance_item = panel_create_item(button_panel, PANEL_BUTTON,
				      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Distance", 0, 0),
				      PANEL_ITEM_X, ATTR_COL(0),
				      PANEL_ITEM_Y, ATTR_ROW(10),
				      PANEL_NOTIFY_PROC, pipe_data_proc,
				      PANEL_CLIENT_DATA, "tell distance",
				      PANEL_SHOW_MENU, TRUE,
				      PANEL_MENU_CHOICE_STRINGS,
			 "Click on two atoms and report the distance", 0,
				      0);

    angle_item = panel_create_item(button_panel, PANEL_BUTTON,
				   PANEL_LABEL_IMAGE,
			 panel_button_image(button_panel, "Angle", 0, 0),
				   PANEL_NOTIFY_PROC, pipe_data_proc,
				   PANEL_CLIENT_DATA, "tell angle",
				   PANEL_SHOW_MENU, TRUE,
				   PANEL_MENU_CHOICE_STRINGS,
			  "Click on three atoms and report the angle", 0,
				   0);

    torsion_item = panel_create_item(button_panel, PANEL_BUTTON,
				     PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "Dihedral", 0, 0),
				     PANEL_NOTIFY_PROC, pipe_data_proc,
				     PANEL_CLIENT_DATA, "tell tor",
				     PANEL_SHOW_MENU, TRUE,
				     PANEL_MENU_CHOICE_STRINGS,
			"Click on four atoms and report the dihedral", 0,
				     0);

    limits_item = panel_create_item(button_panel, PANEL_BUTTON,
				    PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Limits", 0, 0),
				    PANEL_NOTIFY_PROC, pipe_data_proc,
				    PANEL_CLIENT_DATA, "tell limits",
				    PANEL_SHOW_MENU, TRUE,
				    PANEL_MENU_CHOICE_STRINGS,
			      "Report the molecular Z display limits", 0,
				    0);

    number_item = panel_create_item(button_panel, PANEL_BUTTON,
				   PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Number", 0, 0),
				   PANEL_NOTIFY_PROC, pipe_data_proc,
				   PANEL_CLIENT_DATA, "tell number",
				   PANEL_SHOW_MENU, TRUE,
				   PANEL_MENU_CHOICE_STRINGS,
			     "Click on an atom and report its number", 0,
				   0);

    panel_create_item(button_panel, PANEL_MESSAGE,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(13),
		      PANEL_LABEL_BOLD, TRUE,
		      PANEL_LABEL_STRING,
		      "Rotations", 0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "  X  ", 0, 0),
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(14),
		      PANEL_NOTIFY_PROC, turn_proc_x,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		    "Rotate the display in the clockwise X direction", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "  Y  ", 0, 0),
		      PANEL_NOTIFY_PROC, turn_proc_y,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		    "Rotate the display in the clockwise Y direction", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, "  Z  ", 0, 0),
		      PANEL_NOTIFY_PROC, turn_proc_z,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		    "Rotate the display in the clockwise Z direction", 0,
		      0);

    panel_create_item(button_panel, PANEL_BUTTON,
		      PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, " -X  ", 0, 0),
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(15),
		      PANEL_NOTIFY_PROC, turn_proc_mx,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		"Rotate the display in the counterclockwise X direction",
		      0, 0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, " -Y  ", 0, 0),
		      PANEL_NOTIFY_PROC, turn_proc_my,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		"Rotate the display in the counterclockwise Y direction",
		      0, 0);

    panel_create_item(button_panel, PANEL_BUTTON, PANEL_LABEL_IMAGE,
		      panel_button_image(button_panel, " -Z  ", 0, 0),
		      PANEL_NOTIFY_PROC, turn_proc_mz,
		      PANEL_SHOW_MENU, TRUE,
		      PANEL_MENU_CHOICE_STRINGS,
		"Rotate the display in the counterclockwise Z direction",
		      0, 0);

    slider_item_x = panel_create_item(button_panel, PANEL_SLIDER,
				      PANEL_ITEM_X, ATTR_COL(0),
				      PANEL_ITEM_Y, ATTR_ROW(17),
				      PANEL_LABEL_STRING, "X :",
		PANEL_VALUE, 10, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, 90,
				      PANEL_SLIDER_WIDTH, 100,
				      0);

    slider_item_y = panel_create_item(button_panel, PANEL_SLIDER,
				      PANEL_ITEM_X, ATTR_COL(0),
				      PANEL_ITEM_Y, ATTR_ROW(18),
				      PANEL_LABEL_STRING, "Y :",
		PANEL_VALUE, 10, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, 90,
				      PANEL_SLIDER_WIDTH, 100,
				      0);

    slider_item_z = panel_create_item(button_panel, PANEL_SLIDER,
				      PANEL_ITEM_X, ATTR_COL(0),
				      PANEL_ITEM_Y, ATTR_ROW(19),
				      PANEL_LABEL_STRING, "Z :",
		PANEL_VALUE, 10, PANEL_MIN_VALUE, 1, PANEL_MAX_VALUE, 90,
				      PANEL_SLIDER_WIDTH, 100,
				      0);

    model_item = panel_create_item(button_panel, PANEL_CHOICE,
				   PANEL_ITEM_X, ATTR_COL(0),
				   PANEL_ITEM_Y, ATTR_ROW(21),
		    PANEL_CHOICE_STRINGS, "Wireframe", "Ball-n-Stick", 0,
				   PANEL_NOTIFY_PROC, model_proc,
				   0);

    bond_type_item = panel_create_item(button_panel, PANEL_CHOICE,
				       PANEL_ITEM_X, ATTR_COL(0),
				       PANEL_ITEM_Y, ATTR_ROW(22),
		PANEL_CHOICE_STRINGS, "Flat Bond", "Round Bond", 0,
				       PANEL_NOTIFY_PROC, bond_proc,
				       0);

    projection_item = panel_create_item(button_panel, PANEL_CHOICE,
					PANEL_ITEM_X, ATTR_COL(0),
					PANEL_ITEM_Y, ATTR_ROW(23),
		 PANEL_CHOICE_STRINGS, "Orthographic", "Perspective", 0,
				     PANEL_NOTIFY_PROC, perspective_proc,
					0);

    label_item = panel_create_item(button_panel, PANEL_CHOICE,
				   PANEL_ITEM_X, ATTR_COL(0),
				   PANEL_ITEM_Y, ATTR_ROW(24),
	    PANEL_CHOICE_STRINGS, "No Label", "Symbol", "Number", 0,
				   PANEL_NOTIFY_PROC, label_proc,
				   0);

    command_item = panel_create_item(button_panel, PANEL_TEXT,
				     PANEL_ITEM_X, ATTR_COL(0),
				     PANEL_ITEM_Y, ATTR_ROW(26),
				     PANEL_BLINK_CARET, FALSE,
				     PANEL_VALUE_DISPLAY_LENGTH, 20,
				     PANEL_LABEL_STRING, "File:",
				     PANEL_NOTIFY_LEVEL, PANEL_SPECIFIED,
				     PANEL_NOTIFY_STRING, "\015",
				     PANEL_NOTIFY_PROC, execute_proc,
				     PANEL_SHOW_MENU, TRUE,
				     PANEL_MENU_CHOICE_STRINGS,
			 "Enter commands, filenames, and directories", 0,
				     0);

    panel_create_item(button_panel, PANEL_MESSAGE,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(28),
		      PANEL_LABEL_BOLD, TRUE,
		      PANEL_LABEL_STRING,
		      "Text", 0);

    add_label_item = panel_create_item(button_panel, PANEL_BUTTON,
				       PANEL_LABEL_IMAGE,
			   panel_button_image(button_panel, "Add", 0, 0),
				       PANEL_ITEM_X, ATTR_COL(0),
				       PANEL_ITEM_Y, ATTR_ROW(29),
				       PANEL_NOTIFY_PROC, add_proc,
				       PANEL_SHOW_MENU, TRUE,
				       PANEL_MENU_CHOICE_STRINGS,
				    "Add a text label to the display", 0,
				       0);

    move_label_item = panel_create_item(button_panel, PANEL_BUTTON,
					PANEL_LABEL_IMAGE,
			  panel_button_image(button_panel, "Move", 0, 0),
					PANEL_NOTIFY_PROC, pipe_data_proc,
					PANEL_CLIENT_DATA, "move label",
					PANEL_SHOW_MENU, TRUE,
					PANEL_MENU_CHOICE_STRINGS,
				   "Move a text label on the display", 0,
					0);

    delete_label_item = panel_create_item(button_panel, PANEL_BUTTON,
					  PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Delete", 0, 0),
				       PANEL_NOTIFY_PROC, pipe_data_proc,
				       PANEL_CLIENT_DATA, "delete label",
					  PANEL_SHOW_MENU, TRUE,
					  PANEL_MENU_CHOICE_STRINGS,
			       "Delete a text label from the display", 0,
					  0);

    panel_create_item(button_panel, PANEL_MESSAGE,
		      PANEL_ITEM_X, ATTR_COL(0),
		      PANEL_ITEM_Y, ATTR_ROW(31),
		      PANEL_LABEL_BOLD, TRUE,
		      PANEL_LABEL_STRING,
		      "Draw", 0);

    add_arc_item = panel_create_item(button_panel, PANEL_BUTTON,
				     PANEL_ITEM_X, ATTR_COL(0),
				     PANEL_ITEM_Y, ATTR_ROW(32),
				     PANEL_LABEL_IMAGE,
			   panel_button_image(button_panel, "Arc", 0, 0),
				     PANEL_NOTIFY_PROC, pipe_data_proc,
				     PANEL_CLIENT_DATA, "add arc",
				     PANEL_SHOW_MENU, TRUE,
				     PANEL_MENU_CHOICE_STRINGS,
				  "Add a circular arc to the display", 0,
				     0);

    add_line_item = panel_create_item(button_panel, PANEL_BUTTON,
				      PANEL_LABEL_IMAGE,
			  panel_button_image(button_panel, "Line", 0, 0),
				      PANEL_NOTIFY_PROC, pipe_data_proc,
				      PANEL_CLIENT_DATA, "add line",
				      PANEL_SHOW_MENU, TRUE,
				      PANEL_MENU_CHOICE_STRINGS,
				      "Add a line to the display", 0,
				      0);

    arrow_item = panel_create_item(button_panel, PANEL_BUTTON,
				   PANEL_LABEL_IMAGE,
			 panel_button_image(button_panel, "Arrow", 0, 0),
				   PANEL_NOTIFY_PROC, pipe_data_proc,
				   PANEL_CLIENT_DATA, "add head",
				   PANEL_SHOW_MENU, TRUE,
				   PANEL_MENU_CHOICE_STRINGS,
				"Add an arrowhead to an arc or line.", 0,
				   0);

    delete_line_item = panel_create_item(button_panel, PANEL_BUTTON,
					 PANEL_LABEL_IMAGE,
			panel_button_image(button_panel, "Delete", 0, 0),
				       PANEL_NOTIFY_PROC, pipe_data_proc,
					 PANEL_CLIENT_DATA, "delete line",
					 PANEL_SHOW_MENU, TRUE,
					 PANEL_MENU_CHOICE_STRINGS,
			      "Delete a line or arc from the display", 0,
					 0);

    window_fit_height(command_panel);
    window_fit_width(button_panel);

}

static void add_proc()
{
    char   *text_to_add;

    text_to_add = (char *) panel_get_value(command_item);
    if (strlen(text_to_add) == 0) {
	panel_set(command_item, PANEL_LABEL_STRING, "Label:", 0);
	msg("Enter text at the \"Label:\" prompt and hit the \"Add\" button.", 1);
	return;
    }
    send_to_mind("add label");
    send_message("  ");
    send_to_mind(text_to_add);
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    panel_set_value(command_item, "");
}

/*
 * Change the default directory
 */

static void cd_proc()
{
    char   *current_dir;
    current_dir = (char *) panel_get_value(command_item);
    if (strlen(current_dir) == NULL) {
	panel_set(command_item, PANEL_LABEL_STRING, "Dir:", 0);
	msg("Enter path name at the \"Dir:\" prompt and hit the \"cd\" button.", 1);
	return;
    }
    if (chdir(current_dir) != NULL) {
	panel_set(command_item, PANEL_LABEL_STRING, "Dir:", 0);
	msg("Fix path name at the \"Dir:\" prompt.", 1);
	return;
    }
    if ((cwd = getcwd((char *) NULL, 64)) == NULL) {
	perror("pwd");
	exit(1);
    }
    panel_set_value(command_item, "");
    display_buf[0] = '\0';
    sprintf(display_buf, "%s%s], dir: %s", window_label, present_file, cwd);
    window_set(base_frame, FRAME_LABEL, display_buf, 0);
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    send_message("Changed current working directory.");
}

/*
 * Get the associated button data and pipe it to mind.
 */
static void pipe_data_proc(item, event)
Panel_item item;
Event   event;
{
    send_to_mind((char *) panel_get(item, PANEL_CLIENT_DATA));
}

/*
 * Get the associated menu data and pipe it to mind.
 */
static void pipe_menu_proc(m, mi)
Menu    m;
Menu_item mi;
{
    send_to_mind((char *) menu_get(mi, MENU_CLIENT_DATA));
}

static void execute_proc()
{
    send_to_mind((char *) panel_get_value(command_item));
}

static void label_proc(item, value, event)
Panel_item item;
int     value;
Event   event;
{
    switch (value) {
      case 0: send_to_mind("set label none"); break;
      case 1: send_to_mind("set label character"); break;
      case 2: send_to_mind("set label number"); break;
      default:
	send_to_mind("set label none");
	break;
    }
}

static void stereo_proc(item, event)
Panel_item item;
Event  *event;
{
    int  size;

	size = (int) menu_show(stereo_menu, button_panel, event, 0);
    	switch (size) {
	        case 1: send_to_mind("stereo view"); break;
      		case 2: send_to_mind("stereo publ"); break;
      		default: break;
	}
}

static void read_file()
{
    char    filename_buf[MAX_FILENAME_LEN];
/*
 * get the filename at the prompt and check if it exists.
 */
    filename_buf[0] = '\0';
    sprintf(present_file, "%s", panel_get_value(command_item));
    if ((fptest = fopen(present_file, "r")) == NULL) {
	panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
	present_file[0] = '\0';
	msg("Fix the file name at the \"File:\" prompt.", 1);
	return;
    }
    send_to_mind("new");
    send_message("  ");
    sprintf(filename_buf, "%s/%s", cwd, present_file);
    send_to_mind(filename_buf);
    if (!first_time)
	send_to_mind("draw");
    display_buf[0] = '\0';
    sprintf(display_buf, "%s%s], dir: %s", window_label, present_file, cwd);
    window_set(base_frame, FRAME_LABEL, display_buf, 0);
/*
 * Reset all relative display parameters.
 */
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    panel_set_value(slider_item_x, 10);
    panel_set_value(slider_item_y, 10);
    panel_set_value(slider_item_z, 10);
    panel_set_value(model_item, 0);
    panel_set_value(bond_type_item, 0);
    panel_set_value(projection_item, 0);
    panel_set_value(label_item, 0);
    panel_set_value(command_item, "");
    return;
}

static void model_proc(item, value, event)
Panel_item item;
int     value;
Event   event;
{
    if (value == 0) {
	send_to_mind("set model wire");
    } else {
	send_to_mind("set model ball");
    }
}

static void bond_proc(item, value, event)
Panel_item item;
int     value;
Event   event;
{
    if (value == 0) {
	send_to_mind("set bond cap");
    } else {
	send_to_mind("set bond round");
    }
}

static void font_proc(m, mi)
Menu    m;
Menu_item mi;
{
    char    cmdstring[80];
    sprintf(cmdstring, "set font %s", menu_get(mi, MENU_CLIENT_DATA));
    send_to_mind(cmdstring);
}

static void perspective_proc(item, value, event)
Panel_item item;
int     value;
Event   event;
{
    if (value == 0) {
	send_to_mind("set projection ortho");
    } else {
	send_to_mind("set projection per");
    }
}

/*
 * Destroy the base frame and all windows in its path.
 */
static void quit_proc()
{
    send_to_mind("quit");
    sleep(1);
    window_done(base_frame);
}

static void style_proc(m, mi)
Menu    m;
Menu_item mi;
{
    char    cmdstring[80];
    sprintf(cmdstring, "set line %s", menu_get(mi, MENU_CLIENT_DATA));
    send_to_mind(cmdstring);
}

static void scale_proc()
{
    char    cmdstring[80];

	sprintf(cmdstring, "set scale %s", panel_get_value(command_item));
	send_to_mind(cmdstring);
}

static void hbonds_proc()
{
    char    cmdstring[80];

	sprintf(cmdstring, "set hbonds %s", panel_get_value(command_item));
	send_to_mind(cmdstring);
}

static void text_proc(m, mi)
Menu    m;
Menu_item mi;
{
    char    cmdstring[80];
    sprintf(cmdstring, "set text %s", menu_get(mi, MENU_CLIENT_DATA));
    send_to_mind(cmdstring);
}
static void turn_proc_mx()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn x %d", -(int) panel_get_value(slider_item_x));
    send_to_mind(cmdstring);
}

static void turn_proc_x()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn x %d", (int) panel_get_value(slider_item_x));
    send_to_mind(cmdstring);
}

static void turn_proc_my()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn y %d", -(int) panel_get_value(slider_item_y));
    send_to_mind(cmdstring);
}

static void turn_proc_y()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn y %d", (int) panel_get_value(slider_item_y));
    send_to_mind(cmdstring);
}

static void turn_proc_mz()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn z %d", -(int) panel_get_value(slider_item_z));
    send_to_mind(cmdstring);
}

static void turn_proc_z()
{
    char    cmdstring[80];
    sprintf(cmdstring, "turn z %d", (int) panel_get_value(slider_item_z));
    send_to_mind(cmdstring);
}

static void write_file()
{
    char    filename_buf[MAX_FILENAME_LEN];
    char   *file_to_write;

    file_to_write = (char *) panel_get_value(command_item);
    if (strlen(file_to_write) == 0) {
        file_to_write = present_file;
        if (strlen(file_to_write) == 0) {
            panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
            msg("No default filename found.", 1);
            return;
        }
    }   
    if ((fptest = fopen(file_to_write, "w")) == NULL) {
        panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
        msg("Unable to write file, check permission.");
        return;
    }
    send_to_mind("write coor");
    send_message("  ");
    sprintf(filename_buf, "%s/%s", cwd, file_to_write);
    send_to_mind(filename_buf);
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    panel_set_value(command_item, "");
}

static void plot_file()
{
    char    filename_buf[MAX_FILENAME_LEN];
    char   *file_to_plot;

    file_to_plot = (char *) panel_get_value(command_item);
    if (strlen(file_to_plot) == 0) {
        send_to_mind("plot");
        return;
    } else {
        send_to_mind("plot file");
    }    
    if ((fptest = fopen(file_to_plot, "w")) == NULL) {
        panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
        msg("Unable to open plot file, check permission.");
        return;
    }
    send_message("  ");
    sprintf(filename_buf, "%s/%s", cwd, file_to_plot);
    send_to_mind(filename_buf);
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    panel_set_value(command_item, "");
}

static void save_proc()
{
    char    filename_buf[MAX_FILENAME_LEN];
    char   *file_to_write;

    file_to_write = (char *) panel_get_value(command_item);
    if (strlen(file_to_write) == 0) {
        file_to_write = present_file;
        if (strlen(file_to_write) == 0) {
	    panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
	    msg("No default filename found.", 1);
	    return;
        }
    }
    if ((fptest = fopen(file_to_write, "w")) == NULL) {
	panel_set(command_item, PANEL_LABEL_STRING, "File:", 0);
	msg("Unable to write file, check permission.");
	return;
    }
    send_to_mind("write all");
    send_message("  ");
    sprintf(filename_buf, "%s/%s", cwd, file_to_write);
    send_to_mind(filename_buf);
    panel_set(command_item, PANEL_LABEL_STRING, "Cmd:", 0);
    panel_set_value(command_item, "");
}

static  start_mind()
{
    int     pipeto[2], pipefrom[2];
    int     c, numfds;

    if (pipe(pipeto) < 0 || pipe(pipefrom) < 0) {
	perror("mind");
	exit(1);
    }
    switch (childpid = fork()) {

      case -1:
	perror("mind");
	exit(1);

      case 0:	
/*
 *     This is the child process.
 *     Use dup2 to set the child's stdin and stdout to the pipes
 */

	dup2(pipeto[0], 0);
	dup2(pipefrom[1], 1);

/*
 *     Close all other fds (except stderr) since the child process doesn't
 *     know about or need them
 */

	numfds = getdtablesize();
	for (c = 3; c < numfds; c++)
	    close(c);

/*
 *     Execute the child process
 */

	execl(CHILD, "mind", 0);
	perror("mind (child)");	/* Shouldn't get here */
	exit(1);

      default:	
/*    
 *    This is the parent
 */
	close(pipeto[0]);
	close(pipefrom[1]);
	to_child = pipeto[1];
	fp_tochild = fdopen(to_child, "w");
	from_child = pipefrom[0];
	fp_fromchild = fdopen(from_child, "r");

/*
 *     The pipe to mind must be unbuffered or it will not get any data
 *     until 1024 characters have been sent
 */

	setbuf(fp_tochild, NULL);
	break;
    }
}

/*
 * Notify proc that is called whenever there is data to read on the pipe from
 * the child process.
 */

static  Notify_value
        pipe_reader(frame, fd)
Frame   frame;
int     fd;
{
    char    buf[MAX_FILENAME_LEN];

    fgets(buf, 80, fp_fromchild);
    buf[strlen(buf) - 1] = '\0';	/* Strip off the newline character */
    send_message(buf);
    return (NOTIFY_DONE);
}

/*
 * The notify proc that is called if the child dies
 */

static  Notify_value
        dead_child(frame, pid, status, rusage)
Frame   frame;
int     pid;
union wait *status;
struct rusage *rusage;
{
    send_message("mind has died, sorry!");
    child_is_dead = TRUE;

/*
 *  Tell the notifier to stop reading the pipe (since it is invalid now)
 */

    (void) notify_set_input_func(base_frame, NOTIFY_FUNC_NULL,
				 from_child);
    close(to_child);
    close(from_child);
    return (NOTIFY_DONE);
}

static  Notify_value
        mind_interposer(frame, event, arg, type)
Frame   frame;
Event  *event;
Notify_arg arg;
Notify_event_type type;
{
    Notify_value value;

    value = notify_next_event_func(frame, event, arg, type);
    if (event_id(event) == WIN_REPAINT)
	send_to_mind("draw");
    return (value);
}

static void load_icon(argc, argv, next)
int     argc, *next;
char  **argv;
{
    int     i;
    char   *err_msg;
    for (i = 1; i < argc - 1; i++) {
	if (!strcmp(argv[i], "-i")) {
	    strcpy(mind_icon_file, argv[i + 1]);
	    *next = i + 2;
	}
    }
    if ((mind_pr = icon_load_mpr(mind_icon_file, err_msg)) == NULL) {
	fprintf(stderr, "%s\n", err_msg);
	exit(1);
    }
    mindtool_icon = icon_create(ICON_IMAGE, mind_pr,
				ICON_LABEL, "",
				ICON_WIDTH, mind_pr->pr_size.x,
				ICON_HEIGHT, mind_pr->pr_size.y,
				0);
    window_set(base_frame, FRAME_ICON, mindtool_icon, 0);
}
static void get_selection()
{
    Seln_holder holder;
    Seln_request *buffer;

    holder = seln_inquire(SELN_PRIMARY);
    buffer = seln_ask(&holder, SELN_REQ_CONTENTS_ASCII, 0, 0);
    strncpy(present_file, buffer->data + sizeof(Seln_attribute), MAX_FILENAME_LEN);

}

static  send_message(message_string)
char   *message_string;
{
    panel_set(message_item, PANEL_LABEL_STRING, message_string, 0);

}

/* 
 * Send a character over the pipe to mind
 */

static  send_to_mind(string)
char   *string;
{
    if (child_is_dead)
	send_message("mind has died, sorry!");
    else
	fprintf(fp_tochild, "%s\n", string);
}
static  Notify_value
        mind_handler(client, signal, when)
int    *client;
int     signal;
Notify_signal_mode when;
{
/*
 *  Ignore the Hangup message generated when the TTY_ARGV does not allow
 *  forks and the child is terminated.
 */
    return (NOTIFY_IGNORED);
}

msg(msg, beep)
char   *msg;
int     beep;
{
    char    buf[300];
    int     result;
    Event   event;	/* unused */
    char   *contine_msg = "Press \"Continue\" to proceed.";

    result = alert_prompt(base_frame, &event,
			  ALERT_MESSAGE_STRINGS,
			  msg,
			  contine_msg,
			  0,
			  ALERT_NO_BEEPING, (beep) ? 0 : 1,
			  ALERT_BUTTON_YES, "Continue",
			  ALERT_TRIGGER, ACTION_STOP,	/* allow either YES or
							   NO answer */
			  0);
    switch (result) {
      case ALERT_YES:
      case ALERT_TRIGGERED:	/* result of ACTION_STOP trigger */
	break;
      case ALERT_FAILED:	
	break;
    }
}

static void
dumpregion()
{
    int left, top, width, height;
    Pixrect *pr, *pr2;

    pr = pr_open("/dev/fb");
    if (pr == 0)
    {
        msg("Can't open /dev/fb\n",1);
        exit(1);
    }
    if ((fpras = fopen(raster_file, "w")) == NULL) {
        msg("Can't open raster_file\n",1);
	return;
    }
    width = (int) window_get(tty, WIN_WIDTH);
    height = (int) window_get(tty, WIN_HEIGHT);

    left = (int) window_get(base_frame, WIN_X);
    left += (int) window_get(base_frame, WIN_LEFT_MARGIN);
    top = (int) window_get(base_frame, WIN_Y);
    top += (int) window_get(base_frame, WIN_TOP_MARGIN);

    pr2 = pr_region(pr, left, top, width, height);

    if(pr_dump(pr2, fpras, (colormap_t *)0, RT_BYTE_ENCODED, 1) != 0)
    {
        perror("pr_dump");
        exit(1);
    }
}
