#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <unistd.h>

#include "../include/disk.h"
#include "guiutils.h"
#include "conmsg.h"

#include "images/icon_info_32x32.xpm"
#include "images/icon_warning_32x32.xpm"

#include "images/icon_ok_20x20.xpm"
#include "images/icon_cancel_20x20.xpm"
#include "images/icon_clear_20x20.xpm"


/*
 *	Message Dialog:
 */
typedef struct {

	GtkWidget	*toplevel;
	GtkAccelGroup	*accelgrp;
	gint		freeze_count;
	GdkFont		*font;

	GtkWidget	*text,
			*ok_btn,
			*no_more_messages_btn,
			*clear_btn;
} ConMsgDlg;
#define CON_MSG_DLG(p)		((ConMsgDlg *)(p))


static gchar		*prog_name = NULL,
			*out_dlg_title = NULL,
			*err_dlg_title = NULL;
static gint		terminal_columns = 80,
			terminal_lines = 20;
static gboolean		out_show = TRUE,
			err_show = TRUE;
static gint		out_rfd = -1,
			out_wfd = -1,
			err_rfd = -1,
			err_wfd = -1;
static guint		msg_check_toid = 0;
static ConMsgDlg	*out_dlg = NULL,
			*err_dlg = NULL;


static gint ConMsgDlgEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
);
static void ConMsgDlgOKCB(GtkWidget *widget, gpointer data);
static void ConMsgDlgNoMoreMessagesCB(GtkWidget *widget, gpointer data);
static void ConMsgDlgClearCB(GtkWidget *widget, gpointer data);
static ConMsgDlg *ConMsgDlgNew(
	const gchar *title, guint8 **icon_data,
	gint columns, gint lines
);
static void ConMsgDlgMsgAppend(ConMsgDlg *d, const gchar *s);
static void ConMsgDlgDelete(ConMsgDlg *d);

static gboolean ConMsgGetMsg(
	gint fd, ConMsgDlg **d_ptr,
	const gchar *title, guint8 **icon_data
);
static gint ConMsgCheckTimeoutCB(gpointer data);
static gint ConMsgBuffersReset(void);

gint ConMsgInit(
	const gchar *name,	/* Program name */
	gint columns,		/* Can be 0 to indicate use env var $COLUMNS */
	gint lines,		/* Can be 0 to indicate use env var $LINES */
	gboolean show_stdout,
	gboolean show_stderr
);
gint ConMsgReset(
	const gchar *name,	/* Program name */
	gint columns,		/* Can be 0 to indicate use env var $COLUMNS */
	gint lines,		/* Can be 0 to indicate use env var $LINES */
	gboolean show_stdout,
	gboolean show_stderr
);
void ConMsgShutdown(void);

void ConMsgStdOutDlgMap(void);
void ConMsgStdErrDlgMap(void);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s)       (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)        (((a) > (b)) ? (a) : (b))
#define MIN(a,b)        (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s)       (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)

#define UNLINK(p)	(STRISEMPTY(p) ? -1 : (gint)unlink((const char *)(p)))
#define CLOSE(i)	(((i) > -1) ? (gint)close((int)i) : -1)


/*
 *	Message Dialog toplevel GtkWindow event signal callback.
 */
static gint ConMsgDlgEventCB(
	GtkWidget *widget, GdkEvent *event, gpointer data
)
{
	gint status = FALSE;
	ConMsgDlg *d = CON_MSG_DLG(data);
	if((widget == NULL) || (event == NULL) || (d == NULL))
	    return(status);

	switch((gint)event->type)
	{
	  case GDK_DELETE:
	    ConMsgDlgOKCB(d->ok_btn, d);
	    d = NULL;
	    status = TRUE;
	    break;
	}

	return(status);
}

/*
 *	Message Dialog OK callback.
 */
