gsk@parian: foreach file (Emacs_main.m EtermApp.[hm] EtermView.[hm])
? echo ===== diff -c $file{.orig,}
? diff -c $file{.orig,}
? end
===== diff -c Emacs_main.m.orig Emacs_main.m
*** Emacs_main.m.orig	Sat Feb 16 13:36:20 1991
--- Emacs_main.m	Sat Feb 15 13:19:33 1992
***************
*** 25,30 ****
--- 25,32 ----
  #import "EtermView.h"
  #import "InfoDistributor.h"
  
+ id servicesMenu = 0;	/* this wouldn't be here if IB had been used... */
+ 
  void main(int argc, char *argv[])
  {
      id window, view, infoDistributor;
***************
*** 73,78 ****
--- 75,83 ----
  		setTarget:view];
      [editmenu sizeToFit];
  
+     /* Services menu */
+     servicesMenu = [Menu newTitle:"Services"];
+ 
      /* A rather minimal main menu as well */
      menu = [Menu newTitle:"Emacs"];
      [menu setSubmenu:infomenu
***************
*** 79,84 ****
--- 84,91 ----
  		forItem:[menu addItem:"Info" action:0 keyEquivalent:'\0']];
      [menu setSubmenu:editmenu
  		forItem:[menu addItem:"Edit" action:0 keyEquivalent:'\0']];
+     [menu setSubmenu:servicesMenu
+ 		forItem:[menu addItem:"Services" action:0 keyEquivalent:'\0']];
      [menu addItem:"Hide"
  		action:@selector(hide:)
   		keyEquivalent:'h'];
===== diff -c EtermApp.h.orig EtermApp.h
*** EtermApp.h.orig	Sat Feb 16 13:36:21 1991
--- EtermApp.h	Sat Feb 15 13:19:33 1992
***************
*** 18,23 ****
--- 18,24 ----
  
  #import <appkit/appkit.h>
  #import <appkit/Application.h>
+ #import <mach.h>
  #import "EtermView.h"
  
  @interface EtermApp : Application
***************
*** 30,33 ****
--- 31,37 ----
  - etermView;
  - appDidInit:(id)sender;
  - (int)appOpenFile:(const char *)path type:(const char *)type;
+ - registerForServicesMenu;
+ - validRequestorForSendType:(NXAtom) sendType andReturnType:(NXAtom)returnType; 
+ - (BOOL) writeSelectionToPasteboard:pboard types:(NXAtom *)types;
  @end
===== diff -c EtermApp.m.orig EtermApp.m
*** EtermApp.m.orig	Sat Feb 16 14:13:57 1991
--- EtermApp.m	Sat Feb 15 13:19:33 1992
***************
*** 18,23 ****
--- 18,30 ----
  
  #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;
***************
*** 61,66 ****
--- 68,77 ----
  	  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")) {
***************
*** 101,106 ****
--- 112,189 ----
      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
===== diff -c EtermView.h.orig EtermView.h
*** EtermView.h.orig	Sat Feb 16 13:36:23 1991
--- EtermView.h	Sat Feb 15 13:19:34 1992
***************
*** 30,35 ****
--- 30,36 ----
      int masterChannel;		/* FD of /dev/pty device */
      int eventServerSocket;	/* FD listening for event connection */
      FILE *eventChannel;		/* file ptr of event socket */
+     id pasteboard;		/* so EtermApp can use Services */
  }
  
  + initialize;
***************
*** 50,55 ****
--- 51,57 ----
  - cut: sender;
  - copy: sender;
  - paste: sender;
+ - pasteboard;
  - undo: sender;
  /*  - powerOff:*/
  - getDimensions: (int *)linesPtr : (int *) colsPtr;
===== diff -c EtermView.m.orig EtermView.m
*** EtermView.m.orig	Mon Mar 18 19:36:34 1991
--- EtermView.m	Sat Feb 15 13:19:35 1992
***************
*** 114,119 ****
--- 114,121 ----
      [self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE];
      [self notifyAncestorWhenFrameChanged:YES];
  
+     pasteboard = [Pasteboard new];
+ 
      fontname = NXGetDefaultValue("Emacs", "NXFixedPitchFont");
      fontsize = atoi(NXGetDefaultValue("Emacs", "NXFixedPitchFontSize"));
  
***************
*** 429,435 ****
      
  - paste: sender;
  {
-     static id pasteboard;
      const char *const *p, *const *types;
      char *data;
      int len;
--- 431,436 ----
***************
*** 436,442 ****
  
      if (!eventChannel) return self;
  
-     if (!pasteboard) pasteboard = [Pasteboard new];
      types = [pasteboard types];
      for (p=types; *p && strcmp(*p, NXAsciiPboard); p++);
  
--- 437,442 ----
***************
*** 471,476 ****
--- 471,481 ----
      }
  
      return self;
+ }
+ 
+ - pasteboard
+ {
+     return pasteboard;
  }
  
  - undo: sender;
gsk@parian: 