/*
 * Copyright 1990, John G. Myers
 *
 * 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 1, 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.
 */

#import "EtermApp.h"

/* You'll find this variable in Emacs_main.m.
 * Yeah, it's ugly, but it would be less so if the Emacs front end
 * used Interface Builder more to begin with.  We'll get there someday.
 * Anyway, who am I to criticize?
 */
extern id servicesMenu;

@implementation EtermApp

- setEtermView:(id)anObject;
{
    etermView = anObject;
}

- etermView
{
    return etermView;
}

/*
 * We're ready to start.  Size the window apropriately and fire up the
 * emacs process, possibly editing a file.
 */
- appDidInit:(id)sender
{
	NXRect frameRect;
	int x, y;
	int rows, columns;

	DPSSetDeadKeysEnabled(DPSGetCurrentContext(),NO);

	rows = atoi(NXGetDefaultValue("Emacs", "Rows"));
	columns = atoi(NXGetDefaultValue("Emacs", "Columns"));
	[etermView sizeWindowTo: columns: rows];
	[[etermView window] getFrame : &frameRect];

	x = atoi(NXGetDefaultValue("Emacs", "WinLocX"));
	y = screenSize.height -
	    frameRect.size.height -
	    atoi(NXGetDefaultValue("Emacs", "WinLocY"));

	if (x + frameRect.size.width > screenSize.width)
	  x = screenSize.width - frameRect.size.width;
	if (y < 0) y = 0;

	if (x < 0) x = 0;
	if (y > screenSize.height - frameRect.size.height)
	  y = screenSize.height - frameRect.size.height;

	[[etermView window] moveTo: (NXCoord)x: (NXCoord)y];

	[self registerForServicesMenu];
	[self setServicesMenu:servicesMenu]; /* a global from main! sheesh! */

	[etermView startEmacs: fileToEdit];
	if (!strcmp(NXGetDefaultValue("Emacs", "NXAutoLaunch"), "YES") &&
	    !strcmp(NXGetDefaultValue("Emacs", "HideOnAutoLaunch"), "YES")) {
	    [self hide: nil];
	}
	return self;
}


/*
 * Intercept the Quit command and replace it with C-x C-c.
 */
-terminate:(id)sender
{
    if (sender && [etermView quitEmacs]) return self;
    return [super terminate:sender];
}

  
/*
 * Stash the name of a file in an instance variable so we
 * can give it to the child emacs when we fire it up.
 *
 * TODO: Later versions may want to send an "(event-open "foo")"
 * message if the child emacs is already started.  So far, I
 * haven't found out how to get Emacs to get open requests for
 * text files, yet get Edit to eat RTF files.  Also, it's not clear
 * whether all (or most) users of Emacs will want it to replace
 * Edit that way.
 *
 * We should probably also handle multiple appOpenFile:type: messages
 * before the appDidInit: message.
 */
- (int)appOpenFile:(const char *)path type:(const char *)type
{
    if (fileToEdit) return NO;

    fileToEdit = malloc(strlen(path)+1);
    strcpy(fileToEdit, path);
    return YES;
}

/*
 * Services menu support (adapted from Draw).
 *
 * Hacked by Geoffrey S. Knauth, Marble Associates.
 * Thanks to Denise Biscoe for pointing out that Emacs
 * did not support Services.
 */

- registerForServicesMenu
{
    static BOOL registered = NO;
    const char *validSendTypes[2];

    if (!registered) {
	registered = YES;
	validSendTypes[0] = NXAsciiPboardType;
	validSendTypes[1] = NULL;
	[NXApp registerServicesMenuSendTypes:validSendTypes
	       andReturnTypes:NULL];
    }

    return self;
}

- validRequestorForSendType:(NXAtom) sendType andReturnType:(NXAtom)returnType 
{
    return (sendType == NXAsciiPboardType && (!returnType || !*returnType)) ?
      self : nil;
}

- (BOOL) writeSelectionToPasteboard:pboard types:(NXAtom *)types
{
    static char *nilsel = "nil_Selection__Do_Cmd_Copy";
    int nilsellen = strlen(nilsel);
    char *data;
    int length;
    id otherpb = [etermView pasteboard];
    
    while (types && *types)
	if (*types == NXAsciiPboardType) break; else types++;
    if (types && *types)
    {
	if (otherpb &&
	    [otherpb readType:NXAsciiPboardType data:&data length:&length])
	{
	    [pboard declareTypes:&NXAsciiPboardType num:1 owner:self];
	    [pboard writeType:NXAsciiPboardType data:data length:length];
	    vm_deallocate(task_self(), (vm_address_t)data, (vm_size_t)length);
	}
	else
	{
	    /* You may ask, "Why on Earth do you want to send out
	     * that crazy nil selection string?"  The reason is that an
	     * empty pasteboard will cause an error panel to appear
	     * that only says there was an error performing the Service.
	     * The message is not very helpful.  I'm trying to provide
	     * the user with usable feedback.  The way the NeXT front end
	     * to Emacs is implemented, there is no selection active when
	     * you mark a region, or when you do a M-w.  Only the NeXT
	     * Copy command seems to save the region in the pasteboard
	     * belonging to the etermView.  If I figure out another way
	     * to make the user's life easier, I will.
	     */
	    [pboard declareTypes:&NXAsciiPboardType num:1 owner:self];
	    [pboard writeType:NXAsciiPboardType data:nilsel length:nilsellen];
	    
	}
	return YES;
    }
    return NO;
}

@end






