#define PATCHLEVEL 0
/*
**    ScEd: A Constraint Based Scene Editor.
**    Copyright (C) 1994-1995  Stephen Chenney (stephen@cs.su.oz.au)
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
**	sced: A Constraint Based Object Scene Editor
**
**	sced.c : The master file.  Actually, it doesn't do too much.  Just sets
**				up a few widgets and lets it run.
**
**	Created: 20/03/94
*/

#include <sced.h>
#include <layers.h>
#include <select_point.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/param.h>
#include <X11/cursorfont.h>
#include <X11/Shell.h>
#include <X11/Xaw/SimpleMenu.h>

#if ELK_SUPPORT
#include <elk.h>
#endif /* ELK_SUPPORT */

#if ( ! defined(MAXPATHLEN) )
#define MAXPATHLEN 1024
#endif


/*
**	Declaration of global variables.
*/
XtAppContext	app_context;	/* The application context for the program.	*/
WindowInfo		main_window;
WindowInfo		csg_window;
ScedResources	sced_resources;	/* Application resources. */

double	version = VERSION_FLOAT;

Renderer	target_renderer = NoTarget;	/* The target renderer. */

Boolean	changed_scene = FALSE;	/* Whether or not the scene has been modified.*/

/* Various file names. */
char	start_directory_name[MAXPATHLEN];
char	*io_file_name = NULL;

/* GCs for drawing the axes. */
GC				axis_gcs[3];

/* Preferences. */
ScedPreferences	sced_preferences;

/* Temporary filenames (for removal). */
char	**temp_filenames = NULL;
int		num_temp_files = 0;

/* Translations for top level windows, those that stay open. */
char	*top_level_translations = "<Message>:Handle_Client_Message()\n";

extern void Create_Main_Display();

extern void	Main_Button_Down_Action(Widget, XEvent*, String*, Cardinal*);
extern void	Main_Motion_Action(Widget, XEvent*, String*, Cardinal*);
extern void	Main_Button_Up_Action(Widget, XEvent*, String*, Cardinal*);
extern void	Main_Double_Click_Action(Widget, XEvent*, String*, Cardinal*);

extern Widget	edit_shell;

static int	Sced_X_Error_Handler(Display*, XErrorEvent*);
static void Set_Defaults();
static void Initialize_Sced(int, char**, char**);
static void	Set_Signal_Handlers();
static void	Handle_Client_Messages(Widget, XEvent*, String*, Cardinal*);

static char	*defaults_filename = NULL;


/*
**	Declaration of local variables.
*/
/* Fallback resources. Geometries and colors. */
/* Colors are needed because the default resources don't work as expected. */
String	fallbacks[] = {
	"Sced.geometry: 800x600",
	"Sced.csgShell.geometry: 800x600",
	"Sced.editShell.geometry: 800x180",
	"Sced.newObject.geometry: 540x300",
	"Sced.wireSelectShell.geometry: 400x300",
	"Sced.csgSelectShell.geometry: 400x300",
	"Sced.csgReferenceShell.geometry: 400x400",
	"Sced.specAttributesShell.geometry: 400x300",
	"Sced.aliasShell.geometry: 300x200",
	NULL
	};

/* Actions. */
XtActionsRec	actions[] = {
#if ELK_SUPPORT
	{ "elk_eval_string", Elk_Eval_String },
#endif /* ELK_SUPPORT */
	{ "Handle_Client_Message", Handle_Client_Messages },
	{ "Main_Button_Down", Main_Button_Down_Action },
	{ "Main_Motion", Main_Motion_Action },
	{ "Main_Button_Up", Main_Button_Up_Action },
	{ "Highlight_Object", Select_Highlight_Object },
	{ "Select_Point", Select_Point_Action },
	{ "Highlight_Closest", Select_Highlight_Action },
	{ "Rename_Object", Rename_Action_Func },
	{ "Apply_Button", Apply_Button_Action },
	{ "Zoom_Action", Zoom_Action_Func },
	{ "Defaults_Action", Defaults_Pathname_Action },
	{ "Copy_Action", Copy_Action_Func },
	{ "Change_Magnify", Magnify_Step_Action_Func },
	{ "Ambient_Action", Ambient_Action_Func },
	{ "Light_Action", Light_Action_Func },
	{ "View_Name_Action", View_Name_Action_Func },
	{ "csg_tree_notify", CSG_Tree_Notify_Func },
	{ "menu_notify", CSG_Menu_Button_Up_Func },
	{ "csg_motion", CSG_Tree_Motion_Func },
	{ "csg_complete", CSG_Complete_Action_Func },
#if RENDERMAN_SUPPORT
	{ "Renderman_File_Action", Renderman_Action_Func },
#endif
	{ "New_Layer_Action", New_Layer_Action_Function }
	};

