aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYuuki Harano2021-07-04 22:37:03 +0900
committerYuuki Harano2021-07-04 22:37:03 +0900
commit492a0ae5927eda83b65dd08d3e1655a62fc2c43d (patch)
tree8bb6a39483236c3a4574c93b37b0a81b8f639bb0 /src
parent01b0a909b5ca858a09484821cc866127652f4153 (diff)
parent2f2afa0b310bbce43a8703f5467b2638082abdd9 (diff)
downloademacs-492a0ae5927eda83b65dd08d3e1655a62fc2c43d.tar.gz
emacs-492a0ae5927eda83b65dd08d3e1655a62fc2c43d.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs into feature/pgtk
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.in2
-rw-r--r--src/callproc.c61
-rw-r--r--src/comp.c28
-rw-r--r--src/emacs.c16
-rw-r--r--src/lread.c8
-rw-r--r--src/minibuf.c2
-rw-r--r--src/nsfont.m46
-rw-r--r--src/nsmenu.m69
-rw-r--r--src/nsterm.h8
-rw-r--r--src/nsterm.m143
-rw-r--r--src/process.c2
-rw-r--r--src/process.h2
-rw-r--r--src/sysdep.c2
-rw-r--r--src/thread.c17
-rw-r--r--src/xgselect.c16
15 files changed, 225 insertions, 197 deletions
diff --git a/src/Makefile.in b/src/Makefile.in
index 40a423d6a1e..8c28e825da2 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -55,7 +55,7 @@ lwlibdir = ../lwlib
55# Configuration files for .o files to depend on. 55# Configuration files for .o files to depend on.
56config_h = config.h $(srcdir)/conf_post.h 56config_h = config.h $(srcdir)/conf_post.h
57 57
58## ns-app if HAVE_NS, else empty. 58## ns-app if NS self contained app, else empty.
59OTHER_FILES = @OTHER_FILES@ 59OTHER_FILES = @OTHER_FILES@
60 60
61## Flags to pass for profiling builds 61## Flags to pass for profiling builds
diff --git a/src/callproc.c b/src/callproc.c
index e44e243680d..675b78daf3e 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -116,11 +116,13 @@ static CHILD_SETUP_TYPE child_setup (int, int, int, char **, char **,
116 const char *); 116 const char *);
117 117
118/* Return the current buffer's working directory, or the home 118/* Return the current buffer's working directory, or the home
119 directory if it's unreachable, as a string suitable for a system call. 119 directory if it's unreachable. If ENCODE is true, return as a string
120 Signal an error if the result would not be an accessible directory. */ 120 suitable for a system call; otherwise, return a string in its
121 internal representation. Signal an error if the result would not be
122 an accessible directory. */
121 123
122Lisp_Object 124Lisp_Object
123encode_current_directory (void) 125get_current_directory (bool encode)
124{ 126{
125 Lisp_Object curdir = BVAR (current_buffer, directory); 127 Lisp_Object curdir = BVAR (current_buffer, directory);
126 Lisp_Object dir = Funhandled_file_name_directory (curdir); 128 Lisp_Object dir = Funhandled_file_name_directory (curdir);
@@ -131,12 +133,12 @@ encode_current_directory (void)
131 dir = build_string ("~"); 133 dir = build_string ("~");
132 134
133 dir = expand_and_dir_to_file (dir); 135 dir = expand_and_dir_to_file (dir);
134 dir = ENCODE_FILE (remove_slash_colon (dir)); 136 Lisp_Object encoded_dir = ENCODE_FILE (remove_slash_colon (dir));
135 137
136 if (! file_accessible_directory_p (dir)) 138 if (! file_accessible_directory_p (encoded_dir))
137 report_file_error ("Setting current directory", curdir); 139 report_file_error ("Setting current directory", curdir);
138 140
139 return dir; 141 return encode ? encoded_dir : dir;
140} 142}
141 143
142/* If P is reapable, record it as a deleted process and kill it. 144/* If P is reapable, record it as a deleted process and kill it.
@@ -225,8 +227,9 @@ DEFUN ("call-process", Fcall_process, Scall_process, 1, MANY, 0,
225The remaining arguments are optional. 227The remaining arguments are optional.
226 228
227The program's input comes from file INFILE (nil means `null-device'). 229The program's input comes from file INFILE (nil means `null-device').
228If you want to make the input come from an Emacs buffer, use 230If INFILE is a relative path, it will be looked for relative to the
229`call-process-region' instead. 231directory where the process is run (see below). If you want to make the
232input come from an Emacs buffer, use `call-process-region' instead.
230 233
231Third argument DESTINATION specifies how to handle program's output. 234Third argument DESTINATION specifies how to handle program's output.
232If DESTINATION is a buffer, or t that stands for the current buffer, 235If DESTINATION is a buffer, or t that stands for the current buffer,
@@ -270,7 +273,9 @@ usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) *
270 273
271 if (nargs >= 2 && ! NILP (args[1])) 274 if (nargs >= 2 && ! NILP (args[1]))
272 { 275 {
273 infile = Fexpand_file_name (args[1], BVAR (current_buffer, directory)); 276 /* Expand infile relative to the current buffer's current
277 directory, or its unhandled equivalent ("~"). */
278 infile = Fexpand_file_name (args[1], get_current_directory (false));
274 CHECK_STRING (infile); 279 CHECK_STRING (infile);
275 } 280 }
276 else 281 else
@@ -439,7 +444,7 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
439 buffer's current directory, or its unhandled equivalent. We 444 buffer's current directory, or its unhandled equivalent. We
440 can't just have the child check for an error when it does the 445 can't just have the child check for an error when it does the
441 chdir, since it's in a vfork. */ 446 chdir, since it's in a vfork. */
442 current_dir = encode_current_directory (); 447 current_dir = get_current_directory (true);
443 448
444 if (STRINGP (error_file)) 449 if (STRINGP (error_file))
445 { 450 {
@@ -1661,32 +1666,15 @@ make_environment_block (Lisp_Object current_dir)
1661void 1666void
1662init_callproc_1 (void) 1667init_callproc_1 (void)
1663{ 1668{
1664#ifdef HAVE_NS 1669 Vdata_directory = decode_env_path ("EMACSDATA", PATH_DATA, 0);
1665 const char *etc_dir = ns_etc_directory ();
1666 const char *path_exec = ns_exec_path ();
1667#endif
1668
1669 Vdata_directory = decode_env_path ("EMACSDATA",
1670#ifdef HAVE_NS
1671 etc_dir ? etc_dir :
1672#endif
1673 PATH_DATA, 0);
1674 Vdata_directory = Ffile_name_as_directory (Fcar (Vdata_directory)); 1670 Vdata_directory = Ffile_name_as_directory (Fcar (Vdata_directory));
1675 1671
1676 Vdoc_directory = decode_env_path ("EMACSDOC", 1672 Vdoc_directory = decode_env_path ("EMACSDOC", PATH_DOC, 0);
1677#ifdef HAVE_NS
1678 etc_dir ? etc_dir :
1679#endif
1680 PATH_DOC, 0);
1681 Vdoc_directory = Ffile_name_as_directory (Fcar (Vdoc_directory)); 1673 Vdoc_directory = Ffile_name_as_directory (Fcar (Vdoc_directory));
1682 1674
1683 /* Check the EMACSPATH environment variable, defaulting to the 1675 /* Check the EMACSPATH environment variable, defaulting to the
1684 PATH_EXEC path from epaths.h. */ 1676 PATH_EXEC path from epaths.h. */
1685 Vexec_path = decode_env_path ("EMACSPATH", 1677 Vexec_path = decode_env_path ("EMACSPATH", PATH_EXEC, 0);
1686#ifdef HAVE_NS
1687 path_exec ? path_exec :
1688#endif
1689 PATH_EXEC, 0);
1690 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path)); 1678 Vexec_directory = Ffile_name_as_directory (Fcar (Vexec_path));
1691 /* FIXME? For ns, path_exec should go at the front? */ 1679 /* FIXME? For ns, path_exec should go at the front? */
1692 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path); 1680 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path);
@@ -1701,10 +1689,6 @@ init_callproc (void)
1701 1689
1702 char *sh; 1690 char *sh;
1703 Lisp_Object tempdir; 1691 Lisp_Object tempdir;
1704#ifdef HAVE_NS
1705 if (data_dir == 0)
1706 data_dir = ns_etc_directory () != 0;
1707#endif
1708 1692
1709 if (!NILP (Vinstallation_directory)) 1693 if (!NILP (Vinstallation_directory))
1710 { 1694 {
@@ -1716,15 +1700,8 @@ init_callproc (void)
1716 /* MSDOS uses wrapped binaries, so don't do this. */ 1700 /* MSDOS uses wrapped binaries, so don't do this. */
1717 if (NILP (Fmember (tem, Vexec_path))) 1701 if (NILP (Fmember (tem, Vexec_path)))
1718 { 1702 {
1719#ifdef HAVE_NS
1720 const char *path_exec = ns_exec_path ();
1721#endif
1722 /* Running uninstalled, so default to tem rather than PATH_EXEC. */ 1703 /* Running uninstalled, so default to tem rather than PATH_EXEC. */
1723 Vexec_path = decode_env_path ("EMACSPATH", 1704 Vexec_path = decode_env_path ("EMACSPATH", SSDATA (tem), 0);
1724#ifdef HAVE_NS
1725 path_exec ? path_exec :
1726#endif
1727 SSDATA (tem), 0);
1728 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path); 1705 Vexec_path = nconc2 (decode_env_path ("PATH", "", 0), Vexec_path);
1729 } 1706 }
1730 1707
diff --git a/src/comp.c b/src/comp.c
index ea059526274..c3803464827 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -744,8 +744,34 @@ hash_native_abi (void)
744 Vsystem_configuration_options), 744 Vsystem_configuration_options),
745 Fmapconcat (intern_c_string ("comp--subr-signature"), 745 Fmapconcat (intern_c_string ("comp--subr-signature"),
746 Vcomp_subr_list, build_string ("")))); 746 Vcomp_subr_list, build_string (""))));
747
748 Lisp_Object version = Vemacs_version;
749
750#ifdef NS_SELF_CONTAINED
751 /* MacOS self contained app bundles do not like having dots in the
752 directory names under the Contents/Frameworks directory, so
753 convert them to underscores. */
754 version = STRING_MULTIBYTE (Vemacs_version)
755 ? make_uninit_multibyte_string (SCHARS (Vemacs_version),
756 SBYTES (Vemacs_version))
757 : make_uninit_string (SBYTES (Vemacs_version));
758
759 const unsigned char *from = SDATA (Vemacs_version);
760 unsigned char *to = SDATA (version);
761
762 while (from < SDATA (Vemacs_version) + SBYTES (Vemacs_version))
763 {
764 unsigned char c = *from++;
765
766 if (c == '.')
767 c = '_';
768
769 *to++ = c;
770 }
771#endif
772
747 Vcomp_native_version_dir = 773 Vcomp_native_version_dir =
748 concat3 (Vemacs_version, build_string ("-"), Vcomp_abi_hash); 774 concat3 (version, build_string ("-"), Vcomp_abi_hash);
749} 775}
750 776
751static void 777static void
diff --git a/src/emacs.c b/src/emacs.c
index c8bc0ba4bec..fd265b41b03 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -835,7 +835,13 @@ load_pdump (int argc, char **argv)
835 NULL 835 NULL
836#endif 836#endif
837 ; 837 ;
838 const char *argv0_base = "emacs"; 838 const char *argv0_base =
839#ifdef NS_SELF_CONTAINED
840 "Emacs"
841#else
842 "emacs"
843#endif
844 ;
839 845
840 /* TODO: maybe more thoroughly scrub process environment in order to 846 /* TODO: maybe more thoroughly scrub process environment in order to
841 make this use case (loading a dump file in an unexeced emacs) 847 make this use case (loading a dump file in an unexeced emacs)
@@ -912,6 +918,8 @@ load_pdump (int argc, char **argv)
912 /* On MS-Windows, PATH_EXEC normally starts with a literal 918 /* On MS-Windows, PATH_EXEC normally starts with a literal
913 "%emacs_dir%", so it will never work without some tweaking. */ 919 "%emacs_dir%", so it will never work without some tweaking. */
914 path_exec = w32_relocate (path_exec); 920 path_exec = w32_relocate (path_exec);
921#elif defined (HAVE_NS)
922 path_exec = ns_relocate (path_exec);
915#endif 923#endif
916 924
917 /* Look for "emacs.pdmp" in PATH_EXEC. We hardcode "emacs" in 925 /* Look for "emacs.pdmp" in PATH_EXEC. We hardcode "emacs" in
@@ -929,6 +937,7 @@ load_pdump (int argc, char **argv)
929 } 937 }
930 sprintf (dump_file, "%s%c%s%s", 938 sprintf (dump_file, "%s%c%s%s",
931 path_exec, DIRECTORY_SEP, argv0_base, suffix); 939 path_exec, DIRECTORY_SEP, argv0_base, suffix);
940#if !defined (NS_SELF_CONTAINED)
932 /* Assume the Emacs binary lives in a sibling directory as set up by 941 /* Assume the Emacs binary lives in a sibling directory as set up by
933 the default installation configuration. */ 942 the default installation configuration. */
934 const char *go_up = "../../../../bin/"; 943 const char *go_up = "../../../../bin/";
@@ -943,6 +952,7 @@ load_pdump (int argc, char **argv)
943 sprintf (emacs_executable, "%s%c%s%s%s", 952 sprintf (emacs_executable, "%s%c%s%s%s",
944 path_exec, DIRECTORY_SEP, go_up, argv0_base, 953 path_exec, DIRECTORY_SEP, go_up, argv0_base,
945 strip_suffix ? strip_suffix : ""); 954 strip_suffix ? strip_suffix : "");
955#endif
946 result = pdumper_load (dump_file, emacs_executable); 956 result = pdumper_load (dump_file, emacs_executable);
947 957
948 if (result == PDUMPER_LOAD_FILE_NOT_FOUND) 958 if (result == PDUMPER_LOAD_FILE_NOT_FOUND)
@@ -2975,7 +2985,11 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
2975 path = 0; 2985 path = 0;
2976 if (!path) 2986 if (!path)
2977 { 2987 {
2988#ifdef NS_SELF_CONTAINED
2989 path = ns_relocate (defalt);
2990#else
2978 path = defalt; 2991 path = defalt;
2992#endif
2979#ifdef WINDOWSNT 2993#ifdef WINDOWSNT
2980 defaulted = 1; 2994 defaulted = 1;
2981#endif 2995#endif
diff --git a/src/lread.c b/src/lread.c
index 0b33fd0f254..a6c2db5d994 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4769,14 +4769,8 @@ load_path_default (void)
4769 return decode_env_path (0, PATH_DUMPLOADSEARCH, 0); 4769 return decode_env_path (0, PATH_DUMPLOADSEARCH, 0);
4770 4770
4771 Lisp_Object lpath = Qnil; 4771 Lisp_Object lpath = Qnil;
4772 const char *normal = PATH_LOADSEARCH;
4773 const char *loadpath = NULL;
4774 4772
4775#ifdef HAVE_NS 4773 lpath = decode_env_path (0, PATH_LOADSEARCH, 0);
4776 loadpath = ns_load_path ();
4777#endif
4778
4779 lpath = decode_env_path (0, loadpath ? loadpath : normal, 0);
4780 4774
4781 if (!NILP (Vinstallation_directory)) 4775 if (!NILP (Vinstallation_directory))
4782 { 4776 {
diff --git a/src/minibuf.c b/src/minibuf.c
index 00069eabbe5..1b842b77211 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -1210,7 +1210,7 @@ read_minibuf_unwind (void)
1210 WINDOW_FRAME (XWINDOW (minibuf_window)))) 1210 WINDOW_FRAME (XWINDOW (minibuf_window))))
1211 Fset_frame_selected_window (selected_frame, prev, Qnil); 1211 Fset_frame_selected_window (selected_frame, prev, Qnil);
1212 } 1212 }
1213 else 1213 else if (WINDOW_LIVE_P (calling_window))
1214 Fset_frame_selected_window (calling_frame, calling_window, Qnil); 1214 Fset_frame_selected_window (calling_frame, calling_window, Qnil);
1215 } 1215 }
1216 1216
diff --git a/src/nsfont.m b/src/nsfont.m
index f4f0d281674..5a9cdfebc01 100644
--- a/src/nsfont.m
+++ b/src/nsfont.m
@@ -277,30 +277,36 @@ ns_ascii_average_width (NSFont *sfont)
277 277
278 278
279/* Return whether set1 covers set2 to a reasonable extent given by pct. 279/* Return whether set1 covers set2 to a reasonable extent given by pct.
280 We check, out of each 16 Unicode char range containing chars in set2, 280
281 whether at least one character is present in set1. 281 The GNUstep bitmap representation doesn't match Apple's
282 This must be true for pct of the pairs to consider it covering. */ 282 description. It appears to be a single block of bytes, not broken
283 up into planes, where the last byte contains the highest character
284 the character set supports. */
283static BOOL 285static BOOL
284ns_charset_covers(NSCharacterSet *set1, NSCharacterSet *set2, float pct) 286ns_charset_covers(NSCharacterSet *set1, NSCharacterSet *set2, float pct)
285{ 287{
286 const unsigned short *bytes1 = [[set1 bitmapRepresentation] bytes]; 288 NSData *font = [set1 bitmapRepresentation];
287 const unsigned short *bytes2 = [[set2 bitmapRepresentation] bytes]; 289 NSData *script = [set2 bitmapRepresentation];
288 int i, off = 0, tot = 0;
289 290
290 /* Work around what appears to be a GNUstep bug. 291 uint8_t *fontPlane = (uint8_t *)[font bytes];
291 See <https://bugs.gnu.org/11853>. */ 292 uint8_t *scriptPlane = (uint8_t *)[script bytes];
292 if (! (bytes1 && bytes2))
293 return NO;
294 293
295 for (i=0; i<4096; i++, bytes1++, bytes2++) 294 int covered = 0, total = 0;
296 if (*bytes2) 295
297 { 296 for (ptrdiff_t b = 0 ; b < [script length] ; b++)
298 tot++; 297 for (int i = 0 ; i < 8 ; i++)
299 if (*bytes1 == 0) // *bytes1 & *bytes2 != *bytes2 298 {
300 off++; 299 if (*(scriptPlane + b) & (1 << i))
301 } 300 {
302 // fprintf(stderr, "off = %d\ttot = %d\n", off,tot); 301 total++;
303 return (float)off / tot < 1.0F - pct; 302
303 if (b < [font length]
304 && *(fontPlane + b) & (1 << i))
305 covered++;
306 }
307 }
308
309 return (float)covered / total >= 1.0F - pct;
304} 310}
305 311
306 312
@@ -700,7 +706,7 @@ nsfont_open (struct frame *f, Lisp_Object font_entity, int pixel_size)
700 when setting family in ns_spec_to_descriptor(). */ 706 when setting family in ns_spec_to_descriptor(). */
701 if (ns_attribute_fvalue (fontDesc, NSFontWeightTrait) > 0.50F) 707 if (ns_attribute_fvalue (fontDesc, NSFontWeightTrait) > 0.50F)
702 traits |= NSBoldFontMask; 708 traits |= NSBoldFontMask;
703 if (fabs (ns_attribute_fvalue (fontDesc, NSFontSlantTrait) > 0.05F)) 709 if (ns_attribute_fvalue (fontDesc, NSFontSlantTrait) > 0.05F)
704 traits |= NSItalicFontMask; 710 traits |= NSItalicFontMask;
705 711
706 /* see https://web.archive.org/web/20100201175731/http://cocoadev.com/forums/comments.php?DiscussionID=74 */ 712 /* see https://web.archive.org/web/20100201175731/http://cocoadev.com/forums/comments.php?DiscussionID=74 */
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 24aa5a0ac11..1b03fe91a8b 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -73,7 +73,7 @@ free_frame_menubar (struct frame *f)
73 id menu = [NSApp mainMenu]; 73 id menu = [NSApp mainMenu];
74 for (int i = [menu numberOfItems] - 1 ; i >= 0; i--) 74 for (int i = [menu numberOfItems] - 1 ; i >= 0; i--)
75 { 75 {
76 NSMenuItem *item = [menu itemAtIndex:i]; 76 NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i];
77 NSString *title = [item title]; 77 NSString *title = [item title];
78 78
79 if ([ns_app_name isEqualToString:title]) 79 if ([ns_app_name isEqualToString:title])
@@ -358,8 +358,12 @@ ns_update_menubar (struct frame *f, bool deep_p)
358 if (i < [menu numberOfItems]) 358 if (i < [menu numberOfItems])
359 { 359 {
360 NSString *titleStr = [NSString stringWithUTF8String: wv->name]; 360 NSString *titleStr = [NSString stringWithUTF8String: wv->name];
361 NSMenuItem *item = [menu itemAtIndex:i]; 361 NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i];
362 submenu = (EmacsMenu*)[item submenu]; 362 submenu = (EmacsMenu *)[item submenu];
363
364#ifdef NS_IMPL_GNUSTEP
365 [submenu close];
366#endif
363 367
364 [item setTitle:titleStr]; 368 [item setTitle:titleStr];
365 [submenu setTitle:titleStr]; 369 [submenu setTitle:titleStr];
@@ -368,8 +372,10 @@ ns_update_menubar (struct frame *f, bool deep_p)
368 else 372 else
369 submenu = [menu addSubmenuWithTitle: wv->name]; 373 submenu = [menu addSubmenuWithTitle: wv->name];
370 374
375#ifdef NS_IMPL_COCOA
371 if ([[submenu title] isEqualToString:@"Help"]) 376 if ([[submenu title] isEqualToString:@"Help"])
372 [NSApp setHelpMenu:submenu]; 377 [NSApp setHelpMenu:submenu];
378#endif
373 379
374 if (deep_p) 380 if (deep_p)
375 [submenu fillWithWidgetValue: wv->contents]; 381 [submenu fillWithWidgetValue: wv->contents];
@@ -380,6 +386,12 @@ ns_update_menubar (struct frame *f, bool deep_p)
380 while (i < [menu numberOfItems]) 386 while (i < [menu numberOfItems])
381 { 387 {
382 /* Remove any extra items. */ 388 /* Remove any extra items. */
389#ifdef NS_IMPL_GNUSTEP
390 NSMenuItem *item = (NSMenuItem *)[menu itemAtIndex:i];
391 EmacsMenu *submenu = (EmacsMenu *)[item submenu];
392 [submenu close];
393#endif
394
383 [menu removeItemAtIndex:i]; 395 [menu removeItemAtIndex:i];
384 } 396 }
385 397
@@ -472,7 +484,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
472 484
473 if (menu_separator_name_p (wv->name)) 485 if (menu_separator_name_p (wv->name))
474 { 486 {
475 item = [NSMenuItem separatorItem]; 487 item = (NSMenuItem *)[NSMenuItem separatorItem];
476 } 488 }
477 else 489 else
478 { 490 {
@@ -534,7 +546,7 @@ set_frame_menubar (struct frame *f, bool deep_p)
534 needsUpdate = YES; 546 needsUpdate = YES;
535} 547}
536 548
537 549#ifdef NS_IMPL_COCOA
538typedef struct { 550typedef struct {
539 const char *from, *to; 551 const char *from, *to;
540} subst_t; 552} subst_t;
@@ -591,17 +603,18 @@ prettify_key (const char *key)
591 xfree (buf); 603 xfree (buf);
592 return SSDATA (result); 604 return SSDATA (result);
593} 605}
606#endif /* NS_IMPL_COCOA */
594 607
595- (void)fillWithWidgetValue: (void *)wvptr 608- (void)fillWithWidgetValue: (void *)wvptr
596{ 609{
597 widget_value *first_wv = (widget_value *)wvptr; 610 widget_value *first_wv = (widget_value *)wvptr;
598 NSFont *menuFont = [NSFont menuFontOfSize:0];
599 NSDictionary *attributes = nil; 611 NSDictionary *attributes = nil;
600 612
601#ifdef NS_IMPL_COCOA 613#ifdef NS_IMPL_COCOA
602 /* Cocoa doesn't allow multi-key sequences in its menu display, so 614 /* Cocoa doesn't allow multi-key sequences in its menu display, so
603 work around it by using tabs to split the title into two 615 work around it by using tabs to split the title into two
604 columns. */ 616 columns. */
617 NSFont *menuFont = [NSFont menuFontOfSize:0];
605 NSDictionary *font_attribs = @{NSFontAttributeName: menuFont}; 618 NSDictionary *font_attribs = @{NSFontAttributeName: menuFont};
606 CGFloat maxNameWidth = 0; 619 CGFloat maxNameWidth = 0;
607 CGFloat maxKeyWidth = 0; 620 CGFloat maxKeyWidth = 0;
@@ -672,9 +685,9 @@ prettify_key (const char *key)
672- (EmacsMenu *)addSubmenuWithTitle: (const char *)title 685- (EmacsMenu *)addSubmenuWithTitle: (const char *)title
673{ 686{
674 NSString *titleStr = [NSString stringWithUTF8String: title]; 687 NSString *titleStr = [NSString stringWithUTF8String: title];
675 NSMenuItem *item = [self addItemWithTitle: titleStr 688 NSMenuItem *item = (NSMenuItem *)[self addItemWithTitle: titleStr
676 action: (SEL)nil /*@selector (menuDown:) */ 689 action: (SEL)nil
677 keyEquivalent: @""]; 690 keyEquivalent: @""];
678 EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr]; 691 EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr];
679 [self setSubmenu: submenu forItem: item]; 692 [self setSubmenu: submenu forItem: item];
680 [submenu release]; 693 [submenu release];
@@ -711,6 +724,44 @@ prettify_key (const char *key)
711 : Qnil; 724 : Qnil;
712} 725}
713 726
727#ifdef NS_IMPL_GNUSTEP
728- (void) close
729{
730 /* Close all the submenus. This has the unfortunate side-effect of
731 breaking tear-off menus, however if we don't do this then we get
732 a crash when the menus are removed during updates. */
733 for (int i = 0 ; i < [self numberOfItems] ; i++)
734 {
735 NSMenuItem *item = [self itemAtIndex:i];
736 if ([item hasSubmenu])
737 [(EmacsMenu *)[item submenu] close];
738 }
739
740 [super close];
741}
742
743/* GNUstep seems to have a number of required methods in
744 NSMenuDelegate that are optional in Cocoa. */
745
746- (void) menuWillOpen:(NSMenu *)menu
747{
748}
749
750- (void) menuDidClose:(NSMenu *)menu
751{
752}
753
754- (NSRect)confinementRectForMenu:(NSMenu *)menu
755 onScreen:(NSScreen *)screen
756{
757 return NSZeroRect;
758}
759
760- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item
761{
762}
763#endif
764
714@end /* EmacsMenu */ 765@end /* EmacsMenu */
715 766
716 767
diff --git a/src/nsterm.h b/src/nsterm.h
index e7ea907569e..b29e76cc63f 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -504,6 +504,10 @@ typedef id instancetype;
504 NSPoint grabOffset; 504 NSPoint grabOffset;
505} 505}
506 506
507#ifdef NS_IMPL_GNUSTEP
508- (NSInteger) orderedIndex;
509#endif
510
507- (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above; 511- (BOOL)restackWindow:(NSWindow *)win above:(BOOL)above;
508- (void)setAppearance; 512- (void)setAppearance;
509@end 513@end
@@ -1186,9 +1190,7 @@ extern void ns_run_ascript (void);
1186#define NSAPP_DATA2_RUNFILEDIALOG 11 1190#define NSAPP_DATA2_RUNFILEDIALOG 11
1187extern void ns_run_file_dialog (void); 1191extern void ns_run_file_dialog (void);
1188 1192
1189extern const char *ns_etc_directory (void); 1193extern const char *ns_relocate (const char *epath);
1190extern const char *ns_exec_path (void);
1191extern const char *ns_load_path (void);
1192extern void syms_of_nsterm (void); 1194extern void syms_of_nsterm (void);
1193extern void syms_of_nsfns (void); 1195extern void syms_of_nsfns (void);
1194extern void syms_of_nsmenu (void); 1196extern void syms_of_nsmenu (void);
diff --git a/src/nsterm.m b/src/nsterm.m
index 838c14d5abb..b9e2c9b6916 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -277,11 +277,9 @@ static NSView *focus_view = NULL;
277#endif 277#endif
278static int ns_window_num = 0; 278static int ns_window_num = 0;
279static BOOL gsaved = NO; 279static BOOL gsaved = NO;
280static BOOL ns_fake_keydown = NO;
281#ifdef NS_IMPL_COCOA 280#ifdef NS_IMPL_COCOA
282static BOOL ns_menu_bar_is_hidden = NO; 281static BOOL ns_menu_bar_is_hidden = NO;
283#endif 282#endif
284/* static int debug_lock = 0; */
285 283
286/* event loop */ 284/* event loop */
287static BOOL send_appdefined = YES; 285static BOOL send_appdefined = YES;
@@ -499,118 +497,37 @@ append2 (Lisp_Object list, Lisp_Object item)
499 497
500 498
501const char * 499const char *
502ns_etc_directory (void) 500ns_relocate (const char *epath)
503/* If running as a self-contained app bundle, return as a string the 501/* If we're running in a self-contained app bundle some hard-coded
504 filename of the etc directory, if present; else nil. */ 502 paths are relative to the root of the bundle, so work out the full
505{ 503 path.
506 NSBundle *bundle = [NSBundle mainBundle];
507 NSString *resourceDir = [bundle resourcePath];
508 NSString *resourcePath;
509 NSFileManager *fileManager = [NSFileManager defaultManager];
510 BOOL isDir;
511
512 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
513 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
514 {
515 if (isDir) return [resourcePath UTF8String];
516 }
517 return NULL;
518}
519
520 504
521const char * 505 FIXME: I think this should be able to handle cases where multiple
522ns_exec_path (void) 506 directories are separated by colons. */
523/* If running as a self-contained app bundle, return as a path string
524 the filenames of the libexec and bin directories, ie libexec:bin.
525 Otherwise, return nil.
526 Normally, Emacs does not add its own bin/ directory to the PATH.
527 However, a self-contained NS build has a different layout, with
528 bin/ and libexec/ subdirectories in the directory that contains
529 Emacs.app itself.
530 We put libexec first, because init_callproc_1 uses the first
531 element to initialize exec-directory. An alternative would be
532 for init_callproc to check for invocation-directory/libexec.
533*/
534{ 507{
508#ifdef NS_SELF_CONTAINED
535 NSBundle *bundle = [NSBundle mainBundle]; 509 NSBundle *bundle = [NSBundle mainBundle];
536 NSString *resourceDir = [bundle resourcePath]; 510 NSString *root = [bundle bundlePath];
537 NSString *binDir = [bundle bundlePath]; 511 NSString *original = [NSString stringWithUTF8String:epath];
538 NSString *resourcePath, *resourcePaths; 512 NSString *fixedPath = [NSString pathWithComponents:
539 NSRange range; 513 [NSArray arrayWithObjects:
540 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR]; 514 root, original, nil]];
541 NSFileManager *fileManager = [NSFileManager defaultManager]; 515 NSFileManager *fileManager = [NSFileManager defaultManager];
542 NSArray *paths;
543 NSEnumerator *pathEnum;
544 BOOL isDir;
545 516
546 range = [resourceDir rangeOfString: @"Contents"]; 517 if (![original isAbsolutePath]
547 if (range.location != NSNotFound) 518 && [fileManager fileExistsAtPath:fixedPath isDirectory:NULL])
548 { 519 return [fixedPath UTF8String];
549 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
550#ifdef NS_IMPL_COCOA
551 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
552#endif
553 }
554
555 paths = [binDir stringsByAppendingPaths:
556 [NSArray arrayWithObjects: @"libexec", @"bin", nil]];
557 pathEnum = [paths objectEnumerator];
558 resourcePaths = @"";
559 520
560 while ((resourcePath = [pathEnum nextObject])) 521 /* If we reach here either the path is absolute and therefore we
561 { 522 don't need to complete it, or we're unable to relocate the
562 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) 523 file/directory. If it's the latter it may be because the user is
563 if (isDir) 524 trying to use a bundled app as though it's a Unix style install
564 { 525 and we have no way to guess what was intended, so return the
565 if ([resourcePaths length] > 0) 526 original string unaltered. */
566 resourcePaths
567 = [resourcePaths stringByAppendingString: pathSeparator];
568 resourcePaths
569 = [resourcePaths stringByAppendingString: resourcePath];
570 }
571 }
572 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
573 527
574 return NULL; 528#endif
575}
576
577
578const char *
579ns_load_path (void)
580/* If running as a self-contained app bundle, return as a path string
581 the filenames of the site-lisp and lisp directories.
582 Ie, site-lisp:lisp. Otherwise, return nil. */
583{
584 NSBundle *bundle = [NSBundle mainBundle];
585 NSString *resourceDir = [bundle resourcePath];
586 NSString *resourcePath, *resourcePaths;
587 NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR];
588 NSFileManager *fileManager = [NSFileManager defaultManager];
589 BOOL isDir;
590 NSArray *paths = [resourceDir stringsByAppendingPaths:
591 [NSArray arrayWithObjects:
592 @"site-lisp", @"lisp", nil]];
593 NSEnumerator *pathEnum = [paths objectEnumerator];
594 resourcePaths = @"";
595
596 /* Hack to skip site-lisp. */
597 if (no_site_lisp) resourcePath = [pathEnum nextObject];
598
599 while ((resourcePath = [pathEnum nextObject]))
600 {
601 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
602 if (isDir)
603 {
604 if ([resourcePaths length] > 0)
605 resourcePaths
606 = [resourcePaths stringByAppendingString: pathSeparator];
607 resourcePaths
608 = [resourcePaths stringByAppendingString: resourcePath];
609 }
610 }
611 if ([resourcePaths length] > 0) return [resourcePaths UTF8String];
612 529
613 return NULL; 530 return epath;
614} 531}
615 532
616 533
@@ -6374,9 +6291,7 @@ not_in_argv (NSString *arg)
6374 NSTRACE ("[EmacsView keyDown:]"); 6291 NSTRACE ("[EmacsView keyDown:]");
6375 6292
6376 /* Rhapsody and macOS give up and down events for the arrow keys. */ 6293 /* Rhapsody and macOS give up and down events for the arrow keys. */
6377 if (ns_fake_keydown == YES) 6294 if ([theEvent type] != NSEventTypeKeyDown)
6378 ns_fake_keydown = NO;
6379 else if ([theEvent type] != NSEventTypeKeyDown)
6380 return; 6295 return;
6381 6296
6382 if (!emacs_event) 6297 if (!emacs_event)
@@ -8763,6 +8678,16 @@ not_in_argv (NSString *arg)
8763} 8678}
8764 8679
8765 8680
8681#ifdef NS_IMPL_GNUSTEP
8682/* orderedIndex isn't yet available in GNUstep, but it seems pretty
8683 easy to implement. */
8684- (NSInteger) orderedIndex
8685{
8686 return [[NSApp orderedWindows] indexOfObjectIdenticalTo:self];
8687}
8688#endif
8689
8690
8766/* The array returned by [NSWindow parentWindow] may already be 8691/* The array returned by [NSWindow parentWindow] may already be
8767 sorted, but the documentation doesn't tell us whether or not it is, 8692 sorted, but the documentation doesn't tell us whether or not it is,
8768 so to be safe we'll sort it. */ 8693 so to be safe we'll sort it. */
diff --git a/src/process.c b/src/process.c
index ce71545c117..cc1afa8dc3e 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1755,7 +1755,7 @@ usage: (make-process &rest ARGS) */)
1755 buffer's current directory, or its unhandled equivalent. We 1755 buffer's current directory, or its unhandled equivalent. We
1756 can't just have the child check for an error when it does the 1756 can't just have the child check for an error when it does the
1757 chdir, since it's in a vfork. */ 1757 chdir, since it's in a vfork. */
1758 current_dir = encode_current_directory (); 1758 current_dir = get_current_directory (true);
1759 1759
1760 name = Fplist_get (contact, QCname); 1760 name = Fplist_get (contact, QCname);
1761 CHECK_STRING (name); 1761 CHECK_STRING (name);
diff --git a/src/process.h b/src/process.h
index 0890f253a40..4a25d13d268 100644
--- a/src/process.h
+++ b/src/process.h
@@ -264,7 +264,7 @@ enum
264 264
265/* Defined in callproc.c. */ 265/* Defined in callproc.c. */
266 266
267extern Lisp_Object encode_current_directory (void); 267extern Lisp_Object get_current_directory (bool);
268extern void record_kill_process (struct Lisp_Process *, Lisp_Object); 268extern void record_kill_process (struct Lisp_Process *, Lisp_Object);
269 269
270/* Defined in sysdep.c. */ 270/* Defined in sysdep.c. */
diff --git a/src/sysdep.c b/src/sysdep.c
index 51d8b5eeedc..b8ec22d9dd9 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -657,7 +657,7 @@ sys_subshell (void)
657#endif 657#endif
658 pid_t pid; 658 pid_t pid;
659 struct save_signal saved_handlers[5]; 659 struct save_signal saved_handlers[5];
660 char *str = SSDATA (encode_current_directory ()); 660 char *str = SSDATA (get_current_directory (true));
661 661
662#ifdef DOS_NT 662#ifdef DOS_NT
663 pid = 0; 663 pid = 0;
diff --git a/src/thread.c b/src/thread.c
index f74f6111486..714b1cd903a 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -28,6 +28,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
28#include "pdumper.h" 28#include "pdumper.h"
29#include "keyboard.h" 29#include "keyboard.h"
30 30
31#ifdef HAVE_NS
32#include "nsterm.h"
33#endif
34
31#if defined HAVE_GLIB && ! defined (HAVE_NS) 35#if defined HAVE_GLIB && ! defined (HAVE_NS)
32#include <xgselect.h> 36#include <xgselect.h>
33#else 37#else
@@ -735,6 +739,15 @@ run_thread (void *state)
735 struct thread_state *self = state; 739 struct thread_state *self = state;
736 struct thread_state **iter; 740 struct thread_state **iter;
737 741
742#ifdef HAVE_NS
743 /* Allocate an autorelease pool in case this thread calls any
744 Objective C code.
745
746 FIXME: In long running threads we may want to drain the pool
747 regularly instead of just at the end. */
748 void *pool = ns_alloc_autorelease_pool ();
749#endif
750
738 self->m_stack_bottom = self->stack_top = &stack_pos.c; 751 self->m_stack_bottom = self->stack_top = &stack_pos.c;
739 self->thread_id = sys_thread_self (); 752 self->thread_id = sys_thread_self ();
740 753
@@ -777,6 +790,10 @@ run_thread (void *state)
777 current_thread = NULL; 790 current_thread = NULL;
778 sys_cond_broadcast (&self->thread_condvar); 791 sys_cond_broadcast (&self->thread_condvar);
779 792
793#ifdef HAVE_NS
794 ns_release_autorelease_pool (pool);
795#endif
796
780 /* Unlink this thread from the list of all threads. Note that we 797 /* Unlink this thread from the list of all threads. Note that we
781 have to do this very late, after broadcasting our death. 798 have to do this very late, after broadcasting our death.
782 Otherwise the GC may decide to reap the thread_state object, 799 Otherwise the GC may decide to reap the thread_state object,
diff --git a/src/xgselect.c b/src/xgselect.c
index 0d91d55bad6..92b118b9559 100644
--- a/src/xgselect.c
+++ b/src/xgselect.c
@@ -34,12 +34,27 @@ static GMainContext *glib_main_context;
34 34
35void release_select_lock (void) 35void release_select_lock (void)
36{ 36{
37#if GNUC_PREREQ (4, 7, 0)
38 if (__atomic_sub_fetch (&threads_holding_glib_lock, 1, __ATOMIC_ACQ_REL) == 0)
39 g_main_context_release (glib_main_context);
40#else
37 if (--threads_holding_glib_lock == 0) 41 if (--threads_holding_glib_lock == 0)
38 g_main_context_release (glib_main_context); 42 g_main_context_release (glib_main_context);
43#endif
39} 44}
40 45
41static void acquire_select_lock (GMainContext *context) 46static void acquire_select_lock (GMainContext *context)
42{ 47{
48#if GNUC_PREREQ (4, 7, 0)
49 if (__atomic_fetch_add (&threads_holding_glib_lock, 1, __ATOMIC_ACQ_REL) == 0)
50 {
51 glib_main_context = context;
52 while (!g_main_context_acquire (context))
53 {
54 /* Spin. */
55 }
56 }
57#else
43 if (threads_holding_glib_lock++ == 0) 58 if (threads_holding_glib_lock++ == 0)
44 { 59 {
45 glib_main_context = context; 60 glib_main_context = context;
@@ -48,6 +63,7 @@ static void acquire_select_lock (GMainContext *context)
48 /* Spin. */ 63 /* Spin. */
49 } 64 }
50 } 65 }
66#endif
51} 67}
52 68
53/* `xg_select' is a `pselect' replacement. Why do we need a separate function? 69/* `xg_select' is a `pselect' replacement. Why do we need a separate function?