diff --git a/src/ChangeLog b/src/ChangeLog index fb724fb583f..64dabbbfadb 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,17 @@ +2014-10-25 Jan Djärv + + * nsselect.m: pasteboard_changecount is new. + (ns_store_pb_change_count, ns_get_pb_change_count) + (ns_get_our_change_count_for): New functions. + (ns_string_to_pasteboard_internal): Correct comment. + type => gtype in eassert, Call ns_store_pb_change_count. + (Fns_own_selection_internal): Remove data, use value (Bug#18799). + (Fns_disown_selection_internal, Fns_selection_owner_p): Replace + Vselection_alist check, with change count check. + (Fns_get_selection): Initialize val to Qnil. Only get local + selection if change counts match (Bug#18799). + (nxatoms_of_nsselect): Initialize pasteboard_changecount. + 2014-10-25 Noam Postavsky * src/w32proc.c (create_child): If calling a quoted batch file, diff --git a/src/nsselect.m b/src/nsselect.m index 8a2492127d8..904b3b2e17f 100644 --- a/src/nsselect.m +++ b/src/nsselect.m @@ -45,6 +45,7 @@ Updated by Christian Limpach (chris@nice.ch) NSString *NXSecondaryPboard; +static NSMutableDictionary *pasteboard_changecount; /* ========================================================================== @@ -140,6 +141,29 @@ Updated by Christian Limpach (chris@nice.ch) [pb declareTypes: [NSArray array] owner: nil]; } +static void +ns_store_pb_change_count (id pb) +{ + [pasteboard_changecount + setObject: [NSNumber numberWithLong: [pb changeCount]] + forKey: [pb name]]; +} + +static NSInteger +ns_get_pb_change_count (Lisp_Object selection) +{ + id pb = ns_symbol_to_pb (selection); + return pb != nil ? [pb changeCount] : -1; +} + +static NSInteger +ns_get_our_change_count_for (Lisp_Object selection) +{ + NSNumber *num = [pasteboard_changecount + objectForKey: symbol_to_nsstring (selection)]; + return num != nil ? (NSInteger)[num longValue] : -1; +} + static void ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype) @@ -164,7 +188,7 @@ Updated by Christian Limpach (chris@nice.ch) // FIXME: Why those 2 different code paths? if (gtype == nil) { - // Used for ns-store-selection-internal. + // Used for ns_string_to_pasteboard [pb declareTypes: ns_send_types owner: nil]; tenum = [ns_send_types objectEnumerator]; while ( (type = [tenum nextObject]) ) @@ -173,10 +197,11 @@ Updated by Christian Limpach (chris@nice.ch) else { // Used for ns-own-selection-internal. - eassert (type == NSStringPboardType); + eassert (gtype == NSStringPboardType); [pb setString: nsStr forType: gtype]; } [nsStr release]; + ns_store_pb_change_count (pb); } } @@ -340,7 +365,7 @@ Updated by Christian Limpach (chris@nice.ch) id pb; NSString *type; Lisp_Object successful_p = Qnil, rest; - Lisp_Object target_symbol, data; + Lisp_Object target_symbol; check_window_system (NULL); CHECK_SYMBOL (selection); @@ -363,11 +388,9 @@ Updated by Christian Limpach (chris@nice.ch) /* We only support copy of text. */ type = NSStringPboardType; target_symbol = ns_string_to_symbol (type); - data = ns_get_local_selection (selection, target_symbol); - if (!NILP (data)) + if (STRINGP (value)) { - if (STRINGP (data)) - ns_string_to_pasteboard_internal (pb, data, type); + ns_string_to_pasteboard_internal (pb, value, type); successful_p = Qt; } @@ -391,7 +414,10 @@ Updated by Christian Limpach (chris@nice.ch) id pb; check_window_system (NULL); CHECK_SYMBOL (selection); - if (NILP (assq_no_quit (selection, Vselection_alist))) return Qnil; + + if (ns_get_pb_change_count (selection) + != ns_get_our_change_count_for (selection)) + return Qnil; pb = ns_symbol_to_pb (selection); if (pb != nil) ns_undeclare_pasteboard (pb); @@ -450,7 +476,8 @@ Updated by Christian Limpach (chris@nice.ch) CHECK_SYMBOL (selection); if (EQ (selection, Qnil)) selection = QPRIMARY; if (EQ (selection, Qt)) selection = QSECONDARY; - return (NILP (Fassq (selection, Vselection_alist))) ? Qnil : Qt; + return ns_get_pb_change_count (selection) + == ns_get_our_change_count_for (selection); } @@ -472,12 +499,15 @@ Updated by Christian Limpach (chris@nice.ch) (Lisp_Object selection_name, Lisp_Object target_type, Lisp_Object time_stamp, Lisp_Object terminal) { - Lisp_Object val; + Lisp_Object val = Qnil; check_window_system (NULL); CHECK_SYMBOL (selection_name); CHECK_SYMBOL (target_type); - val = ns_get_local_selection (selection_name, target_type); + + if (ns_get_pb_change_count (selection_name) + == ns_get_our_change_count_for (selection_name)) + val = ns_get_local_selection (selection_name, target_type); if (NILP (val)) val = ns_get_foreign_selection (selection_name, target_type); if (CONSP (val) && SYMBOLP (Fcar (val))) @@ -496,6 +526,18 @@ Updated by Christian Limpach (chris@nice.ch) { NXPrimaryPboard = @"Selection"; NXSecondaryPboard = @"Secondary"; + + // This is a memory loss, never released. + pasteboard_changecount = + [[NSMutableDictionary + dictionaryWithObjectsAndKeys: + [NSNumber numberWithLong:0], NSGeneralPboard, + [NSNumber numberWithLong:0], NXPrimaryPboard, + [NSNumber numberWithLong:0], NXSecondaryPboard, + [NSNumber numberWithLong:0], NSStringPboardType, + [NSNumber numberWithLong:0], NSFilenamesPboardType, + [NSNumber numberWithLong:0], NSTabularTextPboardType, + nil] retain]; } void