static void ConMsgDlgOKCB(GtkWidget *widget, gpointer data)
{
	ConMsgDlg *d = CON_MSG_DLG(data);
	if(d == NULL)
	    return;

	/* Reset the global variable that references this Message Dialog
	 * and delete this Message Dialog
	 */
	if(d == out_dlg)
	    out_dlg = NULL;
	else if(d == err_dlg)
	    err_dlg = NULL;

	ConMsgDlgDelete(d);
}

/*
 *	Message Dialog No More Messages callback.
 */
static void ConMsgDlgNoMoreMessagesCB(GtkWidget *widget, gpointer data)
{                          
	ConMsgDlg *d = CON_MSG_DLG(data);
	if(d == NULL)
	    return;

	/* Reset the global variable that references this Message Dialog
	 * and delete this Message Dialog
	 */
	if(d == out_dlg)
	{
	    out_show = FALSE;
	    out_dlg = NULL;
	}
	else if(d == err_dlg)
	{
	    err_show = FALSE;
	    err_dlg = NULL;
	}

	ConMsgDlgDelete(d);
}

/*
 *	Message Dialog Clear callback.
 */
static void ConMsgDlgClearCB(GtkWidget *widget, gpointer data)
{
	GtkText *text;
	ConMsgDlg *d = CON_MSG_DLG(data);
	if(d == NULL)
	    return;

	text = GTK_TEXT(d->text);
	gtk_text_freeze(text);
	gtk_text_set_point(text, 0);
	gtk_text_forward_delete(
	    text,
	    gtk_text_get_length(text)
	);
	gtk_text_thaw(text);
}


/*
 *	Creates a new Message Dialog.
 */