/* Resources. */
#define Offset(field)	XtOffsetOf(ScedResources, field)
XtResource	resources[] = {
	{"xAxisColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(x_axis_color),
	 XtRString, "red"},
	{"yAxisColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(y_axis_color),
	 XtRString, "green"},
	{"zAxisColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(z_axis_color),
	 XtRString, "blue"},
	{"axisWidth", XtCWidth, XtRInt, sizeof(int), Offset(axis_width),
	 XtRImmediate, (XtPointer)2},
	{"xAxisLength", XtCLength, XtRInt, sizeof(int), Offset(x_axis_length),
	 XtRImmediate, (XtPointer)2},
	{"yAxisLength", XtCLength, XtRInt, sizeof(int), Offset(y_axis_length),
	 XtRImmediate, (XtPointer)2},
	{"zAxisLength", XtCLength, XtRInt, sizeof(int), Offset(z_axis_length),
	 XtRImmediate, (XtPointer)2},
	{"axisDenom", XtCLength, XtRInt, sizeof(int), Offset(axis_denom),
	 XtRImmediate, (XtPointer)1},
	{"axisFont", XtCFont, XtRFontStruct, sizeof(XFontStruct*),
	 Offset(axis_font), XtRString, XtDefaultFont },
	{"majorAxisColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(obj_x_axis_color), XtRString, "red"},
	{"minorAxisColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(obj_y_axis_color), XtRString, "green"},
	{"otherAxisColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(obj_z_axis_color), XtRString, "blue"},
	{"editAxisWidth", XtCWidth, XtRInt, sizeof(int), Offset(obj_axis_width),
	 XtRImmediate, (XtPointer)2},
	{"majorAxisLength", XtCLength, XtRInt, sizeof(int),
	 Offset(obj_x_axis_length), XtRImmediate, (XtPointer)4},
	{"minorAxisLength", XtCLength, XtRInt, sizeof(int),
	 Offset(obj_y_axis_length), XtRImmediate, (XtPointer)3},
	{"otherAxisLength", XtCLength, XtRInt, sizeof(int),
	 Offset(obj_z_axis_length), XtRImmediate, (XtPointer)2},
	{"editAxisDenom", XtCLength, XtRInt, sizeof(int), Offset(obj_axis_denom),
	 XtRImmediate, (XtPointer)2},
	{"editPointRadius", XtCWidth, XtRInt, sizeof(int), Offset(edit_pt_rad),
	 XtRImmediate, (XtPointer)10},
	{"controlPointRadius", XtCWidth, XtRInt, sizeof(int),
	 Offset(control_pt_rad), XtRImmediate, (XtPointer)4},
	{"scalingColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(scaling_color),
	 XtRString, "red"},
	{"originColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(origin_color),
	 XtRString, "green"},
	{"torusRadColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(torus_color),
	 XtRString, "purple"},
	{"controlColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(control_color),
	 XtRString, "green"},
	{"controlTextColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(ctext_color),
	 XtRString, "DarkGreen"},
	{"controlFont", XtCFont, XtRFontStruct, sizeof(XFontStruct*),
	 Offset(control_font), XtRString, XtDefaultFont },
	{"objectColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(object_color),
	 XtRString, "blue"},
	{"selectColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(selected_color),
	 XtRString, "red"},
	{"selectWidth", XtCWidth, XtRInt, sizeof(int), Offset(selected_width),
	 XtRImmediate, (XtPointer)0},
	{"lightColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(light_color),
	 XtRString, "yellow"},
	{"lightPointRadius", XtCWidth, XtRInt, sizeof(int), Offset(light_pt_rad),
	 XtRImmediate, (XtPointer)12},
	{"cameraColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(camera_color),
	 XtRString, "midnightblue"},
	{"constraintColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(constraint_color), XtRString, "grey"},
	{"planeConLength", XtCLength, XtRInt, sizeof(int), Offset(plane_con_length),
	 XtRImmediate, (XtPointer)6},
	{"lineConLength", XtCLength, XtRInt, sizeof(int), Offset(line_con_length),
	 XtRImmediate, (XtPointer)6},
	{"pointConWidth", XtCWidth, XtRInt, sizeof(int), Offset(point_con_rad),
	 XtRImmediate, (XtPointer)15},
	{"inconConLength", XtCLength, XtRInt, sizeof(int), Offset(incon_con_length),
	 XtRImmediate, (XtPointer)15},
	{"originConWidth", XtCLength, XtRInt, sizeof(int), Offset(origin_con_width),
	 XtRImmediate, (XtPointer)7},
	{"scaleConWidth", XtCLength, XtRInt, sizeof(int), Offset(scale_con_width),
	 XtRImmediate, (XtPointer)5},
	{"torusRadConWidth", XtCLength, XtRInt, sizeof(int),Offset(torus_con_width),
	 XtRImmediate, (XtPointer)9},
	{"controlConWidth", XtCLength, XtRInt, sizeof(int),
	 Offset(control_con_width), XtRImmediate, (XtPointer)11},
	{"rotateConWidth", XtCLength, XtRInt, sizeof(int), Offset(rotate_con_width),
	 XtRImmediate, (XtPointer)3},
	{"referencedColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(referenced_color), XtRString, "red"},
	{"activeColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(active_color),
	 XtRString, "red"},
	{"selectPointColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(selected_pt_color), XtRString, "blue"},
	{"selectPointWidth", XtCWidth, XtRInt, sizeof(int), Offset(select_pt_width),
	 XtRImmediate, (XtPointer)8},
	{"selectPointLineWidth", XtCWidth, XtRInt, sizeof(int),
	 Offset(select_pt_line_width), XtRImmediate, (XtPointer)2},
	{"absoluteColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(absolute_color),
	 XtRString, "green"},
	{"offsetColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(offset_color),
	 XtRString, "blue"},
	{"referenceColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(reference_color), XtRString, "red"},
	{"vertexColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(vertex_color), XtRString, "red"},
	{"arcballColor", XtCColor, XtRPixel, sizeof(Pixel), Offset(arcball_color),
	 XtRString, "grey"},
	{"constructColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(construct_color), XtRString, "green4"},
	{"aliasColor", XtCColor, XtRPixel, sizeof(Pixel),
	 Offset(aliased_color), XtRString, "maroon"},
	{"editOrientation", XtCOrientation, XtROrientation, sizeof(XtOrientation),
	 Offset(edit_orientation), XtRString, "horizontal" },
	{"editRows", XtCWidth, XtRInt, sizeof(int), Offset(edit_rows),
	 XtRImmediate, (XtPointer)5 },
	{"editColumns", XtCWidth, XtRInt, sizeof(int), Offset(edit_columns),
	 XtRImmediate, (XtPointer)5 }
	};
#undef Offset


/* Icon bitmap. */
#define icon_width 43
#define icon_height 44
static char icon_bits[] = {
 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 0xff,0xff,0xff,0xff,0xdb,0xfe,0xff,0xff,0xff,0xff,0xfe,0xb7,0xff,0xff,0xff,
 0xc7,0x6f,0xef,0xff,0xff,0xff,0x1f,0xfe,0xd5,0xdf,0xff,0xff,0x67,0xb1,0xda,
 0x9f,0xff,0xff,0x8f,0xca,0xd6,0x9f,0xff,0xff,0x57,0x52,0xb5,0x1f,0xfe,0xff,
 0x57,0xa5,0xad,0x1f,0xfc,0xff,0x4f,0x4a,0xd5,0x3f,0xf4,0xff,0x97,0xd4,0xda,
 0x1f,0xf8,0xff,0x57,0xa9,0xb6,0x1f,0xe0,0xff,0xaf,0x52,0xd5,0x3f,0xc0,0xff,
 0x4f,0x4a,0xeb,0x5f,0x88,0xfe,0x9f,0xd4,0xda,0x1f,0x40,0xff,0xaf,0x92,0xd6,
 0x3f,0x00,0xff,0x5f,0x65,0xf5,0x5f,0x80,0xff,0xff,0x54,0xfb,0x1f,0xe1,0xff,
 0xff,0xcb,0xfe,0x3f,0xf8,0xff,0xff,0xbf,0xff,0x5f,0xff,0xff,0xff,0xff,0xff,
 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
 0x7f,0xfe,0xff,0xff,0xff,0xff,0xbf,0xf0,0xff,0x17,0xfe,0xff,0xbf,0x00,0xff,
 0x4b,0xf9,0xff,0x3f,0x02,0xf8,0x01,0xfa,0xff,0xbf,0x00,0xf5,0x8a,0xf0,0xff,
 0x5f,0x00,0xf8,0x02,0xe4,0xff,0x3f,0x44,0x7a,0x01,0xd0,0xff,0x9f,0x00,0xf4,
 0x00,0xf4,0xff,0x5f,0x00,0xfd,0x12,0xe0,0xff,0x2f,0x00,0x7a,0x01,0xd4,0xff,
 0x1f,0xa0,0xfc,0x02,0xf1,0xff,0x4f,0x02,0xfd,0x15,0xf4,0xff,0x2f,0x00,0xfe,
 0x45,0xf9,0xff,0x17,0xa0,0xfe,0x2b,0xfe,0xff,0x0f,0x00,0xfd,0xaf,0xfd,0xff,
 0x97,0x40,0xff,0xff,0xff,0xff,0x0f,0x08,0xfd,0xff,0xff,0xff,0x7f,0x40,0xff,
 0xff,0xff,0xff,0xff,0xa3,0xfe,0xff,0xff,0xff};
Pixmap	icon_bitmap;


void
main(int argc, char *argv[], char *envp[])
{
	FILE 	*infile = NULL;
	Cursor	time_cursor;

	Set_WindowInfo(&main_window);
	Set_WindowInfo(&csg_window);

	/* Create the application shell. */
	/* This gets rid of X command line arguments. */
	main_window.shell = XtVaAppInitialize(&app_context, "Sced",
				(XrmOptionDescList)NULL, 0, &argc, argv, fallbacks,
				XtNtitle, "Scene Window", NULL);

	/* Set up the icon. */
	icon_bitmap = XCreateBitmapFromData(XtDisplay(main_window.shell),
								RootWindowOfScreen(XtScreen(main_window.shell)),
								icon_bits, icon_width, icon_height);
	XtVaSetValues(main_window.shell, XtNiconPixmap, icon_bitmap, NULL);

	XtAppAddConverter(app_context, XtRString, XtROrientation,
					  XmuCvtStringToOrientation, NULL, 0);
	XtGetApplicationResources(main_window.shell, (XtPointer)&sced_resources,
							  resources, XtNumber(resources), (Arg*)NULL, 0);

	/* Global initialization routine. */
	Initialize_Sced(argc, argv, envp);

	/* Register actions. */
	XtAppAddActions(app_context, actions, XtNumber(actions));
	XawSimpleMenuAddGlobalActions(app_context);

	/* Add error handler. */
	XSetErrorHandler(Sced_X_Error_Handler);
	XtAugmentTranslations(main_window.shell,
						  XtParseTranslationTable(top_level_translations));

	/* Create the contents. */
	Create_Main_Display();

	/* Realize it all. */
	XtRealizeWidget(main_window.shell);

	/* Init drawing. */
	Draw_Initialize();

	/* Set the signal handlers. */
	Set_Signal_Handlers();

	/* Load the defaults file, if specified. */
	Load_Defaults_File(defaults_filename);

	/* Load the scene file, if specified. */
	if ( io_file_name )
	{
		/* Try to open the file in the current directory. */
		if ((infile = Open_Load_File_Name(&io_file_name)) == NULL &&
			sced_preferences.scene_path)
		{
			/* Couldn't open it. Try opening in the scenes directory. */
			char	*new_filename = New(char, strlen(io_file_name) +
									strlen(sced_preferences.scene_path) + 4);

			sprintf(new_filename, "%s/%s",
					sced_preferences.scene_path, io_file_name);
			if ( ( infile = Open_Load_File_Name(&new_filename) ) == NULL )
				fprintf(stderr, "Unable to open file %s\n", io_file_name);
			else
			{
				free(io_file_name);
				io_file_name = new_filename;
			}
		}
		/* Check the first character. We want it to be an absolute pathname,
		** since SelFile screws up the current dir otherwise.
		** This in turn screws previewing.
		*/
		if ( io_file_name[0] != '/' )
		{
			char	current_dir[MAXPATHLEN];
			char	*temp;

#if HAVE_GETWD
			getwd(current_dir);
#else
			getcwd(current_dir, MAXPATHLEN);
#endif
			temp = New(char, strlen(io_file_name) + strlen(current_dir) + 5);
			sprintf(temp, "%s/%s", current_dir, io_file_name);
			free(io_file_name);
			io_file_name = temp;
		}
	}
	if ( infile )
	{
		time_cursor = XCreateFontCursor(XtDisplay(main_window.shell), XC_watch);
    	XDefineCursor(XtDisplay(main_window.shell),
					  XtWindow(main_window.shell), time_cursor);

		Sced_Load_File(infile, FALSE);

    	XDefineCursor(XtDisplay(main_window.shell), XtWindow(main_window.shell),
					  None);
		XFreeCursor(XtDisplay(main_window.shell), time_cursor);
	}

#if ELK_SUPPORT
	/*
	 * Fire up scheme interpretor
	 */
	init_elk(argc, argv);
#endif /* ELK_SUPPORT */
	
	/* Loop for events. */
	XtAppMainLoop(app_context);

}

static int
Sced_X_Error_Handler(Display *display, XErrorEvent *error)
{
	char	msg[128];
	XGetErrorText(display, error->error_code, msg, 128);
	fprintf(stderr, "X Error code %s\n", msg);
	Sced_Abort(FALSE);
	/* Never returns. */
	return 0;
}


/*	void
**	Initialize_Sced(int argc, char *argv[], char *envp[])
**	Parses the command line, then calls initialization functions.
*/
static void
Initialize_Sced(int argc, char *argv[], char *envp[])
{
	int		i;
	char	*temp_s;
	int		w, h;
	Boolean	have_filename = FALSE;

	/* Any options left on the command line are mine.	*/
	/* Options at the moment are:
	** -I WxH
	** -F filename
	** -D defaults_file
	*/
	for ( i = 1 ; i < argc ; i++ )
	{
		if ( argv[i][0] != '-' )
		{
			/* Assume it's a filename. */
			if ( have_filename )
				printf("Unexpected argument: %s\n", argv[i]);
			else
			{
				io_file_name = Strdup(argv[i]);
				have_filename = TRUE;
			}
		}
		else
		{
			switch ( argv[i][1] )
			{
				case 'F':
					if ( argv[i][2] != '\0' )
						io_file_name = Strdup(argv[i] + 2);
					else
					{
						i++;
						io_file_name = Strdup(argv[i]);
					}
					have_filename = TRUE;
					break;

				case 'D':
					if ( argv[i][2] != '\0' )
						defaults_filename = Strdup(argv[i] + 2);
					else
					{
						i++;
						defaults_filename = Strdup(argv[i]);
					}
					break;

				case 'I':
					if ( argv[i][2] == '\0' )
					{
						i++;
						temp_s = argv[i];
					}
					else
						temp_s = argv[i] + 2;
					if ( ( sscanf(temp_s, "%dx%d", &w, &h) == 2 ) ||
						 ( sscanf(temp_s, "%dX%d", &w, &h) == 2 ) )
					{
						camera.scr_width = (Dimension)w;
						camera.scr_height = (Dimension)h;
					}
					else
						printf("Invalid geometry string: %s\n", temp_s);
					break;

				default:
					printf("Unknown argument: %s\n", argv[i]);
			}
		}
	}

	/* Set defaults for everything that needs one, such as the viewports. */
	Set_Defaults();

	/* Initialize the default base objects. */
	Initialize_Base_Objects();

	/* Initialize constrained features. */
	Feature_Create_Bases();

	/* Initialize visibility layer info. */
	Layers_Init();

	/* Store the start directory, because SelFile tends to trash it, but
	** preview needs it. */
#if HAVE_GETWD
	getwd(start_directory_name);
#else
	getcwd(start_directory_name, MAXPATHLEN);
#endif



}


/*	void
**	Set_Defaults()
**	Sets default values for:
**	- preferences
**	- main_viewport
**	- csg_viewport
*/
static void
Set_Defaults()
{
	Renderer	i;

	/* Set the default attributes for all new objects. */
	sced_preferences.default_attributes.defined = TRUE;
	sced_preferences.default_attributes.colour.red = DEFAULT_RED;
	sced_preferences.default_attributes.colour.green = DEFAULT_GREEN;
	sced_preferences.default_attributes.colour.blue = DEFAULT_BLUE;
	sced_preferences.default_attributes.diff_coef = DEFAULT_DIFFUSE;
	sced_preferences.default_attributes.spec_coef = DEFAULT_SPECULAR;
	sced_preferences.default_attributes.spec_power = DEFAULT_SPECULAR * 100;
	sced_preferences.default_attributes.reflect_coef = DEFAULT_REFLECT;
	sced_preferences.default_attributes.refract_index = DEFAULT_REFRACT;
	sced_preferences.default_attributes.transparency = DEFAULT_TRANSPARENCY;
	sced_preferences.default_attributes.use_extension = FALSE;
	for ( i = NoTarget ; i < LastTarget ; i++ )
		sced_preferences.default_attributes.extension[i] = NULL;
	sced_preferences.default_attributes.use_obj_trans = FALSE;
	sced_preferences.default_attributes.open = FALSE;

	sced_preferences.scene_path = NULL;
	sced_preferences.compress_output = FALSE;
	sced_preferences.save_simple_wires = FALSE;
	sced_preferences.autosave_time = 0;
	sced_preferences.povray_v3 = (Boolean)POVRAY_V3;

	/* Build the default viewports. */
	Viewport_Init(&(main_window.viewport));
	Viewport_Init(&(csg_window.viewport));

}


static void
Sced_Signal_Handler(int sig_num)
{
	Sced_Abort(TRUE);
}

static void
Sced_Handle_Save_Yourself()
{
	FILE	*save_file;
	char	current_dir[MAXPATHLEN];
	char	*temp;
	char	*argv[2];


#if HAVE_GETWD
	getwd(current_dir);
#else
	getcwd(current_dir, MAXPATHLEN);
#endif
	temp = New(char, strlen(current_dir) + 12);
	sprintf(temp, "%s/sced.save", current_dir);

	/* Clean up and save state. */
	Remove_Temporaries();
	if ( ( save_file = fopen(temp, "w") ) )
		Save_Func(save_file);

	/* Set new arguments and register them. */
	argv[0] = "sced";
	argv[1] = temp;
	XSetCommand(XtDisplay(main_window.shell), XtWindow(main_window.shell),
				argv, 2);
}

static void
Set_Signal_Handlers()
{
	Atom	atoms[2];

	signal(SIGHUP, Sced_Signal_Handler);
	signal(SIGTERM, Sced_Signal_Handler);

	atoms[0] = XInternAtom(XtDisplay(main_window.shell), "WM_SAVE_YOURSELF",
						   FALSE);
	atoms[1] = XInternAtom(XtDisplay(main_window.shell), "WM_DELETE_WINDOW",
						   FALSE);
	XSetWMProtocols(XtDisplay(main_window.shell), XtWindow(main_window.shell), 
					atoms, 2);
}


static void
Handle_Client_Messages(Widget w, XEvent *event, String *s, Cardinal *n)
{
	char	*message_name =
		XGetAtomName(XtDisplay(main_window.shell), event->xclient.data.l[0]);

	if ( ! message_name )
		return;

	if ( ! strcmp(message_name, "WM_DELETE_WINDOW") )
	{
		if ( w == main_window.shell )
			Quit_Dialog_Func(w, NULL, NULL);
		else if ( w == csg_window.shell )
			CSG_Window_Delete_Message();
		else if ( w == edit_shell )
			Edit_Window_Delete_Message();
	}
	else if ( ! strcmp(message_name, "WM_SAVE_YOURSELF") )
		Sced_Handle_Save_Yourself();
}

