changeset 80391:1d3df1b9547b

[!TARGET_API_MAC_CARBON] Include Scrap.h. [MAC_OSX] (install_service_handler): Rename from init_service_handler. All callers changed. Return OSStatus value. (Selection): New typedef. Use instead of ScrapRef. (mac_get_selection_from_symbol): Rename from get_scrap_from_symbol. (mac_valid_selection_target_p): Rename from valid_scrap_target_type_p. (mac_clear_selection): Rename from clear_scrap. (get_flavor_type_from_symbol): New argument SEL and subsume function of scrap_has_target_type. All uses changed. (mac_get_selection_ownership_info, mac_valid_selection_value_p) (mac_selection_has_target_p): New functions. (mac_put_selection_value): Rename from put_scrap_string. (mac_get_selection_value): Rename from get_scrap_string. (mac_get_selection_target_list): Rename from get_scrap_target_type_list. (put_scrap_private_timestamp, scrap_has_target_type) (get_scrap_private_timestamp): Remove functions. (SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP): Remove define. (x_own_selection, x_get_local_selection): Use mac_valid_selection_value_p. (x_own_selection): Don't use put_scrap_private_timestamp. Record OWNERSHIP-INFO into Vselection_alist instead. (x_get_local_selection): Don't check type if request is local. (Fx_selection_owner_p): Don't use get_scrap_private_timestamp. Detect ownership change with OWNERSHIP-INFO in Vselection_alist instead.
author YAMAMOTO Mitsuharu <mituharu@math.s.chiba-u.ac.jp>
date Sat, 29 Mar 2008 00:46:38 +0000
parents 59863894d837
children 80c2bc6163c3
files src/macselect.c
diffstat 1 files changed, 221 insertions(+), 240 deletions(-) [+]
line wrap: on
line diff
--- a/src/macselect.c	Sat Mar 29 00:46:21 2008 +0000
+++ b/src/macselect.c	Sat Mar 29 00:46:38 2008 +0000
@@ -25,22 +25,27 @@
 #include "blockinput.h"
 #include "keymap.h"
 
-#if !TARGET_API_MAC_CARBON
+#if TARGET_API_MAC_CARBON
+typedef ScrapRef Selection;
+#else  /* !TARGET_API_MAC_CARBON */
+#include <Scrap.h>
 #include <Endian.h>
-typedef int ScrapRef;
-typedef ResType ScrapFlavorType;
+typedef int Selection;
 #endif /* !TARGET_API_MAC_CARBON */
 