static ConMsgDlg *ConMsgDlgNew(
	const gchar *title, guint8 **icon_data,
	gint columns, gint lines
)
{
	const gint	border_major = 5,
			border_minor = 2;
	gint font_width, font_height;
	GdkFont *font;
	GdkWindow *window;
	GtkAccelGroup *accelgrp;
	GtkWidget *w, *parent, *parent2, *toplevel, *sb;
	ConMsgDlg *d = CON_MSG_DLG(g_malloc0(sizeof(ConMsgDlg)));
	if(d == NULL)
	    return(NULL);

	if(columns <= 0)
	    columns = 80;
	if(lines <= 0)
	    lines = 20;

	/* Load default font (must be a fixed-width font) and get its
	 * size
	 */
	font = gdk_font_load(
"-adobe-courier-medium-r-normal-*-12-*-*-*-m-*-iso8859-1"
	);
	if(font == NULL)
	    font = gdk_font_load("6x12");
	if(font != NULL)
	{
	    GdkTextBounds b;
	    gdk_text_bounds(font, "X", 1, &b);
	    font_width = b.width;
	    font_height = font->ascent + font->descent;
	}
	else
	{
	    font_width = 6;
	    font_height = 12;
	}

	/* Reset values */
	d->accelgrp = accelgrp = gtk_accel_group_new();
	d->freeze_count = 0;  
	d->font = font;

	/* Toplevel */
	d->toplevel = toplevel = w = gtk_window_new(GTK_WINDOW_DIALOG);
	gtk_window_set_position(GTK_WINDOW(w), GTK_WIN_POS_MOUSE);
	gtk_window_set_policy(
	    GTK_WINDOW(w), TRUE, TRUE, TRUE
	);
	if(title != NULL)
	    gtk_window_set_title(GTK_WINDOW(w), title);
	if(!STRISEMPTY(prog_name))
	    gtk_window_set_wmclass(
		GTK_WINDOW(w), "dialog", prog_name
	    );

	gtk_widget_realize(w);
	window = w->window;
	if(window != NULL)
	{
	    gdk_window_set_decorations(
		window,
		GDK_DECOR_BORDER | GDK_DECOR_MENU | GDK_DECOR_TITLE |
		GDK_DECOR_MINIMIZE
	    );
	    gdk_window_set_functions(
		window,
		GDK_FUNC_MOVE | GDK_FUNC_MINIMIZE | GDK_FUNC_CLOSE
	    );
	    GUISetWMIcon(window, icon_data);
	}
	gtk_signal_connect(
	    GTK_OBJECT(w), "delete_event",
	    GTK_SIGNAL_FUNC(ConMsgDlgEventCB), d
	);
	gtk_window_add_accel_group(GTK_WINDOW(w), accelgrp);
	parent = w;

	/* Main vbox */
	w = gtk_vbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(parent), w);
	gtk_widget_show(w);
	parent = w;

	/* Text table */
	w = gtk_table_new(2, 2, FALSE);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_table_set_row_spacing(GTK_TABLE(w), 0, border_minor);
	gtk_table_set_col_spacing(GTK_TABLE(w), 0, border_minor);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;
	/* Text */
	d->text = w = gtk_text_new(NULL, NULL);
	gtk_widget_set_usize(
	    w,
	    MAX(
		(font_width * columns) + (2 * border_major),
		300
	    ),
	    MAX(
		(font_height * lines) + (2 * border_major),
		100
	    )
	);	    
	gtk_text_set_editable(GTK_TEXT(w), FALSE);
	gtk_text_set_word_wrap(GTK_TEXT(w), TRUE);
	gtk_table_attach(
	    GTK_TABLE(parent2), w,
	    0, 1, 0, 1,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(w);
	/* Vertical scroll bar */
	sb = gtk_vscrollbar_new(GTK_TEXT(w)->vadj);
	gtk_table_attach(   
	    GTK_TABLE(parent2), sb,
	    1, 2, 0, 1,
	    GTK_FILL,
	    GTK_EXPAND | GTK_SHRINK | GTK_FILL,
	    0, 0
	);
	gtk_widget_show(sb);


	/* Separator */
	w = gtk_hseparator_new();
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);                                     


	/* Hbox for buttons */
	w = gtk_hbox_new(TRUE, 0);
	gtk_container_border_width(GTK_CONTAINER(w), border_major);
	gtk_box_pack_start(GTK_BOX(parent), w, FALSE, FALSE, 0);
	gtk_widget_show(w);
	parent2 = w;

	/* OK button */
	d->ok_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_ok_20x20_xpm, "OK", NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH_DEF, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(ConMsgDlgOKCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_Escape, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	gtk_accel_group_add(
	    accelgrp, GDK_o, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_o);
	gtk_widget_show(w);

	/* No More Messages button */
	d->no_more_messages_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_cancel_20x20_xpm, "No More Messages", NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    -1, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(ConMsgDlgNoMoreMessagesCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_n, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_n);
	gtk_widget_show(w);

	/* Clear button */
	d->clear_btn = w = GUIButtonPixmapLabelH(
	    (guint8 **)icon_clear_20x20_xpm, "Clear", NULL
	);
	GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT);
	gtk_widget_set_usize(
	    w,
	    GUI_BUTTON_HLABEL_WIDTH_DEF, GUI_BUTTON_HLABEL_HEIGHT_DEF
	);
	gtk_box_pack_start(GTK_BOX(parent2), w, FALSE, FALSE, 0);
	gtk_signal_connect(  
	    GTK_OBJECT(w), "clicked",
	    GTK_SIGNAL_FUNC(ConMsgDlgClearCB), d
	);
	gtk_accel_group_add(
	    accelgrp, GDK_l, 0, GTK_ACCEL_VISIBLE,
	    GTK_OBJECT(w), "clicked"
	);
	GUIButtonLabelUnderline(w, GDK_l);
	gtk_widget_show(w);  



	/* Map Message Dialog */
	gtk_widget_show_raise(d->toplevel);

	/* Have the OK button grab focus */
	gtk_widget_grab_focus(d->ok_btn);
	gtk_widget_grab_default(d->ok_btn);  

	return(d);
}

/*
 *	Appends the message to the Message Dialog.
 */
