diff options
| author | Michael R. Mauger | 2017-07-03 15:32:41 -0400 |
|---|---|---|
| committer | Michael R. Mauger | 2017-07-03 15:32:41 -0400 |
| commit | 776635c01abd4aa759e7aa9584b513146978568c (patch) | |
| tree | 554f444bc96cb6b05435e8bf195de4df1b00df8f /src | |
| parent | 77083e2d34ba5559ae2899d3b03cf08c2e6c5ad4 (diff) | |
| parent | 4cd0db3d6e6e4d5bd49283483bdafbbfc0f583f1 (diff) | |
| download | emacs-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/.gdbinit | 96 | ||||
| -rw-r--r-- | src/ChangeLog.13 | 2 | ||||
| -rw-r--r-- | src/Makefile.in | 38 | ||||
| -rw-r--r-- | src/alloc.c | 79 | ||||
| -rw-r--r-- | src/bidi.c | 16 | ||||
| -rw-r--r-- | src/buffer.c | 7 | ||||
| -rw-r--r-- | src/buffer.h | 9 | ||||
| -rw-r--r-- | src/callint.c | 1 | ||||
| -rw-r--r-- | src/callproc.c | 38 | ||||
| -rw-r--r-- | src/casefiddle.c | 600 | ||||
| -rw-r--r-- | src/ccl.c | 4 | ||||
| -rw-r--r-- | src/charset.c | 12 | ||||
| -rw-r--r-- | src/chartab.c | 2 | ||||
| -rw-r--r-- | src/cm.c | 14 | ||||
| -rw-r--r-- | src/coding.c | 6 | ||||
| -rw-r--r-- | src/coding.h | 34 | ||||
| -rw-r--r-- | src/composite.c | 2 | ||||
| -rw-r--r-- | src/conf_post.h | 38 | ||||
| -rw-r--r-- | src/data.c | 89 | ||||
| -rw-r--r-- | src/dispextern.h | 37 | ||||
| -rw-r--r-- | src/dispnew.c | 32 | ||||
| -rw-r--r-- | src/doc.c | 6 | ||||
| -rw-r--r-- | src/doprnt.c | 5 | ||||
| -rw-r--r-- | src/dynlib.c | 36 | ||||
| -rw-r--r-- | src/dynlib.h | 16 | ||||
| -rw-r--r-- | src/editfns.c | 460 | ||||
| -rw-r--r-- | src/emacs-module.c | 671 | ||||
| -rw-r--r-- | src/emacs-module.h | 197 | ||||
| -rw-r--r-- | src/emacs-module.h.in | 107 | ||||
| -rw-r--r-- | src/emacs.c | 66 | ||||
| -rw-r--r-- | src/eval.c | 163 | ||||
| -rw-r--r-- | src/fileio.c | 70 | ||||
| -rw-r--r-- | src/filelock.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 36 | ||||
| -rw-r--r-- | src/font.c | 50 | ||||
| -rw-r--r-- | src/font.h | 6 | ||||
| -rw-r--r-- | src/frame.c | 1230 | ||||
| -rw-r--r-- | src/frame.h | 128 | ||||
| -rw-r--r-- | src/ftfont.c | 3 | ||||
| -rw-r--r-- | src/gmalloc.c | 83 | ||||
| -rw-r--r-- | src/gnutls.c | 1 | ||||
| -rw-r--r-- | src/gtkutil.c | 177 | ||||
| -rw-r--r-- | src/gtkutil.h | 8 | ||||
| -rw-r--r-- | src/image.c | 26 | ||||
| -rw-r--r-- | src/indent.c | 1 | ||||
| -rw-r--r-- | src/inotify.c | 32 | ||||
| -rw-r--r-- | src/intervals.h | 12 | ||||
| -rw-r--r-- | src/keyboard.c | 91 | ||||
| -rw-r--r-- | src/kqueue.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 94 | ||||
| -rw-r--r-- | src/lread.c | 386 | ||||
| -rw-r--r-- | src/macfont.m | 41 | ||||
| -rw-r--r-- | src/minibuf.c | 34 | ||||
| -rw-r--r-- | src/module-env-25.h | 140 | ||||
| -rw-r--r-- | src/module-env-26.h | 3 | ||||
| -rw-r--r-- | src/nsfns.m | 262 | ||||
| -rw-r--r-- | src/nsimage.m | 12 | ||||
| -rw-r--r-- | src/nsmenu.m | 25 | ||||
| -rw-r--r-- | src/nsterm.h | 116 | ||||
| -rw-r--r-- | src/nsterm.m | 495 | ||||
| -rw-r--r-- | src/print.c | 809 | ||||
| -rw-r--r-- | src/process.c | 144 | ||||
| -rw-r--r-- | src/regex.c | 10 | ||||
| -rw-r--r-- | src/search.c | 65 | ||||
| -rw-r--r-- | src/syntax.c | 8 | ||||
| -rw-r--r-- | src/sysdep.c | 45 | ||||
| -rw-r--r-- | src/sysstdio.h | 41 | ||||
| -rw-r--r-- | src/systhread.c | 11 | ||||
| -rw-r--r-- | src/syswait.h | 2 | ||||
| -rw-r--r-- | src/term.c | 47 | ||||
| -rw-r--r-- | src/termhooks.h | 3 | ||||
| -rw-r--r-- | src/terminal.c | 5 | ||||
| -rw-r--r-- | src/thread.c | 2 | ||||
| -rw-r--r-- | src/unexelf.c | 12 | ||||
| -rw-r--r-- | src/unexmacosx.c | 25 | ||||
| -rw-r--r-- | src/w32.c | 25 | ||||
| -rw-r--r-- | src/w32fns.c | 814 | ||||
| -rw-r--r-- | src/w32font.c | 21 | ||||
| -rw-r--r-- | src/w32menu.c | 2 | ||||
| -rw-r--r-- | src/w32term.c | 326 | ||||
| -rw-r--r-- | src/w32term.h | 11 | ||||
| -rw-r--r-- | src/widget.c | 13 | ||||
| -rw-r--r-- | src/widget.h | 2 | ||||
| -rw-r--r-- | src/window.c | 256 | ||||
| -rw-r--r-- | src/window.h | 200 | ||||
| -rw-r--r-- | src/xdisp.c | 477 | ||||
| -rw-r--r-- | src/xfaces.c | 12 | ||||
| -rw-r--r-- | src/xfns.c | 718 | ||||
| -rw-r--r-- | src/xmenu.c | 60 | ||||
| -rw-r--r-- | src/xterm.c | 547 | ||||
| -rw-r--r-- | src/xterm.h | 16 |
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 |
| 1266 | end | 1266 | end |
| 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 | |||
| 1273 | python | ||
| 1274 | |||
| 1275 | # Omit pretty-printing in older (pre-7.3) GDBs that lack it. | ||
| 1276 | if 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) | ||
| 1357 | end | ||
| 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 | ||
| 17507 | 2013-03-27 rzl24ozi <rzl24ozi@gmail.com> (tiny changes) | 17507 | 2013-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 | |||
| 48 | lib = ../lib | 48 | lib = ../lib |
| 49 | libsrc = ../lib-src | 49 | libsrc = ../lib-src |
| 50 | etc = ../etc | 50 | etc = ../etc |
| 51 | leimdir = ${lispsource}/leim | ||
| 52 | oldXMenudir = ../oldXMenu | 51 | oldXMenudir = ../oldXMenu |
| 53 | lwlibdir = ../lwlib | 52 | lwlibdir = ../lwlib |
| 54 | 53 | ||
| @@ -347,16 +346,6 @@ am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) | |||
| 347 | am__v_at_0 = @ | 346 | am__v_at_0 = @ |
| 348 | am__v_at_1 = | 347 | am__v_at_1 = |
| 349 | 348 | ||
| 350 | AUTO_DEPEND = @AUTO_DEPEND@ | ||
| 351 | DEPDIR = deps | ||
| 352 | ifeq ($(AUTO_DEPEND),yes) | ||
| 353 | DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP | ||
| 354 | -include $(ALLOBJS:%.o=$(DEPDIR)/%.d) | ||
| 355 | else | ||
| 356 | DEPFLAGS = | ||
| 357 | include $(srcdir)/deps.mk | ||
| 358 | endif | ||
| 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. |
| 361 | NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd | 350 | NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd |
| 362 | 351 | ||
| @@ -445,6 +434,16 @@ otherobj= $(TERMCAP_OBJ) $(PRE_ALLOC_OBJ) $(GMALLOC_OBJ) $(RALLOC_OBJ) \ | |||
| 445 | FIRSTFILE_OBJ=@FIRSTFILE_OBJ@ | 434 | FIRSTFILE_OBJ=@FIRSTFILE_OBJ@ |
| 446 | ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj) | 435 | ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj) |
| 447 | 436 | ||
| 437 | AUTO_DEPEND = @AUTO_DEPEND@ | ||
| 438 | DEPDIR = deps | ||
| 439 | ifeq ($(AUTO_DEPEND),yes) | ||
| 440 | DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP | ||
| 441 | -include $(ALLOBJS:%.o=$(DEPDIR)/%.d) | ||
| 442 | else | ||
| 443 | DEPFLAGS = | ||
| 444 | include $(srcdir)/deps.mk | ||
| 445 | endif | ||
| 446 | |||
| 448 | all: emacs$(EXEEXT) $(OTHER_FILES) | 447 | all: 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 | ||
| 518 | lispintdir = ${lispsource}/international | 510 | lispintdir = ${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. |
| 537 | emacs$(EXEEXT): temacs$(EXEEXT) \ | 529 | emacs$(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} |
| 540 | ifeq ($(CANNOT_DUMP),yes) | 532 | ifeq ($(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 |
| 649 | clean: mostlyclean | 641 | clean: 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. |
| 655 | bootstrap-clean: clean | 647 | bootstrap-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/>. */ | |||
| 75 | static bool valgrind_p; | 75 | static 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 | |||
| 3405 | static struct Lisp_Vector * | ||
| 3406 | allocate_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 | |||
| 3418 | DEFUN ("make-record", Fmake_record, Smake_record, 3, 3, 0, | ||
| 3419 | doc: /* Create a new record. | ||
| 3420 | TYPE is its type as returned by `type-of'; it should be either a | ||
| 3421 | symbol or a type descriptor. SLOTS is the number of non-type slots, | ||
| 3422 | each 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 | |||
| 3435 | DEFUN ("record", Frecord, Srecord, 1, MANY, 0, | ||
| 3436 | doc: /* Create a new record. | ||
| 3437 | TYPE is its type as returned by `type-of'; it should be either a | ||
| 3438 | symbol or a type descriptor. SLOTS is used to initialize the record | ||
| 3439 | slots with shallow copies of the arguments. | ||
| 3440 | usage: (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 | |||
| 3395 | DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, | 3449 | DEFUN ("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. |
| 3397 | See also the function `vector'. */) | 3451 | See 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 | ||
| 3894 | static void | 3947 | static 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 | 568 | verify (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 | ||
| 571 | static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; | 569 | static ptrdiff_t bidi_cache_max_elts = BIDI_CACHE_MAX_ELTS_PER_SLOT; |
| 572 | static struct bidi_it *bidi_cache; | 570 | static struct bidi_it *bidi_cache; |
| 573 | static ptrdiff_t bidi_cache_size = 0; | 571 | static 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)) | 2472 | enum { 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. |
| 5632 | To interactively change the default directory, use command `cd'. */); | 5635 | It should be a directory name (as opposed to a directory file-name). |
| 5636 | On GNU and Unix systems, directory names end in a slash `/'. | ||
| 5637 | To 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 | |||
| 240 | and returns a numeric exit status or a signal description string. | 243 | and returns a numeric exit status or a signal description string. |
| 241 | If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. | 244 | If you quit, the process is killed with SIGINT, or SIGKILL if you quit again. |
| 242 | 245 | ||
| 246 | The process runs in `default-directory' if that is local (as | ||
| 247 | determined by `unhandled-file-name-directory'), or "~" otherwise. If | ||
| 248 | you want to run a process in a remote directory use `process-file'. | ||
| 249 | |||
| 243 | usage: (call-process PROGRAM &optional INFILE DESTINATION DISPLAY &rest ARGS) */) | 250 | usage: (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 | ||
| 3 | Copyright (C) 1985, 1994, 1997-1999, 2001-2017 Free Software Foundation, | 4 | Copyright (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 | ||
| 32 | enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; | 33 | enum case_action {CASE_UP, CASE_DOWN, CASE_CAPITALIZE, CASE_CAPITALIZE_UP}; |
| 33 | 34 | ||
| 34 | static Lisp_Object | 35 | /* State for casing individual characters. */ |
| 35 | casify_object (enum case_action flag, Lisp_Object obj) | 36 | struct 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. */ | ||
| 60 | static void | ||
| 61 | prepare_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 | |||
| 88 | struct 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. */ | ||
| 101 | static int | ||
| 102 | case_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 | |||
| 179 | enum { GREEK_CAPITAL_LETTER_SIGMA = 0x03A3 }; /* Σ */ | ||
| 180 | enum { 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. */ | ||
| 188 | static inline int | ||
| 189 | case_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. */ | ||
| 203 | static bool | ||
| 204 | case_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 | |||
| 223 | static Lisp_Object | ||
| 224 | do_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 | |||
| 256 | static Lisp_Object | ||
| 257 | do_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 | |||
| 293 | static Lisp_Object | ||
| 294 | do_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 | |||
| 316 | static Lisp_Object | ||
| 317 | casify_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 | ||
| 139 | DEFUN ("upcase", Fupcase, Supcase, 1, 1, 0, | 334 | DEFUN ("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. |
| 141 | The argument may be a character or string. The result has the same type. | 336 | The argument may be a character or string. The result has the same type. |
| 142 | The argument object is not altered--the value is a copy. | 337 | The argument object is not altered--the value is a copy. If argument |
| 338 | is a character, characters which map to multiple code points when | ||
| 339 | cased, e.g. fi, are returned unchanged. | ||
| 143 | See also `capitalize', `downcase' and `upcase-initials'. */) | 340 | See 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 | ||
| 158 | DEFUN ("capitalize", Fcapitalize, Scapitalize, 1, 1, 0, | 355 | DEFUN ("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. |
| 160 | This means that each word's first character is upper case | 357 | This means that each word's first character is converted to either |
| 161 | and the rest is lower case. | 358 | title case or upper case, and the rest to lower case. |
| 162 | The argument may be a character or string. The result has the same type. | 359 | The argument may be a character or string. The result has the same type. |
| 163 | The argument object is not altered--the value is a copy. */) | 360 | The argument object is not altered--the value is a copy. If argument |
| 361 | is a character, characters which map to multiple code points when | ||
| 362 | cased, 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 | ||
| 171 | DEFUN ("upcase-initials", Fupcase_initials, Supcase_initials, 1, 1, 0, | 370 | DEFUN ("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. |
| 173 | Do not change the other letters of each word. | 372 | This means that each word's first character is converted to either |
| 373 | title case or upper case, and the rest are left unchanged. | ||
| 174 | The argument may be a character or string. The result has the same type. | 374 | The argument may be a character or string. The result has the same type. |
| 175 | The argument object is not altered--the value is a copy. */) | 375 | The argument object is not altered--the value is a copy. If argument |
| 376 | is a character, characters which map to multiple code points when | ||
| 377 | cased, 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 | ||
| 184 | static void | 385 | Save first and last positions that has changed in *STARTP and *ENDP |
| 185 | casify_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. */ | ||
| 391 | static ptrdiff_t | ||
| 392 | do_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. */ | ||
| 426 | static ptrdiff_t | ||
| 427 | do_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. */ | ||
| 481 | static ptrdiff_t | ||
| 482 | casify_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 | ||
| 291 | DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3, | 519 | DEFUN ("upcase-region", Fupcase_region, Supcase_region, 2, 3, |
| @@ -345,8 +573,8 @@ point and the mark is operated on. */) | |||
| 345 | 573 | ||
| 346 | DEFUN ("capitalize-region", Fcapitalize_region, Scapitalize_region, 2, 2, "r", | 574 | DEFUN ("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. |
| 348 | Capitalized form means each word's first character is upper case | 576 | This means that each word's first character is converted to either |
| 349 | and the rest of it is lower case. | 577 | title case or upper case, and the rest to lower case. |
| 350 | In programs, give two arguments, the starting and ending | 578 | In programs, give two arguments, the starting and ending |
| 351 | character positions to operate on. */) | 579 | character 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. */) | |||
| 360 | DEFUN ("upcase-initials-region", Fupcase_initials_region, | 588 | DEFUN ("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. |
| 363 | Subsequent letters of each word are not changed. | 591 | This means that each word's first character is converted to either |
| 592 | title case or upper case, and the rest are left unchanged. | ||
| 364 | In programs, give two arguments, the starting and ending | 593 | In programs, give two arguments, the starting and ending |
| 365 | character positions to operate on. */) | 594 | character 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 | |||
| 426 | syms_of_casefiddle (void) | 653 | syms_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); |
| @@ -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 | |||
| 185 | copy_char_table (Lisp_Object table) | 185 | copy_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); |
| @@ -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 | |||
| 45 | cmputc (int c) | 45 | cmputc (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 | ||
| 1452 | static bool | 1452 | bool |
| 1453 | encode_coding_utf_8 (struct coding_system *coding) | 1453 | encode_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 | |||
| 96 | extern Lisp_Object Vcoding_system_hash_table; | 96 | extern Lisp_Object Vcoding_system_hash_table; |
| 97 | 97 | ||
| 98 | 98 | ||
| 99 | /* Enumeration of coding system type. */ | ||
| 100 | |||
| 101 | enum 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 | |||
| 118 | enum 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 | ||
| 134 | enum coding_attr_index | 101 | enum coding_attr_index |
| @@ -697,6 +664,7 @@ struct coding_system | |||
| 697 | 664 | ||
| 698 | /* Extern declarations. */ | 665 | /* Extern declarations. */ |
| 699 | extern Lisp_Object code_conversion_save (bool, bool); | 666 | extern Lisp_Object code_conversion_save (bool, bool); |
| 667 | extern bool encode_coding_utf_8 (struct coding_system *); | ||
| 700 | extern void setup_coding_system (Lisp_Object, struct coding_system *); | 668 | extern void setup_coding_system (Lisp_Object, struct coding_system *); |
| 701 | extern Lisp_Object coding_charset_list (struct coding_system *); | 669 | extern Lisp_Object coding_charset_list (struct coding_system *); |
| 702 | extern Lisp_Object coding_system_charset_list (Lisp_Object); | 670 | extern 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 | ||
| 371 | DEFUN ("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 | |||
| 362 | DEFUN ("stringp", Fstringp, Sstringp, 1, 1, 0, | 380 | DEFUN ("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 | ||
| 495 | DEFUN ("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 | |||
| 477 | DEFUN ("char-or-string-p", Fchar_or_string_p, Schar_or_string_p, 1, 1, 0, | 503 | DEFUN ("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. */ | ||
| 681 | DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, | 705 | DEFUN ("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 | ||
| 2250 | DEFUN ("aref", Faref, Saref, 2, 2, 0, | 2274 | DEFUN ("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. |
| 2252 | ARRAY may be a vector, a string, a char-table, a bool-vector, | 2276 | ARG may be a vector, a string, a char-table, a bool-vector, a record, |
| 2253 | or a byte-code object. IDX starts at 0. */) | 2277 | or 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 | ||
| 3041 | static Lisp_Object | 3072 | static Lisp_Object |
| 3042 | ash_lsh_impl (register Lisp_Object value, Lisp_Object count, bool lsh) | 3073 | ash_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 | |||
| 5650 | bitch_at_user (void) | 5650 | bitch_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 |
| @@ -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 | ||
| 123 | bool | 125 | void |
| 124 | dynlib_addr (void *addr, const char **fname, const char **symname) | 126 | dynlib_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 | ||
| 228 | const char * | 224 | const 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 | ||
| 286 | bool | 282 | void |
| 287 | dynlib_addr (void *ptr, const char **path, const char **sym) | 283 | dynlib_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 | ||
| 301 | const char * | 297 | const 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 | ||
| 25 | typedef void *dynlib_handle_ptr; | 25 | typedef void *dynlib_handle_ptr; |
| 26 | dynlib_handle_ptr dynlib_open (const char *path); | 26 | dynlib_handle_ptr dynlib_open (const char *path); |
| 27 | void *dynlib_sym (dynlib_handle_ptr h, const char *sym); | ||
| 28 | typedef struct dynlib_function_ptr_nonce *(*dynlib_function_ptr) (void); | ||
| 29 | dynlib_function_ptr dynlib_func (dynlib_handle_ptr h, const char *sym); | ||
| 30 | bool dynlib_addr (void *ptr, const char **path, const char **sym); | ||
| 31 | const char *dynlib_error (void); | ||
| 32 | int dynlib_close (dynlib_handle_ptr h); | 27 | int dynlib_close (dynlib_handle_ptr h); |
| 28 | const char *dynlib_error (void); | ||
| 29 | |||
| 30 | ATTRIBUTE_MAY_ALIAS void *dynlib_sym (dynlib_handle_ptr h, const char *sym); | ||
| 31 | |||
| 32 | typedef struct dynlib_function_ptr_nonce *(ATTRIBUTE_MAY_ALIAS *dynlib_function_ptr) (void); | ||
| 33 | dynlib_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. */ | ||
| 38 | void 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 | ||
| 82 | enum { tzeqlen = sizeof "TZ=" - 1 }; | 83 | enum { 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. */ | ||
| 86 | static timezone_t local_tz; | 86 | static timezone_t local_tz; |
| 87 | static timezone_t wall_clock_tz; | ||
| 88 | static timezone_t const utc_tz = 0; | 87 | static 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) | |||
| 226 | void | 225 | void |
| 227 | init_editfns (bool dumping) | 226 | init_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. | |||
| 2144 | The optional ZONE is omitted or nil for Emacs local time, t for | 2140 | The optional ZONE is omitted or nil for Emacs local time, t for |
| 2145 | Universal Time, `wall' for system wall clock time, or a string as in | 2141 | Universal Time, `wall' for system wall clock time, or a string as in |
| 2146 | the TZ environment variable. It can also be a list (as from | 2142 | the 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 |
| 2148 | without consideration for daylight saving time. | 2144 | without consideration for daylight saving time. |
| 2149 | 2145 | ||
| 2150 | The list has the following nine members: SEC is an integer between 0 | 2146 | The 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 | |||
| 3133 | struct context; | ||
| 3134 | static void set_bit (unsigned char *, OFFSET); | ||
| 3135 | static bool bit_is_set (const unsigned char *, OFFSET); | ||
| 3136 | static bool buffer_chars_equal (struct context *, OFFSET, OFFSET); | ||
| 3137 | |||
| 3138 | #include "minmax.h" | ||
| 3139 | #include "diffseq.h" | ||
| 3140 | |||
| 3141 | DEFUN ("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. | ||
| 3144 | SOURCE can be a buffer or a string that names a buffer. | ||
| 3145 | Interactively, prompt for SOURCE. | ||
| 3146 | As far as possible the replacement is non-destructive, i.e. existing | ||
| 3147 | buffer contents, markers, properties, and overlays in the current | ||
| 3148 | buffer 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 | |||
| 3266 | static void | ||
| 3267 | set_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 | |||
| 3276 | static bool | ||
| 3277 | bit_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 | |||
| 3291 | static bool | ||
| 3292 | buffer_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 | ||
| 3113 | static void | 3310 | static void |
| 3114 | subst_char_in_region_unwind (Lisp_Object arg) | 3311 | subst_char_in_region_unwind (Lisp_Object arg) |
| @@ -3739,11 +3936,10 @@ In batch mode, the message is printed to the standard error stream, | |||
| 3739 | followed by a newline. | 3936 | followed by a newline. |
| 3740 | 3937 | ||
| 3741 | The first argument is a format control string, and the rest are data | 3938 | The first argument is a format control string, and the rest are data |
| 3742 | to be formatted under control of the string. See `format-message' for | 3939 | to be formatted under control of the string. Percent sign (%), grave |
| 3743 | details. | 3940 | accent (\\=`) and apostrophe (\\=') are special in the format; see |
| 3744 | 3941 | `format-message' for details. To display STRING without special | |
| 3745 | Note: (message "%s" VALUE) displays the string VALUE without | 3942 | treatment, use (message "%s" STRING). |
| 3746 | interpreting format characters like `%', `\\=`', and `\\=''. | ||
| 3747 | 3943 | ||
| 3748 | If the first argument is nil or the empty string, the function clears | 3944 | If the first argument is nil or the empty string, the function clears |
| 3749 | any existing message; this lets the minibuffer contents show. See | 3945 | any 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 | |||
| 4061 | static ptrdiff_t | ||
| 4062 | str2num (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 | |||
| 3859 | DEFUN ("format", Fformat, Sformat, 1, MANY, 0, | 4072 | DEFUN ("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. |
| 3861 | The first argument is a format control string. | 4074 | The first argument is a format control string. |
| 3862 | The other arguments are substituted into it to make the result, a string. | 4075 | The other arguments are substituted into it to make the result, a string. |
| 3863 | 4076 | ||
| 3864 | The format control string may contain %-sequences meaning to substitute | 4077 | The format control string may contain %-sequences meaning to substitute |
| 3865 | the next available argument: | 4078 | the 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: | |||
| 3879 | The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. | 4092 | The argument used for %d, %o, %x, %e, %f, %g or %c must be a number. |
| 3880 | Use %% to put a single % into the output. | 4093 | Use %% to put a single % into the output. |
| 3881 | 4094 | ||
| 3882 | A %-sequence may contain optional flag, width, and precision | 4095 | A %-sequence other than %% may contain optional field number, flag, |
| 3883 | specifiers, as follows: | 4096 | width, and precision specifiers, as follows: |
| 4097 | |||
| 4098 | %<field><flags><width><precision>character | ||
| 3884 | 4099 | ||
| 3885 | %<flags><width><precision>character | 4100 | where field is [0-9]+ followed by a literal dollar "$", flags is |
| 4101 | [+ #-0]+, width is [0-9]+, and precision is a literal period "." | ||
| 4102 | followed by [0-9]+. | ||
| 3886 | 4103 | ||
| 3887 | where flags is [+ #-0]+, width is [0-9]+, and precision is a literal | 4104 | If a %-sequence is numbered with a field with positive value N, the |
| 3888 | period "." followed by [0-9]+ | 4105 | Nth argument is substituted instead of the next one. A format can |
| 4106 | contain either numbered or unnumbered %-sequences but not both, except | ||
| 4107 | that %% can be mixed with numbered %-sequences. | ||
| 3889 | 4108 | ||
| 3890 | The + flag character inserts a + before any positive number, while a | 4109 | The + flag character inserts a + before any positive number, while a |
| 3891 | space inserts a space before any positive number; these flags only | 4110 | space 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) | ||
| 40 | enum { module_has_cleanup = true }; | ||
| 41 | #else | ||
| 42 | enum { 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. */ |
| 63 | typedef int (*emacs_init_function) (struct emacs_runtime *); | 71 | typedef int (*emacs_init_function) (struct emacs_runtime *); |
| 64 | 72 | ||
| 65 | /* Function prototype for the module Lisp functions. */ | ||
| 66 | typedef 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. */ |
| 93 | struct emacs_runtime_private | 102 | struct 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 | ||
| 103 | struct module_fun_env; | ||
| 104 | |||
| 105 | static Lisp_Object module_format_fun_env (const struct module_fun_env *); | ||
| 106 | static Lisp_Object value_to_lisp (emacs_value); | 110 | static Lisp_Object value_to_lisp (emacs_value); |
| 107 | static emacs_value lisp_to_value (Lisp_Object); | 111 | static emacs_value lisp_to_value (emacs_env *, Lisp_Object); |
| 108 | static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *); | 112 | static enum emacs_funcall_exit module_non_local_exit_check (emacs_env *); |
| 109 | static void check_main_thread (void); | 113 | static void module_assert_thread (void); |
| 110 | static void finalize_environment (struct emacs_env_private *); | 114 | static void module_assert_runtime (struct emacs_runtime *); |
| 111 | static void initialize_environment (emacs_env *, struct emacs_env_private *priv); | 115 | static void module_assert_env (emacs_env *); |
| 116 | static _Noreturn void module_abort (const char *format, ...) | ||
| 117 | ATTRIBUTE_FORMAT_PRINTF(1, 2); | ||
| 118 | static emacs_env *initialize_environment (emacs_env *, | ||
| 119 | struct emacs_env_private *); | ||
| 120 | static void finalize_environment (emacs_env *); | ||
| 121 | static void finalize_environment_unwind (void *); | ||
| 122 | static void finalize_runtime_unwind (void *); | ||
| 112 | static void module_handle_signal (emacs_env *, Lisp_Object); | 123 | static void module_handle_signal (emacs_env *, Lisp_Object); |
| 113 | static void module_handle_throw (emacs_env *, Lisp_Object); | 124 | static void module_handle_throw (emacs_env *, Lisp_Object); |
| 114 | static void module_non_local_exit_signal_1 (emacs_env *, Lisp_Object, Lisp_Object); | 125 | static void module_non_local_exit_signal_1 (emacs_env *, |
| 115 | static void module_non_local_exit_throw_1 (emacs_env *, Lisp_Object, Lisp_Object); | 126 | Lisp_Object, Lisp_Object); |
| 127 | static void module_non_local_exit_throw_1 (emacs_env *, | ||
| 128 | Lisp_Object, Lisp_Object); | ||
| 116 | static void module_out_of_memory (emacs_env *); | 129 | static void module_out_of_memory (emacs_env *); |
| 117 | static void module_reset_handlerlist (const int *); | 130 | static 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. */ |
| 123 | verify (NIL_IS_ZERO); | 136 | verify (NIL_IS_ZERO); |
| 124 | static emacs_value const module_nil = 0; | 137 | static emacs_value const module_nil = 0; |
| 138 | |||
| 139 | static bool module_assertions = false; | ||
| 140 | static emacs_env *global_env; | ||
| 141 | static 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 | |||
| 195 | struct 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 | ||
| 246 | static void | 262 | static void |
| @@ -256,8 +272,9 @@ CHECK_USER_PTR (Lisp_Object obj) | |||
| 256 | static emacs_env * | 272 | static emacs_env * |
| 257 | module_get_environment (struct emacs_runtime *ert) | 273 | module_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 | ||
| 292 | static void | 309 | static 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 | ||
| 318 | static enum emacs_funcall_exit | 359 | static enum emacs_funcall_exit |
| 319 | module_non_local_exit_check (emacs_env *env) | 360 | module_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 | ||
| 325 | static void | 367 | static void |
| 326 | module_non_local_exit_clear (emacs_env *env) | 368 | module_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 | ||
| 332 | static enum emacs_funcall_exit | 375 | static enum emacs_funcall_exit |
| 333 | module_non_local_exit_get (emacs_env *env, emacs_value *sym, emacs_value *data) | 376 | module_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) | |||
| 347 | static void | 391 | static void |
| 348 | module_non_local_exit_signal (emacs_env *env, emacs_value sym, emacs_value data) | 392 | module_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) | |||
| 356 | static void | 401 | static void |
| 357 | module_non_local_exit_throw (emacs_env *env, emacs_value tag, emacs_value value) | 402 | module_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 | 411 | static struct Lisp_Module_Function * |
| 366 | `internal--module-call', passing the function pointer of the module | 412 | allocate_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 | ||
| 372 | static emacs_value | 424 | static emacs_value |
| 373 | module_make_function (emacs_env *env, ptrdiff_t min_arity, ptrdiff_t max_arity, | 425 | module_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 | ||
| 412 | static emacs_value | 458 | static 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 | |||
| 435 | module_intern (emacs_env *env, const char *name) | 481 | module_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 | ||
| 441 | static emacs_value | 487 | static emacs_value |
| 442 | module_type_of (emacs_env *env, emacs_value value) | 488 | module_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 | ||
| 448 | static bool | 494 | static bool |
| 449 | module_is_not_nil (emacs_env *env, emacs_value value) | 495 | module_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 | ||
| 457 | static bool | 501 | static bool |
| 458 | module_eq (emacs_env *env, emacs_value a, emacs_value b) | 502 | module_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 | ||
| 484 | static double | 526 | static double |
| @@ -494,7 +536,7 @@ static emacs_value | |||
| 494 | module_make_float (emacs_env *env, double d) | 536 | module_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 | ||
| 500 | static bool | 542 | static 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 | |||
| 535 | module_make_string (emacs_env *env, const char *str, ptrdiff_t length) | 573 | module_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 | ||
| 542 | static emacs_value | 585 | static emacs_value |
| 543 | module_make_user_ptr (emacs_env *env, emacs_finalizer_function fin, void *ptr) | 586 | module_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 | ||
| 549 | static void * | 592 | static void * |
| @@ -558,7 +601,6 @@ module_get_user_ptr (emacs_env *env, emacs_value uptr) | |||
| 558 | static void | 601 | static void |
| 559 | module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr) | 602 | module_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 | |||
| 578 | module_set_user_finalizer (emacs_env *env, emacs_value uptr, | 620 | module_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) | |||
| 597 | static void | 638 | static void |
| 598 | module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val) | 639 | module_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 | ||
| 616 | static ptrdiff_t | 656 | static ptrdiff_t |
| 617 | module_vec_size (emacs_env *env, emacs_value vec) | 657 | module_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. */ | ||
| 667 | static bool | ||
| 668 | module_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 | ||
| 677 | static void | ||
| 678 | module_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 | |||
| 629 | DEFUN ("module-load", Fmodule_load, Smodule_load, 1, 1, 0, | 693 | DEFUN ("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 | ||
| 672 | DEFUN ("internal--module-call", Finternal_module_call, Sinternal_module_call, 1, MANY, 0, | 751 | Lisp_Object |
| 673 | doc: /* Internal function to call a module function. | 752 | funcall_module (Lisp_Object function, ptrdiff_t nargs, Lisp_Object *arglist) |
| 674 | ENVOBJ is a save pointer to a module_fun_env structure. | ||
| 675 | ARGLIST is a list of arguments passed to SUBRPTR. | ||
| 676 | usage: (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; | 793 | Lisp_Object |
| 727 | finalize_environment (&priv); | 794 | module_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 | ||
| 745 | static void | 805 | static bool |
| 746 | check_main_thread (void) | 806 | in_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 | ||
| 755 | static void | 817 | static void |
| 818 | module_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 | |||
| 825 | static void | ||
| 826 | module_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 | |||
| 841 | static void | ||
| 842 | module_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 | |||
| 858 | static void | ||
| 756 | module_non_local_exit_signal_1 (emacs_env *env, Lisp_Object sym, | 859 | module_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) | |||
| 837 | static Lisp_Object | 948 | static Lisp_Object |
| 838 | value_to_lisp (emacs_value v) | 949 | value_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. */ |
| 867 | static emacs_value | 1005 | static emacs_value |
| 868 | lisp_to_value (Lisp_Object o) | 1006 | lisp_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 |
| 901 | static 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. */ | ||
| 1059 | static emacs_env * | ||
| 902 | initialize_environment (emacs_env *env, struct emacs_env_private *priv) | 1060 | initialize_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. */ |
| 939 | static void | 1103 | static void |
| 940 | finalize_environment (struct emacs_env_private *env) | 1104 | finalize_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 | |||
| 1113 | static void | ||
| 1114 | finalize_environment_unwind (void *env) | ||
| 1115 | { | ||
| 1116 | finalize_environment (env); | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | static void | ||
| 1120 | finalize_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 | |||
| 1128 | void | ||
| 1129 | mark_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. */ | ||
| 952 | static void | 1150 | static void |
| 953 | module_reset_handlerlist (const int *dummy) | 1151 | module_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. */ |
| 1175 | void | ||
| 1176 | init_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 | 1189 | static _Noreturn void |
| 978 | representation of the function environment. */ | 1190 | ATTRIBUTE_FORMAT_PRINTF(1, 2) |
| 979 | static Lisp_Object | 1191 | module_abort (const char *format, ...) |
| 980 | module_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 | |||
| 3 | Copyright (C) 2015-2017 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along 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 | ||
| 34 | extern "C" { | ||
| 35 | #endif | ||
| 36 | |||
| 37 | /* Current environment. */ | ||
| 38 | typedef 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! */ | ||
| 42 | typedef struct emacs_value_tag *emacs_value; | ||
| 43 | |||
| 44 | enum { emacs_variadic_function = -2 }; | ||
| 45 | |||
| 46 | /* Struct passed to a module init function (emacs_module_init). */ | ||
| 47 | struct 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. */ | ||
| 61 | enum 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 | |||
| 73 | struct 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. */ | ||
| 191 | extern 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 | |||
| 3 | Copyright (C) 2015-2017 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along 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 | ||
| 46 | extern "C" { | ||
| 47 | #endif | ||
| 48 | |||
| 49 | /* Current environment. */ | ||
| 50 | typedef 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! */ | ||
| 54 | typedef struct emacs_value_tag *emacs_value; | ||
| 55 | |||
| 56 | enum { emacs_variadic_function = -2 }; | ||
| 57 | |||
| 58 | /* Struct passed to a module init function (emacs_module_init). */ | ||
| 59 | struct 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. */ | ||
| 74 | enum 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 | |||
| 86 | struct emacs_env_25 | ||
| 87 | { | ||
| 88 | @module_env_snippet_25@ | ||
| 89 | }; | ||
| 90 | |||
| 91 | struct 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. */ | ||
| 99 | extern 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 | |||
| 137 | bool might_dump; | 137 | bool might_dump; |
| 138 | #endif | 138 | #endif |
| 139 | 139 | ||
| 140 | #ifdef DARWIN_OS | ||
| 141 | extern 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. */ |
| 146 | bool inhibit_window_system; | 142 | bool 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 | ||
| 1227 | Lisp_Object | 1227 | Lisp_Object |
| 1228 | internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform, | 1228 | internal_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 | ||
| 1477 | void | 1482 | void |
| 1478 | maybe_quit (void) | 1483 | maybe_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 | ||
| 2896 | static Lisp_Object | 2901 | static Lisp_Object |
| 2897 | funcall_lambda (Lisp_Object fun, ptrdiff_t nargs, | 2902 | funcall_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 | |||
| 2256 | file_name_case_insensitive_p (const char *filename) | 2256 | file_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 | 3309 | enum { READ_BUF_SIZE = MAX_ALLOCA }; |
| 3350 | #define READ_BUF_SIZE (64 << 10) | ||
| 3351 | #endif | ||
| 3352 | /* Some buffer offsets are stored in 'int' variables. */ | ||
| 3353 | verify (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; |
| @@ -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 | ||
| 477 | DEFUN ("copy-sequence", Fcopy_sequence, Scopy_sequence, 1, 1, 0, | 477 | DEFUN ("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. |
| 479 | The elements of a list or vector are not copied; they are shared | 479 | The elements of a list, vector or record are not copied; they are |
| 480 | with the original. */) | 480 | shared 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 | ||
| 4281 | static EMACS_UINT | 4295 | static 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) | |||
| 424 | INLINE bool | 424 | INLINE bool |
| 425 | FONT_SPEC_P (Lisp_Object x) | 425 | FONT_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) | |||
| 438 | INLINE bool | 438 | INLINE bool |
| 439 | FONT_ENTITY_P (Lisp_Object x) | 439 | FONT_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) | |||
| 452 | INLINE bool | 452 | INLINE bool |
| 453 | FONT_OBJECT_P (Lisp_Object x) | 453 | FONT_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 | */ | ||
| 327 | static int | 346 | static int |
| 328 | frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, | 347 | frame_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 | */ | ||
| 405 | static void | ||
| 406 | keep_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 | */ | ||
| 376 | void | 543 | void |
| 377 | adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, | 544 | adjust_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. */) | |||
| 1107 | Lisp_Object | 1295 | Lisp_Object |
| 1108 | do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) | 1296 | do_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 | |||
| 1253 | to that frame. */) | 1442 | to 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 | ||
| 1264 | DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, | 1456 | DEFUN ("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 | ||
| 1477 | DEFUN ("frame-parent", Fframe_parent, Sframe_parent, | ||
| 1478 | 0, 1, 0, | ||
| 1479 | doc: /* Return the parent frame of FRAME. | ||
| 1480 | The parent frame of FRAME is the Emacs frame whose window-system window | ||
| 1481 | is the parent window of FRAME's window-system window. When such a frame | ||
| 1482 | exists, FRAME is considered a child frame of that frame. | ||
| 1483 | |||
| 1484 | Return nil if FRAME has no parent frame. This means that FRAME's | ||
| 1485 | window-system window is either a "top-level" window (a window whose | ||
| 1486 | parent 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 | ||
| 1507 | bool | ||
| 1508 | frame_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 | |||
| 1524 | DEFUN ("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. | ||
| 1527 | ANCESTOR is an ancestor of DESCENDANT when it is either DESCENDANT's | ||
| 1528 | parent frame or it is an ancestor of DESCENDANT's parent frame. Both, | ||
| 1529 | ANCESTOR and DESCENDANT must be live frames and default to the selected | ||
| 1530 | frame. */) | ||
| 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 | |
| 1447 | static int | 1701 | * but F. Return false otherwise. |
| 1448 | other_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 | */ | ||
| 1711 | static bool | ||
| 1712 | other_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. */ | ||
| 1524 | Lisp_Object | 1809 | Lisp_Object |
| 1525 | delete_frame (Lisp_Object frame, Lisp_Object force) | 1810 | delete_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 | */ | ||
| 2168 | enum internal_border_part | ||
| 2169 | frame_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 | ||
| 1857 | DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0, | 2244 | DEFUN ("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 | ||
| 2295 | DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, | 2682 | DEFUN ("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. |
| 2297 | FRAME nil means use the selected frame. | 2684 | FRAME nil means use the selected frame. Optional argument NOACTIVATE |
| 2685 | means do not activate FRAME. | ||
| 2686 | |||
| 2298 | If there is no window system support, this function does nothing. */) | 2687 | If 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 | ||
| 2779 | DEFUN ("frame-pixel-height", Fframe_pixel_height, | 3198 | DEFUN ("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. |
| 2782 | If FRAME is omitted or nil, the selected frame is used. The exact value | 3201 | For a terminal frame, the result really gives the width in characters. |
| 2783 | of the result depends on the window-system and toolkit in use: | 3202 | If FRAME is omitted or nil, the selected frame is used. */) |
| 2784 | |||
| 2785 | In the Gtk+ version of Emacs, it includes only any window (including | ||
| 2786 | the minibuffer or echo area), mode line, and header line. It does not | ||
| 2787 | include the tool bar or menu bar. | ||
| 2788 | |||
| 2789 | With other graphical versions, it also includes the tool bar and the | ||
| 2790 | menu bar. | ||
| 2791 | |||
| 2792 | For a text terminal, it includes the menu bar. In this case, the | ||
| 2793 | result is really in characters rather than pixels (i.e., is identical | ||
| 2794 | to `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 | ||
| 2807 | DEFUN ("frame-pixel-width", Fframe_pixel_width, | 3215 | DEFUN ("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. |
| 2810 | For a terminal frame, the result really gives the width in characters. | 3218 | If FRAME is omitted or nil, the selected frame is used. The exact value |
| 2811 | If FRAME is omitted or nil, the selected frame is used. */) | 3219 | of the result depends on the window-system and toolkit in use: |
| 3220 | |||
| 3221 | In the Gtk+ and NS versions, it includes only any window (including the | ||
| 3222 | minibuffer or echo area), mode line, and header line. It does not | ||
| 3223 | include the tool bar or menu bar. With other graphical versions, it may | ||
| 3224 | also include the tool bar and the menu bar. | ||
| 3225 | |||
| 3226 | For a text terminal, it includes the menu bar. In this case, the | ||
| 3227 | result is really in characters rather than pixels (i.e., is identical | ||
| 3228 | to `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 | ||
| 2824 | DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width, | 3241 | DEFUN ("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 | ||
| 2904 | DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0, | 3321 | DEFUN ("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. */ | ||
| 3528 | enum 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 | */ | ||
| 3562 | static int | ||
| 3563 | frame_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[] = | |||
| 3109 | void | 3715 | void |
| 3110 | x_set_frame_parameters (struct frame *f, Lisp_Object alist) | 3716 | x_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 | ||
| 3803 | void | 4412 | void |
| @@ -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 | */ | ||
| 4631 | void | ||
| 4632 | x_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. |
| 5810 | The 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. | ||
| 5819 | The 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. |
| 5135 | The functions are run with one arg, the frame to be deleted. | 5824 | The functions are run with one arg, the frame to be deleted. |
| @@ -5176,12 +5865,51 @@ displayed. | |||
| 5176 | 5865 | ||
| 5177 | This variable is local to the current terminal and cannot be buffer-local. */); | 5866 | This 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. |
| 5181 | You should set this variable to tell Emacs how your window manager | 5870 | You should set this variable to tell Emacs how your window manager |
| 5182 | handles focus, since there is no way in general for Emacs to find out | 5871 | handles focus, since there is no way in general for Emacs to find out |
| 5183 | automatically. See also `mouse-autoselect-window'. */); | 5872 | automatically. |
| 5184 | focus_follows_mouse = 0; | 5873 | |
| 5874 | There 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 | |||
| 5888 | If this option is non-nil, Emacs moves the mouse pointer to the frame | ||
| 5889 | selected by `select-frame-set-input-focus'. This function is used by a | ||
| 5890 | number of commands like, for example, `other-frame' and `pop-to-buffer'. | ||
| 5891 | If this option is nil and your focus follows mouse window manager does | ||
| 5892 | not autonomously move the mouse pointer to the newly selected frame, the | ||
| 5893 | previously selected window manager window might get reselected instead | ||
| 5894 | immediately. | ||
| 5895 | |||
| 5896 | The distinction between the values t and `auto-raise' is not needed for | ||
| 5897 | "normal" frames because the window manager takes care of raising them. | ||
| 5898 | Setting this to `auto-raise' will, however, override the standard | ||
| 5899 | behavior of a window manager that does not automatically raise the frame | ||
| 5900 | that gets focus. Setting this to `auto-raise' is also necessary to | ||
| 5901 | automatically raise child frames which are usually left alone by the | ||
| 5902 | window manager. | ||
| 5903 | |||
| 5904 | Note that this option does not distinguish "sloppy" focus (where the | ||
| 5905 | frame that previously had focus retains focus as long as the mouse | ||
| 5906 | pointer does not move into another window manager window) from "strict" | ||
| 5907 | focus (where a frame immediately loses focus when it's left by the mouse | ||
| 5908 | pointer). | ||
| 5909 | |||
| 5910 | In order to extend a "focus follows mouse" policy to individual Emacs | ||
| 5911 | windows, 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 | ||
| 48 | enum z_group | ||
| 49 | { | ||
| 50 | z_group_none, | ||
| 51 | z_group_above, | ||
| 52 | z_group_below, | ||
| 53 | z_group_above_suspended, | ||
| 54 | }; | ||
| 55 | |||
| 56 | enum 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) | ||
| 591 | INLINE void | ||
| 592 | fset_parent_frame (struct frame *f, Lisp_Object val) | ||
| 593 | { | ||
| 594 | f->parent_frame = val; | ||
| 595 | } | ||
| 596 | #endif | ||
| 537 | INLINE void | 597 | INLINE void |
| 538 | fset_focus_frame (struct frame *f, Lisp_Object val) | 598 | fset_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. */ |
| 1218 | INLINE int | 1312 | INLINE int |
| 1219 | FRAME_INTERNAL_BORDER_WIDTH (struct frame *f) | 1313 | FRAME_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. */ |
| 1225 | INLINE int | 1319 | INLINE int |
| 1226 | FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f) | 1320 | FRAME_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 | |||
| 1230 | INLINE int | 1325 | INLINE int |
| 1231 | FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f) | 1326 | FRAME_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); | |||
| 1424 | extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *); | 1519 | extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *); |
| 1425 | 1520 | ||
| 1426 | extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object); | 1521 | extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object); |
| 1522 | extern void x_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object); | ||
| 1427 | 1523 | ||
| 1428 | extern void validate_x_resource_name (void); | 1524 | extern void validate_x_resource_name (void); |
| 1429 | 1525 | ||
| @@ -1446,6 +1542,8 @@ extern void x_activate_menubar (struct frame *); | |||
| 1446 | extern void x_real_positions (struct frame *, int *, int *); | 1542 | extern void x_real_positions (struct frame *, int *, int *); |
| 1447 | extern void free_frame_menubar (struct frame *); | 1543 | extern void free_frame_menubar (struct frame *); |
| 1448 | extern void x_free_frame_resources (struct frame *); | 1544 | extern void x_free_frame_resources (struct frame *); |
| 1545 | extern bool frame_ancestor_p (struct frame *af, struct frame *df); | ||
| 1546 | extern 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 |
| 1451 | extern void x_wm_set_icon_position (struct frame *, int, int); | 1549 | extern 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 | ||
| 1458 | extern void x_query_colors (struct frame *f, XColor *, int); | 1556 | extern void x_query_colors (struct frame *f, XColor *, int); |
| 1459 | extern void x_focus_frame (struct frame *); | 1557 | extern 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 |
| 80 | static bool | ||
| 81 | ALLOCATED_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; | |||
| 166 | extern malloc_info *_heapinfo; | 165 | extern 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); | |||
| 1721 | extern int posix_memalign (void **memptr, size_t alignment, size_t size); | 1710 | extern 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 | |||
| 1719 | static bool | ||
| 1720 | allocated_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) | |||
| 1743 | void | 1746 | void |
| 1744 | hybrid_free (void *ptr) | 1747 | hybrid_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 | |||
| 841 | void | ||
| 842 | xg_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 | |||
| 862 | static int | 839 | static int |
| 863 | xg_get_gdk_scale (void) | 840 | xg_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. */ | ||
| 1488 | void | ||
| 1489 | xg_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. */ | ||
| 1503 | void | ||
| 1504 | xg_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. */ | ||
| 1526 | void | ||
| 1527 | xg_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. */ | ||
| 1539 | void | ||
| 1540 | xg_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 | |||
| 1554 | void | ||
| 1555 | xg_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 | |||
| 1568 | void | ||
| 1569 | xg_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 | ||
| 4236 | static GtkWidget * | 4345 | static 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); | |||
| 150 | extern void free_frame_tool_bar (struct frame *f); | 150 | extern void free_frame_tool_bar (struct frame *f); |
| 151 | extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos); | 151 | extern void xg_change_toolbar_position (struct frame *f, Lisp_Object pos); |
| 152 | 152 | ||
| 153 | extern void xg_clear_under_internal_border (struct frame *f); | ||
| 154 | extern void xg_frame_resized (struct frame *f, | 153 | extern 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 | ||
| 174 | extern void xg_set_undecorated (struct frame *f, Lisp_Object undecorated); | ||
| 175 | extern void xg_frame_restack (struct frame *f1, struct frame *f2, bool above); | ||
| 176 | extern void xg_set_skip_taskbar (struct frame *f, Lisp_Object skip_taskbar); | ||
| 177 | extern void xg_set_no_focus_on_map (struct frame *f, Lisp_Object no_focus_on_map); | ||
| 178 | extern void xg_set_no_accept_focus (struct frame *f, Lisp_Object no_accept_focus); | ||
| 179 | extern void xg_set_override_redirect (struct frame *f, Lisp_Object override_redirect); | ||
| 180 | |||
| 175 | extern bool xg_prepare_tooltip (struct frame *f, | 181 | extern 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. */ |
| 1276 | static void | 1275 | static 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. */ |
| 47 | static int inotifyfd = -1; | 46 | static 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. */ |
| 203 | static Lisp_Object | 203 | static Lisp_Object |
| 204 | add_watch (int wd, Lisp_Object filename, | 204 | add_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 | |||
| 381 | move | 380 | move |
| 382 | close | 381 | close |
| 383 | 382 | ||
| 384 | The following symbols can also be added to a list of aspects: | 383 | ASPECT can also contain the following symbols, which control whether |
| 384 | the watch descriptor will be created: | ||
| 385 | 385 | ||
| 386 | dont-follow | 386 | dont-follow |
| 387 | onlydir | ||
| 387 | 388 | ||
| 388 | Watching a directory is not recursive. CALLBACK is passed a single argument | 389 | Watching a directory is not recursive. CALLBACK is passed a single argument |
| 389 | EVENT which contains an event structure of the format | 390 | EVENT which contains an event structure of the format |
| @@ -409,22 +410,18 @@ See inotify(7) and inotify_add_watch(2) for further information. The | |||
| 409 | inotify fd is managed internally and there is no corresponding | 410 | inotify fd is managed internally and there is no corresponding |
| 410 | inotify_init. Use `inotify-rm-watch' to remove a watch. | 411 | inotify_init. Use `inotify-rm-watch' to remove a watch. |
| 411 | 412 | ||
| 412 | Also note, that the following inotify bit-masks can not be used, due | 413 | The following inotify bit-masks cannot be used because descriptors are |
| 413 | to the fact that descriptors are shared across different callers. | 414 | shared across different callers. |
| 414 | 415 | ||
| 415 | IN_EXCL_UNLINK | 416 | IN_EXCL_UNLINK |
| 416 | IN_MASK_ADD | 417 | IN_MASK_ADD |
| 417 | IN_ONESHOT | 418 | IN_ONESHOT */) |
| 418 | IN_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 | ||
| 448 | static bool | 445 | static 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) | |||
| 634 | static void | 635 | static void |
| 635 | echo_truncate (ptrdiff_t nchars) | 636 | echo_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. */ | ||
| 5133 | static 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). */ |
| 45 | Lisp_Object | 45 | static Lisp_Object |
| 46 | kqueue_directory_listing (Lisp_Object directory_files) | 46 | kqueue_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 | ||
| 548 | typedef struct { EMACS_INT i; } Lisp_Object; | 545 | typedef 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) | |||
| 1344 | INLINE ptrdiff_t | 1343 | INLINE ptrdiff_t |
| 1345 | SCHARS (Lisp_Object string) | 1344 | SCHARS (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 | |||
| 1354 | STRING_BYTES (struct Lisp_String *s) | 1355 | STRING_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 | ||
| 1363 | INLINE ptrdiff_t | 1366 | INLINE ptrdiff_t |
| @@ -1368,6 +1371,11 @@ SBYTES (Lisp_Object string) | |||
| 1368 | INLINE void | 1371 | INLINE void |
| 1369 | STRING_SET_CHARS (Lisp_Object string, ptrdiff_t newsize) | 1372 | STRING_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 | ||
| 1411 | INLINE ptrdiff_t | ||
| 1412 | PVSIZE (Lisp_Object pv) | ||
| 1413 | { | ||
| 1414 | return ASIZE (pv) & PSEUDOVECTOR_SIZE_MASK; | ||
| 1415 | } | ||
| 1416 | |||
| 1403 | INLINE bool | 1417 | INLINE bool |
| 1404 | VECTORP (Lisp_Object x) | 1418 | VECTORP (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 | ||
| 1417 | INLINE enum pvec_type | 1432 | INLINE 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 | ||
| 2750 | INLINE bool | ||
| 2751 | RECORDP (Lisp_Object a) | ||
| 2752 | { | ||
| 2753 | return PSEUDOVECTORP (a, PVEC_RECORD); | ||
| 2754 | } | ||
| 2755 | |||
| 2756 | INLINE void | ||
| 2757 | CHECK_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) */ |
| 2736 | INLINE bool | 2763 | INLINE bool |
| 2737 | IMAGEP (Lisp_Object x) | 2764 | IMAGEP (Lisp_Object x) |
| @@ -3861,11 +3888,62 @@ extern void get_backtrace (Lisp_Object array); | |||
| 3861 | Lisp_Object backtrace_top_function (void); | 3888 | Lisp_Object backtrace_top_function (void); |
| 3862 | extern bool let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol); | 3889 | extern 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 | ||
| 3893 | extern void unexec_init_emacs_zone (void); | ||
| 3894 | extern void *unexec_malloc (size_t); | ||
| 3895 | extern void *unexec_realloc (void *, size_t); | ||
| 3896 | extern void unexec_free (void *); | ||
| 3897 | #endif | ||
| 3898 | |||
| 3899 | #include "emacs-module.h" | ||
| 3900 | |||
| 3901 | /* Function prototype for the module Lisp functions. */ | ||
| 3902 | typedef 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 | |||
| 3912 | struct 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 | |||
| 3925 | INLINE bool | ||
| 3926 | MODULE_FUNCTIONP (Lisp_Object o) | ||
| 3927 | { | ||
| 3928 | return PSEUDOVECTORP (o, PVEC_MODULE_FUNCTION); | ||
| 3929 | } | ||
| 3930 | |||
| 3931 | INLINE struct Lisp_Module_Function * | ||
| 3932 | XMODULE_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. */ |
| 3866 | extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); | 3940 | extern Lisp_Object make_user_ptr (void (*finalizer) (void *), void *p); |
| 3867 | 3941 | ||
| 3868 | /* Defined in emacs-module.c. */ | 3942 | /* Defined in emacs-module.c. */ |
| 3943 | extern Lisp_Object funcall_module (Lisp_Object, ptrdiff_t, Lisp_Object *); | ||
| 3944 | extern Lisp_Object module_function_arity (const struct Lisp_Module_Function *); | ||
| 3945 | extern void mark_modules (void); | ||
| 3946 | extern void init_module_assertions (bool); | ||
| 3869 | extern void syms_of_module (void); | 3947 | extern void syms_of_module (void); |
| 3870 | #endif | 3948 | #endif |
| 3871 | 3949 | ||
| @@ -4077,7 +4155,7 @@ extern bool no_site_lisp; | |||
| 4077 | extern bool build_details; | 4155 | extern 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. */ |
| 4081 | extern int daemon_type; | 4159 | extern 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 |
| 79 | static 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. */ | ||
| 87 | static 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. */ | ||
| 104 | static 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. */ |
| 82 | static FILE *instream; | 107 | static 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) | |||
| 948 | static void | 972 | static void |
| 949 | load_warn_old_style_backquotes (Lisp_Object file) | 973 | load_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 | ||
| 982 | static void | ||
| 983 | load_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 | |||
| 958 | DEFUN ("get-load-suffixes", Fget_load_suffixes, Sget_load_suffixes, 0, 0, 0, | 999 | DEFUN ("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 \ |
| 960 | required. | 1001 | required. |
| @@ -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 | ||
| 3465 | Lisp_Object | 3634 | Lisp_Object |
| 3466 | string_to_number (char const *string, int base, bool ignore_trailing) | 3635 | string_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) | |||
| 4436 | void | 4601 | void |
| 4437 | init_lread (void) | 4602 | init_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 | |||
| 4690 | variables defined in that file, the features provided, and the | 4858 | variables defined in that file, the features provided, and the |
| 4691 | features required. Each entry has the form `(provide . FEATURE)', | 4859 | features 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)', |
| 4694 | may precede a `(defun . FUNCTION)' entry, and means that SYMBOL was an | 4862 | `(cl-defmethod METHOD SPECIALIZERS)', or `(t . SYMBOL)'. |
| 4695 | autoload before this file redefined it as a function. In addition, | 4863 | Entries like `(t . SYMBOL)' may precede a `(defun . FUNCTION)' entry, |
| 4696 | entries may also be single symbols, which means that SYMBOL was | 4864 | and means that SYMBOL was an autoload before this file redefined it |
| 4697 | defined by `defvar' or `defconst'. | 4865 | as a function. In addition, entries may also be single symbols, |
| 4866 | which means that symbol was defined by `defvar' or `defconst'. | ||
| 4698 | 4867 | ||
| 4699 | During preloading, the file name recorded is relative to the main Lisp | 4868 | During preloading, the file name recorded is relative to the main Lisp |
| 4700 | directory. These file names are converted to absolute at startup. */); | 4869 | directory. 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; | 4973 | For 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'. | ||
| 4980 | For 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 |
| 208 | static CGGlyph | 208 | static CGGlyph |
| 209 | mac_font_get_glyph_for_cid (CTFontRef font, CTCharacterCollection collection, | 209 | mac_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 | ||
| 319 | static CFIndex | 318 | static CFIndex |
| 320 | mac_font_shape_1 (NSFont *font, NSString *string, | 319 | mac_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 | ||
| 593 | static CGColorRef | 591 | static 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 *); | |||
| 1333 | static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef); | 1331 | static CFCharacterSetRef macfont_get_cf_charset_for_name (CFStringRef); |
| 1334 | static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char); | 1332 | static CGGlyph macfont_get_glyph_for_character (struct font *, UTF32Char); |
| 1335 | static CGGlyph macfont_get_glyph_for_cid (struct font *font, | 1333 | static CGGlyph macfont_get_glyph_for_cid (struct font *font, |
| 1336 | CTCharacterCollection, CGFontIndex); | 1334 | NSCharacterCollection, CGFontIndex); |
| 1337 | static CFDataRef macfont_get_uvs_table (struct font *, CTCharacterCollection *); | 1335 | static CFDataRef macfont_get_uvs_table (struct font *, NSCharacterCollection *); |
| 1338 | 1336 | ||
| 1339 | static struct macfont_cache * | 1337 | static struct macfont_cache * |
| 1340 | macfont_lookup_cache (CFStringRef key) | 1338 | macfont_lookup_cache (CFStringRef key) |
| @@ -1582,7 +1580,7 @@ macfont_get_glyph_for_character (struct font *font, UTF32Char c) | |||
| 1582 | } | 1580 | } |
| 1583 | 1581 | ||
| 1584 | static CGGlyph | 1582 | static CGGlyph |
| 1585 | macfont_get_glyph_for_cid (struct font *font, CTCharacterCollection collection, | 1583 | macfont_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 | ||
| 1595 | static CFDataRef | 1593 | static CFDataRef |
| 1596 | macfont_get_uvs_table (struct font *font, CTCharacterCollection *collection) | 1594 | macfont_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 | |||
| 3348 | macfont_variation_glyphs (struct font *font, int c, unsigned variations[256]) | 3345 | macfont_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 | ||
| 178 | static Lisp_Object | 179 | static Lisp_Object |
| 179 | interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old) | 180 | interpret_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 | ||
| 1380 | void | 1433 | void |
| 1381 | x_focus_frame (struct frame *f) | 1434 | x_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 | ||
| 1448 | static BOOL | ||
| 1449 | ns_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 | |||
| 1460 | DEFUN ("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. | ||
| 1463 | The optional argument TERMINAL specifies which display to ask about. | ||
| 1464 | TERMINAL should be either a frame or a display name (a string). If | ||
| 1465 | omitted or nil, that stands for the selected frame's display. Return | ||
| 1466 | nil if TERMINAL contains no Emacs frame. | ||
| 1467 | |||
| 1468 | As a special case, if TERMINAL is non-nil and specifies a live frame, | ||
| 1469 | return the child frames of that frame in Z (stacking) order. | ||
| 1470 | |||
| 1471 | Frames 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 | |||
| 1497 | DEFUN ("ns-frame-restack", Fns_frame_restack, Sns_frame_restack, 2, 3, 0, | ||
| 1498 | doc: /* Restack FRAME1 below FRAME2. | ||
| 1499 | This means that if both frames are visible and the display areas of | ||
| 1500 | these frames overlap, FRAME2 (partially) obscures FRAME1. If optional | ||
| 1501 | third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This | ||
| 1502 | means that if both frames are visible and the display areas of these | ||
| 1503 | frames overlap, FRAME1 (partially) obscures FRAME2. | ||
| 1504 | |||
| 1505 | Some 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 | ||
| 1396 | DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, | 1529 | DEFUN ("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 | ||
| 3041 | DEFUN ("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). | ||
| 3045 | The 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 | ||
| 361 | typedef 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 */ |
| 1186 | extern float ns_antialias_threshold; | 1223 | extern float ns_antialias_threshold; |
| 1187 | extern void x_destroy_window (struct frame *f); | 1224 | extern void x_destroy_window (struct frame *f); |
| 1225 | extern void x_set_undecorated (struct frame *f, Lisp_Object new_value, | ||
| 1226 | Lisp_Object old_value); | ||
| 1227 | extern void x_set_parent_frame (struct frame *f, Lisp_Object new_value, | ||
| 1228 | Lisp_Object old_value); | ||
| 1229 | extern void x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, | ||
| 1230 | Lisp_Object old_value); | ||
| 1231 | extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, | ||
| 1232 | Lisp_Object old_value); | ||
| 1233 | extern void x_set_z_group (struct frame *f, Lisp_Object new_value, | ||
| 1234 | Lisp_Object old_value); | ||
| 1188 | extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, | 1235 | extern 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 | ||
| 1239 | extern void ns_run_loop_break (void); | ||
| 1240 | #endif | ||
| 1191 | extern unsigned long ns_get_rgb_color (struct frame *f, | 1241 | extern 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__ | ||
| 1318 | typedef 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 */ |
| 415 | static void ns_condemn_scroll_bars (struct frame *f); | 432 | static void ns_condemn_scroll_bars (struct frame *f); |
| 416 | static void ns_judge_scroll_bars (struct frame *f); | 433 | static 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 | ||
| 1448 | static void | 1465 | static void |
| 1449 | ns_raise_frame (struct frame *f) | 1466 | ns_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 | ||
| 1832 | void | ||
| 1833 | x_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 | |||
| 1882 | void | ||
| 1883 | x_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 | |||
| 1934 | void | ||
| 1935 | x_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 | |||
| 1952 | void | ||
| 1953 | x_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 | |||
| 1969 | void | ||
| 1970 | x_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 | ||
| 1815 | static void | 2010 | static void |
| 1816 | ns_fullscreen_hook (struct frame *f) | 2011 | ns_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 | ||
| 4098 | int | 4294 | int |
| 4099 | ns_select (int nfds, fd_set *readfds, fd_set *writefds, | 4295 | ns_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 | ||
| 4440 | void | ||
| 4441 | ns_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 | ||
| 1350 | static bool | ||
| 1351 | print_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 | |||
| 1348 | static void | 1745 | static void |
| 1349 | print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | 1746 | print_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'. */); | |||
| 2283 | Also print formfeeds as `\\f'. */); | 2344 | Also 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; | |||
| 4626 | static void | 4664 | static void |
| 4627 | server_accept_connection (Lisp_Object server, int channel) | 4665 | server_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 | ||
| 2229 | DEFUN ("re-search-backward", Fre_search_backward, Sre_search_backward, 1, 4, | 2230 | DEFUN ("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. |
| 2232 | Set point to the beginning of the occurrence found, and return point. | 2233 | This function is almost identical to `re-search-forward', except that |
| 2233 | An optional second argument bounds the search; it is a buffer position. | 2234 | by 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 | 2235 | COUNT also indicates exactly the opposite searching direction. |
| 2235 | means search to the beginning of the accessible portion of the buffer. | ||
| 2236 | Optional 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. | ||
| 2238 | Optional 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. | ||
| 2242 | With 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 | |||
| 2246 | Search case-sensitivity is determined by the value of the variable | ||
| 2247 | `case-fold-search', which see. | ||
| 2248 | 2236 | ||
| 2249 | See also the functions `match-beginning', `match-end', `match-string', | 2237 | See `re-search-forward' for details. */) |
| 2250 | and `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. |
| 2259 | Set point to the end of the occurrence found, and return point. | 2246 | Set point to the end of the occurrence found, and return point. |
| 2260 | An optional second argument bounds the search; it is a buffer position. | 2247 | The 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 |
| 2263 | Optional 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. | 2251 | The optional third argument NOERROR indicates how errors are handled |
| 2265 | Optional 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. | 2255 | The optional fourth argument COUNT is a number that indicates the |
| 2269 | With 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. | ||
| 2260 | With 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 | ||
| 2273 | Search case-sensitivity is determined by the value of the variable | 2264 | Search 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. */ |
| 373 | static pid_t | 373 | static pid_t |
| 374 | get_child_status (pid_t child, int *status, int options, bool interruptible) | 374 | get_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. |
| 417 | void | 418 | Return true if successful, false (setting errno) if CHILD cannot be |
| 419 | waited for because waitpid is buggy. */ | ||
| 420 | bool | ||
| 418 | wait_for_termination (pid_t child, int *status, bool interruptible) | 421 | wait_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 | |||
| 3707 | system_process_attributes (Lisp_Object pid) | 3707 | system_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 | ||
| 25 | void | 29 | void |
| @@ -130,6 +134,13 @@ void | |||
| 130 | sys_cond_broadcast (sys_cond_t *cond) | 134 | sys_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 | ||
| 135 | void | 146 | void |
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. */ |
| 59 | extern void wait_for_termination (pid_t, int *, bool); | 59 | extern bool wait_for_termination (pid_t, int *, bool); |
| 60 | extern pid_t child_status_changed (pid_t, int *, int); | 60 | extern 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" |
| 50 | static int been_here = -1; | 50 | static 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 | |||
| 575 | terminal_glyph_code (struct terminal *t, int ch) | 575 | terminal_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, | |||
| 664 | static Lisp_Object | 664 | static Lisp_Object |
| 665 | invoke_thread_function (void) | 665 | invoke_thread_function (void) |
| 666 | { | 666 | { |
| 667 | int count = SPECPDL_INDEX (); | 667 | ptrdiff_t count = SPECPDL_INDEX (); |
| 668 | 668 | ||
| 669 | Ffuncall (1, ¤t_thread->function); | 669 | Ffuncall (1, ¤t_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 | ||
| 349 | static void | ||
| 350 | print_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 |
| @@ -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). */ | ||
| 2984 | int | ||
| 2985 | gettimeofday (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. */ |
| 260 | static struct | 264 | static struct |
| 261 | { | 265 | { |
| @@ -367,17 +371,20 @@ void x_set_title (struct frame *, Lisp_Object, Lisp_Object); | |||
| 367 | void | 371 | void |
| 368 | x_real_positions (struct frame *f, int *xptr, int *yptr) | 372 | x_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 | ||
| 1630 | static 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 | */ | ||
| 1643 | void | ||
| 1631 | x_clear_under_internal_border (struct frame *f) | 1644 | x_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 | */ | ||
| 1653 | void | 1686 | void |
| 1654 | x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval) | 1687 | x_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 | */ | ||
| 1676 | void | 1717 | void |
| 1677 | x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) | 1718 | x_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 | */ | ||
| 2019 | static void | ||
| 2020 | x_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 | */ | ||
| 2078 | static void | ||
| 2079 | x_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 | */ | ||
| 2123 | static void | ||
| 2124 | x_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 | */ | ||
| 2157 | static void | ||
| 2158 | x_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 | */ | ||
| 2176 | static void | ||
| 2177 | x_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 | */ | ||
| 2196 | static void | ||
| 2197 | x_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) | |||
| 2013 | static HWND | 2288 | static HWND |
| 2014 | w32_createvscrollbar (struct frame *f, struct scroll_bar * bar) | 2289 | w32_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) | |||
| 2022 | static HWND | 2302 | static HWND |
| 2023 | w32_createhscrollbar (struct frame *f, struct scroll_bar * bar) | 2303 | w32_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) | |||
| 2031 | static void | 2316 | static void |
| 2032 | w32_createwindow (struct frame *f, int *coords) | 2317 | w32_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 | ||
| 7716 | void | ||
| 7717 | w32_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 | |||
| 7285 | DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, | 7733 | DEFUN ("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. |
| 7287 | Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file | 7735 | Use 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 | */ | ||
| 9035 | static Lisp_Object | ||
| 9036 | w32_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 | |||
| 9058 | DEFUN ("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. | ||
| 9061 | The optional argument DISPLAY specifies which display to ask about. | ||
| 9062 | DISPLAY should be either a frame or a display name (a string). If | ||
| 9063 | omitted or nil, that stands for the selected frame's display. | ||
| 9064 | |||
| 9065 | As a special case, if DISPLAY is non-nil and specifies a live frame, | ||
| 9066 | return the child frames of that frame in Z (stacking) order. | ||
| 9067 | |||
| 9068 | Frames 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 | */ | ||
| 9092 | static void | ||
| 9093 | w32_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 | |||
| 9125 | DEFUN ("w32-frame-restack", Fw32_frame_restack, Sw32_frame_restack, 2, 3, 0, | ||
| 9126 | doc: /* Restack FRAME1 below FRAME2. | ||
| 9127 | This means that if both frames are visible and the display areas of | ||
| 9128 | these frames overlap, FRAME2 (partially) obscures FRAME1. If optional | ||
| 9129 | third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This | ||
| 9130 | means that if both frames are visible and the display areas of these | ||
| 9131 | frames overlap, FRAME1 (partially) obscures FRAME2. | ||
| 9132 | |||
| 9133 | This may be thought of as an atomic action performed in two steps: The | ||
| 9134 | first step removes FRAME1's window-system window from the display. The | ||
| 9135 | second step reinserts FRAME1's window below (above if ABOVE is true) | ||
| 9136 | that of FRAME2. Hence the position of FRAME2 in its display's Z | ||
| 9137 | \(stacking) order relative to all other frames excluding FRAME1 remains | ||
| 9138 | unaltered. | ||
| 9139 | |||
| 9140 | Some 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 | |||
| 8562 | DEFUN ("w32-mouse-absolute-pixel-position", Fw32_mouse_absolute_pixel_position, | 9158 | DEFUN ("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 | ||
| 9758 | void | 10362 | void |
| @@ -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 | ||
| 2563 | static const char *const w32font_booleans [] = { | 2574 | static 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 | ||
| 6316 | void | 6483 | void |
| 6317 | x_focus_frame (struct frame *f) | 6484 | x_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); |
| 248 | extern void initialize_frame_menubar (struct frame *); | 248 | extern void initialize_frame_menubar (struct frame *); |
| 249 | extern void w32_dialog_in_progress (Lisp_Object in_progress); | ||
| 249 | 250 | ||
| 250 | /* w32inevt.c */ | 251 | /* w32inevt.c */ |
| 251 | extern int w32_kbd_patch_key (KEY_EVENT_RECORD *event, int cpId); | 252 | extern 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 | ||
| 707 | extern void w32_sys_ring_bell (struct frame *f); | 716 | extern void w32_sys_ring_bell (struct frame *f); |
| 708 | extern void x_delete_display (struct w32_display_info *dpyinfo); | 717 | extern void x_delete_display (struct w32_display_info *dpyinfo); |
| 709 | 718 | extern void x_clear_under_internal_border (struct frame *f); | |
| 710 | extern void x_query_color (struct frame *, XColor *); | 719 | extern 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 | ||
| 109 | static EmacsFrameClassRec emacsFrameClassRec = { | 109 | static 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 | ||
| 149 | WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec; | 149 | WidgetClass |
| 150 | emacsFrameClass (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 | ||
| 151 | static void | 160 | static void |
| 152 | get_default_char_pixel_size (EmacsFrame ew, int *pixel_width, int *pixel_height) | 161 | get_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/>. */ | |||
| 90 | typedef struct _EmacsFrameRec *EmacsFrame; | 90 | typedef struct _EmacsFrameRec *EmacsFrame; |
| 91 | typedef struct _EmacsFrameClassRec *EmacsFrameClass; | 91 | typedef struct _EmacsFrameClassRec *EmacsFrameClass; |
| 92 | 92 | ||
| 93 | extern WidgetClass emacsFrameClass; | 93 | extern WidgetClass emacsFrameClass (void); |
| 94 | 94 | ||
| 95 | extern struct _DisplayContext *display_context; | 95 | extern 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 | ||
| 572 | Optional second arg NORECORD non-nil means do not put this buffer at the | 572 | Optional second arg NORECORD non-nil means do not put this buffer at the |
| 573 | front of the buffer list and do not make this window the most recently | 573 | front of the buffer list and do not make this window the most recently |
| 574 | selected one. | 574 | selected one. Also, do not mark WINDOW for redisplay unless NORECORD |
| 575 | equals the special symbol `mark-for-redisplay'. | ||
| 575 | 576 | ||
| 576 | Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that | 577 | Run `buffer-list-update-hook' unless NORECORD is non-nil. Note that |
| 577 | applications and internal routines often select a window temporarily for | 578 | applications 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 | ||
| 1901 | DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0, | ||
| 1902 | doc: /* Return pixel dimensions of WINDOW's lines. | ||
| 1903 | The return value is a list of the x- and y-coordinates of the lower | ||
| 1904 | right corner of the last character of each line. Return nil if the | ||
| 1905 | current glyph matrix of WINDOW is not up-to-date. | ||
| 1906 | |||
| 1907 | Optional argument WINDOW specifies the window whose lines' dimensions | ||
| 1908 | shall be returned. Nil or omitted means to return the dimensions for | ||
| 1909 | the selected window. | ||
| 1910 | |||
| 1911 | FIRST, if non-nil, specifies the index of the first line whose | ||
| 1912 | dimensions shall be returned. If FIRST is nil and BODY is non-nil, | ||
| 1913 | start with the first text line of WINDOW. Otherwise, start with the | ||
| 1914 | first line of WINDOW. | ||
| 1915 | |||
| 1916 | LAST, if non-nil, specifies the last line whose dimensions shall be | ||
| 1917 | returned. If LAST is nil and BODY is non-nil, the last line is the last | ||
| 1918 | line of the body (text area) of WINDOW. Otherwise, last is the last | ||
| 1919 | line of WINDOW. | ||
| 1920 | |||
| 1921 | INVERSE, if nil, means that the y-pixel value returned for a specific | ||
| 1922 | line specifies the distance in pixels from the left edge (body edge if | ||
| 1923 | BODY is non-nil) of WINDOW to the right edge of the last glyph of that | ||
| 1924 | line. INVERSE non-nil means that the y-pixel value returned for a | ||
| 1925 | specific line specifies the distance in pixels from the right edge of | ||
| 1926 | the last glyph of that line to the right edge (body edge if BODY is | ||
| 1927 | non-nil) of WINDOW. | ||
| 1928 | |||
| 1929 | LEFT non-nil means to return the x- and y-coordinates of the lower left | ||
| 1930 | corner of the leftmost character on each line. This is the value that | ||
| 1931 | should be used for buffers that mostly display text from right to left. | ||
| 1932 | |||
| 1933 | If LEFT is non-nil and INVERSE is nil, this means that the y-pixel value | ||
| 1934 | returned for a specific line specifies the distance in pixels from the | ||
| 1935 | left 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 | ||
| 1937 | non-nil, the y-pixel value returned for a specific line specifies the | ||
| 1938 | distance in pixels from the left edge (body edge if BODY is non-nil) of | ||
| 1939 | WINDOW to the left edge of the last (leftmost) glyph of that line. | ||
| 1940 | |||
| 1941 | Normally, the value of this function is not available while Emacs is | ||
| 1942 | busy, for example, when processing a command. It should be retrievable | ||
| 1943 | though 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 | |||
| 1900 | DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p, | 2024 | DEFUN ("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 | ||
| 2129 | Lisp_Object | ||
| 2130 | window_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 | |||
| 2005 | DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter, | 2138 | DEFUN ("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. |
| 2008 | WINDOW can be any window and defaults to the selected one. */) | 2141 | WINDOW 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 | ||
| 2017 | DEFUN ("set-window-parameter", Fset_window_parameter, | 2149 | DEFUN ("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 | ||
| 3338 | void | 3479 | void |
| @@ -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 | */ | ||
| 4886 | bool | ||
| 4887 | window_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 | */ | ||
| 4917 | bool | ||
| 4918 | window_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 | ||
| 4735 | int | 4939 | int |
| @@ -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, | |||
| 7035 | WINDOW must be a live window and defaults to the selected one. | 7239 | WINDOW must be a live window and defaults to the selected one. |
| 7036 | 7240 | ||
| 7037 | Second parameter WIDTH specifies the pixel width for the vertical scroll | 7241 | Second parameter WIDTH specifies the pixel width for the vertical scroll |
| 7038 | bar. If WIDTH is nil, use the scroll-bar width of WINDOW's frame. | 7242 | bar. If WIDTH is nil, use the scroll bar width of WINDOW's frame. |
| 7039 | Third parameter VERTICAL-TYPE specifies the type of the vertical scroll | 7243 | Third parameter VERTICAL-TYPE specifies the type of the vertical scroll |
| 7040 | bar: left, right, or nil. If VERTICAL-TYPE is t, this means use the | 7244 | bar: left, right, nil or t where nil means to not display a vertical |
| 7041 | frame's scroll-bar type. | 7245 | scroll bar on WINDOW and t means to use WINDOW frame's vertical scroll |
| 7246 | bar type. | ||
| 7042 | 7247 | ||
| 7043 | Fourth parameter HEIGHT specifies the pixel height for the horizontal | 7248 | Fourth parameter HEIGHT specifies the pixel height for the horizontal |
| 7044 | scroll bar. If HEIGHT is nil, use the scroll-bar height of WINDOW's | 7249 | scroll bar. If HEIGHT is nil, use the scroll bar height of WINDOW's |
| 7045 | frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the | 7250 | frame. Fifth parameter HORIZONTAL-TYPE specifies the type of the |
| 7046 | horizontal scroll bar: nil, bottom, or t. If HORIZONTAL-TYPE is t, this | 7251 | horizontal scroll bar: bottom, nil, or t where nil means to not display |
| 7047 | means to use the frame's horizontal scroll-bar type. | 7252 | a horizontal scroll bar on WINDOW and t means to use WINDOW frame's |
| 7253 | horizontal scroll bar type. | ||
| 7048 | 7254 | ||
| 7049 | Return t if scroll bars were actually changed and nil otherwise. */) | 7255 | Return 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 | ||
| 7475 | Other values are reserved for future use. */); | 7689 | The default value is `window-size'. Other values are reserved for |
| 7690 | future 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); | |||
| 1114 | extern Lisp_Object Vwindow_list; | 1090 | extern Lisp_Object Vwindow_list; |
| 1115 | 1091 | ||
| 1116 | extern Lisp_Object window_list (void); | 1092 | extern Lisp_Object window_list (void); |
| 1093 | extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter); | ||
| 1117 | extern struct window *decode_live_window (Lisp_Object); | 1094 | extern struct window *decode_live_window (Lisp_Object); |
| 1118 | extern struct window *decode_any_window (Lisp_Object); | 1095 | extern struct window *decode_any_window (Lisp_Object); |
| 1119 | extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool); | 1096 | extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool); |
| 1120 | extern void mark_window_cursors_off (struct window *); | 1097 | extern void mark_window_cursors_off (struct window *); |
| 1098 | extern bool window_wants_mode_line (struct window *); | ||
| 1099 | extern bool window_wants_header_line (struct window *); | ||
| 1121 | extern int window_internal_height (struct window *); | 1100 | extern int window_internal_height (struct window *); |
| 1122 | extern int window_body_width (struct window *w, bool); | 1101 | extern int window_body_width (struct window *w, bool); |
| 1123 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; | 1102 | enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; |
| @@ -1133,7 +1112,6 @@ extern void init_window_once (void); | |||
| 1133 | extern void init_window (void); | 1112 | extern void init_window (void); |
| 1134 | extern void syms_of_window (void); | 1113 | extern void syms_of_window (void); |
| 1135 | extern void keys_of_window (void); | 1114 | extern 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); | |||
| 832 | static bool update_menu_bar (struct frame *, bool, bool); | 832 | static bool update_menu_bar (struct frame *, bool, bool); |
| 833 | static bool try_window_reusing_current_matrix (struct window *); | 833 | static bool try_window_reusing_current_matrix (struct window *); |
| 834 | static int try_window_id (struct window *); | 834 | static int try_window_id (struct window *); |
| 835 | static bool display_line (struct it *); | 835 | static bool display_line (struct it *, int); |
| 836 | static int display_mode_lines (struct window *); | 836 | static int display_mode_lines (struct window *); |
| 837 | static int display_mode_line (struct window *, enum face_id, Lisp_Object); | 837 | static int display_mode_line (struct window *, enum face_id, Lisp_Object); |
| 838 | static int display_mode_element (struct it *, int, int, int, Lisp_Object, | 838 | static 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 | ||
| 2530 | static bool | ||
| 2531 | hscrolling_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 | |||
| 2997 | start_display (struct it *it, struct window *w, struct text_pos pos) | 3032 | start_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 | ||
| 10536 | static void ATTRIBUTE_FORMAT_PRINTF (1, 0) | 10577 | static void ATTRIBUTE_FORMAT_PRINTF (1, 0) |
| 10537 | vmessage (const char *m, va_list ap) | 10578 | vmessage (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. */ | ||
| 10592 | void | 10634 | void |
| 10593 | message (const char *m, ...) | 10635 | message (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 | ||
| 11518 | static bool | 11572 | static bool |
| 11519 | mode_line_update_needed (struct window *w) | 11573 | mode_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 | ||
| 20596 | static bool | 20692 | static bool |
| 20597 | display_line (struct it *it) | 20693 | display_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 | |||
| 25580 | static struct glyph_string * | ||
| 25581 | glyph_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 | ||
| 31678 | This variable has the same structure as `mode-line-format', except that | 31977 | This variable has the same structure as `mode-line-format', except that |
| 31679 | the %c and %l constructs are ignored. It is used only on frames for | 31978 | the %c, %C, and %l constructs are ignored. It is used only on frames for |
| 31680 | which no explicit name has been set (see `modify-frame-parameters'). */); | 31979 | which 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, | |||
| 31855 | the frame's other specifications determine how to blink the cursor off. */); | 32154 | the 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. |
| 31860 | If non-nil, windows are automatically scrolled horizontally to make | 32159 | The value `current-line' means the line displaying point in each window |
| 31861 | point visible. */); | 32160 | is automatically scrolled horizontally to make point visible. |
| 31862 | automatic_hscrolling_p = true; | 32161 | Any other non-nil value means all the lines in a window are automatically |
| 32162 | scrolled 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. | ||
| 32359 | The default is to use octal format (\200) whereas hexadecimal (\x80) | ||
| 32360 | may 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; | |||
| 117 | static int dpyinfo_refcount; | 118 | static 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 | |||
| 138 | typedef 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 | |||
| 120 | static struct x_display_info *x_display_info_for_name (Lisp_Object); | 150 | static struct x_display_info *x_display_info_for_name (Lisp_Object); |
| 121 | static void set_up_x_back_buffer (struct frame *f); | 151 | static 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 | */ | ||
| 784 | static void | ||
| 785 | x_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 | */ | ||
| 843 | static void | ||
| 844 | x_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 | */ | ||
| 881 | static void | ||
| 882 | x_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 *) ×tamp, 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 | */ | ||
| 913 | static void | ||
| 914 | x_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 | */ | ||
| 946 | static void | ||
| 947 | x_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! */ |
| 909 | static const struct mouse_cursor_types mouse_cursor_types[] = { | 1149 | static 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 | ||
| 919 | struct mouse_cursor_data { | 1167 | struct 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 | ||
| 3743 | void | 4099 | void |
| 3744 | x_focus_frame (struct frame *f) | 4100 | x_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 | */ | ||
| 5244 | static Lisp_Object | ||
| 5245 | x_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 | |||
| 5278 | DEFUN ("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. | ||
| 5281 | The optional argument TERMINAL specifies which display to ask about. | ||
| 5282 | TERMINAL should be either a frame or a display name (a string). If | ||
| 5283 | omitted or nil, that stands for the selected frame's display. Return | ||
| 5284 | nil if TERMINAL contains no Emacs frame. | ||
| 5285 | |||
| 5286 | As a special case, if TERMINAL is non-nil and specifies a live frame, | ||
| 5287 | return the child frames of that frame in Z (stacking) order. | ||
| 5288 | |||
| 5289 | Frames 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 | */ | ||
| 5312 | static void | ||
| 5313 | x_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 | |||
| 5336 | DEFUN ("x-frame-restack", Fx_frame_restack, Sx_frame_restack, 2, 3, 0, | ||
| 5337 | doc: /* Restack FRAME1 below FRAME2. | ||
| 5338 | This means that if both frames are visible and the display areas of | ||
| 5339 | these frames overlap, FRAME2 (partially) obscures FRAME1. If optional | ||
| 5340 | third argument ABOVE is non-nil, restack FRAME1 above FRAME2. This | ||
| 5341 | means that if both frames are visible and the display areas of these | ||
| 5342 | frames overlap, FRAME1 (partially) obscures FRAME2. | ||
| 5343 | |||
| 5344 | This may be thought of as an atomic action performed in two steps: The | ||
| 5345 | first step removes FRAME1's window-step window from the display. The | ||
| 5346 | second step reinserts FRAME1's window below (above if ABOVE is true) | ||
| 5347 | that of FRAME2. Hence the position of FRAME2 in its display's Z | ||
| 5348 | \(stacking) order relative to all other frames excluding FRAME1 remains | ||
| 5349 | unaltered. | ||
| 5350 | |||
| 5351 | Some 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 | |||
| 4848 | DEFUN ("x-mouse-absolute-pixel-position", Fx_mouse_absolute_pixel_position, | 5370 | DEFUN ("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 | ||
| 6984 | void | 7520 | void |
| @@ -7057,6 +7593,62 @@ This variable takes effect when you create a new frame | |||
| 7057 | or when you set the mouse color. */); | 7593 | or 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. | ||
| 7599 | This variable takes effect when you create a new frame | ||
| 7600 | or 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. | ||
| 7606 | This variable takes effect when you create a new frame | ||
| 7607 | or 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. | ||
| 7613 | This variable takes effect when you create a new frame | ||
| 7614 | or 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. | ||
| 7620 | This variable takes effect when you create a new frame | ||
| 7621 | or 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. | ||
| 7627 | This variable takes effect when you create a new frame | ||
| 7628 | or 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. | ||
| 7634 | This variable takes effect when you create a new frame | ||
| 7635 | or 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. | ||
| 7641 | This variable takes effect when you create a new frame | ||
| 7642 | or 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. | ||
| 7648 | This variable takes effect when you create a new frame | ||
| 7649 | or 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) | |||
| 140 | void | 140 | void |
| 141 | x_menu_set_in_use (bool in_use) | 141 | x_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 | ||
| 1167 | static void | 1207 | static 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 | */ | ||
| 1297 | void | 1304 | void |
| 1298 | x_clear_under_internal_border (struct frame *f) | 1305 | x_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 | |||
| 9992 | x_calc_absolute_position (struct frame *f) | 10167 | x_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 | */ | ||
| 10470 | void | ||
| 10471 | x_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 | */ | ||
| 10501 | void | ||
| 10502 | x_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, | |||
| 11027 | void | 11336 | void |
| 11028 | x_make_frame_visible (struct frame *f) | 11337 | x_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. |
| 12926 | If this variable is t, the GTK build uses the function gtk_window_move | 13273 | If this variable is t (the default), the GTK build uses the function |
| 12927 | to set or store frame positions and disables some time consuming frame | 13274 | gtk_window_move to set or store frame positions and disables some time |
| 12928 | position adjustments. */); | 13275 | consuming 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 | ||
| 1170 | extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); | 1178 | extern void x_set_sticky (struct frame *, Lisp_Object, Lisp_Object); |
| 1179 | extern void x_set_skip_taskbar (struct frame *, Lisp_Object, Lisp_Object); | ||
| 1180 | extern void x_set_z_group (struct frame *, Lisp_Object, Lisp_Object); | ||
| 1171 | extern bool x_wm_supports (struct frame *, Atom); | 1181 | extern bool x_wm_supports (struct frame *, Atom); |
| 1172 | extern void x_wait_for_event (struct frame *, int); | 1182 | extern void x_wait_for_event (struct frame *, int); |
| 1173 | extern void x_clear_under_internal_border (struct frame *f); | 1183 | extern void x_clear_under_internal_border (struct frame *f); |