/*
   Controller.m

   Central controller object for Edit...

   Copyright (c) 1995-1996, NeXT Software, Inc.
   All rights reserved.
   Author: Ali Ozer

   You may freely copy, distribute and reuse the code in this example.
   NeXT disclaims any warranty of any kind, expressed or implied,
   as to its fitness for any particular use.

   mySTEP changes are:
   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:  Felipe A. Rodriguez <far@pcmagic.net>
   Date:	November 1998

   This file is part of the mySTEP Library and is provided
   under the terms of the GNU Library General Public License.
*/

#import <AppKit/AppKit.h>
#import "Controller.h"
#import "Document.h"

#include <math.h>

extern NSWindow *__lineRangeWindow;
static NSButton *__lineRangeField;
static NSRect __lastLineRect;
static int __loops = 0;


@interface GSLineRangeWindow : NSWindow
@end
@implementation GSLineRangeWindow

- (void) orderOut:sender
{
	if (__lineRangeField)
		[super orderOut:sender];
	__loops = 0;
}

@end


@implementation Controller

- (void) method:menuCell							// temp for sake of menu
{
  	NSLog (@"method invoked from cell with title '%@'", [menuCell title]);
}

- (void) applicationDidFinishLaunching:(NSNotification *)aNotification
{
Document *document;
NSString *m = [[NSBundle mainBundle] bundlePath];
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
NSArray *arguments = [processInfo arguments];
NSString *initialFile;

	[NSApp setApplicationIconImage:[NSImage imageNamed:@"Edit.tiff"]];

	if ([arguments count] < 2) 
		initialFile = [m stringByAppendingString:@"/Resources/README"];
	else
		initialFile = [arguments objectAtIndex:1];

	document = [[Document alloc] initWithPath:initialFile 
								 encoding:UnknownStringEncoding];

	__lineRangeWindow = [GSLineRangeWindow alloc];
}

- (BOOL) applicationShouldTerminate:(NSApplication *)app 
{
NSArray *windows = [app windows];
unsigned count = [windows count];
BOOL needsSaving = NO;
												// Determine if there are any 
    while (!needsSaving && count--) 			// unsaved documents.
		{
        NSWindow *window = [windows objectAtIndex:count];
        Document *document = [Document documentForWindow:window];

        if (document && [document isDocumentEdited]) 
			needsSaving = YES;
		}

    if (needsSaving) 
		{
		NSString *quit = @"Title of alert panel which comes up when user \
							chooses Quit and there are unsaved documents.";
		NSString *unsaved = @"Message in the alert panel which comes up when \
						user chooses Quit and there are unsaved documents.";
		NSString *review = @"Choice (on a button) given to user which allows \
						him/her to review all unsaved documents if he/she \
						quits the application without saving them all first.";
		NSString *anyway = @"Choice (on a button) given to user which allows \
						him/her to quit the application even though there are \
						unsaved documents.";
		NSString *cancel = @"Button choice allowing user to cancel.";
        int choice = NSRunAlertPanel(NSLocalizedString(@"Quit", quit), 
					NSLocalizedString(@"You have unsaved documents.", unsaved), 
					NSLocalizedString(@"Review Unsaved", review), 
					NSLocalizedString(@"Quit Anyway", anyway), 
					NSLocalizedString(@"Cancel", cancel));

        if (choice == NSAlertOtherReturn)  
            return NO;											// Cancel

		if (choice != NSAlertAlternateReturn) 
			{								// Review unsaved; Quit Anyway 
			count = [windows count];		// falls through

			while (count--) 
				{
				NSWindow *window = [windows objectAtIndex:count];
				Document *document = [Document documentForWindow:window];

				if (document && (![document canCloseDocument])) 
					return NO;
		}	}	}

//	[Preferences saveDefaults];

    return YES;
}

- (BOOL) application:(NSApplication *)sender openFile:(NSString *)filename 
{
			// If the document is in a .rtfd and it's name is TXT.rtf or 
			// index.rtf, open the parent dir... This is because on windows it  
			// doesn't seem trivial to open folders as files via a double click

#ifdef WIN32
NSString *parentDir = [filename stringByDeletingLastPathComponent];
    if ([[[parentDir pathExtension] lowercaseString] isEqualToString:@"rtfd"]) 		
		{
        NSString *lastPathComponent = [[filename lastPathComponent] 
										lowercaseString];
        if ([lastPathComponent isEqualToString:@"txt.rtf"] || 
				[lastPathComponent isEqualToString:@"index.rtf"]) 
			{
	    	filename = parentDir;
        	}
    	}
#endif

    return [Document openDocumentWithPath:filename 
					 encoding:UnknownStringEncoding] ? YES : NO;
}