static void ConMsgDlgMsgAppend(ConMsgDlg *d, const gchar *s)
{
	GtkAdjustment *adj;
	GtkEditable *editable;
	GtkText *text;
	GtkWidget *w = (d != NULL) ? d->text : NULL;
	if((w == NULL) || (s == NULL))
	    return;

	editable = GTK_EDITABLE(w);
	text = GTK_TEXT(w);

	gtk_text_freeze(text);
	gtk_text_insert(
	    text, d->font, NULL, NULL, s, -1
	);
	gtk_text_thaw(text);

	adj = text->vadj;
	if(adj != NULL)
	    gtk_adjustment_set_value(
		adj,
		MAX(adj->upper - adj->page_size, adj->lower)
	    );
}

/*
 *	Deletes the Message Dialog.
 */
static void ConMsgDlgDelete(ConMsgDlg *d)
{
	if(d == NULL)
	    return;

	GTK_WIDGET_DESTROY(d->text);
	GTK_WIDGET_DESTROY(d->ok_btn);
	GTK_WIDGET_DESTROY(d->no_more_messages_btn);
	GTK_WIDGET_DESTROY(d->clear_btn);
	GTK_WIDGET_DESTROY(d->toplevel);
	GTK_ACCEL_GROUP_UNREF(d->accelgrp);
	GDK_FONT_UNREF(d->font);
	g_free(d);
}


/*
 *	Checks the buffer descriptor for data and processes it.
 *
 *	If the pointer to the Message Dialog is not NULL then the
 *	message will be displayed on that Message Dialog (creating the
 *	Message Dialog as needed).
 *
 *	Returns TRUE if data was processed.
 */
static gboolean ConMsgGetMsg(
	gint fd, ConMsgDlg **d_ptr,
	const gchar *title, guint8 **icon_data
)
{
	gint buf_len, bytes_read, total_bytes_read = 0;
	struct stat stat_buf;
	gchar *buf;
 
	/* Check if the specified descriptor is valid and get its
	 * statistics
	 */
	if((fd > -1) ? fstat(fd, &stat_buf) : TRUE)
	    return(FALSE);

	/* Get block size for optimul reading and allocate the read
	 * buffer
	 */
	buf_len = (gint)stat_buf.st_blksize;
	if(buf_len <= 0)
	    buf_len = 1024;
	buf = (gchar *)g_malloc(buf_len * sizeof(gchar));
	if(buf == NULL)
	    return(FALSE);

	/* Begin reading the message buffer */
	while(TRUE)
	{
	    /* Read data from the message buffer */
	    bytes_read = (gint)read((int)fd, buf, buf_len);
	    if(bytes_read <= 0)
		break;

	    /* Read data */
	    total_bytes_read += bytes_read;

	    /* Null terminate message buffer */
	    if(bytes_read < buf_len)
		buf[bytes_read] = '\0';
	    else
		buf[buf_len - 1] = '\0';

	    /* Create new Message Dialog as needed */
	    if(d_ptr != NULL)
	    {
		ConMsgDlg *d = *d_ptr;
		if(d == NULL)
		    *d_ptr = d = ConMsgDlgNew(
			title, icon_data,
			terminal_columns, terminal_lines
		    );
		ConMsgDlgMsgAppend(d, buf);
	    }
	}

	/* Delete read buffer */
	g_free(buf);

	/* Map and raise the Message Dialog if there was data read */
	if((total_bytes_read > 0) && (d_ptr != NULL))
	{
	    ConMsgDlg *d = *d_ptr;
	    if(d != NULL)
		gtk_widget_show_raise(d->toplevel);
	}

	/* Return TRUE if there was data read */
	return((total_bytes_read > 0) ? TRUE : FALSE);
}

/*
 *	Console message monitor timeout callback.
 */
static gint ConMsgCheckTimeoutCB(gpointer data)
{
	/* Check for data on stdout and stderr, if there is data then
	 * read it and display it on the Message Dialogs
	 */
	ConMsgGetMsg(
	    out_rfd,
	    out_show ? &out_dlg : NULL,
	    out_dlg_title,
	    (guint8 **)icon_info_32x32_xpm
	);
	ConMsgGetMsg(
	    err_rfd,
	    err_show ? &err_dlg : NULL,
	    err_dlg_title,
	    (guint8 **)icon_warning_32x32_xpm
	);

	return(TRUE);
}