-static OSStatus get_scrap_from_symbol P_ ((Lisp_Object, int, ScrapRef *));
-static ScrapFlavorType get_flavor_type_from_symbol P_ ((Lisp_Object));
-static int valid_scrap_target_type_p P_ ((Lisp_Object));
-static OSStatus clear_scrap P_ ((ScrapRef *));
-static OSStatus put_scrap_string P_ ((ScrapRef, Lisp_Object, Lisp_Object));
-static OSStatus put_scrap_private_timestamp P_ ((ScrapRef, unsigned long));
-static ScrapFlavorType scrap_has_target_type P_ ((ScrapRef, Lisp_Object));
-static Lisp_Object get_scrap_string P_ ((ScrapRef, Lisp_Object));
-static OSStatus get_scrap_private_timestamp P_ ((ScrapRef, unsigned long *));
-static Lisp_Object get_scrap_target_type_list P_ ((ScrapRef));
+static OSStatus mac_get_selection_from_symbol P_ ((Lisp_Object, int,
+						   Selection *));
+static ScrapFlavorType get_flavor_type_from_symbol P_ ((Lisp_Object,
+							Selection));
+static int mac_valid_selection_target_p P_ ((Lisp_Object));
+static OSStatus mac_clear_selection P_ ((Selection *));
+static Lisp_Object mac_get_selection_ownership_info P_ ((Selection));
+static int mac_valid_selection_value_p P_ ((Lisp_Object, Lisp_Object));
+static OSStatus mac_put_selection_value P_ ((Selection, Lisp_Object,
+					     Lisp_Object));
+static int mac_selection_has_target_p P_ ((Selection, Lisp_Object));
+static Lisp_Object mac_get_selection_value P_ ((Selection, Lisp_Object));
+static Lisp_Object mac_get_selection_target_list P_ ((Selection));
 static void x_own_selection P_ ((Lisp_Object, Lisp_Object));
 static Lisp_Object x_get_local_selection P_ ((Lisp_Object, Lisp_Object, int));
 static Lisp_Object x_get_foreign_selection P_ ((Lisp_Object,
@@ -56,7 +61,7 @@
 Lisp_Object QPRIMARY, QSECONDARY, QTIMESTAMP, QTARGETS;
 
 static Lisp_Object Vx_lost_selection_functions;
-/* Coding system for communicating with other programs via scrap.  */
+/* Coding system for communicating with other programs via selections.  */
 static Lisp_Object Vselection_coding_system;
 
 /* Coding system for the next communicating with other programs.  */
@@ -70,23 +75,24 @@
 extern unsigned long last_event_timestamp;
 
 /* This is an association list whose elements are of the form
-     ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME)
+     ( SELECTION-NAME SELECTION-VALUE SELECTION-TIMESTAMP FRAME OWNERSHIP-INFO)
    SELECTION-NAME is a lisp symbol.
    SELECTION-VALUE is the value that emacs owns for that selection.
      It may be any kind of Lisp object.
    SELECTION-TIMESTAMP is the time at which emacs began owning this selection,
      as a cons of two 16-bit numbers (making a 32 bit time.)
    FRAME is the frame for which we made the selection.
-   If there is an entry in this alist, and the data for the flavor
-     type SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP in the corresponding scrap
-     (if exists) coincides with SELECTION-TIMESTAMP, then it can be
-     assumed that Emacs owns that selection.
+   OWNERSHIP-INFO is a value saved when emacs owns for that selection.
+     If another application takes the ownership of that selection
+     later, then newly examined ownership info value should be
+     different from the saved one.
+   If there is an entry in this alist, the current ownership info for
+    the selection coincides with OWNERSHIP-INFO, then it can be
+    assumed that Emacs owns that selection.
    The only (eq) parts of this list that are visible from Lisp are the
     selection-values.  */
 static Lisp_Object Vselection_alist;
 
-#define SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP 'Etsp'
-
 /* This is an alist whose CARs are selection-types and whose CDRs are
    the names of Lisp functions to call to convert the given Emacs
    selection value to a string representing the given selection type.
@@ -104,21 +110,22 @@
 static Lisp_Object Vmac_service_selection;
 #endif
 
-/* Get a reference to the scrap corresponding to the symbol SYM.  The
-   reference is set to *SCRAP, and it becomes NULL if there's no
-   corresponding scrap.  Clear the scrap if CLEAR_P is non-zero.  */
+/* Get a reference to the selection corresponding to the symbol SYM.
+   The reference is set to *SEL, and it becomes NULL if there's no
+   corresponding selection.  Clear the selection if CLEAR_P is
+   non-zero.  */
 
 static OSStatus
-get_scrap_from_symbol (sym, clear_p, scrap)
+mac_get_selection_from_symbol (sym, clear_p, sel)
      Lisp_Object sym;
      int clear_p;
-     ScrapRef *scrap;
+     Selection *sel;
 {
   OSStatus err = noErr;
   Lisp_Object str = Fget (sym, Qmac_scrap_name);
 
   if (!STRINGP (str))
-    *scrap = NULL;
+    *sel = NULL;
   else
     {
 #if TARGET_API_MAC_CARBON
@@ -127,19 +134,19 @@
       OptionBits options = (clear_p ? kScrapClearNamedScrap
 			    : kScrapGetNamedScrap);
 
-      err = GetScrapByName (scrap_name, options, scrap);
+      err = GetScrapByName (scrap_name, options, sel);
       CFRelease (scrap_name);
 #else	/* !MAC_OSX */
       if (clear_p)
 	err = ClearCurrentScrap ();
       if (err == noErr)
-	err = GetCurrentScrap (scrap);
+	err = GetCurrentScrap (sel);
 #endif	/* !MAC_OSX */
 #else	/* !TARGET_API_MAC_CARBON */
       if (clear_p)
 	err = ZeroScrap ();
       if (err == noErr)
-	*scrap = 1;
+	*sel = 1;
 #endif	/* !TARGET_API_MAC_CARBON */
     }
 
@@ -147,101 +154,29 @@
 }
 
 /* Get a scrap flavor type from the symbol SYM.  Return 0 if no
-   corresponding flavor type.  */
+   corresponding flavor type.  If SEL is non-zero, the return value is
+   non-zero only when the SEL has the flavor type.  */
 
 static ScrapFlavorType
-get_flavor_type_from_symbol (sym)
+get_flavor_type_from_symbol (sym, sel)
      Lisp_Object sym;
+     Selection sel;
 {
   Lisp_Object str = Fget (sym, Qmac_ostype);
+  ScrapFlavorType flavor_type;
 
   if (STRINGP (str) && SBYTES (str) == 4)
-    return EndianU32_BtoN (*((UInt32 *) SDATA (str)));
-
-  return 0;
-}
-
-/* Check if the symbol SYM has a corresponding scrap flavor type.  */
-
-static int
-valid_scrap_target_type_p (sym)
-     Lisp_Object sym;
-{
-  return get_flavor_type_from_symbol (sym) != 0;
-}
-
-/* Clear the scrap whose reference is *SCRAP. */
-
-static INLINE OSStatus
-clear_scrap (scrap)
-     ScrapRef *scrap;
-{
-#if TARGET_API_MAC_CARBON
-#ifdef MAC_OSX
-  return ClearScrap (scrap);
-#else
-  return ClearCurrentScrap ();
-#endif
-#else  /* !TARGET_API_MAC_CARBON */
-  return ZeroScrap ();
-#endif	/* !TARGET_API_MAC_CARBON */
-}
-
-/* Put Lisp String STR to the scrap SCRAP.  The target type is
-   specified by TYPE. */
-
-static OSStatus
-put_scrap_string (scrap, type, str)
-     ScrapRef scrap;
-     Lisp_Object type, str;
-{
-  ScrapFlavorType flavor_type = get_flavor_type_from_symbol (type);
+    flavor_type = EndianU32_BtoN (*((UInt32 *) SDATA (str)));
+  else
+    flavor_type = 0;
 
-  if (flavor_type == 0)
-    return noTypeErr;
-
-#if TARGET_API_MAC_CARBON
-  return PutScrapFlavor (scrap, flavor_type, kScrapFlavorMaskNone,
-			 SBYTES (str), SDATA (str));
-#else  /* !TARGET_API_MAC_CARBON */
-  return PutScrap (SBYTES (str), flavor_type, SDATA (str));
-#endif	/* !TARGET_API_MAC_CARBON */
-}
-
-/* Put TIMESTAMP to the scrap SCRAP.  The timestamp is used for
-   checking if the scrap is owned by the process.  */
-
-static INLINE OSStatus
-put_scrap_private_timestamp (scrap, timestamp)
-     ScrapRef scrap;
-     unsigned long timestamp;
-{
-#if TARGET_API_MAC_CARBON
-  return PutScrapFlavor (scrap, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP,
-			 kScrapFlavorMaskSenderOnly,
-			 sizeof (timestamp), &timestamp);
-#else  /* !TARGET_API_MAC_CARBON */
-  return PutScrap (sizeof (timestamp), SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP,
-		   &timestamp);
-#endif	/* !TARGET_API_MAC_CARBON */
-}
-
-/* Check if data for the target type TYPE is available in SCRAP.  */
-
-static ScrapFlavorType
-scrap_has_target_type (scrap, type)
-     ScrapRef scrap;
-     Lisp_Object type;
-{
-  OSStatus err;
-  ScrapFlavorType flavor_type = get_flavor_type_from_symbol (type);
-
-  if (flavor_type)
+  if (flavor_type && sel)
     {
 #if TARGET_API_MAC_CARBON
+      OSStatus err;
       ScrapFlavorFlags flags;
 
-      err = GetScrapFlavorFlags (scrap, flavor_type, &flags);
+      err = GetScrapFlavorFlags (sel, flavor_type, &flags);
       if (err != noErr)
 	flavor_type = 0;
 #else  /* !TARGET_API_MAC_CARBON */
@@ -256,29 +191,117 @@
   return flavor_type;
 }
 
-/* Get data for the target type TYPE from SCRAP and create a Lisp
+/* Check if the symbol SYM has a corresponding selection target type.  */
+
+static int
+mac_valid_selection_target_p (sym)
+     Lisp_Object sym;
+{
+  return get_flavor_type_from_symbol (sym, 0) != 0;
+}
+
+/* Clear the selection whose reference is *SEL.  */
+
+static OSStatus
+mac_clear_selection (sel)
+     Selection *sel;
+{
+#if TARGET_API_MAC_CARBON
+#ifdef MAC_OSX
+  return ClearScrap (sel);
+#else
+  OSStatus err;
+
+  err = ClearCurrentScrap ();
+  if (err == noErr)
+    err = GetCurrentScrap (sel);
+  return err;
+#endif
+#else  /* !TARGET_API_MAC_CARBON */
+  return ZeroScrap ();
+#endif	/* !TARGET_API_MAC_CARBON */
+}
+
+/* Get ownership information for SEL.  Emacs can detect a change of
+   the ownership by comparing saved and current values of the
+   ownership information.  */
+
+static Lisp_Object
+mac_get_selection_ownership_info (sel)
+     Selection sel;
+{
+#if TARGET_API_MAC_CARBON
+  return long_to_cons ((unsigned long) sel);
+#else  /* !TARGET_API_MAC_CARBON */
+  ScrapStuffPtr scrap_info = InfoScrap ();
+
+  return make_number (scrap_info->scrapCount);
+#endif	/* !TARGET_API_MAC_CARBON */
+}
+
+/* Return non-zero if VALUE is a valid selection value for TARGET.  */
+
+static int
+mac_valid_selection_value_p (value, target)
+     Lisp_Object value, target;
+{
+  return STRINGP (value);
+}
+
+/* Put Lisp Object VALUE to the selection SEL.  The target type is
+   specified by TARGET. */
+
+static OSStatus
+mac_put_selection_value (sel, target, value)
+     Selection sel;
+     Lisp_Object target, value;
+{
+  ScrapFlavorType flavor_type = get_flavor_type_from_symbol (target, 0);
+
+  if (flavor_type == 0 || !STRINGP (value))
+    return noTypeErr;
+
+#if TARGET_API_MAC_CARBON
+  return PutScrapFlavor (sel, flavor_type, kScrapFlavorMaskNone,
+			 SBYTES (value), SDATA (value));
+#else  /* !TARGET_API_MAC_CARBON */
+  return PutScrap (SBYTES (value), flavor_type, SDATA (value));
+#endif	/* !TARGET_API_MAC_CARBON */
+}
+
+/* Check if data for the target type TARGET is available in SEL.  */
+
+static int
+mac_selection_has_target_p (sel, target)
+     Selection sel;
+     Lisp_Object target;
+{
+  return get_flavor_type_from_symbol (target, sel) != 0;
+}
+
+/* Get data for the target type TARGET from SEL and create a Lisp
    string.  Return nil if failed to get data.  */
 
 static Lisp_Object
-get_scrap_string (scrap, type)
-     ScrapRef scrap;
-     Lisp_Object type;
+mac_get_selection_value (sel, target)
+     Selection sel;
+     Lisp_Object target;
 {
   OSStatus err;
   Lisp_Object result = Qnil;
-  ScrapFlavorType flavor_type = get_flavor_type_from_symbol (type);
+  ScrapFlavorType flavor_type = get_flavor_type_from_symbol (target, sel);
 #if TARGET_API_MAC_CARBON
   Size size;
 
   if (flavor_type)
     {
-      err = GetScrapFlavorSize (scrap, flavor_type, &size);
+      err = GetScrapFlavorSize (sel, flavor_type, &size);
       if (err == noErr)
 	{
 	  do
 	    {
 	      result = make_uninit_string (size);
-	      err = GetScrapFlavorData (scrap, flavor_type,
+	      err = GetScrapFlavorData (sel, flavor_type,
 					&size, SDATA (result));
 	      if (err != noErr)
 		result = Qnil;
@@ -308,72 +331,25 @@
   return result;
 }
 
-/* Get timestamp from the scrap SCRAP and set to *TIMPSTAMP.  */
-
-static OSStatus
-get_scrap_private_timestamp (scrap, timestamp)
-     ScrapRef scrap;
-     unsigned long *timestamp;
-{
-  OSStatus err = noErr;
-#if TARGET_API_MAC_CARBON
-  ScrapFlavorFlags flags;
-
-  err = GetScrapFlavorFlags (scrap, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP, &flags);
-  if (err == noErr)
-    {
-      if (!(flags & kScrapFlavorMaskSenderOnly))
-	err = noTypeErr;
-      else
-	{
-	  Size size = sizeof (*timestamp);
-
-	  err = GetScrapFlavorData (scrap, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP,
-				    &size, timestamp);
-	  if (err == noErr && size != sizeof (*timestamp))
-	    err = noTypeErr;
-	}
-    }
-#else  /* !TARGET_API_MAC_CARBON */
-  Handle handle;
-  SInt32 size, offset;
-
-  size = GetScrap (NULL, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP, &offset);
-  if (size == sizeof (*timestamp))
-    {
-      handle = NewHandle (size);
-      HLock (handle);
-      size = GetScrap (handle, SCRAP_FLAVOR_TYPE_EMACS_TIMESTAMP, &offset);
-      if (size == sizeof (*timestamp))
-	*timestamp = *((unsigned long *) *handle);
-      DisposeHandle (handle);
-    }
-  if (size != sizeof (*timestamp))
-    err = noTypeErr;
-#endif	/* !TARGET_API_MAC_CARBON */
-
-  return err;
-}
-
-/* Get the list of target types in SCRAP.  The return value is a list
-   of target type symbols possibly followed by scrap flavor type
+/* Get the list of target types in SEL.  The return value is a list of
+   target type symbols possibly followed by scrap flavor type
    strings.  */
 
 static Lisp_Object
-get_scrap_target_type_list (scrap)
-     ScrapRef scrap;
+mac_get_selection_target_list (sel)
+     Selection sel;
 {
-  Lisp_Object result = Qnil, rest, target_type;
+  Lisp_Object result = Qnil, rest, target;
 #if TARGET_API_MAC_CARBON
   OSStatus err;
   UInt32 count, i, type;
   ScrapFlavorInfo *flavor_info = NULL;
   Lisp_Object strings = Qnil;
 
-  err = GetScrapFlavorCount (scrap, &count);
+  err = GetScrapFlavorCount (sel, &count);
   if (err == noErr)
     flavor_info = xmalloc (sizeof (ScrapFlavorInfo) * count);
-  err = GetScrapFlavorInfoList (scrap, &count, flavor_info);
+  err = GetScrapFlavorInfoList (sel, &count, flavor_info);
   if (err != noErr)
     {
       xfree (flavor_info);
@@ -387,11 +363,11 @@
       ScrapFlavorType flavor_type = 0;
 
       if (CONSP (XCAR (rest))
-	  && (target_type = XCAR (XCAR (rest)),
-	      SYMBOLP (target_type))
-	  && (flavor_type = scrap_has_target_type (scrap, target_type)))
+	  && (target = XCAR (XCAR (rest)),
+	      SYMBOLP (target))
+	  && (flavor_type = get_flavor_type_from_symbol (target, sel)))
 	{
-	  result = Fcons (target_type, result);
+	  result = Fcons (target, result);
 #if TARGET_API_MAC_CARBON
 	  for (i = 0; i < count; i++)
 	    if (flavor_info[i].flavorType == flavor_type)
@@ -428,9 +404,9 @@
      Lisp_Object selection_name, selection_value;
 {
   OSStatus err;
-  ScrapRef scrap;
+  Selection sel;
   struct gcpro gcpro1, gcpro2;
-  Lisp_Object rest, handler_fn, value, type;
+  Lisp_Object rest, handler_fn, value, target_type;
   int count;
 
   CHECK_SYMBOL (selection_name);
@@ -439,8 +415,8 @@
 
   BLOCK_INPUT;
 
-  err = get_scrap_from_symbol (selection_name, 1, &scrap);
-  if (err == noErr && scrap)
+  err = mac_get_selection_from_symbol (selection_name, 1, &sel);
+  if (err == noErr && sel)
     {
       /* Don't allow a quit within the converter.
 	 When the user types C-g, he would be surprised
@@ -451,49 +427,60 @@
       for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest))
 	{
 	  if (!(CONSP (XCAR (rest))
-		&& (type = XCAR (XCAR (rest)),
-		    SYMBOLP (type))
-		&& valid_scrap_target_type_p (type)
+		&& (target_type = XCAR (XCAR (rest)),
+		    SYMBOLP (target_type))
+		&& mac_valid_selection_target_p (target_type)
 		&& (handler_fn = XCDR (XCAR (rest)),
 		    SYMBOLP (handler_fn))))
 	    continue;
 
 	  if (!NILP (handler_fn))
 	    value = call3 (handler_fn, selection_name,
-			   type, selection_value);
+			   target_type, selection_value);
+
+	  if (NILP (value))
+	    continue;
 
-	  if (STRINGP (value))
-	    err = put_scrap_string (scrap, type, value);
+	  if (mac_valid_selection_value_p (value, target_type))
+	    err = mac_put_selection_value (sel, target_type, value);
 	  else if (CONSP (value)
-		   && EQ (XCAR (value), type)
-		   && STRINGP (XCDR (value)))
-	    err = put_scrap_string (scrap, type, XCDR (value));
+		   && EQ (XCAR (value), target_type)
+		   && mac_valid_selection_value_p (XCDR (value), target_type))
+	    err = mac_put_selection_value (sel, target_type, XCDR (value));
 	}
 
       unbind_to (count, Qnil);
-
-      if (err == noErr)
-	err = put_scrap_private_timestamp (scrap, last_event_timestamp);
     }
 
   UNBLOCK_INPUT;
 
   UNGCPRO;
 
-  if (scrap && err != noErr)
+  if (sel && err != noErr)
     error ("Can't set selection");
 
   /* Now update the local cache */
   {
     Lisp_Object selection_time;
     Lisp_Object selection_data;
+    Lisp_Object ownership_info;
     Lisp_Object prev_value;
 
     selection_time = long_to_cons (last_event_timestamp);
+    if (sel)
+      {
+	BLOCK_INPUT;
+	ownership_info = mac_get_selection_ownership_info (sel);
+	UNBLOCK_INPUT;
+      }
+    else
+      ownership_info = Qnil; 	/* dummy value for local-only selection */
     selection_data = Fcons (selection_name,
 			    Fcons (selection_value,
 				   Fcons (selection_time,
-					  Fcons (selected_frame, Qnil))));
+					  Fcons (selected_frame,
+						 Fcons (ownership_info,
+							Qnil)))));
     prev_value = assq_no_quit (selection_name, Vselection_alist);
 
     Vselection_alist = Fcons (selection_data, Vselection_alist);
@@ -574,29 +561,20 @@
       unbind_to (count, Qnil);
     }
 
+  if (local_request)
+    return value;
+
   /* Make sure this value is of a type that we could transmit
-     to another X client.  */
+     to another application.  */
 
+  type = target_type;
   check = value;
   if (CONSP (value)
       && SYMBOLP (XCAR (value)))
     type = XCAR (value),
     check = XCDR (value);
 
-  if (STRINGP (check)
-      || VECTORP (check)
-      || SYMBOLP (check)
-      || INTEGERP (check)
-      || NILP (value))
-    return value;
-  /* Check for a value that cons_to_long could handle.  */
-  else if (CONSP (check)
-	   && INTEGERP (XCAR (check))
-	   && (INTEGERP (XCDR (check))
-	       ||
-	       (CONSP (XCDR (check))
-		&& INTEGERP (XCAR (XCDR (check)))
-		&& NILP (XCDR (XCDR (check))))))
+  if (NILP (value) || mac_valid_selection_value_p (check, type))
     return value;
 
   signal_error ("Invalid data returned by selection-conversion function",
@@ -676,22 +654,22 @@
      Lisp_Object selection_symbol, target_type, time_stamp;
 {
   OSStatus err;
-  ScrapRef scrap;
+  Selection sel;
   Lisp_Object result = Qnil;
 
   BLOCK_INPUT;
 
-  err = get_scrap_from_symbol (selection_symbol, 0, &scrap);
-  if (err == noErr && scrap)
+  err = mac_get_selection_from_symbol (selection_symbol, 0, &sel);
+  if (err == noErr && sel)
     {
       if (EQ (target_type, QTARGETS))
 	{
-	  result = get_scrap_target_type_list (scrap);
+	  result = mac_get_selection_target_list (sel);
 	  result = Fvconcat (1, &result);
 	}
       else
 	{
-	  result = get_scrap_string (scrap, target_type);
+	  result = mac_get_selection_value (sel, target_type);
 	  if (STRINGP (result))
 	    Fput_text_property (make_number (0), make_number (SBYTES (result)),
 				Qforeign_selection, target_type, result);
@@ -770,7 +748,7 @@
      Lisp_Object time;
 {
   OSStatus err;
-  ScrapRef scrap;
+  Selection sel;
   Lisp_Object local_selection_data;
 
   check_mac ();
@@ -812,9 +790,9 @@
 
   BLOCK_INPUT;
 
-  err = get_scrap_from_symbol (selection, 0, &scrap);
-  if (err == noErr && scrap)
-    clear_scrap (&scrap);
+  err = mac_get_selection_from_symbol (selection, 0, &sel);
+  if (err == noErr && sel)
+    mac_clear_selection (&sel);
 
   UNBLOCK_INPUT;
 
@@ -833,7 +811,7 @@
      Lisp_Object selection;
 {
   OSStatus err;
-  ScrapRef scrap;
+  Selection sel;
   Lisp_Object result = Qnil, local_selection_data;
 
   check_mac ();
@@ -848,15 +826,14 @@
 
   BLOCK_INPUT;
 
-  err = get_scrap_from_symbol (selection, 0, &scrap);
-  if (err == noErr && scrap)
+  err = mac_get_selection_from_symbol (selection, 0, &sel);
+  if (err == noErr && sel)
     {
-      unsigned long timestamp;
+      Lisp_Object ownership_info;
 
-      err = get_scrap_private_timestamp (scrap, &timestamp);
-      if (err == noErr
-	  && (timestamp
-	      == cons_to_long (XCAR (XCDR (XCDR (local_selection_data))))))
+      ownership_info = XCAR (XCDR (XCDR (XCDR (XCDR (local_selection_data)))));
+      if (!NILP (Fequal (ownership_info,
+			 mac_get_selection_ownership_info (sel))))
 	result = Qt;
     }
   else
@@ -878,7 +855,7 @@
      Lisp_Object selection;
 {
   OSStatus err;
-  ScrapRef scrap;
+  Selection sel;
   Lisp_Object result = Qnil, rest;
 
   /* It should be safe to call this before we have an Mac frame.  */
@@ -893,12 +870,12 @@
 
   BLOCK_INPUT;
 
-  err = get_scrap_from_symbol (selection, 0, &scrap);
-  if (err == noErr && scrap)
+  err = mac_get_selection_from_symbol (selection, 0, &sel);
+  if (err == noErr && sel)
     for (rest = Vselection_converter_alist; CONSP (rest); rest = XCDR (rest))
       {
 	if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
-	    && scrap_has_target_type (scrap, XCAR (XCAR (rest))))
+	    && mac_selection_has_target_p (sel, XCAR (XCAR (rest))))
 	  {
 	    result = Qt;
 	    break;
@@ -1623,16 +1600,19 @@
 			Services menu support
 ***********************************************************************/
 #ifdef MAC_OSX
-void
-init_service_handler ()
+OSStatus
+install_service_handler ()
 {
   static const EventTypeSpec specs[] =
     {{kEventClassService, kEventServiceGetTypes},
      {kEventClassService, kEventServiceCopy},
      {kEventClassService, kEventServicePaste},
      {kEventClassService, kEventServicePerform}};
-  InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
-				  GetEventTypeCount (specs), specs, NULL, NULL);
+
+  return InstallApplicationEventHandler (NewEventHandlerUPP
+					 (mac_handle_service_event),
+					 GetEventTypeCount (specs),
+					 specs, NULL, NULL);
 }
 
 extern OSStatus mac_store_service_event P_ ((EventRef));
@@ -1697,7 +1677,7 @@
   if (!SYMBOLP (Vmac_service_selection))
     err = eventNotHandledErr;
   else
-    err = get_scrap_from_symbol (Vmac_service_selection, 0, &cur_scrap);
+    err = mac_get_selection_from_symbol (Vmac_service_selection, 0, &cur_scrap);
   if (!(err == noErr && cur_scrap))
     return eventNotHandledErr;
 
@@ -1716,7 +1696,7 @@
 	   rest = XCDR (rest))
 	if (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))
 	    && (flavor_type =
-		get_flavor_type_from_symbol (XCAR (XCAR (rest)))))
+		get_flavor_type_from_symbol (XCAR (XCAR (rest)), 0)))
 	  {
 	    type = CreateTypeStringWithOSType (flavor_type);
 	    if (type)
@@ -1801,14 +1781,15 @@
 				 NULL, sizeof (ScrapRef), NULL,
 				 &specific_scrap);
 	if (err == noErr)
-	  err = clear_scrap (&cur_scrap);
+	  err = mac_clear_selection (&cur_scrap);
 	if (err == noErr)
 	  for (rest = Vselection_converter_alist; CONSP (rest);
 	       rest = XCDR (rest))
 	    {
 	      if (! (CONSP (XCAR (rest)) && SYMBOLP (XCAR (XCAR (rest)))))
 		continue;
-	      flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest)));
+	      flavor_type = get_flavor_type_from_symbol (XCAR (XCAR (rest)),
+							 specific_scrap);
 	      if (flavor_type == 0)
 		continue;
 	      err = copy_scrap_flavor_data (specific_scrap, cur_scrap,