ftp.nice.ch/Attic/openStep/implementation/gnustep/sources/alpha-snapshots/gnustep-gui-960621.tgz#/gnustep-gui-960621/Source/NSApplication.m

This is NSApplication.m in view mode; [Download] [Up]

/* 
   NSApplication.m

   The one and only application class

   Copyright (C) 1996 Free Software Foundation, Inc.

   Author:  Scott Christley <scottc@net-community.com>
   Date: 1996
   
   This file is part of the GNUstep GUI Library.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.
   
   This library 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
   Library General Public License for more details.

   If you are interested in a warranty or support for this source code,
   contact Scott Christley <scottc@net-community.com> for more information.
   
   You should have received a copy of the GNU Library General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ 

#include <gnustep/gui/NSApplication.h>
#include <gnustep/gui/NSPopUpButton.h>
#include <gnustep/gui/NSPanel.h>
#include <stdio.h>

//
// Class variables
//
// The global application instance
extern id NSApp;
NSEvent *NullEvent;
BOOL gnustep_gui_app_is_in_dealloc;

// Global strings
NSString *NSModalPanelRunLoopMode = @"ModalPanelMode";
NSString *NSEventTrackingRunLoopMode = @"EventTrackingMode";

//
// Global Exception Strings 
//
NSString *NSAbortModalException = @"AbortModalException";
NSString *NSAbortPrintingException = @"AbortPrintingException";
NSString *NSAppKitIgnoredException;
NSString *NSAppKitVirtualMemoryException;
NSString *NSBadBitmapParametersException;
NSString *NSBadComparisonException;
NSString *NSBadRTFColorTableException;
NSString *NSBadRTFDirectiveException;
NSString *NSBadRTFFontTableException;
NSString *NSBadRTFStyleSheetException;
NSString *NSBrowserIllegalDelegateException;
NSString *NSColorListIOException;
NSString *NSColorListNotEditableException;
NSString *NSDraggingException;
NSString *NSFontUnavailableException;
NSString *NSIllegalSelectorException;
NSString *NSImageCacheException;
NSString *NSNibLoadingException;
NSString *NSPPDIncludeNotFoundException;
NSString *NSPPDIncludeStackOverflowException;
NSString *NSPPDIncludeStackUnderflowException;
NSString *NSPPDParseException;
NSString *NSPasteboardCommunicationException;
NSString *NSPrintOperationExistsException;
NSString *NSPrintPackageException;
NSString *NSPrintingCommunicationException;
NSString *NSRTFPropertyStackOverflowException;
NSString *NSTIFFException;
NSString *NSTextLineTooLongException;
NSString *NSTextNoSelectionException;
NSString *NSTextReadException;
NSString *NSTextWriteException;
NSString *NSTypedStreamVersionException;
NSString *NSWindowServerCommunicationException;
NSString *NSWordTablesReadException;
NSString *NSWordTablesWriteException;

// Application notifications
NSString *NSApplicationDidBecomeActiveNotification;
NSString *NSApplicationDidFinishLaunchingNotification;
NSString *NSApplicationDidHideNotification;
NSString *NSApplicationDidResignActiveNotification;
NSString *NSApplicationDidUnhideNotification;
NSString *NSApplicationDidUpdateNotification;
NSString *NSApplicationWillBecomeActiveNotification;
NSString *NSApplicationWillFinishLaunchingNotification;
NSString *NSApplicationWillHideNotification;
NSString *NSApplicationWillResignActiveNotification;
NSString *NSApplicationWillUnhideNotification;
NSString *NSApplicationWillUpdateNotification;

@implementation NSApplication

//
// Class methods
//
+ (void)initialize
{
  if (self == [NSApplication class])
    {
      NSLog(@"Initialize NSApplication class\n");

      // Initial version
      [self setVersion:1];

      // So the application knows its within dealloc
      // and can prevent -release loops.
      gnustep_gui_app_is_in_dealloc = NO;
    }
}

+ (NSApplication *)sharedApplication
{
  // If the global application does not exist yet then create it
  if (!NSApp)
    NSApp = [[self alloc] init];
  return NSApp;
}

//
// Instance methods
//

//
// Creating and initializing the NSApplication
//
- init
{
  [super init];

  NSLog(@"Begin of NSApplication -init\n");

  // allocate the window list
  window_list = [NSMutableArray array];
  window_count = 1;

  //
  // Event handling setup
  //
  // allocate the event queue
  event_queue = [[Queue alloc] init];
  // No current event
  current_event = nil;
  // The NULL event
  NullEvent = [[NSEvent alloc] init];

  //
  // We are the end of the responder chain
  //
  [self setNextResponder:NULL];

  return self;
}

- (void)finishLaunching
{
  // notify that we will finish the launching
  [self applicationWillFinishLaunching:self];

	// finish the launching

	// notify that the launching has finished
  [self applicationDidFinishLaunching:self];
}

- (void)dealloc
{
  int i, j;

  //NSLog(@"Freeing NSApplication\n");

  // Let ourselves know we are within dealloc
  gnustep_gui_app_is_in_dealloc = YES;

  // Release the window list
  // We retain all of the objects in our list
  //   so we need to release them

  //NSArray doesn't know -removeAllObjects yet
  [window_list removeAllObjects];
  //j = [window_list count];
  //for (i = 0;i < j; ++i)
  //  [[window_list objectAtIndex:i] release];

  // no need -array is autoreleased
  //[window_list release];

  [event_queue release];
  [current_event release];
  [super dealloc];
}

//
// Changing the active application
//
- (void)activateIgnoringOtherApps:(BOOL)flag
{
  app_is_active = YES;
}

- (void)deactivate
{
  app_is_active = NO;
}

- (BOOL)isActive
{
  return app_is_active;
}

//
// Running the event loop
//
- (void)abortModal
{
}

- (NSModalSession)beginModalSessionForWindow:(NSWindow *)theWindow
{
  return NULL;
}

- (void)endModalSession:(NSModalSession)theSession
{
}

- (BOOL)isRunning
{
  return app_is_running;
}

- (void)run
{
  NSEvent *e;

  NSLog(@"NSApplication -run\n");

  [self finishLaunching];

  app_should_quit = NO;
  app_is_running = YES;

  do
    {
      e = [self nextEventMatchingMask:NSAnyEventMask untilDate:nil 
		inMode:nil dequeue:YES];
      if (e)
	[self postEvent:e atStart:YES];
      else
	{
	  // Null event
	  // Call the back-end method to handle it
	  [self handleNullEvent];
	}
    } while (!app_should_quit);
  app_is_running = YES;

  NSLog(@"NSApplication end of run loop\n");
}

- (int)runModalForWindow:(NSWindow *)theWindow
{
  return 0;
}

- (int)runModalSession:(NSModalSession)theSession
{
  return 0;
}

- (void)sendEvent:(NSEvent *)theEvent
{
  // Don't send the null event
  if (theEvent == NullEvent)
    {
      NSLog(@"Not sending the Null Event\n");
      return;
    }

  // What is the event type
  switch ([theEvent type])
    {

      //
      // NSApplication traps the periodic events
      //
    case NSPeriodic:
      break;

    case NSKeyDown:
      {
	NSLog(@"send key down event\n");
	[[theEvent window] sendEvent:theEvent];
	break;
      }
    case NSKeyUp:
      {
	NSDebugLog(@"send key up event\n");
	[[theEvent window] sendEvent:theEvent];
	break;
      }
      //
      // All others get passed to the window
      //
    default:
      {
	if (!theEvent) NSLog(@"NSEvent is nil!\n");
	NSLog(@"NSEvent type: %d\n", [theEvent type]);
	NSLog(@"send event to window\n");
	NSLog([[theEvent window] description]);
	NSLog(@"\n");
	if (![theEvent window])
	  NSLog(@"no window\n");
	[[theEvent window] sendEvent:theEvent];
      }
    }
}

- (void)stop:sender
{
  app_is_running = NO;
}

- (void)stopModal
{
}

- (void)stopModalWithCode:(int)returnCode
{
}

//
// Getting, removing, and posting events
//
- (BOOL)event:(NSEvent *)theEvent matchMask:(unsigned int)mask
{
    NSEventType t;

    // If mask is for any event then return success
    if (mask == NSAnyEventMask)
        return YES;

    if (!theEvent) return NO;

    t = [theEvent type];

    if ((t == NSLeftMouseDown) && (mask & NSLeftMouseDownMask))
        return YES;

    if ((t == NSLeftMouseUp) && (mask & NSLeftMouseUpMask))
        return YES;

    if ((t == NSRightMouseDown) && (mask & NSRightMouseDownMask))
        return YES;

    if ((t == NSRightMouseUp) && (mask & NSRightMouseUpMask))
        return YES;

    if ((t == NSMouseMoved) && (mask & NSMouseMovedMask))
        return YES;

    if ((t == NSMouseEntered) && (mask & NSMouseEnteredMask))
        return YES;

    if ((t == NSMouseExited) && (mask & NSMouseExitedMask))
        return YES;

    if ((t == NSLeftMouseDragged) && (mask & NSLeftMouseDraggedMask))
        return YES;

    if ((t == NSRightMouseDragged) && (mask & NSRightMouseDraggedMask))
        return YES;

    if ((t == NSKeyDown) && (mask & NSKeyDownMask))
        return YES;

    if ((t == NSKeyUp) && (mask & NSKeyUpMask))
        return YES;

    if ((t == NSFlagsChanged) && (mask & NSFlagsChangedMask))
        return YES;

    if ((t == NSPeriodic) && (mask & NSPeriodicMask))
        return YES;

    if ((t == NSCursorUpdate) && (mask & NSCursorUpdateMask))
        return YES;

    return NO;
}

- (void)setCurrentEvent:(NSEvent *)theEvent;
{
    [theEvent retain];
    [current_event release];
    current_event = theEvent;
}

- (NSEvent *)currentEvent;
{
  return current_event;
}

- (void)discardEventsMatchingMask:(unsigned int)mask
		      beforeEvent:(NSEvent *)lastEvent
{
}

- (NSEvent *)nextEventMatchingMask:(unsigned int)mask
			 untilDate:(NSDate *)expiration
			    inMode:(NSString *)mode
			   dequeue:(BOOL)flag
{
  NSEvent *e;
  BOOL done;
  int i, j;

  // If the queue isn't empty then check those messages
  if (![event_queue isEmpty])
    {
      j = [event_queue count];
      for (i = j-1;i > 0; --i)
	{
	  e = [event_queue objectAtIndex: i];
	  if ([self event: e matchMask: mask])
	    {
	      [event_queue removeObjectAtIndex: i];
	      [self setCurrentEvent: e];
	      return e;
	    }
	}
    }

  // Not in queue so wait for next event
  done = NO;
  while (!done)
    {
      e = [self getNextEvent];

      // Check mask
      if ([self event: e matchMask: mask])
	{
	  if (e)
	    e = [event_queue dequeueObject];
	  done = YES;
	}
    }

  [self setCurrentEvent: e];
  return e;
}

- (void)postEvent:(NSEvent *)event atStart:(BOOL)flag
{
  [self sendEvent:event];
}

//
// Sending action messages
//
- (BOOL)sendAction:(SEL)aSelector
		to:aTarget
	      from:sender
{
  //
  // If the target responds to the selector
  // then have it perform it
  //
  if ([aTarget respondsToSelector:aSelector])
    {
      [aTarget perform:aSelector withObject:sender];
      return YES;
    }

  //
  // Otherwise traverse the responder chain
  //

  return NO;
}

- targetForAction:(SEL)aSelector
{
  return self;
}

- (BOOL)tryToPerform:(SEL)aSelector
		with:anObject
{
  return NO;
}

// Setting the application's icon
- (void)setApplicationIconImage:(NSImage *)anImage
{
    if (app_icon != nil)
    {
        [app_icon release];
    }

    app_icon = [anImage retain];
}

- (NSImage *)applicationIconImage
{
  return app_icon;
}

//
// Hiding all windows
//
- (void)hide:sender
{
  int i, j;
  NSWindow *w;

  j = [window_list count];
  for (i = 0;i < j; ++i)
    {
      w = [window_list objectAtIndex:i];
      // Do something to hide the window
    }
  app_is_hidden = YES;
}

- (BOOL)isHidden
{
  return app_is_hidden;
}

- (void)unhide:sender
{
  int i, j;
  NSWindow *w;

  app_is_hidden = NO;
  j = [window_list count];
  for (i = 0;i < j; ++i)
    {
      w = [window_list objectAtIndex:i];
      // Do something to unhide the window
    }

  [[self keyWindow] makeKeyAndOrderFront:self];
}

- (void)unhideWithoutActivation
{
  [self unhide: self];
}

//
// Managing windows
//
- (NSWindow *)keyWindow
{
  int i, j;
  id w;

  j = [window_list count];
  for (i = 0;i < j; ++i)
    {
      w = [window_list objectAtIndex:i];
      if ([w isKeyWindow]) return w;
    }
  return nil;
}

- (NSWindow *)mainWindow
{
  int i, j;
  id w;

  j = [window_list count];
  for (i = 0;i < j; ++i)
    {
      w = [window_list objectAtIndex:i];
      if ([w isMainWindow]) return w;
    }
  return nil;
}

- (NSWindow *)makeWindowsPerform:(SEL)aSelector
			 inOrder:(BOOL)flag
{
  return nil;
}

- (void)miniaturizeAll:sender
{
  id e, obj;

  e = [window_list objectEnumerator];
  obj = [e nextObject];
  while (obj)
    {
      [obj miniaturize: sender];
      obj = [e nextObject];
    }
}

- (void)preventWindowOrdering
{
}

- (void)setWindowsNeedUpdate:(BOOL)flag
{
}

- (void)updateWindows
{
  id e, obj;

  e = [window_list objectEnumerator];
  obj = [e nextObject];
  while (obj)
    {
      [obj update];
      obj = [e nextObject];
    }
}

- (NSArray *)windows
{
  return window_list;
}

- (NSWindow *)windowWithWindowNumber:(int)windowNum
{
  int i, j;
  NSWindow *w;

  j = [window_list count];
  for (i = 0;i < j; ++i)
    {
      w = [window_list objectAtIndex:i];
      if ([w windowNumber] == windowNum) return w;
    }
  return nil;
}

//
// Showing Standard Panels
//
- (void)orderFrontColorPanel:sender
{
}

- (void)orderFrontDataLinkPanel:sender
{
}

- (void)orderFrontHelpPanel:sender
{
}

- (void)runPageLayout:sender
{
}

//
// Getting the main menu
//
- (NSMenu *)mainMenu
{
  return main_menu;
}

- (void)setMainMenu:(NSMenu *)aMenu
{
  int i, j;
  NSMenuCell *mc;
  NSArray *mi;
  id w;

  // Release old and retain new
  [main_menu release];
  main_menu = aMenu;
  [main_menu retain];

  // Search for a menucell with the name Windows
  // This is the default windows menu
  mi = [main_menu itemArray];
  j = [mi count];
  windows_menu = nil;
  for (i = 0;i < j; ++i)
    {
      mc = [mi objectAtIndex:i];
      if ([[mc stringValue] compare:@"Windows"] == NSOrderedSame)
	{
	  // Found it!
	  windows_menu = mc;
	  break;
	}
    }
}

//
// Managing the Windows menu
//
- (void)addWindowsItem:aWindow
		 title:(NSString *)aString
	      filename:(BOOL)isFilename
{
  int i;

  // Not a subclass of window --forget it
  if (![aWindow isKindOfClass:[NSWindow class]])
    return;

  // Add to our window list, the array retains it
  i = [window_list count];
  [window_list addObject:aWindow];

  // set its window number
  [aWindow setWindowNumber:window_count];
  ++window_count;
	
  // If this was the first window then
  //   make it the main and key window
  if (i == 0)
    {
      [aWindow becomeMainWindow];
      [aWindow becomeKeyWindow];
    }
}

- (void)arrangeInFront:sender
{
}

- (void)changeWindowsItem:aWindow
		    title:(NSString *)aString
		 filename:(BOOL)isFilename
{
}

- (void)removeWindowsItem:aWindow
{
  int i, j;
  id w;

  // +++ This should be different
  if (aWindow == key_window)
	key_window = nil;
  if (aWindow == main_window)
	main_window = nil;

  // If we are within our dealloc then don't remove the window
  // Most likely dealloc is removing windows from our window list
  // and subsequently NSWindow is caling us to remove itself.
  if (gnustep_gui_app_is_in_dealloc)
      return;

  // Remove it from the window list
  [window_list removeObject: aWindow];

  return;
}

- (void)setWindowsMenu:aMenu
{
  if (windows_menu)
    [windows_menu setSubmenu:aMenu];
}

- (void)updateWindowsItem:aWindow
{
}

- (NSMenu *)windowsMenu
{
  return [windows_menu submenu];
}

//
// Managing the Service menu
//
- (void)registerServicesMenuSendTypes:(NSArray *)sendTypes
			  returnTypes:(NSArray *)returnTypes
{
}

- (NSMenu *)servicesMenu
{
  return nil;
}

- (void)setServicesMenu:(NSMenu *)aMenu
{
}

- validRequestorForSendType:(NSString *)sendType
		 returnType:(NSString *)returnType
{
  return nil;
}

// Getting the display postscript context
- (NSDPSContext *)context
{
    return [NSDPSContext currentContext];
}

// Reporting an exception
//- (void)reportException:(NSException *)anException

//
// Terminating the application
//
- (void)terminate:sender
{
  if ([self applicationShouldTerminate:sender])
    app_should_quit = YES;
}

// Assigning a delegate
- delegate
{
  return delegate;
}

- (void)setDelegate:anObject
{
  delegate = anObject;
}

//
// Implemented by the delegate
//
- (BOOL)application:sender openFileWithoutUI:(NSString *)filename
{
  BOOL result = NO;

  if ([delegate respondsTo:@selector(application:openFileWithoutUI:)])
    result = [delegate application:sender openFileWithoutUI:filename];

  return result;
}
	
- (BOOL)application:(NSApplication *)app openFile:(NSString *)filename
{
  BOOL result = NO;

  if ([delegate respondsTo:@selector(application:openFile:)])
    result = [delegate application:app openFile:filename];

  return result;
}

- (BOOL)application:(NSApplication *)app openTempFile:(NSString *)filename
{
  BOOL result = NO;

  if ([delegate respondsTo:@selector(application:openTempFile:)])
    result = [delegate application:app openTempFile:filename];

  return result;
}

- (void)applicationDidBecomeActive:sender
{
  if ([delegate respondsTo:@selector(applicationDidBecomeActive:)])
    [delegate applicationDidBecomeActive:sender];
}
	
- (void)applicationDidFinishLaunching:sender
{
  if ([delegate respondsTo:@selector(applicationDidFinishLaunching:)])
    [delegate applicationDidFinishLaunching:sender];
}

- (void)applicationDidHide:sender
{
  if ([delegate respondsTo:@selector(applicationDidHide:)])
    [delegate applicationDidHide:sender];
}

- (void)applicationDidResignActive:sender
{
  if ([delegate respondsTo:@selector(applicationDidResignActive:)])
    [delegate applicationDidResignActive:sender];
}

- (void)applicationDidUnhide:sender
{
  if ([delegate respondsTo:@selector(applicationDidUnhide:)])
    [delegate applicationDidUnhide:sender];
}

- (void)applicationDidUpdate:sender
{
  if ([delegate respondsTo:@selector(applicationDidUpdate:)])
    [delegate applicationDidUpdate:sender];
}

- (BOOL)applicationOpenUntitledFile:(NSApplication *)app
{
  BOOL result = NO;

  if ([delegate respondsTo:@selector(applicationOpenUntitledFile:)])
    result = [delegate applicationOpenUntitledFile:app];

  return result;
}

- (BOOL)applicationShouldTerminate:sender
{
  BOOL result = YES;

  if ([delegate respondsTo:@selector(applicationShouldTerminate:)])
    result = [delegate applicationShouldTerminate:sender];

  return result;
}

- (void)applicationWillBecomeActive:sender
{
  if ([delegate respondsTo:@selector(applicationWillBecomeActive:)])
    [delegate applicationWillBecomeActive:sender];
}

- (void)applicationWillFinishLaunching:sender
{
  if ([delegate respondsTo:@selector(applicationWillFinishLaunching:)])
    [delegate applicationWillFinishLaunching:sender];
}

- (void)applicationWillHide:sender
{
  if ([delegate respondsTo:@selector(applicationWillHide:)])
    [delegate applicationWillHide:sender];
}

- (void)applicationWillResignActive:sender
{
  if ([delegate respondsTo:@selector(applicationWillResignActive:)])
    [delegate applicationWillResignActive:sender];
}

- (void)applicationWillUnhide:sender
{
  if ([delegate respondsTo:@selector(applicationWillUnhide:)])
    [delegate applicationWillUnhide:sender];
}

- (void)applicationWillUpdate:sender
{
  if ([delegate respondsTo:@selector(applicationWillUpdate:)])
    [delegate applicationWillUpdate:sender];
}

//
// NSCoding protocol
//
- (void)encodeWithCoder:aCoder
{
  [super encodeWithCoder:aCoder];

  [aCoder encodeObject: window_list];
  // We don't want to code the event queue do we?
  //[aCoder encodeObject: event_queue];
  //[aCoder encodeObject: current_event];
  [aCoder encodeObjectReference: key_window withName: @"Key window"];
  [aCoder encodeObjectReference: main_window withName: @"Main window"];
  [aCoder encodeObjectReference: delegate withName: @"Delegate"];
  [aCoder encodeObject: main_menu];
  [aCoder encodeObjectReference: windows_menu withName: @"Windows menu"];
}

- initWithCoder:aDecoder
{
  [super initWithCoder:aDecoder];

  window_list = [aDecoder decodeObject];
  [aDecoder decodeObjectAt: &key_window withName: NULL];
  [aDecoder decodeObjectAt: &main_window withName: NULL];
  [aDecoder decodeObjectAt: &delegate withName: NULL];
  main_menu = [aDecoder decodeObject];
  [aDecoder decodeObjectAt: &windows_menu withName: NULL];

  return self;
}

@end

//
// Backend methods
// empty implementations
//
@implementation NSApplication (GNUstepBackend)

// Get next event
- (NSEvent *)getNextEvent
{
  [event_queue enqueueObject: NullEvent];
  return NullEvent;
}

// handle a non-translated event
- (void)handleNullEvent
{}

@end

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.