/*
 *	Recreates the message buffers.
 */
static gint ConMsgBuffersReset(void)
{
	/* Close existing message buffers */
	CLOSE(out_rfd);
	out_rfd = -1;
	CLOSE(out_wfd);
	out_wfd = -1;
	CLOSE(err_rfd);
	err_rfd = -1;
	CLOSE(err_wfd);
	err_wfd = -1;  

	/* Create new message buffers */
	if(out_show)
	{
	    gint fdpair[2];
	    if(!pipe(fdpair))
	    {
		out_rfd = fdpair[0];
		out_wfd = fdpair[1];
		dup2(out_wfd, fileno(stdout));
		fcntl(out_rfd, F_SETFL, O_NONBLOCK);
	    }
	}
	if(err_show)
	{
	    gint fdpair[2];
	    if(!pipe(fdpair))
	    {
		err_rfd = fdpair[0];
		err_wfd = fdpair[1];
		dup2(err_wfd, fileno(stderr));
		fcntl(err_rfd, F_SETFL, O_NONBLOCK);
	    }
	}

	return(0);
}


/*
 *	Initializes the Console Message Display System.
 */
gint ConMsgInit(
	const gchar *name,	/* Program name */
	gint columns,		/* Can be 0 to indicate use env var $COLUMNS */ 
	gint lines,		/* Can be 0 to indicate use env var $LINES */
	gboolean show_stdout,
	gboolean show_stderr
)
{
	/* Set program name */
	g_free(prog_name);
	prog_name = STRDUP(name);

	/* Set dialog titles */
	g_free(out_dlg_title);
	if(STRISEMPTY(prog_name))
	    out_dlg_title = STRDUP("Message");
	else
	    out_dlg_title = g_strdup_printf("%s - Message", prog_name);
	g_free(err_dlg_title);
	if(STRISEMPTY(prog_name))
	    err_dlg_title = STRDUP("Error Message");
	else
	    err_dlg_title = g_strdup_printf("%s - Error Message", prog_name);

	/* Set terminal geometry */
	if(columns > 0)
	{
	    terminal_columns = columns;
	}
	else
	{
	    const gchar *s = g_getenv("COLUMNS");
	    if(s != NULL)
		terminal_columns = ATOI(s);
	}
	if(lines > 0)
	{
	    terminal_lines = lines;
	}
	else
	{
	    const gchar *s = g_getenv("LINES");
	    if(s != NULL)
		terminal_lines = ATOI(s);
	}

	/* Set show stdout & stderr options */
	out_show = show_stdout;
	err_show = show_stderr;

	/* Reset buffer descriptors */
	out_rfd = -1;
	out_wfd = -1;
	err_rfd = -1;
	err_wfd = -1;

	/* Reset Message Dialogs */
	out_dlg = NULL;
	err_dlg = NULL;

	/* Create message buffers for the first time */
	ConMsgBuffersReset();

	/* Set console message check timeout callback */
	GTK_TIMEOUT_REMOVE(msg_check_toid);
	msg_check_toid = gtk_timeout_add(
	    1000l,
	    ConMsgCheckTimeoutCB, NULL
	);
#if 0
g_printerr(PROG_USAGE_MESG);
g_printerr(PROG_COPYRIGHT);
#endif

	return(0);
}

/*
 *	Resets the Console Message Display System.
 */
