changeset 46798:a8e027c9c403

In src: 2002-08-03 Andrew Choi <akochoi@shaw.ca> * macterm.c (USE_CARBON_EVENTS): New macro. (macCtrlKey, macShiftKey, macMetaKey, macAltKey): New macros. (x_iconify_frame): Call CollapseWindow. (Vmac_reverse_ctrl_meta): New variable. (Vmac_wheel_button_is_mouse_2): New variable. (init_mac_drag_n_drop): New function. (mac_do_receive_drag): New function. (mac_handle_service_event): New function. (init_service_handler): New function. (mac_to_emacs_modifiers): New function. (mac_event_to_emacs_modifiers): New function. (mac_get_mouse_btn): New function. (mac_convert_event_ref): New function. (XTread_socket) [USE_CARBON_EVENTS]: Call ReceiveNextEvent, SendEventToEventTarget, mac_event_to_emacs_modifiers, and mac_get_mouse_btn. (mac_initialize): Call init_mac_drag_n_drop and init_service_handler. * keyboard.c: Define Qmouse_wheel, mouse_wheel_syms, and lispy_mouse_wheel_names for MAC_OSX as well as for WINDOWS_NT. (kbd_buffer_get_event): Set used_mouse_menu for MENU_BAR_EVENT and TOOL_BAR_EVENT for MAC_OS as well. (make_lispy_event): Handle MOUSE_WHEEL_EVENT for MAC_OSX as well as for WINDOWS_NT. (syms_of_keyboard): Initialize Qmouse_wheel for MAC_OSX. * termhooks.h (event_kind): Define MOUSE_WHEEL_EVENT also for MAC_OSX. In lisp: 2002-08-03 Andrew Choi <akochoi@shaw.ca> * term/mac-win.el: Set keys to enable mouse wheel support.
author Andrew Choi <akochoi@shaw.ca>
date Sat, 03 Aug 2002 22:21:09 +0000
parents 1c4af44cad8c
children c9fab7d532d1
files lisp/ChangeLog lisp/term/mac-win.el src/ChangeLog src/keyboard.c src/macterm.c src/termhooks.h
diffstat 6 files changed, 533 insertions(+), 146 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sat Aug 03 20:54:52 2002 +0000
+++ b/lisp/ChangeLog	Sat Aug 03 22:21:09 2002 +0000
@@ -1,9 +1,13 @@
-2002-08-03  Kai Gro,b_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Andrew Choi  <akochoi@shaw.ca>
+
+	* term/mac-win.el: Set keys to enable mouse wheel support.
+
+2002-08-03  Kai Gro,A_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
 	* net/tramp.el: Version 2.0.8.
 	(tramp-perl-encode, tramp-perl-encode): Double the backslashes.
 
-2002-08-03  Kai Gro,b_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Kai Gro,A_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
 	* net/tramp.el: Version 2.0.7.
 	(tramp-perl-encode-with-module, tramp-perl-decode-with-module) 
