aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBastien2017-07-03 09:06:29 +0200
committerBastien2017-07-03 09:06:29 +0200
commit5ca1888fe670aee7febd4d42665d7372ab2ffebc (patch)
tree1f7f8d8a7580e556fc83cf3a6aaeec567b33a090 /src
parent20e006ffee41062f1b551a92c24d9edc53cd0f56 (diff)
parent1b4f0a92ff3505ef9a465b9b391756e3a73a6443 (diff)
downloademacs-5ca1888fe670aee7febd4d42665d7372ab2ffebc.tar.gz
emacs-5ca1888fe670aee7febd4d42665d7372ab2ffebc.zip
Merge branch 'master' into scratch/org-mode-merge
Diffstat (limited to 'src')
-rw-r--r--src/charset.c6
-rw-r--r--src/cm.c14
-rw-r--r--src/dispextern.h36
-rw-r--r--src/dispnew.c32
-rw-r--r--src/emacs-module.c6
-rw-r--r--src/emacs-module.h.in3
-rw-r--r--src/emacs.c8
-rw-r--r--src/fileio.c16
-rw-r--r--src/frame.c783
-rw-r--r--src/frame.h63
-rw-r--r--src/gtkutil.c2
-rw-r--r--src/image.c11
-rw-r--r--src/intervals.h12
-rw-r--r--src/keyboard.c71
-rw-r--r--src/lread.c11
-rw-r--r--src/minibuf.c34
-rw-r--r--src/module-env-25.h2
-rw-r--r--src/nsfns.m12
-rw-r--r--src/nsterm.h15
-rw-r--r--src/nsterm.m26
-rw-r--r--src/print.c55
-rw-r--r--src/process.c13
-rw-r--r--src/sysdep.c15
-rw-r--r--src/sysstdio.h41
-rw-r--r--src/systhread.c11
-rw-r--r--src/term.c47
-rw-r--r--src/w32fns.c41
-rw-r--r--src/w32term.c63
-rw-r--r--src/w32term.h8
-rw-r--r--src/window.c213
-rw-r--r--src/window.h200
-rw-r--r--src/xdisp.c190
-rw-r--r--src/xfaces.c2
-rw-r--r--src/xfns.c101
-rw-r--r--src/xterm.c16
-rw-r--r--src/xterm.h8
36 files changed, 1644 insertions, 543 deletions
diff --git a/src/charset.c b/src/charset.c
index 9d15375dd79..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
@@ -198,10 +198,6 @@ static struct
198 198
199#define GET_TEMP_CHARSET_WORK_DECODER(CODE) \ 199#define GET_TEMP_CHARSET_WORK_DECODER(CODE) \
200 (temp_charset_work->table.decoder[(CODE)]) 200 (temp_charset_work->table.decoder[(CODE)])
201
202#ifndef HAVE_GETC_UNLOCKED
203#define getc_unlocked getc
204#endif
205 201
206 202
207/* Set to 1 to warn that a charset map is loaded and thus a buffer 203/* Set to 1 to warn that a charset map is loaded and thus a buffer
diff --git a/src/cm.c b/src/cm.c
index efa50b0f58d..9a90f37445c 100644
--- a/src/cm.c
+++ b/src/cm.c
@@ -19,10 +19,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20 20
21#include <config.h> 21#include <config.h>
22#include <stdio.h>
23 22
24#include "lisp.h" 23#include "lisp.h"
25#include "cm.h" 24#include "cm.h"
25#include "sysstdio.h"
26#include "termchar.h" 26#include "termchar.h"
27#include "tparam.h" 27#include "tparam.h"
28 28
@@ -45,8 +45,8 @@ int
45cmputc (int c) 45cmputc (int c)
46{ 46{
47 if (current_tty->termscript) 47 if (current_tty->termscript)
48 putc (c & 0177, current_tty->termscript); 48 putc_unlocked (c & 0177, current_tty->termscript);
49 putc (c & 0177, current_tty->output); 49 putc_unlocked (c & 0177, current_tty->output);
50 return c; 50 return c;
51} 51}
52 52
@@ -117,11 +117,11 @@ cmcheckmagic (struct tty_display_info *tty)
117 if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1) 117 if (!MagicWrap (tty) || curY (tty) >= FrameRows (tty) - 1)
118 emacs_abort (); 118 emacs_abort ();
119 if (tty->termscript) 119 if (tty->termscript)
120 putc ('\r', tty->termscript); 120 putc_unlocked ('\r', tty->termscript);
121 putc ('\r', tty->output); 121 putc_unlocked ('\r', tty->output);
122 if (tty->termscript) 122 if (tty->termscript)
123 putc ('\n', tty->termscript); 123 putc_unlocked ('\n', tty->termscript);
124 putc ('\n', tty->output); 124 putc_unlocked ('\n', tty->output);
125 curX (tty) = 0; 125 curX (tty) = 0;
126 curY (tty)++; 126 curY (tty)++;
127 } 127 }
diff --git a/src/dispextern.h b/src/dispextern.h
index d1e4715c329..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.
diff --git a/src/dispnew.c b/src/dispnew.c
index 27c69bde831..93ef6a55a2e 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -377,7 +377,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
377 { 377 {
378 window_box (w, ANY_AREA, 0, 0, &window_width, &window_height); 378 window_box (w, ANY_AREA, 0, 0, &window_width, &window_height);
379 379
380 header_line_p = WINDOW_WANTS_HEADER_LINE_P (w); 380 header_line_p = window_wants_header_line (w);
381 header_line_changed_p = header_line_p != matrix->header_line_p; 381 header_line_changed_p = header_line_p != matrix->header_line_p;
382 } 382 }
383 matrix->header_line_p = header_line_p; 383 matrix->header_line_p = header_line_p;
@@ -446,7 +446,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
446 446
447 if (w == NULL 447 if (w == NULL
448 || (row == matrix->rows + dim.height - 1 448 || (row == matrix->rows + dim.height - 1
449 && WINDOW_WANTS_MODELINE_P (w)) 449 && window_wants_mode_line (w))
450 || (row == matrix->rows && matrix->header_line_p)) 450 || (row == matrix->rows && matrix->header_line_p))
451 { 451 {
452 row->glyphs[TEXT_AREA] 452 row->glyphs[TEXT_AREA]
@@ -491,7 +491,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
491 491
492 /* The mode line, if displayed, never has marginal areas. */ 492 /* The mode line, if displayed, never has marginal areas. */
493 if ((row == matrix->rows + dim.height - 1 493 if ((row == matrix->rows + dim.height - 1
494 && !(w && WINDOW_WANTS_MODELINE_P (w))) 494 && !(w && window_wants_mode_line (w)))
495 || (row == matrix->rows && matrix->header_line_p)) 495 || (row == matrix->rows && matrix->header_line_p))
496 { 496 {
497 row->glyphs[TEXT_AREA] 497 row->glyphs[TEXT_AREA]
@@ -570,7 +570,7 @@ adjust_glyph_matrix (struct window *w, struct glyph_matrix *matrix, int x, int y
570 the mode line, if any, since otherwise it will remain 570 the mode line, if any, since otherwise it will remain
571 disabled in the current matrix, and expose events won't 571 disabled in the current matrix, and expose events won't
572 redraw it. */ 572 redraw it. */
573 if (WINDOW_WANTS_MODELINE_P (w)) 573 if (window_wants_mode_line (w))
574 w->update_mode_line = 1; 574 w->update_mode_line = 1;
575 } 575 }
576 else if (matrix == w->desired_matrix) 576 else if (matrix == w->desired_matrix)
@@ -3126,9 +3126,9 @@ update_frame (struct frame *f, bool force_p, bool inhibit_hairy_id_p)
3126 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f)) 3126 if (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
3127 { 3127 {
3128 if (FRAME_TTY (f)->termscript) 3128 if (FRAME_TTY (f)->termscript)
3129 fflush (FRAME_TTY (f)->termscript); 3129 fflush_unlocked (FRAME_TTY (f)->termscript);
3130 if (FRAME_TERMCAP_P (f)) 3130 if (FRAME_TERMCAP_P (f))
3131 fflush (FRAME_TTY (f)->output); 3131 fflush_unlocked (FRAME_TTY (f)->output);
3132 } 3132 }
3133 3133
3134 /* Check window matrices for lost pointers. */ 3134 /* Check window matrices for lost pointers. */
@@ -3181,8 +3181,8 @@ update_frame_with_menu (struct frame *f, int row, int col)
3181 update_end (f); 3181 update_end (f);
3182 3182
3183 if (FRAME_TTY (f)->termscript) 3183 if (FRAME_TTY (f)->termscript)
3184 fflush (FRAME_TTY (f)->termscript); 3184 fflush_unlocked (FRAME_TTY (f)->termscript);
3185 fflush (FRAME_TTY (f)->output); 3185 fflush_unlocked (FRAME_TTY (f)->output);
3186 /* Check window matrices for lost pointers. */ 3186 /* Check window matrices for lost pointers. */
3187#if GLYPH_DEBUG 3187#if GLYPH_DEBUG
3188#if 0 3188#if 0
@@ -4531,7 +4531,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p,
4531 ptrdiff_t outq = __fpending (display_output); 4531 ptrdiff_t outq = __fpending (display_output);
4532 if (outq > 900 4532 if (outq > 900
4533 || (outq > 20 && ((i - 1) % preempt_count == 0))) 4533 || (outq > 20 && ((i - 1) % preempt_count == 0)))
4534 fflush (display_output); 4534 fflush_unlocked (display_output);
4535 } 4535 }
4536 } 4536 }
4537 4537
@@ -5188,7 +5188,7 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p
5188 start position, i.e. it excludes the header-line row, but 5188 start position, i.e. it excludes the header-line row, but
5189 MATRIX_ROW includes the header-line row. Adjust for a possible 5189 MATRIX_ROW includes the header-line row. Adjust for a possible
5190 header-line row. */ 5190 header-line row. */
5191 it_vpos = it.vpos + WINDOW_WANTS_HEADER_LINE_P (w); 5191 it_vpos = it.vpos + window_wants_header_line (w);
5192 if (it_vpos < w->current_matrix->nrows 5192 if (it_vpos < w->current_matrix->nrows
5193 && (row = MATRIX_ROW (w->current_matrix, it_vpos), 5193 && (row = MATRIX_ROW (w->current_matrix, it_vpos),
5194 row->enabled_p)) 5194 row->enabled_p))
@@ -5615,13 +5615,13 @@ when TERMINAL is nil. */)
5615 5615
5616 if (tty->termscript) 5616 if (tty->termscript)
5617 { 5617 {
5618 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); 5618 fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->termscript);
5619 fflush (tty->termscript); 5619 fflush_unlocked (tty->termscript);
5620 } 5620 }
5621 out = tty->output; 5621 out = tty->output;
5622 } 5622 }
5623 fwrite (SDATA (string), 1, SBYTES (string), out); 5623 fwrite_unlocked (SDATA (string), 1, SBYTES (string), out);
5624 fflush (out); 5624 fflush_unlocked (out);
5625 unblock_input (); 5625 unblock_input ();
5626 return Qnil; 5626 return Qnil;
5627} 5627}
@@ -5636,7 +5636,7 @@ terminate any keyboard macro currently executing. */)
5636 if (!NILP (arg)) 5636 if (!NILP (arg))
5637 { 5637 {
5638 if (noninteractive) 5638 if (noninteractive)
5639 putchar (07); 5639 putchar_unlocked (07);
5640 else 5640 else
5641 ring_bell (XFRAME (selected_frame)); 5641 ring_bell (XFRAME (selected_frame));
5642 } 5642 }
@@ -5650,7 +5650,7 @@ void
5650bitch_at_user (void) 5650bitch_at_user (void)
5651{ 5651{
5652 if (noninteractive) 5652 if (noninteractive)
5653 putchar (07); 5653 putchar_unlocked (07);
5654 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */ 5654 else if (!INTERACTIVE) /* Stop executing a keyboard macro. */
5655 { 5655 {
5656 const char *msg 5656 const char *msg
diff --git a/src/emacs-module.c b/src/emacs-module.c
index 2693a4529d6..7b1a402eeff 100644
--- a/src/emacs-module.c
+++ b/src/emacs-module.c
@@ -575,6 +575,8 @@ module_make_string (emacs_env *env, const char *str, ptrdiff_t length)
575 MODULE_FUNCTION_BEGIN (module_nil); 575 MODULE_FUNCTION_BEGIN (module_nil);
576 if (! (0 <= length && length <= STRING_BYTES_BOUND)) 576 if (! (0 <= length && length <= STRING_BYTES_BOUND))
577 xsignal0 (Qoverflow_error); 577 xsignal0 (Qoverflow_error);
578 /* FIXME: AUTO_STRING_WITH_LEN requires STR to be null-terminated,
579 but we shouldn’t require that. */
578 AUTO_STRING_WITH_LEN (lstr, str, length); 580 AUTO_STRING_WITH_LEN (lstr, str, length);
579 return lisp_to_value (env, 581 return lisp_to_value (env,
580 code_convert_string_norecord (lstr, Qutf_8, false)); 582 code_convert_string_norecord (lstr, Qutf_8, false));
@@ -599,7 +601,6 @@ module_get_user_ptr (emacs_env *env, emacs_value uptr)
599static void 601static void
600module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr) 602module_set_user_ptr (emacs_env *env, emacs_value uptr, void *ptr)
601{ 603{
602 /* FIXME: This function should return bool because it can fail. */
603 MODULE_FUNCTION_BEGIN (); 604 MODULE_FUNCTION_BEGIN ();
604 Lisp_Object lisp = value_to_lisp (uptr); 605 Lisp_Object lisp = value_to_lisp (uptr);
605 CHECK_USER_PTR (lisp); 606 CHECK_USER_PTR (lisp);
@@ -619,7 +620,6 @@ static void
619module_set_user_finalizer (emacs_env *env, emacs_value uptr, 620module_set_user_finalizer (emacs_env *env, emacs_value uptr,
620 emacs_finalizer_function fin) 621 emacs_finalizer_function fin)
621{ 622{
622 /* FIXME: This function should return bool because it can fail. */
623 MODULE_FUNCTION_BEGIN (); 623 MODULE_FUNCTION_BEGIN ();
624 Lisp_Object lisp = value_to_lisp (uptr); 624 Lisp_Object lisp = value_to_lisp (uptr);
625 CHECK_USER_PTR (lisp); 625 CHECK_USER_PTR (lisp);
@@ -638,7 +638,6 @@ check_vec_index (Lisp_Object lvec, ptrdiff_t i)
638static void 638static void
639module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val) 639module_vec_set (emacs_env *env, emacs_value vec, ptrdiff_t i, emacs_value val)
640{ 640{
641 /* FIXME: This function should return bool because it can fail. */
642 MODULE_FUNCTION_BEGIN (); 641 MODULE_FUNCTION_BEGIN ();
643 Lisp_Object lvec = value_to_lisp (vec); 642 Lisp_Object lvec = value_to_lisp (vec);
644 check_vec_index (lvec, i); 643 check_vec_index (lvec, i);
@@ -657,7 +656,6 @@ module_vec_get (emacs_env *env, emacs_value vec, ptrdiff_t i)
657static ptrdiff_t 656static ptrdiff_t
658module_vec_size (emacs_env *env, emacs_value vec) 657module_vec_size (emacs_env *env, emacs_value vec)
659{ 658{
660 /* FIXME: Return a sentinel value (e.g., -1) on error. */
661 MODULE_FUNCTION_BEGIN (0); 659 MODULE_FUNCTION_BEGIN (0);
662 Lisp_Object lvec = value_to_lisp (vec); 660 Lisp_Object lvec = value_to_lisp (vec);
663 CHECK_VECTOR (lvec); 661 CHECK_VECTOR (lvec);
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index 339234fdb51..40b6448d27e 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -80,7 +80,7 @@ enum emacs_funcall_exit
80 emacs_funcall_exit_signal = 1, 80 emacs_funcall_exit_signal = 1,
81 81
82 /* Function has exit using `throw'. */ 82 /* Function has exit using `throw'. */
83 emacs_funcall_exit_throw = 2, 83 emacs_funcall_exit_throw = 2
84}; 84};
85 85
86struct emacs_env_25 86struct emacs_env_25
@@ -97,6 +97,7 @@ struct emacs_env_26
97 97
98/* Every module should define a function as follows. */ 98/* Every module should define a function as follows. */
99extern int emacs_module_init (struct emacs_runtime *ert) 99extern int emacs_module_init (struct emacs_runtime *ert)
100 EMACS_NOEXCEPT
100 EMACS_ATTRIBUTE_NONNULL(1); 101 EMACS_ATTRIBUTE_NONNULL(1);
101 102
102#ifdef __cplusplus 103#ifdef __cplusplus
diff --git a/src/emacs.c b/src/emacs.c
index da8df1bf1c7..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>
@@ -885,7 +885,7 @@ main (int argc, char **argv)
885 } 885 }
886#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */ 886#endif /* HAVE_SETRLIMIT and RLIMIT_STACK and not CYGWIN */
887 887
888 clearerr (stdin); 888 clearerr_unlocked (stdin);
889 889
890 emacs_backtrace (-1); 890 emacs_backtrace (-1);
891 891
@@ -983,7 +983,7 @@ main (int argc, char **argv)
983 int i; 983 int i;
984 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]); 984 printf ("Usage: %s [OPTION-OR-FILENAME]...\n", argv[0]);
985 for (i = 0; i < ARRAYELTS (usage_message); i++) 985 for (i = 0; i < ARRAYELTS (usage_message); i++)
986 fputs (usage_message[i], stdout); 986 fputs_unlocked (usage_message[i], stdout);
987 exit (0); 987 exit (0);
988 } 988 }
989 989
@@ -2197,7 +2197,7 @@ You must run Emacs in batch mode in order to dump it. */)
2197 } 2197 }
2198#endif 2198#endif
2199 2199
2200 fflush (stdout); 2200 fflush_unlocked (stdout);
2201 /* Tell malloc where start of impure now is. */ 2201 /* Tell malloc where start of impure now is. */
2202 /* Also arrange for warnings when nearly out of space. */ 2202 /* Also arrange for warnings when nearly out of space. */
2203#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC 2203#if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
diff --git a/src/fileio.c b/src/fileio.c
index cb070029a9b..a57d50b24e0 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5643,14 +5643,12 @@ A non-nil CURRENT-ONLY argument means save only current buffer. */)
5643 { 5643 {
5644 block_input (); 5644 block_input ();
5645 if (!NILP (BVAR (b, filename))) 5645 if (!NILP (BVAR (b, filename)))
5646 { 5646 fwrite_unlocked (SDATA (BVAR (b, filename)), 1,
5647 fwrite (SDATA (BVAR (b, filename)), 1, 5647 SBYTES (BVAR (b, filename)), stream);
5648 SBYTES (BVAR (b, filename)), stream); 5648 putc_unlocked ('\n', stream);
5649 } 5649 fwrite_unlocked (SDATA (BVAR (b, auto_save_file_name)), 1,
5650 putc ('\n', stream); 5650 SBYTES (BVAR (b, auto_save_file_name)), stream);
5651 fwrite (SDATA (BVAR (b, auto_save_file_name)), 1, 5651 putc_unlocked ('\n', stream);
5652 SBYTES (BVAR (b, auto_save_file_name)), stream);
5653 putc ('\n', stream);
5654 unblock_input (); 5652 unblock_input ();
5655 } 5653 }
5656 5654
@@ -5841,7 +5839,7 @@ effect except for flushing STREAM's data. */)
5841 5839
5842 binmode = NILP (mode) ? O_TEXT : O_BINARY; 5840 binmode = NILP (mode) ? O_TEXT : O_BINARY;
5843 if (fp != stdin) 5841 if (fp != stdin)
5844 fflush (fp); 5842 fflush_unlocked (fp);
5845 5843
5846 return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil; 5844 return (set_binary_mode (fileno (fp), binmode) == O_BINARY) ? Qt : Qnil;
5847} 5845}
diff --git a/src/frame.c b/src/frame.c
index 4d17a071dc7..1e5e4bbdb48 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -328,8 +328,8 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
328 * frame_windows_min_size: 328 * frame_windows_min_size:
329 * 329 *
330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil) 330 * Return the minimum number of lines (columns if HORIZONTAL is non-nil)
331 * of FRAME. If PIXELWISE is non-nil, return the minimum height (width) 331 * of FRAME. If PIXELWISE is non-nil, return the minimum inner height
332 * in pixels. 332 * (width) of FRAME in pixels.
333 * 333 *
334 * This value is calculated by the function `frame-windows-min-size' in 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 335 * window.el unless the `min-height' (`min-width' if HORIZONTAL is
@@ -341,7 +341,7 @@ DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
341 * of `window-min-height' (`window-min-width' if HORIZONTAL is non-nil). 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. 342 * With IGNORE non-nil the values of these variables are ignored.
343 * 343 *
344 * In either case never return a value less than 1. 344 * In either case, never return a value less than 1.
345 */ 345 */
346static int 346static int
347frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal, 347frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
@@ -373,46 +373,173 @@ frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
373} 373}
374 374
375 375
376/* Make sure windows sizes of frame F are OK. new_width and new_height 376#ifdef HAVE_WINDOW_SYSTEM
377 are in pixels. A value of -1 means no change is requested for that 377/**
378 size (but the frame may still have to be resized to accommodate 378 * keep_ratio:
379 windows with their minimum sizes). This can either issue a request 379 *
380 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
381 frame internally (via resize_frame_windows) or do nothing at all. 381 * frame P got resized. OLD_WIDTH, OLD_HEIGHT specifies the old native
382 * size of F's parent, NEW_WIDTH and NEW_HEIGHT its new size.
383 *
384 * Adjust F's width if F's 'keep_ratio' parameter is non-nil and, if
385 * it is a cons, its car is not 'height-only'. Adjust F's height if F's
386 * 'keep_ratio' parameter is non-nil and, if it is a cons, its car
387 * is not 'width-only'.
388 *
389 * Adjust F's left position if F's 'keep_ratio' parameter is non-nil
390 * and, if its is a cons, its cdr is non-nil and not 'top-only'. Adjust
391 * F's top position if F's 'keep_ratio' parameter is non-nil and, if
392 * its is a cons, its cdr is non-nil and not 'left-only'.
393 *
394 * Note that when positional adjustment is requested but the size of F
395 * should remain unaltered in the corresponding direction, this routine
396 * tries to constrain F to its parent frame - something which usually
397 * happens when the parent frame shrinks. This means, however, that
398 * when the parent frame is re-enlarged later, the child's original
399 * position will not get restored to its pre-shrinking value.
400 *
401 * This routine is currently useful for child frames only. It might be
402 * eventually useful when moving non-child frames between monitors with
403 * different resolutions.
404 */
405static void
406keep_ratio (struct frame *f, struct frame *p, int old_width, int old_height,
407 int new_width, int new_height)
408{
409 Lisp_Object keep_ratio = get_frame_param (f, Qkeep_ratio);
410
411
412 if (!NILP (keep_ratio))
413 {
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;
417
418 if (!CONSP (keep_ratio) || !NILP (Fcdr (keep_ratio)))
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);
382 425
383 The argument INHIBIT can assume the following values: 426 if (CONSP (keep_ratio)
427 && (NILP (Fcar (keep_ratio))
428 || EQ (Fcar (keep_ratio), Qheight_only))
429 && p->pixel_width - f->pixel_width < pos_x)
430 {
431 int p_f_width = p->pixel_width - f->pixel_width;
384 432
385 0 means to unconditionally call x_set_window_size even if sizes 433 if (p_f_width <= 0)
386 apparently do not change. Fx_create_frame uses this to pass the 434 pos_x = 0;
387 initial size to the window manager. 435 else
436 pos_x = (int)(p_f_width * width_factor * 0.5 + 0.5);
437 }
388 438
389 1 means to call x_set_window_size if the outer frame size really 439 f->left_pos = pos_x;
390 changes. Fset_frame_size, Fset_frame_height, ... use this. 440 }
391 441
392 2 means to call x_set_window_size provided frame_inhibit_resize 442 if (CONSP (keep_ratio) && EQ (Fcdr (keep_ratio), Qleft_only))
393 allows it. The menu and tool bar code use this ("3" won't work 443 pos_y = f->top_pos;
394 here in general because menu and tool bar are often not counted in 444 else
395 the frame's text height). 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;
396 459
397 3 means call x_set_window_size if window minimum sizes must be 460 if (p_f_height <= 0)
398 preserved or frame_inhibit_resize allows it. x_set_left_fringe, 461 pos_y = 0;
399 x_set_scroll_bar_width, x_new_font ... use (or should use) this. 462 else
463 pos_y = (int)(p_f_height * height_factor * 0.5 + 0.5);
464 }
400 465
401 4 means call x_set_window_size only if window minimum sizes must be 466 f->top_pos = pos_y;
402 preserved. x_set_right_divider_width, x_set_border_width and the 467 }
403 code responsible for wrapping the tool bar use this.
404 468
405 5 means to never call x_set_window_size. change_frame_size uses 469 x_set_offset (f, pos_x, pos_y, -1);
406 this. 470 }
407 471
408 Note that even when x_set_window_size is not called, individual 472 if (!CONSP (keep_ratio) || !NILP (Fcar (keep_ratio)))
409 windows may have to be resized (via `window--sanitize-window-sizes') 473 {
410 in order to support minimum size constraints. 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 }
411 481
412 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the 482 if (CONSP (keep_ratio) && EQ (Fcar (keep_ratio), Qwidth_only))
413 symbol of the parameter changed (like `menu-bar-lines', `font', ...). 483 pixel_height = -1;
414 This is passed on to frame_inhibit_resize to let the latter decide on 484 else
415 a case-by-case basis whether the frame may be resized externally. */ 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
496
497
498/**
499 * adjust_frame_size:
500 *
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 */
416void 543void
417adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, 544adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
418 bool pretend, Lisp_Object parameter) 545 bool pretend, Lisp_Object parameter)
@@ -636,6 +763,18 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
636 || new_pixel_height != old_pixel_height); 763 || new_pixel_height != old_pixel_height);
637 764
638 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
639} 778}
640 779
641/* Allocate basically initialized frame. */ 780/* Allocate basically initialized frame. */
@@ -684,6 +823,7 @@ make_frame (bool mini_p)
684 f->horizontal_scroll_bars = false; 823 f->horizontal_scroll_bars = false;
685 f->want_fullscreen = FULLSCREEN_NONE; 824 f->want_fullscreen = FULLSCREEN_NONE;
686 f->undecorated = false; 825 f->undecorated = false;
826 f->no_special_glyphs = false;
687#ifndef HAVE_NTGUI 827#ifndef HAVE_NTGUI
688 f->override_redirect = false; 828 f->override_redirect = false;
689#endif 829#endif
@@ -2004,8 +2144,101 @@ The functions are run with one argument, the frame to be deleted. */)
2004{ 2144{
2005 return delete_frame (frame, !NILP (force) ? Qt : Qnil); 2145 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
2006} 2146}
2007
2008 2147
2148#ifdef HAVE_WINDOW_SYSTEM
2149/**
2150 * frame_internal_border_part:
2151 *
2152 * Return part of internal border the coordinates X and Y relative to
2153 * frame F are on. Return nil if the coordinates are not on the
2154 * internal border of F.
2155 *
2156 * Return one of INTERNAL_BORDER_LEFT_EDGE, INTERNAL_BORDER_TOP_EDGE,
2157 * INTERNAL_BORDER_RIGHT_EDGE or INTERNAL_BORDER_BOTTOM_EDGE when the
2158 * mouse cursor is on the corresponding border with an offset of at
2159 * least one canonical character height from that border's edges.
2160 *
2161 * If no border part could be found this way, return one of
2162 * INTERNAL_BORDER_TOP_LEFT_CORNER, INTERNAL_BORDER_TOP_RIGHT_CORNER,
2163 * INTERNAL_BORDER_BOTTOM_LEFT_CORNER or
2164 * INTERNAL_BORDER_BOTTOM_RIGHT_CORNER to indicate that the mouse is in
2165 * one of the corresponding corners. This means that for very small
2166 * frames an `edge' return value is preferred.
2167 */
2168enum internal_border_part
2169frame_internal_border_part (struct frame *f, int x, int y)
2170{
2171 int border = FRAME_INTERNAL_BORDER_WIDTH (f);
2172 int offset = FRAME_LINE_HEIGHT (f);
2173 int width = FRAME_PIXEL_WIDTH (f);
2174 int height = FRAME_PIXEL_HEIGHT (f);
2175 enum internal_border_part part = INTERNAL_BORDER_NONE;
2176
2177 if (offset < border)
2178 /* For very wide borders make offset at least as large as
2179 border. */
2180 offset = border;
2181
2182 if (offset < x && x < width - offset)
2183 /* Top or bottom border. */
2184 {
2185 if (0 <= y && y <= border)
2186 part = INTERNAL_BORDER_TOP_EDGE;
2187 else if (height - border <= y && y <= height)
2188 part = INTERNAL_BORDER_BOTTOM_EDGE;
2189 }
2190 else if (offset < y && y < height - offset)
2191 /* Left or right border. */
2192 {
2193 if (0 <= x && x <= border)
2194 part = INTERNAL_BORDER_LEFT_EDGE;
2195 else if (width - border <= x && x <= width)
2196 part = INTERNAL_BORDER_RIGHT_EDGE;
2197 }
2198 else
2199 {
2200 /* An edge. */
2201 int half_width = width / 2;
2202 int half_height = height / 2;
2203
2204 if (0 <= x && x <= border)
2205 {
2206 /* A left edge. */
2207 if (0 <= y && y <= half_height)
2208 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2209 else if (half_height < y && y <= height)
2210 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2211 }
2212 else if (width - border <= x && x <= width)
2213 {
2214 /* A right edge. */
2215 if (0 <= y && y <= half_height)
2216 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2217 else if (half_height < y && y <= height)
2218 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2219 }
2220 else if (0 <= y && y <= border)
2221 {
2222 /* A top edge. */
2223 if (0 <= x && x <= half_width)
2224 part = INTERNAL_BORDER_TOP_LEFT_CORNER;
2225 else if (half_width < x && x <= width)
2226 part = INTERNAL_BORDER_TOP_RIGHT_CORNER;
2227 }
2228 else if (height - border <= y && y <= height)
2229 {
2230 /* A bottom edge. */
2231 if (0 <= x && x <= half_width)
2232 part = INTERNAL_BORDER_BOTTOM_LEFT_CORNER;
2233 else if (half_width < x && x <= width)
2234 part = INTERNAL_BORDER_BOTTOM_RIGHT_CORNER;
2235 }
2236 }
2237
2238 return part;
2239}
2240#endif
2241
2009/* Return mouse position in character cell units. */ 2242/* Return mouse position in character cell units. */
2010 2243
2011DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0, 2244DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
@@ -2962,49 +3195,47 @@ For a terminal screen, the value is always 1. */)
2962 return make_number (1); 3195 return make_number (1);
2963} 3196}
2964 3197
2965DEFUN ("frame-pixel-height", Fframe_pixel_height, 3198DEFUN ("frame-native-width", Fframe_native_width,
2966 Sframe_pixel_height, 0, 1, 0, 3199 Sframe_native_width, 0, 1, 0,
2967 doc: /* Return a FRAME's height in pixels. 3200 doc: /* Return FRAME's native width in pixels.
2968If FRAME is omitted or nil, the selected frame is used. The exact value 3201For a terminal frame, the result really gives the width in characters.
2969of the result depends on the window-system and toolkit in use: 3202If FRAME is omitted or nil, the selected frame is used. */)
2970
2971In the Gtk+ version of Emacs, it includes only any window (including
2972the minibuffer or echo area), mode line, and header line. It does not
2973include the tool bar or menu bar.
2974
2975With other graphical versions, it also includes the tool bar and the
2976menu bar.
2977
2978For a text terminal, it includes the menu bar. In this case, the
2979result is really in characters rather than pixels (i.e., is identical
2980to `frame-height'). */)
2981 (Lisp_Object frame) 3203 (Lisp_Object frame)
2982{ 3204{
2983 struct frame *f = decode_any_frame (frame); 3205 struct frame *f = decode_any_frame (frame);
2984 3206
2985#ifdef HAVE_WINDOW_SYSTEM 3207#ifdef HAVE_WINDOW_SYSTEM
2986 if (FRAME_WINDOW_P (f)) 3208 if (FRAME_WINDOW_P (f))
2987 return make_number (FRAME_PIXEL_HEIGHT (f)); 3209 return make_number (FRAME_PIXEL_WIDTH (f));
2988 else 3210 else
2989#endif 3211#endif
2990 return make_number (FRAME_TOTAL_LINES (f)); 3212 return make_number (FRAME_TOTAL_COLS (f));
2991} 3213}
2992 3214
2993DEFUN ("frame-pixel-width", Fframe_pixel_width, 3215DEFUN ("frame-native-height", Fframe_native_height,
2994 Sframe_pixel_width, 0, 1, 0, 3216 Sframe_native_height, 0, 1, 0,
2995 doc: /* Return FRAME's width in pixels. 3217 doc: /* Return FRAME's native height in pixels.
2996For a terminal frame, the result really gives the width in characters. 3218If FRAME is omitted or nil, the selected frame is used. The exact value
2997If FRAME is omitted or nil, the selected frame is used. */) 3219of the result depends on the window-system and toolkit in use:
3220
3221In the Gtk+ and NS versions, it includes only any window (including the
3222minibuffer or echo area), mode line, and header line. It does not
3223include the tool bar or menu bar. With other graphical versions, it may
3224also include the tool bar and the menu bar.
3225
3226For a text terminal, it includes the menu bar. In this case, the
3227result is really in characters rather than pixels (i.e., is identical
3228to `frame-height'). */)
2998 (Lisp_Object frame) 3229 (Lisp_Object frame)
2999{ 3230{
3000 struct frame *f = decode_any_frame (frame); 3231 struct frame *f = decode_any_frame (frame);
3001 3232
3002#ifdef HAVE_WINDOW_SYSTEM 3233#ifdef HAVE_WINDOW_SYSTEM
3003 if (FRAME_WINDOW_P (f)) 3234 if (FRAME_WINDOW_P (f))
3004 return make_number (FRAME_PIXEL_WIDTH (f)); 3235 return make_number (FRAME_PIXEL_HEIGHT (f));
3005 else 3236 else
3006#endif 3237#endif
3007 return make_number (FRAME_TOTAL_COLS (f)); 3238 return make_number (FRAME_TOTAL_LINES (f));
3008} 3239}
3009 3240
3010DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width, 3241DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
@@ -3087,8 +3318,8 @@ DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
3087 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame))); 3318 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
3088} 3319}
3089 3320
3090DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0, 3321DEFUN ("frame-internal-border-width", Fframe_internal_border_width, Sframe_internal_border_width, 0, 1, 0,
3091 doc: /* Return border width of FRAME in pixels. */) 3322 doc: /* Return width of FRAME's internal border in pixels. */)
3092 (Lisp_Object frame) 3323 (Lisp_Object frame)
3093{ 3324{
3094 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame))); 3325 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
@@ -3224,7 +3455,6 @@ bottom edge of FRAME's display. */)
3224 3455
3225 return Qt; 3456 return Qt;
3226} 3457}
3227
3228 3458
3229/*********************************************************************** 3459/***********************************************************************
3230 Frame Parameters 3460 Frame Parameters
@@ -3289,10 +3519,193 @@ static const struct frame_parm_table frame_parms[] =
3289 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)}, 3519 {"no-accept-focus", SYMBOL_INDEX (Qno_accept_focus)},
3290 {"z-group", SYMBOL_INDEX (Qz_group)}, 3520 {"z-group", SYMBOL_INDEX (Qz_group)},
3291 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)}, 3521 {"override-redirect", SYMBOL_INDEX (Qoverride_redirect)},
3522 {"no-special-glyphs", SYMBOL_INDEX (Qno_special_glyphs)},
3292}; 3523};
3293 3524
3294#ifdef HAVE_WINDOW_SYSTEM 3525#ifdef HAVE_WINDOW_SYSTEM
3295 3526
3527/* Enumeration type for switch in frame_float. */
3528enum frame_float_type
3529{
3530 FRAME_FLOAT_WIDTH,
3531 FRAME_FLOAT_HEIGHT,
3532 FRAME_FLOAT_LEFT,
3533 FRAME_FLOAT_TOP
3534};
3535
3536/**
3537 * frame_float:
3538 *
3539 * Process the value VAL of the float type frame parameter 'width',
3540 * 'height', 'left', or 'top' specified via a frame_float_type
3541 * enumeration type WHAT for frame F. Such parameters relate the outer
3542 * size or position of F to the size of the F's display or parent frame
3543 * which have to be both available in some way.
3544 *
3545 * The return value is a size or position value in pixels. VAL must be
3546 * in the range 0.0 to 1.0 where a width/height of 0.0 means to return 0
3547 * and 1.0 means to return the full width/height of the display/parent.
3548 * For positions, 0.0 means position in the left/top corner of the
3549 * display/parent while 1.0 means to position at the right/bottom corner
3550 * of the display/parent frame.
3551 *
3552 * Set PARENT_DONE and OUTER_DONE to avoid recalculation of the outer
3553 * size or parent or display attributes when more float parameters are
3554 * calculated in a row: -1 means not processed yet, 0 means processing
3555 * failed, 1 means processing succeeded.
3556 *
3557 * Return DEFAULT_VALUE when processing fails for whatever reason with
3558 * one exception: When calculating F's outer edges fails (probably
3559 * because F has not been created yet) return the difference between F's
3560 * native and text size.
3561 */
3562static int
3563frame_float (struct frame *f, Lisp_Object val, enum frame_float_type what,
3564 int *parent_done, int *outer_done, int default_value)
3565{
3566 double d_val = XFLOAT_DATA (val);
3567
3568 if (d_val < 0.0 || d_val > 1.0)
3569 /* Invalid VAL. */
3570 return default_value;
3571 else
3572 {
3573 static unsigned parent_width, parent_height;
3574 static int parent_left, parent_top;
3575 static unsigned outer_minus_text_width, outer_minus_text_height;
3576 struct frame *p = FRAME_PARENT_FRAME (f);
3577
3578 if (*parent_done == 1)
3579 ;
3580 else if (p)
3581 {
3582 parent_width = FRAME_PIXEL_WIDTH (p);
3583 parent_height = FRAME_PIXEL_HEIGHT (p);
3584 *parent_done = 1;
3585 }
3586 else
3587 {
3588 if (*parent_done == 0)
3589 /* No workarea available. */
3590 return default_value;
3591 else if (*parent_done == -1)
3592 {
3593 Lisp_Object monitor_attributes;
3594 Lisp_Object workarea;
3595 Lisp_Object frame;
3596
3597 XSETFRAME (frame, f);
3598 monitor_attributes = Fcar (call1 (Qdisplay_monitor_attributes_list, frame));
3599 if (NILP (monitor_attributes))
3600 {
3601 /* No monitor attributes available. */
3602 *parent_done = 0;
3603
3604 return default_value;
3605 }
3606
3607 workarea = Fcdr (Fassq (Qworkarea, monitor_attributes));
3608 if (NILP (workarea))
3609 {
3610 /* No workarea available. */
3611 *parent_done = 0;
3612
3613 return default_value;
3614 }
3615
3616 /* Workarea available. */
3617 parent_left = XINT (Fnth (make_number (0), workarea));
3618 parent_top = XINT (Fnth (make_number (1), workarea));
3619 parent_width = XINT (Fnth (make_number (2), workarea));
3620 parent_height = XINT (Fnth (make_number (3), workarea));
3621 *parent_done = 1;
3622 }
3623 }
3624
3625 if (*outer_done == 1)
3626 ;
3627 else if (FRAME_UNDECORATED (f))
3628 {
3629 outer_minus_text_width
3630 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3631 outer_minus_text_height
3632 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3633 *outer_done = 1;
3634 }
3635 else if (*outer_done == 0)
3636 /* No outer size available. */
3637 return default_value;
3638 else if (*outer_done == -1)
3639 {
3640 Lisp_Object frame, outer_edges;
3641
3642 XSETFRAME (frame, f);
3643 outer_edges = call2 (Qframe_edges, frame, Qouter_edges);
3644
3645 if (!NILP (outer_edges))
3646 {
3647 outer_minus_text_width
3648 = (XINT (Fnth (make_number (2), outer_edges))
3649 - XINT (Fnth (make_number (0), outer_edges))
3650 - FRAME_TEXT_WIDTH (f));
3651 outer_minus_text_height
3652 = (XINT (Fnth (make_number (3), outer_edges))
3653 - XINT (Fnth (make_number (1), outer_edges))
3654 - FRAME_TEXT_HEIGHT (f));
3655 }
3656 else
3657 {
3658 /* If we can't get any outer edges, proceed as if the frame
3659 were undecorated. */
3660 outer_minus_text_width
3661 = FRAME_PIXEL_WIDTH (f) - FRAME_TEXT_WIDTH (f);
3662 outer_minus_text_height
3663 = FRAME_PIXEL_HEIGHT (f) - FRAME_TEXT_HEIGHT (f);
3664 }
3665
3666 *outer_done = 1;
3667 }
3668
3669 switch (what)
3670 {
3671 case FRAME_FLOAT_WIDTH:
3672 return parent_width * d_val - outer_minus_text_width;
3673
3674 case FRAME_FLOAT_HEIGHT:
3675 return parent_height * d_val - outer_minus_text_height;
3676
3677 case FRAME_FLOAT_LEFT:
3678 {
3679 int rest_width = (parent_width
3680 - FRAME_TEXT_WIDTH (f)
3681 - outer_minus_text_width);
3682
3683 if (p)
3684 return (rest_width <= 0 ? 0 : d_val * rest_width);
3685 else
3686 return (rest_width <= 0
3687 ? parent_left
3688 : parent_left + d_val * rest_width);
3689 }
3690 case FRAME_FLOAT_TOP:
3691 {
3692 int rest_height = (parent_height
3693 - FRAME_TEXT_HEIGHT (f)
3694 - outer_minus_text_height);
3695
3696 if (p)
3697 return (rest_height <= 0 ? 0 : d_val * rest_height);
3698 else
3699 return (rest_height <= 0
3700 ? parent_top
3701 : parent_top + d_val * rest_height);
3702 }
3703 default:
3704 emacs_abort ();
3705 }
3706 }
3707}
3708
3296/* Change the parameters of frame F as specified by ALIST. 3709/* Change the parameters of frame F as specified by ALIST.
3297 If a parameter is not specially recognized, do nothing special; 3710 If a parameter is not specially recognized, do nothing special;
3298 otherwise call the `x_set_...' function for that parameter. 3711 otherwise call the `x_set_...' function for that parameter.
@@ -3302,7 +3715,8 @@ static const struct frame_parm_table frame_parms[] =
3302void 3715void
3303x_set_frame_parameters (struct frame *f, Lisp_Object alist) 3716x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3304{ 3717{
3305 Lisp_Object tail; 3718 Lisp_Object tail, frame;
3719
3306 3720
3307 /* 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
3308 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
@@ -3327,7 +3741,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3327#ifdef HAVE_X_WINDOWS 3741#ifdef HAVE_X_WINDOWS
3328 bool icon_left_no_change = 0, icon_top_no_change = 0; 3742 bool icon_left_no_change = 0, icon_top_no_change = 0;
3329#endif 3743#endif
3744 int parent_done = -1, outer_done = -1;
3330 3745
3746 XSETFRAME (frame, f);
3331 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail)) 3747 for (size = 0, tail = alist; CONSP (tail); tail = XCDR (tail))
3332 size++; 3748 size++;
3333 CHECK_LIST_END (tail, alist); 3749 CHECK_LIST_END (tail, alist);
@@ -3388,6 +3804,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3388 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) 3804 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3389 && RANGED_INTEGERP (0, XCDR (val), INT_MAX)) 3805 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3390 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);
3391 } 3810 }
3392 else if (EQ (prop, Qheight)) 3811 else if (EQ (prop, Qheight))
3393 { 3812 {
@@ -3396,6 +3815,9 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3396 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels) 3815 else if (CONSP (val) && EQ (XCAR (val), Qtext_pixels)
3397 && RANGED_INTEGERP (0, XCDR (val), INT_MAX)) 3816 && RANGED_INTEGERP (0, XCDR (val), INT_MAX))
3398 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);
3399 } 3821 }
3400 else if (EQ (prop, Qtop)) 3822 else if (EQ (prop, Qtop))
3401 top = val; 3823 top = val;
@@ -3472,105 +3894,100 @@ x_set_frame_parameters (struct frame *f, Lisp_Object alist)
3472 Don't set these parameters unless they actually differ from the 3894 Don't set these parameters unless they actually differ from the
3473 window's current parameters; the window may not actually exist 3895 window's current parameters; the window may not actually exist
3474 yet. */ 3896 yet. */
3475 { 3897 if ((width != -1 && width != FRAME_TEXT_WIDTH (f))
3476 Lisp_Object frame; 3898 || (height != -1 && height != FRAME_TEXT_HEIGHT (f)))
3477 3899 /* We could consider checking f->after_make_frame here, but I
3478 XSETFRAME (frame, f); 3900 don't have the faintest idea why the following is needed at
3479 3901 all. With the old setting it can get a Heisenbug when
3480 if ((width != -1 && width != FRAME_TEXT_WIDTH (f)) 3902 EmacsFrameResize intermittently provokes a delayed
3481 || (height != -1 && height != FRAME_TEXT_HEIGHT (f))) 3903 change_frame_size in the middle of adjust_frame_size. */
3482 /* We could consider checking f->after_make_frame here, but I 3904 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/
3483 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);
3484 all. With the old setting it can get a Heisenbug when 3906
3485 EmacsFrameResize intermittently provokes a delayed 3907 if ((!NILP (left) || !NILP (top))
3486 change_frame_size in the middle of adjust_frame_size. */ 3908 && ! (left_no_change && top_no_change)
3487 /** || (f->can_x_set_window_size && (f->new_height || f->new_width))) **/ 3909 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3488 adjust_frame_size (f, width, height, 1, 0, Qx_set_frame_parameters); 3910 && NUMBERP (top) && XINT (top) == f->top_pos))
3489 3911 {
3490 if ((!NILP (left) || !NILP (top)) 3912 int leftpos = 0;
3491 && ! (left_no_change && top_no_change) 3913 int toppos = 0;
3492 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3493 && NUMBERP (top) && XINT (top) == f->top_pos))
3494 {
3495 int leftpos = 0;
3496 int toppos = 0;
3497 3914
3498 /* Record the signs. */ 3915 /* Record the signs. */
3499 f->size_hint_flags &= ~ (XNegative | YNegative); 3916 f->size_hint_flags &= ~ (XNegative | YNegative);
3500 if (EQ (left, Qminus)) 3917 if (EQ (left, Qminus))
3501 f->size_hint_flags |= XNegative; 3918 f->size_hint_flags |= XNegative;
3502 else if (TYPE_RANGED_INTEGERP (int, left)) 3919 else if (TYPE_RANGED_INTEGERP (int, left))
3503 { 3920 {
3504 leftpos = XINT (left); 3921 leftpos = XINT (left);
3505 if (leftpos < 0) 3922 if (leftpos < 0)
3506 f->size_hint_flags |= XNegative;
3507 }
3508 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3509 && CONSP (XCDR (left))
3510 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3511 {
3512 leftpos = - XINT (XCAR (XCDR (left)));
3513 f->size_hint_flags |= XNegative; 3923 f->size_hint_flags |= XNegative;
3514 } 3924 }
3515 else if (CONSP (left) && EQ (XCAR (left), Qplus) 3925 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3516 && CONSP (XCDR (left)) 3926 && CONSP (XCDR (left))
3517 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left)))) 3927 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3518 { 3928 {
3519 leftpos = XINT (XCAR (XCDR (left))); 3929 leftpos = - XINT (XCAR (XCDR (left)));
3520 } 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);
3521 3939
3522 if (EQ (top, Qminus)) 3940 if (EQ (top, Qminus))
3523 f->size_hint_flags |= YNegative; 3941 f->size_hint_flags |= YNegative;
3524 else if (TYPE_RANGED_INTEGERP (int, top)) 3942 else if (TYPE_RANGED_INTEGERP (int, top))
3525 { 3943 {
3526 toppos = XINT (top); 3944 toppos = XINT (top);
3527 if (toppos < 0) 3945 if (toppos < 0)
3528 f->size_hint_flags |= YNegative;
3529 }
3530 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3531 && CONSP (XCDR (top))
3532 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3533 {
3534 toppos = - XINT (XCAR (XCDR (top)));
3535 f->size_hint_flags |= YNegative; 3946 f->size_hint_flags |= YNegative;
3536 } 3947 }
3537 else if (CONSP (top) && EQ (XCAR (top), Qplus) 3948 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3538 && CONSP (XCDR (top)) 3949 && CONSP (XCDR (top))
3539 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top)))) 3950 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3540 { 3951 {
3541 toppos = XINT (XCAR (XCDR (top))); 3952 toppos = - XINT (XCAR (XCDR (top)));
3542 } 3953 f->size_hint_flags |= YNegative;
3543 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);
3544 3962
3545 /* Store the numeric value of the position. */ 3963 /* Store the numeric value of the position. */
3546 f->top_pos = toppos; 3964 f->top_pos = toppos;
3547 f->left_pos = leftpos; 3965 f->left_pos = leftpos;
3548 3966
3549 f->win_gravity = NorthWestGravity; 3967 f->win_gravity = NorthWestGravity;
3550 3968
3551 /* Actually set that position, and convert to absolute. */ 3969 /* Actually set that position, and convert to absolute. */
3552 x_set_offset (f, leftpos, toppos, -1); 3970 x_set_offset (f, leftpos, toppos, -1);
3553 } 3971 }
3554 3972
3555 if (fullscreen_change) 3973 if (fullscreen_change)
3556 { 3974 {
3557 Lisp_Object old_value = get_frame_param (f, Qfullscreen); 3975 Lisp_Object old_value = get_frame_param (f, Qfullscreen);
3558 3976
3559 frame_size_history_add 3977 frame_size_history_add
3560 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen)); 3978 (f, Qx_set_fullscreen, 0, 0, list2 (old_value, fullscreen));
3561 3979
3562 store_frame_param (f, Qfullscreen, fullscreen); 3980 store_frame_param (f, Qfullscreen, fullscreen);
3563 if (!EQ (fullscreen, old_value)) 3981 if (!EQ (fullscreen, old_value))
3564 x_set_fullscreen (f, fullscreen, old_value); 3982 x_set_fullscreen (f, fullscreen, old_value);
3565 } 3983 }
3566 3984
3567 3985
3568#ifdef HAVE_X_WINDOWS 3986#ifdef HAVE_X_WINDOWS
3569 if ((!NILP (icon_left) || !NILP (icon_top)) 3987 if ((!NILP (icon_left) || !NILP (icon_top))
3570 && ! (icon_left_no_change && icon_top_no_change)) 3988 && ! (icon_left_no_change && icon_top_no_change))
3571 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));
3572#endif /* HAVE_X_WINDOWS */ 3990#endif /* HAVE_X_WINDOWS */
3573 }
3574 3991
3575 SAFE_FREE (); 3992 SAFE_FREE ();
3576} 3993}
@@ -3990,7 +4407,6 @@ x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3990 adjust_frame_glyphs (f); 4407 adjust_frame_glyphs (f);
3991 SET_FRAME_GARBAGED (f); 4408 SET_FRAME_GARBAGED (f);
3992 } 4409 }
3993
3994} 4410}
3995 4411
3996void 4412void
@@ -4204,6 +4620,22 @@ x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
4204 return; 4620 return;
4205} 4621}
4206 4622
4623
4624/**
4625 * x_set_no_special_glyphs:
4626 *
4627 * Set frame F's `no-special-glyphs' parameter which, if non-nil,
4628 * suppresses the display of truncation and continuation glyphs
4629 * outside fringes.
4630 */
4631void
4632x_set_no_special_glyphs (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
4633{
4634 if (!EQ (new_value, old_value))
4635 FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (new_value);
4636}
4637
4638
4207#ifndef HAVE_NS 4639#ifndef HAVE_NS
4208 4640
4209/* Non-zero if mouse is grabbed on DPYINFO 4641/* Non-zero if mouse is grabbed on DPYINFO
@@ -4759,6 +5191,7 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4759 Lisp_Object height, width, user_size, top, left, user_position; 5191 Lisp_Object height, width, user_size, top, left, user_position;
4760 long window_prompting = 0; 5192 long window_prompting = 0;
4761 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); 5193 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
5194 int parent_done = -1, outer_done = -1;
4762 5195
4763 /* Default values if we fall through. 5196 /* Default values if we fall through.
4764 Actually, if that happens we should get 5197 Actually, if that happens we should get
@@ -4823,6 +5256,21 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4823 f->inhibit_horizontal_resize = true; 5256 f->inhibit_horizontal_resize = true;
4824 *x_width = XINT (XCDR (width)); 5257 *x_width = XINT (XCDR (width));
4825 } 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 }
4826 else 5274 else
4827 { 5275 {
4828 CHECK_NUMBER (width); 5276 CHECK_NUMBER (width);
@@ -4845,6 +5293,21 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4845 f->inhibit_vertical_resize = true; 5293 f->inhibit_vertical_resize = true;
4846 *x_height = XINT (XCDR (height)); 5294 *x_height = XINT (XCDR (height));
4847 } 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 }
4848 else 5311 else
4849 { 5312 {
4850 CHECK_NUMBER (height); 5313 CHECK_NUMBER (height);
@@ -4885,6 +5348,9 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4885 { 5348 {
4886 f->top_pos = XINT (XCAR (XCDR (top))); 5349 f->top_pos = XINT (XCAR (XCDR (top)));
4887 } 5350 }
5351 else if (FLOATP (top))
5352 f->top_pos = frame_float (f, top, FRAME_FLOAT_TOP, &parent_done,
5353 &outer_done, 0);
4888 else if (EQ (top, Qunbound)) 5354 else if (EQ (top, Qunbound))
4889 f->top_pos = 0; 5355 f->top_pos = 0;
4890 else 5356 else
@@ -4913,6 +5379,9 @@ x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p, int *x
4913 { 5379 {
4914 f->left_pos = XINT (XCAR (XCDR (left))); 5380 f->left_pos = XINT (XCAR (XCDR (left)));
4915 } 5381 }
5382 else if (FLOATP (left))
5383 f->left_pos = frame_float (f, left, FRAME_FLOAT_LEFT, &parent_done,
5384 &outer_done, 0);
4916 else if (EQ (left, Qunbound)) 5385 else if (EQ (left, Qunbound))
4917 f->left_pos = 0; 5386 f->left_pos = 0;
4918 else 5387 else
@@ -5071,12 +5540,14 @@ syms_of_frame (void)
5071 DEFSYM (Qframep, "framep"); 5540 DEFSYM (Qframep, "framep");
5072 DEFSYM (Qframe_live_p, "frame-live-p"); 5541 DEFSYM (Qframe_live_p, "frame-live-p");
5073 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");
5074 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total"); 5544 DEFSYM (Qwindow__pixel_to_total, "window--pixel-to-total");
5075 DEFSYM (Qexplicit_name, "explicit-name"); 5545 DEFSYM (Qexplicit_name, "explicit-name");
5076 DEFSYM (Qheight, "height"); 5546 DEFSYM (Qheight, "height");
5077 DEFSYM (Qicon, "icon"); 5547 DEFSYM (Qicon, "icon");
5078 DEFSYM (Qminibuffer, "minibuffer"); 5548 DEFSYM (Qminibuffer, "minibuffer");
5079 DEFSYM (Qundecorated, "undecorated"); 5549 DEFSYM (Qundecorated, "undecorated");
5550 DEFSYM (Qno_special_glyphs, "no-special-glyphs");
5080 DEFSYM (Qparent_frame, "parent-frame"); 5551 DEFSYM (Qparent_frame, "parent-frame");
5081 DEFSYM (Qskip_taskbar, "skip-taskbar"); 5552 DEFSYM (Qskip_taskbar, "skip-taskbar");
5082 DEFSYM (Qno_focus_on_map, "no-focus-on-map"); 5553 DEFSYM (Qno_focus_on_map, "no-focus-on-map");
@@ -5129,6 +5600,7 @@ syms_of_frame (void)
5129 DEFSYM (Qframes, "frames"); 5600 DEFSYM (Qframes, "frames");
5130 DEFSYM (Qsource, "source"); 5601 DEFSYM (Qsource, "source");
5131 5602
5603 DEFSYM (Qframe_edges, "frame-edges");
5132 DEFSYM (Qouter_edges, "outer-edges"); 5604 DEFSYM (Qouter_edges, "outer-edges");
5133 DEFSYM (Qouter_position, "outer-position"); 5605 DEFSYM (Qouter_position, "outer-position");
5134 DEFSYM (Qouter_size, "outer-size"); 5606 DEFSYM (Qouter_size, "outer-size");
@@ -5220,6 +5692,11 @@ syms_of_frame (void)
5220 DEFSYM (Qmin_width, "min-width"); 5692 DEFSYM (Qmin_width, "min-width");
5221 DEFSYM (Qmin_height, "min-height"); 5693 DEFSYM (Qmin_height, "min-height");
5222 DEFSYM (Qmouse_wheel_frame, "mouse-wheel-frame"); 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");
5223 5700
5224 { 5701 {
5225 int i; 5702 int i;
@@ -5564,8 +6041,8 @@ Gtk+ tooltips are not used) and on Windows. */);
5564 defsubr (&Smodify_frame_parameters); 6041 defsubr (&Smodify_frame_parameters);
5565 defsubr (&Sframe_char_height); 6042 defsubr (&Sframe_char_height);
5566 defsubr (&Sframe_char_width); 6043 defsubr (&Sframe_char_width);
5567 defsubr (&Sframe_pixel_height); 6044 defsubr (&Sframe_native_height);
5568 defsubr (&Sframe_pixel_width); 6045 defsubr (&Sframe_native_width);
5569 defsubr (&Sframe_text_cols); 6046 defsubr (&Sframe_text_cols);
5570 defsubr (&Sframe_text_lines); 6047 defsubr (&Sframe_text_lines);
5571 defsubr (&Sframe_total_cols); 6048 defsubr (&Sframe_total_cols);
@@ -5575,7 +6052,7 @@ Gtk+ tooltips are not used) and on Windows. */);
5575 defsubr (&Sscroll_bar_width); 6052 defsubr (&Sscroll_bar_width);
5576 defsubr (&Sscroll_bar_height); 6053 defsubr (&Sscroll_bar_height);
5577 defsubr (&Sfringe_width); 6054 defsubr (&Sfringe_width);
5578 defsubr (&Sborder_width); 6055 defsubr (&Sframe_internal_border_width);
5579 defsubr (&Sright_divider_width); 6056 defsubr (&Sright_divider_width);
5580 defsubr (&Sbottom_divider_width); 6057 defsubr (&Sbottom_divider_width);
5581 defsubr (&Stool_bar_pixel_width); 6058 defsubr (&Stool_bar_pixel_width);
diff --git a/src/frame.h b/src/frame.h
index 4aa7c34a29a..154dc9a3bb4 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -52,6 +52,19 @@ enum z_group
52 z_group_below, 52 z_group_below,
53 z_group_above_suspended, 53 z_group_above_suspended,
54}; 54};
55
56enum internal_border_part
57 {
58 INTERNAL_BORDER_NONE,
59 INTERNAL_BORDER_LEFT_EDGE,
60 INTERNAL_BORDER_TOP_LEFT_CORNER,
61 INTERNAL_BORDER_TOP_EDGE,
62 INTERNAL_BORDER_TOP_RIGHT_CORNER,
63 INTERNAL_BORDER_RIGHT_EDGE,
64 INTERNAL_BORDER_BOTTOM_RIGHT_CORNER,
65 INTERNAL_BORDER_BOTTOM_EDGE,
66 INTERNAL_BORDER_BOTTOM_LEFT_CORNER,
67 };
55#endif /* HAVE_WINDOW_SYSTEM */ 68#endif /* HAVE_WINDOW_SYSTEM */
56 69
57/* The structure representing a frame. */ 70/* The structure representing a frame. */
@@ -354,7 +367,11 @@ struct frame
354 367
355 /* The z-group this frame's window belongs to. */ 368 /* The z-group this frame's window belongs to. */
356 ENUM_BF (z_group) z_group : 2; 369 ENUM_BF (z_group) z_group : 2;
357#endif /* HAVE_WINDOW_SYSTEM and not HAVE_NS */ 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 */
358 375
359 /* Whether new_height and new_width shall be interpreted 376 /* Whether new_height and new_width shall be interpreted
360 in pixels. */ 377 in pixels. */
@@ -824,7 +841,7 @@ default_pixels_per_inch_y (void)
824#ifdef USE_GTK 841#ifdef USE_GTK
825#define FRAME_TOOL_BAR_POSITION(f) (f)->tool_bar_position 842#define FRAME_TOOL_BAR_POSITION(f) (f)->tool_bar_position
826#else 843#else
827#define FRAME_TOOL_BAR_POSITION(f) ((void) f, Qtop) 844#define FRAME_TOOL_BAR_POSITION(f) ((void) (f), Qtop)
828#endif 845#endif
829 846
830/* Number of lines of frame F used for the tool-bar. */ 847/* Number of lines of frame F used for the tool-bar. */
@@ -908,16 +925,17 @@ default_pixels_per_inch_y (void)
908 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right) 925 ((f)->vertical_scroll_bar_type == vertical_scroll_bar_right)
909#else /* not HAVE_WINDOW_SYSTEM */ 926#else /* not HAVE_WINDOW_SYSTEM */
910/* If there is no window system, there are no scroll bars. */ 927/* If there is no window system, there are no scroll bars. */
911#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) ((void) f, vertical_scroll_bar_none) 928#define FRAME_VERTICAL_SCROLL_BAR_TYPE(f) \
912#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) f, 0) 929 ((void) (f), vertical_scroll_bar_none)
913#define FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT(f) ((void) f, 0) 930#define FRAME_HAS_VERTICAL_SCROLL_BARS(f) ((void) (f), 0)
914#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)
915#endif /* HAVE_WINDOW_SYSTEM */ 933#endif /* HAVE_WINDOW_SYSTEM */
916 934
917#if defined (HAVE_WINDOW_SYSTEM) 935#if defined (HAVE_WINDOW_SYSTEM)
918#define FRAME_UNDECORATED(f) ((f)->undecorated) 936#define FRAME_UNDECORATED(f) ((f)->undecorated)
919#ifdef HAVE_NTGUI 937#ifdef HAVE_NTGUI
920#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0) 938#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
921#else 939#else
922#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect) 940#define FRAME_OVERRIDE_REDIRECT(f) ((f)->override_redirect)
923#endif 941#endif
@@ -928,6 +946,7 @@ default_pixels_per_inch_y (void)
928#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar) 946#define FRAME_SKIP_TASKBAR(f) ((f)->skip_taskbar)
929#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map) 947#define FRAME_NO_FOCUS_ON_MAP(f) ((f)->no_focus_on_map)
930#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus) 948#define FRAME_NO_ACCEPT_FOCUS(f) ((f)->no_accept_focus)
949#define FRAME_NO_SPECIAL_GLYPHS(f) ((f)->no_special_glyphs)
931#define FRAME_Z_GROUP(f) ((f)->z_group) 950#define FRAME_Z_GROUP(f) ((f)->z_group)
932#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none) 951#define FRAME_Z_GROUP_NONE(f) ((f)->z_group == z_group_none)
933#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above) 952#define FRAME_Z_GROUP_ABOVE(f) ((f)->z_group == z_group_above)
@@ -935,16 +954,17 @@ default_pixels_per_inch_y (void)
935 ((f)->z_group == z_group_above_suspended) 954 ((f)->z_group == z_group_above_suspended)
936#define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below) 955#define FRAME_Z_GROUP_BELOW(f) ((f)->z_group == z_group_below)
937#else /* not HAVE_WINDOW_SYSTEM */ 956#else /* not HAVE_WINDOW_SYSTEM */
938#define FRAME_UNDECORATED(f) ((void) f, 0) 957#define FRAME_UNDECORATED(f) ((void) (f), 0)
939#define FRAME_OVERRIDE_REDIRECT(f) ((void) f, 0) 958#define FRAME_OVERRIDE_REDIRECT(f) ((void) (f), 0)
940#define FRAME_PARENT_FRAME(f) ((void) f, NULL) 959#define FRAME_PARENT_FRAME(f) ((void) (f), NULL)
941#define FRAME_SKIP_TASKBAR(f) ((void) f, 0) 960#define FRAME_SKIP_TASKBAR(f) ((void) (f), 0)
942#define FRAME_NO_FOCUS_ON_MAP(f) ((void) f, 0) 961#define FRAME_NO_FOCUS_ON_MAP(f) ((void) (f), 0)
943#define FRAME_NO_ACCEPT_FOCUS(f) ((void) f, 0) 962#define FRAME_NO_ACCEPT_FOCUS(f) ((void) (f), 0)
944#define FRAME_Z_GROUP(f) ((void) f, z_group_none) 963#define FRAME_NO_SPECIAL_GLYPHS(f) ((void) (f), 0)
945#define FRAME_Z_GROUP_NONE(f) ((void) f, true) 964#define FRAME_Z_GROUP(f) ((void) (f), z_group_none)
946#define FRAME_Z_GROUP_ABOVE(f) ((void) f, false) 965#define FRAME_Z_GROUP_NONE(f) ((void) (f), true)
947#define FRAME_Z_GROUP_BELOW(f) ((void) f, false) 966#define FRAME_Z_GROUP_ABOVE(f) ((void) (f), false)
967#define FRAME_Z_GROUP_BELOW(f) ((void) (f), false)
948#endif /* HAVE_WINDOW_SYSTEM */ 968#endif /* HAVE_WINDOW_SYSTEM */
949 969
950/* Whether horizontal scroll bars are currently enabled for frame F. */ 970/* Whether horizontal scroll bars are currently enabled for frame F. */
@@ -952,7 +972,7 @@ default_pixels_per_inch_y (void)
952#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \ 972#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) \
953 ((f)->horizontal_scroll_bars) 973 ((f)->horizontal_scroll_bars)
954#else 974#else
955#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) ((void) f, 0) 975#define FRAME_HAS_HORIZONTAL_SCROLL_BARS(f) ((void) (f), 0)
956#endif 976#endif
957 977
958/* 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.
@@ -1288,19 +1308,20 @@ FRAME_TOTAL_FRINGE_WIDTH (struct frame *f)
1288 return FRAME_LEFT_FRINGE_WIDTH (f) + FRAME_RIGHT_FRINGE_WIDTH (f); 1308 return FRAME_LEFT_FRINGE_WIDTH (f) + FRAME_RIGHT_FRINGE_WIDTH (f);
1289} 1309}
1290 1310
1291/* Pixel-width of internal border lines */ 1311/* Pixel-width of internal border lines. */
1292INLINE int 1312INLINE int
1293FRAME_INTERNAL_BORDER_WIDTH (struct frame *f) 1313FRAME_INTERNAL_BORDER_WIDTH (struct frame *f)
1294{ 1314{
1295 return frame_dimension (f->internal_border_width); 1315 return frame_dimension (f->internal_border_width);
1296} 1316}
1297 1317
1298/* Pixel-size of window divider lines */ 1318/* Pixel-size of window divider lines. */
1299INLINE int 1319INLINE int
1300FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f) 1320FRAME_RIGHT_DIVIDER_WIDTH (struct frame *f)
1301{ 1321{
1302 return frame_dimension (f->right_divider_width); 1322 return frame_dimension (f->right_divider_width);
1303} 1323}
1324
1304INLINE int 1325INLINE int
1305FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f) 1326FRAME_BOTTOM_DIVIDER_WIDTH (struct frame *f)
1306{ 1327{
@@ -1498,6 +1519,7 @@ extern void x_set_scroll_bar_height (struct frame *, Lisp_Object, Lisp_Object);
1498extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *); 1519extern long x_figure_window_size (struct frame *, Lisp_Object, bool, int *, int *);
1499 1520
1500extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object); 1521extern void x_set_alpha (struct frame *, Lisp_Object, Lisp_Object);
1522extern void x_set_no_special_glyphs (struct frame *, Lisp_Object, Lisp_Object);
1501 1523
1502extern void validate_x_resource_name (void); 1524extern void validate_x_resource_name (void);
1503 1525
@@ -1521,6 +1543,7 @@ extern void x_real_positions (struct frame *, int *, int *);
1521extern void free_frame_menubar (struct frame *); 1543extern void free_frame_menubar (struct frame *);
1522extern void x_free_frame_resources (struct frame *); 1544extern void x_free_frame_resources (struct frame *);
1523extern bool frame_ancestor_p (struct frame *af, struct frame *df); 1545extern bool frame_ancestor_p (struct frame *af, struct frame *df);
1546extern enum internal_border_part frame_internal_border_part (struct frame *f, int x, int y);
1524 1547
1525#if defined HAVE_X_WINDOWS 1548#if defined HAVE_X_WINDOWS
1526extern void x_wm_set_icon_position (struct frame *, int, int); 1549extern void x_wm_set_icon_position (struct frame *, int, int);
diff --git a/src/gtkutil.c b/src/gtkutil.c
index 16eb284d7c7..2d4abefa969 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -1503,6 +1503,7 @@ xg_set_undecorated (struct frame *f, Lisp_Object undecorated)
1503void 1503void
1504xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) 1504xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
1505{ 1505{
1506#if GTK_CHECK_VERSION (2, 18, 0)
1506 block_input (); 1507 block_input ();
1507 if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2)) 1508 if (FRAME_GTK_OUTER_WIDGET (f1) && FRAME_GTK_OUTER_WIDGET (f2))
1508 { 1509 {
@@ -1517,6 +1518,7 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
1517 x_sync (f1); 1518 x_sync (f1);
1518 } 1519 }
1519 unblock_input (); 1520 unblock_input ();
1521#endif
1520} 1522}
1521 1523
1522 1524
diff --git a/src/image.c b/src/image.c
index aedec7954ee..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"
@@ -2361,7 +2361,7 @@ slurp_file (int fd, ptrdiff_t *size)
2361 This can happen if the file grows as we read it. */ 2361 This can happen if the file grows as we read it. */
2362 ptrdiff_t buflen = st.st_size; 2362 ptrdiff_t buflen = st.st_size;
2363 buf = xmalloc (buflen + 1); 2363 buf = xmalloc (buflen + 1);
2364 if (fread (buf, 1, buflen + 1, fp) == buflen) 2364 if (fread_unlocked (buf, 1, buflen + 1, fp) == buflen)
2365 *size = buflen; 2365 *size = buflen;
2366 else 2366 else
2367 { 2367 {
@@ -5890,7 +5890,7 @@ png_read_from_file (png_structp png_ptr, png_bytep data, png_size_t length)
5890{ 5890{
5891 FILE *fp = png_get_io_ptr (png_ptr); 5891 FILE *fp = png_get_io_ptr (png_ptr);
5892 5892
5893 if (fread (data, 1, length, fp) < length) 5893 if (fread_unlocked (data, 1, length, fp) < length)
5894 png_error (png_ptr, "Read error"); 5894 png_error (png_ptr, "Read error");
5895} 5895}
5896 5896
@@ -5959,7 +5959,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5959 } 5959 }
5960 5960
5961 /* Check PNG signature. */ 5961 /* Check PNG signature. */
5962 if (fread (sig, 1, sizeof sig, fp) != sizeof sig 5962 if (fread_unlocked (sig, 1, sizeof sig, fp) != sizeof sig
5963 || png_sig_cmp (sig, 0, sizeof sig)) 5963 || png_sig_cmp (sig, 0, sizeof sig))
5964 { 5964 {
5965 fclose (fp); 5965 fclose (fp);
@@ -6598,7 +6598,8 @@ our_stdio_fill_input_buffer (j_decompress_ptr cinfo)
6598 { 6598 {
6599 ptrdiff_t bytes; 6599 ptrdiff_t bytes;
6600 6600
6601 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);
6602 if (bytes > 0) 6603 if (bytes > 0)
6603 src->mgr.bytes_in_buffer = bytes; 6604 src->mgr.bytes_in_buffer = bytes;
6604 else 6605 else
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 55486c6d9ab..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"
@@ -3290,7 +3291,7 @@ record_char (Lisp_Object c)
3290 if (INTEGERP (c)) 3291 if (INTEGERP (c))
3291 { 3292 {
3292 if (XUINT (c) < 0x100) 3293 if (XUINT (c) < 0x100)
3293 putc (XUINT (c), dribble); 3294 putc_unlocked (XUINT (c), dribble);
3294 else 3295 else
3295 fprintf (dribble, " 0x%"pI"x", XUINT (c)); 3296 fprintf (dribble, " 0x%"pI"x", XUINT (c));
3296 } 3297 }
@@ -3303,15 +3304,15 @@ record_char (Lisp_Object c)
3303 3304
3304 if (SYMBOLP (dribblee)) 3305 if (SYMBOLP (dribblee))
3305 { 3306 {
3306 putc ('<', dribble); 3307 putc_unlocked ('<', dribble);
3307 fwrite (SDATA (SYMBOL_NAME (dribblee)), sizeof (char), 3308 fwrite_unlocked (SDATA (SYMBOL_NAME (dribblee)), sizeof (char),
3308 SBYTES (SYMBOL_NAME (dribblee)), 3309 SBYTES (SYMBOL_NAME (dribblee)),
3309 dribble); 3310 dribble);
3310 putc ('>', dribble); 3311 putc_unlocked ('>', dribble);
3311 } 3312 }
3312 } 3313 }
3313 3314
3314 fflush (dribble); 3315 fflush_unlocked (dribble);
3315 unblock_input (); 3316 unblock_input ();
3316 } 3317 }
3317} 3318}
@@ -3769,7 +3770,7 @@ kbd_buffer_get_event (KBOARD **kbp,
3769 detaching from the terminal. */ 3770 detaching from the terminal. */
3770 || (IS_DAEMON && DAEMON_RUNNING)) 3771 || (IS_DAEMON && DAEMON_RUNNING))
3771 { 3772 {
3772 int c = getchar (); 3773 int c = getchar_unlocked ();
3773 XSETINT (obj, c); 3774 XSETINT (obj, c);
3774 *kbp = current_kboard; 3775 *kbp = current_kboard;
3775 return obj; 3776 return obj;
@@ -5126,6 +5127,17 @@ static short const scroll_bar_parts[] = {
5126 SYMBOL_INDEX (Qrightmost), SYMBOL_INDEX (Qend_scroll), SYMBOL_INDEX (Qratio) 5127 SYMBOL_INDEX (Qrightmost), SYMBOL_INDEX (Qend_scroll), SYMBOL_INDEX (Qratio)
5127}; 5128};
5128 5129
5130/* An array of symbol indexes of internal border parts, indexed by an enum
5131 internal_border_part value. Note that Qnil corresponds to
5132 internal_border_part_none and should not appear in Lisp events. */
5133static short const internal_border_parts[] = {
5134 SYMBOL_INDEX (Qnil), SYMBOL_INDEX (Qleft_edge),
5135 SYMBOL_INDEX (Qtop_left_corner), SYMBOL_INDEX (Qtop_edge),
5136 SYMBOL_INDEX (Qtop_right_corner), SYMBOL_INDEX (Qright_edge),
5137 SYMBOL_INDEX (Qbottom_right_corner), SYMBOL_INDEX (Qbottom_edge),
5138 SYMBOL_INDEX (Qbottom_left_corner)
5139};
5140
5129/* A vector, indexed by button number, giving the down-going location 5141/* A vector, indexed by button number, giving the down-going location
5130 of currently depressed buttons, both scroll bar and non-scroll bar. 5142 of currently depressed buttons, both scroll bar and non-scroll bar.
5131 5143
@@ -5163,15 +5175,15 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
5163 Lisp_Object extra_info = Qnil; 5175 Lisp_Object extra_info = Qnil;
5164 /* Coordinate pixel positions to return. */ 5176 /* Coordinate pixel positions to return. */
5165 int xret = 0, yret = 0; 5177 int xret = 0, yret = 0;
5166 /* The window under frame pixel coordinates (x,y) */ 5178 /* The window or frame under frame pixel coordinates (x,y) */
5167 Lisp_Object window = f 5179 Lisp_Object window_or_frame = f
5168 ? window_from_coordinates (f, XINT (x), XINT (y), &part, 0) 5180 ? window_from_coordinates (f, XINT (x), XINT (y), &part, 0)
5169 : Qnil; 5181 : Qnil;
5170 5182
5171 if (WINDOWP (window)) 5183 if (WINDOWP (window_or_frame))
5172 { 5184 {
5173 /* 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) */
5174 struct window *w = XWINDOW (window); 5186 struct window *w = XWINDOW (window_or_frame);
5175 Lisp_Object string_info = Qnil; 5187 Lisp_Object string_info = Qnil;
5176 ptrdiff_t textpos = 0; 5188 ptrdiff_t textpos = 0;
5177 int col = -1, row = -1; 5189 int col = -1, row = -1;
@@ -5360,17 +5372,31 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
5360 make_number (row)), 5372 make_number (row)),
5361 extra_info))); 5373 extra_info)));
5362 } 5374 }
5363 else if (f != 0) 5375
5376#ifdef HAVE_WINDOW_SYSTEM
5377 else if (f)
5364 { 5378 {
5365 /* Return mouse pixel coordinates here. */ 5379 /* Return mouse pixel coordinates here. */
5366 XSETFRAME (window, f); 5380 XSETFRAME (window_or_frame, f);
5367 xret = XINT (x); 5381 xret = XINT (x);
5368 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 }
5369 } 5393 }
5394#endif
5395
5370 else 5396 else
5371 window = Qnil; 5397 window_or_frame = Qnil;
5372 5398
5373 return Fcons (window, 5399 return Fcons (window_or_frame,
5374 Fcons (posn, 5400 Fcons (posn,
5375 Fcons (Fcons (make_number (xret), 5401 Fcons (Fcons (make_number (xret),
5376 make_number (yret)), 5402 make_number (yret)),
@@ -10377,7 +10403,7 @@ handle_interrupt (bool in_signal_handler)
10377 sigemptyset (&blocked); 10403 sigemptyset (&blocked);
10378 sigaddset (&blocked, SIGINT); 10404 sigaddset (&blocked, SIGINT);
10379 pthread_sigmask (SIG_BLOCK, &blocked, 0); 10405 pthread_sigmask (SIG_BLOCK, &blocked, 0);
10380 fflush (stdout); 10406 fflush_unlocked (stdout);
10381 } 10407 }
10382 10408
10383 reset_all_sys_modes (); 10409 reset_all_sys_modes ();
@@ -11158,6 +11184,17 @@ syms_of_keyboard (void)
11158 Fset (Qinput_method_exit_on_first_char, Qnil); 11184 Fset (Qinput_method_exit_on_first_char, Qnil);
11159 Fset (Qinput_method_use_echo_area, Qnil); 11185 Fset (Qinput_method_use_echo_area, Qnil);
11160 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
11161 /* Symbols to head events. */ 11198 /* Symbols to head events. */
11162 DEFSYM (Qmouse_movement, "mouse-movement"); 11199 DEFSYM (Qmouse_movement, "mouse-movement");
11163 DEFSYM (Qscroll_bar_movement, "scroll-bar-movement"); 11200 DEFSYM (Qscroll_bar_movement, "scroll-bar-movement");
diff --git a/src/lread.c b/src/lread.c
index 8716b86e9bf..182f96223a5 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -72,10 +72,6 @@ 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#ifndef HAVE_GETC_UNLOCKED
76#define getc_unlocked getc
77#endif
78
79/* The objects or placeholders read with the #n=object form. 75/* The objects or placeholders read with the #n=object form.
80 76
81 A hash table maps a number to either a placeholder (while the 77 A hash table maps a number to either a placeholder (while the
@@ -474,16 +470,15 @@ readbyte_from_file (int c, Lisp_Object readcharfun)
474 } 470 }
475 471
476 block_input (); 472 block_input ();
477 c = getc_unlocked (instream);
478 473
479 /* Interrupted reads have been observed while reading over the network. */ 474 /* Interrupted reads have been observed while reading over the network. */
480 while (c == EOF && ferror (instream) && errno == EINTR) 475 while ((c = getc_unlocked (instream)) == EOF && errno == EINTR
476 && ferror_unlocked (instream))
481 { 477 {
482 unblock_input (); 478 unblock_input ();
483 maybe_quit (); 479 maybe_quit ();
484 block_input (); 480 block_input ();
485 clearerr (instream); 481 clearerr_unlocked (instream);
486 c = getc_unlocked (instream);
487 } 482 }
488 483
489 unblock_input (); 484 unblock_input ();
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
index 17e67004b24..675010b995b 100644
--- a/src/module-env-25.h
+++ b/src/module-env-25.h
@@ -92,7 +92,7 @@
92 92
93 SIZE must point to the total size of the buffer. If BUFFER is 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 94 NULL or if SIZE is not big enough, write the required buffer size
95 to SIZE and return false. 95 to SIZE and return true.
96 96
97 Note that SIZE must include the last null byte (e.g. "abc" needs 97 Note that SIZE must include the last null byte (e.g. "abc" needs
98 a buffer of size 4). 98 a buffer of size 4).
diff --git a/src/nsfns.m b/src/nsfns.m
index dbce279da63..68eba8b6a2e 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -984,6 +984,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
984 x_set_no_accept_focus, 984 x_set_no_accept_focus,
985 x_set_z_group, /* x_set_z_group */ 985 x_set_z_group, /* x_set_z_group */
986 0, /* x_set_override_redirect */ 986 0, /* x_set_override_redirect */
987 x_set_no_special_glyphs,
987}; 988};
988 989
989 990
@@ -1256,6 +1257,8 @@ This function is an internal primitive--use `make-frame' instead. */)
1256 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 1257 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1257 x_default_parameter (f, parms, Qright_fringe, Qnil, 1258 x_default_parameter (f, parms, Qright_fringe, Qnil,
1258 "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);
1259 1262
1260 init_frame_faces (f); 1263 init_frame_faces (f);
1261 1264
@@ -1325,6 +1328,15 @@ This function is an internal primitive--use `make-frame' instead. */)
1325 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor]; 1328 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1326 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor]; 1329 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1327 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
1328 FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor 1340 FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1329 = [NSCursor arrowCursor]; 1341 = [NSCursor arrowCursor];
1330 FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor 1342 FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
diff --git a/src/nsterm.h b/src/nsterm.h
index bed0b92c796..0f1b36db7b2 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -957,6 +957,14 @@ struct ns_output
957 Cursor hourglass_cursor; 957 Cursor hourglass_cursor;
958 Cursor horizontal_drag_cursor; 958 Cursor horizontal_drag_cursor;
959 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;
960 968
961 /* NS-specific */ 969 /* NS-specific */
962 Cursor current_pointer; 970 Cursor current_pointer;
@@ -1225,8 +1233,11 @@ extern void x_set_no_accept_focus (struct frame *f, Lisp_Object new_value,
1225extern void x_set_z_group (struct frame *f, Lisp_Object new_value, 1233extern void x_set_z_group (struct frame *f, Lisp_Object new_value,
1226 Lisp_Object old_value); 1234 Lisp_Object old_value);
1227extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds, 1235extern int ns_select (int nfds, fd_set *readfds, fd_set *writefds,
1228 fd_set *exceptfds, struct timespec const *timeout, 1236 fd_set *exceptfds, struct timespec *timeout,
1229 sigset_t const *sigmask); 1237 sigset_t *sigmask);
1238#ifdef HAVE_PTHREAD
1239extern void ns_run_loop_break (void);
1240#endif
1230extern unsigned long ns_get_rgb_color (struct frame *f, 1241extern unsigned long ns_get_rgb_color (struct frame *f,
1231 float r, float g, float b, float a); 1242 float r, float g, float b, float a);
1232 1243
diff --git a/src/nsterm.m b/src/nsterm.m
index e05dbf45fbc..bf83550b3d7 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -4068,7 +4068,7 @@ ns_send_appdefined (int value)
4068 app->nextappdefined = value; 4068 app->nextappdefined = value;
4069 [app performSelectorOnMainThread:@selector (sendFromMainThread:) 4069 [app performSelectorOnMainThread:@selector (sendFromMainThread:)
4070 withObject:nil 4070 withObject:nil
4071 waitUntilDone:YES]; 4071 waitUntilDone:NO];
4072 return; 4072 return;
4073 } 4073 }
4074 4074
@@ -4293,8 +4293,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit)
4293 4293
4294int 4294int
4295ns_select (int nfds, fd_set *readfds, fd_set *writefds, 4295ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4296 fd_set *exceptfds, struct timespec const *timeout, 4296 fd_set *exceptfds, struct timespec *timeout,
4297 sigset_t const *sigmask) 4297 sigset_t *sigmask)
4298/* -------------------------------------------------------------------------- 4298/* --------------------------------------------------------------------------
4299 Replacement for select, checking for events 4299 Replacement for select, checking for events
4300 -------------------------------------------------------------------------- */ 4300 -------------------------------------------------------------------------- */
@@ -4327,7 +4327,13 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4327 if (NSApp == nil 4327 if (NSApp == nil
4328 || ![NSThread isMainThread] 4328 || ![NSThread isMainThread]
4329 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) 4329 || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0))
4330 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 }
4331 4337
4332 [outerpool release]; 4338 [outerpool release];
4333 outerpool = [[NSAutoreleasePool alloc] init]; 4339 outerpool = [[NSAutoreleasePool alloc] init];
@@ -4430,6 +4436,18 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds,
4430 return result; 4436 return result;
4431} 4437}
4432 4438
4439#ifdef HAVE_PTHREAD
4440void
4441ns_run_loop_break ()
4442/* Break out of the NS run loop in ns_select or ns_read_socket. */
4443{
4444 NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_run_loop_break");
4445
4446 /* If we don't have a GUI, don't send the event. */
4447 if (NSApp != NULL)
4448 ns_send_appdefined(-1);
4449}
4450#endif
4433 4451
4434 4452
4435/* ========================================================================== 4453/* ==========================================================================
diff --git a/src/print.c b/src/print.c
index aaec5b04956..50c75d7712c 100644
--- a/src/print.c
+++ b/src/print.c
@@ -228,7 +228,7 @@ printchar_to_stream (unsigned int ch, FILE *stream)
228 { 228 {
229 if (ASCII_CHAR_P (ch)) 229 if (ASCII_CHAR_P (ch))
230 { 230 {
231 putc (ch, stream); 231 putc_unlocked (ch, stream);
232#ifdef WINDOWSNT 232#ifdef WINDOWSNT
233 /* Send the output to a debugger (nothing happens if there 233 /* Send the output to a debugger (nothing happens if there
234 isn't one). */ 234 isn't one). */
@@ -246,7 +246,7 @@ printchar_to_stream (unsigned int ch, FILE *stream)
246 if (encode_p) 246 if (encode_p)
247 encoded_ch = code_convert_string_norecord (encoded_ch, 247 encoded_ch = code_convert_string_norecord (encoded_ch,
248 coding_system, true); 248 coding_system, true);
249 fwrite (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream); 249 fwrite_unlocked (SSDATA (encoded_ch), 1, SBYTES (encoded_ch), stream);
250#ifdef WINDOWSNT 250#ifdef WINDOWSNT
251 if (print_output_debug_flag && stream == stderr) 251 if (print_output_debug_flag && stream == stderr)
252 OutputDebugString (SSDATA (encoded_ch)); 252 OutputDebugString (SSDATA (encoded_ch));
@@ -298,7 +298,7 @@ printchar (unsigned int ch, Lisp_Object fun)
298 if (DISP_TABLE_P (Vstandard_display_table)) 298 if (DISP_TABLE_P (Vstandard_display_table))
299 printchar_to_stream (ch, stdout); 299 printchar_to_stream (ch, stdout);
300 else 300 else
301 fwrite (str, 1, len, stdout); 301 fwrite_unlocked (str, 1, len, stdout);
302 noninteractive_need_newline = 1; 302 noninteractive_need_newline = 1;
303 } 303 }
304 else 304 else
@@ -350,7 +350,7 @@ strout (const char *ptr, ptrdiff_t size, ptrdiff_t size_byte,
350 } 350 }
351 } 351 }
352 else 352 else
353 fwrite (ptr, 1, size_byte, stdout); 353 fwrite_unlocked (ptr, 1, size_byte, stdout);
354 354
355 noninteractive_need_newline = 1; 355 noninteractive_need_newline = 1;
356 } 356 }
@@ -801,7 +801,7 @@ append to existing target file. */)
801 report_file_error ("Cannot open debugging output stream", file); 801 report_file_error ("Cannot open debugging output stream", file);
802 } 802 }
803 803
804 fflush (stderr); 804 fflush_unlocked (stderr);
805 if (dup2 (fd, STDERR_FILENO) < 0) 805 if (dup2 (fd, STDERR_FILENO) < 0)
806 report_file_error ("dup2", file); 806 report_file_error ("dup2", file);
807 if (fd != stderr_dup) 807 if (fd != stderr_dup)
@@ -1870,21 +1870,36 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag)
1870 } 1870 }
1871 else 1871 else
1872 { 1872 {
1873 bool still_need_nonhex = false;
1873 /* If we just had a hex escape, and this character 1874 /* If we just had a hex escape, and this character
1874 could be taken as part of it, 1875 could be taken as part of it,
1875 output `\ ' to prevent that. */ 1876 output `\ ' to prevent that. */
1876 if (need_nonhex && c_isxdigit (c)) 1877 if (c_isxdigit (c))
1877 print_c_string ("\\ ", printcharfun); 1878 {
1878 1879 if (need_nonhex)
1879 if (c == '\n' && print_escape_newlines 1880 print_c_string ("\\ ", printcharfun);
1880 ? (c = 'n', true) 1881 printchar (c, printcharfun);
1881 : c == '\f' && print_escape_newlines 1882 }
1882 ? (c = 'f', true) 1883 else if (c == '\n' && print_escape_newlines
1883 : c == '\"' || c == '\\') 1884 ? (c = 'n', true)
1884 printchar ('\\', printcharfun); 1885 : c == '\f' && print_escape_newlines
1885 1886 ? (c = 'f', true)
1886 printchar (c, printcharfun); 1887 : c == '\0' && print_escape_control_characters
1887 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;
1888 } 1903 }
1889 } 1904 }
1890 printchar ('\"', printcharfun); 1905 printchar ('\"', printcharfun);
@@ -2329,6 +2344,11 @@ A value of nil means no limit. See also `eval-expression-print-level'. */);
2329Also print formfeeds as `\\f'. */); 2344Also print formfeeds as `\\f'. */);
2330 print_escape_newlines = 0; 2345 print_escape_newlines = 0;
2331 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
2332 DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii, 2352 DEFVAR_BOOL ("print-escape-nonascii", print_escape_nonascii,
2333 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.
2334\(OOO is the octal representation of the character code.) 2354\(OOO is the octal representation of the character code.)
@@ -2418,6 +2438,7 @@ priorities. */);
2418 DEFSYM (Qprint_escape_newlines, "print-escape-newlines"); 2438 DEFSYM (Qprint_escape_newlines, "print-escape-newlines");
2419 DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte"); 2439 DEFSYM (Qprint_escape_multibyte, "print-escape-multibyte");
2420 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");
2421 2442
2422 print_prune_charset_plist = Qnil; 2443 print_prune_charset_plist = Qnil;
2423 staticpro (&print_prune_charset_plist); 2444 staticpro (&print_prune_charset_plist);
diff --git a/src/process.c b/src/process.c
index 2a1c2eecde3..abd017bb907 100644
--- a/src/process.c
+++ b/src/process.c
@@ -5371,14 +5371,13 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
5371 nfds = xg_select (max_desc + 1, 5371 nfds = xg_select (max_desc + 1,
5372 &Available, (check_write ? &Writeok : 0), 5372 &Available, (check_write ? &Writeok : 0),
5373 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);
5374#else /* !HAVE_GLIB */ 5379#else /* !HAVE_GLIB */
5375 nfds = thread_select ( 5380 nfds = thread_select (pselect, max_desc + 1,
5376# ifdef HAVE_NS
5377 ns_select
5378# else
5379 pselect
5380# endif
5381 , max_desc + 1,
5382 &Available, 5381 &Available,
5383 (check_write ? &Writeok : 0), 5382 (check_write ? &Writeok : 0),
5384 NULL, &timeout, NULL); 5383 NULL, &timeout, NULL);
diff --git a/src/sysdep.c b/src/sysdep.c
index 70f4a9dd7ea..b52236769e0 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -1408,7 +1408,7 @@ reset_sys_modes (struct tty_display_info *tty_out)
1408{ 1408{
1409 if (noninteractive) 1409 if (noninteractive)
1410 { 1410 {
1411 fflush (stdout); 1411 fflush_unlocked (stdout);
1412 return; 1412 return;
1413 } 1413 }
1414 if (!tty_out->term_initted) 1414 if (!tty_out->term_initted)
@@ -1428,17 +1428,14 @@ reset_sys_modes (struct tty_display_info *tty_out)
1428 } 1428 }
1429 else 1429 else
1430 { /* have to do it the hard way */ 1430 { /* have to do it the hard way */
1431 int i;
1432 tty_turn_off_insert (tty_out); 1431 tty_turn_off_insert (tty_out);
1433 1432
1434 for (i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++) 1433 for (int i = cursorX (tty_out); i < FrameCols (tty_out) - 1; i++)
1435 { 1434 fputc_unlocked (' ', tty_out->output);
1436 fputc (' ', tty_out->output);
1437 }
1438 } 1435 }
1439 1436
1440 cmgoto (tty_out, FrameRows (tty_out) - 1, 0); 1437 cmgoto (tty_out, FrameRows (tty_out) - 1, 0);
1441 fflush (tty_out->output); 1438 fflush_unlocked (tty_out->output);
1442 1439
1443 if (tty_out->terminal->reset_terminal_modes_hook) 1440 if (tty_out->terminal->reset_terminal_modes_hook)
1444 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal); 1441 tty_out->terminal->reset_terminal_modes_hook (tty_out->terminal);
@@ -3079,7 +3076,7 @@ procfs_ttyname (int rdev)
3079 char minor[25]; /* 2 32-bit numbers + dash */ 3076 char minor[25]; /* 2 32-bit numbers + dash */
3080 char *endp; 3077 char *endp;
3081 3078
3082 for (; !feof (fdev) && !ferror (fdev); name[0] = 0) 3079 for (; !feof_unlocked (fdev) && !ferror_unlocked (fdev); name[0] = 0)
3083 { 3080 {
3084 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
3085 && major == MAJOR (rdev)) 3082 && major == MAJOR (rdev))
@@ -3129,7 +3126,7 @@ procfs_get_total_memory (void)
3129 break; 3126 break;
3130 3127
3131 case 0: 3128 case 0:
3132 while ((c = getc (fmem)) != EOF && c != '\n') 3129 while ((c = getc_unlocked (fmem)) != EOF && c != '\n')
3133 continue; 3130 continue;
3134 done = c == EOF; 3131 done = c == EOF;
3135 break; 3132 break;
diff --git a/src/sysstdio.h b/src/sysstdio.h
index 45ee33f5580..7fbcefcdad9 100644
--- a/src/sysstdio.h
+++ b/src/sysstdio.h
@@ -33,4 +33,45 @@ extern FILE *emacs_fopen (char const *, char const *);
33# define FOPEN_TEXT "" 33# define FOPEN_TEXT ""
34#endif 34#endif
35 35
36/* These are compatible with unlocked-io.h, if both files are included. */
37#if !HAVE_DECL_CLEARERR_UNLOCKED
38# define clearerr_unlocked(x) clearerr (x)
39#endif
40#if !HAVE_DECL_FEOF_UNLOCKED
41# define feof_unlocked(x) feof (x)
42#endif
43#if !HAVE_DECL_FERROR_UNLOCKED
44# define ferror_unlocked(x) ferror (x)
45#endif
46#if !HAVE_DECL_FFLUSH_UNLOCKED
47# define fflush_unlocked(x) fflush (x)
48#endif
49#if !HAVE_DECL_FGETS_UNLOCKED
50# define fgets_unlocked(x,y,z) fgets (x,y,z)
51#endif
52#if !HAVE_DECL_FPUTC_UNLOCKED
53# define fputc_unlocked(x,y) fputc (x,y)
54#endif
55#if !HAVE_DECL_FPUTS_UNLOCKED
56# define fputs_unlocked(x,y) fputs (x,y)
57#endif
58#if !HAVE_DECL_FREAD_UNLOCKED
59# define fread_unlocked(w,x,y,z) fread (w,x,y,z)
60#endif
61#if !HAVE_DECL_FWRITE_UNLOCKED
62# define fwrite_unlocked(w,x,y,z) fwrite (w,x,y,z)
63#endif
64#if !HAVE_DECL_GETC_UNLOCKED
65# define getc_unlocked(x) getc (x)
66#endif
67#if !HAVE_DECL_GETCHAR_UNLOCKED
68# define getchar_unlocked() getchar ()
69#endif
70#if !HAVE_DECL_PUTC_UNLOCKED
71# define putc_unlocked(x,y) putc (x,y)
72#endif
73#if !HAVE_DECL_PUTCHAR_UNLOCKED
74# define putchar_unlocked(x) putchar (x)
75#endif
76
36#endif /* EMACS_SYSSTDIO_H */ 77#endif /* EMACS_SYSSTDIO_H */
diff --git a/src/systhread.c b/src/systhread.c
index a84060c18f0..aee12a9b482 100644
--- a/src/systhread.c
+++ b/src/systhread.c
@@ -20,6 +20,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20#include <setjmp.h> 20#include <setjmp.h>
21#include "lisp.h" 21#include "lisp.h"
22 22
23#ifdef HAVE_NS
24#include "nsterm.h"
25#endif
26
23#ifndef THREADS_ENABLED 27#ifndef THREADS_ENABLED
24 28
25void 29void
@@ -130,6 +134,13 @@ void
130sys_cond_broadcast (sys_cond_t *cond) 134sys_cond_broadcast (sys_cond_t *cond)
131{ 135{
132 pthread_cond_broadcast (cond); 136 pthread_cond_broadcast (cond);
137#ifdef HAVE_NS
138 /* Send an app defined event to break out of the NS run loop.
139 It seems that if ns_select is running the NS run loop, this
140 broadcast has no effect until the loop is done, breaking a couple
141 of tests in thread-tests.el. */
142 ns_run_loop_break ();
143#endif
133} 144}
134 145
135void 146void
diff --git a/src/term.c b/src/term.c
index 8770aff8a92..3d7f4ada0b9 100644
--- a/src/term.c
+++ b/src/term.c
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22#include <config.h> 22#include <config.h>
23#include <errno.h> 23#include <errno.h>
24#include <fcntl.h> 24#include <fcntl.h>
25#include <stdio.h>
26#include <stdlib.h> 25#include <stdlib.h>
27#include <sys/file.h> 26#include <sys/file.h>
28#include <sys/time.h> 27#include <sys/time.h>
@@ -45,6 +44,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
45#include "keymap.h" 44#include "keymap.h"
46#include "blockinput.h" 45#include "blockinput.h"
47#include "syssignal.h" 46#include "syssignal.h"
47#include "sysstdio.h"
48#ifdef MSDOS 48#ifdef MSDOS
49#include "msdos.h" 49#include "msdos.h"
50static int been_here = -1; 50static int been_here = -1;
@@ -146,7 +146,7 @@ tty_ring_bell (struct frame *f)
146 OUTPUT (tty, (tty->TS_visible_bell && visible_bell 146 OUTPUT (tty, (tty->TS_visible_bell && visible_bell
147 ? tty->TS_visible_bell 147 ? tty->TS_visible_bell
148 : tty->TS_bell)); 148 : tty->TS_bell));
149 fflush (tty->output); 149 fflush_unlocked (tty->output);
150 } 150 }
151} 151}
152 152
@@ -167,9 +167,10 @@ tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym)
167 Lisp_Object string = XCAR (extra_codes); 167 Lisp_Object string = XCAR (extra_codes);
168 if (STRINGP (string)) 168 if (STRINGP (string))
169 { 169 {
170 fwrite (SDATA (string), 1, SBYTES (string), tty->output); 170 fwrite_unlocked (SDATA (string), 1, SBYTES (string), tty->output);
171 if (tty->termscript) 171 if (tty->termscript)
172 fwrite (SDATA (string), 1, SBYTES (string), tty->termscript); 172 fwrite_unlocked (SDATA (string), 1, SBYTES (string),
173 tty->termscript);
173 } 174 }
174 } 175 }
175} 176}
@@ -197,7 +198,7 @@ tty_set_terminal_modes (struct terminal *terminal)
197 OUTPUT_IF (tty, tty->TS_keypad_mode); 198 OUTPUT_IF (tty, tty->TS_keypad_mode);
198 losecursor (tty); 199 losecursor (tty);
199 tty_send_additional_strings (terminal, Qtty_mode_set_strings); 200 tty_send_additional_strings (terminal, Qtty_mode_set_strings);
200 fflush (tty->output); 201 fflush_unlocked (tty->output);
201 } 202 }
202} 203}
203 204
@@ -220,7 +221,7 @@ tty_reset_terminal_modes (struct terminal *terminal)
220 /* Output raw CR so kernel can track the cursor hpos. */ 221 /* Output raw CR so kernel can track the cursor hpos. */
221 current_tty = tty; 222 current_tty = tty;
222 cmputc ('\r'); 223 cmputc ('\r');
223 fflush (tty->output); 224 fflush_unlocked (tty->output);
224 } 225 }
225} 226}
226 227
@@ -235,7 +236,7 @@ tty_update_end (struct frame *f)
235 tty_show_cursor (tty); 236 tty_show_cursor (tty);
236 tty_turn_off_insert (tty); 237 tty_turn_off_insert (tty);
237 tty_background_highlight (tty); 238 tty_background_highlight (tty);
238 fflush (tty->output); 239 fflush_unlocked (tty->output);
239} 240}
240 241
241/* The implementation of set_terminal_window for termcap frames. */ 242/* The implementation of set_terminal_window for termcap frames. */
@@ -497,8 +498,8 @@ tty_clear_end_of_line (struct frame *f, int first_unused_hpos)
497 for (i = curX (tty); i < first_unused_hpos; i++) 498 for (i = curX (tty); i < first_unused_hpos; i++)
498 { 499 {
499 if (tty->termscript) 500 if (tty->termscript)
500 fputc (' ', tty->termscript); 501 fputc_unlocked (' ', tty->termscript);
501 fputc (' ', tty->output); 502 fputc_unlocked (' ', tty->output);
502 } 503 }
503 cmplus (tty, first_unused_hpos - curX (tty)); 504 cmplus (tty, first_unused_hpos - curX (tty));
504 } 505 }
@@ -771,11 +772,11 @@ tty_write_glyphs (struct frame *f, struct glyph *string, int len)
771 if (coding->produced > 0) 772 if (coding->produced > 0)
772 { 773 {
773 block_input (); 774 block_input ();
774 fwrite (conversion_buffer, 1, coding->produced, tty->output); 775 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
775 if (ferror (tty->output)) 776 clearerr_unlocked (tty->output);
776 clearerr (tty->output);
777 if (tty->termscript) 777 if (tty->termscript)
778 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 778 fwrite_unlocked (conversion_buffer, 1, coding->produced,
779 tty->termscript);
779 unblock_input (); 780 unblock_input ();
780 } 781 }
781 string += n; 782 string += n;
@@ -832,11 +833,11 @@ tty_write_glyphs_with_face (register struct frame *f, register struct glyph *str
832 if (coding->produced > 0) 833 if (coding->produced > 0)
833 { 834 {
834 block_input (); 835 block_input ();
835 fwrite (conversion_buffer, 1, coding->produced, tty->output); 836 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
836 if (ferror (tty->output)) 837 clearerr_unlocked (tty->output);
837 clearerr (tty->output);
838 if (tty->termscript) 838 if (tty->termscript)
839 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 839 fwrite_unlocked (conversion_buffer, 1, coding->produced,
840 tty->termscript);
840 unblock_input (); 841 unblock_input ();
841 } 842 }
842 843
@@ -918,11 +919,11 @@ tty_insert_glyphs (struct frame *f, struct glyph *start, int len)
918 if (coding->produced > 0) 919 if (coding->produced > 0)
919 { 920 {
920 block_input (); 921 block_input ();
921 fwrite (conversion_buffer, 1, coding->produced, tty->output); 922 fwrite_unlocked (conversion_buffer, 1, coding->produced, tty->output);
922 if (ferror (tty->output)) 923 clearerr_unlocked (tty->output);
923 clearerr (tty->output);
924 if (tty->termscript) 924 if (tty->termscript)
925 fwrite (conversion_buffer, 1, coding->produced, tty->termscript); 925 fwrite_unlocked (conversion_buffer, 1, coding->produced,
926 tty->termscript);
926 unblock_input (); 927 unblock_input ();
927 } 928 }
928 929
@@ -3327,7 +3328,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3327 which calls tty_show_cursor. Re-hide it, so it doesn't show 3328 which calls tty_show_cursor. Re-hide it, so it doesn't show
3328 through the menus. */ 3329 through the menus. */
3329 tty_hide_cursor (tty); 3330 tty_hide_cursor (tty);
3330 fflush (tty->output); 3331 fflush_unlocked (tty->output);
3331 } 3332 }
3332 3333
3333 sf->mouse_moved = 0; 3334 sf->mouse_moved = 0;
@@ -3335,7 +3336,7 @@ tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3335 while (statecount--) 3336 while (statecount--)
3336 free_saved_screen (state[statecount].screen_behind); 3337 free_saved_screen (state[statecount].screen_behind);
3337 tty_show_cursor (tty); /* Turn cursor back on. */ 3338 tty_show_cursor (tty); /* Turn cursor back on. */
3338 fflush (tty->output); 3339 fflush_unlocked (tty->output);
3339 3340
3340/* Clean up any mouse events that are waiting inside Emacs event queue. 3341/* Clean up any mouse events that are waiting inside Emacs event queue.
3341 These events are likely to be generated before the menu was even 3342 These events are likely to be generated before the menu was even
diff --git a/src/w32fns.c b/src/w32fns.c
index e490588d01b..b0842b5ee6c 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -5889,6 +5889,8 @@ This function is an internal primitive--use `make-frame' instead. */)
5889 NULL, NULL, RES_TYPE_BOOLEAN); 5889 NULL, NULL, RES_TYPE_BOOLEAN);
5890 x_default_parameter (f, parameters, Qno_accept_focus, Qnil, 5890 x_default_parameter (f, parameters, Qno_accept_focus, Qnil,
5891 NULL, NULL, RES_TYPE_BOOLEAN); 5891 NULL, NULL, RES_TYPE_BOOLEAN);
5892 x_default_parameter (f, parameters, Qno_special_glyphs, Qnil,
5893 NULL, NULL, RES_TYPE_BOOLEAN);
5892 5894
5893 /* Process alpha here (Bug#16619). On XP this fails with child 5895 /* Process alpha here (Bug#16619). On XP this fails with child
5894 frames. For `no-focus-on-map' frames delay processing of alpha 5896 frames. For `no-focus-on-map' frames delay processing of alpha
@@ -5957,6 +5959,14 @@ This function is an internal primitive--use `make-frame' instead. */)
5957 f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT); 5959 f->output_data.w32->hourglass_cursor = w32_load_cursor (IDC_WAIT);
5958 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);
5959 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);
5960 5970
5961 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;
5962 5972
@@ -7049,6 +7059,8 @@ x_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms)
7049 "cursorColor", "Foreground", RES_TYPE_STRING); 7059 "cursorColor", "Foreground", RES_TYPE_STRING);
7050 x_default_parameter (f, parms, Qborder_color, build_string ("black"), 7060 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
7051 "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);
7052 7064
7053 /* Init faces before x_default_parameter is called for the 7065 /* Init faces before x_default_parameter is called for the
7054 scroll-bar-width parameter because otherwise we end up in 7066 scroll-bar-width parameter because otherwise we end up in
@@ -8950,33 +8962,47 @@ menu bar or tool bar of FRAME. */)
8950 if (EQ (type, Qouter_edges)) 8962 if (EQ (type, Qouter_edges))
8951 { 8963 {
8952 RECT rectangle; 8964 RECT rectangle;
8965 BOOL success = false;
8953 8966
8954 block_input (); 8967 block_input ();
8955 /* Outer frame rectangle, including outer borders and title bar. */ 8968 /* Outer frame rectangle, including outer borders and title bar. */
8956 GetWindowRect (FRAME_W32_WINDOW (f), &rectangle); 8969 success = GetWindowRect (FRAME_W32_WINDOW (f), &rectangle);
8957 unblock_input (); 8970 unblock_input ();
8958 8971
8959 return list4 (make_number (rectangle.left), 8972 if (success)
8960 make_number (rectangle.top), 8973 return list4 (make_number (rectangle.left),
8961 make_number (rectangle.right), 8974 make_number (rectangle.top),
8962 make_number (rectangle.bottom)); 8975 make_number (rectangle.right),
8976 make_number (rectangle.bottom));
8977 else
8978 return Qnil;
8963 } 8979 }
8964 else 8980 else
8965 { 8981 {
8966 RECT rectangle; 8982 RECT rectangle;
8967 POINT pt; 8983 POINT pt;
8968 int left, top, right, bottom; 8984 int left, top, right, bottom;
8985 BOOL success;
8969 8986
8970 block_input (); 8987 block_input ();
8971 /* Inner frame rectangle, excluding borders and title bar. */ 8988 /* Inner frame rectangle, excluding borders and title bar. */
8972 GetClientRect (FRAME_W32_WINDOW (f), &rectangle); 8989 success = GetClientRect (FRAME_W32_WINDOW (f), &rectangle);
8973 /* Get top-left corner of native rectangle in screen 8990 /* Get top-left corner of native rectangle in screen
8974 coordinates. */ 8991 coordinates. */
8992 if (!success)
8993 {
8994 unblock_input ();
8995 return Qnil;
8996 }
8997
8975 pt.x = 0; 8998 pt.x = 0;
8976 pt.y = 0; 8999 pt.y = 0;
8977 ClientToScreen (FRAME_W32_WINDOW (f), &pt); 9000 success = ClientToScreen (FRAME_W32_WINDOW (f), &pt);
8978 unblock_input (); 9001 unblock_input ();
8979 9002
9003 if (!success)
9004 return Qnil;
9005
8980 left = pt.x; 9006 left = pt.x;
8981 top = pt.y; 9007 top = pt.y;
8982 right = left + rectangle.right; 9008 right = left + rectangle.right;
@@ -10330,6 +10356,7 @@ frame_parm_handler w32_frame_parm_handlers[] =
10330 x_set_no_accept_focus, 10356 x_set_no_accept_focus,
10331 x_set_z_group, 10357 x_set_z_group,
10332 0, /* x_set_override_redirect */ 10358 0, /* x_set_override_redirect */
10359 x_set_no_special_glyphs,
10333}; 10360};
10334 10361
10335void 10362void
diff --git a/src/w32term.c b/src/w32term.c
index 712bdae5fc3..c37805cb6ca 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5086,6 +5086,51 @@ w32_read_socket (struct terminal *terminal,
5086 } 5086 }
5087 5087
5088 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
5089 case WM_ACTIVATE: 5134 case WM_ACTIVATE:
5090 case WM_ACTIVATEAPP: 5135 case WM_ACTIVATEAPP:
5091 f = x_window_to_frame (dpyinfo, msg.msg.hwnd); 5136 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -6052,7 +6097,7 @@ x_calc_absolute_position (struct frame *f)
6052 int display_top = 0; 6097 int display_top = 0;
6053 struct frame *p = FRAME_PARENT_FRAME (f); 6098 struct frame *p = FRAME_PARENT_FRAME (f);
6054 6099
6055 if (flags & (XNegative | YNegative)) 6100 if (!p && flags & (XNegative | YNegative))
6056 { 6101 {
6057 Lisp_Object list; 6102 Lisp_Object list;
6058 6103
@@ -6078,20 +6123,26 @@ x_calc_absolute_position (struct frame *f)
6078 } 6123 }
6079 6124
6080 /* Treat negative positions as relative to the rightmost bottommost 6125 /* Treat negative positions as relative to the rightmost bottommost
6081 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. */
6082 if (flags & XNegative) 6133 if (flags & XNegative)
6083 { 6134 {
6084 if (p) 6135 if (p)
6085 f->left_pos = (FRAME_PIXEL_WIDTH (p) 6136 f->left_pos = (FRAME_PIXEL_WIDTH (p)
6086 - FRAME_PIXEL_WIDTH (f) 6137 - FRAME_PIXEL_WIDTH (f)
6087 + f->left_pos 6138 + f->left_pos
6088 - (left_right_borders_width - 1)); 6139 - left_right_borders_width);
6089 else 6140 else
6090 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f)) 6141 f->left_pos = (x_display_pixel_width (FRAME_DISPLAY_INFO (f))
6091 + display_left 6142 + display_left
6092 - FRAME_PIXEL_WIDTH (f) 6143 - FRAME_PIXEL_WIDTH (f)
6093 + f->left_pos 6144 + f->left_pos
6094 - (left_right_borders_width - 1)); 6145 - left_right_borders_width);
6095 } 6146 }
6096 6147
6097 if (flags & YNegative) 6148 if (flags & YNegative)
@@ -6100,13 +6151,13 @@ x_calc_absolute_position (struct frame *f)
6100 f->top_pos = (FRAME_PIXEL_HEIGHT (p) 6151 f->top_pos = (FRAME_PIXEL_HEIGHT (p)
6101 - FRAME_PIXEL_HEIGHT (f) 6152 - FRAME_PIXEL_HEIGHT (f)
6102 + f->top_pos 6153 + f->top_pos
6103 - (top_bottom_borders_height - 1)); 6154 - top_bottom_borders_height);
6104 else 6155 else
6105 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f)) 6156 f->top_pos = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
6106 + display_top 6157 + display_top
6107 - FRAME_PIXEL_HEIGHT (f) 6158 - FRAME_PIXEL_HEIGHT (f)
6108 + f->top_pos 6159 + f->top_pos
6109 - (top_bottom_borders_height - 1)); 6160 - top_bottom_borders_height);
6110 } 6161 }
6111 6162
6112 /* 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
diff --git a/src/w32term.h b/src/w32term.h
index 371cf9005bc..9956682c5cd 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -345,6 +345,14 @@ struct w32_output
345 Cursor hourglass_cursor; 345 Cursor hourglass_cursor;
346 Cursor horizontal_drag_cursor; 346 Cursor horizontal_drag_cursor;
347 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;
348 356
349 /* Non-zero means hourglass cursor is currently displayed. */ 357 /* Non-zero means hourglass cursor is currently displayed. */
350 unsigned hourglass_p : 1; 358 unsigned hourglass_p : 1;
diff --git a/src/window.c b/src/window.c
index bf89f0e488b..4816bd69909 100644
--- a/src/window.c
+++ b/src/window.c
@@ -1208,13 +1208,13 @@ coordinates_in_window (register struct window *w, int x, int y)
1208 - WINDOW_BOTTOM_DIVIDER_WIDTH (w)))) 1208 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))))
1209 return ON_HORIZONTAL_SCROLL_BAR; 1209 return ON_HORIZONTAL_SCROLL_BAR;
1210 /* On the mode or header line? */ 1210 /* On the mode or header line? */
1211 else if ((WINDOW_WANTS_MODELINE_P (w) 1211 else if ((window_wants_mode_line (w)
1212 && y >= (bottom_y 1212 && y >= (bottom_y
1213 - CURRENT_MODE_LINE_HEIGHT (w) 1213 - CURRENT_MODE_LINE_HEIGHT (w)
1214 - WINDOW_BOTTOM_DIVIDER_WIDTH (w)) 1214 - WINDOW_BOTTOM_DIVIDER_WIDTH (w))
1215 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w) 1215 && y <= bottom_y - WINDOW_BOTTOM_DIVIDER_WIDTH (w)
1216 && (part = ON_MODE_LINE)) 1216 && (part = ON_MODE_LINE))
1217 || (WINDOW_WANTS_HEADER_LINE_P (w) 1217 || (window_wants_header_line (w)
1218 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w) 1218 && y < top_y + CURRENT_HEADER_LINE_HEIGHT (w)
1219 && (part = ON_HEADER_LINE))) 1219 && (part = ON_HEADER_LINE)))
1220 { 1220 {
@@ -1851,7 +1851,7 @@ Return nil if window display is not up-to-date. In that case, use
1851 1851
1852 if (EQ (line, Qheader_line)) 1852 if (EQ (line, Qheader_line))
1853 { 1853 {
1854 if (!WINDOW_WANTS_HEADER_LINE_P (w)) 1854 if (!window_wants_header_line (w))
1855 return Qnil; 1855 return Qnil;
1856 row = MATRIX_HEADER_LINE_ROW (w->current_matrix); 1856 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
1857 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil; 1857 return row->enabled_p ? list4i (row->height, 0, 0, 0) : Qnil;
@@ -1898,6 +1898,129 @@ Return nil if window display is not up-to-date. In that case, use
1898 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);
1899} 1899}
1900 1900
1901DEFUN ("window-lines-pixel-dimensions", Fwindow_lines_pixel_dimensions, Swindow_lines_pixel_dimensions, 0, 6, 0,
1902 doc: /* Return pixel dimensions of WINDOW's lines.
1903The return value is a list of the x- and y-coordinates of the lower
1904right corner of the last character of each line. Return nil if the
1905current glyph matrix of WINDOW is not up-to-date.
1906
1907Optional argument WINDOW specifies the window whose lines' dimensions
1908shall be returned. Nil or omitted means to return the dimensions for
1909the selected window.
1910
1911FIRST, if non-nil, specifies the index of the first line whose
1912dimensions shall be returned. If FIRST is nil and BODY is non-nil,
1913start with the first text line of WINDOW. Otherwise, start with the
1914first line of WINDOW.
1915
1916LAST, if non-nil, specifies the last line whose dimensions shall be
1917returned. If LAST is nil and BODY is non-nil, the last line is the last
1918line of the body (text area) of WINDOW. Otherwise, last is the last
1919line of WINDOW.
1920
1921INVERSE, if nil, means that the y-pixel value returned for a specific
1922line specifies the distance in pixels from the left edge (body edge if
1923BODY is non-nil) of WINDOW to the right edge of the last glyph of that
1924line. INVERSE non-nil means that the y-pixel value returned for a
1925specific line specifies the distance in pixels from the right edge of
1926the last glyph of that line to the right edge (body edge if BODY is
1927non-nil) of WINDOW.
1928
1929LEFT non-nil means to return the x- and y-coordinates of the lower left
1930corner of the leftmost character on each line. This is the value that
1931should be used for buffers that mostly display text from right to left.
1932
1933If LEFT is non-nil and INVERSE is nil, this means that the y-pixel value
1934returned for a specific line specifies the distance in pixels from the
1935left edge of the last (leftmost) glyph of that line to the right edge
1936(body edge if BODY is non-nil) of WINDOW. If LEFT and INVERSE are both
1937non-nil, the y-pixel value returned for a specific line specifies the
1938distance in pixels from the left edge (body edge if BODY is non-nil) of
1939WINDOW to the left edge of the last (leftmost) glyph of that line.
1940
1941Normally, the value of this function is not available while Emacs is
1942busy, for example, when processing a command. It should be retrievable
1943though when run from an idle timer with a delay of zero seconds. */)
1944 (Lisp_Object window, Lisp_Object first, Lisp_Object last, Lisp_Object body, Lisp_Object inverse, Lisp_Object left)
1945{
1946 struct window *w = decode_live_window (window);
1947 struct buffer *b;
1948 struct glyph_row *row, *end_row;
1949 int max_y = NILP (body) ? WINDOW_PIXEL_HEIGHT (w) : window_text_bottom_y (w);
1950 Lisp_Object rows = Qnil;
1951 int window_width = NILP (body) ? w->pixel_width : window_body_width (w, true);
1952 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
1953 int subtract = NILP (body) ? 0 : header_line_height;
1954 bool invert = !NILP (inverse);
1955 bool left_flag = !NILP (left);
1956
1957 if (noninteractive || w->pseudo_window_p)
1958 return Qnil;
1959
1960 CHECK_BUFFER (w->contents);
1961 b = XBUFFER (w->contents);
1962
1963 /* Fail if current matrix is not up-to-date. */
1964 if (!w->window_end_valid
1965 || windows_or_buffers_changed
1966 || b->clip_changed
1967 || b->prevent_redisplay_optimizations_p
1968 || window_outdated (w))
1969 return Qnil;
1970
1971 if (NILP (first))
1972 row = (NILP (body)
1973 ? MATRIX_ROW (w->current_matrix, 0)
1974 : MATRIX_FIRST_TEXT_ROW (w->current_matrix));
1975 else if (NUMBERP (first))
1976 {
1977 CHECK_RANGED_INTEGER (first, 0, w->current_matrix->nrows);
1978 row = MATRIX_ROW (w->current_matrix, XINT (first));
1979 }
1980 else
1981 error ("Invalid specification of first line");
1982
1983 if (NILP (last))
1984
1985 end_row = (NILP (body)
1986 ? MATRIX_ROW (w->current_matrix, w->current_matrix->nrows)
1987 : MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w));
1988 else if (NUMBERP (last))
1989 {
1990 CHECK_RANGED_INTEGER (last, 0, w->current_matrix->nrows);
1991 end_row = MATRIX_ROW (w->current_matrix, XINT (last));
1992 }
1993 else
1994 error ("Invalid specification of last line");
1995
1996 while (row <= end_row && row->enabled_p
1997 && row->y + row->height < max_y)
1998 {
1999
2000 if (left_flag)
2001 {
2002 struct glyph *glyph = row->glyphs[TEXT_AREA];
2003
2004 rows = Fcons (Fcons (make_number
2005 (invert
2006 ? glyph->pixel_width
2007 : window_width - glyph->pixel_width),
2008 make_number (row->y + row->height - subtract)),
2009 rows);
2010 }
2011 else
2012 rows = Fcons (Fcons (make_number
2013 (invert
2014 ? window_width - row->pixel_width
2015 : row->pixel_width),
2016 make_number (row->y + row->height - subtract)),
2017 rows);
2018 row++;
2019 }
2020
2021 return Fnreverse (rows);
2022}
2023
1901DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p, 2024DEFUN ("window-dedicated-p", Fwindow_dedicated_p, Swindow_dedicated_p,
1902 0, 1, 0, 2025 0, 1, 0,
1903 doc: /* Return non-nil when WINDOW is dedicated to its buffer. 2026 doc: /* Return non-nil when WINDOW is dedicated to its buffer.
@@ -2003,16 +2126,24 @@ return value is a list of elements of the form (PARAMETER . VALUE). */)
2003 return Fcopy_alist (decode_valid_window (window)->window_parameters); 2126 return Fcopy_alist (decode_valid_window (window)->window_parameters);
2004} 2127}
2005 2128
2129Lisp_Object
2130window_parameter (struct window *w, Lisp_Object parameter)
2131{
2132 Lisp_Object result = Fassq (parameter, w->window_parameters);
2133
2134 return CDR_SAFE (result);
2135}
2136
2137
2006DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter, 2138DEFUN ("window-parameter", Fwindow_parameter, Swindow_parameter,
2007 2, 2, 0, 2139 2, 2, 0,
2008 doc: /* Return WINDOW's value for PARAMETER. 2140 doc: /* Return WINDOW's value for PARAMETER.
2009WINDOW can be any window and defaults to the selected one. */) 2141WINDOW can be any window and defaults to the selected one. */)
2010 (Lisp_Object window, Lisp_Object parameter) 2142 (Lisp_Object window, Lisp_Object parameter)
2011{ 2143{
2012 Lisp_Object result; 2144 struct window *w = decode_any_window (window);
2013 2145
2014 result = Fassq (parameter, decode_any_window (window)->window_parameters); 2146 return window_parameter (w, parameter);
2015 return CDR_SAFE (result);
2016} 2147}
2017 2148
2018DEFUN ("set-window-parameter", Fset_window_parameter, 2149DEFUN ("set-window-parameter", Fset_window_parameter,
@@ -4740,6 +4871,69 @@ mark_window_cursors_off (struct window *w)
4740} 4871}
4741 4872
4742 4873
4874/**
4875 * window_wants_mode_line:
4876 *
4877 * Return 1 if window W wants a mode line and is high enough to
4878 * accomodate it, 0 otherwise.
4879 *
4880 * W wants a mode line if it's a leaf window and neither a minibuffer
4881 * nor a pseudo window. Moreover, its 'window-mode-line-format'
4882 * parameter must not be 'none' and either that parameter or W's
4883 * buffer's 'mode-line-format' value must be non-nil. Finally, W must
4884 * be higher than its frame's canonical character height.
4885 */
4886bool
4887window_wants_mode_line (struct window *w)
4888{
4889 Lisp_Object window_mode_line_format =
4890 window_parameter (w, Qmode_line_format);
4891
4892 return ((WINDOW_LEAF_P (w)
4893 && !MINI_WINDOW_P (w)
4894 && !WINDOW_PSEUDO_P (w)
4895 && !EQ (window_mode_line_format, Qnone)
4896 && (!NILP (window_mode_line_format)
4897 || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), mode_line_format)))
4898 && WINDOW_PIXEL_HEIGHT (w) > WINDOW_FRAME_LINE_HEIGHT (w))
4899 ? 1
4900 : 0);
4901}
4902
4903
4904/**
4905 * window_wants_header_line:
4906 *
4907 * Return 1 if window W wants a header line and is high enough to
4908 * accomodate it, 0 otherwise.
4909 *
4910 * W wants a header line if it's a leaf window and neither a minibuffer
4911 * nor a pseudo window. Moreover, its 'window-mode-line-format'
4912 * parameter must not be 'none' and either that parameter or W's
4913 * buffer's 'mode-line-format' value must be non-nil. Finally, W must
4914 * be higher than its frame's canonical character height and be able to
4915 * accomodate a mode line too if necessary (the mode line prevails).
4916 */
4917bool
4918window_wants_header_line (struct window *w)
4919{
4920 Lisp_Object window_header_line_format =
4921 window_parameter (w, Qheader_line_format);
4922
4923 return ((WINDOW_LEAF_P (w)
4924 && !MINI_WINDOW_P (w)
4925 && !WINDOW_PSEUDO_P (w)
4926 && !EQ (window_header_line_format, Qnone)
4927 && (!NILP (window_header_line_format)
4928 || !NILP (BVAR (XBUFFER (WINDOW_BUFFER (w)), header_line_format)))
4929 && (WINDOW_PIXEL_HEIGHT (w)
4930 > (window_wants_mode_line (w)
4931 ? 2 * WINDOW_FRAME_LINE_HEIGHT (w)
4932 : WINDOW_FRAME_LINE_HEIGHT (w))))
4933 ? 1
4934 : 0);
4935}
4936
4743/* 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. */
4744 4938
4745int 4939int
@@ -4753,10 +4947,10 @@ window_internal_height (struct window *w)
4753 || WINDOWP (w->contents) 4947 || WINDOWP (w->contents)
4754 || !NILP (w->next) 4948 || !NILP (w->next)
4755 || !NILP (w->prev) 4949 || !NILP (w->prev)
4756 || WINDOW_WANTS_MODELINE_P (w)) 4950 || window_wants_mode_line (w))
4757 --ht; 4951 --ht;
4758 4952
4759 if (WINDOW_WANTS_HEADER_LINE_P (w)) 4953 if (window_wants_header_line (w))
4760 --ht; 4954 --ht;
4761 } 4955 }
4762 4956
@@ -7354,6 +7548,8 @@ syms_of_window (void)
7354 DEFSYM (Qfloor, "floor"); 7548 DEFSYM (Qfloor, "floor");
7355 DEFSYM (Qceiling, "ceiling"); 7549 DEFSYM (Qceiling, "ceiling");
7356 DEFSYM (Qmark_for_redisplay, "mark-for-redisplay"); 7550 DEFSYM (Qmark_for_redisplay, "mark-for-redisplay");
7551 DEFSYM (Qmode_line_format, "mode-line-format");
7552 DEFSYM (Qheader_line_format, "header-line-format");
7357 7553
7358 staticpro (&Vwindow_list); 7554 staticpro (&Vwindow_list);
7359 7555
@@ -7603,6 +7799,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
7603 defsubr (&Sset_window_point); 7799 defsubr (&Sset_window_point);
7604 defsubr (&Sset_window_start); 7800 defsubr (&Sset_window_start);
7605 defsubr (&Swindow_dedicated_p); 7801 defsubr (&Swindow_dedicated_p);
7802 defsubr (&Swindow_lines_pixel_dimensions);
7606 defsubr (&Sset_window_dedicated_p); 7803 defsubr (&Sset_window_dedicated_p);
7607 defsubr (&Swindow_display_table); 7804 defsubr (&Swindow_display_table);
7608 defsubr (&Sset_window_display_table); 7805 defsubr (&Sset_window_display_table);
diff --git a/src/window.h b/src/window.h
index acb8a5cabfa..e9040f816df 100644
--- a/src/window.h
+++ b/src/window.h
@@ -328,8 +328,9 @@ struct window
328 /* True if this window is a minibuffer window. */ 328 /* True if this window is a minibuffer window. */
329 bool_bf mini : 1; 329 bool_bf mini : 1;
330 330
331 /* Meaningful only if contents is a window, true if this 331 /* Meaningful for internal windows only: true if this window is a
332 internal window is used in horizontal combination. */ 332 horizontal combination, false if it is a vertical
333 combination. */
333 bool_bf horizontal : 1; 334 bool_bf horizontal : 1;
334 335
335 /* True means must regenerate mode line of this window. */ 336 /* True means must regenerate mode line of this window. */
@@ -481,15 +482,14 @@ wset_next_buffers (struct window *w, Lisp_Object val)
481/* True if W is a minibuffer window. */ 482/* True if W is a minibuffer window. */
482#define MINI_WINDOW_P(W) ((W)->mini) 483#define MINI_WINDOW_P(W) ((W)->mini)
483 484
484/* 1 if W is a non-only minibuffer window. */ 485/* True if W is a minibuffer window on a frame that contains at least
485/* The first check is redundant and the second overly complicated. */ 486 one other window. */
486#define MINI_NON_ONLY_WINDOW_P(W) \ 487#define MINI_NON_ONLY_WINDOW_P(W) \
487 (MINI_WINDOW_P (W) \ 488 (MINI_WINDOW_P (W) && !NILP ((W)->prev))
488 && (EQ (W->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))
489 489
490/* 1 if W is a minibuffer-only window. */ 490/* True if W is a minibuffer window that is alone on its frame. */
491#define MINI_ONLY_WINDOW_P(W) \ 491#define MINI_ONLY_WINDOW_P(W) \
492 (MINI_WINDOW_P (W) && NILP (W->prev)) 492 (MINI_WINDOW_P (W) && NILP ((W)->prev))
493 493
494/* General window layout: 494/* General window layout:
495 495
@@ -518,29 +518,34 @@ wset_next_buffers (struct window *w, Lisp_Object val)
518 518
519/* A handy macro. */ 519/* A handy macro. */
520 520
521/* Non-nil if W is leaf (carry the buffer). */ 521/* Non-nil if window W is leaf window (has a buffer). */
522
523#define WINDOW_LEAF_P(W) \ 522#define WINDOW_LEAF_P(W) \
524 (BUFFERP ((W)->contents)) 523 (BUFFERP ((W)->contents))
525 524
526/* Non-nil if W is internal. */ 525/* Non-nil if window W is internal (is a parent window). */
527#define WINDOW_INTERNAL_P(W) \ 526#define WINDOW_INTERNAL_P(W) \
528 (WINDOWP ((W)->contents)) 527 (WINDOWP ((W)->contents))
529 528
530/* True if W is a member of horizontal combination. */ 529/* True if window W is a horizontal combination of windows. */
531#define WINDOW_HORIZONTAL_COMBINATION_P(W) \ 530#define WINDOW_HORIZONTAL_COMBINATION_P(W) \
532 (WINDOW_INTERNAL_P (W) && (W)->horizontal) 531 (WINDOW_INTERNAL_P (W) && (W)->horizontal)
533 532
534/* True if W is a member of vertical combination. */ 533/* True if window W is a vertical combination of windows. */
535#define WINDOW_VERTICAL_COMBINATION_P(W) \ 534#define WINDOW_VERTICAL_COMBINATION_P(W) \
536 (WINDOW_INTERNAL_P (W) && !(W)->horizontal) 535 (WINDOW_INTERNAL_P (W) && !(W)->horizontal)
537 536
538/* WINDOW's XFRAME. */ 537/* Window W's XFRAME. */
539#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) 538#define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W))))
540 539
541/* Whether WINDOW is a pseudo window. */ 540/* Whether window W is a pseudo window. */
542#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p) 541#define WINDOW_PSEUDO_P(W) ((W)->pseudo_window_p)
543 542
543/* Window W's buffer. */
544#define WINDOW_BUFFER(W) \
545 (WINDOW_LEAF_P(W) \
546 ? (W)->contents \
547 : Qnil) \
548
544/* Return the canonical column width of the frame of window W. */ 549/* Return the canonical column width of the frame of window W. */
545#define WINDOW_FRAME_COLUMN_WIDTH(W) \ 550#define WINDOW_FRAME_COLUMN_WIDTH(W) \
546 (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W)))) 551 (FRAME_COLUMN_WIDTH (WINDOW_XFRAME ((W))))
@@ -549,24 +554,24 @@ wset_next_buffers (struct window *w, Lisp_Object val)
549#define WINDOW_FRAME_LINE_HEIGHT(W) \ 554#define WINDOW_FRAME_LINE_HEIGHT(W) \
550 (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W)))) 555 (FRAME_LINE_HEIGHT (WINDOW_XFRAME ((W))))
551 556
552/* Return the pixel width of window W. 557/* Return the pixel width of window W. This includes dividers, scroll
553 This includes scroll bars and fringes. */ 558 bars, fringes and margins, if any. */
554#define WINDOW_PIXEL_WIDTH(W) (W)->pixel_width 559#define WINDOW_PIXEL_WIDTH(W) (W)->pixel_width
555 560
556/* Return the pixel height of window W. 561/* Return the pixel height of window W. This includes dividers, scroll
557 This includes header and mode lines, if any. */ 562 bars, header and mode lines, if any. */
558#define WINDOW_PIXEL_HEIGHT(W) (W)->pixel_height 563#define WINDOW_PIXEL_HEIGHT(W) (W)->pixel_height
559 564
560/* Return the width of window W in canonical column units. 565/* Return the width of window W in canonical column units. This
561 This includes scroll bars and fringes. 566 includes dividers, scroll bars, fringes and margins, if any. The
562 This value is adjusted such that the sum of the widths of all child 567 value is adjusted such that the sum of the widths of all child
563 windows equals the width of their parent window. */ 568 windows equals the width of their parent window. */
564#define WINDOW_TOTAL_COLS(W) (W)->total_cols 569#define WINDOW_TOTAL_COLS(W) (W)->total_cols
565 570
566/* Return the height of window W in canonical line units. 571/* Return the height of window W in canonical line units. This includes
567 This includes header and mode lines, if any. 572 dividers, scroll bars, header and mode lines, if any. The value is
568 This value is adjusted such that the sum of the heights of all child 573 adjusted such that the sum of the heights of all child windows equals
569 windows equals the height of their parent window. */ 574 the height of their parent window. */
570#define WINDOW_TOTAL_LINES(W) (W)->total_lines 575#define WINDOW_TOTAL_LINES(W) (W)->total_lines
571 576
572/* The smallest acceptable dimensions for a window. Anything smaller 577/* The smallest acceptable dimensions for a window. Anything smaller
@@ -581,31 +586,63 @@ wset_next_buffers (struct window *w, Lisp_Object val)
581#define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \ 586#define MIN_SAFE_WINDOW_PIXEL_HEIGHT(W) \
582 (WINDOW_FRAME_LINE_HEIGHT (W)) 587 (WINDOW_FRAME_LINE_HEIGHT (W))
583 588
589/* True if window W has no other windows to its left on its frame. */
590#define WINDOW_LEFTMOST_P(W) \
591 (WINDOW_LEFT_PIXEL_EDGE (W) == 0)
592
593/* True if window W has no other windows above it on its frame. */
594#define WINDOW_TOPMOST_P(W) \
595 (WINDOW_TOP_PIXEL_EDGE (W) == 0)
596
597/* True if window W has no other windows to its right on its frame. */
598#define WINDOW_RIGHTMOST_P(W) \
599 (WINDOW_RIGHT_PIXEL_EDGE (W) \
600 == (WINDOW_RIGHT_PIXEL_EDGE \
601 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
602
603/* True if window W has no other windows below it on its frame (the
604 minibuffer window is not counted in this respect unless W itself is a
605 minibuffer window). */
606#define WINDOW_BOTTOMMOST_P(W) \
607 (WINDOW_BOTTOM_PIXEL_EDGE (W) \
608 == (WINDOW_BOTTOM_PIXEL_EDGE \
609 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
610
611/* True if window W takes up the full width of its frame. */
612#define WINDOW_FULL_WIDTH_P(W) \
613 (WINDOW_PIXEL_WIDTH (W) \
614 == (WINDOW_PIXEL_WIDTH \
615 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
616
584/* Width of right divider of window W. */ 617/* Width of right divider of window W. */
585#define WINDOW_RIGHT_DIVIDER_WIDTH(W) \ 618#define WINDOW_RIGHT_DIVIDER_WIDTH(W) \
586 ((WINDOW_RIGHTMOST_P (W) || MINI_WINDOW_P (W)) \ 619 (WINDOW_RIGHTMOST_P (W) \
587 ? 0 \ 620 ? 0 : FRAME_RIGHT_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
588 : FRAME_RIGHT_DIVIDER_WIDTH (WINDOW_XFRAME (W))) 621
622/* Width of bottom divider of window W. */
623#define WINDOW_BOTTOM_DIVIDER_WIDTH(W) \
624 (((WINDOW_BOTTOMMOST_P (W) \
625 && NILP ((XWINDOW (FRAME_ROOT_WINDOW \
626 (WINDOW_XFRAME (W))))->next)) \
627 || EQ ((W)->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))) \
628 || (W)->pseudo_window_p) \
629 ? 0 : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
589 630
590/* Return the canonical frame column at which window W starts. 631/* Return the canonical frame column at which window W starts.
591 This includes a left-hand scroll bar, if any. */ 632 This includes a left-hand scroll bar, if any. */
592
593#define WINDOW_LEFT_EDGE_COL(W) (W)->left_col 633#define WINDOW_LEFT_EDGE_COL(W) (W)->left_col
594 634
595/* Return the canonical frame column before which window W ends. 635/* Return the canonical frame column before which window W ends.
596 This includes a right-hand scroll bar, if any. */ 636 This includes a right-hand scroll bar, if any. */
597
598#define WINDOW_RIGHT_EDGE_COL(W) \ 637#define WINDOW_RIGHT_EDGE_COL(W) \
599 (WINDOW_LEFT_EDGE_COL (W) + WINDOW_TOTAL_COLS (W)) 638 (WINDOW_LEFT_EDGE_COL (W) + WINDOW_TOTAL_COLS (W))
600 639
601/* Return the canonical frame line at which window W starts. 640/* Return the canonical frame line at which window W starts.
602 This includes a header line, if any. */ 641 This includes a header line, if any. */
603
604#define WINDOW_TOP_EDGE_LINE(W) (W)->top_line 642#define WINDOW_TOP_EDGE_LINE(W) (W)->top_line
605 643
606/* Return the canonical frame line before which window W ends. 644/* Return the canonical frame line before which window W ends.
607 This includes a mode line, if any. */ 645 This includes a mode line, if any. */
608
609#define WINDOW_BOTTOM_EDGE_LINE(W) \ 646#define WINDOW_BOTTOM_EDGE_LINE(W) \
610 (WINDOW_TOP_EDGE_LINE (W) + WINDOW_TOTAL_LINES (W)) 647 (WINDOW_TOP_EDGE_LINE (W) + WINDOW_TOTAL_LINES (W))
611 648
@@ -629,20 +666,17 @@ wset_next_buffers (struct window *w, Lisp_Object val)
629 666
630/* Return the frame x-position at which window W starts. 667/* Return the frame x-position at which window W starts.
631 This includes a left-hand scroll bar, if any. */ 668 This includes a left-hand scroll bar, if any. */
632
633#define WINDOW_LEFT_EDGE_X(W) \ 669#define WINDOW_LEFT_EDGE_X(W) \
634 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 670 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
635 + WINDOW_LEFT_PIXEL_EDGE (W)) 671 + WINDOW_LEFT_PIXEL_EDGE (W))
636 672
637/* Return the frame x- position before which window W ends. 673/* Return the frame x- position before which window W ends.
638 This includes a right-hand scroll bar, if any. */ 674 This includes a right-hand scroll bar, if any. */
639
640#define WINDOW_RIGHT_EDGE_X(W) \ 675#define WINDOW_RIGHT_EDGE_X(W) \
641 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 676 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
642 + WINDOW_RIGHT_PIXEL_EDGE (W)) 677 + WINDOW_RIGHT_PIXEL_EDGE (W))
643 678
644/* True if W is a menu bar window. */ 679/* True if W is a menu bar window. */
645
646#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) 680#if defined (HAVE_X_WINDOWS) && ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
647#define WINDOW_MENU_BAR_P(W) \ 681#define WINDOW_MENU_BAR_P(W) \
648 (WINDOWP (WINDOW_XFRAME (W)->menu_bar_window) \ 682 (WINDOWP (WINDOW_XFRAME (W)->menu_bar_window) \
@@ -661,72 +695,24 @@ wset_next_buffers (struct window *w, Lisp_Object val)
661#define WINDOW_TOOL_BAR_P(W) false 695#define WINDOW_TOOL_BAR_P(W) false
662#endif 696#endif
663 697
664/* Return the frame y-position at which window W starts. 698/* Return the frame y-position at which window W starts. */
665 This includes a header line, if any.
666
667 PXW: With a menu or tool bar this is not symmetric to the _X values
668 since it _does_ include the internal border width. */
669#define WINDOW_TOP_EDGE_Y(W) \ 699#define WINDOW_TOP_EDGE_Y(W) \
670 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \ 700 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
671 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \ 701 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
672 + WINDOW_TOP_PIXEL_EDGE (W)) 702 + WINDOW_TOP_PIXEL_EDGE (W))
673 703
674/* Return the frame y-position before which window W ends. 704/* Return the frame y-position before which window W ends. */
675 This includes a mode line, if any. */
676#define WINDOW_BOTTOM_EDGE_Y(W) \ 705#define WINDOW_BOTTOM_EDGE_Y(W) \
677 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \ 706 (((WINDOW_MENU_BAR_P (W) || WINDOW_TOOL_BAR_P (W)) \
678 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \ 707 ? 0 : FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W))) \
679 + WINDOW_BOTTOM_PIXEL_EDGE (W)) 708 + WINDOW_BOTTOM_PIXEL_EDGE (W))
680 709
681/* True if window W takes up the full width of its frame. */ 710/* Return the pixel value where the text (or left fringe) in window W
682#define WINDOW_FULL_WIDTH_P(W) \ 711 starts. */
683 (WINDOW_PIXEL_WIDTH (W) \
684 == (WINDOW_PIXEL_WIDTH \
685 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
686
687/* True if window W's has no other windows to its left in its frame. */
688
689#define WINDOW_LEFTMOST_P(W) \
690 (WINDOW_LEFT_PIXEL_EDGE (W) == 0)
691
692/* True if window W's has no other windows above in its frame. */
693#define WINDOW_TOPMOST_P(W) \
694 (WINDOW_TOP_PIXEL_EDGE (W) == 0)
695
696/* True if window W's has no other windows to its right in its frame. */
697#define WINDOW_RIGHTMOST_P(W) \
698 (WINDOW_RIGHT_PIXEL_EDGE (W) \
699 == (WINDOW_RIGHT_PIXEL_EDGE \
700 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
701
702/* True if window W's has no other windows below it in its frame
703 (the minibuffer window is not counted in this respect). */
704#define WINDOW_BOTTOMMOST_P(W) \
705 (WINDOW_BOTTOM_PIXEL_EDGE (W) \
706 == (WINDOW_BOTTOM_PIXEL_EDGE \
707 (XWINDOW (FRAME_ROOT_WINDOW (WINDOW_XFRAME (W)))))) \
708
709/* Return the frame column at which the text (or left fringe) in
710 window W starts. This is different from the `LEFT_EDGE' because it
711 does not include a left-hand scroll bar if any. */
712#define WINDOW_BOX_LEFT_EDGE_COL(W) \
713 (WINDOW_LEFT_EDGE_COL (W) \
714 + WINDOW_LEFT_SCROLL_BAR_COLS (W))
715
716/* Return the pixel value where the text (or left fringe) in
717 window W starts. This is different from the `LEFT_EDGE' because it
718 does not include a left-hand scroll bar if any. */
719#define WINDOW_BOX_LEFT_PIXEL_EDGE(W) \ 712#define WINDOW_BOX_LEFT_PIXEL_EDGE(W) \
720 (WINDOW_LEFT_PIXEL_EDGE (W) \ 713 (WINDOW_LEFT_PIXEL_EDGE (W) \
721 + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (W)) 714 + WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (W))
722 715
723/* Return the window column before which the text in window W ends.
724 This is different from WINDOW_RIGHT_EDGE_COL because it does not
725 include a scroll bar or window-separating line on the right edge. */
726#define WINDOW_BOX_RIGHT_EDGE_COL(W) \
727 (WINDOW_RIGHT_EDGE_COL (W) \
728 - WINDOW_RIGHT_SCROLL_BAR_COLS (W))
729
730/* Return the pixel value before which the text in window W ends. This 716/* Return the pixel value before which the text in window W ends. This
731 is different from the `RIGHT_EDGE' because it does not include a 717 is different from the `RIGHT_EDGE' because it does not include a
732 right-hand scroll bar or window-separating line on the right 718 right-hand scroll bar or window-separating line on the right
@@ -736,16 +722,16 @@ wset_next_buffers (struct window *w, Lisp_Object val)
736 - WINDOW_RIGHT_DIVIDER_WIDTH (W) \ 722 - WINDOW_RIGHT_DIVIDER_WIDTH (W) \
737 - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (W)) 723 - WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (W))
738 724
739/* Return the frame position at which the text (or left fringe) in 725/* Return the frame x-position at which the text (or left fringe) in
740 window W starts. This is different from the `LEFT_EDGE' because it 726 window W starts. This does not include a left-hand scroll bar if
741 does not include a left-hand scroll bar if any. */ 727 any. */
742#define WINDOW_BOX_LEFT_EDGE_X(W) \ 728#define WINDOW_BOX_LEFT_EDGE_X(W) \
743 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 729 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
744 + WINDOW_BOX_LEFT_PIXEL_EDGE (W)) 730 + WINDOW_BOX_LEFT_PIXEL_EDGE (W))
745 731
746/* Return the window column before which the text in window W ends. 732/* Return the frame x-position before which the text in window W ends.
747 This is different from WINDOW_RIGHT_EDGE_COL because it does not 733 This does not include a scroll bar, divider or window-separating line
748 include a scroll bar or window-separating line on the right edge. */ 734 on the right edge. */
749#define WINDOW_BOX_RIGHT_EDGE_X(W) \ 735#define WINDOW_BOX_RIGHT_EDGE_X(W) \
750 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \ 736 (FRAME_INTERNAL_BORDER_WIDTH (WINDOW_XFRAME (W)) \
751 + WINDOW_BOX_RIGHT_PIXEL_EDGE (W)) 737 + WINDOW_BOX_RIGHT_PIXEL_EDGE (W))
@@ -899,16 +885,6 @@ wset_next_buffers (struct window *w, Lisp_Object val)
899 ? WINDOW_BOX_RIGHT_EDGE_X (W) \ 885 ? WINDOW_BOX_RIGHT_EDGE_X (W) \
900 : WINDOW_LEFT_EDGE_X (W)) 886 : WINDOW_LEFT_EDGE_X (W))
901 887
902/* Width of bottom divider of window W. */
903#define WINDOW_BOTTOM_DIVIDER_WIDTH(W) \
904 (((WINDOW_BOTTOMMOST_P (W) \
905 && NILP ((XWINDOW (FRAME_ROOT_WINDOW \
906 (WINDOW_XFRAME (W))))->next)) \
907 || EQ ((W)->prev, FRAME_ROOT_WINDOW (WINDOW_XFRAME (W))) \
908 || (W)->pseudo_window_p) \
909 ? 0 \
910 : FRAME_BOTTOM_DIVIDER_WIDTH (WINDOW_XFRAME (W)))
911
912/* Height that a scroll bar in window W should have, if there is one. 888/* Height that a scroll bar in window W should have, if there is one.
913 Measured in pixels. If scroll bars are turned off, this is still 889 Measured in pixels. If scroll bars are turned off, this is still
914 nonzero. */ 890 nonzero. */
@@ -942,22 +918,22 @@ wset_next_buffers (struct window *w, Lisp_Object val)
942/* Height in pixels of the mode line. 918/* Height in pixels of the mode line.
943 May be zero if W doesn't have a mode line. */ 919 May be zero if W doesn't have a mode line. */
944#define WINDOW_MODE_LINE_HEIGHT(W) \ 920#define WINDOW_MODE_LINE_HEIGHT(W) \
945 (WINDOW_WANTS_MODELINE_P ((W)) \ 921 (window_wants_mode_line ((W)) \
946 ? CURRENT_MODE_LINE_HEIGHT (W) \ 922 ? CURRENT_MODE_LINE_HEIGHT (W) \
947 : 0) 923 : 0)
948 924
949#define WINDOW_MODE_LINE_LINES(W) \ 925#define WINDOW_MODE_LINE_LINES(W) \
950 WINDOW_WANTS_MODELINE_P (W) 926 window_wants_mode_line (W)
951 927
952/* Height in pixels of the header line. 928/* Height in pixels of the header line.
953 Zero if W doesn't have a header line. */ 929 Zero if W doesn't have a header line. */
954#define WINDOW_HEADER_LINE_HEIGHT(W) \ 930#define WINDOW_HEADER_LINE_HEIGHT(W) \
955 (WINDOW_WANTS_HEADER_LINE_P (W) \ 931 (window_wants_header_line (W) \
956 ? CURRENT_HEADER_LINE_HEIGHT (W) \ 932 ? CURRENT_HEADER_LINE_HEIGHT (W) \
957 : 0) 933 : 0)
958 934
959#define WINDOW_HEADER_LINE_LINES(W) \ 935#define WINDOW_HEADER_LINE_LINES(W) \
960 WINDOW_WANTS_HEADER_LINE_P (W) 936 window_wants_header_line (W)
961 937
962/* Pixel height of window W without mode line, bottom scroll bar and 938/* Pixel height of window W without mode line, bottom scroll bar and
963 bottom divider. */ 939 bottom divider. */
@@ -1114,10 +1090,13 @@ struct glyph *get_phys_cursor_glyph (struct window *w);
1114extern Lisp_Object Vwindow_list; 1090extern Lisp_Object Vwindow_list;
1115 1091
1116extern Lisp_Object window_list (void); 1092extern Lisp_Object window_list (void);
1093extern Lisp_Object window_parameter (struct window *, Lisp_Object parameter);
1117extern struct window *decode_live_window (Lisp_Object); 1094extern struct window *decode_live_window (Lisp_Object);
1118extern struct window *decode_any_window (Lisp_Object); 1095extern struct window *decode_any_window (Lisp_Object);
1119extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool); 1096extern bool compare_window_configurations (Lisp_Object, Lisp_Object, bool);
1120extern void mark_window_cursors_off (struct window *); 1097extern void mark_window_cursors_off (struct window *);
1098extern bool window_wants_mode_line (struct window *);
1099extern bool window_wants_header_line (struct window *);
1121extern int window_internal_height (struct window *); 1100extern int window_internal_height (struct window *);
1122extern int window_body_width (struct window *w, bool); 1101extern int window_body_width (struct window *w, bool);
1123enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS }; 1102enum margin_unit { MARGIN_IN_LINES, MARGIN_IN_PIXELS };
@@ -1133,7 +1112,6 @@ extern void init_window_once (void);
1133extern void init_window (void); 1112extern void init_window (void);
1134extern void syms_of_window (void); 1113extern void syms_of_window (void);
1135extern void keys_of_window (void); 1114extern void keys_of_window (void);
1136
1137/* Move cursor to row/column position VPOS/HPOS, pixel coordinates 1115/* Move cursor to row/column position VPOS/HPOS, pixel coordinates
1138 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y 1116 Y/X. HPOS/VPOS are window-relative row and column numbers and X/Y
1139 are window-relative pixel positions. This is always done during 1117 are window-relative pixel positions. This is always done during
diff --git a/src/xdisp.c b/src/xdisp.c
index 34ee877e6be..8bc5d81f448 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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,
@@ -2842,13 +2856,12 @@ init_iterator (struct it *it, struct window *w,
2842 2856
2843 /* Get dimensions of truncation and continuation glyphs. These are 2857 /* Get dimensions of truncation and continuation glyphs. These are
2844 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
2845 frames when the fringes are turned off. But leave the dimensions 2859 frames when the fringes are turned off. The no_special_glyphs slot
2846 zero for tooltip frames, as these glyphs look ugly there and also 2860 of the iterator's frame, when set, suppresses their display - by
2847 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. */
2848#ifdef HAVE_WINDOW_SYSTEM 2863#ifdef HAVE_WINDOW_SYSTEM
2849 if (!(FRAME_WINDOW_P (it->f) 2864 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
2850 && FRAMEP (tip_frame)
2851 && it->f == XFRAME (tip_frame)))
2852#endif 2865#endif
2853 { 2866 {
2854 if (it->line_wrap == TRUNCATE) 2867 if (it->line_wrap == TRUNCATE)
@@ -2920,7 +2933,7 @@ init_iterator (struct it *it, struct window *w,
2920 it->last_visible_x -= it->continuation_pixel_width; 2933 it->last_visible_x -= it->continuation_pixel_width;
2921 } 2934 }
2922 2935
2923 it->header_line_p = WINDOW_WANTS_HEADER_LINE_P (w); 2936 it->header_line_p = window_wants_header_line (w);
2924 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll; 2937 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
2925 } 2938 }
2926 2939
@@ -3019,7 +3032,7 @@ void
3019start_display (struct it *it, struct window *w, struct text_pos pos) 3032start_display (struct it *it, struct window *w, struct text_pos pos)
3020{ 3033{
3021 struct glyph_row *row; 3034 struct glyph_row *row;
3022 bool first_vpos = WINDOW_WANTS_HEADER_LINE_P (w); 3035 bool first_vpos = window_wants_header_line (w);
3023 3036
3024 row = w->desired_matrix->rows + first_vpos; 3037 row = w->desired_matrix->rows + first_vpos;
3025 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);
@@ -7755,9 +7768,8 @@ next_element_from_display_vector (struct it *it)
7755 7768
7756 /* 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.
7757 That seemed totally bogus - so I changed it... */ 7770 That seemed totally bogus - so I changed it... */
7758 gc = it->dpvec[it->current.dpvec_index]; 7771 if (it->dpend - it->dpvec > 0 /* empty dpvec[] is invalid */
7759 7772 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
7760 if (GLYPH_CODE_P (gc))
7761 { 7773 {
7762 struct face *this_face, *prev_face, *next_face; 7774 struct face *this_face, *prev_face, *next_face;
7763 7775
@@ -15799,7 +15811,7 @@ compute_window_start_on_continuation_line (struct window *w)
15799 15811
15800 /* Find the start of the continued line. This should be fast 15812 /* Find the start of the continued line. This should be fast
15801 because find_newline is fast (newline cache). */ 15813 because find_newline is fast (newline cache). */
15802 row = w->desired_matrix->rows + WINDOW_WANTS_HEADER_LINE_P (w); 15814 row = w->desired_matrix->rows + window_wants_header_line (w);
15803 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos), 15815 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
15804 row, DEFAULT_FACE_ID); 15816 row, DEFAULT_FACE_ID);
15805 reseat_at_previous_visible_line_start (&it); 15817 reseat_at_previous_visible_line_start (&it);
@@ -15949,7 +15961,7 @@ try_cursor_movement (Lisp_Object window, struct text_pos startp,
15949 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS); 15961 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
15950 15962
15951 top_scroll_margin = this_scroll_margin; 15963 top_scroll_margin = this_scroll_margin;
15952 if (WINDOW_WANTS_HEADER_LINE_P (w)) 15964 if (window_wants_header_line (w))
15953 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w); 15965 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
15954 15966
15955 /* Start with the row the cursor was displayed during the last 15967 /* Start with the row the cursor was displayed during the last
@@ -16732,7 +16744,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
16732 margin, even though this part handles windows that didn't 16744 margin, even though this part handles windows that didn't
16733 scroll at all. */ 16745 scroll at all. */
16734 int pixel_margin = margin * frame_line_height; 16746 int pixel_margin = margin * frame_line_height;
16735 bool header_line = WINDOW_WANTS_HEADER_LINE_P (w); 16747 bool header_line = window_wants_header_line (w);
16736 16748
16737 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop 16749 /* Note: We add an extra FRAME_LINE_HEIGHT, because the loop
16738 below, which finds the row to move point to, advances by 16750 below, which finds the row to move point to, advances by
@@ -17299,15 +17311,15 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
17299 || (w->column_number_displayed != -1 17311 || (w->column_number_displayed != -1
17300 && (w->column_number_displayed != current_column ()))) 17312 && (w->column_number_displayed != current_column ())))
17301 /* This means that the window has a mode line. */ 17313 /* This means that the window has a mode line. */
17302 && (WINDOW_WANTS_MODELINE_P (w) 17314 && (window_wants_mode_line (w)
17303 || WINDOW_WANTS_HEADER_LINE_P (w))) 17315 || window_wants_header_line (w)))
17304 { 17316 {
17305 17317
17306 display_mode_lines (w); 17318 display_mode_lines (w);
17307 17319
17308 /* If mode line height has changed, arrange for a thorough 17320 /* If mode line height has changed, arrange for a thorough
17309 immediate redisplay using the correct mode line height. */ 17321 immediate redisplay using the correct mode line height. */
17310 if (WINDOW_WANTS_MODELINE_P (w) 17322 if (window_wants_mode_line (w)
17311 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w)) 17323 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
17312 { 17324 {
17313 f->fonts_changed = true; 17325 f->fonts_changed = true;
@@ -17318,7 +17330,7 @@ redisplay_window (Lisp_Object window, bool just_this_one_p)
17318 17330
17319 /* If header line height has changed, arrange for a thorough 17331 /* If header line height has changed, arrange for a thorough
17320 immediate redisplay using the correct header line height. */ 17332 immediate redisplay using the correct header line height. */
17321 if (WINDOW_WANTS_HEADER_LINE_P (w) 17333 if (window_wants_header_line (w)
17322 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w)) 17334 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
17323 { 17335 {
17324 f->fonts_changed = true; 17336 f->fonts_changed = true;
@@ -17583,7 +17595,7 @@ try_window_reusing_current_matrix (struct window *w)
17583 return false; 17595 return false;
17584 17596
17585 /* If top-line visibility has changed, give up. */ 17597 /* If top-line visibility has changed, give up. */
17586 if (WINDOW_WANTS_HEADER_LINE_P (w) 17598 if (window_wants_header_line (w)
17587 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p) 17599 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
17588 return false; 17600 return false;
17589 17601
@@ -18818,7 +18830,7 @@ try_window_id (struct window *w)
18818 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix); 18830 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
18819 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos; 18831 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
18820 int end = (WINDOW_TOP_EDGE_LINE (w) 18832 int end = (WINDOW_TOP_EDGE_LINE (w)
18821 + WINDOW_WANTS_HEADER_LINE_P (w) 18833 + window_wants_header_line (w)
18822 + window_internal_height (w)); 18834 + window_internal_height (w));
18823 18835
18824#if defined (HAVE_GPM) || defined (MSDOS) 18836#if defined (HAVE_GPM) || defined (MSDOS)
@@ -18996,7 +19008,7 @@ try_window_id (struct window *w)
18996 { 19008 {
18997 /* Displayed to end of window, but no line containing text was 19009 /* Displayed to end of window, but no line containing text was
18998 displayed. Lines were deleted at the end of the window. */ 19010 displayed. Lines were deleted at the end of the window. */
18999 bool first_vpos = WINDOW_WANTS_HEADER_LINE_P (w); 19011 bool first_vpos = window_wants_header_line (w);
19000 int vpos = w->window_end_vpos; 19012 int vpos = w->window_end_vpos;
19001 struct glyph_row *current_row = current_matrix->rows + vpos; 19013 struct glyph_row *current_row = current_matrix->rows + vpos;
19002 struct glyph_row *desired_row = desired_matrix->rows + vpos; 19014 struct glyph_row *desired_row = desired_matrix->rows + vpos;
@@ -20696,7 +20708,7 @@ display_line (struct it *it, int cursor_vpos)
20696 ptrdiff_t min_pos = ZV + 1, max_pos = 0; 20708 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
20697 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT; 20709 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
20698 bool pending_handle_line_prefix = false; 20710 bool pending_handle_line_prefix = false;
20699 int header_line = WINDOW_WANTS_HEADER_LINE_P (it->w); 20711 int header_line = window_wants_header_line (it->w);
20700 bool hscroll_this_line = (cursor_vpos >= 0 20712 bool hscroll_this_line = (cursor_vpos >= 0
20701 && it->vpos == cursor_vpos - header_line 20713 && it->vpos == cursor_vpos - header_line
20702 && hscrolling_current_line_p (it->w)); 20714 && hscrolling_current_line_p (it->w));
@@ -22649,20 +22661,30 @@ display_mode_lines (struct window *w)
22649 line_number_displayed = false; 22661 line_number_displayed = false;
22650 w->column_number_displayed = -1; 22662 w->column_number_displayed = -1;
22651 22663
22652 if (WINDOW_WANTS_MODELINE_P (w)) 22664 if (window_wants_mode_line (w))
22653 { 22665 {
22666 Lisp_Object window_mode_line_format
22667 = window_parameter (w, Qmode_line_format);
22668
22654 struct window *sel_w = XWINDOW (old_selected_window); 22669 struct window *sel_w = XWINDOW (old_selected_window);
22655 22670
22656 /* Select mode line face based on the real selected window. */ 22671 /* Select mode line face based on the real selected window. */
22657 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),
22658 BVAR (current_buffer, mode_line_format)); 22673 NILP (window_mode_line_format)
22674 ? BVAR (current_buffer, mode_line_format)
22675 : window_mode_line_format);
22659 ++n; 22676 ++n;
22660 } 22677 }
22661 22678
22662 if (WINDOW_WANTS_HEADER_LINE_P (w)) 22679 if (window_wants_header_line (w))
22663 { 22680 {
22681 Lisp_Object window_header_line_format
22682 = window_parameter (w, Qheader_line_format);
22683
22664 display_mode_line (w, HEADER_LINE_FACE_ID, 22684 display_mode_line (w, HEADER_LINE_FACE_ID,
22665 BVAR (current_buffer, header_line_format)); 22685 NILP (window_header_line_format)
22686 ? BVAR (current_buffer, header_line_format)
22687 : window_header_line_format);
22666 ++n; 22688 ++n;
22667 } 22689 }
22668 22690
@@ -30442,13 +30464,67 @@ note_mouse_highlight (struct frame *f, int x, int y)
30442 && part != ON_HEADER_LINE)) 30464 && part != ON_HEADER_LINE))
30443 clear_mouse_face (hlinfo); 30465 clear_mouse_face (hlinfo);
30444 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
30445 /* Not on a window -> return. */ 30524 /* Not on a window -> return. */
30446 if (!WINDOWP (window)) 30525 if (!WINDOWP (window))
30447 return; 30526 return;
30448 30527
30449 /* Reset help_echo_string. It will get recomputed below. */
30450 help_echo_string = Qnil;
30451
30452 /* Convert to window-relative pixel coordinates. */ 30528 /* Convert to window-relative pixel coordinates. */
30453 w = XWINDOW (window); 30529 w = XWINDOW (window);
30454 frame_to_window_pixel_xy (w, &x, &y); 30530 frame_to_window_pixel_xy (w, &x, &y);
@@ -30486,11 +30562,13 @@ note_mouse_highlight (struct frame *f, int x, int y)
30486 { 30562 {
30487 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; 30563 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
30488 help_echo_string = build_string ("drag-mouse-1: resize"); 30564 help_echo_string = build_string ("drag-mouse-1: resize");
30565 goto set_cursor;
30489 } 30566 }
30490 else if (part == ON_RIGHT_DIVIDER) 30567 else if (part == ON_RIGHT_DIVIDER)
30491 { 30568 {
30492 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; 30569 cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor;
30493 help_echo_string = build_string ("drag-mouse-1: resize"); 30570 help_echo_string = build_string ("drag-mouse-1: resize");
30571 goto set_cursor;
30494 } 30572 }
30495 else if (part == ON_BOTTOM_DIVIDER) 30573 else if (part == ON_BOTTOM_DIVIDER)
30496 if (! WINDOW_BOTTOMMOST_P (w) 30574 if (! WINDOW_BOTTOMMOST_P (w)
@@ -30499,6 +30577,7 @@ note_mouse_highlight (struct frame *f, int x, int y)
30499 { 30577 {
30500 cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor; 30578 cursor = FRAME_X_OUTPUT (f)->vertical_drag_cursor;
30501 help_echo_string = build_string ("drag-mouse-1: resize"); 30579 help_echo_string = build_string ("drag-mouse-1: resize");
30580 goto set_cursor;
30502 } 30581 }
30503 else 30582 else
30504 cursor = FRAME_X_OUTPUT (f)->nontext_cursor; 30583 cursor = FRAME_X_OUTPUT (f)->nontext_cursor;
@@ -31193,8 +31272,15 @@ x_draw_right_divider (struct window *w)
31193 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);
31194 int x1 = WINDOW_RIGHT_EDGE_X (w); 31273 int x1 = WINDOW_RIGHT_EDGE_X (w);
31195 int y0 = WINDOW_TOP_EDGE_Y (w); 31274 int y0 = WINDOW_TOP_EDGE_Y (w);
31196 /* The bottom divider prevails. */ 31275 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
31197 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);
31198 31284
31199 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1); 31285 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
31200 } 31286 }
@@ -31213,8 +31299,22 @@ x_draw_bottom_divider (struct window *w)
31213 int x1 = WINDOW_RIGHT_EDGE_X (w); 31299 int x1 = WINDOW_RIGHT_EDGE_X (w);
31214 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);
31215 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;
31216 31303
31217 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);
31218 } 31318 }
31219} 31319}
31220 31320
@@ -31329,7 +31429,7 @@ expose_window (struct window *w, XRectangle *fr)
31329 } 31429 }
31330 31430
31331 /* Display the mode line if there is one. */ 31431 /* Display the mode line if there is one. */
31332 if (WINDOW_WANTS_MODELINE_P (w) 31432 if (window_wants_mode_line (w)
31333 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix), 31433 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
31334 row->enabled_p) 31434 row->enabled_p)
31335 && row->y < r_bottom) 31435 && row->y < r_bottom)
diff --git a/src/xfaces.c b/src/xfaces.c
index 4714b7b3cb8..86bb9b0b496 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -6232,7 +6232,7 @@ where R,G,B are numbers between 0 and 255 and name is an arbitrary string. */)
6232 int red, green, blue; 6232 int red, green, blue;
6233 int num; 6233 int num;
6234 6234
6235 while (fgets (buf, sizeof (buf), fp) != NULL) { 6235 while (fgets_unlocked (buf, sizeof (buf), fp) != NULL) {
6236 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)
6237 { 6237 {
6238#ifdef HAVE_NTGUI 6238#ifdef HAVE_NTGUI
diff --git a/src/xfns.c b/src/xfns.c
index 7be2253cc3b..d8bf9747191 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -1120,6 +1120,14 @@ enum mouse_cursor {
1120 mouse_cursor_hand, 1120 mouse_cursor_hand,
1121 mouse_cursor_horizontal_drag, 1121 mouse_cursor_horizontal_drag,
1122 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,
1123 mouse_cursor_max 1131 mouse_cursor_max
1124}; 1132};
1125 1133
@@ -1139,13 +1147,21 @@ struct mouse_cursor_types {
1139 1147
1140/* This array must stay in sync with enum mouse_cursor above! */ 1148/* This array must stay in sync with enum mouse_cursor above! */
1141static const struct mouse_cursor_types mouse_cursor_types[] = { 1149static const struct mouse_cursor_types mouse_cursor_types[] = {
1142 { "text", &Vx_pointer_shape, XC_xterm }, 1150 { "text", &Vx_pointer_shape, XC_xterm },
1143 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr }, 1151 { "nontext", &Vx_nontext_pointer_shape, XC_left_ptr },
1144 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch }, 1152 { "hourglass", &Vx_hourglass_pointer_shape, XC_watch },
1145 { "modeline", &Vx_mode_pointer_shape, XC_xterm }, 1153 { "modeline", &Vx_mode_pointer_shape, XC_xterm },
1146 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 }, 1154 { NULL, &Vx_sensitive_text_pointer_shape, XC_hand2 },
1147 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow }, 1155 { NULL, &Vx_window_horizontal_drag_shape, XC_sb_h_double_arrow },
1148 { 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 },
1149}; 1165};
1150 1166
1151struct mouse_cursor_data { 1167struct mouse_cursor_data {
@@ -1296,6 +1312,14 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
1296 INSTALL_CURSOR (hand_cursor, hand); 1312 INSTALL_CURSOR (hand_cursor, hand);
1297 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag); 1313 INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag);
1298 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);
1299 1323
1300#undef INSTALL_CURSOR 1324#undef INSTALL_CURSOR
1301 1325
@@ -3814,6 +3838,8 @@ This function is an internal primitive--use `make-frame' instead. */)
3814 "leftFringe", "LeftFringe", RES_TYPE_NUMBER); 3838 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
3815 x_default_parameter (f, parms, Qright_fringe, Qnil, 3839 x_default_parameter (f, parms, Qright_fringe, Qnil,
3816 "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);
3817 3843
3818 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground, 3844 x_default_scroll_bar_color_parameter (f, parms, Qscroll_bar_foreground,
3819 "scrollBarForeground", 3845 "scrollBarForeground",
@@ -5286,7 +5312,7 @@ Frames are listed from topmost (first) to bottommost (last). */)
5286static void 5312static void
5287x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag) 5313x_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
5288{ 5314{
5289#ifdef USE_GTK 5315#if defined (USE_GTK) && GTK_CHECK_VERSION (2, 18, 0)
5290 block_input (); 5316 block_input ();
5291 xg_frame_restack (f1, f2, above_flag); 5317 xg_frame_restack (f1, f2, above_flag);
5292 unblock_input (); 5318 unblock_input ();
@@ -6196,6 +6222,8 @@ x_create_tip_frame (struct x_display_info *dpyinfo, Lisp_Object parms)
6196 "cursorColor", "Foreground", RES_TYPE_STRING); 6222 "cursorColor", "Foreground", RES_TYPE_STRING);
6197 x_default_parameter (f, parms, Qborder_color, build_string ("black"), 6223 x_default_parameter (f, parms, Qborder_color, build_string ("black"),
6198 "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);
6199 6227
6200 /* Init faces before x_default_parameter is called for the 6228 /* Init faces before x_default_parameter is called for the
6201 scroll-bar-width parameter because otherwise we end up in 6229 scroll-bar-width parameter because otherwise we end up in
@@ -7486,6 +7514,7 @@ frame_parm_handler x_frame_parm_handlers[] =
7486 x_set_no_accept_focus, 7514 x_set_no_accept_focus,
7487 x_set_z_group, 7515 x_set_z_group,
7488 x_set_override_redirect, 7516 x_set_override_redirect,
7517 x_set_no_special_glyphs,
7489}; 7518};
7490 7519
7491void 7520void
@@ -7564,6 +7593,62 @@ This variable takes effect when you create a new frame
7564or when you set the mouse color. */); 7593or when you set the mouse color. */);
7565 Vx_window_vertical_drag_shape = Qnil; 7594 Vx_window_vertical_drag_shape = Qnil;
7566 7595
7596 DEFVAR_LISP ("x-window-left-edge-cursor",
7597 Vx_window_left_edge_shape,
7598 doc: /* Pointer shape indicating a left x-window edge can be dragged.
7599This variable takes effect when you create a new frame
7600or when you set the mouse color. */);
7601 Vx_window_left_edge_shape = Qnil;
7602
7603 DEFVAR_LISP ("x-window-top-left-corner-cursor",
7604 Vx_window_top_left_corner_shape,
7605 doc: /* Pointer shape indicating a top left x-window corner can be dragged.
7606This variable takes effect when you create a new frame
7607or when you set the mouse color. */);
7608 Vx_window_top_left_corner_shape = Qnil;
7609
7610 DEFVAR_LISP ("x-window-top-edge-cursor",
7611 Vx_window_top_edge_shape,
7612 doc: /* Pointer shape indicating a top x-window edge can be dragged.
7613This variable takes effect when you create a new frame
7614or when you set the mouse color. */);
7615 Vx_window_top_edge_shape = Qnil;
7616
7617 DEFVAR_LISP ("x-window-top-right-corner-cursor",
7618 Vx_window_top_right_corner_shape,
7619 doc: /* Pointer shape indicating a top right x-window corner can be dragged.
7620This variable takes effect when you create a new frame
7621or when you set the mouse color. */);
7622 Vx_window_top_right_corner_shape = Qnil;
7623
7624 DEFVAR_LISP ("x-window-right-edge-cursor",
7625 Vx_window_right_edge_shape,
7626 doc: /* Pointer shape indicating a right x-window edge can be dragged.
7627This variable takes effect when you create a new frame
7628or when you set the mouse color. */);
7629 Vx_window_right_edge_shape = Qnil;
7630
7631 DEFVAR_LISP ("x-window-bottom-right-corner-cursor",
7632 Vx_window_bottom_right_corner_shape,
7633 doc: /* Pointer shape indicating a bottom right x-window corner can be dragged.
7634This variable takes effect when you create a new frame
7635or when you set the mouse color. */);
7636 Vx_window_bottom_right_corner_shape = Qnil;
7637
7638 DEFVAR_LISP ("x-window-bottom-edge-cursor",
7639 Vx_window_bottom_edge_shape,
7640 doc: /* Pointer shape indicating a bottom x-window edge can be dragged.
7641This variable takes effect when you create a new frame
7642or when you set the mouse color. */);
7643 Vx_window_bottom_edge_shape = Qnil;
7644
7645 DEFVAR_LISP ("x-window-bottom-left-corner-cursor",
7646 Vx_window_bottom_left_corner_shape,
7647 doc: /* Pointer shape indicating a bottom left x-window corner can be dragged.
7648This variable takes effect when you create a new frame
7649or when you set the mouse color. */);
7650 Vx_window_bottom_left_corner_shape = Qnil;
7651
7567 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, 7652 DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel,
7568 doc: /* A string indicating the foreground color of the cursor box. */); 7653 doc: /* A string indicating the foreground color of the cursor box. */);
7569 Vx_cursor_fore_pixel = Qnil; 7654 Vx_cursor_fore_pixel = Qnil;
diff --git a/src/xterm.c b/src/xterm.c
index c8836b7ca78..a214cd81031 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -11757,6 +11757,22 @@ x_free_frame_resources (struct frame *f)
11757 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);
11758 if (f->output_data.x->vertical_drag_cursor != 0) 11758 if (f->output_data.x->vertical_drag_cursor != 0)
11759 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);
11760 11776
11761 XFlush (FRAME_X_DISPLAY (f)); 11777 XFlush (FRAME_X_DISPLAY (f));
11762 } 11778 }
diff --git a/src/xterm.h b/src/xterm.h
index a75257006fd..803feda99f3 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -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. */