gint ConMsgReset(
	const gchar *name,	/* Program name */
	gint columns,		/* Can be 0 to indicate use env var $COLUMNS */
	gint lines,		/* Can be 0 to indicate use env var $LINES */
	gboolean show_stdout,
	gboolean show_stderr
)
{
	/* Set program name */
	g_free(prog_name);
	prog_name = STRDUP(name);

	/* Set dialog titles */
	g_free(out_dlg_title);
	if(STRISEMPTY(prog_name))
	    out_dlg_title = STRDUP("Message");
	else
	    out_dlg_title = g_strdup_printf("%s - Message", prog_name);
	g_free(err_dlg_title);
	if(STRISEMPTY(prog_name))
	    err_dlg_title = STRDUP("Error Message");
	else
	    err_dlg_title = g_strdup_printf("%s - Error Message", prog_name);

	/* Set terminal geometry */
	if(columns > 0)
	{
	    terminal_columns = columns;
	}
	else
	{   
	    const gchar *s = g_getenv("COLUMNS");
	    if(s != NULL)
		terminal_columns = ATOI(s);
	}
	if(lines > 0)
	{
	    terminal_lines = lines;
	}
	else
	{   
	    const gchar *s = g_getenv("LINES");
	    if(s != NULL)
		terminal_lines = ATOI(s);
	}

	/* Set show stdout & stderr options */
	out_show = show_stdout;
	err_show = show_stderr;

	/* Delete Message Dialogs so that they are created next time
	 * with the reset values
	 */
	ConMsgDlgDelete(out_dlg);
	out_dlg = NULL;
	ConMsgDlgDelete(err_dlg);
	err_dlg = NULL;

	/* Recreate message buffers */
	ConMsgBuffersReset();

	/* Reset console message check timeout callback */
	GTK_TIMEOUT_REMOVE(msg_check_toid);
	msg_check_toid = gtk_timeout_add(
	    1000l,
	    ConMsgCheckTimeoutCB, NULL
	);

	return(0);
}

/*
 *	Shuts down the Console Message Display System.
 */
void ConMsgShutdown(void)
{
	/* Wait for all Message Dialogs to be unmapped */
	while(gtk_events_pending() > 0)
	    gtk_main_iteration();
	while((out_dlg != NULL) || (err_dlg != NULL))
	{
	    if(gtk_events_pending() > 0)
		gtk_main_iteration();
	}

	/* Remove console message check timeout callback */
	GTK_TIMEOUT_REMOVE(msg_check_toid);
	msg_check_toid = 0;

	/* Delete Message Dialogs */
	ConMsgDlgDelete(out_dlg);
	out_dlg = NULL;
	ConMsgDlgDelete(err_dlg);
	err_dlg = NULL;

	/* Close existing message buffers */
	CLOSE(out_rfd);
	out_rfd = -1;
	CLOSE(out_wfd);  
	out_wfd = -1;
	CLOSE(err_rfd);
	err_rfd = -1;
	CLOSE(err_wfd);
	err_wfd = -1;

	g_free(prog_name);
	prog_name = NULL;
	g_free(out_dlg_title);
	out_dlg_title = NULL;
	g_free(err_dlg_title);
	err_dlg_title = NULL;
}


/*
 *	Maps the StdOut Message Dialog.
 */
void ConMsgStdOutDlgMap(void)
{
	ConMsgDlg *d = out_dlg;
	if(d == NULL)
	    out_dlg = d = ConMsgDlgNew(
		out_dlg_title, (guint8 **)icon_info_32x32_xpm,
		terminal_columns, terminal_lines
	    );
	if(d == NULL)
	    return;

	gtk_widget_show_raise(d->toplevel);

	/* Have the OK button grab focus */
	gtk_widget_grab_focus(d->ok_btn);
	gtk_widget_grab_default(d->ok_btn);
}

/*
 *	Maps the StdErr Message Dialog.
 */
void ConMsgStdErrDlgMap(void)
{
	ConMsgDlg *d = err_dlg;
	if(d == NULL)          
	    err_dlg = d = ConMsgDlgNew(
		err_dlg_title, (guint8 **)icon_warning_32x32_xpm,
		terminal_columns, terminal_lines
	    );
	if(d == NULL)
	    return;

	gtk_widget_show_raise(d->toplevel);

	/* Have the OK button grab focus */
	gtk_widget_grab_focus(d->ok_btn);
	gtk_widget_grab_default(d->ok_btn);
}