- (BOOL) application:(NSApplication *)sender openTempFile:(NSString *)filename 
{									
    return [Document openDocumentWithPath:filename 				// ??? Why?
					 encoding:UnknownStringEncoding] ? YES : NO;
}

- (BOOL) applicationOpenUntitledFile:(NSApplication *)sender 
{
    return [Document openUntitled];
}

- (BOOL) application:(NSApplication *)sender printFile:(NSString *)filename 
{
BOOL retval = NO;
BOOL releaseDoc = NO;
Document *document = [Document documentForPath:filename];
    
    if (!document) 
		{
        document =  [[Document alloc] initWithPath:filename 
									  encoding:UnknownStringEncoding];
        releaseDoc = YES;
    	}
    if (document) 
		{
        BOOL useUI = [NSPrintInfo defaultPrinter] ? NO : YES;

        [document printDocumentUsingPrintPanel:useUI];
        retval = YES;

        if (releaseDoc) 				// If we created it, we get rid of it.
            [document release];
		}

    return retval;
}

- (void) createNew:(id)sender 		{ (void)[Document openUntitled]; }
- (void) open:(id)sender 			{ (void)[Document open:sender]; }

- (void) saveAll:(id)sender 
{
NSArray *windows = [[NSApplication sharedApplication] windows];
unsigned count = [windows count];

    while (count--) 
		{
        NSWindow *window = [windows objectAtIndex:count];
        Document *document = [Document documentForWindow:window];

        if (document) 
			{
            if ([document isDocumentEdited]) 
				{
                if (![document saveDocument:NO]) 
					return;
        }   }	}
}

- (void) showInfoPanel:(id)sender 								// Info Panel
{
    if (!infoPanel) 
		{
        if (![NSBundle loadNibNamed:@"Info" owner:self])  
			{
            NSLog(@"Failed to load Info.mib");
            NSBeep();
            return;
        	}
		[infoPanel center];
    	}
    [infoPanel makeKeyAndOrderFront:nil];
}

@end


@interface NSObject (Layout)

- (NSRect) lineRect;

@end


@implementation NSText (DisplayLineRangeWindow)

- (void) displayLineRangeWindow:(NSPoint)start :(NSPoint)end
{
	if ((__loops++ > 5) && !_tx.isRichText && !_tx.fieldEditor)						 
		{											// must be plain text obj
		static int ps, pe;
		int e;

		if(__loops == 7)							// first iteration after
			{										// user begings dragging
			NSRect wFrame = [window frame];			// a new selection

			if (!__lineRangeField)
				{
				[__lineRangeWindow initWithContentRect:(NSRect){{0,0},{200,20}}
								   styleMask:NSBorderlessWindowMask
								   backing:NSBackingStoreNonretained	
								   defer:NO];
				__lineRangeField = [NSButton alloc];
				[__lineRangeField initWithFrame:(NSRect){{0,0},{200,20}}];
				[[__lineRangeWindow contentView] addSubview:__lineRangeField];
				}

			NSMinY(wFrame) = NSMaxY(wFrame) + 1;
			[__lineRangeWindow setFrameOrigin:wFrame.origin];
			[__lineRangeWindow orderFront:nil];
			pe = 0;
			__lastLineRect = [[lineLayoutInformation lastObject] lineRect];
//			ps = [self lineLayoutIndexForPoint: start];
			ps = ceil(MAX(1, (int)start.y) / __lastLineRect.size.height);
			}

		e = ceil(MAX(1, (int)end.y) / __lastLineRect.size.height);
														// dynamically display
		if((pe != e))									// selected line range
			{											// indicator
			NSString *v, *format = @"Selected line range: %d -> %d";

			pe = e;
			v = [[NSString alloc] initWithFormat:format, ps, e];
			[__lineRangeField setStringValue:v];
			[__lineRangeField display];
			NSDebugLog(@" selectedRange: %d  %d \n", ps, e);
		}	}
}

@end /* NSText (DisplayLineRangeWindow) */
