aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMichael R. Mauger2017-07-03 15:32:41 -0400
committerMichael R. Mauger2017-07-03 15:32:41 -0400
commit776635c01abd4aa759e7aa9584b513146978568c (patch)
tree554f444bc96cb6b05435e8bf195de4df1b00df8f /src
parent77083e2d34ba5559ae2899d3b03cf08c2e6c5ad4 (diff)
parent4cd0db3d6e6e4d5bd49283483bdafbbfc0f583f1 (diff)
downloademacs-776635c01abd4aa759e7aa9584b513146978568c.tar.gz
emacs-776635c01abd4aa759e7aa9584b513146978568c.zip
Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs
Diffstat (limited to 'src')
-rw-r--r--src/.gdbinit96
-rw-r--r--src/ChangeLog.132
-rw-r--r--src/Makefile.in38
-rw-r--r--src/alloc.c79
-rw-r--r--src/bidi.c16
-rw-r--r--src/buffer.c7
-rw-r--r--src/buffer.h9
-rw-r--r--src/callint.c1
-rw-r--r--src/callproc.c38
-rw-r--r--src/casefiddle.c600
-rw-r--r--src/ccl.c4
-rw-r--r--src/charset.c12
-rw-r--r--src/chartab.c2
-rw-r--r--src/cm.c14
-rw-r--r--src/coding.c6
-rw-r--r--src/coding.h34
-rw-r--r--src/composite.c2
-rw-r--r--src/conf_post.h38
-rw-r--r--src/data.c89
-rw-r--r--src/dispextern.h37
-rw-r--r--src/dispnew.c32
-rw-r--r--src/doc.c6
-rw-r--r--src/doprnt.c5
-rw-r--r--src/dynlib.c36
-rw-r--r--src/dynlib.h16
-rw-r--r--src/editfns.c460
-rw-r--r--src/emacs-module.c671
-rw-r--r--src/emacs-module.h197
-rw-r--r--src/emacs-module.h.in107
-rw-r--r--src/emacs.c66
-rw-r--r--src/eval.c163
-rw-r--r--src/fileio.c70
-rw-r--r--src/filelock.c2
-rw-r--r--src/fns.c36
-rw-r--r--src/font.c50
-rw-r--r--src/font.h6
-rw-r--r--src/frame.c1230
-rw-r--r--src/frame.h128
-rw-r--r--src/ftfont.c3
-rw-r--r--src/gmalloc.c83
-rw-r--r--src/gnutls.c1
-rw-r--r--src/gtkutil.c177
-rw-r--r--src/gtkutil.h8
-rw-r--r--src/image.c26
-rw-r--r--src/indent.c1
-rw-r--r--src/inotify.c32
-rw-r--r--src/intervals.h12
-rw-r--r--src/keyboard.c91
-rw-r--r--src/kqueue.c2
-rw-r--r--src/lisp.h94
-rw-r--r--src/lread.c386
-rw-r--r--src/macfont.m41
-rw-r--r--src/minibuf.c34
-rw-r--r--src/module-env-25.h140
-rw-r--r--src/module-env-26.h3
-rw-r--r--src/nsfns.m262
-rw-r--r--src/nsimage.m12
-rw-r--r--src/nsmenu.m25
-rw-r--r--src/nsterm.h116
-rw-r--r--src/nsterm.m495
-rw-r--r--src/print.c809
-rw-r--r--src/process.c144
-rw-r--r--src/regex.c10
-rw-r--r--src/search.c65
-rw-r--r--src/syntax.c8
-rw-r--r--src/sysdep.c45
-rw-r--r--src/sysstdio.h41
-rw-r--r--src/systhread.c11
-rw-r--r--src/syswait.h2
-rw-r--r--src/term.c47
-rw-r--r--src/termhooks.h3
-rw-r--r--src/terminal.c5
-rw-r--r--src/thread.c2
-rw-r--r--src/unexelf.c12
-rw-r--r--src/unexmacosx.c25
-rw-r--r--src/w32.c25
-rw-r--r--src/w32fns.c814
-rw-r--r--src/w32font.c21
-rw-r--r--src/w32menu.c2
-rw-r--r--src/w32term.c326
-rw-r--r--src/w32term.h11
-rw-r--r--src/widget.c13
-rw-r--r--src/widget.h2
-rw-r--r--src/window.c256
-rw-r--r--src/window.h200
-rw-r--r--src/xdisp.c477
-rw-r--r--src/xfaces.c12
-rw-r--r--src/xfns.c718
-rw-r--r--src/xmenu.c60
-rw-r--r--src/xterm.c547
-rw-r--r--src/xterm.h16
91 files changed, 8186 insertions, 2992 deletions
diff --git a/src/.gdbinit b/src/.gdbinit
index 6d7476d5a72..b5a974bb38d 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1264,3 +1264,99 @@ commands
1264 end 1264 end
1265 continue 1265 continue
1266end 1266end
1267
1268
1269# Put the Python code at the end of .gdbinit so that if GDB does not
1270# support Python, GDB will do all the above initializations before
1271# reporting an error.
1272
1273python
1274
1275# Omit pretty-printing in older (pre-7.3) GDBs that lack it.
1276if hasattr(gdb, 'printing'):
1277
1278 class Emacs_Pretty_Printers (gdb.printing.RegexpCollectionPrettyPrinter):
1279 """A collection of pretty-printers. This is like GDB's
1280 RegexpCollectionPrettyPrinter except when printing Lisp_Object."""
1281 def __call__ (self, val):
1282 """Look up the pretty-printer for the provided value."""
1283 type = val.type.unqualified ()
1284 typename = type.tag or type.name
1285 basic_type = gdb.types.get_basic_type (type)
1286 basic_typename = basic_type.tag or basic_type.name
1287 for printer in self.subprinters:
1288 if (printer.enabled
1289 and ((printer.regexp == '^Lisp_Object$'
1290 and typename == 'Lisp_Object')
1291 or (basic_typename
1292 and printer.compiled_re.search (basic_typename)))):
1293 return printer.gen_printer (val)
1294 return None
1295
1296 class Lisp_Object_Printer:
1297 "A printer for Lisp_Object values."
1298 def __init__ (self, val):
1299 self.val = val
1300
1301 def to_string (self):
1302 "Yield a string that can be fed back into GDB."
1303
1304 # This implementation should work regardless of C compiler, and
1305 # it should not attempt to run any code in the inferior.
1306 EMACS_INT_WIDTH = int(gdb.lookup_symbol("EMACS_INT_WIDTH")[0].value())
1307 USE_LSB_TAG = int(gdb.lookup_symbol("USE_LSB_TAG")[0].value())
1308 GCTYPEBITS = 3
1309 VALBITS = EMACS_INT_WIDTH - GCTYPEBITS
1310 Lisp_Int0 = 2
1311 Lisp_Int1 = 6 if USE_LSB_TAG else 3
1312
1313 # Unpack the Lisp value from its containing structure, if necessary.
1314 val = self.val
1315 basic_type = gdb.types.get_basic_type (val.type)
1316 if (basic_type.code == gdb.TYPE_CODE_STRUCT
1317 and gdb.types.has_field (basic_type, "i")):
1318 val = val["i"]
1319
1320 # For nil, yield "XIL(0)", which is easier to read than "XIL(0x0)".
1321 if not val:
1322 return "XIL(0)"
1323
1324 # Extract the integer representation of the value and its Lisp type.
1325 ival = int(val)
1326 itype = ival >> (0 if USE_LSB_TAG else VALBITS)
1327 itype = itype & ((1 << GCTYPEBITS) - 1)
1328
1329 # For a Lisp integer N, yield "make_number(N)".
1330 if itype == Lisp_Int0 or itype == Lisp_Int1:
1331 if USE_LSB_TAG:
1332 ival = ival >> (GCTYPEBITS - 1)
1333 elif (ival >> VALBITS) & 1:
1334 ival = ival | (-1 << VALBITS)
1335 else:
1336 ival = ival & ((1 << VALBITS) - 1)
1337 return "make_number(%d)" % ival
1338
1339 # For non-integers other than nil yield "XIL(N)", where N is a C integer.
1340 # This helps humans distinguish Lisp_Object values from ordinary
1341 # integers even when Lisp_Object is an integer.
1342 # Perhaps some day the pretty-printing could be fancier.
1343 # Prefer the unsigned representation to negative values, converting
1344 # by hand as val.cast(gdb.lookup_type("EMACS_UINT") does not work in
1345 # GDB 7.12.1; see <http://patchwork.sourceware.org/patch/11557/>.
1346 if ival < 0:
1347 ival = ival + (1 << EMACS_INT_WIDTH)
1348 return "XIL(0x%x)" % ival
1349
1350 def build_pretty_printer ():
1351 pp = Emacs_Pretty_Printers ("Emacs")
1352 pp.add_printer ('Lisp_Object', '^Lisp_Object$', Lisp_Object_Printer)
1353 return pp
1354
1355 gdb.printing.register_pretty_printer (gdb.current_objfile (),
1356 build_pretty_printer (), True)
1357end
1358
1359# GDB mishandles indentation with leading tabs when feeding it to Python.
1360# Local Variables:
1361# indent-tabs-mode: nil
1362# End:
diff --git a/src/ChangeLog.13 b/src/ChangeLog.13
index 3a58c0cc754..66f062d3d3f 100644
--- a/src/ChangeLog.13
+++ b/src/ChangeLog.13
@@ -17504,7 +17504,7 @@
17504 * casetab.c (init_casetab_once): Don't abuse the ascii eqv table for 17504 * casetab.c (init_casetab_once): Don't abuse the ascii eqv table for
17505 the upcase table. 17505 the upcase table.
17506 17506
175072013-03-27 rzl24ozi <rzl24ozi@gmail.com> (tiny changes) 175072013-03-27 rzl24ozi <rzl24ozi@gmail.com> (tiny change)
17508 17508
17509 * image.c [WINDOWSNT]: Fix calls to DEF_IMGLIB_FN for SVG function. 17509 * image.c [WINDOWSNT]: Fix calls to DEF_IMGLIB_FN for SVG function.
17510 17510
diff --git a/src/Makefile.in b/src/Makefile.in
index 5a3d0bd0445..57969d5fc58 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -48,7 +48,6 @@ lispsource = $(top_srcdir)/lisp
48lib = ../lib 48lib = ../lib
49libsrc = ../lib-src 49libsrc = ../lib-src
50etc = ../etc 50etc = ../etc
51leimdir = ${lispsource}/leim
52oldXMenudir = ../oldXMenu 51oldXMenudir = ../oldXMenu
53lwlibdir = ../lwlib 52lwlibdir = ../lwlib
54 53
@@ -347,16 +346,6 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
347am__v_at_0 = @ 346am__v_at_0 = @
348am__v_at_1 = 347am__v_at_1 =
349 348
350AUTO_DEPEND = @AUTO_DEPEND@
351DEPDIR = deps
352ifeq ($(AUTO_DEPEND),yes)
353 DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP
354 -include $(ALLOBJS:%.o=$(DEPDIR)/%.d)
355else
356 DEPFLAGS =
357 include $(srcdir)/deps.mk
358endif
359
360# Flags that might be in WARN_CFLAGS but are not valid for Objective C. 349# Flags that might be in WARN_CFLAGS but are not valid for Objective C.
361NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd 350NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd
362 351
@@ -445,6 +434,16 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \
445FIRSTFILE_OBJ=@FIRSTFILE_OBJ@ 434FIRSTFILE_OBJ=@FIRSTFILE_OBJ@
446ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj) 435ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
447 436
437AUTO_DEPEND = @AUTO_DEPEND@
438DEPDIR = deps
439ifeq ($(AUTO_DEPEND),yes)
440 DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP
441 -include $(ALLOBJS:%.o=$(DEPDIR)/%.d)
442else
443 DEPFLAGS =
444 include $(srcdir)/deps.mk
445endif
446
448all: emacs$(EXEEXT) $(OTHER_FILES) 447all: emacs$(EXEEXT) $(OTHER_FILES)
449.PHONY: all 448.PHONY: all
450 449
@@ -494,9 +493,6 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
494 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) \ 493 $(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) \
495 $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) 494 $(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS)
496 495
497$(leimdir)/leim-list.el: bootstrap-emacs$(EXEEXT)
498 $(MAKE) -C ../leim leim-list.el EMACS="$(bootstrap_exe)"
499
500## FORCE it so that admin/unidata can decide whether these files 496## FORCE it so that admin/unidata can decide whether these files
501## are up-to-date. Although since charprop depends on bootstrap-emacs, 497## are up-to-date. Although since charprop depends on bootstrap-emacs,
502## and emacs (which recreates bootstrap-emacs) depends on charprop, 498## and emacs (which recreates bootstrap-emacs) depends on charprop,
@@ -507,12 +503,8 @@ $(srcdir)/macuvs.h $(lispsource)/international/charprop.el: \
507 503
508## We require charprop.el to exist before ucs-normalize.el is 504## We require charprop.el to exist before ucs-normalize.el is
509## byte-compiled, because ucs-normalize.el needs to load 2 uni-*.el files. 505## byte-compiled, because ucs-normalize.el needs to load 2 uni-*.el files.
510$(lispsource)/international/ucs-normalize.elc: | \ 506## And ns-win requires ucs-normalize.
511 $(lispsource)/international/charprop.el 507$(lispsource)/international/ucs-normalize.elc $(lispsource)/term/ns-win.elc: | \
512
513## ns-win.el loads ucs-normalize, so it also needs the above-mentioned
514## 2 uni-*.el files to exist.
515$(lispsource)/term/ns-win.elc: | \
516 $(lispsource)/international/charprop.el 508 $(lispsource)/international/charprop.el
517 509
518lispintdir = ${lispsource}/international 510lispintdir = ${lispsource}/international
@@ -535,7 +527,7 @@ ${lispintdir}/characters.elc: ${charscript:.el=.elc}
535## since not all pieces are used on all platforms. But DOC depends 527## since not all pieces are used on all platforms. But DOC depends
536## on all of $lisp, and emacs depends on DOC, so it is ok to use $lisp here. 528## on all of $lisp, and emacs depends on DOC, so it is ok to use $lisp here.
537emacs$(EXEEXT): temacs$(EXEEXT) \ 529emacs$(EXEEXT): temacs$(EXEEXT) \
538 lisp.mk $(etc)/DOC $(lisp) $(leimdir)/leim-list.el \ 530 lisp.mk $(etc)/DOC $(lisp) \
539 $(lispsource)/international/charprop.el ${charsets} 531 $(lispsource)/international/charprop.el ${charsets}
540ifeq ($(CANNOT_DUMP),yes) 532ifeq ($(CANNOT_DUMP),yes)
541 ln -f temacs$(EXEEXT) $@ 533 ln -f temacs$(EXEEXT) $@
@@ -647,13 +639,13 @@ mostlyclean:
647 rm -f globals.h gl-stamp 639 rm -f globals.h gl-stamp
648 rm -f *.res *.tmp 640 rm -f *.res *.tmp
649clean: mostlyclean 641clean: mostlyclean
650 rm -f emacs-*.*.*$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/* 642 rm -f emacs-*.*.*[0-9]$(EXEEXT) emacs$(EXEEXT) $(DEPDIR)/*
651 643
652## bootstrap-clean is used to clean up just before a bootstrap. 644## bootstrap-clean is used to clean up just before a bootstrap.
653## It should remove all files generated during a compilation/bootstrap, 645## It should remove all files generated during a compilation/bootstrap,
654## but not things like config.status or TAGS. 646## but not things like config.status or TAGS.
655bootstrap-clean: clean 647bootstrap-clean: clean
656 rm -f epaths.h config.h config.stamp 648 rm -f emacs-module.h epaths.h config.h config.stamp
657 if test -f ./.gdbinit; then \ 649 if test -f ./.gdbinit; then \
658 mv ./.gdbinit ./.gdbinit.save; \ 650 mv ./.gdbinit ./.gdbinit.save; \
659 if test -f "$(srcdir)/.gdbinit"; then rm -f ./.gdbinit.save; \ 651 if test -f "$(srcdir)/.gdbinit"; then rm -f ./.gdbinit.save; \
diff --git a/src/alloc.c b/src/alloc.c
index ae3e1519c04..ac3de83b2b6 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -75,14 +75,20 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
75static bool valgrind_p; 75static bool valgrind_p;
76#endif 76#endif
77 77
78/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. */ 78/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
79 We turn that on by default when ENABLE_CHECKING is defined;
80 define GC_CHECK_MARKED_OBJECTS to zero to disable. */
81
82#if defined ENABLE_CHECKING && !defined GC_CHECK_MARKED_OBJECTS
83# define GC_CHECK_MARKED_OBJECTS 1
84#endif
79 85
80/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd 86/* GC_MALLOC_CHECK defined means perform validity checks of malloc'd
81 memory. Can do this only if using gmalloc.c and if not checking 87 memory. Can do this only if using gmalloc.c and if not checking
82 marked objects. */ 88 marked objects. */
83 89
84#if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \ 90#if (defined SYSTEM_MALLOC || defined DOUG_LEA_MALLOC \
85 || defined HYBRID_MALLOC || defined GC_CHECK_MARKED_OBJECTS) 91 || defined HYBRID_MALLOC || GC_CHECK_MARKED_OBJECTS)
86#undef GC_MALLOC_CHECK 92#undef GC_MALLOC_CHECK
87#endif 93#endif
88 94
@@ -3371,7 +3377,7 @@ allocate_pseudovector (int memlen, int lisplen,
3371 eassert (0 <= tag && tag <= PVEC_FONT); 3377 eassert (0 <= tag && tag <= PVEC_FONT);
3372 eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen); 3378 eassert (0 <= lisplen && lisplen <= zerolen && zerolen <= memlen);
3373 eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1); 3379 eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1);
3374 eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1); 3380 eassert (lisplen <= PSEUDOVECTOR_SIZE_MASK);
3375 3381
3376 /* Only the first LISPLEN slots will be traced normally by the GC. */ 3382 /* Only the first LISPLEN slots will be traced normally by the GC. */
3377 memclear (v->contents, zerolen * word_size); 3383 memclear (v->contents, zerolen * word_size);
@@ -3392,6 +3398,54 @@ allocate_buffer (void)
3392 return b; 3398 return b;
3393} 3399}
3394 3400
3401
3402/* Allocate a record with COUNT slots. COUNT must be positive, and
3403 includes the type slot. */
3404
3405static struct Lisp_Vector *
3406allocate_record (EMACS_INT count)
3407{
3408 if (count > PSEUDOVECTOR_SIZE_MASK)
3409 error ("Attempt to allocate a record of %"pI"d slots; max is %d",
3410 count, PSEUDOVECTOR_SIZE_MASK);
3411 struct Lisp_Vector *p = allocate_vectorlike (count);
3412 p->header.size = count;
3413 XSETPVECTYPE (p, PVEC_RECORD);
3414 return p;
3415}
3416
3417
3418DEFUN ("make-record", Fmake_record, Smake_record, 3, 3, 0,
3419 doc: /* Create a new record.
3420TYPE is its type as returned by `type-of'; it should be either a
3421symbol or a type descriptor. SLOTS is the number of non-type slots,
3422each initialized to INIT. */)
3423 (Lisp_Object type, Lisp_Object slots, Lisp_Object init)
3424{
3425 CHECK_NATNUM (slots);
3426 EMACS_INT size = XFASTINT (slots) + 1;
3427 struct Lisp_Vector *p = allocate_record (size);
3428 p->contents[0] = type;
3429 for (ptrdiff_t i = 1; i < size; i++)
3430 p->contents[i] = init;
3431 return make_lisp_ptr (p, Lisp_Vectorlike);
3432}
3433
3434
3435DEFUN ("record", Frecord, Srecord, 1, MANY, 0,
3436 doc: /* Create a new record.
3437TYPE is its type as returned by `type-of'; it should be either a
3438symbol or a type descriptor. SLOTS is used to initialize the record
3439slots with shallow copies of the arguments.
3440usage: (record TYPE &rest SLOTS) */)
3441 (ptrdiff_t nargs, Lisp_Object *args)
3442{
3443 struct Lisp_Vector *p = allocate_record (nargs);
3444 memcpy (p->contents, args, nargs * sizeof *args);
3445 return make_lisp_ptr (p, Lisp_Vectorlike);
3446}
3447
3448
3395DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, 3449DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0,
3396 doc: /* Return a newly created vector of length LENGTH, with each element being INIT. 3450 doc: /* Return a newly created vector of length LENGTH, with each element being INIT.
3397See also the function `vector'. */) 3451See also the function `vector'. */)
@@ -3888,7 +3942,6 @@ make_user_ptr (void (*finalizer) (void *), void *p)
3888 uptr->p = p; 3942 uptr->p = p;
3889 return obj; 3943 return obj;
3890} 3944}
3891
3892#endif 3945#endif
3893 3946
3894static void 3947static void
@@ -5532,7 +5585,7 @@ purecopy (Lisp_Object obj)
5532 struct Lisp_Hash_Table *h = purecopy_hash_table (table); 5585 struct Lisp_Hash_Table *h = purecopy_hash_table (table);
5533 XSET_HASH_TABLE (obj, h); 5586 XSET_HASH_TABLE (obj, h);
5534 } 5587 }
5535 else if (COMPILEDP (obj) || VECTORP (obj)) 5588 else if (COMPILEDP (obj) || VECTORP (obj) || RECORDP (obj))
5536 { 5589 {
5537 struct Lisp_Vector *objp = XVECTOR (obj); 5590 struct Lisp_Vector *objp = XVECTOR (obj);
5538 ptrdiff_t nbytes = vector_nbytes (objp); 5591 ptrdiff_t nbytes = vector_nbytes (objp);
@@ -5889,6 +5942,10 @@ garbage_collect_1 (void *end)
5889 mark_fringe_data (); 5942 mark_fringe_data ();
5890#endif 5943#endif
5891 5944
5945#ifdef HAVE_MODULES
5946 mark_modules ();
5947#endif
5948
5892 /* Everything is now marked, except for the data in font caches, 5949 /* Everything is now marked, except for the data in font caches,
5893 undo lists, and finalizers. The first two are compacted by 5950 undo lists, and finalizers. The first two are compacted by
5894 removing an items which aren't reachable otherwise. */ 5951 removing an items which aren't reachable otherwise. */
@@ -6295,7 +6352,7 @@ mark_object (Lisp_Object arg)
6295{ 6352{
6296 register Lisp_Object obj; 6353 register Lisp_Object obj;
6297 void *po; 6354 void *po;
6298#ifdef GC_CHECK_MARKED_OBJECTS 6355#if GC_CHECK_MARKED_OBJECTS
6299 struct mem_node *m; 6356 struct mem_node *m;
6300#endif 6357#endif
6301 ptrdiff_t cdr_count = 0; 6358 ptrdiff_t cdr_count = 0;
@@ -6314,7 +6371,7 @@ mark_object (Lisp_Object arg)
6314 /* Perform some sanity checks on the objects marked here. Abort if 6371 /* Perform some sanity checks on the objects marked here. Abort if
6315 we encounter an object we know is bogus. This increases GC time 6372 we encounter an object we know is bogus. This increases GC time
6316 by ~80%. */ 6373 by ~80%. */
6317#ifdef GC_CHECK_MARKED_OBJECTS 6374#if GC_CHECK_MARKED_OBJECTS
6318 6375
6319 /* Check that the object pointed to by PO is known to be a Lisp 6376 /* Check that the object pointed to by PO is known to be a Lisp
6320 structure allocated from the heap. */ 6377 structure allocated from the heap. */
@@ -6383,7 +6440,7 @@ mark_object (Lisp_Object arg)
6383 if (VECTOR_MARKED_P (ptr)) 6440 if (VECTOR_MARKED_P (ptr))
6384 break; 6441 break;
6385 6442
6386#ifdef GC_CHECK_MARKED_OBJECTS 6443#if GC_CHECK_MARKED_OBJECTS
6387 m = mem_find (po); 6444 m = mem_find (po);
6388 if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po)) 6445 if (m == MEM_NIL && !SUBRP (obj) && !main_thread_p (po))
6389 emacs_abort (); 6446 emacs_abort ();
@@ -6400,7 +6457,7 @@ mark_object (Lisp_Object arg)
6400 switch (pvectype) 6457 switch (pvectype)
6401 { 6458 {
6402 case PVEC_BUFFER: 6459 case PVEC_BUFFER:
6403#ifdef GC_CHECK_MARKED_OBJECTS 6460#if GC_CHECK_MARKED_OBJECTS
6404 { 6461 {
6405 struct buffer *b; 6462 struct buffer *b;
6406 FOR_EACH_BUFFER (b) 6463 FOR_EACH_BUFFER (b)
@@ -7107,7 +7164,7 @@ We divide the value by 1024 to make sure it fits in a Lisp integer. */)
7107{ 7164{
7108 Lisp_Object end; 7165 Lisp_Object end;
7109 7166
7110#if defined HAVE_NS || !HAVE_SBRK 7167#if defined HAVE_NS || defined __APPLE__ || !HAVE_SBRK
7111 /* Avoid warning. sbrk has no relation to memory allocated anyway. */ 7168 /* Avoid warning. sbrk has no relation to memory allocated anyway. */
7112 XSETINT (end, 0); 7169 XSETINT (end, 0);
7113#else 7170#else
@@ -7461,10 +7518,12 @@ The time is in seconds as a floating point value. */);
7461 defsubr (&Scons); 7518 defsubr (&Scons);
7462 defsubr (&Slist); 7519 defsubr (&Slist);
7463 defsubr (&Svector); 7520 defsubr (&Svector);
7521 defsubr (&Srecord);
7464 defsubr (&Sbool_vector); 7522 defsubr (&Sbool_vector);
7465 defsubr (&Smake_byte_code); 7523 defsubr (&Smake_byte_code);
7466 defsubr (&Smake_list); 7524 defsubr (&Smake_list);
7467 defsubr (&Smake_vector); 7525 defsubr (&Smake_vector);
7526 defsubr (&Smake_record);
7468 defsubr (&Smake_string); 7527 defsubr (&Smake_string);
7469 defsubr (&Smake_bool_vector); 7528 defsubr (&Smake_bool_vector);
7470 defsubr (&Smake_symbol); 7529 defsubr (&Smake_symbol);
diff --git a/src/bidi.c b/src/bidi.c
index b75ad933626..e34da778ba0 100644
--- a/src/bidi.c
+++ b/src/bidi.c
@@ -565,9 +565,7 @@ bidi_copy_it (struct bidi_it *to, struct bidi_it *from)
565 RTL characters in the offending line of text. */ 565 RTL characters in the offending line of text. */
566/* Do we need to allow customization of this limit? */ 566/* Do we need to allow customization of this limit? */
567#define BIDI_CACHE_MAX_ELTS_PER_SLOT 50000 567#define BIDI_CACHE_MAX_ELTS_PER_SLOT 50000
568#if BIDI_CACHE_CHUNK >= BIDI_CACHE_MAX_ELTS_PER_SLOT 568verify (BIDI_CACHE_CHUNK < BIDI_CACHE_MAX_ELTS_PER_SLOT);
569# error BIDI_CACHE_CHUNK must be less than BIDI_CACHE_MAX_ELTS_PER_SLOT
570#endif
571static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; 569static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT;
572static struct bidi_it *bidi_cache; 570static struct bidi_it *bidi_cache;
573static ptrdiff_t bidi_cache_size = 0; 571static ptrdiff_t bidi_cache_size = 0;
@@ -2092,7 +2090,7 @@ bidi_resolve_explicit (struct bidi_it *bidi_it)
2092 type = RLI; 2090 type = RLI;
2093 bidi_it->orig_type = type; 2091 bidi_it->orig_type = type;
2094 } 2092 }
2095 /* FALLTHROUGH */ 2093 FALLTHROUGH;
2096 case RLI: /* X5a */ 2094 case RLI: /* X5a */
2097 if (override == NEUTRAL_DIR) 2095 if (override == NEUTRAL_DIR)
2098 bidi_it->type_after_wn = type; 2096 bidi_it->type_after_wn = type;
@@ -2468,9 +2466,11 @@ typedef struct bpa_stack_entry {
2468 unsigned flags : 2; 2466 unsigned flags : 2;
2469} bpa_stack_entry; 2467} bpa_stack_entry;
2470 2468
2471/* With MAX_ALLOCA of 16KB, this should allow at least 1K slots in the 2469/* Allow for the two struct bidi_it objects too, since they can be big.
2470 With MAX_ALLOCA of 16 KiB, this should allow at least 900 slots in the
2472 BPA stack, which should be more than enough for actual bidi text. */ 2471 BPA stack, which should be more than enough for actual bidi text. */
2473#define MAX_BPA_STACK ((int)max (MAX_ALLOCA / sizeof (bpa_stack_entry), 1)) 2472enum { MAX_BPA_STACK = max (1, ((MAX_ALLOCA - 2 * sizeof (struct bidi_it))
2473 / sizeof (bpa_stack_entry))) };
2474 2474
2475/* UAX#9 says to match opening brackets with the matching closing 2475/* UAX#9 says to match opening brackets with the matching closing
2476 brackets or their canonical equivalents. As of Unicode 8.0, there 2476 brackets or their canonical equivalents. As of Unicode 8.0, there
@@ -2517,7 +2517,7 @@ typedef struct bpa_stack_entry {
2517#define PUSH_BPA_STACK \ 2517#define PUSH_BPA_STACK \
2518 do { \ 2518 do { \
2519 int ch; \ 2519 int ch; \
2520 if (bpa_sp < MAX_BPA_STACK - 1) \ 2520 if (bpa_sp < MAX_BPA_STACK - 1 && bidi_cache_last_idx <= INT_MAX) \
2521 { \ 2521 { \
2522 bpa_sp++; \ 2522 bpa_sp++; \
2523 ch = CANONICAL_EQU (bidi_it->ch); \ 2523 ch = CANONICAL_EQU (bidi_it->ch); \
@@ -2563,7 +2563,7 @@ bidi_find_bracket_pairs (struct bidi_it *bidi_it)
2563 ptrdiff_t pairing_pos; 2563 ptrdiff_t pairing_pos;
2564 int idx_at_entry = bidi_cache_idx; 2564 int idx_at_entry = bidi_cache_idx;
2565 2565
2566 eassert (MAX_BPA_STACK >= 100); 2566 verify (MAX_BPA_STACK >= 100);
2567 bidi_copy_it (&saved_it, bidi_it); 2567 bidi_copy_it (&saved_it, bidi_it);
2568 /* bidi_cache_iterator_state refuses to cache on backward scans, 2568 /* bidi_cache_iterator_state refuses to cache on backward scans,
2569 and bidi_cache_fetch_state doesn't bring scan_dir from the 2569 and bidi_cache_fetch_state doesn't bring scan_dir from the
diff --git a/src/buffer.c b/src/buffer.c
index ff4a500c8b7..80dbd3318dc 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5486,8 +5486,11 @@ A string is printed verbatim in the mode line except for %-constructs:
5486 For a modified read-only buffer, %* gives % and %+ gives *. 5486 For a modified read-only buffer, %* gives % and %+ gives *.
5487 %s -- print process status. %l -- print the current line number. 5487 %s -- print process status. %l -- print the current line number.
5488 %c -- print the current column number (this makes editing slower). 5488 %c -- print the current column number (this makes editing slower).
5489 Columns are numbered starting from the left margin, and the
5490 leftmost column is displayed as zero.
5489 To make the column number update correctly in all cases, 5491 To make the column number update correctly in all cases,
5490 `column-number-mode' must be non-nil. 5492 `column-number-mode' must be non-nil.
5493 %C -- Like %c, but the leftmost column is displayed as one.
5491 %i -- print the size of the buffer. 5494 %i -- print the size of the buffer.
5492 %I -- like %i, but use k, M, G, etc., to abbreviate. 5495 %I -- like %i, but use k, M, G, etc., to abbreviate.
5493 %p -- print percent of buffer above top of window, or Top, Bot or All. 5496 %p -- print percent of buffer above top of window, or Top, Bot or All.
@@ -5629,7 +5632,9 @@ visual lines rather than logical lines. See the documentation of
5629 DEFVAR_PER_BUFFER ("default-directory", &BVAR (current_buffer, directory), 5632 DEFVAR_PER_BUFFER ("default-directory", &BVAR (current_buffer, directory),
5630 Qstringp, 5633 Qstringp,
5631 doc: /* Name of default directory of current buffer. 5634 doc: /* Name of default directory of current buffer.
5632To interactively change the default directory, use command `cd'. */); 5635It should be a directory name (as opposed to a directory file-name).
5636On GNU and Unix systems, directory names end in a slash `/'.
5637To interactively change the default directory, use command `cd'. */);
5633 5638
5634 DEFVAR_PER_BUFFER ("auto-fill-function", &BVAR (current_buffer, auto_fill_function), 5639 DEFVAR_PER_BUFFER ("auto-fill-function", &BVAR (current_buffer, auto_fill_function),
5635 Qnil, 5640 Qnil,
diff --git a/src/buffer.h b/src/buffer.h
index a2bdc4e7294..be270fe4823 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -412,6 +412,15 @@ extern void enlarge_buffer_text (struct buffer *, ptrdiff_t);
412 ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \ 412 ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \
413 : BUF_FETCH_BYTE ((buf), (pos))) 413 : BUF_FETCH_BYTE ((buf), (pos)))
414 414
415/* Return character at byte position POS in buffer BUF. If BUF is
416 unibyte and the character is not ASCII, make the returning
417 character multibyte. */
418
419#define BUF_FETCH_CHAR_AS_MULTIBYTE(buf, pos) \
420 (! NILP (BVAR ((buf), enable_multibyte_characters)) \
421 ? BUF_FETCH_MULTIBYTE_CHAR ((buf), (pos)) \
422 : UNIBYTE_TO_CHAR (BUF_FETCH_BYTE ((buf), (pos))))
423
415/* Return the byte at byte position N in buffer BUF. */ 424/* Return the byte at byte position N in buffer BUF. */
416 425
417#define BUF_FETCH_BYTE(buf, n) \ 426#define BUF_FETCH_BYTE(buf, n) \
diff --git a/src/callint.c b/src/callint.c
index d96454883cf..96436116c8b 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -690,6 +690,7 @@ invoke it. If KEYS is omitted or nil, the return value of
690 case 'N': /* Prefix arg as number, else number from minibuffer. */ 690 case 'N': /* Prefix arg as number, else number from minibuffer. */
691 if (!NILP (prefix_arg)) 691 if (!NILP (prefix_arg))
692 goto have_prefix_arg; 692 goto have_prefix_arg;
693 FALLTHROUGH;
693 case 'n': /* Read number from minibuffer. */ 694 case 'n': /* Read number from minibuffer. */
694 args[i] = call1 (Qread_number, callint_message); 695 args[i] = call1 (Qread_number, callint_message);
695 /* Passing args[i] directly stimulates compiler bug. */ 696 /* Passing args[i] directly stimulates compiler bug. */
diff --git a/src/callproc.c b/src/callproc.c
index 05048576ce9..4cec02be7ef 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -52,6 +52,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
52#include "syswait.h" 52#include "syswait.h"
53#include "blockinput.h" 53#include "blockinput.h"
54#include "frame.h" 54#include "frame.h"
55#include "systty.h"
56#include "keyboard.h"
55 57
56#ifdef MSDOS 58#ifdef MSDOS
57#include "msdos.h" 59#include "msdos.h"
@@ -200,10 +202,11 @@ call_process_cleanup (Lisp_Object buffer)
200 message1 ("Waiting for process to die...(type C-g again to kill it instantly)"); 202 message1 ("Waiting for process to die...(type C-g again to kill it instantly)");
201 203
202 /* This will quit on C-g. */ 204 /* This will quit on C-g. */
203 wait_for_termination (synch_process_pid, 0, 1); 205 bool wait_ok = wait_for_termination (synch_process_pid, NULL, true);
204
205 synch_process_pid = 0; 206 synch_process_pid = 0;
206 message1 ("Waiting for process to die...done"); 207 message1 (wait_ok
208 ? "Waiting for process to die...done"
209 : "Waiting for process to die...internal error");
207 } 210 }
208#endif /* !MSDOS */ 211#endif /* !MSDOS */
209} 212}
@@ -240,6 +243,10 @@ Otherwise it waits for PROGRAM to terminate
240and returns a numeric exit status or a signal description string. 243and returns a numeric exit status or a signal description string.
241If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. 244If you quit, the process is killed with SIGINT, or SIGKILL if you quit again.
242 245
246The process runs in `default-directory' if that is local (as
247determined by `unhandled-file-name-directory'), or "~" otherwise. If
248you want to run a process in a remote directory use `process-file'.
249
243usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */) 250usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */)
244 (ptrdiff_t nargs, Lisp_Object *args) 251 (ptrdiff_t nargs, Lisp_Object *args)
245{ 252{
@@ -624,9 +631,28 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
624 631
625 if (pid == 0) 632 if (pid == 0)
626 { 633 {
634#ifdef DARWIN_OS
635 /* Work around a macOS bug, where SIGCHLD is apparently
636 delivered to a vforked child instead of to its parent. See:
637 http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00342.html
638 */
639 signal (SIGCHLD, SIG_DFL);
640#endif
641
627 unblock_child_signal (&oldset); 642 unblock_child_signal (&oldset);
628 643
644#ifdef DARWIN_OS
645 /* Darwin doesn't let us run setsid after a vfork, so use
646 TIOCNOTTY when necessary. */
647 int j = emacs_open (DEV_TTY, O_RDWR, 0);
648 if (j >= 0)
649 {
650 ioctl (j, TIOCNOTTY, 0);
651 emacs_close (j);
652 }
653#else
629 setsid (); 654 setsid ();
655#endif
630 656
631 /* Emacs ignores SIGPIPE, but the child should not. */ 657 /* Emacs ignores SIGPIPE, but the child should not. */
632 signal (SIGPIPE, SIG_DFL); 658 signal (SIGPIPE, SIG_DFL);
@@ -849,9 +875,10 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
849 make_number (total_read)); 875 make_number (total_read));
850 } 876 }
851 877
878 bool wait_ok = true;
852#ifndef MSDOS 879#ifndef MSDOS
853 /* Wait for it to terminate, unless it already has. */ 880 /* Wait for it to terminate, unless it already has. */
854 wait_for_termination (pid, &status, fd0 < 0); 881 wait_ok = wait_for_termination (pid, &status, fd0 < 0);
855#endif 882#endif
856 883
857 /* Don't kill any children that the subprocess may have left behind 884 /* Don't kill any children that the subprocess may have left behind
@@ -861,6 +888,9 @@ call_process (ptrdiff_t nargs, Lisp_Object *args, int filefd,
861 SAFE_FREE (); 888 SAFE_FREE ();
862 unbind_to (count, Qnil); 889 unbind_to (count, Qnil);
863 890
891 if (!wait_ok)
892 return build_unibyte_string ("internal error");
893
864 if (WIFSIGNALED (status)) 894 if (WIFSIGNALED (status))
865 { 895 {
866 const char *signame; 896 const char *signame;
diff --git a/src/casefiddle.c b/src/casefiddle.c
index 11d59444916..443d62b6259 100644
--- a/src/casefiddle.c
+++ b/src/casefiddle.c
@@ -1,3 +1,4 @@
1/* -*- coding: utf-8 -*- */
1/* GNU Emacs case conversion functions. 2/* GNU Emacs case conversion functions.
2 3
3Copyright (C) 1985, 1994, 1997-1999, 2001-2017 Free Software Foundation, 4Copyright (C) 1985, 1994, 1997-1999, 2001-2017 Free Software Foundation,
@@ -30,116 +31,312 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
30#include "keymap.h" 31#include "keymap.h"
31 32
32enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; 33enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP};
33 34
34static Lisp_Object 35/* State for casing individual characters. */
35casify_object (enum case_action flag, Lisp_Object obj) 36struct casing_context
37{
38 /* A char-table with title-case character mappings or nil. Non-nil implies
39 flag is CASE_CAPITALIZE or CASE_CAPITALIZE_UP. */
40 Lisp_Object titlecase_char_table;
41
42 /* The unconditional special-casing Unicode property char tables for upper
43 casing, lower casing and title casing respectively. */
44 Lisp_Object specialcase_char_tables[3];
45
46 /* User-requested action. */
47 enum case_action flag;
48
49 /* If true, the function operates on a buffer as opposed to a string
50 or character. When run on a buffer, syntax_prefix_flag_p is
51 taken into account when determining whether the context is within
52 a word. */
53 bool inbuffer;
54
55 /* Whether the context is within a word. */
56 bool inword;
57};
58
59/* Initialize CTX structure for casing characters. */
60static void
61prepare_casing_context (struct casing_context *ctx,
62 enum case_action flag, bool inbuffer)
36{ 63{
37 int c, c1; 64 ctx->flag = flag;
38 bool inword = flag == CASE_DOWN; 65 ctx->inbuffer = inbuffer;
66 ctx->inword = false;
67 ctx->titlecase_char_table
68 = (flag < CASE_CAPITALIZE ? Qnil
69 : uniprop_table (Qtitlecase));
70 ctx->specialcase_char_tables[CASE_UP]
71 = (flag == CASE_DOWN ? Qnil
72 : uniprop_table (Qspecial_uppercase));
73 ctx->specialcase_char_tables[CASE_DOWN]
74 = (flag == CASE_UP ? Qnil
75 : uniprop_table (Qspecial_lowercase));
76 ctx->specialcase_char_tables[CASE_CAPITALIZE]
77 = (flag < CASE_CAPITALIZE ? Qnil
78 : uniprop_table (Qspecial_titlecase));
39 79
40 /* If the case table is flagged as modified, rescan it. */ 80 /* If the case table is flagged as modified, rescan it. */
41 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1])) 81 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1]))
42 Fset_case_table (BVAR (current_buffer, downcase_table)); 82 Fset_case_table (BVAR (current_buffer, downcase_table));
43 83
44 if (NATNUMP (obj)) 84 if (inbuffer && flag >= CASE_CAPITALIZE)
85 SETUP_BUFFER_SYNTAX_TABLE (); /* For syntax_prefix_flag_p. */
86}
87
88struct casing_str_buf
89{
90 unsigned char data[max (6, MAX_MULTIBYTE_LENGTH)];
91 unsigned char len_chars;
92 unsigned char len_bytes;
93};
94
95/* Based on CTX, case character CH. If BUF is NULL, return cased character.
96 Otherwise, if BUF is non-NULL, save result in it and return whether the
97 character has been changed.
98
99 Since meaning of return value depends on arguments, it’s more convenient to
100 use case_single_character or case_character instead. */
101static int
102case_character_impl (struct casing_str_buf *buf,
103 struct casing_context *ctx, int ch)
104{
105 enum case_action flag;
106 Lisp_Object prop;
107 int cased;
108
109 /* Update inword state */
110 bool was_inword = ctx->inword;
111 ctx->inword = SYNTAX (ch) == Sword &&
112 (!ctx->inbuffer || was_inword || !syntax_prefix_flag_p (ch));
113
114 /* Normalize flag so its one of CASE_UP, CASE_DOWN or CASE_CAPITALIZE. */
115 if (ctx->flag == CASE_CAPITALIZE)
116 flag = ctx->flag - was_inword;
117 else if (ctx->flag != CASE_CAPITALIZE_UP)
118 flag = ctx->flag;
119 else if (!was_inword)
120 flag = CASE_CAPITALIZE;
121 else
45 { 122 {
46 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER 123 cased = ch;
47 | CHAR_SHIFT | CHAR_CTL | CHAR_META); 124 goto done;
48 int flags = XINT (obj) & flagbits;
49 bool multibyte = ! NILP (BVAR (current_buffer,
50 enable_multibyte_characters));
51
52 /* If the character has higher bits set
53 above the flags, return it unchanged.
54 It is not a real character. */
55 if (UNSIGNED_CMP (XFASTINT (obj), >, flagbits))
56 return obj;
57
58 c1 = XFASTINT (obj) & ~flagbits;
59 /* FIXME: Even if enable-multibyte-characters is nil, we may
60 manipulate multibyte chars. This means we have a bug for latin-1
61 chars since when we receive an int 128-255 we can't tell whether
62 it's an eight-bit byte or a latin-1 char. */
63 if (c1 >= 256)
64 multibyte = 1;
65 if (! multibyte)
66 MAKE_CHAR_MULTIBYTE (c1);
67 c = flag == CASE_DOWN ? downcase (c1) : upcase (c1);
68 if (c != c1)
69 {
70 if (! multibyte)
71 MAKE_CHAR_UNIBYTE (c);
72 XSETFASTINT (obj, c | flags);
73 }
74 return obj;
75 } 125 }
76 126
77 if (!STRINGP (obj)) 127 /* Look through the special casing entries. */
78 wrong_type_argument (Qchar_or_string_p, obj); 128 if (buf && !NILP (ctx->specialcase_char_tables[flag]))
79 else if (!STRING_MULTIBYTE (obj))
80 { 129 {
81 ptrdiff_t i; 130 prop = CHAR_TABLE_REF (ctx->specialcase_char_tables[flag], ch);
82 ptrdiff_t size = SCHARS (obj); 131 if (STRINGP (prop))
83 132 {
84 obj = Fcopy_sequence (obj); 133 struct Lisp_String *str = XSTRING (prop);
85 for (i = 0; i < size; i++) 134 if (STRING_BYTES (str) <= sizeof buf->data)
86 {
87 c = SREF (obj, i);
88 MAKE_CHAR_MULTIBYTE (c);
89 c1 = c;
90 if (inword && flag != CASE_CAPITALIZE_UP)
91 c = downcase (c);
92 else if (!uppercasep (c)
93 && (!inword || flag != CASE_CAPITALIZE_UP))
94 c = upcase (c1);
95 if ((int) flag >= (int) CASE_CAPITALIZE)
96 inword = (SYNTAX (c) == Sword);
97 if (c != c1)
98 { 135 {
99 MAKE_CHAR_UNIBYTE (c); 136 buf->len_chars = str->size;
100 /* If the char can't be converted to a valid byte, just don't 137 buf->len_bytes = STRING_BYTES (str);
101 change it. */ 138 memcpy (buf->data, str->data, buf->len_bytes);
102 if (c >= 0 && c < 256) 139 return 1;
103 SSET (obj, i, c);
104 } 140 }
105 } 141 }
106 return obj;
107 } 142 }
143
144 /* Handle simple, one-to-one case. */
145 if (flag == CASE_DOWN)
146 cased = downcase (ch);
108 else 147 else
109 { 148 {
110 ptrdiff_t i, i_byte, size = SCHARS (obj); 149 bool cased_is_set = false;
111 int len; 150 if (!NILP (ctx->titlecase_char_table))
112 USE_SAFE_ALLOCA;
113 ptrdiff_t o_size;
114 if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &o_size))
115 o_size = PTRDIFF_MAX;
116 unsigned char *dst = SAFE_ALLOCA (o_size);
117 unsigned char *o = dst;
118
119 for (i = i_byte = 0; i < size; i++, i_byte += len)
120 { 151 {
121 if (o_size - MAX_MULTIBYTE_LENGTH < o - dst) 152 prop = CHAR_TABLE_REF (ctx->titlecase_char_table, ch);
122 string_overflow (); 153 if (CHARACTERP (prop))
123 c = STRING_CHAR_AND_LENGTH (SDATA (obj) + i_byte, len); 154 {
124 if (inword && flag != CASE_CAPITALIZE_UP) 155 cased = XFASTINT (prop);
125 c = downcase (c); 156 cased_is_set = true;
126 else if (!inword || flag != CASE_CAPITALIZE_UP) 157 }
127 c = upcase (c);
128 if ((int) flag >= (int) CASE_CAPITALIZE)
129 inword = (SYNTAX (c) == Sword);
130 o += CHAR_STRING (c, o);
131 } 158 }
132 eassert (o - dst <= o_size); 159 if (!cased_is_set)
133 obj = make_multibyte_string ((char *) dst, size, o - dst); 160 cased = upcase (ch);
134 SAFE_FREE ();
135 return obj;
136 } 161 }
162
163 /* And we’re done. */
164 done:
165 if (!buf)
166 return cased;
167 buf->len_chars = 1;
168 buf->len_bytes = CHAR_STRING (cased, buf->data);
169 return cased != ch;
170}
171
172/* In Greek, lower case sigma has two forms: one when used in the middle and one
173 when used at the end of a word. Below is to help handle those cases when
174 casing.
175
176 The rule does not conflict with any other casing rules so while it is
177 a conditional one, it is independent of language. */
178
179enum { GREEK_CAPITAL_LETTER_SIGMA = 0x03A3 }; /* Σ */
180enum { GREEK_SMALL_LETTER_FINAL_SIGMA = 0x03C2 }; /* ς */
181
182/* Based on CTX, case character CH accordingly. Update CTX as necessary.
183 Return cased character.
184
185 Special casing rules (such as upcase(fi) = FI) are not handled. For
186 characters whose casing results in multiple code points, the character is
187 returned unchanged. */
188static inline int
189case_single_character (struct casing_context *ctx, int ch)
190{
191 return case_character_impl (NULL, ctx, ch);
192}
193
194/* Save in BUF result of casing character CH. Return whether casing changed the
195 character.
196
197 If not-NULL, NEXT points to the next character in the cased string. If NULL,
198 it is assumed current character is the last one being cased. This is used to
199 apply some rules which depend on proceeding state.
200
201 This is like case_single_character but also handles one-to-many casing
202 rules. */
203static bool
204case_character (struct casing_str_buf *buf, struct casing_context *ctx,
205 int ch, const unsigned char *next)
206{
207 bool was_inword = ctx->inword;
208 bool changed = case_character_impl (buf, ctx, ch);
209
210 /* If we have just down-cased a capital sigma and the next character no longer
211 has a word syntax (i.e. current character is end of word), use final
212 sigma. */
213 if (was_inword && ch == GREEK_CAPITAL_LETTER_SIGMA && changed
214 && (!next || SYNTAX (STRING_CHAR (next)) != Sword))
215 {
216 buf->len_bytes = CHAR_STRING (GREEK_SMALL_LETTER_FINAL_SIGMA, buf->data);
217 buf->len_chars = 1;
218 }
219
220 return changed;
221}
222
223static Lisp_Object
224do_casify_natnum (struct casing_context *ctx, Lisp_Object obj)
225{
226 int flagbits = (CHAR_ALT | CHAR_SUPER | CHAR_HYPER
227 | CHAR_SHIFT | CHAR_CTL | CHAR_META);
228 int ch = XFASTINT (obj);
229
230 /* If the character has higher bits set above the flags, return it unchanged.
231 It is not a real character. */
232 if (UNSIGNED_CMP (ch, >, flagbits))
233 return obj;
234
235 int flags = ch & flagbits;
236 ch = ch & ~flagbits;
237
238 /* FIXME: Even if enable-multibyte-characters is nil, we may manipulate
239 multibyte chars. This means we have a bug for latin-1 chars since when we
240 receive an int 128-255 we can't tell whether it's an eight-bit byte or
241 a latin-1 char. */
242 bool multibyte = (ch >= 256
243 || !NILP (BVAR (current_buffer,
244 enable_multibyte_characters)));
245 if (! multibyte)
246 MAKE_CHAR_MULTIBYTE (ch);
247 int cased = case_single_character (ctx, ch);
248 if (cased == ch)
249 return obj;
250
251 if (! multibyte)
252 MAKE_CHAR_UNIBYTE (cased);
253 return make_natnum (cased | flags);
254}
255
256static Lisp_Object
257do_casify_multibyte_string (struct casing_context *ctx, Lisp_Object obj)
258{
259 /* Verify that ‘data’ is the first member of struct casing_str_buf
260 so that when casting char * to struct casing_str_buf *, the
261 representation of the character is at the beginning of the
262 buffer. This is why we don’t need a separate struct
263 casing_str_buf object, and can write directly to the destination. */
264 verify (offsetof (struct casing_str_buf, data) == 0);
265
266 ptrdiff_t size = SCHARS (obj), n;
267 USE_SAFE_ALLOCA;
268 if (INT_MULTIPLY_WRAPV (size, MAX_MULTIBYTE_LENGTH, &n)
269 || INT_ADD_WRAPV (n, sizeof (struct casing_str_buf), &n))
270 n = PTRDIFF_MAX;
271 unsigned char *dst = SAFE_ALLOCA (n);
272 unsigned char *dst_end = dst + n;
273 unsigned char *o = dst;
274
275 const unsigned char *src = SDATA (obj);
276
277 for (n = 0; size; --size)
278 {
279 if (dst_end - o < sizeof (struct casing_str_buf))
280 string_overflow ();
281 int ch = STRING_CHAR_ADVANCE (src);
282 case_character ((struct casing_str_buf *) o, ctx, ch,
283 size > 1 ? src : NULL);
284 n += ((struct casing_str_buf *) o)->len_chars;
285 o += ((struct casing_str_buf *) o)->len_bytes;
286 }
287 eassert (o <= dst_end);
288 obj = make_multibyte_string ((char *) dst, n, o - dst);
289 SAFE_FREE ();
290 return obj;
291}
292
293static Lisp_Object
294do_casify_unibyte_string (struct casing_context *ctx, Lisp_Object obj)
295{
296 ptrdiff_t i, size = SCHARS (obj);
297 int ch, cased;
298
299 obj = Fcopy_sequence (obj);
300 for (i = 0; i < size; i++)
301 {
302 ch = SREF (obj, i);
303 MAKE_CHAR_MULTIBYTE (ch);
304 cased = case_single_character (ctx, ch);
305 if (ch == cased)
306 continue;
307 MAKE_CHAR_UNIBYTE (cased);
308 /* If the char can't be converted to a valid byte, just don't
309 change it. */
310 if (cased >= 0 && cased < 256)
311 SSET (obj, i, cased);
312 }
313 return obj;
314}
315
316static Lisp_Object
317casify_object (enum case_action flag, Lisp_Object obj)
318{
319 struct casing_context ctx;
320 prepare_casing_context (&ctx, flag, false);
321
322 if (NATNUMP (obj))
323 return do_casify_natnum (&ctx, obj);
324 else if (!STRINGP (obj))
325 wrong_type_argument (Qchar_or_string_p, obj);
326 else if (!SCHARS (obj))
327 return obj;
328 else if (STRING_MULTIBYTE (obj))
329 return do_casify_multibyte_string (&ctx, obj);
330 else
331 return do_casify_unibyte_string (&ctx, obj);
137} 332}
138 333
139DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, 334DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0,
140 doc: /* Convert argument to upper case and return that. 335 doc: /* Convert argument to upper case and return that.
141The argument may be a character or string. The result has the same type. 336The argument may be a character or string. The result has the same type.
142The argument object is not altered--the value is a copy. 337The argument object is not altered--the value is a copy. If argument
338is a character, characters which map to multiple code points when
339cased, e.g. fi, are returned unchanged.
143See also `capitalize', `downcase' and `upcase-initials'. */) 340See also `capitalize', `downcase' and `upcase-initials'. */)
144 (Lisp_Object obj) 341 (Lisp_Object obj)
145{ 342{
@@ -157,10 +354,12 @@ The argument object is not altered--the value is a copy. */)
157 354
158DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0, 355DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0,
159 doc: /* Convert argument to capitalized form and return that. 356 doc: /* Convert argument to capitalized form and return that.
160This means that each word's first character is upper case 357This means that each word's first character is converted to either
161and the rest is lower case. 358title case or upper case, and the rest to lower case.
162The argument may be a character or string. The result has the same type. 359The argument may be a character or string. The result has the same type.
163The argument object is not altered--the value is a copy. */) 360The argument object is not altered--the value is a copy. If argument
361is a character, characters which map to multiple code points when
362cased, e.g. fi, are returned unchanged. */)
164 (Lisp_Object obj) 363 (Lisp_Object obj)
165{ 364{
166 return casify_object (CASE_CAPITALIZE, obj); 365 return casify_object (CASE_CAPITALIZE, obj);
@@ -170,122 +369,151 @@ The argument object is not altered--the value is a copy. */)
170 369
171DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0, 370DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0,
172 doc: /* Convert the initial of each word in the argument to upper case. 371 doc: /* Convert the initial of each word in the argument to upper case.
173Do not change the other letters of each word. 372This means that each word's first character is converted to either
373title case or upper case, and the rest are left unchanged.
174The argument may be a character or string. The result has the same type. 374The argument may be a character or string. The result has the same type.
175The argument object is not altered--the value is a copy. */) 375The argument object is not altered--the value is a copy. If argument
376is a character, characters which map to multiple code points when
377cased, e.g. fi, are returned unchanged. */)
176 (Lisp_Object obj) 378 (Lisp_Object obj)
177{ 379{
178 return casify_object (CASE_CAPITALIZE_UP, obj); 380 return casify_object (CASE_CAPITALIZE_UP, obj);
179} 381}
180 382
181/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP. 383/* Based on CTX, case region in a unibyte buffer from *STARTP to *ENDP.
182 b and e specify range of buffer to operate on. */
183 384
184static void 385 Save first and last positions that has changed in *STARTP and *ENDP
185casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e) 386 respectively. If no characters were changed, save -1 to *STARTP and leave
387 *ENDP unspecified.
388
389 Always return 0. This is so that interface of this function is the same as
390 do_casify_multibyte_region. */
391static ptrdiff_t
392do_casify_unibyte_region (struct casing_context *ctx,
393 ptrdiff_t *startp, ptrdiff_t *endp)
186{ 394{
187 int c; 395 ptrdiff_t first = -1, last = -1; /* Position of first and last changes. */
188 bool inword = flag == CASE_DOWN; 396 ptrdiff_t end = *endp;
189 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
190 ptrdiff_t start, end;
191 ptrdiff_t start_byte;
192 397
193 /* Position of first and last changes. */ 398 for (ptrdiff_t pos = *startp; pos < end; ++pos)
194 ptrdiff_t first = -1, last; 399 {
400 int ch = FETCH_BYTE (pos);
401 MAKE_CHAR_MULTIBYTE (ch);
195 402
196 ptrdiff_t opoint = PT; 403 int cased = case_single_character (ctx, ch);
197 ptrdiff_t opoint_byte = PT_BYTE; 404 if (cased == ch)
405 continue;
198 406
199 if (EQ (b, e)) 407 last = pos + 1;
200 /* Not modifying because nothing marked */ 408 if (first < 0)
201 return; 409 first = pos;
202 410
203 /* If the case table is flagged as modified, rescan it. */ 411 MAKE_CHAR_UNIBYTE (cased);
204 if (NILP (XCHAR_TABLE (BVAR (current_buffer, downcase_table))->extras[1])) 412 FETCH_BYTE (pos) = cased;
205 Fset_case_table (BVAR (current_buffer, downcase_table)); 413 }
206 414
207 validate_region (&b, &e); 415 *startp = first;
208 start = XFASTINT (b); 416 *endp = last;
209 end = XFASTINT (e); 417 return 0;
210 modify_text (start, end); 418}
211 record_change (start, end - start);
212 start_byte = CHAR_TO_BYTE (start);
213 419
214 SETUP_BUFFER_SYNTAX_TABLE (); /* For syntax_prefix_flag_p. */ 420/* Based on CTX, case region in a multibyte buffer from *STARTP to *ENDP.
215 421
216 while (start < end) 422 Return number of added characters (may be negative if more characters were
217 { 423 deleted then inserted), save first and last positions that has changed in
218 int c2, len; 424 *STARTP and *ENDP respectively. If no characters were changed, return 0,
425 save -1 to *STARTP and leave *ENDP unspecified. */
426static ptrdiff_t
427do_casify_multibyte_region (struct casing_context *ctx,
428 ptrdiff_t *startp, ptrdiff_t *endp)
429{
430 ptrdiff_t first = -1, last = -1; /* Position of first and last changes. */
431 ptrdiff_t pos = *startp, pos_byte = CHAR_TO_BYTE (pos), size = *endp - pos;
432 ptrdiff_t opoint = PT, added = 0;
219 433
220 if (multibyte) 434 for (; size; --size)
435 {
436 int len;
437 int ch = STRING_CHAR_AND_LENGTH (BYTE_POS_ADDR (pos_byte), len);
438 struct casing_str_buf buf;
439 if (!case_character (&buf, ctx, ch,
440 size > 1 ? BYTE_POS_ADDR (pos_byte + len) : NULL))
221 { 441 {
222 c = FETCH_MULTIBYTE_CHAR (start_byte); 442 pos_byte += len;
223 len = CHAR_BYTES (c); 443 ++pos;
444 continue;
224 } 445 }
446
447 last = pos + buf.len_chars;
448 if (first < 0)
449 first = pos;
450
451 if (buf.len_chars == 1 && buf.len_bytes == len)
452 memcpy (BYTE_POS_ADDR (pos_byte), buf.data, len);
225 else 453 else
226 { 454 {
227 c = FETCH_BYTE (start_byte); 455 /* Replace one character with the other(s), keeping text
228 MAKE_CHAR_MULTIBYTE (c); 456 properties the same. */
229 len = 1; 457 replace_range_2 (pos, pos_byte, pos + 1, pos_byte + len,
458 (const char *) buf.data, buf.len_chars,
459 buf.len_bytes,
460 0);
461 added += (ptrdiff_t) buf.len_chars - 1;
462 if (opoint > pos)
463 opoint += (ptrdiff_t) buf.len_chars - 1;
230 } 464 }
231 c2 = c;
232 if (inword && flag != CASE_CAPITALIZE_UP)
233 c = downcase (c);
234 else if (!inword || flag != CASE_CAPITALIZE_UP)
235 c = upcase (c);
236 if ((int) flag >= (int) CASE_CAPITALIZE)
237 inword = ((SYNTAX (c) == Sword)
238 && (inword || !syntax_prefix_flag_p (c)));
239 if (c != c2)
240 {
241 last = start;
242 if (first < 0)
243 first = start;
244 465
245 if (! multibyte) 466 pos_byte += buf.len_bytes;
246 { 467 pos += buf.len_chars;
247 MAKE_CHAR_UNIBYTE (c);
248 FETCH_BYTE (start_byte) = c;
249 }
250 else if (ASCII_CHAR_P (c2) && ASCII_CHAR_P (c))
251 FETCH_BYTE (start_byte) = c;
252 else
253 {
254 int tolen = CHAR_BYTES (c);
255 int j;
256 unsigned char str[MAX_MULTIBYTE_LENGTH];
257
258 CHAR_STRING (c, str);
259 if (len == tolen)
260 {
261 /* Length is unchanged. */
262 for (j = 0; j < len; ++j)
263 FETCH_BYTE (start_byte + j) = str[j];
264 }
265 else
266 {
267 /* Replace one character with the other,
268 keeping text properties the same. */
269 replace_range_2 (start, start_byte,
270 start + 1, start_byte + len,
271 (char *) str, 1, tolen,
272 0);
273 len = tolen;
274 }
275 }
276 }
277 start++;
278 start_byte += len;
279 } 468 }
280 469
281 if (PT != opoint) 470 if (PT != opoint)
282 TEMP_SET_PT_BOTH (opoint, opoint_byte); 471 TEMP_SET_PT_BOTH (opoint, CHAR_TO_BYTE (opoint));
283 472
284 if (first >= 0) 473 *startp = first;
474 *endp = last;
475 return added;
476}
477
478/* flag is CASE_UP, CASE_DOWN or CASE_CAPITALIZE or CASE_CAPITALIZE_UP. b and
479 e specify range of buffer to operate on. Return character position of the
480 end of the region after changes. */
481static ptrdiff_t
482casify_region (enum case_action flag, Lisp_Object b, Lisp_Object e)
483{
484 ptrdiff_t added;
485 struct casing_context ctx;
486
487 validate_region (&b, &e);
488 ptrdiff_t start = XFASTINT (b);
489 ptrdiff_t end = XFASTINT (e);
490 if (start == end)
491 /* Not modifying because nothing marked. */
492 return end;
493 modify_text (start, end);
494 prepare_casing_context (&ctx, flag, true);
495
496 ptrdiff_t orig_end = end;
497 record_delete (start, make_buffer_string (start, end, true), false);
498 if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
285 { 499 {
286 signal_after_change (first, last + 1 - first, last + 1 - first); 500 record_insert (start, end - start);
287 update_compositions (first, last + 1, CHECK_ALL); 501 added = do_casify_unibyte_region (&ctx, &start, &end);
288 } 502 }
503 else
504 {
505 ptrdiff_t len = end - start, ostart = start;
506 added = do_casify_multibyte_region (&ctx, &start, &end);
507 record_insert (ostart, len + added);
508 }
509
510 if (start >= 0)
511 {
512 signal_after_change (start, end - start - added, end - start);
513 update_compositions (start, end, CHECK_ALL);
514 }
515
516 return orig_end + added;
289} 517}
290 518
291DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3, 519DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3,
@@ -345,8 +573,8 @@ point and the mark is operated on. */)
345 573
346DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r", 574DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r",
347 doc: /* Convert the region to capitalized form. 575 doc: /* Convert the region to capitalized form.
348Capitalized form means each word's first character is upper case 576This means that each word's first character is converted to either
349and the rest of it is lower case. 577title case or upper case, and the rest to lower case.
350In programs, give two arguments, the starting and ending 578In programs, give two arguments, the starting and ending
351character positions to operate on. */) 579character positions to operate on. */)
352 (Lisp_Object beg, Lisp_Object end) 580 (Lisp_Object beg, Lisp_Object end)
@@ -360,7 +588,8 @@ character positions to operate on. */)
360DEFUN ("upcase-initials-region", Fupcase_initials_region, 588DEFUN ("upcase-initials-region", Fupcase_initials_region,
361 Supcase_initials_region, 2, 2, "r", 589 Supcase_initials_region, 2, 2, "r",
362 doc: /* Upcase the initial of each word in the region. 590 doc: /* Upcase the initial of each word in the region.
363Subsequent letters of each word are not changed. 591This means that each word's first character is converted to either
592title case or upper case, and the rest are left unchanged.
364In programs, give two arguments, the starting and ending 593In programs, give two arguments, the starting and ending
365character positions to operate on. */) 594character positions to operate on. */)
366 (Lisp_Object beg, Lisp_Object end) 595 (Lisp_Object beg, Lisp_Object end)
@@ -376,9 +605,7 @@ casify_word (enum case_action flag, Lisp_Object arg)
376 ptrdiff_t farend = scan_words (PT, XINT (arg)); 605 ptrdiff_t farend = scan_words (PT, XINT (arg));
377 if (!farend) 606 if (!farend)
378 farend = XINT (arg) <= 0 ? BEGV : ZV; 607 farend = XINT (arg) <= 0 ? BEGV : ZV;
379 ptrdiff_t newpoint = max (PT, farend); 608 SET_PT (casify_region (flag, make_number (PT), make_number (farend)));
380 casify_region (flag, make_number (PT), make_number (farend));
381 SET_PT (newpoint);
382 return Qnil; 609 return Qnil;
383} 610}
384 611
@@ -426,6 +653,11 @@ void
426syms_of_casefiddle (void) 653syms_of_casefiddle (void)
427{ 654{
428 DEFSYM (Qidentity, "identity"); 655 DEFSYM (Qidentity, "identity");
656 DEFSYM (Qtitlecase, "titlecase");
657 DEFSYM (Qspecial_uppercase, "special-uppercase");
658 DEFSYM (Qspecial_lowercase, "special-lowercase");
659 DEFSYM (Qspecial_titlecase, "special-titlecase");
660
429 defsubr (&Supcase); 661 defsubr (&Supcase);
430 defsubr (&Sdowncase); 662 defsubr (&Sdowncase);
431 defsubr (&Scapitalize); 663 defsubr (&Scapitalize);
diff --git a/src/ccl.c b/src/ccl.c
index 90bd2f46794..b2caf413f7a 100644
--- a/src/ccl.c
+++ b/src/ccl.c
@@ -1000,7 +1000,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
1000 1000
1001 case CCL_ReadBranch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */ 1001 case CCL_ReadBranch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1002 CCL_READ_CHAR (reg[rrr]); 1002 CCL_READ_CHAR (reg[rrr]);
1003 /* fall through ... */ 1003 FALLTHROUGH;
1004 case CCL_Branch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */ 1004 case CCL_Branch: /* CCCCCCCCCCCCCCCCCCCCrrrXXXXX */
1005 { 1005 {
1006 int ioff = 0 <= reg[rrr] && reg[rrr] < field1 ? reg[rrr] : field1; 1006 int ioff = 0 <= reg[rrr] && reg[rrr] < field1 ? reg[rrr] : field1;
@@ -1174,6 +1174,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
1174 1174
1175 case CCL_ReadJumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */ 1175 case CCL_ReadJumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
1176 CCL_READ_CHAR (reg[rrr]); 1176 CCL_READ_CHAR (reg[rrr]);
1177 FALLTHROUGH;
1177 case CCL_JumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */ 1178 case CCL_JumpCondExprConst: /* A--D--D--R--E--S--S-rrrXXXXX */
1178 i = reg[rrr]; 1179 i = reg[rrr];
1179 jump_address = ic + ADDR; 1180 jump_address = ic + ADDR;
@@ -1184,6 +1185,7 @@ ccl_driver (struct ccl_program *ccl, int *source, int *destination, int src_size
1184 1185
1185 case CCL_ReadJumpCondExprReg: /* A--D--D--R--E--S--S-rrrXXXXX */ 1186 case CCL_ReadJumpCondExprReg: /* A--D--D--R--E--S--S-rrrXXXXX */
1186 CCL_READ_CHAR (reg[rrr]); 1187 CCL_READ_CHAR (reg[rrr]);
1188 FALLTHROUGH;
1187 case CCL_JumpCondExprReg: 1189 case CCL_JumpCondExprReg:
1188 i = reg[rrr]; 1190 i = reg[rrr];
1189 jump_address = ic + ADDR; 1191 jump_address = ic + ADDR;
diff --git a/src/charset.c b/src/charset.c
index f0b41400843..d0840f7d2a9 100644
--- a/src/charset.c
+++ b/src/charset.c
@@ -29,7 +29,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
29#include <config.h> 29#include <config.h>
30 30
31#include <errno.h> 31#include <errno.h>
32#include <stdio.h>
33#include <stdlib.h> 32#include <stdlib.h>
34#include <unistd.h> 33#include <unistd.h>
35#include <limits.h> 34#include <limits.h>
@@ -40,6 +39,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
40#include "charset.h" 39#include "charset.h"
41#include "coding.h" 40#include "coding.h"
42#include "buffer.h" 41#include "buffer.h"
42#include "sysstdio.h"
43 43
44/*** GENERAL NOTES on CODED CHARACTER SETS (CHARSETS) *** 44/*** GENERAL NOTES on CODED CHARACTER SETS (CHARSETS) ***
45 45
@@ -416,15 +416,15 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
416 int c; 416 int c;
417 unsigned n; 417 unsigned n;
418 418
419 while ((c = getc (fp)) != EOF) 419 while ((c = getc_unlocked (fp)) != EOF)
420 { 420 {
421 if (c == '#') 421 if (c == '#')
422 { 422 {
423 while ((c = getc (fp)) != EOF && c != '\n'); 423 while ((c = getc_unlocked (fp)) != EOF && c != '\n');
424 } 424 }
425 else if (c == '0') 425 else if (c == '0')
426 { 426 {
427 if ((c = getc (fp)) == EOF || c == 'x') 427 if ((c = getc_unlocked (fp)) == EOF || c == 'x')
428 break; 428 break;
429 } 429 }
430 } 430 }
@@ -434,7 +434,7 @@ read_hex (FILE *fp, bool *eof, bool *overflow)
434 return 0; 434 return 0;
435 } 435 }
436 n = 0; 436 n = 0;
437 while (c_isxdigit (c = getc (fp))) 437 while (c_isxdigit (c = getc_unlocked (fp)))
438 { 438 {
439 if (INT_LEFT_SHIFT_OVERFLOW (n, 4)) 439 if (INT_LEFT_SHIFT_OVERFLOW (n, 4))
440 *overflow = 1; 440 *overflow = 1;
@@ -508,7 +508,7 @@ load_charset_map_from_file (struct charset *charset, Lisp_Object mapfile,
508 from = read_hex (fp, &eof, &overflow); 508 from = read_hex (fp, &eof, &overflow);
509 if (eof) 509 if (eof)
510 break; 510 break;
511 if (getc (fp) == '-') 511 if (getc_unlocked (fp) == '-')
512 to = read_hex (fp, &eof, &overflow); 512 to = read_hex (fp, &eof, &overflow);
513 else 513 else
514 to = from; 514 to = from;
diff --git a/src/chartab.c b/src/chartab.c
index fa5a8e41164..8392c0c07dc 100644
--- a/src/chartab.c
+++ b/src/chartab.c
@@ -185,7 +185,7 @@ Lisp_Object
185copy_char_table (Lisp_Object table) 185copy_char_table (Lisp_Object table)
186{ 186{
187 Lisp_Object copy; 187 Lisp_Object copy;
188 int size = XCHAR_TABLE (table)->header.size & PSEUDOVECTOR_SIZE_MASK; 188 int size = PVSIZE (table);
189 int i; 189 int i;
190 190
191 copy = Fmake_vector (make_number (size), Qnil); 191 copy = Fmake_vector (make_number (size), Qnil);
diff --git a/src/cm.c b/src/cm.c
index efa50b0f58d..9a90f37445c 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -19,10 +19,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20 20
21#include <config.h> 21#include <config.h>
22#include <stdio.h>
23 22
24#include "lisp.h" 23#include "lisp.h"
25#include "cm.h" 24#include "cm.h"
25#include "sysstdio.h"
26#include "termchar.h" 26#include "termchar.h"
27#include "tparam.h" 27#include "tparam.h"
28 28
@@ -45,8 +45,8 @@ int
45cmputc (int c) 45cmputc (int c)
46{ 46{
47 if (current_tty->termscript) 47 if (current_tty->termscript)
48 putc (c & 0177, current_tty->termscript); 48 putc_unlocked (c & 0177, current_tty->termscript);
49 putc (c & 0177, current_tty->output); 49 putc_unlocked (c & 0177, current_tty->output);
50 return c; 50 return c;
51} 51}
52 52
@@ -117,11 +117,11 @@ cmcheckmagic (struct tty_display_info *tty)
117 if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) 117 if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
118 emacs_abort (); 118 emacs_abort ();
119 if (tty->termscript) 119 if (tty->termscript)
120 putc ('\r', tty->termscript); 120 putc_unlocked ('\r', tty->termscript);
121 putc ('\r', tty->output); 121 putc_unlocked ('\r', tty->output);
122 if (tty->termscript) 122 if (tty->termscript)
123 putc ('\n', tty->termscript); 123 putc_unlocked ('\n', tty->termscript);
124 putc ('\n', tty->output); 124 putc_unlocked ('\n', tty->output);
125 curX (tty) = 0; 125 curX (tty) = 0;
126 curY (tty)++; 126 curY (tty)++;
127 } 127 }
diff --git a/src/coding.c b/src/coding.c
index e341a71f576..5682fc015ad 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -1449,7 +1449,7 @@ decode_coding_utf_8 (struct coding_system *coding)
1449} 1449}
1450 1450
1451 1451
1452static bool 1452bool
1453encode_coding_utf_8 (struct coding_system *coding) 1453encode_coding_utf_8 (struct coding_system *coding)
1454{ 1454{
1455 bool multibytep = coding->dst_multibyte; 1455 bool multibytep = coding->dst_multibyte;
@@ -3611,7 +3611,7 @@ decode_coding_iso_2022 (struct coding_system *coding)
3611 || CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS) 3611 || CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS)
3612 goto invalid_code; 3612 goto invalid_code;
3613 /* This is a graphic character, we fall down ... */ 3613 /* This is a graphic character, we fall down ... */
3614 3614 FALLTHROUGH;
3615 case ISO_graphic_plane_1: 3615 case ISO_graphic_plane_1:
3616 if (charset_id_1 < 0) 3616 if (charset_id_1 < 0)
3617 goto invalid_code; 3617 goto invalid_code;
@@ -3646,6 +3646,7 @@ decode_coding_iso_2022 (struct coding_system *coding)
3646 case ISO_single_shift_2_7: 3646 case ISO_single_shift_2_7:
3647 if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS)) 3647 if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SEVEN_BITS))
3648 goto invalid_code; 3648 goto invalid_code;
3649 FALLTHROUGH;
3649 case ISO_single_shift_2: 3650 case ISO_single_shift_2:
3650 if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT)) 3651 if (! (CODING_ISO_FLAGS (coding) & CODING_ISO_FLAG_SINGLE_SHIFT))
3651 goto invalid_code; 3652 goto invalid_code;
@@ -3797,6 +3798,7 @@ decode_coding_iso_2022 (struct coding_system *coding)
3797 { 3798 {
3798 case ']': /* end of the current direction */ 3799 case ']': /* end of the current direction */
3799 coding->mode &= ~CODING_MODE_DIRECTION; 3800 coding->mode &= ~CODING_MODE_DIRECTION;
3801 break;
3800 3802
3801 case '0': /* end of the current direction */ 3803 case '0': /* end of the current direction */
3802 case '1': /* start of left-to-right direction */ 3804 case '1': /* start of left-to-right direction */
diff --git a/src/coding.h b/src/coding.h
index 7a1dd682b29..8ed851d99ff 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -96,39 +96,6 @@ enum define_coding_undecided_arg_index
96extern Lisp_Object Vcoding_system_hash_table; 96extern Lisp_Object Vcoding_system_hash_table;
97 97
98 98
99/* Enumeration of coding system type. */
100
101enum coding_system_type
102 {
103 coding_type_charset,
104 coding_type_utf_8,
105 coding_type_utf_16,
106 coding_type_iso_2022,
107 coding_type_emacs_mule,
108 coding_type_sjis,
109 coding_type_ccl,
110 coding_type_raw_text,
111 coding_type_undecided,
112 coding_type_max
113 };
114
115
116/* Enumeration of end-of-line format type. */
117
118enum end_of_line_type
119 {
120 eol_lf, /* Line-feed only, same as Emacs' internal
121 format. */
122 eol_crlf, /* Sequence of carriage-return and
123 line-feed. */
124 eol_cr, /* Carriage-return only. */
125 eol_any, /* Accept any of above. Produce line-feed
126 only. */
127 eol_undecided, /* This value is used to denote that the
128 eol-type is not yet undecided. */
129 eol_type_max
130 };
131
132/* Enumeration of index to an attribute vector of a coding system. */ 99/* Enumeration of index to an attribute vector of a coding system. */
133 100
134enum coding_attr_index 101enum coding_attr_index
@@ -697,6 +664,7 @@ struct coding_system
697 664
698/* Extern declarations. */ 665/* Extern declarations. */
699extern Lisp_Object code_conversion_save (bool, bool); 666extern Lisp_Object code_conversion_save (bool, bool);
667extern bool encode_coding_utf_8 (struct coding_system *);
700extern void setup_coding_system (Lisp_Object, struct coding_system *); 668extern void setup_coding_system (Lisp_Object, struct coding_system *);
701extern Lisp_Object coding_charset_list (struct coding_system *); 669extern Lisp_Object coding_charset_list (struct coding_system *);
702extern Lisp_Object coding_system_charset_list (Lisp_Object); 670extern Lisp_Object coding_system_charset_list (Lisp_Object);
diff --git a/src/composite.c b/src/composite.c
index b673c53ac83..05a296329a6 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -867,7 +867,6 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
867 Lisp_Object string) 867 Lisp_Object string)
868{ 868{
869 ptrdiff_t count = SPECPDL_INDEX (); 869 ptrdiff_t count = SPECPDL_INDEX ();
870 struct frame *f = XFRAME (win->frame);
871 Lisp_Object pos = make_number (charpos); 870 Lisp_Object pos = make_number (charpos);
872 ptrdiff_t to; 871 ptrdiff_t to;
873 ptrdiff_t pt = PT, pt_byte = PT_BYTE; 872 ptrdiff_t pt = PT, pt_byte = PT_BYTE;
@@ -893,6 +892,7 @@ autocmp_chars (Lisp_Object rule, ptrdiff_t charpos, ptrdiff_t bytepos,
893 to = limit = charpos + len; 892 to = limit = charpos + len;
894 font_object = win->frame; 893 font_object = win->frame;
895#ifdef HAVE_WINDOW_SYSTEM 894#ifdef HAVE_WINDOW_SYSTEM
895 struct frame *f = XFRAME (font_object);
896 if (FRAME_WINDOW_P (f)) 896 if (FRAME_WINDOW_P (f))
897 { 897 {
898 font_object = font_range (charpos, bytepos, &to, win, face, string); 898 font_object = font_range (charpos, bytepos, &to, win, face, string);
diff --git a/src/conf_post.h b/src/conf_post.h
index e146b9bbe8a..e1d6a9397d3 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -57,7 +57,9 @@ typedef bool bool_bf;
57#endif 57#endif
58 58
59/* Simulate __has_attribute on compilers that lack it. It is used only 59/* Simulate __has_attribute on compilers that lack it. It is used only
60 on arguments like alloc_size that are handled in this simulation. */ 60 on arguments like alloc_size that are handled in this simulation.
61 __has_attribute should be used only in #if expressions, as Oracle
62 Studio 12.5's __has_attribute does not work in plain code. */
61#ifndef __has_attribute 63#ifndef __has_attribute
62# define __has_attribute(a) __has_attribute_##a 64# define __has_attribute(a) __has_attribute_##a
63# define __has_attribute_alloc_size GNUC_PREREQ (4, 3, 0) 65# define __has_attribute_alloc_size GNUC_PREREQ (4, 3, 0)
@@ -94,17 +96,11 @@ typedef bool bool_bf;
94#endif 96#endif
95 97
96#ifdef DARWIN_OS 98#ifdef DARWIN_OS
97#ifdef emacs 99#if defined emacs && !defined CANNOT_DUMP
98#define malloc unexec_malloc 100#define malloc unexec_malloc
99#define realloc unexec_realloc 101#define realloc unexec_realloc
100#define free unexec_free 102#define free unexec_free
101#endif 103#endif
102/* The following solves the problem that Emacs hangs when evaluating
103 (make-comint "test0" "/nodir/nofile" nil "") when /nodir/nofile
104 does not exist. Also, setsid is not allowed in the vfork child's
105 context as of Darwin 9/Mac OS X 10.5. */
106#undef HAVE_WORKING_VFORK
107#define vfork fork
108#endif /* DARWIN_OS */ 104#endif /* DARWIN_OS */
109 105
110/* If HYBRID_MALLOC is defined (e.g., on Cygwin), emacs will use 106/* If HYBRID_MALLOC is defined (e.g., on Cygwin), emacs will use
@@ -250,6 +246,12 @@ extern int emacs_setenv_TZ (char const *);
250# define ATTRIBUTE_FORMAT(spec) /* empty */ 246# define ATTRIBUTE_FORMAT(spec) /* empty */
251#endif 247#endif
252 248
249#if GNUC_PREREQ (7, 0, 0)
250# define FALLTHROUGH __attribute__ ((__fallthrough__))
251#else
252# define FALLTHROUGH ((void) 0)
253#endif
254
253#if GNUC_PREREQ (4, 4, 0) && defined __GLIBC_MINOR__ 255#if GNUC_PREREQ (4, 4, 0) && defined __GLIBC_MINOR__
254# define PRINTF_ARCHETYPE __gnu_printf__ 256# define PRINTF_ARCHETYPE __gnu_printf__
255#elif GNUC_PREREQ (4, 4, 0) && defined __MINGW32__ 257#elif GNUC_PREREQ (4, 4, 0) && defined __MINGW32__
@@ -263,6 +265,20 @@ extern int emacs_setenv_TZ (char const *);
263#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST 265#define ATTRIBUTE_CONST _GL_ATTRIBUTE_CONST
264#define ATTRIBUTE_UNUSED _GL_UNUSED 266#define ATTRIBUTE_UNUSED _GL_UNUSED
265 267
268#if GNUC_PREREQ (3, 3, 0) && !defined __ICC
269# define ATTRIBUTE_MAY_ALIAS __attribute__ ((__may_alias__))
270#else
271# define ATTRIBUTE_MAY_ALIAS
272#endif
273
274/* Declare NAME to be a pointer to an object of type TYPE, initialized
275 to the address ADDR, which may be of a different type. Accesses
276 via NAME may alias with other accesses with the traditional
277 behavior, even if options like gcc -fstrict-aliasing are used. */
278
279#define DECLARE_POINTER_ALIAS(name, type, addr) \
280 type ATTRIBUTE_MAY_ALIAS *name = (type *) (addr)
281
266#if 3 <= __GNUC__ 282#if 3 <= __GNUC__
267# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) 283# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
268#else 284#else
@@ -302,6 +318,12 @@ extern int emacs_setenv_TZ (char const *);
302# define ATTRIBUTE_NO_SANITIZE_ADDRESS 318# define ATTRIBUTE_NO_SANITIZE_ADDRESS
303#endif 319#endif
304 320
321/* gcc -fsanitize=address does not work with vfork in Fedora 25 x86-64.
322 For now, assume that this problem occurs on all platforms. */
323#if ADDRESS_SANITIZER && !defined vfork
324# define vfork fork
325#endif
326
305/* Some versions of GNU/Linux define noinline in their headers. */ 327/* Some versions of GNU/Linux define noinline in their headers. */
306#ifdef noinline 328#ifdef noinline
307#undef noinline 329#undef noinline
diff --git a/src/data.c b/src/data.c
index ae8dd9721c2..559844b03fd 100644
--- a/src/data.c
+++ b/src/data.c
@@ -228,8 +228,6 @@ for example, (type-of 1) returns `integer'. */)
228 return Qmarker; 228 return Qmarker;
229 case Lisp_Misc_Overlay: 229 case Lisp_Misc_Overlay:
230 return Qoverlay; 230 return Qoverlay;
231 case Lisp_Misc_Float:
232 return Qfloat;
233 case Lisp_Misc_Finalizer: 231 case Lisp_Misc_Finalizer:
234 return Qfinalizer; 232 return Qfinalizer;
235#ifdef HAVE_MODULES 233#ifdef HAVE_MODULES
@@ -267,6 +265,17 @@ for example, (type-of 1) returns `integer'. */)
267 case PVEC_MUTEX: return Qmutex; 265 case PVEC_MUTEX: return Qmutex;
268 case PVEC_CONDVAR: return Qcondition_variable; 266 case PVEC_CONDVAR: return Qcondition_variable;
269 case PVEC_TERMINAL: return Qterminal; 267 case PVEC_TERMINAL: return Qterminal;
268 case PVEC_RECORD:
269 {
270 Lisp_Object t = AREF (object, 0);
271 if (RECORDP (t) && 1 < PVSIZE (t))
272 /* Return the type name field of the class! */
273 return AREF (t, 1);
274 else
275 return t;
276 }
277 case PVEC_MODULE_FUNCTION:
278 return Qmodule_function;
270 /* "Impossible" cases. */ 279 /* "Impossible" cases. */
271 case PVEC_XWIDGET: 280 case PVEC_XWIDGET:
272 case PVEC_OTHER: 281 case PVEC_OTHER:
@@ -359,6 +368,15 @@ DEFUN ("vectorp", Fvectorp, Svectorp, 1, 1, 0,
359 return Qnil; 368 return Qnil;
360} 369}
361 370
371DEFUN ("recordp", Frecordp, Srecordp, 1, 1, 0,
372 doc: /* Return t if OBJECT is a record. */)
373 (Lisp_Object object)
374{
375 if (RECORDP (object))
376 return Qt;
377 return Qnil;
378}
379
362DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0, 380DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0,
363 doc: /* Return t if OBJECT is a string. */ 381 doc: /* Return t if OBJECT is a string. */
364 attributes: const) 382 attributes: const)
@@ -474,6 +492,14 @@ DEFUN ("byte-code-function-p", Fbyte_code_function_p, Sbyte_code_function_p,
474 return Qnil; 492 return Qnil;
475} 493}
476 494
495DEFUN ("module-function-p", Fmodule_function_p, Smodule_function_p, 1, 1, NULL,
496 doc: /* Return t if OBJECT is a function loaded from a dynamic module. */
497 attributes: const)
498 (Lisp_Object object)
499{
500 return MODULE_FUNCTIONP (object) ? Qt : Qnil;
501}
502
477DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, 503DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0,
478 doc: /* Return t if OBJECT is a character or a string. */ 504 doc: /* Return t if OBJECT is a character or a string. */
479 attributes: const) 505 attributes: const)
@@ -672,12 +698,10 @@ global value outside of any lexical scope. */)
672 return (EQ (valcontents, Qunbound) ? Qnil : Qt); 698 return (EQ (valcontents, Qunbound) ? Qnil : Qt);
673} 699}
674 700
675/* FIXME: It has been previously suggested to make this function an 701/* It has been previously suggested to make this function an alias for
676 alias for symbol-function, but upon discussion at Bug#23957, 702 symbol-function, but upon discussion at Bug#23957, there is a risk
677 there is a risk breaking backward compatibility, as some users of 703 breaking backward compatibility, as some users of fboundp may
678 fboundp may expect `t' in particular, rather than any true 704 expect `t' in particular, rather than any true value. */
679 value. An alias is still welcome so long as the compatibility
680 issues are addressed. */
681DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, 705DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0,
682 doc: /* Return t if SYMBOL's function definition is not void. */) 706 doc: /* Return t if SYMBOL's function definition is not void. */)
683 (register Lisp_Object symbol) 707 (register Lisp_Object symbol)
@@ -884,7 +908,7 @@ Value, if non-nil, is a list (interactive SPEC). */)
884 } 908 }
885 else if (COMPILEDP (fun)) 909 else if (COMPILEDP (fun))
886 { 910 {
887 if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE) 911 if (PVSIZE (fun) > COMPILED_INTERACTIVE)
888 return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE)); 912 return list2 (Qinteractive, AREF (fun, COMPILED_INTERACTIVE));
889 } 913 }
890 else if (AUTOLOADP (fun)) 914 else if (AUTOLOADP (fun))
@@ -2133,7 +2157,7 @@ If the current binding is global (the default), the value is nil. */)
2133 else if (!BUFFER_OBJFWDP (valcontents)) 2157 else if (!BUFFER_OBJFWDP (valcontents))
2134 return Qnil; 2158 return Qnil;
2135 } 2159 }
2136 /* FALLTHROUGH */ 2160 FALLTHROUGH;
2137 case SYMBOL_LOCALIZED: 2161 case SYMBOL_LOCALIZED:
2138 /* For a local variable, record both the symbol and which 2162 /* For a local variable, record both the symbol and which
2139 buffer's or frame's value we are saving. */ 2163 buffer's or frame's value we are saving. */
@@ -2248,8 +2272,8 @@ function chain of symbols. */)
2248/* Extract and set vector and string elements. */ 2272/* Extract and set vector and string elements. */
2249 2273
2250DEFUN ("aref", Faref, Saref, 2, 2, 0, 2274DEFUN ("aref", Faref, Saref, 2, 2, 0,
2251 doc: /* Return the element of ARRAY at index IDX. 2275 doc: /* Return the element of ARG at index IDX.
2252ARRAY may be a vector, a string, a char-table, a bool-vector, 2276ARG may be a vector, a string, a char-table, a bool-vector, a record,
2253or a byte-code object. IDX starts at 0. */) 2277or a byte-code object. IDX starts at 0. */)
2254 (register Lisp_Object array, Lisp_Object idx) 2278 (register Lisp_Object array, Lisp_Object idx)
2255{ 2279{
@@ -2287,8 +2311,8 @@ or a byte-code object. IDX starts at 0. */)
2287 ptrdiff_t size = 0; 2311 ptrdiff_t size = 0;
2288 if (VECTORP (array)) 2312 if (VECTORP (array))
2289 size = ASIZE (array); 2313 size = ASIZE (array);
2290 else if (COMPILEDP (array)) 2314 else if (COMPILEDP (array) || RECORDP (array))
2291 size = ASIZE (array) & PSEUDOVECTOR_SIZE_MASK; 2315 size = PVSIZE (array);
2292 else 2316 else
2293 wrong_type_argument (Qarrayp, array); 2317 wrong_type_argument (Qarrayp, array);
2294 2318
@@ -2308,7 +2332,8 @@ bool-vector. IDX starts at 0. */)
2308 2332
2309 CHECK_NUMBER (idx); 2333 CHECK_NUMBER (idx);
2310 idxval = XINT (idx); 2334 idxval = XINT (idx);
2311 CHECK_ARRAY (array, Qarrayp); 2335 if (! RECORDP (array))
2336 CHECK_ARRAY (array, Qarrayp);
2312 2337
2313 if (VECTORP (array)) 2338 if (VECTORP (array))
2314 { 2339 {
@@ -2328,7 +2353,13 @@ bool-vector. IDX starts at 0. */)
2328 CHECK_CHARACTER (idx); 2353 CHECK_CHARACTER (idx);
2329 CHAR_TABLE_SET (array, idxval, newelt); 2354 CHAR_TABLE_SET (array, idxval, newelt);
2330 } 2355 }
2331 else 2356 else if (RECORDP (array))
2357 {
2358 if (idxval < 0 || idxval >= PVSIZE (array))
2359 args_out_of_range (array, idx);
2360 ASET (array, idxval, newelt);
2361 }
2362 else /* STRINGP */
2332 { 2363 {
2333 int c; 2364 int c;
2334 2365
@@ -3039,9 +3070,12 @@ usage: (logxor &rest INTS-OR-MARKERS) */)
3039} 3070}
3040 3071
3041static Lisp_Object 3072static Lisp_Object
3042ash_lsh_impl (register Lisp_Object value, Lisp_Object count, bool lsh) 3073ash_lsh_impl (Lisp_Object value, Lisp_Object count, bool lsh)
3043{ 3074{
3044 register Lisp_Object val; 3075 /* This code assumes that signed right shifts are arithmetic. */
3076 verify ((EMACS_INT) -1 >> 1 == -1);
3077
3078 Lisp_Object val;
3045 3079
3046 CHECK_NUMBER (value); 3080 CHECK_NUMBER (value);
3047 CHECK_NUMBER (count); 3081 CHECK_NUMBER (count);
@@ -3049,12 +3083,12 @@ ash_lsh_impl (register Lisp_Object value, Lisp_Object count, bool lsh)
3049 if (XINT (count) >= EMACS_INT_WIDTH) 3083 if (XINT (count) >= EMACS_INT_WIDTH)
3050 XSETINT (val, 0); 3084 XSETINT (val, 0);
3051 else if (XINT (count) > 0) 3085 else if (XINT (count) > 0)
3052 XSETINT (val, XUINT (value) << XFASTINT (count)); 3086 XSETINT (val, XUINT (value) << XINT (count));
3053 else if (XINT (count) <= -EMACS_INT_WIDTH) 3087 else if (XINT (count) <= -EMACS_INT_WIDTH)
3054 XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0); 3088 XSETINT (val, lsh ? 0 : XINT (value) < 0 ? -1 : 0);
3055 else 3089 else
3056 XSETINT (val, lsh ? XUINT (value) >> -XINT (count) : \ 3090 XSETINT (val, (lsh ? XUINT (value) >> -XINT (count)
3057 XINT (value) >> -XINT (count)); 3091 : XINT (value) >> -XINT (count)));
3058 return val; 3092 return val;
3059} 3093}
3060 3094
@@ -3563,7 +3597,6 @@ syms_of_data (void)
3563 3597
3564 DEFSYM (Qquote, "quote"); 3598 DEFSYM (Qquote, "quote");
3565 DEFSYM (Qlambda, "lambda"); 3599 DEFSYM (Qlambda, "lambda");
3566 DEFSYM (Qsubr, "subr");
3567 DEFSYM (Qerror_conditions, "error-conditions"); 3600 DEFSYM (Qerror_conditions, "error-conditions");
3568 DEFSYM (Qerror_message, "error-message"); 3601 DEFSYM (Qerror_message, "error-message");
3569 DEFSYM (Qtop_level, "top-level"); 3602 DEFSYM (Qtop_level, "top-level");
@@ -3604,6 +3637,7 @@ syms_of_data (void)
3604 DEFSYM (Qsequencep, "sequencep"); 3637 DEFSYM (Qsequencep, "sequencep");
3605 DEFSYM (Qbufferp, "bufferp"); 3638 DEFSYM (Qbufferp, "bufferp");
3606 DEFSYM (Qvectorp, "vectorp"); 3639 DEFSYM (Qvectorp, "vectorp");
3640 DEFSYM (Qrecordp, "recordp");
3607 DEFSYM (Qbool_vector_p, "bool-vector-p"); 3641 DEFSYM (Qbool_vector_p, "bool-vector-p");
3608 DEFSYM (Qchar_or_string_p, "char-or-string-p"); 3642 DEFSYM (Qchar_or_string_p, "char-or-string-p");
3609 DEFSYM (Qmarkerp, "markerp"); 3643 DEFSYM (Qmarkerp, "markerp");
@@ -3704,28 +3738,31 @@ syms_of_data (void)
3704 DEFSYM (Qoverlay, "overlay"); 3738 DEFSYM (Qoverlay, "overlay");
3705 DEFSYM (Qfinalizer, "finalizer"); 3739 DEFSYM (Qfinalizer, "finalizer");
3706#ifdef HAVE_MODULES 3740#ifdef HAVE_MODULES
3741 DEFSYM (Qmodule_function, "module-function");
3707 DEFSYM (Quser_ptr, "user-ptr"); 3742 DEFSYM (Quser_ptr, "user-ptr");
3708#endif 3743#endif
3709 DEFSYM (Qfloat, "float"); 3744 DEFSYM (Qfloat, "float");
3710 DEFSYM (Qwindow_configuration, "window-configuration"); 3745 DEFSYM (Qwindow_configuration, "window-configuration");
3711 DEFSYM (Qprocess, "process"); 3746 DEFSYM (Qprocess, "process");
3712 DEFSYM (Qwindow, "window"); 3747 DEFSYM (Qwindow, "window");
3748 DEFSYM (Qsubr, "subr");
3713 DEFSYM (Qcompiled_function, "compiled-function"); 3749 DEFSYM (Qcompiled_function, "compiled-function");
3714 DEFSYM (Qbuffer, "buffer"); 3750 DEFSYM (Qbuffer, "buffer");
3715 DEFSYM (Qframe, "frame"); 3751 DEFSYM (Qframe, "frame");
3716 DEFSYM (Qvector, "vector"); 3752 DEFSYM (Qvector, "vector");
3753 DEFSYM (Qrecord, "record");
3717 DEFSYM (Qchar_table, "char-table"); 3754 DEFSYM (Qchar_table, "char-table");
3718 DEFSYM (Qbool_vector, "bool-vector"); 3755 DEFSYM (Qbool_vector, "bool-vector");
3719 DEFSYM (Qhash_table, "hash-table"); 3756 DEFSYM (Qhash_table, "hash-table");
3720 DEFSYM (Qthread, "thread"); 3757 DEFSYM (Qthread, "thread");
3721 DEFSYM (Qmutex, "mutex"); 3758 DEFSYM (Qmutex, "mutex");
3722 DEFSYM (Qcondition_variable, "condition-variable"); 3759 DEFSYM (Qcondition_variable, "condition-variable");
3723
3724 DEFSYM (Qdefun, "defun");
3725
3726 DEFSYM (Qfont_spec, "font-spec"); 3760 DEFSYM (Qfont_spec, "font-spec");
3727 DEFSYM (Qfont_entity, "font-entity"); 3761 DEFSYM (Qfont_entity, "font-entity");
3728 DEFSYM (Qfont_object, "font-object"); 3762 DEFSYM (Qfont_object, "font-object");
3763 DEFSYM (Qterminal, "terminal");
3764
3765 DEFSYM (Qdefun, "defun");
3729 3766
3730 DEFSYM (Qinteractive_form, "interactive-form"); 3767 DEFSYM (Qinteractive_form, "interactive-form");
3731 DEFSYM (Qdefalias_fset_function, "defalias-fset-function"); 3768 DEFSYM (Qdefalias_fset_function, "defalias-fset-function");
@@ -3750,6 +3787,7 @@ syms_of_data (void)
3750 defsubr (&Sstringp); 3787 defsubr (&Sstringp);
3751 defsubr (&Smultibyte_string_p); 3788 defsubr (&Smultibyte_string_p);
3752 defsubr (&Svectorp); 3789 defsubr (&Svectorp);
3790 defsubr (&Srecordp);
3753 defsubr (&Schar_table_p); 3791 defsubr (&Schar_table_p);
3754 defsubr (&Svector_or_char_table_p); 3792 defsubr (&Svector_or_char_table_p);
3755 defsubr (&Sbool_vector_p); 3793 defsubr (&Sbool_vector_p);
@@ -3759,6 +3797,7 @@ syms_of_data (void)
3759 defsubr (&Smarkerp); 3797 defsubr (&Smarkerp);
3760 defsubr (&Ssubrp); 3798 defsubr (&Ssubrp);
3761 defsubr (&Sbyte_code_function_p); 3799 defsubr (&Sbyte_code_function_p);
3800 defsubr (&Smodule_function_p);
3762 defsubr (&Schar_or_string_p); 3801 defsubr (&Schar_or_string_p);
3763 defsubr (&Sthreadp); 3802 defsubr (&Sthreadp);
3764 defsubr (&Smutexp); 3803 defsubr (&Smutexp);
diff --git a/src/dispextern.h b/src/dispextern.h
index 679820d5063..8644ce26d13 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -1106,7 +1106,7 @@ struct glyph_row *matrix_row (struct glyph_matrix *, int);
1106#define MATRIX_BOTTOM_TEXT_ROW(MATRIX, W) \ 1106#define MATRIX_BOTTOM_TEXT_ROW(MATRIX, W) \
1107 ((MATRIX)->rows \ 1107 ((MATRIX)->rows \
1108 + (MATRIX)->nrows \ 1108 + (MATRIX)->nrows \
1109 - (WINDOW_WANTS_MODELINE_P ((W)) ? 1 : 0)) 1109 - (window_wants_mode_line ((W)) ? 1 : 0))
1110 1110
1111/* Non-zero if the face of the last glyph in ROW's text area has 1111/* Non-zero if the face of the last glyph in ROW's text area has
1112 to be drawn to the end of the text area. */ 1112 to be drawn to the end of the text area. */
@@ -1469,40 +1469,6 @@ struct glyph_string
1469#define DESIRED_HEADER_LINE_HEIGHT(W) \ 1469#define DESIRED_HEADER_LINE_HEIGHT(W) \
1470 MATRIX_HEADER_LINE_HEIGHT ((W)->desired_matrix) 1470 MATRIX_HEADER_LINE_HEIGHT ((W)->desired_matrix)
1471 1471
1472/* PXW: The height checks below serve to show at least one text line
1473 instead of a mode- and/or header line when a window gets very small.
1474 But (1) the check fails when the mode- or header-line is taller than
1475 the associated frame's line height and (2) we don't care much about
1476 text visibility anyway when shrinking a frame containing a toolbar.
1477
1478 So maybe these checks should be removed and any clipping left to the
1479 window manager. */
1480
1481/* Value is true if window W wants a mode line and is large enough
1482 to accommodate it. */
1483#define WINDOW_WANTS_MODELINE_P(W) \
1484 (BUFFERP ((W)->contents) \
1485 ? (!MINI_WINDOW_P (W) \
1486 && !(W)->pseudo_window_p \
1487 && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W))) \
1488 && !NILP (BVAR (XBUFFER ((W)->contents), mode_line_format)) \
1489 && WINDOW_PIXEL_HEIGHT (W) > WINDOW_FRAME_LINE_HEIGHT (W)) \
1490 : false)
1491
1492/* Value is true if window W wants a header line and is large enough
1493 to accommodate it. */
1494#define WINDOW_WANTS_HEADER_LINE_P(W) \
1495 (BUFFERP ((W)->contents) \
1496 ? (!MINI_WINDOW_P (W) \
1497 && !(W)->pseudo_window_p \
1498 && FRAME_WANTS_MODELINE_P (XFRAME (WINDOW_FRAME (W))) \
1499 && !NILP (BVAR (XBUFFER ((W)->contents), header_line_format)) \
1500 && (WINDOW_PIXEL_HEIGHT (W) \
1501 > (WINDOW_WANTS_MODELINE_P (W) \
1502 ? (2 * WINDOW_FRAME_LINE_HEIGHT (W)) \
1503 : WINDOW_FRAME_LINE_HEIGHT (W)))) \
1504 : false)
1505
1506/* Return proper value to be used as baseline offset of font that has 1472/* Return proper value to be used as baseline offset of font that has
1507 ASCENT and DESCENT to draw characters by the font at the vertical 1473 ASCENT and DESCENT to draw characters by the font at the vertical
1508 center of the line of frame F. 1474 center of the line of frame F.
@@ -1784,6 +1750,7 @@ enum face_id
1784 WINDOW_DIVIDER_FACE_ID, 1750 WINDOW_DIVIDER_FACE_ID,
1785 WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID, 1751 WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID,
1786 WINDOW_DIVIDER_LAST_PIXEL_FACE_ID, 1752 WINDOW_DIVIDER_LAST_PIXEL_FACE_ID,
1753 INTERNAL_BORDER_FACE_ID,
1787 BASIC_FACE_ID_SENTINEL 1754 BASIC_FACE_ID_SENTINEL
1788}; 1755};
1789 1756
diff --git a/src/dispnew.c b/src/dispnew.c
index 27c69bde831..93ef6a55a2e 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -377,7 +377,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
377 { 377 {
378 window_box (w, ANY_AREA, 0, 0, &window_width, &window_height); 378 window_box (w, ANY_AREA, 0, 0, &window_width, &window_height);
379 379
380 header_line_p = WINDOW_WANTS_HEADER_LINE_P (w); 380 header_line_p = window_wants_header_line (w);
381 header_line_changed_p = header_line_p != matrix->header_line_p; 381 header_line_changed_p = header_line_p != matrix->header_line_p;
382 } 382 }
383 matrix->header_line_p = header_line_p; 383 matrix->header_line_p = header_line_p;
@@ -446,7 +446,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
446 446
447 if (w == NULL 447 if (w == NULL
448 || (row == matrix->rows + dim.height - 1 448 || (row == matrix->rows + dim.height - 1
449 && WINDOW_WANTS_MODELINE_P (w)) 449 && window_wants_mode_line (w))
450 || (row == matrix->rows && matrix->header_line_p)) 450 || (row == matrix->rows && matrix->header_line_p))
451 { 451 {
452 row->glyphs[TEXT_AREA] 452 row->glyphs[TEXT_AREA]
@@ -491,7 +491,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
491 491
492 /* The mode line, if displayed, never has marginal areas. */ 492 /* The mode line, if displayed, never has marginal areas. */
493 if ((row == matrix->rows + dim.height - 1 493 if ((row == matrix->rows + dim.height - 1
494 && !(w && WINDOW_WANTS_MODELINE_P (w))) 494 && !(w && window_wants_mode_line (w)))
495 || (row == matrix->rows && matrix->header_line_p)) 495 || (row == matrix->rows && matrix->header_line_p))
496 { 496 {
497 row->glyphs[TEXT_AREA] 497 row->glyphs[TEXT_AREA]
@@ -570,7 +570,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
570 the mode line, if any, since otherwise it will remain 570 the mode line, if any, since otherwise it will remain
571 disabled in the current matrix, and expose events won't 571 disabled in the current matrix, and expose events won't
572 redraw it. */ 572 redraw it. */
573 if (WINDOW_WANTS_MODELINE_P (w)) 573 if (window_wants_mode_line (w))
574 w->update_mode_line = 1; 574 w->update_mode_line = 1;
575 } 575 }
576 else if (matrix == w->desired_matrix) 576 else if (matrix == w->desired_matrix)
@@ -3126,9 +3126,9 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
3126 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 3126 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
3127 { 3127 {
3128 if (FRAME_TTY (f)->termscript) 3128 if (FRAME_TTY (f)->termscript)
3129 fflush (FRAME_TTY (f)->termscript); 3129 fflush_unlocked (FRAME_TTY (f)->termscript);
3130 if (FRAME_TERMCAP_P (f)) 3130 if (FRAME_TERMCAP_P (f))
3131 fflush (FRAME_TTY (f)->output); 3131 fflush_unlocked (FRAME_TTY (f)->output);
3132 } 3132 }
3133 3133
3134 /* Check window matrices for lost pointers. */ 3134 /* Check window matrices for lost pointers. */
@@ -3181,8 +3181,8 @@ update_frame_with_menu (struct frame *f, int row, int col)
3181 update_end (f); 3181 update_end (f);
3182 3182
3183 if (FRAME_TTY (f)->termscript) 3183 if (FRAME_TTY (f)->termscript)
3184 fflush (FRAME_TTY (f)->termscript); 3184 fflush_unlocked (FRAME_TTY (f)->termscript);
3185 fflush (FRAME_TTY (f)->output); 3185 fflush_unlocked (FRAME_TTY (f)->output);
3186 /* Check window matrices for lost pointers. */ 3186 /* Check window matrices for lost pointers. */
3187#if GLYPH_DEBUG 3187#if GLYPH_DEBUG
3188#if 0 3188#if 0
@@ -4531,7 +4531,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
4531 ptrdiff_t outq = __fpending (display_output); 4531 ptrdiff_t outq = __fpending (display_output);
4532 if (outq > 900 4532 if (outq > 900
4533 || (outq > 20 && ((i - 1) % preempt_count == 0))) 4533 || (outq > 20 && ((i - 1) % preempt_count == 0)))
4534 fflush (display_output); 4534 fflush_unlocked (display_output);
4535 } 4535 }
4536 } 4536 }
4537 4537
@@ -5188,7 +5188,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
5188 start position, i.e. it excludes the header-line row, but 5188 start position, i.e. it excludes the header-line row, but
5189 MATRIX_ROW includes the header-line row. Adjust for a possible 5189 MATRIX_ROW includes the header-line row. Adjust for a possible
5190 header-line row. */ 5190 header-line row. */
5191 it_vpos = it.vpos + WINDOW_WANTS_HEADER_LINE_P (w); 5191 it_vpos = it.vpos + window_wants_header_line (w);
5192 if (it_vpos < w->current_matrix->nrows 5192 if (it_vpos < w->current_matrix->nrows
5193 && (row = MATRIX_ROW (w->current_matrix, it_vpos), 5193 && (row = MATRIX_ROW (w->current_matrix, it_vpos),
5194 row->enabled_p)) 5194 row->enabled_p))
@@ -5615,13 +5615,13 @@ when TERMINAL is nil. */)
5615 5615
5616 if (tty->termscript) 5616 if (tty->termscript)
5617 { 5617 {
5618 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); 5618 fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->termscript);
5619 fflush (tty->termscript); 5619 fflush_unlocked (tty->termscript);
5620 } 5620 }
5621 out = tty->output; 5621 out = tty->output;
5622 } 5622 }
5623 fwrite (SDATA (string), 1, SBYTES (string), out); 5623 fwrite_unlocked (SDATA (string), 1, SBYTES (string), out);
5624 fflush (out); 5624 fflush_unlocked (out);
5625 unblock_input (); 5625 unblock_input ();
5626 return Qnil; 5626 return Qnil;
5627} 5627}
@@ -5636,7 +5636,7 @@ terminate any keyboard macro currently executing. */)
5636 if (!NILP (arg)) 5636 if (!NILP (arg))
5637 { 5637 {
5638 if (noninteractive) 5638 if (noninteractive)
5639 putchar (07); 5639 putchar_unlocked (07);
5640 else 5640 else
5641 ring_bell (XFRAME (selected_frame)); 5641 ring_bell (XFRAME (selected_frame));
5642 } 5642 }
@@ -5650,7 +5650,7 @@ void
5650bitch_at_user (void) 5650bitch_at_user (void)
5651{ 5651{
5652 if (noninteractive) 5652 if (noninteractive)
5653 putchar (07); 5653 putchar_unlocked (07);
5654 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */ 5654 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
5655 { 5655 {
5656 const char *msg 5656 const char *msg
diff --git a/src/doc.c b/src/doc.c
index 1e7e3fcf6a6..345e18b9186 100644
--- a/src/doc.c
+++ b/src/doc.c
@@ -340,9 +340,11 @@ string is passed through `substitute-command-keys'. */)
340 fun = XCDR (fun); 340 fun = XCDR (fun);
341 if (SUBRP (fun)) 341 if (SUBRP (fun))
342 doc = make_number (XSUBR (fun)->doc); 342 doc = make_number (XSUBR (fun)->doc);
343 else if (MODULE_FUNCTIONP (fun))
344 doc = XMODULE_FUNCTION (fun)->documentation;
343 else if (COMPILEDP (fun)) 345 else if (COMPILEDP (fun))
344 { 346 {
345 if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) <= COMPILED_DOC_STRING) 347 if (PVSIZE (fun) <= COMPILED_DOC_STRING)
346 return Qnil; 348 return Qnil;
347 else 349 else
348 { 350 {
@@ -500,7 +502,7 @@ store_function_docstring (Lisp_Object obj, EMACS_INT offset)
500 { 502 {
501 /* This bytecode object must have a slot for the 503 /* This bytecode object must have a slot for the
502 docstring, since we've found a docstring for it. */ 504 docstring, since we've found a docstring for it. */
503 if ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_DOC_STRING) 505 if (PVSIZE (fun) > COMPILED_DOC_STRING)
504 ASET (fun, COMPILED_DOC_STRING, make_number (offset)); 506 ASET (fun, COMPILED_DOC_STRING, make_number (offset));
505 else 507 else
506 { 508 {
diff --git a/src/doprnt.c b/src/doprnt.c
index 09051adc053..418601acb02 100644
--- a/src/doprnt.c
+++ b/src/doprnt.c
@@ -352,6 +352,7 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
352 352
353 case 'S': 353 case 'S':
354 string[-1] = 's'; 354 string[-1] = 's';
355 FALLTHROUGH;
355 case 's': 356 case 's':
356 if (fmtcpy[1] != 's') 357 if (fmtcpy[1] != 's')
357 minlen = atoi (&fmtcpy[1]); 358 minlen = atoi (&fmtcpy[1]);
@@ -437,7 +438,9 @@ doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
437 } 438 }
438 439
439 case '%': 440 case '%':
440 fmt--; /* Drop thru and this % will be treated as normal */ 441 /* Treat this '%' as normal. */
442 fmt0 = fmt - 1;
443 break;
441 } 444 }
442 } 445 }
443 446
diff --git a/src/dynlib.c b/src/dynlib.c
index 95619236d43..47ba5e3d91b 100644
--- a/src/dynlib.c
+++ b/src/dynlib.c
@@ -28,6 +28,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28 28
29#include "dynlib.h" 29#include "dynlib.h"
30 30
31#include <stddef.h>
32
31#ifdef WINDOWSNT 33#ifdef WINDOWSNT
32 34
33/* MS-Windows systems. */ 35/* MS-Windows systems. */
@@ -120,15 +122,13 @@ dynlib_sym (dynlib_handle_ptr h, const char *sym)
120 return (void *)sym_addr; 122 return (void *)sym_addr;
121} 123}
122 124
123bool 125void
124dynlib_addr (void *addr, const char **fname, const char **symname) 126dynlib_addr (void *addr, const char **fname, const char **symname)
125{ 127{
126 static char dll_filename[MAX_UTF8_PATH]; 128 static char dll_filename[MAX_UTF8_PATH];
127 static char addr_str[22];
128 static GetModuleHandleExA_Proc s_pfn_Get_Module_HandleExA = NULL; 129 static GetModuleHandleExA_Proc s_pfn_Get_Module_HandleExA = NULL;
129 char *dll_fn = NULL; 130 char *dll_fn = NULL;
130 HMODULE hm_kernel32 = NULL; 131 HMODULE hm_kernel32 = NULL;
131 bool result = false;
132 HMODULE hm_dll = NULL; 132 HMODULE hm_dll = NULL;
133 wchar_t mfn_w[MAX_PATH]; 133 wchar_t mfn_w[MAX_PATH];
134 char mfn_a[MAX_PATH]; 134 char mfn_a[MAX_PATH];
@@ -206,23 +206,19 @@ dynlib_addr (void *addr, const char **fname, const char **symname)
206 dynlib_last_err = GetLastError (); 206 dynlib_last_err = GetLastError ();
207 } 207 }
208 if (dll_fn) 208 if (dll_fn)
209 { 209 dostounix_filename (dll_fn);
210 dostounix_filename (dll_fn);
211 /* We cannot easily produce the function name, since
212 typically all of the module functions will be unexported,
213 and probably even static, which means the symbols can be
214 obtained only if we link against libbfd (and the DLL can
215 be stripped anyway). So we just show the address and the
216 file name; they can use that with addr2line or GDB to
217 recover the symbolic name. */
218 sprintf (addr_str, "at 0x%x", (DWORD_PTR)addr);
219 *symname = addr_str;
220 result = true;
221 }
222 } 210 }
223 211
224 *fname = dll_fn; 212 *fname = dll_fn;
225 return result; 213
214 /* We cannot easily produce the function name, since typically all
215 of the module functions will be unexported, and probably even
216 static, which means the symbols can be obtained only if we link
217 against libbfd (and the DLL can be stripped anyway). So we just
218 show the address and the file name (see print_vectorlike in
219 print.c); they can use that with addr2line or GDB to recover the
220 symbolic name. */
221 *symname = NULL;
226} 222}
227 223
228const char * 224const char *
@@ -283,19 +279,19 @@ dynlib_sym (dynlib_handle_ptr h, const char *sym)
283 return dlsym (h, sym); 279 return dlsym (h, sym);
284} 280}
285 281
286bool 282void
287dynlib_addr (void *ptr, const char **path, const char **sym) 283dynlib_addr (void *ptr, const char **path, const char **sym)
288{ 284{
285 *path = NULL;
286 *sym = NULL;
289#ifdef HAVE_DLADDR 287#ifdef HAVE_DLADDR
290 Dl_info info; 288 Dl_info info;
291 if (dladdr (ptr, &info) && info.dli_fname && info.dli_sname) 289 if (dladdr (ptr, &info) && info.dli_fname && info.dli_sname)
292 { 290 {
293 *path = info.dli_fname; 291 *path = info.dli_fname;
294 *sym = info.dli_sname; 292 *sym = info.dli_sname;
295 return true;
296 } 293 }
297#endif 294#endif
298 return false;
299} 295}
300 296
301const char * 297const char *
diff --git a/src/dynlib.h b/src/dynlib.h
index 5ccec11bc79..1d53b8e5b2f 100644
--- a/src/dynlib.h
+++ b/src/dynlib.h
@@ -24,11 +24,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 24
25typedef void *dynlib_handle_ptr; 25typedef void *dynlib_handle_ptr;
26dynlib_handle_ptr dynlib_open (const char *path); 26dynlib_handle_ptr dynlib_open (const char *path);
27void *dynlib_sym (dynlib_handle_ptr h, const char *sym);
28typedef struct dynlib_function_ptr_nonce *(*dynlib_function_ptr) (void);
29dynlib_function_ptr dynlib_func (dynlib_handle_ptr h, const char *sym);
30bool dynlib_addr (void *ptr, const char **path, const char **sym);
31const char *dynlib_error (void);
32int dynlib_close (dynlib_handle_ptr h); 27int dynlib_close (dynlib_handle_ptr h);
28const char *dynlib_error (void);
29
30ATTRIBUTE_MAY_ALIAS void *dynlib_sym (dynlib_handle_ptr h, const char *sym);
31
32typedef struct dynlib_function_ptr_nonce *(ATTRIBUTE_MAY_ALIAS *dynlib_function_ptr) (void);
33dynlib_function_ptr dynlib_func (dynlib_handle_ptr h, const char *sym);
34
35/* Sets *FILE to the file name from which PTR was loaded, and *SYM to
36 its symbol name. If the file or symbol name could not be
37 determined, set the corresponding argument to NULL. */
38void dynlib_addr (void *ptr, const char **file, const char **sym);
33 39
34#endif /* DYNLIB_H */ 40#endif /* DYNLIB_H */
diff --git a/src/editfns.c b/src/editfns.c
index 2dafd8e7b1b..da99c055b54 100644
--- a/src/editfns.c
+++ b/src/editfns.c
@@ -48,6 +48,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
48#include <float.h> 48#include <float.h>
49#include <limits.h> 49#include <limits.h>
50 50
51#include <c-ctype.h>
51#include <intprops.h> 52#include <intprops.h>
52#include <stdlib.h> 53#include <stdlib.h>
53#include <strftime.h> 54#include <strftime.h>
@@ -81,10 +82,8 @@ static Lisp_Object styled_format (ptrdiff_t, Lisp_Object *, bool);
81 82
82enum { tzeqlen = sizeof "TZ=" - 1 }; 83enum { tzeqlen = sizeof "TZ=" - 1 };
83 84
84/* Time zones equivalent to current local time, to wall clock time, 85/* Time zones equivalent to current local time and to UTC, respectively. */
85 and to UTC, respectively. */
86static timezone_t local_tz; 86static timezone_t local_tz;
87static timezone_t wall_clock_tz;
88static timezone_t const utc_tz = 0; 87static timezone_t const utc_tz = 0;
89 88
90/* The cached value of Vsystem_name. This is used only to compare it 89/* The cached value of Vsystem_name. This is used only to compare it
@@ -226,7 +225,7 @@ tzlookup (Lisp_Object zone, bool settz)
226void 225void
227init_editfns (bool dumping) 226init_editfns (bool dumping)
228{ 227{
229#if !defined CANNOT_DUMP && defined HAVE_TZSET 228#if !defined CANNOT_DUMP
230 /* A valid but unlikely setting for the TZ environment variable. 229 /* A valid but unlikely setting for the TZ environment variable.
231 It is OK (though a bit slower) if the user chooses this value. */ 230 It is OK (though a bit slower) if the user chooses this value. */
232 static char dump_tz_string[] = "TZ=UtC0"; 231 static char dump_tz_string[] = "TZ=UtC0";
@@ -245,17 +244,15 @@ init_editfns (bool dumping)
245 and skip the rest of this function. */ 244 and skip the rest of this function. */
246 if (dumping) 245 if (dumping)
247 { 246 {
248# ifdef HAVE_TZSET
249 xputenv (dump_tz_string); 247 xputenv (dump_tz_string);
250 tzset (); 248 tzset ();
251# endif
252 return; 249 return;
253 } 250 }
254#endif 251#endif
255 252
256 char *tz = getenv ("TZ"); 253 char *tz = getenv ("TZ");
257 254
258#if !defined CANNOT_DUMP && defined HAVE_TZSET 255#if !defined CANNOT_DUMP
259 /* If the execution TZ happens to be the same as the dump TZ, 256 /* If the execution TZ happens to be the same as the dump TZ,
260 change it to some other value and then change it back, 257 change it to some other value and then change it back,
261 to force the underlying implementation to reload the TZ info. 258 to force the underlying implementation to reload the TZ info.
@@ -271,7 +268,6 @@ init_editfns (bool dumping)
271 268
272 /* Set the time zone rule now, so that the call to putenv is done 269 /* Set the time zone rule now, so that the call to putenv is done
273 before multiple threads are active. */ 270 before multiple threads are active. */
274 wall_clock_tz = xtzalloc (0);
275 tzlookup (tz ? build_string (tz) : Qwall, true); 271 tzlookup (tz ? build_string (tz) : Qwall, true);
276 272
277 pw = getpwuid (getuid ()); 273 pw = getpwuid (getuid ());
@@ -1597,10 +1593,10 @@ time_arith (Lisp_Object a, Lisp_Object b,
1597 { 1593 {
1598 default: 1594 default:
1599 val = Fcons (make_number (t.ps), val); 1595 val = Fcons (make_number (t.ps), val);
1600 /* Fall through. */ 1596 FALLTHROUGH;
1601 case 3: 1597 case 3:
1602 val = Fcons (make_number (t.us), val); 1598 val = Fcons (make_number (t.us), val);
1603 /* Fall through. */ 1599 FALLTHROUGH;
1604 case 2: 1600 case 2:
1605 val = Fcons (make_number (t.lo), val); 1601 val = Fcons (make_number (t.lo), val);
1606 val = Fcons (make_number (t.hi), val); 1602 val = Fcons (make_number (t.hi), val);
@@ -2144,7 +2140,7 @@ the epoch. The obsolete form (HIGH . LOW) is also still accepted.
2144The optional ZONE is omitted or nil for Emacs local time, t for 2140The optional ZONE is omitted or nil for Emacs local time, t for
2145Universal Time, `wall' for system wall clock time, or a string as in 2141Universal Time, `wall' for system wall clock time, or a string as in
2146the TZ environment variable. It can also be a list (as from 2142the TZ environment variable. It can also be a list (as from
2147`current-time-zone') or an integer (as from `decode-time') applied 2143`current-time-zone') or an integer (the UTC offset in seconds) applied
2148without consideration for daylight saving time. 2144without consideration for daylight saving time.
2149 2145
2150The list has the following nine members: SEC is an integer between 0 2146The list has the following nine members: SEC is an integer between 0
@@ -3109,6 +3105,207 @@ determines whether case is significant or ignored. */)
3109 /* Same length too => they are equal. */ 3105 /* Same length too => they are equal. */
3110 return make_number (0); 3106 return make_number (0);
3111} 3107}
3108
3109
3110/* Set up necessary definitions for diffseq.h; see comments in
3111 diffseq.h for explanation. */
3112
3113#undef ELEMENT
3114#undef EQUAL
3115
3116#define XVECREF_YVECREF_EQUAL(ctx, xoff, yoff) \
3117 buffer_chars_equal ((ctx), (xoff), (yoff))
3118
3119#define OFFSET ptrdiff_t
3120
3121#define EXTRA_CONTEXT_FIELDS \
3122 /* Buffers to compare. */ \
3123 struct buffer *buffer_a; \
3124 struct buffer *buffer_b; \
3125 /* Bit vectors recording for each character whether it was deleted
3126 or inserted. */ \
3127 unsigned char *deletions; \
3128 unsigned char *insertions;
3129
3130#define NOTE_DELETE(ctx, xoff) set_bit ((ctx)->deletions, (xoff))
3131#define NOTE_INSERT(ctx, yoff) set_bit ((ctx)->insertions, (yoff))
3132
3133struct context;
3134static void set_bit (unsigned char *, OFFSET);
3135static bool bit_is_set (const unsigned char *, OFFSET);
3136static bool buffer_chars_equal (struct context *, OFFSET, OFFSET);
3137
3138#include "minmax.h"
3139#include "diffseq.h"
3140
3141DEFUN ("replace-buffer-contents", Freplace_buffer_contents,
3142 Sreplace_buffer_contents, 1, 1, "bSource buffer: ",
3143 doc: /* Replace accessible portion of current buffer with that of SOURCE.
3144SOURCE can be a buffer or a string that names a buffer.
3145Interactively, prompt for SOURCE.
3146As far as possible the replacement is non-destructive, i.e. existing
3147buffer contents, markers, properties, and overlays in the current
3148buffer stay intact. */)
3149 (Lisp_Object source)
3150{
3151 struct buffer *a = current_buffer;
3152 Lisp_Object source_buffer = Fget_buffer (source);
3153 if (NILP (source_buffer))
3154 nsberror (source);
3155 struct buffer *b = XBUFFER (source_buffer);
3156 if (! BUFFER_LIVE_P (b))
3157 error ("Selecting deleted buffer");
3158 if (a == b)
3159 error ("Cannot replace a buffer with itself");
3160
3161 ptrdiff_t min_a = BEGV;
3162 ptrdiff_t min_b = BUF_BEGV (b);
3163 ptrdiff_t size_a = ZV - min_a;
3164 ptrdiff_t size_b = BUF_ZV (b) - min_b;
3165 eassume (size_a >= 0);
3166 eassume (size_b >= 0);
3167 bool a_empty = size_a == 0;
3168 bool b_empty = size_b == 0;
3169
3170 /* Handle trivial cases where at least one accessible portion is
3171 empty. */
3172
3173 if (a_empty && b_empty)
3174 return Qnil;
3175
3176 if (a_empty)
3177 return Finsert_buffer_substring (source, Qnil, Qnil);
3178
3179 if (b_empty)
3180 {
3181 del_range_both (BEGV, BEGV_BYTE, ZV, ZV_BYTE, true);
3182 return Qnil;
3183 }
3184
3185 /* FIXME: It is not documented how to initialize the contents of the
3186 context structure. This code cargo-cults from the existing
3187 caller in src/analyze.c of GNU Diffutils, which appears to
3188 work. */
3189
3190 ptrdiff_t diags = size_a + size_b + 3;
3191 ptrdiff_t *buffer;
3192 USE_SAFE_ALLOCA;
3193 SAFE_NALLOCA (buffer, 2, diags);
3194 /* Micro-optimization: Casting to size_t generates much better
3195 code. */
3196 ptrdiff_t del_bytes = (size_t) size_a / CHAR_BIT + 1;
3197 ptrdiff_t ins_bytes = (size_t) size_b / CHAR_BIT + 1;
3198 struct context ctx = {
3199 .buffer_a = a,
3200 .buffer_b = b,
3201 .deletions = SAFE_ALLOCA (del_bytes),
3202 .insertions = SAFE_ALLOCA (ins_bytes),
3203 .fdiag = buffer + size_b + 1,
3204 .bdiag = buffer + diags + size_b + 1,
3205 /* FIXME: Find a good number for .too_expensive. */
3206 .too_expensive = 1000000,
3207 };
3208 memclear (ctx.deletions, del_bytes);
3209 memclear (ctx.insertions, ins_bytes);
3210 /* compareseq requires indices to be zero-based. We add BEGV back
3211 later. */
3212 bool early_abort = compareseq (0, size_a, 0, size_b, false, &ctx);
3213 /* Since we didn’t define EARLY_ABORT, we should never abort
3214 early. */
3215 eassert (! early_abort);
3216 SAFE_FREE ();
3217
3218 Fundo_boundary ();
3219 ptrdiff_t count = SPECPDL_INDEX ();
3220 record_unwind_protect (save_excursion_restore, save_excursion_save ());
3221
3222 ptrdiff_t i = size_a;
3223 ptrdiff_t j = size_b;
3224 /* Walk backwards through the lists of changes. This was also
3225 cargo-culted from src/analyze.c in GNU Diffutils. Because we
3226 walk backwards, we don’t have to keep the positions in sync. */
3227 while (i >= 0 || j >= 0)
3228 {
3229 /* Check whether there is a change (insertion or deletion)
3230 before the current position. */
3231 if ((i > 0 && bit_is_set (ctx.deletions, i - 1)) ||
3232 (j > 0 && bit_is_set (ctx.insertions, j - 1)))
3233 {
3234 ptrdiff_t end_a = min_a + i;
3235 ptrdiff_t end_b = min_b + j;
3236 /* Find the beginning of the current change run. */
3237 while (i > 0 && bit_is_set (ctx.deletions, i - 1))
3238 --i;
3239 while (j > 0 && bit_is_set (ctx.insertions, j - 1))
3240 --j;
3241 ptrdiff_t beg_a = min_a + i;
3242 ptrdiff_t beg_b = min_b + j;
3243 eassert (beg_a >= BEGV);
3244 eassert (beg_b >= BUF_BEGV (b));
3245 eassert (beg_a <= end_a);
3246 eassert (beg_b <= end_b);
3247 eassert (end_a <= ZV);
3248 eassert (end_b <= BUF_ZV (b));
3249 eassert (beg_a < end_a || beg_b < end_b);
3250 if (beg_a < end_a)
3251 del_range (beg_a, end_a);
3252 if (beg_b < end_b)
3253 {
3254 SET_PT (beg_a);
3255 Finsert_buffer_substring (source, make_natnum (beg_b),
3256 make_natnum (end_b));
3257 }
3258 }
3259 --i;
3260 --j;
3261 }
3262
3263 return unbind_to (count, Qnil);
3264}
3265
3266static void
3267set_bit (unsigned char *a, ptrdiff_t i)
3268{
3269 eassert (i >= 0);
3270 /* Micro-optimization: Casting to size_t generates much better
3271 code. */
3272 size_t j = i;
3273 a[j / CHAR_BIT] |= (1 << (j % CHAR_BIT));
3274}
3275
3276static bool
3277bit_is_set (const unsigned char *a, ptrdiff_t i)
3278{
3279 eassert (i >= 0);
3280 /* Micro-optimization: Casting to size_t generates much better
3281 code. */
3282 size_t j = i;
3283 return a[j / CHAR_BIT] & (1 << (j % CHAR_BIT));
3284}
3285
3286/* Return true if the characters at position POS_A of buffer
3287 CTX->buffer_a and at position POS_B of buffer CTX->buffer_b are
3288 equal. POS_A and POS_B are zero-based. Text properties are
3289 ignored. */
3290
3291static bool
3292buffer_chars_equal (struct context *ctx,
3293 ptrdiff_t pos_a, ptrdiff_t pos_b)
3294{
3295 eassert (pos_a >= 0);
3296 pos_a += BUF_BEGV (ctx->buffer_a);
3297 eassert (pos_a >= BUF_BEGV (ctx->buffer_a));
3298 eassert (pos_a < BUF_ZV (ctx->buffer_a));
3299
3300 eassert (pos_b >= 0);
3301 pos_b += BUF_BEGV (ctx->buffer_b);
3302 eassert (pos_b >= BUF_BEGV (ctx->buffer_b));
3303 eassert (pos_b < BUF_ZV (ctx->buffer_b));
3304
3305 return BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_a, pos_a)
3306 == BUF_FETCH_CHAR_AS_MULTIBYTE (ctx->buffer_b, pos_b);
3307}
3308
3112 3309
3113static void 3310static void
3114subst_char_in_region_unwind (Lisp_Object arg) 3311subst_char_in_region_unwind (Lisp_Object arg)
@@ -3739,11 +3936,10 @@ In batch mode, the message is printed to the standard error stream,
3739followed by a newline. 3936followed by a newline.
3740 3937
3741The first argument is a format control string, and the rest are data 3938The first argument is a format control string, and the rest are data
3742to be formatted under control of the string. See `format-message' for 3939to be formatted under control of the string. Percent sign (%), grave
3743details. 3940accent (\\=`) and apostrophe (\\=') are special in the format; see
3744 3941`format-message' for details. To display STRING without special
3745Note: (message "%s" VALUE) displays the string VALUE without 3942treatment, use (message "%s" STRING).
3746interpreting format characters like `%', `\\=`', and `\\=''.
3747 3943
3748If the first argument is nil or the empty string, the function clears 3944If the first argument is nil or the empty string, the function clears
3749any existing message; this lets the minibuffer contents show. See 3945any existing message; this lets the minibuffer contents show. See
@@ -3856,13 +4052,30 @@ usage: (propertize STRING &rest PROPERTIES) */)
3856 return string; 4052 return string;
3857} 4053}
3858 4054
4055/* Convert the prefix of STR from ASCII decimal digits to a number.
4056 Set *STR_END to the address of the first non-digit. Return the
4057 number, or PTRDIFF_MAX on overflow. Return 0 if there is no number.
4058 This is like strtol for ptrdiff_t and base 10 and C locale,
4059 except without negative numbers or errno. */
4060
4061static ptrdiff_t
4062str2num (char *str, char **str_end)
4063{
4064 ptrdiff_t n = 0;
4065 for (; c_isdigit (*str); str++)
4066 if (INT_MULTIPLY_WRAPV (n, 10, &n) || INT_ADD_WRAPV (n, *str - '0', &n))
4067 n = PTRDIFF_MAX;
4068 *str_end = str;
4069 return n;
4070}
4071
3859DEFUN ("format", Fformat, Sformat, 1, MANY, 0, 4072DEFUN ("format", Fformat, Sformat, 1, MANY, 0,
3860 doc: /* Format a string out of a format-string and arguments. 4073 doc: /* Format a string out of a format-string and arguments.
3861The first argument is a format control string. 4074The first argument is a format control string.
3862The other arguments are substituted into it to make the result, a string. 4075The other arguments are substituted into it to make the result, a string.
3863 4076
3864The format control string may contain %-sequences meaning to substitute 4077The format control string may contain %-sequences meaning to substitute
3865the next available argument: 4078the next available argument, or the argument explicitly specified:
3866 4079
3867%s means print a string argument. Actually, prints any object, with `princ'. 4080%s means print a string argument. Actually, prints any object, with `princ'.
3868%d means print as signed number in decimal. 4081%d means print as signed number in decimal.
@@ -3879,13 +4092,19 @@ the next available argument:
3879The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. 4092The argument used for %d, %o, %x, %e, %f, %g or %c must be a number.
3880Use %% to put a single % into the output. 4093Use %% to put a single % into the output.
3881 4094
3882A %-sequence may contain optional flag, width, and precision 4095A %-sequence other than %% may contain optional field number, flag,
3883specifiers, as follows: 4096width, and precision specifiers, as follows:
4097
4098 %<field><flags><width><precision>character
3884 4099
3885 %<flags><width><precision>character 4100where field is [0-9]+ followed by a literal dollar "$", flags is
4101[+ #-0]+, width is [0-9]+, and precision is a literal period "."
4102followed by [0-9]+.
3886 4103
3887where flags is [+ #-0]+, width is [0-9]+, and precision is a literal 4104If a %-sequence is numbered with a field with positive value N, the
3888period "." followed by [0-9]+ 4105Nth argument is substituted instead of the next one. A format can
4106contain either numbered or unnumbered %-sequences but not both, except
4107that %% can be mixed with numbered %-sequences.
3889 4108
3890The + flag character inserts a + before any positive number, while a 4109The + flag character inserts a + before any positive number, while a
3891space inserts a space before any positive number; these flags only 4110space inserts a space before any positive number; these flags only
@@ -3960,38 +4179,42 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
3960 bool maybe_combine_byte; 4179 bool maybe_combine_byte;
3961 bool arg_intervals = false; 4180 bool arg_intervals = false;
3962 USE_SAFE_ALLOCA; 4181 USE_SAFE_ALLOCA;
4182 sa_avail -= sizeof initial_buffer;
3963 4183
3964 /* Each element records, for one argument, 4184 /* Information recorded for each format spec. */
3965 the start and end bytepos in the output string,
3966 whether the argument has been converted to string (e.g., due to "%S"),
3967 and whether the argument is a string with intervals. */
3968 struct info 4185 struct info
3969 { 4186 {
4187 /* The corresponding argument, converted to string if conversion
4188 was needed. */
4189 Lisp_Object argument;
4190
4191 /* The start and end bytepos in the output string. */
3970 ptrdiff_t start, end; 4192 ptrdiff_t start, end;
3971 bool_bf converted_to_string : 1; 4193
4194 /* Whether the argument is a string with intervals. */
3972 bool_bf intervals : 1; 4195 bool_bf intervals : 1;
3973 } *info; 4196 } *info;
3974 4197
3975 CHECK_STRING (args[0]); 4198 CHECK_STRING (args[0]);
3976 char *format_start = SSDATA (args[0]); 4199 char *format_start = SSDATA (args[0]);
4200 bool multibyte_format = STRING_MULTIBYTE (args[0]);
3977 ptrdiff_t formatlen = SBYTES (args[0]); 4201 ptrdiff_t formatlen = SBYTES (args[0]);
3978 4202
4203 /* Upper bound on number of format specs. Each uses at least 2 chars. */
4204 ptrdiff_t nspec_bound = SCHARS (args[0]) >> 1;
4205
3979 /* Allocate the info and discarded tables. */ 4206 /* Allocate the info and discarded tables. */
3980 ptrdiff_t alloca_size; 4207 ptrdiff_t alloca_size;
3981 if (INT_MULTIPLY_WRAPV (nargs, sizeof *info, &alloca_size) 4208 if (INT_MULTIPLY_WRAPV (nspec_bound, sizeof *info, &alloca_size)
3982 || INT_ADD_WRAPV (sizeof *info, alloca_size, &alloca_size)
3983 || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size) 4209 || INT_ADD_WRAPV (formatlen, alloca_size, &alloca_size)
3984 || SIZE_MAX < alloca_size) 4210 || SIZE_MAX < alloca_size)
3985 memory_full (SIZE_MAX); 4211 memory_full (SIZE_MAX);
3986 /* info[0] is unused. Unused elements have -1 for start. */
3987 info = SAFE_ALLOCA (alloca_size); 4212 info = SAFE_ALLOCA (alloca_size);
3988 memset (info, 0, alloca_size);
3989 for (ptrdiff_t i = 0; i < nargs + 1; i++)
3990 info[i].start = -1;
3991 /* discarded[I] is 1 if byte I of the format 4213 /* discarded[I] is 1 if byte I of the format
3992 string was not copied into the output. 4214 string was not copied into the output.
3993 It is 2 if byte I was not the first byte of its character. */ 4215 It is 2 if byte I was not the first byte of its character. */
3994 char *discarded = (char *) &info[nargs + 1]; 4216 char *discarded = (char *) &info[nspec_bound];
4217 memset (discarded, 0, formatlen);
3995 4218
3996 /* Try to determine whether the result should be multibyte. 4219 /* Try to determine whether the result should be multibyte.
3997 This is not always right; sometimes the result needs to be multibyte 4220 This is not always right; sometimes the result needs to be multibyte
@@ -3999,8 +4222,6 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
3999 or because a grave accent or apostrophe is requoted, 4222 or because a grave accent or apostrophe is requoted,
4000 and in that case, we won't know it here. */ 4223 and in that case, we won't know it here. */
4001 4224
4002 /* True if the format is multibyte. */
4003 bool multibyte_format = STRING_MULTIBYTE (args[0]);
4004 /* True if the output should be a multibyte string, 4225 /* True if the output should be a multibyte string,
4005 which is true if any of the inputs is one. */ 4226 which is true if any of the inputs is one. */
4006 bool multibyte = multibyte_format; 4227 bool multibyte = multibyte_format;
@@ -4010,13 +4231,19 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4010 4231
4011 int quoting_style = message ? text_quoting_style () : -1; 4232 int quoting_style = message ? text_quoting_style () : -1;
4012 4233
4234 ptrdiff_t ispec;
4235 ptrdiff_t nspec = 0;
4236
4013 /* If we start out planning a unibyte result, 4237 /* If we start out planning a unibyte result,
4014 then discover it has to be multibyte, we jump back to retry. */ 4238 then discover it has to be multibyte, we jump back to retry. */
4015 retry: 4239 retry:
4016 4240
4017 p = buf; 4241 p = buf;
4018 nchars = 0; 4242 nchars = 0;
4243
4244 /* N is the argument index, ISPEC is the specification index. */
4019 n = 0; 4245 n = 0;
4246 ispec = 0;
4020 4247
4021 /* Scan the format and store result in BUF. */ 4248 /* Scan the format and store result in BUF. */
4022 format = format_start; 4249 format = format_start;
@@ -4025,8 +4252,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4025 4252
4026 while (format != end) 4253 while (format != end)
4027 { 4254 {
4028 /* The values of N and FORMAT when the loop body is entered. */ 4255 /* The values of N, ISPEC, and FORMAT when the loop body is
4256 entered. */
4029 ptrdiff_t n0 = n; 4257 ptrdiff_t n0 = n;
4258 ptrdiff_t ispec0 = ispec;
4030 char *format0 = format; 4259 char *format0 = format;
4031 char const *convsrc = format; 4260 char const *convsrc = format;
4032 unsigned char format_char = *format++; 4261 unsigned char format_char = *format++;
@@ -4038,14 +4267,18 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4038 { 4267 {
4039 /* General format specifications look like 4268 /* General format specifications look like
4040 4269
4041 '%' [flags] [field-width] [precision] format 4270 '%' [field-number] [flags] [field-width] [precision] format
4042 4271
4043 where 4272 where
4044 4273
4274 field-number ::= [0-9]+ '$'
4045 flags ::= [-+0# ]+ 4275 flags ::= [-+0# ]+
4046 field-width ::= [0-9]+ 4276 field-width ::= [0-9]+
4047 precision ::= '.' [0-9]* 4277 precision ::= '.' [0-9]*
4048 4278
4279 If present, a field-number specifies the argument number
4280 to substitute. Otherwise, the next argument is taken.
4281
4049 If a field-width is specified, it specifies to which width 4282 If a field-width is specified, it specifies to which width
4050 the output should be padded with blanks, if the output 4283 the output should be padded with blanks, if the output
4051 string is shorter than field-width. 4284 string is shorter than field-width.
@@ -4054,6 +4287,18 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4054 digits to print after the '.' for floats, or the max. 4287 digits to print after the '.' for floats, or the max.
4055 number of chars to print from a string. */ 4288 number of chars to print from a string. */
4056 4289
4290 ptrdiff_t num;
4291 char *num_end;
4292 if (c_isdigit (*format))
4293 {
4294 num = str2num (format, &num_end);
4295 if (*num_end == '$')
4296 {
4297 n = num - 1;
4298 format = num_end + 1;
4299 }
4300 }
4301
4057 bool minus_flag = false; 4302 bool minus_flag = false;
4058 bool plus_flag = false; 4303 bool plus_flag = false;
4059 bool space_flag = false; 4304 bool space_flag = false;
@@ -4074,19 +4319,18 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4074 } 4319 }
4075 4320
4076 /* Ignore flags when sprintf ignores them. */ 4321 /* Ignore flags when sprintf ignores them. */
4077 space_flag &= ~ plus_flag; 4322 space_flag &= ! plus_flag;
4078 zero_flag &= ~ minus_flag; 4323 zero_flag &= ! minus_flag;
4079 4324
4080 char *num_end; 4325 num = str2num (format, &num_end);
4081 uintmax_t raw_field_width = strtoumax (format, &num_end, 10); 4326 if (max_bufsize <= num)
4082 if (max_bufsize <= raw_field_width)
4083 string_overflow (); 4327 string_overflow ();
4084 ptrdiff_t field_width = raw_field_width; 4328 ptrdiff_t field_width = num;
4085 4329
4086 bool precision_given = *num_end == '.'; 4330 bool precision_given = *num_end == '.';
4087 uintmax_t precision = (precision_given 4331 ptrdiff_t precision = (precision_given
4088 ? strtoumax (num_end + 1, &num_end, 10) 4332 ? str2num (num_end + 1, &num_end)
4089 : UINTMAX_MAX); 4333 : PTRDIFF_MAX);
4090 format = num_end; 4334 format = num_end;
4091 4335
4092 if (format == end) 4336 if (format == end)
@@ -4102,20 +4346,28 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4102 if (! (n < nargs)) 4346 if (! (n < nargs))
4103 error ("Not enough arguments for format string"); 4347 error ("Not enough arguments for format string");
4104 4348
4349 struct info *spec = &info[ispec++];
4350 if (nspec < ispec)
4351 {
4352 spec->argument = args[n];
4353 spec->intervals = false;
4354 nspec = ispec;
4355 }
4356 Lisp_Object arg = spec->argument;
4357
4105 /* For 'S', prin1 the argument, and then treat like 's'. 4358 /* For 'S', prin1 the argument, and then treat like 's'.
4106 For 's', princ any argument that is not a string or 4359 For 's', princ any argument that is not a string or
4107 symbol. But don't do this conversion twice, which might 4360 symbol. But don't do this conversion twice, which might
4108 happen after retrying. */ 4361 happen after retrying. */
4109 if ((conversion == 'S' 4362 if ((conversion == 'S'
4110 || (conversion == 's' 4363 || (conversion == 's'
4111 && ! STRINGP (args[n]) && ! SYMBOLP (args[n])))) 4364 && ! STRINGP (arg) && ! SYMBOLP (arg))))
4112 { 4365 {
4113 if (! info[n].converted_to_string) 4366 if (EQ (arg, args[n]))
4114 { 4367 {
4115 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt; 4368 Lisp_Object noescape = conversion == 'S' ? Qnil : Qt;
4116 args[n] = Fprin1_to_string (args[n], noescape); 4369 spec->argument = arg = Fprin1_to_string (arg, noescape);
4117 info[n].converted_to_string = true; 4370 if (STRING_MULTIBYTE (arg) && ! multibyte)
4118 if (STRING_MULTIBYTE (args[n]) && ! multibyte)
4119 { 4371 {
4120 multibyte = true; 4372 multibyte = true;
4121 goto retry; 4373 goto retry;
@@ -4125,26 +4377,25 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4125 } 4377 }
4126 else if (conversion == 'c') 4378 else if (conversion == 'c')
4127 { 4379 {
4128 if (INTEGERP (args[n]) && ! ASCII_CHAR_P (XINT (args[n]))) 4380 if (INTEGERP (arg) && ! ASCII_CHAR_P (XINT (arg)))
4129 { 4381 {
4130 if (!multibyte) 4382 if (!multibyte)
4131 { 4383 {
4132 multibyte = true; 4384 multibyte = true;
4133 goto retry; 4385 goto retry;
4134 } 4386 }
4135 args[n] = Fchar_to_string (args[n]); 4387 spec->argument = arg = Fchar_to_string (arg);
4136 info[n].converted_to_string = true;
4137 } 4388 }
4138 4389
4139 if (info[n].converted_to_string) 4390 if (!EQ (arg, args[n]))
4140 conversion = 's'; 4391 conversion = 's';
4141 zero_flag = false; 4392 zero_flag = false;
4142 } 4393 }
4143 4394
4144 if (SYMBOLP (args[n])) 4395 if (SYMBOLP (arg))
4145 { 4396 {
4146 args[n] = SYMBOL_NAME (args[n]); 4397 spec->argument = arg = SYMBOL_NAME (arg);
4147 if (STRING_MULTIBYTE (args[n]) && ! multibyte) 4398 if (STRING_MULTIBYTE (arg) && ! multibyte)
4148 { 4399 {
4149 multibyte = true; 4400 multibyte = true;
4150 goto retry; 4401 goto retry;
@@ -4159,7 +4410,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4159 /* handle case (precision[n] >= 0) */ 4410 /* handle case (precision[n] >= 0) */
4160 4411
4161 ptrdiff_t prec = -1; 4412 ptrdiff_t prec = -1;
4162 if (precision_given && precision <= TYPE_MAXIMUM (ptrdiff_t)) 4413 if (precision_given)
4163 prec = precision; 4414 prec = precision;
4164 4415
4165 /* lisp_string_width ignores a precision of 0, but GNU 4416 /* lisp_string_width ignores a precision of 0, but GNU
@@ -4175,11 +4426,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4175 else 4426 else
4176 { 4427 {
4177 ptrdiff_t nch, nby; 4428 ptrdiff_t nch, nby;
4178 width = lisp_string_width (args[n], prec, &nch, &nby); 4429 width = lisp_string_width (arg, prec, &nch, &nby);
4179 if (prec < 0) 4430 if (prec < 0)
4180 { 4431 {
4181 nchars_string = SCHARS (args[n]); 4432 nchars_string = SCHARS (arg);
4182 nbytes = SBYTES (args[n]); 4433 nbytes = SBYTES (arg);
4183 } 4434 }
4184 else 4435 else
4185 { 4436 {
@@ -4189,8 +4440,8 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4189 } 4440 }
4190 4441
4191 convbytes = nbytes; 4442 convbytes = nbytes;
4192 if (convbytes && multibyte && ! STRING_MULTIBYTE (args[n])) 4443 if (convbytes && multibyte && ! STRING_MULTIBYTE (arg))
4193 convbytes = count_size_as_multibyte (SDATA (args[n]), nbytes); 4444 convbytes = count_size_as_multibyte (SDATA (arg), nbytes);
4194 4445
4195 ptrdiff_t padding 4446 ptrdiff_t padding
4196 = width < field_width ? field_width - width : 0; 4447 = width < field_width ? field_width - width : 0;
@@ -4206,18 +4457,18 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4206 p += padding; 4457 p += padding;
4207 nchars += padding; 4458 nchars += padding;
4208 } 4459 }
4209 info[n].start = nchars; 4460 spec->start = nchars;
4210 4461
4211 if (p > buf 4462 if (p > buf
4212 && multibyte 4463 && multibyte
4213 && !ASCII_CHAR_P (*((unsigned char *) p - 1)) 4464 && !ASCII_CHAR_P (*((unsigned char *) p - 1))
4214 && STRING_MULTIBYTE (args[n]) 4465 && STRING_MULTIBYTE (arg)
4215 && !CHAR_HEAD_P (SREF (args[n], 0))) 4466 && !CHAR_HEAD_P (SREF (arg, 0)))
4216 maybe_combine_byte = true; 4467 maybe_combine_byte = true;
4217 4468
4218 p += copy_text (SDATA (args[n]), (unsigned char *) p, 4469 p += copy_text (SDATA (arg), (unsigned char *) p,
4219 nbytes, 4470 nbytes,
4220 STRING_MULTIBYTE (args[n]), multibyte); 4471 STRING_MULTIBYTE (arg), multibyte);
4221 4472
4222 nchars += nchars_string; 4473 nchars += nchars_string;
4223 4474
@@ -4227,12 +4478,12 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4227 p += padding; 4478 p += padding;
4228 nchars += padding; 4479 nchars += padding;
4229 } 4480 }
4230 info[n].end = nchars; 4481 spec->end = nchars;
4231 4482
4232 /* If this argument has text properties, record where 4483 /* If this argument has text properties, record where
4233 in the result string it appears. */ 4484 in the result string it appears. */
4234 if (string_intervals (args[n])) 4485 if (string_intervals (arg))
4235 info[n].intervals = arg_intervals = true; 4486 spec->intervals = arg_intervals = true;
4236 4487
4237 continue; 4488 continue;
4238 } 4489 }
@@ -4243,8 +4494,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4243 || conversion == 'X')) 4494 || conversion == 'X'))
4244 error ("Invalid format operation %%%c", 4495 error ("Invalid format operation %%%c",
4245 STRING_CHAR ((unsigned char *) format - 1)); 4496 STRING_CHAR ((unsigned char *) format - 1));
4246 else if (! (INTEGERP (args[n]) 4497 else if (! (INTEGERP (arg) || (FLOATP (arg) && conversion != 'c')))
4247 || (FLOATP (args[n]) && conversion != 'c')))
4248 error ("Format specifier doesn't match argument type"); 4498 error ("Format specifier doesn't match argument type");
4249 else 4499 else
4250 { 4500 {
@@ -4306,14 +4556,14 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4306 if (INT_AS_LDBL) 4556 if (INT_AS_LDBL)
4307 { 4557 {
4308 *f = 'L'; 4558 *f = 'L';
4309 f += INTEGERP (args[n]); 4559 f += INTEGERP (arg);
4310 } 4560 }
4311 } 4561 }
4312 else if (conversion != 'c') 4562 else if (conversion != 'c')
4313 { 4563 {
4314 memcpy (f, pMd, pMlen); 4564 memcpy (f, pMd, pMlen);
4315 f += pMlen; 4565 f += pMlen;
4316 zero_flag &= ~ precision_given; 4566 zero_flag &= ! precision_given;
4317 } 4567 }
4318 *f++ = conversion; 4568 *f++ = conversion;
4319 *f = '\0'; 4569 *f = '\0';
@@ -4338,22 +4588,22 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4338 ptrdiff_t sprintf_bytes; 4588 ptrdiff_t sprintf_bytes;
4339 if (float_conversion) 4589 if (float_conversion)
4340 { 4590 {
4341 if (INT_AS_LDBL && INTEGERP (args[n])) 4591 if (INT_AS_LDBL && INTEGERP (arg))
4342 { 4592 {
4343 /* Although long double may have a rounding error if 4593 /* Although long double may have a rounding error if
4344 DIG_BITS_LBOUND * LDBL_MANT_DIG < FIXNUM_BITS - 1, 4594 DIG_BITS_LBOUND * LDBL_MANT_DIG < FIXNUM_BITS - 1,
4345 it is more accurate than plain 'double'. */ 4595 it is more accurate than plain 'double'. */
4346 long double x = XINT (args[n]); 4596 long double x = XINT (arg);
4347 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x); 4597 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, x);
4348 } 4598 }
4349 else 4599 else
4350 sprintf_bytes = sprintf (sprintf_buf, convspec, prec, 4600 sprintf_bytes = sprintf (sprintf_buf, convspec, prec,
4351 XFLOATINT (args[n])); 4601 XFLOATINT (arg));
4352 } 4602 }
4353 else if (conversion == 'c') 4603 else if (conversion == 'c')
4354 { 4604 {
4355 /* Don't use sprintf here, as it might mishandle prec. */ 4605 /* Don't use sprintf here, as it might mishandle prec. */
4356 sprintf_buf[0] = XINT (args[n]); 4606 sprintf_buf[0] = XINT (arg);
4357 sprintf_bytes = prec != 0; 4607 sprintf_bytes = prec != 0;
4358 } 4608 }
4359 else if (conversion == 'd' || conversion == 'i') 4609 else if (conversion == 'd' || conversion == 'i')
@@ -4362,11 +4612,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4362 instead so it also works for values outside 4612 instead so it also works for values outside
4363 the integer range. */ 4613 the integer range. */
4364 printmax_t x; 4614 printmax_t x;
4365 if (INTEGERP (args[n])) 4615 if (INTEGERP (arg))
4366 x = XINT (args[n]); 4616 x = XINT (arg);
4367 else 4617 else
4368 { 4618 {
4369 double d = XFLOAT_DATA (args[n]); 4619 double d = XFLOAT_DATA (arg);
4370 if (d < 0) 4620 if (d < 0)
4371 { 4621 {
4372 x = TYPE_MINIMUM (printmax_t); 4622 x = TYPE_MINIMUM (printmax_t);
@@ -4386,11 +4636,11 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4386 { 4636 {
4387 /* Don't sign-extend for octal or hex printing. */ 4637 /* Don't sign-extend for octal or hex printing. */
4388 uprintmax_t x; 4638 uprintmax_t x;
4389 if (INTEGERP (args[n])) 4639 if (INTEGERP (arg))
4390 x = XUINT (args[n]); 4640 x = XUINT (arg);
4391 else 4641 else
4392 { 4642 {
4393 double d = XFLOAT_DATA (args[n]); 4643 double d = XFLOAT_DATA (arg);
4394 if (d < 0) 4644 if (d < 0)
4395 x = 0; 4645 x = 0;
4396 else 4646 else
@@ -4407,8 +4657,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4407 padding and excess precision. Deal with excess precision 4657 padding and excess precision. Deal with excess precision
4408 first. This happens only when the format specifies 4658 first. This happens only when the format specifies
4409 ridiculously large precision. */ 4659 ridiculously large precision. */
4410 uintmax_t excess_precision = precision - prec; 4660 ptrdiff_t excess_precision
4411 uintmax_t leading_zeros = 0, trailing_zeros = 0; 4661 = precision_given ? precision - prec : 0;
4662 ptrdiff_t leading_zeros = 0, trailing_zeros = 0;
4412 if (excess_precision) 4663 if (excess_precision)
4413 { 4664 {
4414 if (float_conversion) 4665 if (float_conversion)
@@ -4434,7 +4685,9 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4434 4685
4435 /* Compute the total bytes needed for this item, including 4686 /* Compute the total bytes needed for this item, including
4436 excess precision and padding. */ 4687 excess precision and padding. */
4437 uintmax_t numwidth = sprintf_bytes + excess_precision; 4688 ptrdiff_t numwidth;
4689 if (INT_ADD_WRAPV (sprintf_bytes, excess_precision, &numwidth))
4690 numwidth = PTRDIFF_MAX;
4438 ptrdiff_t padding 4691 ptrdiff_t padding
4439 = numwidth < field_width ? field_width - numwidth : 0; 4692 = numwidth < field_width ? field_width - numwidth : 0;
4440 if (max_bufsize - sprintf_bytes <= excess_precision 4693 if (max_bufsize - sprintf_bytes <= excess_precision
@@ -4468,7 +4721,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4468 exponent_bytes = src + sprintf_bytes - e; 4721 exponent_bytes = src + sprintf_bytes - e;
4469 } 4722 }
4470 4723
4471 info[n].start = nchars; 4724 spec->start = nchars;
4472 if (! minus_flag) 4725 if (! minus_flag)
4473 { 4726 {
4474 memset (p, ' ', padding); 4727 memset (p, ' ', padding);
@@ -4499,7 +4752,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4499 p += padding; 4752 p += padding;
4500 nchars += padding; 4753 nchars += padding;
4501 } 4754 }
4502 info[n].end = nchars; 4755 spec->end = nchars;
4503 4756
4504 continue; 4757 continue;
4505 } 4758 }
@@ -4585,6 +4838,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4585 p = buf + used; 4838 p = buf + used;
4586 format = format0; 4839 format = format0;
4587 n = n0; 4840 n = n0;
4841 ispec = ispec0;
4588 } 4842 }
4589 4843
4590 if (bufsize < p - buf) 4844 if (bufsize < p - buf)
@@ -4607,7 +4861,7 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4607 if (CONSP (props)) 4861 if (CONSP (props))
4608 { 4862 {
4609 ptrdiff_t bytepos = 0, position = 0, translated = 0; 4863 ptrdiff_t bytepos = 0, position = 0, translated = 0;
4610 ptrdiff_t argn = 1; 4864 ptrdiff_t fieldn = 0;
4611 4865
4612 /* Adjust the bounds of each text property 4866 /* Adjust the bounds of each text property
4613 to the proper start and end in the output string. */ 4867 to the proper start and end in the output string. */
@@ -4637,10 +4891,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4637 else if (discarded[bytepos] == 1) 4891 else if (discarded[bytepos] == 1)
4638 { 4892 {
4639 position++; 4893 position++;
4640 if (translated == info[argn].start) 4894 if (translated == info[fieldn].start)
4641 { 4895 {
4642 translated += info[argn].end - info[argn].start; 4896 translated += info[fieldn].end - info[fieldn].start;
4643 argn++; 4897 fieldn++;
4644 } 4898 }
4645 } 4899 }
4646 } 4900 }
@@ -4657,10 +4911,10 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4657 else if (discarded[bytepos] == 1) 4911 else if (discarded[bytepos] == 1)
4658 { 4912 {
4659 position++; 4913 position++;
4660 if (translated == info[argn].start) 4914 if (translated == info[fieldn].start)
4661 { 4915 {
4662 translated += info[argn].end - info[argn].start; 4916 translated += info[fieldn].end - info[fieldn].start;
4663 argn++; 4917 fieldn++;
4664 } 4918 }
4665 } 4919 }
4666 } 4920 }
@@ -4673,12 +4927,13 @@ styled_format (ptrdiff_t nargs, Lisp_Object *args, bool message)
4673 4927
4674 /* Add text properties from arguments. */ 4928 /* Add text properties from arguments. */
4675 if (arg_intervals) 4929 if (arg_intervals)
4676 for (ptrdiff_t i = 1; i < nargs; i++) 4930 for (ptrdiff_t i = 0; i < nspec; i++)
4677 if (info[i].intervals) 4931 if (info[i].intervals)
4678 { 4932 {
4679 len = make_number (SCHARS (args[i])); 4933 len = make_number (SCHARS (info[i].argument));
4680 Lisp_Object new_len = make_number (info[i].end - info[i].start); 4934 Lisp_Object new_len = make_number (info[i].end - info[i].start);
4681 props = text_property_list (args[i], make_number (0), len, Qnil); 4935 props = text_property_list (info[i].argument,
4936 make_number (0), len, Qnil);
4682 props = extend_property_ranges (props, len, new_len); 4937 props = extend_property_ranges (props, len, new_len);
4683 /* If successive arguments have properties, be sure that 4938 /* If successive arguments have properties, be sure that
4684 the value of `composition' property be the copy. */ 4939 the value of `composition' property be the copy. */
@@ -5262,6 +5517,7 @@ functions if all the text being accessed has this property. */);
5262 5517
5263 defsubr (&Sinsert_buffer_substring); 5518 defsubr (&Sinsert_buffer_substring);
5264 defsubr (&Scompare_buffer_substrings); 5519 defsubr (&Scompare_buffer_substrings);
5520 defsubr (&Sreplace_buffer_contents);
5265 defsubr (&Ssubst_char_in_region); 5521 defsubr (&Ssubst_char_in_region);
5266 defsubr (&Stranslate_region_internal); 5522 defsubr (&Stranslate_region_internal);
5267 defsubr (&Sdelete_region); 5523 defsubr (&Sdelete_region);
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 1b445dcc3b2..7b1a402eeff 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 21
22#include "emacs-module.h" 22#include "emacs-module.h"
23 23
24#include <stdarg.h>
24#include <stddef.h> 25#include <stddef.h>
25#include <stdint.h> 26#include <stdint.h>
26#include <stdio.h> 27#include <stdio.h>
@@ -28,20 +29,27 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include "lisp.h" 29#include "lisp.h"
29#include "dynlib.h" 30#include "dynlib.h"
30#include "coding.h" 31#include "coding.h"
32#include "keyboard.h"
31#include "syssignal.h" 33#include "syssignal.h"
34#include "thread.h"
32 35
33#include <intprops.h> 36#include <intprops.h>
34#include <verify.h> 37#include <verify.h>
35 38
39/* We use different strategies for allocating the user-visible objects
40 (struct emacs_runtime, emacs_env, emacs_value), depending on
41 whether the user supplied the -module-assertions flag. If
42 assertions are disabled, all objects are allocated from the stack.
43 If assertions are enabled, all objects are allocated from the free
44 store, and objects are never freed; this guarantees that they all
45 have different addresses. We use that for checking which objects
46 are live. Without unique addresses, we might consider some dead
47 objects live because their addresses would have been reused in the
48 meantime. */
49
36 50
37/* Feature tests. */ 51/* Feature tests. */
38 52
39#if __has_attribute (cleanup)
40enum { module_has_cleanup = true };
41#else
42enum { module_has_cleanup = false };
43#endif
44
45#ifdef WINDOWSNT 53#ifdef WINDOWSNT
46#include <windows.h> 54#include <windows.h>
47#include "w32term.h" 55#include "w32term.h"
@@ -62,10 +70,6 @@ enum
62/* Function prototype for the module init function. */ 70/* Function prototype for the module init function. */
63typedef int (*emacs_init_function) (struct emacs_runtime *); 71typedef int (*emacs_init_function) (struct emacs_runtime *);
64 72
65/* Function prototype for the module Lisp functions. */
66typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t,
67 emacs_value [], void *);
68
69/* Function prototype for module user-pointer finalizers. These 73/* Function prototype for module user-pointer finalizers. These
70 should not throw C++ exceptions, so emacs-module.h declares the 74 should not throw C++ exceptions, so emacs-module.h declares the
71 corresponding interfaces with EMACS_NOEXCEPT. There is only C code 75 corresponding interfaces with EMACS_NOEXCEPT. There is only C code
@@ -86,35 +90,44 @@ struct emacs_env_private
86 storage is always available for them, even in an out-of-memory 90 storage is always available for them, even in an out-of-memory
87 situation. */ 91 situation. */
88 Lisp_Object non_local_exit_symbol, non_local_exit_data; 92 Lisp_Object non_local_exit_symbol, non_local_exit_data;
93
94 /* List of values allocated from this environment. The code uses
95 this only if the user gave the -module-assertions command-line
96 option. */
97 Lisp_Object values;
89}; 98};
90 99
91/* The private parts of an `emacs_runtime' object contain the initial 100/* The private parts of an `emacs_runtime' object contain the initial
92 environment. */ 101 environment. */
93struct emacs_runtime_private 102struct emacs_runtime_private
94{ 103{
95 /* FIXME: Ideally, we would just define "struct emacs_runtime_private" 104 emacs_env *env;
96 as a synonym of "emacs_env", but I don't know how to do that in C. */
97 emacs_env pub;
98}; 105};
99 106
100 107
101/* Forward declarations. */ 108/* Forward declarations. */
102 109
103struct module_fun_env;
104
105static Lisp_Object module_format_fun_env (const struct module_fun_env *);
106static Lisp_Object value_to_lisp (emacs_value); 110static Lisp_Object value_to_lisp (emacs_value);
107static emacs_value lisp_to_value (Lisp_Object); 111static emacs_value lisp_to_value (emacs_env *, Lisp_Object);
108static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *); 112static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *);
109static void check_main_thread (void); 113static void module_assert_thread (void);
110static void finalize_environment (struct emacs_env_private *); 114static void module_assert_runtime (struct emacs_runtime *);
111static void initialize_environment (emacs_env *, struct emacs_env_private *priv); 115static void module_assert_env (emacs_env *);
116static _Noreturn void module_abort (const char *format, ...)
117 ATTRIBUTE_FORMAT_PRINTF(1, 2);
118static emacs_env *initialize_environment (emacs_env *,
119 struct emacs_env_private *);
120static void finalize_environment (emacs_env *);
121static void finalize_environment_unwind (void *);
122static void finalize_runtime_unwind (void *);
112static void module_handle_signal (emacs_env *, Lisp_Object); 123static void module_handle_signal (emacs_env *, Lisp_Object);
113static void module_handle_throw (emacs_env *, Lisp_Object); 124static void module_handle_throw (emacs_env *, Lisp_Object);
114static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object); 125static void module_non_local_exit_signal_1 (emacs_env *,
115static void module_non_local_exit_throw_1 (emacs_env *, Lisp_Object, Lisp_Object); 126 Lisp_Object, Lisp_Object);
127static void module_non_local_exit_throw_1 (emacs_env *,
128 Lisp_Object, Lisp_Object);
116static void module_out_of_memory (emacs_env *); 129static void module_out_of_memory (emacs_env *);
117static void module_reset_handlerlist (const int *); 130static void module_reset_handlerlist (struct handler **);
118 131
119/* We used to return NULL when emacs_value was a different type from 132/* We used to return NULL when emacs_value was a different type from
120 Lisp_Object, but nowadays we just use Qnil instead. Although they 133 Lisp_Object, but nowadays we just use Qnil instead. Although they
@@ -122,6 +135,10 @@ static void module_reset_handlerlist (const int *);
122 code should not assume this. */ 135 code should not assume this. */
123verify (NIL_IS_ZERO); 136verify (NIL_IS_ZERO);
124static emacs_value const module_nil = 0; 137static emacs_value const module_nil = 0;
138
139static bool module_assertions = false;
140static emacs_env *global_env;
141static struct emacs_env_private global_env_private;
125 142
126/* Convenience macros for non-local exit handling. */ 143/* Convenience macros for non-local exit handling. */
127 144
@@ -153,6 +170,10 @@ static emacs_value const module_nil = 0;
153 internal_handler_##handlertype, \ 170 internal_handler_##handlertype, \
154 internal_cleanup_##handlertype) 171 internal_cleanup_##handlertype)
155 172
173#if !__has_attribute (cleanup)
174 #error "__attribute__ ((cleanup)) not supported by this compiler; try GCC"
175#endif
176
156/* It is very important that pushing the handler doesn't itself raise 177/* It is very important that pushing the handler doesn't itself raise
157 a signal. Install the cleanup only after the handler has been 178 a signal. Install the cleanup only after the handler has been
158 pushed. Use __attribute__ ((cleanup)) to avoid 179 pushed. Use __attribute__ ((cleanup)) to avoid
@@ -165,17 +186,17 @@ static emacs_value const module_nil = 0;
165 186
166/* TODO: Make backtraces work if this macros is used. */ 187/* TODO: Make backtraces work if this macros is used. */
167 188
168#define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c, dummy) \ 189#define MODULE_SETJMP_1(handlertype, handlerfunc, retval, c0, c) \
169 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \ 190 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
170 return retval; \ 191 return retval; \
171 struct handler *c = push_handler_nosignal (Qt, handlertype); \ 192 struct handler *c0 = push_handler_nosignal (Qt, handlertype); \
172 if (!c) \ 193 if (!c0) \
173 { \ 194 { \
174 module_out_of_memory (env); \ 195 module_out_of_memory (env); \
175 return retval; \ 196 return retval; \
176 } \ 197 } \
177 verify (module_has_cleanup); \ 198 struct handler *c __attribute__ ((cleanup (module_reset_handlerlist))) \
178 int dummy __attribute__ ((cleanup (module_reset_handlerlist))); \ 199 = c0; \
179 if (sys_setjmp (c->jmp)) \ 200 if (sys_setjmp (c->jmp)) \
180 { \ 201 { \
181 (handlerfunc) (env, c->val); \ 202 (handlerfunc) (env, c->val); \
@@ -184,29 +205,13 @@ static emacs_value const module_nil = 0;
184 do { } while (false) 205 do { } while (false)
185 206
186 207
187/* Function environments. */
188
189/* A function environment is an auxiliary structure used by
190 `module_make_function' to store information about a module
191 function. It is stored in a save pointer and retrieved by
192 `internal--module-call'. Its members correspond to the arguments
193 given to `module_make_function'. */
194
195struct module_fun_env
196{
197 ptrdiff_t min_arity, max_arity;
198 emacs_subr subr;
199 void *data;
200};
201
202
203/* Implementation of runtime and environment functions. 208/* Implementation of runtime and environment functions.
204 209
205 These should abide by the following rules: 210 These should abide by the following rules:
206 211
207 1. The first argument should always be a pointer to emacs_env. 212 1. The first argument should always be a pointer to emacs_env.
208 213
209 2. Each function should first call check_main_thread. Note that 214 2. Each function should first call check_thread. Note that
210 this function is a no-op unless Emacs was built with 215 this function is a no-op unless Emacs was built with
211 --enable-checking. 216 --enable-checking.
212 217
@@ -233,14 +238,25 @@ struct module_fun_env
233 instead of reporting the error back to Lisp, and also because 238 instead of reporting the error back to Lisp, and also because
234 'eassert' is compiled to nothing in the release version. */ 239 'eassert' is compiled to nothing in the release version. */
235 240
241/* Use MODULE_FUNCTION_BEGIN_NO_CATCH to implement steps 2 and 3 for
242 environment functions that are known to never exit non-locally. On
243 error it will return its argument, which can be a sentinel
244 value. */
245
246#define MODULE_FUNCTION_BEGIN_NO_CATCH(error_retval) \
247 do { \
248 module_assert_thread (); \
249 module_assert_env (env); \
250 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
251 return error_retval; \
252 } while (false)
253
236/* Use MODULE_FUNCTION_BEGIN to implement steps 2 through 4 for most 254/* Use MODULE_FUNCTION_BEGIN to implement steps 2 through 4 for most
237 environment functions. On error it will return its argument, which 255 environment functions. On error it will return its argument, which
238 should be a sentinel value. */ 256 can be a sentinel value. */
239 257
240#define MODULE_FUNCTION_BEGIN(error_retval) \ 258#define MODULE_FUNCTION_BEGIN(error_retval) \
241 check_main_thread (); \ 259 MODULE_FUNCTION_BEGIN_NO_CATCH (error_retval); \
242 if (module_non_local_exit_check (env) != emacs_funcall_exit_return) \
243 return error_retval; \
244 MODULE_HANDLE_NONLOCAL_EXIT (error_retval) 260 MODULE_HANDLE_NONLOCAL_EXIT (error_retval)
245 261
246static void 262static void
@@ -256,8 +272,9 @@ CHECK_USER_PTR (Lisp_Object obj)
256static emacs_env * 272static emacs_env *
257module_get_environment (struct emacs_runtime *ert) 273module_get_environment (struct emacs_runtime *ert)
258{ 274{
259 check_main_thread (); 275 module_assert_thread ();
260 return &ert->private_members->pub; 276 module_assert_runtime (ert);
277 return ert->private_members->env;
261} 278}
262 279
263/* To make global refs (GC-protected global values) keep a hash that 280/* To make global refs (GC-protected global values) keep a hash that
@@ -286,7 +303,7 @@ module_make_global_ref (emacs_env *env, emacs_value ref)
286 hash_put (h, new_obj, make_natnum (1), hashcode); 303 hash_put (h, new_obj, make_natnum (1), hashcode);
287 } 304 }
288 305
289 return lisp_to_value (new_obj); 306 return lisp_to_value (module_assertions ? global_env : env, new_obj);
290} 307}
291 308
292static void 309static void
@@ -313,32 +330,59 @@ module_free_global_ref (emacs_env *env, emacs_value ref)
313 else 330 else
314 hash_remove_from_table (h, value); 331 hash_remove_from_table (h, value);
315 } 332 }
333
334 if (module_assertions)
335 {
336 Lisp_Object globals = global_env_private.values;
337 Lisp_Object prev = Qnil;
338 ptrdiff_t count = 0;
339 for (Lisp_Object tail = global_env_private.values; CONSP (tail);
340 tail = XCDR (tail))
341 {
342 emacs_value global = XSAVE_POINTER (XCAR (globals), 0);
343 if (global == ref)
344 {
345 if (NILP (prev))
346 global_env_private.values = XCDR (globals);
347 else
348 XSETCDR (prev, XCDR (globals));
349 return;
350 }
351 ++count;
352 prev = globals;
353 }
354 module_abort ("Global value was not found in list of %"pD"d globals",
355 count);
356 }
316} 357}
317 358
318static enum emacs_funcall_exit 359static enum emacs_funcall_exit
319module_non_local_exit_check (emacs_env *env) 360module_non_local_exit_check (emacs_env *env)
320{ 361{
321 check_main_thread (); 362 module_assert_thread ();
363 module_assert_env (env);
322 return env->private_members->pending_non_local_exit; 364 return env->private_members->pending_non_local_exit;
323} 365}
324 366
325static void 367static void
326module_non_local_exit_clear (emacs_env *env) 368module_non_local_exit_clear (emacs_env *env)
327{ 369{
328 check_main_thread (); 370 module_assert_thread ();
371 module_assert_env (env);
329 env->private_members->pending_non_local_exit = emacs_funcall_exit_return; 372 env->private_members->pending_non_local_exit = emacs_funcall_exit_return;
330} 373}
331 374
332static enum emacs_funcall_exit 375static enum emacs_funcall_exit
333module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data) 376module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
334{ 377{
335 check_main_thread (); 378 module_assert_thread ();
379 module_assert_env (env);
336 struct emacs_env_private *p = env->private_members; 380 struct emacs_env_private *p = env->private_members;
337 if (p->pending_non_local_exit != emacs_funcall_exit_return) 381 if (p->pending_non_local_exit != emacs_funcall_exit_return)
338 { 382 {
339 /* FIXME: lisp_to_value can exit non-locally. */ 383 /* FIXME: lisp_to_value can exit non-locally. */
340 *sym = lisp_to_value (p->non_local_exit_symbol); 384 *sym = lisp_to_value (env, p->non_local_exit_symbol);
341 *data = lisp_to_value (p->non_local_exit_data); 385 *data = lisp_to_value (env, p->non_local_exit_data);
342 } 386 }
343 return p->pending_non_local_exit; 387 return p->pending_non_local_exit;
344} 388}
@@ -347,7 +391,8 @@ module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data)
347static void 391static void
348module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data) 392module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
349{ 393{
350 check_main_thread (); 394 module_assert_thread ();
395 module_assert_env (env);
351 if (module_non_local_exit_check (env) == emacs_funcall_exit_return) 396 if (module_non_local_exit_check (env) == emacs_funcall_exit_return)
352 module_non_local_exit_signal_1 (env, value_to_lisp (sym), 397 module_non_local_exit_signal_1 (env, value_to_lisp (sym),
353 value_to_lisp (data)); 398 value_to_lisp (data));
@@ -356,18 +401,25 @@ module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data)
356static void 401static void
357module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value) 402module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value)
358{ 403{
359 check_main_thread (); 404 module_assert_thread ();
405 module_assert_env (env);
360 if (module_non_local_exit_check (env) == emacs_funcall_exit_return) 406 if (module_non_local_exit_check (env) == emacs_funcall_exit_return)
361 module_non_local_exit_throw_1 (env, value_to_lisp (tag), 407 module_non_local_exit_throw_1 (env, value_to_lisp (tag),
362 value_to_lisp (value)); 408 value_to_lisp (value));
363} 409}
364 410
365/* A module function is lambda function that calls 411static struct Lisp_Module_Function *
366 `internal--module-call', passing the function pointer of the module 412allocate_module_function (void)
367 function along with the module emacs_env pointer as arguments. 413{
414 return ALLOCATE_PSEUDOVECTOR (struct Lisp_Module_Function,
415 min_arity, PVEC_MODULE_FUNCTION);
416}
368 417
369 (function (lambda (&rest arglist) 418#define XSET_MODULE_FUNCTION(var, ptr) \
370 (internal--module-call envobj arglist))) */ 419 XSETPSEUDOVECTOR (var, ptr, PVEC_MODULE_FUNCTION)
420
421/* A module function is a pseudovector of subtype
422 PVEC_MODULE_FUNCTION; see lisp.h for the definition. */
371 423
372static emacs_value 424static emacs_value
373module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, 425module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
@@ -378,35 +430,29 @@ module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity,
378 430
379 if (! (0 <= min_arity 431 if (! (0 <= min_arity
380 && (max_arity < 0 432 && (max_arity < 0
381 ? max_arity == emacs_variadic_function 433 ? (min_arity <= MOST_POSITIVE_FIXNUM
382 : min_arity <= max_arity))) 434 && max_arity == emacs_variadic_function)
435 : min_arity <= max_arity && max_arity <= MOST_POSITIVE_FIXNUM)))
383 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity)); 436 xsignal2 (Qinvalid_arity, make_number (min_arity), make_number (max_arity));
384 437
385 /* FIXME: This should be freed when envobj is GC'd. */ 438 struct Lisp_Module_Function *function = allocate_module_function ();
386 struct module_fun_env *envptr = xmalloc (sizeof *envptr); 439 function->min_arity = min_arity;
387 envptr->min_arity = min_arity; 440 function->max_arity = max_arity;
388 envptr->max_arity = max_arity; 441 function->subr = subr;
389 envptr->subr = subr; 442 function->data = data;
390 envptr->data = data;
391 443
392 Lisp_Object envobj = make_save_ptr (envptr);
393 Lisp_Object doc = Qnil;
394 if (documentation) 444 if (documentation)
395 { 445 {
396 AUTO_STRING (unibyte_doc, documentation); 446 AUTO_STRING (unibyte_doc, documentation);
397 doc = code_convert_string_norecord (unibyte_doc, Qutf_8, false); 447 function->documentation =
448 code_convert_string_norecord (unibyte_doc, Qutf_8, false);
398 } 449 }
399 450
400 /* FIXME: Use a bytecompiled object, or even better a subr. */ 451 Lisp_Object result;
401 Lisp_Object ret = list4 (Qlambda, 452 XSET_MODULE_FUNCTION (result, function);
402 list2 (Qand_rest, Qargs), 453 eassert (MODULE_FUNCTIONP (result));
403 doc,
404 list4 (Qapply,
405 list2 (Qfunction, Qinternal__module_call),
406 envobj,
407 Qargs));
408 454
409 return lisp_to_value (ret); 455 return lisp_to_value (env, result);
410} 456}
411 457
412static emacs_value 458static emacs_value
@@ -426,7 +472,7 @@ module_funcall (emacs_env *env, emacs_value fun, ptrdiff_t nargs,
426 newargs[0] = value_to_lisp (fun); 472 newargs[0] = value_to_lisp (fun);
427 for (ptrdiff_t i = 0; i < nargs; i++) 473 for (ptrdiff_t i = 0; i < nargs; i++)
428 newargs[1 + i] = value_to_lisp (args[i]); 474 newargs[1 + i] = value_to_lisp (args[i]);
429 emacs_value result = lisp_to_value (Ffuncall (nargs1, newargs)); 475 emacs_value result = lisp_to_value (env, Ffuncall (nargs1, newargs));
430 SAFE_FREE (); 476 SAFE_FREE ();
431 return result; 477 return result;
432} 478}
@@ -435,31 +481,27 @@ static emacs_value
435module_intern (emacs_env *env, const char *name) 481module_intern (emacs_env *env, const char *name)
436{ 482{
437 MODULE_FUNCTION_BEGIN (module_nil); 483 MODULE_FUNCTION_BEGIN (module_nil);
438 return lisp_to_value (intern (name)); 484 return lisp_to_value (env, intern (name));
439} 485}
440 486
441static emacs_value 487static emacs_value
442module_type_of (emacs_env *env, emacs_value value) 488module_type_of (emacs_env *env, emacs_value value)
443{ 489{
444 MODULE_FUNCTION_BEGIN (module_nil); 490 MODULE_FUNCTION_BEGIN (module_nil);
445 return lisp_to_value (Ftype_of (value_to_lisp (value))); 491 return lisp_to_value (env, Ftype_of (value_to_lisp (value)));
446} 492}
447 493
448static bool 494static bool
449module_is_not_nil (emacs_env *env, emacs_value value) 495module_is_not_nil (emacs_env *env, emacs_value value)
450{ 496{
451 check_main_thread (); 497 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
452 if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
453 return false;
454 return ! NILP (value_to_lisp (value)); 498 return ! NILP (value_to_lisp (value));
455} 499}
456 500
457static bool 501static bool
458module_eq (emacs_env *env, emacs_value a, emacs_value b) 502module_eq (emacs_env *env, emacs_value a, emacs_value b)
459{ 503{
460 check_main_thread (); 504 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
461 if (module_non_local_exit_check (env) != emacs_funcall_exit_return)
462 return false;
463 return EQ (value_to_lisp (a), value_to_lisp (b)); 505 return EQ (value_to_lisp (a), value_to_lisp (b));
464} 506}
465 507
@@ -478,7 +520,7 @@ module_make_integer (emacs_env *env, intmax_t n)
478 MODULE_FUNCTION_BEGIN (module_nil); 520 MODULE_FUNCTION_BEGIN (module_nil);
479 if (FIXNUM_OVERFLOW_P (n)) 521 if (FIXNUM_OVERFLOW_P (n))
480 xsignal0 (Qoverflow_error); 522 xsignal0 (Qoverflow_error);
481 return lisp_to_value (make_number (n)); 523 return lisp_to_value (env, make_number (n));
482} 524}
483 525
484static double 526static double
@@ -494,7 +536,7 @@ static emacs_value
494module_make_float (emacs_env *env, double d) 536module_make_float (emacs_env *env, double d)
495{ 537{
496 MODULE_FUNCTION_BEGIN (module_nil); 538 MODULE_FUNCTION_BEGIN (module_nil);
497 return lisp_to_value (make_float (d)); 539 return lisp_to_value (env, make_float (d));
498} 540}
499 541
500static bool 542static bool
@@ -509,16 +551,12 @@ module_copy_string_contents (emacs_env *env, emacs_value value, char *buffer,
509 ptrdiff_t raw_size = SBYTES (lisp_str_utf8); 551 ptrdiff_t raw_size = SBYTES (lisp_str_utf8);
510 ptrdiff_t required_buf_size = raw_size + 1; 552 ptrdiff_t required_buf_size = raw_size + 1;
511 553
512 eassert (length != NULL);
513
514 if (buffer == NULL) 554 if (buffer == NULL)
515 { 555 {
516 *length = required_buf_size; 556 *length = required_buf_size;
517 return true; 557 return true;
518 } 558 }
519 559
520 eassert (*length >= 0);
521
522 if (*length < required_buf_size) 560 if (*length < required_buf_size)
523 { 561 {
524 *length = required_buf_size; 562 *length = required_buf_size;
@@ -535,15 +573,20 @@ static emacs_value
535module_make_string (emacs_env *env, const char *str, ptrdiff_t length) 573module_make_string (emacs_env *env, const char *str, ptrdiff_t length)
536{ 574{
537 MODULE_FUNCTION_BEGIN (module_nil); 575 MODULE_FUNCTION_BEGIN (module_nil);
576 if (! (0 <= length && length <= STRING_BYTES_BOUND))
577 xsignal0 (Qoverflow_error);
578 /* FIXME: AUTO_STRING_WITH_LEN requires STR to be null-terminated,
579 but we shouldn’t require that. */
538 AUTO_STRING_WITH_LEN (lstr, str, length); 580 AUTO_STRING_WITH_LEN (lstr, str, length);
539 return lisp_to_value (code_convert_string_norecord (lstr, Qutf_8, false)); 581 return lisp_to_value (env,
582 code_convert_string_norecord (lstr, Qutf_8, false));
540} 583}
541 584
542static emacs_value 585static emacs_value
543module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr) 586module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr)
544{ 587{
545 MODULE_FUNCTION_BEGIN (module_nil); 588 MODULE_FUNCTION_BEGIN (module_nil);
546 return lisp_to_value (make_user_ptr (fin, ptr)); 589 return lisp_to_value (env, make_user_ptr (fin, ptr));
547} 590}
548 591
549static void * 592static void *
@@ -558,7 +601,6 @@ module_get_user_ptr (emacs_env *env, emacs_value uptr)
558static void 601static void
559module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr) 602module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
560{ 603{
561 /* FIXME: This function should return bool because it can fail. */
562 MODULE_FUNCTION_BEGIN (); 604 MODULE_FUNCTION_BEGIN ();
563 Lisp_Object lisp = value_to_lisp (uptr); 605 Lisp_Object lisp = value_to_lisp (uptr);
564 CHECK_USER_PTR (lisp); 606 CHECK_USER_PTR (lisp);
@@ -578,7 +620,6 @@ static void
578module_set_user_finalizer (emacs_env *env, emacs_value uptr, 620module_set_user_finalizer (emacs_env *env, emacs_value uptr,
579 emacs_finalizer_function fin) 621 emacs_finalizer_function fin)
580{ 622{
581 /* FIXME: This function should return bool because it can fail. */
582 MODULE_FUNCTION_BEGIN (); 623 MODULE_FUNCTION_BEGIN ();
583 Lisp_Object lisp = value_to_lisp (uptr); 624 Lisp_Object lisp = value_to_lisp (uptr);
584 CHECK_USER_PTR (lisp); 625 CHECK_USER_PTR (lisp);
@@ -597,7 +638,6 @@ check_vec_index (Lisp_Object lvec, ptrdiff_t i)
597static void 638static void
598module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val) 639module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val)
599{ 640{
600 /* FIXME: This function should return bool because it can fail. */
601 MODULE_FUNCTION_BEGIN (); 641 MODULE_FUNCTION_BEGIN ();
602 Lisp_Object lvec = value_to_lisp (vec); 642 Lisp_Object lvec = value_to_lisp (vec);
603 check_vec_index (lvec, i); 643 check_vec_index (lvec, i);
@@ -610,22 +650,46 @@ module_vec_get (emacs_env *env, emacs_value vec, ptrdiff_t i)
610 MODULE_FUNCTION_BEGIN (module_nil); 650 MODULE_FUNCTION_BEGIN (module_nil);
611 Lisp_Object lvec = value_to_lisp (vec); 651 Lisp_Object lvec = value_to_lisp (vec);
612 check_vec_index (lvec, i); 652 check_vec_index (lvec, i);
613 return lisp_to_value (AREF (lvec, i)); 653 return lisp_to_value (env, AREF (lvec, i));
614} 654}
615 655
616static ptrdiff_t 656static ptrdiff_t
617module_vec_size (emacs_env *env, emacs_value vec) 657module_vec_size (emacs_env *env, emacs_value vec)
618{ 658{
619 /* FIXME: Return a sentinel value (e.g., -1) on error. */
620 MODULE_FUNCTION_BEGIN (0); 659 MODULE_FUNCTION_BEGIN (0);
621 Lisp_Object lvec = value_to_lisp (vec); 660 Lisp_Object lvec = value_to_lisp (vec);
622 CHECK_VECTOR (lvec); 661 CHECK_VECTOR (lvec);
623 return ASIZE (lvec); 662 return ASIZE (lvec);
624} 663}
625 664
665/* This function should return true if and only if maybe_quit would do
666 anything. */
667static bool
668module_should_quit (emacs_env *env)
669{
670 MODULE_FUNCTION_BEGIN_NO_CATCH (false);
671 return (! NILP (Vquit_flag) && NILP (Vinhibit_quit)) || pending_signals;
672}
673
626 674
627/* Subroutines. */ 675/* Subroutines. */
628 676
677static void
678module_signal_or_throw (struct emacs_env_private *env)
679{
680 switch (env->pending_non_local_exit)
681 {
682 case emacs_funcall_exit_return:
683 return;
684 case emacs_funcall_exit_signal:
685 xsignal (env->non_local_exit_symbol, env->non_local_exit_data);
686 case emacs_funcall_exit_throw:
687 Fthrow (env->non_local_exit_symbol, env->non_local_exit_data);
688 default:
689 eassume (false);
690 }
691}
692
629DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, 693DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
630 doc: /* Load module FILE. */) 694 doc: /* Load module FILE. */)
631 (Lisp_Object file) 695 (Lisp_Object file)
@@ -637,122 +701,161 @@ DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0,
637 CHECK_STRING (file); 701 CHECK_STRING (file);
638 handle = dynlib_open (SSDATA (file)); 702 handle = dynlib_open (SSDATA (file));
639 if (!handle) 703 if (!handle)
640 error ("Cannot load file %s: %s", SDATA (file), dynlib_error ()); 704 xsignal2 (Qmodule_open_failed, file, build_string (dynlib_error ()));
641 705
642 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible"); 706 gpl_sym = dynlib_sym (handle, "plugin_is_GPL_compatible");
643 if (!gpl_sym) 707 if (!gpl_sym)
644 error ("Module %s is not GPL compatible", SDATA (file)); 708 xsignal1 (Qmodule_not_gpl_compatible, file);
645 709
646 module_init = (emacs_init_function) dynlib_func (handle, "emacs_module_init"); 710 module_init = (emacs_init_function) dynlib_func (handle, "emacs_module_init");
647 if (!module_init) 711 if (!module_init)
648 error ("Module %s does not have an init function.", SDATA (file)); 712 xsignal1 (Qmissing_module_init_function, file);
649 713
650 struct emacs_runtime_private rt; /* Includes the public emacs_env. */ 714 struct emacs_runtime rt_pub;
651 struct emacs_env_private priv; 715 struct emacs_runtime_private rt_priv;
652 initialize_environment (&rt.pub, &priv); 716 emacs_env env_pub;
653 struct emacs_runtime pub = 717 struct emacs_env_private env_priv;
654 { 718 rt_priv.env = initialize_environment (&env_pub, &env_priv);
655 .size = sizeof pub, 719
656 .private_members = &rt, 720 /* If we should use module assertions, reallocate the runtime object
657 .get_environment = module_get_environment 721 from the free store, but never free it. That way the addresses
658 }; 722 for two different runtime objects are guaranteed to be distinct,
659 int r = module_init (&pub); 723 which we can use for checking the liveness of runtime
660 finalize_environment (&priv); 724 pointers. */
725 struct emacs_runtime *rt = module_assertions ? xmalloc (sizeof *rt) : &rt_pub;
726 rt->size = sizeof *rt;
727 rt->private_members = &rt_priv;
728 rt->get_environment = module_get_environment;
729
730 Vmodule_runtimes = Fcons (make_save_ptr (rt), Vmodule_runtimes);
731 ptrdiff_t count = SPECPDL_INDEX ();
732 record_unwind_protect_ptr (finalize_runtime_unwind, rt);
733
734 int r = module_init (rt);
735
736 /* Process the quit flag first, so that quitting doesn't get
737 overridden by other non-local exits. */
738 maybe_quit ();
661 739
662 if (r != 0) 740 if (r != 0)
663 { 741 {
664 if (FIXNUM_OVERFLOW_P (r)) 742 if (FIXNUM_OVERFLOW_P (r))
665 xsignal0 (Qoverflow_error); 743 xsignal0 (Qoverflow_error);
666 xsignal2 (Qmodule_load_failed, file, make_number (r)); 744 xsignal2 (Qmodule_init_failed, file, make_number (r));
667 } 745 }
668 746
669 return Qt; 747 module_signal_or_throw (&env_priv);
748 return unbind_to (count, Qt);
670} 749}
671 750
672DEFUN ("internal--module-call", Finternal_module_call, Sinternal_module_call, 1, MANY, 0, 751Lisp_Object
673 doc: /* Internal function to call a module function. 752funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist)
674ENVOBJ is a save pointer to a module_fun_env structure.
675ARGLIST is a list of arguments passed to SUBRPTR.
676usage: (module-call ENVOBJ &rest ARGLIST) */)
677 (ptrdiff_t nargs, Lisp_Object *arglist)
678{ 753{
679 Lisp_Object envobj = arglist[0]; 754 const struct Lisp_Module_Function *func = XMODULE_FUNCTION (function);
680 /* FIXME: Rather than use a save_value, we should create a new object type. 755 eassume (0 <= func->min_arity);
681 Making save_value visible to Lisp is wrong. */ 756 if (! (func->min_arity <= nargs
682 CHECK_TYPE (SAVE_VALUEP (envobj), Qsave_value_p, envobj); 757 && (func->max_arity < 0 || nargs <= func->max_arity)))
683 struct Lisp_Save_Value *save_value = XSAVE_VALUE (envobj); 758 xsignal2 (Qwrong_number_of_arguments, function, make_number (nargs));
684 CHECK_TYPE (save_type (save_value, 0) == SAVE_POINTER, Qsave_pointer_p, envobj);
685 /* FIXME: We have no reason to believe that XSAVE_POINTER (envobj, 0)
686 is a module_fun_env pointer. If some other part of Emacs also
687 exports save_value objects to Elisp, than we may be getting here this
688 other kind of save_value which will likely hold something completely
689 different in this field. */
690 struct module_fun_env *envptr = XSAVE_POINTER (envobj, 0);
691 EMACS_INT len = nargs - 1;
692 eassume (0 <= envptr->min_arity);
693 if (! (envptr->min_arity <= len
694 && len <= (envptr->max_arity < 0 ? PTRDIFF_MAX : envptr->max_arity)))
695 xsignal2 (Qwrong_number_of_arguments, module_format_fun_env (envptr),
696 make_number (len));
697 759
698 emacs_env pub; 760 emacs_env pub;
699 struct emacs_env_private priv; 761 struct emacs_env_private priv;
700 initialize_environment (&pub, &priv); 762 emacs_env *env = initialize_environment (&pub, &priv);
763 ptrdiff_t count = SPECPDL_INDEX ();
764 record_unwind_protect_ptr (finalize_environment_unwind, env);
701 765
702 USE_SAFE_ALLOCA; 766 USE_SAFE_ALLOCA;
703 emacs_value *args; 767 ATTRIBUTE_MAY_ALIAS emacs_value *args;
704 if (plain_values) 768 if (plain_values && ! module_assertions)
705 args = (emacs_value *) arglist + 1; 769 /* FIXME: The cast below is incorrect because the argument array
770 is not declared as const, so module functions can modify it.
771 Either declare it as const, or remove this branch. */
772 args = (emacs_value *) arglist;
706 else 773 else
707 { 774 {
708 args = SAFE_ALLOCA (len * sizeof *args); 775 args = SAFE_ALLOCA (nargs * sizeof *args);
709 for (ptrdiff_t i = 0; i < len; i++) 776 for (ptrdiff_t i = 0; i < nargs; i++)
710 args[i] = lisp_to_value (arglist[i + 1]); 777 args[i] = lisp_to_value (env, arglist[i]);
711 } 778 }
712 779
713 emacs_value ret = envptr->subr (&pub, len, args, envptr->data); 780 emacs_value ret = func->subr (env, nargs, args, func->data);
714 SAFE_FREE (); 781 SAFE_FREE ();
715 782
716 eassert (&priv == pub.private_members); 783 eassert (&priv == env->private_members);
717 784
718 switch (priv.pending_non_local_exit) 785 /* Process the quit flag first, so that quitting doesn't get
719 { 786 overridden by other non-local exits. */
720 case emacs_funcall_exit_return: 787 maybe_quit ();
721 finalize_environment (&priv); 788
722 return value_to_lisp (ret); 789 module_signal_or_throw (&priv);
723 case emacs_funcall_exit_signal: 790 return unbind_to (count, value_to_lisp (ret));
724 { 791}
725 Lisp_Object symbol = priv.non_local_exit_symbol; 792
726 Lisp_Object data = priv.non_local_exit_data; 793Lisp_Object
727 finalize_environment (&priv); 794module_function_arity (const struct Lisp_Module_Function *const function)
728 xsignal (symbol, data); 795{
729 } 796 ptrdiff_t minargs = function->min_arity;
730 case emacs_funcall_exit_throw: 797 ptrdiff_t maxargs = function->max_arity;
731 { 798 return Fcons (make_number (minargs),
732 Lisp_Object tag = priv.non_local_exit_symbol; 799 maxargs == MANY ? Qmany : make_number (maxargs));
733 Lisp_Object value = priv.non_local_exit_data;
734 finalize_environment (&priv);
735 Fthrow (tag, value);
736 }
737 default:
738 eassume (false);
739 }
740} 800}
741 801
742 802
743/* Helper functions. */ 803/* Helper functions. */
744 804
745static void 805static bool
746check_main_thread (void) 806in_current_thread (void)
747{ 807{
808 if (current_thread == NULL)
809 return false;
748#ifdef HAVE_PTHREAD 810#ifdef HAVE_PTHREAD
749 eassert (pthread_equal (pthread_self (), main_thread_id)); 811 return pthread_equal (pthread_self (), current_thread->thread_id);
750#elif defined WINDOWSNT 812#elif defined WINDOWSNT
751 eassert (GetCurrentThreadId () == dwMainThreadId); 813 return GetCurrentThreadId () == current_thread->thread_id;
752#endif 814#endif
753} 815}
754 816
755static void 817static void
818module_assert_thread (void)
819{
820 if (! module_assertions || in_current_thread ())
821 return;
822 module_abort ("Module function called from outside the current Lisp thread");
823}
824
825static void
826module_assert_runtime (struct emacs_runtime *ert)
827{
828 if (! module_assertions)
829 return;
830 ptrdiff_t count = 0;
831 for (Lisp_Object tail = Vmodule_runtimes; CONSP (tail); tail = XCDR (tail))
832 {
833 if (XSAVE_POINTER (XCAR (tail), 0) == ert)
834 return;
835 ++count;
836 }
837 module_abort ("Runtime pointer not found in list of %"pD"d runtimes",
838 count);
839}
840
841static void
842module_assert_env (emacs_env *env)
843{
844 if (! module_assertions)
845 return;
846 ptrdiff_t count = 0;
847 for (Lisp_Object tail = Vmodule_environments; CONSP (tail);
848 tail = XCDR (tail))
849 {
850 if (XSAVE_POINTER (XCAR (tail), 0) == env)
851 return;
852 ++count;
853 }
854 module_abort ("Environment pointer not found in list of %"pD"d environments",
855 count);
856}
857
858static void
756module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, 859module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym,
757 Lisp_Object data) 860 Lisp_Object data)
758{ 861{
@@ -791,6 +894,14 @@ module_out_of_memory (emacs_env *env)
791 894
792/* Value conversion. */ 895/* Value conversion. */
793 896
897/* We represent Lisp objects differently depending on whether the user
898 gave -module-assertions. If assertions are disabled, emacs_value
899 objects are Lisp_Objects cast to emacs_value. If assertions are
900 enabled, emacs_value objects are pointers to Lisp_Object objects
901 allocated from the free store; they are never freed, which ensures
902 that their addresses are unique and can be used for liveness
903 checking. */
904
794/* Unique Lisp_Object used to mark those emacs_values which are really 905/* Unique Lisp_Object used to mark those emacs_values which are really
795 just containers holding a Lisp_Object that does not fit as an emacs_value, 906 just containers holding a Lisp_Object that does not fit as an emacs_value,
796 either because it is an integer out of range, or is not properly aligned. 907 either because it is an integer out of range, or is not properly aligned.
@@ -837,6 +948,33 @@ value_to_lisp_bits (emacs_value v)
837static Lisp_Object 948static Lisp_Object
838value_to_lisp (emacs_value v) 949value_to_lisp (emacs_value v)
839{ 950{
951 if (module_assertions)
952 {
953 /* Check the liveness of the value by iterating over all live
954 environments. */
955 void *vptr = v;
956 ATTRIBUTE_MAY_ALIAS Lisp_Object *optr = vptr;
957 ptrdiff_t num_environments = 0;
958 ptrdiff_t num_values = 0;
959 for (Lisp_Object environments = Vmodule_environments;
960 CONSP (environments); environments = XCDR (environments))
961 {
962 emacs_env *env = XSAVE_POINTER (XCAR (environments), 0);
963 for (Lisp_Object values = env->private_members->values;
964 CONSP (values); values = XCDR (values))
965 {
966 Lisp_Object *p = XSAVE_POINTER (XCAR (values), 0);
967 if (p == optr)
968 return *p;
969 ++num_values;
970 }
971 ++num_environments;
972 }
973 module_abort (("Emacs value not found in %"pD"d values "
974 "of %"pD"d environments"),
975 num_values, num_environments);
976 }
977
840 Lisp_Object o = value_to_lisp_bits (v); 978 Lisp_Object o = value_to_lisp_bits (v);
841 if (! plain_values && CONSP (o) && EQ (XCDR (o), ltv_mark)) 979 if (! plain_values && CONSP (o) && EQ (XCDR (o), ltv_mark))
842 o = XCAR (o); 980 o = XCAR (o);
@@ -865,8 +1003,23 @@ enum { HAVE_STRUCT_ATTRIBUTE_ALIGNED = 0 };
865/* Convert O to an emacs_value. Allocate storage if needed; this can 1003/* Convert O to an emacs_value. Allocate storage if needed; this can
866 signal if memory is exhausted. Must be an injective function. */ 1004 signal if memory is exhausted. Must be an injective function. */
867static emacs_value 1005static emacs_value
868lisp_to_value (Lisp_Object o) 1006lisp_to_value (emacs_env *env, Lisp_Object o)
869{ 1007{
1008 if (module_assertions)
1009 {
1010 /* Add the new value to the list of values allocated from this
1011 environment. The value is actually a pointer to the
1012 Lisp_Object cast to emacs_value. We make a copy of the
1013 object on the free store to guarantee unique addresses. */
1014 ATTRIBUTE_MAY_ALIAS Lisp_Object *optr = xmalloc (sizeof o);
1015 *optr = o;
1016 void *vptr = optr;
1017 ATTRIBUTE_MAY_ALIAS emacs_value ret = vptr;
1018 struct emacs_env_private *priv = env->private_members;
1019 priv->values = Fcons (make_save_ptr (ret), priv->values);
1020 return ret;
1021 }
1022
870 emacs_value v = lisp_to_value_bits (o); 1023 emacs_value v = lisp_to_value_bits (o);
871 1024
872 if (! EQ (o, value_to_lisp_bits (v))) 1025 if (! EQ (o, value_to_lisp_bits (v)))
@@ -897,11 +1050,20 @@ lisp_to_value (Lisp_Object o)
897 1050
898/* Environment lifetime management. */ 1051/* Environment lifetime management. */
899 1052
900/* Must be called before the environment can be used. */ 1053/* Must be called before the environment can be used. Returns another
901static void 1054 pointer that callers should use instead of the ENV argument. If
1055 module assertions are disabled, the return value is ENV. If module
1056 assertions are enabled, the return value points to a heap-allocated
1057 object. That object is never freed to guarantee unique
1058 addresses. */
1059static emacs_env *
902initialize_environment (emacs_env *env, struct emacs_env_private *priv) 1060initialize_environment (emacs_env *env, struct emacs_env_private *priv)
903{ 1061{
1062 if (module_assertions)
1063 env = xmalloc (sizeof *env);
1064
904 priv->pending_non_local_exit = emacs_funcall_exit_return; 1065 priv->pending_non_local_exit = emacs_funcall_exit_return;
1066 priv->values = priv->non_local_exit_symbol = priv->non_local_exit_data = Qnil;
905 env->size = sizeof *env; 1067 env->size = sizeof *env;
906 env->private_members = priv; 1068 env->private_members = priv;
907 env->make_global_ref = module_make_global_ref; 1069 env->make_global_ref = module_make_global_ref;
@@ -931,15 +1093,50 @@ initialize_environment (emacs_env *env, struct emacs_env_private *priv)
931 env->vec_set = module_vec_set; 1093 env->vec_set = module_vec_set;
932 env->vec_get = module_vec_get; 1094 env->vec_get = module_vec_get;
933 env->vec_size = module_vec_size; 1095 env->vec_size = module_vec_size;
1096 env->should_quit = module_should_quit;
934 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments); 1097 Vmodule_environments = Fcons (make_save_ptr (env), Vmodule_environments);
1098 return env;
935} 1099}
936 1100
937/* Must be called before the lifetime of the environment object 1101/* Must be called before the lifetime of the environment object
938 ends. */ 1102 ends. */
939static void 1103static void
940finalize_environment (struct emacs_env_private *env) 1104finalize_environment (emacs_env *env)
941{ 1105{
1106 eassert (XSAVE_POINTER (XCAR (Vmodule_environments), 0) == env);
942 Vmodule_environments = XCDR (Vmodule_environments); 1107 Vmodule_environments = XCDR (Vmodule_environments);
1108 if (module_assertions)
1109 /* There is always at least the global environment. */
1110 eassert (CONSP (Vmodule_environments));
1111}
1112
1113static void
1114finalize_environment_unwind (void *env)
1115{
1116 finalize_environment (env);
1117}
1118
1119static void
1120finalize_runtime_unwind (void* raw_ert)
1121{
1122 struct emacs_runtime *ert = raw_ert;
1123 eassert (XSAVE_POINTER (XCAR (Vmodule_runtimes), 0) == ert);
1124 Vmodule_runtimes = XCDR (Vmodule_runtimes);
1125 finalize_environment (ert->private_members->env);
1126}
1127
1128void
1129mark_modules (void)
1130{
1131 for (Lisp_Object tail = Vmodule_environments; CONSP (tail);
1132 tail = XCDR (tail))
1133 {
1134 emacs_env *env = XSAVE_POINTER (XCAR (tail), 0);
1135 struct emacs_env_private *priv = env->private_members;
1136 mark_object (priv->non_local_exit_symbol);
1137 mark_object (priv->non_local_exit_data);
1138 mark_object (priv->values);
1139 }
943} 1140}
944 1141
945 1142
@@ -948,10 +1145,12 @@ finalize_environment (struct emacs_env_private *env)
948/* Must be called after setting up a handler immediately before 1145/* Must be called after setting up a handler immediately before
949 returning from the function. See the comments in lisp.h and the 1146 returning from the function. See the comments in lisp.h and the
950 code in eval.c for details. The macros below arrange for this 1147 code in eval.c for details. The macros below arrange for this
951 function to be called automatically. DUMMY is ignored. */ 1148 function to be called automatically. PHANDLERLIST points to a word
1149 containing the handler list, for sanity checking. */
952static void 1150static void
953module_reset_handlerlist (const int *dummy) 1151module_reset_handlerlist (struct handler **phandlerlist)
954{ 1152{
1153 eassert (handlerlist == *phandlerlist);
955 handlerlist = handlerlist->next; 1154 handlerlist = handlerlist->next;
956} 1155}
957 1156
@@ -972,30 +1171,33 @@ module_handle_throw (emacs_env *env, Lisp_Object tag_val)
972} 1171}
973 1172
974 1173
975/* Function environments. */ 1174/* Support for assertions. */
1175void
1176init_module_assertions (bool enable)
1177{
1178 module_assertions = enable;
1179 if (enable)
1180 {
1181 /* We use a hidden environment for storing the globals. This
1182 environment is never freed. */
1183 emacs_env env;
1184 global_env = initialize_environment (&env, &global_env_private);
1185 eassert (global_env != &env);
1186 }
1187}
976 1188
977/* Return a string object that contains a user-friendly 1189static _Noreturn void
978 representation of the function environment. */ 1190ATTRIBUTE_FORMAT_PRINTF(1, 2)
979static Lisp_Object 1191module_abort (const char *format, ...)
980module_format_fun_env (const struct module_fun_env *env)
981{ 1192{
982 /* Try to print a function name if possible. */ 1193 fputs ("Emacs module assertion: ", stderr);
983 const char *path, *sym; 1194 va_list args;
984 static char const noaddr_format[] = "#<module function at %p>"; 1195 va_start (args, format);
985 char buffer[sizeof noaddr_format + INT_STRLEN_BOUND (intptr_t) + 256]; 1196 vfprintf (stderr, format, args);
986 char *buf = buffer; 1197 va_end (args);
987 ptrdiff_t bufsize = sizeof buffer; 1198 putc ('\n', stderr);
988 ptrdiff_t size 1199 fflush (NULL);
989 = (dynlib_addr (env->subr, &path, &sym) 1200 emacs_abort ();
990 ? exprintf (&buf, &bufsize, buffer, -1,
991 "#<module function %s from %s>", sym, path)
992 : sprintf (buffer, noaddr_format, env->subr));
993 AUTO_STRING_WITH_LEN (unibyte_result, buffer, size);
994 Lisp_Object result = code_convert_string_norecord (unibyte_result,
995 Qutf_8, false);
996 if (buf != buffer)
997 xfree (buf);
998 return result;
999} 1201}
1000 1202
1001 1203
@@ -1018,6 +1220,14 @@ syms_of_module (void)
1018 Qnil, false); 1220 Qnil, false);
1019 Funintern (Qmodule_refs_hash, Qnil); 1221 Funintern (Qmodule_refs_hash, Qnil);
1020 1222
1223 DEFSYM (Qmodule_runtimes, "module-runtimes");
1224 DEFVAR_LISP ("module-runtimes", Vmodule_runtimes,
1225 doc: /* List of active module runtimes. */);
1226 Vmodule_runtimes = Qnil;
1227 /* Unintern `module-runtimes' because it is only used
1228 internally. */
1229 Funintern (Qmodule_runtimes, Qnil);
1230
1021 DEFSYM (Qmodule_environments, "module-environments"); 1231 DEFSYM (Qmodule_environments, "module-environments");
1022 DEFVAR_LISP ("module-environments", Vmodule_environments, 1232 DEFVAR_LISP ("module-environments", Vmodule_environments,
1023 doc: /* List of active module environments. */); 1233 doc: /* List of active module environments. */);
@@ -1032,11 +1242,34 @@ syms_of_module (void)
1032 Fput (Qmodule_load_failed, Qerror_message, 1242 Fput (Qmodule_load_failed, Qerror_message,
1033 build_pure_c_string ("Module load failed")); 1243 build_pure_c_string ("Module load failed"));
1034 1244
1035 DEFSYM (Qinvalid_module_call, "invalid-module-call"); 1245 DEFSYM (Qmodule_open_failed, "module-open-failed");
1036 Fput (Qinvalid_module_call, Qerror_conditions, 1246 Fput (Qmodule_open_failed, Qerror_conditions,
1037 listn (CONSTYPE_PURE, 2, Qinvalid_module_call, Qerror)); 1247 listn (CONSTYPE_PURE, 3,
1038 Fput (Qinvalid_module_call, Qerror_message, 1248 Qmodule_open_failed, Qmodule_load_failed, Qerror));
1039 build_pure_c_string ("Invalid module call")); 1249 Fput (Qmodule_open_failed, Qerror_message,
1250 build_pure_c_string ("Module could not be opened"));
1251
1252 DEFSYM (Qmodule_not_gpl_compatible, "module-not-gpl-compatible");
1253 Fput (Qmodule_not_gpl_compatible, Qerror_conditions,
1254 listn (CONSTYPE_PURE, 3,
1255 Qmodule_not_gpl_compatible, Qmodule_load_failed, Qerror));
1256 Fput (Qmodule_not_gpl_compatible, Qerror_message,
1257 build_pure_c_string ("Module is not GPL compatible"));
1258
1259 DEFSYM (Qmissing_module_init_function, "missing-module-init-function");
1260 Fput (Qmissing_module_init_function, Qerror_conditions,
1261 listn (CONSTYPE_PURE, 3,
1262 Qmissing_module_init_function, Qmodule_load_failed, Qerror));
1263 Fput (Qmissing_module_init_function, Qerror_message,
1264 build_pure_c_string ("Module does not export an "
1265 "initialization function"));
1266
1267 DEFSYM (Qmodule_init_failed, "module-init-failed");
1268 Fput (Qmodule_init_failed, Qerror_conditions,
1269 listn (CONSTYPE_PURE, 3,
1270 Qmodule_init_failed, Qmodule_load_failed, Qerror));
1271 Fput (Qmodule_init_failed, Qerror_message,
1272 build_pure_c_string ("Module initialization failed"));
1040 1273
1041 DEFSYM (Qinvalid_arity, "invalid-arity"); 1274 DEFSYM (Qinvalid_arity, "invalid-arity");
1042 Fput (Qinvalid_arity, Qerror_conditions, 1275 Fput (Qinvalid_arity, Qerror_conditions,
@@ -1048,11 +1281,7 @@ syms_of_module (void)
1048 code or modules should not access it. */ 1281 code or modules should not access it. */
1049 Funintern (Qmodule_refs_hash, Qnil); 1282 Funintern (Qmodule_refs_hash, Qnil);
1050 1283
1051 DEFSYM (Qsave_value_p, "save-value-p"); 1284 DEFSYM (Qmodule_function_p, "module-function-p");
1052 DEFSYM (Qsave_pointer_p, "save-pointer-p");
1053 1285
1054 defsubr (&Smodule_load); 1286 defsubr (&Smodule_load);
1055
1056 DEFSYM (Qinternal__module_call, "internal--module-call");
1057 defsubr (&Sinternal_module_call);
1058} 1287}
diff --git a/src/emacs-module.h b/src/emacs-module.h
deleted file mode 100644
index d9eeeabec3f..00000000000
--- a/src/emacs-module.h
+++ /dev/null
@@ -1,197 +0,0 @@
1/* emacs-module.h - GNU Emacs module API.
2
3Copyright (C) 2015-2017 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef EMACS_MODULE_H
21#define EMACS_MODULE_H
22
23#include <stdint.h>
24#include <stddef.h>
25#include <stdbool.h>
26
27#if defined __cplusplus && __cplusplus >= 201103L
28# define EMACS_NOEXCEPT noexcept
29#else
30# define EMACS_NOEXCEPT
31#endif
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37/* Current environment. */
38typedef struct emacs_env_25 emacs_env;
39
40/* Opaque pointer representing an Emacs Lisp value.
41 BEWARE: Do not assume NULL is a valid value! */
42typedef struct emacs_value_tag *emacs_value;
43
44enum { emacs_variadic_function = -2 };
45
46/* Struct passed to a module init function (emacs_module_init). */
47struct emacs_runtime
48{
49 /* Structure size (for version checking). */
50 ptrdiff_t size;
51
52 /* Private data; users should not touch this. */
53 struct emacs_runtime_private *private_members;
54
55 /* Return an environment pointer. */
56 emacs_env *(*get_environment) (struct emacs_runtime *ert);
57};
58
59
60/* Possible Emacs function call outcomes. */
61enum emacs_funcall_exit
62{
63 /* Function has returned normally. */
64 emacs_funcall_exit_return = 0,
65
66 /* Function has signaled an error using `signal'. */
67 emacs_funcall_exit_signal = 1,
68
69 /* Function has exit using `throw'. */
70 emacs_funcall_exit_throw = 2,
71};
72
73struct emacs_env_25
74{
75 /* Structure size (for version checking). */
76 ptrdiff_t size;
77
78 /* Private data; users should not touch this. */
79 struct emacs_env_private *private_members;
80
81 /* Memory management. */
82
83 emacs_value (*make_global_ref) (emacs_env *env,
84 emacs_value any_reference);
85
86 void (*free_global_ref) (emacs_env *env,
87 emacs_value global_reference);
88
89 /* Non-local exit handling. */
90
91 enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env);
92
93 void (*non_local_exit_clear) (emacs_env *env);
94
95 enum emacs_funcall_exit (*non_local_exit_get)
96 (emacs_env *env,
97 emacs_value *non_local_exit_symbol_out,
98 emacs_value *non_local_exit_data_out);
99
100 void (*non_local_exit_signal) (emacs_env *env,
101 emacs_value non_local_exit_symbol,
102 emacs_value non_local_exit_data);
103
104 void (*non_local_exit_throw) (emacs_env *env,
105 emacs_value tag,
106 emacs_value value);
107
108 /* Function registration. */
109
110 emacs_value (*make_function) (emacs_env *env,
111 ptrdiff_t min_arity,
112 ptrdiff_t max_arity,
113 emacs_value (*function) (emacs_env *env,
114 ptrdiff_t nargs,
115 emacs_value args[],
116 void *)
117 EMACS_NOEXCEPT,
118 const char *documentation,
119 void *data);
120
121 emacs_value (*funcall) (emacs_env *env,
122 emacs_value function,
123 ptrdiff_t nargs,
124 emacs_value args[]);
125
126 emacs_value (*intern) (emacs_env *env,
127 const char *symbol_name);
128
129 /* Type conversion. */
130
131 emacs_value (*type_of) (emacs_env *env,
132 emacs_value value);
133
134 bool (*is_not_nil) (emacs_env *env, emacs_value value);
135
136 bool (*eq) (emacs_env *env, emacs_value a, emacs_value b);
137
138 intmax_t (*extract_integer) (emacs_env *env, emacs_value value);
139
140 emacs_value (*make_integer) (emacs_env *env, intmax_t value);
141
142 double (*extract_float) (emacs_env *env, emacs_value value);
143
144 emacs_value (*make_float) (emacs_env *env, double value);
145
146 /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
147 null-terminated string.
148
149 SIZE must point to the total size of the buffer. If BUFFER is
150 NULL or if SIZE is not big enough, write the required buffer size
151 to SIZE and return false.
152
153 Note that SIZE must include the last null byte (e.g. "abc" needs
154 a buffer of size 4).
155
156 Return true if the string was successfully copied. */
157
158 bool (*copy_string_contents) (emacs_env *env,
159 emacs_value value,
160 char *buffer,
161 ptrdiff_t *size_inout);
162
163 /* Create a Lisp string from a utf8 encoded string. */
164 emacs_value (*make_string) (emacs_env *env,
165 const char *contents, ptrdiff_t length);
166
167 /* Embedded pointer type. */
168 emacs_value (*make_user_ptr) (emacs_env *env,
169 void (*fin) (void *) EMACS_NOEXCEPT,
170 void *ptr);
171
172 void *(*get_user_ptr) (emacs_env *env, emacs_value uptr);
173 void (*set_user_ptr) (emacs_env *env, emacs_value uptr, void *ptr);
174
175 void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
176 (void *) EMACS_NOEXCEPT;
177 void (*set_user_finalizer) (emacs_env *env,
178 emacs_value uptr,
179 void (*fin) (void *) EMACS_NOEXCEPT);
180
181 /* Vector functions. */
182 emacs_value (*vec_get) (emacs_env *env, emacs_value vec, ptrdiff_t i);
183
184 void (*vec_set) (emacs_env *env, emacs_value vec, ptrdiff_t i,
185 emacs_value val);
186
187 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec);
188};
189
190/* Every module should define a function as follows. */
191extern int emacs_module_init (struct emacs_runtime *ert);
192
193#ifdef __cplusplus
194}
195#endif
196
197#endif /* EMACS_MODULE_H */
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
new file mode 100644
index 00000000000..40b6448d27e
--- /dev/null
+++ b/src/emacs-module.h.in
@@ -0,0 +1,107 @@
1/* emacs-module.h - GNU Emacs module API.
2
3Copyright (C) 2015-2017 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation, either version 3 of the License, or (at
10your option) any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20#ifndef EMACS_MODULE_H
21#define EMACS_MODULE_H
22
23#include <stdint.h>
24#include <stddef.h>
25
26#ifndef __cplusplus
27#include <stdbool.h>
28#endif
29
30#if defined __cplusplus && __cplusplus >= 201103L
31# define EMACS_NOEXCEPT noexcept
32#else
33# define EMACS_NOEXCEPT
34#endif
35
36#ifdef __has_attribute
37#if __has_attribute(__nonnull__)
38# define EMACS_ATTRIBUTE_NONNULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
39#endif
40#endif
41#ifndef EMACS_ATTRIBUTE_NONNULL
42# define EMACS_ATTRIBUTE_NONNULL(...)
43#endif
44
45#ifdef __cplusplus
46extern "C" {
47#endif
48
49/* Current environment. */
50typedef struct emacs_env_26 emacs_env;
51
52/* Opaque pointer representing an Emacs Lisp value.
53 BEWARE: Do not assume NULL is a valid value! */
54typedef struct emacs_value_tag *emacs_value;
55
56enum { emacs_variadic_function = -2 };
57
58/* Struct passed to a module init function (emacs_module_init). */
59struct emacs_runtime
60{
61 /* Structure size (for version checking). */
62 ptrdiff_t size;
63
64 /* Private data; users should not touch this. */
65 struct emacs_runtime_private *private_members;
66
67 /* Return an environment pointer. */
68 emacs_env *(*get_environment) (struct emacs_runtime *ert)
69 EMACS_ATTRIBUTE_NONNULL(1);
70};
71
72
73/* Possible Emacs function call outcomes. */
74enum emacs_funcall_exit
75{
76 /* Function has returned normally. */
77 emacs_funcall_exit_return = 0,
78
79 /* Function has signaled an error using `signal'. */
80 emacs_funcall_exit_signal = 1,
81
82 /* Function has exit using `throw'. */
83 emacs_funcall_exit_throw = 2
84};
85
86struct emacs_env_25
87{
88@module_env_snippet_25@
89};
90
91struct emacs_env_26
92{
93@module_env_snippet_25@
94
95@module_env_snippet_26@
96};
97
98/* Every module should define a function as follows. */
99extern int emacs_module_init (struct emacs_runtime *ert)
100 EMACS_NOEXCEPT
101 EMACS_ATTRIBUTE_NONNULL(1);
102
103#ifdef __cplusplus
104}
105#endif
106
107#endif /* EMACS_MODULE_H */
diff --git a/src/emacs.c b/src/emacs.c
index 1868961090d..0fec7167588 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -23,7 +23,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
23 23
24#include <errno.h> 24#include <errno.h>
25#include <fcntl.h> 25#include <fcntl.h>
26#include <stdio.h>
27#include <stdlib.h> 26#include <stdlib.h>
28 27
29#include <sys/file.h> 28#include <sys/file.h>
@@ -33,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33 32
34#define MAIN_PROGRAM 33#define MAIN_PROGRAM
35#include "lisp.h" 34#include "lisp.h"
35#include "sysstdio.h"
36 36
37#ifdef WINDOWSNT 37#ifdef WINDOWSNT
38#include <fcntl.h> 38#include <fcntl.h>
@@ -137,10 +137,6 @@ static
137bool might_dump; 137bool might_dump;
138#endif 138#endif
139 139
140#ifdef DARWIN_OS
141extern void unexec_init_emacs_zone (void);
142#endif
143
144/* If true, Emacs should not attempt to use a window-specific code, 140/* If true, Emacs should not attempt to use a window-specific code,
145 but instead should use the virtual terminal under which it was started. */ 141 but instead should use the virtual terminal under which it was started. */
146bool inhibit_window_system; 142bool inhibit_window_system;
@@ -223,11 +219,16 @@ Initialization options:\n\
223 "\ 219 "\
224--batch do not do interactive display; implies -q\n\ 220--batch do not do interactive display; implies -q\n\
225--chdir DIR change to directory DIR\n\ 221--chdir DIR change to directory DIR\n\
226--daemon, --old-daemon[=NAME] start a (named) server in the background\n\ 222--daemon, --bg-daemon[=NAME] start a (named) server in the background\n\
227--new-daemon[=NAME] start a (named) server in the foreground\n\ 223--fg-daemon[=NAME] start a (named) server in the foreground\n\
228--debug-init enable Emacs Lisp debugger for init file\n\ 224--debug-init enable Emacs Lisp debugger for init file\n\
229--display, -d DISPLAY use X server DISPLAY\n\ 225--display, -d DISPLAY use X server DISPLAY\n\
230", 226",
227#ifdef HAVE_MODULES
228 "\
229--module-assertions assert behavior of dynamic modules\n\
230",
231#endif
231 "\ 232 "\
232--no-build-details do not add build details such as time stamps\n\ 233--no-build-details do not add build details such as time stamps\n\
233--no-desktop do not load a saved desktop\n\ 234--no-desktop do not load a saved desktop\n\
@@ -467,6 +468,9 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd)
467 468
468 if (!NILP (Vinvocation_directory)) 469 if (!NILP (Vinvocation_directory))
469 { 470 {
471 if (NILP (Vpurify_flag) && !NILP (Ffboundp (Qfile_truename)))
472 Vinvocation_directory = call1 (Qfile_truename, Vinvocation_directory);
473
470 dir = Vinvocation_directory; 474 dir = Vinvocation_directory;
471#ifdef WINDOWSNT 475#ifdef WINDOWSNT
472 /* If we are running from the build directory, set DIR to the 476 /* If we are running from the build directory, set DIR to the
@@ -657,8 +661,11 @@ close_output_streams (void)
657 _exit (EXIT_FAILURE); 661 _exit (EXIT_FAILURE);
658 } 662 }
659 663
660 if (close_stream (stderr) != 0) 664 /* Do not close stderr if addresses are being sanitized, as the
661 _exit (EXIT_FAILURE); 665 sanitizer might report to stderr after this function is
666 invoked. */
667 if (!ADDRESS_SANITIZER && close_stream (stderr) != 0)
668 _exit (EXIT_FAILURE);
662} 669}
663 670
664/* ARGSUSED */ 671/* ARGSUSED */
@@ -683,8 +690,12 @@ main (int argc, char **argv)
683 /* Record (approximately) where the stack begins. */ 690 /* Record (approximately) where the stack begins. */
684 stack_bottom = &stack_bottom_variable; 691 stack_bottom = &stack_bottom_variable;
685 692
693#ifndef CANNOT_DUMP
686 dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0 694 dumping = !initialized && (strcmp (argv[argc - 1], "dump") == 0
687 || strcmp (argv[argc - 1], "bootstrap") == 0); 695 || strcmp (argv[argc - 1], "bootstrap") == 0);
696#else
697 dumping = false;
698#endif
688 699
689 /* True if address randomization interferes with memory allocation. */ 700 /* True if address randomization interferes with memory allocation. */
690# ifdef __PPC64__ 701# ifdef __PPC64__
@@ -742,7 +753,7 @@ main (int argc, char **argv)
742#endif 753#endif
743 754
744/* If using unexmacosx.c (set by s/darwin.h), we must do this. */ 755/* If using unexmacosx.c (set by s/darwin.h), we must do this. */
745#ifdef DARWIN_OS 756#if defined DARWIN_OS && !defined CANNOT_DUMP
746 if (!initialized) 757 if (!initialized)
747 unexec_init_emacs_zone (); 758 unexec_init_emacs_zone ();
748#endif 759#endif
@@ -874,7 +885,7 @@ main (int argc, char **argv)
874 } 885 }
875#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */ 886#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */
876 887
877 clearerr (stdin); 888 clearerr_unlocked (stdin);
878 889
879 emacs_backtrace (-1); 890 emacs_backtrace (-1);
880 891
@@ -972,7 +983,7 @@ main (int argc, char **argv)
972 int i; 983 int i;
973 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); 984 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
974 for (i = 0; i < ARRAYELTS (usage_message); i++) 985 for (i = 0; i < ARRAYELTS (usage_message); i++)
975 fputs (usage_message[i], stdout); 986 fputs_unlocked (usage_message[i], stdout);
976 exit (0); 987 exit (0);
977 } 988 }
978 989
@@ -988,15 +999,15 @@ main (int argc, char **argv)
988 999
989 int sockfd = -1; 1000 int sockfd = -1;
990 1001
991 if (argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, NULL, &skip_args) 1002 if (argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, NULL, &skip_args)
992 || argmatch (argv, argc, "-new-daemon", "--new-daemon", 10, &dname_arg, &skip_args)) 1003 || argmatch (argv, argc, "-fg-daemon", "--fg-daemon", 10, &dname_arg, &skip_args))
993 { 1004 {
994 daemon_type = 1; /* foreground */ 1005 daemon_type = 1; /* foreground */
995 } 1006 }
996 else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args) 1007 else if (argmatch (argv, argc, "-daemon", "--daemon", 5, NULL, &skip_args)
997 || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args) 1008 || argmatch (argv, argc, "-daemon", "--daemon", 5, &dname_arg, &skip_args)
998 || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, NULL, &skip_args) 1009 || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, NULL, &skip_args)
999 || argmatch (argv, argc, "-old-daemon", "--old-daemon", 10, &dname_arg, &skip_args)) 1010 || argmatch (argv, argc, "-bg-daemon", "--bg-daemon", 10, &dname_arg, &skip_args))
1000 { 1011 {
1001 daemon_type = 2; /* background */ 1012 daemon_type = 2; /* background */
1002 } 1013 }
@@ -1111,7 +1122,7 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1111 char fdStr[80]; 1122 char fdStr[80];
1112 int fdStrlen = 1123 int fdStrlen =
1113 snprintf (fdStr, sizeof fdStr, 1124 snprintf (fdStr, sizeof fdStr,
1114 "--old-daemon=\n%d,%d\n%s", daemon_pipe[0], 1125 "--bg-daemon=\n%d,%d\n%s", daemon_pipe[0],
1115 daemon_pipe[1], dname_arg ? dname_arg : ""); 1126 daemon_pipe[1], dname_arg ? dname_arg : "");
1116 1127
1117 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr)) 1128 if (! (0 <= fdStrlen && fdStrlen < sizeof fdStr))
@@ -1257,6 +1268,18 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
1257 build_details = ! argmatch (argv, argc, "-no-build-details", 1268 build_details = ! argmatch (argv, argc, "-no-build-details",
1258 "--no-build-details", 7, NULL, &skip_args); 1269 "--no-build-details", 7, NULL, &skip_args);
1259 1270
1271#ifdef HAVE_MODULES
1272 bool module_assertions
1273 = argmatch (argv, argc, "-module-assertions", "--module-assertions", 15,
1274 NULL, &skip_args);
1275 if (dumping && module_assertions)
1276 {
1277 fputs ("Module assertions are not supported during dumping\n", stderr);
1278 exit (1);
1279 }
1280 init_module_assertions (module_assertions);
1281#endif
1282
1260#ifdef HAVE_NS 1283#ifdef HAVE_NS
1261 ns_pool = ns_alloc_autorelease_pool (); 1284 ns_pool = ns_alloc_autorelease_pool ();
1262#ifdef NS_IMPL_GNUSTEP 1285#ifdef NS_IMPL_GNUSTEP
@@ -1708,12 +1731,15 @@ static const struct standard_args standard_args[] =
1708 { "-batch", "--batch", 100, 0 }, 1731 { "-batch", "--batch", 100, 0 },
1709 { "-script", "--script", 100, 1 }, 1732 { "-script", "--script", 100, 1 },
1710 { "-daemon", "--daemon", 99, 0 }, 1733 { "-daemon", "--daemon", 99, 0 },
1711 { "-old-daemon", "--old-daemon", 99, 0 }, 1734 { "-bg-daemon", "--bg-daemon", 99, 0 },
1712 { "-new-daemon", "--new-daemon", 99, 0 }, 1735 { "-fg-daemon", "--fg-daemon", 99, 0 },
1713 { "-help", "--help", 90, 0 }, 1736 { "-help", "--help", 90, 0 },
1714 { "-nl", "--no-loadup", 70, 0 }, 1737 { "-nl", "--no-loadup", 70, 0 },
1715 { "-nsl", "--no-site-lisp", 65, 0 }, 1738 { "-nsl", "--no-site-lisp", 65, 0 },
1716 { "-no-build-details", "--no-build-details", 63, 0 }, 1739 { "-no-build-details", "--no-build-details", 63, 0 },
1740#ifdef HAVE_MODULES
1741 { "-module-assertions", "--module-assertions", 62, 0 },
1742#endif
1717 /* -d must come last before the options handled in startup.el. */ 1743 /* -d must come last before the options handled in startup.el. */
1718 { "-d", "--display", 60, 1 }, 1744 { "-d", "--display", 60, 1 },
1719 { "-display", 0, 60, 1 }, 1745 { "-display", 0, 60, 1 },
@@ -2171,7 +2197,7 @@ You must run Emacs in batch mode in order to dump it. */)
2171 } 2197 }
2172#endif 2198#endif
2173 2199
2174 fflush (stdout); 2200 fflush_unlocked (stdout);
2175 /* Tell malloc where start of impure now is. */ 2201 /* Tell malloc where start of impure now is. */
2176 /* Also arrange for warnings when nearly out of space. */ 2202 /* Also arrange for warnings when nearly out of space. */
2177#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC 2203#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
diff --git a/src/eval.c b/src/eval.c
index 16d1cf810ea..8f293c9d300 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1225,18 +1225,17 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS) */)
1225 rather than passed in a list. Used by Fbyte_code. */ 1225 rather than passed in a list. Used by Fbyte_code. */
1226 1226
1227Lisp_Object 1227Lisp_Object
1228internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, 1228internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
1229 Lisp_Object handlers) 1229 Lisp_Object handlers)
1230{ 1230{
1231 Lisp_Object val;
1232 struct handler *oldhandlerlist = handlerlist; 1231 struct handler *oldhandlerlist = handlerlist;
1233 int clausenb = 0; 1232 ptrdiff_t clausenb = 0;
1234 1233
1235 CHECK_SYMBOL (var); 1234 CHECK_SYMBOL (var);
1236 1235
1237 for (val = handlers; CONSP (val); val = XCDR (val)) 1236 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
1238 { 1237 {
1239 Lisp_Object tem = XCAR (val); 1238 Lisp_Object tem = XCAR (tail);
1240 clausenb++; 1239 clausenb++;
1241 if (! (NILP (tem) 1240 if (! (NILP (tem)
1242 || (CONSP (tem) 1241 || (CONSP (tem)
@@ -1246,55 +1245,58 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
1246 SDATA (Fprin1_to_string (tem, Qt))); 1245 SDATA (Fprin1_to_string (tem, Qt)));
1247 } 1246 }
1248 1247
1249 { /* The first clause is the one that should be checked first, so it should 1248 /* The first clause is the one that should be checked first, so it
1250 be added to handlerlist last. So we build in `clauses' a table that 1249 should be added to handlerlist last. So build in CLAUSES a table
1251 contains `handlers' but in reverse order. SAFE_ALLOCA won't work 1250 that contains HANDLERS but in reverse order. CLAUSES is pointer
1252 here due to the setjmp, so impose a MAX_ALLOCA limit. */ 1251 to volatile to avoid issues with setjmp and local storage.
1253 if (MAX_ALLOCA / word_size < clausenb) 1252 SAFE_ALLOCA won't work here due to the setjmp, so impose a
1254 memory_full (SIZE_MAX); 1253 MAX_ALLOCA limit. */
1255 Lisp_Object *clauses = alloca (clausenb * sizeof *clauses); 1254 if (MAX_ALLOCA / word_size < clausenb)
1256 Lisp_Object *volatile clauses_volatile = clauses; 1255 memory_full (SIZE_MAX);
1257 int i = clausenb; 1256 Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses);
1258 for (val = handlers; CONSP (val); val = XCDR (val)) 1257 clauses += clausenb;
1259 clauses[--i] = XCAR (val); 1258 for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
1260 for (i = 0; i < clausenb; i++) 1259 *--clauses = XCAR (tail);
1261 { 1260 for (ptrdiff_t i = 0; i < clausenb; i++)
1262 Lisp_Object clause = clauses[i]; 1261 {
1263 Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil; 1262 Lisp_Object clause = clauses[i];
1264 if (!CONSP (condition)) 1263 Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil;
1265 condition = Fcons (condition, Qnil); 1264 if (!CONSP (condition))
1266 struct handler *c = push_handler (condition, CONDITION_CASE); 1265 condition = list1 (condition);
1267 if (sys_setjmp (c->jmp)) 1266 struct handler *c = push_handler (condition, CONDITION_CASE);
1268 { 1267 if (sys_setjmp (c->jmp))
1269 ptrdiff_t count = SPECPDL_INDEX (); 1268 {
1270 Lisp_Object val = handlerlist->val; 1269 Lisp_Object val = handlerlist->val;
1271 Lisp_Object *chosen_clause = clauses_volatile; 1270 Lisp_Object volatile *chosen_clause = clauses;
1272 for (c = handlerlist->next; c != oldhandlerlist; c = c->next) 1271 for (struct handler *h = handlerlist->next; h != oldhandlerlist;
1273 chosen_clause++; 1272 h = h->next)
1274 handlerlist = oldhandlerlist; 1273 chosen_clause++;
1275 if (!NILP (var)) 1274 Lisp_Object handler_body = XCDR (*chosen_clause);
1276 { 1275 handlerlist = oldhandlerlist;
1277 if (!NILP (Vinternal_interpreter_environment)) 1276
1278 specbind (Qinternal_interpreter_environment, 1277 if (NILP (var))
1279 Fcons (Fcons (var, val), 1278 return Fprogn (handler_body);
1280 Vinternal_interpreter_environment)); 1279
1281 else 1280 Lisp_Object handler_var = var;
1282 specbind (var, val); 1281 if (!NILP (Vinternal_interpreter_environment))
1283 } 1282 {
1284 val = Fprogn (XCDR (*chosen_clause)); 1283 val = Fcons (Fcons (var, val),
1285 /* Note that this just undoes the binding of var; whoever 1284 Vinternal_interpreter_environment);
1286 longjumped to us unwound the stack to c.pdlcount before 1285 handler_var = Qinternal_interpreter_environment;
1287 throwing. */ 1286 }
1288 if (!NILP (var))
1289 unbind_to (count, Qnil);
1290 return val;
1291 }
1292 }
1293 }
1294 1287
1295 val = eval_sub (bodyform); 1288 /* Bind HANDLER_VAR to VAL while evaluating HANDLER_BODY.
1289 The unbind_to undoes just this binding; whoever longjumped
1290 to us unwound the stack to C->pdlcount before throwing. */
1291 ptrdiff_t count = SPECPDL_INDEX ();
1292 specbind (handler_var, val);
1293 return unbind_to (count, Fprogn (handler_body));
1294 }
1295 }
1296
1297 Lisp_Object result = eval_sub (bodyform);
1296 handlerlist = oldhandlerlist; 1298 handlerlist = oldhandlerlist;
1297 return val; 1299 return result;
1298} 1300}
1299 1301
1300/* Call the function BFUN with no arguments, catching errors within it 1302/* Call the function BFUN with no arguments, catching errors within it
@@ -1472,7 +1474,10 @@ process_quit_flag (void)
1472 If quit-flag is set to `kill-emacs' the SIGINT handler has received 1474 If quit-flag is set to `kill-emacs' the SIGINT handler has received
1473 a request to exit Emacs when it is safe to do. 1475 a request to exit Emacs when it is safe to do.
1474 1476
1475 When not quitting, process any pending signals. */ 1477 When not quitting, process any pending signals.
1478
1479 If you change this function, also adapt module_should_quit in
1480 emacs-module.c. */
1476 1481
1477void 1482void
1478maybe_quit (void) 1483maybe_quit (void)
@@ -1881,8 +1886,7 @@ then strings and vectors are not accepted. */)
1881 have an element whose index is COMPILED_INTERACTIVE, which is 1886 have an element whose index is COMPILED_INTERACTIVE, which is
1882 where the interactive spec is stored. */ 1887 where the interactive spec is stored. */
1883 else if (COMPILEDP (fun)) 1888 else if (COMPILEDP (fun))
1884 return ((ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK) > COMPILED_INTERACTIVE 1889 return (PVSIZE (fun) > COMPILED_INTERACTIVE ? Qt : if_prop);
1885 ? Qt : if_prop);
1886 1890
1887 /* Strings and vectors are keyboard macros. */ 1891 /* Strings and vectors are keyboard macros. */
1888 if (STRINGP (fun) || VECTORP (fun)) 1892 if (STRINGP (fun) || VECTORP (fun))
@@ -2260,7 +2264,7 @@ eval_sub (Lisp_Object form)
2260 } 2264 }
2261 } 2265 }
2262 } 2266 }
2263 else if (COMPILEDP (fun)) 2267 else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun))
2264 return apply_lambda (fun, original_args, count); 2268 return apply_lambda (fun, original_args, count);
2265 else 2269 else
2266 { 2270 {
@@ -2686,7 +2690,7 @@ FUNCTIONP (Lisp_Object object)
2686 2690
2687 if (SUBRP (object)) 2691 if (SUBRP (object))
2688 return XSUBR (object)->max_args != UNEVALLED; 2692 return XSUBR (object)->max_args != UNEVALLED;
2689 else if (COMPILEDP (object)) 2693 else if (COMPILEDP (object) || MODULE_FUNCTIONP (object))
2690 return true; 2694 return true;
2691 else if (CONSP (object)) 2695 else if (CONSP (object))
2692 { 2696 {
@@ -2741,7 +2745,7 @@ usage: (funcall FUNCTION &rest ARGUMENTS) */)
2741 2745
2742 if (SUBRP (fun)) 2746 if (SUBRP (fun))
2743 val = funcall_subr (XSUBR (fun), numargs, args + 1); 2747 val = funcall_subr (XSUBR (fun), numargs, args + 1);
2744 else if (COMPILEDP (fun)) 2748 else if (COMPILEDP (fun) || MODULE_FUNCTIONP (fun))
2745 val = funcall_lambda (fun, numargs, args + 1); 2749 val = funcall_lambda (fun, numargs, args + 1);
2746 else 2750 else
2747 { 2751 {
@@ -2891,7 +2895,8 @@ apply_lambda (Lisp_Object fun, Lisp_Object args, ptrdiff_t count)
2891 2895
2892/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR 2896/* Apply a Lisp function FUN to the NARGS evaluated arguments in ARG_VECTOR
2893 and return the result of evaluation. 2897 and return the result of evaluation.
2894 FUN must be either a lambda-expression or a compiled-code object. */ 2898 FUN must be either a lambda-expression, a compiled-code object,
2899 or a module function. */
2895 2900
2896static Lisp_Object 2901static Lisp_Object
2897funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, 2902funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
@@ -2922,7 +2927,7 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2922 } 2927 }
2923 else if (COMPILEDP (fun)) 2928 else if (COMPILEDP (fun))
2924 { 2929 {
2925 ptrdiff_t size = ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK; 2930 ptrdiff_t size = PVSIZE (fun);
2926 if (size <= COMPILED_STACK_DEPTH) 2931 if (size <= COMPILED_STACK_DEPTH)
2927 xsignal1 (Qinvalid_function, fun); 2932 xsignal1 (Qinvalid_function, fun);
2928 syms_left = AREF (fun, COMPILED_ARGLIST); 2933 syms_left = AREF (fun, COMPILED_ARGLIST);
@@ -2948,6 +2953,10 @@ funcall_lambda (Lisp_Object fun, ptrdiff_t nargs,
2948 } 2953 }
2949 lexenv = Qnil; 2954 lexenv = Qnil;
2950 } 2955 }
2956#ifdef HAVE_MODULES
2957 else if (MODULE_FUNCTIONP (fun))
2958 return funcall_module (fun, nargs, arg_vector);
2959#endif
2951 else 2960 else
2952 emacs_abort (); 2961 emacs_abort ();
2953 2962
@@ -3059,6 +3068,10 @@ function with `&rest' args, or `unevalled' for a special form. */)
3059 result = Fsubr_arity (function); 3068 result = Fsubr_arity (function);
3060 else if (COMPILEDP (function)) 3069 else if (COMPILEDP (function))
3061 result = lambda_arity (function); 3070 result = lambda_arity (function);
3071#ifdef HAVE_MODULES
3072 else if (MODULE_FUNCTIONP (function))
3073 result = module_function_arity (XMODULE_FUNCTION (function));
3074#endif
3062 else 3075 else
3063 { 3076 {
3064 if (NILP (function)) 3077 if (NILP (function))
@@ -3103,7 +3116,7 @@ lambda_arity (Lisp_Object fun)
3103 } 3116 }
3104 else if (COMPILEDP (fun)) 3117 else if (COMPILEDP (fun))
3105 { 3118 {
3106 ptrdiff_t size = ASIZE (fun) & PSEUDOVECTOR_SIZE_MASK; 3119 ptrdiff_t size = PVSIZE (fun);
3107 if (size <= COMPILED_STACK_DEPTH) 3120 if (size <= COMPILED_STACK_DEPTH)
3108 xsignal1 (Qinvalid_function, fun); 3121 xsignal1 (Qinvalid_function, fun);
3109 syms_left = AREF (fun, COMPILED_ARGLIST); 3122 syms_left = AREF (fun, COMPILED_ARGLIST);
@@ -3148,7 +3161,7 @@ DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
3148 3161
3149 if (COMPILEDP (object)) 3162 if (COMPILEDP (object))
3150 { 3163 {
3151 ptrdiff_t size = ASIZE (object) & PSEUDOVECTOR_SIZE_MASK; 3164 ptrdiff_t size = PVSIZE (object);
3152 if (size <= COMPILED_STACK_DEPTH) 3165 if (size <= COMPILED_STACK_DEPTH)
3153 xsignal1 (Qinvalid_function, object); 3166 xsignal1 (Qinvalid_function, object);
3154 if (CONSP (AREF (object, COMPILED_BYTECODE))) 3167 if (CONSP (AREF (object, COMPILED_BYTECODE)))
@@ -3211,7 +3224,7 @@ do_specbind (struct Lisp_Symbol *sym, union specbinding *bind,
3211 set_default_internal (specpdl_symbol (bind), value, bindflag); 3224 set_default_internal (specpdl_symbol (bind), value, bindflag);
3212 return; 3225 return;
3213 } 3226 }
3214 /* FALLTHROUGH */ 3227 FALLTHROUGH;
3215 case SYMBOL_LOCALIZED: 3228 case SYMBOL_LOCALIZED:
3216 set_internal (specpdl_symbol (bind), value, Qnil, bindflag); 3229 set_internal (specpdl_symbol (bind), value, Qnil, bindflag);
3217 break; 3230 break;
@@ -3389,12 +3402,10 @@ do_one_unbind (union specbinding *this_binding, bool unwinding,
3389 Qnil, bindflag); 3402 Qnil, bindflag);
3390 break; 3403 break;
3391 } 3404 }
3392 else
3393 { /* FALLTHROUGH!!
3394 NOTE: we only ever come here if make_local_foo was used for
3395 the first time on this var within this let. */
3396 }
3397 } 3405 }
3406 /* Come here only if make_local_foo was used for the first time
3407 on this var within this let. */
3408 FALLTHROUGH;
3398 case SPECPDL_LET_DEFAULT: 3409 case SPECPDL_LET_DEFAULT:
3399 set_default_internal (specpdl_symbol (this_binding), 3410 set_default_internal (specpdl_symbol (this_binding),
3400 specpdl_old_value (this_binding), 3411 specpdl_old_value (this_binding),
@@ -3602,8 +3613,12 @@ returns nil. */)
3602 3613
3603 while (backtrace_p (pdl)) 3614 while (backtrace_p (pdl))
3604 { 3615 {
3616 ptrdiff_t i = pdl - specpdl;
3605 backtrace_frame_apply (function, pdl); 3617 backtrace_frame_apply (function, pdl);
3606 pdl = backtrace_next (pdl); 3618 /* Beware! PDL is no longer valid here because FUNCTION might
3619 have caused grow_specpdl to reallocate pdlvec. We must use
3620 the saved index, cf. Bug#27258. */
3621 pdl = backtrace_next (&specpdl[i]);
3607 } 3622 }
3608 3623
3609 return Qnil; 3624 return Qnil;
@@ -3675,12 +3690,10 @@ backtrace_eval_unrewind (int distance)
3675 SET_SYMBOL_VAL (XSYMBOL (sym), old_value); 3690 SET_SYMBOL_VAL (XSYMBOL (sym), old_value);
3676 break; 3691 break;
3677 } 3692 }
3678 else
3679 { /* FALLTHROUGH!!
3680 NOTE: we only ever come here if make_local_foo was used for
3681 the first time on this var within this let. */
3682 }
3683 } 3693 }
3694 /* Come here only if make_local_foo was used for the first
3695 time on this var within this let. */
3696 FALLTHROUGH;
3684 case SPECPDL_LET_DEFAULT: 3697 case SPECPDL_LET_DEFAULT:
3685 { 3698 {
3686 Lisp_Object sym = specpdl_symbol (tmp); 3699 Lisp_Object sym = specpdl_symbol (tmp);
@@ -3836,7 +3849,7 @@ mark_specpdl (union specbinding *first, union specbinding *ptr)
3836 case SPECPDL_LET_DEFAULT: 3849 case SPECPDL_LET_DEFAULT:
3837 case SPECPDL_LET_LOCAL: 3850 case SPECPDL_LET_LOCAL:
3838 mark_object (specpdl_where (pdl)); 3851 mark_object (specpdl_where (pdl));
3839 /* Fall through. */ 3852 FALLTHROUGH;
3840 case SPECPDL_LET: 3853 case SPECPDL_LET:
3841 mark_object (specpdl_symbol (pdl)); 3854 mark_object (specpdl_symbol (pdl));
3842 mark_object (specpdl_old_value (pdl)); 3855 mark_object (specpdl_old_value (pdl));
diff --git a/src/fileio.c b/src/fileio.c
index acbf76e0d81..a57d50b24e0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -2256,61 +2256,21 @@ static bool
2256file_name_case_insensitive_p (const char *filename) 2256file_name_case_insensitive_p (const char *filename)
2257{ 2257{
2258 /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if 2258 /* Use pathconf with _PC_CASE_INSENSITIVE or _PC_CASE_SENSITIVE if
2259 those flags are available. As of this writing (2016-11-14), 2259 those flags are available. As of this writing (2017-05-20),
2260 Cygwin is the only platform known to support the former (starting 2260 Cygwin is the only platform known to support the former (starting
2261 with Cygwin-2.6.1), and Mac OS X is the only platform known to 2261 with Cygwin-2.6.1), and macOS is the only platform known to
2262 support the latter. 2262 support the latter. */
2263
2264 There have been reports that pathconf with _PC_CASE_SENSITIVE
2265 does not work reliably on Mac OS X. If you have a problem,
2266 please recompile Emacs with -D DARWIN_OS_CASE_SENSITIVE_FIXME=1 or
2267 -D DARWIN_OS_CASE_SENSITIVE_FIXME=2, and file a bug report saying
2268 whether this fixed your problem. */
2269 2263
2270#ifdef _PC_CASE_INSENSITIVE 2264#ifdef _PC_CASE_INSENSITIVE
2271 int res = pathconf (filename, _PC_CASE_INSENSITIVE); 2265 int res = pathconf (filename, _PC_CASE_INSENSITIVE);
2272 if (res >= 0) 2266 if (res >= 0)
2273 return res > 0; 2267 return res > 0;
2274#elif defined _PC_CASE_SENSITIVE && !defined DARWIN_OS_CASE_SENSITIVE_FIXME 2268#elif defined _PC_CASE_SENSITIVE
2275 int res = pathconf (filename, _PC_CASE_SENSITIVE); 2269 int res = pathconf (filename, _PC_CASE_SENSITIVE);
2276 if (res >= 0) 2270 if (res >= 0)
2277 return res == 0; 2271 return res == 0;
2278#endif 2272#endif
2279 2273
2280#ifdef DARWIN_OS
2281# ifndef DARWIN_OS_CASE_SENSITIVE_FIXME
2282 int DARWIN_OS_CASE_SENSITIVE_FIXME = 0;
2283# endif
2284
2285 if (DARWIN_OS_CASE_SENSITIVE_FIXME == 1)
2286 {
2287 /* This is based on developer.apple.com's getattrlist man page. */
2288 struct attrlist alist = {.volattr = ATTR_VOL_CAPABILITIES};
2289 vol_capabilities_attr_t vcaps;
2290 if (getattrlist (filename, &alist, &vcaps, sizeof vcaps, 0) == 0)
2291 {
2292 if (vcaps.valid[VOL_CAPABILITIES_FORMAT] & VOL_CAP_FMT_CASE_SENSITIVE)
2293 return ! (vcaps.capabilities[VOL_CAPABILITIES_FORMAT]
2294 & VOL_CAP_FMT_CASE_SENSITIVE);
2295 }
2296 }
2297 else if (DARWIN_OS_CASE_SENSITIVE_FIXME == 2)
2298 {
2299 /* The following is based on
2300 http://lists.apple.com/archives/darwin-dev/2007/Apr/msg00010.html. */
2301 struct attrlist alist;
2302 unsigned char buffer[sizeof (vol_capabilities_attr_t) + sizeof (size_t)];
2303
2304 memset (&alist, 0, sizeof (alist));
2305 alist.volattr = ATTR_VOL_CAPABILITIES;
2306 if (getattrlist (filename, &alist, buffer, sizeof (buffer), 0)
2307 || !(alist.volattr & ATTR_VOL_CAPABILITIES))
2308 return 0;
2309 vol_capabilities_attr_t *vcaps = buffer;
2310 return !(vcaps->capabilities[0] & VOL_CAP_FMT_CASE_SENSITIVE);
2311 }
2312#endif /* DARWIN_OS */
2313
2314#if defined CYGWIN || defined DOS_NT 2274#if defined CYGWIN || defined DOS_NT
2315 return true; 2275 return true;
2316#else 2276#else
@@ -3346,11 +3306,7 @@ otherwise, if FILE2 does not exist, the answer is t. */)
3346 ? Qt : Qnil); 3306 ? Qt : Qnil);
3347} 3307}
3348 3308
3349#ifndef READ_BUF_SIZE 3309enum { READ_BUF_SIZE = MAX_ALLOCA };
3350#define READ_BUF_SIZE (64 << 10)
3351#endif
3352/* Some buffer offsets are stored in 'int' variables. */
3353verify (READ_BUF_SIZE <= INT_MAX);
3354 3310
3355/* This function is called after Lisp functions to decide a coding 3311/* This function is called after Lisp functions to decide a coding
3356 system are called, or when they cause an error. Before they are 3312 system are called, or when they cause an error. Before they are
@@ -5687,14 +5643,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5687 { 5643 {
5688 block_input (); 5644 block_input ();
5689 if (!NILP (BVAR (b, filename))) 5645 if (!NILP (BVAR (b, filename)))
5690 { 5646 fwrite_unlocked (SDATA (BVAR (b, filename)), 1,
5691 fwrite (SDATA (BVAR (b, filename)), 1, 5647 SBYTES (BVAR (b, filename)), stream);
5692 SBYTES (BVAR (b, filename)), stream); 5648 putc_unlocked ('\n', stream);
5693 } 5649 fwrite_unlocked (SDATA (BVAR (b, auto_save_file_name)), 1,
5694 putc ('\n', stream); 5650 SBYTES (BVAR (b, auto_save_file_name)), stream);
5695 fwrite (SDATA (BVAR (b, auto_save_file_name)), 1, 5651 putc_unlocked ('\n', stream);
5696 SBYTES (BVAR (b, auto_save_file_name)), stream);
5697 putc ('\n', stream);
5698 unblock_input (); 5652 unblock_input ();
5699 } 5653 }
5700 5654
@@ -5885,7 +5839,7 @@ effect except for flushing STREAM's data. */)
5885 5839
5886 binmode = NILP (mode) ? O_TEXT : O_BINARY; 5840 binmode = NILP (mode) ? O_TEXT : O_BINARY;
5887 if (fp != stdin) 5841 if (fp != stdin)
5888 fflush (fp); 5842 fflush_unlocked (fp);
5889 5843
5890 return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; 5844 return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil;
5891} 5845}
diff --git a/src/filelock.c b/src/filelock.c
index 67e8dbd34ed..bfa1d63d833 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -569,7 +569,7 @@ current_lock_owner (lock_info_type *owner, char *lfname)
569 if (! (boot[0] == '\200' && boot[1] == '\242')) 569 if (! (boot[0] == '\200' && boot[1] == '\242'))
570 return -1; 570 return -1;
571 boot += 2; 571 boot += 2;
572 /* Fall through. */ 572 FALLTHROUGH;
573 case ':': 573 case ':':
574 if (! c_isdigit (boot[0])) 574 if (! c_isdigit (boot[0]))
575 return -1; 575 return -1;
diff --git a/src/fns.c b/src/fns.c
index de7fc1b47fc..6610d2a6d0e 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -106,8 +106,8 @@ To get the number of bytes, use `string-bytes'. */)
106 XSETFASTINT (val, MAX_CHAR); 106 XSETFASTINT (val, MAX_CHAR);
107 else if (BOOL_VECTOR_P (sequence)) 107 else if (BOOL_VECTOR_P (sequence))
108 XSETFASTINT (val, bool_vector_size (sequence)); 108 XSETFASTINT (val, bool_vector_size (sequence));
109 else if (COMPILEDP (sequence)) 109 else if (COMPILEDP (sequence) || RECORDP (sequence))
110 XSETFASTINT (val, ASIZE (sequence) & PSEUDOVECTOR_SIZE_MASK); 110 XSETFASTINT (val, PVSIZE (sequence));
111 else if (CONSP (sequence)) 111 else if (CONSP (sequence))
112 { 112 {
113 intptr_t i = 0; 113 intptr_t i = 0;
@@ -475,13 +475,18 @@ usage: (vconcat &rest SEQUENCES) */)
475 475
476 476
477DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0, 477DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0,
478 doc: /* Return a copy of a list, vector, string or char-table. 478 doc: /* Return a copy of a list, vector, string, char-table or record.
479The elements of a list or vector are not copied; they are shared 479The elements of a list, vector or record are not copied; they are
480with the original. */) 480shared with the original. */)
481 (Lisp_Object arg) 481 (Lisp_Object arg)
482{ 482{
483 if (NILP (arg)) return arg; 483 if (NILP (arg)) return arg;
484 484
485 if (RECORDP (arg))
486 {
487 return Frecord (PVSIZE (arg), XVECTOR (arg)->contents);
488 }
489
485 if (CHAR_TABLE_P (arg)) 490 if (CHAR_TABLE_P (arg))
486 { 491 {
487 return copy_char_table (arg); 492 return copy_char_table (arg);
@@ -2792,8 +2797,17 @@ suppressed. */)
2792 2797
2793 tem = Fmemq (feature, Vfeatures); 2798 tem = Fmemq (feature, Vfeatures);
2794 if (NILP (tem)) 2799 if (NILP (tem))
2795 error ("Required feature `%s' was not provided", 2800 {
2796 SDATA (SYMBOL_NAME (feature))); 2801 unsigned char *tem2 = SDATA (SYMBOL_NAME (feature));
2802 Lisp_Object tem3 = Fcar (Fcar (Vload_history));
2803
2804 if (NILP (tem3))
2805 error ("Required feature `%s' was not provided", tem2);
2806 else
2807 /* Cf autoload-do-load. */
2808 error ("Loading file %s failed to provide feature `%s'",
2809 SDATA (tem3), tem2);
2810 }
2797 2811
2798 /* Once loading finishes, don't undo it. */ 2812 /* Once loading finishes, don't undo it. */
2799 Vautoload_queue = Qt; 2813 Vautoload_queue = Qt;
@@ -4275,7 +4289,7 @@ sxhash_list (Lisp_Object list, int depth)
4275} 4289}
4276 4290
4277 4291
4278/* Return a hash for vector VECTOR. DEPTH is the current depth in 4292/* Return a hash for (pseudo)vector VECTOR. DEPTH is the current depth in
4279 the Lisp structure. */ 4293 the Lisp structure. */
4280 4294
4281static EMACS_UINT 4295static EMACS_UINT
@@ -4284,7 +4298,7 @@ sxhash_vector (Lisp_Object vec, int depth)
4284 EMACS_UINT hash = ASIZE (vec); 4298 EMACS_UINT hash = ASIZE (vec);
4285 int i, n; 4299 int i, n;
4286 4300
4287 n = min (SXHASH_MAX_LEN, ASIZE (vec)); 4301 n = min (SXHASH_MAX_LEN, hash & PSEUDOVECTOR_FLAG ? PVSIZE (vec) : hash);
4288 for (i = 0; i < n; ++i) 4302 for (i = 0; i < n; ++i)
4289 { 4303 {
4290 EMACS_UINT hash2 = sxhash (AREF (vec, i), depth + 1); 4304 EMACS_UINT hash2 = sxhash (AREF (vec, i), depth + 1);
@@ -4339,11 +4353,11 @@ sxhash (Lisp_Object obj, int depth)
4339 4353
4340 /* This can be everything from a vector to an overlay. */ 4354 /* This can be everything from a vector to an overlay. */
4341 case Lisp_Vectorlike: 4355 case Lisp_Vectorlike:
4342 if (VECTORP (obj)) 4356 if (VECTORP (obj) || RECORDP (obj))
4343 /* According to the CL HyperSpec, two arrays are equal only if 4357 /* According to the CL HyperSpec, two arrays are equal only if
4344 they are `eq', except for strings and bit-vectors. In 4358 they are `eq', except for strings and bit-vectors. In
4345 Emacs, this works differently. We have to compare element 4359 Emacs, this works differently. We have to compare element
4346 by element. */ 4360 by element. Same for records. */
4347 hash = sxhash_vector (obj, depth); 4361 hash = sxhash_vector (obj, depth);
4348 else if (BOOL_VECTOR_P (obj)) 4362 else if (BOOL_VECTOR_P (obj))
4349 hash = sxhash_bool_vector (obj); 4363 hash = sxhash_bool_vector (obj);
diff --git a/src/font.c b/src/font.c
index a929509752c..5a3f271ef85 100644
--- a/src/font.c
+++ b/src/font.c
@@ -306,18 +306,20 @@ font_pixel_size (struct frame *f, Lisp_Object spec)
306 return XINT (size); 306 return XINT (size);
307 if (NILP (size)) 307 if (NILP (size))
308 return 0; 308 return 0;
309 eassert (FLOATP (size)); 309 if (FRAME_WINDOW_P (f))
310 point_size = XFLOAT_DATA (size); 310 {
311 val = AREF (spec, FONT_DPI_INDEX); 311 eassert (FLOATP (size));
312 if (INTEGERP (val)) 312 point_size = XFLOAT_DATA (size);
313 dpi = XINT (val); 313 val = AREF (spec, FONT_DPI_INDEX);
314 else 314 if (INTEGERP (val))
315 dpi = FRAME_RES_Y (f); 315 dpi = XINT (val);
316 pixel_size = POINT_TO_PIXEL (point_size, dpi); 316 else
317 return pixel_size; 317 dpi = FRAME_RES_Y (f);
318#else 318 pixel_size = POINT_TO_PIXEL (point_size, dpi);
319 return 1; 319 return pixel_size;
320 }
320#endif 321#endif
322 return 1;
321} 323}
322 324
323 325
@@ -2777,21 +2779,27 @@ font_list_entities (struct frame *f, Lisp_Object spec)
2777 val = XCDR (val); 2779 val = XCDR (val);
2778 else 2780 else
2779 { 2781 {
2780 val = driver_list->driver->list (f, scratch_font_spec); 2782 Lisp_Object copy;
2781 if (!NILP (val))
2782 {
2783 Lisp_Object copy = copy_font_spec (scratch_font_spec);
2784 2783
2785 val = Fvconcat (1, &val); 2784 val = driver_list->driver->list (f, scratch_font_spec);
2786 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); 2785 /* We put zero_vector in the font-cache to indicate that
2787 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); 2786 no fonts matching SPEC were found on the system.
2788 } 2787 Failure to have this indication in the font cache can
2788 cause severe performance degradation in some rare
2789 cases, see bug#21028. */
2790 if (NILP (val))
2791 val = zero_vector;
2792 else
2793 val = Fvconcat (1, &val);
2794 copy = copy_font_spec (scratch_font_spec);
2795 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type);
2796 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache)));
2789 } 2797 }
2790 if (VECTORP (val) && ASIZE (val) > 0 2798 if (ASIZE (val) > 0
2791 && (need_filtering 2799 && (need_filtering
2792 || ! NILP (Vface_ignored_fonts))) 2800 || ! NILP (Vface_ignored_fonts)))
2793 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size); 2801 val = font_delete_unmatched (val, need_filtering ? spec : Qnil, size);
2794 if (VECTORP (val) && ASIZE (val) > 0) 2802 if (ASIZE (val) > 0)
2795 list = Fcons (val, list); 2803 list = Fcons (val, list);
2796 } 2804 }
2797 2805
diff --git a/src/font.h b/src/font.h
index a469b20e4f4..53e3fc21a3d 100644
--- a/src/font.h
+++ b/src/font.h
@@ -424,7 +424,7 @@ FONTP (Lisp_Object x)
424INLINE bool 424INLINE bool
425FONT_SPEC_P (Lisp_Object x) 425FONT_SPEC_P (Lisp_Object x)
426{ 426{
427 return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_SPEC_MAX; 427 return FONTP (x) && PVSIZE (x) == FONT_SPEC_MAX;
428} 428}
429 429
430/* Like FONT_SPEC_P, but can be used in the garbage collector. */ 430/* Like FONT_SPEC_P, but can be used in the garbage collector. */
@@ -438,7 +438,7 @@ GC_FONT_SPEC_P (Lisp_Object x)
438INLINE bool 438INLINE bool
439FONT_ENTITY_P (Lisp_Object x) 439FONT_ENTITY_P (Lisp_Object x)
440{ 440{
441 return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_ENTITY_MAX; 441 return FONTP (x) && PVSIZE (x) == FONT_ENTITY_MAX;
442} 442}
443 443
444/* Like FONT_ENTITY_P, but can be used in the garbage collector. */ 444/* Like FONT_ENTITY_P, but can be used in the garbage collector. */
@@ -452,7 +452,7 @@ GC_FONT_ENTITY_P (Lisp_Object x)
452INLINE bool 452INLINE bool
453FONT_OBJECT_P (Lisp_Object x) 453FONT_OBJECT_P (Lisp_Object x)
454{ 454{
455 return FONTP (x) && (ASIZE (x) & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX; 455 return FONTP (x) && PVSIZE (x) == FONT_OBJECT_MAX;
456} 456}
457 457
458/* Like FONT_OBJECT_P, but can be used in the garbage collector. */ 458/* Like FONT_OBJECT_P, but can be used in the garbage collector. */
diff --git a/src/frame.c b/src/frame.c
index 162b2038fd8..1e5e4bbdb48 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -324,55 +324,222 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
324 return make_number (0); 324 return make_number (0);
325} 325}
326 326
327/**
328 * frame_windows_min_size:
329 *
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum inner height
332 * (width) of FRAME in pixels.
333 *
334 * This value is calculated by the function `frame-windows-min-size' in
335 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
336 * non-nil) parameter of FRAME is non-nil thus explicitly specifying the
337 * value to be returned. In that latter case IGNORE is ignored.
338 *
339 * If `frame-windows-min-size' is called, it will make sure that the
340 * return value accommodates all windows of FRAME respecting the values
341 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil).
342 * With IGNORE non-nil the values of these variables are ignored.
343 *
344 * In either case, never return a value less than 1.
345 */
327static int 346static int
328frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, 347frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
329 Lisp_Object ignore, Lisp_Object pixelwise) 348 Lisp_Object ignore, Lisp_Object pixelwise)
330{ 349{
331 return XINT (call4 (Qframe_windows_min_size, frame, horizontal, 350 struct frame *f = XFRAME (frame);
351 Lisp_Object par_size;
352
353 if ((!NILP (horizontal)
354 && NUMBERP (par_size = get_frame_param (f, Qmin_width)))
355 || (NILP (horizontal)
356 && NUMBERP (par_size = get_frame_param (f, Qmin_height))))
357 {
358 int min_size = XINT (par_size);
359
360 /* Don't allow phantom frames. */
361 if (min_size < 1)
362 min_size = 1;
363
364 return (NILP (pixelwise)
365 ? min_size
366 : min_size * (NILP (horizontal)
367 ? FRAME_LINE_HEIGHT (f)
368 : FRAME_COLUMN_WIDTH (f)));
369 }
370 else
371 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
332 ignore, pixelwise)); 372 ignore, pixelwise));
333} 373}
334 374
335 375
336/* Make sure windows sizes of frame F are OK. new_width and new_height 376#ifdef HAVE_WINDOW_SYSTEM
337 are in pixels. A value of -1 means no change is requested for that 377/**
338 size (but the frame may still have to be resized to accommodate 378 * keep_ratio:
339 windows with their minimum sizes). This can either issue a request 379 *
340 to resize the frame externally (via x_set_window_size), to resize the 380 * Preserve ratios of frame F which usually happens after its parent
341 frame internally (via resize_frame_windows) or do nothing at all. 381 * frame P got resized. OLD_WIDTH, OLD_HEIGHT specifies the old native
382 * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
383 *
384 * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
385 * it is a cons, its car is not 'height-only'. Adjust F's height if F's
386 * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
387 * is not 'width-only'.
388 *
389 * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
390 * and, if its is a cons, its cdr is non-nil and not 'top-only'. Adjust
391 * F's top position if F's 'keep_ratio' parameter is non-nil and, if
392 * its is a cons, its cdr is non-nil and not 'left-only'.
393 *
394 * Note that when positional adjustment is requested but the size of F
395 * should remain unaltered in the corresponding direction, this routine
396 * tries to constrain F to its parent frame - something which usually
397 * happens when the parent frame shrinks. This means, however, that
398 * when the parent frame is re-enlarged later, the child's original
399 * position will not get restored to its pre-shrinking value.
400 *
401 * This routine is currently useful for child frames only. It might be
402 * eventually useful when moving non-child frames between monitors with
403 * different resolutions.
404 */
405static void
406keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
407 int new_width, int new_height)
408{
409 Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
342 410
343 The argument INHIBIT can assume the following values:
344 411
345 0 means to unconditionally call x_set_window_size even if sizes 412 if (!NILP (keep_ratio))
346 apparently do not change. Fx_create_frame uses this to pass the 413 {
347 initial size to the window manager. 414 double width_factor = (double)new_width / (double)old_width;
415 double height_factor = (double)new_height / (double)old_height;
416 int pixel_width, pixel_height, pos_x, pos_y;
348 417
349 1 means to call x_set_window_size if the outer frame size really 418 if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
350 changes. Fset_frame_size, Fset_frame_height, ... use this. 419 {
420 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qtop_only))
421 pos_x = f->left_pos;
422 else
423 {
424 pos_x = (int)(f->left_pos * width_factor + 0.5);
351 425
352 2 means to call x_set_window_size provided frame_inhibit_resize 426 if (CONSP (keep_ratio)
353 allows it. The menu and tool bar code use this ("3" won't work 427 && (NILP (Fcar (keep_ratio))
354 here in general because menu and tool bar are often not counted in 428 || EQ (Fcar (keep_ratio), Qheight_only))
355 the frame's text height). 429 && p->pixel_width - f->pixel_width < pos_x)
430 {
431 int p_f_width = p->pixel_width - f->pixel_width;
356 432
357 3 means call x_set_window_size if window minimum sizes must be 433 if (p_f_width <= 0)
358 preserved or frame_inhibit_resize allows it. x_set_left_fringe, 434 pos_x = 0;
359 x_set_scroll_bar_width, x_new_font ... use (or should use) this. 435 else
436 pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
437 }
360 438
361 4 means call x_set_window_size only if window minimum sizes must be 439 f->left_pos = pos_x;
362 preserved. x_set_right_divider_width, x_set_border_width and the 440 }
363 code responsible for wrapping the tool bar use this.
364 441
365 5 means to never call x_set_window_size. change_frame_size uses 442 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
366 this. 443 pos_y = f->top_pos;
444 else
445 {
446 pos_y = (int)(f->top_pos * height_factor + 0.5);
447
448 if (CONSP (keep_ratio)
449 && (NILP (Fcar (keep_ratio))
450 || EQ (Fcar (keep_ratio), Qwidth_only))
451 && p->pixel_height - f->pixel_height < pos_y)
452 /* When positional adjustment was requested and the
453 width of F should remain unaltered, try to constrain
454 F to its parent. This means that when the parent
455 frame is enlarged later the child's original position
456 won't get restored. */
457 {
458 int p_f_height = p->pixel_height - f->pixel_height;
459
460 if (p_f_height <= 0)
461 pos_y = 0;
462 else
463 pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
464 }
465
466 f->top_pos = pos_y;
467 }
468
469 x_set_offset (f, pos_x, pos_y, -1);
470 }
471
472 if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
473 {
474 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qheight_only))
475 pixel_width = -1;
476 else
477 {
478 pixel_width = (int)(f->pixel_width * width_factor + 0.5);
479 pixel_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, pixel_width);
480 }
481
482 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
483 pixel_height = -1;
484 else
485 {
486 pixel_height = (int)(f->pixel_height * height_factor + 0.5);
487 pixel_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, pixel_height);
488 }
489
490 adjust_frame_size (f, pixel_width, pixel_height, 1, 0,
491 Qkeep_ratio);
492 }
493 }
494}
495#endif
367 496
368 Note that even when x_set_window_size is not called, individual
369 windows may have to be resized (via `window--sanitize-window-sizes')
370 in order to support minimum size constraints.
371 497
372 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the 498/**
373 symbol of the parameter changed (like `menu-bar-lines', `font', ...). 499 * adjust_frame_size:
374 This is passed on to frame_inhibit_resize to let the latter decide on 500 *
375 a case-by-case basis whether the frame may be resized externally. */ 501 * Adjust size of frame F. NEW_WIDTH and NEW_HEIGHT specify the new
502 * text size of F in pixels. A value of -1 means no change is requested
503 * for that direction (but the frame may still have to be resized to
504 * accommodate windows with their minimum sizes). This can either issue
505 * a request to resize the frame externally (via x_set_window_size), to
506 * resize the frame internally (via resize_frame_windows) or do nothing
507 * at all.
508 *
509 * The argument INHIBIT can assume the following values:
510 *
511 * 0 means to unconditionally call x_set_window_size even if sizes
512 * apparently do not change. Fx_create_frame uses this to pass the
513 * initial size to the window manager.
514 *
515 * 1 means to call x_set_window_size if the native frame size really
516 * changes. Fset_frame_size, Fset_frame_height, ... use this.
517 *
518 * 2 means to call x_set_window_size provided frame_inhibit_resize
519 * allows it. The menu and tool bar code use this ("3" won't work
520 * here in general because menu and tool bar are often not counted in
521 * the frame's text height).
522 *
523 * 3 means call x_set_window_size if window minimum sizes must be
524 * preserved or frame_inhibit_resize allows it. x_set_left_fringe,
525 * x_set_scroll_bar_width, x_new_font ... use (or should use) this.
526 *
527 * 4 means call x_set_window_size only if window minimum sizes must be
528 * preserved. x_set_right_divider_width, x_set_border_width and the
529 * code responsible for wrapping the tool bar use this.
530 *
531 * 5 means to never call x_set_window_size. change_frame_size uses
532 * this.
533 *
534 * Note that even when x_set_window_size is not called, individual
535 * windows may have to be resized (via `window--sanitize-window-sizes')
536 * in order to support minimum size constraints.
537 *
538 * PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
539 * symbol of the parameter changed (like `menu-bar-lines', `font', ...).
540 * This is passed on to frame_inhibit_resize to let the latter decide on
541 * a case-by-case basis whether the frame may be resized externally.
542 */
376void 543void
377adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, 544adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
378 bool pretend, Lisp_Object parameter) 545 bool pretend, Lisp_Object parameter)
@@ -596,6 +763,18 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
596 || new_pixel_height != old_pixel_height); 763 || new_pixel_height != old_pixel_height);
597 764
598 unblock_input (); 765 unblock_input ();
766
767#ifdef HAVE_WINDOW_SYSTEM
768 {
769 /* Adjust size of F's child frames. */
770 Lisp_Object frames, frame1;
771
772 FOR_EACH_FRAME (frames, frame1)
773 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f)
774 keep_ratio (XFRAME (frame1), f, old_pixel_width, old_pixel_height,
775 new_pixel_width, new_pixel_height);
776 }
777#endif
599} 778}
600 779
601/* Allocate basically initialized frame. */ 780/* Allocate basically initialized frame. */
@@ -643,6 +822,15 @@ make_frame (bool mini_p)
643 f->vertical_scroll_bar_type = vertical_scroll_bar_none; 822 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
644 f->horizontal_scroll_bars = false; 823 f->horizontal_scroll_bars = false;
645 f->want_fullscreen = FULLSCREEN_NONE; 824 f->want_fullscreen = FULLSCREEN_NONE;
825 f->undecorated = false;
826 f->no_special_glyphs = false;
827#ifndef HAVE_NTGUI
828 f->override_redirect = false;
829#endif
830 f->skip_taskbar = false;
831 f->no_focus_on_map = false;
832 f->no_accept_focus = false;
833 f->z_group = z_group_none;
646#if ! defined (USE_GTK) && ! defined (HAVE_NS) 834#if ! defined (USE_GTK) && ! defined (HAVE_NS)
647 f->last_tool_bar_item = -1; 835 f->last_tool_bar_item = -1;
648#endif 836#endif
@@ -1107,7 +1295,7 @@ affects all frames on the same terminal device. */)
1107Lisp_Object 1295Lisp_Object
1108do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) 1296do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1109{ 1297{
1110 struct frame *sf = SELECTED_FRAME (); 1298 struct frame *sf = SELECTED_FRAME (), *f;
1111 1299
1112 /* If FRAME is a switch-frame event, extract the frame we should 1300 /* If FRAME is a switch-frame event, extract the frame we should
1113 switch to. */ 1301 switch to. */
@@ -1120,10 +1308,10 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1120 a switch-frame event to arrive after a frame is no longer live, 1308 a switch-frame event to arrive after a frame is no longer live,
1121 especially when deleting the initial frame during startup. */ 1309 especially when deleting the initial frame during startup. */
1122 CHECK_FRAME (frame); 1310 CHECK_FRAME (frame);
1123 if (! FRAME_LIVE_P (XFRAME (frame))) 1311 f = XFRAME (frame);
1312 if (!FRAME_LIVE_P (f))
1124 return Qnil; 1313 return Qnil;
1125 1314 else if (f == sf)
1126 if (sf == XFRAME (frame))
1127 return frame; 1315 return frame;
1128 1316
1129 /* If a frame's focus has been redirected toward the currently 1317 /* If a frame's focus has been redirected toward the currently
@@ -1156,11 +1344,11 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1156#else /* ! 0 */ 1344#else /* ! 0 */
1157 /* Instead, apply it only to the frame we're pointing to. */ 1345 /* Instead, apply it only to the frame we're pointing to. */
1158#ifdef HAVE_WINDOW_SYSTEM 1346#ifdef HAVE_WINDOW_SYSTEM
1159 if (track && FRAME_WINDOW_P (XFRAME (frame))) 1347 if (track && FRAME_WINDOW_P (f))
1160 { 1348 {
1161 Lisp_Object focus, xfocus; 1349 Lisp_Object focus, xfocus;
1162 1350
1163 xfocus = x_get_focus_frame (XFRAME (frame)); 1351 xfocus = x_get_focus_frame (f);
1164 if (FRAMEP (xfocus)) 1352 if (FRAMEP (xfocus))
1165 { 1353 {
1166 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus)); 1354 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
@@ -1168,8 +1356,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1168 /* Redirect frame focus also when FRAME has its minibuffer 1356 /* Redirect frame focus also when FRAME has its minibuffer
1169 window on the selected frame (see Bug#24500). */ 1357 window on the selected frame (see Bug#24500). */
1170 || (NILP (focus) 1358 || (NILP (focus)
1171 && EQ (FRAME_MINIBUF_WINDOW (XFRAME (frame)), 1359 && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))
1172 sf->selected_window)))
1173 Fredirect_frame_focus (xfocus, frame); 1360 Fredirect_frame_focus (xfocus, frame);
1174 } 1361 }
1175 } 1362 }
@@ -1179,9 +1366,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1179 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) 1366 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1180 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); 1367 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1181 1368
1182 if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame))) 1369 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
1183 { 1370 {
1184 struct frame *f = XFRAME (frame);
1185 struct tty_display_info *tty = FRAME_TTY (f); 1371 struct tty_display_info *tty = FRAME_TTY (f);
1186 Lisp_Object top_frame = tty->top_frame; 1372 Lisp_Object top_frame = tty->top_frame;
1187 1373
@@ -1209,7 +1395,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1209 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) 1395 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1210 last_nonminibuf_frame = XFRAME (selected_frame); 1396 last_nonminibuf_frame = XFRAME (selected_frame);
1211 1397
1212 Fselect_window (XFRAME (frame)->selected_window, norecord); 1398 Fselect_window (f->selected_window, norecord);
1213 1399
1214 /* We want to make sure that the next event generates a frame-switch 1400 /* We want to make sure that the next event generates a frame-switch
1215 event to the appropriate frame. This seems kludgy to me, but 1401 event to the appropriate frame. This seems kludgy to me, but
@@ -1217,7 +1403,10 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1217 (select-window (frame-root-window (new-frame))) doesn't end up 1403 (select-window (frame-root-window (new-frame))) doesn't end up
1218 with your typing being interpreted in the new frame instead of 1404 with your typing being interpreted in the new frame instead of
1219 the one you're actually typing in. */ 1405 the one you're actually typing in. */
1220 internal_last_event_frame = Qnil; 1406#ifdef HAVE_WINDOW_SYSTEM
1407 if (!frame_ancestor_p (f, sf))
1408#endif
1409 internal_last_event_frame = Qnil;
1221 1410
1222 return frame; 1411 return frame;
1223} 1412}
@@ -1253,12 +1442,15 @@ If EVENT is frame object, handle it as if it were a switch-frame event
1253to that frame. */) 1442to that frame. */)
1254 (Lisp_Object event) 1443 (Lisp_Object event)
1255{ 1444{
1445 Lisp_Object value;
1446
1256 /* Preserve prefix arg that the command loop just cleared. */ 1447 /* Preserve prefix arg that the command loop just cleared. */
1257 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); 1448 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1258 run_hook (Qmouse_leave_buffer_hook); 1449 run_hook (Qmouse_leave_buffer_hook);
1259 /* `switch-frame' implies a focus in. */ 1450 /* `switch-frame' implies a focus in. */
1451 value = do_switch_frame (event, 0, 0, Qnil);
1260 call1 (intern ("handle-focus-in"), event); 1452 call1 (intern ("handle-focus-in"), event);
1261 return do_switch_frame (event, 0, 0, Qnil); 1453 return value;
1262} 1454}
1263 1455
1264DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, 1456DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
@@ -1282,6 +1474,72 @@ DEFUN ("frame-list", Fframe_list, Sframe_list,
1282 return frames; 1474 return frames;
1283} 1475}
1284 1476
1477DEFUN ("frame-parent", Fframe_parent, Sframe_parent,
1478 0, 1, 0,
1479 doc: /* Return the parent frame of FRAME.
1480The parent frame of FRAME is the Emacs frame whose window-system window
1481is the parent window of FRAME's window-system window. When such a frame
1482exists, FRAME is considered a child frame of that frame.
1483
1484Return nil if FRAME has no parent frame. This means that FRAME's
1485window-system window is either a "top-level" window (a window whose
1486parent window is the window-system's root window) or an embedded window
1487\(a window whose parent window is owned by some other application). */)
1488 (Lisp_Object frame)
1489{
1490 struct frame *f = decode_live_frame (frame);
1491 struct frame *p = FRAME_PARENT_FRAME (f);
1492 Lisp_Object parent;
1493
1494 /* Can't return f->parent_frame directly since it might not be defined
1495 for this platform. */
1496 if (p)
1497 {
1498 XSETFRAME (parent, p);
1499
1500 return parent;
1501 }
1502 else
1503 return Qnil;
1504}
1505
1506#ifdef HAVE_WINDOW_SYSTEM
1507bool
1508frame_ancestor_p (struct frame *af, struct frame *df)
1509{
1510 struct frame *pf = FRAME_PARENT_FRAME (df);
1511
1512 while (pf)
1513 {
1514 if (pf == af)
1515 return true;
1516 else
1517 pf = FRAME_PARENT_FRAME (pf);
1518 }
1519
1520 return false;
1521}
1522#endif
1523
1524DEFUN ("frame-ancestor-p", Fframe_ancestor_p, Sframe_ancestor_p,
1525 2, 2, 0,
1526 doc: /* Return non-nil if ANCESTOR is an ancestor of DESCENDANT.
1527ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's
1528parent frame or it is an ancestor of DESCENDANT's parent frame. Both,
1529ANCESTOR and DESCENDANT must be live frames and default to the selected
1530frame. */)
1531 (Lisp_Object ancestor, Lisp_Object descendant)
1532{
1533#ifdef HAVE_WINDOW_SYSTEM
1534 struct frame *af = decode_live_frame (ancestor);
1535 struct frame *df = decode_live_frame (descendant);
1536
1537 return frame_ancestor_p (af, df) ? Qt : Qnil;
1538#else
1539 return Qnil;
1540#endif
1541 }
1542
1285/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the 1543/* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1286 same tty (for tty frames) or among frames which uses FRAME's keyboard. 1544 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1287 If MINIBUF is nil, do not consider minibuffer-only candidate. 1545 If MINIBUF is nil, do not consider minibuffer-only candidate.
@@ -1302,7 +1560,9 @@ candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1302 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f) 1560 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1303 && FRAME_TTY (c) == FRAME_TTY (f))) 1561 && FRAME_TTY (c) == FRAME_TTY (f)))
1304 { 1562 {
1305 if (NILP (minibuf)) 1563 if (!NILP (get_frame_param (c, Qno_other_frame)))
1564 return Qnil;
1565 else if (NILP (minibuf))
1306 { 1566 {
1307 if (!FRAME_MINIBUF_ONLY_P (c)) 1567 if (!FRAME_MINIBUF_ONLY_P (c))
1308 return candidate; 1568 return candidate;
@@ -1339,9 +1599,6 @@ next_frame (Lisp_Object frame, Lisp_Object minibuf)
1339 Lisp_Object f, tail; 1599 Lisp_Object f, tail;
1340 int passed = 0; 1600 int passed = 0;
1341 1601
1342 /* There must always be at least one frame in Vframe_list. */
1343 eassert (CONSP (Vframe_list));
1344
1345 while (passed < 2) 1602 while (passed < 2)
1346 FOR_EACH_FRAME (tail, f) 1603 FOR_EACH_FRAME (tail, f)
1347 { 1604 {
@@ -1364,9 +1621,6 @@ prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1364{ 1621{
1365 Lisp_Object f, tail, prev = Qnil; 1622 Lisp_Object f, tail, prev = Qnil;
1366 1623
1367 /* There must always be at least one frame in Vframe_list. */
1368 eassert (CONSP (Vframe_list));
1369
1370 FOR_EACH_FRAME (tail, f) 1624 FOR_EACH_FRAME (tail, f)
1371 { 1625 {
1372 if (EQ (frame, f) && !NILP (prev)) 1626 if (EQ (frame, f) && !NILP (prev))
@@ -1440,35 +1694,63 @@ DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1440 return frame; 1694 return frame;
1441} 1695}
1442 1696
1443/* Return 1 if it is ok to delete frame F; 1697/**
1444 0 if all frames aside from F are invisible. 1698 * other_frames:
1445 (Exception: if F is the terminal frame, and we are using X, return 1.) */ 1699 *
1446 1700 * Return true if there exists at least one visible or iconified frame
1447static int 1701 * but F. Return false otherwise.
1448other_visible_frames (struct frame *f) 1702 *
1703 * INVISIBLE true means we are called from make_frame_invisible where
1704 * such a frame must be visible or iconified. INVISIBLE nil means we
1705 * are called from delete_frame. In that case FORCE true means that the
1706 * visibility status of such a frame can be ignored.
1707 *
1708 * If F is the terminal frame and we are using X, return true if at
1709 * least one X frame exists.
1710 */
1711static bool
1712other_frames (struct frame *f, bool invisible, bool force)
1449{ 1713{
1450 Lisp_Object frames, this; 1714 Lisp_Object frames, frame, frame1;
1715 struct frame *f1;
1716 Lisp_Object minibuffer_window = FRAME_MINIBUF_WINDOW (f);
1451 1717
1452 FOR_EACH_FRAME (frames, this) 1718 XSETFRAME (frame, f);
1453 { 1719 if (WINDOWP (minibuffer_window)
1454 if (f == XFRAME (this)) 1720 && !EQ (frame, WINDOW_FRAME (XWINDOW (minibuffer_window))))
1455 continue; 1721 minibuffer_window = Qnil;
1456 1722
1457 /* Verify that we can still talk to the frame's X window, 1723 FOR_EACH_FRAME (frames, frame1)
1458 and note any recent change in visibility. */ 1724 {
1725 f1 = XFRAME (frame1);
1726 if (f != f1)
1727 {
1728 /* Verify that we can still talk to the frame's X window, and
1729 note any recent change in visibility. */
1459#ifdef HAVE_X_WINDOWS 1730#ifdef HAVE_X_WINDOWS
1460 if (FRAME_WINDOW_P (XFRAME (this))) 1731 if (FRAME_WINDOW_P (f1))
1461 x_sync (XFRAME (this)); 1732 x_sync (f1);
1462#endif 1733#endif
1463 1734 if (NILP (Fframe_parameter (frame1, Qtooltip))
1464 if (FRAME_VISIBLE_P (XFRAME (this)) 1735 /* Tooltips and child frames count neither for
1465 || FRAME_ICONIFIED_P (XFRAME (this)) 1736 invisibility nor for deletions. */
1466 /* Allow deleting the terminal frame when at least one X 1737 && !FRAME_PARENT_FRAME (f1)
1467 frame exists. */ 1738 /* Frames with a non-nil `delete-before' parameter don't
1468 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f))) 1739 count for deletions. */
1469 return 1; 1740 && (invisible || NILP (get_frame_param (f1, Qdelete_before)))
1741 /* For invisibility and normal deletions, at least one
1742 visible or iconified frame must remain (Bug#26682). */
1743 && (FRAME_VISIBLE_P (f1) || FRAME_ICONIFIED_P (f1)
1744 || (!invisible
1745 && (force
1746 /* Allow deleting the terminal frame when at
1747 least one X frame exists. */
1748 || (FRAME_WINDOW_P (f1) && !FRAME_WINDOW_P (f))))))
1749 return true;
1750 }
1470 } 1751 }
1471 return 0; 1752
1753 return false;
1472} 1754}
1473 1755
1474/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer 1756/* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
@@ -1517,53 +1799,65 @@ check_minibuf_window (Lisp_Object frame, int select)
1517} 1799}
1518 1800
1519 1801
1520/* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME 1802/**
1521 unconditionally. x_connection_closed and delete_terminal use 1803 * delete_frame:
1522 this. Any other value of FORCE implements the semantics 1804 *
1523 described for Fdelete_frame. */ 1805 * Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1806 * unconditionally. x_connection_closed and delete_terminal use this.
1807 * Any other value of FORCE implements the semantics described for
1808 * Fdelete_frame. */
1524Lisp_Object 1809Lisp_Object
1525delete_frame (Lisp_Object frame, Lisp_Object force) 1810delete_frame (Lisp_Object frame, Lisp_Object force)
1526{ 1811{
1527 struct frame *f = decode_any_frame (frame); 1812 struct frame *f = decode_any_frame (frame);
1528 struct frame *sf; 1813 struct frame *sf;
1529 struct kboard *kb; 1814 struct kboard *kb;
1530 1815 Lisp_Object frames, frame1;
1531 int minibuffer_selected, is_tooltip_frame; 1816 int minibuffer_selected, is_tooltip_frame;
1817 bool nochild = !FRAME_PARENT_FRAME (f);
1532 1818
1533 if (! FRAME_LIVE_P (f)) 1819 if (!FRAME_LIVE_P (f))
1534 return Qnil; 1820 return Qnil;
1535 1821 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1536 if (NILP (force) && !other_visible_frames (f)) 1822 {
1537 error ("Attempt to delete the sole visible or iconified frame"); 1823 if (NILP (force))
1538 1824 error ("Attempt to delete the sole visible or iconified frame");
1539 /* x_connection_closed must have set FORCE to `noelisp' in order 1825 else
1540 to delete the last frame, if it is gone. */ 1826 error ("Attempt to delete the only frame");
1541 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp)) 1827 }
1542 error ("Attempt to delete the only frame");
1543 1828
1544 XSETFRAME (frame, f); 1829 XSETFRAME (frame, f);
1545 1830
1831 /* Softly delete all frames with this frame as their parent frame or
1832 as their `delete-before' frame parameter value. */
1833 FOR_EACH_FRAME (frames, frame1)
1834 if (FRAME_PARENT_FRAME (XFRAME (frame1)) == f
1835 /* Process `delete-before' parameter iff FRAME is not a child
1836 frame. This avoids that we enter an infinite chain of mixed
1837 dependencies. */
1838 || (nochild
1839 && EQ (get_frame_param (XFRAME (frame1), Qdelete_before), frame)))
1840 delete_frame (frame1, Qnil);
1841
1546 /* Does this frame have a minibuffer, and is it the surrogate 1842 /* Does this frame have a minibuffer, and is it the surrogate
1547 minibuffer for any other frame? */ 1843 minibuffer for any other frame? */
1548 if (FRAME_HAS_MINIBUF_P (f)) 1844 if (FRAME_HAS_MINIBUF_P (f))
1549 { 1845 {
1550 Lisp_Object frames, this; 1846 FOR_EACH_FRAME (frames, frame1)
1551
1552 FOR_EACH_FRAME (frames, this)
1553 { 1847 {
1554 Lisp_Object fminiw; 1848 Lisp_Object fminiw;
1555 1849
1556 if (EQ (this, frame)) 1850 if (EQ (frame1, frame))
1557 continue; 1851 continue;
1558 1852
1559 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this)); 1853 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (frame1));
1560 1854
1561 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw)))) 1855 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1562 { 1856 {
1563 /* If we MUST delete this frame, delete the other first. 1857 /* If we MUST delete this frame, delete the other first.
1564 But do this only if FORCE equals `noelisp'. */ 1858 But do this only if FORCE equals `noelisp'. */
1565 if (EQ (force, Qnoelisp)) 1859 if (EQ (force, Qnoelisp))
1566 delete_frame (this, Qnoelisp); 1860 delete_frame (frame1, Qnoelisp);
1567 else 1861 else
1568 error ("Attempt to delete a surrogate minibuffer frame"); 1862 error ("Attempt to delete a surrogate minibuffer frame");
1569 } 1863 }
@@ -1592,20 +1886,26 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1592 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame); 1886 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1593 } 1887 }
1594 1888
1595 /* The hook may sometimes (indirectly) cause the frame to be deleted. */ 1889 /* delete_frame_functions may have deleted any frame, including this
1596 if (! FRAME_LIVE_P (f)) 1890 one. */
1891 if (!FRAME_LIVE_P (f))
1597 return Qnil; 1892 return Qnil;
1893 else if (!EQ (force, Qnoelisp) && !other_frames (f, false, !NILP (force)))
1894 {
1895 if (NILP (force))
1896 error ("Attempt to delete the sole visible or iconified frame");
1897 else
1898 error ("Attempt to delete the only frame");
1899 }
1598 1900
1599 /* At this point, we are committed to deleting the frame. 1901 /* At this point, we are committed to deleting the frame.
1600 There is no more chance for errors to prevent it. */ 1902 There is no more chance for errors to prevent it. */
1601
1602 minibuffer_selected = EQ (minibuf_window, selected_window); 1903 minibuffer_selected = EQ (minibuf_window, selected_window);
1603 sf = SELECTED_FRAME (); 1904 sf = SELECTED_FRAME ();
1604 /* Don't let the frame remain selected. */ 1905 /* Don't let the frame remain selected. */
1605 if (f == sf) 1906 if (f == sf)
1606 { 1907 {
1607 Lisp_Object tail; 1908 Lisp_Object tail;
1608 Lisp_Object frame1 = Qnil;
1609 1909
1610 /* Look for another visible frame on the same terminal. 1910 /* Look for another visible frame on the same terminal.
1611 Do not call next_frame here because it may loop forever. 1911 Do not call next_frame here because it may loop forever.
@@ -1709,8 +2009,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1709 promise that the terminal of the frame must be valid until we 2009 promise that the terminal of the frame must be valid until we
1710 have called the window-system-dependent frame destruction 2010 have called the window-system-dependent frame destruction
1711 routine. */ 2011 routine. */
1712
1713
1714 { 2012 {
1715 struct terminal *terminal; 2013 struct terminal *terminal;
1716 block_input (); 2014 block_input ();
@@ -1747,16 +2045,15 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1747 another one. */ 2045 another one. */
1748 if (f == last_nonminibuf_frame) 2046 if (f == last_nonminibuf_frame)
1749 { 2047 {
1750 Lisp_Object frames, this;
1751
1752 last_nonminibuf_frame = 0; 2048 last_nonminibuf_frame = 0;
1753 2049
1754 FOR_EACH_FRAME (frames, this) 2050 FOR_EACH_FRAME (frames, frame1)
1755 { 2051 {
1756 f = XFRAME (this); 2052 struct frame *f1 = XFRAME (frame1);
1757 if (!FRAME_MINIBUF_ONLY_P (f)) 2053
2054 if (!FRAME_MINIBUF_ONLY_P (f1))
1758 { 2055 {
1759 last_nonminibuf_frame = f; 2056 last_nonminibuf_frame = f1;
1760 break; 2057 break;
1761 } 2058 }
1762 } 2059 }
@@ -1766,13 +2063,12 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1766 single-kboard state if we're in it for this kboard. */ 2063 single-kboard state if we're in it for this kboard. */
1767 if (kb != NULL) 2064 if (kb != NULL)
1768 { 2065 {
1769 Lisp_Object frames, this;
1770 /* Some frame we found on the same kboard, or nil if there are none. */ 2066 /* Some frame we found on the same kboard, or nil if there are none. */
1771 Lisp_Object frame_on_same_kboard = Qnil; 2067 Lisp_Object frame_on_same_kboard = Qnil;
1772 2068
1773 FOR_EACH_FRAME (frames, this) 2069 FOR_EACH_FRAME (frames, frame1)
1774 if (kb == FRAME_KBOARD (XFRAME (this))) 2070 if (kb == FRAME_KBOARD (XFRAME (frame1)))
1775 frame_on_same_kboard = this; 2071 frame_on_same_kboard = frame1;
1776 2072
1777 if (NILP (frame_on_same_kboard)) 2073 if (NILP (frame_on_same_kboard))
1778 not_single_kboard_state (kb); 2074 not_single_kboard_state (kb);
@@ -1784,29 +2080,27 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
1784 frames with other windows. */ 2080 frames with other windows. */
1785 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame))) 2081 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1786 { 2082 {
1787 Lisp_Object frames, this;
1788
1789 /* The last frame we saw with a minibuffer, minibuffer-only or not. */ 2083 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1790 Lisp_Object frame_with_minibuf = Qnil; 2084 Lisp_Object frame_with_minibuf = Qnil;
1791 /* Some frame we found on the same kboard, or nil if there are none. */ 2085 /* Some frame we found on the same kboard, or nil if there are none. */
1792 Lisp_Object frame_on_same_kboard = Qnil; 2086 Lisp_Object frame_on_same_kboard = Qnil;
1793 2087
1794 FOR_EACH_FRAME (frames, this) 2088 FOR_EACH_FRAME (frames, frame1)
1795 { 2089 {
1796 struct frame *f1 = XFRAME (this); 2090 struct frame *f1 = XFRAME (frame1);
1797 2091
1798 /* Consider only frames on the same kboard 2092 /* Consider only frames on the same kboard
1799 and only those with minibuffers. */ 2093 and only those with minibuffers. */
1800 if (kb == FRAME_KBOARD (f1) 2094 if (kb == FRAME_KBOARD (f1)
1801 && FRAME_HAS_MINIBUF_P (f1)) 2095 && FRAME_HAS_MINIBUF_P (f1))
1802 { 2096 {
1803 frame_with_minibuf = this; 2097 frame_with_minibuf = frame1;
1804 if (FRAME_MINIBUF_ONLY_P (f1)) 2098 if (FRAME_MINIBUF_ONLY_P (f1))
1805 break; 2099 break;
1806 } 2100 }
1807 2101
1808 if (kb == FRAME_KBOARD (f1)) 2102 if (kb == FRAME_KBOARD (f1))
1809 frame_on_same_kboard = this; 2103 frame_on_same_kboard = frame1;
1810 } 2104 }
1811 2105
1812 if (!NILP (frame_on_same_kboard)) 2106 if (!NILP (frame_on_same_kboard))
@@ -1850,8 +2144,101 @@ The functions are run with one argument, the frame to be deleted. */)
1850{ 2144{
1851 return delete_frame (frame, !NILP (force) ? Qt : Qnil); 2145 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
1852} 2146}
1853
1854 2147
2148#ifdef HAVE_WINDOW_SYSTEM
2149/**
2150 * frame_internal_border_part:
2151 *
2152 * Return part of internal border the coordinates X and Y relative to
2153 * frame F are on. Return nil if the coordinates are not on the
2154 * internal border of F.
2155 *
2156 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2157 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2158 * mouse cursor is on the corresponding border with an offset of at
2159 * least one canonical character height from that border's edges.
2160 *
2161 * If no border part could be found this way, return one of
2162 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2163 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2164 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2165 * one of the corresponding corners. This means that for very small
2166 * frames an `edge' return value is preferred.
2167 */
2168enum internal_border_part
2169frame_internal_border_part (struct frame *f, int x, int y)
2170{
2171 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2172 int offset = FRAME_LINE_HEIGHT (f);
2173 int width = FRAME_PIXEL_WIDTH (f);
2174 int height = FRAME_PIXEL_HEIGHT (f);
2175 enum internal_border_part part = INTERNAL_BORDER_NONE;
2176
2177 if (offset < border)
2178 /* For very wide borders make offset at least as large as
2179 border. */
2180 offset = border;
2181
2182 if (offset < x && x < width - offset)
2183 /* Top or bottom border. */
2184 {
2185 if (0 <= y && y <= border)
2186 part = INTERNAL_BORDER_TOP_EDGE;
2187 else if (height - border <= y && y <= height)
2188 part = INTERNAL_BORDER_BOTTOM_EDGE;
2189 }
2190 else if (offset < y && y < height - offset)
2191 /* Left or right border. */
2192 {
2193 if (0 <= x && x <= border)
2194 part = INTERNAL_BORDER_LEFT_EDGE;
2195 else if (width - border <= x && x <= width)
2196 part = INTERNAL_BORDER_RIGHT_EDGE;
2197 }
2198 else
2199 {
2200 /* An edge. */
2201 int half_width = width / 2;
2202 int half_height = height / 2;
2203
2204 if (0 <= x && x <= border)
2205 {
2206 /* A left edge. */
2207 if (0 <= y && y <= half_height)
2208 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2209 else if (half_height < y && y <= height)
2210 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2211 }
2212 else if (width - border <= x && x <= width)
2213 {
2214 /* A right edge. */
2215 if (0 <= y && y <= half_height)
2216 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2217 else if (half_height < y && y <= height)
2218 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2219 }
2220 else if (0 <= y && y <= border)
2221 {
2222 /* A top edge. */
2223 if (0 <= x && x <= half_width)
2224 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2225 else if (half_width < x && x <= width)
2226 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2227 }
2228 else if (height - border <= y && y <= height)
2229 {
2230 /* A bottom edge. */
2231 if (0 <= x && x <= half_width)
2232 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2233 else if (half_width < x && x <= width)
2234 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2235 }
2236 }
2237
2238 return part;
2239}
2240#endif
2241
1855/* Return mouse position in character cell units. */ 2242/* Return mouse position in character cell units. */
1856 2243
1857DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0, 2244DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
@@ -2119,7 +2506,7 @@ displayed in the terminal. */)
2119{ 2506{
2120 struct frame *f = decode_live_frame (frame); 2507 struct frame *f = decode_live_frame (frame);
2121 2508
2122 if (NILP (force) && !other_visible_frames (f)) 2509 if (NILP (force) && !other_frames (f, true, false))
2123 error ("Attempt to make invisible the sole visible or iconified frame"); 2510 error ("Attempt to make invisible the sole visible or iconified frame");
2124 2511
2125 /* Don't allow minibuf_window to remain on an invisible frame. */ 2512 /* Don't allow minibuf_window to remain on an invisible frame. */
@@ -2292,14 +2679,16 @@ See `redirect-frame-focus'. */)
2292 return FRAME_FOCUS_FRAME (decode_live_frame (frame)); 2679 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2293} 2680}
2294 2681
2295DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, 2682DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 2, 0,
2296 doc: /* Set the input focus to FRAME. 2683 doc: /* Set the input focus to FRAME.
2297FRAME nil means use the selected frame. 2684FRAME nil means use the selected frame. Optional argument NOACTIVATE
2685means do not activate FRAME.
2686
2298If there is no window system support, this function does nothing. */) 2687If there is no window system support, this function does nothing. */)
2299 (Lisp_Object frame) 2688 (Lisp_Object frame, Lisp_Object noactivate)
2300{ 2689{
2301#ifdef HAVE_WINDOW_SYSTEM 2690#ifdef HAVE_WINDOW_SYSTEM
2302 x_focus_frame (decode_window_system_frame (frame)); 2691 x_focus_frame (decode_window_system_frame (frame), !NILP (noactivate));
2303#endif 2692#endif
2304 return Qnil; 2693 return Qnil;
2305} 2694}
@@ -2454,9 +2843,39 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2454 } 2843 }
2455 } 2844 }
2456 2845
2846 /* Check each parent-frame and delete-before parameter for a
2847 circular dependency. Do not check between parameters, so you can
2848 still create circular dependencies with different properties, for
2849 example a chain of frames F1->F2->...Fn such that F1 is an ancestor
2850 frame of Fn and thus cannot be deleted before Fn and a second chain
2851 Fn->Fn-1->...F1 such that Fn cannot be deleted before F1. */
2852 else if (EQ (prop, Qparent_frame) || EQ (prop, Qdelete_before))
2853 {
2854 Lisp_Object oldval = Fcdr (Fassq (prop, f->param_alist));
2855
2856 if (!EQ (oldval, val) && !NILP (val))
2857 {
2858 Lisp_Object frame;
2859 Lisp_Object frame1 = val;
2860
2861 if (!FRAMEP (frame1) || !FRAME_LIVE_P (XFRAME (frame1)))
2862 error ("Invalid `%s' frame parameter",
2863 SSDATA (SYMBOL_NAME (prop)));
2864
2865 XSETFRAME (frame, f);
2866
2867 while (FRAMEP (frame1) && FRAME_LIVE_P (XFRAME (frame1)))
2868 if (EQ (frame1, frame))
2869 error ("Circular specification of `%s' frame parameter",
2870 SSDATA (SYMBOL_NAME (prop)));
2871 else
2872 frame1 = get_frame_param (XFRAME (frame1), prop);
2873 }
2874 }
2875
2457 /* The buffer-list parameters are stored in a special place and not 2876 /* The buffer-list parameters are stored in a special place and not
2458 in the alist. All buffers must be live. */ 2877 in the alist. All buffers must be live. */
2459 if (EQ (prop, Qbuffer_list)) 2878 else if (EQ (prop, Qbuffer_list))
2460 { 2879 {
2461 Lisp_Object list = Qnil; 2880 Lisp_Object list = Qnil;
2462 for (; CONSP (val); val = XCDR (val)) 2881 for (; CONSP (val); val = XCDR (val))
@@ -2465,7 +2884,7 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2465 fset_buffer_list (f, Fnreverse (list)); 2884 fset_buffer_list (f, Fnreverse (list));
2466 return; 2885 return;
2467 } 2886 }
2468 if (EQ (prop, Qburied_buffer_list)) 2887 else if (EQ (prop, Qburied_buffer_list))
2469 { 2888 {
2470 Lisp_Object list = Qnil; 2889 Lisp_Object list = Qnil;
2471 for (; CONSP (val); val = XCDR (val)) 2890 for (; CONSP (val); val = XCDR (val))
@@ -2776,49 +3195,47 @@ For a terminal screen, the value is always 1. */)
2776 return make_number (1); 3195 return make_number (1);
2777} 3196}
2778 3197
2779DEFUN ("frame-pixel-height", Fframe_pixel_height, 3198DEFUN ("frame-native-width", Fframe_native_width,
2780 Sframe_pixel_height, 0, 1, 0, 3199 Sframe_native_width, 0, 1, 0,
2781 doc: /* Return a FRAME's height in pixels. 3200 doc: /* Return FRAME's native width in pixels.
2782If FRAME is omitted or nil, the selected frame is used. The exact value 3201For a terminal frame, the result really gives the width in characters.
2783of the result depends on the window-system and toolkit in use: 3202If FRAME is omitted or nil, the selected frame is used. */)
2784
2785In the Gtk+ version of Emacs, it includes only any window (including
2786the minibuffer or echo area), mode line, and header line. It does not
2787include the tool bar or menu bar.
2788
2789With other graphical versions, it also includes the tool bar and the
2790menu bar.
2791
2792For a text terminal, it includes the menu bar. In this case, the
2793result is really in characters rather than pixels (i.e., is identical
2794to `frame-height'). */)
2795 (Lisp_Object frame) 3203 (Lisp_Object frame)
2796{ 3204{
2797 struct frame *f = decode_any_frame (frame); 3205 struct frame *f = decode_any_frame (frame);
2798 3206
2799#ifdef HAVE_WINDOW_SYSTEM 3207#ifdef HAVE_WINDOW_SYSTEM
2800 if (FRAME_WINDOW_P (f)) 3208 if (FRAME_WINDOW_P (f))
2801 return make_number (FRAME_PIXEL_HEIGHT (f)); 3209 return make_number (FRAME_PIXEL_WIDTH (f));
2802 else 3210 else
2803#endif 3211#endif
2804 return make_number (FRAME_TOTAL_LINES (f)); 3212 return make_number (FRAME_TOTAL_COLS (f));
2805} 3213}
2806 3214
2807DEFUN ("frame-pixel-width", Fframe_pixel_width, 3215DEFUN ("frame-native-height", Fframe_native_height,
2808 Sframe_pixel_width, 0, 1, 0, 3216 Sframe_native_height, 0, 1, 0,
2809 doc: /* Return FRAME's width in pixels. 3217 doc: /* Return FRAME's native height in pixels.
2810For a terminal frame, the result really gives the width in characters. 3218If FRAME is omitted or nil, the selected frame is used. The exact value
2811If FRAME is omitted or nil, the selected frame is used. */) 3219of the result depends on the window-system and toolkit in use:
3220
3221In the Gtk+ and NS versions, it includes only any window (including the
3222minibuffer or echo area), mode line, and header line. It does not
3223include the tool bar or menu bar. With other graphical versions, it may
3224also include the tool bar and the menu bar.
3225
3226For a text terminal, it includes the menu bar. In this case, the
3227result is really in characters rather than pixels (i.e., is identical
3228to `frame-height'). */)
2812 (Lisp_Object frame) 3229 (Lisp_Object frame)
2813{ 3230{
2814 struct frame *f = decode_any_frame (frame); 3231 struct frame *f = decode_any_frame (frame);
2815 3232
2816#ifdef HAVE_WINDOW_SYSTEM 3233#ifdef HAVE_WINDOW_SYSTEM
2817 if (FRAME_WINDOW_P (f)) 3234 if (FRAME_WINDOW_P (f))
2818 return make_number (FRAME_PIXEL_WIDTH (f)); 3235 return make_number (FRAME_PIXEL_HEIGHT (f));
2819 else 3236 else
2820#endif 3237#endif
2821 return make_number (FRAME_TOTAL_COLS (f)); 3238 return make_number (FRAME_TOTAL_LINES (f));
2822} 3239}
2823 3240
2824DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width, 3241DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
@@ -2901,8 +3318,8 @@ DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
2901 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame))); 3318 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
2902} 3319}
2903 3320
2904DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0, 3321DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
2905 doc: /* Return border width of FRAME in pixels. */) 3322 doc: /* Return width of FRAME's internal border in pixels. */)
2906 (Lisp_Object frame) 3323 (Lisp_Object frame)
2907{ 3324{
2908 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame))); 3325 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
@@ -3038,7 +3455,6 @@ bottom edge of FRAME's display. */)
3038 3455
3039 return Qt; 3456 return Qt;
3040} 3457}
3041
3042 3458
3043/*********************************************************************** 3459/***********************************************************************
3044 Frame Parameters 3460 Frame Parameters
@@ -3096,10 +3512,200 @@ static const struct frame_parm_table frame_parms[] =
3096 {"sticky", SYMBOL_INDEX (Qsticky)}, 3512 {"sticky", SYMBOL_INDEX (Qsticky)},
3097 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)}, 3513 {"tool-bar-position", SYMBOL_INDEX (Qtool_bar_position)},
3098 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)}, 3514 {"inhibit-double-buffering", SYMBOL_INDEX (Qinhibit_double_buffering)},
3515 {"undecorated", SYMBOL_INDEX (Qundecorated)},
3516 {"parent-frame", SYMBOL_INDEX (Qparent_frame)},
3517 {"skip-taskbar", SYMBOL_INDEX (Qskip_taskbar)},
3518 {"no-focus-on-map", SYMBOL_INDEX (Qno_focus_on_map)},
3519 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3520 {"z-group", SYMBOL_INDEX (Qz_group)},
3521 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3522 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3099}; 3523};
3100 3524
3101#ifdef HAVE_WINDOW_SYSTEM 3525#ifdef HAVE_WINDOW_SYSTEM
3102 3526
3527/* Enumeration type for switch in frame_float. */
3528enum frame_float_type
3529{
3530 FRAME_FLOAT_WIDTH,
3531 FRAME_FLOAT_HEIGHT,
3532 FRAME_FLOAT_LEFT,
3533 FRAME_FLOAT_TOP
3534};
3535
3536/**
3537 * frame_float:
3538 *
3539 * Process the value VAL of the float type frame parameter 'width',
3540 * 'height', 'left', or 'top' specified via a frame_float_type
3541 * enumeration type WHAT for frame F. Such parameters relate the outer
3542 * size or position of F to the size of the F's display or parent frame
3543 * which have to be both available in some way.
3544 *
3545 * The return value is a size or position value in pixels. VAL must be
3546 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3547 * and 1.0 means to return the full width/height of the display/parent.
3548 * For positions, 0.0 means position in the left/top corner of the
3549 * display/parent while 1.0 means to position at the right/bottom corner
3550 * of the display/parent frame.
3551 *
3552 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3553 * size or parent or display attributes when more float parameters are
3554 * calculated in a row: -1 means not processed yet, 0 means processing
3555 * failed, 1 means processing succeeded.
3556 *
3557 * Return DEFAULT_VALUE when processing fails for whatever reason with
3558 * one exception: When calculating F's outer edges fails (probably
3559 * because F has not been created yet) return the difference between F's
3560 * native and text size.
3561 */
3562static int
3563frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3564 int *parent_done, int *outer_done, int default_value)
3565{
3566 double d_val = XFLOAT_DATA (val);
3567
3568 if (d_val < 0.0 || d_val > 1.0)
3569 /* Invalid VAL. */
3570 return default_value;
3571 else
3572 {
3573 static unsigned parent_width, parent_height;
3574 static int parent_left, parent_top;
3575 static unsigned outer_minus_text_width, outer_minus_text_height;
3576 struct frame *p = FRAME_PARENT_FRAME (f);
3577
3578 if (*parent_done == 1)
3579 ;
3580 else if (p)
3581 {
3582 parent_width = FRAME_PIXEL_WIDTH (p);
3583 parent_height = FRAME_PIXEL_HEIGHT (p);
3584 *parent_done = 1;
3585 }
3586 else
3587 {
3588 if (*parent_done == 0)
3589 /* No workarea available. */
3590 return default_value;
3591 else if (*parent_done == -1)
3592 {
3593 Lisp_Object monitor_attributes;
3594 Lisp_Object workarea;
3595 Lisp_Object frame;
3596
3597 XSETFRAME (frame, f);
3598 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3599 if (NILP (monitor_attributes))
3600 {
3601 /* No monitor attributes available. */
3602 *parent_done = 0;
3603
3604 return default_value;
3605 }
3606
3607 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3608 if (NILP (workarea))
3609 {
3610 /* No workarea available. */
3611 *parent_done = 0;
3612
3613 return default_value;
3614 }
3615
3616 /* Workarea available. */
3617 parent_left = XINT (Fnth (make_number (0), workarea));
3618 parent_top = XINT (Fnth (make_number (1), workarea));
3619 parent_width = XINT (Fnth (make_number (2), workarea));
3620 parent_height = XINT (Fnth (make_number (3), workarea));
3621 *parent_done = 1;
3622 }
3623 }
3624
3625 if (*outer_done == 1)
3626 ;
3627 else if (FRAME_UNDECORATED (f))
3628 {
3629 outer_minus_text_width
3630 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3631 outer_minus_text_height
3632 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3633 *outer_done = 1;
3634 }
3635 else if (*outer_done == 0)
3636 /* No outer size available. */
3637 return default_value;
3638 else if (*outer_done == -1)
3639 {
3640 Lisp_Object frame, outer_edges;
3641
3642 XSETFRAME (frame, f);
3643 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3644
3645 if (!NILP (outer_edges))
3646 {
3647 outer_minus_text_width
3648 = (XINT (Fnth (make_number (2), outer_edges))
3649 - XINT (Fnth (make_number (0), outer_edges))
3650 - FRAME_TEXT_WIDTH (f));
3651 outer_minus_text_height
3652 = (XINT (Fnth (make_number (3), outer_edges))
3653 - XINT (Fnth (make_number (1), outer_edges))
3654 - FRAME_TEXT_HEIGHT (f));
3655 }
3656 else
3657 {
3658 /* If we can't get any outer edges, proceed as if the frame
3659 were undecorated. */
3660 outer_minus_text_width
3661 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3662 outer_minus_text_height
3663 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3664 }
3665
3666 *outer_done = 1;
3667 }
3668
3669 switch (what)
3670 {
3671 case FRAME_FLOAT_WIDTH:
3672 return parent_width * d_val - outer_minus_text_width;
3673
3674 case FRAME_FLOAT_HEIGHT:
3675 return parent_height * d_val - outer_minus_text_height;
3676
3677 case FRAME_FLOAT_LEFT:
3678 {
3679 int rest_width = (parent_width
3680 - FRAME_TEXT_WIDTH (f)
3681 - outer_minus_text_width);
3682
3683 if (p)
3684 return (rest_width <= 0 ? 0 : d_val * rest_width);
3685 else
3686 return (rest_width <= 0
3687 ? parent_left
3688 : parent_left + d_val * rest_width);
3689 }
3690 case FRAME_FLOAT_TOP:
3691 {
3692 int rest_height = (parent_height
3693 - FRAME_TEXT_HEIGHT (f)
3694 - outer_minus_text_height);
3695
3696 if (p)
3697 return (rest_height <= 0 ? 0 : d_val * rest_height);
3698 else
3699 return (rest_height <= 0
3700 ? parent_top
3701 : parent_top + d_val * rest_height);
3702 }
3703 default:
3704 emacs_abort ();
3705 }
3706 }
3707}
3708
3103/* Change the parameters of frame F as specified by ALIST. 3709/* Change the parameters of frame F as specified by ALIST.
3104 If a parameter is not specially recognized, do nothing special; 3710 If a parameter is not specially recognized, do nothing special;
3105 otherwise call the `x_set_...' function for that parameter. 3711 otherwise call the `x_set_...' function for that parameter.
@@ -3109,7 +3715,8 @@ static const struct frame_parm_table frame_parms[] =
3109void 3715void
3110x_set_frame_parameters (struct frame *f, Lisp_Object alist) 3716x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3111{ 3717{
3112 Lisp_Object tail; 3718 Lisp_Object tail, frame;
3719
3113 3720
3114 /* If both of these parameters are present, it's more efficient to 3721 /* If both of these parameters are present, it's more efficient to
3115 set them both at once. So we wait until we've looked at the 3722 set them both at once. So we wait until we've looked at the
@@ -3134,7 +3741,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3134#ifdef HAVE_X_WINDOWS 3741#ifdef HAVE_X_WINDOWS
3135 bool icon_left_no_change = 0, icon_top_no_change = 0; 3742 bool icon_left_no_change = 0, icon_top_no_change = 0;
3136#endif 3743#endif
3744 int parent_done = -1, outer_done = -1;
3137 3745
3746 XSETFRAME (frame, f);
3138 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail)) 3747 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3139 size++; 3748 size++;
3140 CHECK_LIST_END (tail, alist); 3749 CHECK_LIST_END (tail, alist);
@@ -3195,6 +3804,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3195 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) 3804 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3196 && RANGED_INTEGERP (0, XCDR (val), INT_MAX)) 3805 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3197 width = XFASTINT (XCDR (val)); 3806 width = XFASTINT (XCDR (val));
3807 else if (FLOATP (val))
3808 width = frame_float (f, val, FRAME_FLOAT_WIDTH, &parent_done,
3809 &outer_done, -1);
3198 } 3810 }
3199 else if (EQ (prop, Qheight)) 3811 else if (EQ (prop, Qheight))
3200 { 3812 {
@@ -3203,6 +3815,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3203 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) 3815 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3204 && RANGED_INTEGERP (0, XCDR (val), INT_MAX)) 3816 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3205 height = XFASTINT (XCDR (val)); 3817 height = XFASTINT (XCDR (val));
3818 else if (FLOATP (val))
3819 height = frame_float (f, val, FRAME_FLOAT_HEIGHT, &parent_done,
3820 &outer_done, -1);
3206 } 3821 }
3207 else if (EQ (prop, Qtop)) 3822 else if (EQ (prop, Qtop))
3208 top = val; 3823 top = val;
@@ -3279,105 +3894,100 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3279 Don't set these parameters unless they actually differ from the 3894 Don't set these parameters unless they actually differ from the
3280 window's current parameters; the window may not actually exist 3895 window's current parameters; the window may not actually exist
3281 yet. */ 3896 yet. */
3282 { 3897 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3283 Lisp_Object frame; 3898 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3284 3899 /* We could consider checking f->after_make_frame here, but I
3285 XSETFRAME (frame, f); 3900 don't have the faintest idea why the following is needed at
3286 3901 all. With the old setting it can get a Heisenbug when
3287 if ((width != -1 && width != FRAME_TEXT_WIDTH (f)) 3902 EmacsFrameResize intermittently provokes a delayed
3288 || (height != -1 && height != FRAME_TEXT_HEIGHT (f))) 3903 change_frame_size in the middle of adjust_frame_size. */
3289 /* We could consider checking f->after_make_frame here, but I 3904 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3290 don't have the faintest idea why the following is needed at 3905 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters);
3291 all. With the old setting it can get a Heisenbug when 3906
3292 EmacsFrameResize intermittently provokes a delayed 3907 if ((!NILP (left) || !NILP (top))
3293 change_frame_size in the middle of adjust_frame_size. */ 3908 && ! (left_no_change && top_no_change)
3294 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/ 3909 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3295 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters); 3910 && NUMBERP (top) && XINT (top) == f->top_pos))
3296 3911 {
3297 if ((!NILP (left) || !NILP (top)) 3912 int leftpos = 0;
3298 && ! (left_no_change && top_no_change) 3913 int toppos = 0;
3299 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3300 && NUMBERP (top) && XINT (top) == f->top_pos))
3301 {
3302 int leftpos = 0;
3303 int toppos = 0;
3304 3914
3305 /* Record the signs. */ 3915 /* Record the signs. */
3306 f->size_hint_flags &= ~ (XNegative | YNegative); 3916 f->size_hint_flags &= ~ (XNegative | YNegative);
3307 if (EQ (left, Qminus)) 3917 if (EQ (left, Qminus))
3308 f->size_hint_flags |= XNegative; 3918 f->size_hint_flags |= XNegative;
3309 else if (TYPE_RANGED_INTEGERP (int, left)) 3919 else if (TYPE_RANGED_INTEGERP (int, left))
3310 { 3920 {
3311 leftpos = XINT (left); 3921 leftpos = XINT (left);
3312 if (leftpos < 0) 3922 if (leftpos < 0)
3313 f->size_hint_flags |= XNegative;
3314 }
3315 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3316 && CONSP (XCDR (left))
3317 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3318 {
3319 leftpos = - XINT (XCAR (XCDR (left)));
3320 f->size_hint_flags |= XNegative; 3923 f->size_hint_flags |= XNegative;
3321 } 3924 }
3322 else if (CONSP (left) && EQ (XCAR (left), Qplus) 3925 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3323 && CONSP (XCDR (left)) 3926 && CONSP (XCDR (left))
3324 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left)))) 3927 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3325 { 3928 {
3326 leftpos = XINT (XCAR (XCDR (left))); 3929 leftpos = - XINT (XCAR (XCDR (left)));
3327 } 3930 f->size_hint_flags |= XNegative;
3931 }
3932 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3933 && CONSP (XCDR (left))
3934 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3935 leftpos = XINT (XCAR (XCDR (left)));
3936 else if (FLOATP (left))
3937 leftpos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
3938 &outer_done, 0);
3328 3939
3329 if (EQ (top, Qminus)) 3940 if (EQ (top, Qminus))
3330 f->size_hint_flags |= YNegative; 3941 f->size_hint_flags |= YNegative;
3331 else if (TYPE_RANGED_INTEGERP (int, top)) 3942 else if (TYPE_RANGED_INTEGERP (int, top))
3332 { 3943 {
3333 toppos = XINT (top); 3944 toppos = XINT (top);
3334 if (toppos < 0) 3945 if (toppos < 0)
3335 f->size_hint_flags |= YNegative;
3336 }
3337 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3338 && CONSP (XCDR (top))
3339 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3340 {
3341 toppos = - XINT (XCAR (XCDR (top)));
3342 f->size_hint_flags |= YNegative; 3946 f->size_hint_flags |= YNegative;
3343 } 3947 }
3344 else if (CONSP (top) && EQ (XCAR (top), Qplus) 3948 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3345 && CONSP (XCDR (top)) 3949 && CONSP (XCDR (top))
3346 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top)))) 3950 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3347 { 3951 {
3348 toppos = XINT (XCAR (XCDR (top))); 3952 toppos = - XINT (XCAR (XCDR (top)));
3349 } 3953 f->size_hint_flags |= YNegative;
3350 3954 }
3955 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3956 && CONSP (XCDR (top))
3957 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3958 toppos = XINT (XCAR (XCDR (top)));
3959 else if (FLOATP (top))
3960 toppos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
3961 &outer_done, 0);
3351 3962
3352 /* Store the numeric value of the position. */ 3963 /* Store the numeric value of the position. */
3353 f->top_pos = toppos; 3964 f->top_pos = toppos;
3354 f->left_pos = leftpos; 3965 f->left_pos = leftpos;
3355 3966
3356 f->win_gravity = NorthWestGravity; 3967 f->win_gravity = NorthWestGravity;
3357 3968
3358 /* Actually set that position, and convert to absolute. */ 3969 /* Actually set that position, and convert to absolute. */
3359 x_set_offset (f, leftpos, toppos, -1); 3970 x_set_offset (f, leftpos, toppos, -1);
3360 } 3971 }
3361 3972
3362 if (fullscreen_change) 3973 if (fullscreen_change)
3363 { 3974 {
3364 Lisp_Object old_value = get_frame_param (f, Qfullscreen); 3975 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3365 3976
3366 frame_size_history_add 3977 frame_size_history_add
3367 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen)); 3978 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3368 3979
3369 store_frame_param (f, Qfullscreen, fullscreen); 3980 store_frame_param (f, Qfullscreen, fullscreen);
3370 if (!EQ (fullscreen, old_value)) 3981 if (!EQ (fullscreen, old_value))
3371 x_set_fullscreen (f, fullscreen, old_value); 3982 x_set_fullscreen (f, fullscreen, old_value);
3372 } 3983 }
3373 3984
3374 3985
3375#ifdef HAVE_X_WINDOWS 3986#ifdef HAVE_X_WINDOWS
3376 if ((!NILP (icon_left) || !NILP (icon_top)) 3987 if ((!NILP (icon_left) || !NILP (icon_top))
3377 && ! (icon_left_no_change && icon_top_no_change)) 3988 && ! (icon_left_no_change && icon_top_no_change))
3378 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top)); 3989 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3379#endif /* HAVE_X_WINDOWS */ 3990#endif /* HAVE_X_WINDOWS */
3380 }
3381 3991
3382 SAFE_FREE (); 3992 SAFE_FREE ();
3383} 3993}
@@ -3797,7 +4407,6 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3797 adjust_frame_glyphs (f); 4407 adjust_frame_glyphs (f);
3798 SET_FRAME_GARBAGED (f); 4408 SET_FRAME_GARBAGED (f);
3799 } 4409 }
3800
3801} 4410}
3802 4411
3803void 4412void
@@ -4011,6 +4620,22 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4011 return; 4620 return;
4012} 4621}
4013 4622
4623
4624/**
4625 * x_set_no_special_glyphs:
4626 *
4627 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4628 * suppresses the display of truncation and continuation glyphs
4629 * outside fringes.
4630 */
4631void
4632x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4633{
4634 if (!EQ (new_value, old_value))
4635 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4636}
4637
4638
4014#ifndef HAVE_NS 4639#ifndef HAVE_NS
4015 4640
4016/* Non-zero if mouse is grabbed on DPYINFO 4641/* Non-zero if mouse is grabbed on DPYINFO
@@ -4566,6 +5191,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4566 Lisp_Object height, width, user_size, top, left, user_position; 5191 Lisp_Object height, width, user_size, top, left, user_position;
4567 long window_prompting = 0; 5192 long window_prompting = 0;
4568 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); 5193 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5194 int parent_done = -1, outer_done = -1;
4569 5195
4570 /* Default values if we fall through. 5196 /* Default values if we fall through.
4571 Actually, if that happens we should get 5197 Actually, if that happens we should get
@@ -4630,6 +5256,21 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4630 f->inhibit_horizontal_resize = true; 5256 f->inhibit_horizontal_resize = true;
4631 *x_width = XINT (XCDR (width)); 5257 *x_width = XINT (XCDR (width));
4632 } 5258 }
5259 else if (FLOATP (width))
5260 {
5261 double d_width = XFLOAT_DATA (width);
5262
5263 if (d_width < 0.0 || d_width > 1.0)
5264 xsignal1 (Qargs_out_of_range, width);
5265 else
5266 {
5267 int new_width = frame_float (f, width, FRAME_FLOAT_WIDTH,
5268 &parent_done, &outer_done, -1);
5269
5270 if (new_width > -1)
5271 SET_FRAME_WIDTH (f, new_width);
5272 }
5273 }
4633 else 5274 else
4634 { 5275 {
4635 CHECK_NUMBER (width); 5276 CHECK_NUMBER (width);
@@ -4652,6 +5293,21 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4652 f->inhibit_vertical_resize = true; 5293 f->inhibit_vertical_resize = true;
4653 *x_height = XINT (XCDR (height)); 5294 *x_height = XINT (XCDR (height));
4654 } 5295 }
5296 else if (FLOATP (height))
5297 {
5298 double d_height = XFLOAT_DATA (height);
5299
5300 if (d_height < 0.0 || d_height > 1.0)
5301 xsignal1 (Qargs_out_of_range, height);
5302 else
5303 {
5304 int new_height = frame_float (f, height, FRAME_FLOAT_HEIGHT,
5305 &parent_done, &outer_done, -1);
5306
5307 if (new_height > -1)
5308 SET_FRAME_HEIGHT (f, new_height);
5309 }
5310 }
4655 else 5311 else
4656 { 5312 {
4657 CHECK_NUMBER (height); 5313 CHECK_NUMBER (height);
@@ -4692,6 +5348,9 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4692 { 5348 {
4693 f->top_pos = XINT (XCAR (XCDR (top))); 5349 f->top_pos = XINT (XCAR (XCDR (top)));
4694 } 5350 }
5351 else if (FLOATP (top))
5352 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5353 &outer_done, 0);
4695 else if (EQ (top, Qunbound)) 5354 else if (EQ (top, Qunbound))
4696 f->top_pos = 0; 5355 f->top_pos = 0;
4697 else 5356 else
@@ -4720,6 +5379,9 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4720 { 5379 {
4721 f->left_pos = XINT (XCAR (XCDR (left))); 5380 f->left_pos = XINT (XCAR (XCDR (left)));
4722 } 5381 }
5382 else if (FLOATP (left))
5383 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5384 &outer_done, 0);
4723 else if (EQ (left, Qunbound)) 5385 else if (EQ (left, Qunbound))
4724 f->left_pos = 0; 5386 f->left_pos = 0;
4725 else 5387 else
@@ -4878,11 +5540,21 @@ syms_of_frame (void)
4878 DEFSYM (Qframep, "framep"); 5540 DEFSYM (Qframep, "framep");
4879 DEFSYM (Qframe_live_p, "frame-live-p"); 5541 DEFSYM (Qframe_live_p, "frame-live-p");
4880 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size"); 5542 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
5543 DEFSYM (Qdisplay_monitor_attributes_list, "display-monitor-attributes-list");
4881 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total"); 5544 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
4882 DEFSYM (Qexplicit_name, "explicit-name"); 5545 DEFSYM (Qexplicit_name, "explicit-name");
4883 DEFSYM (Qheight, "height"); 5546 DEFSYM (Qheight, "height");
4884 DEFSYM (Qicon, "icon"); 5547 DEFSYM (Qicon, "icon");
4885 DEFSYM (Qminibuffer, "minibuffer"); 5548 DEFSYM (Qminibuffer, "minibuffer");
5549 DEFSYM (Qundecorated, "undecorated");
5550 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5551 DEFSYM (Qparent_frame, "parent-frame");
5552 DEFSYM (Qskip_taskbar, "skip-taskbar");
5553 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
5554 DEFSYM (Qno_accept_focus, "no-accept-focus");
5555 DEFSYM (Qz_group, "z-group");
5556 DEFSYM (Qoverride_redirect, "override-redirect");
5557 DEFSYM (Qdelete_before, "delete-before");
4886 DEFSYM (Qmodeline, "modeline"); 5558 DEFSYM (Qmodeline, "modeline");
4887 DEFSYM (Qonly, "only"); 5559 DEFSYM (Qonly, "only");
4888 DEFSYM (Qnone, "none"); 5560 DEFSYM (Qnone, "none");
@@ -4923,13 +5595,12 @@ syms_of_frame (void)
4923 DEFSYM (Qx_resource_name, "x-resource-name"); 5595 DEFSYM (Qx_resource_name, "x-resource-name");
4924 DEFSYM (Qx_frame_parameter, "x-frame-parameter"); 5596 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4925 5597
4926 DEFSYM (Qterminal, "terminal");
4927
4928 DEFSYM (Qworkarea, "workarea"); 5598 DEFSYM (Qworkarea, "workarea");
4929 DEFSYM (Qmm_size, "mm-size"); 5599 DEFSYM (Qmm_size, "mm-size");
4930 DEFSYM (Qframes, "frames"); 5600 DEFSYM (Qframes, "frames");
4931 DEFSYM (Qsource, "source"); 5601 DEFSYM (Qsource, "source");
4932 5602
5603 DEFSYM (Qframe_edges, "frame-edges");
4933 DEFSYM (Qouter_edges, "outer-edges"); 5604 DEFSYM (Qouter_edges, "outer-edges");
4934 DEFSYM (Qouter_position, "outer-position"); 5605 DEFSYM (Qouter_position, "outer-position");
4935 DEFSYM (Qouter_size, "outer-size"); 5606 DEFSYM (Qouter_size, "outer-size");
@@ -4981,6 +5652,7 @@ syms_of_frame (void)
4981 DEFSYM (Qauto_raise, "auto-raise"); 5652 DEFSYM (Qauto_raise, "auto-raise");
4982 DEFSYM (Qborder_color, "border-color"); 5653 DEFSYM (Qborder_color, "border-color");
4983 DEFSYM (Qborder_width, "border-width"); 5654 DEFSYM (Qborder_width, "border-width");
5655 DEFSYM (Qouter_border_width, "outer-border-width");
4984 DEFSYM (Qbottom_divider_width, "bottom-divider-width"); 5656 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
4985 DEFSYM (Qcursor_color, "cursor-color"); 5657 DEFSYM (Qcursor_color, "cursor-color");
4986 DEFSYM (Qcursor_type, "cursor-type"); 5658 DEFSYM (Qcursor_type, "cursor-type");
@@ -5014,6 +5686,17 @@ syms_of_frame (void)
5014 DEFSYM (Qvisibility, "visibility"); 5686 DEFSYM (Qvisibility, "visibility");
5015 DEFSYM (Qwait_for_wm, "wait-for-wm"); 5687 DEFSYM (Qwait_for_wm, "wait-for-wm");
5016 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering"); 5688 DEFSYM (Qinhibit_double_buffering, "inhibit-double-buffering");
5689 DEFSYM (Qno_other_frame, "no-other-frame");
5690 DEFSYM (Qbelow, "below");
5691 DEFSYM (Qabove_suspended, "above-suspended");
5692 DEFSYM (Qmin_width, "min-width");
5693 DEFSYM (Qmin_height, "min-height");
5694 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame");
5695 DEFSYM (Qkeep_ratio, "keep-ratio");
5696 DEFSYM (Qwidth_only, "width-only");
5697 DEFSYM (Qheight_only, "height-only");
5698 DEFSYM (Qleft_only, "left-only");
5699 DEFSYM (Qtop_only, "top-only");
5017 5700
5018 { 5701 {
5019 int i; 5702 int i;
@@ -5123,13 +5806,19 @@ The pointer becomes visible again when the mouse is moved. */);
5123 Vmake_pointer_invisible = Qt; 5806 Vmake_pointer_invisible = Qt;
5124 5807
5125 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook, 5808 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
5126 doc: /* Normal hook run when a frame gains input focus. */); 5809 doc: /* Normal hook run when a frame gains input focus.
5810The frame gaining focus is selected at the time this hook is run. */);
5127 Vfocus_in_hook = Qnil; 5811 Vfocus_in_hook = Qnil;
5128 5812
5129 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook, 5813 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
5130 doc: /* Normal hook run when a frame loses input focus. */); 5814 doc: /* Normal hook run when all frames lost input focus. */);
5131 Vfocus_out_hook = Qnil; 5815 Vfocus_out_hook = Qnil;
5132 5816
5817 DEFVAR_LISP ("move-frame-functions", Vmove_frame_functions,
5818 doc: /* Functions run after a frame was moved.
5819The functions are run with one arg, the frame that moved. */);
5820 Vmove_frame_functions = Qnil;
5821
5133 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions, 5822 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
5134 doc: /* Functions run before deleting a frame. 5823 doc: /* Functions run before deleting a frame.
5135The functions are run with one arg, the frame to be deleted. 5824The functions are run with one arg, the frame to be deleted.
@@ -5176,12 +5865,51 @@ displayed.
5176 5865
5177This variable is local to the current terminal and cannot be buffer-local. */); 5866This variable is local to the current terminal and cannot be buffer-local. */);
5178 5867
5179 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse, 5868 DEFVAR_LISP ("focus-follows-mouse", focus_follows_mouse,
5180 doc: /* Non-nil if window system changes focus when you move the mouse. 5869 doc: /* Non-nil if window system changes focus when you move the mouse.
5181You should set this variable to tell Emacs how your window manager 5870You should set this variable to tell Emacs how your window manager
5182handles focus, since there is no way in general for Emacs to find out 5871handles focus, since there is no way in general for Emacs to find out
5183automatically. See also `mouse-autoselect-window'. */); 5872automatically.
5184 focus_follows_mouse = 0; 5873
5874There are three meaningful values:
5875
5876- The default nil should be used when your window manager follows a
5877 "click-to-focus" policy where you have to click the mouse inside of a
5878 frame in order for that frame to get focus.
5879
5880- The value t should be used when your window manager has the focus
5881 automatically follow the position of the mouse pointer but a window
5882 that gains focus is not raised automatically.
5883
5884- The value `auto-raise' should be used when your window manager has the
5885 focus automatically follow the position of the mouse pointer and a
5886 window that gains focus is raised automatically.
5887
5888If this option is non-nil, Emacs moves the mouse pointer to the frame
5889selected by `select-frame-set-input-focus'. This function is used by a
5890number of commands like, for example, `other-frame' and `pop-to-buffer'.
5891If this option is nil and your focus follows mouse window manager does
5892not autonomously move the mouse pointer to the newly selected frame, the
5893previously selected window manager window might get reselected instead
5894immediately.
5895
5896The distinction between the values t and `auto-raise' is not needed for
5897"normal" frames because the window manager takes care of raising them.
5898Setting this to `auto-raise' will, however, override the standard
5899behavior of a window manager that does not automatically raise the frame
5900that gets focus. Setting this to `auto-raise' is also necessary to
5901automatically raise child frames which are usually left alone by the
5902window manager.
5903
5904Note that this option does not distinguish "sloppy" focus (where the
5905frame that previously had focus retains focus as long as the mouse
5906pointer does not move into another window manager window) from "strict"
5907focus (where a frame immediately loses focus when it's left by the mouse
5908pointer).
5909
5910In order to extend a "focus follows mouse" policy to individual Emacs
5911windows, customize the variable `mouse-autoselect-window'. */);
5912 focus_follows_mouse = Qnil;
5185 5913
5186 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise, 5914 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
5187 doc: /* Non-nil means resize frames pixelwise. 5915 doc: /* Non-nil means resize frames pixelwise.
@@ -5283,6 +6011,8 @@ Gtk+ tooltips are not used) and on Windows. */);
5283 defsubr (&Sselect_frame); 6011 defsubr (&Sselect_frame);
5284 defsubr (&Sselected_frame); 6012 defsubr (&Sselected_frame);
5285 defsubr (&Sframe_list); 6013 defsubr (&Sframe_list);
6014 defsubr (&Sframe_parent);
6015 defsubr (&Sframe_ancestor_p);
5286 defsubr (&Snext_frame); 6016 defsubr (&Snext_frame);
5287 defsubr (&Sprevious_frame); 6017 defsubr (&Sprevious_frame);
5288 defsubr (&Slast_nonminibuf_frame); 6018 defsubr (&Slast_nonminibuf_frame);
@@ -5311,8 +6041,8 @@ Gtk+ tooltips are not used) and on Windows. */);
5311 defsubr (&Smodify_frame_parameters); 6041 defsubr (&Smodify_frame_parameters);
5312 defsubr (&Sframe_char_height); 6042 defsubr (&Sframe_char_height);
5313 defsubr (&Sframe_char_width); 6043 defsubr (&Sframe_char_width);
5314 defsubr (&Sframe_pixel_height); 6044 defsubr (&Sframe_native_height);
5315 defsubr (&Sframe_pixel_width); 6045 defsubr (&Sframe_native_width);
5316 defsubr (&Sframe_text_cols); 6046 defsubr (&Sframe_text_cols);
5317 defsubr (&Sframe_text_lines); 6047 defsubr (&Sframe_text_lines);
5318 defsubr (&Sframe_total_cols); 6048 defsubr (&Sframe_total_cols);
@@ -5322,7 +6052,7 @@ Gtk+ tooltips are not used) and on Windows. */);
5322 defsubr (&Sscroll_bar_width); 6052 defsubr (&Sscroll_bar_width);
5323 defsubr (&Sscroll_bar_height); 6053 defsubr (&Sscroll_bar_height);
5324 defsubr (&Sfringe_width); 6054 defsubr (&Sfringe_width);
5325 defsubr (&Sborder_width); 6055 defsubr (&Sframe_internal_border_width);
5326 defsubr (&Sright_divider_width); 6056 defsubr (&Sright_divider_width);
5327 defsubr (&Sbottom_divider_width); 6057 defsubr (&Sbottom_divider_width);
5328 defsubr (&Stool_bar_pixel_width); 6058 defsubr (&Stool_bar_pixel_width);
diff --git a/src/frame.h b/src/frame.h
index 5f18901a17c..154dc9a3bb4 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -45,6 +45,26 @@ enum fullscreen_type
45#endif 45#endif
46}; 46};
47 47
48enum z_group
49{
50 z_group_none,
51 z_group_above,
52 z_group_below,
53 z_group_above_suspended,
54};
55
56enum internal_border_part
57 {
58 INTERNAL_BORDER_NONE,
59 INTERNAL_BORDER_LEFT_EDGE,
60 INTERNAL_BORDER_TOP_LEFT_CORNER,
61 INTERNAL_BORDER_TOP_EDGE,
62 INTERNAL_BORDER_TOP_RIGHT_CORNER,
63 INTERNAL_BORDER_RIGHT_EDGE,
64 INTERNAL_BORDER_BOTTOM_RIGHT_CORNER,
65 INTERNAL_BORDER_BOTTOM_EDGE,
66 INTERNAL_BORDER_BOTTOM_LEFT_CORNER,
67 };
48#endif /* HAVE_WINDOW_SYSTEM */ 68#endif /* HAVE_WINDOW_SYSTEM */
49 69
50/* The structure representing a frame. */ 70/* The structure representing a frame. */
@@ -68,6 +88,11 @@ struct frame
68 Usually it is nil. */ 88 Usually it is nil. */
69 Lisp_Object title; 89 Lisp_Object title;
70 90
91#if defined (HAVE_WINDOW_SYSTEM)
92 /* This frame's parent frame, if it has one. */
93 Lisp_Object parent_frame;
94#endif /* HAVE_WINDOW_SYSTEM */
95
71 /* The frame which should receive keystrokes that occur in this 96 /* The frame which should receive keystrokes that occur in this
72 frame, or nil if they should go to the frame itself. This is 97 frame, or nil if they should go to the frame itself. This is
73 usually nil, but if the frame is minibufferless, we can use this 98 usually nil, but if the frame is minibufferless, we can use this
@@ -320,6 +345,34 @@ struct frame
320 bool_bf horizontal_scroll_bars : 1; 345 bool_bf horizontal_scroll_bars : 1;
321#endif /* HAVE_WINDOW_SYSTEM */ 346#endif /* HAVE_WINDOW_SYSTEM */
322 347
348#if defined (HAVE_WINDOW_SYSTEM)
349 /* True if this is an undecorated frame. */
350 bool_bf undecorated : 1;
351
352#ifndef HAVE_NTGUI
353 /* True if this is an override_redirect frame. */
354 bool_bf override_redirect : 1;
355#endif
356
357 /* Nonzero if this frame's icon should not appear on its display's taskbar. */
358 bool_bf skip_taskbar : 1;
359
360 /* Nonzero if this frame's window F's X window does not want to
361 receive input focus when it is mapped. */
362 bool_bf no_focus_on_map : 1;
363
364 /* Nonzero if this frame's window does not want to receive input focus
365 via mouse clicks or by moving the mouse into it. */
366 bool_bf no_accept_focus : 1;
367
368 /* The z-group this frame's window belongs to. */
369 ENUM_BF (z_group) z_group : 2;
370
371 /* Non-zero if display of truncation and continuation glyphs outside
372 the fringes is suppressed. */
373 bool_bf no_special_glyphs : 1;
374#endif /* HAVE_WINDOW_SYSTEM */
375
323 /* Whether new_height and new_width shall be interpreted 376 /* Whether new_height and new_width shall be interpreted
324 in pixels. */ 377 in pixels. */
325 bool_bf new_pixelwise : 1; 378 bool_bf new_pixelwise : 1;
@@ -534,6 +587,13 @@ fset_face_alist (struct frame *f, Lisp_Object val)
534{ 587{
535 f->face_alist = val; 588 f->face_alist = val;
536} 589}
590#if defined (HAVE_WINDOW_SYSTEM)
591INLINE void
592fset_parent_frame (struct frame *f, Lisp_Object val)
593{
594 f->parent_frame = val;
595}
596#endif
537INLINE void 597INLINE void
538fset_focus_frame (struct frame *f, Lisp_Object val) 598fset_focus_frame (struct frame *f, Lisp_Object val)
539{ 599{
@@ -781,7 +841,7 @@ default_pixels_per_inch_y (void)
781#ifdef USE_GTK 841#ifdef USE_GTK
782#define FRAME_TOOL_BAR_POSITION(f) (f)->tool_bar_position 842#define FRAME_TOOL_BAR_POSITION(f) (f)->tool_bar_position
783#else 843#else
784#define FRAME_TOOL_BAR_POSITION(f) ((void) f, Qtop) 844#define FRAME_TOOL_BAR_POSITION(f) ((void) (f), Qtop)
785#endif 845#endif
786 846
787/* Number of lines of frame F used for the tool-bar. */ 847/* Number of lines of frame F used for the tool-bar. */
@@ -854,7 +914,6 @@ default_pixels_per_inch_y (void)
854#define FRAME_FOCUS_FRAME(f) f->focus_frame 914#define FRAME_FOCUS_FRAME(f) f->focus_frame
855 915
856#ifdef HAVE_WINDOW_SYSTEM 916#ifdef HAVE_WINDOW_SYSTEM
857
858/* This frame slot says whether scroll bars are currently enabled for frame F, 917/* This frame slot says whether scroll bars are currently enabled for frame F,
859 and which side they are on. */ 918 and which side they are on. */
860#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type) 919#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((f)->vertical_scroll_bar_type)
@@ -864,15 +923,48 @@ default_pixels_per_inch_y (void)
864 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_left) 923 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_left)
865#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \ 924#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) \
866 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) 925 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right)
867
868#else /* not HAVE_WINDOW_SYSTEM */ 926#else /* not HAVE_WINDOW_SYSTEM */
869
870/* If there is no window system, there are no scroll bars. */ 927/* If there is no window system, there are no scroll bars. */
871#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none) 928#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) \
872#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0) 929 ((void) (f), vertical_scroll_bar_none)
873#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) 930#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) (f), 0)
874#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) f, 0) 931#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) (f), 0)
932#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT(f) ((void) (f), 0)
933#endif /* HAVE_WINDOW_SYSTEM */
875 934
935#if defined (HAVE_WINDOW_SYSTEM)
936#define FRAME_UNDECORATED(f) ((f)->undecorated)
937#ifdef HAVE_NTGUI
938#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
939#else
940#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect)
941#endif
942#define FRAME_PARENT_FRAME(f) \
943 (NILP ((f)->parent_frame) \
944 ? NULL \
945 : XFRAME ((f)->parent_frame))
946#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar)
947#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map)
948#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus)
949#define FRAME_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
950#define FRAME_Z_GROUP(f) ((f)->z_group)
951#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none)
952#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above)
953#define FRAME_Z_GROUP_ABOVE_SUSPENDED(f) \
954 ((f)->z_group == z_group_above_suspended)
955#define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below)
956#else /* not HAVE_WINDOW_SYSTEM */
957#define FRAME_UNDECORATED(f) ((void) (f), 0)
958#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
959#define FRAME_PARENT_FRAME(f) ((void) (f), NULL)
960#define FRAME_SKIP_TASKBAR(f) ((void) (f), 0)
961#define FRAME_NO_FOCUS_ON_MAP(f) ((void) (f), 0)
962#define FRAME_NO_ACCEPT_FOCUS(f) ((void) (f), 0)
963#define FRAME_NO_SPECIAL_GLYPHS(f) ((void) (f), 0)
964#define FRAME_Z_GROUP(f) ((void) (f), z_group_none)
965#define FRAME_Z_GROUP_NONE(f) ((void) (f), true)
966#define FRAME_Z_GROUP_ABOVE(f) ((void) (f), false)
967#define FRAME_Z_GROUP_BELOW(f) ((void) (f), false)
876#endif /* HAVE_WINDOW_SYSTEM */ 968#endif /* HAVE_WINDOW_SYSTEM */
877 969
878/* Whether horizontal scroll bars are currently enabled for frame F. */ 970/* Whether horizontal scroll bars are currently enabled for frame F. */
@@ -880,7 +972,7 @@ default_pixels_per_inch_y (void)
880#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \ 972#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
881 ((f)->horizontal_scroll_bars) 973 ((f)->horizontal_scroll_bars)
882#else 974#else
883#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) ((void) f, 0) 975#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) ((void) (f), 0)
884#endif 976#endif
885 977
886/* Width that a scroll bar in frame F should have, if there is one. 978/* Width that a scroll bar in frame F should have, if there is one.
@@ -1039,16 +1131,18 @@ default_pixels_per_inch_y (void)
1039/* FOR_EACH_FRAME (LIST_VAR, FRAME_VAR) followed by a statement is a 1131/* FOR_EACH_FRAME (LIST_VAR, FRAME_VAR) followed by a statement is a
1040 `for' loop which iterates over the elements of Vframe_list. The 1132 `for' loop which iterates over the elements of Vframe_list. The
1041 loop will set FRAME_VAR, a Lisp_Object, to each frame in 1133 loop will set FRAME_VAR, a Lisp_Object, to each frame in
1042 Vframe_list in succession and execute the statement. LIST_VAR 1134 Vframe_list in succession and execute the statement. Vframe_list
1135 should be nonempty, so the body is executed at least once. LIST_VAR
1043 should be a Lisp_Object too; it is used to iterate through the 1136 should be a Lisp_Object too; it is used to iterate through the
1044 Vframe_list. 1137 Vframe_list. Note that this macro walks over child frames and
1138 the tooltip frame as well.
1045 1139
1046 This macro is a holdover from a time when multiple frames weren't always 1140 This macro is a holdover from a time when multiple frames weren't always
1047 supported. An alternate definition of the macro would expand to 1141 supported. An alternate definition of the macro would expand to
1048 something which executes the statement once. */ 1142 something which executes the statement once. */
1049 1143
1050#define FOR_EACH_FRAME(list_var, frame_var) \ 1144#define FOR_EACH_FRAME(list_var, frame_var) \
1051 for ((list_var) = Vframe_list; \ 1145 for ((list_var) = (eassume (CONSP (Vframe_list)), Vframe_list); \
1052 (CONSP (list_var) \ 1146 (CONSP (list_var) \
1053 && (frame_var = XCAR (list_var), true)); \ 1147 && (frame_var = XCAR (list_var), true)); \
1054 list_var = XCDR (list_var)) 1148 list_var = XCDR (list_var))
@@ -1214,19 +1308,20 @@ FRAME_TOTAL_FRINGE_WIDTH (struct frame *f)
1214 return FRAME_LEFT_FRINGE_WIDTH (f) + FRAME_RIGHT_FRINGE_WIDTH (f); 1308 return FRAME_LEFT_FRINGE_WIDTH (f) + FRAME_RIGHT_FRINGE_WIDTH (f);
1215} 1309}
1216 1310
1217/* Pixel-width of internal border lines */ 1311/* Pixel-width of internal border lines. */
1218INLINE int 1312INLINE int
1219FRAME_INTERNAL_BORDER_WIDTH (struct frame *f) 1313FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
1220{ 1314{
1221 return frame_dimension (f->internal_border_width); 1315 return frame_dimension (f->internal_border_width);
1222} 1316}
1223 1317
1224/* Pixel-size of window border lines */ 1318/* Pixel-size of window divider lines. */
1225INLINE int 1319INLINE int
1226FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f) 1320FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f)
1227{ 1321{
1228 return frame_dimension (f->right_divider_width); 1322 return frame_dimension (f->right_divider_width);
1229} 1323}
1324
1230INLINE int 1325INLINE int
1231FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f) 1326FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f)
1232{ 1327{
@@ -1424,6 +1519,7 @@ extern void x_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object);
1424extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *); 1519extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *);
1425 1520
1426extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object); 1521extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
1522extern void x_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
1427 1523
1428extern void validate_x_resource_name (void); 1524extern void validate_x_resource_name (void);
1429 1525
@@ -1446,6 +1542,8 @@ extern void x_activate_menubar (struct frame *);
1446extern void x_real_positions (struct frame *, int *, int *); 1542extern void x_real_positions (struct frame *, int *, int *);
1447extern void free_frame_menubar (struct frame *); 1543extern void free_frame_menubar (struct frame *);
1448extern void x_free_frame_resources (struct frame *); 1544extern void x_free_frame_resources (struct frame *);
1545extern bool frame_ancestor_p (struct frame *af, struct frame *df);
1546extern enum internal_border_part frame_internal_border_part (struct frame *f, int x, int y);
1449 1547
1450#if defined HAVE_X_WINDOWS 1548#if defined HAVE_X_WINDOWS
1451extern void x_wm_set_icon_position (struct frame *, int, int); 1549extern void x_wm_set_icon_position (struct frame *, int, int);
@@ -1456,7 +1554,7 @@ extern void x_sync (struct frame *);
1456#endif /* HAVE_X_WINDOWS */ 1554#endif /* HAVE_X_WINDOWS */
1457 1555
1458extern void x_query_colors (struct frame *f, XColor *, int); 1556extern void x_query_colors (struct frame *f, XColor *, int);
1459extern void x_focus_frame (struct frame *); 1557extern void x_focus_frame (struct frame *, bool);
1460 1558
1461#ifndef HAVE_NS 1559#ifndef HAVE_NS
1462 1560
diff --git a/src/ftfont.c b/src/ftfont.c
index 6cabddda370..5600bde646d 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -1546,7 +1546,8 @@ ftfont_get_metrics (MFLTFont *font, MFLTGlyphString *gstring,
1546 { 1546 {
1547 FT_Glyph_Metrics *m; 1547 FT_Glyph_Metrics *m;
1548 1548
1549 if (FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_DEFAULT) != 0) 1549 if (FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_DEFAULT) != 0
1550 && FT_Load_Glyph (ft_face, g->g.code, FT_LOAD_NO_HINTING) != 0)
1550 emacs_abort (); 1551 emacs_abort ();
1551 m = &ft_face->glyph->metrics; 1552 m = &ft_face->glyph->metrics;
1552 if (flt_font_ft->matrix) 1553 if (flt_font_ft->matrix)
diff --git a/src/gmalloc.c b/src/gmalloc.c
index 49f1fafccc0..baaff58050f 100644
--- a/src/gmalloc.c
+++ b/src/gmalloc.c
@@ -77,11 +77,6 @@ extern void *(*__morecore) (ptrdiff_t);
77#ifdef HYBRID_MALLOC 77#ifdef HYBRID_MALLOC
78# include "sheap.h" 78# include "sheap.h"
79# define DUMPED bss_sbrk_did_unexec 79# define DUMPED bss_sbrk_did_unexec
80static bool
81ALLOCATED_BEFORE_DUMPING (char *p)
82{
83 return bss_sbrk_buffer <= p && p < bss_sbrk_buffer + STATIC_HEAP_SIZE;
84}
85#endif 80#endif
86 81
87#ifdef __cplusplus 82#ifdef __cplusplus
@@ -133,8 +128,13 @@ typedef union
133 /* Heap information for a busy block. */ 128 /* Heap information for a busy block. */
134 struct 129 struct
135 { 130 {
136 /* Zero for a large (multiblock) object, or positive giving the 131 /* Zero for a block that is not one of ours (typically,
137 logarithm to the base two of the fragment size. */ 132 allocated by system malloc), positive for the log base 2 of
133 the fragment size of a fragmented block, -1 for the first
134 block of a multiblock object, and unspecified for later
135 blocks of that object. Type-0 blocks can be present
136 because the system malloc can be invoked by library
137 functions in an undumped Emacs. */
138 int type; 138 int type;
139 union 139 union
140 { 140 {
@@ -144,8 +144,7 @@ typedef union
144 size_t first; /* First free fragment of the block. */ 144 size_t first; /* First free fragment of the block. */
145 } frag; 145 } frag;
146 /* For a large object, in its first block, this has the number 146 /* For a large object, in its first block, this has the number
147 of blocks in the object. In the other blocks, this has a 147 of blocks in the object. */
148 negative number which says how far back the first block is. */
149 ptrdiff_t size; 148 ptrdiff_t size;
150 } info; 149 } info;
151 } busy; 150 } busy;
@@ -166,7 +165,7 @@ extern char *_heapbase;
166extern malloc_info *_heapinfo; 165extern malloc_info *_heapinfo;
167 166
168/* Address to block number and vice versa. */ 167/* Address to block number and vice versa. */
169#define BLOCK(A) (((char *) (A) - _heapbase) / BLOCKSIZE + 1) 168#define BLOCK(A) ((size_t) ((char *) (A) - _heapbase) / BLOCKSIZE + 1)
170#define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + _heapbase)) 169#define ADDRESS(B) ((void *) (((B) - 1) * BLOCKSIZE + _heapbase))
171 170
172/* Current search index for the heap table. */ 171/* Current search index for the heap table. */
@@ -491,11 +490,8 @@ register_heapinfo (void)
491 ++_chunks_used; 490 ++_chunks_used;
492 491
493 /* Describe the heapinfo block itself in the heapinfo. */ 492 /* Describe the heapinfo block itself in the heapinfo. */
494 _heapinfo[block].busy.type = 0; 493 _heapinfo[block].busy.type = -1;
495 _heapinfo[block].busy.info.size = blocks; 494 _heapinfo[block].busy.info.size = blocks;
496 /* Leave back-pointers for malloc_find_address. */
497 while (--blocks > 0)
498 _heapinfo[block + blocks].busy.info.size = -blocks;
499} 495}
500 496
501#ifdef USE_PTHREAD 497#ifdef USE_PTHREAD
@@ -608,7 +604,7 @@ morecore_nolock (size_t size)
608 PROTECT_MALLOC_STATE (0); 604 PROTECT_MALLOC_STATE (0);
609 605
610 /* Check if we need to grow the info table. */ 606 /* Check if we need to grow the info table. */
611 if ((size_t) BLOCK ((char *) result + size) > heapsize) 607 if (heapsize < BLOCK ((char *) result + size))
612 { 608 {
613 /* Calculate the new _heapinfo table size. We do not account for the 609 /* Calculate the new _heapinfo table size. We do not account for the
614 added blocks in the table itself, as we hope to place them in 610 added blocks in the table itself, as we hope to place them in
@@ -617,7 +613,7 @@ morecore_nolock (size_t size)
617 newsize = heapsize; 613 newsize = heapsize;
618 do 614 do
619 newsize *= 2; 615 newsize *= 2;
620 while ((size_t) BLOCK ((char *) result + size) > newsize); 616 while (newsize < BLOCK ((char *) result + size));
621 617
622 /* We must not reuse existing core for the new info table when called 618 /* We must not reuse existing core for the new info table when called
623 from realloc in the case of growing a large block, because the 619 from realloc in the case of growing a large block, because the
@@ -665,8 +661,7 @@ morecore_nolock (size_t size)
665 661
666 /* Is it big enough to record status for its own space? 662 /* Is it big enough to record status for its own space?
667 If so, we win. */ 663 If so, we win. */
668 if ((size_t) BLOCK ((char *) newinfo 664 if (BLOCK ((char *) newinfo + newsize * sizeof (malloc_info))
669 + newsize * sizeof (malloc_info))
670 < newsize) 665 < newsize)
671 break; 666 break;
672 667
@@ -883,17 +878,11 @@ _malloc_internal_nolock (size_t size)
883 --_chunks_free; 878 --_chunks_free;
884 } 879 }
885 880
886 _heapinfo[block].busy.type = 0; 881 _heapinfo[block].busy.type = -1;
887 _heapinfo[block].busy.info.size = blocks; 882 _heapinfo[block].busy.info.size = blocks;
888 ++_chunks_used; 883 ++_chunks_used;
889 _bytes_used += blocks * BLOCKSIZE; 884 _bytes_used += blocks * BLOCKSIZE;
890 _bytes_free -= blocks * BLOCKSIZE; 885 _bytes_free -= blocks * BLOCKSIZE;
891
892 /* Mark all the blocks of the object just allocated except for the
893 first with a negative number so you can find the first block by
894 adding that adjustment. */
895 while (--blocks > 0)
896 _heapinfo[block + blocks].busy.info.size = -blocks;
897 } 886 }
898 887
899 PROTECT_MALLOC_STATE (1); 888 PROTECT_MALLOC_STATE (1);
@@ -1026,7 +1015,7 @@ _free_internal_nolock (void *ptr)
1026 type = _heapinfo[block].busy.type; 1015 type = _heapinfo[block].busy.type;
1027 switch (type) 1016 switch (type)
1028 { 1017 {
1029 case 0: 1018 case -1:
1030 /* Get as many statistics as early as we can. */ 1019 /* Get as many statistics as early as we can. */
1031 --_chunks_used; 1020 --_chunks_used;
1032 _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE; 1021 _bytes_used -= _heapinfo[block].busy.info.size * BLOCKSIZE;
@@ -1187,7 +1176,7 @@ _free_internal_nolock (void *ptr)
1187 prev->prev->next = next; 1176 prev->prev->next = next;
1188 if (next != NULL) 1177 if (next != NULL)
1189 next->prev = prev->prev; 1178 next->prev = prev->prev;
1190 _heapinfo[block].busy.type = 0; 1179 _heapinfo[block].busy.type = -1;
1191 _heapinfo[block].busy.info.size = 1; 1180 _heapinfo[block].busy.info.size = 1;
1192 1181
1193 /* Keep the statistics accurate. */ 1182 /* Keep the statistics accurate. */
@@ -1326,7 +1315,7 @@ _realloc_internal_nolock (void *ptr, size_t size)
1326 type = _heapinfo[block].busy.type; 1315 type = _heapinfo[block].busy.type;
1327 switch (type) 1316 switch (type)
1328 { 1317 {
1329 case 0: 1318 case -1:
1330 /* Maybe reallocate a large block to a small fragment. */ 1319 /* Maybe reallocate a large block to a small fragment. */
1331 if (size <= BLOCKSIZE / 2) 1320 if (size <= BLOCKSIZE / 2)
1332 { 1321 {
@@ -1346,7 +1335,7 @@ _realloc_internal_nolock (void *ptr, size_t size)
1346 { 1335 {
1347 /* The new size is smaller; return 1336 /* The new size is smaller; return
1348 excess memory to the free list. */ 1337 excess memory to the free list. */
1349 _heapinfo[block + blocks].busy.type = 0; 1338 _heapinfo[block + blocks].busy.type = -1;
1350 _heapinfo[block + blocks].busy.info.size 1339 _heapinfo[block + blocks].busy.info.size
1351 = _heapinfo[block].busy.info.size - blocks; 1340 = _heapinfo[block].busy.info.size - blocks;
1352 _heapinfo[block].busy.info.size = blocks; 1341 _heapinfo[block].busy.info.size = blocks;
@@ -1721,6 +1710,20 @@ extern void *aligned_alloc (size_t alignment, size_t size);
1721extern int posix_memalign (void **memptr, size_t alignment, size_t size); 1710extern int posix_memalign (void **memptr, size_t alignment, size_t size);
1722#endif 1711#endif
1723 1712
1713/* Assuming PTR was allocated via the hybrid malloc, return true if
1714 PTR was allocated via gmalloc, not the system malloc. Also, return
1715 true if _heaplimit is zero; this can happen temporarily when
1716 gmalloc calls itself for internal use, and in that case PTR is
1717 already known to be allocated via gmalloc. */
1718
1719static bool
1720allocated_via_gmalloc (void *ptr)
1721{
1722 size_t block = BLOCK (ptr);
1723 size_t blockmax = _heaplimit - 1;
1724 return block <= blockmax && _heapinfo[block].busy.type != 0;
1725}
1726
1724/* See the comments near the beginning of this file for explanations 1727/* See the comments near the beginning of this file for explanations
1725 of the following functions. */ 1728 of the following functions. */
1726 1729
@@ -1743,13 +1746,10 @@ hybrid_calloc (size_t nmemb, size_t size)
1743void 1746void
1744hybrid_free (void *ptr) 1747hybrid_free (void *ptr)
1745{ 1748{
1746 if (!DUMPED) 1749 if (allocated_via_gmalloc (ptr))
1747 gfree (ptr); 1750 gfree (ptr);
1748 else if (!ALLOCATED_BEFORE_DUMPING (ptr)) 1751 else
1749 free (ptr); 1752 free (ptr);
1750 /* Otherwise the dumped emacs is trying to free something allocated
1751 before dumping; do nothing. */
1752 return;
1753} 1753}
1754 1754
1755#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN 1755#if defined HAVE_ALIGNED_ALLOC || defined HAVE_POSIX_MEMALIGN
@@ -1775,19 +1775,20 @@ hybrid_realloc (void *ptr, size_t size)
1775 int type; 1775 int type;
1776 size_t block, oldsize; 1776 size_t block, oldsize;
1777 1777
1778 if (!ptr)
1779 return hybrid_malloc (size);
1780 if (!allocated_via_gmalloc (ptr))
1781 return realloc (ptr, size);
1778 if (!DUMPED) 1782 if (!DUMPED)
1779 return grealloc (ptr, size); 1783 return grealloc (ptr, size);
1780 if (!ALLOCATED_BEFORE_DUMPING (ptr))
1781 return realloc (ptr, size);
1782 1784
1783 /* The dumped emacs is trying to realloc storage allocated before 1785 /* The dumped emacs is trying to realloc storage allocated before
1784 dumping. We just malloc new space and copy the data. */ 1786 dumping via gmalloc. Allocate new space and copy the data. Do
1785 if (size == 0 || ptr == NULL) 1787 not bother with gfree (ptr), as that would just waste time. */
1786 return malloc (size); 1788 block = BLOCK (ptr);
1787 block = ((char *) ptr - _heapbase) / BLOCKSIZE + 1;
1788 type = _heapinfo[block].busy.type; 1789 type = _heapinfo[block].busy.type;
1789 oldsize = 1790 oldsize =
1790 type == 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE 1791 type < 0 ? _heapinfo[block].busy.info.size * BLOCKSIZE
1791 : (size_t) 1 << type; 1792 : (size_t) 1 << type;
1792 result = malloc (size); 1793 result = malloc (size);
1793 if (result) 1794 if (result)
diff --git a/src/gnutls.c b/src/gnutls.c
index 28ab10de05c..2078ad88f28 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -605,6 +605,7 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
605 max_log_level, 605 max_log_level,
606 "retry:", 606 "retry:",
607 str); 607 str);
608 FALLTHROUGH;
608 default: 609 default:
609 GNUTLS_LOG2 (1, 610 GNUTLS_LOG2 (1,
610 max_log_level, 611 max_log_level,
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 63f01436413..2d4abefa969 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -554,10 +554,11 @@ xg_check_special_colors (struct frame *f,
554 else 554 else
555 gtk_style_context_get_background_color (gsty, state, &col); 555 gtk_style_context_get_background_color (gsty, state, &col);
556 556
557 sprintf (buf, "rgb:%04x/%04x/%04x", 557 unsigned short
558 (unsigned) (col.red * 65535), 558 r = col.red * 65535,
559 (unsigned) (col.green * 65535), 559 g = col.green * 65535,
560 (unsigned) (col.blue * 65535)); 560 b = col.blue * 65535;
561 sprintf (buf, "rgb:%04x/%04x/%04x", r, g, b);
561 success_p = x_parse_color (f, buf, color) != 0; 562 success_p = x_parse_color (f, buf, color) != 0;
562#else 563#else
563 GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f)); 564 GtkStyle *gsty = gtk_widget_get_style (FRAME_GTK_WIDGET (f));
@@ -835,30 +836,6 @@ xg_set_geometry (struct frame *f)
835 } 836 }
836} 837}
837 838
838/* Clear under internal border if any. As we use a mix of Gtk+ and X calls
839 and use a GtkFixed widget, this doesn't happen automatically. */
840
841void
842xg_clear_under_internal_border (struct frame *f)
843{
844 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0)
845 {
846 x_clear_area (f, 0, 0,
847 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
848
849 x_clear_area (f, 0, 0,
850 FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
851
852 x_clear_area (f, 0,
853 FRAME_PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
854 FRAME_PIXEL_WIDTH (f), FRAME_INTERNAL_BORDER_WIDTH (f));
855
856 x_clear_area (f,
857 FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f),
858 0, FRAME_INTERNAL_BORDER_WIDTH (f), FRAME_PIXEL_HEIGHT (f));
859 }
860}
861
862static int 839static int
863xg_get_gdk_scale (void) 840xg_get_gdk_scale (void)
864{ 841{
@@ -905,7 +882,7 @@ xg_frame_resized (struct frame *f, int pixelwidth, int pixelheight)
905 || pixelwidth != FRAME_PIXEL_WIDTH (f) 882 || pixelwidth != FRAME_PIXEL_WIDTH (f)
906 || pixelheight != FRAME_PIXEL_HEIGHT (f)) 883 || pixelheight != FRAME_PIXEL_HEIGHT (f))
907 { 884 {
908 xg_clear_under_internal_border (f); 885 x_clear_under_internal_border (f);
909 change_frame_size (f, width, height, 0, 1, 0, 1); 886 change_frame_size (f, width, height, 0, 1, 0, 1);
910 SET_FRAME_GARBAGED (f); 887 SET_FRAME_GARBAGED (f);
911 cancel_mouse_face (f); 888 cancel_mouse_face (f);
@@ -933,7 +910,7 @@ xg_frame_set_char_size (struct frame *f, int width, int height)
933 &gwidth, &gheight); 910 &gwidth, &gheight);
934 911
935 /* Do this before resize, as we don't know yet if we will be resized. */ 912 /* Do this before resize, as we don't know yet if we will be resized. */
936 xg_clear_under_internal_border (f); 913 x_clear_under_internal_border (f);
937 914
938 if (FRAME_VISIBLE_P (f)) 915 if (FRAME_VISIBLE_P (f))
939 { 916 {
@@ -1200,7 +1177,14 @@ xg_create_frame_widgets (struct frame *f)
1200 else if (! NILP (f->name)) 1177 else if (! NILP (f->name))
1201 title = SSDATA (ENCODE_UTF_8 (f->name)); 1178 title = SSDATA (ENCODE_UTF_8 (f->name));
1202 1179
1203 if (title) gtk_window_set_title (GTK_WINDOW (wtop), title); 1180 if (title)
1181 gtk_window_set_title (GTK_WINDOW (wtop), title);
1182
1183 if (FRAME_UNDECORATED (f))
1184 {
1185 gtk_window_set_decorated (GTK_WINDOW (wtop), FALSE);
1186 store_frame_param (f, Qundecorated, Qt);
1187 }
1204 1188
1205 FRAME_GTK_OUTER_WIDGET (f) = wtop; 1189 FRAME_GTK_OUTER_WIDGET (f) = wtop;
1206 FRAME_GTK_WIDGET (f) = wfixed; 1190 FRAME_GTK_WIDGET (f) = wfixed;
@@ -1275,6 +1259,14 @@ xg_create_frame_widgets (struct frame *f)
1275 gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE); 1259 gtk_window_set_resizable (GTK_WINDOW (wtop), TRUE);
1276#endif 1260#endif
1277 1261
1262 if (FRAME_OVERRIDE_REDIRECT (f))
1263 {
1264 GdkWindow *gwin = gtk_widget_get_window (wtop);
1265
1266 if (gwin)
1267 gdk_window_set_override_redirect (gwin, TRUE);
1268 }
1269
1278#ifdef USE_GTK_TOOLTIP 1270#ifdef USE_GTK_TOOLTIP
1279 /* Steal a tool tip window we can move ourselves. */ 1271 /* Steal a tool tip window we can move ourselves. */
1280 f->output_data.x->ttip_widget = 0; 1272 f->output_data.x->ttip_widget = 0;
@@ -1356,7 +1348,9 @@ x_wm_set_size_hint (struct frame *f, long int flags, bool user_position)
1356 /* Don't set size hints during initialization; that apparently leads 1348 /* Don't set size hints during initialization; that apparently leads
1357 to a race condition. See the thread at 1349 to a race condition. See the thread at
1358 http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */ 1350 http://lists.gnu.org/archive/html/emacs-devel/2008-10/msg00033.html */
1359 if (NILP (Vafter_init_time) || !FRAME_GTK_OUTER_WIDGET (f)) 1351 if (NILP (Vafter_init_time)
1352 || !FRAME_GTK_OUTER_WIDGET (f)
1353 || FRAME_PARENT_FRAME (f))
1360 return; 1354 return;
1361 1355
1362 XSETFRAME (frame, f); 1356 XSETFRAME (frame, f);
@@ -1489,6 +1483,102 @@ xg_set_background_color (struct frame *f, unsigned long bg)
1489 } 1483 }
1490} 1484}
1491 1485
1486/* Change the frame's decoration (title bar + resize borders). This
1487 might not work with all window managers. */
1488void
1489xg_set_undecorated (struct frame *f, Lisp_Object undecorated)
1490{
1491 if (FRAME_GTK_WIDGET (f))
1492 {
1493 block_input ();
1494 gtk_window_set_decorated (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
1495 NILP (undecorated) ? TRUE : FALSE);
1496 unblock_input ();
1497 }
1498}
1499
1500
1501/* Restack F1 below F2, above if ABOVE_FLAG is true. This might not
1502 work with all window managers. */
1503void
1504xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
1505{
1506#if GTK_CHECK_VERSION (2, 18, 0)
1507 block_input ();
1508 if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))
1509 {
1510 GdkWindow *gwin1 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f1));
1511 GdkWindow *gwin2 = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f2));
1512 Lisp_Object frame1, frame2;
1513
1514 XSETFRAME (frame1, f1);
1515 XSETFRAME (frame2, f2);
1516
1517 gdk_window_restack (gwin1, gwin2, above_flag);
1518 x_sync (f1);
1519 }
1520 unblock_input ();
1521#endif
1522}
1523
1524
1525/* Don't show frame in taskbar, don't ALT-TAB to it. */
1526void
1527xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar)
1528{
1529 block_input ();
1530 if (FRAME_GTK_WIDGET (f))
1531 gdk_window_set_skip_taskbar_hint
1532 (gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f)),
1533 NILP (skip_taskbar) ? FALSE : TRUE);
1534 unblock_input ();
1535}
1536
1537
1538/* Don't give frame focus. */
1539void
1540xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map)
1541{
1542 block_input ();
1543 if (FRAME_GTK_WIDGET (f))
1544 {
1545 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
1546 gboolean g_no_focus_on_map = NILP (no_focus_on_map) ? TRUE : FALSE;
1547
1548 gtk_window_set_focus_on_map (gwin, g_no_focus_on_map);
1549 }
1550 unblock_input ();
1551}
1552
1553
1554void
1555xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus)
1556{
1557 block_input ();
1558 if (FRAME_GTK_WIDGET (f))
1559 {
1560 GtkWindow *gwin = GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f));
1561 gboolean g_no_accept_focus = NILP (no_accept_focus) ? TRUE : FALSE;
1562
1563 gtk_window_set_accept_focus (gwin, g_no_accept_focus);
1564 }
1565 unblock_input ();
1566}
1567
1568void
1569xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect)
1570{
1571 block_input ();
1572
1573 if (FRAME_GTK_OUTER_WIDGET (f))
1574 {
1575 GdkWindow *gwin = gtk_widget_get_window (FRAME_GTK_OUTER_WIDGET (f));
1576
1577 gdk_window_set_override_redirect (gwin, NILP (override_redirect) ? FALSE : TRUE);
1578 }
1579
1580 unblock_input ();
1581}
1492 1582
1493/* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK 1583/* Set the frame icon to ICON_PIXMAP/MASK. This must be done with GTK
1494 functions so GTK does not overwrite the icon. */ 1584 functions so GTK does not overwrite the icon. */
@@ -3787,7 +3877,8 @@ xg_update_scrollbar_pos (struct frame *f,
3787 /* Move and resize to new values. */ 3877 /* Move and resize to new values. */
3788 gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top); 3878 gtk_fixed_move (GTK_FIXED (wfixed), wparent, left, top);
3789 gtk_widget_style_get (wscroll, "min-slider-length", &msl, NULL); 3879 gtk_widget_style_get (wscroll, "min-slider-length", &msl, NULL);
3790 if (msl > height) 3880 bool hidden = height < msl;
3881 if (hidden)
3791 { 3882 {
3792 /* No room. Hide scroll bar as some themes output a warning if 3883 /* No room. Hide scroll bar as some themes output a warning if
3793 the height is less than the min size. */ 3884 the height is less than the min size. */
@@ -3807,6 +3898,15 @@ xg_update_scrollbar_pos (struct frame *f,
3807 x_clear_area (f, oldx, oldy, oldw, oldh); 3898 x_clear_area (f, oldx, oldy, oldw, oldh);
3808 } 3899 }
3809 3900
3901 if (!hidden)
3902 {
3903 GtkWidget *scrollbar = xg_get_widget_from_map (scrollbar_id);
3904 GtkWidget *webox = gtk_widget_get_parent (scrollbar);
3905
3906 /* Don't obscure any child frames. */
3907 XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
3908 }
3909
3810 /* GTK does not redraw until the main loop is entered again, but 3910 /* GTK does not redraw until the main loop is entered again, but
3811 if there are no X events pending we will not enter it. So we sync 3911 if there are no X events pending we will not enter it. So we sync
3812 here to get some events. */ 3912 here to get some events. */
@@ -3872,6 +3972,15 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
3872 if there are no X events pending we will not enter it. So we sync 3972 if there are no X events pending we will not enter it. So we sync
3873 here to get some events. */ 3973 here to get some events. */
3874 3974
3975 {
3976 GtkWidget *scrollbar =
3977 xg_get_widget_from_map (scrollbar_id);
3978 GtkWidget *webox = gtk_widget_get_parent (scrollbar);
3979
3980 /* Don't obscure any child frames. */
3981 XLowerWindow (FRAME_X_DISPLAY (f), GTK_WIDGET_TO_X_WIN (webox));
3982 }
3983
3875 x_sync (f); 3984 x_sync (f);
3876 SET_FRAME_GARBAGED (f); 3985 SET_FRAME_GARBAGED (f);
3877 cancel_mouse_face (f); 3986 cancel_mouse_face (f);
@@ -4230,7 +4339,7 @@ xg_tool_bar_callback (GtkWidget *w, gpointer client_data)
4230 4339
4231 /* Return focus to the frame after we have clicked on a detached 4340 /* Return focus to the frame after we have clicked on a detached
4232 tool bar button. */ 4341 tool bar button. */
4233 x_focus_frame (f); 4342 x_focus_frame (f, false);
4234} 4343}
4235 4344
4236static GtkWidget * 4345static GtkWidget *
diff --git a/src/gtkutil.h b/src/gtkutil.h
index d67a7bc4328..0abcb06bc71 100644
--- a/src/gtkutil.h
+++ b/src/gtkutil.h
@@ -150,7 +150,6 @@ extern void update_frame_tool_bar (struct frame *f);
150extern void free_frame_tool_bar (struct frame *f); 150extern void free_frame_tool_bar (struct frame *f);
151extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos); 151extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos);
152 152
153extern void xg_clear_under_internal_border (struct frame *f);
154extern void xg_frame_resized (struct frame *f, 153extern void xg_frame_resized (struct frame *f,
155 int pixelwidth, 154 int pixelwidth,
156 int pixelheight); 155 int pixelheight);
@@ -172,6 +171,13 @@ extern void xg_set_frame_icon (struct frame *f,
172 Pixmap icon_pixmap, 171 Pixmap icon_pixmap,
173 Pixmap icon_mask); 172 Pixmap icon_mask);
174 173
174extern void xg_set_undecorated (struct frame *f, Lisp_Object undecorated);
175extern void xg_frame_restack (struct frame *f1, struct frame *f2, bool above);
176extern void xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar);
177extern void xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map);
178extern void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus);
179extern void xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect);
180
175extern bool xg_prepare_tooltip (struct frame *f, 181extern bool xg_prepare_tooltip (struct frame *f,
176 Lisp_Object string, 182 Lisp_Object string,
177 int *width, 183 int *width,
diff --git a/src/image.c b/src/image.c
index 3ebf469e8b3..07c4769e9e3 100644
--- a/src/image.c
+++ b/src/image.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <config.h> 20#include <config.h>
21 21
22#include <fcntl.h> 22#include <fcntl.h>
23#include <stdio.h>
24#include <unistd.h> 23#include <unistd.h>
25 24
26/* Include this before including <setjmp.h> to work around bugs with 25/* Include this before including <setjmp.h> to work around bugs with
@@ -41,6 +40,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#include "buffer.h" 40#include "buffer.h"
42#include "dispextern.h" 41#include "dispextern.h"
43#include "blockinput.h" 42#include "blockinput.h"
43#include "sysstdio.h"
44#include "systime.h" 44#include "systime.h"
45#include <epaths.h> 45#include <epaths.h>
46#include "coding.h" 46#include "coding.h"
@@ -1269,8 +1269,7 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
1269 return img->background_transparent; 1269 return img->background_transparent;
1270} 1270}
1271 1271
1272#if defined (HAVE_PNG) || defined (HAVE_NS) \ 1272#if defined (HAVE_PNG) || defined (HAVE_IMAGEMAGICK) || defined (HAVE_RSVG)
1273 || defined (HAVE_IMAGEMAGICK) || defined (HAVE_RSVG)
1274 1273
1275/* Store F's background color into *BGCOLOR. */ 1274/* Store F's background color into *BGCOLOR. */
1276static void 1275static void
@@ -1284,7 +1283,7 @@ x_query_frame_background_color (struct frame *f, XColor *bgcolor)
1284#endif 1283#endif
1285} 1284}
1286 1285
1287#endif /* HAVE_PNG || HAVE_NS || HAVE_IMAGEMAGICK || HAVE_RSVG */ 1286#endif /* HAVE_PNG || HAVE_IMAGEMAGICK || HAVE_RSVG */
1288 1287
1289/*********************************************************************** 1288/***********************************************************************
1290 Helper functions for X image types 1289 Helper functions for X image types
@@ -2042,10 +2041,20 @@ x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
2042 (*ximg)->info.bmiColors[0].rgbGreen = 0; 2041 (*ximg)->info.bmiColors[0].rgbGreen = 0;
2043 (*ximg)->info.bmiColors[0].rgbRed = 0; 2042 (*ximg)->info.bmiColors[0].rgbRed = 0;
2044 (*ximg)->info.bmiColors[0].rgbReserved = 0; 2043 (*ximg)->info.bmiColors[0].rgbReserved = 0;
2044 /* bmiColors is a variable-length array declared by w32api
2045 headers as bmiColors[1], which triggers a warning under
2046 -Warray-bounds; shut that up. */
2047# if GNUC_PREREQ (4, 4, 0)
2048# pragma GCC push_options
2049# pragma GCC diagnostic ignored "-Warray-bounds"
2050# endif
2045 (*ximg)->info.bmiColors[1].rgbBlue = 255; 2051 (*ximg)->info.bmiColors[1].rgbBlue = 255;
2046 (*ximg)->info.bmiColors[1].rgbGreen = 255; 2052 (*ximg)->info.bmiColors[1].rgbGreen = 255;
2047 (*ximg)->info.bmiColors[1].rgbRed = 255; 2053 (*ximg)->info.bmiColors[1].rgbRed = 255;
2048 (*ximg)->info.bmiColors[1].rgbReserved = 0; 2054 (*ximg)->info.bmiColors[1].rgbReserved = 0;
2055# if GNUC_PREREQ (4, 4, 0)
2056# pragma GCC pop_options
2057# endif
2049 } 2058 }
2050 2059
2051 hdc = get_frame_dc (f); 2060 hdc = get_frame_dc (f);
@@ -2352,7 +2361,7 @@ slurp_file (int fd, ptrdiff_t *size)
2352 This can happen if the file grows as we read it. */ 2361 This can happen if the file grows as we read it. */
2353 ptrdiff_t buflen = st.st_size; 2362 ptrdiff_t buflen = st.st_size;
2354 buf = xmalloc (buflen + 1); 2363 buf = xmalloc (buflen + 1);
2355 if (fread (buf, 1, buflen + 1, fp) == buflen) 2364 if (fread_unlocked (buf, 1, buflen + 1, fp) == buflen)
2356 *size = buflen; 2365 *size = buflen;
2357 else 2366 else
2358 { 2367 {
@@ -5881,7 +5890,7 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
5881{ 5890{
5882 FILE *fp = png_get_io_ptr (png_ptr); 5891 FILE *fp = png_get_io_ptr (png_ptr);
5883 5892
5884 if (fread (data, 1, length, fp) < length) 5893 if (fread_unlocked (data, 1, length, fp) < length)
5885 png_error (png_ptr, "Read error"); 5894 png_error (png_ptr, "Read error");
5886} 5895}
5887 5896
@@ -5950,7 +5959,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5950 } 5959 }
5951 5960
5952 /* Check PNG signature. */ 5961 /* Check PNG signature. */
5953 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 5962 if (fread_unlocked (sig, 1, sizeof sig, fp) != sizeof sig
5954 || png_sig_cmp (sig, 0, sizeof sig)) 5963 || png_sig_cmp (sig, 0, sizeof sig))
5955 { 5964 {
5956 fclose (fp); 5965 fclose (fp);
@@ -6589,7 +6598,8 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
6589 { 6598 {
6590 ptrdiff_t bytes; 6599 ptrdiff_t bytes;
6591 6600
6592 bytes = fread (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE, src->file); 6601 bytes = fread_unlocked (src->buffer, 1, JPEG_STDIO_BUFFER_SIZE,
6602 src->file);
6593 if (bytes > 0) 6603 if (bytes > 0)
6594 src->mgr.bytes_in_buffer = bytes; 6604 src->mgr.bytes_in_buffer = bytes;
6595 else 6605 else
diff --git a/src/indent.c b/src/indent.c
index f630ebb847c..adecc3622a8 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -925,6 +925,7 @@ position_indentation (ptrdiff_t pos_byte)
925 case 0240: 925 case 0240:
926 if (! NILP (BVAR (current_buffer, enable_multibyte_characters))) 926 if (! NILP (BVAR (current_buffer, enable_multibyte_characters)))
927 return column; 927 return column;
928 FALLTHROUGH;
928 case ' ': 929 case ' ':
929 column++; 930 column++;
930 break; 931 break;
diff --git a/src/inotify.c b/src/inotify.c
index 290701349ef..3d5d3d2621f 100644
--- a/src/inotify.c
+++ b/src/inotify.c
@@ -41,7 +41,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
41#ifndef IN_ONLYDIR 41#ifndef IN_ONLYDIR
42# define IN_ONLYDIR 0 42# define IN_ONLYDIR 0
43#endif 43#endif
44#define INOTIFY_DEFAULT_MASK (IN_ALL_EVENTS | IN_EXCL_UNLINK)
45 44
46/* File handle for inotify. */ 45/* File handle for inotify. */
47static int inotifyfd = -1; 46static int inotifyfd = -1;
@@ -58,7 +57,6 @@ static int inotifyfd = -1;
58 IN_EXCL_UNLINK 57 IN_EXCL_UNLINK
59 IN_MASK_ADD 58 IN_MASK_ADD
60 IN_ONESHOT 59 IN_ONESHOT
61 IN_ONLYDIR
62 60
63 Each element of this list is of the form (DESCRIPTOR . WATCHES) 61 Each element of this list is of the form (DESCRIPTOR . WATCHES)
64 where no two DESCRIPTOR values are the same. DESCRIPTOR represents 62 where no two DESCRIPTOR values are the same. DESCRIPTOR represents
@@ -145,6 +143,8 @@ symbol_to_inotifymask (Lisp_Object symb)
145 143
146 else if (EQ (symb, Qdont_follow)) 144 else if (EQ (symb, Qdont_follow))
147 return IN_DONT_FOLLOW; 145 return IN_DONT_FOLLOW;
146 else if (EQ (symb, Qonlydir))
147 return IN_ONLYDIR;
148 148
149 else if (EQ (symb, Qt) || EQ (symb, Qall_events)) 149 else if (EQ (symb, Qt) || EQ (symb, Qall_events))
150 return IN_ALL_EVENTS; 150 return IN_ALL_EVENTS;
@@ -198,16 +198,15 @@ inotifyevent_to_event (Lisp_Object watch, struct inotify_event const *ev)
198} 198}
199 199
200/* Add a new watch to watch-descriptor WD watching FILENAME and using 200/* Add a new watch to watch-descriptor WD watching FILENAME and using
201 CALLBACK. Returns a cons (DESCRIPTOR . ID) uniquely identifying the 201 IMASK and CALLBACK. Return a cons (DESCRIPTOR . ID) uniquely
202 new watch. */ 202 identifying the new watch. */
203static Lisp_Object 203static Lisp_Object
204add_watch (int wd, Lisp_Object filename, 204add_watch (int wd, Lisp_Object filename,
205 Lisp_Object aspect, Lisp_Object callback) 205 uint32_t imask, Lisp_Object callback)
206{ 206{
207 Lisp_Object descriptor = INTEGER_TO_CONS (wd); 207 Lisp_Object descriptor = INTEGER_TO_CONS (wd);
208 Lisp_Object tail = assoc_no_quit (descriptor, watch_list); 208 Lisp_Object tail = assoc_no_quit (descriptor, watch_list);
209 Lisp_Object watch, watch_id; 209 Lisp_Object watch, watch_id;
210 uint32_t imask = aspect_to_inotifymask (aspect);
211 Lisp_Object mask = INTEGER_TO_CONS (imask); 210 Lisp_Object mask = INTEGER_TO_CONS (imask);
212 211
213 EMACS_INT id = 0; 212 EMACS_INT id = 0;
@@ -381,9 +380,11 @@ all-events or t
381move 380move
382close 381close
383 382
384The following symbols can also be added to a list of aspects: 383ASPECT can also contain the following symbols, which control whether
384the watch descriptor will be created:
385 385
386dont-follow 386dont-follow
387onlydir
387 388
388Watching a directory is not recursive. CALLBACK is passed a single argument 389Watching a directory is not recursive. CALLBACK is passed a single argument
389EVENT which contains an event structure of the format 390EVENT which contains an event structure of the format
@@ -409,22 +410,18 @@ See inotify(7) and inotify_add_watch(2) for further information. The
409inotify fd is managed internally and there is no corresponding 410inotify fd is managed internally and there is no corresponding
410inotify_init. Use `inotify-rm-watch' to remove a watch. 411inotify_init. Use `inotify-rm-watch' to remove a watch.
411 412
412Also note, that the following inotify bit-masks can not be used, due 413The following inotify bit-masks cannot be used because descriptors are
413to the fact that descriptors are shared across different callers. 414shared across different callers.
414 415
415IN_EXCL_UNLINK 416IN_EXCL_UNLINK
416IN_MASK_ADD 417IN_MASK_ADD
417IN_ONESHOT 418IN_ONESHOT */)
418IN_ONLYDIR */)
419 (Lisp_Object filename, Lisp_Object aspect, Lisp_Object callback) 419 (Lisp_Object filename, Lisp_Object aspect, Lisp_Object callback)
420{ 420{
421 Lisp_Object encoded_file_name; 421 Lisp_Object encoded_file_name;
422 bool dont_follow = (CONSP (aspect)
423 ? ! NILP (Fmemq (Qdont_follow, aspect))
424 : EQ (Qdont_follow, aspect));
425 int wd = -1; 422 int wd = -1;
426 uint32_t mask = (INOTIFY_DEFAULT_MASK 423 uint32_t imask = aspect_to_inotifymask (aspect);
427 | (dont_follow ? IN_DONT_FOLLOW : 0)); 424 uint32_t mask = imask | IN_MASK_ADD | IN_EXCL_UNLINK;
428 425
429 CHECK_STRING (filename); 426 CHECK_STRING (filename);
430 427
@@ -442,7 +439,7 @@ IN_ONLYDIR */)
442 if (wd < 0) 439 if (wd < 0)
443 report_file_notify_error ("Could not add watch for file", filename); 440 report_file_notify_error ("Could not add watch for file", filename);
444 441
445 return add_watch (wd, filename, aspect, callback); 442 return add_watch (wd, filename, imask, callback);
446} 443}
447 444
448static bool 445static bool
@@ -534,6 +531,7 @@ syms_of_inotify (void)
534 DEFSYM (Qclose, "close"); /* IN_CLOSE */ 531 DEFSYM (Qclose, "close"); /* IN_CLOSE */
535 532
536 DEFSYM (Qdont_follow, "dont-follow"); /* IN_DONT_FOLLOW */ 533 DEFSYM (Qdont_follow, "dont-follow"); /* IN_DONT_FOLLOW */
534 DEFSYM (Qonlydir, "onlydir"); /* IN_ONLYDIR */
537 535
538 DEFSYM (Qignored, "ignored"); /* IN_IGNORED */ 536 DEFSYM (Qignored, "ignored"); /* IN_IGNORED */
539 DEFSYM (Qisdir, "isdir"); /* IN_ISDIR */ 537 DEFSYM (Qisdir, "isdir"); /* IN_ISDIR */
diff --git a/src/intervals.h b/src/intervals.h
index db91b3f21a0..a0da6f37801 100644
--- a/src/intervals.h
+++ b/src/intervals.h
@@ -85,10 +85,10 @@ struct interval
85#define LEAF_INTERVAL_P(i) ((i)->left == NULL && (i)->right == NULL) 85#define LEAF_INTERVAL_P(i) ((i)->left == NULL && (i)->right == NULL)
86 86
87/* True if this interval has no parent and is therefore the root. */ 87/* True if this interval has no parent and is therefore the root. */
88#define ROOT_INTERVAL_P(i) (NULL_PARENT (i)) 88#define ROOT_INTERVAL_P(i) NULL_PARENT (i)
89 89
90/* True if this interval is the only interval in the interval tree. */ 90/* True if this interval is the only interval in the interval tree. */
91#define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P ((i)) && LEAF_INTERVAL_P ((i))) 91#define ONLY_INTERVAL_P(i) (ROOT_INTERVAL_P (i) && LEAF_INTERVAL_P (i))
92 92
93/* True if this interval has both left and right children. */ 93/* True if this interval has both left and right children. */
94#define BOTH_KIDS_P(i) ((i)->left != NULL && (i)->right != NULL) 94#define BOTH_KIDS_P(i) ((i)->left != NULL && (i)->right != NULL)
@@ -98,13 +98,13 @@ struct interval
98#define TOTAL_LENGTH(i) ((i) == NULL ? 0 : (i)->total_length) 98#define TOTAL_LENGTH(i) ((i) == NULL ? 0 : (i)->total_length)
99 99
100/* The size of text represented by this interval alone. */ 100/* The size of text represented by this interval alone. */
101#define LENGTH(i) ((i) == NULL ? 0 : (TOTAL_LENGTH ((i)) \ 101#define LENGTH(i) ((i)->total_length \
102 - TOTAL_LENGTH ((i)->right) \ 102 - TOTAL_LENGTH ((i)->right) \
103 - TOTAL_LENGTH ((i)->left))) 103 - TOTAL_LENGTH ((i)->left))
104 104
105/* The position of the character just past the end of I. Note that 105/* The position of the character just past the end of I. Note that
106 the position cache i->position must be valid for this to work. */ 106 the position cache i->position must be valid for this to work. */
107#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH ((i))) 107#define INTERVAL_LAST_POS(i) ((i)->position + LENGTH (i))
108 108
109/* The total size of the left subtree of this interval. */ 109/* The total size of the left subtree of this interval. */
110#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0) 110#define LEFT_TOTAL_LENGTH(i) ((i)->left ? (i)->left->total_length : 0)
diff --git a/src/keyboard.c b/src/keyboard.c
index 2e0a813bb08..9e90899c569 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -39,6 +39,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
39#include "intervals.h" 39#include "intervals.h"
40#include "keymap.h" 40#include "keymap.h"
41#include "blockinput.h" 41#include "blockinput.h"
42#include "sysstdio.h"
42#include "systime.h" 43#include "systime.h"
43#include "atimer.h" 44#include "atimer.h"
44#include "process.h" 45#include "process.h"
@@ -634,7 +635,8 @@ echo_length (void)
634static void 635static void
635echo_truncate (ptrdiff_t nchars) 636echo_truncate (ptrdiff_t nchars)
636{ 637{
637 if (STRINGP (KVAR (current_kboard, echo_string))) 638 Lisp_Object es = KVAR (current_kboard, echo_string);
639 if (STRINGP (es) && SCHARS (es) > nchars)
638 kset_echo_string (current_kboard, 640 kset_echo_string (current_kboard,
639 Fsubstring (KVAR (current_kboard, echo_string), 641 Fsubstring (KVAR (current_kboard, echo_string),
640 make_number (0), make_number (nchars))); 642 make_number (0), make_number (nchars)));
@@ -3289,7 +3291,7 @@ record_char (Lisp_Object c)
3289 if (INTEGERP (c)) 3291 if (INTEGERP (c))
3290 { 3292 {
3291 if (XUINT (c) < 0x100) 3293 if (XUINT (c) < 0x100)
3292 putc (XUINT (c), dribble); 3294 putc_unlocked (XUINT (c), dribble);
3293 else 3295 else
3294 fprintf (dribble, " 0x%"pI"x", XUINT (c)); 3296 fprintf (dribble, " 0x%"pI"x", XUINT (c));
3295 } 3297 }
@@ -3302,15 +3304,15 @@ record_char (Lisp_Object c)
3302 3304
3303 if (SYMBOLP (dribblee)) 3305 if (SYMBOLP (dribblee))
3304 { 3306 {
3305 putc ('<', dribble); 3307 putc_unlocked ('<', dribble);
3306 fwrite (SDATA (SYMBOL_NAME (dribblee)), sizeof (char), 3308 fwrite_unlocked (SDATA (SYMBOL_NAME (dribblee)), sizeof (char),
3307 SBYTES (SYMBOL_NAME (dribblee)), 3309 SBYTES (SYMBOL_NAME (dribblee)),
3308 dribble); 3310 dribble);
3309 putc ('>', dribble); 3311 putc_unlocked ('>', dribble);
3310 } 3312 }
3311 } 3313 }
3312 3314
3313 fflush (dribble); 3315 fflush_unlocked (dribble);
3314 unblock_input (); 3316 unblock_input ();
3315 } 3317 }
3316} 3318}
@@ -3768,7 +3770,7 @@ kbd_buffer_get_event (KBOARD **kbp,
3768 detaching from the terminal. */ 3770 detaching from the terminal. */
3769 || (IS_DAEMON && DAEMON_RUNNING)) 3771 || (IS_DAEMON && DAEMON_RUNNING))
3770 { 3772 {
3771 int c = getchar (); 3773 int c = getchar_unlocked ();
3772 XSETINT (obj, c); 3774 XSETINT (obj, c);
3773 *kbp = current_kboard; 3775 *kbp = current_kboard;
3774 return obj; 3776 return obj;
@@ -4056,6 +4058,14 @@ kbd_buffer_get_event (KBOARD **kbp,
4056 kbd_fetch_ptr = event + 1; 4058 kbd_fetch_ptr = event + 1;
4057 } 4059 }
4058#endif 4060#endif
4061#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (HAVE_NS)
4062 else if (event->kind == MOVE_FRAME_EVENT)
4063 {
4064 /* Make an event (move-frame (FRAME)). */
4065 obj = list2 (Qmove_frame, list1 (event->ie.frame_or_window));
4066 kbd_fetch_ptr = event + 1;
4067 }
4068#endif
4059#ifdef HAVE_XWIDGETS 4069#ifdef HAVE_XWIDGETS
4060 else if (event->kind == XWIDGET_EVENT) 4070 else if (event->kind == XWIDGET_EVENT)
4061 { 4071 {
@@ -4068,6 +4078,11 @@ kbd_buffer_get_event (KBOARD **kbp,
4068 obj = make_lispy_event (&event->ie); 4078 obj = make_lispy_event (&event->ie);
4069 kbd_fetch_ptr = event + 1; 4079 kbd_fetch_ptr = event + 1;
4070 } 4080 }
4081 else if (event->kind == SELECT_WINDOW_EVENT)
4082 {
4083 obj = list2 (Qselect_window, list1 (event->ie.frame_or_window));
4084 kbd_fetch_ptr = event + 1;
4085 }
4071 else 4086 else
4072 { 4087 {
4073 /* If this event is on a different frame, return a switch-frame this 4088 /* If this event is on a different frame, return a switch-frame this
@@ -5112,6 +5127,17 @@ static short const scroll_bar_parts[] = {
5112 SYMBOL_INDEX (Qrightmost), SYMBOL_INDEX (Qend_scroll), SYMBOL_INDEX (Qratio) 5127 SYMBOL_INDEX (Qrightmost), SYMBOL_INDEX (Qend_scroll), SYMBOL_INDEX (Qratio)
5113}; 5128};
5114 5129
5130/* An array of symbol indexes of internal border parts, indexed by an enum
5131 internal_border_part value. Note that Qnil corresponds to
5132 internal_border_part_none and should not appear in Lisp events. */
5133static short const internal_border_parts[] = {
5134 SYMBOL_INDEX (Qnil), SYMBOL_INDEX (Qleft_edge),
5135 SYMBOL_INDEX (Qtop_left_corner), SYMBOL_INDEX (Qtop_edge),
5136 SYMBOL_INDEX (Qtop_right_corner), SYMBOL_INDEX (Qright_edge),
5137 SYMBOL_INDEX (Qbottom_right_corner), SYMBOL_INDEX (Qbottom_edge),
5138 SYMBOL_INDEX (Qbottom_left_corner)
5139};
5140
5115/* A vector, indexed by button number, giving the down-going location 5141/* A vector, indexed by button number, giving the down-going location
5116 of currently depressed buttons, both scroll bar and non-scroll bar. 5142 of currently depressed buttons, both scroll bar and non-scroll bar.
5117 5143
@@ -5149,15 +5175,15 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
5149 Lisp_Object extra_info = Qnil; 5175 Lisp_Object extra_info = Qnil;
5150 /* Coordinate pixel positions to return. */ 5176 /* Coordinate pixel positions to return. */
5151 int xret = 0, yret = 0; 5177 int xret = 0, yret = 0;
5152 /* The window under frame pixel coordinates (x,y) */ 5178 /* The window or frame under frame pixel coordinates (x,y) */
5153 Lisp_Object window = f 5179 Lisp_Object window_or_frame = f
5154 ? window_from_coordinates (f, XINT (x), XINT (y), &part, 0) 5180 ? window_from_coordinates (f, XINT (x), XINT (y), &part, 0)
5155 : Qnil; 5181 : Qnil;
5156 5182
5157 if (WINDOWP (window)) 5183 if (WINDOWP (window_or_frame))
5158 { 5184 {
5159 /* It's a click in window WINDOW at frame coordinates (X,Y) */ 5185 /* It's a click in window WINDOW at frame coordinates (X,Y) */
5160 struct window *w = XWINDOW (window); 5186 struct window *w = XWINDOW (window_or_frame);
5161 Lisp_Object string_info = Qnil; 5187 Lisp_Object string_info = Qnil;
5162 ptrdiff_t textpos = 0; 5188 ptrdiff_t textpos = 0;
5163 int col = -1, row = -1; 5189 int col = -1, row = -1;
@@ -5346,17 +5372,31 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
5346 make_number (row)), 5372 make_number (row)),
5347 extra_info))); 5373 extra_info)));
5348 } 5374 }
5349 else if (f != 0) 5375
5376#ifdef HAVE_WINDOW_SYSTEM
5377 else if (f)
5350 { 5378 {
5351 /* Return mouse pixel coordinates here. */ 5379 /* Return mouse pixel coordinates here. */
5352 XSETFRAME (window, f); 5380 XSETFRAME (window_or_frame, f);
5353 xret = XINT (x); 5381 xret = XINT (x);
5354 yret = XINT (y); 5382 yret = XINT (y);
5383
5384 if (FRAME_LIVE_P (f)
5385 && FRAME_INTERNAL_BORDER_WIDTH (f) > 0
5386 && !NILP (get_frame_param (f, Qdrag_internal_border)))
5387 {
5388 enum internal_border_part part
5389 = frame_internal_border_part (f, xret, yret);
5390
5391 posn = builtin_lisp_symbol (internal_border_parts[part]);
5392 }
5355 } 5393 }
5394#endif
5395
5356 else 5396 else
5357 window = Qnil; 5397 window_or_frame = Qnil;
5358 5398
5359 return Fcons (window, 5399 return Fcons (window_or_frame,
5360 Fcons (posn, 5400 Fcons (posn,
5361 Fcons (Fcons (make_number (xret), 5401 Fcons (Fcons (make_number (xret),
5362 make_number (yret)), 5402 make_number (yret)),
@@ -10363,7 +10403,7 @@ handle_interrupt (bool in_signal_handler)
10363 sigemptyset (&blocked); 10403 sigemptyset (&blocked);
10364 sigaddset (&blocked, SIGINT); 10404 sigaddset (&blocked, SIGINT);
10365 pthread_sigmask (SIG_BLOCK, &blocked, 0); 10405 pthread_sigmask (SIG_BLOCK, &blocked, 0);
10366 fflush (stdout); 10406 fflush_unlocked (stdout);
10367 } 10407 }
10368 10408
10369 reset_all_sys_modes (); 10409 reset_all_sys_modes ();
@@ -10977,6 +11017,7 @@ static const struct event_head head_table[] = {
10977 11017
10978 {SYMBOL_INDEX (Qfocus_in), SYMBOL_INDEX (Qfocus_in)}, 11018 {SYMBOL_INDEX (Qfocus_in), SYMBOL_INDEX (Qfocus_in)},
10979 {SYMBOL_INDEX (Qfocus_out), SYMBOL_INDEX (Qfocus_out)}, 11019 {SYMBOL_INDEX (Qfocus_out), SYMBOL_INDEX (Qfocus_out)},
11020 {SYMBOL_INDEX (Qmove_frame), SYMBOL_INDEX (Qmove_frame)},
10980 {SYMBOL_INDEX (Qdelete_frame), SYMBOL_INDEX (Qdelete_frame)}, 11021 {SYMBOL_INDEX (Qdelete_frame), SYMBOL_INDEX (Qdelete_frame)},
10981 {SYMBOL_INDEX (Qiconify_frame), SYMBOL_INDEX (Qiconify_frame)}, 11022 {SYMBOL_INDEX (Qiconify_frame), SYMBOL_INDEX (Qiconify_frame)},
10982 {SYMBOL_INDEX (Qmake_frame_visible), SYMBOL_INDEX (Qmake_frame_visible)}, 11023 {SYMBOL_INDEX (Qmake_frame_visible), SYMBOL_INDEX (Qmake_frame_visible)},
@@ -11143,12 +11184,24 @@ syms_of_keyboard (void)
11143 Fset (Qinput_method_exit_on_first_char, Qnil); 11184 Fset (Qinput_method_exit_on_first_char, Qnil);
11144 Fset (Qinput_method_use_echo_area, Qnil); 11185 Fset (Qinput_method_use_echo_area, Qnil);
11145 11186
11187 /* Symbols for dragging internal borders. */
11188 DEFSYM (Qdrag_internal_border, "drag-internal-border");
11189 DEFSYM (Qleft_edge, "left-edge");
11190 DEFSYM (Qtop_left_corner, "top-left-corner");
11191 DEFSYM (Qtop_edge, "top-edge");
11192 DEFSYM (Qtop_right_corner, "top-right-corner");
11193 DEFSYM (Qright_edge, "right-edge");
11194 DEFSYM (Qbottom_right_corner, "bottom-right-corner");
11195 DEFSYM (Qbottom_edge, "bottom-edge");
11196 DEFSYM (Qbottom_left_corner, "bottom-left-corner");
11197
11146 /* Symbols to head events. */ 11198 /* Symbols to head events. */
11147 DEFSYM (Qmouse_movement, "mouse-movement"); 11199 DEFSYM (Qmouse_movement, "mouse-movement");
11148 DEFSYM (Qscroll_bar_movement, "scroll-bar-movement"); 11200 DEFSYM (Qscroll_bar_movement, "scroll-bar-movement");
11149 DEFSYM (Qswitch_frame, "switch-frame"); 11201 DEFSYM (Qswitch_frame, "switch-frame");
11150 DEFSYM (Qfocus_in, "focus-in"); 11202 DEFSYM (Qfocus_in, "focus-in");
11151 DEFSYM (Qfocus_out, "focus-out"); 11203 DEFSYM (Qfocus_out, "focus-out");
11204 DEFSYM (Qmove_frame, "move-frame");
11152 DEFSYM (Qdelete_frame, "delete-frame"); 11205 DEFSYM (Qdelete_frame, "delete-frame");
11153 DEFSYM (Qiconify_frame, "iconify-frame"); 11206 DEFSYM (Qiconify_frame, "iconify-frame");
11154 DEFSYM (Qmake_frame_visible, "make-frame-visible"); 11207 DEFSYM (Qmake_frame_visible, "make-frame-visible");
@@ -11895,6 +11948,8 @@ keys_of_keyboard (void)
11895 "handle-focus-in"); 11948 "handle-focus-in");
11896 initial_define_lispy_key (Vspecial_event_map, "focus-out", 11949 initial_define_lispy_key (Vspecial_event_map, "focus-out",
11897 "handle-focus-out"); 11950 "handle-focus-out");
11951 initial_define_lispy_key (Vspecial_event_map, "move-frame",
11952 "handle-move-frame");
11898} 11953}
11899 11954
11900/* Mark the pointers in the kboard objects. 11955/* Mark the pointers in the kboard objects.
diff --git a/src/kqueue.c b/src/kqueue.c
index 8e6b1e149f7..a8eb4cb797c 100644
--- a/src/kqueue.c
+++ b/src/kqueue.c
@@ -42,7 +42,7 @@ static Lisp_Object watch_list;
42 42
43/* Generate a list from the directory_files_internal output. 43/* Generate a list from the directory_files_internal output.
44 Items are (INODE FILE-NAME LAST-MOD LAST-STATUS-MOD SIZE). */ 44 Items are (INODE FILE-NAME LAST-MOD LAST-STATUS-MOD SIZE). */
45Lisp_Object 45static Lisp_Object
46kqueue_directory_listing (Lisp_Object directory_files) 46kqueue_directory_listing (Lisp_Object directory_files)
47{ 47{
48 Lisp_Object dl, result = Qnil; 48 Lisp_Object dl, result = Qnil;
diff --git a/src/lisp.h b/src/lisp.h
index 3125bd2a5dd..ff8dde2b825 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -466,9 +466,6 @@ enum Lisp_Misc_Type
466#ifdef HAVE_MODULES 466#ifdef HAVE_MODULES
467 Lisp_Misc_User_Ptr, 467 Lisp_Misc_User_Ptr,
468#endif 468#endif
469 /* Currently floats are not a misc type,
470 but let's define this in case we want to change that. */
471 Lisp_Misc_Float,
472 /* This is not a type code. It is for range checking. */ 469 /* This is not a type code. It is for range checking. */
473 Lisp_Misc_Limit 470 Lisp_Misc_Limit
474 }; 471 };
@@ -545,7 +542,7 @@ enum Lisp_Fwd_Type
545 542
546#ifdef CHECK_LISP_OBJECT_TYPE 543#ifdef CHECK_LISP_OBJECT_TYPE
547 544
548typedef struct { EMACS_INT i; } Lisp_Object; 545typedef struct Lisp_Object { EMACS_INT i; } Lisp_Object;
549 546
550#define LISP_INITIALLY(i) {i} 547#define LISP_INITIALLY(i) {i}
551 548
@@ -884,11 +881,13 @@ enum pvec_type
884 PVEC_THREAD, 881 PVEC_THREAD,
885 PVEC_MUTEX, 882 PVEC_MUTEX,
886 PVEC_CONDVAR, 883 PVEC_CONDVAR,
884 PVEC_MODULE_FUNCTION,
887 885
888 /* These should be last, check internal_equal to see why. */ 886 /* These should be last, check internal_equal to see why. */
889 PVEC_COMPILED, 887 PVEC_COMPILED,
890 PVEC_CHAR_TABLE, 888 PVEC_CHAR_TABLE,
891 PVEC_SUB_CHAR_TABLE, 889 PVEC_SUB_CHAR_TABLE,
890 PVEC_RECORD,
892 PVEC_FONT /* Should be last because it's used for range checking. */ 891 PVEC_FONT /* Should be last because it's used for range checking. */
893}; 892};
894 893
@@ -1344,7 +1343,9 @@ SSET (Lisp_Object string, ptrdiff_t index, unsigned char new)
1344INLINE ptrdiff_t 1343INLINE ptrdiff_t
1345SCHARS (Lisp_Object string) 1344SCHARS (Lisp_Object string)
1346{ 1345{
1347 return XSTRING (string)->size; 1346 ptrdiff_t nchars = XSTRING (string)->size;
1347 eassume (0 <= nchars);
1348 return nchars;
1348} 1349}
1349 1350
1350#ifdef GC_CHECK_STRING_BYTES 1351#ifdef GC_CHECK_STRING_BYTES
@@ -1354,10 +1355,12 @@ INLINE ptrdiff_t
1354STRING_BYTES (struct Lisp_String *s) 1355STRING_BYTES (struct Lisp_String *s)
1355{ 1356{
1356#ifdef GC_CHECK_STRING_BYTES 1357#ifdef GC_CHECK_STRING_BYTES
1357 return string_bytes (s); 1358 ptrdiff_t nbytes = string_bytes (s);
1358#else 1359#else
1359 return s->size_byte < 0 ? s->size : s->size_byte; 1360 ptrdiff_t nbytes = s->size_byte < 0 ? s->size : s->size_byte;
1360#endif 1361#endif
1362 eassume (0 <= nbytes);
1363 return nbytes;
1361} 1364}
1362 1365
1363INLINE ptrdiff_t 1366INLINE ptrdiff_t
@@ -1368,6 +1371,11 @@ SBYTES (Lisp_Object string)
1368INLINE void 1371INLINE void
1369STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize) 1372STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize)
1370{ 1373{
1374 /* This function cannot change the size of data allocated for the
1375 string when it was created. */
1376 eassert (STRING_MULTIBYTE (string)
1377 ? 0 <= newsize && newsize <= SBYTES (string)
1378 : newsize == SCHARS (string));
1371 XSTRING (string)->size = newsize; 1379 XSTRING (string)->size = newsize;
1372} 1380}
1373 1381
@@ -1400,6 +1408,12 @@ ASIZE (Lisp_Object array)
1400 return size; 1408 return size;
1401} 1409}
1402 1410
1411INLINE ptrdiff_t
1412PVSIZE (Lisp_Object pv)
1413{
1414 return ASIZE (pv) & PSEUDOVECTOR_SIZE_MASK;
1415}
1416
1403INLINE bool 1417INLINE bool
1404VECTORP (Lisp_Object x) 1418VECTORP (Lisp_Object x)
1405{ 1419{
@@ -1412,6 +1426,7 @@ CHECK_VECTOR (Lisp_Object x)
1412 CHECK_TYPE (VECTORP (x), Qvectorp, x); 1426 CHECK_TYPE (VECTORP (x), Qvectorp, x);
1413} 1427}
1414 1428
1429
1415/* A pseudovector is like a vector, but has other non-Lisp components. */ 1430/* A pseudovector is like a vector, but has other non-Lisp components. */
1416 1431
1417INLINE enum pvec_type 1432INLINE enum pvec_type
@@ -2732,6 +2747,18 @@ FRAMEP (Lisp_Object a)
2732 return PSEUDOVECTORP (a, PVEC_FRAME); 2747 return PSEUDOVECTORP (a, PVEC_FRAME);
2733} 2748}
2734 2749
2750INLINE bool
2751RECORDP (Lisp_Object a)
2752{
2753 return PSEUDOVECTORP (a, PVEC_RECORD);
2754}
2755
2756INLINE void
2757CHECK_RECORD (Lisp_Object x)
2758{
2759 CHECK_TYPE (RECORDP (x), Qrecordp, x);
2760}
2761
2735/* Test for image (image . spec) */ 2762/* Test for image (image . spec) */
2736INLINE bool 2763INLINE bool
2737IMAGEP (Lisp_Object x) 2764IMAGEP (Lisp_Object x)
@@ -3861,11 +3888,62 @@ extern void get_backtrace (Lisp_Object array);
3861Lisp_Object backtrace_top_function (void); 3888Lisp_Object backtrace_top_function (void);
3862extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); 3889extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol);
3863 3890
3891/* Defined in unexmacosx.c. */
3892#if defined DARWIN_OS && !defined CANNOT_DUMP
3893extern void unexec_init_emacs_zone (void);
3894extern void *unexec_malloc (size_t);
3895extern void *unexec_realloc (void *, size_t);
3896extern void unexec_free (void *);
3897#endif
3898
3899#include "emacs-module.h"
3900
3901/* Function prototype for the module Lisp functions. */
3902typedef emacs_value (*emacs_subr) (emacs_env *, ptrdiff_t,
3903 emacs_value [], void *);
3904
3905/* Module function. */
3906
3907/* A function environment is an auxiliary structure returned by
3908 `module_make_function' to store information about a module
3909 function. It is stored in a pseudovector. Its members correspond
3910 to the arguments given to `module_make_function'. */
3911
3912struct Lisp_Module_Function
3913{
3914 struct vectorlike_header header;
3915
3916 /* Fields traced by GC; these must come first. */
3917 Lisp_Object documentation;
3918
3919 /* Fields ignored by GC. */
3920 ptrdiff_t min_arity, max_arity;
3921 emacs_subr subr;
3922 void *data;
3923};
3924
3925INLINE bool
3926MODULE_FUNCTIONP (Lisp_Object o)
3927{
3928 return PSEUDOVECTORP (o, PVEC_MODULE_FUNCTION);
3929}
3930
3931INLINE struct Lisp_Module_Function *
3932XMODULE_FUNCTION (Lisp_Object o)
3933{
3934 eassert (MODULE_FUNCTIONP (o));
3935 return XUNTAG (o, Lisp_Vectorlike);
3936}
3937
3864#ifdef HAVE_MODULES 3938#ifdef HAVE_MODULES
3865/* Defined in alloc.c. */ 3939/* Defined in alloc.c. */
3866extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); 3940extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p);
3867 3941
3868/* Defined in emacs-module.c. */ 3942/* Defined in emacs-module.c. */
3943extern Lisp_Object funcall_module (Lisp_Object, ptrdiff_t, Lisp_Object *);
3944extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *);
3945extern void mark_modules (void);
3946extern void init_module_assertions (bool);
3869extern void syms_of_module (void); 3947extern void syms_of_module (void);
3870#endif 3948#endif
3871 3949
@@ -4077,7 +4155,7 @@ extern bool no_site_lisp;
4077extern bool build_details; 4155extern bool build_details;
4078 4156
4079#ifndef WINDOWSNT 4157#ifndef WINDOWSNT
4080/* 0 not a daemon, 1 new-style (foreground), 2 old-style (background). */ 4158/* 0 not a daemon, 1 foreground daemon, 2 background daemon. */
4081extern int daemon_type; 4159extern int daemon_type;
4082#define IS_DAEMON (daemon_type != 0) 4160#define IS_DAEMON (daemon_type != 0)
4083#define DAEMON_RUNNING (daemon_type >= 0) 4161#define DAEMON_RUNNING (daemon_type >= 0)
diff --git a/src/lread.c b/src/lread.c
index 5c6a7f97f52..182f96223a5 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -72,11 +72,36 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
72#define file_tell ftell 72#define file_tell ftell
73#endif 73#endif
74 74
75/* The association list of objects read with the #n=object form. 75/* The objects or placeholders read with the #n=object form.
76 Each member of the list has the form (n . object), and is used to 76
77 look up the object for the corresponding #n# construct. 77 A hash table maps a number to either a placeholder (while the
78 It must be set to nil before all top-level calls to read0. */ 78 object is still being parsed, in case it's referenced within its
79static Lisp_Object read_objects; 79 own definition) or to the completed object. With small integers
80 for keys, it's effectively little more than a vector, but it'll
81 manage any needed resizing for us.
82
83 The variable must be reset to an empty hash table before all
84 top-level calls to read0. In between calls, it may be an empty
85 hash table left unused from the previous call (to reduce
86 allocations), or nil. */
87static Lisp_Object read_objects_map;
88
89/* The recursive objects read with the #n=object form.
90
91 Objects that might have circular references are stored here, so
92 that recursive substitution knows not to keep processing them
93 multiple times.
94
95 Only objects that are completely processed, including substituting
96 references to themselves (but not necessarily replacing
97 placeholders for other objects still being read), are stored.
98
99 A hash table is used for efficient lookups of keys. We don't care
100 what the value slots hold. The variable must be set to an empty
101 hash table before all top-level calls to read0. In between calls,
102 it may be an empty hash table left unused from the previous call
103 (to reduce allocations), or nil. */
104static Lisp_Object read_objects_completed;
80 105
81/* File for get_file_char to read from. Use by load. */ 106/* File for get_file_char to read from. Use by load. */
82static FILE *instream; 107static FILE *instream;
@@ -445,16 +470,15 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
445 } 470 }
446 471
447 block_input (); 472 block_input ();
448 c = getc (instream);
449 473
450 /* Interrupted reads have been observed while reading over the network. */ 474 /* Interrupted reads have been observed while reading over the network. */
451 while (c == EOF && ferror (instream) && errno == EINTR) 475 while ((c = getc_unlocked (instream)) == EOF && errno == EINTR
476 && ferror_unlocked (instream))
452 { 477 {
453 unblock_input (); 478 unblock_input ();
454 maybe_quit (); 479 maybe_quit ();
455 block_input (); 480 block_input ();
456 clearerr (instream); 481 clearerr_unlocked (instream);
457 c = getc (instream);
458 } 482 }
459 483
460 unblock_input (); 484 unblock_input ();
@@ -757,7 +781,7 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0,
757{ 781{
758 register Lisp_Object val; 782 register Lisp_Object val;
759 block_input (); 783 block_input ();
760 XSETINT (val, getc (instream)); 784 XSETINT (val, getc_unlocked (instream));
761 unblock_input (); 785 unblock_input ();
762 return val; 786 return val;
763} 787}
@@ -948,13 +972,30 @@ load_error_handler (Lisp_Object data)
948static void 972static void
949load_warn_old_style_backquotes (Lisp_Object file) 973load_warn_old_style_backquotes (Lisp_Object file)
950{ 974{
951 if (!NILP (Vold_style_backquotes)) 975 if (!NILP (Vlread_old_style_backquotes))
952 { 976 {
953 AUTO_STRING (format, "Loading `%s': old-style backquotes detected!"); 977 AUTO_STRING (format, "Loading `%s': old-style backquotes detected!");
954 CALLN (Fmessage, format, file); 978 CALLN (Fmessage, format, file);
955 } 979 }
956} 980}
957 981
982static void
983load_warn_unescaped_character_literals (Lisp_Object file)
984{
985 if (NILP (Vlread_unescaped_character_literals)) return;
986 CHECK_CONS (Vlread_unescaped_character_literals);
987 Lisp_Object format =
988 build_string ("Loading `%s': unescaped character literals %s detected!");
989 Lisp_Object separator = build_string (", ");
990 Lisp_Object inner_format = build_string ("`?%c'");
991 CALLN (Fmessage,
992 format, file,
993 Fmapconcat (list3 (Qlambda, list1 (Qchar),
994 list3 (Qformat, inner_format, Qchar)),
995 Fsort (Vlread_unescaped_character_literals, Qlss),
996 separator));
997}
998
958DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0, 999DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0,
959 doc: /* Return the suffixes that `load' should try if a suffix is \ 1000 doc: /* Return the suffixes that `load' should try if a suffix is \
960required. 1001required.
@@ -1199,9 +1240,14 @@ Return t if the file exists and loads successfully. */)
1199 version = -1; 1240 version = -1;
1200 1241
1201 /* Check for the presence of old-style quotes and warn about them. */ 1242 /* Check for the presence of old-style quotes and warn about them. */
1202 specbind (Qold_style_backquotes, Qnil); 1243 specbind (Qlread_old_style_backquotes, Qnil);
1203 record_unwind_protect (load_warn_old_style_backquotes, file); 1244 record_unwind_protect (load_warn_old_style_backquotes, file);
1204 1245
1246 /* Check for the presence of unescaped character literals and warn
1247 about them. */
1248 specbind (Qlread_unescaped_character_literals, Qnil);
1249 record_unwind_protect (load_warn_unescaped_character_literals, file);
1250
1205 int is_elc; 1251 int is_elc;
1206 if ((is_elc = suffix_p (found, ".elc")) != 0 1252 if ((is_elc = suffix_p (found, ".elc")) != 0
1207 /* version = 1 means the file is empty, in which case we can 1253 /* version = 1 means the file is empty, in which case we can
@@ -1865,7 +1911,7 @@ readevalloop (Lisp_Object readcharfun,
1865 /* On the first cycle, we can easily test here 1911 /* On the first cycle, we can easily test here
1866 whether we are reading the whole buffer. */ 1912 whether we are reading the whole buffer. */
1867 if (b && first_sexp) 1913 if (b && first_sexp)
1868 whole_buffer = (PT == BEG && ZV == Z); 1914 whole_buffer = (BUF_PT (b) == BUF_BEG (b) && BUF_ZV (b) == BUF_Z (b));
1869 1915
1870 instream = stream; 1916 instream = stream;
1871 read_next: 1917 read_next:
@@ -1886,6 +1932,18 @@ readevalloop (Lisp_Object readcharfun,
1886 || c == NO_BREAK_SPACE) 1932 || c == NO_BREAK_SPACE)
1887 goto read_next; 1933 goto read_next;
1888 1934
1935 if (! HASH_TABLE_P (read_objects_map)
1936 || XHASH_TABLE (read_objects_map)->count)
1937 read_objects_map
1938 = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
1939 DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
1940 Qnil, false);
1941 if (! HASH_TABLE_P (read_objects_completed)
1942 || XHASH_TABLE (read_objects_completed)->count)
1943 read_objects_completed
1944 = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE,
1945 DEFAULT_REHASH_SIZE, DEFAULT_REHASH_THRESHOLD,
1946 Qnil, false);
1889 if (!NILP (Vpurify_flag) && c == '(') 1947 if (!NILP (Vpurify_flag) && c == '(')
1890 { 1948 {
1891 val = read_list (0, readcharfun); 1949 val = read_list (0, readcharfun);
@@ -1893,7 +1951,6 @@ readevalloop (Lisp_Object readcharfun,
1893 else 1951 else
1894 { 1952 {
1895 UNREAD (c); 1953 UNREAD (c);
1896 read_objects = Qnil;
1897 if (!NILP (readfun)) 1954 if (!NILP (readfun))
1898 { 1955 {
1899 val = call1 (readfun, readcharfun); 1956 val = call1 (readfun, readcharfun);
@@ -1913,6 +1970,13 @@ readevalloop (Lisp_Object readcharfun,
1913 else 1970 else
1914 val = read_internal_start (readcharfun, Qnil, Qnil); 1971 val = read_internal_start (readcharfun, Qnil, Qnil);
1915 } 1972 }
1973 /* Empty hashes can be reused; otherwise, reset on next call. */
1974 if (HASH_TABLE_P (read_objects_map)
1975 && XHASH_TABLE (read_objects_map)->count > 0)
1976 read_objects_map = Qnil;
1977 if (HASH_TABLE_P (read_objects_completed)
1978 && XHASH_TABLE (read_objects_completed)->count > 0)
1979 read_objects_completed = Qnil;
1916 1980
1917 if (!NILP (start) && continue_reading_p) 1981 if (!NILP (start) && continue_reading_p)
1918 start = Fpoint_marker (); 1982 start = Fpoint_marker ();
@@ -1988,6 +2052,7 @@ This function preserves the position of point. */)
1988 record_unwind_protect (save_excursion_restore, save_excursion_save ()); 2052 record_unwind_protect (save_excursion_restore, save_excursion_save ());
1989 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); 2053 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
1990 specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil); 2054 specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil);
2055 BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf)));
1991 readevalloop (buf, 0, filename, 2056 readevalloop (buf, 0, filename,
1992 !NILP (printflag), unibyte, Qnil, Qnil, Qnil); 2057 !NILP (printflag), unibyte, Qnil, Qnil, Qnil);
1993 unbind_to (count, Qnil); 2058 unbind_to (count, Qnil);
@@ -2083,7 +2148,18 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
2083 2148
2084 readchar_count = 0; 2149 readchar_count = 0;
2085 new_backquote_flag = 0; 2150 new_backquote_flag = 0;
2086 read_objects = Qnil; 2151 /* We can get called from readevalloop which may have set these
2152 already. */
2153 if (! HASH_TABLE_P (read_objects_map)
2154 || XHASH_TABLE (read_objects_map)->count)
2155 read_objects_map
2156 = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
2157 DEFAULT_REHASH_THRESHOLD, Qnil, false);
2158 if (! HASH_TABLE_P (read_objects_completed)
2159 || XHASH_TABLE (read_objects_completed)->count)
2160 read_objects_completed
2161 = make_hash_table (hashtest_eq, DEFAULT_HASH_SIZE, DEFAULT_REHASH_SIZE,
2162 DEFAULT_REHASH_THRESHOLD, Qnil, false);
2087 if (EQ (Vread_with_symbol_positions, Qt) 2163 if (EQ (Vread_with_symbol_positions, Qt)
2088 || EQ (Vread_with_symbol_positions, stream)) 2164 || EQ (Vread_with_symbol_positions, stream))
2089 Vread_symbol_positions_list = Qnil; 2165 Vread_symbol_positions_list = Qnil;
@@ -2111,6 +2187,13 @@ read_internal_start (Lisp_Object stream, Lisp_Object start, Lisp_Object end)
2111 if (EQ (Vread_with_symbol_positions, Qt) 2187 if (EQ (Vread_with_symbol_positions, Qt)
2112 || EQ (Vread_with_symbol_positions, stream)) 2188 || EQ (Vread_with_symbol_positions, stream))
2113 Vread_symbol_positions_list = Fnreverse (Vread_symbol_positions_list); 2189 Vread_symbol_positions_list = Fnreverse (Vread_symbol_positions_list);
2190 /* Empty hashes can be reused; otherwise, reset on next call. */
2191 if (HASH_TABLE_P (read_objects_map)
2192 && XHASH_TABLE (read_objects_map)->count > 0)
2193 read_objects_map = Qnil;
2194 if (HASH_TABLE_P (read_objects_completed)
2195 && XHASH_TABLE (read_objects_completed)->count > 0)
2196 read_objects_completed = Qnil;
2114 return retval; 2197 return retval;
2115} 2198}
2116 2199
@@ -2286,6 +2369,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2286 c = READCHAR; 2369 c = READCHAR;
2287 if (c != '-') 2370 if (c != '-')
2288 error ("Invalid escape character syntax"); 2371 error ("Invalid escape character syntax");
2372 FALLTHROUGH;
2289 case '^': 2373 case '^':
2290 c = READCHAR; 2374 c = READCHAR;
2291 if (c == '\\') 2375 if (c == '\\')
@@ -2376,6 +2460,7 @@ read_escape (Lisp_Object readcharfun, bool stringp)
2376 case 'U': 2460 case 'U':
2377 /* Post-Unicode-2.0: Up to eight hex chars. */ 2461 /* Post-Unicode-2.0: Up to eight hex chars. */
2378 unicode_hex_count = 8; 2462 unicode_hex_count = 8;
2463 FALLTHROUGH;
2379 case 'u': 2464 case 'u':
2380 2465
2381 /* A Unicode escape. We only permit them in strings and characters, 2466 /* A Unicode escape. We only permit them in strings and characters,
@@ -2603,8 +2688,18 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2603 int param_count = 0; 2688 int param_count = 0;
2604 2689
2605 if (!EQ (head, Qhash_table)) 2690 if (!EQ (head, Qhash_table))
2606 error ("Invalid extended read marker at head of #s list " 2691 {
2607 "(only hash-table allowed)"); 2692 ptrdiff_t size = XINT (Flength (tmp));
2693 Lisp_Object record = Fmake_record (CAR_SAFE (tmp),
2694 make_number (size - 1),
2695 Qnil);
2696 for (int i = 1; i < size; i++)
2697 {
2698 tmp = Fcdr (tmp);
2699 ASET (record, i, Fcar (tmp));
2700 }
2701 return record;
2702 }
2608 2703
2609 tmp = CDR_SAFE (tmp); 2704 tmp = CDR_SAFE (tmp);
2610 2705
@@ -2866,7 +2961,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2866 /* Copy that many characters into saved_doc_string. */ 2961 /* Copy that many characters into saved_doc_string. */
2867 block_input (); 2962 block_input ();
2868 for (i = 0; i < nskip && c >= 0; i++) 2963 for (i = 0; i < nskip && c >= 0; i++)
2869 saved_doc_string[i] = c = getc (instream); 2964 saved_doc_string[i] = c = getc_unlocked (instream);
2870 unblock_input (); 2965 unblock_input ();
2871 2966
2872 saved_doc_string_length = i; 2967 saved_doc_string_length = i;
@@ -2939,7 +3034,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2939 /* Note: We used to use AUTO_CONS to allocate 3034 /* Note: We used to use AUTO_CONS to allocate
2940 placeholder, but that is a bad idea, since it 3035 placeholder, but that is a bad idea, since it
2941 will place a stack-allocated cons cell into 3036 will place a stack-allocated cons cell into
2942 the list in read_objects, which is a 3037 the list in read_objects_map, which is a
2943 staticpro'd global variable, and thus each of 3038 staticpro'd global variable, and thus each of
2944 its elements is marked during each GC. A 3039 its elements is marked during each GC. A
2945 stack-allocated object will become garbled 3040 stack-allocated object will become garbled
@@ -2948,27 +3043,62 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
2948 different purposes, which will cause crashes 3043 different purposes, which will cause crashes
2949 in GC. */ 3044 in GC. */
2950 Lisp_Object placeholder = Fcons (Qnil, Qnil); 3045 Lisp_Object placeholder = Fcons (Qnil, Qnil);
2951 Lisp_Object cell = Fcons (make_number (n), placeholder); 3046 struct Lisp_Hash_Table *h
2952 read_objects = Fcons (cell, read_objects); 3047 = XHASH_TABLE (read_objects_map);
3048 EMACS_UINT hash;
3049 Lisp_Object number = make_number (n);
3050
3051 ptrdiff_t i = hash_lookup (h, number, &hash);
3052 if (i >= 0)
3053 /* Not normal, but input could be malformed. */
3054 set_hash_value_slot (h, i, placeholder);
3055 else
3056 hash_put (h, number, placeholder, hash);
2953 3057
2954 /* Read the object itself. */ 3058 /* Read the object itself. */
2955 tem = read0 (readcharfun); 3059 tem = read0 (readcharfun);
2956 3060
3061 /* If it can be recursive, remember it for
3062 future substitutions. */
3063 if (! SYMBOLP (tem)
3064 && ! NUMBERP (tem)
3065 && ! (STRINGP (tem) && !string_intervals (tem)))
3066 {
3067 struct Lisp_Hash_Table *h2
3068 = XHASH_TABLE (read_objects_completed);
3069 i = hash_lookup (h2, tem, &hash);
3070 eassert (i < 0);
3071 hash_put (h2, tem, Qnil, hash);
3072 }
3073
2957 /* Now put it everywhere the placeholder was... */ 3074 /* Now put it everywhere the placeholder was... */
2958 Fsubstitute_object_in_subtree (tem, placeholder); 3075 if (CONSP (tem))
3076 {
3077 Fsetcar (placeholder, XCAR (tem));
3078 Fsetcdr (placeholder, XCDR (tem));
3079 return placeholder;
3080 }
3081 else
3082 {
3083 Fsubstitute_object_in_subtree (tem, placeholder);
2959 3084
2960 /* ...and #n# will use the real value from now on. */ 3085 /* ...and #n# will use the real value from now on. */
2961 Fsetcdr (cell, tem); 3086 i = hash_lookup (h, number, &hash);
3087 eassert (i >= 0);
3088 set_hash_value_slot (h, i, tem);
2962 3089
2963 return tem; 3090 return tem;
3091 }
2964 } 3092 }
2965 3093
2966 /* #n# returns a previously read object. */ 3094 /* #n# returns a previously read object. */
2967 if (c == '#') 3095 if (c == '#')
2968 { 3096 {
2969 tem = Fassq (make_number (n), read_objects); 3097 struct Lisp_Hash_Table *h
2970 if (CONSP (tem)) 3098 = XHASH_TABLE (read_objects_map);
2971 return XCDR (tem); 3099 ptrdiff_t i = hash_lookup (h, make_number (n), NULL);
3100 if (i >= 0)
3101 return HASH_VALUE (h, i);
2972 } 3102 }
2973 } 3103 }
2974 } 3104 }
@@ -3007,7 +3137,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3007 "(\`" anyway). */ 3137 "(\`" anyway). */
3008 if (!new_backquote_flag && first_in_list && next_char == ' ') 3138 if (!new_backquote_flag && first_in_list && next_char == ' ')
3009 { 3139 {
3010 Vold_style_backquotes = Qt; 3140 Vlread_old_style_backquotes = Qt;
3011 goto default_label; 3141 goto default_label;
3012 } 3142 }
3013 else 3143 else
@@ -3061,7 +3191,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3061 } 3191 }
3062 else 3192 else
3063 { 3193 {
3064 Vold_style_backquotes = Qt; 3194 Vlread_old_style_backquotes = Qt;
3065 goto default_label; 3195 goto default_label;
3066 } 3196 }
3067 } 3197 }
@@ -3082,6 +3212,16 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3082 if (c == ' ' || c == '\t') 3212 if (c == ' ' || c == '\t')
3083 return make_number (c); 3213 return make_number (c);
3084 3214
3215 if (c == '(' || c == ')' || c == '[' || c == ']'
3216 || c == '"' || c == ';')
3217 {
3218 CHECK_LIST (Vlread_unescaped_character_literals);
3219 Lisp_Object char_obj = make_natnum (c);
3220 if (NILP (Fmemq (char_obj, Vlread_unescaped_character_literals)))
3221 Vlread_unescaped_character_literals =
3222 Fcons (char_obj, Vlread_unescaped_character_literals);
3223 }
3224
3085 if (c == '\\') 3225 if (c == '\\')
3086 c = read_escape (readcharfun, 0); 3226 c = read_escape (readcharfun, 0);
3087 modifiers = c & CHAR_MODIFIER_MASK; 3227 modifiers = c & CHAR_MODIFIER_MASK;
@@ -3235,11 +3375,11 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3235 *pch = c; 3375 *pch = c;
3236 return Qnil; 3376 return Qnil;
3237 } 3377 }
3238
3239 /* Otherwise, we fall through! Note that the atom-reading loop
3240 below will now loop at least once, assuring that we will not
3241 try to UNREAD two characters in a row. */
3242 } 3378 }
3379 /* The atom-reading loop below will now loop at least once,
3380 assuring that we will not try to UNREAD two characters in a
3381 row. */
3382 FALLTHROUGH;
3243 default: 3383 default:
3244 default_label: 3384 default_label:
3245 if (c <= 040) goto retry; 3385 if (c <= 040) goto retry;
@@ -3297,25 +3437,51 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list)
3297 if (! NILP (result)) 3437 if (! NILP (result))
3298 return unbind_to (count, result); 3438 return unbind_to (count, result);
3299 } 3439 }
3440 {
3441 Lisp_Object result;
3442 ptrdiff_t nbytes = p - read_buffer;
3443 ptrdiff_t nchars
3444 = (multibyte
3445 ? multibyte_chars_in_text ((unsigned char *) read_buffer,
3446 nbytes)
3447 : nbytes);
3448
3449 if (uninterned_symbol)
3450 {
3451 Lisp_Object name
3452 = ((! NILP (Vpurify_flag)
3453 ? make_pure_string : make_specified_string)
3454 (read_buffer, nchars, nbytes, multibyte));
3455 result = Fmake_symbol (name);
3456 }
3457 else
3458 {
3459 /* Don't create the string object for the name unless
3460 we're going to retain it in a new symbol.
3300 3461
3301 ptrdiff_t nbytes = p - read_buffer; 3462 Like intern_1 but supports multibyte names. */
3302 ptrdiff_t nchars 3463 Lisp_Object obarray = check_obarray (Vobarray);
3303 = (multibyte 3464 Lisp_Object tem = oblookup (obarray, read_buffer,
3304 ? multibyte_chars_in_text ((unsigned char *) read_buffer, 3465 nchars, nbytes);
3305 nbytes) 3466
3306 : nbytes); 3467 if (SYMBOLP (tem))
3307 Lisp_Object name = ((uninterned_symbol && ! NILP (Vpurify_flag) 3468 result = tem;
3308 ? make_pure_string : make_specified_string) 3469 else
3309 (read_buffer, nchars, nbytes, multibyte)); 3470 {
3310 Lisp_Object result = (uninterned_symbol ? Fmake_symbol (name) 3471 Lisp_Object name
3311 : Fintern (name, Qnil)); 3472 = make_specified_string (read_buffer, nchars, nbytes,
3312 3473 multibyte);
3313 if (EQ (Vread_with_symbol_positions, Qt) 3474 result = intern_driver (name, obarray, tem);
3314 || EQ (Vread_with_symbol_positions, readcharfun)) 3475 }
3315 Vread_symbol_positions_list 3476 }
3316 = Fcons (Fcons (result, make_number (start_position)), 3477
3317 Vread_symbol_positions_list); 3478 if (EQ (Vread_with_symbol_positions, Qt)
3318 return unbind_to (count, result); 3479 || EQ (Vread_with_symbol_positions, readcharfun))
3480 Vread_symbol_positions_list
3481 = Fcons (Fcons (result, make_number (start_position)),
3482 Vread_symbol_positions_list);
3483 return unbind_to (count, result);
3484 }
3319 } 3485 }
3320 } 3486 }
3321} 3487}
@@ -3369,6 +3535,13 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3369 if (EQ (placeholder, subtree)) 3535 if (EQ (placeholder, subtree))
3370 return object; 3536 return object;
3371 3537
3538 /* For common object types that can't contain other objects, don't
3539 bother looking them up; we're done. */
3540 if (SYMBOLP (subtree)
3541 || (STRINGP (subtree) && !string_intervals (subtree))
3542 || NUMBERP (subtree))
3543 return subtree;
3544
3372 /* If we've been to this node before, don't explore it again. */ 3545 /* If we've been to this node before, don't explore it again. */
3373 if (!EQ (Qnil, Fmemq (subtree, seen_list))) 3546 if (!EQ (Qnil, Fmemq (subtree, seen_list)))
3374 return subtree; 3547 return subtree;
@@ -3376,8 +3549,8 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3376 /* If this node can be the entry point to a cycle, remember that 3549 /* If this node can be the entry point to a cycle, remember that
3377 we've seen it. It can only be such an entry point if it was made 3550 we've seen it. It can only be such an entry point if it was made
3378 by #n=, which means that we can find it as a value in 3551 by #n=, which means that we can find it as a value in
3379 read_objects. */ 3552 read_objects_completed. */
3380 if (!EQ (Qnil, Frassq (subtree, read_objects))) 3553 if (hash_lookup (XHASH_TABLE (read_objects_completed), subtree, NULL) >= 0)
3381 seen_list = Fcons (subtree, seen_list); 3554 seen_list = Fcons (subtree, seen_list);
3382 3555
3383 /* Recurse according to subtree's type. 3556 /* Recurse according to subtree's type.
@@ -3390,8 +3563,9 @@ substitute_object_recurse (Lisp_Object object, Lisp_Object placeholder, Lisp_Obj
3390 if (BOOL_VECTOR_P (subtree)) 3563 if (BOOL_VECTOR_P (subtree))
3391 return subtree; /* No sub-objects anyway. */ 3564 return subtree; /* No sub-objects anyway. */
3392 else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree) 3565 else if (CHAR_TABLE_P (subtree) || SUB_CHAR_TABLE_P (subtree)
3393 || COMPILEDP (subtree) || HASH_TABLE_P (subtree)) 3566 || COMPILEDP (subtree) || HASH_TABLE_P (subtree)
3394 length = ASIZE (subtree) & PSEUDOVECTOR_SIZE_MASK; 3567 || RECORDP (subtree))
3568 length = PVSIZE (subtree);
3395 else if (VECTORP (subtree)) 3569 else if (VECTORP (subtree))
3396 length = ASIZE (subtree); 3570 length = ASIZE (subtree);
3397 else 3571 else
@@ -3449,25 +3623,18 @@ substitute_in_interval (INTERVAL interval, Lisp_Object arg)
3449} 3623}
3450 3624
3451 3625
3452#define LEAD_INT 1 3626/* Convert STRING to a number, assuming base BASE. Return a fixnum if
3453#define DOT_CHAR 2 3627 STRING has integer syntax and fits in a fixnum, else return the
3454#define TRAIL_INT 4 3628 nearest float if STRING has either floating point or integer syntax
3455#define E_EXP 16 3629 and BASE is 10, else return nil. If IGNORE_TRAILING, consider just
3456 3630 the longest prefix of STRING that has valid floating point syntax.
3457 3631 Signal an overflow if BASE is not 10 and the number has integer
3458/* Convert STRING to a number, assuming base BASE. Return a fixnum if CP has 3632 syntax but does not fit. */
3459 integer syntax and fits in a fixnum, else return the nearest float if CP has
3460 either floating point or integer syntax and BASE is 10, else return nil. If
3461 IGNORE_TRAILING, consider just the longest prefix of CP that has
3462 valid floating point syntax. Signal an overflow if BASE is not 10 and the
3463 number has integer syntax but does not fit. */
3464 3633
3465Lisp_Object 3634Lisp_Object
3466string_to_number (char const *string, int base, bool ignore_trailing) 3635string_to_number (char const *string, int base, bool ignore_trailing)
3467{ 3636{
3468 int state;
3469 char const *cp = string; 3637 char const *cp = string;
3470 int leading_digit;
3471 bool float_syntax = 0; 3638 bool float_syntax = 0;
3472 double value = 0; 3639 double value = 0;
3473 3640
@@ -3479,15 +3646,23 @@ string_to_number (char const *string, int base, bool ignore_trailing)
3479 bool signedp = negative || *cp == '+'; 3646 bool signedp = negative || *cp == '+';
3480 cp += signedp; 3647 cp += signedp;
3481 3648
3482 state = 0; 3649 enum { INTOVERFLOW = 1, LEAD_INT = 2, DOT_CHAR = 4, TRAIL_INT = 8,
3483 3650 E_EXP = 16 };
3484 leading_digit = digit_to_number (*cp, base); 3651 int state = 0;
3652 int leading_digit = digit_to_number (*cp, base);
3653 uintmax_t n = leading_digit;
3485 if (leading_digit >= 0) 3654 if (leading_digit >= 0)
3486 { 3655 {
3487 state |= LEAD_INT; 3656 state |= LEAD_INT;
3488 do 3657 for (int digit; 0 <= (digit = digit_to_number (*++cp, base)); )
3489 ++cp; 3658 {
3490 while (digit_to_number (*cp, base) >= 0); 3659 if (INT_MULTIPLY_OVERFLOW (n, base))
3660 state |= INTOVERFLOW;
3661 n *= base;
3662 if (INT_ADD_OVERFLOW (n, digit))
3663 state |= INTOVERFLOW;
3664 n += digit;
3665 }
3491 } 3666 }
3492 if (*cp == '.') 3667 if (*cp == '.')
3493 { 3668 {
@@ -3537,32 +3712,22 @@ string_to_number (char const *string, int base, bool ignore_trailing)
3537 } 3712 }
3538 3713
3539 float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT) 3714 float_syntax = ((state & (DOT_CHAR|TRAIL_INT)) == (DOT_CHAR|TRAIL_INT)
3540 || state == (LEAD_INT|E_EXP)); 3715 || (state & ~INTOVERFLOW) == (LEAD_INT|E_EXP));
3541 } 3716 }
3542 3717
3543 /* Return nil if the number uses invalid syntax. If IGNORE_TRAILING, accept 3718 /* Return nil if the number uses invalid syntax. If IGNORE_TRAILING, accept
3544 any prefix that matches. Otherwise, the entire string must match. */ 3719 any prefix that matches. Otherwise, the entire string must match. */
3545 if (! (ignore_trailing 3720 if (! (ignore_trailing
3546 ? ((state & LEAD_INT) != 0 || float_syntax) 3721 ? ((state & LEAD_INT) != 0 || float_syntax)
3547 : (!*cp && ((state & ~DOT_CHAR) == LEAD_INT || float_syntax)))) 3722 : (!*cp && ((state & ~(INTOVERFLOW | DOT_CHAR)) == LEAD_INT
3723 || float_syntax))))
3548 return Qnil; 3724 return Qnil;
3549 3725
3550 /* If the number uses integer and not float syntax, and is in C-language 3726 /* If the number uses integer and not float syntax, and is in C-language
3551 range, use its value, preferably as a fixnum. */ 3727 range, use its value, preferably as a fixnum. */
3552 if (leading_digit >= 0 && ! float_syntax) 3728 if (leading_digit >= 0 && ! float_syntax)
3553 { 3729 {
3554 uintmax_t n; 3730 if (state & INTOVERFLOW)
3555
3556 /* Fast special case for single-digit integers. This also avoids a
3557 glitch when BASE is 16 and IGNORE_TRAILING, because in that
3558 case some versions of strtoumax accept numbers like "0x1" that Emacs
3559 does not allow. */
3560 if (digit_to_number (string[signedp + 1], base) < 0)
3561 return make_number (negative ? -leading_digit : leading_digit);
3562
3563 errno = 0;
3564 n = strtoumax (string + signedp, NULL, base);
3565 if (errno == ERANGE)
3566 { 3731 {
3567 /* Unfortunately there's no simple and accurate way to convert 3732 /* Unfortunately there's no simple and accurate way to convert
3568 non-base-10 numbers that are out of C-language range. */ 3733 non-base-10 numbers that are out of C-language range. */
@@ -4436,6 +4601,9 @@ load_path_default (void)
4436void 4601void
4437init_lread (void) 4602init_lread (void)
4438{ 4603{
4604 if (NILP (Vpurify_flag) && !NILP (Ffboundp (Qfile_truename)))
4605 Vsource_directory = call1 (Qfile_truename, Vsource_directory);
4606
4439 /* First, set Vload_path. */ 4607 /* First, set Vload_path. */
4440 4608
4441 /* Ignore EMACSLOADPATH when dumping. */ 4609 /* Ignore EMACSLOADPATH when dumping. */
@@ -4690,11 +4858,12 @@ The remaining ENTRIES in the alist element describe the functions and
4690variables defined in that file, the features provided, and the 4858variables defined in that file, the features provided, and the
4691features required. Each entry has the form `(provide . FEATURE)', 4859features required. Each entry has the form `(provide . FEATURE)',
4692`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)', 4860`(require . FEATURE)', `(defun . FUNCTION)', `(autoload . SYMBOL)',
4693`(defface . SYMBOL)', or `(t . SYMBOL)'. Entries like `(t . SYMBOL)' 4861`(defface . SYMBOL)', `(define-type . SYMBOL)',
4694may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an 4862`(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'.
4695autoload before this file redefined it as a function. In addition, 4863Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry,
4696entries may also be single symbols, which means that SYMBOL was 4864and means that SYMBOL was an autoload before this file redefined it
4697defined by `defvar' or `defconst'. 4865as a function. In addition, entries may also be single symbols,
4866which means that symbol was defined by `defvar' or `defconst'.
4698 4867
4699During preloading, the file name recorded is relative to the main Lisp 4868During preloading, the file name recorded is relative to the main Lisp
4700directory. These file names are converted to absolute at startup. */); 4869directory. These file names are converted to absolute at startup. */);
@@ -4799,10 +4968,23 @@ variables, this must be set in the first line of a file. */);
4799 doc: /* List of buffers being read from by calls to `eval-buffer' and `eval-region'. */); 4968 doc: /* List of buffers being read from by calls to `eval-buffer' and `eval-region'. */);
4800 Veval_buffer_list = Qnil; 4969 Veval_buffer_list = Qnil;
4801 4970
4802 DEFVAR_LISP ("old-style-backquotes", Vold_style_backquotes, 4971 DEFVAR_LISP ("lread--old-style-backquotes", Vlread_old_style_backquotes,
4803 doc: /* Set to non-nil when `read' encounters an old-style backquote. */); 4972 doc: /* Set to non-nil when `read' encounters an old-style backquote.
4804 Vold_style_backquotes = Qnil; 4973For internal use only. */);
4805 DEFSYM (Qold_style_backquotes, "old-style-backquotes"); 4974 Vlread_old_style_backquotes = Qnil;
4975 DEFSYM (Qlread_old_style_backquotes, "lread--old-style-backquotes");
4976
4977 DEFVAR_LISP ("lread--unescaped-character-literals",
4978 Vlread_unescaped_character_literals,
4979 doc: /* List of deprecated unescaped character literals encountered by `read'.
4980For internal use only. */);
4981 Vlread_unescaped_character_literals = Qnil;
4982 DEFSYM (Qlread_unescaped_character_literals,
4983 "lread--unescaped-character-literals");
4984
4985 DEFSYM (Qlss, "<");
4986 DEFSYM (Qchar, "char");
4987 DEFSYM (Qformat, "format");
4806 4988
4807 DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer, 4989 DEFVAR_BOOL ("load-prefer-newer", load_prefer_newer,
4808 doc: /* Non-nil means `load' prefers the newest version of a file. 4990 doc: /* Non-nil means `load' prefers the newest version of a file.
@@ -4844,8 +5026,10 @@ that are loaded before your customizations are read! */);
4844 DEFSYM (Qdir_ok, "dir-ok"); 5026 DEFSYM (Qdir_ok, "dir-ok");
4845 DEFSYM (Qdo_after_load_evaluation, "do-after-load-evaluation"); 5027 DEFSYM (Qdo_after_load_evaluation, "do-after-load-evaluation");
4846 5028
4847 staticpro (&read_objects); 5029 staticpro (&read_objects_map);
4848 read_objects = Qnil; 5030 read_objects_map = Qnil;
5031 staticpro (&read_objects_completed);
5032 read_objects_completed = Qnil;
4849 staticpro (&seen_list); 5033 staticpro (&seen_list);
4850 seen_list = Qnil; 5034 seen_list = Qnil;
4851 5035
diff --git a/src/macfont.m b/src/macfont.m
index f356842db18..4d310e47aec 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -206,7 +206,7 @@ mac_screen_font_get_advance_width_for_glyph (ScreenFontRef font, CGGlyph glyph)
206 206
207#if !USE_CT_GLYPH_INFO 207#if !USE_CT_GLYPH_INFO
208static CGGlyph 208static CGGlyph
209mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, 209mac_font_get_glyph_for_cid (CTFontRef font, NSCharacterCollection collection,
210 CGFontIndex cid) 210 CGFontIndex cid)
211{ 211{
212 CGGlyph result = kCGFontIndexInvalid; 212 CGGlyph result = kCGFontIndexInvalid;
@@ -284,7 +284,6 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
284 284
285 [textStorage setFont:nsFont]; 285 [textStorage setFont:nsFont];
286 [textContainer setLineFragmentPadding:0]; 286 [textContainer setLineFragmentPadding:0];
287 [layoutManager setUsesScreenFonts:YES];
288 287
289 [layoutManager addTextContainer:textContainer]; 288 [layoutManager addTextContainer:textContainer];
290 [textContainer release]; 289 [textContainer release];
@@ -318,8 +317,7 @@ mac_screen_font_get_metrics (ScreenFontRef font, CGFloat *ascent,
318 317
319static CFIndex 318static CFIndex
320mac_font_shape_1 (NSFont *font, NSString *string, 319mac_font_shape_1 (NSFont *font, NSString *string,
321 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len, 320 struct mac_glyph_layout *glyph_layouts, CFIndex glyph_len)
322 BOOL screen_font_p)
323{ 321{
324 NSUInteger i; 322 NSUInteger i;
325 CFIndex result = 0; 323 CFIndex result = 0;
@@ -339,7 +337,6 @@ mac_font_shape_1 (NSFont *font, NSString *string,
339 initWithString:@" "] autorelease])]; 337 initWithString:@" "] autorelease])];
340 [textStorage setFont:font]; 338 [textStorage setFont:font];
341 [textContainer setLineFragmentPadding:0]; 339 [textContainer setLineFragmentPadding:0];
342 [layoutManager setUsesScreenFonts:screen_font_p];
343 340
344 [layoutManager addTextContainer:textContainer]; 341 [layoutManager addTextContainer:textContainer];
345 [textContainer release]; 342 [textContainer release];
@@ -413,8 +410,9 @@ mac_font_shape_1 (NSFont *font, NSString *string,
413 /* For now we assume the direction is not changed within the 410 /* For now we assume the direction is not changed within the
414 string. */ 411 string. */
415 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1)) 412 [layoutManager getGlyphsInRange:(NSMakeRange (glyphIndex, 1))
416 glyphs:NULL characterIndexes:NULL 413 glyphs:NULL
417 glyphInscriptions:NULL elasticBits:NULL 414 properties:NULL
415 characterIndexes:NULL
418 bidiLevels:&bidiLevel]; 416 bidiLevels:&bidiLevel];
419 if (bidiLevel & 1) 417 if (bidiLevel & 1)
420 permutation = xmalloc (sizeof (NSUInteger) * used); 418 permutation = xmalloc (sizeof (NSUInteger) * used);
@@ -587,7 +585,7 @@ mac_screen_font_shape (ScreenFontRef font, CFStringRef string,
587{ 585{
588 return mac_font_shape_1 ([(NSFont *)font printerFont], 586 return mac_font_shape_1 ([(NSFont *)font printerFont],
589 (NSString *) string, 587 (NSString *) string,
590 glyph_layouts, glyph_len, YES); 588 glyph_layouts, glyph_len);
591} 589}
592 590
593static CGColorRef 591static CGColorRef
@@ -1321,8 +1319,8 @@ struct macfont_cache
1321 /* Character collection specifying the destination of the mapping 1319 /* Character collection specifying the destination of the mapping
1322 provided by `table' above. If `table' is obtained from the UVS 1320 provided by `table' above. If `table' is obtained from the UVS
1323 subtable in the font cmap table, then the value of this member 1321 subtable in the font cmap table, then the value of this member
1324 should be kCTCharacterCollectionIdentityMapping. */ 1322 should be NSIdentityMappingCharacterCollection. */
1325 CTCharacterCollection collection; 1323 NSCharacterCollection collection;
1326 } uvs; 1324 } uvs;
1327}; 1325};
1328 1326
@@ -1333,8 +1331,8 @@ static CFCharacterSetRef macfont_get_cf_charset (struct font *);
1333static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef); 1331static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef);
1334static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char); 1332static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char);
1335static CGGlyph macfont_get_glyph_for_cid (struct font *font, 1333static CGGlyph macfont_get_glyph_for_cid (struct font *font,
1336 CTCharacterCollection, CGFontIndex); 1334 NSCharacterCollection, CGFontIndex);
1337static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *); 1335static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *);
1338 1336
1339static struct macfont_cache * 1337static struct macfont_cache *
1340macfont_lookup_cache (CFStringRef key) 1338macfont_lookup_cache (CFStringRef key)
@@ -1582,7 +1580,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c)
1582} 1580}
1583 1581
1584static CGGlyph 1582static CGGlyph
1585macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection, 1583macfont_get_glyph_for_cid (struct font *font, NSCharacterCollection collection,
1586 CGFontIndex cid) 1584 CGFontIndex cid)
1587{ 1585{
1588 struct macfont_info *macfont_info = (struct macfont_info *) font; 1586 struct macfont_info *macfont_info = (struct macfont_info *) font;
@@ -1593,7 +1591,7 @@ macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection,
1593} 1591}
1594 1592
1595static CFDataRef 1593static CFDataRef
1596macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection) 1594macfont_get_uvs_table (struct font *font, NSCharacterCollection *collection)
1597{ 1595{
1598 struct macfont_info *macfont_info = (struct macfont_info *) font; 1596 struct macfont_info *macfont_info = (struct macfont_info *) font;
1599 CTFontRef macfont = macfont_info->macfont; 1597 CTFontRef macfont = macfont_info->macfont;
@@ -1603,12 +1601,12 @@ macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1603 if (cache->uvs.table == NULL) 1601 if (cache->uvs.table == NULL)
1604 { 1602 {
1605 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont); 1603 CFDataRef uvs_table = mac_font_copy_uvs_table (macfont);
1606 CTCharacterCollection uvs_collection = 1604 NSCharacterCollection uvs_collection =
1607 kCTCharacterCollectionIdentityMapping; 1605 NSIdentityMappingCharacterCollection;
1608 1606
1609 if (uvs_table == NULL 1607 if (uvs_table == NULL
1610 && mac_font_get_glyph_for_cid (macfont, 1608 && mac_font_get_glyph_for_cid (macfont,
1611 kCTCharacterCollectionAdobeJapan1, 1609 NSAdobeJapan1CharacterCollection,
1612 6480) != kCGFontIndexInvalid) 1610 6480) != kCGFontIndexInvalid)
1613 { 1611 {
1614 /* If the glyph for U+4E55 is accessible via its CID 6480, 1612 /* If the glyph for U+4E55 is accessible via its CID 6480,
@@ -1625,7 +1623,7 @@ macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection)
1625 if (mac_uvs_table_adobe_japan1) 1623 if (mac_uvs_table_adobe_japan1)
1626 { 1624 {
1627 uvs_table = CFRetain (mac_uvs_table_adobe_japan1); 1625 uvs_table = CFRetain (mac_uvs_table_adobe_japan1);
1628 uvs_collection = kCTCharacterCollectionAdobeJapan1; 1626 uvs_collection = NSAdobeJapan1CharacterCollection;
1629 } 1627 }
1630 } 1628 }
1631 if (uvs_table == NULL) 1629 if (uvs_table == NULL)
@@ -2538,8 +2536,7 @@ macfont_open (struct frame * f, Lisp_Object entity, int pixel_size)
2538 int size; 2536 int size;
2539 CTFontRef macfont; 2537 CTFontRef macfont;
2540 CTFontSymbolicTraits sym_traits; 2538 CTFontSymbolicTraits sym_traits;
2541 char name[256]; 2539 int i, total_width;
2542 int len, i, total_width;
2543 CGGlyph glyph; 2540 CGGlyph glyph;
2544 CGFloat ascent, descent, leading; 2541 CGFloat ascent, descent, leading;
2545 2542
@@ -3348,7 +3345,7 @@ static int
3348macfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) 3345macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3349{ 3346{
3350 CFDataRef uvs_table; 3347 CFDataRef uvs_table;
3351 CTCharacterCollection uvs_collection; 3348 NSCharacterCollection uvs_collection;
3352 int i, n = 0; 3349 int i, n = 0;
3353 3350
3354 block_input (); 3351 block_input ();
@@ -3368,7 +3365,7 @@ macfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
3368 { 3365 {
3369 CGGlyph glyph = glyphs[i]; 3366 CGGlyph glyph = glyphs[i];
3370 3367
3371 if (uvs_collection != kCTCharacterCollectionIdentityMapping 3368 if (uvs_collection != NSIdentityMappingCharacterCollection
3372 && glyph != kCGFontIndexInvalid) 3369 && glyph != kCGFontIndexInvalid)
3373 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph); 3370 glyph = macfont_get_glyph_for_cid (font, uvs_collection, glyph);
3374 if (glyph == kCGFontIndexInvalid) 3371 if (glyph == kCGFontIndexInvalid)
diff --git a/src/minibuf.c b/src/minibuf.c
index 1bbe276776e..d4128ce01c1 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -20,7 +20,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20 20
21#include <config.h> 21#include <config.h>
22#include <errno.h> 22#include <errno.h>
23#include <stdio.h>
24 23
25#include <binary-io.h> 24#include <binary-io.h>
26 25
@@ -31,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
31#include "frame.h" 30#include "frame.h"
32#include "window.h" 31#include "window.h"
33#include "keymap.h" 32#include "keymap.h"
33#include "sysstdio.h"
34#include "systty.h" 34#include "systty.h"
35 35
36/* List of buffers for use as minibuffers. 36/* List of buffers for use as minibuffers.
@@ -209,15 +209,15 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial,
209 suppress_echo_on_tty (STDIN_FILENO); 209 suppress_echo_on_tty (STDIN_FILENO);
210 } 210 }
211 211
212 fwrite (SDATA (prompt), 1, SBYTES (prompt), stdout); 212 fwrite_unlocked (SDATA (prompt), 1, SBYTES (prompt), stdout);
213 fflush (stdout); 213 fflush_unlocked (stdout);
214 214
215 val = Qnil; 215 val = Qnil;
216 size = 100; 216 size = 100;
217 len = 0; 217 len = 0;
218 line = xmalloc (size); 218 line = xmalloc (size);
219 219
220 while ((c = getchar ()) != '\n' && c != '\r') 220 while ((c = getchar_unlocked ()) != '\n' && c != '\r')
221 { 221 {
222 if (c == EOF) 222 if (c == EOF)
223 { 223 {
@@ -874,6 +874,30 @@ read_minibuf_unwind (void)
874 if (minibuf_level == 0) 874 if (minibuf_level == 0)
875 resize_mini_window (XWINDOW (window), 0); 875 resize_mini_window (XWINDOW (window), 0);
876 876
877 /* Deal with frames that should be removed when exiting the
878 minibuffer. */
879 {
880 Lisp_Object frames, frame1, val;
881 struct frame *f1;
882
883 FOR_EACH_FRAME (frames, frame1)
884 {
885 f1 = XFRAME (frame1);
886
887 if ((FRAME_PARENT_FRAME (f1)
888 || !NILP (get_frame_param (f1, Qdelete_before)))
889 && !NILP (val = (get_frame_param (f1, Qminibuffer_exit))))
890 {
891 if (EQ (val, Qiconify_frame))
892 Ficonify_frame (frame1);
893 else if (EQ (val, Qdelete_frame))
894 Fdelete_frame (frame1, Qnil);
895 else
896 Fmake_frame_invisible (frame1, Qnil);
897 }
898 }
899 }
900
877 /* In case the previous minibuffer displayed in this miniwindow is 901 /* In case the previous minibuffer displayed in this miniwindow is
878 dead, we may keep displaying this buffer (tho it's inactive), so reset it, 902 dead, we may keep displaying this buffer (tho it's inactive), so reset it,
879 to make sure we don't leave around bindings and stuff which only 903 to make sure we don't leave around bindings and stuff which only
@@ -1930,6 +1954,8 @@ syms_of_minibuf (void)
1930 DEFSYM (Qactivate_input_method, "activate-input-method"); 1954 DEFSYM (Qactivate_input_method, "activate-input-method");
1931 DEFSYM (Qcase_fold_search, "case-fold-search"); 1955 DEFSYM (Qcase_fold_search, "case-fold-search");
1932 DEFSYM (Qmetadata, "metadata"); 1956 DEFSYM (Qmetadata, "metadata");
1957 /* A frame parameter. */
1958 DEFSYM (Qminibuffer_exit, "minibuffer-exit");
1933 1959
1934 DEFVAR_LISP ("read-expression-history", Vread_expression_history, 1960 DEFVAR_LISP ("read-expression-history", Vread_expression_history,
1935 doc: /* A history list for arguments that are Lisp expressions to evaluate. 1961 doc: /* A history list for arguments that are Lisp expressions to evaluate.
diff --git a/src/module-env-25.h b/src/module-env-25.h
new file mode 100644
index 00000000000..675010b995b
--- /dev/null
+++ b/src/module-env-25.h
@@ -0,0 +1,140 @@
1 /* Structure size (for version checking). */
2 ptrdiff_t size;
3
4 /* Private data; users should not touch this. */
5 struct emacs_env_private *private_members;
6
7 /* Memory management. */
8
9 emacs_value (*make_global_ref) (emacs_env *env,
10 emacs_value any_reference)
11 EMACS_ATTRIBUTE_NONNULL(1);
12
13 void (*free_global_ref) (emacs_env *env,
14 emacs_value global_reference)
15 EMACS_ATTRIBUTE_NONNULL(1);
16
17 /* Non-local exit handling. */
18
19 enum emacs_funcall_exit (*non_local_exit_check) (emacs_env *env)
20 EMACS_ATTRIBUTE_NONNULL(1);
21
22 void (*non_local_exit_clear) (emacs_env *env)
23 EMACS_ATTRIBUTE_NONNULL(1);
24
25 enum emacs_funcall_exit (*non_local_exit_get)
26 (emacs_env *env,
27 emacs_value *non_local_exit_symbol_out,
28 emacs_value *non_local_exit_data_out)
29 EMACS_ATTRIBUTE_NONNULL(1, 2, 3);
30
31 void (*non_local_exit_signal) (emacs_env *env,
32 emacs_value non_local_exit_symbol,
33 emacs_value non_local_exit_data)
34 EMACS_ATTRIBUTE_NONNULL(1);
35
36 void (*non_local_exit_throw) (emacs_env *env,
37 emacs_value tag,
38 emacs_value value)
39 EMACS_ATTRIBUTE_NONNULL(1);
40
41 /* Function registration. */
42
43 emacs_value (*make_function) (emacs_env *env,
44 ptrdiff_t min_arity,
45 ptrdiff_t max_arity,
46 emacs_value (*function) (emacs_env *env,
47 ptrdiff_t nargs,
48 emacs_value args[],
49 void *)
50 EMACS_NOEXCEPT
51 EMACS_ATTRIBUTE_NONNULL(1),
52 const char *documentation,
53 void *data)
54 EMACS_ATTRIBUTE_NONNULL(1, 4);
55
56 emacs_value (*funcall) (emacs_env *env,
57 emacs_value function,
58 ptrdiff_t nargs,
59 emacs_value args[])
60 EMACS_ATTRIBUTE_NONNULL(1);
61
62 emacs_value (*intern) (emacs_env *env,
63 const char *symbol_name)
64 EMACS_ATTRIBUTE_NONNULL(1, 2);
65
66 /* Type conversion. */
67
68 emacs_value (*type_of) (emacs_env *env,
69 emacs_value value)
70 EMACS_ATTRIBUTE_NONNULL(1);
71
72 bool (*is_not_nil) (emacs_env *env, emacs_value value)
73 EMACS_ATTRIBUTE_NONNULL(1);
74
75 bool (*eq) (emacs_env *env, emacs_value a, emacs_value b)
76 EMACS_ATTRIBUTE_NONNULL(1);
77
78 intmax_t (*extract_integer) (emacs_env *env, emacs_value value)
79 EMACS_ATTRIBUTE_NONNULL(1);
80
81 emacs_value (*make_integer) (emacs_env *env, intmax_t value)
82 EMACS_ATTRIBUTE_NONNULL(1);
83
84 double (*extract_float) (emacs_env *env, emacs_value value)
85 EMACS_ATTRIBUTE_NONNULL(1);
86
87 emacs_value (*make_float) (emacs_env *env, double value)
88 EMACS_ATTRIBUTE_NONNULL(1);
89
90 /* Copy the content of the Lisp string VALUE to BUFFER as an utf8
91 null-terminated string.
92
93 SIZE must point to the total size of the buffer. If BUFFER is
94 NULL or if SIZE is not big enough, write the required buffer size
95 to SIZE and return true.
96
97 Note that SIZE must include the last null byte (e.g. "abc" needs
98 a buffer of size 4).
99
100 Return true if the string was successfully copied. */
101
102 bool (*copy_string_contents) (emacs_env *env,
103 emacs_value value,
104 char *buffer,
105 ptrdiff_t *size_inout)
106 EMACS_ATTRIBUTE_NONNULL(1, 4);
107
108 /* Create a Lisp string from a utf8 encoded string. */
109 emacs_value (*make_string) (emacs_env *env,
110 const char *contents, ptrdiff_t length)
111 EMACS_ATTRIBUTE_NONNULL(1, 2);
112
113 /* Embedded pointer type. */
114 emacs_value (*make_user_ptr) (emacs_env *env,
115 void (*fin) (void *) EMACS_NOEXCEPT,
116 void *ptr)
117 EMACS_ATTRIBUTE_NONNULL(1);
118
119 void *(*get_user_ptr) (emacs_env *env, emacs_value uptr)
120 EMACS_ATTRIBUTE_NONNULL(1);
121 void (*set_user_ptr) (emacs_env *env, emacs_value uptr, void *ptr)
122 EMACS_ATTRIBUTE_NONNULL(1);
123
124 void (*(*get_user_finalizer) (emacs_env *env, emacs_value uptr))
125 (void *) EMACS_NOEXCEPT EMACS_ATTRIBUTE_NONNULL(1);
126 void (*set_user_finalizer) (emacs_env *env,
127 emacs_value uptr,
128 void (*fin) (void *) EMACS_NOEXCEPT)
129 EMACS_ATTRIBUTE_NONNULL(1);
130
131 /* Vector functions. */
132 emacs_value (*vec_get) (emacs_env *env, emacs_value vec, ptrdiff_t i)
133 EMACS_ATTRIBUTE_NONNULL(1);
134
135 void (*vec_set) (emacs_env *env, emacs_value vec, ptrdiff_t i,
136 emacs_value val)
137 EMACS_ATTRIBUTE_NONNULL(1);
138
139 ptrdiff_t (*vec_size) (emacs_env *env, emacs_value vec)
140 EMACS_ATTRIBUTE_NONNULL(1);
diff --git a/src/module-env-26.h b/src/module-env-26.h
new file mode 100644
index 00000000000..1ab12d45c84
--- /dev/null
+++ b/src/module-env-26.h
@@ -0,0 +1,3 @@
1 /* Returns whether a quit is pending. */
2 bool (*should_quit) (emacs_env *env)
3 EMACS_ATTRIBUTE_NONNULL(1);
diff --git a/src/nsfns.m b/src/nsfns.m
index 9e904c68382..68eba8b6a2e 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -175,6 +175,7 @@ ns_directory_from_panel (NSSavePanel *panel)
175#endif 175#endif
176} 176}
177 177
178#ifndef NS_IMPL_COCOA
178static Lisp_Object 179static Lisp_Object
179interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old) 180interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
180/* -------------------------------------------------------------------------- 181/* --------------------------------------------------------------------------
@@ -223,7 +224,7 @@ interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
223 } 224 }
224 return old; 225 return old;
225} 226}
226 227#endif
227 228
228 229
229/* ========================================================================== 230/* ==========================================================================
@@ -972,6 +973,18 @@ frame_parm_handler ns_frame_parm_handlers[] =
972 0, /* x_set_sticky */ 973 0, /* x_set_sticky */
973 0, /* x_set_tool_bar_position */ 974 0, /* x_set_tool_bar_position */
974 0, /* x_set_inhibit_double_buffering */ 975 0, /* x_set_inhibit_double_buffering */
976#ifdef NS_IMPL_COCOA
977 x_set_undecorated,
978#else
979 0, /*x_set_undecorated */
980#endif
981 x_set_parent_frame,
982 0, /* x_set_skip_taskbar */
983 x_set_no_focus_on_map,
984 x_set_no_accept_focus,
985 x_set_z_group, /* x_set_z_group */
986 0, /* x_set_override_redirect */
987 x_set_no_special_glyphs,
975}; 988};
976 989
977 990
@@ -1080,7 +1093,7 @@ This function is an internal primitive--use `make-frame' instead. */)
1080 ptrdiff_t count = specpdl_ptr - specpdl; 1093 ptrdiff_t count = specpdl_ptr - specpdl;
1081 Lisp_Object display; 1094 Lisp_Object display;
1082 struct ns_display_info *dpyinfo = NULL; 1095 struct ns_display_info *dpyinfo = NULL;
1083 Lisp_Object parent; 1096 Lisp_Object parent, parent_frame;
1084 struct kboard *kb; 1097 struct kboard *kb;
1085 static int desc_ctr = 1; 1098 static int desc_ctr = 1;
1086 int x_width = 0, x_height = 0; 1099 int x_width = 0, x_height = 0;
@@ -1244,14 +1257,45 @@ This function is an internal primitive--use `make-frame' instead. */)
1244 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 1257 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1245 x_default_parameter (f, parms, Qright_fringe, Qnil, 1258 x_default_parameter (f, parms, Qright_fringe, Qnil,
1246 "rightFringe", "RightFringe", RES_TYPE_NUMBER); 1259 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1260 x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
1261 NULL, NULL, RES_TYPE_BOOLEAN);
1247 1262
1248 init_frame_faces (f); 1263 init_frame_faces (f);
1249 1264
1250 /* Read comment about this code in corresponding place in xfns.c. */ 1265 /* Read comment about this code in corresponding place in xfns.c. */
1266 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
1267 if (NUMBERP (tem))
1268 store_frame_param (f, Qmin_width, tem);
1269 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
1270 if (NUMBERP (tem))
1271 store_frame_param (f, Qmin_height, tem);
1251 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 1272 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1252 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1, 1273 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1253 Qx_create_frame_1); 1274 Qx_create_frame_1);
1254 1275
1276 tem = x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN);
1277 FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
1278 store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
1279
1280 parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
1281 RES_TYPE_SYMBOL);
1282 /* Accept parent-frame iff parent-id was not specified. */
1283 if (!NILP (parent)
1284 || EQ (parent_frame, Qunbound)
1285 || NILP (parent_frame)
1286 || !FRAMEP (parent_frame)
1287 || !FRAME_LIVE_P (XFRAME (parent_frame)))
1288 parent_frame = Qnil;
1289
1290 fset_parent_frame (f, parent_frame);
1291 store_frame_param (f, Qparent_frame, parent_frame);
1292
1293 x_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
1294 x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
1295 NULL, NULL, RES_TYPE_BOOLEAN);
1296 x_default_parameter (f, parms, Qno_accept_focus, Qnil,
1297 NULL, NULL, RES_TYPE_BOOLEAN);
1298
1255 /* The resources controlling the menu-bar and tool-bar are 1299 /* The resources controlling the menu-bar and tool-bar are
1256 processed specially at startup, and reflected in the mode 1300 processed specially at startup, and reflected in the mode
1257 variables; ignore them here. */ 1301 variables; ignore them here. */
@@ -1284,6 +1328,15 @@ This function is an internal primitive--use `make-frame' instead. */)
1284 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor]; 1328 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1285 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor]; 1329 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1286 f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor]; 1330 f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1331 f->output_data.ns->left_edge_cursor = [NSCursor resizeLeftRightCursor];
1332 f->output_data.ns->top_left_corner_cursor = [NSCursor arrowCursor];
1333 f->output_data.ns->top_edge_cursor = [NSCursor resizeUpDownCursor];
1334 f->output_data.ns->top_right_corner_cursor = [NSCursor arrowCursor];
1335 f->output_data.ns->right_edge_cursor = [NSCursor resizeLeftRightCursor];
1336 f->output_data.ns->bottom_right_corner_cursor = [NSCursor arrowCursor];
1337 f->output_data.ns->bottom_edge_cursor = [NSCursor resizeUpDownCursor];
1338 f->output_data.ns->bottom_left_corner_cursor = [NSCursor arrowCursor];
1339
1287 FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor 1340 FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1288 = [NSCursor arrowCursor]; 1341 = [NSCursor arrowCursor];
1289 FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor 1342 FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
@@ -1378,7 +1431,7 @@ This function is an internal primitive--use `make-frame' instead. */)
1378} 1431}
1379 1432
1380void 1433void
1381x_focus_frame (struct frame *f) 1434x_focus_frame (struct frame *f, bool noactivate)
1382{ 1435{
1383 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 1436 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1384 1437
@@ -1392,6 +1445,86 @@ x_focus_frame (struct frame *f)
1392 } 1445 }
1393} 1446}
1394 1447
1448static BOOL
1449ns_window_is_ancestor (NSWindow *win, NSWindow *candidate)
1450/* Test whether CANDIDATE is an ancestor window of WIN. */
1451{
1452 if (candidate == NULL)
1453 return NO;
1454 else if (win == candidate)
1455 return YES;
1456 else
1457 return ns_window_is_ancestor(win, [candidate parentWindow]);
1458}
1459
1460DEFUN ("ns-frame-list-z-order", Fns_frame_list_z_order,
1461 Sns_frame_list_z_order, 0, 1, 0,
1462 doc: /* Return list of Emacs' frames, in Z (stacking) order.
1463The optional argument TERMINAL specifies which display to ask about.
1464TERMINAL should be either a frame or a display name (a string). If
1465omitted or nil, that stands for the selected frame's display. Return
1466nil if TERMINAL contains no Emacs frame.
1467
1468As a special case, if TERMINAL is non-nil and specifies a live frame,
1469return the child frames of that frame in Z (stacking) order.
1470
1471Frames are listed from topmost (first) to bottommost (last). */)
1472 (Lisp_Object terminal)
1473{
1474 Lisp_Object frames = Qnil;
1475 NSWindow *parent = nil;
1476
1477 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
1478 parent = [FRAME_NS_VIEW (XFRAME (terminal)) window];
1479 else if (!NILP (terminal))
1480 return Qnil;
1481
1482 for (NSWindow *win in [[NSApp orderedWindows] reverseObjectEnumerator])
1483 {
1484 Lisp_Object frame;
1485
1486 /* Check against [win parentWindow] so that it doesn't match itself. */
1487 if (parent == nil || ns_window_is_ancestor (parent, [win parentWindow]))
1488 {
1489 XSETFRAME (frame, ((EmacsView *)[win delegate])->emacsframe);
1490 frames = Fcons(frame, frames);
1491 }
1492 }
1493
1494 return frames;
1495}
1496
1497DEFUN ("ns-frame-restack", Fns_frame_restack, Sns_frame_restack, 2, 3, 0,
1498 doc: /* Restack FRAME1 below FRAME2.
1499This means that if both frames are visible and the display areas of
1500these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
1501third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
1502means that if both frames are visible and the display areas of these
1503frames overlap, FRAME1 (partially) obscures FRAME2.
1504
1505Some window managers may refuse to restack windows. */)
1506 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
1507{
1508 struct frame *f1 = decode_live_frame (frame1);
1509 struct frame *f2 = decode_live_frame (frame2);
1510
1511 if (FRAME_NS_VIEW (f1) && FRAME_NS_VIEW (f2))
1512 {
1513 NSWindow *window = [FRAME_NS_VIEW (f1) window];
1514 NSInteger window2 = [[FRAME_NS_VIEW (f2) window] windowNumber];
1515 NSWindowOrderingMode flag = NILP (above) ? NSWindowBelow : NSWindowAbove;
1516
1517 [window orderWindow: flag
1518 relativeTo: window2];
1519
1520 return Qt;
1521 }
1522 else
1523 {
1524 error ("Cannot restack frames");
1525 return Qnil;
1526 }
1527}
1395 1528
1396DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, 1529DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1397 0, 1, "", 1530 0, 1, "",
@@ -1989,9 +2122,6 @@ DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1989#else 2122#else
1990 Lisp_Object ret = Qnil; 2123 Lisp_Object ret = Qnil;
1991 NSMenu *svcs; 2124 NSMenu *svcs;
1992#ifdef NS_IMPL_COCOA
1993 id delegate;
1994#endif
1995 2125
1996 check_window_system (NULL); 2126 check_window_system (NULL);
1997 svcs = [[NSMenu alloc] initWithTitle: @"Services"]; 2127 svcs = [[NSMenu alloc] initWithTitle: @"Services"];
@@ -1999,33 +2129,7 @@ DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1999 [NSApp registerServicesMenuSendTypes: ns_send_types 2129 [NSApp registerServicesMenuSendTypes: ns_send_types
2000 returnTypes: ns_return_types]; 2130 returnTypes: ns_return_types];
2001 2131
2002/* On Tiger, services menu updating was made lazier (waits for user to
2003 actually click on the menu), so we have to force things along: */
2004#ifdef NS_IMPL_COCOA
2005 delegate = [svcs delegate];
2006 if (delegate != nil)
2007 {
2008 if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2009 [delegate menuNeedsUpdate: svcs];
2010 if ([delegate respondsToSelector:
2011 @selector (menu:updateItem:atIndex:shouldCancel:)])
2012 {
2013 int i, len = [delegate numberOfItemsInMenu: svcs];
2014 for (i =0; i<len; i++)
2015 [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2016 for (i =0; i<len; i++)
2017 if (![delegate menu: svcs
2018 updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2019 atIndex: i shouldCancel: NO])
2020 break;
2021 }
2022 }
2023#endif
2024
2025 [svcs setAutoenablesItems: NO]; 2132 [svcs setAutoenablesItems: NO];
2026#ifdef NS_IMPL_COCOA
2027 [svcs update]; /* on macOS, converts from '/' structure */
2028#endif
2029 2133
2030 ret = interpret_services_menu (svcs, Qnil, ret); 2134 ret = interpret_services_menu (svcs, Qnil, ret);
2031 return ret; 2135 return ret;
@@ -2639,9 +2743,8 @@ compute_tip_xy (struct frame *f,
2639 int *root_y) 2743 int *root_y)
2640{ 2744{
2641 Lisp_Object left, top, right, bottom; 2745 Lisp_Object left, top, right, bottom;
2642 EmacsView *view = FRAME_NS_VIEW (f);
2643 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2644 NSPoint pt; 2746 NSPoint pt;
2747 NSScreen *screen;
2645 2748
2646 /* Start with user-specified or mouse position. */ 2749 /* Start with user-specified or mouse position. */
2647 left = Fcdr (Fassq (Qleft, parms)); 2750 left = Fcdr (Fassq (Qleft, parms));
@@ -2651,22 +2754,7 @@ compute_tip_xy (struct frame *f,
2651 2754
2652 if ((!INTEGERP (left) && !INTEGERP (right)) 2755 if ((!INTEGERP (left) && !INTEGERP (right))
2653 || (!INTEGERP (top) && !INTEGERP (bottom))) 2756 || (!INTEGERP (top) && !INTEGERP (bottom)))
2654 { 2757 pt = [NSEvent mouseLocation];
2655 pt.x = dpyinfo->last_mouse_motion_x;
2656 pt.y = dpyinfo->last_mouse_motion_y;
2657 /* Convert to screen coordinates */
2658 pt = [view convertPoint: pt toView: nil];
2659#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
2660 pt = [[view window] convertBaseToScreen: pt];
2661#else
2662 {
2663 NSRect r = NSMakeRect (pt.x, pt.y, 0, 0);
2664 r = [[view window] convertRectToScreen: r];
2665 pt.x = r.origin.x;
2666 pt.y = r.origin.y;
2667 }
2668#endif
2669 }
2670 else 2758 else
2671 { 2759 {
2672 /* Absolute coordinates. */ 2760 /* Absolute coordinates. */
@@ -2676,13 +2764,28 @@ compute_tip_xy (struct frame *f,
2676 - height); 2764 - height);
2677 } 2765 }
2678 2766
2767 /* Find the screen that pt is on. */
2768 for (screen in [NSScreen screens])
2769 if (pt.x >= screen.frame.origin.x
2770 && pt.x < screen.frame.origin.x + screen.frame.size.width
2771 && pt.y >= screen.frame.origin.y
2772 && pt.y < screen.frame.origin.y + screen.frame.size.height)
2773 break;
2774
2775 /* We could use this instead of the if above:
2776
2777 if (CGRectContainsPoint ([screen frame], pt))
2778
2779 which would be neater, but it causes problems building on old
2780 versions of macOS and in GNUstep. */
2781
2679 /* Ensure in bounds. (Note, screen origin = lower left.) */ 2782 /* Ensure in bounds. (Note, screen origin = lower left.) */
2680 if (INTEGERP (left) || INTEGERP (right)) 2783 if (INTEGERP (left) || INTEGERP (right))
2681 *root_x = pt.x; 2784 *root_x = pt.x;
2682 else if (pt.x + XINT (dx) <= 0) 2785 else if (pt.x + XINT (dx) <= screen.frame.origin.x)
2683 *root_x = 0; /* Can happen for negative dx */ 2786 *root_x = screen.frame.origin.x; /* Can happen for negative dx */
2684 else if (pt.x + XINT (dx) + width 2787 else if (pt.x + XINT (dx) + width
2685 <= x_display_pixel_width (FRAME_DISPLAY_INFO (f))) 2788 <= screen.frame.origin.x + screen.frame.size.width)
2686 /* It fits to the right of the pointer. */ 2789 /* It fits to the right of the pointer. */
2687 *root_x = pt.x + XINT (dx); 2790 *root_x = pt.x + XINT (dx);
2688 else if (width + XINT (dx) <= pt.x) 2791 else if (width + XINT (dx) <= pt.x)
@@ -2690,20 +2793,20 @@ compute_tip_xy (struct frame *f,
2690 *root_x = pt.x - width - XINT (dx); 2793 *root_x = pt.x - width - XINT (dx);
2691 else 2794 else
2692 /* Put it left justified on the screen -- it ought to fit that way. */ 2795 /* Put it left justified on the screen -- it ought to fit that way. */
2693 *root_x = 0; 2796 *root_x = screen.frame.origin.x;
2694 2797
2695 if (INTEGERP (top) || INTEGERP (bottom)) 2798 if (INTEGERP (top) || INTEGERP (bottom))
2696 *root_y = pt.y; 2799 *root_y = pt.y;
2697 else if (pt.y - XINT (dy) - height >= 0) 2800 else if (pt.y - XINT (dy) - height >= screen.frame.origin.y)
2698 /* It fits below the pointer. */ 2801 /* It fits below the pointer. */
2699 *root_y = pt.y - height - XINT (dy); 2802 *root_y = pt.y - height - XINT (dy);
2700 else if (pt.y + XINT (dy) + height 2803 else if (pt.y + XINT (dy) + height
2701 <= x_display_pixel_height (FRAME_DISPLAY_INFO (f))) 2804 <= screen.frame.origin.y + screen.frame.size.height)
2702 /* It fits above the pointer */ 2805 /* It fits above the pointer */
2703 *root_y = pt.y + XINT (dy); 2806 *root_y = pt.y + XINT (dy);
2704 else 2807 else
2705 /* Put it on the top. */ 2808 /* Put it on the top. */
2706 *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height; 2809 *root_y = screen.frame.origin.y + screen.frame.size.height - height;
2707} 2810}
2708 2811
2709 2812
@@ -2935,6 +3038,48 @@ menu bar or tool bar of FRAME. */)
2935 : Qnative_edges)); 3038 : Qnative_edges));
2936} 3039}
2937 3040
3041DEFUN ("ns-set-mouse-absolute-pixel-position",
3042 Fns_set_mouse_absolute_pixel_position,
3043 Sns_set_mouse_absolute_pixel_position, 2, 2, 0,
3044 doc: /* Move mouse pointer to absolute pixel position (X, Y).
3045The coordinates X and Y are interpreted in pixels relative to a position
3046\(0, 0) of the selected frame's display. */)
3047 (Lisp_Object x, Lisp_Object y)
3048{
3049#ifdef NS_IMPL_COCOA
3050 /* GNUstep doesn't support CGWarpMouseCursorPosition, so none of
3051 this will work. */
3052 struct frame *f = SELECTED_FRAME ();
3053 EmacsView *view = FRAME_NS_VIEW (f);
3054 NSScreen *screen = [[view window] screen];
3055 NSRect screen_frame = [screen frame];
3056 int mouse_x, mouse_y;
3057
3058 NSScreen *primary_screen = [[NSScreen screens] objectAtIndex:0];
3059 NSRect primary_screen_frame = [primary_screen frame];
3060 CGFloat primary_screen_height = primary_screen_frame.size.height;
3061
3062 if (FRAME_INITIAL_P (f) || !FRAME_NS_P (f))
3063 return Qnil;
3064
3065 CHECK_TYPE_RANGED_INTEGER (int, x);
3066 CHECK_TYPE_RANGED_INTEGER (int, y);
3067
3068 mouse_x = screen_frame.origin.x + XINT (x);
3069
3070 if (screen == primary_screen)
3071 mouse_y = screen_frame.origin.y + XINT (y);
3072 else
3073 mouse_y = (primary_screen_height - screen_frame.size.height
3074 - screen_frame.origin.y) + XINT (y);
3075
3076 CGPoint mouse_pos = CGPointMake(mouse_x, mouse_y);
3077 CGWarpMouseCursorPosition (mouse_pos);
3078#endif /* NS_IMPL_COCOA */
3079
3080 return Qnil;
3081}
3082
2938/* ========================================================================== 3083/* ==========================================================================
2939 3084
2940 Class implementations 3085 Class implementations
@@ -3121,6 +3266,9 @@ be used as the image of the icon representing the frame. */);
3121 defsubr (&Sns_display_monitor_attributes_list); 3266 defsubr (&Sns_display_monitor_attributes_list);
3122 defsubr (&Sns_frame_geometry); 3267 defsubr (&Sns_frame_geometry);
3123 defsubr (&Sns_frame_edges); 3268 defsubr (&Sns_frame_edges);
3269 defsubr (&Sns_frame_list_z_order);
3270 defsubr (&Sns_frame_restack);
3271 defsubr (&Sns_set_mouse_absolute_pixel_position);
3124 defsubr (&Sx_display_mm_width); 3272 defsubr (&Sx_display_mm_width);
3125 defsubr (&Sx_display_mm_height); 3273 defsubr (&Sx_display_mm_height);
3126 defsubr (&Sx_display_screens); 3274 defsubr (&Sx_display_screens);
diff --git a/src/nsimage.m b/src/nsimage.m
index cc8abf76094..fb2322afc30 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -152,7 +152,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
152 152
153@implementation EmacsImage 153@implementation EmacsImage
154 154
155+ allocInitFromFile: (Lisp_Object)file 155+ (instancetype)allocInitFromFile: (Lisp_Object)file
156{ 156{
157 NSImageRep *imgRep; 157 NSImageRep *imgRep;
158 Lisp_Object found; 158 Lisp_Object found;
@@ -197,7 +197,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
197 197
198/* Create image from monochrome bitmap. If both FG and BG are 0 198/* Create image from monochrome bitmap. If both FG and BG are 0
199 (black), set the background to white and make it transparent. */ 199 (black), set the background to white and make it transparent. */
200- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h 200- (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
201 fg: (unsigned long)fg bg: (unsigned long)bg 201 fg: (unsigned long)fg bg: (unsigned long)bg
202{ 202{
203 unsigned char *planes[5]; 203 unsigned char *planes[5];
@@ -269,7 +269,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
269} 269}
270 270
271/* Set color for a bitmap image. */ 271/* Set color for a bitmap image. */
272- setXBMColor: (NSColor *)color 272- (instancetype)setXBMColor: (NSColor *)color
273{ 273{
274 NSSize s = [self size]; 274 NSSize s = [self size];
275 unsigned char *planes[5]; 275 unsigned char *planes[5];
@@ -302,14 +302,14 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
302 planes[1][i] = gg; 302 planes[1][i] = gg;
303 planes[2][i] = bb; 303 planes[2][i] = bb;
304 } 304 }
305 xbm_fg = ((rr << 16) & 0xff) + ((gg << 8) & 0xff) + (bb & 0xff); 305 xbm_fg = ((rr << 16) & 0xff0000) + ((gg << 8) & 0xff00) + (bb & 0xff);
306 } 306 }
307 307
308 return self; 308 return self;
309} 309}
310 310
311 311
312- initForXPMWithDepth: (int)depth width: (int)width height: (int)height 312- (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height
313{ 313{
314 NSSize s = {width, height}; 314 NSSize s = {width, height};
315 int i; 315 int i;
@@ -386,7 +386,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
386 386
387- (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r 387- (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r
388 green: (unsigned char)g blue: (unsigned char)b 388 green: (unsigned char)g blue: (unsigned char)b
389 alpha:(unsigned char)a; 389 alpha:(unsigned char)a
390{ 390{
391 if (bmRep == nil) 391 if (bmRep == nil)
392 return; 392 return;
diff --git a/src/nsmenu.m b/src/nsmenu.m
index 59ea3855ed1..37a1a62d6d3 100644
--- a/src/nsmenu.m
+++ b/src/nsmenu.m
@@ -493,7 +493,7 @@ x_activate_menubar (struct frame *f)
493@implementation EmacsMenu 493@implementation EmacsMenu
494 494
495/* override designated initializer */ 495/* override designated initializer */
496- initWithTitle: (NSString *)title 496- (instancetype)initWithTitle: (NSString *)title
497{ 497{
498 frame = 0; 498 frame = 0;
499 if ((self = [super initWithTitle: title])) 499 if ((self = [super initWithTitle: title]))
@@ -503,7 +503,7 @@ x_activate_menubar (struct frame *f)
503 503
504 504
505/* used for top-level */ 505/* used for top-level */
506- initWithTitle: (NSString *)title frame: (struct frame *)f 506- (instancetype)initWithTitle: (NSString *)title frame: (struct frame *)f
507{ 507{
508 [self initWithTitle: title]; 508 [self initWithTitle: title];
509 frame = f; 509 frame = f;
@@ -750,7 +750,7 @@ x_activate_menubar (struct frame *f)
750 modifierFlags: 0 750 modifierFlags: 0
751 timestamp: [e timestamp] 751 timestamp: [e timestamp]
752 windowNumber: [[view window] windowNumber] 752 windowNumber: [[view window] windowNumber]
753 context: [e context] 753 context: nil
754 eventNumber: 0/*[e eventNumber] */ 754 eventNumber: 0/*[e eventNumber] */
755 clickCount: 1 755 clickCount: 1
756 pressure: 0]; 756 pressure: 0];
@@ -995,8 +995,6 @@ free_frame_tool_bar (struct frame *f)
995 block_input (); 995 block_input ();
996 view->wait_for_tool_bar = NO; 996 view->wait_for_tool_bar = NO;
997 997
998 FRAME_TOOLBAR_HEIGHT (f) = 0;
999
1000 /* Note: This trigger an animation, which calls windowDidResize 998 /* Note: This trigger an animation, which calls windowDidResize
1001 repeatedly. */ 999 repeatedly. */
1002 f->output_data.ns->in_animation = 1; 1000 f->output_data.ns->in_animation = 1;
@@ -1014,7 +1012,6 @@ update_frame_tool_bar (struct frame *f)
1014{ 1012{
1015 int i, k = 0; 1013 int i, k = 0;
1016 EmacsView *view = FRAME_NS_VIEW (f); 1014 EmacsView *view = FRAME_NS_VIEW (f);
1017 NSWindow *window = [view window];
1018 EmacsToolbar *toolbar = [view toolbar]; 1015 EmacsToolbar *toolbar = [view toolbar];
1019 int oldh; 1016 int oldh;
1020 1017
@@ -1129,12 +1126,6 @@ update_frame_tool_bar (struct frame *f)
1129 } 1126 }
1130#endif 1127#endif
1131 1128
1132 FRAME_TOOLBAR_HEIGHT (f) =
1133 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1134 - FRAME_NS_TITLEBAR_HEIGHT (f);
1135 if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen.
1136 FRAME_TOOLBAR_HEIGHT (f) = 0;
1137
1138 if (oldh != FRAME_TOOLBAR_HEIGHT (f)) 1129 if (oldh != FRAME_TOOLBAR_HEIGHT (f))
1139 [view updateFrameSize:YES]; 1130 [view updateFrameSize:YES];
1140 if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0) 1131 if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
@@ -1155,7 +1146,7 @@ update_frame_tool_bar (struct frame *f)
1155 1146
1156@implementation EmacsToolbar 1147@implementation EmacsToolbar
1157 1148
1158- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier 1149- (instancetype)initForView: (EmacsView *)view withIdentifier: (NSString *)identifier
1159{ 1150{
1160 NSTRACE ("[EmacsToolbar initForView: withIdentifier:]"); 1151 NSTRACE ("[EmacsToolbar initForView: withIdentifier:]");
1161 1152
@@ -1311,7 +1302,7 @@ update_frame_tool_bar (struct frame *f)
1311 display. */ 1302 display. */
1312@implementation EmacsTooltip 1303@implementation EmacsTooltip
1313 1304
1314- init 1305- (instancetype)init
1315{ 1306{
1316 NSColor *col = [NSColor colorWithCalibratedRed: 1.0 green: 1.0 1307 NSColor *col = [NSColor colorWithCalibratedRed: 1.0 green: 1.0
1317 blue: 0.792 alpha: 0.95]; 1308 blue: 0.792 alpha: 0.95];
@@ -1502,7 +1493,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
1502#define TEXTHEIGHT 20.0 1493#define TEXTHEIGHT 20.0
1503#define MINCELLWIDTH 90.0 1494#define MINCELLWIDTH 90.0
1504 1495
1505- initWithContentRect: (NSRect)contentRect styleMask: (NSUInteger)aStyle 1496- (instancetype)initWithContentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)aStyle
1506 backing: (NSBackingStoreType)backingType defer: (BOOL)flag 1497 backing: (NSBackingStoreType)backingType defer: (BOOL)flag
1507{ 1498{
1508 NSSize spacing = {SPACER, SPACER}; 1499 NSSize spacing = {SPACER, SPACER};
@@ -1526,7 +1517,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
1526 [img autorelease]; 1517 [img autorelease];
1527 [imgView autorelease]; 1518 [imgView autorelease];
1528 1519
1529 aStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSUtilityWindowMask; 1520 aStyle = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskUtilityWindow;
1530 flag = YES; 1521 flag = YES;
1531 rows = 0; 1522 rows = 0;
1532 cols = 1; 1523 cols = 1;
@@ -1706,7 +1697,7 @@ ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
1706} 1697}
1707 1698
1708 1699
1709- initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ 1700- (instancetype)initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ
1710{ 1701{
1711 Lisp_Object head; 1702 Lisp_Object head;
1712 [super init]; 1703 [super init];
diff --git a/src/nsterm.h b/src/nsterm.h
index 53d9344cc78..0f1b36db7b2 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -356,6 +356,12 @@ char const * nstrace_fullscreen_type_name (int);
356#endif 356#endif
357 357
358 358
359/* If the compiler doesn't support instancetype, map it to id. */
360#ifndef NATIVE_OBJC_INSTANCETYPE
361typedef id instancetype;
362#endif
363
364
359/* ========================================================================== 365/* ==========================================================================
360 366
361 NSColor, EmacsColor category. 367 NSColor, EmacsColor category.
@@ -430,7 +436,7 @@ char const * nstrace_fullscreen_type_name (int);
430 NSString *workingText; 436 NSString *workingText;
431 BOOL processingCompose; 437 BOOL processingCompose;
432 int fs_state, fs_before_fs, next_maximized; 438 int fs_state, fs_before_fs, next_maximized;
433 int tibar_height, tobar_height, bwidth; 439 int bwidth;
434 int maximized_width, maximized_height; 440 int maximized_width, maximized_height;
435 NSWindow *nonfs_window; 441 NSWindow *nonfs_window;
436 BOOL fs_is_native; 442 BOOL fs_is_native;
@@ -444,16 +450,17 @@ char const * nstrace_fullscreen_type_name (int);
444 } 450 }
445 451
446/* AppKit-side interface */ 452/* AppKit-side interface */
447- menuDown: (id)sender; 453- (instancetype)menuDown: (id)sender;
448- toolbarClicked: (id)item; 454- (instancetype)toolbarClicked: (id)item;
449- toggleToolbar: (id)sender; 455- (instancetype)toggleToolbar: (id)sender;
450- (void)keyDown: (NSEvent *)theEvent; 456- (void)keyDown: (NSEvent *)theEvent;
451- (void)mouseDown: (NSEvent *)theEvent; 457- (void)mouseDown: (NSEvent *)theEvent;
452- (void)mouseUp: (NSEvent *)theEvent; 458- (void)mouseUp: (NSEvent *)theEvent;
453- setMiniwindowImage: (BOOL)setMini; 459- (instancetype)setMiniwindowImage: (BOOL)setMini;
454 460
455/* Emacs-side interface */ 461/* Emacs-side interface */
456- initFrameFromEmacs: (struct frame *) f; 462- (instancetype) initFrameFromEmacs: (struct frame *) f;
463- (void) createToolbar: (struct frame *)f;
457- (void) setRows: (int) r andColumns: (int) c; 464- (void) setRows: (int) r andColumns: (int) c;
458- (void) setWindowClosing: (BOOL)closing; 465- (void) setWindowClosing: (BOOL)closing;
459- (EmacsToolbar *) toolbar; 466- (EmacsToolbar *) toolbar;
@@ -512,7 +519,7 @@ char const * nstrace_fullscreen_type_name (int);
512 unsigned long keyEquivModMask; 519 unsigned long keyEquivModMask;
513} 520}
514 521
515- initWithTitle: (NSString *)title frame: (struct frame *)f; 522- (instancetype)initWithTitle: (NSString *)title frame: (struct frame *)f;
516- (void)setFrame: (struct frame *)f; 523- (void)setFrame: (struct frame *)f;
517- (void)menuNeedsUpdate: (NSMenu *)menu; /* (delegate method) */ 524- (void)menuNeedsUpdate: (NSMenu *)menu; /* (delegate method) */
518- (NSString *)parseKeyEquiv: (const char *)key; 525- (NSString *)parseKeyEquiv: (const char *)key;
@@ -546,7 +553,7 @@ char const * nstrace_fullscreen_type_name (int);
546 NSArray *prevIdentifiers; 553 NSArray *prevIdentifiers;
547 unsigned long enablement, prevEnablement; 554 unsigned long enablement, prevEnablement;
548 } 555 }
549- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier; 556- (instancetype) initForView: (EmacsView *)view withIdentifier: (NSString *)identifier;
550- (void) clearActive; 557- (void) clearActive;
551- (void) clearAll; 558- (void) clearAll;
552- (BOOL) changed; 559- (BOOL) changed;
@@ -581,7 +588,7 @@ char const * nstrace_fullscreen_type_name (int);
581 Lisp_Object dialog_return; 588 Lisp_Object dialog_return;
582 Lisp_Object *button_values; 589 Lisp_Object *button_values;
583 } 590 }
584- initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ; 591- (instancetype)initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ;
585- (void)process_dialog: (Lisp_Object)list; 592- (void)process_dialog: (Lisp_Object)list;
586- (void)addButton: (char *)str value: (int)tag row: (int)row; 593- (void)addButton: (char *)str value: (int)tag row: (int)row;
587- (void)addString: (char *)str row: (int)row; 594- (void)addString: (char *)str row: (int)row;
@@ -600,7 +607,7 @@ char const * nstrace_fullscreen_type_name (int);
600 NSTextField *textField; 607 NSTextField *textField;
601 NSTimer *timer; 608 NSTimer *timer;
602 } 609 }
603- init; 610- (instancetype) init;
604- (void) setText: (char *)text; 611- (void) setText: (char *)text;
605- (void) showAtX: (int)x Y: (int)y for: (int)seconds; 612- (void) showAtX: (int)x Y: (int)y for: (int)seconds;
606- (void) hide; 613- (void) hide;
@@ -648,12 +655,12 @@ char const * nstrace_fullscreen_type_name (int);
648 NSColor *stippleMask; 655 NSColor *stippleMask;
649 unsigned long xbm_fg; 656 unsigned long xbm_fg;
650} 657}
651+ allocInitFromFile: (Lisp_Object)file; 658+ (instancetype)allocInitFromFile: (Lisp_Object)file;
652- (void)dealloc; 659- (void)dealloc;
653- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h 660- (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
654 fg: (unsigned long)fg bg: (unsigned long)bg; 661 fg: (unsigned long)fg bg: (unsigned long)bg;
655- setXBMColor: (NSColor *)color; 662- (instancetype)setXBMColor: (NSColor *)color;
656- initForXPMWithDepth: (int)depth width: (int)width height: (int)height; 663- (instancetype)initForXPMWithDepth: (int)depth width: (int)width height: (int)height;
657- (void)setPixmapData; 664- (void)setPixmapData;
658- (unsigned long)getPixelAtX: (int)x Y: (int)y; 665- (unsigned long)getPixelAtX: (int)x Y: (int)y;
659- (void)setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r 666- (void)setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r
@@ -692,16 +699,16 @@ char const * nstrace_fullscreen_type_name (int);
692 int em_whole; 699 int em_whole;
693 } 700 }
694 701
695- initFrame: (NSRect )r window: (Lisp_Object)win; 702- (instancetype) initFrame: (NSRect )r window: (Lisp_Object)win;
696- (void)setFrame: (NSRect)r; 703- (void)setFrame: (NSRect)r;
697 704
698- setPosition: (int) position portion: (int) portion whole: (int) whole; 705- (instancetype) setPosition: (int) position portion: (int) portion whole: (int) whole;
699- (int) checkSamePosition: (int)position portion: (int)portion 706- (int) checkSamePosition: (int)position portion: (int)portion
700 whole: (int)whole; 707 whole: (int)whole;
701- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e; 708- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e;
702- repeatScroll: (NSTimer *)sender; 709- (instancetype)repeatScroll: (NSTimer *)sender;
703- condemn; 710- (instancetype)condemn;
704- reprieve; 711- (instancetype)reprieve;
705- (bool)judge; 712- (bool)judge;
706+ (CGFloat)scrollerWidth; 713+ (CGFloat)scrollerWidth;
707@end 714@end
@@ -724,7 +731,7 @@ char const * nstrace_fullscreen_type_name (int);
724 unsigned long maxChar, maxGlyph; 731 unsigned long maxChar, maxGlyph;
725 long i, len; 732 long i, len;
726} 733}
727- initWithCapacity: (unsigned long) c; 734- (instancetype)initWithCapacity: (unsigned long) c;
728- (void) setString: (NSString *)str font: (NSFont *)font; 735- (void) setString: (NSString *)str font: (NSFont *)font;
729@end 736@end
730#endif /* NS_IMPL_COCOA */ 737#endif /* NS_IMPL_COCOA */
@@ -950,6 +957,14 @@ struct ns_output
950 Cursor hourglass_cursor; 957 Cursor hourglass_cursor;
951 Cursor horizontal_drag_cursor; 958 Cursor horizontal_drag_cursor;
952 Cursor vertical_drag_cursor; 959 Cursor vertical_drag_cursor;
960 Cursor left_edge_cursor;
961 Cursor top_left_corner_cursor;
962 Cursor top_edge_cursor;
963 Cursor top_right_corner_cursor;
964 Cursor right_edge_cursor;
965 Cursor bottom_right_corner_cursor;
966 Cursor bottom_edge_cursor;
967 Cursor bottom_left_corner_cursor;
953 968
954 /* NS-specific */ 969 /* NS-specific */
955 Cursor current_pointer; 970 Cursor current_pointer;
@@ -1012,8 +1027,6 @@ struct x_output
1012 1027
1013#define NS_FACE_FOREGROUND(f) ((f)->foreground) 1028#define NS_FACE_FOREGROUND(f) ((f)->foreground)
1014#define NS_FACE_BACKGROUND(f) ((f)->background) 1029#define NS_FACE_BACKGROUND(f) ((f)->background)
1015#define FRAME_NS_TITLEBAR_HEIGHT(f) ((f)->output_data.ns->titlebar_height)
1016#define FRAME_TOOLBAR_HEIGHT(f) ((f)->output_data.ns->toolbar_height)
1017 1030
1018#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) 1031#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID)
1019 1032
@@ -1029,6 +1042,25 @@ struct x_output
1029#define XNS_SCROLL_BAR(vec) XSAVE_POINTER (vec, 0) 1042#define XNS_SCROLL_BAR(vec) XSAVE_POINTER (vec, 0)
1030#endif 1043#endif
1031 1044
1045/* Compute pixel height of the frame's titlebar. */
1046#define FRAME_NS_TITLEBAR_HEIGHT(f) \
1047 (NSHeight([FRAME_NS_VIEW (f) frame]) == 0 ? \
1048 0 \
1049 : (int)(NSHeight([FRAME_NS_VIEW (f) window].frame) \
1050 - NSHeight([NSWindow contentRectForFrameRect: \
1051 [[FRAME_NS_VIEW (f) window] frame] \
1052 styleMask:[[FRAME_NS_VIEW (f) window] styleMask]])))
1053
1054/* Compute pixel height of the toolbar. */
1055#define FRAME_TOOLBAR_HEIGHT(f) \
1056 (([[FRAME_NS_VIEW (f) window] toolbar] == nil \
1057 || ! [[FRAME_NS_VIEW (f) window] toolbar].isVisible) ? \
1058 0 \
1059 : (int)(NSHeight([NSWindow contentRectForFrameRect: \
1060 [[FRAME_NS_VIEW (f) window] frame] \
1061 styleMask:[[FRAME_NS_VIEW (f) window] styleMask]]) \
1062 - NSHeight([[[FRAME_NS_VIEW (f) window] contentView] frame])))
1063
1032/* Compute pixel size for vertical scroll bars */ 1064/* Compute pixel size for vertical scroll bars */
1033#define NS_SCROLL_BAR_WIDTH(f) \ 1065#define NS_SCROLL_BAR_WIDTH(f) \
1034 (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \ 1066 (FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
@@ -1059,12 +1091,17 @@ struct x_output
1059 (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \ 1091 (FRAME_SCROLL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f) \
1060 - NS_SCROLL_BAR_HEIGHT (f)) : 0) 1092 - NS_SCROLL_BAR_HEIGHT (f)) : 0)
1061 1093
1062/* XXX: fix for GNUstep inconsistent accounting for titlebar */ 1094/* Calculate system coordinates of the left and top of the parent
1063#ifdef NS_IMPL_GNUSTEP 1095 window or, if there is no parent window, the screen. */
1064#define NS_TOP_POS(f) ((f)->top_pos + 18) 1096#define NS_PARENT_WINDOW_LEFT_POS(f) \
1065#else 1097 (FRAME_PARENT_FRAME (f) != NULL \
1066#define NS_TOP_POS(f) ((f)->top_pos) 1098 ? [[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.x : 0)
1067#endif 1099#define NS_PARENT_WINDOW_TOP_POS(f) \
1100 (FRAME_PARENT_FRAME (f) != NULL \
1101 ? ([[FRAME_NS_VIEW (f) window] parentWindow].frame.origin.y \
1102 + [[FRAME_NS_VIEW (f) window] parentWindow].frame.size.height \
1103 - FRAME_NS_TITLEBAR_HEIGHT (FRAME_PARENT_FRAME (f))) \
1104 : [[[NSScreen screens] objectAtIndex: 0] frame].size.height)
1068 1105
1069#define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table) 1106#define FRAME_NS_FONT_TABLE(f) (FRAME_DISPLAY_INFO (f)->font_table)
1070 1107
@@ -1185,9 +1222,22 @@ extern int x_display_pixel_width (struct ns_display_info *);
1185/* This in nsterm.m */ 1222/* This in nsterm.m */
1186extern float ns_antialias_threshold; 1223extern float ns_antialias_threshold;
1187extern void x_destroy_window (struct frame *f); 1224extern void x_destroy_window (struct frame *f);
1225extern void x_set_undecorated (struct frame *f, Lisp_Object new_value,
1226 Lisp_Object old_value);
1227extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value,
1228 Lisp_Object old_value);
1229extern void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value,
1230 Lisp_Object old_value);
1231extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
1232 Lisp_Object old_value);
1233extern void x_set_z_group (struct frame *f, Lisp_Object new_value,
1234 Lisp_Object old_value);
1188extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, 1235extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds,
1189 fd_set *exceptfds, struct timespec const *timeout, 1236 fd_set *exceptfds, struct timespec *timeout,
1190 sigset_t const *sigmask); 1237 sigset_t *sigmask);
1238#ifdef HAVE_PTHREAD
1239extern void ns_run_loop_break (void);
1240#endif
1191extern unsigned long ns_get_rgb_color (struct frame *f, 1241extern unsigned long ns_get_rgb_color (struct frame *f,
1192 float r, float g, float b, float a); 1242 float r, float g, float b, float a);
1193 1243
@@ -1259,8 +1309,14 @@ extern char gnustep_base_version[]; /* version tracking */
1259#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask 1309#define NSWindowStyleMaskMiniaturizable NSMiniaturizableWindowMask
1260#define NSWindowStyleMaskResizable NSResizableWindowMask 1310#define NSWindowStyleMaskResizable NSResizableWindowMask
1261#define NSWindowStyleMaskTitled NSTitledWindowMask 1311#define NSWindowStyleMaskTitled NSTitledWindowMask
1312#define NSWindowStyleMaskUtilityWindow NSUtilityWindowMask
1262#define NSAlertStyleCritical NSCriticalAlertStyle 1313#define NSAlertStyleCritical NSCriticalAlertStyle
1263#define NSControlSizeRegular NSRegularControlSize 1314#define NSControlSizeRegular NSRegularControlSize
1315
1316/* And adds NSWindowStyleMask. */
1317#ifdef __OBJC__
1318typedef NSUInteger NSWindowStyleMask;
1319#endif
1264#endif 1320#endif
1265 1321
1266#endif /* HAVE_NS */ 1322#endif /* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
index b03ad526212..bf83550b3d7 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -411,6 +411,23 @@ static CGPoint menu_mouse_point;
411 ns_send_appdefined (-1); \ 411 ns_send_appdefined (-1); \
412 } 412 }
413 413
414
415/* GNUstep always shows decorations if the window is resizable,
416 miniaturizable or closable, but Cocoa does strange things in native
417 fullscreen mode if you don't have at least resizable enabled.
418
419 These flags will be OR'd or XOR'd with the NSWindow's styleMask
420 property depending on what we're doing. */
421#ifdef NS_IMPL_COCOA
422#define FRAME_DECORATED_FLAGS NSWindowStyleMaskTitled
423#else
424#define FRAME_DECORATED_FLAGS (NSWindowStyleMaskTitled \
425 | NSWindowStyleMaskResizable \
426 | NSWindowStyleMaskMiniaturizable \
427 | NSWindowStyleMaskClosable)
428#endif
429#define FRAME_UNDECORATED_FLAGS NSWindowStyleMaskBorderless
430
414/* TODO: get rid of need for these forward declarations */ 431/* TODO: get rid of need for these forward declarations */
415static void ns_condemn_scroll_bars (struct frame *f); 432static void ns_condemn_scroll_bars (struct frame *f);
416static void ns_judge_scroll_bars (struct frame *f); 433static void ns_judge_scroll_bars (struct frame *f);
@@ -1300,7 +1317,7 @@ ns_clip_to_row (struct window *w, struct glyph_row *row,
1300 1317
1301@implementation EmacsBell 1318@implementation EmacsBell
1302 1319
1303- (id)init; 1320- (id)init
1304{ 1321{
1305 NSTRACE ("[EmacsBell init]"); 1322 NSTRACE ("[EmacsBell init]");
1306 if ((self = [super init])) 1323 if ((self = [super init]))
@@ -1446,9 +1463,9 @@ hide_bell (void)
1446 1463
1447 1464
1448static void 1465static void
1449ns_raise_frame (struct frame *f) 1466ns_raise_frame (struct frame *f, BOOL make_key)
1450/* -------------------------------------------------------------------------- 1467/* --------------------------------------------------------------------------
1451 Bring window to foreground and make it active 1468 Bring window to foreground and if make_key is YES, give it focus.
1452 -------------------------------------------------------------------------- */ 1469 -------------------------------------------------------------------------- */
1453{ 1470{
1454 NSView *view; 1471 NSView *view;
@@ -1457,7 +1474,12 @@ ns_raise_frame (struct frame *f)
1457 view = FRAME_NS_VIEW (f); 1474 view = FRAME_NS_VIEW (f);
1458 block_input (); 1475 block_input ();
1459 if (FRAME_VISIBLE_P (f)) 1476 if (FRAME_VISIBLE_P (f))
1460 [[view window] makeKeyAndOrderFront: NSApp]; 1477 {
1478 if (make_key)
1479 [[view window] makeKeyAndOrderFront: NSApp];
1480 else
1481 [[view window] orderFront: NSApp];
1482 }
1461 unblock_input (); 1483 unblock_input ();
1462} 1484}
1463 1485
@@ -1487,7 +1509,7 @@ ns_frame_raise_lower (struct frame *f, bool raise)
1487 NSTRACE ("ns_frame_raise_lower"); 1509 NSTRACE ("ns_frame_raise_lower");
1488 1510
1489 if (raise) 1511 if (raise)
1490 ns_raise_frame (f); 1512 ns_raise_frame (f, YES);
1491 else 1513 else
1492 ns_lower_frame (f); 1514 ns_lower_frame (f);
1493} 1515}
@@ -1550,7 +1572,7 @@ x_make_frame_visible (struct frame *f)
1550 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); 1572 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1551 1573
1552 SET_FRAME_VISIBLE (f, 1); 1574 SET_FRAME_VISIBLE (f, 1);
1553 ns_raise_frame (f); 1575 ns_raise_frame (f, ! FRAME_NO_FOCUS_ON_MAP (f));
1554 1576
1555 /* Making a new frame from a fullscreen frame will make the new frame 1577 /* Making a new frame from a fullscreen frame will make the new frame
1556 fullscreen also. So skip handleFS as this will print an error. */ 1578 fullscreen also. So skip handleFS as this will print an error. */
@@ -1668,6 +1690,17 @@ x_destroy_window (struct frame *f)
1668 -------------------------------------------------------------------------- */ 1690 -------------------------------------------------------------------------- */
1669{ 1691{
1670 NSTRACE ("x_destroy_window"); 1692 NSTRACE ("x_destroy_window");
1693
1694 /* If this frame has a parent window, detach it as not doing so can
1695 cause a crash in GNUStep. */
1696 if (FRAME_PARENT_FRAME (f) != NULL)
1697 {
1698 NSWindow *child = [FRAME_NS_VIEW (f) window];
1699 NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window];
1700
1701 [parent removeChildWindow: child];
1702 }
1703
1671 check_window_system (f); 1704 check_window_system (f);
1672 x_free_frame_resources (f); 1705 x_free_frame_resources (f);
1673 ns_window_num--; 1706 ns_window_num--;
@@ -1706,14 +1739,18 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1706 - FRAME_TOOLBAR_HEIGHT (f)) 1739 - FRAME_TOOLBAR_HEIGHT (f))
1707 : f->top_pos; 1740 : f->top_pos;
1708#ifdef NS_IMPL_GNUSTEP 1741#ifdef NS_IMPL_GNUSTEP
1709 if (f->left_pos < 100) 1742 if (FRAME_PARENT_FRAME (f) == NULL)
1710 f->left_pos = 100; /* don't overlap menu */ 1743 {
1744 if (f->left_pos < 100)
1745 f->left_pos = 100; /* don't overlap menu */
1746 }
1711#endif 1747#endif
1712 /* Constrain the setFrameTopLeftPoint so we don't move behind the 1748 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1713 menu bar. */ 1749 menu bar. */
1714 NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos), 1750 NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos
1715 SCREENMAXBOUND ([fscreen frame].size.height 1751 + NS_PARENT_WINDOW_LEFT_POS (f)),
1716 - NS_TOP_POS (f))); 1752 SCREENMAXBOUND (NS_PARENT_WINDOW_TOP_POS (f)
1753 - f->top_pos));
1717 NSTRACE_POINT ("setFrameTopLeftPoint", pt); 1754 NSTRACE_POINT ("setFrameTopLeftPoint", pt);
1718 [[view window] setFrameTopLeftPoint: pt]; 1755 [[view window] setFrameTopLeftPoint: pt];
1719 f->size_hint_flags &= ~(XNegative|YNegative); 1756 f->size_hint_flags &= ~(XNegative|YNegative);
@@ -1738,7 +1775,6 @@ x_set_window_size (struct frame *f,
1738 EmacsView *view = FRAME_NS_VIEW (f); 1775 EmacsView *view = FRAME_NS_VIEW (f);
1739 NSWindow *window = [view window]; 1776 NSWindow *window = [view window];
1740 NSRect wr = [window frame]; 1777 NSRect wr = [window frame];
1741 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1742 int pixelwidth, pixelheight; 1778 int pixelwidth, pixelheight;
1743 int orig_height = wr.size.height; 1779 int orig_height = wr.size.height;
1744 1780
@@ -1764,25 +1800,6 @@ x_set_window_size (struct frame *f,
1764 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height); 1800 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
1765 } 1801 }
1766 1802
1767 /* If we have a toolbar, take its height into account. */
1768 if (tb && ! [view isFullscreen])
1769 {
1770 /* NOTE: previously this would generate wrong result if toolbar not
1771 yet displayed and fixing toolbar_height=32 helped, but
1772 now (200903) seems no longer needed */
1773 FRAME_TOOLBAR_HEIGHT (f) =
1774 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1775 - FRAME_NS_TITLEBAR_HEIGHT (f);
1776#if 0
1777 /* Only breaks things here, removed by martin 2015-09-30. */
1778#ifdef NS_IMPL_GNUSTEP
1779 FRAME_TOOLBAR_HEIGHT (f) -= 3;
1780#endif
1781#endif
1782 }
1783 else
1784 FRAME_TOOLBAR_HEIGHT (f) = 0;
1785
1786 wr.size.width = pixelwidth + f->border_width; 1803 wr.size.width = pixelwidth + f->border_width;
1787 wr.size.height = pixelheight; 1804 wr.size.height = pixelheight;
1788 if (! [view isFullscreen]) 1805 if (! [view isFullscreen])
@@ -1811,6 +1828,184 @@ x_set_window_size (struct frame *f,
1811 unblock_input (); 1828 unblock_input ();
1812} 1829}
1813 1830
1831#ifdef NS_IMPL_COCOA
1832void
1833x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1834/* --------------------------------------------------------------------------
1835 Set frame F's `undecorated' parameter. If non-nil, F's window-system
1836 window is drawn without decorations, title, minimize/maximize boxes
1837 and external borders. This usually means that the window cannot be
1838 dragged, resized, iconified, maximized or deleted with the mouse. If
1839 nil, draw the frame with all the elements listed above unless these
1840 have been suspended via window manager settings.
1841
1842 GNUStep cannot change an existing window's style.
1843 -------------------------------------------------------------------------- */
1844{
1845 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1846 NSWindow *window = [view window];
1847
1848 NSTRACE ("x_set_undecorated");
1849
1850 if (!EQ (new_value, old_value))
1851 {
1852 block_input ();
1853
1854 if (NILP (new_value))
1855 {
1856 FRAME_UNDECORATED (f) = false;
1857 [window setStyleMask: ((window.styleMask | FRAME_DECORATED_FLAGS)
1858 ^ FRAME_UNDECORATED_FLAGS)];
1859
1860 [view createToolbar: f];
1861 }
1862 else
1863 {
1864 [window setToolbar: nil];
1865 /* Do I need to release the toolbar here? */
1866
1867 FRAME_UNDECORATED (f) = true;
1868 [window setStyleMask: ((window.styleMask | FRAME_UNDECORATED_FLAGS)
1869 ^ FRAME_DECORATED_FLAGS)];
1870 }
1871
1872 /* At this point it seems we don't have an active NSResponder,
1873 so some key presses (TAB) are swallowed by the system. */
1874 [window makeFirstResponder: view];
1875
1876 [view updateFrameSize: NO];
1877 unblock_input ();
1878 }
1879}
1880#endif /* NS_IMPL_COCOA */
1881
1882void
1883x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1884/* --------------------------------------------------------------------------
1885 Set frame F's `parent-frame' parameter. If non-nil, make F a child
1886 frame of the frame specified by that parameter. Technically, this
1887 makes F's window-system window a child window of the parent frame's
1888 window-system window. If nil, make F's window-system window a
1889 top-level window--a child of its display's root window.
1890
1891 A child frame's `left' and `top' parameters specify positions
1892 relative to the top-left corner of its parent frame's native
1893 rectangle. On macOS moving a parent frame moves all its child
1894 frames too, keeping their position relative to the parent
1895 unaltered. When a parent frame is iconified or made invisible, its
1896 child frames are made invisible. When a parent frame is deleted,
1897 its child frames are deleted too.
1898
1899 Whether a child frame has a tool bar may be window-system or window
1900 manager dependent. It's advisable to disable it via the frame
1901 parameter settings.
1902
1903 Some window managers may not honor this parameter.
1904 -------------------------------------------------------------------------- */
1905{
1906 struct frame *p = NULL;
1907 NSWindow *parent, *child;
1908
1909 NSTRACE ("x_set_parent_frame");
1910
1911 if (!NILP (new_value)
1912 && (!FRAMEP (new_value)
1913 || !FRAME_LIVE_P (p = XFRAME (new_value))
1914 || !FRAME_X_P (p)))
1915 {
1916 store_frame_param (f, Qparent_frame, old_value);
1917 error ("Invalid specification of `parent-frame'");
1918 }
1919
1920 if (p != FRAME_PARENT_FRAME (f))
1921 {
1922 parent = [FRAME_NS_VIEW (p) window];
1923 child = [FRAME_NS_VIEW (f) window];
1924
1925 block_input ();
1926 [parent addChildWindow: child
1927 ordered: NSWindowAbove];
1928 unblock_input ();
1929
1930 fset_parent_frame (f, new_value);
1931 }
1932}
1933
1934void
1935x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1936/* Set frame F's `no-focus-on-map' parameter which, if non-nil, means
1937 * that F's window-system window does not want to receive input focus
1938 * when it is mapped. (A frame's window is mapped when the frame is
1939 * displayed for the first time and when the frame changes its state
1940 * from `iconified' or `invisible' to `visible'.)
1941 *
1942 * Some window managers may not honor this parameter. */
1943{
1944 NSTRACE ("x_set_no_focus_on_map");
1945
1946 if (!EQ (new_value, old_value))
1947 {
1948 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
1949 }
1950}
1951
1952void
1953x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1954/* Set frame F's `no-accept-focus' parameter which, if non-nil, hints
1955 * that F's window-system window does not want to receive input focus
1956 * via mouse clicks or by moving the mouse into it.
1957 *
1958 * If non-nil, this may have the unwanted side-effect that a user cannot
1959 * scroll a non-selected frame with the mouse.
1960 *
1961 * Some window managers may not honor this parameter. */
1962{
1963 NSTRACE ("x_set_no_accept_focus");
1964
1965 if (!EQ (new_value, old_value))
1966 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
1967}
1968
1969void
1970x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
1971/* Set frame F's `z-group' parameter. If `above', F's window-system
1972 window is displayed above all windows that do not have the `above'
1973 property set. If nil, F's window is shown below all windows that
1974 have the `above' property set and above all windows that have the
1975 `below' property set. If `below', F's window is displayed below
1976 all windows that do.
1977
1978 Some window managers may not honor this parameter. */
1979{
1980 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
1981 NSWindow *window = [view window];
1982
1983 NSTRACE ("x_set_z_group");
1984
1985 if (NILP (new_value))
1986 {
1987 window.level = NSNormalWindowLevel;
1988 FRAME_Z_GROUP (f) = z_group_none;
1989 }
1990 else if (EQ (new_value, Qabove))
1991 {
1992 window.level = NSNormalWindowLevel + 1;
1993 FRAME_Z_GROUP (f) = z_group_above;
1994 }
1995 else if (EQ (new_value, Qabove_suspended))
1996 {
1997 /* Not sure what level this should be. */
1998 window.level = NSNormalWindowLevel + 1;
1999 FRAME_Z_GROUP (f) = z_group_above_suspended;
2000 }
2001 else if (EQ (new_value, Qbelow))
2002 {
2003 window.level = NSNormalWindowLevel - 1;
2004 FRAME_Z_GROUP (f) = z_group_below;
2005 }
2006 else
2007 error ("Invalid z-group specification");
2008}
1814 2009
1815static void 2010static void
1816ns_fullscreen_hook (struct frame *f) 2011ns_fullscreen_hook (struct frame *f)
@@ -2149,14 +2344,14 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
2149 -------------------------------------------------------------------------- */ 2344 -------------------------------------------------------------------------- */
2150{ 2345{
2151 NSTRACE ("frame_set_mouse_pixel_position"); 2346 NSTRACE ("frame_set_mouse_pixel_position");
2152 ns_raise_frame (f); 2347
2153#if 0 2348 /* FIXME: what about GNUstep? */
2154 /* FIXME: this does not work, and what about GNUstep? */
2155#ifdef NS_IMPL_COCOA 2349#ifdef NS_IMPL_COCOA
2156 [FRAME_NS_VIEW (f) lockFocus]; 2350 CGPoint mouse_pos =
2157 PSsetmouse ((float)pix_x, (float)pix_y); 2351 CGPointMake(f->left_pos + pix_x,
2158 [FRAME_NS_VIEW (f) unlockFocus]; 2352 f->top_pos + pix_y +
2159#endif 2353 FRAME_NS_TITLEBAR_HEIGHT(f) + FRAME_TOOLBAR_HEIGHT(f));
2354 CGWarpMouseCursorPosition (mouse_pos);
2160#endif 2355#endif
2161} 2356}
2162 2357
@@ -3873,7 +4068,7 @@ ns_send_appdefined (int value)
3873 app->nextappdefined = value; 4068 app->nextappdefined = value;
3874 [app performSelectorOnMainThread:@selector (sendFromMainThread:) 4069 [app performSelectorOnMainThread:@selector (sendFromMainThread:)
3875 withObject:nil 4070 withObject:nil
3876 waitUntilDone:YES]; 4071 waitUntilDone:NO];
3877 return; 4072 return;
3878 } 4073 }
3879 4074
@@ -4075,7 +4270,6 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
4075 } 4270 }
4076 else 4271 else
4077 { 4272 {
4078 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
4079 /* Run and wait for events. We must always send one NX_APPDEFINED event 4273 /* Run and wait for events. We must always send one NX_APPDEFINED event
4080 to ourself, otherwise [NXApp run] will never exit. */ 4274 to ourself, otherwise [NXApp run] will never exit. */
4081 send_appdefined = YES; 4275 send_appdefined = YES;
@@ -4090,6 +4284,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
4090 q_event_ptr = NULL; 4284 q_event_ptr = NULL;
4091 unblock_input (); 4285 unblock_input ();
4092 } 4286 }
4287 else
4288 return -1;
4093 4289
4094 return nevents; 4290 return nevents;
4095} 4291}
@@ -4097,8 +4293,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
4097 4293
4098int 4294int
4099ns_select (int nfds, fd_set *readfds, fd_set *writefds, 4295ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4100 fd_set *exceptfds, struct timespec const *timeout, 4296 fd_set *exceptfds, struct timespec *timeout,
4101 sigset_t const *sigmask) 4297 sigset_t *sigmask)
4102/* -------------------------------------------------------------------------- 4298/* --------------------------------------------------------------------------
4103 Replacement for select, checking for events 4299 Replacement for select, checking for events
4104 -------------------------------------------------------------------------- */ 4300 -------------------------------------------------------------------------- */
@@ -4131,7 +4327,13 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4131 if (NSApp == nil 4327 if (NSApp == nil
4132 || ![NSThread isMainThread] 4328 || ![NSThread isMainThread]
4133 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) 4329 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
4134 return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); 4330 return thread_select(pselect, nfds, readfds, writefds,
4331 exceptfds, timeout, sigmask);
4332 else
4333 {
4334 struct timespec t = {0, 0};
4335 thread_select(pselect, 0, NULL, NULL, NULL, &t, sigmask);
4336 }
4135 4337
4136 [outerpool release]; 4338 [outerpool release];
4137 outerpool = [[NSAutoreleasePool alloc] init]; 4339 outerpool = [[NSAutoreleasePool alloc] init];
@@ -4234,6 +4436,18 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4234 return result; 4436 return result;
4235} 4437}
4236 4438
4439#ifdef HAVE_PTHREAD
4440void
4441ns_run_loop_break ()
4442/* Break out of the NS run loop in ns_select or ns_read_socket. */
4443{
4444 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_run_loop_break");
4445
4446 /* If we don't have a GUI, don't send the event. */
4447 if (NSApp != NULL)
4448 ns_send_appdefined(-1);
4449}
4450#endif
4237 4451
4238 4452
4239/* ========================================================================== 4453/* ==========================================================================
@@ -6288,7 +6502,7 @@ not_in_argv (NSString *arg)
6288 if (WINDOWP (window) 6502 if (WINDOWP (window)
6289 && !EQ (window, last_mouse_window) 6503 && !EQ (window, last_mouse_window)
6290 && !EQ (window, selected_window) 6504 && !EQ (window, selected_window)
6291 && (focus_follows_mouse 6505 && (!NILP (focus_follows_mouse)
6292 || (EQ (XWINDOW (window)->frame, 6506 || (EQ (XWINDOW (window)->frame,
6293 XWINDOW (selected_window)->frame)))) 6507 XWINDOW (selected_window)->frame))))
6294 { 6508 {
@@ -6357,7 +6571,7 @@ not_in_argv (NSString *arg)
6357 return NO; 6571 return NO;
6358} 6572}
6359 6573
6360- (void) updateFrameSize: (BOOL) delay; 6574- (void) updateFrameSize: (BOOL) delay
6361{ 6575{
6362 NSWindow *window = [self window]; 6576 NSWindow *window = [self window];
6363 NSRect wr = [window frame]; 6577 NSRect wr = [window frame];
@@ -6387,7 +6601,10 @@ not_in_argv (NSString *arg)
6387 6601
6388 if (wait_for_tool_bar) 6602 if (wait_for_tool_bar)
6389 { 6603 {
6390 if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0) 6604 /* The toolbar height is always 0 in fullscreen, so don't wait
6605 for it to become available. */
6606 if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0
6607 && ! [self isFullscreen])
6391 { 6608 {
6392 NSTRACE_MSG ("Waiting for toolbar"); 6609 NSTRACE_MSG ("Waiting for toolbar");
6393 return; 6610 return;
@@ -6399,7 +6616,8 @@ not_in_argv (NSString *arg)
6399 newh = (int)wr.size.height - extra; 6616 newh = (int)wr.size.height - extra;
6400 6617
6401 NSTRACE_SIZE ("New size", NSMakeSize (neww, newh)); 6618 NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
6402 NSTRACE_MSG ("tool_bar_height: %d", emacsframe->tool_bar_height); 6619 NSTRACE_MSG ("FRAME_TOOLBAR_HEIGHT: %d", FRAME_TOOLBAR_HEIGHT (emacsframe));
6620 NSTRACE_MSG ("FRAME_NS_TITLEBAR_HEIGHT: %d", FRAME_NS_TITLEBAR_HEIGHT (emacsframe));
6403 6621
6404 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww); 6622 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
6405 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh); 6623 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
@@ -6424,9 +6642,11 @@ not_in_argv (NSString *arg)
6424 SET_FRAME_GARBAGED (emacsframe); 6642 SET_FRAME_GARBAGED (emacsframe);
6425 cancel_mouse_face (emacsframe); 6643 cancel_mouse_face (emacsframe);
6426 6644
6427 wr = NSMakeRect (0, 0, neww, newh); 6645 /* The next two lines appear to be setting the frame to the same
6646 size as it already is. Why are they there? */
6647 // wr = NSMakeRect (0, 0, neww, newh);
6428 6648
6429 [view setFrame: wr]; 6649 // [view setFrame: wr];
6430 6650
6431 // to do: consider using [NSNotificationCenter postNotificationName:]. 6651 // to do: consider using [NSNotificationCenter postNotificationName:].
6432 [self windowDidMove: // Update top/left. 6652 [self windowDidMove: // Update top/left.
@@ -6489,7 +6709,8 @@ not_in_argv (NSString *arg)
6489 old_title = 0; 6709 old_title = 0;
6490 } 6710 }
6491 } 6711 }
6492 else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize) 6712 else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize
6713 && [[self window] title] != NULL)
6493 { 6714 {
6494 char *size_title; 6715 char *size_title;
6495 NSWindow *window = [self window]; 6716 NSWindow *window = [self window];
@@ -6671,7 +6892,7 @@ not_in_argv (NSString *arg)
6671} 6892}
6672 6893
6673 6894
6674- (void)setFrame:(NSRect)frameRect; 6895- (void)setFrame:(NSRect)frameRect
6675{ 6896{
6676 NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]", 6897 NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]",
6677 NSTRACE_ARG_RECT (frameRect)); 6898 NSTRACE_ARG_RECT (frameRect));
@@ -6692,7 +6913,35 @@ not_in_argv (NSString *arg)
6692} 6913}
6693 6914
6694 6915
6695- initFrameFromEmacs: (struct frame *)f 6916- (void)createToolbar: (struct frame *)f
6917{
6918 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
6919 NSWindow *window = [view window];
6920
6921 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
6922 [NSString stringWithFormat: @"Emacs Frame %d",
6923 ns_window_num]];
6924 [toolbar setVisible: NO];
6925 [window setToolbar: toolbar];
6926
6927 /* Don't set frame garbaged until tool bar is up to date?
6928 This avoids an extra clear and redraw (flicker) at frame creation. */
6929 if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES;
6930 else wait_for_tool_bar = NO;
6931
6932
6933#ifdef NS_IMPL_COCOA
6934 {
6935 NSButton *toggleButton;
6936 toggleButton = [window standardWindowButton: NSWindowToolbarButton];
6937 [toggleButton setTarget: self];
6938 [toggleButton setAction: @selector (toggleToolbar: )];
6939 }
6940#endif
6941}
6942
6943
6944- (instancetype) initFrameFromEmacs: (struct frame *)f
6696{ 6945{
6697 NSRect r, wr; 6946 NSRect r, wr;
6698 Lisp_Object tem; 6947 Lisp_Object tem;
@@ -6731,12 +6980,15 @@ not_in_argv (NSString *arg)
6731 6980
6732 win = [[EmacsWindow alloc] 6981 win = [[EmacsWindow alloc]
6733 initWithContentRect: r 6982 initWithContentRect: r
6734 styleMask: (NSWindowStyleMaskResizable | 6983 styleMask: (FRAME_UNDECORATED (f)
6735#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 6984 ? FRAME_UNDECORATED_FLAGS
6736 NSWindowStyleMaskTitled | 6985 : FRAME_DECORATED_FLAGS
6986#ifdef NS_IMPL_COCOA
6987 | NSWindowStyleMaskResizable
6988 | NSWindowStyleMaskMiniaturizable
6989 | NSWindowStyleMaskClosable
6737#endif 6990#endif
6738 NSWindowStyleMaskMiniaturizable | 6991 )
6739 NSWindowStyleMaskClosable)
6740 backing: NSBackingStoreBuffered 6992 backing: NSBackingStoreBuffered
6741 defer: YES]; 6993 defer: YES];
6742 6994
@@ -6746,7 +6998,6 @@ not_in_argv (NSString *arg)
6746 6998
6747 wr = [win frame]; 6999 wr = [win frame];
6748 bwidth = f->border_width = wr.size.width - r.size.width; 7000 bwidth = f->border_width = wr.size.width - r.size.width;
6749 tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
6750 7001
6751 [win setAcceptsMouseMovedEvents: YES]; 7002 [win setAcceptsMouseMovedEvents: YES];
6752 [win setDelegate: self]; 7003 [win setDelegate: self];
@@ -6766,42 +7017,36 @@ not_in_argv (NSString *arg)
6766 [win setTitle: name]; 7017 [win setTitle: name];
6767 7018
6768 /* toolbar support */ 7019 /* toolbar support */
6769 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier: 7020 if (! FRAME_UNDECORATED (f))
6770 [NSString stringWithFormat: @"Emacs Frame %d", 7021 [self createToolbar: f];
6771 ns_window_num]];
6772 [win setToolbar: toolbar];
6773 [toolbar setVisible: NO];
6774
6775 /* Don't set frame garbaged until tool bar is up to date?
6776 This avoids an extra clear and redraw (flicker) at frame creation. */
6777 if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES;
6778 else wait_for_tool_bar = NO;
6779
6780
6781#ifdef NS_IMPL_COCOA
6782 {
6783 NSButton *toggleButton;
6784 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
6785 [toggleButton setTarget: self];
6786 [toggleButton setAction: @selector (toggleToolbar: )];
6787 }
6788#endif
6789 FRAME_TOOLBAR_HEIGHT (f) = 0;
6790 7022
6791 tem = f->icon_name; 7023 tem = f->icon_name;
6792 if (!NILP (tem)) 7024 if (!NILP (tem))
6793 [win setMiniwindowTitle: 7025 [win setMiniwindowTitle:
6794 [NSString stringWithUTF8String: SSDATA (tem)]]; 7026 [NSString stringWithUTF8String: SSDATA (tem)]];
6795 7027
7028 if (FRAME_PARENT_FRAME (f) != NULL)
7029 {
7030 NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window];
7031 [parent addChildWindow: win
7032 ordered: NSWindowAbove];
7033 }
7034
7035 if (FRAME_Z_GROUP (f) != z_group_none)
7036 win.level = NSNormalWindowLevel
7037 + (FRAME_Z_GROUP_BELOW (f) ? -1 : 1);
7038
6796 { 7039 {
6797 NSScreen *screen = [win screen]; 7040 NSScreen *screen = [win screen];
6798 7041
6799 if (screen != 0) 7042 if (screen != 0)
6800 { 7043 {
6801 NSPoint pt = NSMakePoint 7044 NSPoint pt = NSMakePoint
6802 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX), 7045 (IN_BOUND (-SCREENMAX, f->left_pos
7046 + NS_PARENT_WINDOW_LEFT_POS (f), SCREENMAX),
6803 IN_BOUND (-SCREENMAX, 7047 IN_BOUND (-SCREENMAX,
6804 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX)); 7048 NS_PARENT_WINDOW_TOP_POS (f) - f->top_pos,
7049 SCREENMAX));
6805 7050
6806 [win setFrameTopLeftPoint: pt]; 7051 [win setFrameTopLeftPoint: pt];
6807 7052
@@ -6823,7 +7068,15 @@ not_in_argv (NSString *arg)
6823 [self allocateGState]; 7068 [self allocateGState];
6824#endif 7069#endif
6825 [NSApp registerServicesMenuSendTypes: ns_send_types 7070 [NSApp registerServicesMenuSendTypes: ns_send_types
6826 returnTypes: nil]; 7071 returnTypes: [NSArray array]];
7072
7073 /* macOS Sierra automatically enables tabbed windows. We can't
7074 allow this to be enabled until it's available on a Free system.
7075 Currently it only happens by accident and is buggy anyway. */
7076#if defined (NS_IMPL_COCOA) && \
7077 MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
7078 [win setTabbingMode: NSWindowTabbingModeDisallowed];
7079#endif
6827 7080
6828 ns_window_num++; 7081 ns_window_num++;
6829 return self; 7082 return self;
@@ -6843,9 +7096,15 @@ not_in_argv (NSString *arg)
6843 return; 7096 return;
6844 if (screen != nil) 7097 if (screen != nil)
6845 { 7098 {
6846 emacsframe->left_pos = r.origin.x; 7099 emacsframe->left_pos = r.origin.x - NS_PARENT_WINDOW_LEFT_POS (emacsframe);
6847 emacsframe->top_pos = 7100 emacsframe->top_pos =
6848 [screen frame].size.height - (r.origin.y + r.size.height); 7101 NS_PARENT_WINDOW_TOP_POS (emacsframe) - (r.origin.y + r.size.height);
7102
7103 if (emacs_event)
7104 {
7105 emacs_event->kind = MOVE_FRAME_EVENT;
7106 EV_TRAILER ((id)nil);
7107 }
6849 } 7108 }
6850} 7109}
6851 7110
@@ -7262,9 +7521,6 @@ not_in_argv (NSString *arg)
7262 [fw setOpaque: NO]; 7521 [fw setOpaque: NO];
7263 7522
7264 f->border_width = 0; 7523 f->border_width = 0;
7265 FRAME_NS_TITLEBAR_HEIGHT (f) = 0;
7266 tobar_height = FRAME_TOOLBAR_HEIGHT (f);
7267 FRAME_TOOLBAR_HEIGHT (f) = 0;
7268 7524
7269 nonfs_window = w; 7525 nonfs_window = w;
7270 7526
@@ -7298,9 +7554,6 @@ not_in_argv (NSString *arg)
7298 [w setOpaque: NO]; 7554 [w setOpaque: NO];
7299 7555
7300 f->border_width = bwidth; 7556 f->border_width = bwidth;
7301 FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height;
7302 if (FRAME_EXTERNAL_TOOL_BAR (f))
7303 FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
7304 7557
7305 // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications. 7558 // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications.
7306 7559
@@ -7418,7 +7671,7 @@ not_in_argv (NSString *arg)
7418} 7671}
7419 7672
7420 7673
7421- menuDown: sender 7674- (instancetype)menuDown: sender
7422{ 7675{
7423 NSTRACE ("[EmacsView menuDown:]"); 7676 NSTRACE ("[EmacsView menuDown:]");
7424 if (context_menu_value == -1) 7677 if (context_menu_value == -1)
@@ -7443,7 +7696,7 @@ not_in_argv (NSString *arg)
7443 7696
7444 7697
7445/* this gets called on toolbar button click */ 7698/* this gets called on toolbar button click */
7446- toolbarClicked: (id)item 7699- (instancetype)toolbarClicked: (id)item
7447{ 7700{
7448 NSEvent *theEvent; 7701 NSEvent *theEvent;
7449 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS; 7702 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
@@ -7469,7 +7722,7 @@ not_in_argv (NSString *arg)
7469} 7722}
7470 7723
7471 7724
7472- toggleToolbar: (id)sender 7725- (instancetype)toggleToolbar: (id)sender
7473{ 7726{
7474 NSTRACE ("[EmacsView toggleToolbar:]"); 7727 NSTRACE ("[EmacsView toggleToolbar:]");
7475 7728
@@ -7697,7 +7950,7 @@ not_in_argv (NSString *arg)
7697 (gives a miniaturized version of the window); currently we use the latter for 7950 (gives a miniaturized version of the window); currently we use the latter for
7698 frames whose active buffer doesn't correspond to any file 7951 frames whose active buffer doesn't correspond to any file
7699 (e.g., '*scratch*') */ 7952 (e.g., '*scratch*') */
7700- setMiniwindowImage: (BOOL) setMini 7953- (instancetype)setMiniwindowImage: (BOOL) setMini
7701{ 7954{
7702 id image = [[self window] miniwindowImage]; 7955 id image = [[self window] miniwindowImage];
7703 NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini); 7956 NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini);
@@ -7832,7 +8085,40 @@ not_in_argv (NSString *arg)
7832 NSTRACE_RETURN_RECT (frameRect); 8085 NSTRACE_RETURN_RECT (frameRect);
7833 return frameRect; 8086 return frameRect;
7834 } 8087 }
7835#endif 8088 else
8089#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
8090 // Check that the proposed frameRect is visible in at least one
8091 // screen. If it is not, ask the system to reposition it (only
8092 // for non-child windows).
8093
8094 if (!FRAME_PARENT_FRAME (((EmacsView *)[self delegate])->emacsframe))
8095 {
8096 NSArray *screens = [NSScreen screens];
8097 NSUInteger nr_screens = [screens count];
8098
8099 int i;
8100 BOOL frame_on_screen = NO;
8101
8102 for (i = 0; i < nr_screens; ++i)
8103 {
8104 NSScreen *s = [screens objectAtIndex: i];
8105 NSRect scrRect = [s frame];
8106
8107 if (NSIntersectsRect(frameRect, scrRect))
8108 {
8109 frame_on_screen = YES;
8110 break;
8111 }
8112 }
8113
8114 if (!frame_on_screen)
8115 {
8116 NSTRACE_MSG ("Frame outside screens; constraining");
8117 frameRect = [super constrainFrameRect:frameRect toScreen:screen];
8118 NSTRACE_RETURN_RECT (frameRect);
8119 return frameRect;
8120 }
8121 }
7836#endif 8122#endif
7837 8123
7838 return constrain_frame_rect(frameRect, 8124 return constrain_frame_rect(frameRect,
@@ -7966,6 +8252,11 @@ not_in_argv (NSString *arg)
7966 8252
7967 [super setFrameTopLeftPoint:point]; 8253 [super setFrameTopLeftPoint:point];
7968} 8254}
8255
8256- (BOOL)canBecomeKeyWindow
8257{
8258 return !FRAME_NO_ACCEPT_FOCUS (((EmacsView *)[self delegate])->emacsframe);
8259}
7969@end /* EmacsWindow */ 8260@end /* EmacsWindow */
7970 8261
7971 8262
@@ -8011,7 +8302,7 @@ not_in_argv (NSString *arg)
8011 return r; 8302 return r;
8012} 8303}
8013 8304
8014- initFrame: (NSRect )r window: (Lisp_Object)nwin 8305- (instancetype)initFrame: (NSRect )r window: (Lisp_Object)nwin
8015{ 8306{
8016 NSTRACE ("[EmacsScroller initFrame: window:]"); 8307 NSTRACE ("[EmacsScroller initFrame: window:]");
8017 8308
@@ -8095,7 +8386,7 @@ not_in_argv (NSString *arg)
8095} 8386}
8096 8387
8097 8388
8098- condemn 8389- (instancetype)condemn
8099{ 8390{
8100 NSTRACE ("[EmacsScroller condemn]"); 8391 NSTRACE ("[EmacsScroller condemn]");
8101 condemned =YES; 8392 condemned =YES;
@@ -8103,7 +8394,7 @@ not_in_argv (NSString *arg)
8103} 8394}
8104 8395
8105 8396
8106- reprieve 8397- (instancetype)reprieve
8107{ 8398{
8108 NSTRACE ("[EmacsScroller reprieve]"); 8399 NSTRACE ("[EmacsScroller reprieve]");
8109 condemned =NO; 8400 condemned =NO;
@@ -8158,7 +8449,7 @@ not_in_argv (NSString *arg)
8158} 8449}
8159 8450
8160 8451
8161- setPosition: (int)position portion: (int)portion whole: (int)whole 8452- (instancetype)setPosition: (int)position portion: (int)portion whole: (int)whole
8162{ 8453{
8163 NSTRACE ("[EmacsScroller setPosition:portion:whole:]"); 8454 NSTRACE ("[EmacsScroller setPosition:portion:whole:]");
8164 8455
@@ -8237,7 +8528,7 @@ not_in_argv (NSString *arg)
8237 8528
8238 8529
8239/* called manually thru timer to implement repeated button action w/hold-down */ 8530/* called manually thru timer to implement repeated button action w/hold-down */
8240- repeatScroll: (NSTimer *)scrollEntry 8531- (instancetype)repeatScroll: (NSTimer *)scrollEntry
8241{ 8532{
8242 NSEvent *e = [[self window] currentEvent]; 8533 NSEvent *e = [[self window] currentEvent];
8243 NSPoint p = [[self window] mouseLocationOutsideOfEventStream]; 8534 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
@@ -8297,7 +8588,7 @@ not_in_argv (NSString *arg)
8297 case NSScrollerKnobSlot: /* GNUstep-only */ 8588 case NSScrollerKnobSlot: /* GNUstep-only */
8298 last_hit_part = scroll_bar_move_ratio; break; 8589 last_hit_part = scroll_bar_move_ratio; break;
8299 default: /* NSScrollerNoPart? */ 8590 default: /* NSScrollerNoPart? */
8300 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %ld\n", 8591 fprintf (stderr, "EmacsScroller-mouseDown: unexpected part %ld\n",
8301 (long) part); 8592 (long) part);
8302 return; 8593 return;
8303 } 8594 }
@@ -8356,7 +8647,7 @@ not_in_argv (NSString *arg)
8356 modifierFlags: [e modifierFlags] 8647 modifierFlags: [e modifierFlags]
8357 timestamp: [e timestamp] 8648 timestamp: [e timestamp]
8358 windowNumber: [e windowNumber] 8649 windowNumber: [e windowNumber]
8359 context: [e context] 8650 context: nil
8360 eventNumber: [e eventNumber] 8651 eventNumber: [e eventNumber]
8361 clickCount: [e clickCount] 8652 clickCount: [e clickCount]
8362 pressure: [e pressure]]; 8653 pressure: [e pressure]];
diff --git a/src/print.c b/src/print.c
index e857761bd46..50c75d7712c 100644
--- a/src/print.c
+++ b/src/print.c
@@ -33,6 +33,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
33#include "intervals.h" 33#include "intervals.h"
34#include "blockinput.h" 34#include "blockinput.h"
35#include "xwidget.h" 35#include "xwidget.h"
36#include "dynlib.h"
36 37
37#include <c-ctype.h> 38#include <c-ctype.h>
38#include <float.h> 39#include <float.h>
@@ -227,7 +228,7 @@ printchar_to_stream (unsigned int ch, FILE *stream)
227 { 228 {
228 if (ASCII_CHAR_P (ch)) 229 if (ASCII_CHAR_P (ch))
229 { 230 {
230 putc (ch, stream); 231 putc_unlocked (ch, stream);
231#ifdef WINDOWSNT 232#ifdef WINDOWSNT
232 /* Send the output to a debugger (nothing happens if there 233 /* Send the output to a debugger (nothing happens if there
233 isn't one). */ 234 isn't one). */
@@ -245,7 +246,7 @@ printchar_to_stream (unsigned int ch, FILE *stream)
245 if (encode_p) 246 if (encode_p)
246 encoded_ch = code_convert_string_norecord (encoded_ch, 247 encoded_ch = code_convert_string_norecord (encoded_ch,
247 coding_system, true); 248 coding_system, true);
248 fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream); 249 fwrite_unlocked (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream);
249#ifdef WINDOWSNT 250#ifdef WINDOWSNT
250 if (print_output_debug_flag && stream == stderr) 251 if (print_output_debug_flag && stream == stderr)
251 OutputDebugString (SSDATA (encoded_ch)); 252 OutputDebugString (SSDATA (encoded_ch));
@@ -297,7 +298,7 @@ printchar (unsigned int ch, Lisp_Object fun)
297 if (DISP_TABLE_P (Vstandard_display_table)) 298 if (DISP_TABLE_P (Vstandard_display_table))
298 printchar_to_stream (ch, stdout); 299 printchar_to_stream (ch, stdout);
299 else 300 else
300 fwrite (str, 1, len, stdout); 301 fwrite_unlocked (str, 1, len, stdout);
301 noninteractive_need_newline = 1; 302 noninteractive_need_newline = 1;
302 } 303 }
303 else 304 else
@@ -349,7 +350,7 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
349 } 350 }
350 } 351 }
351 else 352 else
352 fwrite (ptr, 1, size_byte, stdout); 353 fwrite_unlocked (ptr, 1, size_byte, stdout);
353 354
354 noninteractive_need_newline = 1; 355 noninteractive_need_newline = 1;
355 } 356 }
@@ -800,7 +801,7 @@ append to existing target file. */)
800 report_file_error ("Cannot open debugging output stream", file); 801 report_file_error ("Cannot open debugging output stream", file);
801 } 802 }
802 803
803 fflush (stderr); 804 fflush_unlocked (stderr);
804 if (dup2 (fd, STDERR_FILENO) < 0) 805 if (dup2 (fd, STDERR_FILENO) < 0)
805 report_file_error ("dup2", file); 806 report_file_error ("dup2", file);
806 if (fd != stderr_dup) 807 if (fd != stderr_dup)
@@ -1135,7 +1136,8 @@ print (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1135 || (VECTORLIKEP (obj) \ 1136 || (VECTORLIKEP (obj) \
1136 && (VECTORP (obj) || COMPILEDP (obj) \ 1137 && (VECTORP (obj) || COMPILEDP (obj) \
1137 || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \ 1138 || CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj) \
1138 || HASH_TABLE_P (obj) || FONTP (obj))) \ 1139 || HASH_TABLE_P (obj) || FONTP (obj) \
1140 || RECORDP (obj))) \
1139 || (! NILP (Vprint_gensym) \ 1141 || (! NILP (Vprint_gensym) \
1140 && SYMBOLP (obj) \ 1142 && SYMBOLP (obj) \
1141 && !SYMBOL_INTERNED_P (obj))) 1143 && !SYMBOL_INTERNED_P (obj)))
@@ -1345,6 +1347,401 @@ print_prune_string_charset (Lisp_Object string)
1345 return string; 1347 return string;
1346} 1348}
1347 1349
1350static bool
1351print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
1352 char *buf)
1353{
1354 switch (PSEUDOVECTOR_TYPE (XVECTOR (obj)))
1355 {
1356 case PVEC_PROCESS:
1357 if (escapeflag)
1358 {
1359 print_c_string ("#<process ", printcharfun);
1360 print_string (XPROCESS (obj)->name, printcharfun);
1361 printchar ('>', printcharfun);
1362 }
1363 else
1364 print_string (XPROCESS (obj)->name, printcharfun);
1365 break;
1366
1367 case PVEC_BOOL_VECTOR:
1368 {
1369 EMACS_INT size = bool_vector_size (obj);
1370 ptrdiff_t size_in_chars = bool_vector_bytes (size);
1371 ptrdiff_t real_size_in_chars = size_in_chars;
1372
1373 int len = sprintf (buf, "#&%"pI"d\"", size);
1374 strout (buf, len, len, printcharfun);
1375
1376 /* Don't print more characters than the specified maximum.
1377 Negative values of print-length are invalid. Treat them
1378 like a print-length of nil. */
1379 if (NATNUMP (Vprint_length)
1380 && XFASTINT (Vprint_length) < size_in_chars)
1381 size_in_chars = XFASTINT (Vprint_length);
1382
1383 for (ptrdiff_t i = 0; i < size_in_chars; i++)
1384 {
1385 maybe_quit ();
1386 unsigned char c = bool_vector_uchar_data (obj)[i];
1387 if (c == '\n' && print_escape_newlines)
1388 print_c_string ("\\n", printcharfun);
1389 else if (c == '\f' && print_escape_newlines)
1390 print_c_string ("\\f", printcharfun);
1391 else if (c > '\177')
1392 {
1393 /* Use octal escapes to avoid encoding issues. */
1394 int len = sprintf (buf, "\\%o", c);
1395 strout (buf, len, len, printcharfun);
1396 }
1397 else
1398 {
1399 if (c == '\"' || c == '\\')
1400 printchar ('\\', printcharfun);
1401 printchar (c, printcharfun);
1402 }
1403 }
1404
1405 if (size_in_chars < real_size_in_chars)
1406 print_c_string (" ...", printcharfun);
1407 printchar ('\"', printcharfun);
1408 }
1409 break;
1410
1411 case PVEC_SUBR:
1412 print_c_string ("#<subr ", printcharfun);
1413 print_c_string (XSUBR (obj)->symbol_name, printcharfun);
1414 printchar ('>', printcharfun);
1415 break;
1416
1417 case PVEC_XWIDGET: case PVEC_XWIDGET_VIEW:
1418 print_c_string ("#<xwidget ", printcharfun);
1419 printchar ('>', printcharfun);
1420 break;
1421
1422 case PVEC_WINDOW:
1423 {
1424 int len = sprintf (buf, "#<window %"pI"d",
1425 XWINDOW (obj)->sequence_number);
1426 strout (buf, len, len, printcharfun);
1427 if (BUFFERP (XWINDOW (obj)->contents))
1428 {
1429 print_c_string (" on ", printcharfun);
1430 print_string (BVAR (XBUFFER (XWINDOW (obj)->contents), name),
1431 printcharfun);
1432 }
1433 printchar ('>', printcharfun);
1434 }
1435 break;
1436
1437 case PVEC_TERMINAL:
1438 {
1439 struct terminal *t = XTERMINAL (obj);
1440 int len = sprintf (buf, "#<terminal %d", t->id);
1441 strout (buf, len, len, printcharfun);
1442 if (t->name)
1443 {
1444 print_c_string (" on ", printcharfun);
1445 print_c_string (t->name, printcharfun);
1446 }
1447 printchar ('>', printcharfun);
1448 }
1449 break;
1450
1451 case PVEC_HASH_TABLE:
1452 {
1453 struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
1454 /* Implement a readable output, e.g.:
1455 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
1456 /* Always print the size. */
1457 int len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next));
1458 strout (buf, len, len, printcharfun);
1459
1460 if (!NILP (h->test.name))
1461 {
1462 print_c_string (" test ", printcharfun);
1463 print_object (h->test.name, printcharfun, escapeflag);
1464 }
1465
1466 if (!NILP (h->weak))
1467 {
1468 print_c_string (" weakness ", printcharfun);
1469 print_object (h->weak, printcharfun, escapeflag);
1470 }
1471
1472 print_c_string (" rehash-size ", printcharfun);
1473 print_object (Fhash_table_rehash_size (obj),
1474 printcharfun, escapeflag);
1475
1476 print_c_string (" rehash-threshold ", printcharfun);
1477 print_object (Fhash_table_rehash_threshold (obj),
1478 printcharfun, escapeflag);
1479
1480 if (h->pure)
1481 {
1482 print_c_string (" purecopy ", printcharfun);
1483 print_object (h->pure ? Qt : Qnil, printcharfun, escapeflag);
1484 }
1485
1486 print_c_string (" data ", printcharfun);
1487
1488 /* Print the data here as a plist. */
1489 ptrdiff_t real_size = HASH_TABLE_SIZE (h);
1490 ptrdiff_t size = real_size;
1491
1492 /* Don't print more elements than the specified maximum. */
1493 if (NATNUMP (Vprint_length) && XFASTINT (Vprint_length) < size)
1494 size = XFASTINT (Vprint_length);
1495
1496 printchar ('(', printcharfun);
1497 for (ptrdiff_t i = 0; i < size; i++)
1498 if (!NILP (HASH_HASH (h, i)))
1499 {
1500 if (i) printchar (' ', printcharfun);
1501 print_object (HASH_KEY (h, i), printcharfun, escapeflag);
1502 printchar (' ', printcharfun);
1503 print_object (HASH_VALUE (h, i), printcharfun, escapeflag);
1504 }
1505
1506 if (size < real_size)
1507 print_c_string (" ...", printcharfun);
1508
1509 print_c_string ("))", printcharfun);
1510 }
1511 break;
1512
1513 case PVEC_BUFFER:
1514 if (!BUFFER_LIVE_P (XBUFFER (obj)))
1515 print_c_string ("#<killed buffer>", printcharfun);
1516 else if (escapeflag)
1517 {
1518 print_c_string ("#<buffer ", printcharfun);
1519 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1520 printchar ('>', printcharfun);
1521 }
1522 else
1523 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1524 break;
1525
1526 case PVEC_WINDOW_CONFIGURATION:
1527 print_c_string ("#<window-configuration>", printcharfun);
1528 break;
1529
1530 case PVEC_FRAME:
1531 {
1532 void *ptr = XFRAME (obj);
1533 Lisp_Object frame_name = XFRAME (obj)->name;
1534
1535 print_c_string ((FRAME_LIVE_P (XFRAME (obj))
1536 ? "#<frame "
1537 : "#<dead frame "),
1538 printcharfun);
1539 if (!STRINGP (frame_name))
1540 {
1541 /* A frame could be too young and have no name yet;
1542 don't crash. */
1543 if (SYMBOLP (frame_name))
1544 frame_name = Fsymbol_name (frame_name);
1545 else /* can't happen: name should be either nil or string */
1546 frame_name = build_string ("*INVALID*FRAME*NAME*");
1547 }
1548 print_string (frame_name, printcharfun);
1549 int len = sprintf (buf, " %p>", ptr);
1550 strout (buf, len, len, printcharfun);
1551 }
1552 break;
1553
1554 case PVEC_FONT:
1555 {
1556 if (! FONT_OBJECT_P (obj))
1557 {
1558 if (FONT_SPEC_P (obj))
1559 print_c_string ("#<font-spec", printcharfun);
1560 else
1561 print_c_string ("#<font-entity", printcharfun);
1562 for (int i = 0; i < FONT_SPEC_MAX; i++)
1563 {
1564 printchar (' ', printcharfun);
1565 if (i < FONT_WEIGHT_INDEX || i > FONT_WIDTH_INDEX)
1566 print_object (AREF (obj, i), printcharfun, escapeflag);
1567 else
1568 print_object (font_style_symbolic (obj, i, 0),
1569 printcharfun, escapeflag);
1570 }
1571 }
1572 else
1573 {
1574 print_c_string ("#<font-object ", printcharfun);
1575 print_object (AREF (obj, FONT_NAME_INDEX), printcharfun,
1576 escapeflag);
1577 }
1578 printchar ('>', printcharfun);
1579 }
1580 break;
1581
1582 case PVEC_THREAD:
1583 print_c_string ("#<thread ", printcharfun);
1584 if (STRINGP (XTHREAD (obj)->name))
1585 print_string (XTHREAD (obj)->name, printcharfun);
1586 else
1587 {
1588 int len = sprintf (buf, "%p", XTHREAD (obj));
1589 strout (buf, len, len, printcharfun);
1590 }
1591 printchar ('>', printcharfun);
1592 break;
1593
1594 case PVEC_MUTEX:
1595 print_c_string ("#<mutex ", printcharfun);
1596 if (STRINGP (XMUTEX (obj)->name))
1597 print_string (XMUTEX (obj)->name, printcharfun);
1598 else
1599 {
1600 int len = sprintf (buf, "%p", XMUTEX (obj));
1601 strout (buf, len, len, printcharfun);
1602 }
1603 printchar ('>', printcharfun);
1604 break;
1605
1606 case PVEC_CONDVAR:
1607 print_c_string ("#<condvar ", printcharfun);
1608 if (STRINGP (XCONDVAR (obj)->name))
1609 print_string (XCONDVAR (obj)->name, printcharfun);
1610 else
1611 {
1612 int len = sprintf (buf, "%p", XCONDVAR (obj));
1613 strout (buf, len, len, printcharfun);
1614 }
1615 printchar ('>', printcharfun);
1616 break;
1617
1618 case PVEC_RECORD:
1619 {
1620 ptrdiff_t size = PVSIZE (obj);
1621
1622 /* Don't print more elements than the specified maximum. */
1623 ptrdiff_t n
1624 = (NATNUMP (Vprint_length) && XFASTINT (Vprint_length) < size
1625 ? XFASTINT (Vprint_length) : size);
1626
1627 print_c_string ("#s(", printcharfun);
1628 for (ptrdiff_t i = 0; i < n; i ++)
1629 {
1630 if (i) printchar (' ', printcharfun);
1631 print_object (AREF (obj, i), printcharfun, escapeflag);
1632 }
1633 if (n < size)
1634 print_c_string (" ...", printcharfun);
1635 printchar (')', printcharfun);
1636 }
1637 break;
1638
1639 case PVEC_SUB_CHAR_TABLE:
1640 case PVEC_COMPILED:
1641 case PVEC_CHAR_TABLE:
1642 case PVEC_NORMAL_VECTOR:
1643 {
1644 ptrdiff_t size = ASIZE (obj);
1645 if (COMPILEDP (obj))
1646 {
1647 printchar ('#', printcharfun);
1648 size &= PSEUDOVECTOR_SIZE_MASK;
1649 }
1650 if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj))
1651 {
1652 /* Print a char-table as if it were a vector,
1653 lumping the parent and default slots in with the
1654 character slots. But add #^ as a prefix. */
1655
1656 /* Make each lowest sub_char_table start a new line.
1657 Otherwise we'll make a line extremely long, which
1658 results in slow redisplay. */
1659 if (SUB_CHAR_TABLE_P (obj)
1660 && XSUB_CHAR_TABLE (obj)->depth == 3)
1661 printchar ('\n', printcharfun);
1662 print_c_string ("#^", printcharfun);
1663 if (SUB_CHAR_TABLE_P (obj))
1664 printchar ('^', printcharfun);
1665 size &= PSEUDOVECTOR_SIZE_MASK;
1666 }
1667 if (size & PSEUDOVECTOR_FLAG)
1668 return false;
1669
1670 printchar ('[', printcharfun);
1671
1672 int idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0;
1673 Lisp_Object tem;
1674 ptrdiff_t real_size = size;
1675
1676 /* For a sub char-table, print heading non-Lisp data first. */
1677 if (SUB_CHAR_TABLE_P (obj))
1678 {
1679 int i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth,
1680 XSUB_CHAR_TABLE (obj)->min_char);
1681 strout (buf, i, i, printcharfun);
1682 }
1683
1684 /* Don't print more elements than the specified maximum. */
1685 if (NATNUMP (Vprint_length)
1686 && XFASTINT (Vprint_length) < size)
1687 size = XFASTINT (Vprint_length);
1688
1689 for (int i = idx; i < size; i++)
1690 {
1691 if (i) printchar (' ', printcharfun);
1692 tem = AREF (obj, i);
1693 print_object (tem, printcharfun, escapeflag);
1694 }
1695 if (size < real_size)
1696 print_c_string (" ...", printcharfun);
1697 printchar (']', printcharfun);
1698 }
1699 break;
1700
1701#ifdef HAVE_MODULES
1702 case PVEC_MODULE_FUNCTION:
1703 {
1704 print_c_string ("#<module function ", printcharfun);
1705 void *ptr = XMODULE_FUNCTION (obj)->subr;
1706 const char *file = NULL;
1707 const char *symbol = NULL;
1708 dynlib_addr (ptr, &file, &symbol);
1709
1710 if (symbol == NULL)
1711 {
1712 print_c_string ("at ", printcharfun);
1713 enum { pointer_bufsize = sizeof ptr * 16 / CHAR_BIT + 2 + 1 };
1714 char buffer[pointer_bufsize];
1715 int needed = snprintf (buffer, sizeof buffer, "%p", ptr);
1716 const char p0x[] = "0x";
1717 eassert (needed <= sizeof buffer);
1718 /* ANSI C doesn't guarantee that %p produces a string that
1719 begins with a "0x". */
1720 if (c_strncasecmp (buffer, p0x, sizeof (p0x) - 1) != 0)
1721 print_c_string (p0x, printcharfun);
1722 print_c_string (buffer, printcharfun);
1723 }
1724 else
1725 print_c_string (symbol, printcharfun);
1726
1727 if (file != NULL)
1728 {
1729 print_c_string (" from ", printcharfun);
1730 print_c_string (file, printcharfun);
1731 }
1732
1733 printchar ('>', printcharfun);
1734 }
1735 break;
1736#endif
1737
1738 default:
1739 emacs_abort ();
1740 }
1741
1742 return true;
1743}
1744
1348static void 1745static void
1349print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) 1746print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1350{ 1747{
@@ -1473,21 +1870,36 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1473 } 1870 }
1474 else 1871 else
1475 { 1872 {
1873 bool still_need_nonhex = false;
1476 /* If we just had a hex escape, and this character 1874 /* If we just had a hex escape, and this character
1477 could be taken as part of it, 1875 could be taken as part of it,
1478 output `\ ' to prevent that. */ 1876 output `\ ' to prevent that. */
1479 if (need_nonhex && c_isxdigit (c)) 1877 if (c_isxdigit (c))
1480 print_c_string ("\\ ", printcharfun); 1878 {
1481 1879 if (need_nonhex)
1482 if (c == '\n' && print_escape_newlines 1880 print_c_string ("\\ ", printcharfun);
1483 ? (c = 'n', true) 1881 printchar (c, printcharfun);
1484 : c == '\f' && print_escape_newlines 1882 }
1485 ? (c = 'f', true) 1883 else if (c == '\n' && print_escape_newlines
1486 : c == '\"' || c == '\\') 1884 ? (c = 'n', true)
1487 printchar ('\\', printcharfun); 1885 : c == '\f' && print_escape_newlines
1488 1886 ? (c = 'f', true)
1489 printchar (c, printcharfun); 1887 : c == '\0' && print_escape_control_characters
1490 need_nonhex = false; 1888 ? (c = '0', still_need_nonhex = true)
1889 : c == '\"' || c == '\\')
1890 {
1891 printchar ('\\', printcharfun);
1892 printchar (c, printcharfun);
1893 }
1894 else if (print_escape_control_characters && c_iscntrl (c))
1895 {
1896 char outbuf[1 + 3 + 1];
1897 int len = sprintf (outbuf, "\\%03o", c + 0u);
1898 strout (outbuf, len, len, printcharfun);
1899 }
1900 else
1901 printchar (c, printcharfun);
1902 need_nonhex = still_need_nonhex;
1491 } 1903 }
1492 } 1904 }
1493 printchar ('\"', printcharfun); 1905 printchar ('\"', printcharfun);
@@ -1677,359 +2089,8 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1677 break; 2089 break;
1678 2090
1679 case Lisp_Vectorlike: 2091 case Lisp_Vectorlike:
1680 switch (PSEUDOVECTOR_TYPE (XVECTOR (obj))) { 2092 if (! print_vectorlike (obj, printcharfun, escapeflag, buf))
1681 case PVEC_PROCESS: 2093 goto badtype;
1682 {
1683 if (escapeflag)
1684 {
1685 print_c_string ("#<process ", printcharfun);
1686 print_string (XPROCESS (obj)->name, printcharfun);
1687 printchar ('>', printcharfun);
1688 }
1689 else
1690 print_string (XPROCESS (obj)->name, printcharfun);
1691 }
1692 break;
1693
1694 case PVEC_BOOL_VECTOR:
1695 {
1696 ptrdiff_t i;
1697 unsigned char c;
1698 EMACS_INT size = bool_vector_size (obj);
1699 ptrdiff_t size_in_chars = bool_vector_bytes (size);
1700 ptrdiff_t real_size_in_chars = size_in_chars;
1701
1702 int len = sprintf (buf, "#&%"pI"d\"", size);
1703 strout (buf, len, len, printcharfun);
1704
1705 /* Don't print more characters than the specified maximum.
1706 Negative values of print-length are invalid. Treat them
1707 like a print-length of nil. */
1708 if (NATNUMP (Vprint_length)
1709 && XFASTINT (Vprint_length) < size_in_chars)
1710 size_in_chars = XFASTINT (Vprint_length);
1711
1712 for (i = 0; i < size_in_chars; i++)
1713 {
1714 maybe_quit ();
1715 c = bool_vector_uchar_data (obj)[i];
1716 if (c == '\n' && print_escape_newlines)
1717 print_c_string ("\\n", printcharfun);
1718 else if (c == '\f' && print_escape_newlines)
1719 print_c_string ("\\f", printcharfun);
1720 else if (c > '\177')
1721 {
1722 /* Use octal escapes to avoid encoding issues. */
1723 len = sprintf (buf, "\\%o", c);
1724 strout (buf, len, len, printcharfun);
1725 }
1726 else
1727 {
1728 if (c == '\"' || c == '\\')
1729 printchar ('\\', printcharfun);
1730 printchar (c, printcharfun);
1731 }
1732 }
1733
1734 if (size_in_chars < real_size_in_chars)
1735 print_c_string (" ...", printcharfun);
1736 printchar ('\"', printcharfun);
1737 }
1738 break;
1739
1740 case PVEC_SUBR:
1741 {
1742 print_c_string ("#<subr ", printcharfun);
1743 print_c_string (XSUBR (obj)->symbol_name, printcharfun);
1744 printchar ('>', printcharfun);
1745 }
1746 break;
1747
1748 case PVEC_XWIDGET: case PVEC_XWIDGET_VIEW:
1749 {
1750 print_c_string ("#<xwidget ", printcharfun);
1751 printchar ('>', printcharfun);
1752 }
1753 break;
1754
1755 case PVEC_WINDOW:
1756 {
1757 int len = sprintf (buf, "#<window %"pI"d",
1758 XWINDOW (obj)->sequence_number);
1759 strout (buf, len, len, printcharfun);
1760 if (BUFFERP (XWINDOW (obj)->contents))
1761 {
1762 print_c_string (" on ", printcharfun);
1763 print_string (BVAR (XBUFFER (XWINDOW (obj)->contents), name),
1764 printcharfun);
1765 }
1766 printchar ('>', printcharfun);
1767 }
1768 break;
1769
1770 case PVEC_TERMINAL:
1771 {
1772 struct terminal *t = XTERMINAL (obj);
1773 int len = sprintf (buf, "#<terminal %d", t->id);
1774 strout (buf, len, len, printcharfun);
1775 if (t->name)
1776 {
1777 print_c_string (" on ", printcharfun);
1778 print_c_string (t->name, printcharfun);
1779 }
1780 printchar ('>', printcharfun);
1781 }
1782 break;
1783
1784 case PVEC_HASH_TABLE:
1785 {
1786 struct Lisp_Hash_Table *h = XHASH_TABLE (obj);
1787 ptrdiff_t i;
1788 ptrdiff_t real_size, size;
1789 int len;
1790 /* Implement a readable output, e.g.:
1791 #s(hash-table size 2 test equal data (k1 v1 k2 v2)) */
1792 /* Always print the size. */
1793 len = sprintf (buf, "#s(hash-table size %"pD"d", ASIZE (h->next));
1794 strout (buf, len, len, printcharfun);
1795
1796 if (!NILP (h->test.name))
1797 {
1798 print_c_string (" test ", printcharfun);
1799 print_object (h->test.name, printcharfun, escapeflag);
1800 }
1801
1802 if (!NILP (h->weak))
1803 {
1804 print_c_string (" weakness ", printcharfun);
1805 print_object (h->weak, printcharfun, escapeflag);
1806 }
1807
1808 print_c_string (" rehash-size ", printcharfun);
1809 print_object (Fhash_table_rehash_size (obj),
1810 printcharfun, escapeflag);
1811
1812 print_c_string (" rehash-threshold ", printcharfun);
1813 print_object (Fhash_table_rehash_threshold (obj),
1814 printcharfun, escapeflag);
1815
1816 if (h->pure)
1817 {
1818 print_c_string (" purecopy ", printcharfun);
1819 print_object (h->pure ? Qt : Qnil, printcharfun, escapeflag);
1820 }
1821
1822 print_c_string (" data ", printcharfun);
1823
1824 /* Print the data here as a plist. */
1825 real_size = HASH_TABLE_SIZE (h);
1826 size = real_size;
1827
1828 /* Don't print more elements than the specified maximum. */
1829 if (NATNUMP (Vprint_length)
1830 && XFASTINT (Vprint_length) < size)
1831 size = XFASTINT (Vprint_length);
1832
1833 printchar ('(', printcharfun);
1834 for (i = 0; i < size; i++)
1835 if (!NILP (HASH_HASH (h, i)))
1836 {
1837 if (i) printchar (' ', printcharfun);
1838 print_object (HASH_KEY (h, i), printcharfun, escapeflag);
1839 printchar (' ', printcharfun);
1840 print_object (HASH_VALUE (h, i), printcharfun, escapeflag);
1841 }
1842
1843 if (size < real_size)
1844 print_c_string (" ...", printcharfun);
1845
1846 print_c_string ("))", printcharfun);
1847 }
1848 break;
1849
1850 case PVEC_BUFFER:
1851 {
1852 if (!BUFFER_LIVE_P (XBUFFER (obj)))
1853 print_c_string ("#<killed buffer>", printcharfun);
1854 else if (escapeflag)
1855 {
1856 print_c_string ("#<buffer ", printcharfun);
1857 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1858 printchar ('>', printcharfun);
1859 }
1860 else
1861 print_string (BVAR (XBUFFER (obj), name), printcharfun);
1862 }
1863 break;
1864
1865 case PVEC_WINDOW_CONFIGURATION:
1866 print_c_string ("#<window-configuration>", printcharfun);
1867 break;
1868
1869 case PVEC_FRAME: ;
1870 {
1871 int len;
1872 void *ptr = XFRAME (obj);
1873 Lisp_Object frame_name = XFRAME (obj)->name;
1874
1875 print_c_string ((FRAME_LIVE_P (XFRAME (obj))
1876 ? "#<frame "
1877 : "#<dead frame "),
1878 printcharfun);
1879 if (!STRINGP (frame_name))
1880 {
1881 /* A frame could be too young and have no name yet;
1882 don't crash. */
1883 if (SYMBOLP (frame_name))
1884 frame_name = Fsymbol_name (frame_name);
1885 else /* can't happen: name should be either nil or string */
1886 frame_name = build_string ("*INVALID*FRAME*NAME*");
1887 }
1888 print_string (frame_name, printcharfun);
1889 len = sprintf (buf, " %p>", ptr);
1890 strout (buf, len, len, printcharfun);
1891 }
1892 break;
1893
1894 case PVEC_FONT:
1895 {
1896 int i;
1897
1898 if (! FONT_OBJECT_P (obj))
1899 {
1900 if (FONT_SPEC_P (obj))
1901 print_c_string ("#<font-spec", printcharfun);
1902 else
1903 print_c_string ("#<font-entity", printcharfun);
1904 for (i = 0; i < FONT_SPEC_MAX; i++)
1905 {
1906 printchar (' ', printcharfun);
1907 if (i < FONT_WEIGHT_INDEX || i > FONT_WIDTH_INDEX)
1908 print_object (AREF (obj, i), printcharfun, escapeflag);
1909 else
1910 print_object (font_style_symbolic (obj, i, 0),
1911 printcharfun, escapeflag);
1912 }
1913 }
1914 else
1915 {
1916 print_c_string ("#<font-object ", printcharfun);
1917 print_object (AREF (obj, FONT_NAME_INDEX), printcharfun,
1918 escapeflag);
1919 }
1920 printchar ('>', printcharfun);
1921 }
1922 break;
1923
1924 case PVEC_THREAD:
1925 {
1926 print_c_string ("#<thread ", printcharfun);
1927 if (STRINGP (XTHREAD (obj)->name))
1928 print_string (XTHREAD (obj)->name, printcharfun);
1929 else
1930 {
1931 int len = sprintf (buf, "%p", XTHREAD (obj));
1932 strout (buf, len, len, printcharfun);
1933 }
1934 printchar ('>', printcharfun);
1935 }
1936 break;
1937
1938 case PVEC_MUTEX:
1939 {
1940 print_c_string ("#<mutex ", printcharfun);
1941 if (STRINGP (XMUTEX (obj)->name))
1942 print_string (XMUTEX (obj)->name, printcharfun);
1943 else
1944 {
1945 int len = sprintf (buf, "%p", XMUTEX (obj));
1946 strout (buf, len, len, printcharfun);
1947 }
1948 printchar ('>', printcharfun);
1949 }
1950 break;
1951
1952 case PVEC_CONDVAR:
1953 {
1954 print_c_string ("#<condvar ", printcharfun);
1955 if (STRINGP (XCONDVAR (obj)->name))
1956 print_string (XCONDVAR (obj)->name, printcharfun);
1957 else
1958 {
1959 int len = sprintf (buf, "%p", XCONDVAR (obj));
1960 strout (buf, len, len, printcharfun);
1961 }
1962 printchar ('>', printcharfun);
1963 }
1964 break;
1965
1966 case PVEC_SUB_CHAR_TABLE:
1967 case PVEC_COMPILED:
1968 case PVEC_CHAR_TABLE:
1969 case PVEC_NORMAL_VECTOR: ;
1970 {
1971 ptrdiff_t size = ASIZE (obj);
1972 if (COMPILEDP (obj))
1973 {
1974 printchar ('#', printcharfun);
1975 size &= PSEUDOVECTOR_SIZE_MASK;
1976 }
1977 if (CHAR_TABLE_P (obj) || SUB_CHAR_TABLE_P (obj))
1978 {
1979 /* We print a char-table as if it were a vector,
1980 lumping the parent and default slots in with the
1981 character slots. But we add #^ as a prefix. */
1982
1983 /* Make each lowest sub_char_table start a new line.
1984 Otherwise we'll make a line extremely long, which
1985 results in slow redisplay. */
1986 if (SUB_CHAR_TABLE_P (obj)
1987 && XSUB_CHAR_TABLE (obj)->depth == 3)
1988 printchar ('\n', printcharfun);
1989 print_c_string ("#^", printcharfun);
1990 if (SUB_CHAR_TABLE_P (obj))
1991 printchar ('^', printcharfun);
1992 size &= PSEUDOVECTOR_SIZE_MASK;
1993 }
1994 if (size & PSEUDOVECTOR_FLAG)
1995 goto badtype;
1996
1997 printchar ('[', printcharfun);
1998 {
1999 int i, idx = SUB_CHAR_TABLE_P (obj) ? SUB_CHAR_TABLE_OFFSET : 0;
2000 Lisp_Object tem;
2001 ptrdiff_t real_size = size;
2002
2003 /* For a sub char-table, print heading non-Lisp data first. */
2004 if (SUB_CHAR_TABLE_P (obj))
2005 {
2006 i = sprintf (buf, "%d %d", XSUB_CHAR_TABLE (obj)->depth,
2007 XSUB_CHAR_TABLE (obj)->min_char);
2008 strout (buf, i, i, printcharfun);
2009 }
2010
2011 /* Don't print more elements than the specified maximum. */
2012 if (NATNUMP (Vprint_length)
2013 && XFASTINT (Vprint_length) < size)
2014 size = XFASTINT (Vprint_length);
2015
2016 for (i = idx; i < size; i++)
2017 {
2018 if (i) printchar (' ', printcharfun);
2019 tem = AREF (obj, i);
2020 print_object (tem, printcharfun, escapeflag);
2021 }
2022 if (size < real_size)
2023 print_c_string (" ...", printcharfun);
2024 }
2025 printchar (']', printcharfun);
2026 }
2027 break;
2028
2029 case PVEC_OTHER:
2030 case PVEC_FREE:
2031 emacs_abort ();
2032 }
2033 break; 2094 break;
2034 2095
2035 case Lisp_Misc: 2096 case Lisp_Misc:
@@ -2283,6 +2344,11 @@ A value of nil means no limit. See also `eval-expression-print-level'. */);
2283Also print formfeeds as `\\f'. */); 2344Also print formfeeds as `\\f'. */);
2284 print_escape_newlines = 0; 2345 print_escape_newlines = 0;
2285 2346
2347 DEFVAR_BOOL ("print-escape-control-characters", print_escape_control_characters,
2348 doc: /* Non-nil means print control characters in strings as `\\OOO'.
2349\(OOO is the octal representation of the character code.)*/);
2350 print_escape_control_characters = 0;
2351
2286 DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii, 2352 DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii,
2287 doc: /* Non-nil means print unibyte non-ASCII chars in strings as \\OOO. 2353 doc: /* Non-nil means print unibyte non-ASCII chars in strings as \\OOO.
2288\(OOO is the octal representation of the character code.) 2354\(OOO is the octal representation of the character code.)
@@ -2372,6 +2438,7 @@ priorities. */);
2372 DEFSYM (Qprint_escape_newlines, "print-escape-newlines"); 2438 DEFSYM (Qprint_escape_newlines, "print-escape-newlines");
2373 DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte"); 2439 DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte");
2374 DEFSYM (Qprint_escape_nonascii, "print-escape-nonascii"); 2440 DEFSYM (Qprint_escape_nonascii, "print-escape-nonascii");
2441 DEFSYM (Qprint_escape_control_characters, "print-escape-control-characters");
2375 2442
2376 print_prune_charset_plist = Qnil; 2443 print_prune_charset_plist = Qnil;
2377 staticpro (&print_prune_charset_plist); 2444 staticpro (&print_prune_charset_plist);
diff --git a/src/process.c b/src/process.c
index 2f2e5c1b251..abd017bb907 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2049,7 +2049,21 @@ create_process (Lisp_Object process, char **new_argv, Lisp_Object current_dir)
2049 int volatile forkerr_volatile = forkerr; 2049 int volatile forkerr_volatile = forkerr;
2050 struct Lisp_Process *p_volatile = p; 2050 struct Lisp_Process *p_volatile = p;
2051 2051
2052#ifdef DARWIN_OS
2053 /* Darwin doesn't let us run setsid after a vfork, so use fork when
2054 necessary. Also, reset SIGCHLD handling after a vfork, as
2055 apparently macOS can mistakenly deliver SIGCHLD to the child. */
2056 if (pty_flag)
2057 pid = fork ();
2058 else
2059 {
2060 pid = vfork ();
2061 if (pid == 0)
2062 signal (SIGCHLD, SIG_DFL);
2063 }
2064#else
2052 pid = vfork (); 2065 pid = vfork ();
2066#endif
2053 2067
2054 current_dir = current_dir_volatile; 2068 current_dir = current_dir_volatile;
2055 lisp_pty_name = lisp_pty_name_volatile; 2069 lisp_pty_name = lisp_pty_name_volatile;
@@ -2467,7 +2481,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2467 { 2481 {
2468 case AF_INET: 2482 case AF_INET:
2469 { 2483 {
2470 struct sockaddr_in *sin = (struct sockaddr_in *) sa; 2484 DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
2471 len = sizeof (sin->sin_addr) + 1; 2485 len = sizeof (sin->sin_addr) + 1;
2472 address = Fmake_vector (make_number (len), Qnil); 2486 address = Fmake_vector (make_number (len), Qnil);
2473 p = XVECTOR (address); 2487 p = XVECTOR (address);
@@ -2478,8 +2492,8 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2478#ifdef AF_INET6 2492#ifdef AF_INET6
2479 case AF_INET6: 2493 case AF_INET6:
2480 { 2494 {
2481 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; 2495 DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
2482 uint16_t *ip6 = (uint16_t *) &sin6->sin6_addr; 2496 DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
2483 len = sizeof (sin6->sin6_addr) / 2 + 1; 2497 len = sizeof (sin6->sin6_addr) / 2 + 1;
2484 address = Fmake_vector (make_number (len), Qnil); 2498 address = Fmake_vector (make_number (len), Qnil);
2485 p = XVECTOR (address); 2499 p = XVECTOR (address);
@@ -2492,7 +2506,7 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
2492#ifdef HAVE_LOCAL_SOCKETS 2506#ifdef HAVE_LOCAL_SOCKETS
2493 case AF_LOCAL: 2507 case AF_LOCAL:
2494 { 2508 {
2495 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; 2509 DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
2496 ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path); 2510 ptrdiff_t name_length = len - offsetof (struct sockaddr_un, sun_path);
2497 /* If the first byte is NUL, the name is a Linux abstract 2511 /* If the first byte is NUL, the name is a Linux abstract
2498 socket name, and the name can contain embedded NULs. If 2512 socket name, and the name can contain embedded NULs. If
@@ -2603,7 +2617,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2603 p = XVECTOR (address); 2617 p = XVECTOR (address);
2604 if (family == AF_INET) 2618 if (family == AF_INET)
2605 { 2619 {
2606 struct sockaddr_in *sin = (struct sockaddr_in *) sa; 2620 DECLARE_POINTER_ALIAS (sin, struct sockaddr_in, sa);
2607 len = sizeof (sin->sin_addr) + 1; 2621 len = sizeof (sin->sin_addr) + 1;
2608 hostport = XINT (p->contents[--len]); 2622 hostport = XINT (p->contents[--len]);
2609 sin->sin_port = htons (hostport); 2623 sin->sin_port = htons (hostport);
@@ -2613,8 +2627,8 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2613#ifdef AF_INET6 2627#ifdef AF_INET6
2614 else if (family == AF_INET6) 2628 else if (family == AF_INET6)
2615 { 2629 {
2616 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) sa; 2630 DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
2617 uint16_t *ip6 = (uint16_t *)&sin6->sin6_addr; 2631 DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
2618 len = sizeof (sin6->sin6_addr) / 2 + 1; 2632 len = sizeof (sin6->sin6_addr) / 2 + 1;
2619 hostport = XINT (p->contents[--len]); 2633 hostport = XINT (p->contents[--len]);
2620 sin6->sin6_port = htons (hostport); 2634 sin6->sin6_port = htons (hostport);
@@ -2636,7 +2650,7 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
2636#ifdef HAVE_LOCAL_SOCKETS 2650#ifdef HAVE_LOCAL_SOCKETS
2637 if (family == AF_LOCAL) 2651 if (family == AF_LOCAL)
2638 { 2652 {
2639 struct sockaddr_un *sockun = (struct sockaddr_un *) sa; 2653 DECLARE_POINTER_ALIAS (sockun, struct sockaddr_un, sa);
2640 cp = SDATA (address); 2654 cp = SDATA (address);
2641 for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++) 2655 for (i = 0; i < sizeof (sockun->sun_path) && *cp; i++)
2642 sockun->sun_path[i] = *cp++; 2656 sockun->sun_path[i] = *cp++;
@@ -3409,18 +3423,33 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3409 report_file_error ("Cannot bind server socket", Qnil); 3423 report_file_error ("Cannot bind server socket", Qnil);
3410 3424
3411#ifdef HAVE_GETSOCKNAME 3425#ifdef HAVE_GETSOCKNAME
3412 if (p->port == 0) 3426 if (p->port == 0
3427#ifdef HAVE_LOCAL_SOCKETS
3428 && family != AF_LOCAL
3429#endif
3430 )
3413 { 3431 {
3414 struct sockaddr_in sa1; 3432 struct sockaddr_in sa1;
3415 socklen_t len1 = sizeof (sa1); 3433 socklen_t len1 = sizeof (sa1);
3416 if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) 3434#ifdef AF_INET6
3435 /* The code below assumes the port is at the same offset
3436 and of the same width in both IPv4 and IPv6
3437 structures, but the standards don't guarantee that,
3438 so verify it here. */
3439 struct sockaddr_in6 sa6;
3440 verify ((offsetof (struct sockaddr_in, sin_port)
3441 == offsetof (struct sockaddr_in6, sin6_port))
3442 && sizeof (sa1.sin_port) == sizeof (sa6.sin6_port));
3443#endif
3444 DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
3445 if (getsockname (s, psa1, &len1) == 0)
3417 { 3446 {
3418 Lisp_Object service; 3447 Lisp_Object service = make_number (ntohs (sa1.sin_port));
3419 service = make_number (ntohs (sa1.sin_port));
3420 contact = Fplist_put (contact, QCservice, service); 3448 contact = Fplist_put (contact, QCservice, service);
3421 /* Save the port number so that we can stash it in 3449 /* Save the port number so that we can stash it in
3422 the process object later. */ 3450 the process object later. */
3423 ((struct sockaddr_in *)sa)->sin_port = sa1.sin_port; 3451 DECLARE_POINTER_ALIAS (psa, struct sockaddr_in, sa);
3452 psa->sin_port = sa1.sin_port;
3424 } 3453 }
3425 } 3454 }
3426#endif 3455#endif
@@ -3526,11 +3555,12 @@ connect_network_socket (Lisp_Object proc, Lisp_Object addrinfos,
3526#ifdef HAVE_GETSOCKNAME 3555#ifdef HAVE_GETSOCKNAME
3527 if (!p->is_server) 3556 if (!p->is_server)
3528 { 3557 {
3529 struct sockaddr_in sa1; 3558 struct sockaddr_storage sa1;
3530 socklen_t len1 = sizeof (sa1); 3559 socklen_t len1 = sizeof (sa1);
3531 if (getsockname (s, (struct sockaddr *)&sa1, &len1) == 0) 3560 DECLARE_POINTER_ALIAS (psa1, struct sockaddr, &sa1);
3561 if (getsockname (s, psa1, &len1) == 0)
3532 contact = Fplist_put (contact, QClocal, 3562 contact = Fplist_put (contact, QClocal,
3533 conv_sockaddr_to_lisp ((struct sockaddr *)&sa1, len1)); 3563 conv_sockaddr_to_lisp (psa1, len1));
3534 } 3564 }
3535#endif 3565#endif
3536 } 3566 }
@@ -4379,7 +4409,7 @@ network_interface_info (Lisp_Object ifname)
4379 4409
4380 for (it = ifap; it != NULL; it = it->ifa_next) 4410 for (it = ifap; it != NULL; it = it->ifa_next)
4381 { 4411 {
4382 struct sockaddr_dl *sdl = (struct sockaddr_dl *) it->ifa_addr; 4412 DECLARE_POINTER_ALIAS (sdl, struct sockaddr_dl, it->ifa_addr);
4383 unsigned char linkaddr[6]; 4413 unsigned char linkaddr[6];
4384 int n; 4414 int n;
4385 4415
@@ -4563,8 +4593,16 @@ is nil, from any process) before the timeout expired. */)
4563 /* Can't wait for a process that is dedicated to a different 4593 /* Can't wait for a process that is dedicated to a different
4564 thread. */ 4594 thread. */
4565 if (!EQ (proc->thread, Qnil) && !EQ (proc->thread, Fcurrent_thread ())) 4595 if (!EQ (proc->thread, Qnil) && !EQ (proc->thread, Fcurrent_thread ()))
4566 error ("Attempt to accept output from process %s locked to thread %s", 4596 {
4567 SDATA (proc->name), SDATA (XTHREAD (proc->thread)->name)); 4597 Lisp_Object proc_thread_name = XTHREAD (proc->thread)->name;
4598
4599 if (STRINGP (proc_thread_name))
4600 error ("Attempt to accept output from process %s locked to thread %s",
4601 SDATA (proc->name), SDATA (proc_thread_name));
4602 else
4603 error ("Attempt to accept output from process %s locked to thread %p",
4604 SDATA (proc->name), XTHREAD (proc->thread));
4605 }
4568 } 4606 }
4569 else 4607 else
4570 just_this_one = Qnil; 4608 just_this_one = Qnil;
@@ -4626,7 +4664,7 @@ static EMACS_INT connect_counter = 0;
4626static void 4664static void
4627server_accept_connection (Lisp_Object server, int channel) 4665server_accept_connection (Lisp_Object server, int channel)
4628{ 4666{
4629 Lisp_Object proc, caller, name, buffer; 4667 Lisp_Object buffer;
4630 Lisp_Object contact, host, service; 4668 Lisp_Object contact, host, service;
4631 struct Lisp_Process *ps = XPROCESS (server); 4669 struct Lisp_Process *ps = XPROCESS (server);
4632 struct Lisp_Process *p; 4670 struct Lisp_Process *p;
@@ -4668,49 +4706,43 @@ server_accept_connection (Lisp_Object server, int channel)
4668 information for this process. */ 4706 information for this process. */
4669 host = Qt; 4707 host = Qt;
4670 service = Qnil; 4708 service = Qnil;
4709 Lisp_Object args[11];
4710 int nargs = 0;
4711 AUTO_STRING (procname_format_in, "%s <%d.%d.%d.%d:%d>");
4712 AUTO_STRING (procname_format_in6, "%s <[%x:%x:%x:%x:%x:%x:%x:%x]:%d>");
4713 AUTO_STRING (procname_format_default, "%s <%d>");
4671 switch (saddr.sa.sa_family) 4714 switch (saddr.sa.sa_family)
4672 { 4715 {
4673 case AF_INET: 4716 case AF_INET:
4674 { 4717 {
4718 args[nargs++] = procname_format_in;
4719 nargs++;
4675 unsigned char *ip = (unsigned char *)&saddr.in.sin_addr.s_addr; 4720 unsigned char *ip = (unsigned char *)&saddr.in.sin_addr.s_addr;
4676
4677 AUTO_STRING (ipv4_format, "%d.%d.%d.%d");
4678 host = CALLN (Fformat, ipv4_format,
4679 make_number (ip[0]), make_number (ip[1]),
4680 make_number (ip[2]), make_number (ip[3]));
4681 service = make_number (ntohs (saddr.in.sin_port)); 4721 service = make_number (ntohs (saddr.in.sin_port));
4682 AUTO_STRING (caller_format, " <%s:%d>"); 4722 for (int i = 0; i < 4; i++)
4683 caller = CALLN (Fformat, caller_format, host, service); 4723 args[nargs++] = make_number (ip[i]);
4724 args[nargs++] = service;
4684 } 4725 }
4685 break; 4726 break;
4686 4727
4687#ifdef AF_INET6 4728#ifdef AF_INET6
4688 case AF_INET6: 4729 case AF_INET6:
4689 { 4730 {
4690 Lisp_Object args[9]; 4731 args[nargs++] = procname_format_in6;
4691 uint16_t *ip6 = (uint16_t *)&saddr.in6.sin6_addr; 4732 nargs++;
4692 int i; 4733 DECLARE_POINTER_ALIAS (ip6, uint16_t, &saddr.in6.sin6_addr);
4693
4694 AUTO_STRING (ipv6_format, "%x:%x:%x:%x:%x:%x:%x:%x");
4695 args[0] = ipv6_format;
4696 for (i = 0; i < 8; i++)
4697 args[i + 1] = make_number (ntohs (ip6[i]));
4698 host = CALLMANY (Fformat, args);
4699 service = make_number (ntohs (saddr.in.sin_port)); 4734 service = make_number (ntohs (saddr.in.sin_port));
4700 AUTO_STRING (caller_format, " <[%s]:%d>"); 4735 for (int i = 0; i < 8; i++)
4701 caller = CALLN (Fformat, caller_format, host, service); 4736 args[nargs++] = make_number (ip6[i]);
4737 args[nargs++] = service;
4702 } 4738 }
4703 break; 4739 break;
4704#endif 4740#endif
4705 4741
4706#ifdef HAVE_LOCAL_SOCKETS
4707 case AF_LOCAL:
4708#endif
4709 default: 4742 default:
4710 caller = Fnumber_to_string (make_number (connect_counter)); 4743 args[nargs++] = procname_format_default;
4711 AUTO_STRING (space_less_than, " <"); 4744 nargs++;
4712 AUTO_STRING (greater_than, ">"); 4745 args[nargs++] = make_number (connect_counter);
4713 caller = concat3 (space_less_than, caller, greater_than);
4714 break; 4746 break;
4715 } 4747 }
4716 4748
@@ -4731,16 +4763,17 @@ server_accept_connection (Lisp_Object server, int channel)
4731 buffer = ps->name; 4763 buffer = ps->name;
4732 if (!NILP (buffer)) 4764 if (!NILP (buffer))
4733 { 4765 {
4734 buffer = concat2 (buffer, caller); 4766 args[1] = buffer;
4735 buffer = Fget_buffer_create (buffer); 4767 buffer = Fget_buffer_create (Fformat (nargs, args));
4736 } 4768 }
4737 } 4769 }
4738 4770
4739 /* Generate a unique name for the new server process. Combine the 4771 /* Generate a unique name for the new server process. Combine the
4740 server process name with the caller identification. */ 4772 server process name with the caller identification. */
4741 4773
4742 name = concat2 (ps->name, caller); 4774 args[1] = ps->name;
4743 proc = make_process (name); 4775 Lisp_Object name = Fformat (nargs, args);
4776 Lisp_Object proc = make_process (name);
4744 4777
4745 chan_process[s] = proc; 4778 chan_process[s] = proc;
4746 4779
@@ -5338,14 +5371,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5338 nfds = xg_select (max_desc + 1, 5371 nfds = xg_select (max_desc + 1,
5339 &Available, (check_write ? &Writeok : 0), 5372 &Available, (check_write ? &Writeok : 0),
5340 NULL, &timeout, NULL); 5373 NULL, &timeout, NULL);
5374#elif defined HAVE_NS
5375 /* And NS builds call thread_select in ns_select. */
5376 nfds = ns_select (max_desc + 1,
5377 &Available, (check_write ? &Writeok : 0),
5378 NULL, &timeout, NULL);
5341#else /* !HAVE_GLIB */ 5379#else /* !HAVE_GLIB */
5342 nfds = thread_select ( 5380 nfds = thread_select (pselect, max_desc + 1,
5343# ifdef HAVE_NS
5344 ns_select
5345# else
5346 pselect
5347# endif
5348 , max_desc + 1,
5349 &Available, 5381 &Available,
5350 (check_write ? &Writeok : 0), 5382 (check_write ? &Writeok : 0),
5351 NULL, &timeout, NULL); 5383 NULL, &timeout, NULL);
diff --git a/src/regex.c b/src/regex.c
index 8e38a920cdb..240a91f2ba8 100644
--- a/src/regex.c
+++ b/src/regex.c
@@ -2636,8 +2636,9 @@ regex_compile (const_re_char *pattern, size_t size,
2636 if ((syntax & RE_BK_PLUS_QM) 2636 if ((syntax & RE_BK_PLUS_QM)
2637 || (syntax & RE_LIMITED_OPS)) 2637 || (syntax & RE_LIMITED_OPS))
2638 goto normal_char; 2638 goto normal_char;
2639 handle_plus: 2639 FALLTHROUGH;
2640 case '*': 2640 case '*':
2641 handle_plus:
2641 /* If there is no previous pattern... */ 2642 /* If there is no previous pattern... */
2642 if (!laststart) 2643 if (!laststart)
2643 { 2644 {
@@ -3086,6 +3087,7 @@ regex_compile (const_re_char *pattern, size_t size,
3086 with non-0. */ 3087 with non-0. */
3087 if (regnum == 0) 3088 if (regnum == 0)
3088 FREE_STACK_RETURN (REG_BADPAT); 3089 FREE_STACK_RETURN (REG_BADPAT);
3090 FALLTHROUGH;
3089 case '1': case '2': case '3': case '4': 3091 case '1': case '2': case '3': case '4':
3090 case '5': case '6': case '7': case '8': case '9': 3092 case '5': case '6': case '7': case '8': case '9':
3091 regnum = 10*regnum + (c - '0'); break; 3093 regnum = 10*regnum + (c - '0'); break;
@@ -3905,8 +3907,7 @@ analyze_first (const_re_char *p, const_re_char *pend, char *fastmap,
3905 j < (1 << BYTEWIDTH); j++) 3907 j < (1 << BYTEWIDTH); j++)
3906 fastmap[j] = 1; 3908 fastmap[j] = 1;
3907 } 3909 }
3908 3910 FALLTHROUGH;
3909 /* Fallthrough */
3910 case charset: 3911 case charset:
3911 if (!fastmap) break; 3912 if (!fastmap) break;
3912 not = (re_opcode_t) *(p - 1) == charset_not; 3913 not = (re_opcode_t) *(p - 1) == charset_not;
@@ -6182,8 +6183,7 @@ re_match_2_internal (struct re_pattern_buffer *bufp, const_re_char *string1,
6182 case on_failure_jump_nastyloop: 6183 case on_failure_jump_nastyloop:
6183 assert ((re_opcode_t)pat[-2] == no_op); 6184 assert ((re_opcode_t)pat[-2] == no_op);
6184 PUSH_FAILURE_POINT (pat - 2, str); 6185 PUSH_FAILURE_POINT (pat - 2, str);
6185 /* Fallthrough */ 6186 FALLTHROUGH;
6186
6187 case on_failure_jump_loop: 6187 case on_failure_jump_loop:
6188 case on_failure_jump: 6188 case on_failure_jump:
6189 case succeed_n: 6189 case succeed_n:
diff --git a/src/search.c b/src/search.c
index 33cb02aa7af..19e789dfa87 100644
--- a/src/search.c
+++ b/src/search.c
@@ -1804,6 +1804,7 @@ boyer_moore (EMACS_INT n, unsigned char *base_pat,
1804 { 1804 {
1805 /* Setup translate_prev_byte1/2/3/4 from CHAR_BASE. Only a 1805 /* Setup translate_prev_byte1/2/3/4 from CHAR_BASE. Only a
1806 byte following them are the target of translation. */ 1806 byte following them are the target of translation. */
1807 eassume (0x80 <= char_base && char_base <= MAX_CHAR);
1807 unsigned char str[MAX_MULTIBYTE_LENGTH]; 1808 unsigned char str[MAX_MULTIBYTE_LENGTH];
1808 int cblen = CHAR_STRING (char_base, str); 1809 int cblen = CHAR_STRING (char_base, str);
1809 1810
@@ -2228,26 +2229,12 @@ See also the functions `match-beginning', `match-end' and `replace-match'. */)
2228 2229
2229DEFUN ("re-search-backward", Fre_search_backward, Sre_search_backward, 1, 4, 2230DEFUN ("re-search-backward", Fre_search_backward, Sre_search_backward, 1, 4,
2230 "sRE search backward: ", 2231 "sRE search backward: ",
2231 doc: /* Search backward from point for match for regular expression REGEXP. 2232 doc: /* Search backward from point for regular expression REGEXP.
2232Set point to the beginning of the occurrence found, and return point. 2233This function is almost identical to `re-search-forward', except that
2233An optional second argument bounds the search; it is a buffer position. 2234by default it searches backward instead of forward, and the sign of
2234 The match found must not begin before that position. A value of nil 2235COUNT also indicates exactly the opposite searching direction.
2235 means search to the beginning of the accessible portion of the buffer.
2236Optional third argument, if t, means if fail just return nil (no error).
2237 If not nil and not t, position at limit of search and return nil.
2238Optional fourth argument COUNT, if a positive number, means to search
2239 for COUNT successive occurrences. If COUNT is negative, search
2240 forward, instead of backward, for -COUNT occurrences. A value of
2241 nil means the same as 1.
2242With COUNT positive, the match found is the COUNTth to last one (or
2243 last, if COUNT is 1 or nil) in the buffer located entirely before
2244 the origin of the search; correspondingly with COUNT negative.
2245
2246Search case-sensitivity is determined by the value of the variable
2247`case-fold-search', which see.
2248 2236
2249See also the functions `match-beginning', `match-end', `match-string', 2237See `re-search-forward' for details. */)
2250and `replace-match'. */)
2251 (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count) 2238 (Lisp_Object regexp, Lisp_Object bound, Lisp_Object noerror, Lisp_Object count)
2252{ 2239{
2253 return search_command (regexp, bound, noerror, count, -1, 1, 0); 2240 return search_command (regexp, bound, noerror, count, -1, 1, 0);
@@ -2257,18 +2244,22 @@ DEFUN ("re-search-forward", Fre_search_forward, Sre_search_forward, 1, 4,
2257 "sRE search: ", 2244 "sRE search: ",
2258 doc: /* Search forward from point for regular expression REGEXP. 2245 doc: /* Search forward from point for regular expression REGEXP.
2259Set point to the end of the occurrence found, and return point. 2246Set point to the end of the occurrence found, and return point.
2260An optional second argument bounds the search; it is a buffer position. 2247The optional second argument BOUND is a buffer position that bounds
2261 The match found must not end after that position. A value of nil 2248 the search. The match found must not end after that position. A
2262 means search to the end of the accessible portion of the buffer. 2249 value of nil means search to the end of the accessible portion of
2263Optional third argument, if t, means if fail just return nil (no error). 2250 the buffer.
2264 If not nil and not t, move to limit of search and return nil. 2251The optional third argument NOERROR indicates how errors are handled
2265Optional fourth argument COUNT, if a positive number, means to search 2252 when the search fails. If it is nil or omitted, emit an error; if
2266 for COUNT successive occurrences. If COUNT is negative, search 2253 it is t, simply return nil and do nothing; if it is neither nil nor
2267 backward, instead of forward, for -COUNT occurrences. A value of 2254 t, move to the limit of search and return nil.
2268 nil means the same as 1. 2255The optional fourth argument COUNT is a number that indicates the
2269With COUNT positive, the match found is the COUNTth one (or first, 2256 search direction and the number of occurrences to search for. If it
2270 if COUNT is 1 or nil) in the buffer located entirely after the 2257 is positive, search forward for COUNT successive occurrences; if it
2271 origin of the search; correspondingly with COUNT negative. 2258 is negative, search backward, instead of forward, for -COUNT
2259 occurrences. A value of nil means the same as 1.
2260With COUNT positive/negative, the match found is the COUNTth/-COUNTth
2261 one in the buffer located entirely after/before the origin of the
2262 search.
2272 2263
2273Search case-sensitivity is determined by the value of the variable 2264Search case-sensitivity is determined by the value of the variable
2274`case-fold-search', which see. 2265`case-fold-search', which see.
@@ -2640,7 +2631,7 @@ since only regular expressions have distinguished subexpressions. */)
2640 const unsigned char *add_stuff = NULL; 2631 const unsigned char *add_stuff = NULL;
2641 ptrdiff_t add_len = 0; 2632 ptrdiff_t add_len = 0;
2642 ptrdiff_t idx = -1; 2633 ptrdiff_t idx = -1;
2643 ptrdiff_t begbyte; 2634 ptrdiff_t begbyte UNINIT;
2644 2635
2645 if (str_multibyte) 2636 if (str_multibyte)
2646 { 2637 {
@@ -3389,6 +3380,10 @@ syms_of_search (void)
3389 /* Error condition used for failing searches. */ 3380 /* Error condition used for failing searches. */
3390 DEFSYM (Qsearch_failed, "search-failed"); 3381 DEFSYM (Qsearch_failed, "search-failed");
3391 3382
3383 /* Error condition used for failing searches started by user, i.e.,
3384 where failure should not invoke the debugger. */
3385 DEFSYM (Quser_search_failed, "user-search-failed");
3386
3392 /* Error condition signaled when regexp compile_pattern fails. */ 3387 /* Error condition signaled when regexp compile_pattern fails. */
3393 DEFSYM (Qinvalid_regexp, "invalid-regexp"); 3388 DEFSYM (Qinvalid_regexp, "invalid-regexp");
3394 3389
@@ -3397,6 +3392,12 @@ syms_of_search (void)
3397 Fput (Qsearch_failed, Qerror_message, 3392 Fput (Qsearch_failed, Qerror_message,
3398 build_pure_c_string ("Search failed")); 3393 build_pure_c_string ("Search failed"));
3399 3394
3395 Fput (Quser_search_failed, Qerror_conditions,
3396 listn (CONSTYPE_PURE, 4,
3397 Quser_search_failed, Quser_error, Qsearch_failed, Qerror));
3398 Fput (Quser_search_failed, Qerror_message,
3399 build_pure_c_string ("Search failed"));
3400
3400 Fput (Qinvalid_regexp, Qerror_conditions, 3401 Fput (Qinvalid_regexp, Qerror_conditions,
3401 listn (CONSTYPE_PURE, 2, Qinvalid_regexp, Qerror)); 3402 listn (CONSTYPE_PURE, 2, Qinvalid_regexp, Qerror));
3402 Fput (Qinvalid_regexp, Qerror_message, 3403 Fput (Qinvalid_regexp, Qerror_message,
diff --git a/src/syntax.c b/src/syntax.c
index 7aa43e6e5c7..dcaca22f0e2 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -810,6 +810,7 @@ back_comment (ptrdiff_t from, ptrdiff_t from_byte, ptrdiff_t stop,
810 case Sstring_fence: 810 case Sstring_fence:
811 case Scomment_fence: 811 case Scomment_fence:
812 c = (code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE); 812 c = (code == Sstring_fence ? ST_STRING_STYLE : ST_COMMENT_STYLE);
813 FALLTHROUGH;
813 case Sstring: 814 case Sstring:
814 /* Track parity of quotes. */ 815 /* Track parity of quotes. */
815 if (string_style == -1) 816 if (string_style == -1)
@@ -2690,6 +2691,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2690 goto lose; 2691 goto lose;
2691 INC_BOTH (from, from_byte); 2692 INC_BOTH (from, from_byte);
2692 /* Treat following character as a word constituent. */ 2693 /* Treat following character as a word constituent. */
2694 FALLTHROUGH;
2693 case Sword: 2695 case Sword:
2694 case Ssymbol: 2696 case Ssymbol:
2695 if (depth || !sexpflag) break; 2697 if (depth || !sexpflag) break;
@@ -2721,7 +2723,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2721 2723
2722 case Scomment_fence: 2724 case Scomment_fence:
2723 comstyle = ST_COMMENT_STYLE; 2725 comstyle = ST_COMMENT_STYLE;
2724 /* FALLTHROUGH */ 2726 FALLTHROUGH;
2725 case Scomment: 2727 case Scomment:
2726 if (!parse_sexp_ignore_comments) break; 2728 if (!parse_sexp_ignore_comments) break;
2727 UPDATE_SYNTAX_TABLE_FORWARD (from); 2729 UPDATE_SYNTAX_TABLE_FORWARD (from);
@@ -2753,7 +2755,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2753 goto close1; 2755 goto close1;
2754 } 2756 }
2755 mathexit = 1; 2757 mathexit = 1;
2756 2758 FALLTHROUGH;
2757 case Sopen: 2759 case Sopen:
2758 if (!++depth) goto done; 2760 if (!++depth) goto done;
2759 break; 2761 break;
@@ -2909,7 +2911,7 @@ scan_lists (EMACS_INT from, EMACS_INT count, EMACS_INT depth, bool sexpflag)
2909 goto open2; 2911 goto open2;
2910 } 2912 }
2911 mathexit = 1; 2913 mathexit = 1;
2912 2914 FALLTHROUGH;
2913 case Sclose: 2915 case Sclose:
2914 if (!++depth) goto done2; 2916 if (!++depth) goto done2;
2915 break; 2917 break;
diff --git a/src/sysdep.c b/src/sysdep.c
index 91b2a5cb943..b52236769e0 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -368,8 +368,8 @@ init_baud_rate (int fd)
368 Use waitpid-style OPTIONS when waiting. 368 Use waitpid-style OPTIONS when waiting.
369 If INTERRUPTIBLE, this function is interruptible by a signal. 369 If INTERRUPTIBLE, this function is interruptible by a signal.
370 370
371 Return CHILD if successful, 0 if no status is available; 371 Return CHILD if successful, 0 if no status is available, and a
372 the latter is possible only when options & NOHANG. */ 372 negative value (setting errno) if waitpid is buggy. */
373static pid_t 373static pid_t
374get_child_status (pid_t child, int *status, int options, bool interruptible) 374get_child_status (pid_t child, int *status, int options, bool interruptible)
375{ 375{
@@ -392,13 +392,14 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
392 pid = waitpid (child, status, options); 392 pid = waitpid (child, status, options);
393 if (0 <= pid) 393 if (0 <= pid)
394 break; 394 break;
395
396 /* Check that CHILD is a child process that has not been reaped,
397 and that STATUS and OPTIONS are valid. Otherwise abort,
398 as continuing after this internal error could cause Emacs to
399 become confused and kill innocent-victim processes. */
400 if (errno != EINTR) 395 if (errno != EINTR)
401 emacs_abort (); 396 {
397 /* Most likely, waitpid is buggy and the operating system
398 lost track of the child somehow. Return -1 and let the
399 caller try to figure things out. Possibly the bug could
400 cause Emacs to kill the wrong process. Oh well. */
401 return pid;
402 }
402 } 403 }
403 404
404 /* If successful and status is requested, tell wait_reading_process_output 405 /* If successful and status is requested, tell wait_reading_process_output
@@ -413,11 +414,13 @@ get_child_status (pid_t child, int *status, int options, bool interruptible)
413 CHILD must be a child process that has not been reaped. 414 CHILD must be a child process that has not been reaped.
414 If STATUS is non-null, store the waitpid-style exit status into *STATUS 415 If STATUS is non-null, store the waitpid-style exit status into *STATUS
415 and tell wait_reading_process_output that it needs to look around. 416 and tell wait_reading_process_output that it needs to look around.
416 If INTERRUPTIBLE, this function is interruptible by a signal. */ 417 If INTERRUPTIBLE, this function is interruptible by a signal.
417void 418 Return true if successful, false (setting errno) if CHILD cannot be
419 waited for because waitpid is buggy. */
420bool
418wait_for_termination (pid_t child, int *status, bool interruptible) 421wait_for_termination (pid_t child, int *status, bool interruptible)
419{ 422{
420 get_child_status (child, status, 0, interruptible); 423 return 0 <= get_child_status (child, status, 0, interruptible);
421} 424}
422 425
423/* Report whether the subprocess with process id CHILD has changed status. 426/* Report whether the subprocess with process id CHILD has changed status.
@@ -1405,7 +1408,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
1405{ 1408{
1406 if (noninteractive) 1409 if (noninteractive)
1407 { 1410 {
1408 fflush (stdout); 1411 fflush_unlocked (stdout);
1409 return; 1412 return;
1410 } 1413 }
1411 if (!tty_out->term_initted) 1414 if (!tty_out->term_initted)
@@ -1425,17 +1428,14 @@ reset_sys_modes (struct tty_display_info *tty_out)
1425 } 1428 }
1426 else 1429 else
1427 { /* have to do it the hard way */ 1430 { /* have to do it the hard way */
1428 int i;
1429 tty_turn_off_insert (tty_out); 1431 tty_turn_off_insert (tty_out);
1430 1432
1431 for (i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++) 1433 for (int i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++)
1432 { 1434 fputc_unlocked (' ', tty_out->output);
1433 fputc (' ', tty_out->output);
1434 }
1435 } 1435 }
1436 1436
1437 cmgoto (tty_out, FrameRows (tty_out) - 1, 0); 1437 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1438 fflush (tty_out->output); 1438 fflush_unlocked (tty_out->output);
1439 1439
1440 if (tty_out->terminal->reset_terminal_modes_hook) 1440 if (tty_out->terminal->reset_terminal_modes_hook)
1441 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal); 1441 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
@@ -3076,7 +3076,7 @@ procfs_ttyname (int rdev)
3076 char minor[25]; /* 2 32-bit numbers + dash */ 3076 char minor[25]; /* 2 32-bit numbers + dash */
3077 char *endp; 3077 char *endp;
3078 3078
3079 for (; !feof (fdev) && !ferror (fdev); name[0] = 0) 3079 for (; !feof_unlocked (fdev) && !ferror_unlocked (fdev); name[0] = 0)
3080 { 3080 {
3081 if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3 3081 if (fscanf (fdev, "%*s %s %u %s %*s\n", name, &major, minor) >= 3
3082 && major == MAJOR (rdev)) 3082 && major == MAJOR (rdev))
@@ -3126,7 +3126,7 @@ procfs_get_total_memory (void)
3126 break; 3126 break;
3127 3127
3128 case 0: 3128 case 0:
3129 while ((c = getc (fmem)) != EOF && c != '\n') 3129 while ((c = getc_unlocked (fmem)) != EOF && c != '\n')
3130 continue; 3130 continue;
3131 done = c == EOF; 3131 done = c == EOF;
3132 break; 3132 break;
@@ -3707,14 +3707,9 @@ Lisp_Object
3707system_process_attributes (Lisp_Object pid) 3707system_process_attributes (Lisp_Object pid)
3708{ 3708{
3709 int proc_id; 3709 int proc_id;
3710 int pagesize = getpagesize ();
3711 unsigned long npages;
3712 int fscale;
3713 struct passwd *pw; 3710 struct passwd *pw;
3714 struct group *gr; 3711 struct group *gr;
3715 char *ttyname; 3712 char *ttyname;
3716 size_t len;
3717 char args[MAXPATHLEN];
3718 struct timeval starttime; 3713 struct timeval starttime;
3719 struct timespec t, now; 3714 struct timespec t, now;
3720 struct rusage *rusage; 3715 struct rusage *rusage;
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 45ee33f5580..7fbcefcdad9 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -33,4 +33,45 @@ extern FILE *emacs_fopen (char const *, char const *);
33# define FOPEN_TEXT "" 33# define FOPEN_TEXT ""
34#endif 34#endif
35 35
36/* These are compatible with unlocked-io.h, if both files are included. */
37#if !HAVE_DECL_CLEARERR_UNLOCKED
38# define clearerr_unlocked(x) clearerr (x)
39#endif
40#if !HAVE_DECL_FEOF_UNLOCKED
41# define feof_unlocked(x) feof (x)
42#endif
43#if !HAVE_DECL_FERROR_UNLOCKED
44# define ferror_unlocked(x) ferror (x)
45#endif
46#if !HAVE_DECL_FFLUSH_UNLOCKED
47# define fflush_unlocked(x) fflush (x)
48#endif
49#if !HAVE_DECL_FGETS_UNLOCKED
50# define fgets_unlocked(x,y,z) fgets (x,y,z)
51#endif
52#if !HAVE_DECL_FPUTC_UNLOCKED
53# define fputc_unlocked(x,y) fputc (x,y)
54#endif
55#if !HAVE_DECL_FPUTS_UNLOCKED
56# define fputs_unlocked(x,y) fputs (x,y)
57#endif
58#if !HAVE_DECL_FREAD_UNLOCKED
59# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
60#endif
61#if !HAVE_DECL_FWRITE_UNLOCKED
62# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
63#endif
64#if !HAVE_DECL_GETC_UNLOCKED
65# define getc_unlocked(x) getc (x)
66#endif
67#if !HAVE_DECL_GETCHAR_UNLOCKED
68# define getchar_unlocked() getchar ()
69#endif
70#if !HAVE_DECL_PUTC_UNLOCKED
71# define putc_unlocked(x,y) putc (x,y)
72#endif
73#if !HAVE_DECL_PUTCHAR_UNLOCKED
74# define putchar_unlocked(x) putchar (x)
75#endif
76
36#endif /* EMACS_SYSSTDIO_H */ 77#endif /* EMACS_SYSSTDIO_H */
diff --git a/src/systhread.c b/src/systhread.c
index a84060c18f0..aee12a9b482 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -20,6 +20,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <setjmp.h> 20#include <setjmp.h>
21#include "lisp.h" 21#include "lisp.h"
22 22
23#ifdef HAVE_NS
24#include "nsterm.h"
25#endif
26
23#ifndef THREADS_ENABLED 27#ifndef THREADS_ENABLED
24 28
25void 29void
@@ -130,6 +134,13 @@ void
130sys_cond_broadcast (sys_cond_t *cond) 134sys_cond_broadcast (sys_cond_t *cond)
131{ 135{
132 pthread_cond_broadcast (cond); 136 pthread_cond_broadcast (cond);
137#ifdef HAVE_NS
138 /* Send an app defined event to break out of the NS run loop.
139 It seems that if ns_select is running the NS run loop, this
140 broadcast has no effect until the loop is done, breaking a couple
141 of tests in thread-tests.el. */
142 ns_run_loop_break ();
143#endif
133} 144}
134 145
135void 146void
diff --git a/src/syswait.h b/src/syswait.h
index 846a975b241..055562ae48b 100644
--- a/src/syswait.h
+++ b/src/syswait.h
@@ -56,7 +56,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
56#endif 56#endif
57 57
58/* Defined in sysdep.c. */ 58/* Defined in sysdep.c. */
59extern void wait_for_termination (pid_t, int *, bool); 59extern bool wait_for_termination (pid_t, int *, bool);
60extern pid_t child_status_changed (pid_t, int *, int); 60extern pid_t child_status_changed (pid_t, int *, int);
61 61
62#endif /* EMACS_SYSWAIT_H */ 62#endif /* EMACS_SYSWAIT_H */
diff --git a/src/term.c b/src/term.c
index 8770aff8a92..3d7f4ada0b9 100644
--- a/src/term.c
+++ b/src/term.c
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include <config.h> 22#include <config.h>
23#include <errno.h> 23#include <errno.h>
24#include <fcntl.h> 24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h> 25#include <stdlib.h>
27#include <sys/file.h> 26#include <sys/file.h>
28#include <sys/time.h> 27#include <sys/time.h>
@@ -45,6 +44,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
45#include "keymap.h" 44#include "keymap.h"
46#include "blockinput.h" 45#include "blockinput.h"
47#include "syssignal.h" 46#include "syssignal.h"
47#include "sysstdio.h"
48#ifdef MSDOS 48#ifdef MSDOS
49#include "msdos.h" 49#include "msdos.h"
50static int been_here = -1; 50static int been_here = -1;
@@ -146,7 +146,7 @@ tty_ring_bell (struct frame *f)
146 OUTPUT (tty, (tty->TS_visible_bell && visible_bell 146 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
147 ? tty->TS_visible_bell 147 ? tty->TS_visible_bell
148 : tty->TS_bell)); 148 : tty->TS_bell));
149 fflush (tty->output); 149 fflush_unlocked (tty->output);
150 } 150 }
151} 151}
152 152
@@ -167,9 +167,10 @@ tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym)
167 Lisp_Object string = XCAR (extra_codes); 167 Lisp_Object string = XCAR (extra_codes);
168 if (STRINGP (string)) 168 if (STRINGP (string))
169 { 169 {
170 fwrite (SDATA (string), 1, SBYTES (string), tty->output); 170 fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->output);
171 if (tty->termscript) 171 if (tty->termscript)
172 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); 172 fwrite_unlocked (SDATA (string), 1, SBYTES (string),
173 tty->termscript);
173 } 174 }
174 } 175 }
175} 176}
@@ -197,7 +198,7 @@ tty_set_terminal_modes (struct terminal *terminal)
197 OUTPUT_IF (tty, tty->TS_keypad_mode); 198 OUTPUT_IF (tty, tty->TS_keypad_mode);
198 losecursor (tty); 199 losecursor (tty);
199 tty_send_additional_strings (terminal, Qtty_mode_set_strings); 200 tty_send_additional_strings (terminal, Qtty_mode_set_strings);
200 fflush (tty->output); 201 fflush_unlocked (tty->output);
201 } 202 }
202} 203}
203 204
@@ -220,7 +221,7 @@ tty_reset_terminal_modes (struct terminal *terminal)
220 /* Output raw CR so kernel can track the cursor hpos. */ 221 /* Output raw CR so kernel can track the cursor hpos. */
221 current_tty = tty; 222 current_tty = tty;
222 cmputc ('\r'); 223 cmputc ('\r');
223 fflush (tty->output); 224 fflush_unlocked (tty->output);
224 } 225 }
225} 226}
226 227
@@ -235,7 +236,7 @@ tty_update_end (struct frame *f)
235 tty_show_cursor (tty); 236 tty_show_cursor (tty);
236 tty_turn_off_insert (tty); 237 tty_turn_off_insert (tty);
237 tty_background_highlight (tty); 238 tty_background_highlight (tty);
238 fflush (tty->output); 239 fflush_unlocked (tty->output);
239} 240}
240 241
241/* The implementation of set_terminal_window for termcap frames. */ 242/* The implementation of set_terminal_window for termcap frames. */
@@ -497,8 +498,8 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
497 for (i = curX (tty); i < first_unused_hpos; i++) 498 for (i = curX (tty); i < first_unused_hpos; i++)
498 { 499 {
499 if (tty->termscript) 500 if (tty->termscript)
500 fputc (' ', tty->termscript); 501 fputc_unlocked (' ', tty->termscript);
501 fputc (' ', tty->output); 502 fputc_unlocked (' ', tty->output);
502 } 503 }
503 cmplus (tty, first_unused_hpos - curX (tty)); 504 cmplus (tty, first_unused_hpos - curX (tty));
504 } 505 }
@@ -771,11 +772,11 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
771 if (coding->produced > 0) 772 if (coding->produced > 0)
772 { 773 {
773 block_input (); 774 block_input ();
774 fwrite (conversion_buffer, 1, coding->produced, tty->output); 775 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
775 if (ferror (tty->output)) 776 clearerr_unlocked (tty->output);
776 clearerr (tty->output);
777 if (tty->termscript) 777 if (tty->termscript)
778 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 778 fwrite_unlocked (conversion_buffer, 1, coding->produced,
779 tty->termscript);
779 unblock_input (); 780 unblock_input ();
780 } 781 }
781 string += n; 782 string += n;
@@ -832,11 +833,11 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
832 if (coding->produced > 0) 833 if (coding->produced > 0)
833 { 834 {
834 block_input (); 835 block_input ();
835 fwrite (conversion_buffer, 1, coding->produced, tty->output); 836 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
836 if (ferror (tty->output)) 837 clearerr_unlocked (tty->output);
837 clearerr (tty->output);
838 if (tty->termscript) 838 if (tty->termscript)
839 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 839 fwrite_unlocked (conversion_buffer, 1, coding->produced,
840 tty->termscript);
840 unblock_input (); 841 unblock_input ();
841 } 842 }
842 843
@@ -918,11 +919,11 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
918 if (coding->produced > 0) 919 if (coding->produced > 0)
919 { 920 {
920 block_input (); 921 block_input ();
921 fwrite (conversion_buffer, 1, coding->produced, tty->output); 922 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
922 if (ferror (tty->output)) 923 clearerr_unlocked (tty->output);
923 clearerr (tty->output);
924 if (tty->termscript) 924 if (tty->termscript)
925 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 925 fwrite_unlocked (conversion_buffer, 1, coding->produced,
926 tty->termscript);
926 unblock_input (); 927 unblock_input ();
927 } 928 }
928 929
@@ -3327,7 +3328,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3327 which calls tty_show_cursor. Re-hide it, so it doesn't show 3328 which calls tty_show_cursor. Re-hide it, so it doesn't show
3328 through the menus. */ 3329 through the menus. */
3329 tty_hide_cursor (tty); 3330 tty_hide_cursor (tty);
3330 fflush (tty->output); 3331 fflush_unlocked (tty->output);
3331 } 3332 }
3332 3333
3333 sf->mouse_moved = 0; 3334 sf->mouse_moved = 0;
@@ -3335,7 +3336,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3335 while (statecount--) 3336 while (statecount--)
3336 free_saved_screen (state[statecount].screen_behind); 3337 free_saved_screen (state[statecount].screen_behind);
3337 tty_show_cursor (tty); /* Turn cursor back on. */ 3338 tty_show_cursor (tty); /* Turn cursor back on. */
3338 fflush (tty->output); 3339 fflush_unlocked (tty->output);
3339 3340
3340/* Clean up any mouse events that are waiting inside Emacs event queue. 3341/* Clean up any mouse events that are waiting inside Emacs event queue.
3341 These events are likely to be generated before the menu was even 3342 These events are likely to be generated before the menu was even
diff --git a/src/termhooks.h b/src/termhooks.h
index 3b1b4959b1d..14ec397346a 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -202,6 +202,9 @@ enum event_kind
202 202
203 FOCUS_OUT_EVENT, 203 FOCUS_OUT_EVENT,
204 204
205 /* Generated when a frame is moved. */
206 MOVE_FRAME_EVENT,
207
205 /* Generated when mouse moves over window not currently selected. */ 208 /* Generated when mouse moves over window not currently selected. */
206 SELECT_WINDOW_EVENT, 209 SELECT_WINDOW_EVENT,
207 210
diff --git a/src/terminal.c b/src/terminal.c
index 0b1cbe7b791..367f2ac7192 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -575,7 +575,10 @@ Lisp_Object
575terminal_glyph_code (struct terminal *t, int ch) 575terminal_glyph_code (struct terminal *t, int ch)
576{ 576{
577#if HAVE_STRUCT_UNIPAIR_UNICODE 577#if HAVE_STRUCT_UNIPAIR_UNICODE
578 if (t->type == output_termcap) 578 /* Heuristically assume that a terminal supporting glyph codes is in
579 UTF-8 mode if and only if its coding system is UTF-8 (Bug#26396). */
580 if (t->type == output_termcap
581 && t->terminal_coding->encoder == encode_coding_utf_8)
579 { 582 {
580 /* As a hack, recompute the table when CH is the maximum 583 /* As a hack, recompute the table when CH is the maximum
581 character. */ 584 character. */
diff --git a/src/thread.c b/src/thread.c
index 9ea7e121a82..e3787971a53 100644
--- a/src/thread.c
+++ b/src/thread.c
@@ -664,7 +664,7 @@ DEFUN ("thread-yield", Fthread_yield, Sthread_yield, 0, 0, 0,
664static Lisp_Object 664static Lisp_Object
665invoke_thread_function (void) 665invoke_thread_function (void)
666{ 666{
667 int count = SPECPDL_INDEX (); 667 ptrdiff_t count = SPECPDL_INDEX ();
668 668
669 Ffuncall (1, &current_thread->function); 669 Ffuncall (1, &current_thread->function);
670 return unbind_to (count, Qnil); 670 return unbind_to (count, Qnil);
diff --git a/src/unexelf.c b/src/unexelf.c
index 7fad64fab17..5129784ade2 100644
--- a/src/unexelf.c
+++ b/src/unexelf.c
@@ -576,7 +576,17 @@ unexec (const char *new_name, const char *old_name)
576 } 576 }
577 577
578 /* This loop seeks out relocation sections for the data section, so 578 /* This loop seeks out relocation sections for the data section, so
579 that it can undo relocations performed by the runtime loader. */ 579 that it can undo relocations performed by the runtime loader.
580
581 The following approach does not work on x86 platforms that use
582 the GNU Gold linker, which can generate .rel.dyn relocation
583 sections containing R_386_32 entries that the following code does
584 not grok. Emacs works around this problem by avoiding C
585 constructs that generate such entries, which is horrible hack.
586
587 FIXME: Presumably more problems like this will crop up as linkers
588 get fancier. We really need to stop assuming that Emacs can grok
589 arbitrary linker output. See Bug#27248. */
580 for (n = new_file_h->e_shnum; 0 < --n; ) 590 for (n = new_file_h->e_shnum; 0 < --n; )
581 { 591 {
582 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n); 592 ElfW (Shdr) *rel_shdr = &NEW_SECTION_H (n);
diff --git a/src/unexmacosx.c b/src/unexmacosx.c
index 97dcb435d37..3b1efa3ca30 100644
--- a/src/unexmacosx.c
+++ b/src/unexmacosx.c
@@ -346,31 +346,6 @@ print_region_list (void)
346 print_region (r->address, r->size, r->protection, r->max_protection); 346 print_region (r->address, r->size, r->protection, r->max_protection);
347} 347}
348 348
349static void
350print_regions (void)
351{
352 task_t target_task = mach_task_self ();
353 vm_address_t address = (vm_address_t) 0;
354 vm_size_t size;
355 struct vm_region_basic_info info;
356 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
357 mach_port_t object_name;
358
359 printf (" address size prot maxp\n");
360
361 while (vm_region (target_task, &address, &size, VM_REGION_BASIC_INFO,
362 (vm_region_info_t) &info, &info_count, &object_name)
363 == KERN_SUCCESS && info_count == VM_REGION_BASIC_INFO_COUNT)
364 {
365 print_region (address, size, info.protection, info.max_protection);
366
367 if (object_name != MACH_PORT_NULL)
368 mach_port_deallocate (target_task, object_name);
369
370 address += size;
371 }
372}
373
374/* Build the list of regions that need to be dumped. Regions with 349/* Build the list of regions that need to be dumped. Regions with
375 addresses above VM_DATA_TOP are omitted. Adjacent regions with 350 addresses above VM_DATA_TOP are omitted. Adjacent regions with
376 identical protection are merged. Note that non-writable regions 351 identical protection are merged. Note that non-writable regions
diff --git a/src/w32.c b/src/w32.c
index f35ad67d829..fa3cbe183fb 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2978,31 +2978,6 @@ emacs_root_dir (void)
2978 return root_dir; 2978 return root_dir;
2979} 2979}
2980 2980
2981#include <sys/timeb.h>
2982
2983/* Emulate gettimeofday (Ulrich Leodolter, 1/11/95). */
2984int
2985gettimeofday (struct timeval *__restrict tv, struct timezone *__restrict tz)
2986{
2987 struct _timeb tb;
2988 _ftime (&tb);
2989
2990 tv->tv_sec = tb.time;
2991 tv->tv_usec = tb.millitm * 1000L;
2992 /* Implementation note: _ftime sometimes doesn't update the dstflag
2993 according to the new timezone when the system timezone is
2994 changed. We could fix that by using GetSystemTime and
2995 GetTimeZoneInformation, but that doesn't seem necessary, since
2996 Emacs always calls gettimeofday with the 2nd argument NULL (see
2997 current_emacs_time). */
2998 if (tz)
2999 {
3000 tz->tz_minuteswest = tb.timezone; /* minutes west of Greenwich */
3001 tz->tz_dsttime = tb.dstflag; /* type of dst correction */
3002 }
3003 return 0;
3004}
3005
3006/* Emulate fdutimens. */ 2981/* Emulate fdutimens. */
3007 2982
3008/* Set the access and modification time stamps of FD (a.k.a. FILE) to be 2983/* Set the access and modification time stamps of FD (a.k.a. FILE) to be
diff --git a/src/w32fns.c b/src/w32fns.c
index dd16d74439f..b0842b5ee6c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -256,6 +256,10 @@ static unsigned int sound_type = 0xFFFFFFFF;
256# define WTS_SESSION_LOCK 0x7 256# define WTS_SESSION_LOCK 0x7
257#endif 257#endif
258 258
259#ifndef WS_EX_NOACTIVATE
260#define WS_EX_NOACTIVATE 0x08000000L
261#endif
262
259/* Keyboard hook state data. */ 263/* Keyboard hook state data. */
260static struct 264static struct
261{ 265{
@@ -367,17 +371,20 @@ void x_set_title (struct frame *, Lisp_Object, Lisp_Object);
367void 371void
368x_real_positions (struct frame *f, int *xptr, int *yptr) 372x_real_positions (struct frame *f, int *xptr, int *yptr)
369{ 373{
370 POINT pt;
371 RECT rect; 374 RECT rect;
372 375
373 /* Get the bounds of the WM window. */ 376 /* Get the bounds of the WM window. */
374 GetWindowRect (FRAME_W32_WINDOW (f), &rect); 377 GetWindowRect (FRAME_W32_WINDOW (f), &rect);
375 378
376 pt.x = 0; 379 if (FRAME_PARENT_FRAME (f))
377 pt.y = 0; 380 {
381 /* For a child window we have to get its coordinates wrt its
382 parent. */
383 HWND parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
378 384
379 /* Convert (0, 0) in the client area to screen co-ordinates. */ 385 if (parent_hwnd)
380 ClientToScreen (FRAME_W32_WINDOW (f), &pt); 386 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
387 }
381 388
382 *xptr = rect.left; 389 *xptr = rect.left;
383 *yptr = rect.top; 390 *yptr = rect.top;
@@ -1627,7 +1634,13 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1627#endif 1634#endif
1628} 1635}
1629 1636
1630static void 1637/**
1638 * x_clear_under_internal_border:
1639 *
1640 * Clear area of frame F's internal border. If the internal border face
1641 * of F has been specified (is not null), fill the area with that face.
1642 */
1643void
1631x_clear_under_internal_border (struct frame *f) 1644x_clear_under_internal_border (struct frame *f)
1632{ 1645{
1633 int border = FRAME_INTERNAL_BORDER_WIDTH (f); 1646 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
@@ -1638,18 +1651,38 @@ x_clear_under_internal_border (struct frame *f)
1638 HDC hdc = get_frame_dc (f); 1651 HDC hdc = get_frame_dc (f);
1639 int width = FRAME_PIXEL_WIDTH (f); 1652 int width = FRAME_PIXEL_WIDTH (f);
1640 int height = FRAME_PIXEL_HEIGHT (f); 1653 int height = FRAME_PIXEL_HEIGHT (f);
1654 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
1641 1655
1642 block_input (); 1656 block_input ();
1643 w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border); 1657 if (face)
1644 w32_clear_area (f, hdc, 0, 0, border, height); 1658 {
1645 w32_clear_area (f, hdc, width - border, 0, border, height); 1659 /* Fill border with internal border face. */
1646 w32_clear_area (f, hdc, 0, height - border, width, border); 1660 unsigned long color = face->background;
1661
1662 w32_fill_area (f, hdc, color, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
1663 w32_fill_area (f, hdc, color, 0, 0, border, height);
1664 w32_fill_area (f, hdc, color, width - border, 0, border, height);
1665 w32_fill_area (f, hdc, color, 0, height - border, width, border);
1666 }
1667 else
1668 {
1669 w32_clear_area (f, hdc, 0, FRAME_TOP_MARGIN_HEIGHT (f), width, border);
1670 w32_clear_area (f, hdc, 0, 0, border, height);
1671 w32_clear_area (f, hdc, width - border, 0, border, height);
1672 w32_clear_area (f, hdc, 0, height - border, width, border);
1673 }
1647 release_frame_dc (f, hdc); 1674 release_frame_dc (f, hdc);
1648 unblock_input (); 1675 unblock_input ();
1649 } 1676 }
1650} 1677}
1651 1678
1652 1679
1680/**
1681 * x_set_internal_border_width:
1682 *
1683 * Set width of frame F's internal border to ARG pixels. ARG < 0 is
1684 * treated like ARG = 0.
1685 */
1653void 1686void
1654x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) 1687x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1655{ 1688{
@@ -1673,44 +1706,59 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
1673} 1706}
1674 1707
1675 1708
1709/**
1710 * x_set_menu_bar_lines:
1711 *
1712 * Set number of lines of frame F's menu bar to VALUE. An integer
1713 * greater zero specifies 1 line and turns the menu bar on if it was off
1714 * before. Any other value specifies 0 lines and turns the menu bar off
1715 * if it was on before.
1716 */
1676void 1717void
1677x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) 1718x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1678{ 1719{
1679 int nlines;
1680
1681 /* Right now, menu bars don't work properly in minibuf-only frames; 1720 /* Right now, menu bars don't work properly in minibuf-only frames;
1682 most of the commands try to apply themselves to the minibuffer 1721 most of the commands try to apply themselves to the minibuffer
1683 frame itself, and get an error because you can't switch buffers 1722 frame itself, and get an error because you can't switch buffers in
1684 in or split the minibuffer window. */ 1723 or split the minibuffer window. Child frames don't like menu bars
1685 if (FRAME_MINIBUF_ONLY_P (f)) 1724 either. */
1686 return; 1725 if (!FRAME_MINIBUF_ONLY_P (f) && !FRAME_PARENT_FRAME (f))
1726 {
1727 boolean old = FRAME_EXTERNAL_MENU_BAR (f);
1728 boolean new = (INTEGERP (value) && XINT (value) > 0) ? true : false;
1687 1729
1688 if (INTEGERP (value)) 1730 FRAME_MENU_BAR_LINES (f) = 0;
1689 nlines = XINT (value); 1731 FRAME_MENU_BAR_HEIGHT (f) = 0;
1690 else
1691 nlines = 0;
1692 1732
1693 FRAME_MENU_BAR_LINES (f) = 0; 1733 if (old != new)
1694 FRAME_MENU_BAR_HEIGHT (f) = 0; 1734 {
1695 if (nlines) 1735 FRAME_EXTERNAL_MENU_BAR (f) = new;
1696 FRAME_EXTERNAL_MENU_BAR (f) = 1;
1697 else
1698 {
1699 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
1700 free_frame_menubar (f);
1701 FRAME_EXTERNAL_MENU_BAR (f) = 0;
1702 1736
1703 /* Adjust the frame size so that the client (text) dimensions 1737 if (!old)
1704 remain the same. This depends on FRAME_EXTERNAL_MENU_BAR being 1738 /* Make menu bar when there was none. Emacs 25 waited until
1705 set correctly. Note that we resize twice: The first time upon 1739 the next redisplay for this to take effect. */
1706 a request from the window manager who wants to keep the height 1740 set_frame_menubar (f, false, true);
1707 of the outer rectangle (including decorations) unchanged, and a 1741 else
1708 second time because we want to keep the height of the inner 1742 {
1709 rectangle (without the decorations unchanged). */ 1743 /* Remove menu bar. */
1710 adjust_frame_size (f, -1, -1, 2, true, Qmenu_bar_lines); 1744 free_frame_menubar (f);
1745
1746 /* Adjust the frame size so that the client (text) dimensions
1747 remain the same. Note that we resize twice: The first time
1748 upon a request from the window manager who wants to keep
1749 the height of the outer rectangle (including decorations)
1750 unchanged, and a second time because we want to keep the
1751 height of the inner rectangle (without the decorations
1752 unchanged). */
1753 adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
1754 }
1711 1755
1712 /* Not sure whether this is needed. */ 1756 if (FRAME_W32_WINDOW (f))
1713 x_clear_under_internal_border (f); 1757 x_clear_under_internal_border (f);
1758
1759 /* Don't store anything but 1 or 0 in the parameter. */
1760 store_frame_param (f, Qmenu_bar_lines, make_number (new ? 1 : 0));
1761 }
1714 } 1762 }
1715} 1763}
1716 1764
@@ -1793,7 +1841,7 @@ x_change_tool_bar_height (struct frame *f, int height)
1793 here. */ 1841 here. */
1794 adjust_frame_glyphs (f); 1842 adjust_frame_glyphs (f);
1795 SET_FRAME_GARBAGED (f); 1843 SET_FRAME_GARBAGED (f);
1796 if (FRAME_X_WINDOW (f)) 1844 if (FRAME_W32_WINDOW (f))
1797 x_clear_under_internal_border (f); 1845 x_clear_under_internal_border (f);
1798} 1846}
1799 1847
@@ -1955,6 +2003,233 @@ x_set_scroll_bar_default_height (struct frame *f)
1955 FRAME_CONFIG_SCROLL_BAR_LINES (f) 2003 FRAME_CONFIG_SCROLL_BAR_LINES (f)
1956 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit; 2004 = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) + unit - 1) / unit;
1957} 2005}
2006
2007/**
2008 * x_set_undecorated:
2009 *
2010 * Set frame F's `undecorated' parameter. If non-nil, F's window-system
2011 * window is drawn without decorations, title, minimize/maximize boxes
2012 * and external borders. This usually means that the window cannot be
2013 * dragged, resized, iconified, maximized or deleted with the mouse. If
2014 * nil, draw the frame with all the elements listed above unless these
2015 * have been suspended via window manager settings.
2016 *
2017 * Some window managers may not honor this parameter.
2018 */
2019static void
2020x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2021{
2022 HWND hwnd = FRAME_W32_WINDOW (f);
2023 DWORD dwStyle = GetWindowLong (hwnd, GWL_STYLE);
2024 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
2025
2026 block_input ();
2027 if (!NILP (new_value) && !FRAME_UNDECORATED (f))
2028 {
2029 dwStyle = ((dwStyle & ~WS_THICKFRAME & ~WS_CAPTION)
2030 | ((NUMBERP (border_width) && (XINT (border_width) > 0))
2031 ? WS_BORDER : false));
2032 SetWindowLong (hwnd, GWL_STYLE, dwStyle);
2033 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
2034 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
2035 | SWP_FRAMECHANGED);
2036 FRAME_UNDECORATED (f) = true;
2037 }
2038 else if (NILP (new_value) && FRAME_UNDECORATED (f))
2039 {
2040 SetWindowLong (hwnd, GWL_STYLE, dwStyle | WS_THICKFRAME | WS_CAPTION
2041 | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_SYSMENU);
2042 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0,
2043 SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE
2044 | SWP_FRAMECHANGED);
2045 FRAME_UNDECORATED (f) = false;
2046 }
2047 unblock_input ();
2048}
2049
2050/**
2051 * x_set_parent_frame:
2052 *
2053 * Set frame F's `parent-frame' parameter. If non-nil, make F a child
2054 * frame of the frame specified by that parameter. Technically, this
2055 * makes F's window-system window a child window of the parent frame's
2056 * window-system window. If nil, make F's window-system window a
2057 * top-level window--a child of its display's root window.
2058 *
2059 * A child frame is clipped at the native edges of its parent frame.
2060 * Its `left' and `top' parameters specify positions relative to the
2061 * top-left corner of its parent frame's native rectangle. Usually,
2062 * moving a parent frame moves all its child frames too, keeping their
2063 * position relative to the parent unaltered. When a parent frame is
2064 * iconified or made invisible, its child frames are made invisible.
2065 * When a parent frame is deleted, its child frames are deleted too.
2066 *
2067 * A visible child frame always appears on top of its parent frame thus
2068 * obscuring parts of it. When a frame has more than one child frame,
2069 * their stacking order is specified just as that of non-child frames
2070 * relative to their display.
2071 *
2072 * Whether a child frame has a menu or tool bar may be window-system or
2073 * window manager dependent. It's advisable to disable both via the
2074 * frame parameter settings.
2075 *
2076 * Some window managers may not honor this parameter.
2077 */
2078static void
2079x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2080{
2081 struct frame *p = NULL;
2082
2083 if (!NILP (new_value)
2084 && (!FRAMEP (new_value)
2085 || !FRAME_LIVE_P (p = XFRAME (new_value))
2086 || !FRAME_W32_P (p)))
2087 {
2088 store_frame_param (f, Qparent_frame, old_value);
2089 error ("Invalid specification of `parent-frame'");
2090 }
2091
2092 if (p != FRAME_PARENT_FRAME (f))
2093 {
2094 HWND hwnd = FRAME_W32_WINDOW (f);
2095 HWND hwnd_parent = p ? FRAME_W32_WINDOW (p) : NULL;
2096 HWND hwnd_value;
2097
2098 block_input ();
2099 hwnd_value = SetParent (hwnd, hwnd_parent);
2100 unblock_input ();
2101
2102 if (hwnd_value)
2103 fset_parent_frame (f, new_value);
2104 else
2105 {
2106 store_frame_param (f, Qparent_frame, old_value);
2107 error ("Reparenting frame failed");
2108 }
2109 }
2110}
2111
2112/**
2113 * x_set_skip_taskbar:
2114 *
2115 * Set frame F's `skip-taskbar' parameter. If non-nil, this should
2116 * remove F's icon from the taskbar associated with the display of F's
2117 * window-system window and inhibit switching to F's window via
2118 * <Alt>-<TAB>. On Windows iconifying F will "roll in" its window at
2119 * the bottom of the desktop. If nil, lift these restrictions.
2120 *
2121 * Some window managers may not honor this parameter.
2122 */
2123static void
2124x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2125{
2126 if (!EQ (new_value, old_value))
2127 {
2128 HWND hwnd = FRAME_W32_WINDOW (f);
2129 DWORD exStyle = GetWindowLong (hwnd, GWL_EXSTYLE);
2130
2131 block_input ();
2132 /* Temporarily hide the window while changing its WS_EX_NOACTIVATE
2133 setting. */
2134 ShowWindow (hwnd, SW_HIDE);
2135 if (!NILP (new_value))
2136 SetWindowLong (hwnd, GWL_EXSTYLE, exStyle | WS_EX_NOACTIVATE);
2137 else
2138 SetWindowLong (hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_NOACTIVATE);
2139 ShowWindow (hwnd, SW_SHOWNOACTIVATE);
2140 unblock_input ();
2141
2142 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
2143 }
2144}
2145
2146/**
2147 * x_set_no_focus_on_map:
2148 *
2149 * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
2150 * that F's window-system window does not want to receive input focus
2151 * when it is mapped. (A frame's window is mapped when the frame is
2152 * displayed for the first time and when the frame changes its state
2153 * from `iconified' or `invisible' to `visible'.)
2154 *
2155 * Some window managers may not honor this parameter.
2156 */
2157static void
2158x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2159{
2160 if (!EQ (new_value, old_value))
2161 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
2162}
2163
2164/**
2165 * x_set_no_accept_focus:
2166 *
2167 * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
2168 * that F's window-system window does not want to receive input focus
2169 * via mouse clicks or by moving the mouse into it.
2170 *
2171 * If non-nil, this may have the unwanted side-effect that a user cannot
2172 * scroll a non-selected frame with the mouse.
2173 *
2174 * Some window managers may not honor this parameter.
2175 */
2176static void
2177x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2178{
2179 if (!EQ (new_value, old_value))
2180 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
2181}
2182
2183/**
2184 * x_set_z_group:
2185 *
2186 * Set frame F's `z-group' parameter. If `above', F's window-system
2187 * window is displayed above all windows that do not have the `above'
2188 * property set. If nil, F's window is shown below all windows that
2189 * have the `above' property set and above all windows that have the
2190 * `below' property set. If `below', F's window is displayed below all
2191 * windows that do not have the `below' property set.
2192 *
2193 * Some window managers may not honor this parameter. The value `below'
2194 * is not supported on Windows.
2195 */
2196static void
2197x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
2198{
2199 HWND hwnd = FRAME_W32_WINDOW (f);
2200
2201 if (NILP (new_value))
2202 {
2203 block_input ();
2204 SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
2205 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2206 | SWP_NOOWNERZORDER);
2207 unblock_input ();
2208 FRAME_Z_GROUP (f) = z_group_none;
2209 }
2210 else if (EQ (new_value, Qabove))
2211 {
2212 block_input ();
2213 SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0,
2214 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2215 | SWP_NOOWNERZORDER);
2216 unblock_input ();
2217 FRAME_Z_GROUP (f) = z_group_above;
2218 }
2219 else if (EQ (new_value, Qabove_suspended))
2220 {
2221 block_input ();
2222 SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
2223 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE
2224 | SWP_NOOWNERZORDER);
2225 unblock_input ();
2226 FRAME_Z_GROUP (f) = z_group_above_suspended;
2227 }
2228 else if (EQ (new_value, Qbelow))
2229 error ("Value `below' for z-group is not supported on Windows");
2230 else
2231 error ("Invalid z-group specification");
2232}
1958 2233
1959/* Subroutines for creating a frame. */ 2234/* Subroutines for creating a frame. */
1960 2235
@@ -2013,7 +2288,12 @@ w32_init_class (HINSTANCE hinst)
2013static HWND 2288static HWND
2014w32_createvscrollbar (struct frame *f, struct scroll_bar * bar) 2289w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
2015{ 2290{
2016 return CreateWindow ("SCROLLBAR", "", SBS_VERT | WS_CHILD | WS_VISIBLE, 2291 return CreateWindow ("SCROLLBAR", "",
2292 /* Clip siblings so we don't draw over child
2293 frames. Apparently this is not always
2294 sufficient so we also try to make bar windows
2295 bottommost. */
2296 SBS_VERT | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
2017 /* Position and size of scroll bar. */ 2297 /* Position and size of scroll bar. */
2018 bar->left, bar->top, bar->width, bar->height, 2298 bar->left, bar->top, bar->width, bar->height,
2019 FRAME_W32_WINDOW (f), NULL, hinst, NULL); 2299 FRAME_W32_WINDOW (f), NULL, hinst, NULL);
@@ -2022,7 +2302,12 @@ w32_createvscrollbar (struct frame *f, struct scroll_bar * bar)
2022static HWND 2302static HWND
2023w32_createhscrollbar (struct frame *f, struct scroll_bar * bar) 2303w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
2024{ 2304{
2025 return CreateWindow ("SCROLLBAR", "", SBS_HORZ | WS_CHILD | WS_VISIBLE, 2305 return CreateWindow ("SCROLLBAR", "",
2306 /* Clip siblings so we don't draw over child
2307 frames. Apparently this is not always
2308 sufficient so we also try to make bar windows
2309 bottommost. */
2310 SBS_HORZ | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
2026 /* Position and size of scroll bar. */ 2311 /* Position and size of scroll bar. */
2027 bar->left, bar->top, bar->width, bar->height, 2312 bar->left, bar->top, bar->width, bar->height,
2028 FRAME_W32_WINDOW (f), NULL, hinst, NULL); 2313 FRAME_W32_WINDOW (f), NULL, hinst, NULL);
@@ -2031,20 +2316,52 @@ w32_createhscrollbar (struct frame *f, struct scroll_bar * bar)
2031static void 2316static void
2032w32_createwindow (struct frame *f, int *coords) 2317w32_createwindow (struct frame *f, int *coords)
2033{ 2318{
2034 HWND hwnd; 2319 HWND hwnd = NULL, parent_hwnd = NULL;
2035 RECT rect; 2320 RECT rect;
2036 int top; 2321 int top, left;
2037 int left; 2322 Lisp_Object border_width = Fcdr (Fassq (Qborder_width, f->param_alist));
2323
2324 if (FRAME_PARENT_FRAME (f) && FRAME_W32_P (FRAME_PARENT_FRAME (f)))
2325 {
2326 parent_hwnd = FRAME_W32_WINDOW (FRAME_PARENT_FRAME (f));
2327 f->output_data.w32->dwStyle = WS_CHILD | WS_CLIPSIBLINGS;
2328
2329 if (FRAME_UNDECORATED (f))
2330 {
2331 /* If we want a thin border, specify it here. */
2332 if (NUMBERP (border_width) && (XINT (border_width) > 0))
2333 f->output_data.w32->dwStyle |= WS_BORDER;
2334 }
2335 else
2336 /* To decorate a child frame, list all needed elements. */
2337 f->output_data.w32->dwStyle |= (WS_THICKFRAME | WS_CAPTION
2338 | WS_MAXIMIZEBOX | WS_MINIMIZEBOX
2339 | WS_SYSMENU);
2340 }
2341 else if (FRAME_UNDECORATED (f))
2342 {
2343 /* All attempts to start with ~WS_OVERLAPPEDWINDOW or overlapped
2344 with all other style elements negated failed here. */
2345 f->output_data.w32->dwStyle = WS_POPUP;
2346
2347 /* If we want a thin border, specify it here. */
2348 if (NUMBERP (border_width) && (XINT (border_width) > 0))
2349 f->output_data.w32->dwStyle |= WS_BORDER;
2350 }
2351 else
2352 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
2353
2354 /* Always clip children. */
2355 f->output_data.w32->dwStyle |= WS_CLIPCHILDREN;
2038 2356
2039 rect.left = rect.top = 0; 2357 rect.left = rect.top = 0;
2040 rect.right = FRAME_PIXEL_WIDTH (f); 2358 rect.right = FRAME_PIXEL_WIDTH (f);
2041 rect.bottom = FRAME_PIXEL_HEIGHT (f); 2359 rect.bottom = FRAME_PIXEL_HEIGHT (f);
2042 2360
2043 AdjustWindowRect (&rect, f->output_data.w32->dwStyle, 2361 AdjustWindowRect (&rect, f->output_data.w32->dwStyle,
2044 FRAME_EXTERNAL_MENU_BAR (f)); 2362 FRAME_EXTERNAL_MENU_BAR (f) && !parent_hwnd);
2045 2363
2046 /* Do first time app init */ 2364 /* Do first time app init */
2047
2048 w32_init_class (hinst); 2365 w32_init_class (hinst);
2049 2366
2050 if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition) 2367 if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition)
@@ -2059,18 +2376,16 @@ w32_createwindow (struct frame *f, int *coords)
2059 } 2376 }
2060 2377
2061 FRAME_W32_WINDOW (f) = hwnd 2378 FRAME_W32_WINDOW (f) = hwnd
2062 = CreateWindow (EMACS_CLASS, 2379 = CreateWindow (EMACS_CLASS, f->namebuf, f->output_data.w32->dwStyle,
2063 f->namebuf, 2380 left, top, rect.right - rect.left, rect.bottom - rect.top,
2064 f->output_data.w32->dwStyle | WS_CLIPCHILDREN, 2381 parent_hwnd, NULL, hinst, NULL);
2065 left, top,
2066 rect.right - rect.left, rect.bottom - rect.top,
2067 NULL,
2068 NULL,
2069 hinst,
2070 NULL);
2071 2382
2072 if (hwnd) 2383 if (hwnd)
2073 { 2384 {
2385 if (FRAME_SKIP_TASKBAR (f))
2386 SetWindowLong (hwnd, GWL_EXSTYLE,
2387 GetWindowLong (hwnd, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
2388
2074 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f)); 2389 SetWindowLong (hwnd, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
2075 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f)); 2390 SetWindowLong (hwnd, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
2076 SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f)); 2391 SetWindowLong (hwnd, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
@@ -2086,6 +2401,12 @@ w32_createwindow (struct frame *f, int *coords)
2086 2401
2087 /* Update frame positions. */ 2402 /* Update frame positions. */
2088 GetWindowRect (hwnd, &rect); 2403 GetWindowRect (hwnd, &rect);
2404
2405 if (parent_hwnd)
2406 /* For a child window we have to get its coordinates wrt its
2407 parent. */
2408 MapWindowPoints (HWND_DESKTOP, parent_hwnd, (LPPOINT) &rect, 2);
2409
2089 f->left_pos = rect.left; 2410 f->left_pos = rect.left;
2090 f->top_pos = rect.top; 2411 f->top_pos = rect.top;
2091 } 2412 }
@@ -4381,6 +4702,22 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4381 } 4702 }
4382 } 4703 }
4383 4704
4705 if (f && (msg == WM_LBUTTONDOWN || msg == WM_RBUTTONDOWN
4706 || msg == WM_MBUTTONDOWN ||msg == WM_XBUTTONDOWN)
4707 && !FRAME_NO_ACCEPT_FOCUS (f))
4708 /* When clicking into a child frame or when clicking into a
4709 parent frame with the child frame selected and
4710 `no-accept-focus' is not set, select the clicked frame. */
4711 {
4712 struct frame *p = FRAME_PARENT_FRAME (XFRAME (selected_frame));
4713
4714 if (FRAME_PARENT_FRAME (f) || f == p)
4715 {
4716 SetFocus (hwnd);
4717 SetWindowPos (hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
4718 }
4719 }
4720
4384 wmsg.dwModifiers = w32_get_modifiers (); 4721 wmsg.dwModifiers = w32_get_modifiers ();
4385 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4722 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
4386 signal_user_input (); 4723 signal_user_input ();
@@ -4486,6 +4823,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4486 if (w32_pass_multimedia_buttons_to_system) 4823 if (w32_pass_multimedia_buttons_to_system)
4487 goto dflt; 4824 goto dflt;
4488 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */ 4825 /* Otherwise, pass to lisp, the same way we do with mousehwheel. */
4826
4827 /* FIXME!!! This is never reached so what's the purpose? If the
4828 non-zero return remark below is right we're doing it wrong all
4829 the time. */
4489 case WM_MOUSEHWHEEL: 4830 case WM_MOUSEHWHEEL:
4490 wmsg.dwModifiers = w32_get_modifiers (); 4831 wmsg.dwModifiers = w32_get_modifiers ();
4491 my_post_msg (&wmsg, hwnd, msg, wParam, lParam); 4832 my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
@@ -4712,19 +5053,34 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4712 } 5053 }
4713 return 0; 5054 return 0;
4714 5055
4715#if 0 5056 case WM_MOUSEACTIVATE:
5057 /* WM_MOUSEACTIVATE is the only way on Windows to implement the
5058 `no-accept-focus' frame parameter. This means that one can't
5059 use the mouse to scroll a window on a non-selected frame. */
5060
4716 /* Still not right - can't distinguish between clicks in the 5061 /* Still not right - can't distinguish between clicks in the
4717 client area of the frame from clicks forwarded from the scroll 5062 client area of the frame from clicks forwarded from the scroll
4718 bars - may have to hook WM_NCHITTEST to remember the mouse 5063 bars - may have to hook WM_NCHITTEST to remember the mouse
4719 position and then check if it is in the client area ourselves. */ 5064 position and then check if it is in the client area
4720 case WM_MOUSEACTIVATE: 5065 ourselves. */
5066
4721 /* Discard the mouse click that activates a frame, allowing the 5067 /* Discard the mouse click that activates a frame, allowing the
4722 user to click anywhere without changing point (or worse!). 5068 user to click anywhere without changing point (or worse!).
4723 Don't eat mouse clicks on scrollbars though!! */ 5069 Don't eat mouse clicks on scrollbars though!! */
4724 if (LOWORD (lParam) == HTCLIENT ) 5070
4725 return MA_ACTIVATEANDEAT; 5071 if ((f = x_window_to_frame (dpyinfo, hwnd))
5072 && FRAME_NO_ACCEPT_FOCUS (f)
5073 /* Ignore child frames, they don't accept focus anyway. */
5074 && !FRAME_PARENT_FRAME (f))
5075 {
5076 Lisp_Object frame;
5077
5078 XSETFRAME (frame, f);
5079 if (!EQ (selected_frame, frame))
5080 /* Don't discard the message, GTK doesn't either. */
5081 return MA_NOACTIVATE; /* ANDEAT; */
5082 }
4726 goto dflt; 5083 goto dflt;
4727#endif
4728 5084
4729 case WM_MOUSELEAVE: 5085 case WM_MOUSELEAVE:
4730 /* No longer tracking mouse. */ 5086 /* No longer tracking mouse. */
@@ -4903,6 +5259,10 @@ w32_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
4903 AttachThreadInput (GetCurrentThreadId (), 5259 AttachThreadInput (GetCurrentThreadId (),
4904 foreground_thread, FALSE); 5260 foreground_thread, FALSE);
4905 5261
5262 /* SetFocus to give/remove focus to/from a child window. */
5263 if (msg == WM_EMACS_SETFOREGROUND)
5264 SetFocus ((HWND) wParam);
5265
4906 return retval; 5266 return retval;
4907 } 5267 }
4908 5268
@@ -5134,7 +5494,8 @@ w32_window (struct frame *f, long window_prompting, bool minibuffer_only)
5134 5494
5135 unblock_input (); 5495 unblock_input ();
5136 5496
5137 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 5497 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)
5498 && !FRAME_PARENT_FRAME (f))
5138 initialize_frame_menubar (f); 5499 initialize_frame_menubar (f);
5139 5500
5140 if (FRAME_W32_WINDOW (f) == 0) 5501 if (FRAME_W32_WINDOW (f) == 0)
@@ -5322,7 +5683,7 @@ This function is an internal primitive--use `make-frame' instead. */)
5322 ptrdiff_t count = SPECPDL_INDEX (); 5683 ptrdiff_t count = SPECPDL_INDEX ();
5323 Lisp_Object display; 5684 Lisp_Object display;
5324 struct w32_display_info *dpyinfo = NULL; 5685 struct w32_display_info *dpyinfo = NULL;
5325 Lisp_Object parent; 5686 Lisp_Object parent, parent_frame;
5326 struct kboard *kb; 5687 struct kboard *kb;
5327 int x_width = 0, x_height = 0; 5688 int x_width = 0, x_height = 0;
5328 5689
@@ -5359,10 +5720,11 @@ This function is an internal primitive--use `make-frame' instead. */)
5359 Vx_resource_name = name; 5720 Vx_resource_name = name;
5360 5721
5361 /* See if parent window is specified. */ 5722 /* See if parent window is specified. */
5362 parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL, RES_TYPE_NUMBER); 5723 parent = x_get_arg (dpyinfo, parameters, Qparent_id, NULL, NULL,
5724 RES_TYPE_NUMBER);
5363 if (EQ (parent, Qunbound)) 5725 if (EQ (parent, Qunbound))
5364 parent = Qnil; 5726 parent = Qnil;
5365 if (! NILP (parent)) 5727 else if (!NILP (parent))
5366 CHECK_NUMBER (parent); 5728 CHECK_NUMBER (parent);
5367 5729
5368 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */ 5730 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
@@ -5385,6 +5747,31 @@ This function is an internal primitive--use `make-frame' instead. */)
5385 5747
5386 XSETFRAME (frame, f); 5748 XSETFRAME (frame, f);
5387 5749
5750 parent_frame = x_get_arg (dpyinfo, parameters, Qparent_frame, NULL, NULL,
5751 RES_TYPE_SYMBOL);
5752 /* Apply `parent-frame' parameter only when no `parent-id' was
5753 specified. */
5754 if (!NILP (parent_frame)
5755 && (!NILP (parent)
5756 || !FRAMEP (parent_frame)
5757 || !FRAME_LIVE_P (XFRAME (parent_frame))
5758 || !FRAME_W32_P (XFRAME (parent_frame))))
5759 parent_frame = Qnil;
5760
5761 fset_parent_frame (f, parent_frame);
5762 store_frame_param (f, Qparent_frame, parent_frame);
5763
5764 tem = x_get_arg (dpyinfo, parameters, Qundecorated, NULL, NULL,
5765 RES_TYPE_BOOLEAN);
5766 FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
5767 store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
5768
5769 tem = x_get_arg (dpyinfo, parameters, Qskip_taskbar, NULL, NULL,
5770 RES_TYPE_BOOLEAN);
5771 FRAME_SKIP_TASKBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
5772 store_frame_param (f, Qskip_taskbar,
5773 (NILP (tem) || EQ (tem, Qunbound)) ? Qnil : Qt);
5774
5388 /* By default, make scrollbars the system standard width and height. */ 5775 /* By default, make scrollbars the system standard width and height. */
5389 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL); 5776 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = GetSystemMetrics (SM_CXVSCROLL);
5390 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL); 5777 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = GetSystemMetrics (SM_CXHSCROLL);
@@ -5412,7 +5799,9 @@ This function is an internal primitive--use `make-frame' instead. */)
5412 dpyinfo_refcount = dpyinfo->reference_count; 5799 dpyinfo_refcount = dpyinfo->reference_count;
5413#endif /* GLYPH_DEBUG */ 5800#endif /* GLYPH_DEBUG */
5414 5801
5415 /* Specify the parent under which to make this window. */ 5802 /* Specify the parent under which to make this window - this seems to
5803 have no effect on Windows because parent_desc is explicitly reset
5804 below. */
5416 if (!NILP (parent)) 5805 if (!NILP (parent))
5417 { 5806 {
5418 /* Cast to UINT_PTR shuts up compiler warnings about cast to 5807 /* Cast to UINT_PTR shuts up compiler warnings about cast to
@@ -5496,23 +5885,44 @@ This function is an internal primitive--use `make-frame' instead. */)
5496 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 5885 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
5497 x_default_parameter (f, parameters, Qright_fringe, Qnil, 5886 x_default_parameter (f, parameters, Qright_fringe, Qnil,
5498 "rightFringe", "RightFringe", RES_TYPE_NUMBER); 5887 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
5499 /* Process alpha here (Bug#16619). */ 5888 x_default_parameter (f, parameters, Qno_focus_on_map, Qnil,
5500 x_default_parameter (f, parameters, Qalpha, Qnil, 5889 NULL, NULL, RES_TYPE_BOOLEAN);
5501 "alpha", "Alpha", RES_TYPE_NUMBER); 5890 x_default_parameter (f, parameters, Qno_accept_focus, Qnil,
5891 NULL, NULL, RES_TYPE_BOOLEAN);
5892 x_default_parameter (f, parameters, Qno_special_glyphs, Qnil,
5893 NULL, NULL, RES_TYPE_BOOLEAN);
5894
5895 /* Process alpha here (Bug#16619). On XP this fails with child
5896 frames. For `no-focus-on-map' frames delay processing of alpha
5897 until the frame becomes visible. */
5898 if (!FRAME_NO_FOCUS_ON_MAP (f))
5899 x_default_parameter (f, parameters, Qalpha, Qnil,
5900 "alpha", "Alpha", RES_TYPE_NUMBER);
5502 5901
5503 /* Init faces first since we need the frame's column width/line 5902 /* Init faces first since we need the frame's column width/line
5504 height in various occasions. */ 5903 height in various occasions. */
5505 init_frame_faces (f); 5904 init_frame_faces (f);
5506 5905
5507 /* The following call of change_frame_size is needed since otherwise 5906 /* We have to call adjust_frame_size here since otherwise
5508 x_set_tool_bar_lines will already work with the character sizes 5907 x_set_tool_bar_lines will already work with the character sizes
5509 installed by init_frame_faces while the frame's pixel size is 5908 installed by init_frame_faces while the frame's pixel size is still
5510 still calculated from a character size of 1 and we subsequently 5909 calculated from a character size of 1 and we subsequently hit the
5511 hit the (height >= 0) assertion in window_box_height. 5910 (height >= 0) assertion in window_box_height.
5512 5911
5513 The non-pixelwise code apparently worked around this because it 5912 The non-pixelwise code apparently worked around this because it
5514 had one frame line vs one toolbar line which left us with a zero 5913 had one frame line vs one toolbar line which left us with a zero
5515 root window height which was obviously wrong as well ... */ 5914 root window height which was obviously wrong as well ...
5915
5916 Also process `min-width' and `min-height' parameters right here
5917 because `frame-windows-min-size' needs them. */
5918 tem = x_get_arg (dpyinfo, parameters, Qmin_width, NULL, NULL,
5919 RES_TYPE_NUMBER);
5920 if (NUMBERP (tem))
5921 store_frame_param (f, Qmin_width, tem);
5922 tem = x_get_arg (dpyinfo, parameters, Qmin_height, NULL, NULL,
5923 RES_TYPE_NUMBER);
5924 if (NUMBERP (tem))
5925 store_frame_param (f, Qmin_height, tem);
5516 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 5926 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
5517 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, 5927 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
5518 Qx_create_frame_1); 5928 Qx_create_frame_1);
@@ -5520,10 +5930,17 @@ This function is an internal primitive--use `make-frame' instead. */)
5520 /* The X resources controlling the menu-bar and tool-bar are 5930 /* The X resources controlling the menu-bar and tool-bar are
5521 processed specially at startup, and reflected in the mode 5931 processed specially at startup, and reflected in the mode
5522 variables; ignore them here. */ 5932 variables; ignore them here. */
5523 x_default_parameter (f, parameters, Qmenu_bar_lines, 5933 if (NILP (parent_frame))
5524 NILP (Vmenu_bar_mode) 5934 {
5525 ? make_number (0) : make_number (1), 5935 x_default_parameter (f, parameters, Qmenu_bar_lines,
5526 NULL, NULL, RES_TYPE_NUMBER); 5936 NILP (Vmenu_bar_mode)
5937 ? make_number (0) : make_number (1),
5938 NULL, NULL, RES_TYPE_NUMBER);
5939 }
5940 else
5941 /* No menu bar for child frames. */
5942 store_frame_param (f, Qmenu_bar_lines, make_number (0));
5943
5527 x_default_parameter (f, parameters, Qtool_bar_lines, 5944 x_default_parameter (f, parameters, Qtool_bar_lines,
5528 NILP (Vtool_bar_mode) 5945 NILP (Vtool_bar_mode)
5529 ? make_number (0) : make_number (1), 5946 ? make_number (0) : make_number (1),
@@ -5534,9 +5951,7 @@ This function is an internal primitive--use `make-frame' instead. */)
5534 x_default_parameter (f, parameters, Qtitle, Qnil, 5951 x_default_parameter (f, parameters, Qtitle, Qnil,
5535 "title", "Title", RES_TYPE_STRING); 5952 "title", "Title", RES_TYPE_STRING);
5536 5953
5537 f->output_data.w32->dwStyle = WS_OVERLAPPEDWINDOW;
5538 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; 5954 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
5539
5540 f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM); 5955 f->output_data.w32->text_cursor = w32_load_cursor (IDC_IBEAM);
5541 f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW); 5956 f->output_data.w32->nontext_cursor = w32_load_cursor (IDC_ARROW);
5542 f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW); 5957 f->output_data.w32->modeline_cursor = w32_load_cursor (IDC_ARROW);
@@ -5544,6 +5959,14 @@ This function is an internal primitive--use `make-frame' instead. */)
5544 f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT); 5959 f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
5545 f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE); 5960 f->output_data.w32->horizontal_drag_cursor = w32_load_cursor (IDC_SIZEWE);
5546 f->output_data.w32->vertical_drag_cursor = w32_load_cursor (IDC_SIZENS); 5961 f->output_data.w32->vertical_drag_cursor = w32_load_cursor (IDC_SIZENS);
5962 f->output_data.w32->left_edge_cursor = w32_load_cursor (IDC_SIZEWE);
5963 f->output_data.w32->top_left_corner_cursor = w32_load_cursor (IDC_SIZENWSE);
5964 f->output_data.w32->top_edge_cursor = w32_load_cursor (IDC_SIZENS);
5965 f->output_data.w32->top_right_corner_cursor = w32_load_cursor (IDC_SIZENESW);
5966 f->output_data.w32->right_edge_cursor = w32_load_cursor (IDC_SIZEWE);
5967 f->output_data.w32->bottom_right_corner_cursor = w32_load_cursor (IDC_SIZENWSE);
5968 f->output_data.w32->bottom_edge_cursor = w32_load_cursor (IDC_SIZENS);
5969 f->output_data.w32->bottom_left_corner_cursor = w32_load_cursor (IDC_SIZENESW);
5547 5970
5548 f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor; 5971 f->output_data.w32->current_cursor = f->output_data.w32->nontext_cursor;
5549 5972
@@ -5601,29 +6024,36 @@ This function is an internal primitive--use `make-frame' instead. */)
5601 adjust_frame_size call. */ 6024 adjust_frame_size call. */
5602 x_default_parameter (f, parameters, Qfullscreen, Qnil, 6025 x_default_parameter (f, parameters, Qfullscreen, Qnil,
5603 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL); 6026 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
6027 x_default_parameter (f, parameters, Qz_group, Qnil,
6028 NULL, NULL, RES_TYPE_SYMBOL);
5604 6029
5605 /* Make the window appear on the frame and enable display, unless 6030 /* Make the window appear on the frame and enable display, unless
5606 the caller says not to. However, with explicit parent, Emacs 6031 the caller says not to. However, with explicit parent, Emacs
5607 cannot control visibility, so don't try. */ 6032 cannot control visibility, so don't try. */
5608 if (! f->output_data.w32->explicit_parent) 6033 if (!f->output_data.w32->explicit_parent)
5609 { 6034 {
5610 Lisp_Object visibility; 6035 Lisp_Object visibility
5611 6036 = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5612 visibility = x_get_arg (dpyinfo, parameters, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
5613 if (EQ (visibility, Qunbound))
5614 visibility = Qt;
5615 6037
5616 if (EQ (visibility, Qicon)) 6038 if (EQ (visibility, Qicon))
5617 x_iconify_frame (f); 6039 x_iconify_frame (f);
5618 else if (! NILP (visibility))
5619 x_make_frame_visible (f);
5620 else 6040 else
5621 { 6041 {
5622 /* Must have been Qnil. */ 6042 if (EQ (visibility, Qunbound))
5623 ; 6043 visibility = Qt;
6044
6045 if (!NILP (visibility))
6046 x_make_frame_visible (f);
5624 } 6047 }
6048
6049 store_frame_param (f, Qvisibility, visibility);
5625 } 6050 }
5626 6051
6052 /* For `no-focus-on-map' frames set alpha here. */
6053 if (FRAME_NO_FOCUS_ON_MAP (f))
6054 x_default_parameter (f, parameters, Qalpha, Qnil,
6055 "alpha", "Alpha", RES_TYPE_NUMBER);
6056
5627 /* Initialize `default-minibuffer-frame' in case this is the first 6057 /* Initialize `default-minibuffer-frame' in case this is the first
5628 frame on this terminal. */ 6058 frame on this terminal. */
5629 if (FRAME_HAS_MINIBUF_P (f) 6059 if (FRAME_HAS_MINIBUF_P (f)
@@ -6572,8 +7002,6 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6572 dpyinfo_refcount = dpyinfo->reference_count; 7002 dpyinfo_refcount = dpyinfo->reference_count;
6573#endif /* GLYPH_DEBUG */ 7003#endif /* GLYPH_DEBUG */
6574 FRAME_KBOARD (f) = kb; 7004 FRAME_KBOARD (f) = kb;
6575 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
6576 f->output_data.w32->explicit_parent = false;
6577 7005
6578 /* Set the name; the functions to which we pass f expect the name to 7006 /* Set the name; the functions to which we pass f expect the name to
6579 be set. */ 7007 be set. */
@@ -6631,6 +7059,8 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6631 "cursorColor", "Foreground", RES_TYPE_STRING); 7059 "cursorColor", "Foreground", RES_TYPE_STRING);
6632 x_default_parameter (f, parms, Qborder_color, build_string ("black"), 7060 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
6633 "borderColor", "BorderColor", RES_TYPE_STRING); 7061 "borderColor", "BorderColor", RES_TYPE_STRING);
7062 x_default_parameter (f, parms, Qno_special_glyphs, Qt,
7063 NULL, NULL, RES_TYPE_BOOLEAN);
6634 7064
6635 /* Init faces before x_default_parameter is called for the 7065 /* Init faces before x_default_parameter is called for the
6636 scroll-bar-width parameter because otherwise we end up in 7066 scroll-bar-width parameter because otherwise we end up in
@@ -6639,6 +7069,7 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
6639 7069
6640 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED; 7070 f->output_data.w32->dwStyle = WS_BORDER | WS_POPUP | WS_DISABLED;
6641 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window; 7071 f->output_data.w32->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
7072 f->output_data.w32->explicit_parent = false;
6642 7073
6643 x_figure_window_size (f, parms, true, &x_width, &x_height); 7074 x_figure_window_size (f, parms, true, &x_width, &x_height);
6644 7075
@@ -6740,7 +7171,7 @@ compute_tip_xy (struct frame *f,
6740 int width, int height, int *root_x, int *root_y) 7171 int width, int height, int *root_x, int *root_y)
6741{ 7172{
6742 Lisp_Object left, top, right, bottom; 7173 Lisp_Object left, top, right, bottom;
6743 int min_x, min_y, max_x, max_y; 7174 int min_x = 0, min_y, max_x = 0, max_y;
6744 7175
6745 /* User-specified position? */ 7176 /* User-specified position? */
6746 left = Fcdr (Fassq (Qleft, parms)); 7177 left = Fcdr (Fassq (Qleft, parms));
@@ -7282,6 +7713,23 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
7282 return 0; 7713 return 0;
7283} 7714}
7284 7715
7716void
7717w32_dialog_in_progress (Lisp_Object in_progress)
7718{
7719 Lisp_Object frames, frame;
7720
7721 /* Don't let frames in `above' z-group obscure popups. */
7722 FOR_EACH_FRAME (frames, frame)
7723 {
7724 struct frame *f = XFRAME (frame);
7725
7726 if (!NILP (in_progress) && FRAME_Z_GROUP_ABOVE (f))
7727 x_set_z_group (f, Qabove_suspended, Qabove);
7728 else if (NILP (in_progress) && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
7729 x_set_z_group (f, Qabove, Qabove_suspended);
7730 }
7731}
7732
7285DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, 7733DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0,
7286 doc: /* Read file name, prompting with PROMPT in directory DIR. 7734 doc: /* Read file name, prompting with PROMPT in directory DIR.
7287Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file 7735Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
@@ -7341,7 +7789,7 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
7341 OPENFILENAMEA * file_details_a = &new_file_details_a.details; 7789 OPENFILENAMEA * file_details_a = &new_file_details_a.details;
7342 int use_unicode = w32_unicode_filenames; 7790 int use_unicode = w32_unicode_filenames;
7343 wchar_t *prompt_w; 7791 wchar_t *prompt_w;
7344 char *prompt_a; 7792 char *prompt_a UNINIT;
7345 int len; 7793 int len;
7346 char fname_ret[MAX_UTF8_PATH]; 7794 char fname_ret[MAX_UTF8_PATH];
7347#endif /* NTGUI_UNICODE */ 7795#endif /* NTGUI_UNICODE */
@@ -7513,8 +7961,12 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
7513 7961
7514 { 7962 {
7515 int count = SPECPDL_INDEX (); 7963 int count = SPECPDL_INDEX ();
7964
7965 w32_dialog_in_progress (Qt);
7966
7516 /* Prevent redisplay. */ 7967 /* Prevent redisplay. */
7517 specbind (Qinhibit_redisplay, Qt); 7968 specbind (Qinhibit_redisplay, Qt);
7969 record_unwind_protect (w32_dialog_in_progress, Qnil);
7518 block_input (); 7970 block_input ();
7519 if (use_unicode) 7971 if (use_unicode)
7520 { 7972 {
@@ -8065,8 +8517,8 @@ w32_parse_and_hook_hot_key (Lisp_Object key, int hook)
8065{ 8517{
8066 /* Copied from Fdefine_key and store_in_keymap. */ 8518 /* Copied from Fdefine_key and store_in_keymap. */
8067 register Lisp_Object c; 8519 register Lisp_Object c;
8068 int vk_code; 8520 int vk_code = 0;
8069 int lisp_modifiers; 8521 int lisp_modifiers = 0;
8070 int w32_modifiers; 8522 int w32_modifiers;
8071 Lisp_Object res = Qnil; 8523 Lisp_Object res = Qnil;
8072 char* vkname; 8524 char* vkname;
@@ -8510,33 +8962,47 @@ menu bar or tool bar of FRAME. */)
8510 if (EQ (type, Qouter_edges)) 8962 if (EQ (type, Qouter_edges))
8511 { 8963 {
8512 RECT rectangle; 8964 RECT rectangle;
8965 BOOL success = false;
8513 8966
8514 block_input (); 8967 block_input ();
8515 /* Outer frame rectangle, including outer borders and title bar. */ 8968 /* Outer frame rectangle, including outer borders and title bar. */
8516 GetWindowRect (FRAME_W32_WINDOW (f), &rectangle); 8969 success = GetWindowRect (FRAME_W32_WINDOW (f), &rectangle);
8517 unblock_input (); 8970 unblock_input ();
8518 8971
8519 return list4 (make_number (rectangle.left), 8972 if (success)
8520 make_number (rectangle.top), 8973 return list4 (make_number (rectangle.left),
8521 make_number (rectangle.right), 8974 make_number (rectangle.top),
8522 make_number (rectangle.bottom)); 8975 make_number (rectangle.right),
8976 make_number (rectangle.bottom));
8977 else
8978 return Qnil;
8523 } 8979 }
8524 else 8980 else
8525 { 8981 {
8526 RECT rectangle; 8982 RECT rectangle;
8527 POINT pt; 8983 POINT pt;
8528 int left, top, right, bottom; 8984 int left, top, right, bottom;
8985 BOOL success;
8529 8986
8530 block_input (); 8987 block_input ();
8531 /* Inner frame rectangle, excluding borders and title bar. */ 8988 /* Inner frame rectangle, excluding borders and title bar. */
8532 GetClientRect (FRAME_W32_WINDOW (f), &rectangle); 8989 success = GetClientRect (FRAME_W32_WINDOW (f), &rectangle);
8533 /* Get top-left corner of native rectangle in screen 8990 /* Get top-left corner of native rectangle in screen
8534 coordinates. */ 8991 coordinates. */
8992 if (!success)
8993 {
8994 unblock_input ();
8995 return Qnil;
8996 }
8997
8535 pt.x = 0; 8998 pt.x = 0;
8536 pt.y = 0; 8999 pt.y = 0;
8537 ClientToScreen (FRAME_W32_WINDOW (f), &pt); 9000 success = ClientToScreen (FRAME_W32_WINDOW (f), &pt);
8538 unblock_input (); 9001 unblock_input ();
8539 9002
9003 if (!success)
9004 return Qnil;
9005
8540 left = pt.x; 9006 left = pt.x;
8541 top = pt.y; 9007 top = pt.y;
8542 right = left + rectangle.right; 9008 right = left + rectangle.right;
@@ -8559,6 +9025,136 @@ menu bar or tool bar of FRAME. */)
8559 } 9025 }
8560} 9026}
8561 9027
9028/**
9029 * w32_frame_list_z_order:
9030 *
9031 * Recursively add list of all frames on the display specified via
9032 * DPYINFO and whose window-system window's parent is specified by
9033 * WINDOW to FRAMES and return FRAMES.
9034 */
9035static Lisp_Object
9036w32_frame_list_z_order (struct w32_display_info *dpyinfo, HWND window)
9037{
9038 Lisp_Object frame, frames = Qnil;
9039
9040 while (window)
9041 {
9042 struct frame *f = x_window_to_frame (dpyinfo, window);
9043
9044 if (f)
9045 {
9046 XSETFRAME (frame, f);
9047 frames = Fcons (frame, frames);
9048 }
9049
9050 block_input ();
9051 window = GetNextWindow (window, GW_HWNDNEXT);
9052 unblock_input ();
9053 }
9054
9055 return Fnreverse (frames);
9056}
9057
9058DEFUN ("w32-frame-list-z-order", Fw32_frame_list_z_order,
9059 Sw32_frame_list_z_order, 0, 1, 0,
9060 doc: /* Return list of Emacs' frames, in Z (stacking) order.
9061The optional argument DISPLAY specifies which display to ask about.
9062DISPLAY should be either a frame or a display name (a string). If
9063omitted or nil, that stands for the selected frame's display.
9064
9065As a special case, if DISPLAY is non-nil and specifies a live frame,
9066return the child frames of that frame in Z (stacking) order.
9067
9068Frames are listed from topmost (first) to bottommost (last). */)
9069 (Lisp_Object display)
9070{
9071 struct w32_display_info *dpyinfo = check_x_display_info (display);
9072 HWND window;
9073
9074 block_input ();
9075 if (FRAMEP (display) && FRAME_LIVE_P (XFRAME (display)))
9076 window = GetWindow (FRAME_W32_WINDOW (XFRAME (display)), GW_CHILD);
9077 else
9078 window = GetTopWindow (NULL);
9079 unblock_input ();
9080
9081 return w32_frame_list_z_order (dpyinfo, window);
9082}
9083
9084/**
9085 * w32_frame_restack:
9086 *
9087 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
9088 * practice this is a two-step action: The first step removes F1's
9089 * window-system window from the display. The second step reinserts
9090 * F1's window below (above if ABOVE_FLAG is true) that of F2.
9091 */
9092static void
9093w32_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
9094{
9095 HWND hwnd1 = FRAME_W32_WINDOW (f1);
9096 HWND hwnd2 = FRAME_W32_WINDOW (f2);
9097
9098 block_input ();
9099 if (above_flag)
9100 /* Put F1 above F2 in the z-order. */
9101 {
9102 if (GetNextWindow (hwnd1, GW_HWNDNEXT) != hwnd2)
9103 {
9104 /* Make sure F1 is below F2 first because we must not
9105 change the relative position of F2 wrt any other
9106 window but F1. */
9107 if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
9108 SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
9109 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9110 | SWP_FRAMECHANGED);
9111 /* Now put F1 above F2. */
9112 SetWindowPos (hwnd2, hwnd1, 0, 0, 0, 0,
9113 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9114 | SWP_FRAMECHANGED);
9115 }
9116 }
9117 else if (GetNextWindow (hwnd2, GW_HWNDNEXT) != hwnd1)
9118 /* Put F1 below F2 in the z-order. */
9119 SetWindowPos (hwnd1, hwnd2, 0, 0, 0, 0,
9120 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE
9121 | SWP_FRAMECHANGED);
9122 unblock_input ();
9123}
9124
9125DEFUN ("w32-frame-restack", Fw32_frame_restack, Sw32_frame_restack, 2, 3, 0,
9126 doc: /* Restack FRAME1 below FRAME2.
9127This means that if both frames are visible and the display areas of
9128these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
9129third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
9130means that if both frames are visible and the display areas of these
9131frames overlap, FRAME1 (partially) obscures FRAME2.
9132
9133This may be thought of as an atomic action performed in two steps: The
9134first step removes FRAME1's window-system window from the display. The
9135second step reinserts FRAME1's window below (above if ABOVE is true)
9136that of FRAME2. Hence the position of FRAME2 in its display's Z
9137\(stacking) order relative to all other frames excluding FRAME1 remains
9138unaltered.
9139
9140Some window managers may refuse to restack windows. */)
9141 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
9142{
9143 struct frame *f1 = decode_live_frame (frame1);
9144 struct frame *f2 = decode_live_frame (frame2);
9145
9146 if (FRAME_W32_P (f1) && FRAME_W32_P (f2))
9147 {
9148 w32_frame_restack (f1, f2, !NILP (above));
9149 return Qt;
9150 }
9151 else
9152 {
9153 error ("Cannot restack frames");
9154 return Qnil;
9155 }
9156}
9157
8562DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position, 9158DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position,
8563 Sw32_mouse_absolute_pixel_position, 0, 0, 0, 9159 Sw32_mouse_absolute_pixel_position, 0, 0, 0,
8564 doc: /* Return absolute position of mouse cursor in pixels. 9160 doc: /* Return absolute position of mouse cursor in pixels.
@@ -9753,6 +10349,14 @@ frame_parm_handler w32_frame_parm_handlers[] =
9753 0, /* x_set_sticky */ 10349 0, /* x_set_sticky */
9754 0, /* x_set_tool_bar_position */ 10350 0, /* x_set_tool_bar_position */
9755 0, /* x_set_inhibit_double_buffering */ 10351 0, /* x_set_inhibit_double_buffering */
10352 x_set_undecorated,
10353 x_set_parent_frame,
10354 x_set_skip_taskbar,
10355 x_set_no_focus_on_map,
10356 x_set_no_accept_focus,
10357 x_set_z_group,
10358 0, /* x_set_override_redirect */
10359 x_set_no_special_glyphs,
9756}; 10360};
9757 10361
9758void 10362void
@@ -10132,6 +10736,8 @@ tip frame. */);
10132 defsubr (&Sx_display_list); 10736 defsubr (&Sx_display_list);
10133 defsubr (&Sw32_frame_geometry); 10737 defsubr (&Sw32_frame_geometry);
10134 defsubr (&Sw32_frame_edges); 10738 defsubr (&Sw32_frame_edges);
10739 defsubr (&Sw32_frame_list_z_order);
10740 defsubr (&Sw32_frame_restack);
10135 defsubr (&Sw32_mouse_absolute_pixel_position); 10741 defsubr (&Sw32_mouse_absolute_pixel_position);
10136 defsubr (&Sw32_set_mouse_absolute_pixel_position); 10742 defsubr (&Sw32_set_mouse_absolute_pixel_position);
10137 defsubr (&Sx_synchronize); 10743 defsubr (&Sx_synchronize);
diff --git a/src/w32font.c b/src/w32font.c
index 37df1bc43c0..67d2f6d666d 100644
--- a/src/w32font.c
+++ b/src/w32font.c
@@ -436,7 +436,7 @@ w32font_text_extents (struct font *font, unsigned *code,
436 int i; 436 int i;
437 HFONT old_font = NULL; 437 HFONT old_font = NULL;
438 HDC dc = NULL; 438 HDC dc = NULL;
439 struct frame * f; 439 struct frame * f UNINIT;
440 int total_width = 0; 440 int total_width = 0;
441 WORD *wcode; 441 WORD *wcode;
442 SIZE size; 442 SIZE size;
@@ -2553,11 +2553,22 @@ in the font selection dialog. */)
2553 SelectObject (hdc, oldobj); 2553 SelectObject (hdc, oldobj);
2554 ReleaseDC (FRAME_W32_WINDOW (f), hdc); 2554 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
2555 2555
2556 if (!ChooseFont (&cf) 2556 {
2557 || logfont_to_fcname (&lf, cf.iPointSize, buf, 100) < 0) 2557 int count = SPECPDL_INDEX ();
2558 return Qnil; 2558 Lisp_Object value = Qnil;
2559
2560 w32_dialog_in_progress (Qt);
2561 specbind (Qinhibit_redisplay, Qt);
2562 record_unwind_protect (w32_dialog_in_progress, Qnil);
2563
2564 if (ChooseFont (&cf)
2565 && logfont_to_fcname (&lf, cf.iPointSize, buf, 100) >= 0)
2566 value = DECODE_SYSTEM (build_string (buf));
2559 2567
2560 return DECODE_SYSTEM (build_string (buf)); 2568 unbind_to (count, Qnil);
2569
2570 return value;
2571 }
2561} 2572}
2562 2573
2563static const char *const w32font_booleans [] = { 2574static const char *const w32font_booleans [] = {
diff --git a/src/w32menu.c b/src/w32menu.c
index 7dae9de2966..de5c4b46b54 100644
--- a/src/w32menu.c
+++ b/src/w32menu.c
@@ -267,7 +267,7 @@ set_frame_menubar (struct frame *f, bool first_time, bool deep_p)
267 HMENU menubar_widget = f->output_data.w32->menubar_widget; 267 HMENU menubar_widget = f->output_data.w32->menubar_widget;
268 Lisp_Object items; 268 Lisp_Object items;
269 widget_value *wv, *first_wv, *prev_wv = 0; 269 widget_value *wv, *first_wv, *prev_wv = 0;
270 int i, last_i; 270 int i, last_i = 0;
271 int *submenu_start, *submenu_end; 271 int *submenu_start, *submenu_end;
272 int *submenu_top_level_items, *submenu_n_panes; 272 int *submenu_top_level_items, *submenu_n_panes;
273 273
diff --git a/src/w32term.c b/src/w32term.c
index 81666f5bc47..c37805cb6ca 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -782,9 +782,23 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
782 block_input (); 782 block_input ();
783 { 783 {
784 HDC hdc = get_frame_dc (f); 784 HDC hdc = get_frame_dc (f);
785 w32_clear_area (f, hdc, 0, y, width, height); 785 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
786 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width, 786
787 y, width, height); 787 if (face)
788 {
789 /* Fill border with internal border face. */
790 unsigned long color = face->background;
791
792 w32_fill_area (f, hdc, color, 0, y, width, height);
793 w32_fill_area (f, hdc, color, FRAME_PIXEL_WIDTH (f) - width,
794 y, width, height);
795 }
796 else
797 {
798 w32_clear_area (f, hdc, 0, y, width, height);
799 w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
800 y, width, height);
801 }
788 release_frame_dc (f, hdc); 802 release_frame_dc (f, hdc);
789 } 803 }
790 unblock_input (); 804 unblock_input ();
@@ -940,6 +954,10 @@ x_set_cursor_gc (struct glyph_string *s)
940 if (s->font == FRAME_FONT (s->f) 954 if (s->font == FRAME_FONT (s->f)
941 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) 955 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
942 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) 956 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
957 /* Sometimes we are not called for each change in the default
958 face's background color (e.g., bug#26851), so the additional
959 test in the next line gives us a chance to resync. */
960 && s->f->output_data.w32->cursor_gc->foreground == s->face->background
943 && !s->cmp) 961 && !s->cmp)
944 s->gc = s->f->output_data.w32->cursor_gc; 962 s->gc = s->f->output_data.w32->cursor_gc;
945 else 963 else
@@ -2440,7 +2458,7 @@ x_draw_glyph_string (struct glyph_string *s)
2440 thickness = font->underline_thickness; 2458 thickness = font->underline_thickness;
2441 else 2459 else
2442 thickness = 1; 2460 thickness = 1;
2443 if (x_underline_at_descent_line) 2461 if (x_underline_at_descent_line || !font)
2444 position = (s->height - thickness) - (s->ybase - s->y); 2462 position = (s->height - thickness) - (s->ybase - s->y);
2445 else 2463 else
2446 { 2464 {
@@ -2453,9 +2471,9 @@ x_draw_glyph_string (struct glyph_string *s)
2453 ROUND (x) = floor (x + 0.5) */ 2471 ROUND (x) = floor (x + 0.5) */
2454 2472
2455 if (x_use_underline_position_properties 2473 if (x_use_underline_position_properties
2456 && font && font->underline_position >= 0) 2474 && font->underline_position >= 0)
2457 position = font->underline_position; 2475 position = font->underline_position;
2458 else if (font) 2476 else
2459 position = (font->descent + 1) / 2; 2477 position = (font->descent + 1) / 2;
2460 } 2478 }
2461 position = max (position, underline_minimum_offset); 2479 position = max (position, underline_minimum_offset);
@@ -3095,7 +3113,8 @@ construct_mouse_wheel (struct input_event *result, W32Msg *msg, struct frame *f)
3095 coordinates, so cast to short to interpret them correctly. */ 3113 coordinates, so cast to short to interpret them correctly. */
3096 p.x = (short) LOWORD (msg->msg.lParam); 3114 p.x = (short) LOWORD (msg->msg.lParam);
3097 p.y = (short) HIWORD (msg->msg.lParam); 3115 p.y = (short) HIWORD (msg->msg.lParam);
3098 ScreenToClient (msg->msg.hwnd, &p); 3116 /* For the case that F's w32 window is not msg->msg.hwnd. */
3117 ScreenToClient (FRAME_W32_WINDOW (f), &p);
3099 XSETINT (result->x, p.x); 3118 XSETINT (result->x, p.x);
3100 XSETINT (result->y, p.y); 3119 XSETINT (result->y, p.y);
3101 XSETFRAME (result->frame_or_window, f); 3120 XSETFRAME (result->frame_or_window, f);
@@ -3412,7 +3431,6 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3412 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, 3431 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
3413 Time *time) 3432 Time *time)
3414{ 3433{
3415 struct frame *f1;
3416 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp); 3434 struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (*fp);
3417 3435
3418 block_input (); 3436 block_input ();
@@ -3429,8 +3447,8 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3429 else 3447 else
3430 { 3448 {
3431 POINT pt; 3449 POINT pt;
3432
3433 Lisp_Object frame, tail; 3450 Lisp_Object frame, tail;
3451 struct frame *f1 = NULL;
3434 3452
3435 /* Clear the mouse-moved flag for every frame on this display. */ 3453 /* Clear the mouse-moved flag for every frame on this display. */
3436 FOR_EACH_FRAME (tail, frame) 3454 FOR_EACH_FRAME (tail, frame)
@@ -3446,8 +3464,31 @@ w32_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
3446 /* If mouse was grabbed on a frame, give coords for that 3464 /* If mouse was grabbed on a frame, give coords for that
3447 frame even if the mouse is now outside it. Otherwise 3465 frame even if the mouse is now outside it. Otherwise
3448 check for window under mouse on one of our frames. */ 3466 check for window under mouse on one of our frames. */
3449 f1 = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame 3467 if (x_mouse_grabbed (dpyinfo))
3450 : x_any_window_to_frame (dpyinfo, WindowFromPoint (pt))); 3468 f1 = dpyinfo->last_mouse_frame;
3469 else
3470 {
3471 HWND wfp = WindowFromPoint (pt);
3472
3473 if (wfp)
3474 {
3475 f1 = x_any_window_to_frame (dpyinfo, wfp);
3476 if (f1)
3477 {
3478 HWND cwfp = ChildWindowFromPoint (wfp, pt);
3479
3480 if (cwfp)
3481 {
3482 struct frame *f2 = x_any_window_to_frame (dpyinfo, cwfp);
3483
3484 /* If a child window was found, make sure that its
3485 frame is a child frame (Bug#26615, maybe). */
3486 if (f2 && FRAME_PARENT_FRAME (f2))
3487 f1 = f2;
3488 }
3489 }
3490 }
3491 }
3451 3492
3452 /* If not, is it one of our scroll bars? */ 3493 /* If not, is it one of our scroll bars? */
3453 if (! f1) 3494 if (! f1)
@@ -3893,11 +3934,15 @@ w32_set_vertical_scroll_bar (struct window *w,
3893 for them on the frame, we have to clear "under" them. */ 3934 for them on the frame, we have to clear "under" them. */
3894 w32_clear_area (f, hdc, left, top, width, height); 3935 w32_clear_area (f, hdc, left, top, width, height);
3895 release_frame_dc (f, hdc); 3936 release_frame_dc (f, hdc);
3937 x_clear_under_internal_border (f);
3896 } 3938 }
3897 /* Make sure scroll bar is "visible" before moving, to ensure the 3939 /* Make sure scroll bar is "visible" before moving, to ensure the
3898 area of the parent window now exposed will be refreshed. */ 3940 area of the parent window now exposed will be refreshed. */
3899 my_show_window (f, hwnd, SW_HIDE); 3941 my_show_window (f, hwnd, SW_HIDE);
3900 MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); 3942/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
3943 /* Try to not draw over child frames. */
3944 SetWindowPos (hwnd, HWND_BOTTOM, left, top, width, max (height, 1),
3945 SWP_FRAMECHANGED);
3901 3946
3902 si.cbSize = sizeof (si); 3947 si.cbSize = sizeof (si);
3903 si.fMask = SIF_RANGE; 3948 si.fMask = SIF_RANGE;
@@ -3991,11 +4036,15 @@ w32_set_horizontal_scroll_bar (struct window *w,
3991 for them on the frame, we have to clear "under" them. */ 4036 for them on the frame, we have to clear "under" them. */
3992 w32_clear_area (f, hdc, clear_left, top, clear_width, height); 4037 w32_clear_area (f, hdc, clear_left, top, clear_width, height);
3993 release_frame_dc (f, hdc); 4038 release_frame_dc (f, hdc);
4039 x_clear_under_internal_border (f);
3994 } 4040 }
3995 /* Make sure scroll bar is "visible" before moving, to ensure the 4041 /* Make sure scroll bar is "visible" before moving, to ensure the
3996 area of the parent window now exposed will be refreshed. */ 4042 area of the parent window now exposed will be refreshed. */
3997 my_show_window (f, hwnd, SW_HIDE); 4043 my_show_window (f, hwnd, SW_HIDE);
3998 MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); 4044/** MoveWindow (hwnd, left, top, width, max (height, 1), TRUE); **/
4045 /* Try to not draw over child frames. */
4046 SetWindowPos (hwnd, HWND_BOTTOM, left, top, max (width, 1), height,
4047 SWP_FRAMECHANGED);
3999 4048
4000 /* +++ SetScrollInfo +++ */ 4049 /* +++ SetScrollInfo +++ */
4001 si.cbSize = sizeof (si); 4050 si.cbSize = sizeof (si);
@@ -4532,6 +4581,7 @@ x_scroll_bar_clear (struct frame *f)
4532 GetClientRect (window, &rect); 4581 GetClientRect (window, &rect);
4533 select_palette (f, hdc); 4582 select_palette (f, hdc);
4534 w32_clear_rect (f, hdc, &rect); 4583 w32_clear_rect (f, hdc, &rect);
4584 x_clear_under_internal_border (f);
4535 deselect_palette (f, hdc); 4585 deselect_palette (f, hdc);
4536 4586
4537 ReleaseDC (window, hdc); 4587 ReleaseDC (window, hdc);
@@ -4649,7 +4699,7 @@ w32_read_socket (struct terminal *terminal,
4649 in that case expose_frame will do nothing, and if 4699 in that case expose_frame will do nothing, and if
4650 the various redisplay flags happen to be unset, 4700 the various redisplay flags happen to be unset,
4651 we are left with a blank frame. */ 4701 we are left with a blank frame. */
4652 if (!FRAME_GARBAGED_P (f)) 4702 if (!FRAME_GARBAGED_P (f) || FRAME_PARENT_FRAME (f))
4653 { 4703 {
4654 HDC hdc = get_frame_dc (f); 4704 HDC hdc = get_frame_dc (f);
4655 4705
@@ -4661,6 +4711,7 @@ w32_read_socket (struct terminal *terminal,
4661 msg.rect.top, 4711 msg.rect.top,
4662 msg.rect.right - msg.rect.left, 4712 msg.rect.right - msg.rect.left,
4663 msg.rect.bottom - msg.rect.top); 4713 msg.rect.bottom - msg.rect.top);
4714 x_clear_under_internal_border (f);
4664 } 4715 }
4665 } 4716 }
4666 break; 4717 break;
@@ -4835,8 +4886,15 @@ w32_read_socket (struct terminal *terminal,
4835 4886
4836 if (f) 4887 if (f)
4837 { 4888 {
4838 /* Generate SELECT_WINDOW_EVENTs when needed. */ 4889 /* Maybe generate SELECT_WINDOW_EVENTs for
4839 if (!NILP (Vmouse_autoselect_window)) 4890 `mouse-autoselect-window'. */
4891 if (!NILP (Vmouse_autoselect_window)
4892 && (f == XFRAME (selected_frame)
4893 /* Switch to f from another frame iff
4894 focus_follows_mouse is set and f accepts
4895 focus. */
4896 || (!NILP (focus_follows_mouse)
4897 && !FRAME_NO_ACCEPT_FOCUS (f))))
4840 { 4898 {
4841 static Lisp_Object last_mouse_window; 4899 static Lisp_Object last_mouse_window;
4842 Lisp_Object window = window_from_coordinates 4900 Lisp_Object window = window_from_coordinates
@@ -4848,20 +4906,16 @@ w32_read_socket (struct terminal *terminal,
4848 only when it is active. */ 4906 only when it is active. */
4849 if (WINDOWP (window) 4907 if (WINDOWP (window)
4850 && !EQ (window, last_mouse_window) 4908 && !EQ (window, last_mouse_window)
4851 && !EQ (window, selected_window) 4909 && !EQ (window, selected_window))
4852 /* For click-to-focus window managers
4853 create event iff we don't leave the
4854 selected frame. */
4855 && (focus_follows_mouse
4856 || (EQ (XWINDOW (window)->frame,
4857 XWINDOW (selected_window)->frame))))
4858 { 4910 {
4859 inev.kind = SELECT_WINDOW_EVENT; 4911 inev.kind = SELECT_WINDOW_EVENT;
4860 inev.frame_or_window = window; 4912 inev.frame_or_window = window;
4861 } 4913 }
4914
4862 /* Remember the last window where we saw the mouse. */ 4915 /* Remember the last window where we saw the mouse. */
4863 last_mouse_window = window; 4916 last_mouse_window = window;
4864 } 4917 }
4918
4865 if (!note_mouse_movement (f, &msg.msg)) 4919 if (!note_mouse_movement (f, &msg.msg))
4866 help_echo_string = previous_help_echo_string; 4920 help_echo_string = previous_help_echo_string;
4867 } 4921 }
@@ -4927,7 +4981,10 @@ w32_read_socket (struct terminal *terminal,
4927 4981
4928 if (tool_bar_p 4982 if (tool_bar_p
4929 || (dpyinfo->w32_focus_frame 4983 || (dpyinfo->w32_focus_frame
4930 && f != dpyinfo->w32_focus_frame)) 4984 && f != dpyinfo->w32_focus_frame
4985 /* This does not help when the click happens in
4986 a grand-parent frame. */
4987 && !frame_ancestor_p (f, dpyinfo->w32_focus_frame)))
4931 inev.kind = NO_EVENT; 4988 inev.kind = NO_EVENT;
4932 } 4989 }
4933 4990
@@ -4964,21 +5021,40 @@ w32_read_socket (struct terminal *terminal,
4964 5021
4965 if (f) 5022 if (f)
4966 { 5023 {
4967
4968 if (!dpyinfo->w32_focus_frame 5024 if (!dpyinfo->w32_focus_frame
4969 || f == dpyinfo->w32_focus_frame) 5025 || f == dpyinfo->w32_focus_frame)
5026 /* Emit an Emacs wheel-up/down event. */
4970 { 5027 {
4971 /* Emit an Emacs wheel-up/down event. */
4972 construct_mouse_wheel (&inev, &msg, f); 5028 construct_mouse_wheel (&inev, &msg, f);
5029
5030 /* Ignore any mouse motion that happened before this
5031 event; any subsequent mouse-movement Emacs events
5032 should reflect only motion after the ButtonPress. */
5033 f->mouse_moved = false;
5034 f->last_tool_bar_item = -1;
5035 dpyinfo->last_mouse_frame = f;
4973 } 5036 }
4974 /* Ignore any mouse motion that happened before this 5037 else if (FRAME_NO_ACCEPT_FOCUS (f)
4975 event; any subsequent mouse-movement Emacs events 5038 && !x_mouse_grabbed (dpyinfo))
4976 should reflect only motion after the 5039 {
4977 ButtonPress. */ 5040 Lisp_Object frame1 = get_frame_param (f, Qmouse_wheel_frame);
4978 f->mouse_moved = false; 5041 struct frame *f1 = FRAMEP (frame1) ? XFRAME (frame1) : NULL;
4979 f->last_tool_bar_item = -1; 5042
5043 if (f1 && FRAME_LIVE_P (f1) && FRAME_W32_P (f1))
5044 {
5045 construct_mouse_wheel (&inev, &msg, f1);
5046 f1->mouse_moved = false;
5047 f1->last_tool_bar_item = -1;
5048 dpyinfo->last_mouse_frame = f1;
5049 }
5050 else
5051 dpyinfo->last_mouse_frame = f;
5052 }
5053 else
5054 dpyinfo->last_mouse_frame = f;
4980 } 5055 }
4981 dpyinfo->last_mouse_frame = f; 5056 else
5057 dpyinfo->last_mouse_frame = f;
4982 } 5058 }
4983 break; 5059 break;
4984 5060
@@ -5010,6 +5086,51 @@ w32_read_socket (struct terminal *terminal,
5010 } 5086 }
5011 5087
5012 case WM_WINDOWPOSCHANGED: 5088 case WM_WINDOWPOSCHANGED:
5089 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5090
5091 if (f)
5092 {
5093 RECT rect;
5094 int /* rows, columns, */ width, height, text_width, text_height;
5095
5096 if (GetClientRect (msg.msg.hwnd, &rect)
5097 /* GetClientRect evidently returns (0, 0, 0, 0) if
5098 called on a minimized frame. Such "dimensions"
5099 aren't useful anyway. */
5100 && !(rect.bottom == 0
5101 && rect.top == 0
5102 && rect.left == 0
5103 && rect.right == 0))
5104 {
5105 height = rect.bottom - rect.top;
5106 width = rect.right - rect.left;
5107 text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, width);
5108 text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, height);
5109 /* rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); */
5110 /* columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); */
5111
5112 /* TODO: Clip size to the screen dimensions. */
5113
5114 /* Even if the number of character rows and columns
5115 has not changed, the font size may have changed,
5116 so we need to check the pixel dimensions as well. */
5117
5118 if (width != FRAME_PIXEL_WIDTH (f)
5119 || height != FRAME_PIXEL_HEIGHT (f)
5120 || text_width != FRAME_TEXT_WIDTH (f)
5121 || text_height != FRAME_TEXT_HEIGHT (f))
5122 {
5123 change_frame_size (f, text_width, text_height, 0, 1, 0, 1);
5124 SET_FRAME_GARBAGED (f);
5125 cancel_mouse_face (f);
5126 f->win_gravity = NorthWestGravity;
5127 }
5128 }
5129 }
5130
5131 check_visibility = 1;
5132 break;
5133
5013 case WM_ACTIVATE: 5134 case WM_ACTIVATE:
5014 case WM_ACTIVATEAPP: 5135 case WM_ACTIVATEAPP:
5015 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 5136 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -5031,14 +5152,19 @@ w32_read_socket (struct terminal *terminal,
5031 w32fullscreen_hook (f); 5152 w32fullscreen_hook (f);
5032 } 5153 }
5033 } 5154 }
5155
5034 check_visibility = 1; 5156 check_visibility = 1;
5035 break; 5157 break;
5036 5158
5037 case WM_MOVE: 5159 case WM_MOVE:
5038 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 5160 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5039 5161
5040 if (f && !FRAME_ICONIFIED_P (f)) 5162 if (f && FRAME_VISIBLE_P (f) && !FRAME_ICONIFIED_P(f))
5041 x_real_positions (f, &f->left_pos, &f->top_pos); 5163 {
5164 x_real_positions (f, &f->left_pos, &f->top_pos);
5165 inev.kind = MOVE_FRAME_EVENT;
5166 XSETFRAME (inev.frame_or_window, f);
5167 }
5042 5168
5043 check_visibility = 1; 5169 check_visibility = 1;
5044 break; 5170 break;
@@ -5067,6 +5193,10 @@ w32_read_socket (struct terminal *terminal,
5067 } 5193 }
5068#endif 5194#endif
5069 5195
5196 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
5197 if (f)
5198 x_clear_under_internal_border (f);
5199
5070 check_visibility = 1; 5200 check_visibility = 1;
5071 break; 5201 break;
5072 5202
@@ -5965,7 +6095,9 @@ x_calc_absolute_position (struct frame *f)
5965 are computed correctly (Bug#21173). */ 6095 are computed correctly (Bug#21173). */
5966 int display_left = 0; 6096 int display_left = 0;
5967 int display_top = 0; 6097 int display_top = 0;
5968 if (flags & (XNegative | YNegative)) 6098 struct frame *p = FRAME_PARENT_FRAME (f);
6099
6100 if (!p && flags & (XNegative | YNegative))
5969 { 6101 {
5970 Lisp_Object list; 6102 Lisp_Object list;
5971 6103
@@ -5991,20 +6123,42 @@ x_calc_absolute_position (struct frame *f)
5991 } 6123 }
5992 6124
5993 /* Treat negative positions as relative to the rightmost bottommost 6125 /* Treat negative positions as relative to the rightmost bottommost
5994 position that fits on the screen. */ 6126 position that fits on the screen or parent frame.
6127
6128 I see no need for subtracting 1 from the border widths - is there
6129 any on the remaining platforms? Here these subtractions did put
6130 the last pixel line/column of a frame off-display when, for
6131 example, a (set-frame-parameter nil 'left '(- 0)) specification was
6132 used - martin 20017-05-05. */
5995 if (flags & XNegative) 6133 if (flags & XNegative)
5996 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) 6134 {
5997 + display_left 6135 if (p)
5998 - FRAME_PIXEL_WIDTH (f) 6136 f->left_pos = (FRAME_PIXEL_WIDTH (p)
5999 + f->left_pos 6137 - FRAME_PIXEL_WIDTH (f)
6000 - (left_right_borders_width - 1)); 6138 + f->left_pos
6139 - left_right_borders_width);
6140 else
6141 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
6142 + display_left
6143 - FRAME_PIXEL_WIDTH (f)
6144 + f->left_pos
6145 - left_right_borders_width);
6146 }
6001 6147
6002 if (flags & YNegative) 6148 if (flags & YNegative)
6003 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) 6149 {
6004 + display_top 6150 if (p)
6005 - FRAME_PIXEL_HEIGHT (f) 6151 f->top_pos = (FRAME_PIXEL_HEIGHT (p)
6006 + f->top_pos 6152 - FRAME_PIXEL_HEIGHT (f)
6007 - (top_bottom_borders_height - 1)); 6153 + f->top_pos
6154 - top_bottom_borders_height);
6155 else
6156 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
6157 + display_top
6158 - FRAME_PIXEL_HEIGHT (f)
6159 + f->top_pos
6160 - top_bottom_borders_height);
6161 }
6008 6162
6009 /* The left_pos and top_pos are now relative to the top and left 6163 /* The left_pos and top_pos are now relative to the top and left
6010 screen edges, so the flags should correspond. */ 6164 screen edges, so the flags should correspond. */
@@ -6042,11 +6196,16 @@ x_set_offset (struct frame *f, register int xoff, register int yoff,
6042 modified_left = f->left_pos; 6196 modified_left = f->left_pos;
6043 modified_top = f->top_pos; 6197 modified_top = f->top_pos;
6044 6198
6045 my_set_window_pos (FRAME_W32_WINDOW (f), 6199 if (!FRAME_PARENT_FRAME (f))
6046 NULL, 6200 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6047 modified_left, modified_top, 6201 modified_left, modified_top,
6048 0, 0, 6202 0, 0,
6049 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE); 6203 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6204 else
6205 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6206 modified_left, modified_top,
6207 0, 0,
6208 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
6050 unblock_input (); 6209 unblock_input ();
6051} 6210}
6052 6211
@@ -6168,10 +6327,7 @@ x_set_window_size (struct frame *f, bool change_gravity,
6168 6327
6169 /* Get the height of the menu bar here. It's used below to detect 6328 /* Get the height of the menu bar here. It's used below to detect
6170 whether the menu bar is wrapped. It's also used to specify the 6329 whether the menu bar is wrapped. It's also used to specify the
6171 third argument for AdjustWindowRect. FRAME_EXTERNAL_MENU_BAR which 6330 third argument for AdjustWindowRect. See bug#22105. */
6172 has been used before for that reason is unreliable because it only
6173 specifies whether we _want_ a menu bar for this frame and not
6174 whether this frame _has_ a menu bar. See bug#22105. */
6175 info.cbSize = sizeof (info); 6331 info.cbSize = sizeof (info);
6176 info.rcBar.top = info.rcBar.bottom = 0; 6332 info.rcBar.top = info.rcBar.bottom = 0;
6177 GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info); 6333 GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &info);
@@ -6250,11 +6406,18 @@ x_set_window_size (struct frame *f, bool change_gravity,
6250 Fcons (make_number (rect.right - rect.left), 6406 Fcons (make_number (rect.right - rect.left),
6251 make_number (rect.bottom - rect.top)))); 6407 make_number (rect.bottom - rect.top))));
6252 6408
6253 my_set_window_pos (FRAME_W32_WINDOW (f), NULL, 6409 if (!FRAME_PARENT_FRAME (f))
6254 0, 0, 6410 my_set_window_pos (FRAME_W32_WINDOW (f), NULL,
6255 rect.right - rect.left, 6411 0, 0,
6256 rect.bottom - rect.top, 6412 rect.right - rect.left,
6257 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE); 6413 rect.bottom - rect.top,
6414 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
6415 else
6416 my_set_window_pos (FRAME_W32_WINDOW (f), HWND_TOP,
6417 0, 0,
6418 rect.right - rect.left,
6419 rect.bottom - rect.top,
6420 SWP_NOMOVE | SWP_NOACTIVATE);
6258 6421
6259 change_frame_size (f, 6422 change_frame_size (f,
6260 ((pixelwidth == 0) 6423 ((pixelwidth == 0)
@@ -6311,10 +6474,14 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
6311} 6474}
6312 6475
6313 6476
6314/* focus shifting, raising and lowering. */ 6477/* Focus shifting, raising and lowering. */
6478
6479/* The NOACTIVATE argument has no effect on Windows. According to the
6480 Windows API: An application cannot activate an inactive window
6481 without also bringing it to the top of the Z order. */
6315 6482
6316void 6483void
6317x_focus_frame (struct frame *f) 6484x_focus_frame (struct frame *f, bool noactivate)
6318{ 6485{
6319#if 0 6486#if 0
6320 struct w32_display_info *dpyinfo = &one_w32_display_info; 6487 struct w32_display_info *dpyinfo = &one_w32_display_info;
@@ -6443,18 +6610,21 @@ x_make_frame_visible (struct frame *f)
6443 if (! FRAME_ICONIFIED_P (f) 6610 if (! FRAME_ICONIFIED_P (f)
6444 && ! f->output_data.w32->asked_for_visible) 6611 && ! f->output_data.w32->asked_for_visible)
6445 { 6612 {
6446 RECT workarea_rect; 6613 if (!FRAME_PARENT_FRAME (f))
6447 RECT window_rect; 6614 {
6448 6615 RECT workarea_rect;
6449 /* Adjust vertical window position in order to avoid being 6616 RECT window_rect;
6450 covered by a taskbar placed at the bottom of the desktop. */ 6617
6451 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0); 6618 /* Adjust vertical window position in order to avoid being
6452 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect); 6619 covered by a taskbar placed at the bottom of the desktop. */
6453 if (window_rect.bottom > workarea_rect.bottom 6620 SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
6454 && window_rect.top > workarea_rect.top) 6621 GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
6455 f->top_pos = max (window_rect.top 6622 if (window_rect.bottom > workarea_rect.bottom
6456 - window_rect.bottom + workarea_rect.bottom, 6623 && window_rect.top > workarea_rect.top)
6457 workarea_rect.top); 6624 f->top_pos = max (window_rect.top
6625 - window_rect.bottom + workarea_rect.bottom,
6626 workarea_rect.top);
6627 }
6458 6628
6459 x_set_offset (f, f->left_pos, f->top_pos, 0); 6629 x_set_offset (f, f->left_pos, f->top_pos, 0);
6460 } 6630 }
@@ -6469,7 +6639,11 @@ x_make_frame_visible (struct frame *f)
6469 set for minimized windows that are still visible, so use that to 6639 set for minimized windows that are still visible, so use that to
6470 determine the appropriate flag to pass ShowWindow. */ 6640 determine the appropriate flag to pass ShowWindow. */
6471 my_show_window (f, FRAME_W32_WINDOW (f), 6641 my_show_window (f, FRAME_W32_WINDOW (f),
6472 FRAME_ICONIFIED_P (f) ? SW_RESTORE : SW_SHOWNORMAL); 6642 FRAME_ICONIFIED_P (f)
6643 ? SW_RESTORE
6644 : FRAME_NO_FOCUS_ON_MAP (f)
6645 ? SW_SHOWNOACTIVATE
6646 : SW_SHOWNORMAL);
6473 } 6647 }
6474 6648
6475 /* Synchronize to ensure Emacs knows the frame is visible 6649 /* Synchronize to ensure Emacs knows the frame is visible
diff --git a/src/w32term.h b/src/w32term.h
index 990d3794b22..9956682c5cd 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -246,6 +246,7 @@ extern void x_set_internal_border_width (struct frame *f,
246 Lisp_Object value, 246 Lisp_Object value,
247 Lisp_Object oldval); 247 Lisp_Object oldval);
248extern void initialize_frame_menubar (struct frame *); 248extern void initialize_frame_menubar (struct frame *);
249extern void w32_dialog_in_progress (Lisp_Object in_progress);
249 250
250/* w32inevt.c */ 251/* w32inevt.c */
251extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId); 252extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId);
@@ -344,6 +345,14 @@ struct w32_output
344 Cursor hourglass_cursor; 345 Cursor hourglass_cursor;
345 Cursor horizontal_drag_cursor; 346 Cursor horizontal_drag_cursor;
346 Cursor vertical_drag_cursor; 347 Cursor vertical_drag_cursor;
348 Cursor left_edge_cursor;
349 Cursor top_left_corner_cursor;
350 Cursor top_edge_cursor;
351 Cursor top_right_corner_cursor;
352 Cursor right_edge_cursor;
353 Cursor bottom_right_corner_cursor;
354 Cursor bottom_edge_cursor;
355 Cursor bottom_left_corner_cursor;
347 356
348 /* Non-zero means hourglass cursor is currently displayed. */ 357 /* Non-zero means hourglass cursor is currently displayed. */
349 unsigned hourglass_p : 1; 358 unsigned hourglass_p : 1;
@@ -706,7 +715,7 @@ extern BOOL parse_button (int, int, int *, int *);
706 715
707extern void w32_sys_ring_bell (struct frame *f); 716extern void w32_sys_ring_bell (struct frame *f);
708extern void x_delete_display (struct w32_display_info *dpyinfo); 717extern void x_delete_display (struct w32_display_info *dpyinfo);
709 718extern void x_clear_under_internal_border (struct frame *f);
710extern void x_query_color (struct frame *, XColor *); 719extern void x_query_color (struct frame *, XColor *);
711 720
712#define FILE_NOTIFICATIONS_SIZE 16384 721#define FILE_NOTIFICATIONS_SIZE 16384
diff --git a/src/widget.c b/src/widget.c
index d7ec7028517..585039d58c6 100644
--- a/src/widget.c
+++ b/src/widget.c
@@ -108,7 +108,7 @@ emacsFrameTranslations [] = "\
108 108
109static EmacsFrameClassRec emacsFrameClassRec = { 109static EmacsFrameClassRec emacsFrameClassRec = {
110 { /* core fields */ 110 { /* core fields */
111 /* superclass */ &widgetClassRec, 111 /* superclass */ 0, /* filled in by emacsFrameClass */
112 /* class_name */ (char *) "EmacsFrame", 112 /* class_name */ (char *) "EmacsFrame",
113 /* widget_size */ sizeof (EmacsFrameRec), 113 /* widget_size */ sizeof (EmacsFrameRec),
114 /* class_initialize */ 0, 114 /* class_initialize */ 0,
@@ -146,7 +146,16 @@ static EmacsFrameClassRec emacsFrameClassRec = {
146 } 146 }
147}; 147};
148 148
149WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec; 149WidgetClass
150emacsFrameClass (void)
151{
152 /* Set the superclass here rather than relying on static
153 initialization, to work around an unexelf.c bug on x86 platforms
154 that use the GNU Gold linker (Bug#27248). */
155 emacsFrameClassRec.core_class.superclass = &widgetClassRec;
156
157 return (WidgetClass) &emacsFrameClassRec;
158}
150 159
151static void 160static void
152get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height) 161get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height)
diff --git a/src/widget.h b/src/widget.h
index 2c5fb61df2f..97dd6ab61de 100644
--- a/src/widget.h
+++ b/src/widget.h
@@ -90,7 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
90typedef struct _EmacsFrameRec *EmacsFrame; 90typedef struct _EmacsFrameRec *EmacsFrame;
91typedef struct _EmacsFrameClassRec *EmacsFrameClass; 91typedef struct _EmacsFrameClassRec *EmacsFrameClass;
92 92
93extern WidgetClass emacsFrameClass; 93extern WidgetClass emacsFrameClass (void);
94 94
95extern struct _DisplayContext *display_context; 95extern struct _DisplayContext *display_context;
96 96
diff --git a/src/window.c b/src/window.c
index 95690443f8e..4816bd69909 100644
--- a/src/window.c
+++ b/src/window.c
@@ -492,7 +492,7 @@ select_window (Lisp_Object window, Lisp_Object norecord,
492 record_buffer before returning here. */ 492 record_buffer before returning here. */
493 goto record_and_return; 493 goto record_and_return;
494 494
495 if (NILP (norecord)) 495 if (NILP (norecord) || EQ (norecord, Qmark_for_redisplay))
496 { /* Mark the window for redisplay since the selected-window has 496 { /* Mark the window for redisplay since the selected-window has
497 a different mode-line. */ 497 a different mode-line. */
498 wset_redisplay (XWINDOW (selected_window)); 498 wset_redisplay (XWINDOW (selected_window));
@@ -571,7 +571,8 @@ Return WINDOW.
571 571
572Optional second arg NORECORD non-nil means do not put this buffer at the 572Optional second arg NORECORD non-nil means do not put this buffer at the
573front of the buffer list and do not make this window the most recently 573front of the buffer list and do not make this window the most recently
574selected one. 574selected one. Also, do not mark WINDOW for redisplay unless NORECORD
575equals the special symbol `mark-for-redisplay'.
575 576
576Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that 577Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that
577applications and internal routines often select a window temporarily for 578applications and internal routines often select a window temporarily for
@@ -1207,13 +1208,13 @@ coordinates_in_window (register struct window *w, int x, int y)
1207 - WINDOW_BOTTOM_DIVIDER_WIDTH (w)))) 1208 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
1208 return ON_HORIZONTAL_SCROLL_BAR; 1209 return ON_HORIZONTAL_SCROLL_BAR;
1209 /* On the mode or header line? */ 1210 /* On the mode or header line? */
1210 else if ((WINDOW_WANTS_MODELINE_P (w) 1211 else if ((window_wants_mode_line (w)
1211 && y >= (bottom_y 1212 && y >= (bottom_y
1212 - CURRENT_MODE_LINE_HEIGHT (w) 1213 - CURRENT_MODE_LINE_HEIGHT (w)
1213 - WINDOW_BOTTOM_DIVIDER_WIDTH (w)) 1214 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1214 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w) 1215 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1215 && (part = ON_MODE_LINE)) 1216 && (part = ON_MODE_LINE))
1216 || (WINDOW_WANTS_HEADER_LINE_P (w) 1217 || (window_wants_header_line (w)
1217 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w) 1218 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1218 && (part = ON_HEADER_LINE))) 1219 && (part = ON_HEADER_LINE)))
1219 { 1220 {
@@ -1850,7 +1851,7 @@ Return nil if window display is not up-to-date. In that case, use
1850 1851
1851 if (EQ (line, Qheader_line)) 1852 if (EQ (line, Qheader_line))
1852 { 1853 {
1853 if (!WINDOW_WANTS_HEADER_LINE_P (w)) 1854 if (!window_wants_header_line (w))
1854 return Qnil; 1855 return Qnil;
1855 row = MATRIX_HEADER_LINE_ROW (w->current_matrix); 1856 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1856 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil; 1857 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
@@ -1897,6 +1898,129 @@ Return nil if window display is not up-to-date. In that case, use
1897 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop); 1898 return list4i (row->height + min (0, row->y) - crop, i, row->y, crop);
1898} 1899}
1899 1900
1901DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0,
1902 doc: /* Return pixel dimensions of WINDOW's lines.
1903The return value is a list of the x- and y-coordinates of the lower
1904right corner of the last character of each line. Return nil if the
1905current glyph matrix of WINDOW is not up-to-date.
1906
1907Optional argument WINDOW specifies the window whose lines' dimensions
1908shall be returned. Nil or omitted means to return the dimensions for
1909the selected window.
1910
1911FIRST, if non-nil, specifies the index of the first line whose
1912dimensions shall be returned. If FIRST is nil and BODY is non-nil,
1913start with the first text line of WINDOW. Otherwise, start with the
1914first line of WINDOW.
1915
1916LAST, if non-nil, specifies the last line whose dimensions shall be
1917returned. If LAST is nil and BODY is non-nil, the last line is the last
1918line of the body (text area) of WINDOW. Otherwise, last is the last
1919line of WINDOW.
1920
1921INVERSE, if nil, means that the y-pixel value returned for a specific
1922line specifies the distance in pixels from the left edge (body edge if
1923BODY is non-nil) of WINDOW to the right edge of the last glyph of that
1924line. INVERSE non-nil means that the y-pixel value returned for a
1925specific line specifies the distance in pixels from the right edge of
1926the last glyph of that line to the right edge (body edge if BODY is
1927non-nil) of WINDOW.
1928
1929LEFT non-nil means to return the x- and y-coordinates of the lower left
1930corner of the leftmost character on each line. This is the value that
1931should be used for buffers that mostly display text from right to left.
1932
1933If LEFT is non-nil and INVERSE is nil, this means that the y-pixel value
1934returned for a specific line specifies the distance in pixels from the
1935left edge of the last (leftmost) glyph of that line to the right edge
1936(body edge if BODY is non-nil) of WINDOW. If LEFT and INVERSE are both
1937non-nil, the y-pixel value returned for a specific line specifies the
1938distance in pixels from the left edge (body edge if BODY is non-nil) of
1939WINDOW to the left edge of the last (leftmost) glyph of that line.
1940
1941Normally, the value of this function is not available while Emacs is
1942busy, for example, when processing a command. It should be retrievable
1943though when run from an idle timer with a delay of zero seconds. */)
1944 (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left)
1945{
1946 struct window *w = decode_live_window (window);
1947 struct buffer *b;
1948 struct glyph_row *row, *end_row;
1949 int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
1950 Lisp_Object rows = Qnil;
1951 int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
1952 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
1953 int subtract = NILP (body) ? 0 : header_line_height;
1954 bool invert = !NILP (inverse);
1955 bool left_flag = !NILP (left);
1956
1957 if (noninteractive || w->pseudo_window_p)
1958 return Qnil;
1959
1960 CHECK_BUFFER (w->contents);
1961 b = XBUFFER (w->contents);
1962
1963 /* Fail if current matrix is not up-to-date. */
1964 if (!w->window_end_valid
1965 || windows_or_buffers_changed
1966 || b->clip_changed
1967 || b->prevent_redisplay_optimizations_p
1968 || window_outdated (w))
1969 return Qnil;
1970
1971 if (NILP (first))
1972 row = (NILP (body)
1973 ? MATRIX_ROW (w->current_matrix, 0)
1974 : MATRIX_FIRST_TEXT_ROW (w->current_matrix));
1975 else if (NUMBERP (first))
1976 {
1977 CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
1978 row = MATRIX_ROW (w->current_matrix, XINT (first));
1979 }
1980 else
1981 error ("Invalid specification of first line");
1982
1983 if (NILP (last))
1984
1985 end_row = (NILP (body)
1986 ? MATRIX_ROW (w->current_matrix, w->current_matrix->nrows)
1987 : MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w));
1988 else if (NUMBERP (last))
1989 {
1990 CHECK_RANGED_INTEGER (last, 0, w->current_matrix->nrows);
1991 end_row = MATRIX_ROW (w->current_matrix, XINT (last));
1992 }
1993 else
1994 error ("Invalid specification of last line");
1995
1996 while (row <= end_row && row->enabled_p
1997 && row->y + row->height < max_y)
1998 {
1999
2000 if (left_flag)
2001 {
2002 struct glyph *glyph = row->glyphs[TEXT_AREA];
2003
2004 rows = Fcons (Fcons (make_number
2005 (invert
2006 ? glyph->pixel_width
2007 : window_width - glyph->pixel_width),
2008 make_number (row->y + row->height - subtract)),
2009 rows);
2010 }
2011 else
2012 rows = Fcons (Fcons (make_number
2013 (invert
2014 ? window_width - row->pixel_width
2015 : row->pixel_width),
2016 make_number (row->y + row->height - subtract)),
2017 rows);
2018 row++;
2019 }
2020
2021 return Fnreverse (rows);
2022}
2023
1900DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p, 2024DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1901 0, 1, 0, 2025 0, 1, 0,
1902 doc: /* Return non-nil when WINDOW is dedicated to its buffer. 2026 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
@@ -2002,16 +2126,24 @@ return value is a list of elements of the form (PARAMETER . VALUE). */)
2002 return Fcopy_alist (decode_valid_window (window)->window_parameters); 2126 return Fcopy_alist (decode_valid_window (window)->window_parameters);
2003} 2127}
2004 2128
2129Lisp_Object
2130window_parameter (struct window *w, Lisp_Object parameter)
2131{
2132 Lisp_Object result = Fassq (parameter, w->window_parameters);
2133
2134 return CDR_SAFE (result);
2135}
2136
2137
2005DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter, 2138DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2006 2, 2, 0, 2139 2, 2, 0,
2007 doc: /* Return WINDOW's value for PARAMETER. 2140 doc: /* Return WINDOW's value for PARAMETER.
2008WINDOW can be any window and defaults to the selected one. */) 2141WINDOW can be any window and defaults to the selected one. */)
2009 (Lisp_Object window, Lisp_Object parameter) 2142 (Lisp_Object window, Lisp_Object parameter)
2010{ 2143{
2011 Lisp_Object result; 2144 struct window *w = decode_any_window (window);
2012 2145
2013 result = Fassq (parameter, decode_any_window (window)->window_parameters); 2146 return window_parameter (w, parameter);
2014 return CDR_SAFE (result);
2015} 2147}
2016 2148
2017DEFUN ("set-window-parameter", Fset_window_parameter, 2149DEFUN ("set-window-parameter", Fset_window_parameter,
@@ -3314,6 +3446,9 @@ run_window_size_change_functions (Lisp_Object frame)
3314 Lisp_Object functions = Vwindow_size_change_functions; 3446 Lisp_Object functions = Vwindow_size_change_functions;
3315 3447
3316 if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) 3448 if (FRAME_WINDOW_CONFIGURATION_CHANGED (f)
3449 /* Here we implicitly exclude the possibility that the height of
3450 FRAME and its minibuffer window both change leaving the height
3451 of FRAME's root window alone. */
3317 || window_size_changed (r)) 3452 || window_size_changed (r))
3318 { 3453 {
3319 while (CONSP (functions)) 3454 while (CONSP (functions))
@@ -3324,6 +3459,12 @@ run_window_size_change_functions (Lisp_Object frame)
3324 } 3459 }
3325 3460
3326 window_set_before_size_change_sizes (r); 3461 window_set_before_size_change_sizes (r);
3462
3463 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f))
3464 /* Record size of FRAME's minibuffer window too. */
3465 window_set_before_size_change_sizes
3466 (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
3467
3327 FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; 3468 FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false;
3328 } 3469 }
3329} 3470}
@@ -3332,7 +3473,7 @@ run_window_size_change_functions (Lisp_Object frame)
3332/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed 3473/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
3333 to run hooks. See make_frame for a case where it's not allowed. 3474 to run hooks. See make_frame for a case where it's not allowed.
3334 KEEP_MARGINS_P means that the current margins, fringes, and 3475 KEEP_MARGINS_P means that the current margins, fringes, and
3335 scroll-bar settings of the window are not reset from the buffer's 3476 scroll bar settings of the window are not reset from the buffer's
3336 local settings. */ 3477 local settings. */
3337 3478
3338void 3479void
@@ -4730,6 +4871,69 @@ mark_window_cursors_off (struct window *w)
4730} 4871}
4731 4872
4732 4873
4874/**
4875 * window_wants_mode_line:
4876 *
4877 * Return 1 if window W wants a mode line and is high enough to
4878 * accomodate it, 0 otherwise.
4879 *
4880 * W wants a mode line if it's a leaf window and neither a minibuffer
4881 * nor a pseudo window. Moreover, its 'window-mode-line-format'
4882 * parameter must not be 'none' and either that parameter or W's
4883 * buffer's 'mode-line-format' value must be non-nil. Finally, W must
4884 * be higher than its frame's canonical character height.
4885 */
4886bool
4887window_wants_mode_line (struct window *w)
4888{
4889 Lisp_Object window_mode_line_format =
4890 window_parameter (w, Qmode_line_format);
4891
4892 return ((WINDOW_LEAF_P (w)
4893 && !MINI_WINDOW_P (w)
4894 && !WINDOW_PSEUDO_P (w)
4895 && !EQ (window_mode_line_format, Qnone)
4896 && (!NILP (window_mode_line_format)
4897 || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format)))
4898 && WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w))
4899 ? 1
4900 : 0);
4901}
4902
4903
4904/**
4905 * window_wants_header_line:
4906 *
4907 * Return 1 if window W wants a header line and is high enough to
4908 * accomodate it, 0 otherwise.
4909 *
4910 * W wants a header line if it's a leaf window and neither a minibuffer
4911 * nor a pseudo window. Moreover, its 'window-mode-line-format'
4912 * parameter must not be 'none' and either that parameter or W's
4913 * buffer's 'mode-line-format' value must be non-nil. Finally, W must
4914 * be higher than its frame's canonical character height and be able to
4915 * accomodate a mode line too if necessary (the mode line prevails).
4916 */
4917bool
4918window_wants_header_line (struct window *w)
4919{
4920 Lisp_Object window_header_line_format =
4921 window_parameter (w, Qheader_line_format);
4922
4923 return ((WINDOW_LEAF_P (w)
4924 && !MINI_WINDOW_P (w)
4925 && !WINDOW_PSEUDO_P (w)
4926 && !EQ (window_header_line_format, Qnone)
4927 && (!NILP (window_header_line_format)
4928 || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
4929 && (WINDOW_PIXEL_HEIGHT (w)
4930 > (window_wants_mode_line (w)
4931 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
4932 : WINDOW_FRAME_LINE_HEIGHT (w))))
4933 ? 1
4934 : 0);
4935}
4936
4733/* Return number of lines of text (not counting mode lines) in W. */ 4937/* Return number of lines of text (not counting mode lines) in W. */
4734 4938
4735int 4939int
@@ -4743,10 +4947,10 @@ window_internal_height (struct window *w)
4743 || WINDOWP (w->contents) 4947 || WINDOWP (w->contents)
4744 || !NILP (w->next) 4948 || !NILP (w->next)
4745 || !NILP (w->prev) 4949 || !NILP (w->prev)
4746 || WINDOW_WANTS_MODELINE_P (w)) 4950 || window_wants_mode_line (w))
4747 --ht; 4951 --ht;
4748 4952
4749 if (WINDOW_WANTS_HEADER_LINE_P (w)) 4953 if (window_wants_header_line (w))
4750 --ht; 4954 --ht;
4751 } 4955 }
4752 4956
@@ -7035,16 +7239,18 @@ DEFUN ("set-window-scroll-bars", Fset_window_scroll_bars,
7035WINDOW must be a live window and defaults to the selected one. 7239WINDOW must be a live window and defaults to the selected one.
7036 7240
7037Second parameter WIDTH specifies the pixel width for the vertical scroll 7241Second parameter WIDTH specifies the pixel width for the vertical scroll
7038bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame. 7242bar. If WIDTH is nil, use the scroll bar width of WINDOW's frame.
7039Third parameter VERTICAL-TYPE specifies the type of the vertical scroll 7243Third parameter VERTICAL-TYPE specifies the type of the vertical scroll
7040bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the 7244bar: left, right, nil or t where nil means to not display a vertical
7041frame's scroll-bar type. 7245scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll
7246bar type.
7042 7247
7043Fourth parameter HEIGHT specifies the pixel height for the horizontal 7248Fourth parameter HEIGHT specifies the pixel height for the horizontal
7044scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's 7249scroll bar. If HEIGHT is nil, use the scroll bar height of WINDOW's
7045frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the 7250frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the
7046horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this 7251horizontal scroll bar: bottom, nil, or t where nil means to not display
7047means to use the frame's horizontal scroll-bar type. 7252a horizontal scroll bar on WINDOW and t means to use WINDOW frame's
7253horizontal scroll bar type.
7048 7254
7049Return t if scroll bars were actually changed and nil otherwise. */) 7255Return t if scroll bars were actually changed and nil otherwise. */)
7050 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type, 7256 (Lisp_Object window, Lisp_Object width, Lisp_Object vertical_type,
@@ -7341,6 +7547,9 @@ syms_of_window (void)
7341 DEFSYM (Qclone_of, "clone-of"); 7547 DEFSYM (Qclone_of, "clone-of");
7342 DEFSYM (Qfloor, "floor"); 7548 DEFSYM (Qfloor, "floor");
7343 DEFSYM (Qceiling, "ceiling"); 7549 DEFSYM (Qceiling, "ceiling");
7550 DEFSYM (Qmark_for_redisplay, "mark-for-redisplay");
7551 DEFSYM (Qmode_line_format, "mode-line-format");
7552 DEFSYM (Qheader_line_format, "header-line-format");
7344 7553
7345 staticpro (&Vwindow_list); 7554 staticpro (&Vwindow_list);
7346 7555
@@ -7457,9 +7666,14 @@ nil means splitting a window will create a new parent window only if the
7457 `window-height' or `window-width' entry in the alist used by 7666 `window-height' or `window-width' entry in the alist used by
7458 `display-buffer'. Otherwise, this value is handled like nil. 7667 `display-buffer'. Otherwise, this value is handled like nil.
7459 7668
7669`temp-buffer-resize' means that splitting a window for displaying a
7670 temporary buffer via `with-temp-buffer-window' makes a new parent
7671 window only if `temp-buffer-resize-mode' is enabled. Otherwise,
7672 this value is handled like nil.
7673
7460`temp-buffer' means that splitting a window for displaying a temporary 7674`temp-buffer' means that splitting a window for displaying a temporary
7461 buffer always makes a new parent window. Otherwise, this value is 7675 buffer via `with-temp-buffer-window' always makes a new parent
7462 handled like nil. 7676 window. Otherwise, this value is handled like nil.
7463 7677
7464`display-buffer' means that splitting a window for displaying a buffer 7678`display-buffer' means that splitting a window for displaying a buffer
7465 always makes a new parent window. Since temporary buffers are 7679 always makes a new parent window. Since temporary buffers are
@@ -7472,7 +7686,8 @@ t means that splitting a window always creates a new parent window. If
7472 tree and every window but the frame's root window has exactly one 7686 tree and every window but the frame's root window has exactly one
7473 sibling. 7687 sibling.
7474 7688
7475Other values are reserved for future use. */); 7689The default value is `window-size'. Other values are reserved for
7690future use. */);
7476 Vwindow_combination_limit = Qwindow_size; 7691 Vwindow_combination_limit = Qwindow_size;
7477 7692
7478 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters, 7693 DEFVAR_LISP ("window-persistent-parameters", Vwindow_persistent_parameters,
@@ -7584,6 +7799,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
7584 defsubr (&Sset_window_point); 7799 defsubr (&Sset_window_point);
7585 defsubr (&Sset_window_start); 7800 defsubr (&Sset_window_start);
7586 defsubr (&Swindow_dedicated_p); 7801 defsubr (&Swindow_dedicated_p);
7802 defsubr (&Swindow_lines_pixel_dimensions);
7587 defsubr (&Sset_window_dedicated_p); 7803 defsubr (&Sset_window_dedicated_p);
7588 defsubr (&Swindow_display_table); 7804 defsubr (&Swindow_display_table);
7589 defsubr (&Sset_window_display_table); 7805 defsubr (&Sset_window_display_table);
diff --git a/src/window.h b/src/window.h
index acb8a5cabfa..e9040f816df 100644
--- a/src/window.h
+++ b/src/window.h
@@ -328,8 +328,9 @@ struct window
328 /* True if this window is a minibuffer window. */ 328 /* True if this window is a minibuffer window. */
329 bool_bf mini : 1; 329 bool_bf mini : 1;
330 330
331 /* Meaningful only if contents is a window, true if this 331 /* Meaningful for internal windows only: true if this window is a
332 internal window is used in horizontal combination. */ 332 horizontal combination, false if it is a vertical
333 combination. */
333 bool_bf horizontal : 1; 334 bool_bf horizontal : 1;
334 335
335 /* True means must regenerate mode line of this window. */ 336 /* True means must regenerate mode line of this window. */
@@ -481,15 +482,14 @@ wset_next_buffers (struct window *w, Lisp_Object val)
481/* True if W is a minibuffer window. */ 482/* True if W is a minibuffer window. */
482#define MINI_WINDOW_P(W) ((W)->mini) 483#define MINI_WINDOW_P(W) ((W)->mini)
483 484
484/* 1 if W is a non-only minibuffer window. */ 485/* True if W is a minibuffer window on a frame that contains at least
485/* The first check is redundant and the second overly complicated. */ 486 one other window. */
486#define MINI_NON_ONLY_WINDOW_P(W) \ 487#define MINI_NON_ONLY_WINDOW_P(W) \
487 (MINI_WINDOW_P (W) \ 488 (MINI_WINDOW_P (W) && !NILP ((W)->prev))
488 && (EQ (W->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))
489 489
490/* 1 if W is a minibuffer-only window. */ 490/* True if W is a minibuffer window that is alone on its frame. */
491#define MINI_ONLY_WINDOW_P(W) \ 491#define MINI_ONLY_WINDOW_P(W) \
492 (MINI_WINDOW_P (W) && NILP (W->prev)) 492 (MINI_WINDOW_P (W) && NILP ((W)->prev))
493 493
494/* General window layout: 494/* General window layout:
495 495
@@ -518,29 +518,34 @@ wset_next_buffers (struct window *w, Lisp_Object val)
518 518
519/* A handy macro. */ 519/* A handy macro. */
520 520
521/* Non-nil if W is leaf (carry the buffer). */ 521/* Non-nil if window W is leaf window (has a buffer). */
522
523#define WINDOW_LEAF_P(W) \ 522#define WINDOW_LEAF_P(W) \
524 (BUFFERP ((W)->contents)) 523 (BUFFERP ((W)->contents))
525 524
526/* Non-nil if W is internal. */ 525/* Non-nil if window W is internal (is a parent window). */
527#define WINDOW_INTERNAL_P(W) \ 526#define WINDOW_INTERNAL_P(W) \
528 (WINDOWP ((W)->contents)) 527 (WINDOWP ((W)->contents))
529 528
530/* True if W is a member of horizontal combination. */ 529/* True if window W is a horizontal combination of windows. */
531#define WINDOW_HORIZONTAL_COMBINATION_P(W) \ 530#define WINDOW_HORIZONTAL_COMBINATION_P(W) \
532 (WINDOW_INTERNAL_P (W) && (W)->horizontal) 531 (WINDOW_INTERNAL_P (W) && (W)->horizontal)
533 532
534/* True if W is a member of vertical combination. */ 533/* True if window W is a vertical combination of windows. */
535#define WINDOW_VERTICAL_COMBINATION_P(W) \ 534#define WINDOW_VERTICAL_COMBINATION_P(W) \
536 (WINDOW_INTERNAL_P (W) && !(W)->horizontal) 535 (WINDOW_INTERNAL_P (W) && !(W)->horizontal)
537 536
538/* WINDOW's XFRAME. */ 537/* Window W's XFRAME. */
539#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) 538#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W))))
540 539
541/* Whether WINDOW is a pseudo window. */ 540/* Whether window W is a pseudo window. */
542#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p) 541#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p)
543 542
543/* Window W's buffer. */
544#define WINDOW_BUFFER(W) \
545 (WINDOW_LEAF_P(W) \
546 ? (W)->contents \
547 : Qnil) \
548
544/* Return the canonical column width of the frame of window W. */ 549/* Return the canonical column width of the frame of window W. */
545#define WINDOW_FRAME_COLUMN_WIDTH(W) \ 550#define WINDOW_FRAME_COLUMN_WIDTH(W) \
546 (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W)))) 551 (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W))))
@@ -549,24 +554,24 @@ wset_next_buffers (struct window *w, Lisp_Object val)
549#define WINDOW_FRAME_LINE_HEIGHT(W) \ 554#define WINDOW_FRAME_LINE_HEIGHT(W) \
550 (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W)))) 555 (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W))))
551 556
552/* Return the pixel width of window W. 557/* Return the pixel width of window W. This includes dividers, scroll
553 This includes scroll bars and fringes. */ 558 bars, fringes and margins, if any. */
554#define WINDOW_PIXEL_WIDTH(W) (W)->pixel_width 559#define WINDOW_PIXEL_WIDTH(W) (W)->pixel_width
555 560
556/* Return the pixel height of window W. 561/* Return the pixel height of window W. This includes dividers, scroll
557 This includes header and mode lines, if any. */ 562 bars, header and mode lines, if any. */
558#define WINDOW_PIXEL_HEIGHT(W) (W)->pixel_height 563#define WINDOW_PIXEL_HEIGHT(W) (W)->pixel_height
559 564
560/* Return the width of window W in canonical column units. 565/* Return the width of window W in canonical column units. This
561 This includes scroll bars and fringes. 566 includes dividers, scroll bars, fringes and margins, if any. The
562 This value is adjusted such that the sum of the widths of all child 567 value is adjusted such that the sum of the widths of all child
563 windows equals the width of their parent window. */ 568 windows equals the width of their parent window. */
564#define WINDOW_TOTAL_COLS(W) (W)->total_cols 569#define WINDOW_TOTAL_COLS(W) (W)->total_cols
565 570
566/* Return the height of window W in canonical line units. 571/* Return the height of window W in canonical line units. This includes
567 This includes header and mode lines, if any. 572 dividers, scroll bars, header and mode lines, if any. The value is
568 This value is adjusted such that the sum of the heights of all child 573 adjusted such that the sum of the heights of all child windows equals
569 windows equals the height of their parent window. */ 574 the height of their parent window. */
570#define WINDOW_TOTAL_LINES(W) (W)->total_lines 575#define WINDOW_TOTAL_LINES(W) (W)->total_lines
571 576
572/* The smallest acceptable dimensions for a window. Anything smaller 577/* The smallest acceptable dimensions for a window. Anything smaller
@@ -581,31 +586,63 @@ wset_next_buffers (struct window *w, Lisp_Object val)
581#define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \ 586#define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \
582 (WINDOW_FRAME_LINE_HEIGHT (W)) 587 (WINDOW_FRAME_LINE_HEIGHT (W))
583 588
589/* True if window W has no other windows to its left on its frame. */
590#define WINDOW_LEFTMOST_P(W) \
591 (WINDOW_LEFT_PIXEL_EDGE (W) == 0)
592
593/* True if window W has no other windows above it on its frame. */
594#define WINDOW_TOPMOST_P(W) \
595 (WINDOW_TOP_PIXEL_EDGE (W) == 0)
596
597/* True if window W has no other windows to its right on its frame. */
598#define WINDOW_RIGHTMOST_P(W) \
599 (WINDOW_RIGHT_PIXEL_EDGE (W) \
600 == (WINDOW_RIGHT_PIXEL_EDGE \
601 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
602
603/* True if window W has no other windows below it on its frame (the
604 minibuffer window is not counted in this respect unless W itself is a
605 minibuffer window). */
606#define WINDOW_BOTTOMMOST_P(W) \
607 (WINDOW_BOTTOM_PIXEL_EDGE (W) \
608 == (WINDOW_BOTTOM_PIXEL_EDGE \
609 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
610
611/* True if window W takes up the full width of its frame. */
612#define WINDOW_FULL_WIDTH_P(W) \
613 (WINDOW_PIXEL_WIDTH (W) \
614 == (WINDOW_PIXEL_WIDTH \
615 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
616
584/* Width of right divider of window W. */ 617/* Width of right divider of window W. */
585#define WINDOW_RIGHT_DIVIDER_WIDTH(W) \ 618#define WINDOW_RIGHT_DIVIDER_WIDTH(W) \
586 ((WINDOW_RIGHTMOST_P (W) || MINI_WINDOW_P (W)) \ 619 (WINDOW_RIGHTMOST_P (W) \
587 ? 0 \ 620 ? 0 : FRAME_RIGHT_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
588 : FRAME_RIGHT_DIVIDER_WIDTH (WINDOW_XFRAME (W))) 621
622/* Width of bottom divider of window W. */
623#define WINDOW_BOTTOM_DIVIDER_WIDTH(W) \
624 (((WINDOW_BOTTOMMOST_P (W) \
625 && NILP ((XWINDOW (FRAME_ROOT_WINDOW \
626 (WINDOW_XFRAME (W))))->next)) \
627 || EQ ((W)->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))) \
628 || (W)->pseudo_window_p) \
629 ? 0 : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
589 630
590/* Return the canonical frame column at which window W starts. 631/* Return the canonical frame column at which window W starts.
591 This includes a left-hand scroll bar, if any. */ 632 This includes a left-hand scroll bar, if any. */
592
593#define WINDOW_LEFT_EDGE_COL(W) (W)->left_col 633#define WINDOW_LEFT_EDGE_COL(W) (W)->left_col
594 634
595/* Return the canonical frame column before which window W ends. 635/* Return the canonical frame column before which window W ends.
596 This includes a right-hand scroll bar, if any. */ 636 This includes a right-hand scroll bar, if any. */
597
598#define WINDOW_RIGHT_EDGE_COL(W) \ 637#define WINDOW_RIGHT_EDGE_COL(W) \
599 (WINDOW_LEFT_EDGE_COL (W) + WINDOW_TOTAL_COLS (W)) 638 (WINDOW_LEFT_EDGE_COL (W) + WINDOW_TOTAL_COLS (W))
600 639
601/* Return the canonical frame line at which window W starts. 640/* Return the canonical frame line at which window W starts.
602 This includes a header line, if any. */ 641 This includes a header line, if any. */
603
604#define WINDOW_TOP_EDGE_LINE(W) (W)->top_line 642#define WINDOW_TOP_EDGE_LINE(W) (W)->top_line
605 643
606/* Return the canonical frame line before which window W ends. 644/* Return the canonical frame line before which window W ends.
607 This includes a mode line, if any. */ 645 This includes a mode line, if any. */
608
609#define WINDOW_BOTTOM_EDGE_LINE(W) \ 646#define WINDOW_BOTTOM_EDGE_LINE(W) \
610 (WINDOW_TOP_EDGE_LINE (W) + WINDOW_TOTAL_LINES (W)) 647 (WINDOW_TOP_EDGE_LINE (W) + WINDOW_TOTAL_LINES (W))
611 648
@@ -629,20 +666,17 @@ wset_next_buffers (struct window *w, Lisp_Object val)
629 666
630/* Return the frame x-position at which window W starts. 667/* Return the frame x-position at which window W starts.
631 This includes a left-hand scroll bar, if any. */ 668 This includes a left-hand scroll bar, if any. */
632
633#define WINDOW_LEFT_EDGE_X(W) \ 669#define WINDOW_LEFT_EDGE_X(W) \
634 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 670 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
635 + WINDOW_LEFT_PIXEL_EDGE (W)) 671 + WINDOW_LEFT_PIXEL_EDGE (W))
636 672
637/* Return the frame x- position before which window W ends. 673/* Return the frame x- position before which window W ends.
638 This includes a right-hand scroll bar, if any. */ 674 This includes a right-hand scroll bar, if any. */
639
640#define WINDOW_RIGHT_EDGE_X(W) \ 675#define WINDOW_RIGHT_EDGE_X(W) \
641 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 676 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
642 + WINDOW_RIGHT_PIXEL_EDGE (W)) 677 + WINDOW_RIGHT_PIXEL_EDGE (W))
643 678
644/* True if W is a menu bar window. */ 679/* True if W is a menu bar window. */
645
646#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) 680#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
647#define WINDOW_MENU_BAR_P(W) \ 681#define WINDOW_MENU_BAR_P(W) \
648 (WINDOWP (WINDOW_XFRAME (W)->menu_bar_window) \ 682 (WINDOWP (WINDOW_XFRAME (W)->menu_bar_window) \
@@ -661,72 +695,24 @@ wset_next_buffers (struct window *w, Lisp_Object val)
661#define WINDOW_TOOL_BAR_P(W) false 695#define WINDOW_TOOL_BAR_P(W) false
662#endif 696#endif
663 697
664/* Return the frame y-position at which window W starts. 698/* Return the frame y-position at which window W starts. */
665 This includes a header line, if any.
666
667 PXW: With a menu or tool bar this is not symmetric to the _X values
668 since it _does_ include the internal border width. */
669#define WINDOW_TOP_EDGE_Y(W) \ 699#define WINDOW_TOP_EDGE_Y(W) \
670 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \ 700 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
671 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \ 701 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
672 + WINDOW_TOP_PIXEL_EDGE (W)) 702 + WINDOW_TOP_PIXEL_EDGE (W))
673 703
674/* Return the frame y-position before which window W ends. 704/* Return the frame y-position before which window W ends. */
675 This includes a mode line, if any. */
676#define WINDOW_BOTTOM_EDGE_Y(W) \ 705#define WINDOW_BOTTOM_EDGE_Y(W) \
677 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \ 706 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
678 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \ 707 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
679 + WINDOW_BOTTOM_PIXEL_EDGE (W)) 708 + WINDOW_BOTTOM_PIXEL_EDGE (W))
680 709
681/* True if window W takes up the full width of its frame. */ 710/* Return the pixel value where the text (or left fringe) in window W
682#define WINDOW_FULL_WIDTH_P(W) \ 711 starts. */
683 (WINDOW_PIXEL_WIDTH (W) \
684 == (WINDOW_PIXEL_WIDTH \
685 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
686
687/* True if window W's has no other windows to its left in its frame. */
688
689#define WINDOW_LEFTMOST_P(W) \
690 (WINDOW_LEFT_PIXEL_EDGE (W) == 0)
691
692/* True if window W's has no other windows above in its frame. */
693#define WINDOW_TOPMOST_P(W) \
694 (WINDOW_TOP_PIXEL_EDGE (W) == 0)
695
696/* True if window W's has no other windows to its right in its frame. */
697#define WINDOW_RIGHTMOST_P(W) \
698 (WINDOW_RIGHT_PIXEL_EDGE (W) \
699 == (WINDOW_RIGHT_PIXEL_EDGE \
700 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
701
702/* True if window W's has no other windows below it in its frame
703 (the minibuffer window is not counted in this respect). */
704#define WINDOW_BOTTOMMOST_P(W) \
705 (WINDOW_BOTTOM_PIXEL_EDGE (W) \
706 == (WINDOW_BOTTOM_PIXEL_EDGE \
707 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
708
709/* Return the frame column at which the text (or left fringe) in
710 window W starts. This is different from the `LEFT_EDGE' because it
711 does not include a left-hand scroll bar if any. */
712#define WINDOW_BOX_LEFT_EDGE_COL(W) \
713 (WINDOW_LEFT_EDGE_COL (W) \
714 + WINDOW_LEFT_SCROLL_BAR_COLS (W))
715
716/* Return the pixel value where the text (or left fringe) in
717 window W starts. This is different from the `LEFT_EDGE' because it
718 does not include a left-hand scroll bar if any. */
719#define WINDOW_BOX_LEFT_PIXEL_EDGE(W) \ 712#define WINDOW_BOX_LEFT_PIXEL_EDGE(W) \
720 (WINDOW_LEFT_PIXEL_EDGE (W) \ 713 (WINDOW_LEFT_PIXEL_EDGE (W) \
721 + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (W)) 714 + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (W))
722 715
723/* Return the window column before which the text in window W ends.
724 This is different from WINDOW_RIGHT_EDGE_COL because it does not
725 include a scroll bar or window-separating line on the right edge. */
726#define WINDOW_BOX_RIGHT_EDGE_COL(W) \
727 (WINDOW_RIGHT_EDGE_COL (W) \
728 - WINDOW_RIGHT_SCROLL_BAR_COLS (W))
729
730/* Return the pixel value before which the text in window W ends. This 716/* Return the pixel value before which the text in window W ends. This
731 is different from the `RIGHT_EDGE' because it does not include a 717 is different from the `RIGHT_EDGE' because it does not include a
732 right-hand scroll bar or window-separating line on the right 718 right-hand scroll bar or window-separating line on the right
@@ -736,16 +722,16 @@ wset_next_buffers (struct window *w, Lisp_Object val)
736 - WINDOW_RIGHT_DIVIDER_WIDTH (W) \ 722 - WINDOW_RIGHT_DIVIDER_WIDTH (W) \
737 - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (W)) 723 - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (W))
738 724
739/* Return the frame position at which the text (or left fringe) in 725/* Return the frame x-position at which the text (or left fringe) in
740 window W starts. This is different from the `LEFT_EDGE' because it 726 window W starts. This does not include a left-hand scroll bar if
741 does not include a left-hand scroll bar if any. */ 727 any. */
742#define WINDOW_BOX_LEFT_EDGE_X(W) \ 728#define WINDOW_BOX_LEFT_EDGE_X(W) \
743 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 729 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
744 + WINDOW_BOX_LEFT_PIXEL_EDGE (W)) 730 + WINDOW_BOX_LEFT_PIXEL_EDGE (W))
745 731
746/* Return the window column before which the text in window W ends. 732/* Return the frame x-position before which the text in window W ends.
747 This is different from WINDOW_RIGHT_EDGE_COL because it does not 733 This does not include a scroll bar, divider or window-separating line
748 include a scroll bar or window-separating line on the right edge. */ 734 on the right edge. */
749#define WINDOW_BOX_RIGHT_EDGE_X(W) \ 735#define WINDOW_BOX_RIGHT_EDGE_X(W) \
750 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 736 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
751 + WINDOW_BOX_RIGHT_PIXEL_EDGE (W)) 737 + WINDOW_BOX_RIGHT_PIXEL_EDGE (W))
@@ -899,16 +885,6 @@ wset_next_buffers (struct window *w, Lisp_Object val)
899 ? WINDOW_BOX_RIGHT_EDGE_X (W) \ 885 ? WINDOW_BOX_RIGHT_EDGE_X (W) \
900 : WINDOW_LEFT_EDGE_X (W)) 886 : WINDOW_LEFT_EDGE_X (W))
901 887
902/* Width of bottom divider of window W. */
903#define WINDOW_BOTTOM_DIVIDER_WIDTH(W) \
904 (((WINDOW_BOTTOMMOST_P (W) \
905 && NILP ((XWINDOW (FRAME_ROOT_WINDOW \
906 (WINDOW_XFRAME (W))))->next)) \
907 || EQ ((W)->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))) \
908 || (W)->pseudo_window_p) \
909 ? 0 \
910 : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
911
912/* Height that a scroll bar in window W should have, if there is one. 888/* Height that a scroll bar in window W should have, if there is one.
913 Measured in pixels. If scroll bars are turned off, this is still 889 Measured in pixels. If scroll bars are turned off, this is still
914 nonzero. */ 890 nonzero. */
@@ -942,22 +918,22 @@ wset_next_buffers (struct window *w, Lisp_Object val)
942/* Height in pixels of the mode line. 918/* Height in pixels of the mode line.
943 May be zero if W doesn't have a mode line. */ 919 May be zero if W doesn't have a mode line. */
944#define WINDOW_MODE_LINE_HEIGHT(W) \ 920#define WINDOW_MODE_LINE_HEIGHT(W) \
945 (WINDOW_WANTS_MODELINE_P ((W)) \ 921 (window_wants_mode_line ((W)) \
946 ? CURRENT_MODE_LINE_HEIGHT (W) \ 922 ? CURRENT_MODE_LINE_HEIGHT (W) \
947 : 0) 923 : 0)
948 924
949#define WINDOW_MODE_LINE_LINES(W) \ 925#define WINDOW_MODE_LINE_LINES(W) \
950 WINDOW_WANTS_MODELINE_P (W) 926 window_wants_mode_line (W)
951 927
952/* Height in pixels of the header line. 928/* Height in pixels of the header line.
953 Zero if W doesn't have a header line. */ 929 Zero if W doesn't have a header line. */
954#define WINDOW_HEADER_LINE_HEIGHT(W) \ 930#define WINDOW_HEADER_LINE_HEIGHT(W) \
955 (WINDOW_WANTS_HEADER_LINE_P (W) \ 931 (window_wants_header_line (W) \
956 ? CURRENT_HEADER_LINE_HEIGHT (W) \ 932 ? CURRENT_HEADER_LINE_HEIGHT (W) \
957 : 0) 933 : 0)
958 934
959#define WINDOW_HEADER_LINE_LINES(W) \ 935#define WINDOW_HEADER_LINE_LINES(W) \
960 WINDOW_WANTS_HEADER_LINE_P (W) 936 window_wants_header_line (W)
961 937
962/* Pixel height of window W without mode line, bottom scroll bar and 938/* Pixel height of window W without mode line, bottom scroll bar and
963 bottom divider. */ 939 bottom divider. */
@@ -1114,10 +1090,13 @@ struct glyph *get_phys_cursor_glyph (struct window *w);
1114extern Lisp_Object Vwindow_list; 1090extern Lisp_Object Vwindow_list;
1115 1091
1116extern Lisp_Object window_list (void); 1092extern Lisp_Object window_list (void);
1093extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter);
1117extern struct window *decode_live_window (Lisp_Object); 1094extern struct window *decode_live_window (Lisp_Object);
1118extern struct window *decode_any_window (Lisp_Object); 1095extern struct window *decode_any_window (Lisp_Object);
1119extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool); 1096extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
1120extern void mark_window_cursors_off (struct window *); 1097extern void mark_window_cursors_off (struct window *);
1098extern bool window_wants_mode_line (struct window *);
1099extern bool window_wants_header_line (struct window *);
1121extern int window_internal_height (struct window *); 1100extern int window_internal_height (struct window *);
1122extern int window_body_width (struct window *w, bool); 1101extern int window_body_width (struct window *w, bool);
1123enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; 1102enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
@@ -1133,7 +1112,6 @@ extern void init_window_once (void);
1133extern void init_window (void); 1112extern void init_window (void);
1134extern void syms_of_window (void); 1113extern void syms_of_window (void);
1135extern void keys_of_window (void); 1114extern void keys_of_window (void);
1136
1137/* Move cursor to row/column position VPOS/HPOS, pixel coordinates 1115/* Move cursor to row/column position VPOS/HPOS, pixel coordinates
1138 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y 1116 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y
1139 are window-relative pixel positions. This is always done during 1117 are window-relative pixel positions. This is always done during
diff --git a/src/xdisp.c b/src/xdisp.c
index af086d17eb8..8bc5d81f448 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -476,7 +476,7 @@ int windows_or_buffers_changed;
476 used to track down the cause for this full-redisplay). 476 used to track down the cause for this full-redisplay).
477 477
478 Since the frame title uses the same %-constructs as the mode line 478 Since the frame title uses the same %-constructs as the mode line
479 (except %c and %l), if this variable is non-zero, we also consider 479 (except %c, %C, and %l), if this variable is non-zero, we also consider
480 redisplaying the title of each frame, see x_consider_frame_title. 480 redisplaying the title of each frame, see x_consider_frame_title.
481 481
482 The `redisplay' bits are the same as those used for 482 The `redisplay' bits are the same as those used for
@@ -832,7 +832,7 @@ static bool cursor_row_fully_visible_p (struct window *, bool, bool);
832static bool update_menu_bar (struct frame *, bool, bool); 832static bool update_menu_bar (struct frame *, bool, bool);
833static bool try_window_reusing_current_matrix (struct window *); 833static bool try_window_reusing_current_matrix (struct window *);
834static int try_window_id (struct window *); 834static int try_window_id (struct window *);
835static bool display_line (struct it *); 835static bool display_line (struct it *, int);
836static int display_mode_lines (struct window *); 836static int display_mode_lines (struct window *);
837static int display_mode_line (struct window *, enum face_id, Lisp_Object); 837static int display_mode_line (struct window *, enum face_id, Lisp_Object);
838static int display_mode_element (struct it *, int, int, int, Lisp_Object, 838static int display_mode_element (struct it *, int, int, int, Lisp_Object,
@@ -921,7 +921,7 @@ window_text_bottom_y (struct window *w)
921 921
922 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w); 922 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
923 923
924 if (WINDOW_WANTS_MODELINE_P (w)) 924 if (window_wants_mode_line (w))
925 height -= CURRENT_MODE_LINE_HEIGHT (w); 925 height -= CURRENT_MODE_LINE_HEIGHT (w);
926 926
927 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w); 927 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
@@ -978,7 +978,7 @@ window_box_height (struct window *w)
978 the appropriate glyph row has its `mode_line_p' flag set, 978 the appropriate glyph row has its `mode_line_p' flag set,
979 and if it doesn't, uses estimate_mode_line_height instead. */ 979 and if it doesn't, uses estimate_mode_line_height instead. */
980 980
981 if (WINDOW_WANTS_MODELINE_P (w)) 981 if (window_wants_mode_line (w))
982 { 982 {
983 struct glyph_row *ml_row 983 struct glyph_row *ml_row
984 = (w->current_matrix && w->current_matrix->rows 984 = (w->current_matrix && w->current_matrix->rows
@@ -990,7 +990,7 @@ window_box_height (struct window *w)
990 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w)); 990 height -= estimate_mode_line_height (f, CURRENT_MODE_LINE_FACE_ID (w));
991 } 991 }
992 992
993 if (WINDOW_WANTS_HEADER_LINE_P (w)) 993 if (window_wants_header_line (w))
994 { 994 {
995 struct glyph_row *hl_row 995 struct glyph_row *hl_row
996 = (w->current_matrix && w->current_matrix->rows 996 = (w->current_matrix && w->current_matrix->rows
@@ -1102,7 +1102,7 @@ window_box (struct window *w, enum glyph_row_area area, int *box_x,
1102 if (box_y) 1102 if (box_y)
1103 { 1103 {
1104 *box_y = WINDOW_TOP_EDGE_Y (w); 1104 *box_y = WINDOW_TOP_EDGE_Y (w);
1105 if (WINDOW_WANTS_HEADER_LINE_P (w)) 1105 if (window_wants_header_line (w))
1106 *box_y += CURRENT_HEADER_LINE_HEIGHT (w); 1106 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1107 } 1107 }
1108} 1108}
@@ -1322,15 +1322,29 @@ pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1322 return visible_p; 1322 return visible_p;
1323 1323
1324 /* Compute exact mode line heights. */ 1324 /* Compute exact mode line heights. */
1325 if (WINDOW_WANTS_MODELINE_P (w)) 1325 if (window_wants_mode_line (w))
1326 w->mode_line_height 1326 {
1327 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w), 1327 Lisp_Object window_mode_line_format
1328 BVAR (current_buffer, mode_line_format)); 1328 = window_parameter (w, Qmode_line_format);
1329
1330 w->mode_line_height
1331 = display_mode_line (w, CURRENT_MODE_LINE_FACE_ID (w),
1332 NILP (window_mode_line_format)
1333 ? BVAR (current_buffer, mode_line_format)
1334 : window_mode_line_format);
1335 }
1329 1336
1330 if (WINDOW_WANTS_HEADER_LINE_P (w)) 1337 if (window_wants_header_line (w))
1331 w->header_line_height 1338 {
1332 = display_mode_line (w, HEADER_LINE_FACE_ID, 1339 Lisp_Object window_header_line_format
1333 BVAR (current_buffer, header_line_format)); 1340 = window_parameter (w, Qheader_line_format);
1341
1342 w->header_line_height
1343 = display_mode_line (w, HEADER_LINE_FACE_ID,
1344 NILP (window_header_line_format)
1345 ? BVAR (current_buffer, header_line_format)
1346 : window_header_line_format);
1347 }
1334 1348
1335 start_display (&it, w, top); 1349 start_display (&it, w, top);
1336 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1, 1350 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
@@ -2513,6 +2527,14 @@ adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2513 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix); 2527 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2514} 2528}
2515 2529
2530static bool
2531hscrolling_current_line_p (struct window *w)
2532{
2533 return (!w->suspend_auto_hscroll
2534 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2535 Qcurrent_line));
2536}
2537
2516/*********************************************************************** 2538/***********************************************************************
2517 Lisp form evaluation 2539 Lisp form evaluation
2518 ***********************************************************************/ 2540 ***********************************************************************/
@@ -2834,13 +2856,12 @@ init_iterator (struct it *it, struct window *w,
2834 2856
2835 /* Get dimensions of truncation and continuation glyphs. These are 2857 /* Get dimensions of truncation and continuation glyphs. These are
2836 displayed as fringe bitmaps under X, but we need them for such 2858 displayed as fringe bitmaps under X, but we need them for such
2837 frames when the fringes are turned off. But leave the dimensions 2859 frames when the fringes are turned off. The no_special_glyphs slot
2838 zero for tooltip frames, as these glyphs look ugly there and also 2860 of the iterator's frame, when set, suppresses their display - by
2839 sabotage calculations of tooltip dimensions in x-show-tip. */ 2861 default for tooltip frames and when set via the 'no-special-glyphs'
2862 frame parameter. */
2840#ifdef HAVE_WINDOW_SYSTEM 2863#ifdef HAVE_WINDOW_SYSTEM
2841 if (!(FRAME_WINDOW_P (it->f) 2864 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
2842 && FRAMEP (tip_frame)
2843 && it->f == XFRAME (tip_frame)))
2844#endif 2865#endif
2845 { 2866 {
2846 if (it->line_wrap == TRUNCATE) 2867 if (it->line_wrap == TRUNCATE)
@@ -2882,8 +2903,22 @@ init_iterator (struct it *it, struct window *w,
2882 } 2903 }
2883 else 2904 else
2884 { 2905 {
2885 it->first_visible_x 2906 /* When hscrolling only the current line, don't apply the
2886 = window_hscroll_limited (it->w, it->f) * FRAME_COLUMN_WIDTH (it->f); 2907 hscroll here, it will be applied by display_line when it gets
2908 to laying out the line showing point. However, if the
2909 window's min_hscroll is positive, the user specified a lower
2910 bound for automatic hscrolling, so they expect the
2911 non-current lines to obey that hscroll amount. */
2912 if (hscrolling_current_line_p (w))
2913 {
2914 if (w->min_hscroll > 0)
2915 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
2916 else
2917 it->first_visible_x = 0;
2918 }
2919 else
2920 it->first_visible_x =
2921 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
2887 it->last_visible_x = (it->first_visible_x 2922 it->last_visible_x = (it->first_visible_x
2888 + window_box_width (w, TEXT_AREA)); 2923 + window_box_width (w, TEXT_AREA));
2889 2924
@@ -2898,7 +2933,7 @@ init_iterator (struct it *it, struct window *w,
2898 it->last_visible_x -= it->continuation_pixel_width; 2933 it->last_visible_x -= it->continuation_pixel_width;
2899 } 2934 }
2900 2935
2901 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w); 2936 it->header_line_p = window_wants_header_line (w);
2902 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll; 2937 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
2903 } 2938 }
2904 2939
@@ -2997,7 +3032,7 @@ void
2997start_display (struct it *it, struct window *w, struct text_pos pos) 3032start_display (struct it *it, struct window *w, struct text_pos pos)
2998{ 3033{
2999 struct glyph_row *row; 3034 struct glyph_row *row;
3000 bool first_vpos = WINDOW_WANTS_HEADER_LINE_P (w); 3035 bool first_vpos = window_wants_header_line (w);
3001 3036
3002 row = w->desired_matrix->rows + first_vpos; 3037 row = w->desired_matrix->rows + first_vpos;
3003 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID); 3038 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
@@ -4318,7 +4353,8 @@ handle_invisible_prop (struct it *it)
4318 bidi_move_to_visually_next (&it->bidi_it); 4353 bidi_move_to_visually_next (&it->bidi_it);
4319 } 4354 }
4320 while (oldpos <= it->bidi_it.charpos 4355 while (oldpos <= it->bidi_it.charpos
4321 && it->bidi_it.charpos < endpos); 4356 && it->bidi_it.charpos < endpos
4357 && it->bidi_it.charpos < it->bidi_it.string.schars);
4322 4358
4323 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos; 4359 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
4324 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos; 4360 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
@@ -7032,7 +7068,7 @@ get_next_display_element (struct it *it)
7032 translated too. 7068 translated too.
7033 7069
7034 Non-printable characters and raw-byte characters are also 7070 Non-printable characters and raw-byte characters are also
7035 translated to octal form. */ 7071 translated to octal or hexadecimal form. */
7036 if (((c < ' ' || c == 127) /* ASCII control chars. */ 7072 if (((c < ' ' || c == 127) /* ASCII control chars. */
7037 ? (it->area != TEXT_AREA 7073 ? (it->area != TEXT_AREA
7038 /* In mode line, treat \n, \t like other crl chars. */ 7074 /* In mode line, treat \n, \t like other crl chars. */
@@ -7139,9 +7175,12 @@ get_next_display_element (struct it *it)
7139 int len, i; 7175 int len, i;
7140 7176
7141 if (CHAR_BYTE8_P (c)) 7177 if (CHAR_BYTE8_P (c))
7142 /* Display \200 instead of \17777600. */ 7178 /* Display \200 or \x80 instead of \17777600. */
7143 c = CHAR_TO_BYTE8 (c); 7179 c = CHAR_TO_BYTE8 (c);
7144 len = sprintf (str, "%03o", c + 0u); 7180 const char *format_string = display_raw_bytes_as_hex
7181 ? "x%02x"
7182 : "%03o";
7183 len = sprintf (str, format_string, c + 0u);
7145 7184
7146 XSETINT (it->ctl_chars[0], escape_glyph); 7185 XSETINT (it->ctl_chars[0], escape_glyph);
7147 for (i = 0; i < len; i++) 7186 for (i = 0; i < len; i++)
@@ -7729,9 +7768,8 @@ next_element_from_display_vector (struct it *it)
7729 7768
7730 /* KFS: This code used to check ip->dpvec[0] instead of the current element. 7769 /* KFS: This code used to check ip->dpvec[0] instead of the current element.
7731 That seemed totally bogus - so I changed it... */ 7770 That seemed totally bogus - so I changed it... */
7732 gc = it->dpvec[it->current.dpvec_index]; 7771 if (it->dpend - it->dpvec > 0 /* empty dpvec[] is invalid */
7733 7772 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
7734 if (GLYPH_CODE_P (gc))
7735 { 7773 {
7736 struct face *this_face, *prev_face, *next_face; 7774 struct face *this_face, *prev_face, *next_face;
7737 7775
@@ -10529,9 +10567,12 @@ message_with_string (const char *m, Lisp_Object string, bool log)
10529/* Dump an informative message to the minibuf. If M is 0, clear out 10567/* Dump an informative message to the minibuf. If M is 0, clear out
10530 any existing message, and let the mini-buffer text show through. 10568 any existing message, and let the mini-buffer text show through.
10531 10569
10532 The message must be safe ASCII and the format must not contain ` or 10570 The message must be safe ASCII (because when Emacs is
10533 '. If your message and format do not fit into this category, 10571 non-interactive the message is sent straight to stderr without
10534 convert your arguments to Lisp objects and use Fmessage instead. */ 10572 encoding first) and the format must not contain ` or ' (because
10573 this function does not account for `text-quoting-style'). If your
10574 message and format do not fit into this category, convert your
10575 arguments to Lisp objects and use Fmessage instead. */
10535 10576
10536static void ATTRIBUTE_FORMAT_PRINTF (1, 0) 10577static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
10537vmessage (const char *m, va_list ap) 10578vmessage (const char *m, va_list ap)
@@ -10589,6 +10630,7 @@ vmessage (const char *m, va_list ap)
10589 } 10630 }
10590} 10631}
10591 10632
10633/* See vmessage for restrictions on the text of the message. */
10592void 10634void
10593message (const char *m, ...) 10635message (const char *m, ...)
10594{ 10636{
@@ -11379,6 +11421,11 @@ clear_garbaged_frames (void)
11379 redraw_frame (f); 11421 redraw_frame (f);
11380 else 11422 else
11381 clear_current_matrices (f); 11423 clear_current_matrices (f);
11424
11425#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
11426 x_clear_under_internal_border (f);
11427#endif /* HAVE_WINDOW_SYSTEM && !HAVE_NS */
11428
11382 fset_redisplay (f); 11429 fset_redisplay (f);
11383 f->garbaged = false; 11430 f->garbaged = false;
11384 f->resized_p = false; 11431 f->resized_p = false;
@@ -11441,7 +11488,14 @@ echo_area_display (bool update_frame_p)
11441 been called, so that mode lines above the echo area are 11488 been called, so that mode lines above the echo area are
11442 garbaged. This looks odd, so we prevent it here. */ 11489 garbaged. This looks odd, so we prevent it here. */
11443 if (!display_completed) 11490 if (!display_completed)
11444 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false); 11491 {
11492 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
11493
11494#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
11495 x_clear_under_internal_border (f);
11496#endif /* HAVE_WINDOW_SYSTEM && !HAVE_NS */
11497
11498 }
11445 11499
11446 if (window_height_changed_p 11500 if (window_height_changed_p
11447 /* Don't do this if Emacs is shutting down. Redisplay 11501 /* Don't do this if Emacs is shutting down. Redisplay
@@ -11513,7 +11567,7 @@ window_buffer_changed (struct window *w)
11513 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star; 11567 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
11514} 11568}
11515 11569
11516/* True if W has %c in its mode line and mode line should be updated. */ 11570/* True if W has %c or %C in its mode line and mode line should be updated. */
11517 11571
11518static bool 11572static bool
11519mode_line_update_needed (struct window *w) 11573mode_line_update_needed (struct window *w)
@@ -11767,6 +11821,7 @@ x_consider_frame_title (Lisp_Object frame)
11767 && FRAME_KBOARD (tf) == FRAME_KBOARD (f) 11821 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
11768 && !FRAME_MINIBUF_ONLY_P (tf) 11822 && !FRAME_MINIBUF_ONLY_P (tf)
11769 && !EQ (other_frame, tip_frame) 11823 && !EQ (other_frame, tip_frame)
11824 && !FRAME_PARENT_FRAME (tf)
11770 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf))) 11825 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
11771 break; 11826 break;
11772 } 11827 }
@@ -11883,6 +11938,7 @@ prepare_menu_bars (void)
11883 continue; 11938 continue;
11884 11939
11885 if (!EQ (frame, tooltip_frame) 11940 if (!EQ (frame, tooltip_frame)
11941 && !FRAME_PARENT_FRAME (f)
11886 && (FRAME_ICONIFIED_P (f) 11942 && (FRAME_ICONIFIED_P (f)
11887 || FRAME_VISIBLE_P (f) == 1 11943 || FRAME_VISIBLE_P (f) == 1
11888 /* Exclude TTY frames that are obscured because they 11944 /* Exclude TTY frames that are obscured because they
@@ -11929,6 +11985,10 @@ prepare_menu_bars (void)
11929 continue; 11985 continue;
11930 11986
11931 run_window_size_change_functions (frame); 11987 run_window_size_change_functions (frame);
11988
11989 if (FRAME_PARENT_FRAME (f))
11990 continue;
11991
11932 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); 11992 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
11933#ifdef HAVE_WINDOW_SYSTEM 11993#ifdef HAVE_WINDOW_SYSTEM
11934 update_tool_bar (f, false); 11994 update_tool_bar (f, false);
@@ -13008,6 +13068,7 @@ hscroll_window_tree (Lisp_Object window)
13008 cursor_row = bottom_row - 1; 13068 cursor_row = bottom_row - 1;
13009 } 13069 }
13010 bool row_r2l_p = cursor_row->reversed_p; 13070 bool row_r2l_p = cursor_row->reversed_p;
13071 bool hscl = hscrolling_current_line_p (w);
13011 13072
13012 text_area_width = window_box_width (w, TEXT_AREA); 13073 text_area_width = window_box_width (w, TEXT_AREA);
13013 13074
@@ -13058,7 +13119,15 @@ hscroll_window_tree (Lisp_Object window)
13058 && cursor_row->truncated_on_right_p 13119 && cursor_row->truncated_on_right_p
13059 && w->cursor.x <= h_margin) 13120 && w->cursor.x <= h_margin)
13060 || (w->hscroll 13121 || (w->hscroll
13061 && (w->cursor.x >= text_area_width - h_margin)))))) 13122 && (w->cursor.x >= text_area_width - h_margin))))
13123 /* This last condition is needed when moving
13124 vertically from an hscrolled line to a short line
13125 that doesn't need to be hscrolled. If we omit
13126 this condition, the line from which we move will
13127 remain hscrolled. */
13128 || (hscl
13129 && w->hscroll != w->min_hscroll
13130 && !cursor_row->truncated_on_left_p)))
13062 { 13131 {
13063 struct it it; 13132 struct it it;
13064 ptrdiff_t hscroll; 13133 ptrdiff_t hscroll;
@@ -13078,6 +13147,9 @@ hscroll_window_tree (Lisp_Object window)
13078 /* Move iterator to pt starting at cursor_row->start in 13147 /* Move iterator to pt starting at cursor_row->start in
13079 a line with infinite width. */ 13148 a line with infinite width. */
13080 init_to_row_start (&it, w, cursor_row); 13149 init_to_row_start (&it, w, cursor_row);
13150 if (hscl)
13151 it.first_visible_x = window_hscroll_limited (w, it.f)
13152 * FRAME_COLUMN_WIDTH (it.f);
13081 it.last_visible_x = INFINITY; 13153 it.last_visible_x = INFINITY;
13082 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS); 13154 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
13083 /* If the line ends in an overlay string with a newline, 13155 /* If the line ends in an overlay string with a newline,
@@ -13089,6 +13161,9 @@ hscroll_window_tree (Lisp_Object window)
13089 if (it.method == GET_FROM_STRING && pt > 1) 13161 if (it.method == GET_FROM_STRING && pt > 1)
13090 { 13162 {
13091 init_to_row_start (&it, w, cursor_row); 13163 init_to_row_start (&it, w, cursor_row);
13164 if (hscl)
13165 it.first_visible_x = (window_hscroll_limited (w, it.f)
13166 * FRAME_COLUMN_WIDTH (it.f));
13092 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS); 13167 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
13093 } 13168 }
13094 current_buffer = saved_current_buffer; 13169 current_buffer = saved_current_buffer;
@@ -13130,7 +13205,12 @@ hscroll_window_tree (Lisp_Object window)
13130 /* Don't prevent redisplay optimizations if hscroll 13205 /* Don't prevent redisplay optimizations if hscroll
13131 hasn't changed, as it will unnecessarily slow down 13206 hasn't changed, as it will unnecessarily slow down
13132 redisplay. */ 13207 redisplay. */
13133 if (w->hscroll != hscroll) 13208 if (w->hscroll != hscroll
13209 /* When hscrolling only the current line, we need to
13210 report hscroll even if its value is equal to the
13211 previous one, because the new line might need a
13212 different value. */
13213 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
13134 { 13214 {
13135 struct buffer *b = XBUFFER (w->contents); 13215 struct buffer *b = XBUFFER (w->contents);
13136 b->prevent_redisplay_optimizations_p = true; 13216 b->prevent_redisplay_optimizations_p = true;
@@ -13596,6 +13676,14 @@ redisplay_internal (void)
13596 enum { MAX_HSCROLL_RETRIES = 16 }; 13676 enum { MAX_HSCROLL_RETRIES = 16 };
13597 int hscroll_retries = 0; 13677 int hscroll_retries = 0;
13598 13678
13679 /* Limit the number of retries for when frame(s) become garbaged as
13680 result of redisplaying them. Some packages set various redisplay
13681 hooks, such as window-scroll-functions, to run Lisp that always
13682 calls APIs which cause the frame's garbaged flag to become set,
13683 so we loop indefinitely. */
13684 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
13685 int garbaged_frame_retries = 0;
13686
13599 /* True means redisplay has to consider all windows on all 13687 /* True means redisplay has to consider all windows on all
13600 frames. False, only selected_window is considered. */ 13688 frames. False, only selected_window is considered. */
13601 bool consider_all_windows_p; 13689 bool consider_all_windows_p;
@@ -13898,7 +13986,7 @@ redisplay_internal (void)
13898 it.vpos = this_line_vpos; 13986 it.vpos = this_line_vpos;
13899 it.current_y = this_line_y; 13987 it.current_y = this_line_y;
13900 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos); 13988 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
13901 display_line (&it); 13989 display_line (&it, -1);
13902 13990
13903 /* If line contains point, is not continued, 13991 /* If line contains point, is not continued,
13904 and ends at same distance from eob as before, we win. */ 13992 and ends at same distance from eob as before, we win. */
@@ -14142,9 +14230,14 @@ redisplay_internal (void)
14142 garbage. We have to start over. These cases 14230 garbage. We have to start over. These cases
14143 should be rare, so going all the way back to the 14231 should be rare, so going all the way back to the
14144 top of redisplay should be good enough. */ 14232 top of redisplay should be good enough. */
14145 if (FRAME_GARBAGED_P (f)) 14233 if (FRAME_GARBAGED_P (f)
14234 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
14146 goto retry; 14235 goto retry;
14147 14236
14237#if defined (HAVE_WINDOW_SYSTEM) && !defined (HAVE_NS)
14238 x_clear_under_internal_border (f);
14239#endif /* HAVE_WINDOW_SYSTEM && !HAVE_NS */
14240
14148 /* Prevent various kinds of signals during display 14241 /* Prevent various kinds of signals during display
14149 update. stdio is not robust about handling 14242 update. stdio is not robust about handling
14150 signals, which can cause an apparent I/O error. */ 14243 signals, which can cause an apparent I/O error. */
@@ -15718,7 +15811,7 @@ compute_window_start_on_continuation_line (struct window *w)
15718 15811
15719 /* Find the start of the continued line. This should be fast 15812 /* Find the start of the continued line. This should be fast
15720 because find_newline is fast (newline cache). */ 15813 because find_newline is fast (newline cache). */
15721 row = w->desired_matrix->rows + WINDOW_WANTS_HEADER_LINE_P (w); 15814 row = w->desired_matrix->rows + window_wants_header_line (w);
15722 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), 15815 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
15723 row, DEFAULT_FACE_ID); 15816 row, DEFAULT_FACE_ID);
15724 reseat_at_previous_visible_line_start (&it); 15817 reseat_at_previous_visible_line_start (&it);
@@ -15868,7 +15961,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
15868 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS); 15961 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
15869 15962
15870 top_scroll_margin = this_scroll_margin; 15963 top_scroll_margin = this_scroll_margin;
15871 if (WINDOW_WANTS_HEADER_LINE_P (w)) 15964 if (window_wants_header_line (w))
15872 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w); 15965 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
15873 15966
15874 /* Start with the row the cursor was displayed during the last 15967 /* Start with the row the cursor was displayed during the last
@@ -16404,7 +16497,8 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16404 = (w->window_end_valid 16497 = (w->window_end_valid
16405 && !current_buffer->clip_changed 16498 && !current_buffer->clip_changed
16406 && !current_buffer->prevent_redisplay_optimizations_p 16499 && !current_buffer->prevent_redisplay_optimizations_p
16407 && !window_outdated (w)); 16500 && !window_outdated (w)
16501 && !hscrolling_current_line_p (w));
16408 16502
16409 /* Run the window-text-change-functions 16503 /* Run the window-text-change-functions
16410 if it is possible that the text on the screen has changed 16504 if it is possible that the text on the screen has changed
@@ -16650,7 +16744,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16650 margin, even though this part handles windows that didn't 16744 margin, even though this part handles windows that didn't
16651 scroll at all. */ 16745 scroll at all. */
16652 int pixel_margin = margin * frame_line_height; 16746 int pixel_margin = margin * frame_line_height;
16653 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w); 16747 bool header_line = window_wants_header_line (w);
16654 16748
16655 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop 16749 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
16656 below, which finds the row to move point to, advances by 16750 below, which finds the row to move point to, advances by
@@ -17217,15 +17311,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
17217 || (w->column_number_displayed != -1 17311 || (w->column_number_displayed != -1
17218 && (w->column_number_displayed != current_column ()))) 17312 && (w->column_number_displayed != current_column ())))
17219 /* This means that the window has a mode line. */ 17313 /* This means that the window has a mode line. */
17220 && (WINDOW_WANTS_MODELINE_P (w) 17314 && (window_wants_mode_line (w)
17221 || WINDOW_WANTS_HEADER_LINE_P (w))) 17315 || window_wants_header_line (w)))
17222 { 17316 {
17223 17317
17224 display_mode_lines (w); 17318 display_mode_lines (w);
17225 17319
17226 /* If mode line height has changed, arrange for a thorough 17320 /* If mode line height has changed, arrange for a thorough
17227 immediate redisplay using the correct mode line height. */ 17321 immediate redisplay using the correct mode line height. */
17228 if (WINDOW_WANTS_MODELINE_P (w) 17322 if (window_wants_mode_line (w)
17229 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w)) 17323 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
17230 { 17324 {
17231 f->fonts_changed = true; 17325 f->fonts_changed = true;
@@ -17236,7 +17330,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
17236 17330
17237 /* If header line height has changed, arrange for a thorough 17331 /* If header line height has changed, arrange for a thorough
17238 immediate redisplay using the correct header line height. */ 17332 immediate redisplay using the correct header line height. */
17239 if (WINDOW_WANTS_HEADER_LINE_P (w) 17333 if (window_wants_header_line (w)
17240 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w)) 17334 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
17241 { 17335 {
17242 f->fonts_changed = true; 17336 f->fonts_changed = true;
@@ -17381,6 +17475,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
17381 struct it it; 17475 struct it it;
17382 struct glyph_row *last_text_row = NULL; 17476 struct glyph_row *last_text_row = NULL;
17383 struct frame *f = XFRAME (w->frame); 17477 struct frame *f = XFRAME (w->frame);
17478 int cursor_vpos = w->cursor.vpos;
17384 17479
17385 /* Make POS the new window start. */ 17480 /* Make POS the new window start. */
17386 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos)); 17481 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
@@ -17396,7 +17491,7 @@ try_window (Lisp_Object window, struct text_pos pos, int flags)
17396 /* Display all lines of W. */ 17491 /* Display all lines of W. */
17397 while (it.current_y < it.last_visible_y) 17492 while (it.current_y < it.last_visible_y)
17398 { 17493 {
17399 if (display_line (&it)) 17494 if (display_line (&it, cursor_vpos))
17400 last_text_row = it.glyph_row - 1; 17495 last_text_row = it.glyph_row - 1;
17401 if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)) 17496 if (f->fonts_changed && !(flags & TRY_WINDOW_IGNORE_FONTS_CHANGE))
17402 return 0; 17497 return 0;
@@ -17500,7 +17595,7 @@ try_window_reusing_current_matrix (struct window *w)
17500 return false; 17595 return false;
17501 17596
17502 /* If top-line visibility has changed, give up. */ 17597 /* If top-line visibility has changed, give up. */
17503 if (WINDOW_WANTS_HEADER_LINE_P (w) 17598 if (window_wants_header_line (w)
17504 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p) 17599 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
17505 return false; 17600 return false;
17506 17601
@@ -17572,7 +17667,7 @@ try_window_reusing_current_matrix (struct window *w)
17572 break; 17667 break;
17573 17668
17574 it.glyph_row->reversed_p = false; 17669 it.glyph_row->reversed_p = false;
17575 if (display_line (&it)) 17670 if (display_line (&it, -1))
17576 last_text_row = it.glyph_row - 1; 17671 last_text_row = it.glyph_row - 1;
17577 17672
17578 } 17673 }
@@ -17751,7 +17846,7 @@ try_window_reusing_current_matrix (struct window *w)
17751 w->cursor.vpos = -1; 17846 w->cursor.vpos = -1;
17752 last_text_row = NULL; 17847 last_text_row = NULL;
17753 while (it.current_y < it.last_visible_y && !f->fonts_changed) 17848 while (it.current_y < it.last_visible_y && !f->fonts_changed)
17754 if (display_line (&it)) 17849 if (display_line (&it, w->cursor.vpos))
17755 last_text_row = it.glyph_row - 1; 17850 last_text_row = it.glyph_row - 1;
17756 17851
17757 /* If point is in a reused row, adjust y and vpos of the cursor 17852 /* If point is in a reused row, adjust y and vpos of the cursor
@@ -18607,7 +18702,7 @@ try_window_id (struct window *w)
18607 && (first_unchanged_at_end_row == NULL 18702 && (first_unchanged_at_end_row == NULL
18608 || IT_CHARPOS (it) < stop_pos)) 18703 || IT_CHARPOS (it) < stop_pos))
18609 { 18704 {
18610 if (display_line (&it)) 18705 if (display_line (&it, -1))
18611 last_text_row = it.glyph_row - 1; 18706 last_text_row = it.glyph_row - 1;
18612 } 18707 }
18613 18708
@@ -18735,7 +18830,7 @@ try_window_id (struct window *w)
18735 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix); 18830 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
18736 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos; 18831 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
18737 int end = (WINDOW_TOP_EDGE_LINE (w) 18832 int end = (WINDOW_TOP_EDGE_LINE (w)
18738 + WINDOW_WANTS_HEADER_LINE_P (w) 18833 + window_wants_header_line (w)
18739 + window_internal_height (w)); 18834 + window_internal_height (w));
18740 18835
18741#if defined (HAVE_GPM) || defined (MSDOS) 18836#if defined (HAVE_GPM) || defined (MSDOS)
@@ -18873,7 +18968,7 @@ try_window_id (struct window *w)
18873 displayed invalid in the current matrix by setting their 18968 displayed invalid in the current matrix by setting their
18874 enabled_p flag to false. */ 18969 enabled_p flag to false. */
18875 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false); 18970 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
18876 if (display_line (&it)) 18971 if (display_line (&it, w->cursor.vpos))
18877 last_text_row_at_end = it.glyph_row - 1; 18972 last_text_row_at_end = it.glyph_row - 1;
18878 } 18973 }
18879 } 18974 }
@@ -18913,7 +19008,7 @@ try_window_id (struct window *w)
18913 { 19008 {
18914 /* Displayed to end of window, but no line containing text was 19009 /* Displayed to end of window, but no line containing text was
18915 displayed. Lines were deleted at the end of the window. */ 19010 displayed. Lines were deleted at the end of the window. */
18916 bool first_vpos = WINDOW_WANTS_HEADER_LINE_P (w); 19011 bool first_vpos = window_wants_header_line (w);
18917 int vpos = w->window_end_vpos; 19012 int vpos = w->window_end_vpos;
18918 struct glyph_row *current_row = current_matrix->rows + vpos; 19013 struct glyph_row *current_row = current_matrix->rows + vpos;
18919 struct glyph_row *desired_row = desired_matrix->rows + vpos; 19014 struct glyph_row *desired_row = desired_matrix->rows + vpos;
@@ -20591,10 +20686,11 @@ find_row_edges (struct it *it, struct glyph_row *row,
20591 IT->w from text at the current position of IT. See dispextern.h 20686 IT->w from text at the current position of IT. See dispextern.h
20592 for an overview of struct it. Value is true if 20687 for an overview of struct it. Value is true if
20593 IT->glyph_row displays text, as opposed to a line displaying ZV 20688 IT->glyph_row displays text, as opposed to a line displaying ZV
20594 only. */ 20689 only. CURSOR_VPOS is the window-relative vertical position of
20690 the glyph row displaying the cursor, or -1 if unknown. */
20595 20691
20596static bool 20692static bool
20597display_line (struct it *it) 20693display_line (struct it *it, int cursor_vpos)
20598{ 20694{
20599 struct glyph_row *row = it->glyph_row; 20695 struct glyph_row *row = it->glyph_row;
20600 Lisp_Object overlay_arrow_string; 20696 Lisp_Object overlay_arrow_string;
@@ -20612,6 +20708,13 @@ display_line (struct it *it)
20612 ptrdiff_t min_pos = ZV + 1, max_pos = 0; 20708 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
20613 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; 20709 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
20614 bool pending_handle_line_prefix = false; 20710 bool pending_handle_line_prefix = false;
20711 int header_line = window_wants_header_line (it->w);
20712 bool hscroll_this_line = (cursor_vpos >= 0
20713 && it->vpos == cursor_vpos - header_line
20714 && hscrolling_current_line_p (it->w));
20715 int first_visible_x = it->first_visible_x;
20716 int last_visible_x = it->last_visible_x;
20717 int x_incr = 0;
20615 20718
20616 /* We always start displaying at hpos zero even if hscrolled. */ 20719 /* We always start displaying at hpos zero even if hscrolled. */
20617 eassert (it->hpos == 0 && it->current_x == 0); 20720 eassert (it->hpos == 0 && it->current_x == 0);
@@ -20641,19 +20744,32 @@ display_line (struct it *it)
20641 recenter_overlay_lists but the first will be pretty cheap. */ 20744 recenter_overlay_lists but the first will be pretty cheap. */
20642 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it)); 20745 recenter_overlay_lists (current_buffer, IT_CHARPOS (*it));
20643 20746
20747 /* If we are going to display the cursor's line, account for the
20748 hscroll of that line. We subtract the window's min_hscroll,
20749 because that was already accounted for in init_iterator. */
20750 if (hscroll_this_line)
20751 x_incr =
20752 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
20753 * FRAME_COLUMN_WIDTH (it->f);
20754
20644 /* Move over display elements that are not visible because we are 20755 /* Move over display elements that are not visible because we are
20645 hscrolled. This may stop at an x-position < IT->first_visible_x 20756 hscrolled. This may stop at an x-position < first_visible_x
20646 if the first glyph is partially visible or if we hit a line end. */ 20757 if the first glyph is partially visible or if we hit a line end. */
20647 if (it->current_x < it->first_visible_x) 20758 if (it->current_x < it->first_visible_x + x_incr)
20648 { 20759 {
20649 enum move_it_result move_result; 20760 enum move_it_result move_result;
20650 20761
20651 this_line_min_pos = row->start.pos; 20762 this_line_min_pos = row->start.pos;
20763 if (hscroll_this_line)
20764 {
20765 it->first_visible_x += x_incr;
20766 it->last_visible_x += x_incr;
20767 }
20652 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x, 20768 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
20653 MOVE_TO_POS | MOVE_TO_X); 20769 MOVE_TO_POS | MOVE_TO_X);
20654 /* If we are under a large hscroll, move_it_in_display_line_to 20770 /* If we are under a large hscroll, move_it_in_display_line_to
20655 could hit the end of the line without reaching 20771 could hit the end of the line without reaching
20656 it->first_visible_x. Pretend that we did reach it. This is 20772 first_visible_x. Pretend that we did reach it. This is
20657 especially important on a TTY, where we will call 20773 especially important on a TTY, where we will call
20658 extend_face_to_end_of_line, which needs to know how many 20774 extend_face_to_end_of_line, which needs to know how many
20659 blank glyphs to produce. */ 20775 blank glyphs to produce. */
@@ -21430,6 +21546,13 @@ display_line (struct it *it)
21430 row to be used. */ 21546 row to be used. */
21431 it->current_x = it->hpos = 0; 21547 it->current_x = it->hpos = 0;
21432 it->current_y += row->height; 21548 it->current_y += row->height;
21549 /* Restore the first and last visible X if we adjusted them for
21550 current-line hscrolling. */
21551 if (hscroll_this_line)
21552 {
21553 it->first_visible_x = first_visible_x;
21554 it->last_visible_x = last_visible_x;
21555 }
21433 SET_TEXT_POS (it->eol_pos, 0, 0); 21556 SET_TEXT_POS (it->eol_pos, 0, 0);
21434 ++it->vpos; 21557 ++it->vpos;
21435 ++it->glyph_row; 21558 ++it->glyph_row;
@@ -22538,20 +22661,30 @@ display_mode_lines (struct window *w)
22538 line_number_displayed = false; 22661 line_number_displayed = false;
22539 w->column_number_displayed = -1; 22662 w->column_number_displayed = -1;
22540 22663
22541 if (WINDOW_WANTS_MODELINE_P (w)) 22664 if (window_wants_mode_line (w))
22542 { 22665 {
22666 Lisp_Object window_mode_line_format
22667 = window_parameter (w, Qmode_line_format);
22668
22543 struct window *sel_w = XWINDOW (old_selected_window); 22669 struct window *sel_w = XWINDOW (old_selected_window);
22544 22670
22545 /* Select mode line face based on the real selected window. */ 22671 /* Select mode line face based on the real selected window. */
22546 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w), 22672 display_mode_line (w, CURRENT_MODE_LINE_FACE_ID_3 (sel_w, sel_w, w),
22547 BVAR (current_buffer, mode_line_format)); 22673 NILP (window_mode_line_format)
22674 ? BVAR (current_buffer, mode_line_format)
22675 : window_mode_line_format);
22548 ++n; 22676 ++n;
22549 } 22677 }
22550 22678
22551 if (WINDOW_WANTS_HEADER_LINE_P (w)) 22679 if (window_wants_header_line (w))
22552 { 22680 {
22681 Lisp_Object window_header_line_format
22682 = window_parameter (w, Qheader_line_format);
22683
22553 display_mode_line (w, HEADER_LINE_FACE_ID, 22684 display_mode_line (w, HEADER_LINE_FACE_ID,
22554 BVAR (current_buffer, header_line_format)); 22685 NILP (window_header_line_format)
22686 ? BVAR (current_buffer, header_line_format)
22687 : window_header_line_format);
22555 ++n; 22688 ++n;
22556 } 22689 }
22557 22690
@@ -23663,7 +23796,8 @@ decode_mode_spec (struct window *w, register int c, int field_width,
23663 break; 23796 break;
23664 23797
23665 case 'c': 23798 case 'c':
23666 /* %c and %l are ignored in `frame-title-format'. 23799 case 'C':
23800 /* %c, %C, and %l are ignored in `frame-title-format'.
23667 (In redisplay_internal, the frame title is drawn _before_ the 23801 (In redisplay_internal, the frame title is drawn _before_ the
23668 windows are updated, so the stuff which depends on actual 23802 windows are updated, so the stuff which depends on actual
23669 window contents (such as %l) may fail to render properly, or 23803 window contents (such as %l) may fail to render properly, or
@@ -23673,8 +23807,9 @@ decode_mode_spec (struct window *w, register int c, int field_width,
23673 else 23807 else
23674 { 23808 {
23675 ptrdiff_t col = current_column (); 23809 ptrdiff_t col = current_column ();
23810 int disp_col = (c == 'C') ? col + 1 : col;
23676 w->column_number_displayed = col; 23811 w->column_number_displayed = col;
23677 pint2str (decode_mode_spec_buf, width, col); 23812 pint2str (decode_mode_spec_buf, width, disp_col);
23678 return decode_mode_spec_buf; 23813 return decode_mode_spec_buf;
23679 } 23814 }
23680 23815
@@ -23722,7 +23857,7 @@ decode_mode_spec (struct window *w, register int c, int field_width,
23722 ptrdiff_t topline, nlines, height; 23857 ptrdiff_t topline, nlines, height;
23723 ptrdiff_t junk; 23858 ptrdiff_t junk;
23724 23859
23725 /* %c and %l are ignored in `frame-title-format'. */ 23860 /* %c, %C, and %l are ignored in `frame-title-format'. */
23726 if (mode_line_target == MODE_LINE_TITLE) 23861 if (mode_line_target == MODE_LINE_TITLE)
23727 return ""; 23862 return "";
23728 23863
@@ -23841,6 +23976,27 @@ decode_mode_spec (struct window *w, register int c, int field_width,
23841 return " Narrow"; 23976 return " Narrow";
23842 break; 23977 break;
23843 23978
23979 /* Display the "degree of travel" of the window through the buffer. */
23980 case 'o':
23981 {
23982 ptrdiff_t toppos = marker_position (w->start);
23983 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
23984 ptrdiff_t begv = BUF_BEGV (b);
23985 ptrdiff_t zv = BUF_ZV (b);
23986
23987 if (zv <= botpos)
23988 return toppos <= begv ? "All" : "Bottom";
23989 else if (toppos <= begv)
23990 return "Top";
23991 else
23992 {
23993 sprintf (decode_mode_spec_buf, "%2d%%",
23994 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
23995 return decode_mode_spec_buf;
23996 }
23997 }
23998
23999 /* Display percentage of buffer above the top of the screen. */
23844 case 'p': 24000 case 'p':
23845 { 24001 {
23846 ptrdiff_t pos = marker_position (w->start); 24002 ptrdiff_t pos = marker_position (w->start);
@@ -23878,6 +24034,30 @@ decode_mode_spec (struct window *w, register int c, int field_width,
23878 } 24034 }
23879 } 24035 }
23880 24036
24037 /* Display percentage offsets of top and bottom of the window,
24038 using "All" (but not "Top" or "Bottom") where appropriate. */
24039 case 'q':
24040 {
24041 ptrdiff_t toppos = marker_position (w->start);
24042 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
24043 ptrdiff_t begv = BUF_BEGV (b);
24044 ptrdiff_t zv = BUF_ZV (b);
24045 int top_perc, bot_perc;
24046
24047 if ((toppos <= begv) && (zv <= botpos))
24048 return "All ";
24049
24050 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
24051 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
24052
24053 if (top_perc == bot_perc)
24054 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
24055 else
24056 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
24057
24058 return decode_mode_spec_buf;
24059 }
24060
23881 case 's': 24061 case 's':
23882 /* status of process */ 24062 /* status of process */
23883 obj = Fget_buffer_process (Fcurrent_buffer ()); 24063 obj = Fget_buffer_process (Fcurrent_buffer ());
@@ -25394,6 +25574,20 @@ set_glyph_string_background_width (struct glyph_string *s, int start, int last_x
25394} 25574}
25395 25575
25396 25576
25577/* Return glyph string that shares background with glyph string S and
25578 whose `background_width' member has been set. */
25579
25580static struct glyph_string *
25581glyph_string_containing_background_width (struct glyph_string *s)
25582{
25583 if (s->cmp)
25584 while (s->cmp_from)
25585 s = s->prev;
25586
25587 return s;
25588}
25589
25590
25397/* Compute overhangs and x-positions for glyph string S and its 25591/* Compute overhangs and x-positions for glyph string S and its
25398 predecessors, or successors. X is the starting x-position for S. 25592 predecessors, or successors. X is the starting x-position for S.
25399 BACKWARD_P means process predecessors. */ 25593 BACKWARD_P means process predecessors. */
@@ -25407,7 +25601,8 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25407 { 25601 {
25408 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs) 25602 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
25409 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s); 25603 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
25410 x -= s->width; 25604 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
25605 x -= s->width;
25411 s->x = x; 25606 s->x = x;
25412 s = s->prev; 25607 s = s->prev;
25413 } 25608 }
@@ -25419,7 +25614,8 @@ compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
25419 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs) 25614 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
25420 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s); 25615 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
25421 s->x = x; 25616 s->x = x;
25422 x += s->width; 25617 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
25618 x += s->width;
25423 s = s->next; 25619 s = s->next;
25424 } 25620 }
25425 } 25621 }
@@ -25751,7 +25947,10 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
25751 USE_SAFE_ALLOCA; 25947 USE_SAFE_ALLOCA;
25752 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x); 25948 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
25753 if (tail) 25949 if (tail)
25754 x_reached = tail->x + tail->background_width; 25950 {
25951 s = glyph_string_containing_background_width (tail);
25952 x_reached = s->x + s->background_width;
25953 }
25755 else 25954 else
25756 x_reached = x; 25955 x_reached = x;
25757 25956
@@ -25906,6 +26105,9 @@ draw_glyphs (struct window *w, int x, struct glyph_row *row,
25906 compute_overhangs_and_x (h, tail->x + tail->width, false); 26105 compute_overhangs_and_x (h, tail->x + tail->width, false);
25907 append_glyph_string_lists (&head, &tail, h, t); 26106 append_glyph_string_lists (&head, &tail, h, t);
25908 } 26107 }
26108 tail = glyph_string_containing_background_width (tail);
26109 if (clip_tail)
26110 clip_tail = glyph_string_containing_background_width (clip_tail);
25909 if (clip_head || clip_tail) 26111 if (clip_head || clip_tail)
25910 for (s = head; s; s = s->next) 26112 for (s = head; s; s = s->next)
25911 { 26113 {
@@ -28613,7 +28815,6 @@ display_and_set_cursor (struct window *w, bool on,
28613 be in the midst of changing its size, and x and y may be off the 28815 be in the midst of changing its size, and x and y may be off the
28614 window. */ 28816 window. */
28615 if (! FRAME_VISIBLE_P (f) 28817 if (! FRAME_VISIBLE_P (f)
28616 || FRAME_GARBAGED_P (f)
28617 || vpos >= w->current_matrix->nrows 28818 || vpos >= w->current_matrix->nrows
28618 || hpos >= w->current_matrix->matrix_w) 28819 || hpos >= w->current_matrix->matrix_w)
28619 return; 28820 return;
@@ -28631,6 +28832,26 @@ display_and_set_cursor (struct window *w, bool on,
28631 return; 28832 return;
28632 } 28833 }
28633 28834
28835 /* A frame might be marked garbaged even though its cursor position
28836 is correct, and will not change upon subsequent redisplay. This
28837 happens in some rare situations, like toggling the sort order in
28838 Dired windows. We've already established that VPOS is valid, so
28839 it shouldn't do any harm to record the cursor position, as we are
28840 going to return without acting on it anyway. Otherwise, expose
28841 events might come in and call update_window_cursor, which will
28842 blindly use outdated values in w->phys_cursor. */
28843 if (FRAME_GARBAGED_P (f))
28844 {
28845 if (on)
28846 {
28847 w->phys_cursor.x = x;
28848 w->phys_cursor.y = glyph_row->y;
28849 w->phys_cursor.hpos = hpos;
28850 w->phys_cursor.vpos = vpos;
28851 }
28852 return;
28853 }
28854
28634 glyph = NULL; 28855 glyph = NULL;
28635 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA]) 28856 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
28636 glyph = glyph_row->glyphs[TEXT_AREA] + hpos; 28857 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
@@ -30243,13 +30464,67 @@ note_mouse_highlight (struct frame *f, int x, int y)
30243 && part != ON_HEADER_LINE)) 30464 && part != ON_HEADER_LINE))
30244 clear_mouse_face (hlinfo); 30465 clear_mouse_face (hlinfo);
30245 30466
30467 /* Reset help_echo_string. It will get recomputed below. */
30468 help_echo_string = Qnil;
30469
30470#ifdef HAVE_WINDOW_SYSTEM
30471 /* If the cursor is on the internal border of FRAME and FRAME's
30472 internal border is draggable, provide some visual feedback. */
30473 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
30474 && !NILP (get_frame_param (f, Qdrag_internal_border)))
30475 {
30476 enum internal_border_part part = frame_internal_border_part (f, x, y);
30477
30478 switch (part)
30479 {
30480 case INTERNAL_BORDER_NONE:
30481 if (cursor != FRAME_X_OUTPUT (f)->nontext_cursor)
30482 /* Reset cursor. */
30483 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
30484 break;
30485 case INTERNAL_BORDER_LEFT_EDGE:
30486 cursor = FRAME_X_OUTPUT (f)->left_edge_cursor;
30487 break;
30488 case INTERNAL_BORDER_TOP_LEFT_CORNER:
30489 cursor = FRAME_X_OUTPUT (f)->top_left_corner_cursor;
30490 break;
30491 case INTERNAL_BORDER_TOP_EDGE:
30492 cursor = FRAME_X_OUTPUT (f)->top_edge_cursor;
30493 break;
30494 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
30495 cursor = FRAME_X_OUTPUT (f)->top_right_corner_cursor;
30496 break;
30497 case INTERNAL_BORDER_RIGHT_EDGE:
30498 cursor = FRAME_X_OUTPUT (f)->right_edge_cursor;
30499 break;
30500 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
30501 cursor = FRAME_X_OUTPUT (f)->bottom_right_corner_cursor;
30502 break;
30503 case INTERNAL_BORDER_BOTTOM_EDGE:
30504 cursor = FRAME_X_OUTPUT (f)->bottom_edge_cursor;
30505 break;
30506 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
30507 cursor = FRAME_X_OUTPUT (f)->bottom_left_corner_cursor;
30508 break;
30509 default:
30510 /* This should not happen. */
30511 if (cursor != FRAME_X_OUTPUT (f)->nontext_cursor)
30512 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
30513 }
30514
30515 if (cursor != FRAME_X_OUTPUT (f)->nontext_cursor)
30516 {
30517 /* Do we really want a help echo here? */
30518 help_echo_string = build_string ("drag-mouse-1: resize frame");
30519 goto set_cursor;
30520 }
30521 }
30522#endif /* HAVE_WINDOW_SYSTEM */
30523
30246 /* Not on a window -> return. */ 30524 /* Not on a window -> return. */
30247 if (!WINDOWP (window)) 30525 if (!WINDOWP (window))
30248 return; 30526 return;
30249 30527
30250 /* Reset help_echo_string. It will get recomputed below. */
30251 help_echo_string = Qnil;
30252
30253 /* Convert to window-relative pixel coordinates. */ 30528 /* Convert to window-relative pixel coordinates. */
30254 w = XWINDOW (window); 30529 w = XWINDOW (window);
30255 frame_to_window_pixel_xy (w, &x, &y); 30530 frame_to_window_pixel_xy (w, &x, &y);
@@ -30287,11 +30562,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
30287 { 30562 {
30288 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; 30563 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
30289 help_echo_string = build_string ("drag-mouse-1: resize"); 30564 help_echo_string = build_string ("drag-mouse-1: resize");
30565 goto set_cursor;
30290 } 30566 }
30291 else if (part == ON_RIGHT_DIVIDER) 30567 else if (part == ON_RIGHT_DIVIDER)
30292 { 30568 {
30293 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; 30569 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
30294 help_echo_string = build_string ("drag-mouse-1: resize"); 30570 help_echo_string = build_string ("drag-mouse-1: resize");
30571 goto set_cursor;
30295 } 30572 }
30296 else if (part == ON_BOTTOM_DIVIDER) 30573 else if (part == ON_BOTTOM_DIVIDER)
30297 if (! WINDOW_BOTTOMMOST_P (w) 30574 if (! WINDOW_BOTTOMMOST_P (w)
@@ -30300,6 +30577,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
30300 { 30577 {
30301 cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor; 30578 cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
30302 help_echo_string = build_string ("drag-mouse-1: resize"); 30579 help_echo_string = build_string ("drag-mouse-1: resize");
30580 goto set_cursor;
30303 } 30581 }
30304 else 30582 else
30305 cursor = FRAME_X_OUTPUT (f)->nontext_cursor; 30583 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -30994,8 +31272,15 @@ x_draw_right_divider (struct window *w)
30994 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w); 31272 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
30995 int x1 = WINDOW_RIGHT_EDGE_X (w); 31273 int x1 = WINDOW_RIGHT_EDGE_X (w);
30996 int y0 = WINDOW_TOP_EDGE_Y (w); 31274 int y0 = WINDOW_TOP_EDGE_Y (w);
30997 /* The bottom divider prevails. */ 31275 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
30998 int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); 31276
31277 /* If W is horizontally combined and has a right sibling, don't
31278 draw over any bottom divider. */
31279 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
31280 && !NILP (w->parent)
31281 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
31282 && !NILP (w->next))
31283 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
30999 31284
31000 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1); 31285 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
31001 } 31286 }
@@ -31014,8 +31299,22 @@ x_draw_bottom_divider (struct window *w)
31014 int x1 = WINDOW_RIGHT_EDGE_X (w); 31299 int x1 = WINDOW_RIGHT_EDGE_X (w);
31015 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w); 31300 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
31016 int y1 = WINDOW_BOTTOM_EDGE_Y (w); 31301 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
31302 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : false;
31017 31303
31018 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1); 31304 /* If W is vertically combined and has a sibling below, don't draw
31305 over any right divider. */
31306 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
31307 && p
31308 && ((WINDOW_VERTICAL_COMBINATION_P (p)
31309 && !NILP (w->next))
31310 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
31311 && NILP (w->next)
31312 && !NILP (p->parent)
31313 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
31314 && !NILP (XWINDOW (p->parent)->next))))
31315 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
31316
31317 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
31019 } 31318 }
31020} 31319}
31021 31320
@@ -31130,7 +31429,7 @@ expose_window (struct window *w, XRectangle *fr)
31130 } 31429 }
31131 31430
31132 /* Display the mode line if there is one. */ 31431 /* Display the mode line if there is one. */
31133 if (WINDOW_WANTS_MODELINE_P (w) 31432 if (window_wants_mode_line (w)
31134 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), 31433 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
31135 row->enabled_p) 31434 row->enabled_p)
31136 && row->y < r_bottom) 31435 && row->y < r_bottom)
@@ -31676,7 +31975,7 @@ This variable is not guaranteed to be accurate except while processing
31676\(Assuming the window manager supports this feature.) 31975\(Assuming the window manager supports this feature.)
31677 31976
31678This variable has the same structure as `mode-line-format', except that 31977This variable has the same structure as `mode-line-format', except that
31679the %c and %l constructs are ignored. It is used only on frames for 31978the %c, %C, and %l constructs are ignored. It is used only on frames for
31680which no explicit name has been set (see `modify-frame-parameters'). */); 31979which no explicit name has been set (see `modify-frame-parameters'). */);
31681 31980
31682 DEFVAR_LISP ("icon-title-format", Vicon_title_format, 31981 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
@@ -31855,12 +32154,15 @@ If a frame's ON-STATE has no entry in this list,
31855the frame's other specifications determine how to blink the cursor off. */); 32154the frame's other specifications determine how to blink the cursor off. */);
31856 Vblink_cursor_alist = Qnil; 32155 Vblink_cursor_alist = Qnil;
31857 32156
31858 DEFVAR_BOOL ("auto-hscroll-mode", automatic_hscrolling_p, 32157 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
31859 doc: /* Allow or disallow automatic horizontal scrolling of windows. 32158 doc: /* Allow or disallow automatic horizontal scrolling of windows.
31860If non-nil, windows are automatically scrolled horizontally to make 32159The value `current-line' means the line displaying point in each window
31861point visible. */); 32160is automatically scrolled horizontally to make point visible.
31862 automatic_hscrolling_p = true; 32161Any other non-nil value means all the lines in a window are automatically
32162scrolled horizontally to make point visible. */);
32163 automatic_hscrolling = Qt;
31863 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode"); 32164 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
32165 DEFSYM (Qcurrent_line, "current-line");
31864 32166
31865 DEFVAR_INT ("hscroll-margin", hscroll_margin, 32167 DEFVAR_INT ("hscroll-margin", hscroll_margin,
31866 doc: /* How many columns away from the window edge point is allowed to get 32168 doc: /* How many columns away from the window edge point is allowed to get
@@ -32051,6 +32353,13 @@ display table takes effect; in this case, Emacs does not consult
32051 /* Initialize to t, since we need to disable reordering until 32353 /* Initialize to t, since we need to disable reordering until
32052 loadup.el successfully loads charprop.el. */ 32354 loadup.el successfully loads charprop.el. */
32053 redisplay__inhibit_bidi = true; 32355 redisplay__inhibit_bidi = true;
32356
32357 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
32358 doc: /* Non-nil means display raw bytes in hexadecimal format.
32359The default is to use octal format (\200) whereas hexadecimal (\x80)
32360may be more familiar to users. */);
32361 display_raw_bytes_as_hex = false;
32362
32054} 32363}
32055 32364
32056 32365
diff --git a/src/xfaces.c b/src/xfaces.c
index 7fcaef4e41a..86bb9b0b496 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -4474,6 +4474,10 @@ lookup_basic_face (struct frame *f, int face_id)
4474 case CURSOR_FACE_ID: name = Qcursor; break; 4474 case CURSOR_FACE_ID: name = Qcursor; break;
4475 case MOUSE_FACE_ID: name = Qmouse; break; 4475 case MOUSE_FACE_ID: name = Qmouse; break;
4476 case MENU_FACE_ID: name = Qmenu; break; 4476 case MENU_FACE_ID: name = Qmenu; break;
4477 case WINDOW_DIVIDER_FACE_ID: name = Qwindow_divider; break;
4478 case WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID: name = Qwindow_divider_first_pixel; break;
4479 case WINDOW_DIVIDER_LAST_PIXEL_FACE_ID: name = Qwindow_divider_last_pixel; break;
4480 case INTERNAL_BORDER_FACE_ID: name = Qinternal_border; break;
4477 4481
4478 default: 4482 default:
4479 emacs_abort (); /* the caller is supposed to pass us a basic face id */ 4483 emacs_abort (); /* the caller is supposed to pass us a basic face id */
@@ -5168,6 +5172,7 @@ realize_basic_faces (struct frame *f)
5168 WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID); 5172 WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
5169 realize_named_face (f, Qwindow_divider_last_pixel, 5173 realize_named_face (f, Qwindow_divider_last_pixel,
5170 WINDOW_DIVIDER_LAST_PIXEL_FACE_ID); 5174 WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
5175 realize_named_face (f, Qinternal_border, INTERNAL_BORDER_FACE_ID);
5171 5176
5172 /* Reflect changes in the `menu' face in menu bars. */ 5177 /* Reflect changes in the `menu' face in menu bars. */
5173 if (FRAME_FACE_CACHE (f)->menu_face_changed_p) 5178 if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
@@ -6227,7 +6232,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6227 int red, green, blue; 6232 int red, green, blue;
6228 int num; 6233 int num;
6229 6234
6230 while (fgets (buf, sizeof (buf), fp) != NULL) { 6235 while (fgets_unlocked (buf, sizeof (buf), fp) != NULL) {
6231 if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3) 6236 if (sscanf (buf, "%d %d %d %n", &red, &green, &blue, &num) == 3)
6232 { 6237 {
6233#ifdef HAVE_NTGUI 6238#ifdef HAVE_NTGUI
@@ -6420,11 +6425,12 @@ syms_of_xfaces (void)
6420 DEFSYM (Qmouse, "mouse"); 6425 DEFSYM (Qmouse, "mouse");
6421 DEFSYM (Qmode_line_inactive, "mode-line-inactive"); 6426 DEFSYM (Qmode_line_inactive, "mode-line-inactive");
6422 DEFSYM (Qvertical_border, "vertical-border"); 6427 DEFSYM (Qvertical_border, "vertical-border");
6423
6424 /* TTY color-related functions (defined in tty-colors.el). */
6425 DEFSYM (Qwindow_divider, "window-divider"); 6428 DEFSYM (Qwindow_divider, "window-divider");
6426 DEFSYM (Qwindow_divider_first_pixel, "window-divider-first-pixel"); 6429 DEFSYM (Qwindow_divider_first_pixel, "window-divider-first-pixel");
6427 DEFSYM (Qwindow_divider_last_pixel, "window-divider-last-pixel"); 6430 DEFSYM (Qwindow_divider_last_pixel, "window-divider-last-pixel");
6431 DEFSYM (Qinternal_border, "internal-border");
6432
6433 /* TTY color-related functions (defined in tty-colors.el). */
6428 DEFSYM (Qtty_color_desc, "tty-color-desc"); 6434 DEFSYM (Qtty_color_desc, "tty-color-desc");
6429 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values"); 6435 DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
6430 DEFSYM (Qtty_color_by_index, "tty-color-by-index"); 6436 DEFSYM (Qtty_color_by_index, "tty-color-by-index");
diff --git a/src/xfns.c b/src/xfns.c
index d3e0839d8ac..d8bf9747191 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -90,6 +90,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
90#include <Xm/FileSB.h> 90#include <Xm/FileSB.h>
91#include <Xm/List.h> 91#include <Xm/List.h>
92#include <Xm/TextF.h> 92#include <Xm/TextF.h>
93#include <Xm/MwmUtil.h>
93#endif 94#endif
94 95
95#ifdef USE_LUCID 96#ifdef USE_LUCID
@@ -117,6 +118,35 @@ static ptrdiff_t image_cache_refcount;
117static int dpyinfo_refcount; 118static int dpyinfo_refcount;
118#endif 119#endif
119 120
121#ifndef USE_MOTIF
122#ifndef USE_GTK
123/** #define MWM_HINTS_FUNCTIONS (1L << 0) **/
124#define MWM_HINTS_DECORATIONS (1L << 1)
125/** #define MWM_HINTS_INPUT_MODE (1L << 2) **/
126/** #define MWM_HINTS_STATUS (1L << 3) **/
127
128#define MWM_DECOR_ALL (1L << 0)
129/** #define MWM_DECOR_BORDER (1L << 1) **/
130/** #define MWM_DECOR_RESIZEH (1L << 2) **/
131/** #define MWM_DECOR_TITLE (1L << 3) **/
132/** #define MWM_DECOR_MENU (1L << 4) **/
133/** #define MWM_DECOR_MINIMIZE (1L << 5) **/
134/** #define MWM_DECOR_MAXIMIZE (1L << 6) **/
135
136/** #define _XA_MOTIF_WM_HINTS "_MOTIF_WM_HINTS" **/
137
138typedef struct {
139 unsigned long flags;
140 unsigned long functions;
141 unsigned long decorations;
142 long input_mode;
143 unsigned long status;
144} PropMotifWmHints;
145
146#define PROP_MOTIF_WM_HINTS_ELEMENTS 5
147#endif /* NOT USE_GTK */
148#endif /* NOT USE_MOTIF */
149
120static struct x_display_info *x_display_info_for_name (Lisp_Object); 150static struct x_display_info *x_display_info_for_name (Lisp_Object);
121static void set_up_x_back_buffer (struct frame *f); 151static void set_up_x_back_buffer (struct frame *f);
122 152
@@ -185,7 +215,9 @@ x_real_pos_and_offsets (struct frame *f,
185 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0; 215 int win_x = 0, win_y = 0, outer_x = 0, outer_y = 0;
186 int real_x = 0, real_y = 0; 216 int real_x = 0, real_y = 0;
187 bool had_errors = false; 217 bool had_errors = false;
188 Window win = f->output_data.x->parent_desc; 218 Window win = (FRAME_PARENT_FRAME (f)
219 ? FRAME_X_WINDOW (FRAME_PARENT_FRAME (f))
220 : f->output_data.x->parent_desc);
189 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); 221 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
190 long max_len = 400; 222 long max_len = 400;
191 Atom target_type = XA_CARDINAL; 223 Atom target_type = XA_CARDINAL;
@@ -323,7 +355,8 @@ x_real_pos_and_offsets (struct frame *f,
323 outer_geom_cookie = xcb_get_geometry (xcb_conn, 355 outer_geom_cookie = xcb_get_geometry (xcb_conn,
324 FRAME_OUTER_WINDOW (f)); 356 FRAME_OUTER_WINDOW (f));
325 357
326 if (dpyinfo->root_window == f->output_data.x->parent_desc) 358 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
359 && !FRAME_PARENT_FRAME (f))
327 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */ 360 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
328 prop_cookie = xcb_get_property (xcb_conn, 0, win, 361 prop_cookie = xcb_get_property (xcb_conn, 0, win,
329 dpyinfo->Xatom_net_frame_extents, 362 dpyinfo->Xatom_net_frame_extents,
@@ -437,7 +470,8 @@ x_real_pos_and_offsets (struct frame *f,
437#endif 470#endif
438 } 471 }
439 472
440 if (dpyinfo->root_window == f->output_data.x->parent_desc) 473 if ((dpyinfo->root_window == f->output_data.x->parent_desc)
474 && !FRAME_PARENT_FRAME (f))
441 { 475 {
442 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */ 476 /* Try _NET_FRAME_EXTENTS if our parent is the root window. */
443#ifdef USE_XCB 477#ifdef USE_XCB
@@ -735,6 +769,204 @@ x_set_inhibit_double_buffering (struct frame *f,
735 unblock_input (); 769 unblock_input ();
736} 770}
737 771
772/**
773 * x_set_undecorated:
774 *
775 * Set frame F's `undecorated' parameter. If non-nil, F's window-system
776 * window is drawn without decorations, title, minimize/maximize boxes
777 * and external borders. This usually means that the window cannot be
778 * dragged, resized, iconified, maximized or deleted with the mouse. If
779 * nil, draw the frame with all the elements listed above unless these
780 * have been suspended via window manager settings.
781 *
782 * Some window managers may not honor this parameter.
783 */
784static void
785x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
786{
787 if (!EQ (new_value, old_value))
788 {
789 FRAME_UNDECORATED (f) = NILP (new_value) ? false : true;
790#ifdef USE_GTK
791 xg_set_undecorated (f, new_value);
792#else
793 Display *dpy = FRAME_X_DISPLAY (f);
794 PropMotifWmHints hints;
795 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
796
797 memset (&hints, 0, sizeof(hints));
798 hints.flags = MWM_HINTS_DECORATIONS;
799 hints.decorations = NILP (new_value) ? MWM_DECOR_ALL : 0;
800
801 block_input ();
802 /* For some reason the third and fourth arguments in the following
803 call must be identical: In the corresponding XGetWindowProperty
804 call in getMotifHints, xfwm has the third and seventh args both
805 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
806 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
807 PropModeReplace, (unsigned char *) &hints,
808 PROP_MOTIF_WM_HINTS_ELEMENTS);
809 unblock_input ();
810
811#endif /* USE_GTK */
812 }
813}
814
815/**
816 * x_set_parent_frame:
817 *
818 * Set frame F's `parent-frame' parameter. If non-nil, make F a child
819 * frame of the frame specified by that parameter. Technically, this
820 * makes F's window-system window a child window of the parent frame's
821 * window-system window. If nil, make F's window-system window a
822 * top-level window--a child of its display's root window.
823 *
824 * A child frame is clipped at the native edges of its parent frame.
825 * Its `left' and `top' parameters specify positions relative to the
826 * top-left corner of its parent frame's native rectangle. Usually,
827 * moving a parent frame moves all its child frames too, keeping their
828 * position relative to the parent unaltered. When a parent frame is
829 * iconified or made invisible, its child frames are made invisible.
830 * When a parent frame is deleted, its child frames are deleted too.
831 *
832 * A visible child frame always appears on top of its parent frame thus
833 * obscuring parts of it. When a frame has more than one child frame,
834 * their stacking order is specified just as that of non-child frames
835 * relative to their display.
836 *
837 * Whether a child frame has a menu or tool bar may be window-system or
838 * window manager dependent. It's advisable to disable both via the
839 * frame parameter settings.
840 *
841 * Some window managers may not honor this parameter.
842 */
843static void
844x_set_parent_frame (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
845{
846 struct frame *p = NULL;
847
848 if (!NILP (new_value)
849 && (!FRAMEP (new_value)
850 || !FRAME_LIVE_P (p = XFRAME (new_value))
851 || !FRAME_X_P (p)))
852 {
853 store_frame_param (f, Qparent_frame, old_value);
854 error ("Invalid specification of `parent-frame'");
855 }
856
857 if (p != FRAME_PARENT_FRAME (f))
858 {
859 block_input ();
860 XReparentWindow
861 (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
862 p ? FRAME_X_WINDOW (p) : DefaultRootWindow (FRAME_X_DISPLAY (f)),
863 f->left_pos, f->top_pos);
864 unblock_input ();
865
866 fset_parent_frame (f, new_value);
867 }
868}
869
870/**
871 * x_set_no_focus_on_map:
872 *
873 * Set frame F's `no-focus-on-map' parameter which, if non-nil, means
874 * that F's window-system window does not want to receive input focus
875 * when it is mapped. (A frame's window is mapped when the frame is
876 * displayed for the first time and when the frame changes its state
877 * from `iconified' or `invisible' to `visible'.)
878 *
879 * Some window managers may not honor this parameter.
880 */
881static void
882x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
883{
884 if (!EQ (new_value, old_value))
885 {
886#ifdef USE_GTK
887 xg_set_no_focus_on_map (f, new_value);
888#else /* not USE_GTK */
889 Display *dpy = FRAME_X_DISPLAY (f);
890 Atom prop = XInternAtom (dpy, "_NET_WM_USER_TIME", False);
891 Time timestamp = NILP (new_value) ? CurrentTime : 0;
892
893 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop,
894 XA_CARDINAL, 32, PropModeReplace,
895 (unsigned char *) &timestamp, 1);
896#endif /* USE_GTK */
897 FRAME_NO_FOCUS_ON_MAP (f) = !NILP (new_value);
898 }
899}
900
901/**
902 * x_set_no_accept_focus:
903 *
904 * Set frame F's `no-accept-focus' parameter which, if non-nil, hints
905 * that F's window-system window does not want to receive input focus
906 * via mouse clicks or by moving the mouse into it.
907 *
908 * If non-nil, this may have the unwanted side-effect that a user cannot
909 * scroll a non-selected frame with the mouse.
910 *
911 * Some window managers may not honor this parameter.
912 */
913static void
914x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
915{
916 if (!EQ (new_value, old_value))
917 {
918#ifdef USE_GTK
919 xg_set_no_accept_focus (f, new_value);
920#else /* not USE_GTK */
921#ifdef USE_X_TOOLKIT
922 Arg al[1];
923
924 XtSetArg (al[0], XtNinput, NILP (new_value) ? True : False);
925 XtSetValues (f->output_data.x->widget, al, 1);
926#else /* not USE_X_TOOLKIT */
927 Window window = FRAME_X_WINDOW (f);
928
929 f->output_data.x->wm_hints.input = NILP (new_value) ? True : False;
930 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
931#endif /* USE_X_TOOLKIT */
932#endif /* USE_GTK */
933 FRAME_NO_ACCEPT_FOCUS (f) = !NILP (new_value);
934 }
935}
936
937/**
938 * x_set_override_redirect:
939 *
940 * Set frame F's `override_redirect' parameter which, if non-nil, hints
941 * that the window manager doesn't want to deal with F. Usually, such
942 * frames have no decorations and always appear on top of all frames.
943 *
944 * Some window managers may not honor this parameter.
945 */
946static void
947x_set_override_redirect (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
948{
949 if (!EQ (new_value, old_value))
950 {
951 /* Here (xfwm) override_redirect can be changed for invisible
952 frames only. */
953 x_make_frame_invisible (f);
954
955#ifdef USE_GTK
956 xg_set_override_redirect (f, new_value);
957#else /* not USE_GTK */
958 XSetWindowAttributes attributes;
959
960 attributes.override_redirect = NILP (new_value) ? False : True;
961 XChangeWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
962 CWOverrideRedirect, &attributes);
963#endif
964 x_make_frame_visible (f);
965 FRAME_OVERRIDE_REDIRECT (f) = !NILP (new_value);
966 }
967}
968
969
738#ifdef USE_GTK 970#ifdef USE_GTK
739 971
740/* Set icon from FILE for frame F. By using GTK functions the icon 972/* Set icon from FILE for frame F. By using GTK functions the icon
@@ -888,6 +1120,14 @@ enum mouse_cursor {
888 mouse_cursor_hand, 1120 mouse_cursor_hand,
889 mouse_cursor_horizontal_drag, 1121 mouse_cursor_horizontal_drag,
890 mouse_cursor_vertical_drag, 1122 mouse_cursor_vertical_drag,
1123 mouse_cursor_left_edge,
1124 mouse_cursor_top_left_corner,
1125 mouse_cursor_top_edge,
1126 mouse_cursor_top_right_corner,
1127 mouse_cursor_right_edge,
1128 mouse_cursor_bottom_right_corner,
1129 mouse_cursor_bottom_edge,
1130 mouse_cursor_bottom_left_corner,
891 mouse_cursor_max 1131 mouse_cursor_max
892}; 1132};
893 1133
@@ -907,13 +1147,21 @@ struct mouse_cursor_types {
907 1147
908/* This array must stay in sync with enum mouse_cursor above! */ 1148/* This array must stay in sync with enum mouse_cursor above! */
909static const struct mouse_cursor_types mouse_cursor_types[] = { 1149static const struct mouse_cursor_types mouse_cursor_types[] = {
910 { "text", &Vx_pointer_shape, XC_xterm }, 1150 { "text", &Vx_pointer_shape, XC_xterm },
911 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr }, 1151 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
912 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch }, 1152 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
913 { "modeline", &Vx_mode_pointer_shape, XC_xterm }, 1153 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
914 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 }, 1154 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
915 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow }, 1155 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
916 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow }, 1156 { NULL, &Vx_window_vertical_drag_shape, XC_sb_v_double_arrow },
1157 { NULL, &Vx_window_left_edge_shape, XC_left_side },
1158 { NULL, &Vx_window_top_left_corner_shape, XC_top_left_corner },
1159 { NULL, &Vx_window_top_edge_shape, XC_top_side },
1160 { NULL, &Vx_window_top_right_corner_shape, XC_top_right_corner },
1161 { NULL, &Vx_window_right_edge_shape, XC_right_side },
1162 { NULL, &Vx_window_bottom_right_corner_shape, XC_bottom_right_corner },
1163 { NULL, &Vx_window_bottom_edge_shape, XC_bottom_side },
1164 { NULL, &Vx_window_bottom_left_corner_shape, XC_bottom_left_corner },
917}; 1165};
918 1166
919struct mouse_cursor_data { 1167struct mouse_cursor_data {
@@ -1064,6 +1312,14 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1064 INSTALL_CURSOR (hand_cursor, hand); 1312 INSTALL_CURSOR (hand_cursor, hand);
1065 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag); 1313 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1066 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag); 1314 INSTALL_CURSOR (vertical_drag_cursor, vertical_drag);
1315 INSTALL_CURSOR (left_edge_cursor, left_edge);
1316 INSTALL_CURSOR (top_left_corner_cursor, top_left_corner);
1317 INSTALL_CURSOR (top_edge_cursor, top_edge);
1318 INSTALL_CURSOR (top_right_corner_cursor, top_right_corner);
1319 INSTALL_CURSOR (right_edge_cursor, right_edge);
1320 INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner);
1321 INSTALL_CURSOR (bottom_edge_cursor, bottom_edge);
1322 INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner);
1067 1323
1068#undef INSTALL_CURSOR 1324#undef INSTALL_CURSOR
1069 1325
@@ -1272,7 +1528,7 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1272 most of the commands try to apply themselves to the minibuffer 1528 most of the commands try to apply themselves to the minibuffer
1273 frame itself, and get an error because you can't switch buffers 1529 frame itself, and get an error because you can't switch buffers
1274 in or split the minibuffer window. */ 1530 in or split the minibuffer window. */
1275 if (FRAME_MINIBUF_ONLY_P (f)) 1531 if (FRAME_MINIBUF_ONLY_P (f) || FRAME_PARENT_FRAME (f))
1276 return; 1532 return;
1277 1533
1278 if (TYPE_RANGED_INTEGERP (int, value)) 1534 if (TYPE_RANGED_INTEGERP (int, value))
@@ -1471,15 +1727,10 @@ x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldva
1471 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget); 1727 widget_store_internal_border (FRAME_X_OUTPUT (f)->edit_widget);
1472#endif 1728#endif
1473 1729
1474 if (FRAME_X_WINDOW (f) != 0) 1730 if (FRAME_X_WINDOW (f))
1475 { 1731 {
1476 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width); 1732 adjust_frame_size (f, -1, -1, 3, false, Qinternal_border_width);
1477
1478#ifdef USE_GTK
1479 xg_clear_under_internal_border (f);
1480#else
1481 x_clear_under_internal_border (f); 1733 x_clear_under_internal_border (f);
1482#endif
1483 } 1734 }
1484 } 1735 }
1485 1736
@@ -2648,7 +2899,7 @@ x_window (struct frame *f, long window_prompting)
2648 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++; 2899 XtSetArg (al[ac], XtNdepth, FRAME_DISPLAY_INFO (f)->n_planes); ac++;
2649 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++; 2900 XtSetArg (al[ac], XtNcolormap, FRAME_X_COLORMAP (f)); ac++;
2650 XtSetArg (al[ac], XtNborderWidth, 0); ac++; 2901 XtSetArg (al[ac], XtNborderWidth, 0); ac++;
2651 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass, pane_widget, 2902 frame_widget = XtCreateWidget (f->namebuf, emacsFrameClass (), pane_widget,
2652 al, ac); 2903 al, ac);
2653 2904
2654 f->output_data.x->edit_widget = frame_widget; 2905 f->output_data.x->edit_widget = frame_widget;
@@ -2693,7 +2944,7 @@ x_window (struct frame *f, long window_prompting)
2693 and specify it. 2944 and specify it.
2694 Note that we do not specify here whether the position 2945 Note that we do not specify here whether the position
2695 is a user-specified or program-specified one. 2946 is a user-specified or program-specified one.
2696 We pass that information later, in x_wm_set_size_hints. */ 2947 We pass that information later, in x_wm_set_size_hint. */
2697 { 2948 {
2698 int left = f->left_pos; 2949 int left = f->left_pos;
2699 bool xneg = (window_prompting & XNegative) != 0; 2950 bool xneg = (window_prompting & XNegative) != 0;
@@ -2783,7 +3034,8 @@ x_window (struct frame *f, long window_prompting)
2783 } 3034 }
2784#endif /* HAVE_X_I18N */ 3035#endif /* HAVE_X_I18N */
2785 3036
2786 attribute_mask = CWEventMask; 3037 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
3038 attribute_mask = CWEventMask | CWOverrideRedirect;
2787 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget), 3039 XChangeWindowAttributes (XtDisplay (shell_widget), XtWindow (shell_widget),
2788 attribute_mask, &attributes); 3040 attribute_mask, &attributes);
2789 3041
@@ -2803,6 +3055,25 @@ x_window (struct frame *f, long window_prompting)
2803 x_set_name (f, name, explicit); 3055 x_set_name (f, name, explicit);
2804 } 3056 }
2805 3057
3058 if (FRAME_UNDECORATED (f))
3059 {
3060 Display *dpy = FRAME_X_DISPLAY (f);
3061 PropMotifWmHints hints;
3062 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3063
3064 memset (&hints, 0, sizeof(hints));
3065 hints.flags = MWM_HINTS_DECORATIONS;
3066 hints.decorations = 0;
3067
3068 /* For some reason the third and fourth arguments in the following
3069 call must be identical: In the corresponding XGetWindowProperty
3070 call in getMotifHints, xfwm has the third and seventh args both
3071 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3072 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3073 PropModeReplace, (unsigned char *) &hints,
3074 PROP_MOTIF_WM_HINTS_ELEMENTS);
3075 }
3076
2806 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3077 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2807 f->output_data.x->current_cursor 3078 f->output_data.x->current_cursor
2808 = f->output_data.x->text_cursor); 3079 = f->output_data.x->text_cursor);
@@ -2870,8 +3141,9 @@ x_window (struct frame *f)
2870 attributes.save_under = True; 3141 attributes.save_under = True;
2871 attributes.event_mask = STANDARD_EVENT_SET; 3142 attributes.event_mask = STANDARD_EVENT_SET;
2872 attributes.colormap = FRAME_X_COLORMAP (f); 3143 attributes.colormap = FRAME_X_COLORMAP (f);
3144 attributes.override_redirect = FRAME_OVERRIDE_REDIRECT (f);
2873 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask 3145 attribute_mask = (CWBackPixel | CWBorderPixel | CWBitGravity | CWEventMask
2874 | CWColormap); 3146 | CWOverrideRedirect | CWColormap);
2875 3147
2876 block_input (); 3148 block_input ();
2877 FRAME_X_WINDOW (f) 3149 FRAME_X_WINDOW (f)
@@ -2943,6 +3215,26 @@ x_window (struct frame *f)
2943 x_set_name (f, name, explicit); 3215 x_set_name (f, name, explicit);
2944 } 3216 }
2945 3217
3218 if (FRAME_UNDECORATED (f))
3219 {
3220 Display *dpy = FRAME_X_DISPLAY (f);
3221 PropMotifWmHints hints;
3222 Atom prop = XInternAtom (dpy, "_MOTIF_WM_HINTS", False);
3223
3224 memset (&hints, 0, sizeof(hints));
3225 hints.flags = MWM_HINTS_DECORATIONS;
3226 hints.decorations = 0;
3227
3228 /* For some reason the third and fourth arguments in the following
3229 call must be identical: In the corresponding XGetWindowProperty
3230 call in getMotifHints, xfwm has the third and seventh args both
3231 display_info->atoms[MOTIF_WM_HINTS]. Obviously, YMMV. */
3232 XChangeProperty (dpy, FRAME_OUTER_WINDOW (f), prop, prop, 32,
3233 PropModeReplace, (unsigned char *) &hints,
3234 PROP_MOTIF_WM_HINTS_ELEMENTS);
3235 }
3236
3237
2946 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3238 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
2947 f->output_data.x->current_cursor 3239 f->output_data.x->current_cursor
2948 = f->output_data.x->text_cursor); 3240 = f->output_data.x->text_cursor);
@@ -3285,11 +3577,12 @@ This function is an internal primitive--use `make-frame' instead. */)
3285 Lisp_Object frame, tem; 3577 Lisp_Object frame, tem;
3286 Lisp_Object name; 3578 Lisp_Object name;
3287 bool minibuffer_only = false; 3579 bool minibuffer_only = false;
3580 bool undecorated = false, override_redirect = false;
3288 long window_prompting = 0; 3581 long window_prompting = 0;
3289 ptrdiff_t count = SPECPDL_INDEX (); 3582 ptrdiff_t count = SPECPDL_INDEX ();
3290 Lisp_Object display; 3583 Lisp_Object display;
3291 struct x_display_info *dpyinfo = NULL; 3584 struct x_display_info *dpyinfo = NULL;
3292 Lisp_Object parent; 3585 Lisp_Object parent, parent_frame;
3293 struct kboard *kb; 3586 struct kboard *kb;
3294 int x_width = 0, x_height = 0; 3587 int x_width = 0, x_height = 0;
3295 3588
@@ -3341,6 +3634,36 @@ This function is an internal primitive--use `make-frame' instead. */)
3341 else 3634 else
3342 f = make_frame (true); 3635 f = make_frame (true);
3343 3636
3637 parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
3638 RES_TYPE_SYMBOL);
3639 /* Accept parent-frame iff parent-id was not specified. */
3640 if (!NILP (parent)
3641 || EQ (parent_frame, Qunbound)
3642 || NILP (parent_frame)
3643 || !FRAMEP (parent_frame)
3644 || !FRAME_LIVE_P (XFRAME (parent_frame))
3645 || !FRAME_X_P (XFRAME (parent_frame)))
3646 parent_frame = Qnil;
3647
3648 fset_parent_frame (f, parent_frame);
3649 store_frame_param (f, Qparent_frame, parent_frame);
3650
3651 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL,
3652 RES_TYPE_BOOLEAN)))
3653 && !(EQ (tem, Qunbound)))
3654 undecorated = true;
3655
3656 FRAME_UNDECORATED (f) = undecorated;
3657 store_frame_param (f, Qundecorated, undecorated ? Qt : Qnil);
3658
3659 if (!NILP (tem = (x_get_arg (dpyinfo, parms, Qoverride_redirect, NULL, NULL,
3660 RES_TYPE_BOOLEAN)))
3661 && !(EQ (tem, Qunbound)))
3662 override_redirect = true;
3663
3664 FRAME_OVERRIDE_REDIRECT (f) = override_redirect;
3665 store_frame_param (f, Qoverride_redirect, override_redirect ? Qt : Qnil);
3666
3344 XSETFRAME (frame, f); 3667 XSETFRAME (frame, f);
3345 3668
3346 f->terminal = dpyinfo->terminal; 3669 f->terminal = dpyinfo->terminal;
@@ -3515,6 +3838,8 @@ This function is an internal primitive--use `make-frame' instead. */)
3515 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 3838 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3516 x_default_parameter (f, parms, Qright_fringe, Qnil, 3839 x_default_parameter (f, parms, Qright_fringe, Qnil,
3517 "rightFringe", "RightFringe", RES_TYPE_NUMBER); 3840 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
3841 x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
3842 NULL, NULL, RES_TYPE_BOOLEAN);
3518 3843
3519 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground, 3844 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3520 "scrollBarForeground", 3845 "scrollBarForeground",
@@ -3528,15 +3853,24 @@ This function is an internal primitive--use `make-frame' instead. */)
3528 init_iterator with a null face cache, which should not happen. */ 3853 init_iterator with a null face cache, which should not happen. */
3529 init_frame_faces (f); 3854 init_frame_faces (f);
3530 3855
3531 /* The following call of change_frame_size is needed since otherwise 3856 /* We have to call adjust_frame_size here since otherwise
3532 x_set_tool_bar_lines will already work with the character sizes 3857 x_set_tool_bar_lines will already work with the character sizes
3533 installed by init_frame_faces while the frame's pixel size is 3858 installed by init_frame_faces while the frame's pixel size is still
3534 still calculated from a character size of 1 and we subsequently 3859 calculated from a character size of 1 and we subsequently hit the
3535 hit the (height >= 0) assertion in window_box_height. 3860 (height >= 0) assertion in window_box_height.
3536 3861
3537 The non-pixelwise code apparently worked around this because it 3862 The non-pixelwise code apparently worked around this because it
3538 had one frame line vs one toolbar line which left us with a zero 3863 had one frame line vs one toolbar line which left us with a zero
3539 root window height which was obviously wrong as well ... */ 3864 root window height which was obviously wrong as well ...
3865
3866 Also process `min-width' and `min-height' parameters right here
3867 because `frame-windows-min-size' needs them. */
3868 tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
3869 if (NUMBERP (tem))
3870 store_frame_param (f, Qmin_width, tem);
3871 tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
3872 if (NUMBERP (tem))
3873 store_frame_param (f, Qmin_height, tem);
3540 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f), 3874 adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
3541 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true, 3875 FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, true,
3542 Qx_create_frame_1); 3876 Qx_create_frame_1);
@@ -3611,6 +3945,21 @@ This function is an internal primitive--use `make-frame' instead. */)
3611 x_default_parameter (f, parms, Qalpha, Qnil, 3945 x_default_parameter (f, parms, Qalpha, Qnil,
3612 "alpha", "Alpha", RES_TYPE_NUMBER); 3946 "alpha", "Alpha", RES_TYPE_NUMBER);
3613 3947
3948 if (!NILP (parent_frame))
3949 {
3950 struct frame *p = XFRAME (parent_frame);
3951
3952 block_input ();
3953 XReparentWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
3954 FRAME_X_WINDOW (p), f->left_pos, f->top_pos);
3955 unblock_input ();
3956 }
3957
3958 x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
3959 NULL, NULL, RES_TYPE_BOOLEAN);
3960 x_default_parameter (f, parms, Qno_accept_focus, Qnil,
3961 NULL, NULL, RES_TYPE_BOOLEAN);
3962
3614#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 3963#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
3615 /* Create the menu bar. */ 3964 /* Create the menu bar. */
3616 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f)) 3965 if (!minibuffer_only && FRAME_EXTERNAL_MENU_BAR (f))
@@ -3656,23 +4005,23 @@ This function is an internal primitive--use `make-frame' instead. */)
3656 /* Make the window appear on the frame and enable display, unless 4005 /* Make the window appear on the frame and enable display, unless
3657 the caller says not to. However, with explicit parent, Emacs 4006 the caller says not to. However, with explicit parent, Emacs
3658 cannot control visibility, so don't try. */ 4007 cannot control visibility, so don't try. */
3659 if (! f->output_data.x->explicit_parent) 4008 if (!f->output_data.x->explicit_parent)
3660 { 4009 {
3661 Lisp_Object visibility; 4010 Lisp_Object visibility
3662 4011 = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
3663 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
3664 RES_TYPE_SYMBOL);
3665 if (EQ (visibility, Qunbound))
3666 visibility = Qt;
3667 4012
3668 if (EQ (visibility, Qicon)) 4013 if (EQ (visibility, Qicon))
3669 x_iconify_frame (f); 4014 x_iconify_frame (f);
3670 else if (! NILP (visibility))
3671 x_make_frame_visible (f);
3672 else 4015 else
3673 { 4016 {
3674 /* Must have been Qnil. */ 4017 if (EQ (visibility, Qunbound))
4018 visibility = Qt;
4019
4020 if (!NILP (visibility))
4021 x_make_frame_visible (f);
3675 } 4022 }
4023
4024 store_frame_param (f, Qvisibility, visibility);
3676 } 4025 }
3677 4026
3678 block_input (); 4027 block_input ();
@@ -3685,14 +4034,21 @@ This function is an internal primitive--use `make-frame' instead. */)
3685 if (dpyinfo->client_leader_window != 0) 4034 if (dpyinfo->client_leader_window != 0)
3686 { 4035 {
3687 XChangeProperty (FRAME_X_DISPLAY (f), 4036 XChangeProperty (FRAME_X_DISPLAY (f),
3688 FRAME_OUTER_WINDOW (f), 4037 FRAME_OUTER_WINDOW (f),
3689 dpyinfo->Xatom_wm_client_leader, 4038 dpyinfo->Xatom_wm_client_leader,
3690 XA_WINDOW, 32, PropModeReplace, 4039 XA_WINDOW, 32, PropModeReplace,
3691 (unsigned char *) &dpyinfo->client_leader_window, 1); 4040 (unsigned char *) &dpyinfo->client_leader_window, 1);
3692 } 4041 }
3693 4042
3694 unblock_input (); 4043 unblock_input ();
3695 4044
4045 /* Works iff frame has been already mapped. */
4046 x_default_parameter (f, parms, Qskip_taskbar, Qnil,
4047 NULL, NULL, RES_TYPE_BOOLEAN);
4048 /* The `z-group' parameter works only for visible frames. */
4049 x_default_parameter (f, parms, Qz_group, Qnil,
4050 NULL, NULL, RES_TYPE_SYMBOL);
4051
3696 /* Initialize `default-minibuffer-frame' in case this is the first 4052 /* Initialize `default-minibuffer-frame' in case this is the first
3697 frame on this terminal. */ 4053 frame on this terminal. */
3698 if (FRAME_HAS_MINIBUF_P (f) 4054 if (FRAME_HAS_MINIBUF_P (f)
@@ -3710,7 +4066,7 @@ This function is an internal primitive--use `make-frame' instead. */)
3710 and similar functions. */ 4066 and similar functions. */
3711 Vwindow_list = Qnil; 4067 Vwindow_list = Qnil;
3712 4068
3713 return unbind_to (count, frame); 4069 return unbind_to (count, frame);
3714} 4070}
3715 4071
3716 4072
@@ -3741,7 +4097,7 @@ x_get_focus_frame (struct frame *frame)
3741 following a user-command. */ 4097 following a user-command. */
3742 4098
3743void 4099void
3744x_focus_frame (struct frame *f) 4100x_focus_frame (struct frame *f, bool noactivate)
3745{ 4101{
3746 Display *dpy = FRAME_X_DISPLAY (f); 4102 Display *dpy = FRAME_X_DISPLAY (f);
3747 4103
@@ -3759,7 +4115,8 @@ x_focus_frame (struct frame *f)
3759 { 4115 {
3760 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 4116 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3761 RevertToParent, CurrentTime); 4117 RevertToParent, CurrentTime);
3762 x_ewmh_activate_frame (f); 4118 if (!noactivate)
4119 x_ewmh_activate_frame (f);
3763 } 4120 }
3764 4121
3765 x_uncatch_errors (); 4122 x_uncatch_errors ();
@@ -4644,9 +5001,9 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4644 struct frame *f = decode_live_frame (frame); 5001 struct frame *f = decode_live_frame (frame);
4645 /** XWindowAttributes atts; **/ 5002 /** XWindowAttributes atts; **/
4646 Window rootw; 5003 Window rootw;
4647 unsigned int ign, native_width, native_height; 5004 unsigned int ign, native_width, native_height, x_border_width = 0;
4648 int xy_ign, xptr, yptr; 5005 int x_native = 0, y_native = 0, xptr = 0, yptr = 0;
4649 int left_off, right_off, top_off, bottom_off; 5006 int left_off = 0, right_off = 0, top_off = 0, bottom_off = 0;
4650 int outer_left, outer_top, outer_right, outer_bottom; 5007 int outer_left, outer_top, outer_right, outer_bottom;
4651 int native_left, native_top, native_right, native_bottom; 5008 int native_left, native_top, native_right, native_bottom;
4652 int inner_left, inner_top, inner_right, inner_bottom; 5009 int inner_left, inner_top, inner_right, inner_bottom;
@@ -4660,25 +5017,51 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4660 5017
4661 block_input (); 5018 block_input ();
4662 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 5019 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
4663 &rootw, &xy_ign, &xy_ign, &native_width, &native_height, 5020 &rootw, &x_native, &y_native, &native_width, &native_height,
4664 &ign, &ign); 5021 &x_border_width, &ign);
4665 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/ 5022 /** XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), &atts); **/
4666 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off, 5023 if (!FRAME_PARENT_FRAME (f))
4667 NULL, NULL, &xptr, &yptr, NULL); 5024 x_real_pos_and_offsets (f, &left_off, &right_off, &top_off, &bottom_off,
5025 NULL, NULL, &xptr, &yptr, NULL);
4668 unblock_input (); 5026 unblock_input ();
4669 5027
4670 /** native_width = atts.width; **/ 5028 /** native_width = atts.width; **/
4671 /** native_height = atts.height; **/ 5029 /** native_height = atts.height; **/
4672 5030
4673 outer_left = xptr; 5031 if (FRAME_PARENT_FRAME (f))
4674 outer_top = yptr; 5032 {
4675 outer_right = outer_left + left_off + native_width + right_off; 5033 Lisp_Object parent, edges;
4676 outer_bottom = outer_top + top_off + native_height + bottom_off;
4677 5034
4678 native_left = outer_left + left_off; 5035 XSETFRAME (parent, FRAME_PARENT_FRAME (f));
4679 native_top = outer_top + top_off; 5036 edges = Fx_frame_edges (parent, Qnative_edges);
4680 native_right = native_left + native_width; 5037 if (!NILP (edges))
4681 native_bottom = native_top + native_height; 5038 {
5039 x_native += XINT (Fnth (make_number (0), edges));
5040 y_native += XINT (Fnth (make_number (1), edges));
5041 }
5042
5043 outer_left = x_native;
5044 outer_top = y_native;
5045 outer_right = outer_left + native_width + 2 * x_border_width;
5046 outer_bottom = outer_top + native_height + 2 * x_border_width;
5047
5048 native_left = x_native + x_border_width;
5049 native_top = y_native + x_border_width;
5050 native_right = native_left + native_width;
5051 native_bottom = native_top + native_height;
5052 }
5053 else
5054 {
5055 outer_left = xptr;
5056 outer_top = yptr;
5057 outer_right = outer_left + left_off + native_width + right_off;
5058 outer_bottom = outer_top + top_off + native_height + bottom_off;
5059
5060 native_left = outer_left + left_off;
5061 native_top = outer_top + top_off;
5062 native_right = native_left + native_width;
5063 native_bottom = native_top + native_height;
5064 }
4682 5065
4683 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f); 5066 internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
4684 inner_left = native_left + internal_border_width; 5067 inner_left = native_left + internal_border_width;
@@ -4749,7 +5132,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4749 make_number (inner_right), make_number (inner_bottom)); 5132 make_number (inner_right), make_number (inner_bottom));
4750 else 5133 else
4751 return 5134 return
4752 listn (CONSTYPE_HEAP, 10, 5135 listn (CONSTYPE_HEAP, 11,
4753 Fcons (Qouter_position, 5136 Fcons (Qouter_position,
4754 Fcons (make_number (outer_left), 5137 Fcons (make_number (outer_left),
4755 make_number (outer_top))), 5138 make_number (outer_top))),
@@ -4760,6 +5143,7 @@ frame_geometry (Lisp_Object frame, Lisp_Object attribute)
4760 Fcons (Qexternal_border_size, 5143 Fcons (Qexternal_border_size,
4761 Fcons (make_number (right_off), 5144 Fcons (make_number (right_off),
4762 make_number (bottom_off))), 5145 make_number (bottom_off))),
5146 Fcons (Qouter_border_width, make_number (x_border_width)),
4763 /* Approximate. */ 5147 /* Approximate. */
4764 Fcons (Qtitle_bar_size, 5148 Fcons (Qtitle_bar_size,
4765 Fcons (make_number (0), 5149 Fcons (make_number (0),
@@ -4788,7 +5172,8 @@ and width values are in pixels.
4788 5172
4789`outer-size' is a cons of the outer width and height of FRAME. The 5173`outer-size' is a cons of the outer width and height of FRAME. The
4790 outer size includes the title bar and the external borders as well as 5174 outer size includes the title bar and the external borders as well as
4791 any menu and/or tool bar of frame. 5175 any menu and/or tool bar of frame. For a child frame the value
5176 includes FRAME's X borders, if any.
4792 5177
4793`external-border-size' is a cons of the horizontal and vertical width of 5178`external-border-size' is a cons of the horizontal and vertical width of
4794 FRAME's external borders as supplied by the window manager. 5179 FRAME's external borders as supplied by the window manager.
@@ -4815,7 +5200,11 @@ and width values are in pixels.
4815 FRAME. 5200 FRAME.
4816 5201
4817`internal-border-width' is the width of the internal border of 5202`internal-border-width' is the width of the internal border of
4818 FRAME. */) 5203 FRAME.
5204
5205`outer-border-width' is the width of the X border of FRAME. The X
5206 border is usually only shown for frames without window manager
5207 decorations like child and tooltip frames. */)
4819 (Lisp_Object frame) 5208 (Lisp_Object frame)
4820{ 5209{
4821 return frame_geometry (frame, Qnil); 5210 return frame_geometry (frame, Qnil);
@@ -4845,6 +5234,139 @@ menu bar or tool bar of FRAME. */)
4845 : Qnative_edges)); 5234 : Qnative_edges));
4846} 5235}
4847 5236
5237/**
5238 * x_frame_list_z_order:
5239 *
5240 * Recursively add list of all frames on the display specified via
5241 * DPYINFO and whose window-system window's parent is specified by
5242 * WINDOW to FRAMES and return FRAMES.
5243 */
5244static Lisp_Object
5245x_frame_list_z_order (Display* dpy, Window window)
5246{
5247 Window root, parent, *children;
5248 unsigned int nchildren;
5249 int i;
5250 Lisp_Object frames = Qnil;
5251
5252 block_input ();
5253 if (XQueryTree (dpy, window, &root, &parent, &children, &nchildren))
5254 {
5255 unblock_input ();
5256 for (i = 0; i < nchildren; i++)
5257 {
5258 Lisp_Object frame, tail;
5259
5260 FOR_EACH_FRAME (tail, frame)
5261 /* With a reparenting window manager the parent_desc field
5262 usually specifies the topmost windows of our frames.
5263 Otherwise FRAME_OUTER_WINDOW should do. */
5264 if (XFRAME (frame)->output_data.x->parent_desc == children[i]
5265 || FRAME_OUTER_WINDOW (XFRAME (frame)) == children[i])
5266 frames = Fcons (frame, frames);
5267 }
5268
5269 if (children) XFree ((char *)children);
5270 }
5271 else
5272 unblock_input ();
5273
5274 return frames;
5275}
5276
5277
5278DEFUN ("x-frame-list-z-order", Fx_frame_list_z_order,
5279 Sx_frame_list_z_order, 0, 1, 0,
5280 doc: /* Return list of Emacs' frames, in Z (stacking) order.
5281The optional argument TERMINAL specifies which display to ask about.
5282TERMINAL should be either a frame or a display name (a string). If
5283omitted or nil, that stands for the selected frame's display. Return
5284nil if TERMINAL contains no Emacs frame.
5285
5286As a special case, if TERMINAL is non-nil and specifies a live frame,
5287return the child frames of that frame in Z (stacking) order.
5288
5289Frames are listed from topmost (first) to bottommost (last). */)
5290 (Lisp_Object terminal)
5291{
5292 struct x_display_info *dpyinfo = check_x_display_info (terminal);
5293 Display *dpy = dpyinfo->display;
5294 Window window;
5295
5296 if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
5297 window = FRAME_X_WINDOW (XFRAME (terminal));
5298 else
5299 window = dpyinfo->root_window;
5300
5301 return x_frame_list_z_order (dpy, window);
5302}
5303
5304/**
5305 * x_frame_restack:
5306 *
5307 * Restack frame F1 below frame F2, above if ABOVE_FLAG is non-nil. In
5308 * practice this is a two-step action: The first step removes F1's
5309 * window-system window from the display. The second step reinserts
5310 * F1's window below (above if ABOVE_FLAG is true) that of F2.
5311 */
5312static void
5313x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5314{
5315#if defined (USE_GTK) && GTK_CHECK_VERSION (2, 18, 0)
5316 block_input ();
5317 xg_frame_restack (f1, f2, above_flag);
5318 unblock_input ();
5319#else
5320 Display *dpy = FRAME_X_DISPLAY (f1);
5321 Window window1 = FRAME_OUTER_WINDOW (f1);
5322 XWindowChanges wc;
5323 unsigned long mask = (CWSibling | CWStackMode);
5324
5325 wc.sibling = FRAME_OUTER_WINDOW (f2);
5326 wc.stack_mode = above_flag ? Above : Below;
5327 block_input ();
5328 /* Configure the window manager window (a normal XConfigureWindow
5329 won't cut it). This should also work for child frames. */
5330 XReconfigureWMWindow (dpy, window1, FRAME_X_SCREEN_NUMBER (f1), mask, &wc);
5331 unblock_input ();
5332#endif /* USE_GTK */
5333}
5334
5335
5336DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0,
5337 doc: /* Restack FRAME1 below FRAME2.
5338This means that if both frames are visible and the display areas of
5339these frames overlap, FRAME2 (partially) obscures FRAME1. If optional
5340third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This
5341means that if both frames are visible and the display areas of these
5342frames overlap, FRAME1 (partially) obscures FRAME2.
5343
5344This may be thought of as an atomic action performed in two steps: The
5345first step removes FRAME1's window-step window from the display. The
5346second step reinserts FRAME1's window below (above if ABOVE is true)
5347that of FRAME2. Hence the position of FRAME2 in its display's Z
5348\(stacking) order relative to all other frames excluding FRAME1 remains
5349unaltered.
5350
5351Some window managers may refuse to restack windows. */)
5352 (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
5353{
5354 struct frame *f1 = decode_live_frame (frame1);
5355 struct frame *f2 = decode_live_frame (frame2);
5356
5357 if (FRAME_OUTER_WINDOW (f1) && FRAME_OUTER_WINDOW (f2))
5358 {
5359 x_frame_restack (f1, f2, !NILP (above));
5360 return Qt;
5361 }
5362 else
5363 {
5364 error ("Cannot restack frames");
5365 return Qnil;
5366 }
5367}
5368
5369
4848DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position, 5370DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position,
4849 Sx_mouse_absolute_pixel_position, 0, 0, 0, 5371 Sx_mouse_absolute_pixel_position, 0, 0, 0,
4850 doc: /* Return absolute position of mouse cursor in pixels. 5372 doc: /* Return absolute position of mouse cursor in pixels.
@@ -5700,6 +6222,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
5700 "cursorColor", "Foreground", RES_TYPE_STRING); 6222 "cursorColor", "Foreground", RES_TYPE_STRING);
5701 x_default_parameter (f, parms, Qborder_color, build_string ("black"), 6223 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
5702 "borderColor", "BorderColor", RES_TYPE_STRING); 6224 "borderColor", "BorderColor", RES_TYPE_STRING);
6225 x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
6226 NULL, NULL, RES_TYPE_BOOLEAN);
5703 6227
5704 /* Init faces before x_default_parameter is called for the 6228 /* Init faces before x_default_parameter is called for the
5705 scroll-bar-width parameter because otherwise we end up in 6229 scroll-bar-width parameter because otherwise we end up in
@@ -6585,6 +7109,8 @@ value of DIR as in previous invocations; this is standard Windows behavior. */)
6585 7109
6586 if (popup_activated ()) 7110 if (popup_activated ())
6587 error ("Trying to use a menu from within a menu-entry"); 7111 error ("Trying to use a menu from within a menu-entry");
7112 else
7113 x_menu_set_in_use (true);
6588 7114
6589 CHECK_STRING (prompt); 7115 CHECK_STRING (prompt);
6590 CHECK_STRING (dir); 7116 CHECK_STRING (dir);
@@ -6641,6 +7167,8 @@ nil, it defaults to the selected frame. */)
6641 7167
6642 if (popup_activated ()) 7168 if (popup_activated ())
6643 error ("Trying to use a menu from within a menu-entry"); 7169 error ("Trying to use a menu from within a menu-entry");
7170 else
7171 x_menu_set_in_use (true);
6644 7172
6645 /* Prevent redisplay. */ 7173 /* Prevent redisplay. */
6646 specbind (Qinhibit_redisplay, Qt); 7174 specbind (Qinhibit_redisplay, Qt);
@@ -6979,6 +7507,14 @@ frame_parm_handler x_frame_parm_handlers[] =
6979 x_set_sticky, 7507 x_set_sticky,
6980 x_set_tool_bar_position, 7508 x_set_tool_bar_position,
6981 x_set_inhibit_double_buffering, 7509 x_set_inhibit_double_buffering,
7510 x_set_undecorated,
7511 x_set_parent_frame,
7512 x_set_skip_taskbar,
7513 x_set_no_focus_on_map,
7514 x_set_no_accept_focus,
7515 x_set_z_group,
7516 x_set_override_redirect,
7517 x_set_no_special_glyphs,
6982}; 7518};
6983 7519
6984void 7520void
@@ -7057,6 +7593,62 @@ This variable takes effect when you create a new frame
7057or when you set the mouse color. */); 7593or when you set the mouse color. */);
7058 Vx_window_vertical_drag_shape = Qnil; 7594 Vx_window_vertical_drag_shape = Qnil;
7059 7595
7596 DEFVAR_LISP ("x-window-left-edge-cursor",
7597 Vx_window_left_edge_shape,
7598 doc: /* Pointer shape indicating a left x-window edge can be dragged.
7599This variable takes effect when you create a new frame
7600or when you set the mouse color. */);
7601 Vx_window_left_edge_shape = Qnil;
7602
7603 DEFVAR_LISP ("x-window-top-left-corner-cursor",
7604 Vx_window_top_left_corner_shape,
7605 doc: /* Pointer shape indicating a top left x-window corner can be dragged.
7606This variable takes effect when you create a new frame
7607or when you set the mouse color. */);
7608 Vx_window_top_left_corner_shape = Qnil;
7609
7610 DEFVAR_LISP ("x-window-top-edge-cursor",
7611 Vx_window_top_edge_shape,
7612 doc: /* Pointer shape indicating a top x-window edge can be dragged.
7613This variable takes effect when you create a new frame
7614or when you set the mouse color. */);
7615 Vx_window_top_edge_shape = Qnil;
7616
7617 DEFVAR_LISP ("x-window-top-right-corner-cursor",
7618 Vx_window_top_right_corner_shape,
7619 doc: /* Pointer shape indicating a top right x-window corner can be dragged.
7620This variable takes effect when you create a new frame
7621or when you set the mouse color. */);
7622 Vx_window_top_right_corner_shape = Qnil;
7623
7624 DEFVAR_LISP ("x-window-right-edge-cursor",
7625 Vx_window_right_edge_shape,
7626 doc: /* Pointer shape indicating a right x-window edge can be dragged.
7627This variable takes effect when you create a new frame
7628or when you set the mouse color. */);
7629 Vx_window_right_edge_shape = Qnil;
7630
7631 DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
7632 Vx_window_bottom_right_corner_shape,
7633 doc: /* Pointer shape indicating a bottom right x-window corner can be dragged.
7634This variable takes effect when you create a new frame
7635or when you set the mouse color. */);
7636 Vx_window_bottom_right_corner_shape = Qnil;
7637
7638 DEFVAR_LISP ("x-window-bottom-edge-cursor",
7639 Vx_window_bottom_edge_shape,
7640 doc: /* Pointer shape indicating a bottom x-window edge can be dragged.
7641This variable takes effect when you create a new frame
7642or when you set the mouse color. */);
7643 Vx_window_bottom_edge_shape = Qnil;
7644
7645 DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
7646 Vx_window_bottom_left_corner_shape,
7647 doc: /* Pointer shape indicating a bottom left x-window corner can be dragged.
7648This variable takes effect when you create a new frame
7649or when you set the mouse color. */);
7650 Vx_window_bottom_left_corner_shape = Qnil;
7651
7060 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, 7652 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7061 doc: /* A string indicating the foreground color of the cursor box. */); 7653 doc: /* A string indicating the foreground color of the cursor box. */);
7062 Vx_cursor_fore_pixel = Qnil; 7654 Vx_cursor_fore_pixel = Qnil;
@@ -7183,6 +7775,8 @@ When using Gtk+ tooltips, the tooltip face is not used. */);
7183 defsubr (&Sx_display_monitor_attributes_list); 7775 defsubr (&Sx_display_monitor_attributes_list);
7184 defsubr (&Sx_frame_geometry); 7776 defsubr (&Sx_frame_geometry);
7185 defsubr (&Sx_frame_edges); 7777 defsubr (&Sx_frame_edges);
7778 defsubr (&Sx_frame_list_z_order);
7779 defsubr (&Sx_frame_restack);
7186 defsubr (&Sx_mouse_absolute_pixel_position); 7780 defsubr (&Sx_mouse_absolute_pixel_position);
7187 defsubr (&Sx_set_mouse_absolute_pixel_position); 7781 defsubr (&Sx_set_mouse_absolute_pixel_position);
7188 defsubr (&Sx_wm_set_size_hint); 7782 defsubr (&Sx_wm_set_size_hint);
diff --git a/src/xmenu.c b/src/xmenu.c
index 249cd6903fa..6c8a0c506cc 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -140,14 +140,26 @@ menubar_id_to_frame (LWLIB_ID id)
140void 140void
141x_menu_set_in_use (bool in_use) 141x_menu_set_in_use (bool in_use)
142{ 142{
143 Lisp_Object frames, frame;
144
143 menu_items_inuse = in_use ? Qt : Qnil; 145 menu_items_inuse = in_use ? Qt : Qnil;
144 popup_activated_flag = in_use; 146 popup_activated_flag = in_use;
145#ifdef USE_X_TOOLKIT 147#ifdef USE_X_TOOLKIT
146 if (popup_activated_flag) 148 if (popup_activated_flag)
147 x_activate_timeout_atimer (); 149 x_activate_timeout_atimer ();
148#endif 150#endif
149}
150 151
152 /* Don't let frames in `above' z-group obscure popups. */
153 FOR_EACH_FRAME (frames, frame)
154 {
155 struct frame *f = XFRAME (frame);
156
157 if (in_use && FRAME_Z_GROUP_ABOVE (f))
158 x_set_z_group (f, Qabove_suspended, Qabove);
159 else if (!in_use && FRAME_Z_GROUP_ABOVE_SUSPENDED (f))
160 x_set_z_group (f, Qabove, Qabove_suspended);
161 }
162}
151#endif 163#endif
152 164
153/* Wait for an X event to arrive or for a timer to expire. */ 165/* Wait for an X event to arrive or for a timer to expire. */
@@ -1148,9 +1160,37 @@ menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer
1148{ 1160{
1149 struct next_popup_x_y *data = user_data; 1161 struct next_popup_x_y *data = user_data;
1150 GtkRequisition req; 1162 GtkRequisition req;
1151 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (data->f); 1163 int max_x = -1;
1152 int disp_width = x_display_pixel_width (dpyinfo); 1164 int max_y = -1;
1153 int disp_height = x_display_pixel_height (dpyinfo); 1165
1166 Lisp_Object frame, workarea;
1167
1168 XSETFRAME (frame, data->f);
1169
1170 /* TODO: Get the monitor workarea directly without calculating other
1171 items in x-display-monitor-attributes-list. */
1172 workarea = call3 (Qframe_monitor_workarea,
1173 Qnil,
1174 make_number (data->x),
1175 make_number (data->y));
1176
1177 if (CONSP (workarea))
1178 {
1179 int min_x, min_y;
1180
1181 min_x = XINT (XCAR (workarea));
1182 min_y = XINT (Fnth (make_number (1), workarea));
1183 max_x = min_x + XINT (Fnth (make_number (2), workarea));
1184 max_y = min_y + XINT (Fnth (make_number (3), workarea));
1185 }
1186
1187 if (max_x < 0 || max_y < 0)
1188 {
1189 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (data->f);
1190
1191 max_x = x_display_pixel_width (dpyinfo);
1192 max_y = x_display_pixel_height (dpyinfo);
1193 }
1154 1194
1155 *x = data->x; 1195 *x = data->x;
1156 *y = data->y; 1196 *y = data->y;
@@ -1158,10 +1198,10 @@ menu_position_func (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer
1158 /* Check if there is room for the menu. If not, adjust x/y so that 1198 /* Check if there is room for the menu. If not, adjust x/y so that
1159 the menu is fully visible. */ 1199 the menu is fully visible. */
1160 gtk_widget_get_preferred_size (GTK_WIDGET (menu), NULL, &req); 1200 gtk_widget_get_preferred_size (GTK_WIDGET (menu), NULL, &req);
1161 if (data->x + req.width > disp_width) 1201 if (data->x + req.width > max_x)
1162 *x -= data->x + req.width - disp_width; 1202 *x -= data->x + req.width - max_x;
1163 if (data->y + req.height > disp_height) 1203 if (data->y + req.height > max_y)
1164 *y -= data->y + req.height - disp_height; 1204 *y -= data->y + req.height - max_y;
1165} 1205}
1166 1206
1167static void 1207static void
@@ -2349,6 +2389,10 @@ syms_of_xmenu (void)
2349 DEFSYM (Qdebug_on_next_call, "debug-on-next-call"); 2389 DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
2350 defsubr (&Smenu_or_popup_active_p); 2390 defsubr (&Smenu_or_popup_active_p);
2351 2391
2392#ifdef USE_GTK
2393 DEFSYM (Qframe_monitor_workarea, "frame-monitor-workarea");
2394#endif
2395
2352#if defined (USE_GTK) || defined (USE_X_TOOLKIT) 2396#if defined (USE_GTK) || defined (USE_X_TOOLKIT)
2353 defsubr (&Sx_menu_bar_open_internal); 2397 defsubr (&Sx_menu_bar_open_internal);
2354 Ffset (intern_c_string ("accelerate-menu"), 2398 Ffset (intern_c_string ("accelerate-menu"),
diff --git a/src/xterm.c b/src/xterm.c
index 4f9eff6c5e6..a214cd81031 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -569,7 +569,7 @@ x_cr_export_frames (Lisp_Object frames, cairo_surface_type_t surface_type)
569 int width, height; 569 int width, height;
570 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL; 570 void (*surface_set_size_func) (cairo_surface_t *, double, double) = NULL;
571 Lisp_Object acc = Qnil; 571 Lisp_Object acc = Qnil;
572 int count = SPECPDL_INDEX (); 572 ptrdiff_t count = SPECPDL_INDEX ();
573 573
574 specbind (Qredisplay_dont_pause, Qt); 574 specbind (Qredisplay_dont_pause, Qt);
575 redisplay_preserve_echo_area (31); 575 redisplay_preserve_echo_area (31);
@@ -945,11 +945,14 @@ x_set_frame_alpha (struct frame *f)
945 Do this unconditionally as this function is called on reparent when 945 Do this unconditionally as this function is called on reparent when
946 alpha has not changed on the frame. */ 946 alpha has not changed on the frame. */
947 947
948 parent = x_find_topmost_parent (f); 948 if (!FRAME_PARENT_FRAME (f))
949 if (parent != None) 949 {
950 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity, 950 parent = x_find_topmost_parent (f);
951 XA_CARDINAL, 32, PropModeReplace, 951 if (parent != None)
952 (unsigned char *) &opac, 1); 952 XChangeProperty (dpy, parent, dpyinfo->Xatom_net_wm_window_opacity,
953 XA_CARDINAL, 32, PropModeReplace,
954 (unsigned char *) &opac, 1);
955 }
953 956
954 /* return unless necessary */ 957 /* return unless necessary */
955 { 958 {
@@ -1292,8 +1295,12 @@ XTbuffer_flipping_unblocked_hook (struct frame *f)
1292 show_back_buffer (f); 1295 show_back_buffer (f);
1293} 1296}
1294 1297
1295/* Clear under internal border if any (GTK has its own version). */ 1298/**
1296#ifndef USE_GTK 1299 * x_clear_under_internal_border:
1300 *
1301 * Clear area of frame F's internal border. If the internal border face
1302 * of F has been specified (is not null), fill the area with that face.
1303 */
1297void 1304void
1298x_clear_under_internal_border (struct frame *f) 1305x_clear_under_internal_border (struct frame *f)
1299{ 1306{
@@ -1302,17 +1309,39 @@ x_clear_under_internal_border (struct frame *f)
1302 int border = FRAME_INTERNAL_BORDER_WIDTH (f); 1309 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
1303 int width = FRAME_PIXEL_WIDTH (f); 1310 int width = FRAME_PIXEL_WIDTH (f);
1304 int height = FRAME_PIXEL_HEIGHT (f); 1311 int height = FRAME_PIXEL_HEIGHT (f);
1312#ifdef USE_GTK
1313 int margin = 0;
1314#else
1305 int margin = FRAME_TOP_MARGIN_HEIGHT (f); 1315 int margin = FRAME_TOP_MARGIN_HEIGHT (f);
1316#endif
1317 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
1306 1318
1307 block_input (); 1319 block_input ();
1308 x_clear_area (f, 0, 0, border, height); 1320
1309 x_clear_area (f, 0, margin, width, border); 1321 if (face)
1310 x_clear_area (f, width - border, 0, border, height); 1322 {
1311 x_clear_area (f, 0, height - border, width, border); 1323 unsigned long color = face->background;
1324 Display *display = FRAME_X_DISPLAY (f);
1325 GC gc = f->output_data.x->normal_gc;
1326
1327 XSetForeground (display, gc, color);
1328 x_fill_rectangle (f, gc, 0, margin, width, border);
1329 x_fill_rectangle (f, gc, 0, 0, border, height);
1330 x_fill_rectangle (f, gc, width - border, 0, border, height);
1331 x_fill_rectangle (f, gc, 0, height - border, width, border);
1332 XSetForeground (display, gc, FRAME_FOREGROUND_PIXEL (f));
1333 }
1334 else
1335 {
1336 x_clear_area (f, 0, 0, border, height);
1337 x_clear_area (f, 0, margin, width, border);
1338 x_clear_area (f, width - border, 0, border, height);
1339 x_clear_area (f, 0, height - border, width, border);
1340 }
1341
1312 unblock_input (); 1342 unblock_input ();
1313 } 1343 }
1314} 1344}
1315#endif
1316 1345
1317/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay 1346/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1318 arrow bitmaps, or clear the fringes if no bitmaps are required 1347 arrow bitmaps, or clear the fringes if no bitmaps are required
@@ -1348,10 +1377,25 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
1348 height > 0)) 1377 height > 0))
1349 { 1378 {
1350 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); 1379 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1380 struct face *face = FACE_FROM_ID_OR_NULL (f, INTERNAL_BORDER_FACE_ID);
1351 1381
1352 block_input (); 1382 block_input ();
1353 x_clear_area (f, 0, y, width, height); 1383 if (face)
1354 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height); 1384 {
1385 unsigned long color = face->background;
1386 Display *display = FRAME_X_DISPLAY (f);
1387
1388 XSetForeground (display, f->output_data.x->normal_gc, color);
1389 x_fill_rectangle (f, f->output_data.x->normal_gc,
1390 0, y, width, height);
1391 x_fill_rectangle (f, f->output_data.x->normal_gc,
1392 FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1393 }
1394 else
1395 {
1396 x_clear_area (f, 0, y, width, height);
1397 x_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height);
1398 }
1355 unblock_input (); 1399 unblock_input ();
1356 } 1400 }
1357 } 1401 }
@@ -1961,9 +2005,9 @@ x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
1961 } 2005 }
1962 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE) 2006 else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
1963 { 2007 {
1964 sprintf (buf, "%0*X", 2008 unsigned int ch = glyph->u.glyphless.ch;
1965 glyph->u.glyphless.ch < 0x10000 ? 4 : 6, 2009 eassume (ch <= MAX_CHAR);
1966 glyph->u.glyphless.ch + 0u); 2010 sprintf (buf, "%0*X", ch < 0x10000 ? 4 : 6, ch);
1967 str = buf; 2011 str = buf;
1968 } 2012 }
1969 2013
@@ -3846,11 +3890,11 @@ x_clear_area (struct frame *f, int x, int y, int width, int height)
3846 cairo_fill (cr); 3890 cairo_fill (cr);
3847 x_end_cr_clip (f); 3891 x_end_cr_clip (f);
3848#else 3892#else
3849 if (FRAME_X_DOUBLE_BUFFERED_P (f)) 3893 if (FRAME_X_DOUBLE_BUFFERED_P (f))
3850 XFillRectangle (FRAME_X_DISPLAY (f), 3894 XFillRectangle (FRAME_X_DISPLAY (f),
3851 FRAME_X_DRAWABLE (f), 3895 FRAME_X_DRAWABLE (f),
3852 f->output_data.x->reverse_gc, 3896 f->output_data.x->reverse_gc,
3853 x, y, width, height); 3897 x, y, width, height);
3854 else 3898 else
3855 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3899 x_clear_area1 (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3856 x, y, width, height, False); 3900 x, y, width, height, False);
@@ -4964,6 +5008,9 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
4964 containing the pointer. */ 5008 containing the pointer. */
4965 { 5009 {
4966 Window win, child; 5010 Window win, child;
5011#ifdef USE_GTK
5012 Window first_win = 0;
5013#endif
4967 int win_x, win_y; 5014 int win_x, win_y;
4968 int parent_x = 0, parent_y = 0; 5015 int parent_x = 0, parent_y = 0;
4969 5016
@@ -5010,20 +5057,37 @@ XTmouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
5010 &child); 5057 &child);
5011 5058
5012 if (child == None || child == win) 5059 if (child == None || child == win)
5013 break; 5060 {
5061#ifdef USE_GTK
5062 /* On GTK we have not inspected WIN yet. If it has
5063 a frame and that frame has a parent, use it. */
5064 struct frame *f = x_window_to_frame (dpyinfo, win);
5065
5066 if (f && FRAME_PARENT_FRAME (f))
5067 first_win = win;
5068#endif
5069 break;
5070 }
5014#ifdef USE_GTK 5071#ifdef USE_GTK
5015 /* We don't wan't to know the innermost window. We 5072 /* We don't wan't to know the innermost window. We
5016 want the edit window. For non-Gtk+ the innermost 5073 want the edit window. For non-Gtk+ the innermost
5017 window is the edit window. For Gtk+ it might not 5074 window is the edit window. For Gtk+ it might not
5018 be. It might be the tool bar for example. */ 5075 be. It might be the tool bar for example. */
5019 if (x_window_to_frame (dpyinfo, win)) 5076 if (x_window_to_frame (dpyinfo, win))
5020 break; 5077 /* But don't hurry. We might find a child frame
5078 beneath. */
5079 first_win = win;
5021#endif 5080#endif
5022 win = child; 5081 win = child;
5023 parent_x = win_x; 5082 parent_x = win_x;
5024 parent_y = win_y; 5083 parent_y = win_y;
5025 } 5084 }
5026 5085
5086#ifdef USE_GTK
5087 if (first_win)
5088 win = first_win;
5089#endif
5090
5027 /* Now we know that: 5091 /* Now we know that:
5028 win is the innermost window containing the pointer 5092 win is the innermost window containing the pointer
5029 (XTC says it has no child containing the pointer), 5093 (XTC says it has no child containing the pointer),
@@ -5284,20 +5348,22 @@ xt_horizontal_action_hook (Widget widget, XtPointer client_data, String action_n
5284 x_send_scroll_bar_event (window_being_scrolled, 5348 x_send_scroll_bar_event (window_being_scrolled,
5285 scroll_bar_end_scroll, 0, 0, true); 5349 scroll_bar_end_scroll, 0, 0, true);
5286 w = XWINDOW (window_being_scrolled); 5350 w = XWINDOW (window_being_scrolled);
5287 bar = XSCROLL_BAR (w->horizontal_scroll_bar); 5351 if (!NILP (w->horizontal_scroll_bar))
5288
5289 if (bar->dragging != -1)
5290 { 5352 {
5291 bar->dragging = -1; 5353 bar = XSCROLL_BAR (w->horizontal_scroll_bar);
5292 /* The thumb size is incorrect while dragging: fix it. */ 5354 if (bar->dragging != -1)
5293 set_horizontal_scroll_bar (w); 5355 {
5294 } 5356 bar->dragging = -1;
5295 window_being_scrolled = Qnil; 5357 /* The thumb size is incorrect while dragging: fix it. */
5358 set_horizontal_scroll_bar (w);
5359 }
5360 window_being_scrolled = Qnil;
5296#if defined (USE_LUCID) 5361#if defined (USE_LUCID)
5297 bar->last_seen_part = scroll_bar_nowhere; 5362 bar->last_seen_part = scroll_bar_nowhere;
5298#endif 5363#endif
5299 /* Xt timeouts no longer needed. */ 5364 /* Xt timeouts no longer needed. */
5300 toolkit_scroll_bar_interaction = false; 5365 toolkit_scroll_bar_interaction = false;
5366 }
5301 } 5367 }
5302} 5368}
5303#endif /* not USE_GTK */ 5369#endif /* not USE_GTK */
@@ -6496,10 +6562,14 @@ x_scroll_bar_create (struct window *w, int top, int left,
6496 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar); 6562 Widget scroll_bar = SCROLL_BAR_X_WIDGET (FRAME_X_DISPLAY (f), bar);
6497 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0); 6563 XtConfigureWidget (scroll_bar, left, top, width, max (height, 1), 0);
6498 XtMapWidget (scroll_bar); 6564 XtMapWidget (scroll_bar);
6565 /* Don't obscure any child frames. */
6566 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6499#endif /* not USE_GTK */ 6567#endif /* not USE_GTK */
6500 } 6568 }
6501#else /* not USE_TOOLKIT_SCROLL_BARS */ 6569#else /* not USE_TOOLKIT_SCROLL_BARS */
6502 XMapRaised (FRAME_X_DISPLAY (f), bar->x_window); 6570 XMapWindow (FRAME_X_DISPLAY (f), bar->x_window);
6571 /* Don't obscure any child frames. */
6572 XLowerWindow (FRAME_X_DISPLAY (f), bar->x_window);
6503#endif /* not USE_TOOLKIT_SCROLL_BARS */ 6573#endif /* not USE_TOOLKIT_SCROLL_BARS */
6504 6574
6505 unblock_input (); 6575 unblock_input ();
@@ -7067,10 +7137,10 @@ x_scroll_bar_expose (struct scroll_bar *bar, const XEvent *event)
7067 /* x, y, width, height */ 7137 /* x, y, width, height */
7068 0, 0, bar->width - 1, bar->height - 1); 7138 0, 0, bar->width - 1, bar->height - 1);
7069 7139
7070 /* Restore the foreground color of the GC if we changed it above. */ 7140 /* Restore the foreground color of the GC if we changed it above. */
7071 if (f->output_data.x->scroll_bar_foreground_pixel != -1) 7141 if (f->output_data.x->scroll_bar_foreground_pixel != -1)
7072 XSetForeground (FRAME_X_DISPLAY (f), gc, 7142 XSetForeground (FRAME_X_DISPLAY (f), gc,
7073 FRAME_FOREGROUND_PIXEL (f)); 7143 FRAME_FOREGROUND_PIXEL (f));
7074 7144
7075 unblock_input (); 7145 unblock_input ();
7076 7146
@@ -7839,8 +7909,21 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7839 f = x_top_window_to_frame (dpyinfo, event->xreparent.window); 7909 f = x_top_window_to_frame (dpyinfo, event->xreparent.window);
7840 if (f) 7910 if (f)
7841 { 7911 {
7842 f->output_data.x->parent_desc = event->xreparent.parent; 7912 /* Maybe we shouldn't set this for child frames ?? */
7843 x_real_positions (f, &f->left_pos, &f->top_pos); 7913 f->output_data.x->parent_desc = event->xreparent.parent;
7914 if (!FRAME_PARENT_FRAME (f))
7915 x_real_positions (f, &f->left_pos, &f->top_pos);
7916 else
7917 {
7918 Window root;
7919 unsigned int dummy_uint;
7920
7921 block_input ();
7922 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
7923 &root, &f->left_pos, &f->top_pos,
7924 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
7925 unblock_input ();
7926 }
7844 7927
7845 /* Perhaps reparented due to a WM restart. Reset this. */ 7928 /* Perhaps reparented due to a WM restart. Reset this. */
7846 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; 7929 FRAME_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN;
@@ -7880,6 +7963,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7880 event->xexpose.x, event->xexpose.y, 7963 event->xexpose.x, event->xexpose.y,
7881 event->xexpose.width, event->xexpose.height, 7964 event->xexpose.width, event->xexpose.height,
7882 0); 7965 0);
7966 x_clear_under_internal_border (f);
7883#endif 7967#endif
7884 } 7968 }
7885 7969
@@ -7895,6 +7979,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7895#endif 7979#endif
7896 expose_frame (f, event->xexpose.x, event->xexpose.y, 7980 expose_frame (f, event->xexpose.x, event->xexpose.y,
7897 event->xexpose.width, event->xexpose.height); 7981 event->xexpose.width, event->xexpose.height);
7982#ifdef USE_GTK
7983 x_clear_under_internal_border (f);
7984#endif
7898 } 7985 }
7899 7986
7900 if (!FRAME_GARBAGED_P (f)) 7987 if (!FRAME_GARBAGED_P (f))
@@ -7943,7 +8030,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
7943 event->xgraphicsexpose.y, 8030 event->xgraphicsexpose.y,
7944 event->xgraphicsexpose.width, 8031 event->xgraphicsexpose.width,
7945 event->xgraphicsexpose.height); 8032 event->xgraphicsexpose.height);
7946 show_back_buffer (f); 8033#ifdef USE_GTK
8034 x_clear_under_internal_border (f);
8035#endif
8036 show_back_buffer (f);
7947 } 8037 }
7948#ifdef USE_X_TOOLKIT 8038#ifdef USE_X_TOOLKIT
7949 else 8039 else
@@ -8000,7 +8090,26 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8000 /* Check if fullscreen was specified before we where mapped the 8090 /* Check if fullscreen was specified before we where mapped the
8001 first time, i.e. from the command line. */ 8091 first time, i.e. from the command line. */
8002 if (!f->output_data.x->has_been_visible) 8092 if (!f->output_data.x->has_been_visible)
8003 x_check_fullscreen (f); 8093 {
8094
8095 x_check_fullscreen (f);
8096#ifndef USE_GTK
8097 /* For systems that cannot synthesize `skip_taskbar' for
8098 unmapped windows do the following. */
8099 if (FRAME_SKIP_TASKBAR (f))
8100 x_set_skip_taskbar (f, Qt, Qnil);
8101#endif /* Not USE_GTK */
8102 }
8103
8104 if (!iconified)
8105 {
8106 /* The `z-group' is reset every time a frame becomes
8107 invisible. Handle this here. */
8108 if (FRAME_Z_GROUP (f) == z_group_above)
8109 x_set_z_group (f, Qabove, Qnil);
8110 else if (FRAME_Z_GROUP (f) == z_group_below)
8111 x_set_z_group (f, Qbelow, Qnil);
8112 }
8004 8113
8005 SET_FRAME_VISIBLE (f, 1); 8114 SET_FRAME_VISIBLE (f, 1);
8006 SET_FRAME_ICONIFIED (f, false); 8115 SET_FRAME_ICONIFIED (f, false);
@@ -8444,34 +8553,46 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8444#endif 8553#endif
8445 if (f) 8554 if (f)
8446 { 8555 {
8447 8556 /* Maybe generate a SELECT_WINDOW_EVENT for
8448 /* Generate SELECT_WINDOW_EVENTs when needed. 8557 `mouse-autoselect-window' but don't let popup menus
8449 Don't let popup menus influence things (bug#1261). */ 8558 interfere with this (Bug#1261). */
8450 if (!NILP (Vmouse_autoselect_window) && !popup_activated ()) 8559 if (!NILP (Vmouse_autoselect_window)
8560 && !popup_activated ()
8561 /* Don't switch if we're currently in the minibuffer.
8562 This tries to work around problems where the
8563 minibuffer gets unselected unexpectedly, and where
8564 you then have to move your mouse all the way down to
8565 the minibuffer to select it. */
8566 && !MINI_WINDOW_P (XWINDOW (selected_window))
8567 /* With `focus-follows-mouse' non-nil create an event
8568 also when the target window is on another frame. */
8569 && (f == XFRAME (selected_frame)
8570 || !NILP (focus_follows_mouse)))
8451 { 8571 {
8452 static Lisp_Object last_mouse_window; 8572 static Lisp_Object last_mouse_window;
8453 Lisp_Object window = window_from_coordinates 8573 Lisp_Object window = window_from_coordinates
8454 (f, event->xmotion.x, event->xmotion.y, 0, false); 8574 (f, event->xmotion.x, event->xmotion.y, 0, false);
8455 8575
8456 /* Window will be selected only when it is not selected now and 8576 /* A window will be autoselected only when it is not
8457 last mouse movement event was not in it. Minibuffer window 8577 selected now and the last mouse movement event was
8458 will be selected only when it is active. */ 8578 not in it. The remainder of the code is a bit vague
8579 wrt what a "window" is. For immediate autoselection,
8580 the window is usually the entire window but for GTK
8581 where the scroll bars don't count. For delayed
8582 autoselection the window is usually the window's text
8583 area including the margins. */
8459 if (WINDOWP (window) 8584 if (WINDOWP (window)
8460 && !EQ (window, last_mouse_window) 8585 && !EQ (window, last_mouse_window)
8461 && !EQ (window, selected_window) 8586 && !EQ (window, selected_window))
8462 /* For click-to-focus window managers
8463 create event iff we don't leave the
8464 selected frame. */
8465 && (focus_follows_mouse
8466 || (EQ (XWINDOW (window)->frame,
8467 XWINDOW (selected_window)->frame))))
8468 { 8587 {
8469 inev.ie.kind = SELECT_WINDOW_EVENT; 8588 inev.ie.kind = SELECT_WINDOW_EVENT;
8470 inev.ie.frame_or_window = window; 8589 inev.ie.frame_or_window = window;
8471 } 8590 }
8591
8472 /* Remember the last window where we saw the mouse. */ 8592 /* Remember the last window where we saw the mouse. */
8473 last_mouse_window = window; 8593 last_mouse_window = window;
8474 } 8594 }
8595
8475 if (!note_mouse_movement (f, &event->xmotion)) 8596 if (!note_mouse_movement (f, &event->xmotion))
8476 help_echo_string = previous_help_echo_string; 8597 help_echo_string = previous_help_echo_string;
8477 } 8598 }
@@ -8614,7 +8735,34 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8614 if (FRAME_GTK_OUTER_WIDGET (f) 8735 if (FRAME_GTK_OUTER_WIDGET (f)
8615 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f))) 8736 && gtk_widget_get_mapped (FRAME_GTK_OUTER_WIDGET (f)))
8616#endif 8737#endif
8617 x_real_positions (f, &f->left_pos, &f->top_pos); 8738 {
8739 int old_left = f->left_pos;
8740 int old_top = f->top_pos;
8741 Lisp_Object frame = Qnil;
8742
8743 XSETFRAME (frame, f);
8744
8745 if (!FRAME_PARENT_FRAME (f))
8746 x_real_positions (f, &f->left_pos, &f->top_pos);
8747 else
8748 {
8749 Window root;
8750 unsigned int dummy_uint;
8751
8752 block_input ();
8753 XGetGeometry (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8754 &root, &f->left_pos, &f->top_pos,
8755 &dummy_uint, &dummy_uint, &dummy_uint, &dummy_uint);
8756 unblock_input ();
8757 }
8758
8759 if (old_left != f->left_pos || old_top != f->top_pos)
8760 {
8761 inev.ie.kind = MOVE_FRAME_EVENT;
8762 XSETFRAME (inev.ie.frame_or_window, f);
8763 }
8764 }
8765
8618 8766
8619#ifdef HAVE_X_I18N 8767#ifdef HAVE_X_I18N
8620 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea)) 8768 if (FRAME_XIC (f) && (FRAME_XIC_STYLE (f) & XIMStatusArea))
@@ -8635,8 +8783,35 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8635 dpyinfo->last_mouse_glyph_frame = NULL; 8783 dpyinfo->last_mouse_glyph_frame = NULL;
8636 x_display_set_last_user_time (dpyinfo, event->xbutton.time); 8784 x_display_set_last_user_time (dpyinfo, event->xbutton.time);
8637 8785
8638 f = (x_mouse_grabbed (dpyinfo) ? dpyinfo->last_mouse_frame 8786 if (x_mouse_grabbed (dpyinfo))
8639 : x_window_to_frame (dpyinfo, event->xbutton.window)); 8787 f = dpyinfo->last_mouse_frame;
8788 else
8789 {
8790 f = x_window_to_frame (dpyinfo, event->xbutton.window);
8791
8792 if (f && event->xbutton.type == ButtonPress
8793 && !popup_activated ()
8794 && !x_window_to_scroll_bar (event->xbutton.display,
8795 event->xbutton.window, 2)
8796 && !FRAME_NO_ACCEPT_FOCUS (f))
8797 {
8798 /* When clicking into a child frame or when clicking
8799 into a parent frame with the child frame selected and
8800 `no-accept-focus' is not set, select the clicked
8801 frame. */
8802 struct frame *hf = dpyinfo->x_highlight_frame;
8803
8804 if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
8805 {
8806 block_input ();
8807 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
8808 RevertToParent, CurrentTime);
8809 if (FRAME_PARENT_FRAME (f))
8810 XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
8811 unblock_input ();
8812 }
8813 }
8814 }
8640 8815
8641#ifdef USE_GTK 8816#ifdef USE_GTK
8642 if (f && xg_event_is_for_scrollbar (f, event)) 8817 if (f && xg_event_is_for_scrollbar (f, event))
@@ -8774,7 +8949,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
8774 { 8949 {
8775 case MappingModifier: 8950 case MappingModifier:
8776 x_find_modifier_meanings (dpyinfo); 8951 x_find_modifier_meanings (dpyinfo);
8777 /* This is meant to fall through. */ 8952 FALLTHROUGH;
8778 case MappingKeyboard: 8953 case MappingKeyboard:
8779 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping); 8954 XRefreshKeyboardMapping ((XMappingEvent *) &event->xmapping);
8780 } 8955 }
@@ -9992,6 +10167,7 @@ static void
9992x_calc_absolute_position (struct frame *f) 10167x_calc_absolute_position (struct frame *f)
9993{ 10168{
9994 int flags = f->size_hint_flags; 10169 int flags = f->size_hint_flags;
10170 struct frame *p = FRAME_PARENT_FRAME (f);
9995 10171
9996 /* We have nothing to do if the current position 10172 /* We have nothing to do if the current position
9997 is already for the top-left corner. */ 10173 is already for the top-left corner. */
@@ -10000,32 +10176,72 @@ x_calc_absolute_position (struct frame *f)
10000 10176
10001 /* Treat negative positions as relative to the leftmost bottommost 10177 /* Treat negative positions as relative to the leftmost bottommost
10002 position that fits on the screen. */ 10178 position that fits on the screen. */
10003 if (flags & XNegative) 10179 if ((flags & XNegative) && (f->left_pos <= 0))
10004 f->left_pos = x_display_pixel_width (FRAME_DISPLAY_INFO (f)) 10180 {
10005 - FRAME_PIXEL_WIDTH (f) + f->left_pos; 10181 int width = FRAME_PIXEL_WIDTH (f);
10006 10182
10007 { 10183 /* A frame that has been visible at least once should have outer
10008 int height = FRAME_PIXEL_HEIGHT (f); 10184 edges. */
10185 if (f->output_data.x->has_been_visible && !p)
10186 {
10187 Lisp_Object frame;
10188 Lisp_Object edges = Qnil;
10189
10190 XSETFRAME (frame, f);
10191 edges = Fx_frame_edges (frame, Qouter_edges);
10192 if (!NILP (edges))
10193 width = (XINT (Fnth (make_number (2), edges))
10194 - XINT (Fnth (make_number (0), edges)));
10195 }
10196
10197 if (p)
10198 f->left_pos = (FRAME_PIXEL_WIDTH (p) - width - 2 * f->border_width
10199 + f->left_pos);
10200 else
10201 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
10202 - width + f->left_pos);
10203
10204 }
10205
10206 if ((flags & YNegative) && (f->top_pos <= 0))
10207 {
10208 int height = FRAME_PIXEL_HEIGHT (f);
10009 10209
10010#if defined USE_X_TOOLKIT && defined USE_MOTIF 10210#if defined USE_X_TOOLKIT && defined USE_MOTIF
10011 /* Something is fishy here. When using Motif, starting Emacs with 10211 /* Something is fishy here. When using Motif, starting Emacs with
10012 `-g -0-0', the frame appears too low by a few pixels. 10212 `-g -0-0', the frame appears too low by a few pixels.
10013 10213
10014 This seems to be so because initially, while Emacs is starting, 10214 This seems to be so because initially, while Emacs is starting,
10015 the column widget's height and the frame's pixel height are 10215 the column widget's height and the frame's pixel height are
10016 different. The column widget's height is the right one. In 10216 different. The column widget's height is the right one. In
10017 later invocations, when Emacs is up, the frame's pixel height 10217 later invocations, when Emacs is up, the frame's pixel height
10018 is right, though. 10218 is right, though.
10019 10219
10020 It's not obvious where the initial small difference comes from. 10220 It's not obvious where the initial small difference comes from.
10021 2000-12-01, gerd. */ 10221 2000-12-01, gerd. */
10022 10222
10023 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL); 10223 XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
10024#endif 10224#endif
10025 10225
10026 if (flags & YNegative) 10226 if (f->output_data.x->has_been_visible && !p)
10027 f->top_pos = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) 10227 {
10028 - height + f->top_pos; 10228 Lisp_Object frame;
10229 Lisp_Object edges = Qnil;
10230
10231 XSETFRAME (frame, f);
10232 if (NILP (edges))
10233 edges = Fx_frame_edges (frame, Qouter_edges);
10234 if (!NILP (edges))
10235 height = (XINT (Fnth (make_number (3), edges))
10236 - XINT (Fnth (make_number (1), edges)));
10237 }
10238
10239 if (p)
10240 f->top_pos = (FRAME_PIXEL_HEIGHT (p) - height - 2 * f->border_width
10241 + f->top_pos);
10242 else
10243 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
10244 - height + f->top_pos);
10029 } 10245 }
10030 10246
10031 /* The left_pos and top_pos 10247 /* The left_pos and top_pos
@@ -10088,8 +10304,13 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
10088 modified_top += FRAME_X_OUTPUT (f)->move_offset_top; 10304 modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
10089 } 10305 }
10090 10306
10307#ifdef USE_GTK
10308 gtk_window_move (GTK_WINDOW (FRAME_GTK_OUTER_WIDGET (f)),
10309 modified_left, modified_top);
10310#else
10091 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), 10311 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
10092 modified_left, modified_top); 10312 modified_left, modified_top);
10313#endif
10093 10314
10094 x_sync_with_move (f, f->left_pos, f->top_pos, 10315 x_sync_with_move (f, f->left_pos, f->top_pos,
10095 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN); 10316 FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
@@ -10105,6 +10326,7 @@ x_set_offset (struct frame *f, register int xoff, register int yoff, int change_
10105 need to compute the top/left offset adjustment for this frame. */ 10326 need to compute the top/left offset adjustment for this frame. */
10106 10327
10107 if (change_gravity != 0 10328 if (change_gravity != 0
10329 && !FRAME_PARENT_FRAME (f)
10108 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN 10330 && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
10109 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A 10331 || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
10110 && (FRAME_X_OUTPUT (f)->move_offset_left == 0 10332 && (FRAME_X_OUTPUT (f)->move_offset_left == 0
@@ -10235,6 +10457,92 @@ x_set_sticky (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10235 dpyinfo->Xatom_net_wm_state_sticky, None); 10457 dpyinfo->Xatom_net_wm_state_sticky, None);
10236} 10458}
10237 10459
10460/**
10461 * x_set_skip_taskbar:
10462 *
10463 * Set frame F's `skip-taskbar' parameter. If non-nil, this should
10464 * remove F's icon from the taskbar associated with the display of F's
10465 * window-system window and inhibit switching to F's window via
10466 * <Alt>-<TAB>. If nil, lift these restrictions.
10467 *
10468 * Some window managers may not honor this parameter.
10469 */
10470void
10471x_set_skip_taskbar (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10472{
10473 if (!EQ (new_value, old_value))
10474 {
10475#ifdef USE_GTK
10476 xg_set_skip_taskbar (f, new_value);
10477#else
10478 Lisp_Object frame;
10479 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10480
10481 XSETFRAME (frame, f);
10482 set_wm_state (frame, !NILP (new_value),
10483 dpyinfo->Xatom_net_wm_state_skip_taskbar, None);
10484#endif /* USE_GTK */
10485 FRAME_SKIP_TASKBAR (f) = !NILP (new_value);
10486 }
10487}
10488
10489/**
10490 * x_set_z_group:
10491 *
10492 * Set frame F's `z-group' parameter. If `above', F's window-system
10493 * window is displayed above all windows that do not have the `above'
10494 * property set. If nil, F's window is shown below all windows that
10495 * have the `above' property set and above all windows that have the
10496 * `below' property set. If `below', F's window is displayed below all
10497 * windows that do not have the `below' property set.
10498 *
10499 * Some window managers may not honor this parameter.
10500 */
10501void
10502x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
10503{
10504 /* We don't care about old_value. The window manager might have
10505 reset the value without telling us. */
10506 Lisp_Object frame;
10507 struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
10508
10509 XSETFRAME (frame, f);
10510
10511 if (NILP (new_value))
10512 {
10513 set_wm_state (frame, false,
10514 dpyinfo->Xatom_net_wm_state_above, None);
10515 set_wm_state (frame, false,
10516 dpyinfo->Xatom_net_wm_state_below, None);
10517 FRAME_Z_GROUP (f) = z_group_none;
10518 }
10519 else if (EQ (new_value, Qabove))
10520 {
10521 set_wm_state (frame, true,
10522 dpyinfo->Xatom_net_wm_state_above, None);
10523 set_wm_state (frame, false,
10524 dpyinfo->Xatom_net_wm_state_below, None);
10525 FRAME_Z_GROUP (f) = z_group_above;
10526 }
10527 else if (EQ (new_value, Qbelow))
10528 {
10529 set_wm_state (frame, false,
10530 dpyinfo->Xatom_net_wm_state_above, None);
10531 set_wm_state (frame, true,
10532 dpyinfo->Xatom_net_wm_state_below, None);
10533 FRAME_Z_GROUP (f) = z_group_below;
10534 }
10535 else if (EQ (new_value, Qabove_suspended))
10536 {
10537 set_wm_state (frame, false,
10538 dpyinfo->Xatom_net_wm_state_above, None);
10539 FRAME_Z_GROUP (f) = z_group_above_suspended;
10540 }
10541 else
10542 error ("Invalid z-group specification");
10543}
10544
10545
10238/* Return the current _NET_WM_STATE. 10546/* Return the current _NET_WM_STATE.
10239 SIZE_STATE is set to one of the FULLSCREEN_* values. 10547 SIZE_STATE is set to one of the FULLSCREEN_* values.
10240 Set *STICKY to the sticky state. 10548 Set *STICKY to the sticky state.
@@ -10738,7 +11046,8 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
10738 int old_height = FRAME_PIXEL_HEIGHT (f); 11046 int old_height = FRAME_PIXEL_HEIGHT (f);
10739 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen); 11047 Lisp_Object fullscreen = get_frame_param (f, Qfullscreen);
10740 11048
10741 if (change_gravity) f->win_gravity = NorthWestGravity; 11049 if (change_gravity)
11050 f->win_gravity = NorthWestGravity;
10742 x_wm_set_size_hint (f, 0, false); 11051 x_wm_set_size_hint (f, 0, false);
10743 11052
10744 /* When the frame is fullheight and we only want to change the width 11053 /* When the frame is fullheight and we only want to change the width
@@ -11027,6 +11336,26 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
11027void 11336void
11028x_make_frame_visible (struct frame *f) 11337x_make_frame_visible (struct frame *f)
11029{ 11338{
11339 if (FRAME_PARENT_FRAME (f))
11340 {
11341 if (!FRAME_VISIBLE_P (f))
11342 {
11343 block_input ();
11344#ifdef USE_GTK
11345 gtk_widget_show_all (FRAME_GTK_OUTER_WIDGET (f));
11346 XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
11347 f->left_pos, f->top_pos);
11348#else
11349 XMapRaised (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
11350#endif
11351 unblock_input ();
11352
11353 SET_FRAME_VISIBLE (f, true);
11354 SET_FRAME_ICONIFIED (f, false);
11355 }
11356 return;
11357 }
11358
11030 block_input (); 11359 block_input ();
11031 11360
11032 x_set_bitmap_icon (f); 11361 x_set_bitmap_icon (f);
@@ -11095,9 +11424,10 @@ x_make_frame_visible (struct frame *f)
11095 because the window manager may choose the position 11424 because the window manager may choose the position
11096 and we don't want to override it. */ 11425 and we don't want to override it. */
11097 11426
11098 if (! FRAME_VISIBLE_P (f) 11427 if (!FRAME_VISIBLE_P (f)
11099 && ! FRAME_ICONIFIED_P (f) 11428 && !FRAME_ICONIFIED_P (f)
11100 && ! FRAME_X_EMBEDDED_P (f) 11429 && !FRAME_X_EMBEDDED_P (f)
11430 && !FRAME_PARENT_FRAME (f)
11101 && f->win_gravity == NorthWestGravity 11431 && f->win_gravity == NorthWestGravity
11102 && previously_visible) 11432 && previously_visible)
11103 { 11433 {
@@ -11160,15 +11490,15 @@ x_make_frame_invisible (struct frame *f)
11160 xembed_set_info (f, 0); 11490 xembed_set_info (f, 0);
11161 else 11491 else
11162#endif 11492#endif
11163 {
11164 11493
11165 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window, 11494 if (! XWithdrawWindow (FRAME_X_DISPLAY (f), window,
11166 DefaultScreen (FRAME_X_DISPLAY (f)))) 11495 DefaultScreen (FRAME_X_DISPLAY (f))))
11167 { 11496 {
11168 unblock_input (); 11497 unblock_input ();
11169 error ("Can't notify window manager of window withdrawal"); 11498 error ("Can't notify window manager of window withdrawal");
11170 } 11499 }
11171 } 11500
11501 x_sync (f);
11172 11502
11173 /* We can't distinguish this from iconification 11503 /* We can't distinguish this from iconification
11174 just by the event that we get from the server. 11504 just by the event that we get from the server.
@@ -11178,8 +11508,6 @@ x_make_frame_invisible (struct frame *f)
11178 SET_FRAME_VISIBLE (f, 0); 11508 SET_FRAME_VISIBLE (f, 0);
11179 SET_FRAME_ICONIFIED (f, false); 11509 SET_FRAME_ICONIFIED (f, false);
11180 11510
11181 x_sync (f);
11182
11183 unblock_input (); 11511 unblock_input ();
11184} 11512}
11185 11513
@@ -11429,6 +11757,22 @@ x_free_frame_resources (struct frame *f)
11429 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor); 11757 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->horizontal_drag_cursor);
11430 if (f->output_data.x->vertical_drag_cursor != 0) 11758 if (f->output_data.x->vertical_drag_cursor != 0)
11431 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor); 11759 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->vertical_drag_cursor);
11760 if (f->output_data.x->left_edge_cursor != 0)
11761 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->left_edge_cursor);
11762 if (f->output_data.x->top_left_corner_cursor != 0)
11763 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_left_corner_cursor);
11764 if (f->output_data.x->top_edge_cursor != 0)
11765 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_edge_cursor);
11766 if (f->output_data.x->top_right_corner_cursor != 0)
11767 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->top_right_corner_cursor);
11768 if (f->output_data.x->right_edge_cursor != 0)
11769 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->right_edge_cursor);
11770 if (f->output_data.x->bottom_right_corner_cursor != 0)
11771 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_right_corner_cursor);
11772 if (f->output_data.x->bottom_edge_cursor != 0)
11773 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_edge_cursor);
11774 if (f->output_data.x->bottom_left_corner_cursor != 0)
11775 XFreeCursor (FRAME_X_DISPLAY (f), f->output_data.x->bottom_left_corner_cursor);
11432 11776
11433 XFlush (FRAME_X_DISPLAY (f)); 11777 XFlush (FRAME_X_DISPLAY (f));
11434 } 11778 }
@@ -12335,6 +12679,9 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
12335 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID) 12679 ATOM_REFS_INIT ("SM_CLIENT_ID", Xatom_SM_CLIENT_ID)
12336 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop) 12680 ATOM_REFS_INIT ("_XSETTINGS_SETTINGS", Xatom_xsettings_prop)
12337 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr) 12681 ATOM_REFS_INIT ("MANAGER", Xatom_xsettings_mgr)
12682 ATOM_REFS_INIT ("_NET_WM_STATE_SKIP_TASKBAR", Xatom_net_wm_state_skip_taskbar)
12683 ATOM_REFS_INIT ("_NET_WM_STATE_ABOVE", Xatom_net_wm_state_above)
12684 ATOM_REFS_INIT ("_NET_WM_STATE_BELOW", Xatom_net_wm_state_below)
12338 }; 12685 };
12339 12686
12340 int i; 12687 int i;
@@ -12923,8 +13270,8 @@ transition between the various maximization states. */);
12923 13270
12924 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move, 13271 DEFVAR_BOOL ("x-gtk-use-window-move", x_gtk_use_window_move,
12925 doc: /* Non-nil means rely on gtk_window_move to set frame positions. 13272 doc: /* Non-nil means rely on gtk_window_move to set frame positions.
12926If this variable is t, the GTK build uses the function gtk_window_move 13273If this variable is t (the default), the GTK build uses the function
12927to set or store frame positions and disables some time consuming frame 13274gtk_window_move to set or store frame positions and disables some time
12928position adjustments. */); 13275consuming frame position adjustments. */);
12929 x_gtk_use_window_move = false; 13276 x_gtk_use_window_move = true;
12930} 13277}
diff --git a/src/xterm.h b/src/xterm.h
index 32c879bcdca..803feda99f3 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -447,9 +447,9 @@ struct x_display_info
447 /* Atoms dealing with EWMH (i.e. _NET_...) */ 447 /* Atoms dealing with EWMH (i.e. _NET_...) */
448 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen, 448 Atom Xatom_net_wm_state, Xatom_net_wm_state_fullscreen,
449 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert, 449 Xatom_net_wm_state_maximized_horz, Xatom_net_wm_state_maximized_vert,
450 Xatom_net_wm_state_sticky, Xatom_net_wm_state_hidden, 450 Xatom_net_wm_state_sticky, Xatom_net_wm_state_above, Xatom_net_wm_state_below,
451 Xatom_net_frame_extents, 451 Xatom_net_wm_state_hidden, Xatom_net_wm_state_skip_taskbar,
452 Xatom_net_current_desktop, Xatom_net_workarea; 452 Xatom_net_frame_extents, Xatom_net_current_desktop, Xatom_net_workarea;
453 453
454 /* XSettings atoms and windows. */ 454 /* XSettings atoms and windows. */
455 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr; 455 Atom Xatom_xsettings_sel, Xatom_xsettings_prop, Xatom_xsettings_mgr;
@@ -637,6 +637,14 @@ struct x_output
637 Cursor horizontal_drag_cursor; 637 Cursor horizontal_drag_cursor;
638 Cursor vertical_drag_cursor; 638 Cursor vertical_drag_cursor;
639 Cursor current_cursor; 639 Cursor current_cursor;
640 Cursor left_edge_cursor;
641 Cursor top_left_corner_cursor;
642 Cursor top_edge_cursor;
643 Cursor top_right_corner_cursor;
644 Cursor right_edge_cursor;
645 Cursor bottom_right_corner_cursor;
646 Cursor bottom_edge_cursor;
647 Cursor bottom_left_corner_cursor;
640 648
641 /* Window whose cursor is hourglass_cursor. This window is temporarily 649 /* Window whose cursor is hourglass_cursor. This window is temporarily
642 mapped to display an hourglass cursor. */ 650 mapped to display an hourglass cursor. */
@@ -1168,6 +1176,8 @@ x_mutable_colormap (Visual *visual)
1168} 1176}
1169 1177
1170extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); 1178extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object);
1179extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object);
1180extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object);
1171extern bool x_wm_supports (struct frame *, Atom); 1181extern bool x_wm_supports (struct frame *, Atom);
1172extern void x_wait_for_event (struct frame *, int); 1182extern void x_wait_for_event (struct frame *, int);
1173extern void x_clear_under_internal_border (struct frame *f); 1183extern void x_clear_under_internal_border (struct frame *f);