@@ -17,7 +21,7 @@
 	(f90-font-lock-keywords-2): Fix `implicit type(foo)' case.
 	(f90-type-def-re): Fix value.
 
-2002-08-03  Kai Gro,b_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-08-03  Kai Gro,A_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
 	* net/tramp.el: Version 2.0.6.
 	(tramp-default-method): Change to "ssh" from "sm".
@@ -111,7 +115,7 @@
 	(update-subdirs-CMD): Generate the right list of subdirectories.  From
 	Tak Ota <Takaaki.Ota@am.sony.com>.
 
-2002-07-30  Kai Gro,b_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-07-30  Kai Gro,A_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
 	* net/tramp.el: New version 2.0.5.
 	(tramp-methods): Remove inline encoding method parameters.  The
@@ -257,7 +261,7 @@
 	* ps-print.el: Update copyright year.
 	(ps-begin-cut-regexp, ps-end-cut-regexp): Fix type.
 
-2002-07-26  Kai Gro,b_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
+2002-07-26  Kai Gro,A_(Bjohann  <Kai.Grossjohann@CS.Uni-Dortmund.DE>
 
 	* eshell/eshell.el (eshell): Numeric prefix arg means to switch
 	to the session with that number.  Old behavior still available
--- a/lisp/term/mac-win.el	Sat Aug 03 20:54:52 2002 +0000
+++ b/lisp/term/mac-win.el	Sat Aug 03 22:21:09 2002 +0000
@@ -234,6 +234,16 @@
 ;; or bold bitmap versions will not display these variants correctly.
 (setq scalable-fonts-allowed t)
 
+;; Make suspend-emacs [C-z] collapse the current frame
+(substitute-key-definition 'suspend-emacs 'iconify-frame
+			   global-map)
+ 
+;; Support mouse-wheel scrolling
+(autoload 'mwheel-scroll "mwheel")
+(global-set-key [mouse-wheel] 'mwheel-scroll)
+(global-set-key [C-mouse-wheel] 'mwheel-scroll)
+(global-set-key [S-mouse-wheel] 'mwheel-scroll)
+
 ;; (prefer-coding-system 'mac-roman)
 
 ;;
--- a/src/ChangeLog	Sat Aug 03 20:54:52 2002 +0000
+++ b/src/ChangeLog	Sat Aug 03 22:21:09 2002 +0000
@@ -1,3 +1,35 @@
+2002-08-03  Andrew Choi  <akochoi@shaw.ca>
+
+	* macterm.c (USE_CARBON_EVENTS): New macro.
+	(macCtrlKey, macShiftKey, macMetaKey, macAltKey): New macros.
+	(x_iconify_frame): Call CollapseWindow.
+	(Vmac_reverse_ctrl_meta): New variable.
+	(Vmac_wheel_button_is_mouse_2): New variable.
+	(init_mac_drag_n_drop): New function.
+	(mac_do_receive_drag): New function.
+	(mac_handle_service_event): New function.
+	(init_service_handler): New function.
+	(mac_to_emacs_modifiers): New function.
+	(mac_event_to_emacs_modifiers): New function.
+	(mac_get_mouse_btn): New function.
+	(mac_convert_event_ref): New function.
+	(XTread_socket) [USE_CARBON_EVENTS]: Call ReceiveNextEvent,
+	SendEventToEventTarget, mac_event_to_emacs_modifiers, and
+	mac_get_mouse_btn.
+	(mac_initialize): Call init_mac_drag_n_drop and
+	init_service_handler.
+
+	* keyboard.c: Define Qmouse_wheel, mouse_wheel_syms, and
+	lispy_mouse_wheel_names for MAC_OSX as well as for WINDOWS_NT.
+	(kbd_buffer_get_event): Set used_mouse_menu for MENU_BAR_EVENT and
+	TOOL_BAR_EVENT for MAC_OS as well.
+	(make_lispy_event): Handle MOUSE_WHEEL_EVENT for MAC_OSX as well
+	as for WINDOWS_NT.
+	(syms_of_keyboard): Initialize Qmouse_wheel for MAC_OSX.
+
+	* termhooks.h (event_kind): Define MOUSE_WHEEL_EVENT also for
+	MAC_OSX.
+	
 2002-08-03  Gerd Moellmann  <gerd.moellmann@t-online.de>
 
 	* xdisp.c (forward_to_next_line_start): Fix a condition that
--- a/src/keyboard.c	Sat Aug 03 20:54:52 2002 +0000
+++ b/src/keyboard.c	Sat Aug 03 22:21:09 2002 +0000
@@ -550,8 +550,10 @@
 /* Symbols to denote kinds of events.  */
 Lisp_Object Qfunction_key;
 Lisp_Object Qmouse_click;
+#if defined(WINDOWSNT) || defined(MAC_OSX)
+Lisp_Object Qmouse_wheel;
+#endif
 #ifdef WINDOWSNT
-Lisp_Object Qmouse_wheel;
 Lisp_Object Qlanguage_change;
 #endif
 Lisp_Object Qdrag_n_drop;
@@ -644,7 +646,7 @@
 
 /* If we support a window system, turn on the code to poll periodically
    to detect C-g.  It isn't actually used when doing interrupt input.  */
-#ifdef HAVE_WINDOW_SYSTEM
+#if defined(HAVE_WINDOW_SYSTEM) && !defined(USE_ASYNC_EVENTS)
 #define POLL_FOR_INPUT
 #endif
 
@@ -3881,7 +3883,7 @@
 	    {
 	      obj = make_lispy_event (event);
 	      
-#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
+#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS)
 	      /* If this was a menu selection, then set the flag to inhibit
 		 writing to last_nonmenu_event.  Don't do this if the event
 		 we're returning is (menu-bar), though; that indicates the
@@ -4260,7 +4262,7 @@
 static Lisp_Object accent_key_syms;
 static Lisp_Object func_key_syms;
 static Lisp_Object mouse_syms;
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 static Lisp_Object mouse_wheel_syms;
 #endif
 static Lisp_Object drag_n_drop_syms;
@@ -4669,7 +4671,7 @@
 
 Lisp_Object Vlispy_mouse_stem;
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
 /* mouse-wheel events are generated by the wheel on devices such as
    the MS Intellimouse.  The wheel sits in between the left and right
    mouse buttons, and is typically used to scroll or zoom the window
@@ -5279,6 +5281,8 @@
 			       Qnil));
 	}
       }
+#endif /* WINDOWS_NT */
+#if defined(WINDOWS_NT) || defined(MAC_OSX)
     case MOUSE_WHEEL_EVENT:
       {
 	int part;
@@ -5350,7 +5354,7 @@
 					     Qnil))));
 	}
       }
-#endif /* WINDOWSNT */
+#endif /* WINDOWSNT || MAC_OSX */
 
     case DRAG_N_DROP_EVENT:
       {
@@ -10433,9 +10437,11 @@
   staticpro (&Qfunction_key);
   Qmouse_click = intern ("mouse-click");
   staticpro (&Qmouse_click);
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   Qmouse_wheel = intern ("mouse-wheel");
   staticpro (&Qmouse_wheel);
+#endif
+#ifdef WINDOWSNT
   Qlanguage_change = intern ("language-change");
   staticpro (&Qlanguage_change);
 #endif
@@ -10583,10 +10589,9 @@
   func_key_syms = Qnil;
   staticpro (&func_key_syms);
 
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   mouse_wheel_syms = Qnil;
   staticpro (&mouse_wheel_syms);
-  
   drag_n_drop_syms = Qnil;
   staticpro (&drag_n_drop_syms);
 #endif
--- a/src/macterm.c	Sat Aug 03 20:54:52 2002 +0000
+++ b/src/macterm.c	Sat Aug 03 22:21:09 2002 +0000
@@ -58,6 +58,10 @@
 #define max(a, b) ((a) > (b) ? (a) : (b))
 #undef init_process
 #define init_process emacs_init_process
+/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
+   obtain events from the event queue.  If set to 0, WaitNextEvent is
+   used instead.  */
+#define USE_CARBON_EVENTS 1
 #else /* not MAC_OSX */
 #include <Quickdraw.h>
 #include <ToolUtils.h>
@@ -106,6 +110,15 @@
 
 #define BETWEEN(X, LOWER, UPPER)  ((X) >= (LOWER) && (X) < (UPPER))
 
+/* Set of macros that handle mapping of Mac modifier keys to emacs.  */
+#define macCtrlKey     (NILP (Vmac_reverse_ctrl_meta) ? controlKey :	\
+			(NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+#define macShiftKey    (shiftKey)
+#define macMetaKey     (NILP (Vmac_reverse_ctrl_meta) ?			\
+			(NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
+			: controlKey)
+#define macAltKey      (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
+
 
 /* Fringe bitmaps.  */
 
@@ -10092,108 +10105,21 @@
 x_iconify_frame (f)
      struct frame *f;
 {
-#if 0 /* MAC_TODO: really no iconify on Mac */
-  int result;
-  Lisp_Object type;
-
   /* Don't keep the highlight on an invisible frame.  */
-  if (FRAME_X_DISPLAY_INFO (f)->x_highlight_frame == f)
-    FRAME_X_DISPLAY_INFO (f)->x_highlight_frame = 0;
-
+  if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
+    FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
+
+#if 0
+  /* Review:  Since window is still visible in dock, still allow updates? */
   if (f->async_iconified)
     return;
-
-  BLOCK_INPUT;
-
-  FRAME_SAMPLE_VISIBILITY (f);
-
-  type = x_icon_type (f);
-  if (!NILP (type))
-    x_bitmap_icon (f, type);
-
-#ifdef USE_X_TOOLKIT
-
-  if (! FRAME_VISIBLE_P (f))
-    {
-      if (! EQ (Vx_no_window_manager, Qt))
-	x_wm_set_window_state (f, IconicState);
-      /* This was XtPopup, but that did nothing for an iconified frame.  */
-      XtMapWidget (f->output_data.x->widget);
-      /* The server won't give us any event to indicate
-	 that an invisible frame was changed to an icon,
-	 so we have to record it here.  */
-      f->iconified = 1;
-      f->visible = 1;
-      f->async_iconified = 1;
-      f->async_visible = 0;
-      UNBLOCK_INPUT;
-      return;
-    }
-
-  result = XIconifyWindow (FRAME_X_DISPLAY (f),
-			   XtWindow (f->output_data.x->widget),
-			   DefaultScreen (FRAME_X_DISPLAY (f)));
-  UNBLOCK_INPUT;
-
-  if (!result)
-    error ("Can't notify window manager of iconification");
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
+#endif
 
   BLOCK_INPUT;
-  XFlush (FRAME_X_DISPLAY (f));
+
+  CollapseWindow (FRAME_MAC_WINDOW (f), true);
+  
   UNBLOCK_INPUT;
-#else /* not USE_X_TOOLKIT */
-
-  /* Make sure the X server knows where the window should be positioned,
-     in case the user deiconifies with the window manager.  */
-  if (! FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P (f))
-    x_set_offset (f, f->output_data.x->left_pos, f->output_data.x->top_pos, 0);
-
-  /* Since we don't know which revision of X we're running, we'll use both
-     the X11R3 and X11R4 techniques.  I don't know if this is a good idea.  */
-
-  /* X11R4: send a ClientMessage to the window manager using the
-     WM_CHANGE_STATE type.  */
-  {
-    XEvent message;
-
-    message.xclient.window = FRAME_X_WINDOW (f);
-    message.xclient.type = ClientMessage;
-    message.xclient.message_type = FRAME_X_DISPLAY_INFO (f)->Xatom_wm_change_state;
-    message.xclient.format = 32;
-    message.xclient.data.l[0] = IconicState;
-
-    if (! XSendEvent (FRAME_X_DISPLAY (f),
-		      DefaultRootWindow (FRAME_X_DISPLAY (f)),
-		      False,
-		      SubstructureRedirectMask | SubstructureNotifyMask,
-		      &message))
-      {
-	UNBLOCK_INPUT_RESIGNAL;
-	error ("Can't notify window manager of iconification");
-      }
-  }
-
-  /* X11R3: set the initial_state field of the window manager hints to
-     IconicState.  */
-  x_wm_set_window_state (f, IconicState);
-
-  if (!FRAME_VISIBLE_P (f))
-    {
-      /* If the frame was withdrawn, before, we must map it.  */
-      XMapRaised (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
-    }
-
-  f->async_iconified = 1;
-  f->async_visible = 0;
-
-  XFlush (FRAME_X_DISPLAY (f));
-  UNBLOCK_INPUT;
-#endif /* not USE_X_TOOLKIT */
-#endif /* MAC_TODO */
 }
 
 
@@ -11560,9 +11486,18 @@
 
 Boolean	terminate_flag = false;
 
-/* true if using command key as meta key */
+/* True if using command key as meta key.  */
 Lisp_Object Vmac_command_key_is_meta;
 
+/* True if the ctrl and meta keys should be reversed.  */
+Lisp_Object Vmac_reverse_ctrl_meta;
+
+#if USE_CARBON_EVENTS
+/* True if the mouse wheel button (i.e. button 4) should map to
+   mouse-2, instead of mouse-3.  */
+Lisp_Object Vmac_wheel_button_is_mouse_2;
+#endif
+
 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
    to this text encoding */
 int mac_keyboard_text_encoding;
@@ -11577,13 +11512,23 @@
 Point saved_menu_event_location;
 
 /* Apple Events */
-static void init_required_apple_events(void);
+static void init_required_apple_events (void);
 static pascal OSErr
-do_ae_open_application(const AppleEvent *, AppleEvent *, long);
+do_ae_open_application (const AppleEvent *, AppleEvent *, long);
 static pascal OSErr
-do_ae_print_documents(const AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_open_documents(AppleEvent *, AppleEvent *, long);
-static pascal OSErr do_ae_quit_application(AppleEvent *, AppleEvent *, long);
+do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
+static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
+
+/* Drag and Drop */
+static OSErr init_mac_drag_n_drop ();
+static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference); 
+
+#if USE_CARBON_EVENTS
+/* Preliminary Support for the OSX Services Menu */
+static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
+static void init_service_handler ();
+#endif
 
 extern void init_emacs_passwd_dir ();
 extern int emacs_main (int, char **, char **);
@@ -11592,6 +11537,104 @@
 extern void initialize_applescript();
 extern void terminate_applescript();
 
+static unsigned int 
+#if USE_CARBON_EVENTS
+mac_to_emacs_modifiers (UInt32 mods)
+#else
+mac_to_emacs_modifiers (EventModifiers mods)
+#endif
+{
+  unsigned int result = 0;
+  if (mods & macShiftKey)
+    result |= shift_modifier;
+  if (mods & macCtrlKey)
+    result |= ctrl_modifier;
+  if (mods & macMetaKey)
+    result |= meta_modifier;
+  if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
+    result |= alt_modifier;
+  return result;
+}
+
+#if USE_CARBON_EVENTS
+/* Obtains the event modifiers from the event ref and then calls
+   mac_to_emacs_modifiers.  */
+static int 
+mac_event_to_emacs_modifiers (EventRef eventRef) 
+{
+  UInt32 mods = 0;
+  GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
+		    sizeof (UInt32), NULL, &mods);
+  return mac_to_emacs_modifiers (mods);
+}
+
+/* Given an event ref, return the code to use for the mouse button
+   code in the emacs input_event.  */
+static int
+mac_get_mouse_btn (EventRef ref) 
+{
+  EventMouseButton result = kEventMouseButtonPrimary;
+  GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
+		    sizeof (EventMouseButton), NULL, &result);
+  switch (result) 
+    {
+    case kEventMouseButtonPrimary:
+      return 0;
+    case kEventMouseButtonSecondary:
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1; 
+    case kEventMouseButtonTertiary:
+    case 4:  /* 4 is the number for the mouse wheel button */
+      return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2; 
+    default:
+      return 0;
+    }
+}
+
+/* Normally, ConvertEventRefToEventRecord will correctly handle all
+   events.  However the click of the mouse wheel is not converted to a
+   mouseDown or mouseUp event.  This calls ConvertEventRef, but then
+   checks to see if it is a mouse up or down carbon event that has not
+   been converted, and if so, converts it by hand (to be picked up in
+   the XTread_socket loop).  */
+static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) 
+{
+  Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
+  /* Do special case for mouse wheel button.  */
+  if (!result && GetEventClass (eventRef) == kEventClassMouse) 
+    { 
+      UInt32 kind = GetEventKind (eventRef);
+      if (kind == kEventMouseDown && !(eventRec->what == mouseDown)) 
+	{
+	  eventRec->what = mouseDown;
+	  result=1;
+	}
+      if (kind == kEventMouseUp && !(eventRec->what == mouseUp)) 
+	{
+	  eventRec->what = mouseUp;
+	  result=1;
+	}
+      if (result) 
+	{
+	  /* Need where and when.  */
+	  UInt32 mods;
+	  GetEventParameter (eventRef, kEventParamMouseLocation,
+			     typeQDPoint, NULL, sizeof (Point),
+			     NULL, &eventRec->where);
+	  /* Use two step process because new event modifiers are
+	     32-bit and old are 16-bit.  Currently, only loss is
+	     NumLock & Fn. */
+	  GetEventParameter (eventRef, kEventParamKeyModifiers,
+			     typeUInt32, NULL, sizeof (UInt32),
+			     NULL, &mods);
+	  eventRec->modifiers = mods;
+	  
+	  eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
+	}
+    }
+  return result;
+}
+
+#endif
 
 static void
 do_get_menus (void)
@@ -12019,6 +12062,13 @@
   SetPort (save_port);
 }
 
+/* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
+static OSErr
+init_mac_drag_n_drop ()
+{
+  OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
+  return result;
+}
 
 /* Intialize AppleEvent dispatcher table for the required events.  */
 void
@@ -12092,6 +12142,102 @@
     abort ();
 }
 
+#if USE_CARBON_EVENTS
+
+void init_service_handler()
+{
+  EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
+			   {kEventClassService, kEventServiceCopy},
+			   {kEventClassService, kEventServicePaste}};
+  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
+				  3, specs, NULL, NULL);
+}
+
+/*
+   MAC_TODO: Check to see if this is called by AEProcessDesc...
+ */
+OSStatus mac_handle_service_event (EventHandlerCallRef callRef,
+				   EventRef event, void *data)
+{
+  OSStatus err = noErr; 
+  switch (GetEventKind (event))
+    {
+    case kEventServiceGetTypes: 
+      {
+	CFMutableArrayRef copyTypes, pasteTypes;
+	CFStringRef type;
+	Boolean selection = true;
+	/*
+	  GetEventParameter(event, kEventParamServicePasteTypes,
+	  typeCFMutableArrayRef, NULL,
+	  sizeof (CFMutableArrayRef), NULL, &pasteTypes);
+	*/
+	GetEventParameter(event, kEventParamServiceCopyTypes,
+			  typeCFMutableArrayRef, NULL,
+			  sizeof (CFMutableArrayRef), NULL, &copyTypes);
+	type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
+	if (type) {
+	  CFArrayAppendValue (copyTypes, type);
+	  //CFArrayAppendValue (pasteTypes, type);
+	  CFRelease (type);
+	}
+      }
+    case kEventServiceCopy:
+      {
+	ScrapRef currentScrap, specificScrap;
+	char * buf = "";
+	Size byteCount = 0;
+
+	GetCurrentScrap (&currentScrap);
+
+	err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
+	if (err == noErr)
+	  {
+	    void *buffer = xmalloc (byteCount);
+	    if (buffer != NULL)
+	      {
+		GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
+				   sizeof (ScrapRef), NULL, &specificScrap);
+	      
+		err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
+					  &byteCount, buffer);
+		if (err == noErr)
+		  PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
+				  kScrapFlavorMaskNone, byteCount, buffer);
+		xfree (buffer);
+	      } 
+	  }
+	err = noErr;
+      }
+    case kEventServicePaste:
+      {
+	/*
+	// Get the current location
+        Size     byteCount;
+        ScrapRef specificScrap;
+        GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
+			  sizeof(ScrapRef), NULL, &specificScrap);
+        err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
+        if (err == noErr) {
+	  void * buffer = xmalloc(byteCount);
+	  if (buffer != NULL ) {
+	    err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText, 
+				     &byteCount, buffer);
+	    if (err == noErr) {
+	      // Actually place in the buffer
+	      BLOCK_INPUT;
+	      // Get the current "selection" string here
+	      UNBLOCK_INPUT;
+	    }
+	  }
+	  xfree(buffer);
+        }
+        */
+      }   
+    }
+  return err;
+}
+#endif
 
 /* Open Application Apple Event */
 static pascal OSErr
@@ -12187,6 +12333,83 @@
 }
 
 
+static pascal OSErr mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
+					 DragReference theDrag)
+{
+  short items;
+  short index;
+  FlavorFlags theFlags;
+  Point mouse;
+  OSErr result;
+  ItemReference theItem;
+  HFSFlavor data;
+  FSRef fref;
+  Size size = sizeof (HFSFlavor);
+
+  drag_and_drop_file_list = Qnil;
+  GetDragMouse (theDrag, &mouse, 0L);
+  CountDragItems (theDrag, &items);
+  for (index = 1; index <= items; index++) 
+    {
+      /* Only handle file references.  */
+      GetDragItemReferenceNumber (theDrag, index, &theItem);
+      result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
+      if (result == noErr)
+	{
+#ifdef MAC_OSX
+	  FSRef frref;
+#else
+	  Str255 path_name;
+#endif
+	  Str255 unix_path_name;
+	  GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
+#ifdef MAC_OSX
+	  /* Use Carbon routines, otherwise it converts the file name
+	     to /Macintosh HD/..., which is not correct. */
+	  FSpMakeFSRef (&data.fileSpec, &fref);
+	  if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
+#else
+	  if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
+				      data.fileSpec.parID, data.fileSpec.name) &&
+	      mac_to_posix_pathname (path_name, unix_path_name, 255))
+#endif
+            drag_and_drop_file_list = Fcons (build_string (unix_path_name),
+					     drag_and_drop_file_list);
+	}
+      else
+	return;
+    }
+  /* If there are items in the list, construct an event and post it to
+     the queue like an interrupt using kbd_buffer_store_event.  */
+  if (!NILP (drag_and_drop_file_list)) 
+    {
+      struct input_event event;
+      Lisp_Object frame;
+      struct frame *f = ((mac_output *) GetWRefCon(window))->mFP;
+      SetPort (GetWindowPort (window));
+      GlobalToLocal (&mouse);
+
+      event.kind = DRAG_N_DROP_EVENT;
+      event.code = 0;
+      event.modifiers = 0;
+      event.timestamp = TickCount () * (1000 / 60);
+      XSETINT (event.x, mouse.h);
+      XSETINT (event.y, mouse.v);
+      XSETFRAME (frame, f);
+      event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
+      event.arg = Qnil;
+      /* Post to the interrupt queue */
+      kbd_buffer_store_event (&event);
+      /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
+      {
+	ProcessSerialNumber psn;
+	GetCurrentProcess (&psn);
+	SetFrontProcess (&psn);
+      }
+    }
+}
+
+
 /* Print Document Apple Event */
 static pascal OSErr
 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
@@ -12334,7 +12557,12 @@
 int
 XTread_socket (int sd, struct input_event *bufp, int numchars, int expected)
 {
-  int count = 0;
+  int count = 0; 
+#if USE_CARBON_EVENTS
+  OSStatus rneResult;
+  EventRef eventRef;
+  EventMouseButton mouseBtn;
+#endif
   EventRecord er;
   int the_modifiers;
   EventMask event_mask;
@@ -12380,7 +12608,52 @@
   if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
     event_mask -= highLevelEventMask;
 
+#if USE_CARBON_EVENTS
+  rneResult = ReceiveNextEvent (0, NULL, 
+				expected ? TicksToEventTime(app_sleep_time) : 0,
+				true, &eventRef);
+  if (!rneResult)
+    {
+      /* Handle new events */
+      if (!mac_convert_event_ref (eventRef, &er)) 
+	switch (GetEventClass (eventRef)) 
+	  {
+	  case kEventClassMouse:
+	    if (GetEventKind (eventRef) == kEventMouseWheelMoved) 
+	      {
+		SInt32 delta;
+		Point point;
+		WindowPtr window_ptr = FrontWindow ();
+		struct mac_output *mwp = (mac_output *) GetWRefCon (window_ptr);
+		GetEventParameter(eventRef, kEventParamMouseWheelDelta,
+				  typeSInt32, NULL, sizeof (SInt32),
+				  NULL, &delta);
+		GetEventParameter(eventRef, kEventParamMouseLocation,
+				  typeQDPoint, NULL, sizeof (Point),
+				  NULL, &point);
+		bufp->kind = MOUSE_WHEEL_EVENT;
+		bufp->code = delta;
+		bufp->modifiers = mac_event_to_emacs_modifiers(eventRef);
+		SetPort (GetWindowPort (window_ptr));
+		GlobalToLocal (&point);
+		XSETINT (bufp->x, point.h);
+		XSETINT (bufp->y, point.v);
+		XSETFRAME (bufp->frame_or_window, mwp->mFP);
+		bufp->timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
+		count++;
+	      }
+	    else
+	      SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+
+	    break;
+	  default:
+	    /* Send the event to the appropriate receiver.  */
+	    SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+	  }
+      else
+#else
   if (WaitNextEvent (event_mask, &er, (expected ? app_sleep_time : 0L), NULL))
+#endif /* USE_CARBON_EVENTS */
     switch (er.what)
       {
       case mouseDown:
@@ -12389,6 +12662,11 @@
 	  WindowPtr window_ptr = FrontWindow ();
 	  SInt16 part_code;
 
+#if USE_CARBON_EVENTS
+	  /* This is needed to correctly */
+	  SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+#endif
+
           if (mouse_tracking_in_progress == mouse_tracking_scroll_bar
 	      && er.what == mouseUp)
             {
@@ -12404,11 +12682,20 @@
 
 	      GlobalToLocal (&mouse_loc);
 		  
+#if USE_CARBON_EVENTS
+	      bufp->code = mac_get_mouse_btn (eventRef);
+#else
 	      bufp->code = 0;  /* only one mouse button */
+#endif
               bufp->kind = SCROLL_BAR_CLICK_EVENT;
               bufp->frame_or_window = tracked_scroll_bar->window;
               bufp->part = scroll_bar_handle;
-              bufp->modifiers = up_modifier;
+#if USE_CARBON_EVENTS
+	      bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+	      bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+              bufp->modifiers |= up_modifier;
 	      bufp->timestamp = er.when * (1000 / 60);
 	        /* ticks to milliseconds */
 
@@ -12461,7 +12748,12 @@
 #else
 		  control_part_code = FindControl (mouse_loc, window_ptr, &ch);
 #endif		  
+
+#if USE_CARBON_EVENTS
+		  bufp->code = mac_get_mouse_btn (eventRef);
+#else		  
 	          bufp->code = 0;  /* only one mouse button */
+#endif
 		  XSETINT (bufp->x, mouse_loc.h);
 		  XSETINT (bufp->y, mouse_loc.v);
 		  bufp->timestamp = er.when * (1000 / 60);
@@ -12501,13 +12793,19 @@
 		        mouse_tracking_in_progress = mouse_tracking_none;
 	            }
 	      	  		
+#if USE_CARBON_EVENTS
+		  bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+		  bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+
 	          switch (er.what)
 		    {
 		    case mouseDown:
-		      bufp->modifiers = down_modifier;
+		      bufp->modifiers |= down_modifier;
 		      break;
 		    case mouseUp:
-		      bufp->modifiers = up_modifier;
+		      bufp->modifiers |= up_modifier;
 		      break;
 		    }
 								
@@ -12559,6 +12857,9 @@
       case updateEvt:
       case osEvt:
       case activateEvt:
+#if USE_CARBON_EVENTS
+	SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+#endif	
     	do_events (&er);
 	break;
 	
@@ -12579,11 +12880,21 @@
 	    {
 	      bufp->code = 0xff00 | xkeysym;
 	      bufp->kind = NON_ASCII_KEYSTROKE_EVENT;
-	    }	      
+	    }	   
+	  else if (!NILP (Vmac_reverse_ctrl_meta) && (er.modifiers & controlKey))
+	    {
+	      /* This is a special case to deal with converting from
+		 a control character to non-control character */
+	      int new_modifiers = er.modifiers & ~controlKey;
+	      int new_keycode = keycode | new_modifiers;	      
+	      Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
+	      unsigned long some_state = 0;
+	      bufp->code = KeyTranslate (kchr_ptr, new_keycode, &some_state) & 0xff;
+	      bufp->kind = ASCII_KEYSTROKE_EVENT;
+	    }
 	  else
 	    {
-	      if (er.modifiers
-		  & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
+	      if (er.modifiers & macMetaKey)
 	        {
 	          /* This code comes from Keyboard Resource, Appendix
 		     C of IM - Text.  This is necessary since shift is
@@ -12597,6 +12908,16 @@
 	          bufp->code = KeyTranslate (kchr_ptr, new_keycode,
 					     &some_state) & 0xff;
 	        }
+#if USE_CARBON_EVENTS
+	      else if (er.modifiers & cmdKey &&
+		       (NILP (Vmac_command_key_is_meta)))
+		{
+		  /* If this is a command key (and we are not overriding it),
+		     send back to the operating system  */
+		  SendEventToEventTarget (eventRef, GetEventDispatcherTarget ());
+		  break;
+		}
+#endif
 	      else
 	        bufp->code = er.message & charCodeMask;
 	      bufp->kind = ASCII_KEYSTROKE_EVENT;
@@ -12654,24 +12975,12 @@
               }
 	  }
 
-	the_modifiers = 0;
-	if (er.modifiers & shiftKey)
-	  the_modifiers |= shift_modifier;
-	if (er.modifiers & controlKey)
-	  the_modifiers |= ctrl_modifier;
-	/* Use option or command key as meta depending on value of
-	   mac-command-key-is-meta.  */
-	if (er.modifiers
-	    & (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
-	  the_modifiers |= meta_modifier;
- 
-	/* If the Mac option key is meta, then make Emacs recognize
-	   the Mac command key as alt.  */
-	if (NILP (Vmac_command_key_is_meta) && (er.modifiers & cmdKey))
-	  the_modifiers |= alt_modifier;
-
-	bufp->modifiers	= the_modifiers;
-				
+#if USE_CARBON_EVENTS
+	bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+	bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
+	
 	{
 	  mac_output *mwp
 	    = (mac_output *) GetWRefCon (FrontNonFloatingWindow ());
@@ -12706,7 +13015,11 @@
             bufp->code = 0;
             bufp->timestamp = er.when * (1000 / 60);
 	      /* ticks to milliseconds */
-            bufp->modifiers = 0;
+#if USE_CARBON_EVENTS
+	    bufp->modifiers = mac_event_to_emacs_modifiers (eventRef);
+#else
+	    bufp->modifiers = mac_to_emacs_modifiers (er.modifiers);
+#endif
 
             XSETINT (bufp->x, 0);
             XSETINT (bufp->y, 0);
@@ -12732,10 +13045,13 @@
             
             count++;
           }
-        
       default:
 	break;
       }
+#if USE_CARBON_EVENTS
+      ReleaseEvent (eventRef);
+    }
+#endif
 
   /* If the focus was just given to an autoraising frame,
      raise it now.  */
@@ -12847,7 +13163,6 @@
     if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
       abort ();
   
-
   SetWRefCon (mwp->mWP, (long) mwp);
     /* so that update events can find this mac_output struct */
   mwp->mFP = fp;  /* point back to emacs frame */
@@ -13183,6 +13498,12 @@
 #if TARGET_API_MAC_CARBON
   init_required_apple_events ();
 
+  init_mac_drag_n_drop ();
+
+#if USE_CARBON_EVENTS
+  init_service_handler ();
+#endif
+
   DisableMenuCommand (NULL, kHICommandQuit);
 #endif
 }
@@ -13253,6 +13574,19 @@
 Otherwise the option key is used.  */);
   Vmac_command_key_is_meta = Qt;
 
+  DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
+    doc: /* Non-nil means that the control and meta keys are reversed.  This is
+	    useful for non-standard keyboard layouts.  */);
+  Vmac_reverse_ctrl_meta = Qnil;
+
+#if USE_CARBON_EVENTS
+  DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
+   doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
+the right click will be mouse-3.
+Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
+  Vmac_wheel_button_is_mouse_2 = Qt;
+#endif
+
   DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
     doc: /* One of the Text Encoding Base constant values defined in the
 Basic Text Constants section of Inside Macintosh - Text Encoding
--- a/src/termhooks.h	Sat Aug 03 20:54:52 2002 +0000
+++ b/src/termhooks.h	Sat Aug 03 22:21:09 2002 +0000
@@ -242,9 +242,9 @@
 				   the mouse click occurred in.
 				   .timestamp gives a timestamp (in
 				   milliseconds) for the click.  */
-#ifdef WINDOWSNT
+#if defined(WINDOWSNT) || defined(MAC_OSX)
   MOUSE_WHEEL_EVENT,		/* A mouse-wheel event is generated 
-				   on WINDOWSNT by a 
+				   on WINDOWSNT or MAC_OSX by a 
 				   wheel on a mouse (e.g., MS Intellimouse).
 				   The event contains a delta that corresponds
 				   to the amount and direction that the wheel
@@ -259,6 +259,8 @@
 				   the wheel event occurred in.
 				   .timestamp gives a timestamp (in
 				   milliseconds) for the wheel event.  */
+#endif
+#ifdef WINDOWSNT
   LANGUAGE_CHANGE_EVENT,	/* A LANGUAGE_CHANGE_EVENT is generated
 				   on WINDOWSNT when the keyboard layout
 				   or input language is changed by the