/* Unix emulation routines for GNU Emacs on the Mac OS.
- Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
+ 2008 Free Software Foundation, Inc.
This file is part of GNU Emacs.
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* Contributed by Andrew Choi (akochoi@mac.com). */
/* The single script context used for all script executions. */
static OSAID as_script_context;
-#ifndef MAC_OS_X
+#ifndef MAC_OSX
#if TARGET_API_MAC_CARBON
static int wakeup_from_rne_enabled_p = 0;
#define ENABLE_WAKEUP_FROM_RNE (wakeup_from_rne_enabled_p = 1)
}
#if TARGET_API_MAC_CARBON
-static OSErr
+OSErr
create_apple_event (class, id, result)
AEEventClass class;
AEEventID id;
return err;
}
-OSStatus
-create_apple_event_from_event_ref (event, num_params, names, types, result)
+Lisp_Object
+mac_event_parameters_to_lisp (event, num_params, names, types)
EventRef event;
UInt32 num_params;
const EventParamName *names;
const EventParamType *types;
- AppleEvent *result;
{
OSStatus err;
- UInt32 i, size;
+ Lisp_Object result = Qnil;
+ UInt32 i;
+ ByteCount size;
+#ifdef MAC_OSX
CFStringRef string;
CFDataRef data;
- char *buf = NULL;
-
- err = create_apple_event (0, 0, result); /* Dummy class and ID. */
- if (err != noErr)
- return err;
-
- for (i = 0; i < num_params; i++)
- switch (types[i])
- {
-#ifdef MAC_OSX
- case typeCFStringRef:
- err = GetEventParameter (event, names[i], typeCFStringRef, NULL,
- sizeof (CFStringRef), NULL, &string);
- if (err != noErr)
- break;
- data = CFStringCreateExternalRepresentation (NULL, string,
- kCFStringEncodingUTF8,
- '?');
- if (data == NULL)
- break;
- AEPutParamPtr (result, names[i], typeUTF8Text,
- CFDataGetBytePtr (data), CFDataGetLength (data));
- CFRelease (data);
- break;
#endif
-
- default:
- err = GetEventParameter (event, names[i], types[i], NULL,
- 0, &size, NULL);
- if (err != noErr)
- break;
- buf = xrealloc (buf, size);
- err = GetEventParameter (event, names[i], types[i], NULL,
- size, NULL, buf);
- if (err == noErr)
- AEPutParamPtr (result, names[i], types[i], buf, size);
- break;
- }
- if (buf)
- xfree (buf);
-
- return noErr;
-}
-
-OSErr
-create_apple_event_from_drag_ref (drag, num_types, types, result)
- DragRef drag;
- UInt32 num_types;
- const FlavorType *types;
- AppleEvent *result;
-{
- OSErr err;
- UInt16 num_items;
- AppleEvent items;
- long index;
char *buf = NULL;
- err = CountDragItems (drag, &num_items);
- if (err != noErr)
- return err;
- err = AECreateList (NULL, 0, false, &items);
- if (err != noErr)
- return err;
-
- for (index = 1; index <= num_items; index++)
+ for (i = 0; i < num_params; i++)
{
- ItemReference item;
- DescType desc_type = typeNull;
- Size size;
+ EventParamName name = names[i];
+ EventParamType type = types[i];
- err = GetDragItemReferenceNumber (drag, index, &item);
- if (err == noErr)
+ switch (type)
{
- int i;
+#ifdef MAC_OSX
+ case typeCFStringRef:
+ err = GetEventParameter (event, name, typeCFStringRef, NULL,
+ sizeof (CFStringRef), NULL, &string);
+ if (err != noErr)
+ break;
+ data = CFStringCreateExternalRepresentation (NULL, string,
+ kCFStringEncodingUTF8,
+ '?');
+ if (data == NULL)
+ break;
+ name = EndianU32_NtoB (name);
+ type = EndianU32_NtoB (typeUTF8Text);
+ result =
+ Fcons (Fcons (make_unibyte_string ((char *) &name, 4),
+ Fcons (make_unibyte_string ((char *) &type, 4),
+ make_unibyte_string (CFDataGetBytePtr (data),
+ CFDataGetLength (data)))),
+ result);
+ CFRelease (data);
+ break;
+#endif
- for (i = 0; i < num_types; i++)
+ default:
+ err = GetEventParameter (event, name, type, NULL, 0, &size, NULL);
+ if (err != noErr)
+ break;
+ buf = xrealloc (buf, size);
+ err = GetEventParameter (event, name, type, NULL, size, NULL, buf);
+ if (err == noErr)
{
- err = GetFlavorDataSize (drag, item, types[i], &size);
- if (err == noErr)
- {
- buf = xrealloc (buf, size);
- err = GetFlavorData (drag, item, types[i], buf, &size, 0);
- }
- if (err == noErr)
- {
- desc_type = types[i];
- break;
- }
+ name = EndianU32_NtoB (name);
+ type = EndianU32_NtoB (type);
+ result =
+ Fcons (Fcons (make_unibyte_string ((char *) &name, 4),
+ Fcons (make_unibyte_string ((char *) &type, 4),
+ make_unibyte_string (buf, size))),
+ result);
}
+ break;
}
- err = AEPutPtr (&items, index, desc_type,
- desc_type != typeNull ? buf : NULL,
- desc_type != typeNull ? size : 0);
- if (err != noErr)
- break;
- }
- if (buf)
- xfree (buf);
-
- if (err == noErr)
- {
- err = create_apple_event (0, 0, result); /* Dummy class and ID. */
- if (err == noErr)
- err = AEPutParamDesc (result, keyDirectObject, &items);
- if (err != noErr)
- AEDisposeDesc (result);
}
+ xfree (buf);
- AEDisposeDesc (&items);
-
- return err;
+ return result;
}
#endif /* TARGET_API_MAC_CARBON */
\f
out_len / sizeof (UniChar));
if (uni)
DisposeUnicodeToTextInfo (&uni);
- if (out_buf)
- xfree (out_buf);
- if (buffer)
- xfree (buffer);
+ xfree (out_buf);
+ xfree (buffer);
}
else
{
SELECT_TIMEOUT_THRESHOLD_RUNLOOP seconds).
-> Create CFSocket for each socket and add it into the current
event RunLoop so that the current event loop gets quit when
- the socket becomes ready. Then CFRunLoopRunInMode can wait
- for both kinds of inputs.
+ the socket becomes ready. Then mac_run_loop_run_once can
+ wait for both kinds of inputs.
4. Otherwise.
-> Periodically poll the window input channel while repeatedly
executing `select' with a short timeout
#if SELECT_USE_CFSOCKET
#define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
+/* Dictionary of file descriptors vs CFSocketRef's allocated in
+ sys_select. */
+static CFMutableDictionaryRef cfsockets_for_select;
+
+/* Process ID of Emacs. */
+static pid_t mac_emacs_pid;
+
static void
socket_callback (s, type, address, data, info)
CFSocketRef s;
if (efds) oefds = *efds;
}
- /* Try detect_input_pending before CFRunLoopRunInMode in the same
+ /* Try detect_input_pending before mac_run_loop_run_once in the same
BLOCK_INPUT block, in case that some input has already been read
asynchronously. */
BLOCK_INPUT;
if (timeoutval == 0.0)
timedout_p = 1;
else
- {
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (NULL);
-#endif
- if (CFRunLoopRunInMode (kCFRunLoopDefaultMode,
- timeoutval >= 0 ? timeoutval : 100000, true)
- == kCFRunLoopRunTimedOut)
- timedout_p = 1;
- }
+ timedout_p = mac_run_loop_run_once (timeoutval);
if (timeout == NULL && timedout_p)
{
return 0;
}
+/* Clean up the CFSocket associated with the file descriptor FD in
+ case the same descriptor is used in other threads later. If no
+ CFSocket is associated with FD, then return 0 without closing FD.
+ Otherwise, return 1 with closing FD. */
+
+int
+mac_try_close_socket (fd)
+ int fd;
+{
+#if SELECT_USE_CFSOCKET
+ if (getpid () == mac_emacs_pid && cfsockets_for_select)
+ {
+ void *key = (void *) fd;
+ CFSocketRef socket =
+ (CFSocketRef) CFDictionaryGetValue (cfsockets_for_select, key);
+
+ if (socket)
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
+ CFOptionFlags flags = CFSocketGetSocketFlags (socket);
+
+ if (!(flags & kCFSocketCloseOnInvalidate))
+ CFSocketSetSocketFlags (socket, flags | kCFSocketCloseOnInvalidate);
+#endif
+ BLOCK_INPUT;
+ CFSocketInvalidate (socket);
+ CFDictionaryRemoveValue (cfsockets_for_select, key);
+ UNBLOCK_INPUT;
+
+ return 1;
+ }
+ }
+#endif
+
+ return 0;
+}
+
int
sys_select (nfds, rfds, wfds, efds, timeout)
int nfds;
if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
goto poll_periodically;
- /* Try detect_input_pending before CFRunLoopRunInMode in the
+ /* Try detect_input_pending before mac_run_loop_run_once in the
same BLOCK_INPUT block, in case that some input has already
been read asynchronously. */
BLOCK_INPUT;
CFDictionaryCreateMutable (NULL, 0, NULL,
&kCFTypeDictionaryValueCallBacks);
+ if (cfsockets_for_select == NULL)
+ cfsockets_for_select =
+ CFDictionaryCreateMutable (NULL, 0, NULL,
+ &kCFTypeDictionaryValueCallBacks);
+
for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel. */
if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds)))
break;
CFRunLoopSourceRef source =
(CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
- if (source == NULL)
+ if (source == NULL || !CFRunLoopSourceIsValid (source))
{
CFSocketRef socket =
CFSocketCreateWithNative (NULL, fd,
if (socket == NULL)
continue;
+ CFDictionarySetValue (cfsockets_for_select, key, socket);
source = CFSocketCreateRunLoopSource (NULL, socket, 0);
CFRelease (socket);
if (source == NULL)
continue;
- CFDictionaryAddValue (sources, key, source);
+ CFDictionarySetValue (sources, key, source);
CFRelease (source);
}
CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
}
-#if USE_CG_DRAWING
- mac_prepare_for_quickdraw (NULL);
-#endif
- if (CFRunLoopRunInMode (kCFRunLoopDefaultMode,
- timeoutval >= 0 ? timeoutval : 100000, true)
- == kCFRunLoopRunTimedOut)
- timedout_p = 1;
+ timedout_p = mac_run_loop_run_once (timeoutval);
for (fd = minfd; fd < nfds; fd++)
if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds)))
char *p, *q;
struct stat st;
+ mac_emacs_pid = getpid ();
+
/* Initialize locale related variables. */
mac_system_script_code =
(ScriptCode) GetScriptManagerVariable (smSysScript);