summaryrefslogtreecommitdiff
path: root/src/mac.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mac.c')
-rw-r--r--src/mac.c5477
1 files changed, 0 insertions, 5477 deletions
diff --git a/src/mac.c b/src/mac.c
deleted file mode 100644
index 20872b2bdc9..00000000000
--- a/src/mac.c
+++ /dev/null
@@ -1,5477 +0,0 @@
-/* Unix emulation routines for GNU Emacs on the Mac OS.
- 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
-it under the terms of the GNU General Public License as published by
-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
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
-
-/* Contributed by Andrew Choi (akochoi@mac.com). */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "lisp.h"
-#include "process.h"
-#ifdef MAC_OSX
-#undef select
-#endif
-#include "systime.h"
-#include "sysselect.h"
-#include "blockinput.h"
-
-#include "macterm.h"
-
-#include "charset.h"
-#include "coding.h"
-#if !TARGET_API_MAC_CARBON
-#include <Files.h>
-#include <MacTypes.h>
-#include <TextUtils.h>
-#include <Folders.h>
-#include <Resources.h>
-#include <Aliases.h>
-#include <Timer.h>
-#include <OSA.h>
-#include <AppleScript.h>
-#include <Events.h>
-#include <Processes.h>
-#include <EPPC.h>
-#include <MacLocales.h>
-#include <Endian.h>
-#endif /* not TARGET_API_MAC_CARBON */
-
-#include <utime.h>
-#include <dirent.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pwd.h>
-#include <grp.h>
-#include <sys/param.h>
-#include <fcntl.h>
-#if __MWERKS__
-#include <unistd.h>
-#endif
-
-/* The system script code. */
-static int mac_system_script_code;
-
-/* The system locale identifier string. */
-static Lisp_Object Vmac_system_locale;
-
-/* An instance of the AppleScript component. */
-static ComponentInstance as_scripting_component;
-/* The single script context used for all script executions. */
-static OSAID as_script_context;
-
-#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)
-#define DISABLE_WAKEUP_FROM_RNE (wakeup_from_rne_enabled_p = 0)
-#else
-#define ENABLE_WAKEUP_FROM_RNE 0
-#define DISABLE_WAKEUP_FROM_RNE 0
-#endif
-#endif
-
-#ifndef MAC_OSX
-static OSErr posix_pathname_to_fsspec P_ ((const char *, FSSpec *));
-static OSErr fsspec_to_posix_pathname P_ ((const FSSpec *, char *, int));
-#endif
-
-/* When converting from Mac to Unix pathnames, /'s in folder names are
- converted to :'s. This function, used in copying folder names,
- performs a strncat and converts all character a to b in the copy of
- the string s2 appended to the end of s1. */
-
-void
-string_cat_and_replace (char *s1, const char *s2, int n, char a, char b)
-{
- int l1 = strlen (s1);
- int l2 = strlen (s2);
- char *p = s1 + l1;
- int i;
-
- strncat (s1, s2, n);
- for (i = 0; i < l2; i++)
- {
- if (*p == a)
- *p = b;
- p++;
- }
-}
-
-
-/* Convert a Mac pathname to Posix form. A Mac full pathname is one
- that does not begin with a ':' and contains at least one ':'. A Mac
- full pathname causes a '/' to be prepended to the Posix pathname.
- The algorithm for the rest of the pathname is as follows:
- For each segment between two ':',
- if it is non-null, copy as is and then add a '/' at the end,
- otherwise, insert a "../" into the Posix pathname.
- Returns 1 if successful; 0 if fails. */
-
-int
-mac_to_posix_pathname (const char *mfn, char *ufn, int ufnbuflen)
-{
- const char *p, *q, *pe;
-
- strcpy (ufn, "");
-
- if (*mfn == '\0')
- return 1;
-
- p = strchr (mfn, ':');
- if (p != 0 && p != mfn) /* full pathname */
- strcat (ufn, "/");
-
- p = mfn;
- if (*p == ':')
- p++;
-
- pe = mfn + strlen (mfn);
- while (p < pe)
- {
- q = strchr (p, ':');
- if (q)
- {
- if (q == p)
- { /* two consecutive ':' */
- if (strlen (ufn) + 3 >= ufnbuflen)
- return 0;
- strcat (ufn, "../");
- }
- else
- {
- if (strlen (ufn) + (q - p) + 1 >= ufnbuflen)
- return 0;
- string_cat_and_replace (ufn, p, q - p, '/', ':');
- strcat (ufn, "/");
- }
- p = q + 1;
- }
- else
- {
- if (strlen (ufn) + (pe - p) >= ufnbuflen)
- return 0;
- string_cat_and_replace (ufn, p, pe - p, '/', ':');
- /* no separator for last one */
- p = pe;
- }
- }
-
- return 1;
-}
-
-
-extern char *get_temp_dir_name ();
-
-
-/* Convert a Posix pathname to Mac form. Approximately reverse of the
- above in algorithm. */
-
-int
-posix_to_mac_pathname (const char *ufn, char *mfn, int mfnbuflen)
-{
- const char *p, *q, *pe;
- char expanded_pathname[MAXPATHLEN+1];
-
- strcpy (mfn, "");
-
- if (*ufn == '\0')
- return 1;
-
- p = ufn;
-
- /* Check for and handle volume names. Last comparison: strangely
- somewhere "/.emacs" is passed. A temporary fix for now. */
- if (*p == '/' && strchr (p+1, '/') == NULL && strcmp (p, "/.emacs") != 0)
- {
- if (strlen (p) + 1 > mfnbuflen)
- return 0;
- strcpy (mfn, p+1);
- strcat (mfn, ":");
- return 1;
- }
-
- /* expand to emacs dir found by init_emacs_passwd_dir */
- if (strncmp (p, "~emacs/", 7) == 0)
- {
- struct passwd *pw = getpwnam ("emacs");
- p += 7;
- if (strlen (pw->pw_dir) + strlen (p) > MAXPATHLEN)
- return 0;
- strcpy (expanded_pathname, pw->pw_dir);
- strcat (expanded_pathname, p);
- p = expanded_pathname;
- /* now p points to the pathname with emacs dir prefix */
- }
- else if (strncmp (p, "/tmp/", 5) == 0)
- {
- char *t = get_temp_dir_name ();
- p += 5;
- if (strlen (t) + strlen (p) > MAXPATHLEN)
- return 0;
- strcpy (expanded_pathname, t);
- strcat (expanded_pathname, p);
- p = expanded_pathname;
- /* now p points to the pathname with emacs dir prefix */
- }
- else if (*p != '/') /* relative pathname */
- strcat (mfn, ":");
-
- if (*p == '/')
- p++;
-
- pe = p + strlen (p);
- while (p < pe)
- {
- q = strchr (p, '/');
- if (q)
- {
- if (q - p == 2 && *p == '.' && *(p+1) == '.')
- {
- if (strlen (mfn) + 1 >= mfnbuflen)
- return 0;
- strcat (mfn, ":");
- }
- else
- {
- if (strlen (mfn) + (q - p) + 1 >= mfnbuflen)
- return 0;
- string_cat_and_replace (mfn, p, q - p, ':', '/');
- strcat (mfn, ":");
- }
- p = q + 1;
- }
- else
- {
- if (strlen (mfn) + (pe - p) >= mfnbuflen)
- return 0;
- string_cat_and_replace (mfn, p, pe - p, ':', '/');
- p = pe;
- }
- }
-
- return 1;
-}
-
-
-/***********************************************************************
- Conversions on Apple event objects
- ***********************************************************************/
-
-static Lisp_Object Qundecoded_file_name;
-
-static struct {
- AEKeyword keyword;
- char *name;
- Lisp_Object symbol;
-} ae_attr_table [] =
- {{keyTransactionIDAttr, "transaction-id"},
- {keyReturnIDAttr, "return-id"},
- {keyEventClassAttr, "event-class"},
- {keyEventIDAttr, "event-id"},
- {keyAddressAttr, "address"},
- {keyOptionalKeywordAttr, "optional-keyword"},
- {keyTimeoutAttr, "timeout"},
- {keyInteractLevelAttr, "interact-level"},
- {keyEventSourceAttr, "event-source"},
- /* {keyMissedKeywordAttr, "missed-keyword"}, */
- {keyOriginalAddressAttr, "original-address"},
- {keyReplyRequestedAttr, "reply-requested"},
- {KEY_EMACS_SUSPENSION_ID_ATTR, "emacs-suspension-id"}
- };
-
-static Lisp_Object
-mac_aelist_to_lisp (desc_list)
- const AEDescList *desc_list;
-{
- OSErr err;
- long count;
- Lisp_Object result, elem;
- DescType desc_type;
- Size size;
- AEKeyword keyword;
- AEDesc desc;
- int attribute_p = 0;
-
- err = AECountItems (desc_list, &count);
- if (err != noErr)
- return Qnil;
- result = Qnil;
-
- again:
- while (count > 0)
- {
- if (attribute_p)
- {
- keyword = ae_attr_table[count - 1].keyword;
- err = AESizeOfAttribute (desc_list, keyword, &desc_type, &size);
- }
- else
- err = AESizeOfNthItem (desc_list, count, &desc_type, &size);
-
- if (err == noErr)
- switch (desc_type)
- {
- case typeAEList:
- case typeAERecord:
- case typeAppleEvent:
- if (attribute_p)
- err = AEGetAttributeDesc (desc_list, keyword, typeWildCard,
- &desc);
- else
- err = AEGetNthDesc (desc_list, count, typeWildCard,
- &keyword, &desc);
- if (err != noErr)
- break;
- elem = mac_aelist_to_lisp (&desc);
- AEDisposeDesc (&desc);
- break;
-
- default:
- if (desc_type == typeNull)
- elem = Qnil;
- else
- {
- elem = make_uninit_string (size);
- if (attribute_p)
- err = AEGetAttributePtr (desc_list, keyword, typeWildCard,
- &desc_type, SDATA (elem),
- size, &size);
- else
- err = AEGetNthPtr (desc_list, count, typeWildCard, &keyword,
- &desc_type, SDATA (elem), size, &size);
- }
- if (err != noErr)
- break;
- desc_type = EndianU32_NtoB (desc_type);
- elem = Fcons (make_unibyte_string ((char *) &desc_type, 4), elem);
- break;
- }
-
- if (err == noErr || desc_list->descriptorType == typeAEList)
- {
- if (err != noErr)
- elem = Qnil; /* Don't skip elements in AEList. */
- else if (desc_list->descriptorType != typeAEList)
- {
- if (attribute_p)
- elem = Fcons (ae_attr_table[count-1].symbol, elem);
- else
- {
- keyword = EndianU32_NtoB (keyword);
- elem = Fcons (make_unibyte_string ((char *) &keyword, 4),
- elem);
- }
- }
-
- result = Fcons (elem, result);
- }
-
- count--;
- }
-
- if (desc_list->descriptorType == typeAppleEvent && !attribute_p)
- {
- attribute_p = 1;
- count = sizeof (ae_attr_table) / sizeof (ae_attr_table[0]);
- goto again;
- }
-
- desc_type = EndianU32_NtoB (desc_list->descriptorType);
- return Fcons (make_unibyte_string ((char *) &desc_type, 4), result);
-}
-
-Lisp_Object
-mac_aedesc_to_lisp (desc)
- const AEDesc *desc;
-{
- OSErr err = noErr;
- DescType desc_type = desc->descriptorType;
- Lisp_Object result;
-
- switch (desc_type)
- {
- case typeNull:
- result = Qnil;
- break;
-
- case typeAEList:
- case typeAERecord:
- case typeAppleEvent:
- return mac_aelist_to_lisp (desc);
-#if 0
- /* The following one is much simpler, but creates and disposes
- of Apple event descriptors many times. */
- {
- long count;
- Lisp_Object elem;
- AEKeyword keyword;
- AEDesc desc1;
-
- err = AECountItems (desc, &count);
- if (err != noErr)
- break;
- result = Qnil;
- while (count > 0)
- {
- err = AEGetNthDesc (desc, count, typeWildCard, &keyword, &desc1);
- if (err != noErr)
- break;
- elem = mac_aedesc_to_lisp (&desc1);
- AEDisposeDesc (&desc1);
- if (desc_type != typeAEList)
- {
- keyword = EndianU32_NtoB (keyword);
- elem = Fcons (make_unibyte_string ((char *) &keyword, 4), elem);
- }
- result = Fcons (elem, result);
- count--;
- }
- }
-#endif
- break;
-
- default:
-#if TARGET_API_MAC_CARBON
- result = make_uninit_string (AEGetDescDataSize (desc));
- err = AEGetDescData (desc, SDATA (result), SBYTES (result));
-#else
- result = make_uninit_string (GetHandleSize (desc->dataHandle));
- memcpy (SDATA (result), *(desc->dataHandle), SBYTES (result));
-#endif
- break;
- }
-
- if (err != noErr)
- return Qnil;
-
- desc_type = EndianU32_NtoB (desc_type);
- return Fcons (make_unibyte_string ((char *) &desc_type, 4), result);
-}
-
-OSErr
-mac_ae_put_lisp (desc, keyword_or_index, obj)
- AEDescList *desc;
- UInt32 keyword_or_index;
- Lisp_Object obj;
-{
- OSErr err;
-
- if (!(desc->descriptorType == typeAppleEvent
- || desc->descriptorType == typeAERecord
- || desc->descriptorType == typeAEList))
- return errAEWrongDataType;
-
- if (CONSP (obj) && STRINGP (XCAR (obj)) && SBYTES (XCAR (obj)) == 4)
- {
- DescType desc_type1 = EndianU32_BtoN (*((UInt32 *) SDATA (XCAR (obj))));
- Lisp_Object data = XCDR (obj), rest;
- AEDesc desc1;
-
- switch (desc_type1)
- {
- case typeNull:
- case typeAppleEvent:
- break;
-
- case typeAEList:
- case typeAERecord:
- err = AECreateList (NULL, 0, desc_type1 == typeAERecord, &desc1);
- if (err == noErr)
- {
- for (rest = data; CONSP (rest); rest = XCDR (rest))
- {
- UInt32 keyword_or_index1 = 0;
- Lisp_Object elem = XCAR (rest);
-
- if (desc_type1 == typeAERecord)
- {
- if (CONSP (elem) && STRINGP (XCAR (elem))
- && SBYTES (XCAR (elem)) == 4)
- {
- keyword_or_index1 =
- EndianU32_BtoN (*((UInt32 *)
- SDATA (XCAR (elem))));
- elem = XCDR (elem);
- }
- else
- continue;
- }
-
- err = mac_ae_put_lisp (&desc1, keyword_or_index1, elem);
- if (err != noErr)
- break;
- }
-
- if (err == noErr)
- {
- if (desc->descriptorType == typeAEList)
- err = AEPutDesc (desc, keyword_or_index, &desc1);
- else
- err = AEPutParamDesc (desc, keyword_or_index, &desc1);
- }
-
- AEDisposeDesc (&desc1);
- }
- return err;
-
- default:
- if (!STRINGP (data))
- break;
- if (desc->descriptorType == typeAEList)
- err = AEPutPtr (desc, keyword_or_index, desc_type1,
- SDATA (data), SBYTES (data));
- else
- err = AEPutParamPtr (desc, keyword_or_index, desc_type1,
- SDATA (data), SBYTES (data));
- return err;
- }
- }
-
- if (desc->descriptorType == typeAEList)
- err = AEPutPtr (desc, keyword_or_index, typeNull, NULL, 0);
- else
- err = AEPutParamPtr (desc, keyword_or_index, typeNull, NULL, 0);
-
- return err;
-}
-
-static pascal OSErr
-mac_coerce_file_name_ptr (type_code, data_ptr, data_size,
- to_type, handler_refcon, result)
- DescType type_code;
- const void *data_ptr;
- Size data_size;
- DescType to_type;
- long handler_refcon;
- AEDesc *result;
-{
- OSErr err;
-
- if (type_code == typeNull)
- err = errAECoercionFail;
- else if (type_code == to_type || to_type == typeWildCard)
- err = AECreateDesc (TYPE_FILE_NAME, data_ptr, data_size, result);
- else if (type_code == TYPE_FILE_NAME)
- /* Coercion from undecoded file name. */
- {
-#ifdef MAC_OSX
- CFStringRef str;
- CFURLRef url = NULL;
- CFDataRef data = NULL;
-
- str = CFStringCreateWithBytes (NULL, data_ptr, data_size,
- kCFStringEncodingUTF8, false);
- if (str)
- {
- url = CFURLCreateWithFileSystemPath (NULL, str,
- kCFURLPOSIXPathStyle, false);
- CFRelease (str);
- }
- if (url)
- {
- data = CFURLCreateData (NULL, url, kCFStringEncodingUTF8, true);
- CFRelease (url);
- }
- if (data)
- {
- err = AECoercePtr (typeFileURL, CFDataGetBytePtr (data),
- CFDataGetLength (data), to_type, result);
- CFRelease (data);
- }
- else
- err = memFullErr;
-
- if (err != noErr)
- {
- /* Just to be paranoid ... */
- FSRef fref;
- char *buf;
-
- buf = xmalloc (data_size + 1);
- memcpy (buf, data_ptr, data_size);
- buf[data_size] = '\0';
- err = FSPathMakeRef (buf, &fref, NULL);
- xfree (buf);
- if (err == noErr)
- err = AECoercePtr (typeFSRef, &fref, sizeof (FSRef),
- to_type, result);
- }
-#else
- FSSpec fs;
- char *buf;
-
- buf = xmalloc (data_size + 1);
- memcpy (buf, data_ptr, data_size);
- buf[data_size] = '\0';
- err = posix_pathname_to_fsspec (buf, &fs);
- xfree (buf);
- if (err == noErr)
- err = AECoercePtr (typeFSS, &fs, sizeof (FSSpec), to_type, result);
-#endif
- }
- else if (to_type == TYPE_FILE_NAME)
- /* Coercion to undecoded file name. */
- {
-#ifdef MAC_OSX
- CFURLRef url = NULL;
- CFStringRef str = NULL;
- CFDataRef data = NULL;
-
- if (type_code == typeFileURL)
- url = CFURLCreateWithBytes (NULL, data_ptr, data_size,
- kCFStringEncodingUTF8, NULL);
- else
- {
- AEDesc desc;
- Size size;
- char *buf;
-
- err = AECoercePtr (type_code, data_ptr, data_size,
- typeFileURL, &desc);
- if (err == noErr)
- {
- size = AEGetDescDataSize (&desc);
- buf = xmalloc (size);
- err = AEGetDescData (&desc, buf, size);
- if (err == noErr)
- url = CFURLCreateWithBytes (NULL, buf, size,
- kCFStringEncodingUTF8, NULL);
- xfree (buf);
- AEDisposeDesc (&desc);
- }
- }
- if (url)
- {
- str = CFURLCopyFileSystemPath (url, kCFURLPOSIXPathStyle);
- CFRelease (url);
- }
- if (str)
- {
- data = CFStringCreateExternalRepresentation (NULL, str,
- kCFStringEncodingUTF8,
- '\0');
- CFRelease (str);
- }
- if (data)
- {
- err = AECreateDesc (TYPE_FILE_NAME, CFDataGetBytePtr (data),
- CFDataGetLength (data), result);
- CFRelease (data);
- }
-
- if (err != noErr)
- {
- /* Coercion from typeAlias to typeFileURL fails on Mac OS X
- 10.2. In such cases, try typeFSRef as a target type. */
- char file_name[MAXPATHLEN];
-
- if (type_code == typeFSRef && data_size == sizeof (FSRef))
- err = FSRefMakePath (data_ptr, file_name, sizeof (file_name));
- else
- {
- AEDesc desc;
- FSRef fref;
-
- err = AECoercePtr (type_code, data_ptr, data_size,
- typeFSRef, &desc);
- if (err == noErr)
- {
- err = AEGetDescData (&desc, &fref, sizeof (FSRef));
- AEDisposeDesc (&desc);
- }
- if (err == noErr)
- err = FSRefMakePath (&fref, file_name, sizeof (file_name));
- }
- if (err == noErr)
- err = AECreateDesc (TYPE_FILE_NAME, file_name,
- strlen (file_name), result);
- }
-#else
- char file_name[MAXPATHLEN];
-
- if (type_code == typeFSS && data_size == sizeof (FSSpec))
- err = fsspec_to_posix_pathname (data_ptr, file_name,
- sizeof (file_name) - 1);
- else
- {
- AEDesc desc;
- FSSpec fs;
-
- err = AECoercePtr (type_code, data_ptr, data_size, typeFSS, &desc);
- if (err == noErr)
- {
-#if TARGET_API_MAC_CARBON
- err = AEGetDescData (&desc, &fs, sizeof (FSSpec));
-#else
- fs = *(FSSpec *)(*(desc.dataHandle));
-#endif
- AEDisposeDesc (&desc);
- }
- if (err == noErr)
- err = fsspec_to_posix_pathname (&fs, file_name,
- sizeof (file_name) - 1);
- }
- if (err == noErr)
- err = AECreateDesc (TYPE_FILE_NAME, file_name,
- strlen (file_name), result);
-#endif
- }
- else
- abort ();
-
- if (err != noErr)
- return errAECoercionFail;
- return noErr;
-}
-
-static pascal OSErr
-mac_coerce_file_name_desc (from_desc, to_type, handler_refcon, result)
- const AEDesc *from_desc;
- DescType to_type;
- long handler_refcon;
- AEDesc *result;
-{
- OSErr err = noErr;
- DescType from_type = from_desc->descriptorType;
-
- if (from_type == typeNull)
- err = errAECoercionFail;
- else if (from_type == to_type || to_type == typeWildCard)
- err = AEDuplicateDesc (from_desc, result);
- else
- {
- char *data_ptr;
- Size data_size;
-
-#if TARGET_API_MAC_CARBON
- data_size = AEGetDescDataSize (from_desc);
-#else
- data_size = GetHandleSize (from_desc->dataHandle);
-#endif
- data_ptr = xmalloc (data_size);
-#if TARGET_API_MAC_CARBON
- err = AEGetDescData (from_desc, data_ptr, data_size);
-#else
- memcpy (data_ptr, *(from_desc->dataHandle), data_size);
-#endif
- if (err == noErr)
- err = mac_coerce_file_name_ptr (from_type, data_ptr,
- data_size, to_type,
- handler_refcon, result);
- xfree (data_ptr);
- }
-
- if (err != noErr)
- return errAECoercionFail;
- return noErr;
-}
-
-OSErr
-init_coercion_handler ()
-{
- OSErr err;
-
- static AECoercePtrUPP coerce_file_name_ptrUPP = NULL;
- static AECoerceDescUPP coerce_file_name_descUPP = NULL;
-
- if (coerce_file_name_ptrUPP == NULL)
- {
- coerce_file_name_ptrUPP = NewAECoercePtrUPP (mac_coerce_file_name_ptr);
- coerce_file_name_descUPP = NewAECoerceDescUPP (mac_coerce_file_name_desc);
- }
-
- err = AEInstallCoercionHandler (TYPE_FILE_NAME, typeWildCard,
- (AECoercionHandlerUPP)
- coerce_file_name_ptrUPP, 0, false, false);
- if (err == noErr)
- err = AEInstallCoercionHandler (typeWildCard, TYPE_FILE_NAME,
- (AECoercionHandlerUPP)
- coerce_file_name_ptrUPP, 0, false, false);
- if (err == noErr)
- err = AEInstallCoercionHandler (TYPE_FILE_NAME, typeWildCard,
- coerce_file_name_descUPP, 0, true, false);
- if (err == noErr)
- err = AEInstallCoercionHandler (typeWildCard, TYPE_FILE_NAME,
- coerce_file_name_descUPP, 0, true, false);
- return err;
-}
-
-#if TARGET_API_MAC_CARBON
-OSErr
-create_apple_event (class, id, result)
- AEEventClass class;
- AEEventID id;
- AppleEvent *result;
-{
- OSErr err;
- static const ProcessSerialNumber psn = {0, kCurrentProcess};
- AEAddressDesc address_desc;
-
- err = AECreateDesc (typeProcessSerialNumber, &psn,
- sizeof (ProcessSerialNumber), &address_desc);
- if (err == noErr)
- {
- err = AECreateAppleEvent (class, id,
- &address_desc, /* NULL is not allowed
- on Mac OS Classic. */
- kAutoGenerateReturnID,
- kAnyTransactionID, result);
- AEDisposeDesc (&address_desc);
- }
-
- return err;
-}
-
-Lisp_Object
-mac_event_parameters_to_lisp (event, num_params, names, types)
- EventRef event;
- UInt32 num_params;
- const EventParamName *names;
- const EventParamType *types;
-{
- OSStatus err;
- Lisp_Object result = Qnil;
- UInt32 i;
- ByteCount size;
-#ifdef MAC_OSX
- CFStringRef string;
- CFDataRef data;
-#endif
- char *buf = NULL;
-
- for (i = 0; i < num_params; i++)
- {
- EventParamName name = names[i];
- EventParamType type = types[i];
-
- switch (type)
- {
-#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
-
- 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)
- {
- 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;
- }
- }
- xfree (buf);
-
- return result;
-}
-#endif /* TARGET_API_MAC_CARBON */
-
-/***********************************************************************
- Conversion between Lisp and Core Foundation objects
- ***********************************************************************/
-
-#if TARGET_API_MAC_CARBON
-static Lisp_Object Qstring, Qnumber, Qboolean, Qdate, Qdata;
-static Lisp_Object Qarray, Qdictionary;
-
-struct cfdict_context
-{
- Lisp_Object *result;
- int with_tag, hash_bound;
-};
-
-/* C string to CFString. */
-
-CFStringRef
-cfstring_create_with_utf8_cstring (c_str)
- const char *c_str;
-{
- CFStringRef str;
-
- str = CFStringCreateWithCString (NULL, c_str, kCFStringEncodingUTF8);
- if (str == NULL)
- /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
- str = CFStringCreateWithCString (NULL, c_str, kCFStringEncodingMacRoman);
-
- return str;
-}
-
-
-/* Lisp string to CFString. */
-
-CFStringRef
-cfstring_create_with_string (s)
- Lisp_Object s;
-{
- CFStringRef string = NULL;
-
- if (STRING_MULTIBYTE (s))
- {
- char *p, *end = SDATA (s) + SBYTES (s);
-
- for (p = SDATA (s); p < end; p++)
- if (!isascii (*p))
- {
- s = ENCODE_UTF_8 (s);
- break;
- }
- string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
- kCFStringEncodingUTF8, false);
- }
-
- if (string == NULL)
- /* Failed to interpret as UTF 8. Fall back on Mac Roman. */
- string = CFStringCreateWithBytes (NULL, SDATA (s), SBYTES (s),
- kCFStringEncodingMacRoman, false);
-
- return string;
-}
-
-
-/* From CFData to a lisp string. Always returns a unibyte string. */
-
-Lisp_Object
-cfdata_to_lisp (data)
- CFDataRef data;
-{
- CFIndex len = CFDataGetLength (data);
- Lisp_Object result = make_uninit_string (len);
-
- CFDataGetBytes (data, CFRangeMake (0, len), SDATA (result));
-
- return result;
-}
-
-
-/* From CFString to a lisp string. Returns a unibyte string
- containing a UTF-8 byte sequence. */
-
-Lisp_Object
-cfstring_to_lisp_nodecode (string)
- CFStringRef string;
-{
- Lisp_Object result = Qnil;
- const char *s = CFStringGetCStringPtr (string, kCFStringEncodingUTF8);
-
- if (s)
- result = make_unibyte_string (s, strlen (s));
- else
- {
- CFDataRef data =
- CFStringCreateExternalRepresentation (NULL, string,
- kCFStringEncodingUTF8, '?');
-
- if (data)
- {
- result = cfdata_to_lisp (data);
- CFRelease (data);
- }
- }
-
- return result;
-}
-
-
-/* From CFString to a lisp string. Never returns a unibyte string
- (even if it only contains ASCII characters).
- This may cause GC during code conversion. */
-
-Lisp_Object
-cfstring_to_lisp (string)
- CFStringRef string;
-{
- Lisp_Object result = cfstring_to_lisp_nodecode (string);
-
- if (!NILP (result))
- {
- result = code_convert_string_norecord (result, Qutf_8, 0);
- /* This may be superfluous. Just to make sure that the result
- is a multibyte string. */
- result = string_to_multibyte (result);
- }
-
- return result;
-}
-
-
-/* CFNumber to a lisp integer or a lisp float. */
-
-Lisp_Object
-cfnumber_to_lisp (number)
- CFNumberRef number;
-{
- Lisp_Object result = Qnil;
-#if BITS_PER_EMACS_INT > 32
- SInt64 int_val;
- CFNumberType emacs_int_type = kCFNumberSInt64Type;
-#else
- SInt32 int_val;
- CFNumberType emacs_int_type = kCFNumberSInt32Type;
-#endif
- double float_val;
-
- if (CFNumberGetValue (number, emacs_int_type, &int_val)
- && !FIXNUM_OVERFLOW_P (int_val))
- result = make_number (int_val);
- else
- if (CFNumberGetValue (number, kCFNumberDoubleType, &float_val))
- result = make_float (float_val);
- return result;
-}
-
-
-/* CFDate to a list of three integers as in a return value of
- `current-time'. */
-
-Lisp_Object
-cfdate_to_lisp (date)
- CFDateRef date;
-{
- CFTimeInterval sec;
- int high, low, microsec;
-
- sec = CFDateGetAbsoluteTime (date) + kCFAbsoluteTimeIntervalSince1970;
- high = sec / 65536.0;
- low = sec - high * 65536.0;
- microsec = (sec - floor (sec)) * 1000000.0;
-
- return list3 (make_number (high), make_number (low), make_number (microsec));
-}
-
-
-/* CFBoolean to a lisp symbol, `t' or `nil'. */
-
-Lisp_Object
-cfboolean_to_lisp (boolean)
- CFBooleanRef boolean;
-{
- return CFBooleanGetValue (boolean) ? Qt : Qnil;
-}
-
-
-/* Any Core Foundation object to a (lengthy) lisp string. */
-
-Lisp_Object
-cfobject_desc_to_lisp (object)
- CFTypeRef object;
-{
- Lisp_Object result = Qnil;
- CFStringRef desc = CFCopyDescription (object);
-
- if (desc)
- {
- result = cfstring_to_lisp (desc);
- CFRelease (desc);
- }
-
- return result;
-}
-
-
-/* Callback functions for cfproperty_list_to_lisp. */
-
-static void
-cfdictionary_add_to_list (key, value, context)
- const void *key;
- const void *value;
- void *context;
-{
- struct cfdict_context *cxt = (struct cfdict_context *)context;
-
- *cxt->result =
- Fcons (Fcons (cfstring_to_lisp (key),
- cfproperty_list_to_lisp (value, cxt->with_tag,
- cxt->hash_bound)),
- *cxt->result);
-}
-
-static void
-cfdictionary_puthash (key, value, context)
- const void *key;
- const void *value;
- void *context;
-{
- Lisp_Object lisp_key = cfstring_to_lisp (key);
- struct cfdict_context *cxt = (struct cfdict_context *)context;
- struct Lisp_Hash_Table *h = XHASH_TABLE (*(cxt->result));
- unsigned hash_code;
-
- hash_lookup (h, lisp_key, &hash_code);
- hash_put (h, lisp_key,
- cfproperty_list_to_lisp (value, cxt->with_tag, cxt->hash_bound),
- hash_code);
-}
-
-
-/* Convert CFPropertyList PLIST to a lisp object. If WITH_TAG is
- non-zero, a symbol that represents the type of the original Core
- Foundation object is prepended. HASH_BOUND specifies which kinds
- of the lisp objects, alists or hash tables, are used as the targets
- of the conversion from CFDictionary. If HASH_BOUND is negative,
- always generate alists. If HASH_BOUND >= 0, generate an alist if
- the number of keys in the dictionary is smaller than HASH_BOUND,
- and a hash table otherwise. */
-
-Lisp_Object
-cfproperty_list_to_lisp (plist, with_tag, hash_bound)
- CFPropertyListRef plist;
- int with_tag, hash_bound;
-{
- CFTypeID type_id = CFGetTypeID (plist);
- Lisp_Object tag = Qnil, result = Qnil;
- struct gcpro gcpro1, gcpro2;
-
- GCPRO2 (tag, result);
-
- if (type_id == CFStringGetTypeID ())
- {
- tag = Qstring;
- result = cfstring_to_lisp (plist);
- }
- else if (type_id == CFNumberGetTypeID ())
- {
- tag = Qnumber;
- result = cfnumber_to_lisp (plist);
- }
- else if (type_id == CFBooleanGetTypeID ())
- {
- tag = Qboolean;
- result = cfboolean_to_lisp (plist);
- }
- else if (type_id == CFDateGetTypeID ())
- {
- tag = Qdate;
- result = cfdate_to_lisp (plist);
- }
- else if (type_id == CFDataGetTypeID ())
- {
- tag = Qdata;
- result = cfdata_to_lisp (plist);
- }
- else if (type_id == CFArrayGetTypeID ())
- {
- CFIndex index, count = CFArrayGetCount (plist);
-
- tag = Qarray;
- result = Fmake_vector (make_number (count), Qnil);
- for (index = 0; index < count; index++)
- XVECTOR (result)->contents[index] =
- cfproperty_list_to_lisp (CFArrayGetValueAtIndex (plist, index),
- with_tag, hash_bound);
- }
- else if (type_id == CFDictionaryGetTypeID ())
- {
- struct cfdict_context context;
- CFIndex count = CFDictionaryGetCount (plist);
-
- tag = Qdictionary;
- context.result = &result;
- context.with_tag = with_tag;
- context.hash_bound = hash_bound;
- if (hash_bound < 0 || count < hash_bound)
- {
- result = Qnil;
- CFDictionaryApplyFunction (plist, cfdictionary_add_to_list,
- &context);
- }
- else
- {
- result = make_hash_table (Qequal,
- make_number (count),
- make_float (DEFAULT_REHASH_SIZE),
- make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
- CFDictionaryApplyFunction (plist, cfdictionary_puthash,
- &context);
- }
- }
- else
- abort ();
-
- UNGCPRO;
-
- if (with_tag)
- result = Fcons (tag, result);
-
- return result;
-}
-#endif
-
-
-/***********************************************************************
- Emulation of the X Resource Manager
- ***********************************************************************/
-
-/* Parser functions for resource lines. Each function takes an
- address of a variable whose value points to the head of a string.
- The value will be advanced so that it points to the next character
- of the parsed part when the function returns.
-
- A resource name such as "Emacs*font" is parsed into a non-empty
- list called `quarks'. Each element is either a Lisp string that
- represents a concrete component, a Lisp symbol LOOSE_BINDING
- (actually Qlambda) that represents any number (>=0) of intervening
- components, or a Lisp symbol SINGLE_COMPONENT (actually Qquote)
- that represents as any single component. */
-
-#define P (*p)
-
-#define LOOSE_BINDING Qlambda /* '*' ("L"oose) */
-#define SINGLE_COMPONENT Qquote /* '?' ("Q"uestion) */
-
-static void
-skip_white_space (p)
- const char **p;
-{
- /* WhiteSpace = {<space> | <horizontal tab>} */
- while (*P == ' ' || *P == '\t')
- P++;
-}
-
-static int
-parse_comment (p)
- const char **p;
-{
- /* Comment = "!" {<any character except null or newline>} */
- if (*P == '!')
- {
- P++;
- while (*P)
- if (*P++ == '\n')
- break;
- return 1;
- }
- else
- return 0;
-}
-
-/* Don't interpret filename. Just skip until the newline. */
-static int
-parse_include_file (p)
- const char **p;
-{
- /* IncludeFile = "#" WhiteSpace "include" WhiteSpace FileName WhiteSpace */
- if (*P == '#')
- {
- P++;
- while (*P)
- if (*P++ == '\n')
- break;
- return 1;
- }
- else
- return 0;
-}
-
-static char
-parse_binding (p)
- const char **p;
-{
- /* Binding = "." | "*" */
- if (*P == '.' || *P == '*')
- {
- char binding = *P++;
-
- while (*P == '.' || *P == '*')
- if (*P++ == '*')
- binding = '*';
- return binding;
- }
- else
- return '\0';
-}
-
-static Lisp_Object
-parse_component (p)
- const char **p;
-{
- /* Component = "?" | ComponentName
- ComponentName = NameChar {NameChar}
- NameChar = "a"-"z" | "A"-"Z" | "0"-"9" | "_" | "-" */
- if (*P == '?')
- {
- P++;
- return SINGLE_COMPONENT;
- }
- else if (isalnum (*P) || *P == '_' || *P == '-')
- {
- const char *start = P++;
-
- while (isalnum (*P) || *P == '_' || *P == '-')
- P++;
-
- return make_unibyte_string (start, P - start);
- }
- else
- return Qnil;
-}
-
-static Lisp_Object
-parse_resource_name (p)
- const char **p;
-{
- Lisp_Object result = Qnil, component;
- char binding;
-
- /* ResourceName = [Binding] {Component Binding} ComponentName */
- if (parse_binding (p) == '*')
- result = Fcons (LOOSE_BINDING, result);
-
- component = parse_component (p);
- if (NILP (component))
- return Qnil;
-
- result = Fcons (component, result);
- while ((binding = parse_binding (p)) != '\0')
- {
- if (binding == '*')
- result = Fcons (LOOSE_BINDING, result);
- component = parse_component (p);
- if (NILP (component))
- return Qnil;
- else
- result = Fcons (component, result);
- }
-
- /* The final component should not be '?'. */
- if (EQ (component, SINGLE_COMPONENT))
- return Qnil;
-
- return Fnreverse (result);
-}
-
-static Lisp_Object
-parse_value (p)
- const char **p;
-{
- char *q, *buf;
- Lisp_Object seq = Qnil, result;
- int buf_len, total_len = 0, len, continue_p;
-
- q = strchr (P, '\n');
- buf_len = q ? q - P : strlen (P);
- buf = xmalloc (buf_len);
-
- while (1)
- {
- q = buf;
- continue_p = 0;
- while (*P)
- {
- if (*P == '\n')
- {
- P++;
- break;
- }
- else if (*P == '\\')
- {
- P++;
- if (*P == '\0')
- break;
- else if (*P == '\n')
- {
- P++;
- continue_p = 1;
- break;
- }
- else if (*P == 'n')
- {
- *q++ = '\n';
- P++;
- }
- else if ('0' <= P[0] && P[0] <= '7'
- && '0' <= P[1] && P[1] <= '7'
- && '0' <= P[2] && P[2] <= '7')
- {
- *q++ = ((P[0] - '0') << 6) + ((P[1] - '0') << 3) + (P[2] - '0');
- P += 3;
- }
- else
- *q++ = *P++;
- }
- else
- *q++ = *P++;
- }
- len = q - buf;
- seq = Fcons (make_unibyte_string (buf, len), seq);
- total_len += len;
-
- if (continue_p)
- {
- q = strchr (P, '\n');
- len = q ? q - P : strlen (P);
- if (len > buf_len)
- {
- xfree (buf);
- buf_len = len;
- buf = xmalloc (buf_len);
- }
- }
- else
- break;
- }
- xfree (buf);
-
- if (SBYTES (XCAR (seq)) == total_len)
- return make_string (SDATA (XCAR (seq)), total_len);
- else
- {
- buf = xmalloc (total_len);
- q = buf + total_len;
- for (; CONSP (seq); seq = XCDR (seq))
- {
- len = SBYTES (XCAR (seq));
- q -= len;
- memcpy (q, SDATA (XCAR (seq)), len);
- }
- result = make_string (buf, total_len);
- xfree (buf);
- return result;
- }
-}
-
-static Lisp_Object
-parse_resource_line (p)
- const char **p;
-{
- Lisp_Object quarks, value;
-
- /* ResourceLine = Comment | IncludeFile | ResourceSpec | <empty line> */
- if (parse_comment (p) || parse_include_file (p))
- return Qnil;
-
- /* ResourceSpec = WhiteSpace ResourceName WhiteSpace ":" WhiteSpace Value */
- skip_white_space (p);
- quarks = parse_resource_name (p);
- if (NILP (quarks))
- goto cleanup;
- skip_white_space (p);
- if (*P != ':')
- goto cleanup;
- P++;
- skip_white_space (p);
- value = parse_value (p);
- return Fcons (quarks, value);
-
- cleanup:
- /* Skip the remaining data as a dummy value. */
- parse_value (p);
- return Qnil;
-}
-
-#undef P
-
-/* Equivalents of X Resource Manager functions.
-
- An X Resource Database acts as a collection of resource names and
- associated values. It is implemented as a trie on quarks. Namely,
- each edge is labeled by either a string, LOOSE_BINDING, or
- SINGLE_COMPONENT. Each node has a node id, which is a unique
- nonnegative integer, and the root node id is 0. A database is
- implemented as a hash table that maps a pair (SRC-NODE-ID .
- EDGE-LABEL) to DEST-NODE-ID. It also holds a maximum node id used
- in the table as a value for HASHKEY_MAX_NID. A value associated to
- a node is recorded as a value for the node id.
-
- A database also has a cache for past queries as a value for
- HASHKEY_QUERY_CACHE. It is another hash table that maps
- "NAME-STRING\0CLASS-STRING" to the result of the query. */
-
-#define HASHKEY_MAX_NID (make_number (0))
-#define HASHKEY_QUERY_CACHE (make_number (-1))
-
-static XrmDatabase
-xrm_create_database ()
-{
- XrmDatabase database;
-
- database = make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
- make_float (DEFAULT_REHASH_SIZE),
- make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
- Fputhash (HASHKEY_MAX_NID, make_number (0), database);
- Fputhash (HASHKEY_QUERY_CACHE, Qnil, database);
-
- return database;
-}
-
-static void
-xrm_q_put_resource (database, quarks, value)
- XrmDatabase database;
- Lisp_Object quarks, value;
-{
- struct Lisp_Hash_Table *h = XHASH_TABLE (database);
- unsigned hash_code;
- int max_nid, i;
- Lisp_Object node_id, key;
-
- max_nid = XINT (Fgethash (HASHKEY_MAX_NID, database, Qnil));
-
- XSETINT (node_id, 0);
- for (; CONSP (quarks); quarks = XCDR (quarks))
- {
- key = Fcons (node_id, XCAR (quarks));
- i = hash_lookup (h, key, &hash_code);
- if (i < 0)
- {
- max_nid++;
- XSETINT (node_id, max_nid);
- hash_put (h, key, node_id, hash_code);
- }
- else
- node_id = HASH_VALUE (h, i);
- }
- Fputhash (node_id, value, database);
-
- Fputhash (HASHKEY_MAX_NID, make_number (max_nid), database);
- Fputhash (HASHKEY_QUERY_CACHE, Qnil, database);
-}
-
-/* Merge multiple resource entries specified by DATA into a resource
- database DATABASE. DATA points to the head of a null-terminated
- string consisting of multiple resource lines. It's like a
- combination of XrmGetStringDatabase and XrmMergeDatabases. */
-
-void
-xrm_merge_string_database (database, data)
- XrmDatabase database;
- const char *data;
-{
- Lisp_Object quarks_value;
-
- while (*data)
- {
- quarks_value = parse_resource_line (&data);
- if (!NILP (quarks_value))
- xrm_q_put_resource (database,
- XCAR (quarks_value), XCDR (quarks_value));
- }
-}
-
-static Lisp_Object
-xrm_q_get_resource_1 (database, node_id, quark_name, quark_class)
- XrmDatabase database;
- Lisp_Object node_id, quark_name, quark_class;
-{
- struct Lisp_Hash_Table *h = XHASH_TABLE (database);
- Lisp_Object key, labels[3], value;
- int i, k;
-
- if (!CONSP (quark_name))
- return Fgethash (node_id, database, Qnil);
-
- /* First, try tight bindings */
- labels[0] = XCAR (quark_name);
- labels[1] = XCAR (quark_class);
- labels[2] = SINGLE_COMPONENT;
-
- key = Fcons (node_id, Qnil);
- for (k = 0; k < sizeof (labels) / sizeof (*labels); k++)
- {
- XSETCDR (key, labels[k]);
- i = hash_lookup (h, key, NULL);
- if (i >= 0)
- {
- value = xrm_q_get_resource_1 (database, HASH_VALUE (h, i),
- XCDR (quark_name), XCDR (quark_class));
- if (!NILP (value))
- return value;
- }
- }
-
- /* Then, try loose bindings */
- XSETCDR (key, LOOSE_BINDING);
- i = hash_lookup (h, key, NULL);
- if (i >= 0)
- {
- value = xrm_q_get_resource_1 (database, HASH_VALUE (h, i),
- quark_name, quark_class);
- if (!NILP (value))
- return value;
- else
- return xrm_q_get_resource_1 (database, node_id,
- XCDR (quark_name), XCDR (quark_class));
- }
- else
- return Qnil;
-}
-
-static Lisp_Object
-xrm_q_get_resource (database, quark_name, quark_class)
- XrmDatabase database;
- Lisp_Object quark_name, quark_class;
-{
- return xrm_q_get_resource_1 (database, make_number (0),
- quark_name, quark_class);
-}
-
-/* Retrieve a resource value for the specified NAME and CLASS from the
- resource database DATABASE. It corresponds to XrmGetResource. */
-
-Lisp_Object
-xrm_get_resource (database, name, class)
- XrmDatabase database;
- const char *name, *class;
-{
- Lisp_Object key, query_cache, quark_name, quark_class, tmp;
- int i, nn, nc;
- struct Lisp_Hash_Table *h;
- unsigned hash_code;
-
- nn = strlen (name);
- nc = strlen (class);
- key = make_uninit_string (nn + nc + 1);
- strcpy (SDATA (key), name);
- strncpy (SDATA (key) + nn + 1, class, nc);
-
- query_cache = Fgethash (HASHKEY_QUERY_CACHE, database, Qnil);
- if (NILP (query_cache))
- {
- query_cache = make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE),
- make_float (DEFAULT_REHASH_SIZE),
- make_float (DEFAULT_REHASH_THRESHOLD),
- Qnil, Qnil, Qnil);
- Fputhash (HASHKEY_QUERY_CACHE, query_cache, database);
- }
- h = XHASH_TABLE (query_cache);
- i = hash_lookup (h, key, &hash_code);
- if (i >= 0)
- return HASH_VALUE (h, i);
-
- quark_name = parse_resource_name (&name);
- if (*name != '\0')
- return Qnil;
- for (tmp = quark_name, nn = 0; CONSP (tmp); tmp = XCDR (tmp), nn++)
- if (!STRINGP (XCAR (tmp)))
- return Qnil;
-
- quark_class = parse_resource_name (&class);
- if (*class != '\0')
- return Qnil;
- for (tmp = quark_class, nc = 0; CONSP (tmp); tmp = XCDR (tmp), nc++)
- if (!STRINGP (XCAR (tmp)))
- return Qnil;
-
- if (nn != nc)
- return Qnil;
- else
- {
- tmp = xrm_q_get_resource (database, quark_name, quark_class);
- hash_put (h, key, tmp, hash_code);
- return tmp;
- }
-}
-
-#if TARGET_API_MAC_CARBON
-static Lisp_Object
-xrm_cfproperty_list_to_value (plist)
- CFPropertyListRef plist;
-{
- CFTypeID type_id = CFGetTypeID (plist);
-
- if (type_id == CFStringGetTypeID ())
- return cfstring_to_lisp (plist);
- else if (type_id == CFNumberGetTypeID ())
- {
- CFStringRef string;
- Lisp_Object result = Qnil;
-
- string = CFStringCreateWithFormat (NULL, NULL, CFSTR ("%@"), plist);
- if (string)
- {
- result = cfstring_to_lisp (string);
- CFRelease (string);
- }
- return result;
- }
- else if (type_id == CFBooleanGetTypeID ())
- return build_string (CFBooleanGetValue (plist) ? "true" : "false");
- else if (type_id == CFDataGetTypeID ())
- return cfdata_to_lisp (plist);
- else
- return Qnil;
-}
-#endif
-
-/* Create a new resource database from the preferences for the
- application APPLICATION. APPLICATION is either a string that
- specifies an application ID, or NULL that represents the current
- application. */
-
-XrmDatabase
-xrm_get_preference_database (application)
- const char *application;
-{
-#if TARGET_API_MAC_CARBON
- CFStringRef app_id, *keys, user_doms[2], host_doms[2];
- CFMutableSetRef key_set = NULL;
- CFArrayRef key_array;
- CFIndex index, count;
- char *res_name;
- XrmDatabase database;
- Lisp_Object quarks = Qnil, value = Qnil;
- CFPropertyListRef plist;
- int iu, ih;
- struct gcpro gcpro1, gcpro2, gcpro3;
-
- user_doms[0] = kCFPreferencesCurrentUser;
- user_doms[1] = kCFPreferencesAnyUser;
- host_doms[0] = kCFPreferencesCurrentHost;
- host_doms[1] = kCFPreferencesAnyHost;
-
- database = xrm_create_database ();
-
- GCPRO3 (database, quarks, value);
-
- app_id = kCFPreferencesCurrentApplication;
- if (application)
- {
- app_id = cfstring_create_with_utf8_cstring (application);
- if (app_id == NULL)
- goto out;
- }
- if (!CFPreferencesAppSynchronize (app_id))
- goto out;
-
- key_set = CFSetCreateMutable (NULL, 0, &kCFCopyStringSetCallBacks);
- if (key_set == NULL)
- goto out;
- for (iu = 0; iu < sizeof (user_doms) / sizeof (*user_doms) ; iu++)
- for (ih = 0; ih < sizeof (host_doms) / sizeof (*host_doms); ih++)
- {
- key_array = CFPreferencesCopyKeyList (app_id, user_doms[iu],
- host_doms[ih]);
- if (key_array)
- {
- count = CFArrayGetCount (key_array);
- for (index = 0; index < count; index++)
- CFSetAddValue (key_set,
- CFArrayGetValueAtIndex (key_array, index));
- CFRelease (key_array);
- }
- }
-
- count = CFSetGetCount (key_set);
- keys = xmalloc (sizeof (CFStringRef) * count);
- CFSetGetValues (key_set, (const void **)keys);
- for (index = 0; index < count; index++)
- {
- res_name = SDATA (cfstring_to_lisp_nodecode (keys[index]));
- quarks = parse_resource_name (&res_name);
- if (!(NILP (quarks) || *res_name))
- {
- plist = CFPreferencesCopyAppValue (keys[index], app_id);
- value = xrm_cfproperty_list_to_value (plist);
- CFRelease (plist);
- if (!NILP (value))
- xrm_q_put_resource (database, quarks, value);
- }
- }
-
- xfree (keys);
- out:
- if (key_set)
- CFRelease (key_set);
- CFRelease (app_id);
-
- UNGCPRO;
-
- return database;
-#else
- return xrm_create_database ();
-#endif
-}
-
-
-#ifndef MAC_OSX
-
-/* The following functions with "sys_" prefix are stubs to Unix
- functions that have already been implemented by CW or MPW. The
- calls to them in Emacs source course are #define'd to call the sys_
- versions by the header files s-mac.h. In these stubs pathnames are
- converted between their Unix and Mac forms. */
-
-
-/* Unix epoch is Jan 1, 1970 while Mac epoch is Jan 1, 1904: 66 years
- + 17 leap days. These are for adjusting time values returned by
- MacOS Toolbox functions. */
-
-#define MAC_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-
-#ifdef __MWERKS__
-#if __MSL__ < 0x6000
-/* CW Pro 5 epoch is Jan 1, 1900 (aaarghhhhh!); remember, 1900 is not
- a leap year! This is for adjusting time_t values returned by MSL
- functions. */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 70 + 17) * 24 * 60 * 60)
-#else /* __MSL__ >= 0x6000 */
-/* CW changes Pro 6 to follow Unix! */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-#endif /* __MSL__ >= 0x6000 */
-#elif __MRC__
-/* MPW library functions follow Unix (confused?). */
-#define CW_OR_MPW_UNIX_EPOCH_DIFF ((365L * 66 + 17) * 24 * 60 * 60)
-#else /* not __MRC__ */
-You lose!!!
-#endif /* not __MRC__ */
-
-
-/* Define our own stat function for both MrC and CW. The reason for
- doing this: "stat" is both the name of a struct and function name:
- can't use the same trick like that for sys_open, sys_close, etc. to
- redirect Emacs's calls to our own version that converts Unix style
- filenames to Mac style filename because all sorts of compilation
- errors will be generated if stat is #define'd to be sys_stat. */
-
-int
-stat_noalias (const char *path, struct stat *buf)
-{
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (posix_to_mac_pathname (path, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno == -43) /* -43: fnfErr defined in Errors.h */
- errno = ENOENT;
- if (errno != noErr)
- return -1;
-
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
- {
- buf->st_mode = S_IFDIR | S_IREAD | S_IEXEC;
-
- if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
- buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
- buf->st_ino = cipb.dirInfo.ioDrDirID;
- buf->st_dev = cipb.dirInfo.ioVRefNum;
- buf->st_size = cipb.dirInfo.ioDrNmFls;
- /* size of dir = number of files and dirs */
- buf->st_atime
- = buf->st_mtime
- = cipb.dirInfo.ioDrMdDat - MAC_UNIX_EPOCH_DIFF;
- buf->st_ctime = cipb.dirInfo.ioDrCrDat - MAC_UNIX_EPOCH_DIFF;
- }
- else
- {
- buf->st_mode = S_IFREG | S_IREAD;
- if (!(cipb.hFileInfo.ioFlAttrib & 0x1))
- buf->st_mode |= S_IWRITE; /* bit 1 = 1 for locked files/directories */
- if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
- buf->st_mode |= S_IEXEC;
- buf->st_ino = cipb.hFileInfo.ioDirID;
- buf->st_dev = cipb.hFileInfo.ioVRefNum;
- buf->st_size = cipb.hFileInfo.ioFlLgLen;
- buf->st_atime
- = buf->st_mtime
- = cipb.hFileInfo.ioFlMdDat - MAC_UNIX_EPOCH_DIFF;
- buf->st_ctime = cipb.hFileInfo.ioFlCrDat - MAC_UNIX_EPOCH_DIFF;
- }
-
- if (cipb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000)
- {
- /* identify alias files as symlinks */
- buf->st_mode &= ~S_IFREG;
- buf->st_mode |= S_IFLNK;
- }
-
- buf->st_nlink = 1;
- buf->st_uid = getuid ();
- buf->st_gid = getgid ();
- buf->st_rdev = 0;
-
- return 0;
-}
-
-
-int
-lstat (const char *path, struct stat *buf)
-{
- int result;
- char true_pathname[MAXPATHLEN+1];
-
- /* Try looking for the file without resolving aliases first. */
- if ((result = stat_noalias (path, buf)) >= 0)
- return result;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- return stat_noalias (true_pathname, buf);
-}
-
-
-int
-stat (const char *path, struct stat *sb)
-{
- int result;
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
-
- if ((result = stat_noalias (path, sb)) >= 0 &&
- ! (sb->st_mode & S_IFLNK))
- return result;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- {
- fully_resolved_name[len] = '\0';
- /* in fact our readlink terminates strings */
- return lstat (fully_resolved_name, sb);
- }
- else
- return lstat (true_pathname, sb);
-}
-
-
-#if __MRC__
-/* CW defines fstat in stat.mac.c while MPW does not provide this
- function. Without the information of how to get from a file
- descriptor in MPW StdCLib to a Mac OS file spec, it should be hard
- to implement this function. Fortunately, there is only one place
- where this function is called in our configuration: in fileio.c,
- where only the st_dev and st_ino fields are used to determine
- whether two fildes point to different i-nodes to prevent copying
- a file onto itself equal. What we have here probably needs
- improvement. */
-
-int
-fstat (int fildes, struct stat *buf)
-{
- buf->st_dev = 0;
- buf->st_ino = fildes;
- buf->st_mode = S_IFREG; /* added by T.I. for the copy-file */
- return 0; /* success */
-}
-#endif /* __MRC__ */
-
-
-int
-mkdir (const char *dirname, int mode)
-{
-#pragma unused(mode)
-
- HFileParam hfpb;
- char true_pathname[MAXPATHLEN+1], mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- hfpb.ioNamePtr = mac_pathname;
- hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
- hfpb.ioDirID = 0; /* parent is the root */
-
- errno = PBDirCreate ((HParmBlkPtr) &hfpb, false);
- /* just return the Mac OSErr code for now */
- return errno == noErr ? 0 : -1;
-}
-
-
-#undef rmdir
-sys_rmdir (const char *dirname)
-{
- HFileParam hfpb;
- char mac_pathname[MAXPATHLEN+1];
-
- if (posix_to_mac_pathname (dirname, mac_pathname, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_pathname);
- hfpb.ioNamePtr = mac_pathname;
- hfpb.ioVRefNum = 0; /* ignored unless name is invalid */
- hfpb.ioDirID = 0; /* parent is the root */
-
- errno = PBHDelete ((HParmBlkPtr) &hfpb, false);
- return errno == noErr ? 0 : -1;
-}
-
-
-#ifdef __MRC__
-/* No implementation yet. */
-int
-execvp (const char *path, ...)
-{
- return -1;
-}
-#endif /* __MRC__ */
-
-
-int
-utime (const char *path, const struct utimbuf *times)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- return -1;
-
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* bit 4 = 1 for directories */
- {
- if (times)
- cipb.dirInfo.ioDrMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
- else
- GetDateTime (&cipb.dirInfo.ioDrMdDat);
- }
- else
- {
- if (times)
- cipb.hFileInfo.ioFlMdDat = times->modtime + MAC_UNIX_EPOCH_DIFF;
- else
- GetDateTime (&cipb.hFileInfo.ioFlMdDat);
- }
-
- errno = PBSetCatInfo (&cipb, false);
- return errno == noErr ? 0 : -1;
-}
-
-
-#ifndef F_OK
-#define F_OK 0
-#endif
-#ifndef X_OK
-#define X_OK 1
-#endif
-#ifndef W_OK
-#define W_OK 2
-#endif
-
-/* Like stat, but test for access mode in hfpb.ioFlAttrib */
-int
-access (const char *path, int mode)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
- CInfoPBRec cipb;
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- return -1;
-
- if (mode == F_OK) /* got this far, file exists */
- return 0;
-
- if (mode & X_OK)
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* path refers to a directory */
- return 0;
- else
- {
- if (cipb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')
- return 0;
- else
- return -1;
- }
-
- if (mode & W_OK)
- return (cipb.hFileInfo.ioFlAttrib & 0x1) ? -1 : 0;
- /* don't allow if lock bit is on */
-
- return -1;
-}
-
-
-#define DEV_NULL_FD 0x10000
-
-#undef open
-int
-sys_open (const char *path, int oflag)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (strcmp (path, "/dev/null") == 0)
- return DEV_NULL_FD; /* some bogus fd to be ignored in write */
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- {
-#ifdef __MRC__
- int res = open (mac_pathname, oflag);
- /* if (oflag == O_WRONLY || oflag == O_RDWR) */
- if (oflag & O_CREAT)
- fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
- return res;
-#else /* not __MRC__ */
- return open (mac_pathname, oflag);
-#endif /* not __MRC__ */
- }
-}
-
-
-#undef creat
-int
-sys_creat (const char *path, mode_t mode)
-{
- char true_pathname[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (!posix_to_mac_pathname (true_pathname, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- {
-#ifdef __MRC__
- int result = creat (mac_pathname);
- fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
- return result;
-#else /* not __MRC__ */
- return creat (mac_pathname, mode);
-#endif /* not __MRC__ */
- }
-}
-
-
-#undef unlink
-int
-sys_unlink (const char *path)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (path, true_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return -1;
- else
- return unlink (mac_pathname);
-}
-
-
-#undef read
-int
-sys_read (int fildes, char *buf, int count)
-{
- if (fildes == 0) /* this should not be used for console input */
- return -1;
- else
-#if __MSL__ >= 0x6000
- return _read (fildes, buf, count);
-#else
- return read (fildes, buf, count);
-#endif
-}
-
-
-#undef write
-int
-sys_write (int fildes, const char *buf, int count)
-{
- if (fildes == DEV_NULL_FD)
- return count;
- else
-#if __MSL__ >= 0x6000
- return _write (fildes, buf, count);
-#else
- return write (fildes, buf, count);
-#endif
-}
-
-
-#undef rename
-int
-sys_rename (const char * old_name, const char * new_name)
-{
- char true_old_pathname[MAXPATHLEN+1], true_new_pathname[MAXPATHLEN+1];
- char fully_resolved_old_name[MAXPATHLEN+1];
- int len;
- char mac_old_name[MAXPATHLEN+1], mac_new_name[MAXPATHLEN+1];
-
- if (find_true_pathname (old_name, true_old_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- len = readlink (true_old_pathname, fully_resolved_old_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_old_name[len] = '\0';
- else
- strcpy (fully_resolved_old_name, true_old_pathname);
-
- if (find_true_pathname (new_name, true_new_pathname, MAXPATHLEN+1) == -1)
- return -1;
-
- if (strcmp (fully_resolved_old_name, true_new_pathname) == 0)
- return 0;
-
- if (!posix_to_mac_pathname (fully_resolved_old_name,
- mac_old_name,
- MAXPATHLEN+1))
- return -1;
-
- if (!posix_to_mac_pathname(true_new_pathname, mac_new_name, MAXPATHLEN+1))
- return -1;
-
- /* If a file with new_name already exists, rename deletes the old
- file in Unix. CW version fails in these situation. So we add a
- call to unlink here. */
- (void) unlink (mac_new_name);
-
- return rename (mac_old_name, mac_new_name);
-}
-
-
-#undef fopen
-extern FILE *fopen (const char *name, const char *mode);
-FILE *
-sys_fopen (const char *name, const char *mode)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- int len;
- char mac_pathname[MAXPATHLEN+1];
-
- if (find_true_pathname (name, true_pathname, MAXPATHLEN+1) == -1)
- return 0;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return 0;
- else
- {
-#ifdef __MRC__
- if (mode[0] == 'w' || mode[0] == 'a')
- fsetfileinfo (mac_pathname, MAC_EMACS_CREATOR_CODE, 'TEXT');
-#endif /* not __MRC__ */
- return fopen (mac_pathname, mode);
- }
-}
-
-
-extern Boolean mac_wait_next_event P_ ((EventRecord *, UInt32, Boolean));
-
-int
-select (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- OSStatus err = noErr;
-
- /* Can only handle wait for keyboard input. */
- if (nfds > 1 || wfds || efds)
- return -1;
-
- /* Try detect_input_pending before ReceiveNextEvent in the same
- BLOCK_INPUT block, in case that some input has already been read
- asynchronously. */
- BLOCK_INPUT;
- ENABLE_WAKEUP_FROM_RNE;
- if (!detect_input_pending ())
- {
-#if TARGET_API_MAC_CARBON
- EventTimeout timeoutval =
- (timeout
- ? (EMACS_SECS (*timeout) * kEventDurationSecond
- + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
- : kEventDurationForever);
-
- if (timeoutval == 0.0)
- err = eventLoopTimedOutErr;
- else
- err = ReceiveNextEvent (0, NULL, timeoutval,
- kEventLeaveInQueue, NULL);
-#else /* not TARGET_API_MAC_CARBON */
- EventRecord e;
- UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
- ((EMACS_USECS (*timeout) * 60) / 1000000);
-
- if (sleep_time == 0)
- err = -9875; /* eventLoopTimedOutErr */
- else
- {
- if (mac_wait_next_event (&e, sleep_time, false))
- err = noErr;
- else
- err = -9875; /* eventLoopTimedOutErr */
- }
-#endif /* not TARGET_API_MAC_CARBON */
- }
- DISABLE_WAKEUP_FROM_RNE;
- UNBLOCK_INPUT;
-
- if (err == noErr)
- {
- /* Pretend that `select' is interrupted by a signal. */
- detect_input_pending ();
- errno = EINTR;
- return -1;
- }
- else
- {
- if (rfds)
- FD_ZERO (rfds);
- return 0;
- }
-}
-
-
-/* Simulation of SIGALRM. The stub for function signal stores the
- signal handler function in alarm_signal_func if a SIGALRM is
- encountered. */
-
-#include <signal.h>
-#include "syssignal.h"
-
-static TMTask mac_atimer_task;
-
-static QElemPtr mac_atimer_qlink = (QElemPtr) &mac_atimer_task;
-
-static int signal_mask = 0;
-
-#ifdef __MRC__
-__sigfun alarm_signal_func = (__sigfun) 0;
-#elif __MWERKS__
-__signal_func_ptr alarm_signal_func = (__signal_func_ptr) 0;
-#else /* not __MRC__ and not __MWERKS__ */
-You lose!!!
-#endif /* not __MRC__ and not __MWERKS__ */
-
-#undef signal
-#ifdef __MRC__
-extern __sigfun signal (int signal, __sigfun signal_func);
-__sigfun
-sys_signal (int signal_num, __sigfun signal_func)
-#elif __MWERKS__
-extern __signal_func_ptr signal (int signal, __signal_func_ptr signal_func);
-__signal_func_ptr
-sys_signal (int signal_num, __signal_func_ptr signal_func)
-#else /* not __MRC__ and not __MWERKS__ */
- You lose!!!
-#endif /* not __MRC__ and not __MWERKS__ */
-{
- if (signal_num != SIGALRM)
- return signal (signal_num, signal_func);
- else
- {
-#ifdef __MRC__
- __sigfun old_signal_func;
-#elif __MWERKS__
- __signal_func_ptr old_signal_func;
-#else
- You lose!!!
-#endif
- old_signal_func = alarm_signal_func;
- alarm_signal_func = signal_func;
- return old_signal_func;
- }
-}
-
-
-static pascal void
-mac_atimer_handler (qlink)
- TMTaskPtr qlink;
-{
- if (alarm_signal_func)
- (alarm_signal_func) (SIGALRM);
-}
-
-
-static void
-set_mac_atimer (count)
- long count;
-{
- static TimerUPP mac_atimer_handlerUPP = NULL;
-
- if (mac_atimer_handlerUPP == NULL)
- mac_atimer_handlerUPP = NewTimerUPP (mac_atimer_handler);
- mac_atimer_task.tmCount = 0;
- mac_atimer_task.tmAddr = mac_atimer_handlerUPP;
- mac_atimer_qlink = (QElemPtr) &mac_atimer_task;
- InsTime (mac_atimer_qlink);
- if (count)
- PrimeTime (mac_atimer_qlink, count);
-}
-
-
-int
-remove_mac_atimer (remaining_count)
- long *remaining_count;
-{
- if (mac_atimer_qlink)
- {
- RmvTime (mac_atimer_qlink);
- if (remaining_count)
- *remaining_count = mac_atimer_task.tmCount;
- mac_atimer_qlink = NULL;
-
- return 0;
- }
- else
- return -1;
-}
-
-
-int
-sigblock (int mask)
-{
- int old_mask = signal_mask;
-
- signal_mask |= mask;
-
- if ((old_mask ^ signal_mask) & sigmask (SIGALRM))
- remove_mac_atimer (NULL);
-
- return old_mask;
-}
-
-
-int
-sigsetmask (int mask)
-{
- int old_mask = signal_mask;
-
- signal_mask = mask;
-
- if ((old_mask ^ signal_mask) & sigmask (SIGALRM))
- if (signal_mask & sigmask (SIGALRM))
- remove_mac_atimer (NULL);
- else
- set_mac_atimer (mac_atimer_task.tmCount);
-
- return old_mask;
-}
-
-
-int
-alarm (int seconds)
-{
- long remaining_count;
-
- if (remove_mac_atimer (&remaining_count) == 0)
- {
- set_mac_atimer (seconds * 1000);
-
- return remaining_count / 1000;
- }
- else
- {
- mac_atimer_task.tmCount = seconds * 1000;
-
- return 0;
- }
-}
-
-
-int
-setitimer (which, value, ovalue)
- int which;
- const struct itimerval *value;
- struct itimerval *ovalue;
-{
- long remaining_count;
- long count = (EMACS_SECS (value->it_value) * 1000
- + (EMACS_USECS (value->it_value) + 999) / 1000);
-
- if (remove_mac_atimer (&remaining_count) == 0)
- {
- if (ovalue)
- {
- bzero (ovalue, sizeof (*ovalue));
- EMACS_SET_SECS_USECS (ovalue->it_value, remaining_count / 1000,
- (remaining_count % 1000) * 1000);
- }
- set_mac_atimer (count);
- }
- else
- mac_atimer_task.tmCount = count;
-
- return 0;
-}
-
-
-/* gettimeofday should return the amount of time (in a timeval
- structure) since midnight today. The toolbox function Microseconds
- returns the number of microseconds (in a UnsignedWide value) since
- the machine was booted. Also making this complicated is WideAdd,
- WideSubtract, etc. take wide values. */
-
-int
-gettimeofday (tp)
- struct timeval *tp;
-{
- static inited = 0;
- static wide wall_clock_at_epoch, clicks_at_epoch;
- UnsignedWide uw_microseconds;
- wide w_microseconds;
- time_t sys_time (time_t *);
-
- /* If this function is called for the first time, record the number
- of seconds since midnight and the number of microseconds since
- boot at the time of this first call. */
- if (!inited)
- {
- time_t systime;
- inited = 1;
- systime = sys_time (NULL);
- /* Store microseconds since midnight in wall_clock_at_epoch. */
- WideMultiply (systime, 1000000L, &wall_clock_at_epoch);
- Microseconds (&uw_microseconds);
- /* Store microseconds since boot in clicks_at_epoch. */
- clicks_at_epoch.hi = uw_microseconds.hi;
- clicks_at_epoch.lo = uw_microseconds.lo;
- }
-
- /* Get time since boot */
- Microseconds (&uw_microseconds);
-
- /* Convert to time since midnight*/
- w_microseconds.hi = uw_microseconds.hi;
- w_microseconds.lo = uw_microseconds.lo;
- WideSubtract (&w_microseconds, &clicks_at_epoch);
- WideAdd (&w_microseconds, &wall_clock_at_epoch);
- tp->tv_sec = WideDivide (&w_microseconds, 1000000L, &tp->tv_usec);
-
- return 0;
-}
-
-
-#ifdef __MRC__
-unsigned int
-sleep (unsigned int seconds)
-{
- unsigned long time_up;
- EventRecord e;
-
- time_up = TickCount () + seconds * 60;
- while (TickCount () < time_up)
- {
- /* Accept no event; just wait. by T.I. */
- WaitNextEvent (0, &e, 30, NULL);
- }
-
- return (0);
-}
-#endif /* __MRC__ */
-
-
-/* The time functions adjust time values according to the difference
- between the Unix and CW epoches. */
-
-#undef gmtime
-extern struct tm *gmtime (const time_t *);
-struct tm *
-sys_gmtime (const time_t *timer)
-{
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-
- return gmtime (&unix_time);
-}
-
-
-#undef localtime
-extern struct tm *localtime (const time_t *);
-struct tm *
-sys_localtime (const time_t *timer)
-{
-#if __MSL__ >= 0x6000
- time_t unix_time = *timer;
-#else
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- return localtime (&unix_time);
-}
-
-
-#undef ctime
-extern char *ctime (const time_t *);
-char *
-sys_ctime (const time_t *timer)
-{
-#if __MSL__ >= 0x6000
- time_t unix_time = *timer;
-#else
- time_t unix_time = *timer + CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- return ctime (&unix_time);
-}
-
-
-#undef time
-extern time_t time (time_t *);
-time_t
-sys_time (time_t *timer)
-{
-#if __MSL__ >= 0x6000
- time_t mac_time = time (NULL);
-#else
- time_t mac_time = time (NULL) - CW_OR_MPW_UNIX_EPOCH_DIFF;
-#endif
-
- if (timer)
- *timer = mac_time;
-
- return mac_time;
-}
-
-
-/* no subprocesses, empty wait */
-
-int
-wait (int pid)
-{
- return 0;
-}
-
-
-void
-croak (char *badfunc)
-{
- printf ("%s not yet implemented\r\n", badfunc);
- exit (1);
-}
-
-
-char *
-mktemp (char *template)
-{
- int len, k;
- static seqnum = 0;
-
- len = strlen (template);
- k = len - 1;
- while (k >= 0 && template[k] == 'X')
- k--;
-
- k++; /* make k index of first 'X' */
-
- if (k < len)
- {
- /* Zero filled, number of digits equal to the number of X's. */
- sprintf (&template[k], "%0*d", len-k, seqnum++);
-
- return template;
- }
- else
- return 0;
-}
-
-
-/* Emulate getpwuid, getpwnam and others. */
-
-#define PASSWD_FIELD_SIZE 256
-
-static char my_passwd_name[PASSWD_FIELD_SIZE];
-static char my_passwd_dir[MAXPATHLEN+1];
-
-static struct passwd my_passwd =
-{
- my_passwd_name,
- my_passwd_dir,
-};
-
-static struct group my_group =
-{
- /* There are no groups on the mac, so we just return "root" as the
- group name. */
- "root",
-};
-
-
-/* Initialized by main () in macterm.c to pathname of emacs directory. */
-
-char emacs_passwd_dir[MAXPATHLEN+1];
-
-char *
-getwd (char *);
-
-void
-init_emacs_passwd_dir ()
-{
- int found = false;
-
- if (getwd (emacs_passwd_dir) && getwd (my_passwd_dir))
- {
- /* Need pathname of first ancestor that begins with "emacs"
- since Mac emacs application is somewhere in the emacs-*
- tree. */
- int len = strlen (emacs_passwd_dir);
- int j = len - 1;
- /* j points to the "/" following the directory name being
- compared. */
- int i = j - 1;
- while (i >= 0 && !found)
- {
- while (i >= 0 && emacs_passwd_dir[i] != '/')
- i--;
- if (emacs_passwd_dir[i] == '/' && i+5 < len)
- found = (strncmp (&(emacs_passwd_dir[i+1]), "emacs", 5) == 0);
- if (found)
- emacs_passwd_dir[j+1] = '\0';
- else
- {
- j = i;
- i = j - 1;
- }
- }
- }
-
- if (!found)
- {
- /* Setting to "/" probably won't work but set it to something
- anyway. */
- strcpy (emacs_passwd_dir, "/");
- strcpy (my_passwd_dir, "/");
- }
-}
-
-
-static struct passwd emacs_passwd =
-{
- "emacs",
- emacs_passwd_dir,
-};
-
-static int my_passwd_inited = 0;
-
-
-static void
-init_my_passwd ()
-{
- char **owner_name;
-
- /* Note: my_passwd_dir initialized in int_emacs_passwd_dir to
- directory where Emacs was started. */
-
- owner_name = (char **) GetResource ('STR ',-16096);
- if (owner_name)
- {
- HLock (owner_name);
- BlockMove ((unsigned char *) *owner_name,
- (unsigned char *) my_passwd_name,
- *owner_name[0]+1);
- HUnlock (owner_name);
- p2cstr ((unsigned char *) my_passwd_name);
- }
- else
- my_passwd_name[0] = 0;
-}
-
-
-struct passwd *
-getpwuid (uid_t uid)
-{
- if (!my_passwd_inited)
- {
- init_my_passwd ();
- my_passwd_inited = 1;
- }
-
- return &my_passwd;
-}
-
-
-struct group *
-getgrgid (gid_t gid)
-{
- return &my_group;
-}
-
-
-struct passwd *
-getpwnam (const char *name)
-{
- if (strcmp (name, "emacs") == 0)
- return &emacs_passwd;
-
- if (!my_passwd_inited)
- {
- init_my_passwd ();
- my_passwd_inited = 1;
- }
-
- return &my_passwd;
-}
-
-
-/* The functions fork, kill, sigsetmask, sigblock, request_sigio,
- setpgrp, setpriority, and unrequest_sigio are defined to be empty
- as in msdos.c. */
-
-
-int
-fork ()
-{
- return -1;
-}
-
-
-int
-kill (int x, int y)
-{
- return -1;
-}
-
-
-void
-sys_subshell ()
-{
- error ("Can't spawn subshell");
-}
-
-
-void
-request_sigio (void)
-{
-}
-
-
-void
-unrequest_sigio (void)
-{
-}
-
-
-int
-setpgrp ()
-{
- return 0;
-}
-
-
-/* No pipes yet. */
-
-int
-pipe (int _fildes[2])
-{
- errno = EACCES;
- return -1;
-}
-
-
-/* Hard and symbolic links. */
-
-int
-symlink (const char *name1, const char *name2)
-{
- errno = ENOENT;
- return -1;
-}
-
-
-int
-link (const char *name1, const char *name2)
-{
- errno = ENOENT;
- return -1;
-}
-
-#endif /* ! MAC_OSX */
-
-/* Determine the path name of the file specified by VREFNUM, DIRID,
- and NAME and place that in the buffer PATH of length
- MAXPATHLEN. */
-static int
-path_from_vol_dir_name (char *path, int man_path_len, short vol_ref_num,
- long dir_id, ConstStr255Param name)
-{
- Str255 dir_name;
- CInfoPBRec cipb;
- OSErr err;
-
- if (strlen (name) > man_path_len)
- return 0;
-
- memcpy (dir_name, name, name[0]+1);
- memcpy (path, name, name[0]+1);
- p2cstr (path);
-
- cipb.dirInfo.ioDrParID = dir_id;
- cipb.dirInfo.ioNamePtr = dir_name;
-
- do
- {
- cipb.dirInfo.ioVRefNum = vol_ref_num;
- cipb.dirInfo.ioFDirIndex = -1;
- cipb.dirInfo.ioDrDirID = cipb.dirInfo.ioDrParID;
- /* go up to parent each time */
-
- err = PBGetCatInfo (&cipb, false);
- if (err != noErr)
- return 0;
-
- p2cstr (dir_name);
- if (strlen (dir_name) + strlen (path) + 1 >= man_path_len)
- return 0;
-
- strcat (dir_name, ":");
- strcat (dir_name, path);
- /* attach to front since we're going up directory tree */
- strcpy (path, dir_name);
- }
- while (cipb.dirInfo.ioDrDirID != fsRtDirID);
- /* stop when we see the volume's root directory */
-
- return 1; /* success */
-}
-
-
-#ifndef MAC_OSX
-
-static OSErr
-posix_pathname_to_fsspec (ufn, fs)
- const char *ufn;
- FSSpec *fs;
-{
- Str255 mac_pathname;
-
- if (posix_to_mac_pathname (ufn, mac_pathname, sizeof (mac_pathname)) == 0)
- return fnfErr;
- else
- {
- c2pstr (mac_pathname);
- return FSMakeFSSpec (0, 0, mac_pathname, fs);
- }
-}
-
-static OSErr
-fsspec_to_posix_pathname (fs, ufn, ufnbuflen)
- const FSSpec *fs;
- char *ufn;
- int ufnbuflen;
-{
- char mac_pathname[MAXPATHLEN];
-
- if (path_from_vol_dir_name (mac_pathname, sizeof (mac_pathname) - 1,
- fs->vRefNum, fs->parID, fs->name)
- && mac_to_posix_pathname (mac_pathname, ufn, ufnbuflen))
- return noErr;
- else
- return fnfErr;
-}
-
-int
-readlink (const char *path, char *buf, int bufsiz)
-{
- char mac_sym_link_name[MAXPATHLEN+1];
- OSErr err;
- FSSpec fsspec;
- Boolean target_is_folder, was_aliased;
- Str255 directory_name, mac_pathname;
- CInfoPBRec cipb;
-
- if (posix_to_mac_pathname (path, mac_sym_link_name, MAXPATHLEN+1) == 0)
- return -1;
-
- c2pstr (mac_sym_link_name);
- err = FSMakeFSSpec (0, 0, mac_sym_link_name, &fsspec);
- if (err != noErr)
- {
- errno = ENOENT;
- return -1;
- }
-
- err = ResolveAliasFile (&fsspec, true, &target_is_folder, &was_aliased);
- if (err != noErr || !was_aliased)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (path_from_vol_dir_name (mac_pathname, 255, fsspec.vRefNum, fsspec.parID,
- fsspec.name) == 0)
- {
- errno = ENOENT;
- return -1;
- }
-
- if (mac_to_posix_pathname (mac_pathname, buf, bufsiz) == 0)
- {
- errno = ENOENT;
- return -1;
- }
-
- return strlen (buf);
-}
-
-
-/* Convert a path to one with aliases fully expanded. */
-
-static int
-find_true_pathname (const char *path, char *buf, int bufsiz)
-{
- char *q, temp[MAXPATHLEN+1];
- const char *p;
- int len;
-
- if (bufsiz <= 0 || path == 0 || path[0] == '\0')
- return -1;
-
- buf[0] = '\0';
-
- p = path;
- if (*p == '/')
- q = strchr (p + 1, '/');
- else
- q = strchr (p, '/');
- len = 0; /* loop may not be entered, e.g., for "/" */
-
- while (q)
- {
- strcpy (temp, buf);
- strncat (temp, p, q - p);
- len = readlink (temp, buf, bufsiz);
- if (len <= -1)
- {
- if (strlen (temp) + 1 > bufsiz)
- return -1;
- strcpy (buf, temp);
- }
- strcat (buf, "/");
- len++;
- p = q + 1;
- q = strchr(p, '/');
- }
-
- if (len + strlen (p) + 1 >= bufsiz)
- return -1;
-
- strcat (buf, p);
- return len + strlen (p);
-}
-
-
-mode_t
-umask (mode_t numask)
-{
- static mode_t mask = 022;
- mode_t oldmask = mask;
- mask = numask;
- return oldmask;
-}
-
-
-int
-chmod (const char *path, mode_t mode)
-{
- /* say it always succeed for now */
- return 0;
-}
-
-
-int
-fchmod (int fd, mode_t mode)
-{
- /* say it always succeed for now */
- return 0;
-}
-
-
-int
-fchown (int fd, uid_t owner, gid_t group)
-{
- /* say it always succeed for now */
- return 0;
-}
-
-
-int
-dup (int oldd)
-{
-#ifdef __MRC__
- return fcntl (oldd, F_DUPFD, 0);
-#elif __MWERKS__
- /* current implementation of fcntl in fcntl.mac.c simply returns old
- descriptor */
- return fcntl (oldd, F_DUPFD);
-#else
-You lose!!!
-#endif
-}
-
-
-/* This is from the original sysdep.c. Emulate BSD dup2. First close
- newd if it already exists. Then, attempt to dup oldd. If not
- successful, call dup2 recursively until we are, then close the
- unsuccessful ones. */
-
-int
-dup2 (int oldd, int newd)
-{
- int fd, ret;
-
- close (newd);
-
- fd = dup (oldd);
- if (fd == -1)
- return -1;
- if (fd == newd)
- return newd;
- ret = dup2 (oldd, newd);
- close (fd);
- return ret;
-}
-
-
-/* let it fail for now */
-
-char *
-sbrk (int incr)
-{
- return (char *) -1;
-}
-
-
-int
-fsync (int fd)
-{
- return 0;
-}
-
-
-int
-ioctl (int d, int request, void *argp)
-{
- return -1;
-}
-
-
-#ifdef __MRC__
-int
-isatty (int fildes)
-{
- if (fildes >=0 && fildes <= 2)
- return 1;
- else
- return 0;
-}
-
-
-int
-getgid ()
-{
- return 100;
-}
-
-
-int
-getegid ()
-{
- return 100;
-}
-
-
-int
-getuid ()
-{
- return 200;
-}
-
-
-int
-geteuid ()
-{
- return 200;
-}
-#endif /* __MRC__ */
-
-
-#ifdef __MWERKS__
-#if __MSL__ < 0x6000
-#undef getpid
-int
-getpid ()
-{
- return 9999;
-}
-#endif
-#endif /* __MWERKS__ */
-
-#endif /* ! MAC_OSX */
-
-
-/* Return the path to the directory in which Emacs can create
- temporary files. The MacOS "temporary items" directory cannot be
- used because it removes the file written by a process when it
- exits. In that sense it's more like "/dev/null" than "/tmp" (but
- again not exactly). And of course Emacs needs to read back the
- files written by its subprocesses. So here we write the files to a
- directory "Emacs" in the Preferences Folder. This directory is
- created if it does not exist. */
-
-char *
-get_temp_dir_name ()
-{
- static char *temp_dir_name = NULL;
- short vol_ref_num;
- long dir_id;
- OSErr err;
- Str255 full_path;
- char unix_dir_name[MAXPATHLEN+1];
- DIR *dir;
-
- /* Cache directory name with pointer temp_dir_name.
- Look for it only the first time. */
- if (!temp_dir_name)
- {
- err = FindFolder (kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- &vol_ref_num, &dir_id);
- if (err != noErr)
- return NULL;
-
- if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
- return NULL;
-
- if (strlen (full_path) + 6 <= MAXPATHLEN)
- strcat (full_path, "Emacs:");
- else
- return NULL;
-
- if (!mac_to_posix_pathname (full_path, unix_dir_name, MAXPATHLEN+1))
- return NULL;
-
- dir = opendir (unix_dir_name); /* check whether temp directory exists */
- if (dir)
- closedir (dir);
- else if (mkdir (unix_dir_name, 0700) != 0) /* create it if not */
- return NULL;
-
- temp_dir_name = (char *) malloc (strlen (unix_dir_name) + 1);
- strcpy (temp_dir_name, unix_dir_name);
- }
-
- return temp_dir_name;
-}
-
-#ifndef MAC_OSX
-
-/* Allocate and construct an array of pointers to strings from a list
- of strings stored in a 'STR#' resource. The returned pointer array
- is stored in the style of argv and environ: if the 'STR#' resource
- contains numString strings, a pointer array with numString+1
- elements is returned in which the last entry contains a null
- pointer. The pointer to the pointer array is passed by pointer in
- parameter t. The resource ID of the 'STR#' resource is passed in
- parameter StringListID.
- */
-
-void
-get_string_list (char ***t, short string_list_id)
-{
- Handle h;
- Ptr p;
- int i, num_strings;
-
- h = GetResource ('STR#', string_list_id);
- if (h)
- {
- HLock (h);
- p = *h;
- num_strings = * (short *) p;
- p += sizeof(short);
- *t = (char **) malloc (sizeof (char *) * (num_strings + 1));
- for (i = 0; i < num_strings; i++)
- {
- short length = *p++;
- (*t)[i] = (char *) malloc (length + 1);
- strncpy ((*t)[i], p, length);
- (*t)[i][length] = '\0';
- p += length;
- }
- (*t)[num_strings] = 0;
- HUnlock (h);
- }
- else
- {
- /* Return no string in case GetResource fails. Bug fixed by
- Ikegami Tsutomu. Caused MPW build to crash without sym -on
- option (no sym -on implies -opt local). */
- *t = (char **) malloc (sizeof (char *));
- (*t)[0] = 0;
- }
-}
-
-
-static char *
-get_path_to_system_folder ()
-{
- short vol_ref_num;
- long dir_id;
- OSErr err;
- Str255 full_path;
- static char system_folder_unix_name[MAXPATHLEN+1];
- DIR *dir;
-
- err = FindFolder (kOnSystemDisk, kSystemFolderType, kDontCreateFolder,
- &vol_ref_num, &dir_id);
- if (err != noErr)
- return NULL;
-
- if (!path_from_vol_dir_name (full_path, 255, vol_ref_num, dir_id, "\p"))
- return NULL;
-
- if (!mac_to_posix_pathname (full_path, system_folder_unix_name,
- MAXPATHLEN+1))
- return NULL;
-
- return system_folder_unix_name;
-}
-
-
-char **environ;
-
-#define ENVIRON_STRING_LIST_ID 128
-
-/* Get environment variable definitions from STR# resource. */
-
-void
-init_environ ()
-{
- int i;
-
- get_string_list (&environ, ENVIRON_STRING_LIST_ID);
-
- i = 0;
- while (environ[i])
- i++;
-
- /* Make HOME directory the one Emacs starts up in if not specified
- by resource. */
- if (getenv ("HOME") == NULL)
- {
- environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
- if (environ)
- {
- environ[i] = (char *) malloc (strlen (my_passwd_dir) + 6);
- if (environ[i])
- {
- strcpy (environ[i], "HOME=");
- strcat (environ[i], my_passwd_dir);
- }
- environ[i+1] = 0;
- i++;
- }
- }
-
- /* Make HOME directory the one Emacs starts up in if not specified
- by resource. */
- if (getenv ("MAIL") == NULL)
- {
- environ = (char **) realloc (environ, sizeof (char *) * (i + 2));
- if (environ)
- {
- char * path_to_system_folder = get_path_to_system_folder ();
- environ[i] = (char *) malloc (strlen (path_to_system_folder) + 22);
- if (environ[i])
- {
- strcpy (environ[i], "MAIL=");
- strcat (environ[i], path_to_system_folder);
- strcat (environ[i], "Eudora Folder/In");
- }
- environ[i+1] = 0;
- }
- }
-}
-
-
-/* Return the value of the environment variable NAME. */
-
-char *
-getenv (const char *name)
-{
- int length = strlen(name);
- char **e;
-
- for (e = environ; *e != 0; e++)
- if (strncmp(*e, name, length) == 0 && (*e)[length] == '=')
- return &(*e)[length + 1];
-
- if (strcmp (name, "TMPDIR") == 0)
- return get_temp_dir_name ();
-
- return 0;
-}
-
-
-#ifdef __MRC__
-/* see Interfaces&Libraries:Interfaces:CIncludes:signal.h */
-char *sys_siglist[] =
-{
- "Zero is not a signal!!!",
- "Abort", /* 1 */
- "Interactive user interrupt", /* 2 */ "?",
- "Floating point exception", /* 4 */ "?", "?", "?",
- "Illegal instruction", /* 8 */ "?", "?", "?", "?", "?", "?", "?",
- "Segment violation", /* 16 */ "?", "?", "?", "?", "?", "?", "?",
- "?", "?", "?", "?", "?", "?", "?", "?",
- "Terminal" /* 32 */
-};
-#elif __MWERKS__
-char *sys_siglist[] =
-{
- "Zero is not a signal!!!",
- "Abort",
- "Floating point exception",
- "Illegal instruction",
- "Interactive user interrupt",
- "Segment violation",
- "Terminal"
-};
-#else /* not __MRC__ and not __MWERKS__ */
-You lose!!!
-#endif /* not __MRC__ and not __MWERKS__ */
-
-
-#include <utsname.h>
-
-int
-uname (struct utsname *name)
-{
- char **system_name;
- system_name = GetString (-16413); /* IM - Resource Manager Reference */
- if (system_name)
- {
- BlockMove (*system_name, name->nodename, (*system_name)[0]+1);
- p2cstr (name->nodename);
- return 0;
- }
- else
- return -1;
-}
-
-
-/* Event class of HLE sent to subprocess. */
-const OSType kEmacsSubprocessSend = 'ESND';
-
-/* Event class of HLE sent back from subprocess. */
-const OSType kEmacsSubprocessReply = 'ERPY';
-
-
-char *
-mystrchr (char *s, char c)
-{
- while (*s && *s != c)
- {
- if (*s == '\\')
- s++;
- s++;
- }
-
- if (*s)
- {
- *s = '\0';
- return s;
- }
- else
- return NULL;
-}
-
-
-char *
-mystrtok (char *s)
-{
- while (*s)
- s++;
-
- return s + 1;
-}
-
-
-void
-mystrcpy (char *to, char *from)
-{
- while (*from)
- {
- if (*from == '\\')
- from++;
- *to++ = *from++;
- }
- *to = '\0';
-}
-
-
-/* Start a Mac subprocess. Arguments for it is passed in argv (null
- terminated). The process should run with the default directory
- "workdir", read input from "infn", and write output and error to
- "outfn" and "errfn", resp. The Process Manager call
- LaunchApplication is used to start the subprocess. We use high
- level events as the mechanism to pass arguments to the subprocess
- and to make Emacs wait for the subprocess to terminate and pass
- back a result code. The bulk of the code here packs the arguments
- into one message to be passed together with the high level event.
- Emacs also sometimes starts a subprocess using a shell to perform
- wildcard filename expansion. Since we don't really have a shell on
- the Mac, this case is detected and the starting of the shell is
- by-passed. We really need to add code here to do filename
- expansion to support such functionality.
-
- We can't use this strategy in Carbon because the High Level Event
- APIs are not available. */
-
-int
-run_mac_command (argv, workdir, infn, outfn, errfn)
- unsigned char **argv;
- const char *workdir;
- const char *infn, *outfn, *errfn;
-{
-#if TARGET_API_MAC_CARBON
- return -1;
-#else /* not TARGET_API_MAC_CARBON */
- char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
- char macinfn[MAXPATHLEN+1], macoutfn[MAXPATHLEN+1], macerrfn[MAXPATHLEN+1];
- int paramlen, argc, newargc, j, retries;
- char **newargv, *param, *p;
- OSErr iErr;
- FSSpec spec;
- LaunchParamBlockRec lpbr;
- EventRecord send_event, reply_event;
- RgnHandle cursor_region_handle;
- TargetID targ;
- unsigned long ref_con, len;
-
- if (posix_to_mac_pathname (workdir, macworkdir, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (infn, macinfn, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (outfn, macoutfn, MAXPATHLEN+1) == 0)
- return -1;
- if (posix_to_mac_pathname (errfn, macerrfn, MAXPATHLEN+1) == 0)
- return -1;
-
- paramlen = strlen (macworkdir) + strlen (macinfn) + strlen (macoutfn)
- + strlen (macerrfn) + 4; /* count nulls at end of strings */
-
- argc = 0;
- while (argv[argc])
- argc++;
-
- if (argc == 0)
- return -1;
-
- /* If a subprocess is invoked with a shell, we receive 3 arguments
- of the form: "<path to emacs bins>/sh" "-c" "<path to emacs
- bins>/<command> <command args>" */
- j = strlen (argv[0]);
- if (j >= 3 && strcmp (argv[0]+j-3, "/sh") == 0
- && argc == 3 && strcmp (argv[1], "-c") == 0)
- {
- char *command, *t, tempmacpathname[MAXPATHLEN+1];
-
- /* The arguments for the command in argv[2] are separated by
- spaces. Count them and put the count in newargc. */
- command = (char *) alloca (strlen (argv[2])+2);
- strcpy (command, argv[2]);
- if (command[strlen (command) - 1] != ' ')
- strcat (command, " ");
-
- t = command;
- newargc = 0;
- t = mystrchr (t, ' ');
- while (t)
- {
- newargc++;
- t = mystrchr (t+1, ' ');
- }
-
- newargv = (char **) alloca (sizeof (char *) * newargc);
-
- t = command;
- for (j = 0; j < newargc; j++)
- {
- newargv[j] = (char *) alloca (strlen (t) + 1);
- mystrcpy (newargv[j], t);
-
- t = mystrtok (t);
- paramlen += strlen (newargv[j]) + 1;
- }
-
- if (strncmp (newargv[0], "~emacs/", 7) == 0)
- {
- if (posix_to_mac_pathname (newargv[0], tempmacpathname, MAXPATHLEN+1)
- == 0)
- return -1;
- }
- else
- { /* sometimes Emacs call "sh" without a path for the command */
-#if 0
- char *t = (char *) alloca (strlen (newargv[0]) + 7 + 1);
- strcpy (t, "~emacs/");
- strcat (t, newargv[0]);
-#endif /* 0 */
- Lisp_Object path;
- openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path,
- make_number (X_OK));
-
- if (NILP (path))
- return -1;
- if (posix_to_mac_pathname (SDATA (path), tempmacpathname,
- MAXPATHLEN+1) == 0)
- return -1;
- }
- strcpy (macappname, tempmacpathname);
- }
- else
- {
- if (posix_to_mac_pathname (argv[0], macappname, MAXPATHLEN+1) == 0)
- return -1;
-
- newargv = (char **) alloca (sizeof (char *) * argc);
- newargc = argc;
- for (j = 1; j < argc; j++)
- {
- if (strncmp (argv[j], "~emacs/", 7) == 0)
- {
- char *t = strchr (argv[j], ' ');
- if (t)
- {
- char tempcmdname[MAXPATHLEN+1], tempmaccmdname[MAXPATHLEN+1];
- strncpy (tempcmdname, argv[j], t-argv[j]);
- tempcmdname[t-argv[j]] = '\0';
- if (posix_to_mac_pathname (tempcmdname, tempmaccmdname,
- MAXPATHLEN+1) == 0)
- return -1;
- newargv[j] = (char *) alloca (strlen (tempmaccmdname)
- + strlen (t) + 1);
- strcpy (newargv[j], tempmaccmdname);
- strcat (newargv[j], t);
- }
- else
- {
- char tempmaccmdname[MAXPATHLEN+1];
- if (posix_to_mac_pathname (argv[j], tempmaccmdname,
- MAXPATHLEN+1) == 0)
- return -1;
- newargv[j] = (char *) alloca (strlen (tempmaccmdname)+1);
- strcpy (newargv[j], tempmaccmdname);
- }
- }
- else
- newargv[j] = argv[j];
- paramlen += strlen (newargv[j]) + 1;
- }
- }
-
- /* After expanding all the arguments, we now know the length of the
- parameter block to be sent to the subprocess as a message
- attached to the HLE. */
- param = (char *) malloc (paramlen + 1);
- if (!param)
- return -1;
-
- p = param;
- *p++ = newargc;
- /* first byte of message contains number of arguments for command */
- strcpy (p, macworkdir);
- p += strlen (macworkdir);
- *p++ = '\0';
- /* null terminate strings sent so it's possible to use strcpy over there */
- strcpy (p, macinfn);
- p += strlen (macinfn);
- *p++ = '\0';
- strcpy (p, macoutfn);
- p += strlen (macoutfn);
- *p++ = '\0';
- strcpy (p, macerrfn);
- p += strlen (macerrfn);
- *p++ = '\0';
- for (j = 1; j < newargc; j++)
- {
- strcpy (p, newargv[j]);
- p += strlen (newargv[j]);
- *p++ = '\0';
- }
-
- c2pstr (macappname);
-
- iErr = FSMakeFSSpec (0, 0, macappname, &spec);
-
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- lpbr.launchBlockID = extendedBlock;
- lpbr.launchEPBLength = extendedBlockLen;
- lpbr.launchControlFlags = launchContinue + launchNoFileFlags;
- lpbr.launchAppSpec = &spec;
- lpbr.launchAppParameters = NULL;
-
- iErr = LaunchApplication (&lpbr); /* call the subprocess */
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- send_event.what = kHighLevelEvent;
- send_event.message = kEmacsSubprocessSend;
- /* Event ID stored in "where" unused */
-
- retries = 3;
- /* OS may think current subprocess has terminated if previous one
- terminated recently. */
- do
- {
- iErr = PostHighLevelEvent (&send_event, &lpbr.launchProcessSN, 0, param,
- paramlen + 1, receiverIDisPSN);
- }
- while (iErr == sessClosedErr && retries-- > 0);
-
- if (iErr != noErr)
- {
- free (param);
- return -1;
- }
-
- cursor_region_handle = NewRgn ();
-
- /* Wait for the subprocess to finish, when it will send us a ERPY
- high level event. */
- while (1)
- if (WaitNextEvent (highLevelEventMask, &reply_event, 180,
- cursor_region_handle)
- && reply_event.message == kEmacsSubprocessReply)
- break;
-
- /* The return code is sent through the refCon */
- iErr = AcceptHighLevelEvent (&targ, &ref_con, NULL, &len);
- if (iErr != noErr)
- {
- DisposeHandle ((Handle) cursor_region_handle);
- free (param);
- return -1;
- }
-
- DisposeHandle ((Handle) cursor_region_handle);
- free (param);
-
- return ref_con;
-#endif /* not TARGET_API_MAC_CARBON */
-}
-
-
-DIR *
-opendir (const char *dirname)
-{
- char true_pathname[MAXPATHLEN+1], fully_resolved_name[MAXPATHLEN+1];
- char mac_pathname[MAXPATHLEN+1], vol_name[MAXPATHLEN+1];
- DIR *dirp;
- CInfoPBRec cipb;
- HVolumeParam vpb;
- int len, vol_name_len;
-
- if (find_true_pathname (dirname, true_pathname, MAXPATHLEN+1) == -1)
- return 0;
-
- len = readlink (true_pathname, fully_resolved_name, MAXPATHLEN);
- if (len > -1)
- fully_resolved_name[len] = '\0';
- else
- strcpy (fully_resolved_name, true_pathname);
-
- dirp = (DIR *) malloc (sizeof(DIR));
- if (!dirp)
- return 0;
-
- /* Handle special case when dirname is "/": sets up for readir to
- get all mount volumes. */
- if (strcmp (fully_resolved_name, "/") == 0)
- {
- dirp->getting_volumes = 1; /* special all mounted volumes DIR struct */
- dirp->current_index = 1; /* index for first volume */
- return dirp;
- }
-
- /* Handle typical cases: not accessing all mounted volumes. */
- if (!posix_to_mac_pathname (fully_resolved_name, mac_pathname, MAXPATHLEN+1))
- return 0;
-
- /* Emacs calls opendir without the trailing '/', Mac needs trailing ':' */
- len = strlen (mac_pathname);
- if (mac_pathname[len - 1] != ':' && len < MAXPATHLEN)
- strcat (mac_pathname, ":");
-
- /* Extract volume name */
- vol_name_len = strchr (mac_pathname, ':') - mac_pathname;
- strncpy (vol_name, mac_pathname, vol_name_len);
- vol_name[vol_name_len] = '\0';
- strcat (vol_name, ":");
-
- c2pstr (mac_pathname);
- cipb.hFileInfo.ioNamePtr = mac_pathname;
- /* using full pathname so vRefNum and DirID ignored */
- cipb.hFileInfo.ioVRefNum = 0;
- cipb.hFileInfo.ioDirID = 0;
- cipb.hFileInfo.ioFDirIndex = 0;
- /* set to 0 to get information about specific dir or file */
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- if (!(cipb.hFileInfo.ioFlAttrib & 0x10)) /* bit 4 = 1 for directories */
- return 0; /* not a directory */
-
- dirp->dir_id = cipb.dirInfo.ioDrDirID; /* used later in readdir */
- dirp->getting_volumes = 0;
- dirp->current_index = 1; /* index for first file/directory */
-
- c2pstr (vol_name);
- vpb.ioNamePtr = vol_name;
- /* using full pathname so vRefNum and DirID ignored */
- vpb.ioVRefNum = 0;
- vpb.ioVolIndex = -1;
- errno = PBHGetVInfo ((union HParamBlockRec *) &vpb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- dirp->vol_ref_num = vpb.ioVRefNum;
-
- return dirp;
-}
-
-int
-closedir (DIR *dp)
-{
- free (dp);
-
- return 0;
-}
-
-
-struct dirent *
-readdir (DIR *dp)
-{
- HParamBlockRec hpblock;
- CInfoPBRec cipb;
- static struct dirent s_dirent;
- static Str255 s_name;
- int done;
- char *p;
-
- /* Handle the root directory containing the mounted volumes. Call
- PBHGetVInfo specifying an index to obtain the info for a volume.
- PBHGetVInfo returns an error when it receives an index beyond the
- last volume, at which time we should return a nil dirent struct
- pointer. */
- if (dp->getting_volumes)
- {
- hpblock.volumeParam.ioNamePtr = s_name;
- hpblock.volumeParam.ioVRefNum = 0;
- hpblock.volumeParam.ioVolIndex = dp->current_index;
-
- errno = PBHGetVInfo (&hpblock, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- p2cstr (s_name);
- strcat (s_name, "/"); /* need "/" for stat to work correctly */
-
- dp->current_index++;
-
- s_dirent.d_ino = hpblock.volumeParam.ioVRefNum;
- s_dirent.d_name = s_name;
-
- return &s_dirent;
- }
- else
- {
- cipb.hFileInfo.ioVRefNum = dp->vol_ref_num;
- cipb.hFileInfo.ioNamePtr = s_name;
- /* location to receive filename returned */
-
- /* return only visible files */
- done = false;
- while (!done)
- {
- cipb.hFileInfo.ioDirID = dp->dir_id;
- /* directory ID found by opendir */
- cipb.hFileInfo.ioFDirIndex = dp->current_index;
-
- errno = PBGetCatInfo (&cipb, false);
- if (errno != noErr)
- {
- errno = ENOENT;
- return 0;
- }
-
- /* insist on a visible entry */
- if (cipb.hFileInfo.ioFlAttrib & 0x10) /* directory? */
- done = !(cipb.dirInfo.ioDrUsrWds.frFlags & fInvisible);
- else
- done = !(cipb.hFileInfo.ioFlFndrInfo.fdFlags & fInvisible);
-
- dp->current_index++;
- }
-
- p2cstr (s_name);
-
- p = s_name;
- while (*p)
- {
- if (*p == '/')
- *p = ':';
- p++;
- }
-
- s_dirent.d_ino = cipb.dirInfo.ioDrDirID;
- /* value unimportant: non-zero for valid file */
- s_dirent.d_name = s_name;
-
- return &s_dirent;
- }
-}
-
-
-char *
-getwd (char *path)
-{
- char mac_pathname[MAXPATHLEN+1];
- Str255 directory_name;
- OSErr errno;
- CInfoPBRec cipb;
-
- if (path_from_vol_dir_name (mac_pathname, 255, 0, 0, "\p") == 0)
- return NULL;
-
- if (mac_to_posix_pathname (mac_pathname, path, MAXPATHLEN+1) == 0)
- return 0;
- else
- return path;
-}
-
-#endif /* ! MAC_OSX */
-
-
-void
-initialize_applescript ()
-{
- AEDesc null_desc;
- OSAError osaerror;
-
- /* if open fails, as_scripting_component is set to NULL. Its
- subsequent use in OSA calls will fail with badComponentInstance
- error. */
- as_scripting_component = OpenDefaultComponent (kOSAComponentType,
- kAppleScriptSubtype);
-
- null_desc.descriptorType = typeNull;
- null_desc.dataHandle = 0;
- osaerror = OSAMakeContext (as_scripting_component, &null_desc,
- kOSANullScript, &as_script_context);
- if (osaerror)
- as_script_context = kOSANullScript;
- /* use default context if create fails */
-}
-
-
-void
-terminate_applescript()
-{
- OSADispose (as_scripting_component, as_script_context);
- CloseComponent (as_scripting_component);
-}
-
-/* Convert a lisp string to the 4 byte character code. */
-
-OSType
-mac_get_code_from_arg(Lisp_Object arg, OSType defCode)
-{
- OSType result;
- if (NILP(arg))
- {
- result = defCode;
- }
- else
- {
- /* check type string */
- CHECK_STRING(arg);
- if (SBYTES (arg) != 4)
- {
- error ("Wrong argument: need string of length 4 for code");
- }
- result = EndianU32_BtoN (*((UInt32 *) SDATA (arg)));
- }
- return result;
-}
-
-/* Convert the 4 byte character code into a 4 byte string. */
-
-Lisp_Object
-mac_get_object_from_code(OSType defCode)
-{
- UInt32 code = EndianU32_NtoB (defCode);
-
- return make_unibyte_string ((char *)&code, 4);
-}
-
-
-DEFUN ("mac-get-file-creator", Fmac_get_file_creator, Smac_get_file_creator, 1, 1, 0,
- doc: /* Get the creator code of FILENAME as a four character string. */)
- (filename)
- Lisp_Object filename;
-{
- OSStatus status;
-#ifdef MAC_OSX
- FSRef fref;
-#else
- FSSpec fss;
-#endif
- Lisp_Object result = Qnil;
- CHECK_STRING (filename);
-
- if (NILP(Ffile_exists_p(filename)) || !NILP(Ffile_directory_p(filename))) {
- return Qnil;
- }
- filename = Fexpand_file_name (filename, Qnil);
-
- BLOCK_INPUT;
-#ifdef MAC_OSX
- status = FSPathMakeRef(SDATA(ENCODE_FILE(filename)), &fref, NULL);
-#else
- status = posix_pathname_to_fsspec (SDATA (ENCODE_FILE (filename)), &fss);
-#endif
-
- if (status == noErr)
- {
-#ifdef MAC_OSX
- FSCatalogInfo catalogInfo;
-
- status = FSGetCatalogInfo(&fref, kFSCatInfoFinderInfo,
- &catalogInfo, NULL, NULL, NULL);
-#else
- FInfo finder_info;
-
- status = FSpGetFInfo (&fss, &finder_info);
-#endif
- if (status == noErr)
- {
-#ifdef MAC_OSX
- result = mac_get_object_from_code(((FileInfo*)&catalogInfo.finderInfo)->fileCreator);
-#else
- result = mac_get_object_from_code (finder_info.fdCreator);
-#endif
- }
- }
- UNBLOCK_INPUT;
- if (status != noErr) {
- error ("Error while getting file information.");
- }
- return result;
-}
-
-DEFUN ("mac-get-file-type", Fmac_get_file_type, Smac_get_file_type, 1, 1, 0,
- doc: /* Get the type code of FILENAME as a four character string. */)
- (filename)
- Lisp_Object filename;
-{
- OSStatus status;
-#ifdef MAC_OSX
- FSRef fref;
-#else
- FSSpec fss;
-#endif
- Lisp_Object result = Qnil;
- CHECK_STRING (filename);
-
- if (NILP(Ffile_exists_p(filename)) || !NILP(Ffile_directory_p(filename))) {
- return Qnil;
- }
- filename = Fexpand_file_name (filename, Qnil);
-
- BLOCK_INPUT;
-#ifdef MAC_OSX
- status = FSPathMakeRef(SDATA(ENCODE_FILE(filename)), &fref, NULL);
-#else
- status = posix_pathname_to_fsspec (SDATA (ENCODE_FILE (filename)), &fss);
-#endif
-
- if (status == noErr)
- {
-#ifdef MAC_OSX
- FSCatalogInfo catalogInfo;
-
- status = FSGetCatalogInfo(&fref, kFSCatInfoFinderInfo,
- &catalogInfo, NULL, NULL, NULL);
-#else
- FInfo finder_info;
-
- status = FSpGetFInfo (&fss, &finder_info);
-#endif
- if (status == noErr)
- {
-#ifdef MAC_OSX
- result = mac_get_object_from_code(((FileInfo*)&catalogInfo.finderInfo)->fileType);
-#else
- result = mac_get_object_from_code (finder_info.fdType);
-#endif
- }
- }
- UNBLOCK_INPUT;
- if (status != noErr) {
- error ("Error while getting file information.");
- }
- return result;
-}
-
-DEFUN ("mac-set-file-creator", Fmac_set_file_creator, Smac_set_file_creator, 1, 2, 0,
- doc: /* Set creator code of file FILENAME to CODE.
-If non-nil, CODE must be a 4-character string. Otherwise, 'EMAx' is
-assumed. Return non-nil if successful. */)
- (filename, code)
- Lisp_Object filename, code;
-{
- OSStatus status;
-#ifdef MAC_OSX
- FSRef fref;
-#else
- FSSpec fss;
-#endif
- OSType cCode;
- CHECK_STRING (filename);
-
- cCode = mac_get_code_from_arg(code, MAC_EMACS_CREATOR_CODE);
-
- if (NILP(Ffile_exists_p(filename)) || !NILP(Ffile_directory_p(filename))) {
- return Qnil;
- }
- filename = Fexpand_file_name (filename, Qnil);
-
- BLOCK_INPUT;
-#ifdef MAC_OSX
- status = FSPathMakeRef(SDATA(ENCODE_FILE(filename)), &fref, NULL);
-#else
- status = posix_pathname_to_fsspec (SDATA (ENCODE_FILE (filename)), &fss);
-#endif
-
- if (status == noErr)
- {
-#ifdef MAC_OSX
- FSCatalogInfo catalogInfo;
- FSRef parentDir;
- status = FSGetCatalogInfo(&fref, kFSCatInfoFinderInfo,
- &catalogInfo, NULL, NULL, &parentDir);
-#else
- FInfo finder_info;
-
- status = FSpGetFInfo (&fss, &finder_info);
-#endif
- if (status == noErr)
- {
-#ifdef MAC_OSX
- ((FileInfo*)&catalogInfo.finderInfo)->fileCreator = cCode;
- status = FSSetCatalogInfo(&fref, kFSCatInfoFinderInfo, &catalogInfo);
- /* TODO: on Mac OS 10.2, we need to touch the parent dir, FNNotify? */
-#else
- finder_info.fdCreator = cCode;
- status = FSpSetFInfo (&fss, &finder_info);
-#endif
- }
- }
- UNBLOCK_INPUT;
- if (status != noErr) {
- error ("Error while setting creator information.");
- }
- return Qt;
-}
-
-DEFUN ("mac-set-file-type", Fmac_set_file_type, Smac_set_file_type, 2, 2, 0,
- doc: /* Set file code of file FILENAME to CODE.
-CODE must be a 4-character string. Return non-nil if successful. */)
- (filename, code)
- Lisp_Object filename, code;
-{
- OSStatus status;
-#ifdef MAC_OSX
- FSRef fref;
-#else
- FSSpec fss;
-#endif
- OSType cCode;
- CHECK_STRING (filename);
-
- cCode = mac_get_code_from_arg(code, 0); /* Default to empty code*/
-
- if (NILP(Ffile_exists_p(filename)) || !NILP(Ffile_directory_p(filename))) {
- return Qnil;
- }
- filename = Fexpand_file_name (filename, Qnil);
-
- BLOCK_INPUT;
-#ifdef MAC_OSX
- status = FSPathMakeRef(SDATA(ENCODE_FILE(filename)), &fref, NULL);
-#else
- status = posix_pathname_to_fsspec (SDATA (ENCODE_FILE (filename)), &fss);
-#endif
-
- if (status == noErr)
- {
-#ifdef MAC_OSX
- FSCatalogInfo catalogInfo;
- FSRef parentDir;
- status = FSGetCatalogInfo(&fref, kFSCatInfoFinderInfo,
- &catalogInfo, NULL, NULL, &parentDir);
-#else
- FInfo finder_info;
-
- status = FSpGetFInfo (&fss, &finder_info);
-#endif
- if (status == noErr)
- {
-#ifdef MAC_OSX
- ((FileInfo*)&catalogInfo.finderInfo)->fileType = cCode;
- status = FSSetCatalogInfo(&fref, kFSCatInfoFinderInfo, &catalogInfo);
- /* TODO: on Mac OS 10.2, we need to touch the parent dir, FNNotify? */
-#else
- finder_info.fdType = cCode;
- status = FSpSetFInfo (&fss, &finder_info);
-#endif
- }
- }
- UNBLOCK_INPUT;
- if (status != noErr) {
- error ("Error while setting creator information.");
- }
- return Qt;
-}
-
-
-/* Compile and execute the AppleScript SCRIPT and return the error
- status as function value. A zero is returned if compilation and
- execution is successful, in which case *RESULT is set to a Lisp
- string containing the resulting script value. Otherwise, the Mac
- error code is returned and *RESULT is set to an error Lisp string.
- For documentation on the MacOS scripting architecture, see Inside
- Macintosh - Interapplication Communications: Scripting
- Components. */
-
-static long
-do_applescript (script, result)
- Lisp_Object script, *result;
-{
- AEDesc script_desc, result_desc, error_desc, *desc = NULL;
- OSErr error;
- OSAError osaerror;
-
- *result = Qnil;
-
- if (!as_scripting_component)
- initialize_applescript();
-
- error = AECreateDesc (typeChar, SDATA (script), SBYTES (script),
- &script_desc);
- if (error)
- return error;
-
- osaerror = OSADoScript (as_scripting_component, &script_desc, kOSANullScript,
- typeChar, kOSAModeNull, &result_desc);
-
- if (osaerror == noErr)
- /* success: retrieve resulting script value */
- desc = &result_desc;
- else if (osaerror == errOSAScriptError)
- /* error executing AppleScript: retrieve error message */
- if (!OSAScriptError (as_scripting_component, kOSAErrorMessage, typeChar,
- &error_desc))
- desc = &error_desc;
-
- if (desc)
- {
-#if TARGET_API_MAC_CARBON
- *result = make_uninit_string (AEGetDescDataSize (desc));
- AEGetDescData (desc, SDATA (*result), SBYTES (*result));
-#else /* not TARGET_API_MAC_CARBON */
- *result = make_uninit_string (GetHandleSize (desc->dataHandle));
- memcpy (SDATA (*result), *(desc->dataHandle), SBYTES (*result));
-#endif /* not TARGET_API_MAC_CARBON */
- AEDisposeDesc (desc);
- }
-
- AEDisposeDesc (&script_desc);
-
- return osaerror;
-}
-
-
-DEFUN ("do-applescript", Fdo_applescript, Sdo_applescript, 1, 1, 0,
- doc: /* Compile and execute AppleScript SCRIPT and return the result.
-If compilation and execution are successful, the resulting script
-value is returned as a string. Otherwise the function aborts and
-displays the error message returned by the AppleScript scripting
-component. */)
- (script)
- Lisp_Object script;
-{
- Lisp_Object result;
- long status;
-
- CHECK_STRING (script);
-
- BLOCK_INPUT;
- status = do_applescript (script, &result);
- UNBLOCK_INPUT;
- if (status == 0)
- return result;
- else if (!STRINGP (result))
- error ("AppleScript error %d", status);
- else
- error ("%s", SDATA (result));
-}
-
-
-DEFUN ("mac-file-name-to-posix", Fmac_file_name_to_posix,
- Smac_file_name_to_posix, 1, 1, 0,
- doc: /* Convert Macintosh FILENAME to Posix form. */)
- (filename)
- Lisp_Object filename;
-{
- char posix_filename[MAXPATHLEN+1];
-
- CHECK_STRING (filename);
-
- if (mac_to_posix_pathname (SDATA (filename), posix_filename, MAXPATHLEN))
- return build_string (posix_filename);
- else
- return Qnil;
-}
-
-
-DEFUN ("posix-file-name-to-mac", Fposix_file_name_to_mac,
- Sposix_file_name_to_mac, 1, 1, 0,
- doc: /* Convert Posix FILENAME to Mac form. */)
- (filename)
- Lisp_Object filename;
-{
- char mac_filename[MAXPATHLEN+1];
-
- CHECK_STRING (filename);
-
- if (posix_to_mac_pathname (SDATA (filename), mac_filename, MAXPATHLEN))
- return build_string (mac_filename);
- else
- return Qnil;
-}
-
-
-DEFUN ("mac-coerce-ae-data", Fmac_coerce_ae_data, Smac_coerce_ae_data, 3, 3, 0,
- doc: /* Coerce Apple event data SRC-DATA of type SRC-TYPE to DST-TYPE.
-Each type should be a string of length 4 or the symbol
-`undecoded-file-name'. */)
- (src_type, src_data, dst_type)
- Lisp_Object src_type, src_data, dst_type;
-{
- OSErr err;
- Lisp_Object result = Qnil;
- DescType src_desc_type, dst_desc_type;
- AEDesc dst_desc;
-
- CHECK_STRING (src_data);
- if (EQ (src_type, Qundecoded_file_name))
- src_desc_type = TYPE_FILE_NAME;
- else
- src_desc_type = mac_get_code_from_arg (src_type, 0);
-
- if (EQ (dst_type, Qundecoded_file_name))
- dst_desc_type = TYPE_FILE_NAME;
- else
- dst_desc_type = mac_get_code_from_arg (dst_type, 0);
-
- BLOCK_INPUT;
- err = AECoercePtr (src_desc_type, SDATA (src_data), SBYTES (src_data),
- dst_desc_type, &dst_desc);
- if (err == noErr)
- {
- result = Fcdr (mac_aedesc_to_lisp (&dst_desc));
- AEDisposeDesc (&dst_desc);
- }
- UNBLOCK_INPUT;
-
- return result;
-}
-
-
-#if TARGET_API_MAC_CARBON
-static Lisp_Object Qxml, Qmime_charset;
-static Lisp_Object QNFD, QNFKD, QNFC, QNFKC, QHFS_plus_D, QHFS_plus_C;
-
-DEFUN ("mac-get-preference", Fmac_get_preference, Smac_get_preference, 1, 4, 0,
- doc: /* Return the application preference value for KEY.
-KEY is either a string specifying a preference key, or a list of key
-strings. If it is a list, the (i+1)-th element is used as a key for
-the CFDictionary value obtained by the i-th element. Return nil if
-lookup is failed at some stage.
-
-Optional arg APPLICATION is an application ID string. If omitted or
-nil, that stands for the current application.
-
-Optional arg FORMAT specifies the data format of the return value. If
-omitted or nil, each Core Foundation object is converted into a
-corresponding Lisp object as follows:
-
- Core Foundation Lisp Tag
- ------------------------------------------------------------
- CFString Multibyte string string
- CFNumber Integer or float number
- CFBoolean Symbol (t or nil) boolean
- CFDate List of three integers date
- (cf. `current-time')
- CFData Unibyte string data
- CFArray Vector array
- CFDictionary Alist or hash table dictionary
- (depending on HASH-BOUND)
-
-If it is t, a symbol that represents the type of the original Core
-Foundation object is prepended. If it is `xml', the value is returned
-as an XML representation.
-
-Optional arg HASH-BOUND specifies which kinds of the list objects,
-alists or hash tables, are used as the targets of the conversion from
-CFDictionary. If HASH-BOUND is a negative integer or nil, always
-generate alists. If HASH-BOUND >= 0, generate an alist if the number
-of keys in the dictionary is smaller than HASH-BOUND, and a hash table
-otherwise. */)
- (key, application, format, hash_bound)
- Lisp_Object key, application, format, hash_bound;
-{
- CFStringRef app_id, key_str;
- CFPropertyListRef app_plist = NULL, plist;
- Lisp_Object result = Qnil, tmp;
- struct gcpro gcpro1, gcpro2;
-
- if (STRINGP (key))
- key = Fcons (key, Qnil);
- else
- {
- CHECK_CONS (key);
- for (tmp = key; CONSP (tmp); tmp = XCDR (tmp))
- CHECK_STRING_CAR (tmp);
- CHECK_LIST_END (tmp, key);
- }
- if (!NILP (application))
- CHECK_STRING (application);
- CHECK_SYMBOL (format);
- if (!NILP (hash_bound))
- CHECK_NUMBER (hash_bound);
-
- GCPRO2 (key, format);
-
- BLOCK_INPUT;
-
- app_id = kCFPreferencesCurrentApplication;
- if (!NILP (application))
- {
- app_id = cfstring_create_with_string (application);
- if (app_id == NULL)
- goto out;
- }
- if (!CFPreferencesAppSynchronize (app_id))
- goto out;
-
- key_str = cfstring_create_with_string (XCAR (key));
- if (key_str == NULL)
- goto out;
- app_plist = CFPreferencesCopyAppValue (key_str, app_id);
- CFRelease (key_str);
- if (app_plist == NULL)
- goto out;
-
- plist = app_plist;
- for (key = XCDR (key); CONSP (key); key = XCDR (key))
- {
- if (CFGetTypeID (plist) != CFDictionaryGetTypeID ())
- break;
- key_str = cfstring_create_with_string (XCAR (key));
- if (key_str == NULL)
- goto out;
- plist = CFDictionaryGetValue (plist, key_str);
- CFRelease (key_str);
- if (plist == NULL)
- goto out;
- }
-
- if (NILP (key))
- {
- if (EQ (format, Qxml))
- {
- CFDataRef data = CFPropertyListCreateXMLData (NULL, plist);
- if (data == NULL)
- goto out;
- result = cfdata_to_lisp (data);
- CFRelease (data);
- }
- else
- result =
- cfproperty_list_to_lisp (plist, EQ (format, Qt),
- NILP (hash_bound) ? -1 : XINT (hash_bound));
- }
-
- out:
- if (app_plist)
- CFRelease (app_plist);
- CFRelease (app_id);
-
- UNBLOCK_INPUT;
-
- UNGCPRO;
-
- return result;
-}
-
-
-static CFStringEncoding
-get_cfstring_encoding_from_lisp (obj)
- Lisp_Object obj;
-{
- CFStringRef iana_name;
- CFStringEncoding encoding = kCFStringEncodingInvalidId;
-
- if (NILP (obj))
- return kCFStringEncodingUnicode;
-
- if (INTEGERP (obj))
- return XINT (obj);
-
- if (SYMBOLP (obj) && !NILP (Fcoding_system_p (obj)))
- {
- Lisp_Object coding_spec, plist;
-
- coding_spec = Fget (obj, Qcoding_system);
- plist = XVECTOR (coding_spec)->contents[3];
- obj = Fplist_get (XVECTOR (coding_spec)->contents[3], Qmime_charset);
- }
-
- if (SYMBOLP (obj))
- obj = SYMBOL_NAME (obj);
-
- if (STRINGP (obj))
- {
- iana_name = cfstring_create_with_string (obj);
- if (iana_name)
- {
- encoding = CFStringConvertIANACharSetNameToEncoding (iana_name);
- CFRelease (iana_name);
- }
- }
-
- return encoding;
-}
-
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
-static CFStringRef
-cfstring_create_normalized (str, symbol)
- CFStringRef str;
- Lisp_Object symbol;
-{
- int form = -1;
- TextEncodingVariant variant;
- float initial_mag = 0.0;
- CFStringRef result = NULL;
-
- if (EQ (symbol, QNFD))
- form = kCFStringNormalizationFormD;
- else if (EQ (symbol, QNFKD))
- form = kCFStringNormalizationFormKD;
- else if (EQ (symbol, QNFC))
- form = kCFStringNormalizationFormC;
- else if (EQ (symbol, QNFKC))
- form = kCFStringNormalizationFormKC;
- else if (EQ (symbol, QHFS_plus_D))
- {
- variant = kUnicodeHFSPlusDecompVariant;
- initial_mag = 1.5;
- }
- else if (EQ (symbol, QHFS_plus_C))
- {
- variant = kUnicodeHFSPlusCompVariant;
- initial_mag = 1.0;
- }
-
- if (form >= 0)
- {
- CFMutableStringRef mut_str = CFStringCreateMutableCopy (NULL, 0, str);
-
- if (mut_str)
- {
- CFStringNormalize (mut_str, form);
- result = mut_str;
- }
- }
- else if (initial_mag > 0.0)
- {
- UnicodeToTextInfo uni = NULL;
- UnicodeMapping map;
- CFIndex length;
- UniChar *in_text, *buffer = NULL, *out_buf = NULL;
- OSStatus err = noErr;
- ByteCount out_read, out_size, out_len;
-
- map.unicodeEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
- kUnicodeNoSubset,
- kTextEncodingDefaultFormat);
- map.otherEncoding = CreateTextEncoding (kTextEncodingUnicodeDefault,
- variant,
- kTextEncodingDefaultFormat);
- map.mappingVersion = kUnicodeUseLatestMapping;
-
- length = CFStringGetLength (str);
- out_size = (int)((float)length * initial_mag) * sizeof (UniChar);
- if (out_size < 32)
- out_size = 32;
-
- in_text = (UniChar *)CFStringGetCharactersPtr (str);
- if (in_text == NULL)
- {
- buffer = xmalloc (sizeof (UniChar) * length);
- CFStringGetCharacters (str, CFRangeMake (0, length), buffer);
- in_text = buffer;
- }
-
- if (in_text)
- err = CreateUnicodeToTextInfo (&map, &uni);
- while (err == noErr)
- {
- out_buf = xmalloc (out_size);
- err = ConvertFromUnicodeToText (uni, length * sizeof (UniChar),
- in_text,
- kUnicodeDefaultDirectionMask,
- 0, NULL, NULL, NULL,
- out_size, &out_read, &out_len,
- out_buf);
- if (err == noErr && out_read < length * sizeof (UniChar))
- {
- xfree (out_buf);
- out_size += length;
- }
- else
- break;
- }
- if (err == noErr)
- result = CFStringCreateWithCharacters (NULL, out_buf,
- out_len / sizeof (UniChar));
- if (uni)
- DisposeUnicodeToTextInfo (&uni);
- xfree (out_buf);
- xfree (buffer);
- }
- else
- {
- result = str;
- CFRetain (result);
- }
-
- return result;
-}
-#endif
-
-DEFUN ("mac-code-convert-string", Fmac_code_convert_string, Smac_code_convert_string, 3, 4, 0,
- doc: /* Convert STRING from SOURCE encoding to TARGET encoding.
-The conversion is performed using the converter provided by the system.
-Each encoding is specified by either a coding system symbol, a mime
-charset string, or an integer as a CFStringEncoding value. An encoding
-of nil means UTF-16 in native byte order, no byte order mark.
-On Mac OS X 10.2 and later, you can do Unicode Normalization by
-specifying the optional argument NORMALIZATION-FORM with a symbol NFD,
-NFKD, NFC, NFKC, HFS+D, or HFS+C.
-On successful conversion, return the result string, else return nil. */)
- (string, source, target, normalization_form)
- Lisp_Object string, source, target, normalization_form;
-{
- Lisp_Object result = Qnil;
- struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
- CFStringEncoding src_encoding, tgt_encoding;
- CFStringRef str = NULL;
-
- CHECK_STRING (string);
- if (!INTEGERP (source) && !STRINGP (source))
- CHECK_SYMBOL (source);
- if (!INTEGERP (target) && !STRINGP (target))
- CHECK_SYMBOL (target);
- CHECK_SYMBOL (normalization_form);
-
- GCPRO4 (string, source, target, normalization_form);
-
- BLOCK_INPUT;
-
- src_encoding = get_cfstring_encoding_from_lisp (source);
- tgt_encoding = get_cfstring_encoding_from_lisp (target);
-
- /* We really want string_to_unibyte, but since it doesn't exist yet, we
- use string_as_unibyte which works as well, except for the fact that
- it's too permissive (it doesn't check that the multibyte string only
- contain single-byte chars). */
- string = Fstring_as_unibyte (string);
- if (src_encoding != kCFStringEncodingInvalidId
- && tgt_encoding != kCFStringEncodingInvalidId)
- str = CFStringCreateWithBytes (NULL, SDATA (string), SBYTES (string),
- src_encoding, !NILP (source));
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020
- if (str)
- {
- CFStringRef saved_str = str;
-
- str = cfstring_create_normalized (saved_str, normalization_form);
- CFRelease (saved_str);
- }
-#endif
- if (str)
- {
- CFIndex str_len, buf_len;
-
- str_len = CFStringGetLength (str);
- if (CFStringGetBytes (str, CFRangeMake (0, str_len), tgt_encoding, 0,
- !NILP (target), NULL, 0, &buf_len) == str_len)
- {
- result = make_uninit_string (buf_len);
- CFStringGetBytes (str, CFRangeMake (0, str_len), tgt_encoding, 0,
- !NILP (target), SDATA (result), buf_len, NULL);
- }
- CFRelease (str);
- }
-
- UNBLOCK_INPUT;
-
- UNGCPRO;
-
- return result;
-}
-
-DEFUN ("mac-process-hi-command", Fmac_process_hi_command, Smac_process_hi_command, 1, 1, 0,
- doc: /* Send a HI command whose ID is COMMAND-ID to the command chain.
-COMMAND-ID must be a 4-character string. Some common command IDs are
-defined in the Carbon Event Manager. */)
- (command_id)
- Lisp_Object command_id;
-{
- OSStatus err;
- HICommand command;
-
- bzero (&command, sizeof (HICommand));
- command.commandID = mac_get_code_from_arg (command_id, 0);
-
- BLOCK_INPUT;
- err = ProcessHICommand (&command);
- UNBLOCK_INPUT;
-
- if (err != noErr)
- error ("HI command (command ID: '%s') not handled.", SDATA (command_id));
-
- return Qnil;
-}
-
-#endif /* TARGET_API_MAC_CARBON */
-
-
-static Lisp_Object
-mac_get_system_locale ()
-{
- OSStatus err;
- LangCode lang;
- RegionCode region;
- LocaleRef locale;
- Str255 str;
-
- lang = GetScriptVariable (smSystemScript, smScriptLang);
- region = GetScriptManagerVariable (smRegionCode);
- err = LocaleRefFromLangOrRegionCode (lang, region, &locale);
- if (err == noErr)
- err = LocaleRefGetPartString (locale, kLocaleAllPartsMask,
- sizeof (str), str);
- if (err == noErr)
- return build_string (str);
- else
- return Qnil;
-}
-
-
-#ifdef MAC_OSX
-
-extern int inhibit_window_system;
-extern int noninteractive;
-
-/* Unlike in X11, window events in Carbon do not come from sockets.
- So we cannot simply use `select' to monitor two kinds of inputs:
- window events and process outputs. We emulate such functionality
- by regarding fd 0 as the window event channel and simultaneously
- monitoring both kinds of input channels. It is implemented by
- dividing into some cases:
- 1. The window event channel is not involved.
- -> Use `select'.
- 2. Sockets are not involved.
- -> Use ReceiveNextEvent.
- 3. [If SELECT_USE_CFSOCKET is set]
- Only the window event channel and socket read/write channels are
- involved, and timeout is not too short (greater than
- 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 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
- (SELECT_POLLING_PERIOD_USEC microseconds). */
-
-#ifndef SELECT_USE_CFSOCKET
-#define SELECT_USE_CFSOCKET 1
-#endif
-
-#define SELECT_POLLING_PERIOD_USEC 100000
-#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;
- CFSocketCallBackType type;
- CFDataRef address;
- const void *data;
- void *info;
-{
-}
-#endif /* SELECT_USE_CFSOCKET */
-
-static int
-select_and_poll_event (nfds, rfds, wfds, efds, timeout)
- int nfds;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- int timedout_p = 0;
- int r = 0;
- EMACS_TIME select_timeout;
- EventTimeout timeoutval =
- (timeout
- ? (EMACS_SECS (*timeout) * kEventDurationSecond
- + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
- : kEventDurationForever);
- SELECT_TYPE orfds, owfds, oefds;
-
- if (timeout == NULL)
- {
- if (rfds) orfds = *rfds;
- if (wfds) owfds = *wfds;
- if (efds) oefds = *efds;
- }
-
- /* 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;
- while (1)
- {
- if (detect_input_pending ())
- break;
-
- EMACS_SET_SECS_USECS (select_timeout, 0, 0);
- r = select (nfds, rfds, wfds, efds, &select_timeout);
- if (r != 0)
- break;
-
- if (timeoutval == 0.0)
- timedout_p = 1;
- else
- timedout_p = mac_run_loop_run_once (timeoutval);
-
- if (timeout == NULL && timedout_p)
- {
- if (rfds) *rfds = orfds;
- if (wfds) *wfds = owfds;
- if (efds) *efds = oefds;
- }
- else
- break;
- }
- UNBLOCK_INPUT;
-
- if (r != 0)
- return r;
- else if (!timedout_p)
- {
- /* Pretend that `select' is interrupted by a signal. */
- detect_input_pending ();
- errno = EINTR;
- return -1;
- }
- else
- 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;
- SELECT_TYPE *rfds, *wfds, *efds;
- EMACS_TIME *timeout;
-{
- int timedout_p = 0;
- int r;
- EMACS_TIME select_timeout;
- SELECT_TYPE orfds, owfds, oefds;
-
- if (inhibit_window_system || noninteractive
- || nfds < 1 || rfds == NULL || !FD_ISSET (0, rfds))
- return select (nfds, rfds, wfds, efds, timeout);
-
- FD_CLR (0, rfds);
- orfds = *rfds;
-
- if (wfds)
- owfds = *wfds;
- else
- FD_ZERO (&owfds);
-
- if (efds)
- oefds = *efds;
- else
- {
- EventTimeout timeoutval =
- (timeout
- ? (EMACS_SECS (*timeout) * kEventDurationSecond
- + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
- : kEventDurationForever);
-
- FD_SET (0, rfds); /* sentinel */
- do
- {
- nfds--;
- }
- while (!(FD_ISSET (nfds, rfds) || (wfds && FD_ISSET (nfds, wfds))));
- nfds++;
- FD_CLR (0, rfds);
-
- if (nfds == 1)
- return select_and_poll_event (nfds, rfds, wfds, efds, timeout);
-
- /* Avoid initial overhead of RunLoop setup for the case that
- some input is already available. */
- EMACS_SET_SECS_USECS (select_timeout, 0, 0);
- r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
- if (r != 0 || timeoutval == 0.0)
- return r;
-
- *rfds = orfds;
- if (wfds)
- *wfds = owfds;
-
-#if SELECT_USE_CFSOCKET
- if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
- goto poll_periodically;
-
- /* 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 (!detect_input_pending ())
- {
- int minfd, fd;
- CFRunLoopRef runloop =
- (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ());
- static CFMutableDictionaryRef sources;
-
- if (sources == NULL)
- sources =
- 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;
-
- for (fd = minfd; fd < nfds; fd++)
- if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds)))
- {
- void *key = (void *) fd;
- CFRunLoopSourceRef source =
- (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
-
- if (source == NULL || !CFRunLoopSourceIsValid (source))
- {
- CFSocketRef socket =
- CFSocketCreateWithNative (NULL, fd,
- (kCFSocketReadCallBack
- | kCFSocketConnectCallBack),
- socket_callback, NULL);
-
- if (socket == NULL)
- continue;
- CFDictionarySetValue (cfsockets_for_select, key, socket);
- source = CFSocketCreateRunLoopSource (NULL, socket, 0);
- CFRelease (socket);
- if (source == NULL)
- continue;
- CFDictionarySetValue (sources, key, source);
- CFRelease (source);
- }
- CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
- }
-
- timedout_p = mac_run_loop_run_once (timeoutval);
-
- for (fd = minfd; fd < nfds; fd++)
- if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds)))
- {
- void *key = (void *) fd;
- CFRunLoopSourceRef source =
- (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key);
-
- CFRunLoopRemoveSource (runloop, source, kCFRunLoopDefaultMode);
- }
- }
- UNBLOCK_INPUT;
-
- if (!timedout_p)
- {
- EMACS_SET_SECS_USECS (select_timeout, 0, 0);
- return select_and_poll_event (nfds, rfds, wfds, efds,
- &select_timeout);
- }
- else
- {
- FD_ZERO (rfds);
- if (wfds)
- FD_ZERO (wfds);
- return 0;
- }
-#endif /* SELECT_USE_CFSOCKET */
- }
-
- poll_periodically:
- {
- EMACS_TIME end_time, now, remaining_time;
-
- if (timeout)
- {
- remaining_time = *timeout;
- EMACS_GET_TIME (now);
- EMACS_ADD_TIME (end_time, now, remaining_time);
- }
-
- do
- {
- EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC);
- if (timeout && EMACS_TIME_LT (remaining_time, select_timeout))
- select_timeout = remaining_time;
- r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
- if (r != 0)
- return r;
-
- *rfds = orfds;
- if (wfds)
- *wfds = owfds;
- if (efds)
- *efds = oefds;
-
- if (timeout)
- {
- EMACS_GET_TIME (now);
- EMACS_SUB_TIME (remaining_time, end_time, now);
- }
- }
- while (!timeout || EMACS_TIME_LT (now, end_time));
-
- EMACS_SET_SECS_USECS (select_timeout, 0, 0);
- return select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout);
- }
-}
-
-/* Set up environment variables so that Emacs can correctly find its
- support files when packaged as an application bundle. Directories
- placed in /usr/local/share/emacs/<emacs-version>/, /usr/local/bin,
- and /usr/local/libexec/emacs/<emacs-version>/<system-configuration>
- by `make install' by default can instead be placed in
- .../Emacs.app/Contents/Resources/ and
- .../Emacs.app/Contents/MacOS/. Each of these environment variables
- is changed only if it is not already set. Presumably if the user
- sets an environment variable, he will want to use files in his path
- instead of ones in the application bundle. */
-void
-init_mac_osx_environment ()
-{
- CFBundleRef bundle;
- CFURLRef bundleURL;
- CFStringRef cf_app_bundle_pathname;
- int app_bundle_pathname_len;
- char *app_bundle_pathname;
- char *p, *q;
- struct stat st;
-
- mac_emacs_pid = getpid ();
-
- /* Initialize locale related variables. */
- mac_system_script_code =
- (ScriptCode) GetScriptManagerVariable (smSysScript);
- Vmac_system_locale = mac_get_system_locale ();
-
- /* Fetch the pathname of the application bundle as a C string into
- app_bundle_pathname. */
-
- bundle = CFBundleGetMainBundle ();
- if (!bundle || CFBundleGetIdentifier (bundle) == NULL)
- {
- /* We could not find the bundle identifier. For now, prevent
- the fatal error by bringing it up in the terminal. */
- inhibit_window_system = 1;
- return;
- }
-
- bundleURL = CFBundleCopyBundleURL (bundle);
- if (!bundleURL)
- return;
-
- cf_app_bundle_pathname = CFURLCopyFileSystemPath (bundleURL,
- kCFURLPOSIXPathStyle);
- app_bundle_pathname_len = CFStringGetLength (cf_app_bundle_pathname);
- app_bundle_pathname = (char *) alloca (app_bundle_pathname_len + 1);
-
- if (!CFStringGetCString (cf_app_bundle_pathname,
- app_bundle_pathname,
- app_bundle_pathname_len + 1,
- kCFStringEncodingISOLatin1))
- {
- CFRelease (cf_app_bundle_pathname);
- return;
- }
-
- CFRelease (cf_app_bundle_pathname);
-
- /* P should have sufficient room for the pathname of the bundle plus
- the subpath in it leading to the respective directories. Q
- should have three times that much room because EMACSLOADPATH can
- have the value "<path to site-lisp dir>:<path to lisp dir>:<path
- to leim dir>". */
- p = (char *) alloca (app_bundle_pathname_len + 50);
- q = (char *) alloca (3 * app_bundle_pathname_len + 150);
- if (!getenv ("EMACSLOADPATH"))
- {
- q[0] = '\0';
-
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/site-lisp");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- strcat (q, p);
-
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/lisp");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- {
- if (q[0] != '\0')
- strcat (q, ":");
- strcat (q, p);
- }
-
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/leim");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- {
- if (q[0] != '\0')
- strcat (q, ":");
- strcat (q, p);
- }
-
- if (q[0] != '\0')
- setenv ("EMACSLOADPATH", q, 1);
- }
-
- if (!getenv ("EMACSPATH"))
- {
- q[0] = '\0';
-
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/MacOS/libexec");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- strcat (q, p);
-
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/MacOS/bin");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- {
- if (q[0] != '\0')
- strcat (q, ":");
- strcat (q, p);
- }
-
- if (q[0] != '\0')
- setenv ("EMACSPATH", q, 1);
- }
-
- if (!getenv ("EMACSDATA"))
- {
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/etc");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- setenv ("EMACSDATA", p, 1);
- }
-
- if (!getenv ("EMACSDOC"))
- {
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/etc");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- setenv ("EMACSDOC", p, 1);
- }
-
- if (!getenv ("INFOPATH"))
- {
- strcpy (p, app_bundle_pathname);
- strcat (p, "/Contents/Resources/info");
- if (stat (p, &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR)
- setenv ("INFOPATH", p, 1);
- }
-}
-#endif /* MAC_OSX */
-
-#if TARGET_API_MAC_CARBON
-void
-mac_wakeup_from_rne ()
-{
-#ifndef MAC_OSX
- if (wakeup_from_rne_enabled_p)
- /* Post a harmless event so as to wake up from
- ReceiveNextEvent. */
- mac_post_mouse_moved_event ();
-#endif
-}
-#endif
-
-void
-syms_of_mac ()
-{
- Qundecoded_file_name = intern ("undecoded-file-name");
- staticpro (&Qundecoded_file_name);
-
-#if TARGET_API_MAC_CARBON
- Qstring = intern ("string"); staticpro (&Qstring);
- Qnumber = intern ("number"); staticpro (&Qnumber);
- Qboolean = intern ("boolean"); staticpro (&Qboolean);
- Qdate = intern ("date"); staticpro (&Qdate);
- Qdata = intern ("data"); staticpro (&Qdata);
- Qarray = intern ("array"); staticpro (&Qarray);
- Qdictionary = intern ("dictionary"); staticpro (&Qdictionary);
-
- Qxml = intern ("xml");
- staticpro (&Qxml);
-
- Qmime_charset = intern ("mime-charset");
- staticpro (&Qmime_charset);
-
- QNFD = intern ("NFD"); staticpro (&QNFD);
- QNFKD = intern ("NFKD"); staticpro (&QNFKD);
- QNFC = intern ("NFC"); staticpro (&QNFC);
- QNFKC = intern ("NFKC"); staticpro (&QNFKC);
- QHFS_plus_D = intern ("HFS+D"); staticpro (&QHFS_plus_D);
- QHFS_plus_C = intern ("HFS+C"); staticpro (&QHFS_plus_C);
-#endif
-
- {
- int i;
-
- for (i = 0; i < sizeof (ae_attr_table) / sizeof (ae_attr_table[0]); i++)
- {
- ae_attr_table[i].symbol = intern (ae_attr_table[i].name);
- staticpro (&ae_attr_table[i].symbol);
- }
- }
-
- defsubr (&Smac_coerce_ae_data);
-#if TARGET_API_MAC_CARBON
- defsubr (&Smac_get_preference);
- defsubr (&Smac_code_convert_string);
- defsubr (&Smac_process_hi_command);
-#endif
-
- defsubr (&Smac_set_file_creator);
- defsubr (&Smac_set_file_type);
- defsubr (&Smac_get_file_creator);
- defsubr (&Smac_get_file_type);
- defsubr (&Sdo_applescript);
- defsubr (&Smac_file_name_to_posix);
- defsubr (&Sposix_file_name_to_mac);
-
- DEFVAR_INT ("mac-system-script-code", &mac_system_script_code,
- doc: /* The system script code. */);
- mac_system_script_code = (ScriptCode) GetScriptManagerVariable (smSysScript);
-
- DEFVAR_LISP ("mac-system-locale", &Vmac_system_locale,
- doc: /* The system locale identifier string.
-This is not a POSIX locale ID, but an ICU locale ID. So encoding
-information is not included. */);
- Vmac_system_locale = mac_get_system_locale ();
-}
-
-/* arch-tag: 29d30c1f-0c6b-4f88-8a6d-0558d7f9dbff
- (do not change this comment) */