/* Set up the Ivy Application,
   Copyright (C) 1996, Felix H. Gatzemeier.

This file is part of Ivy.app, the minimal NeXTstep(TM) Editor..

Ivy.app 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, or (at your option)
any later version.

Ivy.app 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 Ivy.app; see the file COPYING.  If not, write to
fxg@imib.rwth-aachen.de
or the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */


#import "MiniText.h"
#import <appkit/appkit.h>
/* Default defaults. Just some coordinates that should work ok on all screens */
#define XOFFSNAME				"NXWindow X"
#define XOFFSVALUE			"300.0"
#define XOFFSVALUEFLOAT	300.0
#define YOFFSNAME				"NXWindow Y"
#define YOFFSVALUE			"250.0"
#define YOFFSVALUEFLOAT	250.0
#define WINEXT					400.0						/* Maximal Text height */

void main(void);

void main(void)
{
	NXApp = [Application new];		/* connect to the window server */
	if (NXArgc == 2)
	{
		MiniText	*theMiniText;
		NXRect		frame1 = {origin:{x:0.0, y:0.0}, size:{width:WINEXT, width:WINEXT}};

		/*
		 * Do the Defaults
		 * ================= 
		 */
		int	i;

		/* The list of defaults in use */
		static NXDefaultsVector IvyDefaults = {
																					 {FONTSIZENAME, FONTSIZEVALUE},
																					 {MAXWIDTHNAME, MAXWIDTHVALUE},
																					 {XOFFSNAME, XOFFSVALUE},
																					 {YOFFSNAME, YOFFSVALUE},
																					 {NULL}
		};

		/* Enter the defaults into the cache. */
		NXRegisterDefaults(DEFAULTOWNER, IvyDefaults);
		/* Force a write to the database for each default not already there. */
		for (i = 0; IvyDefaults[i].name != NULL; i++)
			if (NXReadDefault(DEFAULTOWNER, IvyDefaults[i].name) == NULL)
				NXWriteDefault(DEFAULTOWNER, IvyDefaults[i].name, IvyDefaults[i].value);

		/*
		 * Set up the Text
		 * ===================
		 * Reads the file, resizes itself. May very well fail. 
		 */
		if (theMiniText = [[MiniText alloc] initFrame:&frame1])
		{
			Menu				*theMenu;
			Menu				*subMenu;
			Window			*theWindow;
			ScrollView	*theScrollView;
			NXRect			frame2;
			const char	*defStr;

			/*
			 * Set up the ScrollView
			 * =========================
			 * Wrap it around the Text. 
			 */
			[theMiniText getFrame:&frame1];
			/* The height may be extravagant for a Window, so limit THAT. */
			if (NX_HEIGHT(&frame1) > WINEXT)
				NX_HEIGHT(&frame1) = WINEXT;
			[ScrollView getFrameSize:&(frame2.size)
			 forContentSize :&(frame1.size)
			 horizScroller :NO
			 vertScroller:YES
			 borderType:NX_NOBORDER];
			theScrollView = [[ScrollView alloc] initFrame:&frame2];
			[[theScrollView setDocView:theMiniText] free];

			/*
			 * The ScrollView will resize by default, only its contentView, a
			 * ClipView won't. It's not accessible from the ScrollView, so we sneak
			 * up on it from behind... 
			 */
			[[[theMiniText superview]
				setAutoresizeSubviews:YES]
			 setAutosizing:NX_HEIGHTSIZABLE | NX_WIDTHSIZABLE];

			/*
			 * For things to look ok, the scroller has to be added AFTER the
			 * docView! As a result, the contentView's size changes. The docView is
			 * resized also iff the contentView has been set up to
			 * AutoresizeSubviews! (Which means that the MiniText is uselessly
			 * rewrapped once or twice) 
			 */
			[theScrollView setVertScrollerRequired:YES];

			/*
			 * Set up the Window
			 * ===================== 
			 */
			[theScrollView getFrame:&frame2];
			if ((defStr = NXGetDefaultValue(DEFAULTOWNER, XOFFSNAME)) != NULL)
				frame2.origin.x = atof(defStr);
			else
				frame2.origin.x = XOFFSVALUEFLOAT;
			if ((defStr = NXGetDefaultValue(DEFAULTOWNER, YOFFSNAME)) != NULL)
				frame2.origin.y = atof(defStr);
			else
				frame2.origin.y = YOFFSVALUEFLOAT;
			[Window getFrameRect:&frame1
			 forContentRect:&frame2
			 style:NX_RESIZEBARSTYLE];
			theWindow = [[Window alloc] initContent:&frame1
			 style:NX_RESIZEBARSTYLE
			 backing:NX_BUFFERED
			 buttonMask:NX_MINIATURIZEBUTTONMASK | NX_CLOSEBUTTONMASK
			 defer:YES];
			/* This may resize the ScrollView */
			[[theWindow setContentView:theScrollView] free];
			[theWindow setTitleAsFilename:NXArgv[NXArgc - 1]];
			
			/* see to it that the window is neatly propped up. The text guarantees a maximum width and height, but the offsets from the defaults might have been too large. The height is tested by makeKeyAndOrderFront, too. But this should feel a little more integrated. */
			[NXApp getScreenSize: &frame1.size];
			[theWindow getFrame: &frame2];
			if(frame1.size.width < NX_MAXX(&frame2))
				frame1.origin.x = (frame1.size.width - frame2.size.width) / 2;
			else
				frame1.origin.x = frame2 .origin.x;
			if(frame1.size.height < NX_MAXY(&frame2))
				frame1.origin.y = (frame1.size.height - frame2.size.height) / 2;
			else
				frame1.origin.y = frame2 .origin.y;
			[theWindow moveTo:frame1.origin.x :frame1.origin.y];

			/*
			 * Set up the Menu
			 * =================== 
			 */
			theMenu = [[Menu alloc] initTitle:"Ivy"];

			/* The Edit Menu */
			subMenu = [[Menu alloc] initTitle:"Edit"];
			[subMenu addItem:"Cut" action:@selector(cut:) keyEquivalent :'x'];
			[subMenu addItem:"Copy" action:@selector(copy:) keyEquivalent :'c'];
			[subMenu addItem:"Paste" action:@selector(paste:) keyEquivalent :'v'];
			[subMenu addItem:"Select All" action:@selector(selectAll:) keyEquivalent :'a'];
			[subMenu sizeToFit];
			[[subMenu itemList] setTarget:theMiniText];

			[theMenu setSubmenu:subMenu forItem:
			 [theMenu addItem:"Edit" action:(SEL)nil keyEquivalent:0]];
			
			/* The Print entry */
			[theMenu addItem:"Print..." 
					action:@selector(printPSCode:) 
					keyEquivalent:'p'];

			[[theMenu itemList] setTarget: theMiniText at:1:0];

			/* The Services Menu */
			subMenu = [[Menu alloc] initTitle:"Services"];

			[theMenu setSubmenu:subMenu forItem:
			 [theMenu addItem:"Services" action:(SEL)nil keyEquivalent:0]];

			/* The Hide entry */
			[theMenu addItem:"Hide" action:@selector(hide:) keyEquivalent :'h'];

			/* The Quit entry */
			[theMenu addItem:"Quit" action:@selector(terminate:) keyEquivalent :'q'];


			[NXApp setMainMenu:theMenu];
			[NXApp setServicesMenu: subMenu];

			/*
			 * Delegating
			 * ============== 
			 */

			/*
			 * Being the Window and the Application delegate enables the Text to
			 * react to window closing. 
			 */
			[theWindow setDelegate:theMiniText];
			[NXApp setDelegate:theMiniText];

			/*
			 * Finally, launch
			 * =================== 
			 */
			[theWindow makeKeyAndOrderFront:NXApp];

			/*
			 * This isn't what I'd call good style, but such a little editor should
			 * be visible immediately. 
			 */
			[NXApp activateSelf:YES];
			[NXApp run];
		}
	}
	else
	{
		NXRunAlertPanel("Sorry",
				"Ivy takes exactly one non-defaults argument: a file to be opened.",
										"Terminate", NULL, NULL);
	}
	[NXApp free];
	exit(0);
}
