]> code.delx.au - gnu-emacs/blob - src/frame.c
Fix line-move-visual's following of column in R2L lines.
[gnu-emacs] / src / frame.c
1 /* Generic frame functions.
2
3 Copyright (C) 1993-1995, 1997, 1999-2015 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19
20 #include <config.h>
21
22 #include <stdio.h>
23 #include <errno.h>
24 #include <limits.h>
25
26 #include <c-ctype.h>
27
28 #include "lisp.h"
29 #include "character.h"
30
31 #ifdef HAVE_WINDOW_SYSTEM
32 #include TERM_HEADER
33 #endif /* HAVE_WINDOW_SYSTEM */
34
35 #include "buffer.h"
36 /* These help us bind and responding to switch-frame events. */
37 #include "commands.h"
38 #include "keyboard.h"
39 #include "frame.h"
40 #include "blockinput.h"
41 #include "termchar.h"
42 #include "termhooks.h"
43 #include "dispextern.h"
44 #include "window.h"
45 #include "font.h"
46 #ifdef HAVE_WINDOW_SYSTEM
47 #include "fontset.h"
48 #endif
49 #include "cm.h"
50 #ifdef MSDOS
51 #include "msdos.h"
52 #include "dosfns.h"
53 #endif
54 #ifdef USE_X_TOOLKIT
55 #include "widget.h"
56 #endif
57
58 /* The currently selected frame. */
59
60 Lisp_Object selected_frame;
61
62 /* A frame which is not just a mini-buffer, or NULL if there are no such
63 frames. This is usually the most recent such frame that was selected. */
64
65 static struct frame *last_nonminibuf_frame;
66
67 /* False means there are no visible garbaged frames. */
68 bool frame_garbaged;
69
70 #ifdef HAVE_WINDOW_SYSTEM
71 static void x_report_frame_params (struct frame *, Lisp_Object *);
72 #endif
73
74 /* These setters are used only in this file, so they can be private. */
75 static void
76 fset_buffer_predicate (struct frame *f, Lisp_Object val)
77 {
78 f->buffer_predicate = val;
79 }
80 static void
81 fset_minibuffer_window (struct frame *f, Lisp_Object val)
82 {
83 f->minibuffer_window = val;
84 }
85
86 struct frame *
87 decode_live_frame (register Lisp_Object frame)
88 {
89 if (NILP (frame))
90 frame = selected_frame;
91 CHECK_LIVE_FRAME (frame);
92 return XFRAME (frame);
93 }
94
95 struct frame *
96 decode_any_frame (register Lisp_Object frame)
97 {
98 if (NILP (frame))
99 frame = selected_frame;
100 CHECK_FRAME (frame);
101 return XFRAME (frame);
102 }
103
104 #ifdef HAVE_WINDOW_SYSTEM
105
106 bool
107 window_system_available (struct frame *f)
108 {
109 return f ? FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f) : x_display_list != NULL;
110 }
111
112 #endif /* HAVE_WINDOW_SYSTEM */
113
114 struct frame *
115 decode_window_system_frame (Lisp_Object frame)
116 {
117 struct frame *f = decode_live_frame (frame);
118
119 if (!window_system_available (f))
120 error ("Window system frame should be used");
121 return f;
122 }
123
124 void
125 check_window_system (struct frame *f)
126 {
127 if (!window_system_available (f))
128 error (f ? "Window system frame should be used"
129 : "Window system is not in use or not initialized");
130 }
131
132 /* Return the value of frame parameter PROP in frame FRAME. */
133
134 Lisp_Object
135 get_frame_param (register struct frame *frame, Lisp_Object prop)
136 {
137 register Lisp_Object tem;
138
139 tem = Fassq (prop, frame->param_alist);
140 if (EQ (tem, Qnil))
141 return tem;
142 return Fcdr (tem);
143 }
144
145 /* Return 1 if `frame-inhibit-implied-resize' is non-nil or fullscreen
146 state of frame F would be affected by a vertical (horizontal if
147 HORIZONTAL is true) resize. PARAMETER is the symbol of the frame
148 parameter that is changed. */
149 bool
150 frame_inhibit_resize (struct frame *f, bool horizontal, Lisp_Object parameter)
151 {
152 return (EQ (frame_inhibit_implied_resize, Qt)
153 || (CONSP (frame_inhibit_implied_resize)
154 && !NILP (Fmemq (parameter, frame_inhibit_implied_resize)))
155 || !NILP (get_frame_param (f, Qfullscreen))
156 || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
157 }
158
159 static void
160 set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
161 {
162 int nlines;
163 int olines = FRAME_MENU_BAR_LINES (f);
164
165 /* Right now, menu bars don't work properly in minibuf-only frames;
166 most of the commands try to apply themselves to the minibuffer
167 frame itself, and get an error because you can't switch buffers
168 in or split the minibuffer window. */
169 if (FRAME_MINIBUF_ONLY_P (f))
170 return;
171
172 if (TYPE_RANGED_INTEGERP (int, value))
173 nlines = XINT (value);
174 else
175 nlines = 0;
176
177 if (nlines != olines)
178 {
179 windows_or_buffers_changed = 14;
180 FRAME_MENU_BAR_LINES (f) = nlines;
181 FRAME_MENU_BAR_HEIGHT (f) = nlines * FRAME_LINE_HEIGHT (f);
182 change_frame_size (f, FRAME_COLS (f),
183 FRAME_LINES (f) + olines - nlines,
184 0, 1, 0, 0);
185 }
186 }
187 \f
188 Lisp_Object Vframe_list;
189
190 \f
191 DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
192 doc: /* Return non-nil if OBJECT is a frame.
193 Value is:
194 t for a termcap frame (a character-only terminal),
195 'x' for an Emacs frame that is really an X window,
196 'w32' for an Emacs frame that is a window on MS-Windows display,
197 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
198 'pc' for a direct-write MS-DOS frame.
199 See also `frame-live-p'. */)
200 (Lisp_Object object)
201 {
202 if (!FRAMEP (object))
203 return Qnil;
204 switch (XFRAME (object)->output_method)
205 {
206 case output_initial: /* The initial frame is like a termcap frame. */
207 case output_termcap:
208 return Qt;
209 case output_x_window:
210 return Qx;
211 case output_w32:
212 return Qw32;
213 case output_msdos_raw:
214 return Qpc;
215 case output_ns:
216 return Qns;
217 default:
218 emacs_abort ();
219 }
220 }
221
222 DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
223 doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
224 Value is nil if OBJECT is not a live frame. If object is a live
225 frame, the return value indicates what sort of terminal device it is
226 displayed on. See the documentation of `framep' for possible
227 return values. */)
228 (Lisp_Object object)
229 {
230 return ((FRAMEP (object)
231 && FRAME_LIVE_P (XFRAME (object)))
232 ? Fframep (object)
233 : Qnil);
234 }
235
236 DEFUN ("window-system", Fwindow_system, Swindow_system, 0, 1, 0,
237 doc: /* The name of the window system that FRAME is displaying through.
238 The value is a symbol:
239 nil for a termcap frame (a character-only terminal),
240 'x' for an Emacs frame that is really an X window,
241 'w32' for an Emacs frame that is a window on MS-Windows display,
242 'ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
243 'pc' for a direct-write MS-DOS frame.
244
245 FRAME defaults to the currently selected frame.
246
247 Use of this function as a predicate is deprecated. Instead,
248 use `display-graphic-p' or any of the other `display-*-p'
249 predicates which report frame's specific UI-related capabilities. */)
250 (Lisp_Object frame)
251 {
252 Lisp_Object type;
253 if (NILP (frame))
254 frame = selected_frame;
255
256 type = Fframep (frame);
257
258 if (NILP (type))
259 wrong_type_argument (Qframep, frame);
260
261 if (EQ (type, Qt))
262 return Qnil;
263 else
264 return type;
265 }
266
267 /* Placeholder used by temacs -nw before window.el is loaded. */
268 DEFUN ("frame-windows-min-size", Fframe_windows_min_size,
269 Sframe_windows_min_size, 4, 4, 0,
270 doc: /* */)
271 (Lisp_Object frame, Lisp_Object horizontal,
272 Lisp_Object ignore, Lisp_Object pixelwise)
273 {
274 return make_number (0);
275 }
276
277 static int
278 frame_windows_min_size (Lisp_Object frame, Lisp_Object horizontal,
279 Lisp_Object ignore, Lisp_Object pixelwise)
280 {
281 return XINT (call4 (Qframe_windows_min_size, frame, horizontal,
282 ignore, pixelwise));
283 }
284
285
286 /* Make sure windows sizes of frame F are OK. new_width and new_height
287 are in pixels. A value of -1 means no change is requested for that
288 size (but the frame may still have to be resized to accommodate
289 windows with their minimum sizes). This can either issue a request
290 to resize the frame externally (via x_set_window_size), to resize the
291 frame internally (via resize_frame_windows) or do nothing at all.
292
293 The argument INHIBIT can assume the following values:
294
295 0 means to unconditionally call x_set_window_size even if sizes
296 apparently do not change. Fx_create_frame uses this to pass the
297 initial size to the window manager.
298
299 1 means to call x_set_window_size if the outer frame size really
300 changes. Fset_frame_size, Fset_frame_height, ... use this.
301
302 2 means to call x_set_window_size provided frame_inhibit_resize
303 allows it. The menu and tool bar code use this ("3" won't work
304 here in general because menu and tool bar are often not counted in
305 the frame's text height).
306
307 3 means call x_set_window_size if window minimum sizes must be
308 preserved or frame_inhibit_resize allows it. x_set_left_fringe,
309 x_set_scroll_bar_width, x_new_font ... use (or should use) this.
310
311 4 means call x_set_window_size only if window minimum sizes must be
312 preserved. x_set_right_divider_width, x_set_border_width and the
313 code responsible for wrapping the tool bar use this.
314
315 5 means to never call x_set_window_size. change_frame_size uses
316 this.
317
318 Note that even when x_set_window_size is not called, individual
319 windows may have to be resized (via `window--sanitize-window-sizes')
320 in order to support minimum size constraints.
321
322 PRETEND is as for change_frame_size. PARAMETER, if non-nil, is the
323 symbol of the parameter changed (like `menu-bar-lines', `font', ...).
324 This is passed on to frame_inhibit_resize to let the latter decide on
325 a case-by-case basis whether the frame may be resized externally. */
326 void
327 adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit,
328 bool pretend, Lisp_Object parameter)
329 {
330 int unit_width = FRAME_COLUMN_WIDTH (f);
331 int unit_height = FRAME_LINE_HEIGHT (f);
332 int old_pixel_width = FRAME_PIXEL_WIDTH (f);
333 int old_pixel_height = FRAME_PIXEL_HEIGHT (f);
334 int new_pixel_width, new_pixel_height;
335 /* The following two values are calculated from the old frame pixel
336 sizes and any "new" settings for tool bar, menu bar and internal
337 borders. We do it this way to detect whether we have to call
338 x_set_window_size as consequence of the new settings. */
339 int windows_width = FRAME_WINDOWS_WIDTH (f);
340 int windows_height = FRAME_WINDOWS_HEIGHT (f);
341 int min_windows_width, min_windows_height;
342 /* These are a bit tedious, maybe we should use a macro. */
343 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
344 int old_windows_width = WINDOW_PIXEL_WIDTH (r);
345 int old_windows_height
346 = (WINDOW_PIXEL_HEIGHT (r)
347 + (FRAME_HAS_MINIBUF_P (f)
348 ? WINDOW_PIXEL_HEIGHT (XWINDOW (FRAME_MINIBUF_WINDOW (f)))
349 : 0));
350 int new_windows_width, new_windows_height;
351 int old_text_width = FRAME_TEXT_WIDTH (f);
352 int old_text_height = FRAME_TEXT_HEIGHT (f);
353 /* If a size is < 0 use the old value. */
354 int new_text_width = (new_width >= 0) ? new_width : old_text_width;
355 int new_text_height = (new_height >= 0) ? new_height : old_text_height;
356 int new_cols, new_lines;
357 bool inhibit_horizontal, inhibit_vertical;
358 Lisp_Object frame;
359
360 XSETFRAME (frame, f);
361 /* The following two values are calculated from the old window body
362 sizes and any "new" settings for scroll bars, dividers, fringes and
363 margins (though the latter should have been processed already). */
364 min_windows_width
365 = frame_windows_min_size (frame, Qt, (inhibit == 5) ? Qt : Qnil, Qt);
366 min_windows_height
367 = frame_windows_min_size (frame, Qnil, (inhibit == 5) ? Qt : Qnil, Qt);
368
369 if (inhibit >= 2 && inhibit <= 4)
370 /* If INHIBIT is in [2..4] inhibit if the "old" window sizes stay
371 within the limits and either frame_inhibit_resize tells us to do
372 so or INHIBIT equals 4. */
373 {
374 inhibit_horizontal = ((windows_width >= min_windows_width
375 && (inhibit == 4
376 || frame_inhibit_resize (f, true, parameter)))
377 ? true : false);
378 inhibit_vertical = ((windows_height >= min_windows_height
379 && (inhibit == 4
380 || frame_inhibit_resize (f, false, parameter)))
381 ? true : false);
382 }
383 else
384 /* Otherwise inhibit if INHIBIT equals 5. */
385 inhibit_horizontal = inhibit_vertical = inhibit == 5;
386
387 new_pixel_width = ((inhibit_horizontal && (inhibit < 5))
388 ? old_pixel_width
389 : max (FRAME_TEXT_TO_PIXEL_WIDTH (f, new_text_width),
390 min_windows_width
391 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
392 new_windows_width = new_pixel_width - 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
393 new_text_width = FRAME_PIXEL_TO_TEXT_WIDTH (f, new_pixel_width);
394 new_cols = new_text_width / unit_width;
395
396 new_pixel_height = ((inhibit_vertical && (inhibit < 5))
397 ? old_pixel_height
398 : max (FRAME_TEXT_TO_PIXEL_HEIGHT (f, new_text_height),
399 min_windows_height
400 + FRAME_TOP_MARGIN_HEIGHT (f)
401 + 2 * FRAME_INTERNAL_BORDER_WIDTH (f)));
402 new_windows_height = (new_pixel_height
403 - FRAME_TOP_MARGIN_HEIGHT (f)
404 - 2 * FRAME_INTERNAL_BORDER_WIDTH (f));
405 new_text_height = FRAME_PIXEL_TO_TEXT_HEIGHT (f, new_pixel_height);
406 new_lines = new_text_height / unit_height;
407
408 #ifdef HAVE_WINDOW_SYSTEM
409 if (FRAME_WINDOW_P (f)
410 && f->can_x_set_window_size
411 && ((!inhibit_horizontal
412 && (new_pixel_width != old_pixel_width
413 || inhibit == 0 || inhibit == 2))
414 || (!inhibit_vertical
415 && (new_pixel_height != old_pixel_height
416 || inhibit == 0 || inhibit == 2))))
417 /* We are either allowed to change the frame size or the minimum
418 sizes request such a change. Do not care for fixing minimum
419 sizes here, we do that eventually when we're called from
420 change_frame_size. */
421 {
422 /* Make sure we respect fullheight and fullwidth. */
423 if (inhibit_horizontal)
424 new_text_width = old_text_width;
425 else if (inhibit_vertical)
426 new_text_height = old_text_height;
427
428 x_set_window_size (f, 0, new_text_width, new_text_height, 1);
429 f->resized_p = true;
430
431 return;
432 }
433 #endif
434
435 if (new_text_width == old_text_width
436 && new_text_height == old_text_height
437 && new_windows_width == old_windows_width
438 && new_windows_height == old_windows_height
439 && new_pixel_width == old_pixel_width
440 && new_pixel_height == old_pixel_height)
441 /* No change. Sanitize window sizes and return. */
442 {
443 sanitize_window_sizes (frame, Qt);
444 sanitize_window_sizes (frame, Qnil);
445
446 return;
447 }
448
449 block_input ();
450
451 #ifdef MSDOS
452 /* We only can set screen dimensions to certain values supported
453 by our video hardware. Try to find the smallest size greater
454 or equal to the requested dimensions. */
455 dos_set_window_size (&new_lines, &new_cols);
456 #endif
457
458 if (new_windows_width != old_windows_width)
459 {
460 resize_frame_windows (f, new_windows_width, 1, 1);
461
462 /* MSDOS frames cannot PRETEND, as they change frame size by
463 manipulating video hardware. */
464 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
465 FrameCols (FRAME_TTY (f)) = new_cols;
466
467 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (USE_GTK) && ! defined (HAVE_NS)
468 if (WINDOWP (f->tool_bar_window))
469 {
470 XWINDOW (f->tool_bar_window)->pixel_width = new_windows_width;
471 XWINDOW (f->tool_bar_window)->total_cols
472 = new_windows_width / unit_width;
473 }
474 #endif
475 }
476
477 if (new_windows_height != old_windows_height
478 /* When the top margin has changed we have to recalculate the top
479 edges of all windows. No such calculation is necessary for the
480 left edges. */
481 || WINDOW_TOP_PIXEL_EDGE (r) != FRAME_TOP_MARGIN_HEIGHT (f))
482 {
483 resize_frame_windows (f, new_windows_height, 0, 1);
484
485 /* MSDOS frames cannot PRETEND, as they change frame size by
486 manipulating video hardware. */
487 if ((FRAME_TERMCAP_P (f) && !pretend) || FRAME_MSDOS_P (f))
488 FrameRows (FRAME_TTY (f)) = new_lines + FRAME_TOP_MARGIN (f);
489 }
490
491 /* Assign new sizes. */
492 FRAME_TEXT_WIDTH (f) = new_text_width;
493 FRAME_TEXT_HEIGHT (f) = new_text_height;
494 FRAME_PIXEL_WIDTH (f) = new_pixel_width;
495 FRAME_PIXEL_HEIGHT (f) = new_pixel_height;
496 SET_FRAME_COLS (f, new_cols);
497 SET_FRAME_LINES (f, new_lines);
498
499 {
500 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
501 int text_area_x, text_area_y, text_area_width, text_area_height;
502
503 window_box (w, TEXT_AREA, &text_area_x, &text_area_y, &text_area_width,
504 &text_area_height);
505 if (w->cursor.x >= text_area_x + text_area_width)
506 w->cursor.hpos = w->cursor.x = 0;
507 if (w->cursor.y >= text_area_y + text_area_height)
508 w->cursor.vpos = w->cursor.y = 0;
509 }
510
511 /* Sanitize window sizes. */
512 sanitize_window_sizes (frame, Qt);
513 sanitize_window_sizes (frame, Qnil);
514
515 adjust_frame_glyphs (f);
516 calculate_costs (f);
517 SET_FRAME_GARBAGED (f);
518
519 /* A frame was "resized" if one of its pixelsizes changed, even if its
520 X window wasn't resized at all. */
521 f->resized_p = (new_pixel_width != old_pixel_width
522 || new_pixel_height != old_pixel_height);
523
524 unblock_input ();
525
526 run_window_configuration_change_hook (f);
527 }
528
529
530 struct frame *
531 make_frame (bool mini_p)
532 {
533 Lisp_Object frame;
534 register struct frame *f;
535 register struct window *rw, *mw;
536 register Lisp_Object root_window;
537 register Lisp_Object mini_window;
538
539 f = allocate_frame ();
540 XSETFRAME (frame, f);
541
542 #ifdef USE_GTK
543 /* Initialize Lisp data. Note that allocate_frame initializes all
544 Lisp data to nil, so do it only for slots which should not be nil. */
545 fset_tool_bar_position (f, Qtop);
546 #endif
547
548 /* Initialize non-Lisp data. Note that allocate_frame zeroes out all
549 non-Lisp data, so do it only for slots which should not be zero.
550 To avoid subtle bugs and for the sake of readability, it's better to
551 initialize enum members explicitly even if their values are zero. */
552 f->wants_modeline = true;
553 f->redisplay = true;
554 f->garbaged = true;
555 f->can_x_set_window_size = false;
556 f->can_run_window_configuration_change_hook = false;
557 f->column_width = 1; /* !FRAME_WINDOW_P value. */
558 f->line_height = 1; /* !FRAME_WINDOW_P value. */
559 #ifdef HAVE_WINDOW_SYSTEM
560 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
561 f->horizontal_scroll_bars = false;
562 f->want_fullscreen = FULLSCREEN_NONE;
563 #if ! defined (USE_GTK) && ! defined (HAVE_NS)
564 f->last_tool_bar_item = -1;
565 #endif
566 #endif
567
568 root_window = make_window ();
569 rw = XWINDOW (root_window);
570 if (mini_p)
571 {
572 mini_window = make_window ();
573 mw = XWINDOW (mini_window);
574 wset_next (rw, mini_window);
575 wset_prev (mw, root_window);
576 mw->mini = 1;
577 wset_frame (mw, frame);
578 fset_minibuffer_window (f, mini_window);
579 }
580 else
581 {
582 mini_window = Qnil;
583 wset_next (rw, Qnil);
584 fset_minibuffer_window (f, Qnil);
585 }
586
587 wset_frame (rw, frame);
588
589 /* 10 is arbitrary,
590 just so that there is "something there."
591 Correct size will be set up later with adjust_frame_size. */
592
593 SET_FRAME_COLS (f, 10);
594 SET_FRAME_LINES (f, 10);
595 SET_FRAME_WIDTH (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f));
596 SET_FRAME_HEIGHT (f, FRAME_LINES (f) * FRAME_LINE_HEIGHT (f));
597
598 rw->total_cols = 10;
599 rw->pixel_width = rw->total_cols * FRAME_COLUMN_WIDTH (f);
600 rw->total_lines = mini_p ? 9 : 10;
601 rw->pixel_height = rw->total_lines * FRAME_LINE_HEIGHT (f);
602
603 if (mini_p)
604 {
605 mw->top_line = rw->total_lines;
606 mw->pixel_top = rw->pixel_height;
607 mw->total_cols = rw->total_cols;
608 mw->pixel_width = rw->pixel_width;
609 mw->total_lines = 1;
610 mw->pixel_height = FRAME_LINE_HEIGHT (f);
611 }
612
613 /* Choose a buffer for the frame's root window. */
614 {
615 Lisp_Object buf = Fcurrent_buffer ();
616
617 /* If current buffer is hidden, try to find another one. */
618 if (BUFFER_HIDDEN_P (XBUFFER (buf)))
619 buf = other_buffer_safely (buf);
620
621 /* Use set_window_buffer, not Fset_window_buffer, and don't let
622 hooks be run by it. The reason is that the whole frame/window
623 arrangement is not yet fully initialized at this point. Windows
624 don't have the right size, glyph matrices aren't initialized
625 etc. Running Lisp functions at this point surely ends in a
626 SEGV. */
627 set_window_buffer (root_window, buf, 0, 0);
628 fset_buffer_list (f, list1 (buf));
629 }
630
631 if (mini_p)
632 {
633 set_window_buffer (mini_window,
634 (NILP (Vminibuffer_list)
635 ? get_minibuffer (0)
636 : Fcar (Vminibuffer_list)),
637 0, 0);
638 /* No horizontal scroll bars in minibuffers. */
639 wset_horizontal_scroll_bar (mw, Qnil);
640 }
641
642 fset_root_window (f, root_window);
643 fset_selected_window (f, root_window);
644 /* Make sure this window seems more recently used than
645 a newly-created, never-selected window. */
646 XWINDOW (f->selected_window)->use_time = ++window_select_count;
647
648 return f;
649 }
650 \f
651 #ifdef HAVE_WINDOW_SYSTEM
652 /* Make a frame using a separate minibuffer window on another frame.
653 MINI_WINDOW is the minibuffer window to use. nil means use the
654 default (the global minibuffer). */
655
656 struct frame *
657 make_frame_without_minibuffer (register Lisp_Object mini_window, KBOARD *kb, Lisp_Object display)
658 {
659 register struct frame *f;
660 struct gcpro gcpro1;
661
662 if (!NILP (mini_window))
663 CHECK_LIVE_WINDOW (mini_window);
664
665 if (!NILP (mini_window)
666 && FRAME_KBOARD (XFRAME (XWINDOW (mini_window)->frame)) != kb)
667 error ("Frame and minibuffer must be on the same terminal");
668
669 /* Make a frame containing just a root window. */
670 f = make_frame (0);
671
672 if (NILP (mini_window))
673 {
674 /* Use default-minibuffer-frame if possible. */
675 if (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
676 || ! FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame))))
677 {
678 Lisp_Object frame_dummy;
679
680 XSETFRAME (frame_dummy, f);
681 GCPRO1 (frame_dummy);
682 /* If there's no minibuffer frame to use, create one. */
683 kset_default_minibuffer_frame
684 (kb, call1 (intern ("make-initial-minibuffer-frame"), display));
685 UNGCPRO;
686 }
687
688 mini_window
689 = XFRAME (KVAR (kb, Vdefault_minibuffer_frame))->minibuffer_window;
690 }
691
692 fset_minibuffer_window (f, mini_window);
693
694 /* Make the chosen minibuffer window display the proper minibuffer,
695 unless it is already showing a minibuffer. */
696 if (NILP (Fmemq (XWINDOW (mini_window)->contents, Vminibuffer_list)))
697 /* Use set_window_buffer instead of Fset_window_buffer (see
698 discussion of bug#11984, bug#12025, bug#12026). */
699 set_window_buffer (mini_window,
700 (NILP (Vminibuffer_list)
701 ? get_minibuffer (0)
702 : Fcar (Vminibuffer_list)), 0, 0);
703 return f;
704 }
705
706 /* Make a frame containing only a minibuffer window. */
707
708 struct frame *
709 make_minibuffer_frame (void)
710 {
711 /* First make a frame containing just a root window, no minibuffer. */
712
713 register struct frame *f = make_frame (0);
714 register Lisp_Object mini_window;
715 register Lisp_Object frame;
716
717 XSETFRAME (frame, f);
718
719 f->auto_raise = 0;
720 f->auto_lower = 0;
721 f->no_split = 1;
722 f->wants_modeline = 0;
723
724 /* Now label the root window as also being the minibuffer.
725 Avoid infinite looping on the window chain by marking next pointer
726 as nil. */
727
728 mini_window = f->root_window;
729 fset_minibuffer_window (f, mini_window);
730 XWINDOW (mini_window)->mini = 1;
731 wset_next (XWINDOW (mini_window), Qnil);
732 wset_prev (XWINDOW (mini_window), Qnil);
733 wset_frame (XWINDOW (mini_window), frame);
734
735 /* Put the proper buffer in that window. */
736
737 /* Use set_window_buffer instead of Fset_window_buffer (see
738 discussion of bug#11984, bug#12025, bug#12026). */
739 set_window_buffer (mini_window,
740 (NILP (Vminibuffer_list)
741 ? get_minibuffer (0)
742 : Fcar (Vminibuffer_list)), 0, 0);
743 return f;
744 }
745 #endif /* HAVE_WINDOW_SYSTEM */
746 \f
747 /* Construct a frame that refers to a terminal. */
748
749 static printmax_t tty_frame_count;
750
751 struct frame *
752 make_initial_frame (void)
753 {
754 struct frame *f;
755 struct terminal *terminal;
756 Lisp_Object frame;
757
758 eassert (initial_kboard);
759
760 /* The first call must initialize Vframe_list. */
761 if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
762 Vframe_list = Qnil;
763
764 terminal = init_initial_terminal ();
765
766 f = make_frame (1);
767 XSETFRAME (frame, f);
768
769 Vframe_list = Fcons (frame, Vframe_list);
770
771 tty_frame_count = 1;
772 fset_name (f, build_pure_c_string ("F1"));
773
774 SET_FRAME_VISIBLE (f, 1);
775
776 f->output_method = terminal->type;
777 f->terminal = terminal;
778 f->terminal->reference_count++;
779 f->output_data.nothing = 0;
780
781 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
782 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
783
784 #ifdef HAVE_WINDOW_SYSTEM
785 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
786 f->horizontal_scroll_bars = false;
787 #endif
788
789 /* The default value of menu-bar-mode is t. */
790 set_menu_bar_lines (f, make_number (1), Qnil);
791
792 if (!noninteractive)
793 init_frame_faces (f);
794
795 last_nonminibuf_frame = f;
796
797 return f;
798 }
799
800
801 static struct frame *
802 make_terminal_frame (struct terminal *terminal)
803 {
804 register struct frame *f;
805 Lisp_Object frame;
806 char name[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
807
808 if (!terminal->name)
809 error ("Terminal is not live, can't create new frames on it");
810
811 f = make_frame (1);
812
813 XSETFRAME (frame, f);
814 Vframe_list = Fcons (frame, Vframe_list);
815
816 fset_name (f, make_formatted_string (name, "F%"pMd, ++tty_frame_count));
817
818 SET_FRAME_VISIBLE (f, 1);
819
820 f->terminal = terminal;
821 f->terminal->reference_count++;
822 #ifdef MSDOS
823 f->output_data.tty->display_info = &the_only_display_info;
824 if (!inhibit_window_system
825 && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
826 || XFRAME (selected_frame)->output_method == output_msdos_raw))
827 f->output_method = output_msdos_raw;
828 else
829 f->output_method = output_termcap;
830 #else /* not MSDOS */
831 f->output_method = output_termcap;
832 create_tty_output (f);
833 FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
834 FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
835 #endif /* not MSDOS */
836
837 #ifdef HAVE_WINDOW_SYSTEM
838 f->vertical_scroll_bar_type = vertical_scroll_bar_none;
839 f->horizontal_scroll_bars = false;
840 #endif
841
842 FRAME_MENU_BAR_LINES (f) = NILP (Vmenu_bar_mode) ? 0 : 1;
843 FRAME_LINES (f) = FRAME_LINES (f) - FRAME_MENU_BAR_LINES (f);
844 FRAME_MENU_BAR_HEIGHT (f) = FRAME_MENU_BAR_LINES (f) * FRAME_LINE_HEIGHT (f);
845 FRAME_TEXT_HEIGHT (f) = FRAME_TEXT_HEIGHT (f) - FRAME_MENU_BAR_HEIGHT (f);
846
847 /* Set the top frame to the newly created frame. */
848 if (FRAMEP (FRAME_TTY (f)->top_frame)
849 && FRAME_LIVE_P (XFRAME (FRAME_TTY (f)->top_frame)))
850 SET_FRAME_VISIBLE (XFRAME (FRAME_TTY (f)->top_frame), 2); /* obscured */
851
852 FRAME_TTY (f)->top_frame = frame;
853
854 if (!noninteractive)
855 init_frame_faces (f);
856
857 return f;
858 }
859
860 /* Get a suitable value for frame parameter PARAMETER for a newly
861 created frame, based on (1) the user-supplied frame parameter
862 alist SUPPLIED_PARMS, and (2) CURRENT_VALUE. */
863
864 static Lisp_Object
865 get_future_frame_param (Lisp_Object parameter,
866 Lisp_Object supplied_parms,
867 char *current_value)
868 {
869 Lisp_Object result;
870
871 result = Fassq (parameter, supplied_parms);
872 if (NILP (result))
873 result = Fassq (parameter, XFRAME (selected_frame)->param_alist);
874 if (NILP (result) && current_value != NULL)
875 result = build_string (current_value);
876 if (!NILP (result) && !STRINGP (result))
877 result = XCDR (result);
878 if (NILP (result) || !STRINGP (result))
879 result = Qnil;
880
881 return result;
882 }
883
884 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
885 1, 1, 0,
886 doc: /* Create an additional terminal frame, possibly on another terminal.
887 This function takes one argument, an alist specifying frame parameters.
888
889 You can create multiple frames on a single text terminal, but only one
890 of them (the selected terminal frame) is actually displayed.
891
892 In practice, generally you don't need to specify any parameters,
893 except when you want to create a new frame on another terminal.
894 In that case, the `tty' parameter specifies the device file to open,
895 and the `tty-type' parameter specifies the terminal type. Example:
896
897 (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))
898
899 Note that changing the size of one terminal frame automatically
900 affects all frames on the same terminal device. */)
901 (Lisp_Object parms)
902 {
903 struct frame *f;
904 struct terminal *t = NULL;
905 Lisp_Object frame, tem;
906 struct frame *sf = SELECTED_FRAME ();
907
908 #ifdef MSDOS
909 if (sf->output_method != output_msdos_raw
910 && sf->output_method != output_termcap)
911 emacs_abort ();
912 #else /* not MSDOS */
913
914 #ifdef WINDOWSNT /* This should work now! */
915 if (sf->output_method != output_termcap)
916 error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
917 #endif
918 #endif /* not MSDOS */
919
920 {
921 Lisp_Object terminal;
922
923 terminal = Fassq (Qterminal, parms);
924 if (CONSP (terminal))
925 {
926 terminal = XCDR (terminal);
927 t = decode_live_terminal (terminal);
928 }
929 #ifdef MSDOS
930 if (t && t != the_only_display_info.terminal)
931 /* msdos.c assumes a single tty_display_info object. */
932 error ("Multiple terminals are not supported on this platform");
933 if (!t)
934 t = the_only_display_info.terminal;
935 #endif
936 }
937
938 if (!t)
939 {
940 char *name = 0, *type = 0;
941 Lisp_Object tty, tty_type;
942 USE_SAFE_ALLOCA;
943
944 tty = get_future_frame_param
945 (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
946 ? FRAME_TTY (XFRAME (selected_frame))->name
947 : NULL));
948 if (!NILP (tty))
949 SAFE_ALLOCA_STRING (name, tty);
950
951 tty_type = get_future_frame_param
952 (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
953 ? FRAME_TTY (XFRAME (selected_frame))->type
954 : NULL));
955 if (!NILP (tty_type))
956 SAFE_ALLOCA_STRING (type, tty_type);
957
958 t = init_tty (name, type, 0); /* Errors are not fatal. */
959 SAFE_FREE ();
960 }
961
962 f = make_terminal_frame (t);
963
964 {
965 int width, height;
966 get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
967 adjust_frame_size (f, width, height - FRAME_MENU_BAR_LINES (f), 5, 0, Qnil);
968 }
969
970 adjust_frame_glyphs (f);
971 calculate_costs (f);
972 XSETFRAME (frame, f);
973
974 store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
975 store_in_alist (&parms, Qtty,
976 (t->display_info.tty->name
977 ? build_string (t->display_info.tty->name)
978 : Qnil));
979 Fmodify_frame_parameters (frame, parms);
980
981 /* Make the frame face alist be frame-specific, so that each
982 frame could change its face definitions independently. */
983 fset_face_alist (f, Fcopy_alist (sf->face_alist));
984 /* Simple Fcopy_alist isn't enough, because we need the contents of
985 the vectors which are the CDRs of associations in face_alist to
986 be copied as well. */
987 for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
988 XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
989 return frame;
990 }
991
992 \f
993 /* Perform the switch to frame FRAME.
994
995 If FRAME is a switch-frame event `(switch-frame FRAME1)', use
996 FRAME1 as frame.
997
998 If TRACK is non-zero and the frame that currently has the focus
999 redirects its focus to the selected frame, redirect that focused
1000 frame's focus to FRAME instead.
1001
1002 FOR_DELETION non-zero means that the selected frame is being
1003 deleted, which includes the possibility that the frame's terminal
1004 is dead.
1005
1006 The value of NORECORD is passed as argument to Fselect_window. */
1007
1008 Lisp_Object
1009 do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
1010 {
1011 struct frame *sf = SELECTED_FRAME ();
1012
1013 /* If FRAME is a switch-frame event, extract the frame we should
1014 switch to. */
1015 if (CONSP (frame)
1016 && EQ (XCAR (frame), Qswitch_frame)
1017 && CONSP (XCDR (frame)))
1018 frame = XCAR (XCDR (frame));
1019
1020 /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
1021 a switch-frame event to arrive after a frame is no longer live,
1022 especially when deleting the initial frame during startup. */
1023 CHECK_FRAME (frame);
1024 if (! FRAME_LIVE_P (XFRAME (frame)))
1025 return Qnil;
1026
1027 if (sf == XFRAME (frame))
1028 return frame;
1029
1030 /* If a frame's focus has been redirected toward the currently
1031 selected frame, we should change the redirection to point to the
1032 newly selected frame. This means that if the focus is redirected
1033 from a minibufferless frame to a surrogate minibuffer frame, we
1034 can use `other-window' to switch between all the frames using
1035 that minibuffer frame, and the focus redirection will follow us
1036 around. */
1037 #if 0
1038 /* This is too greedy; it causes inappropriate focus redirection
1039 that's hard to get rid of. */
1040 if (track)
1041 {
1042 Lisp_Object tail;
1043
1044 for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
1045 {
1046 Lisp_Object focus;
1047
1048 if (!FRAMEP (XCAR (tail)))
1049 emacs_abort ();
1050
1051 focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
1052
1053 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1054 Fredirect_frame_focus (XCAR (tail), frame);
1055 }
1056 }
1057 #else /* ! 0 */
1058 /* Instead, apply it only to the frame we're pointing to. */
1059 #ifdef HAVE_WINDOW_SYSTEM
1060 if (track && FRAME_WINDOW_P (XFRAME (frame)))
1061 {
1062 Lisp_Object focus, xfocus;
1063
1064 xfocus = x_get_focus_frame (XFRAME (frame));
1065 if (FRAMEP (xfocus))
1066 {
1067 focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
1068 if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
1069 Fredirect_frame_focus (xfocus, frame);
1070 }
1071 }
1072 #endif /* HAVE_X_WINDOWS */
1073 #endif /* ! 0 */
1074
1075 if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
1076 resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
1077
1078 if (FRAME_TERMCAP_P (XFRAME (frame)) || FRAME_MSDOS_P (XFRAME (frame)))
1079 {
1080 struct frame *f = XFRAME (frame);
1081 struct tty_display_info *tty = FRAME_TTY (f);
1082 Lisp_Object top_frame = tty->top_frame;
1083
1084 /* Don't mark the frame garbaged and/or obscured if we are
1085 switching to the frame that is already the top frame of that
1086 TTY. */
1087 if (!EQ (frame, top_frame))
1088 {
1089 if (FRAMEP (top_frame))
1090 /* Mark previously displayed frame as now obscured. */
1091 SET_FRAME_VISIBLE (XFRAME (top_frame), 2);
1092 SET_FRAME_VISIBLE (f, 1);
1093 /* If the new TTY frame changed dimensions, we need to
1094 resync term.c's idea of the frame size with the new
1095 frame's data. */
1096 if (FRAME_COLS (f) != FrameCols (tty))
1097 FrameCols (tty) = FRAME_COLS (f);
1098 if (FRAME_TOTAL_LINES (f) != FrameRows (tty))
1099 FrameRows (tty) = FRAME_TOTAL_LINES (f);
1100 }
1101 tty->top_frame = frame;
1102 }
1103
1104 selected_frame = frame;
1105 if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
1106 last_nonminibuf_frame = XFRAME (selected_frame);
1107
1108 Fselect_window (XFRAME (frame)->selected_window, norecord);
1109
1110 /* We want to make sure that the next event generates a frame-switch
1111 event to the appropriate frame. This seems kludgy to me, but
1112 before you take it out, make sure that evaluating something like
1113 (select-window (frame-root-window (new-frame))) doesn't end up
1114 with your typing being interpreted in the new frame instead of
1115 the one you're actually typing in. */
1116 internal_last_event_frame = Qnil;
1117
1118 return frame;
1119 }
1120
1121 DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
1122 doc: /* Select FRAME.
1123 Subsequent editing commands apply to its selected window.
1124 Optional argument NORECORD means to neither change the order of
1125 recently selected windows nor the buffer list.
1126
1127 The selection of FRAME lasts until the next time the user does
1128 something to select a different frame, or until the next time
1129 this function is called. If you are using a window system, the
1130 previously selected frame may be restored as the selected frame
1131 when returning to the command loop, because it still may have
1132 the window system's input focus. On a text terminal, the next
1133 redisplay will display FRAME.
1134
1135 This function returns FRAME, or nil if FRAME has been deleted. */)
1136 (Lisp_Object frame, Lisp_Object norecord)
1137 {
1138 return do_switch_frame (frame, 1, 0, norecord);
1139 }
1140
1141 DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
1142 doc: /* Handle a switch-frame event EVENT.
1143 Switch-frame events are usually bound to this function.
1144 A switch-frame event tells Emacs that the window manager has requested
1145 that the user's events be directed to the frame mentioned in the event.
1146 This function selects the selected window of the frame of EVENT.
1147
1148 If EVENT is frame object, handle it as if it were a switch-frame event
1149 to that frame. */)
1150 (Lisp_Object event)
1151 {
1152 /* Preserve prefix arg that the command loop just cleared. */
1153 kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
1154 run_hook (Qmouse_leave_buffer_hook);
1155 /* `switch-frame' implies a focus in. */
1156 call1 (intern ("handle-focus-in"), event);
1157 return do_switch_frame (event, 0, 0, Qnil);
1158 }
1159
1160 DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1161 doc: /* Return the frame that is now selected. */)
1162 (void)
1163 {
1164 return selected_frame;
1165 }
1166 \f
1167 DEFUN ("frame-list", Fframe_list, Sframe_list,
1168 0, 0, 0,
1169 doc: /* Return a list of all live frames. */)
1170 (void)
1171 {
1172 Lisp_Object frames;
1173 frames = Fcopy_sequence (Vframe_list);
1174 #ifdef HAVE_WINDOW_SYSTEM
1175 if (FRAMEP (tip_frame))
1176 frames = Fdelq (tip_frame, frames);
1177 #endif
1178 return frames;
1179 }
1180
1181 /* Return CANDIDATE if it can be used as 'other-than-FRAME' frame on the
1182 same tty (for tty frames) or among frames which uses FRAME's keyboard.
1183 If MINIBUF is nil, do not consider minibuffer-only candidate.
1184 If MINIBUF is `visible', do not consider an invisible candidate.
1185 If MINIBUF is a window, consider only its own frame and candidate now
1186 using that window as the minibuffer.
1187 If MINIBUF is 0, consider candidate if it is visible or iconified.
1188 Otherwise consider any candidate and return nil if CANDIDATE is not
1189 acceptable. */
1190
1191 static Lisp_Object
1192 candidate_frame (Lisp_Object candidate, Lisp_Object frame, Lisp_Object minibuf)
1193 {
1194 struct frame *c = XFRAME (candidate), *f = XFRAME (frame);
1195
1196 if ((!FRAME_TERMCAP_P (c) && !FRAME_TERMCAP_P (f)
1197 && FRAME_KBOARD (c) == FRAME_KBOARD (f))
1198 || (FRAME_TERMCAP_P (c) && FRAME_TERMCAP_P (f)
1199 && FRAME_TTY (c) == FRAME_TTY (f)))
1200 {
1201 if (NILP (minibuf))
1202 {
1203 if (!FRAME_MINIBUF_ONLY_P (c))
1204 return candidate;
1205 }
1206 else if (EQ (minibuf, Qvisible))
1207 {
1208 if (FRAME_VISIBLE_P (c))
1209 return candidate;
1210 }
1211 else if (WINDOWP (minibuf))
1212 {
1213 if (EQ (FRAME_MINIBUF_WINDOW (c), minibuf)
1214 || EQ (WINDOW_FRAME (XWINDOW (minibuf)), candidate)
1215 || EQ (WINDOW_FRAME (XWINDOW (minibuf)),
1216 FRAME_FOCUS_FRAME (c)))
1217 return candidate;
1218 }
1219 else if (XFASTINT (minibuf) == 0)
1220 {
1221 if (FRAME_VISIBLE_P (c) || FRAME_ICONIFIED_P (c))
1222 return candidate;
1223 }
1224 else
1225 return candidate;
1226 }
1227 return Qnil;
1228 }
1229
1230 /* Return the next frame in the frame list after FRAME. */
1231
1232 static Lisp_Object
1233 next_frame (Lisp_Object frame, Lisp_Object minibuf)
1234 {
1235 Lisp_Object f, tail;
1236 int passed = 0;
1237
1238 /* There must always be at least one frame in Vframe_list. */
1239 eassert (CONSP (Vframe_list));
1240
1241 while (passed < 2)
1242 FOR_EACH_FRAME (tail, f)
1243 {
1244 if (passed)
1245 {
1246 f = candidate_frame (f, frame, minibuf);
1247 if (!NILP (f))
1248 return f;
1249 }
1250 if (EQ (frame, f))
1251 passed++;
1252 }
1253 return frame;
1254 }
1255
1256 /* Return the previous frame in the frame list before FRAME. */
1257
1258 static Lisp_Object
1259 prev_frame (Lisp_Object frame, Lisp_Object minibuf)
1260 {
1261 Lisp_Object f, tail, prev = Qnil;
1262
1263 /* There must always be at least one frame in Vframe_list. */
1264 eassert (CONSP (Vframe_list));
1265
1266 FOR_EACH_FRAME (tail, f)
1267 {
1268 if (EQ (frame, f) && !NILP (prev))
1269 return prev;
1270 f = candidate_frame (f, frame, minibuf);
1271 if (!NILP (f))
1272 prev = f;
1273 }
1274
1275 /* We've scanned the entire list. */
1276 if (NILP (prev))
1277 /* We went through the whole frame list without finding a single
1278 acceptable frame. Return the original frame. */
1279 return frame;
1280 else
1281 /* There were no acceptable frames in the list before FRAME; otherwise,
1282 we would have returned directly from the loop. Since PREV is the last
1283 acceptable frame in the list, return it. */
1284 return prev;
1285 }
1286
1287
1288 DEFUN ("next-frame", Fnext_frame, Snext_frame, 0, 2, 0,
1289 doc: /* Return the next frame in the frame list after FRAME.
1290 It considers only frames on the same terminal as FRAME.
1291 By default, skip minibuffer-only frames.
1292 If omitted, FRAME defaults to the selected frame.
1293 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1294 If MINIFRAME is a window, include only its own frame
1295 and any frame now using that window as the minibuffer.
1296 If MINIFRAME is `visible', include all visible frames.
1297 If MINIFRAME is 0, include all visible and iconified frames.
1298 Otherwise, include all frames. */)
1299 (Lisp_Object frame, Lisp_Object miniframe)
1300 {
1301 if (NILP (frame))
1302 frame = selected_frame;
1303 CHECK_LIVE_FRAME (frame);
1304 return next_frame (frame, miniframe);
1305 }
1306
1307 DEFUN ("previous-frame", Fprevious_frame, Sprevious_frame, 0, 2, 0,
1308 doc: /* Return the previous frame in the frame list before FRAME.
1309 It considers only frames on the same terminal as FRAME.
1310 By default, skip minibuffer-only frames.
1311 If omitted, FRAME defaults to the selected frame.
1312 If optional argument MINIFRAME is nil, exclude minibuffer-only frames.
1313 If MINIFRAME is a window, include only its own frame
1314 and any frame now using that window as the minibuffer.
1315 If MINIFRAME is `visible', include all visible frames.
1316 If MINIFRAME is 0, include all visible and iconified frames.
1317 Otherwise, include all frames. */)
1318 (Lisp_Object frame, Lisp_Object miniframe)
1319 {
1320 if (NILP (frame))
1321 frame = selected_frame;
1322 CHECK_LIVE_FRAME (frame);
1323 return prev_frame (frame, miniframe);
1324 }
1325
1326 DEFUN ("last-nonminibuffer-frame", Flast_nonminibuf_frame,
1327 Slast_nonminibuf_frame, 0, 0, 0,
1328 doc: /* Return last non-minibuffer frame selected. */)
1329 (void)
1330 {
1331 Lisp_Object frame = Qnil;
1332
1333 if (last_nonminibuf_frame)
1334 XSETFRAME (frame, last_nonminibuf_frame);
1335
1336 return frame;
1337 }
1338 \f
1339 /* Return 1 if it is ok to delete frame F;
1340 0 if all frames aside from F are invisible.
1341 (Exception: if F is the terminal frame, and we are using X, return 1.) */
1342
1343 static int
1344 other_visible_frames (struct frame *f)
1345 {
1346 Lisp_Object frames, this;
1347
1348 FOR_EACH_FRAME (frames, this)
1349 {
1350 if (f == XFRAME (this))
1351 continue;
1352
1353 /* Verify that we can still talk to the frame's X window,
1354 and note any recent change in visibility. */
1355 #ifdef HAVE_X_WINDOWS
1356 if (FRAME_WINDOW_P (XFRAME (this)))
1357 x_sync (XFRAME (this));
1358 #endif
1359
1360 if (FRAME_VISIBLE_P (XFRAME (this))
1361 || FRAME_ICONIFIED_P (XFRAME (this))
1362 /* Allow deleting the terminal frame when at least one X
1363 frame exists. */
1364 || (FRAME_WINDOW_P (XFRAME (this)) && !FRAME_WINDOW_P (f)))
1365 return 1;
1366 }
1367 return 0;
1368 }
1369
1370 /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer
1371 window. Preferably use the selected frame's minibuffer window
1372 instead. If the selected frame doesn't have one, get some other
1373 frame's minibuffer window. SELECT non-zero means select the new
1374 minibuffer window. */
1375 static void
1376 check_minibuf_window (Lisp_Object frame, int select)
1377 {
1378 struct frame *f = decode_live_frame (frame);
1379
1380 XSETFRAME (frame, f);
1381
1382 if (WINDOWP (minibuf_window) && EQ (f->minibuffer_window, minibuf_window))
1383 {
1384 Lisp_Object frames, this, window = make_number (0);
1385
1386 if (!EQ (frame, selected_frame)
1387 && FRAME_HAS_MINIBUF_P (XFRAME (selected_frame)))
1388 window = FRAME_MINIBUF_WINDOW (XFRAME (selected_frame));
1389 else
1390 FOR_EACH_FRAME (frames, this)
1391 {
1392 if (!EQ (this, frame) && FRAME_HAS_MINIBUF_P (XFRAME (this)))
1393 {
1394 window = FRAME_MINIBUF_WINDOW (XFRAME (this));
1395 break;
1396 }
1397 }
1398
1399 /* Don't abort if no window was found (Bug#15247). */
1400 if (WINDOWP (window))
1401 {
1402 /* Use set_window_buffer instead of Fset_window_buffer (see
1403 discussion of bug#11984, bug#12025, bug#12026). */
1404 set_window_buffer (window, XWINDOW (minibuf_window)->contents, 0, 0);
1405 minibuf_window = window;
1406
1407 /* SELECT non-zero usually means that FRAME's minibuffer
1408 window was selected; select the new one. */
1409 if (select)
1410 Fselect_window (minibuf_window, Qnil);
1411 }
1412 }
1413 }
1414
1415
1416 /* Delete FRAME. When FORCE equals Qnoelisp, delete FRAME
1417 unconditionally. x_connection_closed and delete_terminal use
1418 this. Any other value of FORCE implements the semantics
1419 described for Fdelete_frame. */
1420 Lisp_Object
1421 delete_frame (Lisp_Object frame, Lisp_Object force)
1422 {
1423 struct frame *f = decode_any_frame (frame);
1424 struct frame *sf;
1425 struct kboard *kb;
1426
1427 int minibuffer_selected, is_tooltip_frame;
1428
1429 if (! FRAME_LIVE_P (f))
1430 return Qnil;
1431
1432 if (NILP (force) && !other_visible_frames (f))
1433 error ("Attempt to delete the sole visible or iconified frame");
1434
1435 /* x_connection_closed must have set FORCE to `noelisp' in order
1436 to delete the last frame, if it is gone. */
1437 if (NILP (XCDR (Vframe_list)) && !EQ (force, Qnoelisp))
1438 error ("Attempt to delete the only frame");
1439
1440 XSETFRAME (frame, f);
1441
1442 /* Does this frame have a minibuffer, and is it the surrogate
1443 minibuffer for any other frame? */
1444 if (FRAME_HAS_MINIBUF_P (f))
1445 {
1446 Lisp_Object frames, this;
1447
1448 FOR_EACH_FRAME (frames, this)
1449 {
1450 Lisp_Object fminiw;
1451
1452 if (EQ (this, frame))
1453 continue;
1454
1455 fminiw = FRAME_MINIBUF_WINDOW (XFRAME (this));
1456
1457 if (WINDOWP (fminiw) && EQ (frame, WINDOW_FRAME (XWINDOW (fminiw))))
1458 {
1459 /* If we MUST delete this frame, delete the other first.
1460 But do this only if FORCE equals `noelisp'. */
1461 if (EQ (force, Qnoelisp))
1462 delete_frame (this, Qnoelisp);
1463 else
1464 error ("Attempt to delete a surrogate minibuffer frame");
1465 }
1466 }
1467 }
1468
1469 is_tooltip_frame = !NILP (Fframe_parameter (frame, intern ("tooltip")));
1470
1471 /* Run `delete-frame-functions' unless FORCE is `noelisp' or
1472 frame is a tooltip. FORCE is set to `noelisp' when handling
1473 a disconnect from the terminal, so we don't dare call Lisp
1474 code. */
1475 if (NILP (Vrun_hooks) || is_tooltip_frame)
1476 ;
1477 else if (EQ (force, Qnoelisp))
1478 pending_funcalls
1479 = Fcons (list3 (Qrun_hook_with_args, Qdelete_frame_functions, frame),
1480 pending_funcalls);
1481 else
1482 {
1483 #ifdef HAVE_X_WINDOWS
1484 /* Also, save clipboard to the clipboard manager. */
1485 x_clipboard_manager_save_frame (frame);
1486 #endif
1487
1488 safe_call2 (Qrun_hook_with_args, Qdelete_frame_functions, frame);
1489 }
1490
1491 /* The hook may sometimes (indirectly) cause the frame to be deleted. */
1492 if (! FRAME_LIVE_P (f))
1493 return Qnil;
1494
1495 /* At this point, we are committed to deleting the frame.
1496 There is no more chance for errors to prevent it. */
1497
1498 minibuffer_selected = EQ (minibuf_window, selected_window);
1499 sf = SELECTED_FRAME ();
1500 /* Don't let the frame remain selected. */
1501 if (f == sf)
1502 {
1503 Lisp_Object tail;
1504 Lisp_Object frame1 = Qnil;
1505
1506 /* Look for another visible frame on the same terminal.
1507 Do not call next_frame here because it may loop forever.
1508 See http://debbugs.gnu.org/cgi/bugreport.cgi?bug=15025. */
1509 FOR_EACH_FRAME (tail, frame1)
1510 if (!EQ (frame, frame1)
1511 && (FRAME_TERMINAL (XFRAME (frame))
1512 == FRAME_TERMINAL (XFRAME (frame1)))
1513 && FRAME_VISIBLE_P (XFRAME (frame1)))
1514 break;
1515
1516 /* If there is none, find *some* other frame. */
1517 if (NILP (frame1) || EQ (frame1, frame))
1518 {
1519 FOR_EACH_FRAME (tail, frame1)
1520 {
1521 if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
1522 {
1523 /* Do not change a text terminal's top-frame. */
1524 struct frame *f1 = XFRAME (frame1);
1525 if (FRAME_TERMCAP_P (f1) || FRAME_MSDOS_P (f1))
1526 {
1527 Lisp_Object top_frame = FRAME_TTY (f1)->top_frame;
1528 if (!EQ (top_frame, frame))
1529 frame1 = top_frame;
1530 }
1531 break;
1532 }
1533 }
1534 }
1535 #ifdef NS_IMPL_COCOA
1536 else
1537 /* Under NS, there is no system mechanism for choosing a new
1538 window to get focus -- it is left to application code.
1539 So the portion of THIS application interfacing with NS
1540 needs to know about it. We call Fraise_frame, but the
1541 purpose is really to transfer focus. */
1542 Fraise_frame (frame1);
1543 #endif
1544
1545 do_switch_frame (frame1, 0, 1, Qnil);
1546 sf = SELECTED_FRAME ();
1547 }
1548
1549 /* Don't allow minibuf_window to remain on a deleted frame. */
1550 check_minibuf_window (frame, minibuffer_selected);
1551
1552 /* Don't let echo_area_window to remain on a deleted frame. */
1553 if (EQ (f->minibuffer_window, echo_area_window))
1554 echo_area_window = sf->minibuffer_window;
1555
1556 /* Clear any X selections for this frame. */
1557 #ifdef HAVE_X_WINDOWS
1558 if (FRAME_X_P (f))
1559 x_clear_frame_selections (f);
1560 #endif
1561
1562 /* Free glyphs.
1563 This function must be called before the window tree of the
1564 frame is deleted because windows contain dynamically allocated
1565 memory. */
1566 free_glyphs (f);
1567
1568 #ifdef HAVE_WINDOW_SYSTEM
1569 /* Give chance to each font driver to free a frame specific data. */
1570 font_update_drivers (f, Qnil);
1571 #endif
1572
1573 /* Mark all the windows that used to be on FRAME as deleted, and then
1574 remove the reference to them. */
1575 delete_all_child_windows (f->root_window);
1576 fset_root_window (f, Qnil);
1577
1578 Vframe_list = Fdelq (frame, Vframe_list);
1579 SET_FRAME_VISIBLE (f, 0);
1580
1581 /* Allow the vector of menu bar contents to be freed in the next
1582 garbage collection. The frame object itself may not be garbage
1583 collected until much later, because recent_keys and other data
1584 structures can still refer to it. */
1585 fset_menu_bar_vector (f, Qnil);
1586
1587 /* If FRAME's buffer lists contains killed
1588 buffers, this helps GC to reclaim them. */
1589 fset_buffer_list (f, Qnil);
1590 fset_buried_buffer_list (f, Qnil);
1591
1592 free_font_driver_list (f);
1593 #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
1594 xfree (f->namebuf);
1595 #endif
1596 xfree (f->decode_mode_spec_buffer);
1597 xfree (FRAME_INSERT_COST (f));
1598 xfree (FRAME_DELETEN_COST (f));
1599 xfree (FRAME_INSERTN_COST (f));
1600 xfree (FRAME_DELETE_COST (f));
1601
1602 /* Since some events are handled at the interrupt level, we may get
1603 an event for f at any time; if we zero out the frame's terminal
1604 now, then we may trip up the event-handling code. Instead, we'll
1605 promise that the terminal of the frame must be valid until we
1606 have called the window-system-dependent frame destruction
1607 routine. */
1608
1609
1610 {
1611 struct terminal *terminal;
1612 block_input ();
1613 if (FRAME_TERMINAL (f)->delete_frame_hook)
1614 (*FRAME_TERMINAL (f)->delete_frame_hook) (f);
1615 terminal = FRAME_TERMINAL (f);
1616 f->output_data.nothing = 0;
1617 f->terminal = 0; /* Now the frame is dead. */
1618 unblock_input ();
1619
1620 /* If needed, delete the terminal that this frame was on.
1621 (This must be done after the frame is killed.) */
1622 terminal->reference_count--;
1623 #ifdef USE_GTK
1624 /* FIXME: Deleting the terminal crashes emacs because of a GTK
1625 bug.
1626 http://lists.gnu.org/archive/html/emacs-devel/2011-10/msg00363.html */
1627 if (terminal->reference_count == 0 && terminal->type == output_x_window)
1628 terminal->reference_count = 1;
1629 #endif /* USE_GTK */
1630 if (terminal->reference_count == 0)
1631 {
1632 Lisp_Object tmp;
1633 XSETTERMINAL (tmp, terminal);
1634
1635 kb = NULL;
1636 Fdelete_terminal (tmp, NILP (force) ? Qt : force);
1637 }
1638 else
1639 kb = terminal->kboard;
1640 }
1641
1642 /* If we've deleted the last_nonminibuf_frame, then try to find
1643 another one. */
1644 if (f == last_nonminibuf_frame)
1645 {
1646 Lisp_Object frames, this;
1647
1648 last_nonminibuf_frame = 0;
1649
1650 FOR_EACH_FRAME (frames, this)
1651 {
1652 f = XFRAME (this);
1653 if (!FRAME_MINIBUF_ONLY_P (f))
1654 {
1655 last_nonminibuf_frame = f;
1656 break;
1657 }
1658 }
1659 }
1660
1661 /* If there's no other frame on the same kboard, get out of
1662 single-kboard state if we're in it for this kboard. */
1663 if (kb != NULL)
1664 {
1665 Lisp_Object frames, this;
1666 /* Some frame we found on the same kboard, or nil if there are none. */
1667 Lisp_Object frame_on_same_kboard = Qnil;
1668
1669 FOR_EACH_FRAME (frames, this)
1670 if (kb == FRAME_KBOARD (XFRAME (this)))
1671 frame_on_same_kboard = this;
1672
1673 if (NILP (frame_on_same_kboard))
1674 not_single_kboard_state (kb);
1675 }
1676
1677
1678 /* If we've deleted this keyboard's default_minibuffer_frame, try to
1679 find another one. Prefer minibuffer-only frames, but also notice
1680 frames with other windows. */
1681 if (kb != NULL && EQ (frame, KVAR (kb, Vdefault_minibuffer_frame)))
1682 {
1683 Lisp_Object frames, this;
1684
1685 /* The last frame we saw with a minibuffer, minibuffer-only or not. */
1686 Lisp_Object frame_with_minibuf = Qnil;
1687 /* Some frame we found on the same kboard, or nil if there are none. */
1688 Lisp_Object frame_on_same_kboard = Qnil;
1689
1690 FOR_EACH_FRAME (frames, this)
1691 {
1692 struct frame *f1 = XFRAME (this);
1693
1694 /* Consider only frames on the same kboard
1695 and only those with minibuffers. */
1696 if (kb == FRAME_KBOARD (f1)
1697 && FRAME_HAS_MINIBUF_P (f1))
1698 {
1699 frame_with_minibuf = this;
1700 if (FRAME_MINIBUF_ONLY_P (f1))
1701 break;
1702 }
1703
1704 if (kb == FRAME_KBOARD (f1))
1705 frame_on_same_kboard = this;
1706 }
1707
1708 if (!NILP (frame_on_same_kboard))
1709 {
1710 /* We know that there must be some frame with a minibuffer out
1711 there. If this were not true, all of the frames present
1712 would have to be minibufferless, which implies that at some
1713 point their minibuffer frames must have been deleted, but
1714 that is prohibited at the top; you can't delete surrogate
1715 minibuffer frames. */
1716 if (NILP (frame_with_minibuf))
1717 emacs_abort ();
1718
1719 kset_default_minibuffer_frame (kb, frame_with_minibuf);
1720 }
1721 else
1722 /* No frames left on this kboard--say no minibuffer either. */
1723 kset_default_minibuffer_frame (kb, Qnil);
1724 }
1725
1726 /* Cause frame titles to update--necessary if we now have just one frame. */
1727 if (!is_tooltip_frame)
1728 update_mode_lines = 15;
1729
1730 return Qnil;
1731 }
1732
1733 DEFUN ("delete-frame", Fdelete_frame, Sdelete_frame, 0, 2, "",
1734 doc: /* Delete FRAME, permanently eliminating it from use.
1735 FRAME defaults to the selected frame.
1736
1737 A frame may not be deleted if its minibuffer is used by other frames.
1738 Normally, you may not delete a frame if all other frames are invisible,
1739 but if the second optional argument FORCE is non-nil, you may do so.
1740
1741 This function runs `delete-frame-functions' before actually
1742 deleting the frame, unless the frame is a tooltip.
1743 The functions are run with one argument, the frame to be deleted. */)
1744 (Lisp_Object frame, Lisp_Object force)
1745 {
1746 return delete_frame (frame, !NILP (force) ? Qt : Qnil);
1747 }
1748
1749 \f
1750 /* Return mouse position in character cell units. */
1751
1752 DEFUN ("mouse-position", Fmouse_position, Smouse_position, 0, 0, 0,
1753 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1754 The position is given in canonical character cells, where (0, 0) is the
1755 upper-left corner of the frame, X is the horizontal offset, and Y is the
1756 vertical offset, measured in units of the frame's default character size.
1757 If Emacs is running on a mouseless terminal or hasn't been programmed
1758 to read the mouse position, it returns the selected frame for FRAME
1759 and nil for X and Y.
1760 If `mouse-position-function' is non-nil, `mouse-position' calls it,
1761 passing the normal return value to that function as an argument,
1762 and returns whatever that function returns. */)
1763 (void)
1764 {
1765 struct frame *f;
1766 Lisp_Object lispy_dummy;
1767 Lisp_Object x, y, retval;
1768 struct gcpro gcpro1;
1769
1770 f = SELECTED_FRAME ();
1771 x = y = Qnil;
1772
1773 /* It's okay for the hook to refrain from storing anything. */
1774 if (FRAME_TERMINAL (f)->mouse_position_hook)
1775 {
1776 enum scroll_bar_part party_dummy;
1777 Time time_dummy;
1778 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1779 &lispy_dummy, &party_dummy,
1780 &x, &y,
1781 &time_dummy);
1782 }
1783
1784 if (! NILP (x))
1785 {
1786 int col = XINT (x);
1787 int row = XINT (y);
1788 pixel_to_glyph_coords (f, col, row, &col, &row, NULL, 1);
1789 XSETINT (x, col);
1790 XSETINT (y, row);
1791 }
1792 XSETFRAME (lispy_dummy, f);
1793 retval = Fcons (lispy_dummy, Fcons (x, y));
1794 GCPRO1 (retval);
1795 if (!NILP (Vmouse_position_function))
1796 retval = call1 (Vmouse_position_function, retval);
1797 RETURN_UNGCPRO (retval);
1798 }
1799
1800 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
1801 Smouse_pixel_position, 0, 0, 0,
1802 doc: /* Return a list (FRAME X . Y) giving the current mouse frame and position.
1803 The position is given in pixel units, where (0, 0) is the
1804 upper-left corner of the frame, X is the horizontal offset, and Y is
1805 the vertical offset.
1806 If Emacs is running on a mouseless terminal or hasn't been programmed
1807 to read the mouse position, it returns the selected frame for FRAME
1808 and nil for X and Y. */)
1809 (void)
1810 {
1811 struct frame *f;
1812 Lisp_Object lispy_dummy;
1813 Lisp_Object x, y, retval;
1814 struct gcpro gcpro1;
1815
1816 f = SELECTED_FRAME ();
1817 x = y = Qnil;
1818
1819 /* It's okay for the hook to refrain from storing anything. */
1820 if (FRAME_TERMINAL (f)->mouse_position_hook)
1821 {
1822 enum scroll_bar_part party_dummy;
1823 Time time_dummy;
1824 (*FRAME_TERMINAL (f)->mouse_position_hook) (&f, -1,
1825 &lispy_dummy, &party_dummy,
1826 &x, &y,
1827 &time_dummy);
1828 }
1829
1830 XSETFRAME (lispy_dummy, f);
1831 retval = Fcons (lispy_dummy, Fcons (x, y));
1832 GCPRO1 (retval);
1833 if (!NILP (Vmouse_position_function))
1834 retval = call1 (Vmouse_position_function, retval);
1835 RETURN_UNGCPRO (retval);
1836 }
1837
1838 #ifdef HAVE_WINDOW_SYSTEM
1839
1840 /* On frame F, convert character coordinates X and Y to pixel
1841 coordinates *PIX_X and *PIX_Y. */
1842
1843 static void
1844 frame_char_to_pixel_position (struct frame *f, int x, int y,
1845 int *pix_x, int *pix_y)
1846 {
1847 *pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
1848 *pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
1849
1850 if (*pix_x < 0)
1851 *pix_x = 0;
1852 if (*pix_x > FRAME_PIXEL_WIDTH (f))
1853 *pix_x = FRAME_PIXEL_WIDTH (f);
1854
1855 if (*pix_y < 0)
1856 *pix_y = 0;
1857 if (*pix_y > FRAME_PIXEL_HEIGHT (f))
1858 *pix_y = FRAME_PIXEL_HEIGHT (f);
1859 }
1860
1861 /* On frame F, reposition mouse pointer to character coordinates X and Y. */
1862
1863 static void
1864 frame_set_mouse_position (struct frame *f, int x, int y)
1865 {
1866 int pix_x, pix_y;
1867
1868 frame_char_to_pixel_position (f, x, y, &pix_x, &pix_y);
1869 frame_set_mouse_pixel_position (f, pix_x, pix_y);
1870 }
1871
1872 #endif /* HAVE_WINDOW_SYSTEM */
1873
1874 DEFUN ("set-mouse-position", Fset_mouse_position, Sset_mouse_position, 3, 3, 0,
1875 doc: /* Move the mouse pointer to the center of character cell (X,Y) in FRAME.
1876 Coordinates are relative to the frame, not a window,
1877 so the coordinates of the top left character in the frame
1878 may be nonzero due to left-hand scroll bars or the menu bar.
1879
1880 The position is given in canonical character cells, where (0, 0) is
1881 the upper-left corner of the frame, X is the horizontal offset, and
1882 Y is the vertical offset, measured in units of the frame's default
1883 character size.
1884
1885 This function is a no-op for an X frame that is not visible.
1886 If you have just created a frame, you must wait for it to become visible
1887 before calling this function on it, like this.
1888 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1889 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1890 {
1891 CHECK_LIVE_FRAME (frame);
1892 CHECK_TYPE_RANGED_INTEGER (int, x);
1893 CHECK_TYPE_RANGED_INTEGER (int, y);
1894
1895 /* I think this should be done with a hook. */
1896 #ifdef HAVE_WINDOW_SYSTEM
1897 if (FRAME_WINDOW_P (XFRAME (frame)))
1898 /* Warping the mouse will cause enternotify and focus events. */
1899 frame_set_mouse_position (XFRAME (frame), XINT (x), XINT (y));
1900 #else
1901 #if defined (MSDOS)
1902 if (FRAME_MSDOS_P (XFRAME (frame)))
1903 {
1904 Fselect_frame (frame, Qnil);
1905 mouse_moveto (XINT (x), XINT (y));
1906 }
1907 #else
1908 #ifdef HAVE_GPM
1909 {
1910 Fselect_frame (frame, Qnil);
1911 term_mouse_moveto (XINT (x), XINT (y));
1912 }
1913 #endif
1914 #endif
1915 #endif
1916
1917 return Qnil;
1918 }
1919
1920 DEFUN ("set-mouse-pixel-position", Fset_mouse_pixel_position,
1921 Sset_mouse_pixel_position, 3, 3, 0,
1922 doc: /* Move the mouse pointer to pixel position (X,Y) in FRAME.
1923 The position is given in pixels, where (0, 0) is the upper-left corner
1924 of the frame, X is the horizontal offset, and Y is the vertical offset.
1925
1926 Note, this is a no-op for an X frame that is not visible.
1927 If you have just created a frame, you must wait for it to become visible
1928 before calling this function on it, like this.
1929 (while (not (frame-visible-p frame)) (sleep-for .5)) */)
1930 (Lisp_Object frame, Lisp_Object x, Lisp_Object y)
1931 {
1932 CHECK_LIVE_FRAME (frame);
1933 CHECK_TYPE_RANGED_INTEGER (int, x);
1934 CHECK_TYPE_RANGED_INTEGER (int, y);
1935
1936 /* I think this should be done with a hook. */
1937 #ifdef HAVE_WINDOW_SYSTEM
1938 if (FRAME_WINDOW_P (XFRAME (frame)))
1939 /* Warping the mouse will cause enternotify and focus events. */
1940 frame_set_mouse_pixel_position (XFRAME (frame), XINT (x), XINT (y));
1941 #else
1942 #if defined (MSDOS)
1943 if (FRAME_MSDOS_P (XFRAME (frame)))
1944 {
1945 Fselect_frame (frame, Qnil);
1946 mouse_moveto (XINT (x), XINT (y));
1947 }
1948 #else
1949 #ifdef HAVE_GPM
1950 {
1951 Fselect_frame (frame, Qnil);
1952 term_mouse_moveto (XINT (x), XINT (y));
1953 }
1954 #endif
1955 #endif
1956 #endif
1957
1958 return Qnil;
1959 }
1960 \f
1961 static void make_frame_visible_1 (Lisp_Object);
1962
1963 DEFUN ("make-frame-visible", Fmake_frame_visible, Smake_frame_visible,
1964 0, 1, "",
1965 doc: /* Make the frame FRAME visible (assuming it is an X window).
1966 If omitted, FRAME defaults to the currently selected frame. */)
1967 (Lisp_Object frame)
1968 {
1969 struct frame *f = decode_live_frame (frame);
1970
1971 /* I think this should be done with a hook. */
1972 #ifdef HAVE_WINDOW_SYSTEM
1973 if (FRAME_WINDOW_P (f))
1974 x_make_frame_visible (f);
1975 #endif
1976
1977 make_frame_visible_1 (f->root_window);
1978
1979 /* Make menu bar update for the Buffers and Frames menus. */
1980 /* windows_or_buffers_changed = 15; FIXME: Why? */
1981
1982 XSETFRAME (frame, f);
1983 return frame;
1984 }
1985
1986 /* Update the display_time slot of the buffers shown in WINDOW
1987 and all its descendants. */
1988
1989 static void
1990 make_frame_visible_1 (Lisp_Object window)
1991 {
1992 struct window *w;
1993
1994 for (; !NILP (window); window = w->next)
1995 {
1996 w = XWINDOW (window);
1997 if (WINDOWP (w->contents))
1998 make_frame_visible_1 (w->contents);
1999 else
2000 bset_display_time (XBUFFER (w->contents), Fcurrent_time ());
2001 }
2002 }
2003
2004 DEFUN ("make-frame-invisible", Fmake_frame_invisible, Smake_frame_invisible,
2005 0, 2, "",
2006 doc: /* Make the frame FRAME invisible.
2007 If omitted, FRAME defaults to the currently selected frame.
2008 On graphical displays, invisible frames are not updated and are
2009 usually not displayed at all, even in a window system's \"taskbar\".
2010
2011 Normally you may not make FRAME invisible if all other frames are invisible,
2012 but if the second optional argument FORCE is non-nil, you may do so.
2013
2014 This function has no effect on text terminal frames. Such frames are
2015 always considered visible, whether or not they are currently being
2016 displayed in the terminal. */)
2017 (Lisp_Object frame, Lisp_Object force)
2018 {
2019 struct frame *f = decode_live_frame (frame);
2020
2021 if (NILP (force) && !other_visible_frames (f))
2022 error ("Attempt to make invisible the sole visible or iconified frame");
2023
2024 /* Don't allow minibuf_window to remain on an invisible frame. */
2025 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2026
2027 /* I think this should be done with a hook. */
2028 #ifdef HAVE_WINDOW_SYSTEM
2029 if (FRAME_WINDOW_P (f))
2030 x_make_frame_invisible (f);
2031 #endif
2032
2033 /* Make menu bar update for the Buffers and Frames menus. */
2034 windows_or_buffers_changed = 16;
2035
2036 return Qnil;
2037 }
2038
2039 DEFUN ("iconify-frame", Ficonify_frame, Siconify_frame,
2040 0, 1, "",
2041 doc: /* Make the frame FRAME into an icon.
2042 If omitted, FRAME defaults to the currently selected frame. */)
2043 (Lisp_Object frame)
2044 {
2045 struct frame *f = decode_live_frame (frame);
2046
2047 /* Don't allow minibuf_window to remain on an iconified frame. */
2048 check_minibuf_window (frame, EQ (minibuf_window, selected_window));
2049
2050 /* I think this should be done with a hook. */
2051 #ifdef HAVE_WINDOW_SYSTEM
2052 if (FRAME_WINDOW_P (f))
2053 x_iconify_frame (f);
2054 #endif
2055
2056 /* Make menu bar update for the Buffers and Frames menus. */
2057 windows_or_buffers_changed = 17;
2058
2059 return Qnil;
2060 }
2061
2062 DEFUN ("frame-visible-p", Fframe_visible_p, Sframe_visible_p,
2063 1, 1, 0,
2064 doc: /* Return t if FRAME is \"visible\" (actually in use for display).
2065 Return the symbol `icon' if FRAME is iconified or \"minimized\".
2066 Return nil if FRAME was made invisible, via `make-frame-invisible'.
2067 On graphical displays, invisible frames are not updated and are
2068 usually not displayed at all, even in a window system's \"taskbar\".
2069
2070 If FRAME is a text terminal frame, this always returns t.
2071 Such frames are always considered visible, whether or not they are
2072 currently being displayed on the terminal. */)
2073 (Lisp_Object frame)
2074 {
2075 CHECK_LIVE_FRAME (frame);
2076
2077 if (FRAME_VISIBLE_P (XFRAME (frame)))
2078 return Qt;
2079 if (FRAME_ICONIFIED_P (XFRAME (frame)))
2080 return Qicon;
2081 return Qnil;
2082 }
2083
2084 DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
2085 0, 0, 0,
2086 doc: /* Return a list of all frames now \"visible\" (being updated). */)
2087 (void)
2088 {
2089 Lisp_Object tail, frame, value = Qnil;
2090
2091 FOR_EACH_FRAME (tail, frame)
2092 if (FRAME_VISIBLE_P (XFRAME (frame)))
2093 value = Fcons (frame, value);
2094
2095 return value;
2096 }
2097
2098
2099 DEFUN ("raise-frame", Fraise_frame, Sraise_frame, 0, 1, "",
2100 doc: /* Bring FRAME to the front, so it occludes any frames it overlaps.
2101 If FRAME is invisible or iconified, make it visible.
2102 If you don't specify a frame, the selected frame is used.
2103 If Emacs is displaying on an ordinary terminal or some other device which
2104 doesn't support multiple overlapping frames, this function selects FRAME. */)
2105 (Lisp_Object frame)
2106 {
2107 struct frame *f = decode_live_frame (frame);
2108
2109 XSETFRAME (frame, f);
2110
2111 if (FRAME_TERMCAP_P (f))
2112 /* On a text terminal select FRAME. */
2113 Fselect_frame (frame, Qnil);
2114 else
2115 /* Do like the documentation says. */
2116 Fmake_frame_visible (frame);
2117
2118 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2119 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 1);
2120
2121 return Qnil;
2122 }
2123
2124 /* Should we have a corresponding function called Flower_Power? */
2125 DEFUN ("lower-frame", Flower_frame, Slower_frame, 0, 1, "",
2126 doc: /* Send FRAME to the back, so it is occluded by any frames that overlap it.
2127 If you don't specify a frame, the selected frame is used.
2128 If Emacs is displaying on an ordinary terminal or some other device which
2129 doesn't support multiple overlapping frames, this function does nothing. */)
2130 (Lisp_Object frame)
2131 {
2132 struct frame *f = decode_live_frame (frame);
2133
2134 if (FRAME_TERMINAL (f)->frame_raise_lower_hook)
2135 (*FRAME_TERMINAL (f)->frame_raise_lower_hook) (f, 0);
2136
2137 return Qnil;
2138 }
2139
2140 \f
2141 DEFUN ("redirect-frame-focus", Fredirect_frame_focus, Sredirect_frame_focus,
2142 1, 2, 0,
2143 doc: /* Arrange for keystrokes typed at FRAME to be sent to FOCUS-FRAME.
2144 In other words, switch-frame events caused by events in FRAME will
2145 request a switch to FOCUS-FRAME, and `last-event-frame' will be
2146 FOCUS-FRAME after reading an event typed at FRAME.
2147
2148 If FOCUS-FRAME is nil, any existing redirection is canceled, and the
2149 frame again receives its own keystrokes.
2150
2151 Focus redirection is useful for temporarily redirecting keystrokes to
2152 a surrogate minibuffer frame when a frame doesn't have its own
2153 minibuffer window.
2154
2155 A frame's focus redirection can be changed by `select-frame'. If frame
2156 FOO is selected, and then a different frame BAR is selected, any
2157 frames redirecting their focus to FOO are shifted to redirect their
2158 focus to BAR. This allows focus redirection to work properly when the
2159 user switches from one frame to another using `select-window'.
2160
2161 This means that a frame whose focus is redirected to itself is treated
2162 differently from a frame whose focus is redirected to nil; the former
2163 is affected by `select-frame', while the latter is not.
2164
2165 The redirection lasts until `redirect-frame-focus' is called to change it. */)
2166 (Lisp_Object frame, Lisp_Object focus_frame)
2167 {
2168 /* Note that we don't check for a live frame here. It's reasonable
2169 to redirect the focus of a frame you're about to delete, if you
2170 know what other frame should receive those keystrokes. */
2171 struct frame *f = decode_any_frame (frame);
2172
2173 if (! NILP (focus_frame))
2174 CHECK_LIVE_FRAME (focus_frame);
2175
2176 fset_focus_frame (f, focus_frame);
2177
2178 if (FRAME_TERMINAL (f)->frame_rehighlight_hook)
2179 (*FRAME_TERMINAL (f)->frame_rehighlight_hook) (f);
2180
2181 return Qnil;
2182 }
2183
2184
2185 DEFUN ("frame-focus", Fframe_focus, Sframe_focus, 0, 1, 0,
2186 doc: /* Return the frame to which FRAME's keystrokes are currently being sent.
2187 If FRAME is omitted or nil, the selected frame is used.
2188 Return nil if FRAME's focus is not redirected.
2189 See `redirect-frame-focus'. */)
2190 (Lisp_Object frame)
2191 {
2192 return FRAME_FOCUS_FRAME (decode_live_frame (frame));
2193 }
2194
2195 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
2196 doc: /* Set the input focus to FRAME.
2197 FRAME nil means use the selected frame.
2198 If there is no window system support, this function does nothing. */)
2199 (Lisp_Object frame)
2200 {
2201 #ifdef HAVE_WINDOW_SYSTEM
2202 x_focus_frame (decode_window_system_frame (frame));
2203 #endif
2204 return Qnil;
2205 }
2206
2207 DEFUN ("frame-can-run-window-configuration-change-hook",
2208 Fcan_run_window_configuration_change_hook,
2209 Scan_run_window_configuration_change_hook, 2, 2, 0,
2210 doc: /* Whether `window-configuration-change-hook' is run for frame FRAME.
2211 FRAME nil means use the selected frame. Second argument ALLOW non-nil
2212 means functions on `window-configuration-change-hook' are called
2213 whenever the window configuration of FRAME changes. ALLOW nil means
2214 these functions are not called.
2215
2216 This function is currently called by `face-set-after-frame-default' only
2217 and should be otherwise used with utter care to avoid that running
2218 functions on `window-configuration-change-hook' is impeded forever. */)
2219 (Lisp_Object frame, Lisp_Object allow)
2220 {
2221 struct frame *f = decode_live_frame (frame);
2222
2223 f->can_run_window_configuration_change_hook = NILP (allow) ? false : true;
2224 return Qnil;
2225 }
2226
2227 \f
2228 /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame. */
2229
2230 void
2231 frames_discard_buffer (Lisp_Object buffer)
2232 {
2233 Lisp_Object frame, tail;
2234
2235 FOR_EACH_FRAME (tail, frame)
2236 {
2237 fset_buffer_list
2238 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buffer_list));
2239 fset_buried_buffer_list
2240 (XFRAME (frame), Fdelq (buffer, XFRAME (frame)->buried_buffer_list));
2241 }
2242 }
2243
2244 /* Modify the alist in *ALISTPTR to associate PROP with VAL.
2245 If the alist already has an element for PROP, we change it. */
2246
2247 void
2248 store_in_alist (Lisp_Object *alistptr, Lisp_Object prop, Lisp_Object val)
2249 {
2250 register Lisp_Object tem;
2251
2252 tem = Fassq (prop, *alistptr);
2253 if (EQ (tem, Qnil))
2254 *alistptr = Fcons (Fcons (prop, val), *alistptr);
2255 else
2256 Fsetcdr (tem, val);
2257 }
2258
2259 static int
2260 frame_name_fnn_p (char *str, ptrdiff_t len)
2261 {
2262 if (len > 1 && str[0] == 'F' && '0' <= str[1] && str[1] <= '9')
2263 {
2264 char *p = str + 2;
2265 while ('0' <= *p && *p <= '9')
2266 p++;
2267 if (p == str + len)
2268 return 1;
2269 }
2270 return 0;
2271 }
2272
2273 /* Set the name of the terminal frame. Also used by MSDOS frames.
2274 Modeled after x_set_name which is used for WINDOW frames. */
2275
2276 static void
2277 set_term_frame_name (struct frame *f, Lisp_Object name)
2278 {
2279 f->explicit_name = ! NILP (name);
2280
2281 /* If NAME is nil, set the name to F<num>. */
2282 if (NILP (name))
2283 {
2284 char namebuf[sizeof "F" + INT_STRLEN_BOUND (printmax_t)];
2285
2286 /* Check for no change needed in this very common case
2287 before we do any consing. */
2288 if (frame_name_fnn_p (SSDATA (f->name), SBYTES (f->name)))
2289 return;
2290
2291 name = make_formatted_string (namebuf, "F%"pMd, ++tty_frame_count);
2292 }
2293 else
2294 {
2295 CHECK_STRING (name);
2296
2297 /* Don't change the name if it's already NAME. */
2298 if (! NILP (Fstring_equal (name, f->name)))
2299 return;
2300
2301 /* Don't allow the user to set the frame name to F<num>, so it
2302 doesn't clash with the names we generate for terminal frames. */
2303 if (frame_name_fnn_p (SSDATA (name), SBYTES (name)))
2304 error ("Frame names of the form F<num> are usurped by Emacs");
2305 }
2306
2307 fset_name (f, name);
2308 update_mode_lines = 16;
2309 }
2310
2311 void
2312 store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val)
2313 {
2314 register Lisp_Object old_alist_elt;
2315
2316 /* The buffer-list parameters are stored in a special place and not
2317 in the alist. All buffers must be live. */
2318 if (EQ (prop, Qbuffer_list))
2319 {
2320 Lisp_Object list = Qnil;
2321 for (; CONSP (val); val = XCDR (val))
2322 if (!NILP (Fbuffer_live_p (XCAR (val))))
2323 list = Fcons (XCAR (val), list);
2324 fset_buffer_list (f, Fnreverse (list));
2325 return;
2326 }
2327 if (EQ (prop, Qburied_buffer_list))
2328 {
2329 Lisp_Object list = Qnil;
2330 for (; CONSP (val); val = XCDR (val))
2331 if (!NILP (Fbuffer_live_p (XCAR (val))))
2332 list = Fcons (XCAR (val), list);
2333 fset_buried_buffer_list (f, Fnreverse (list));
2334 return;
2335 }
2336
2337 /* If PROP is a symbol which is supposed to have frame-local values,
2338 and it is set up based on this frame, switch to the global
2339 binding. That way, we can create or alter the frame-local binding
2340 without messing up the symbol's status. */
2341 if (SYMBOLP (prop))
2342 {
2343 struct Lisp_Symbol *sym = XSYMBOL (prop);
2344 start:
2345 switch (sym->redirect)
2346 {
2347 case SYMBOL_VARALIAS: sym = indirect_variable (sym); goto start;
2348 case SYMBOL_PLAINVAL: case SYMBOL_FORWARDED: break;
2349 case SYMBOL_LOCALIZED:
2350 { struct Lisp_Buffer_Local_Value *blv = sym->val.blv;
2351 if (blv->frame_local && blv_found (blv) && XFRAME (blv->where) == f)
2352 swap_in_global_binding (sym);
2353 break;
2354 }
2355 default: emacs_abort ();
2356 }
2357 }
2358
2359 /* The tty color needed to be set before the frame's parameter
2360 alist was updated with the new value. This is not true any more,
2361 but we still do this test early on. */
2362 if (FRAME_TERMCAP_P (f) && EQ (prop, Qtty_color_mode)
2363 && f == FRAME_TTY (f)->previous_frame)
2364 /* Force redisplay of this tty. */
2365 FRAME_TTY (f)->previous_frame = NULL;
2366
2367 /* Update the frame parameter alist. */
2368 old_alist_elt = Fassq (prop, f->param_alist);
2369 if (EQ (old_alist_elt, Qnil))
2370 fset_param_alist (f, Fcons (Fcons (prop, val), f->param_alist));
2371 else
2372 Fsetcdr (old_alist_elt, val);
2373
2374 /* Update some other special parameters in their special places
2375 in addition to the alist. */
2376
2377 if (EQ (prop, Qbuffer_predicate))
2378 fset_buffer_predicate (f, val);
2379
2380 if (! FRAME_WINDOW_P (f))
2381 {
2382 if (EQ (prop, Qmenu_bar_lines))
2383 set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f)));
2384 else if (EQ (prop, Qname))
2385 set_term_frame_name (f, val);
2386 }
2387
2388 if (EQ (prop, Qminibuffer) && WINDOWP (val))
2389 {
2390 if (! MINI_WINDOW_P (XWINDOW (val)))
2391 error ("Surrogate minibuffer windows must be minibuffer windows");
2392
2393 if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
2394 && !EQ (val, f->minibuffer_window))
2395 error ("Can't change the surrogate minibuffer of a frame with its own minibuffer");
2396
2397 /* Install the chosen minibuffer window, with proper buffer. */
2398 fset_minibuffer_window (f, val);
2399 }
2400 }
2401
2402 /* Return color matches UNSPEC on frame F or nil if UNSPEC
2403 is not an unspecified foreground or background color. */
2404
2405 static Lisp_Object
2406 frame_unspecified_color (struct frame *f, Lisp_Object unspec)
2407 {
2408 return (!strncmp (SSDATA (unspec), unspecified_bg, SBYTES (unspec))
2409 ? tty_color_name (f, FRAME_BACKGROUND_PIXEL (f))
2410 : (!strncmp (SSDATA (unspec), unspecified_fg, SBYTES (unspec))
2411 ? tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)) : Qnil));
2412 }
2413
2414 DEFUN ("frame-parameters", Fframe_parameters, Sframe_parameters, 0, 1, 0,
2415 doc: /* Return the parameters-alist of frame FRAME.
2416 It is a list of elements of the form (PARM . VALUE), where PARM is a symbol.
2417 The meaningful PARMs depend on the kind of frame.
2418 If FRAME is omitted or nil, return information on the currently selected frame. */)
2419 (Lisp_Object frame)
2420 {
2421 Lisp_Object alist;
2422 struct frame *f = decode_any_frame (frame);
2423 int height, width;
2424 struct gcpro gcpro1;
2425
2426 if (!FRAME_LIVE_P (f))
2427 return Qnil;
2428
2429 alist = Fcopy_alist (f->param_alist);
2430 GCPRO1 (alist);
2431
2432 if (!FRAME_WINDOW_P (f))
2433 {
2434 Lisp_Object elt;
2435
2436 /* If the frame's parameter alist says the colors are
2437 unspecified and reversed, take the frame's background pixel
2438 for foreground and vice versa. */
2439 elt = Fassq (Qforeground_color, alist);
2440 if (CONSP (elt) && STRINGP (XCDR (elt)))
2441 {
2442 elt = frame_unspecified_color (f, XCDR (elt));
2443 if (!NILP (elt))
2444 store_in_alist (&alist, Qforeground_color, elt);
2445 }
2446 else
2447 store_in_alist (&alist, Qforeground_color,
2448 tty_color_name (f, FRAME_FOREGROUND_PIXEL (f)));
2449 elt = Fassq (Qbackground_color, alist);
2450 if (CONSP (elt) && STRINGP (XCDR (elt)))
2451 {
2452 elt = frame_unspecified_color (f, XCDR (elt));
2453 if (!NILP (elt))
2454 store_in_alist (&alist, Qbackground_color, elt);
2455 }
2456 else
2457 store_in_alist (&alist, Qbackground_color,
2458 tty_color_name (f, FRAME_BACKGROUND_PIXEL (f)));
2459 store_in_alist (&alist, intern ("font"),
2460 build_string (FRAME_MSDOS_P (f)
2461 ? "ms-dos"
2462 : FRAME_W32_P (f) ? "w32term"
2463 :"tty"));
2464 }
2465 store_in_alist (&alist, Qname, f->name);
2466 height = (f->new_height
2467 ? (f->new_pixelwise
2468 ? (f->new_height / FRAME_LINE_HEIGHT (f))
2469 : f->new_height)
2470 : FRAME_LINES (f));
2471 store_in_alist (&alist, Qheight, make_number (height));
2472 width = (f->new_width
2473 ? (f->new_pixelwise
2474 ? (f->new_width / FRAME_COLUMN_WIDTH (f))
2475 : f->new_width)
2476 : FRAME_COLS (f));
2477 store_in_alist (&alist, Qwidth, make_number (width));
2478 store_in_alist (&alist, Qmodeline, (FRAME_WANTS_MODELINE_P (f) ? Qt : Qnil));
2479 store_in_alist (&alist, Qminibuffer,
2480 (! FRAME_HAS_MINIBUF_P (f) ? Qnil
2481 : FRAME_MINIBUF_ONLY_P (f) ? Qonly
2482 : FRAME_MINIBUF_WINDOW (f)));
2483 store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
2484 store_in_alist (&alist, Qbuffer_list, f->buffer_list);
2485 store_in_alist (&alist, Qburied_buffer_list, f->buried_buffer_list);
2486
2487 /* I think this should be done with a hook. */
2488 #ifdef HAVE_WINDOW_SYSTEM
2489 if (FRAME_WINDOW_P (f))
2490 x_report_frame_params (f, &alist);
2491 else
2492 #endif
2493 {
2494 /* This ought to be correct in f->param_alist for an X frame. */
2495 Lisp_Object lines;
2496 XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
2497 store_in_alist (&alist, Qmenu_bar_lines, lines);
2498 }
2499
2500 UNGCPRO;
2501 return alist;
2502 }
2503
2504
2505 DEFUN ("frame-parameter", Fframe_parameter, Sframe_parameter, 2, 2, 0,
2506 doc: /* Return FRAME's value for parameter PARAMETER.
2507 If FRAME is nil, describe the currently selected frame. */)
2508 (Lisp_Object frame, Lisp_Object parameter)
2509 {
2510 struct frame *f = decode_any_frame (frame);
2511 Lisp_Object value = Qnil;
2512
2513 CHECK_SYMBOL (parameter);
2514
2515 XSETFRAME (frame, f);
2516
2517 if (FRAME_LIVE_P (f))
2518 {
2519 /* Avoid consing in frequent cases. */
2520 if (EQ (parameter, Qname))
2521 value = f->name;
2522 #ifdef HAVE_X_WINDOWS
2523 else if (EQ (parameter, Qdisplay) && FRAME_X_P (f))
2524 value = XCAR (FRAME_DISPLAY_INFO (f)->name_list_element);
2525 #endif /* HAVE_X_WINDOWS */
2526 else if (EQ (parameter, Qbackground_color)
2527 || EQ (parameter, Qforeground_color))
2528 {
2529 value = Fassq (parameter, f->param_alist);
2530 if (CONSP (value))
2531 {
2532 value = XCDR (value);
2533 /* Fframe_parameters puts the actual fg/bg color names,
2534 even if f->param_alist says otherwise. This is
2535 important when param_alist's notion of colors is
2536 "unspecified". We need to do the same here. */
2537 if (STRINGP (value) && !FRAME_WINDOW_P (f))
2538 value = frame_unspecified_color (f, value);
2539 }
2540 else
2541 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2542 }
2543 else if (EQ (parameter, Qdisplay_type)
2544 || EQ (parameter, Qbackground_mode))
2545 value = Fcdr (Fassq (parameter, f->param_alist));
2546 else
2547 /* FIXME: Avoid this code path at all (as well as code duplication)
2548 by sharing more code with Fframe_parameters. */
2549 value = Fcdr (Fassq (parameter, Fframe_parameters (frame)));
2550 }
2551
2552 return value;
2553 }
2554
2555
2556 DEFUN ("modify-frame-parameters", Fmodify_frame_parameters,
2557 Smodify_frame_parameters, 2, 2, 0,
2558 doc: /* Modify the parameters of frame FRAME according to ALIST.
2559 If FRAME is nil, it defaults to the selected frame.
2560 ALIST is an alist of parameters to change and their new values.
2561 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.
2562 The meaningful PARMs depend on the kind of frame.
2563 Undefined PARMs are ignored, but stored in the frame's parameter list
2564 so that `frame-parameters' will return them.
2565
2566 The value of frame parameter FOO can also be accessed
2567 as a frame-local binding for the variable FOO, if you have
2568 enabled such bindings for that variable with `make-variable-frame-local'.
2569 Note that this functionality is obsolete as of Emacs 22.2, and its
2570 use is not recommended. Explicitly check for a frame-parameter instead. */)
2571 (Lisp_Object frame, Lisp_Object alist)
2572 {
2573 struct frame *f = decode_live_frame (frame);
2574 register Lisp_Object prop, val;
2575
2576 CHECK_LIST (alist);
2577
2578 /* I think this should be done with a hook. */
2579 #ifdef HAVE_WINDOW_SYSTEM
2580 if (FRAME_WINDOW_P (f))
2581 x_set_frame_parameters (f, alist);
2582 else
2583 #endif
2584 #ifdef MSDOS
2585 if (FRAME_MSDOS_P (f))
2586 IT_set_frame_parameters (f, alist);
2587 else
2588 #endif
2589
2590 {
2591 EMACS_INT length = XFASTINT (Flength (alist));
2592 ptrdiff_t i;
2593 Lisp_Object *parms;
2594 Lisp_Object *values;
2595 USE_SAFE_ALLOCA;
2596 SAFE_ALLOCA_LISP (parms, 2 * length);
2597 values = parms + length;
2598
2599 /* Extract parm names and values into those vectors. */
2600
2601 for (i = 0; CONSP (alist); alist = XCDR (alist))
2602 {
2603 Lisp_Object elt;
2604
2605 elt = XCAR (alist);
2606 parms[i] = Fcar (elt);
2607 values[i] = Fcdr (elt);
2608 i++;
2609 }
2610
2611 /* Now process them in reverse of specified order. */
2612 while (--i >= 0)
2613 {
2614 prop = parms[i];
2615 val = values[i];
2616 store_frame_param (f, prop, val);
2617
2618 if (EQ (prop, Qforeground_color)
2619 || EQ (prop, Qbackground_color))
2620 update_face_from_frame_parameter (f, prop, val);
2621 }
2622
2623 SAFE_FREE ();
2624 }
2625 return Qnil;
2626 }
2627 \f
2628 DEFUN ("frame-char-height", Fframe_char_height, Sframe_char_height,
2629 0, 1, 0,
2630 doc: /* Height in pixels of a line in the font in frame FRAME.
2631 If FRAME is omitted or nil, the selected frame is used.
2632 For a terminal frame, the value is always 1. */)
2633 (Lisp_Object frame)
2634 {
2635 #ifdef HAVE_WINDOW_SYSTEM
2636 struct frame *f = decode_any_frame (frame);
2637
2638 if (FRAME_WINDOW_P (f))
2639 return make_number (FRAME_LINE_HEIGHT (f));
2640 else
2641 #endif
2642 return make_number (1);
2643 }
2644
2645
2646 DEFUN ("frame-char-width", Fframe_char_width, Sframe_char_width,
2647 0, 1, 0,
2648 doc: /* Width in pixels of characters in the font in frame FRAME.
2649 If FRAME is omitted or nil, the selected frame is used.
2650 On a graphical screen, the width is the standard width of the default font.
2651 For a terminal screen, the value is always 1. */)
2652 (Lisp_Object frame)
2653 {
2654 #ifdef HAVE_WINDOW_SYSTEM
2655 struct frame *f = decode_any_frame (frame);
2656
2657 if (FRAME_WINDOW_P (f))
2658 return make_number (FRAME_COLUMN_WIDTH (f));
2659 else
2660 #endif
2661 return make_number (1);
2662 }
2663
2664 DEFUN ("frame-pixel-height", Fframe_pixel_height,
2665 Sframe_pixel_height, 0, 1, 0,
2666 doc: /* Return a FRAME's height in pixels.
2667 If FRAME is omitted or nil, the selected frame is used. The exact value
2668 of the result depends on the window-system and toolkit in use:
2669
2670 In the Gtk+ version of Emacs, it includes only any window (including
2671 the minibuffer or echo area), mode line, and header line. It does not
2672 include the tool bar or menu bar.
2673
2674 With other graphical versions, it also includes the tool bar and the
2675 menu bar.
2676
2677 For a text terminal, it includes the menu bar. In this case, the
2678 result is really in characters rather than pixels (i.e., is identical
2679 to `frame-height'). */)
2680 (Lisp_Object frame)
2681 {
2682 struct frame *f = decode_any_frame (frame);
2683
2684 #ifdef HAVE_WINDOW_SYSTEM
2685 if (FRAME_WINDOW_P (f))
2686 return make_number (FRAME_PIXEL_HEIGHT (f));
2687 else
2688 #endif
2689 return make_number (FRAME_TOTAL_LINES (f));
2690 }
2691
2692 DEFUN ("frame-pixel-width", Fframe_pixel_width,
2693 Sframe_pixel_width, 0, 1, 0,
2694 doc: /* Return FRAME's width in pixels.
2695 For a terminal frame, the result really gives the width in characters.
2696 If FRAME is omitted or nil, the selected frame is used. */)
2697 (Lisp_Object frame)
2698 {
2699 struct frame *f = decode_any_frame (frame);
2700
2701 #ifdef HAVE_WINDOW_SYSTEM
2702 if (FRAME_WINDOW_P (f))
2703 return make_number (FRAME_PIXEL_WIDTH (f));
2704 else
2705 #endif
2706 return make_number (FRAME_TOTAL_COLS (f));
2707 }
2708
2709 DEFUN ("tool-bar-pixel-width", Ftool_bar_pixel_width,
2710 Stool_bar_pixel_width, 0, 1, 0,
2711 doc: /* Return width in pixels of FRAME's tool bar.
2712 The result is greater than zero only when the tool bar is on the left
2713 or right side of FRAME. If FRAME is omitted or nil, the selected frame
2714 is used. */)
2715 (Lisp_Object frame)
2716 {
2717 #ifdef FRAME_TOOLBAR_WIDTH
2718 struct frame *f = decode_any_frame (frame);
2719
2720 if (FRAME_WINDOW_P (f))
2721 return make_number (FRAME_TOOLBAR_WIDTH (f));
2722 #endif
2723 return make_number (0);
2724 }
2725
2726 DEFUN ("frame-text-cols", Fframe_text_cols, Sframe_text_cols, 0, 1, 0,
2727 doc: /* Return width in columns of FRAME's text area. */)
2728 (Lisp_Object frame)
2729 {
2730 return make_number (FRAME_COLS (decode_any_frame (frame)));
2731 }
2732
2733 DEFUN ("frame-text-lines", Fframe_text_lines, Sframe_text_lines, 0, 1, 0,
2734 doc: /* Return height in lines of FRAME's text area. */)
2735 (Lisp_Object frame)
2736 {
2737 return make_number (FRAME_LINES (decode_any_frame (frame)));
2738 }
2739
2740 DEFUN ("frame-total-cols", Fframe_total_cols, Sframe_total_cols, 0, 1, 0,
2741 doc: /* Return number of total columns of FRAME. */)
2742 (Lisp_Object frame)
2743 {
2744 return make_number (FRAME_TOTAL_COLS (decode_any_frame (frame)));
2745 }
2746
2747 DEFUN ("frame-total-lines", Fframe_total_lines, Sframe_total_lines, 0, 1, 0,
2748 doc: /* Return number of total lines of FRAME. */)
2749 (Lisp_Object frame)
2750 {
2751 return make_number (FRAME_TOTAL_LINES (decode_any_frame (frame)));
2752 }
2753
2754 DEFUN ("frame-text-width", Fframe_text_width, Sframe_text_width, 0, 1, 0,
2755 doc: /* Return text area width of FRAME in pixels. */)
2756 (Lisp_Object frame)
2757 {
2758 return make_number (FRAME_TEXT_WIDTH (decode_any_frame (frame)));
2759 }
2760
2761 DEFUN ("frame-text-height", Fframe_text_height, Sframe_text_height, 0, 1, 0,
2762 doc: /* Return text area height of FRAME in pixels. */)
2763 (Lisp_Object frame)
2764 {
2765 return make_number (FRAME_TEXT_HEIGHT (decode_any_frame (frame)));
2766 }
2767
2768 DEFUN ("frame-scroll-bar-width", Fscroll_bar_width, Sscroll_bar_width, 0, 1, 0,
2769 doc: /* Return scroll bar width of FRAME in pixels. */)
2770 (Lisp_Object frame)
2771 {
2772 return make_number (FRAME_SCROLL_BAR_AREA_WIDTH (decode_any_frame (frame)));
2773 }
2774
2775 DEFUN ("frame-scroll-bar-height", Fscroll_bar_height, Sscroll_bar_height, 0, 1, 0,
2776 doc: /* Return scroll bar height of FRAME in pixels. */)
2777 (Lisp_Object frame)
2778 {
2779 return make_number (FRAME_SCROLL_BAR_AREA_HEIGHT (decode_any_frame (frame)));
2780 }
2781
2782 DEFUN ("frame-fringe-width", Ffringe_width, Sfringe_width, 0, 1, 0,
2783 doc: /* Return fringe width of FRAME in pixels. */)
2784 (Lisp_Object frame)
2785 {
2786 return make_number (FRAME_TOTAL_FRINGE_WIDTH (decode_any_frame (frame)));
2787 }
2788
2789 DEFUN ("frame-border-width", Fborder_width, Sborder_width, 0, 1, 0,
2790 doc: /* Return border width of FRAME in pixels. */)
2791 (Lisp_Object frame)
2792 {
2793 return make_number (FRAME_INTERNAL_BORDER_WIDTH (decode_any_frame (frame)));
2794 }
2795
2796 DEFUN ("frame-right-divider-width", Fright_divider_width, Sright_divider_width, 0, 1, 0,
2797 doc: /* Return width (in pixels) of vertical window dividers on FRAME. */)
2798 (Lisp_Object frame)
2799 {
2800 return make_number (FRAME_RIGHT_DIVIDER_WIDTH (decode_any_frame (frame)));
2801 }
2802
2803 DEFUN ("frame-bottom-divider-width", Fbottom_divider_width, Sbottom_divider_width, 0, 1, 0,
2804 doc: /* Return width (in pixels) of horizontal window dividers on FRAME. */)
2805 (Lisp_Object frame)
2806 {
2807 return make_number (FRAME_BOTTOM_DIVIDER_WIDTH (decode_any_frame (frame)));
2808 }
2809
2810 DEFUN ("set-frame-height", Fset_frame_height, Sset_frame_height, 2, 4, 0,
2811 doc: /* Set height of frame FRAME to HEIGHT lines.
2812 Optional third arg PRETEND non-nil means that redisplay should use
2813 HEIGHT lines but that the idea of the actual height of the frame should
2814 not be changed.
2815
2816 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2817 HEIGHT pixels high. Note: When `frame-resize-pixelwise' is nil, some
2818 window managers may refuse to honor a HEIGHT that is not an integer
2819 multiple of the default frame font height. */)
2820 (Lisp_Object frame, Lisp_Object height, Lisp_Object pretend, Lisp_Object pixelwise)
2821 {
2822 struct frame *f = decode_live_frame (frame);
2823 int pixel_height;
2824
2825 CHECK_TYPE_RANGED_INTEGER (int, height);
2826
2827 pixel_height = (!NILP (pixelwise)
2828 ? XINT (height)
2829 : XINT (height) * FRAME_LINE_HEIGHT (f));
2830 if (pixel_height != FRAME_TEXT_HEIGHT (f))
2831 adjust_frame_size (f, -1, pixel_height, 1, !NILP (pretend), Qheight);
2832
2833 return Qnil;
2834 }
2835
2836 DEFUN ("set-frame-width", Fset_frame_width, Sset_frame_width, 2, 4, 0,
2837 doc: /* Set width of frame FRAME to WIDTH columns.
2838 Optional third arg PRETEND non-nil means that redisplay should use WIDTH
2839 columns but that the idea of the actual width of the frame should not
2840 be changed.
2841
2842 Optional fourth argument PIXELWISE non-nil means that FRAME should be
2843 WIDTH pixels wide. Note: When `frame-resize-pixelwise' is nil, some
2844 window managers may refuse to honor a WIDTH that is not an integer
2845 multiple of the default frame font width. */)
2846 (Lisp_Object frame, Lisp_Object width, Lisp_Object pretend, Lisp_Object pixelwise)
2847 {
2848 struct frame *f = decode_live_frame (frame);
2849 int pixel_width;
2850
2851 CHECK_TYPE_RANGED_INTEGER (int, width);
2852
2853 pixel_width = (!NILP (pixelwise)
2854 ? XINT (width)
2855 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2856 if (pixel_width != FRAME_TEXT_WIDTH (f))
2857 adjust_frame_size (f, pixel_width, -1, 1, !NILP (pretend), Qwidth);
2858
2859 return Qnil;
2860 }
2861
2862 DEFUN ("set-frame-size", Fset_frame_size, Sset_frame_size, 3, 4, 0,
2863 doc: /* Set size of FRAME to WIDTH by HEIGHT, measured in characters.
2864 Optional argument PIXELWISE non-nil means to measure in pixels. Note:
2865 When `frame-resize-pixelwise' is nil, some window managers may refuse to
2866 honor a WIDTH that is not an integer multiple of the default frame font
2867 width or a HEIGHT that is not an integer multiple of the default frame
2868 font height. */)
2869 (Lisp_Object frame, Lisp_Object width, Lisp_Object height, Lisp_Object pixelwise)
2870 {
2871 struct frame *f = decode_live_frame (frame);
2872 int pixel_width, pixel_height;
2873
2874 CHECK_TYPE_RANGED_INTEGER (int, width);
2875 CHECK_TYPE_RANGED_INTEGER (int, height);
2876
2877 pixel_width = (!NILP (pixelwise)
2878 ? XINT (width)
2879 : XINT (width) * FRAME_COLUMN_WIDTH (f));
2880 pixel_height = (!NILP (pixelwise)
2881 ? XINT (height)
2882 : XINT (height) * FRAME_LINE_HEIGHT (f));
2883
2884 if (pixel_width != FRAME_TEXT_WIDTH (f)
2885 || pixel_height != FRAME_TEXT_HEIGHT (f))
2886 adjust_frame_size (f, pixel_width, pixel_height, 1, 0, Qsize);
2887
2888 return Qnil;
2889 }
2890
2891 DEFUN ("set-frame-position", Fset_frame_position,
2892 Sset_frame_position, 3, 3, 0,
2893 doc: /* Sets position of FRAME in pixels to XOFFSET by YOFFSET.
2894 If FRAME is nil, the selected frame is used. XOFFSET and YOFFSET are
2895 actually the position of the upper left corner of the frame. Negative
2896 values for XOFFSET or YOFFSET are interpreted relative to the rightmost
2897 or bottommost possible position (that stays within the screen). */)
2898 (Lisp_Object frame, Lisp_Object xoffset, Lisp_Object yoffset)
2899 {
2900 register struct frame *f = decode_live_frame (frame);
2901
2902 CHECK_TYPE_RANGED_INTEGER (int, xoffset);
2903 CHECK_TYPE_RANGED_INTEGER (int, yoffset);
2904
2905 /* I think this should be done with a hook. */
2906 #ifdef HAVE_WINDOW_SYSTEM
2907 if (FRAME_WINDOW_P (f))
2908 x_set_offset (f, XINT (xoffset), XINT (yoffset), 1);
2909 #endif
2910
2911 return Qt;
2912 }
2913
2914 \f
2915 /***********************************************************************
2916 Frame Parameters
2917 ***********************************************************************/
2918
2919 /* Connect the frame-parameter names for X frames
2920 to the ways of passing the parameter values to the window system.
2921
2922 The name of a parameter, as a Lisp symbol,
2923 has an `x-frame-parameter' property which is an integer in Lisp
2924 that is an index in this table. */
2925
2926 struct frame_parm_table {
2927 const char *name;
2928 struct Lisp_Symbol *sym;
2929 };
2930
2931 static const struct frame_parm_table frame_parms[] =
2932 {
2933 {"auto-raise", XSYMBOL_INIT (Qauto_raise)},
2934 {"auto-lower", XSYMBOL_INIT (Qauto_lower)},
2935 {"background-color", 0},
2936 {"border-color", XSYMBOL_INIT (Qborder_color)},
2937 {"border-width", XSYMBOL_INIT (Qborder_width)},
2938 {"cursor-color", XSYMBOL_INIT (Qcursor_color)},
2939 {"cursor-type", XSYMBOL_INIT (Qcursor_type)},
2940 {"font", 0},
2941 {"foreground-color", 0},
2942 {"icon-name", XSYMBOL_INIT (Qicon_name)},
2943 {"icon-type", XSYMBOL_INIT (Qicon_type)},
2944 {"internal-border-width", XSYMBOL_INIT (Qinternal_border_width)},
2945 {"right-divider-width", XSYMBOL_INIT (Qright_divider_width)},
2946 {"bottom-divider-width", XSYMBOL_INIT (Qbottom_divider_width)},
2947 {"menu-bar-lines", XSYMBOL_INIT (Qmenu_bar_lines)},
2948 {"mouse-color", XSYMBOL_INIT (Qmouse_color)},
2949 {"name", XSYMBOL_INIT (Qname)},
2950 {"scroll-bar-width", XSYMBOL_INIT (Qscroll_bar_width)},
2951 {"scroll-bar-height", XSYMBOL_INIT (Qscroll_bar_height)},
2952 {"title", XSYMBOL_INIT (Qtitle)},
2953 {"unsplittable", XSYMBOL_INIT (Qunsplittable)},
2954 {"vertical-scroll-bars", XSYMBOL_INIT (Qvertical_scroll_bars)},
2955 {"horizontal-scroll-bars", XSYMBOL_INIT (Qhorizontal_scroll_bars)},
2956 {"visibility", XSYMBOL_INIT (Qvisibility)},
2957 {"tool-bar-lines", XSYMBOL_INIT (Qtool_bar_lines)},
2958 {"scroll-bar-foreground", XSYMBOL_INIT (Qscroll_bar_foreground)},
2959 {"scroll-bar-background", XSYMBOL_INIT (Qscroll_bar_background)},
2960 {"screen-gamma", XSYMBOL_INIT (Qscreen_gamma)},
2961 {"line-spacing", XSYMBOL_INIT (Qline_spacing)},
2962 {"left-fringe", XSYMBOL_INIT (Qleft_fringe)},
2963 {"right-fringe", XSYMBOL_INIT (Qright_fringe)},
2964 {"wait-for-wm", XSYMBOL_INIT (Qwait_for_wm)},
2965 {"fullscreen", XSYMBOL_INIT (Qfullscreen)},
2966 {"font-backend", XSYMBOL_INIT (Qfont_backend)},
2967 {"alpha", XSYMBOL_INIT (Qalpha)},
2968 {"sticky", XSYMBOL_INIT (Qsticky)},
2969 {"tool-bar-position", XSYMBOL_INIT (Qtool_bar_position)},
2970 };
2971
2972 #ifdef HAVE_WINDOW_SYSTEM
2973
2974 /* Change the parameters of frame F as specified by ALIST.
2975 If a parameter is not specially recognized, do nothing special;
2976 otherwise call the `x_set_...' function for that parameter.
2977 Except for certain geometry properties, always call store_frame_param
2978 to store the new value in the parameter alist. */
2979
2980 void
2981 x_set_frame_parameters (struct frame *f, Lisp_Object alist)
2982 {
2983 Lisp_Object tail;
2984
2985 /* If both of these parameters are present, it's more efficient to
2986 set them both at once. So we wait until we've looked at the
2987 entire list before we set them. */
2988 int width IF_LINT (= 0), height IF_LINT (= 0);
2989 bool width_change = 0, height_change = 0;
2990
2991 /* Same here. */
2992 Lisp_Object left, top;
2993
2994 /* Same with these. */
2995 Lisp_Object icon_left, icon_top;
2996
2997 /* Record in these vectors all the parms specified. */
2998 Lisp_Object *parms;
2999 Lisp_Object *values;
3000 ptrdiff_t i, p;
3001 bool left_no_change = 0, top_no_change = 0;
3002 #ifdef HAVE_X_WINDOWS
3003 bool icon_left_no_change = 0, icon_top_no_change = 0;
3004 #endif
3005
3006 i = 0;
3007 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3008 i++;
3009
3010 USE_SAFE_ALLOCA;
3011 SAFE_ALLOCA_LISP (parms, 2 * i);
3012 values = parms + i;
3013
3014 /* Extract parm names and values into those vectors. */
3015
3016 i = 0;
3017 for (tail = alist; CONSP (tail); tail = XCDR (tail))
3018 {
3019 Lisp_Object elt;
3020
3021 elt = XCAR (tail);
3022 parms[i] = Fcar (elt);
3023 values[i] = Fcdr (elt);
3024 i++;
3025 }
3026 /* TAIL and ALIST are not used again below here. */
3027 alist = tail = Qnil;
3028
3029 /* There is no need to gcpro LEFT, TOP, ICON_LEFT, or ICON_TOP,
3030 because their values appear in VALUES and strings are not valid. */
3031 top = left = Qunbound;
3032 icon_left = icon_top = Qunbound;
3033
3034 /* Process foreground_color and background_color before anything else.
3035 They are independent of other properties, but other properties (e.g.,
3036 cursor_color) are dependent upon them. */
3037 /* Process default font as well, since fringe widths depends on it. */
3038 for (p = 0; p < i; p++)
3039 {
3040 Lisp_Object prop, val;
3041
3042 prop = parms[p];
3043 val = values[p];
3044 if (EQ (prop, Qforeground_color)
3045 || EQ (prop, Qbackground_color)
3046 || EQ (prop, Qfont))
3047 {
3048 register Lisp_Object param_index, old_value;
3049
3050 old_value = get_frame_param (f, prop);
3051 if (NILP (Fequal (val, old_value)))
3052 {
3053 store_frame_param (f, prop, val);
3054
3055 param_index = Fget (prop, Qx_frame_parameter);
3056 if (NATNUMP (param_index)
3057 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3058 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3059 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3060 }
3061 }
3062 }
3063
3064 /* Now process them in reverse of specified order. */
3065 while (i-- != 0)
3066 {
3067 Lisp_Object prop, val;
3068
3069 prop = parms[i];
3070 val = values[i];
3071
3072 if (EQ (prop, Qwidth) && RANGED_INTEGERP (0, val, INT_MAX))
3073 {
3074 width_change = 1;
3075 width = XFASTINT (val) * FRAME_COLUMN_WIDTH (f) ;
3076 }
3077 else if (EQ (prop, Qheight) && RANGED_INTEGERP (0, val, INT_MAX))
3078 {
3079 height_change = 1;
3080 height = XFASTINT (val) * FRAME_LINE_HEIGHT (f);
3081 }
3082 else if (EQ (prop, Qtop))
3083 top = val;
3084 else if (EQ (prop, Qleft))
3085 left = val;
3086 else if (EQ (prop, Qicon_top))
3087 icon_top = val;
3088 else if (EQ (prop, Qicon_left))
3089 icon_left = val;
3090 else if (EQ (prop, Qforeground_color)
3091 || EQ (prop, Qbackground_color)
3092 || EQ (prop, Qfont))
3093 /* Processed above. */
3094 continue;
3095 else
3096 {
3097 register Lisp_Object param_index, old_value;
3098
3099 old_value = get_frame_param (f, prop);
3100
3101 store_frame_param (f, prop, val);
3102
3103 param_index = Fget (prop, Qx_frame_parameter);
3104 if (NATNUMP (param_index)
3105 && XFASTINT (param_index) < ARRAYELTS (frame_parms)
3106 && FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])
3107 (*(FRAME_RIF (f)->frame_parm_handlers[XINT (param_index)])) (f, val, old_value);
3108 }
3109 }
3110
3111 /* Don't die if just one of these was set. */
3112 if (EQ (left, Qunbound))
3113 {
3114 left_no_change = 1;
3115 if (f->left_pos < 0)
3116 left = list2 (Qplus, make_number (f->left_pos));
3117 else
3118 XSETINT (left, f->left_pos);
3119 }
3120 if (EQ (top, Qunbound))
3121 {
3122 top_no_change = 1;
3123 if (f->top_pos < 0)
3124 top = list2 (Qplus, make_number (f->top_pos));
3125 else
3126 XSETINT (top, f->top_pos);
3127 }
3128
3129 /* If one of the icon positions was not set, preserve or default it. */
3130 if (! TYPE_RANGED_INTEGERP (int, icon_left))
3131 {
3132 #ifdef HAVE_X_WINDOWS
3133 icon_left_no_change = 1;
3134 #endif
3135 icon_left = Fcdr (Fassq (Qicon_left, f->param_alist));
3136 if (NILP (icon_left))
3137 XSETINT (icon_left, 0);
3138 }
3139 if (! TYPE_RANGED_INTEGERP (int, icon_top))
3140 {
3141 #ifdef HAVE_X_WINDOWS
3142 icon_top_no_change = 1;
3143 #endif
3144 icon_top = Fcdr (Fassq (Qicon_top, f->param_alist));
3145 if (NILP (icon_top))
3146 XSETINT (icon_top, 0);
3147 }
3148
3149 /* Don't set these parameters unless they've been explicitly
3150 specified. The window might be mapped or resized while we're in
3151 this function, and we don't want to override that unless the lisp
3152 code has asked for it.
3153
3154 Don't set these parameters unless they actually differ from the
3155 window's current parameters; the window may not actually exist
3156 yet. */
3157 {
3158 Lisp_Object frame;
3159
3160 XSETFRAME (frame, f);
3161
3162 if ((width_change && width != FRAME_TEXT_WIDTH (f))
3163 || (height_change && height != FRAME_TEXT_HEIGHT (f))
3164 || (f->can_x_set_window_size && (f->new_height || f->new_width)))
3165 {
3166 /* If necessary provide default values for HEIGHT and WIDTH. Do
3167 that here since otherwise a size change implied by an
3168 intermittent font change may get lost as in Bug#17142. */
3169 if (!width_change)
3170 width = (f->new_width
3171 ? (f->new_pixelwise
3172 ? f->new_width
3173 : (f->new_width * FRAME_COLUMN_WIDTH (f)))
3174 : FRAME_TEXT_WIDTH (f));
3175
3176 if (!height_change)
3177 height = (f->new_height
3178 ? (f->new_pixelwise
3179 ? f->new_height
3180 : (f->new_height * FRAME_LINE_HEIGHT (f)))
3181 : FRAME_TEXT_HEIGHT (f));
3182
3183 Fset_frame_size (frame, make_number (width), make_number (height), Qt);
3184 }
3185
3186 if ((!NILP (left) || !NILP (top))
3187 && ! (left_no_change && top_no_change)
3188 && ! (NUMBERP (left) && XINT (left) == f->left_pos
3189 && NUMBERP (top) && XINT (top) == f->top_pos))
3190 {
3191 int leftpos = 0;
3192 int toppos = 0;
3193
3194 /* Record the signs. */
3195 f->size_hint_flags &= ~ (XNegative | YNegative);
3196 if (EQ (left, Qminus))
3197 f->size_hint_flags |= XNegative;
3198 else if (TYPE_RANGED_INTEGERP (int, left))
3199 {
3200 leftpos = XINT (left);
3201 if (leftpos < 0)
3202 f->size_hint_flags |= XNegative;
3203 }
3204 else if (CONSP (left) && EQ (XCAR (left), Qminus)
3205 && CONSP (XCDR (left))
3206 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
3207 {
3208 leftpos = - XINT (XCAR (XCDR (left)));
3209 f->size_hint_flags |= XNegative;
3210 }
3211 else if (CONSP (left) && EQ (XCAR (left), Qplus)
3212 && CONSP (XCDR (left))
3213 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
3214 {
3215 leftpos = XINT (XCAR (XCDR (left)));
3216 }
3217
3218 if (EQ (top, Qminus))
3219 f->size_hint_flags |= YNegative;
3220 else if (TYPE_RANGED_INTEGERP (int, top))
3221 {
3222 toppos = XINT (top);
3223 if (toppos < 0)
3224 f->size_hint_flags |= YNegative;
3225 }
3226 else if (CONSP (top) && EQ (XCAR (top), Qminus)
3227 && CONSP (XCDR (top))
3228 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
3229 {
3230 toppos = - XINT (XCAR (XCDR (top)));
3231 f->size_hint_flags |= YNegative;
3232 }
3233 else if (CONSP (top) && EQ (XCAR (top), Qplus)
3234 && CONSP (XCDR (top))
3235 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
3236 {
3237 toppos = XINT (XCAR (XCDR (top)));
3238 }
3239
3240
3241 /* Store the numeric value of the position. */
3242 f->top_pos = toppos;
3243 f->left_pos = leftpos;
3244
3245 f->win_gravity = NorthWestGravity;
3246
3247 /* Actually set that position, and convert to absolute. */
3248 x_set_offset (f, leftpos, toppos, -1);
3249 }
3250 #ifdef HAVE_X_WINDOWS
3251 if ((!NILP (icon_left) || !NILP (icon_top))
3252 && ! (icon_left_no_change && icon_top_no_change))
3253 x_wm_set_icon_position (f, XINT (icon_left), XINT (icon_top));
3254 #endif /* HAVE_X_WINDOWS */
3255 }
3256
3257 SAFE_FREE ();
3258 }
3259
3260
3261 /* Insert a description of internally-recorded parameters of frame X
3262 into the parameter alist *ALISTPTR that is to be given to the user.
3263 Only parameters that are specific to the X window system
3264 and whose values are not correctly recorded in the frame's
3265 param_alist need to be considered here. */
3266
3267 void
3268 x_report_frame_params (struct frame *f, Lisp_Object *alistptr)
3269 {
3270 Lisp_Object tem;
3271 uprintmax_t w;
3272 char buf[INT_BUFSIZE_BOUND (w)];
3273
3274 /* Represent negative positions (off the top or left screen edge)
3275 in a way that Fmodify_frame_parameters will understand correctly. */
3276 XSETINT (tem, f->left_pos);
3277 if (f->left_pos >= 0)
3278 store_in_alist (alistptr, Qleft, tem);
3279 else
3280 store_in_alist (alistptr, Qleft, list2 (Qplus, tem));
3281
3282 XSETINT (tem, f->top_pos);
3283 if (f->top_pos >= 0)
3284 store_in_alist (alistptr, Qtop, tem);
3285 else
3286 store_in_alist (alistptr, Qtop, list2 (Qplus, tem));
3287
3288 store_in_alist (alistptr, Qborder_width,
3289 make_number (f->border_width));
3290 store_in_alist (alistptr, Qinternal_border_width,
3291 make_number (FRAME_INTERNAL_BORDER_WIDTH (f)));
3292 store_in_alist (alistptr, Qright_divider_width,
3293 make_number (FRAME_RIGHT_DIVIDER_WIDTH (f)));
3294 store_in_alist (alistptr, Qbottom_divider_width,
3295 make_number (FRAME_BOTTOM_DIVIDER_WIDTH (f)));
3296 store_in_alist (alistptr, Qleft_fringe,
3297 make_number (FRAME_LEFT_FRINGE_WIDTH (f)));
3298 store_in_alist (alistptr, Qright_fringe,
3299 make_number (FRAME_RIGHT_FRINGE_WIDTH (f)));
3300 store_in_alist (alistptr, Qscroll_bar_width,
3301 (! FRAME_HAS_VERTICAL_SCROLL_BARS (f)
3302 ? make_number (0)
3303 : FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0
3304 ? make_number (FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3305 /* nil means "use default width"
3306 for non-toolkit scroll bar.
3307 ruler-mode.el depends on this. */
3308 : Qnil));
3309 store_in_alist (alistptr, Qscroll_bar_height,
3310 (! FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)
3311 ? make_number (0)
3312 : FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) > 0
3313 ? make_number (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3314 /* nil means "use default height"
3315 for non-toolkit scroll bar. */
3316 : Qnil));
3317 /* FRAME_X_WINDOW is not guaranteed to return an integer. E.g., on
3318 MS-Windows it returns a value whose type is HANDLE, which is
3319 actually a pointer. Explicit casting avoids compiler
3320 warnings. */
3321 w = (uintptr_t) FRAME_X_WINDOW (f);
3322 store_in_alist (alistptr, Qwindow_id,
3323 make_formatted_string (buf, "%"pMu, w));
3324 #ifdef HAVE_X_WINDOWS
3325 #ifdef USE_X_TOOLKIT
3326 /* Tooltip frame may not have this widget. */
3327 if (FRAME_X_OUTPUT (f)->widget)
3328 #endif
3329 w = (uintptr_t) FRAME_OUTER_WINDOW (f);
3330 store_in_alist (alistptr, Qouter_window_id,
3331 make_formatted_string (buf, "%"pMu, w));
3332 #endif
3333 store_in_alist (alistptr, Qicon_name, f->icon_name);
3334 store_in_alist (alistptr, Qvisibility,
3335 (FRAME_VISIBLE_P (f) ? Qt
3336 : FRAME_ICONIFIED_P (f) ? Qicon : Qnil));
3337 store_in_alist (alistptr, Qdisplay,
3338 XCAR (FRAME_DISPLAY_INFO (f)->name_list_element));
3339
3340 if (FRAME_X_OUTPUT (f)->parent_desc == FRAME_DISPLAY_INFO (f)->root_window)
3341 tem = Qnil;
3342 else
3343 tem = make_natnum ((uintptr_t) FRAME_X_OUTPUT (f)->parent_desc);
3344 store_in_alist (alistptr, Qexplicit_name, (f->explicit_name ? Qt : Qnil));
3345 store_in_alist (alistptr, Qparent_id, tem);
3346 store_in_alist (alistptr, Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f));
3347 }
3348
3349
3350 /* Change the `fullscreen' frame parameter of frame F. OLD_VALUE is
3351 the previous value of that parameter, NEW_VALUE is the new value. */
3352
3353 void
3354 x_set_fullscreen (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3355 {
3356 if (NILP (new_value))
3357 f->want_fullscreen = FULLSCREEN_NONE;
3358 else if (EQ (new_value, Qfullboth) || EQ (new_value, Qfullscreen))
3359 f->want_fullscreen = FULLSCREEN_BOTH;
3360 else if (EQ (new_value, Qfullwidth))
3361 f->want_fullscreen = FULLSCREEN_WIDTH;
3362 else if (EQ (new_value, Qfullheight))
3363 f->want_fullscreen = FULLSCREEN_HEIGHT;
3364 else if (EQ (new_value, Qmaximized))
3365 f->want_fullscreen = FULLSCREEN_MAXIMIZED;
3366
3367 if (FRAME_TERMINAL (f)->fullscreen_hook != NULL)
3368 FRAME_TERMINAL (f)->fullscreen_hook (f);
3369 }
3370
3371
3372 /* Change the `line-spacing' frame parameter of frame F. OLD_VALUE is
3373 the previous value of that parameter, NEW_VALUE is the new value. */
3374
3375 void
3376 x_set_line_spacing (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3377 {
3378 if (NILP (new_value))
3379 f->extra_line_spacing = 0;
3380 else if (RANGED_INTEGERP (0, new_value, INT_MAX))
3381 f->extra_line_spacing = XFASTINT (new_value);
3382 else if (FLOATP (new_value))
3383 {
3384 int new_spacing = XFLOAT_DATA (new_value) * FRAME_LINE_HEIGHT (f) + 0.5;
3385
3386 if (new_spacing >= 0)
3387 f->extra_line_spacing = new_spacing;
3388 else
3389 signal_error ("Invalid line-spacing", new_value);
3390 }
3391 else
3392 signal_error ("Invalid line-spacing", new_value);
3393 if (FRAME_VISIBLE_P (f))
3394 redraw_frame (f);
3395 }
3396
3397
3398 /* Change the `screen-gamma' frame parameter of frame F. OLD_VALUE is
3399 the previous value of that parameter, NEW_VALUE is the new value. */
3400
3401 void
3402 x_set_screen_gamma (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3403 {
3404 Lisp_Object bgcolor;
3405
3406 if (NILP (new_value))
3407 f->gamma = 0;
3408 else if (NUMBERP (new_value) && XFLOATINT (new_value) > 0)
3409 /* The value 0.4545 is the normal viewing gamma. */
3410 f->gamma = 1.0 / (0.4545 * XFLOATINT (new_value));
3411 else
3412 signal_error ("Invalid screen-gamma", new_value);
3413
3414 /* Apply the new gamma value to the frame background. */
3415 bgcolor = Fassq (Qbackground_color, f->param_alist);
3416 if (CONSP (bgcolor) && (bgcolor = XCDR (bgcolor), STRINGP (bgcolor)))
3417 {
3418 Lisp_Object parm_index = Fget (Qbackground_color, Qx_frame_parameter);
3419 if (NATNUMP (parm_index)
3420 && XFASTINT (parm_index) < ARRAYELTS (frame_parms)
3421 && FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3422 (*FRAME_RIF (f)->frame_parm_handlers[XFASTINT (parm_index)])
3423 (f, bgcolor, Qnil);
3424 }
3425
3426 Fclear_face_cache (Qnil);
3427 }
3428
3429
3430 void
3431 x_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3432 {
3433 Lisp_Object font_object;
3434 int fontset = -1;
3435 #ifdef HAVE_X_WINDOWS
3436 Lisp_Object font_param = arg;
3437 #endif
3438
3439 /* Set the frame parameter back to the old value because we may
3440 fail to use ARG as the new parameter value. */
3441 store_frame_param (f, Qfont, oldval);
3442
3443 /* ARG is a fontset name, a font name, a cons of fontset name and a
3444 font object, or a font object. In the last case, this function
3445 never fail. */
3446 if (STRINGP (arg))
3447 {
3448 fontset = fs_query_fontset (arg, 0);
3449 if (fontset < 0)
3450 {
3451 font_object = font_open_by_name (f, arg);
3452 if (NILP (font_object))
3453 error ("Font `%s' is not defined", SSDATA (arg));
3454 arg = AREF (font_object, FONT_NAME_INDEX);
3455 }
3456 else if (fontset > 0)
3457 {
3458 font_object = font_open_by_name (f, fontset_ascii (fontset));
3459 if (NILP (font_object))
3460 error ("Font `%s' is not defined", SDATA (arg));
3461 arg = AREF (font_object, FONT_NAME_INDEX);
3462 }
3463 else
3464 error ("The default fontset can't be used for a frame font");
3465 }
3466 else if (CONSP (arg) && STRINGP (XCAR (arg)) && FONT_OBJECT_P (XCDR (arg)))
3467 {
3468 /* This is the case that the ASCII font of F's fontset XCAR
3469 (arg) is changed to the font XCDR (arg) by
3470 `set-fontset-font'. */
3471 fontset = fs_query_fontset (XCAR (arg), 0);
3472 if (fontset < 0)
3473 error ("Unknown fontset: %s", SDATA (XCAR (arg)));
3474 font_object = XCDR (arg);
3475 arg = AREF (font_object, FONT_NAME_INDEX);
3476 #ifdef HAVE_X_WINDOWS
3477 font_param = Ffont_get (font_object, QCname);
3478 #endif
3479 }
3480 else if (FONT_OBJECT_P (arg))
3481 {
3482 font_object = arg;
3483 #ifdef HAVE_X_WINDOWS
3484 font_param = Ffont_get (font_object, QCname);
3485 #endif
3486 /* This is to store the XLFD font name in the frame parameter for
3487 backward compatibility. We should store the font-object
3488 itself in the future. */
3489 arg = AREF (font_object, FONT_NAME_INDEX);
3490 fontset = FRAME_FONTSET (f);
3491 /* Check if we can use the current fontset. If not, set FONTSET
3492 to -1 to generate a new fontset from FONT-OBJECT. */
3493 if (fontset >= 0)
3494 {
3495 Lisp_Object ascii_font = fontset_ascii (fontset);
3496 Lisp_Object spec = font_spec_from_name (ascii_font);
3497
3498 if (NILP (spec))
3499 signal_error ("Invalid font name", ascii_font);
3500
3501 if (! font_match_p (spec, font_object))
3502 fontset = -1;
3503 }
3504 }
3505 else
3506 signal_error ("Invalid font", arg);
3507
3508 if (! NILP (Fequal (font_object, oldval)))
3509 return;
3510
3511 x_new_font (f, font_object, fontset);
3512 store_frame_param (f, Qfont, arg);
3513 #ifdef HAVE_X_WINDOWS
3514 store_frame_param (f, Qfont_param, font_param);
3515 #endif
3516 /* Recalculate toolbar height. */
3517 f->n_tool_bar_rows = 0;
3518
3519 /* Ensure we redraw it. */
3520 clear_current_matrices (f);
3521
3522 /* Attempt to hunt down bug#16028. */
3523 SET_FRAME_GARBAGED (f);
3524
3525 recompute_basic_faces (f);
3526
3527 do_pending_window_change (0);
3528
3529 /* We used to call face-set-after-frame-default here, but it leads to
3530 recursive calls (since that function can set the `default' face's
3531 font which in turns changes the frame's `font' parameter).
3532 Also I don't know what this call is meant to do, but it seems the
3533 wrong way to do it anyway (it does a lot more work than what seems
3534 reasonable in response to a change to `font'). */
3535 }
3536
3537
3538 void
3539 x_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3540 {
3541 if (! NILP (new_value)
3542 && !CONSP (new_value))
3543 {
3544 char *p0, *p1;
3545
3546 CHECK_STRING (new_value);
3547 p0 = p1 = SSDATA (new_value);
3548 new_value = Qnil;
3549 while (*p0)
3550 {
3551 while (*p1 && ! c_isspace (*p1) && *p1 != ',') p1++;
3552 if (p0 < p1)
3553 new_value = Fcons (Fintern (make_string (p0, p1 - p0), Qnil),
3554 new_value);
3555 if (*p1)
3556 {
3557 int c;
3558
3559 while ((c = *++p1) && c_isspace (c));
3560 }
3561 p0 = p1;
3562 }
3563 new_value = Fnreverse (new_value);
3564 }
3565
3566 if (! NILP (old_value) && ! NILP (Fequal (old_value, new_value)))
3567 return;
3568
3569 if (FRAME_FONT (f))
3570 free_all_realized_faces (Qnil);
3571
3572 new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
3573 if (NILP (new_value))
3574 {
3575 if (NILP (old_value))
3576 error ("No font backend available");
3577 font_update_drivers (f, old_value);
3578 error ("None of specified font backends are available");
3579 }
3580 store_frame_param (f, Qfont_backend, new_value);
3581
3582 if (FRAME_FONT (f))
3583 {
3584 Lisp_Object frame;
3585
3586 XSETFRAME (frame, f);
3587 x_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
3588 ++face_change_count;
3589 windows_or_buffers_changed = 18;
3590 }
3591 }
3592
3593 void
3594 x_set_left_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3595 {
3596 int unit = FRAME_COLUMN_WIDTH (f);
3597 int old_width = FRAME_LEFT_FRINGE_WIDTH (f);
3598 int new_width;
3599
3600 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3601 ? eabs (XINT (new_value)) : 8);
3602
3603 if (new_width != old_width)
3604 {
3605 FRAME_LEFT_FRINGE_WIDTH (f) = new_width;
3606 FRAME_FRINGE_COLS (f) /* Round up. */
3607 = (new_width + FRAME_RIGHT_FRINGE_WIDTH (f) + unit - 1) / unit;
3608
3609 if (FRAME_X_WINDOW (f) != 0)
3610 adjust_frame_size (f, -1, -1, 3, 0, Qleft_fringe);
3611
3612 SET_FRAME_GARBAGED (f);
3613 }
3614 }
3615
3616
3617 void
3618 x_set_right_fringe (struct frame *f, Lisp_Object new_value, Lisp_Object old_value)
3619 {
3620 int unit = FRAME_COLUMN_WIDTH (f);
3621 int old_width = FRAME_RIGHT_FRINGE_WIDTH (f);
3622 int new_width;
3623
3624 new_width = (RANGED_INTEGERP (-INT_MAX, new_value, INT_MAX)
3625 ? eabs (XINT (new_value)) : 8);
3626
3627 if (new_width != old_width)
3628 {
3629 FRAME_RIGHT_FRINGE_WIDTH (f) = new_width;
3630 FRAME_FRINGE_COLS (f) /* Round up. */
3631 = (new_width + FRAME_LEFT_FRINGE_WIDTH (f) + unit - 1) / unit;
3632
3633 if (FRAME_X_WINDOW (f) != 0)
3634 adjust_frame_size (f, -1, -1, 3, 0, Qright_fringe);
3635
3636 SET_FRAME_GARBAGED (f);
3637 }
3638 }
3639
3640
3641 void
3642 x_set_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3643 {
3644 CHECK_TYPE_RANGED_INTEGER (int, arg);
3645
3646 if (XINT (arg) == f->border_width)
3647 return;
3648
3649 if (FRAME_X_WINDOW (f) != 0)
3650 error ("Cannot change the border width of a frame");
3651
3652 f->border_width = XINT (arg);
3653 }
3654
3655 void
3656 x_set_right_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3657 {
3658 int old = FRAME_RIGHT_DIVIDER_WIDTH (f);
3659
3660 CHECK_TYPE_RANGED_INTEGER (int, arg);
3661 FRAME_RIGHT_DIVIDER_WIDTH (f) = XINT (arg);
3662 if (FRAME_RIGHT_DIVIDER_WIDTH (f) < 0)
3663 FRAME_RIGHT_DIVIDER_WIDTH (f) = 0;
3664 if (FRAME_RIGHT_DIVIDER_WIDTH (f) != old)
3665 {
3666 adjust_frame_size (f, -1, -1, 4, 0, Qright_divider_width);
3667 adjust_frame_glyphs (f);
3668 SET_FRAME_GARBAGED (f);
3669 }
3670
3671 }
3672
3673 void
3674 x_set_bottom_divider_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3675 {
3676 int old = FRAME_BOTTOM_DIVIDER_WIDTH (f);
3677
3678 CHECK_TYPE_RANGED_INTEGER (int, arg);
3679 FRAME_BOTTOM_DIVIDER_WIDTH (f) = XINT (arg);
3680 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) < 0)
3681 FRAME_BOTTOM_DIVIDER_WIDTH (f) = 0;
3682 if (FRAME_BOTTOM_DIVIDER_WIDTH (f) != old)
3683 {
3684 adjust_frame_size (f, -1, -1, 4, 0, Qbottom_divider_width);
3685 adjust_frame_glyphs (f);
3686 SET_FRAME_GARBAGED (f);
3687 }
3688 }
3689
3690 void
3691 x_set_visibility (struct frame *f, Lisp_Object value, Lisp_Object oldval)
3692 {
3693 Lisp_Object frame;
3694 XSETFRAME (frame, f);
3695
3696 if (NILP (value))
3697 Fmake_frame_invisible (frame, Qt);
3698 else if (EQ (value, Qicon))
3699 Ficonify_frame (frame);
3700 else
3701 Fmake_frame_visible (frame);
3702 }
3703
3704 void
3705 x_set_autoraise (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3706 {
3707 f->auto_raise = !EQ (Qnil, arg);
3708 }
3709
3710 void
3711 x_set_autolower (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3712 {
3713 f->auto_lower = !EQ (Qnil, arg);
3714 }
3715
3716 void
3717 x_set_unsplittable (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3718 {
3719 f->no_split = !NILP (arg);
3720 }
3721
3722 void
3723 x_set_vertical_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3724 {
3725 if ((EQ (arg, Qleft) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
3726 || (EQ (arg, Qright) && FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f))
3727 || (NILP (arg) && FRAME_HAS_VERTICAL_SCROLL_BARS (f))
3728 || (!NILP (arg) && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)))
3729 {
3730 FRAME_VERTICAL_SCROLL_BAR_TYPE (f)
3731 = (NILP (arg)
3732 ? vertical_scroll_bar_none
3733 : EQ (Qleft, arg)
3734 ? vertical_scroll_bar_left
3735 : EQ (Qright, arg)
3736 ? vertical_scroll_bar_right
3737 : EQ (Qleft, Vdefault_frame_scroll_bars)
3738 ? vertical_scroll_bar_left
3739 : EQ (Qright, Vdefault_frame_scroll_bars)
3740 ? vertical_scroll_bar_right
3741 : vertical_scroll_bar_none);
3742
3743 /* We set this parameter before creating the X window for the
3744 frame, so we can get the geometry right from the start.
3745 However, if the window hasn't been created yet, we shouldn't
3746 call x_set_window_size. */
3747 if (FRAME_X_WINDOW (f))
3748 adjust_frame_size (f, -1, -1, 3, 0, Qvertical_scroll_bars);
3749
3750 SET_FRAME_GARBAGED (f);
3751 }
3752 }
3753
3754 void
3755 x_set_horizontal_scroll_bars (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3756 {
3757 #if USE_HORIZONTAL_SCROLL_BARS
3758 if ((NILP (arg) && FRAME_HAS_HORIZONTAL_SCROLL_BARS (f))
3759 || (!NILP (arg) && !FRAME_HAS_HORIZONTAL_SCROLL_BARS (f)))
3760 {
3761 f->horizontal_scroll_bars = NILP (arg) ? false : true;
3762
3763 /* We set this parameter before creating the X window for the
3764 frame, so we can get the geometry right from the start.
3765 However, if the window hasn't been created yet, we shouldn't
3766 call x_set_window_size. */
3767 if (FRAME_X_WINDOW (f))
3768 adjust_frame_size (f, -1, -1, 3, 0, Qhorizontal_scroll_bars);
3769
3770 SET_FRAME_GARBAGED (f);
3771 }
3772 #endif
3773 }
3774
3775 void
3776 x_set_scroll_bar_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3777 {
3778 int unit = FRAME_COLUMN_WIDTH (f);
3779
3780 if (NILP (arg))
3781 {
3782 x_set_scroll_bar_default_width (f);
3783
3784 if (FRAME_X_WINDOW (f))
3785 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3786
3787 SET_FRAME_GARBAGED (f);
3788 }
3789 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3790 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_WIDTH (f))
3791 {
3792 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = XFASTINT (arg);
3793 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (XFASTINT (arg) + unit - 1) / unit;
3794 if (FRAME_X_WINDOW (f))
3795 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_width);
3796
3797 SET_FRAME_GARBAGED (f);
3798 }
3799
3800 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.hpos = 0;
3801 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.x = 0;
3802 }
3803
3804 void
3805 x_set_scroll_bar_height (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3806 {
3807 #if USE_HORIZONTAL_SCROLL_BARS
3808 int unit = FRAME_LINE_HEIGHT (f);
3809
3810 if (NILP (arg))
3811 {
3812 x_set_scroll_bar_default_height (f);
3813
3814 if (FRAME_X_WINDOW (f))
3815 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3816
3817 SET_FRAME_GARBAGED (f);
3818 }
3819 else if (RANGED_INTEGERP (1, arg, INT_MAX)
3820 && XFASTINT (arg) != FRAME_CONFIG_SCROLL_BAR_HEIGHT (f))
3821 {
3822 FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = XFASTINT (arg);
3823 FRAME_CONFIG_SCROLL_BAR_LINES (f) = (XFASTINT (arg) + unit - 1) / unit;
3824 if (FRAME_X_WINDOW (f))
3825 adjust_frame_size (f, -1, -1, 3, 0, Qscroll_bar_height);
3826
3827 SET_FRAME_GARBAGED (f);
3828 }
3829
3830 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.vpos = 0;
3831 XWINDOW (FRAME_SELECTED_WINDOW (f))->cursor.y = 0;
3832 #endif
3833 }
3834
3835 void
3836 x_set_alpha (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
3837 {
3838 double alpha = 1.0;
3839 double newval[2];
3840 int i;
3841 Lisp_Object item;
3842
3843 for (i = 0; i < 2; i++)
3844 {
3845 newval[i] = 1.0;
3846 if (CONSP (arg))
3847 {
3848 item = CAR (arg);
3849 arg = CDR (arg);
3850 }
3851 else
3852 item = arg;
3853
3854 if (NILP (item))
3855 alpha = - 1.0;
3856 else if (FLOATP (item))
3857 {
3858 alpha = XFLOAT_DATA (item);
3859 if (! (0 <= alpha && alpha <= 1.0))
3860 args_out_of_range (make_float (0.0), make_float (1.0));
3861 }
3862 else if (INTEGERP (item))
3863 {
3864 EMACS_INT ialpha = XINT (item);
3865 if (! (0 <= ialpha && alpha <= 100))
3866 args_out_of_range (make_number (0), make_number (100));
3867 alpha = ialpha / 100.0;
3868 }
3869 else
3870 wrong_type_argument (Qnumberp, item);
3871 newval[i] = alpha;
3872 }
3873
3874 for (i = 0; i < 2; i++)
3875 f->alpha[i] = newval[i];
3876
3877 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA)
3878 block_input ();
3879 x_set_frame_alpha (f);
3880 unblock_input ();
3881 #endif
3882
3883 return;
3884 }
3885
3886 #ifndef HAVE_NS
3887
3888 /* Non-zero if mouse is grabbed on DPYINFO
3889 and we know the frame where it is. */
3890
3891 bool x_mouse_grabbed (Display_Info *dpyinfo)
3892 {
3893 return (dpyinfo->grabbed
3894 && dpyinfo->last_mouse_frame
3895 && FRAME_LIVE_P (dpyinfo->last_mouse_frame));
3896 }
3897
3898 /* Re-highlight something with mouse-face properties
3899 on DPYINFO using saved frame and mouse position. */
3900
3901 void
3902 x_redo_mouse_highlight (Display_Info *dpyinfo)
3903 {
3904 if (dpyinfo->last_mouse_motion_frame
3905 && FRAME_LIVE_P (dpyinfo->last_mouse_motion_frame))
3906 note_mouse_highlight (dpyinfo->last_mouse_motion_frame,
3907 dpyinfo->last_mouse_motion_x,
3908 dpyinfo->last_mouse_motion_y);
3909 }
3910
3911 #endif /* HAVE_NS */
3912
3913 /* Subroutines of creating an X frame. */
3914
3915 /* Make sure that Vx_resource_name is set to a reasonable value.
3916 Fix it up, or set it to `emacs' if it is too hopeless. */
3917
3918 void
3919 validate_x_resource_name (void)
3920 {
3921 ptrdiff_t len = 0;
3922 /* Number of valid characters in the resource name. */
3923 ptrdiff_t good_count = 0;
3924 /* Number of invalid characters in the resource name. */
3925 ptrdiff_t bad_count = 0;
3926 Lisp_Object new;
3927 ptrdiff_t i;
3928
3929 if (!STRINGP (Vx_resource_class))
3930 Vx_resource_class = build_string (EMACS_CLASS);
3931
3932 if (STRINGP (Vx_resource_name))
3933 {
3934 unsigned char *p = SDATA (Vx_resource_name);
3935
3936 len = SBYTES (Vx_resource_name);
3937
3938 /* Only letters, digits, - and _ are valid in resource names.
3939 Count the valid characters and count the invalid ones. */
3940 for (i = 0; i < len; i++)
3941 {
3942 int c = p[i];
3943 if (! ((c >= 'a' && c <= 'z')
3944 || (c >= 'A' && c <= 'Z')
3945 || (c >= '0' && c <= '9')
3946 || c == '-' || c == '_'))
3947 bad_count++;
3948 else
3949 good_count++;
3950 }
3951 }
3952 else
3953 /* Not a string => completely invalid. */
3954 bad_count = 5, good_count = 0;
3955
3956 /* If name is valid already, return. */
3957 if (bad_count == 0)
3958 return;
3959
3960 /* If name is entirely invalid, or nearly so, or is so implausibly
3961 large that alloca might not work, use `emacs'. */
3962 if (good_count < 2 || MAX_ALLOCA - sizeof ".customization" < len)
3963 {
3964 Vx_resource_name = build_string ("emacs");
3965 return;
3966 }
3967
3968 /* Name is partly valid. Copy it and replace the invalid characters
3969 with underscores. */
3970
3971 Vx_resource_name = new = Fcopy_sequence (Vx_resource_name);
3972
3973 for (i = 0; i < len; i++)
3974 {
3975 int c = SREF (new, i);
3976 if (! ((c >= 'a' && c <= 'z')
3977 || (c >= 'A' && c <= 'Z')
3978 || (c >= '0' && c <= '9')
3979 || c == '-' || c == '_'))
3980 SSET (new, i, '_');
3981 }
3982 }
3983
3984 /* Get specified attribute from resource database RDB.
3985 See Fx_get_resource below for other parameters. */
3986
3987 static Lisp_Object
3988 xrdb_get_resource (XrmDatabase rdb, Lisp_Object attribute, Lisp_Object class, Lisp_Object component, Lisp_Object subclass)
3989 {
3990 CHECK_STRING (attribute);
3991 CHECK_STRING (class);
3992
3993 if (!NILP (component))
3994 CHECK_STRING (component);
3995 if (!NILP (subclass))
3996 CHECK_STRING (subclass);
3997 if (NILP (component) != NILP (subclass))
3998 error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
3999
4000 validate_x_resource_name ();
4001
4002 /* Allocate space for the components, the dots which separate them,
4003 and the final '\0'. Make them big enough for the worst case. */
4004 ptrdiff_t name_keysize = (SBYTES (Vx_resource_name)
4005 + (STRINGP (component)
4006 ? SBYTES (component) : 0)
4007 + SBYTES (attribute)
4008 + 3);
4009
4010 ptrdiff_t class_keysize = (SBYTES (Vx_resource_class)
4011 + SBYTES (class)
4012 + (STRINGP (subclass)
4013 ? SBYTES (subclass) : 0)
4014 + 3);
4015 USE_SAFE_ALLOCA;
4016 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4017 char *class_key = name_key + name_keysize;
4018
4019 /* Start with emacs.FRAMENAME for the name (the specific one)
4020 and with `Emacs' for the class key (the general one). */
4021 char *nz = lispstpcpy (name_key, Vx_resource_name);
4022 char *cz = lispstpcpy (class_key, Vx_resource_class);
4023
4024 *cz++ = '.';
4025 cz = lispstpcpy (cz, class);
4026
4027 if (!NILP (component))
4028 {
4029 *cz++ = '.';
4030 lispstpcpy (cz, subclass);
4031
4032 *nz++ = '.';
4033 nz = lispstpcpy (nz, component);
4034 }
4035
4036 *nz++ = '.';
4037 lispstpcpy (nz, attribute);
4038
4039 char *value = x_get_string_resource (rdb, name_key, class_key);
4040 SAFE_FREE();
4041
4042 if (value && *value)
4043 return build_string (value);
4044 else
4045 return Qnil;
4046 }
4047
4048
4049 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
4050 doc: /* Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.
4051 This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the
4052 class, where INSTANCE is the name under which Emacs was invoked, or
4053 the name specified by the `-name' or `-rn' command-line arguments.
4054
4055 The optional arguments COMPONENT and SUBCLASS add to the key and the
4056 class, respectively. You must specify both of them or neither.
4057 If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'
4058 and the class is `Emacs.CLASS.SUBCLASS'. */)
4059 (Lisp_Object attribute, Lisp_Object class, Lisp_Object component,
4060 Lisp_Object subclass)
4061 {
4062 check_window_system (NULL);
4063
4064 return xrdb_get_resource (check_x_display_info (Qnil)->xrdb,
4065 attribute, class, component, subclass);
4066 }
4067
4068 /* Get an X resource, like Fx_get_resource, but for display DPYINFO. */
4069
4070 Lisp_Object
4071 display_x_get_resource (Display_Info *dpyinfo, Lisp_Object attribute,
4072 Lisp_Object class, Lisp_Object component,
4073 Lisp_Object subclass)
4074 {
4075 return xrdb_get_resource (dpyinfo->xrdb,
4076 attribute, class, component, subclass);
4077 }
4078
4079 #if defined HAVE_X_WINDOWS && !defined USE_X_TOOLKIT
4080 /* Used when C code wants a resource value. */
4081 /* Called from oldXMenu/Create.c. */
4082 char *
4083 x_get_resource_string (const char *attribute, const char *class)
4084 {
4085 char *result;
4086 struct frame *sf = SELECTED_FRAME ();
4087 ptrdiff_t invocation_namelen = SBYTES (Vinvocation_name);
4088 USE_SAFE_ALLOCA;
4089
4090 /* Allocate space for the components, the dots which separate them,
4091 and the final '\0'. */
4092 ptrdiff_t name_keysize = invocation_namelen + strlen (attribute) + 2;
4093 ptrdiff_t class_keysize = sizeof (EMACS_CLASS) - 1 + strlen (class) + 2;
4094 char *name_key = SAFE_ALLOCA (name_keysize + class_keysize);
4095 char *class_key = name_key + name_keysize;
4096
4097 esprintf (name_key, "%s.%s", SSDATA (Vinvocation_name), attribute);
4098 sprintf (class_key, "%s.%s", EMACS_CLASS, class);
4099
4100 result = x_get_string_resource (FRAME_DISPLAY_INFO (sf)->xrdb,
4101 name_key, class_key);
4102 SAFE_FREE ();
4103 return result;
4104 }
4105 #endif
4106
4107 /* Return the value of parameter PARAM.
4108
4109 First search ALIST, then Vdefault_frame_alist, then the X defaults
4110 database, using ATTRIBUTE as the attribute name and CLASS as its class.
4111
4112 Convert the resource to the type specified by desired_type.
4113
4114 If no default is specified, return Qunbound. If you call
4115 x_get_arg, make sure you deal with Qunbound in a reasonable way,
4116 and don't let it get stored in any Lisp-visible variables! */
4117
4118 Lisp_Object
4119 x_get_arg (Display_Info *dpyinfo, Lisp_Object alist, Lisp_Object param,
4120 const char *attribute, const char *class, enum resource_types type)
4121 {
4122 Lisp_Object tem;
4123
4124 tem = Fassq (param, alist);
4125
4126 if (!NILP (tem))
4127 {
4128 /* If we find this parm in ALIST, clear it out
4129 so that it won't be "left over" at the end. */
4130 Lisp_Object tail;
4131 XSETCAR (tem, Qnil);
4132 /* In case the parameter appears more than once in the alist,
4133 clear it out. */
4134 for (tail = alist; CONSP (tail); tail = XCDR (tail))
4135 if (CONSP (XCAR (tail))
4136 && EQ (XCAR (XCAR (tail)), param))
4137 XSETCAR (XCAR (tail), Qnil);
4138 }
4139 else
4140 tem = Fassq (param, Vdefault_frame_alist);
4141
4142 /* If it wasn't specified in ALIST or the Lisp-level defaults,
4143 look in the X resources. */
4144 if (EQ (tem, Qnil))
4145 {
4146 if (attribute && dpyinfo)
4147 {
4148 AUTO_STRING (at, attribute);
4149 AUTO_STRING (cl, class);
4150 tem = display_x_get_resource (dpyinfo, at, cl, Qnil, Qnil);
4151
4152 if (NILP (tem))
4153 return Qunbound;
4154
4155 switch (type)
4156 {
4157 case RES_TYPE_NUMBER:
4158 return make_number (atoi (SSDATA (tem)));
4159
4160 case RES_TYPE_BOOLEAN_NUMBER:
4161 if (!strcmp (SSDATA (tem), "on")
4162 || !strcmp (SSDATA (tem), "true"))
4163 return make_number (1);
4164 return make_number (atoi (SSDATA (tem)));
4165 break;
4166
4167 case RES_TYPE_FLOAT:
4168 return make_float (atof (SSDATA (tem)));
4169
4170 case RES_TYPE_BOOLEAN:
4171 tem = Fdowncase (tem);
4172 if (!strcmp (SSDATA (tem), "on")
4173 #ifdef HAVE_NS
4174 || !strcmp (SSDATA (tem), "yes")
4175 #endif
4176 || !strcmp (SSDATA (tem), "true"))
4177 return Qt;
4178 else
4179 return Qnil;
4180
4181 case RES_TYPE_STRING:
4182 return tem;
4183
4184 case RES_TYPE_SYMBOL:
4185 /* As a special case, we map the values `true' and `on'
4186 to Qt, and `false' and `off' to Qnil. */
4187 {
4188 Lisp_Object lower;
4189 lower = Fdowncase (tem);
4190 if (!strcmp (SSDATA (lower), "on")
4191 #ifdef HAVE_NS
4192 || !strcmp (SSDATA (lower), "yes")
4193 #endif
4194 || !strcmp (SSDATA (lower), "true"))
4195 return Qt;
4196 else if (!strcmp (SSDATA (lower), "off")
4197 #ifdef HAVE_NS
4198 || !strcmp (SSDATA (lower), "no")
4199 #endif
4200 || !strcmp (SSDATA (lower), "false"))
4201 return Qnil;
4202 else
4203 return Fintern (tem, Qnil);
4204 }
4205
4206 default:
4207 emacs_abort ();
4208 }
4209 }
4210 else
4211 return Qunbound;
4212 }
4213 return Fcdr (tem);
4214 }
4215
4216 static Lisp_Object
4217 x_frame_get_arg (struct frame *f, Lisp_Object alist, Lisp_Object param,
4218 const char *attribute, const char *class,
4219 enum resource_types type)
4220 {
4221 return x_get_arg (FRAME_DISPLAY_INFO (f),
4222 alist, param, attribute, class, type);
4223 }
4224
4225 /* Like x_frame_get_arg, but also record the value in f->param_alist. */
4226
4227 Lisp_Object
4228 x_frame_get_and_record_arg (struct frame *f, Lisp_Object alist,
4229 Lisp_Object param,
4230 const char *attribute, const char *class,
4231 enum resource_types type)
4232 {
4233 Lisp_Object value;
4234
4235 value = x_get_arg (FRAME_DISPLAY_INFO (f), alist, param,
4236 attribute, class, type);
4237 if (! NILP (value) && ! EQ (value, Qunbound))
4238 store_frame_param (f, param, value);
4239
4240 return value;
4241 }
4242
4243
4244 /* Record in frame F the specified or default value according to ALIST
4245 of the parameter named PROP (a Lisp symbol).
4246 If no value is specified for PROP, look for an X default for XPROP
4247 on the frame named NAME.
4248 If that is not found either, use the value DEFLT. */
4249
4250 Lisp_Object
4251 x_default_parameter (struct frame *f, Lisp_Object alist, Lisp_Object prop,
4252 Lisp_Object deflt, const char *xprop, const char *xclass,
4253 enum resource_types type)
4254 {
4255 Lisp_Object tem;
4256
4257 tem = x_frame_get_arg (f, alist, prop, xprop, xclass, type);
4258 if (EQ (tem, Qunbound))
4259 tem = deflt;
4260 AUTO_FRAME_ARG (arg, prop, tem);
4261 x_set_frame_parameters (f, arg);
4262 return tem;
4263 }
4264
4265
4266 #if !defined (HAVE_X_WINDOWS) && defined (NoValue)
4267
4268 /*
4269 * XParseGeometry parses strings of the form
4270 * "=<width>x<height>{+-}<xoffset>{+-}<yoffset>", where
4271 * width, height, xoffset, and yoffset are unsigned integers.
4272 * Example: "=80x24+300-49"
4273 * The equal sign is optional.
4274 * It returns a bitmask that indicates which of the four values
4275 * were actually found in the string. For each value found,
4276 * the corresponding argument is updated; for each value
4277 * not found, the corresponding argument is left unchanged.
4278 */
4279
4280 static int
4281 XParseGeometry (char *string,
4282 int *x, int *y,
4283 unsigned int *width, unsigned int *height)
4284 {
4285 int mask = NoValue;
4286 char *strind;
4287 unsigned long tempWidth, tempHeight;
4288 long int tempX, tempY;
4289 char *nextCharacter;
4290
4291 if (string == NULL || *string == '\0')
4292 return mask;
4293 if (*string == '=')
4294 string++; /* ignore possible '=' at beg of geometry spec */
4295
4296 strind = string;
4297 if (*strind != '+' && *strind != '-' && *strind != 'x')
4298 {
4299 tempWidth = strtoul (strind, &nextCharacter, 10);
4300 if (strind == nextCharacter)
4301 return 0;
4302 strind = nextCharacter;
4303 mask |= WidthValue;
4304 }
4305
4306 if (*strind == 'x' || *strind == 'X')
4307 {
4308 strind++;
4309 tempHeight = strtoul (strind, &nextCharacter, 10);
4310 if (strind == nextCharacter)
4311 return 0;
4312 strind = nextCharacter;
4313 mask |= HeightValue;
4314 }
4315
4316 if (*strind == '+' || *strind == '-')
4317 {
4318 if (*strind == '-')
4319 mask |= XNegative;
4320 tempX = strtol (strind, &nextCharacter, 10);
4321 if (strind == nextCharacter)
4322 return 0;
4323 strind = nextCharacter;
4324 mask |= XValue;
4325 if (*strind == '+' || *strind == '-')
4326 {
4327 if (*strind == '-')
4328 mask |= YNegative;
4329 tempY = strtol (strind, &nextCharacter, 10);
4330 if (strind == nextCharacter)
4331 return 0;
4332 strind = nextCharacter;
4333 mask |= YValue;
4334 }
4335 }
4336
4337 /* If strind isn't at the end of the string then it's an invalid
4338 geometry specification. */
4339
4340 if (*strind != '\0')
4341 return 0;
4342
4343 if (mask & XValue)
4344 *x = clip_to_bounds (INT_MIN, tempX, INT_MAX);
4345 if (mask & YValue)
4346 *y = clip_to_bounds (INT_MIN, tempY, INT_MAX);
4347 if (mask & WidthValue)
4348 *width = min (tempWidth, UINT_MAX);
4349 if (mask & HeightValue)
4350 *height = min (tempHeight, UINT_MAX);
4351 return mask;
4352 }
4353
4354 #endif /* !defined (HAVE_X_WINDOWS) && defined (NoValue) */
4355
4356 \f
4357 /* NS used to define x-parse-geometry in ns-win.el, but that confused
4358 make-docfile: the documentation string in ns-win.el was used for
4359 x-parse-geometry even in non-NS builds.
4360
4361 With two definitions of x-parse-geometry in this file, various
4362 things still get confused (eg M-x apropos documentation), so that
4363 it is best if the two definitions just share the same doc-string.
4364 */
4365 DEFUN ("x-parse-geometry", Fx_parse_geometry, Sx_parse_geometry, 1, 1, 0,
4366 doc: /* Parse a display geometry string STRING.
4367 Returns an alist of the form ((top . TOP), (left . LEFT) ... ).
4368 The properties returned may include `top', `left', `height', and `width'.
4369 For X, the value of `left' or `top' may be an integer,
4370 or a list (+ N) meaning N pixels relative to top/left corner,
4371 or a list (- N) meaning -N pixels relative to bottom/right corner.
4372 On Nextstep, this just calls `ns-parse-geometry'. */)
4373 (Lisp_Object string)
4374 {
4375 int geometry, x, y;
4376 unsigned int width, height;
4377 Lisp_Object result;
4378
4379 CHECK_STRING (string);
4380
4381 #ifdef HAVE_NS
4382 if (strchr (SSDATA (string), ' ') != NULL)
4383 return call1 (Qns_parse_geometry, string);
4384 #endif
4385 geometry = XParseGeometry (SSDATA (string),
4386 &x, &y, &width, &height);
4387 result = Qnil;
4388 if (geometry & XValue)
4389 {
4390 Lisp_Object element;
4391
4392 if (x >= 0 && (geometry & XNegative))
4393 element = list3 (Qleft, Qminus, make_number (-x));
4394 else if (x < 0 && ! (geometry & XNegative))
4395 element = list3 (Qleft, Qplus, make_number (x));
4396 else
4397 element = Fcons (Qleft, make_number (x));
4398 result = Fcons (element, result);
4399 }
4400
4401 if (geometry & YValue)
4402 {
4403 Lisp_Object element;
4404
4405 if (y >= 0 && (geometry & YNegative))
4406 element = list3 (Qtop, Qminus, make_number (-y));
4407 else if (y < 0 && ! (geometry & YNegative))
4408 element = list3 (Qtop, Qplus, make_number (y));
4409 else
4410 element = Fcons (Qtop, make_number (y));
4411 result = Fcons (element, result);
4412 }
4413
4414 if (geometry & WidthValue)
4415 result = Fcons (Fcons (Qwidth, make_number (width)), result);
4416 if (geometry & HeightValue)
4417 result = Fcons (Fcons (Qheight, make_number (height)), result);
4418
4419 return result;
4420 }
4421
4422
4423 /* Calculate the desired size and position of frame F.
4424 Return the flags saying which aspects were specified.
4425
4426 Also set the win_gravity and size_hint_flags of F.
4427
4428 Adjust height for toolbar if TOOLBAR_P is 1.
4429
4430 This function does not make the coordinates positive. */
4431
4432 #define DEFAULT_ROWS 35
4433 #define DEFAULT_COLS 80
4434
4435 long
4436 x_figure_window_size (struct frame *f, Lisp_Object parms, bool toolbar_p)
4437 {
4438 Lisp_Object height, width, user_size, top, left, user_position;
4439 long window_prompting = 0;
4440 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
4441
4442 /* Default values if we fall through.
4443 Actually, if that happens we should get
4444 window manager prompting. */
4445 SET_FRAME_WIDTH (f, DEFAULT_COLS * FRAME_COLUMN_WIDTH (f));
4446 SET_FRAME_COLS (f, DEFAULT_COLS);
4447 SET_FRAME_HEIGHT (f, DEFAULT_ROWS * FRAME_LINE_HEIGHT (f));
4448 SET_FRAME_LINES (f, DEFAULT_ROWS);
4449
4450 /* Window managers expect that if program-specified
4451 positions are not (0,0), they're intentional, not defaults. */
4452 f->top_pos = 0;
4453 f->left_pos = 0;
4454
4455 /* Ensure that earlier new_width and new_height settings won't
4456 override what we specify below. */
4457 f->new_width = f->new_height = 0;
4458
4459 height = x_get_arg (dpyinfo, parms, Qheight, 0, 0, RES_TYPE_NUMBER);
4460 width = x_get_arg (dpyinfo, parms, Qwidth, 0, 0, RES_TYPE_NUMBER);
4461 if (!EQ (width, Qunbound) || !EQ (height, Qunbound))
4462 {
4463 if (!EQ (width, Qunbound))
4464 {
4465 CHECK_NUMBER (width);
4466 if (! (0 <= XINT (width) && XINT (width) <= INT_MAX))
4467 xsignal1 (Qargs_out_of_range, width);
4468
4469 SET_FRAME_WIDTH (f, XINT (width) * FRAME_COLUMN_WIDTH (f));
4470 }
4471
4472 if (!EQ (height, Qunbound))
4473 {
4474 CHECK_NUMBER (height);
4475 if (! (0 <= XINT (height) && XINT (height) <= INT_MAX))
4476 xsignal1 (Qargs_out_of_range, height);
4477
4478 SET_FRAME_HEIGHT (f, XINT (height) * FRAME_LINE_HEIGHT (f));
4479 }
4480
4481 user_size = x_get_arg (dpyinfo, parms, Quser_size, 0, 0, RES_TYPE_NUMBER);
4482 if (!NILP (user_size) && !EQ (user_size, Qunbound))
4483 window_prompting |= USSize;
4484 else
4485 window_prompting |= PSize;
4486 }
4487
4488 /* Add a tool bar height to the initial frame height so that the user
4489 gets a text display area of the size he specified with -g or via
4490 .Xdefaults. Later changes of the tool bar height don't change the
4491 frame size. This is done so that users can create tall Emacs
4492 frames without having to guess how tall the tool bar will get. */
4493 if (toolbar_p && FRAME_TOOL_BAR_LINES (f))
4494 {
4495 int margin, relief;
4496
4497 relief = (tool_bar_button_relief >= 0
4498 ? tool_bar_button_relief
4499 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
4500
4501 if (RANGED_INTEGERP (1, Vtool_bar_button_margin, INT_MAX))
4502 margin = XFASTINT (Vtool_bar_button_margin);
4503 else if (CONSP (Vtool_bar_button_margin)
4504 && RANGED_INTEGERP (1, XCDR (Vtool_bar_button_margin), INT_MAX))
4505 margin = XFASTINT (XCDR (Vtool_bar_button_margin));
4506 else
4507 margin = 0;
4508
4509 FRAME_TOOL_BAR_HEIGHT (f)
4510 = DEFAULT_TOOL_BAR_IMAGE_HEIGHT + 2 * margin + 2 * relief;
4511 Vframe_initial_frame_tool_bar_height = make_number (FRAME_TOOL_BAR_HEIGHT (f));
4512 }
4513
4514 top = x_get_arg (dpyinfo, parms, Qtop, 0, 0, RES_TYPE_NUMBER);
4515 left = x_get_arg (dpyinfo, parms, Qleft, 0, 0, RES_TYPE_NUMBER);
4516 user_position = x_get_arg (dpyinfo, parms, Quser_position, 0, 0, RES_TYPE_NUMBER);
4517 if (! EQ (top, Qunbound) || ! EQ (left, Qunbound))
4518 {
4519 if (EQ (top, Qminus))
4520 {
4521 f->top_pos = 0;
4522 window_prompting |= YNegative;
4523 }
4524 else if (CONSP (top) && EQ (XCAR (top), Qminus)
4525 && CONSP (XCDR (top))
4526 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (top)), INT_MAX))
4527 {
4528 f->top_pos = - XINT (XCAR (XCDR (top)));
4529 window_prompting |= YNegative;
4530 }
4531 else if (CONSP (top) && EQ (XCAR (top), Qplus)
4532 && CONSP (XCDR (top))
4533 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (top))))
4534 {
4535 f->top_pos = XINT (XCAR (XCDR (top)));
4536 }
4537 else if (EQ (top, Qunbound))
4538 f->top_pos = 0;
4539 else
4540 {
4541 CHECK_TYPE_RANGED_INTEGER (int, top);
4542 f->top_pos = XINT (top);
4543 if (f->top_pos < 0)
4544 window_prompting |= YNegative;
4545 }
4546
4547 if (EQ (left, Qminus))
4548 {
4549 f->left_pos = 0;
4550 window_prompting |= XNegative;
4551 }
4552 else if (CONSP (left) && EQ (XCAR (left), Qminus)
4553 && CONSP (XCDR (left))
4554 && RANGED_INTEGERP (-INT_MAX, XCAR (XCDR (left)), INT_MAX))
4555 {
4556 f->left_pos = - XINT (XCAR (XCDR (left)));
4557 window_prompting |= XNegative;
4558 }
4559 else if (CONSP (left) && EQ (XCAR (left), Qplus)
4560 && CONSP (XCDR (left))
4561 && TYPE_RANGED_INTEGERP (int, XCAR (XCDR (left))))
4562 {
4563 f->left_pos = XINT (XCAR (XCDR (left)));
4564 }
4565 else if (EQ (left, Qunbound))
4566 f->left_pos = 0;
4567 else
4568 {
4569 CHECK_TYPE_RANGED_INTEGER (int, left);
4570 f->left_pos = XINT (left);
4571 if (f->left_pos < 0)
4572 window_prompting |= XNegative;
4573 }
4574
4575 if (!NILP (user_position) && ! EQ (user_position, Qunbound))
4576 window_prompting |= USPosition;
4577 else
4578 window_prompting |= PPosition;
4579 }
4580
4581 if (window_prompting & XNegative)
4582 {
4583 if (window_prompting & YNegative)
4584 f->win_gravity = SouthEastGravity;
4585 else
4586 f->win_gravity = NorthEastGravity;
4587 }
4588 else
4589 {
4590 if (window_prompting & YNegative)
4591 f->win_gravity = SouthWestGravity;
4592 else
4593 f->win_gravity = NorthWestGravity;
4594 }
4595
4596 f->size_hint_flags = window_prompting;
4597
4598 return window_prompting;
4599 }
4600
4601
4602
4603 #endif /* HAVE_WINDOW_SYSTEM */
4604
4605 void
4606 frame_make_pointer_invisible (struct frame *f)
4607 {
4608 if (! NILP (Vmake_pointer_invisible))
4609 {
4610 if (f && FRAME_LIVE_P (f) && !f->pointer_invisible
4611 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4612 {
4613 f->mouse_moved = 0;
4614 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 1);
4615 f->pointer_invisible = 1;
4616 }
4617 }
4618 }
4619
4620 void
4621 frame_make_pointer_visible (struct frame *f)
4622 {
4623 /* We don't check Vmake_pointer_invisible here in case the
4624 pointer was invisible when Vmake_pointer_invisible was set to nil. */
4625 if (f && FRAME_LIVE_P (f) && f->pointer_invisible && f->mouse_moved
4626 && FRAME_TERMINAL (f)->toggle_invisible_pointer_hook)
4627 {
4628 FRAME_TERMINAL (f)->toggle_invisible_pointer_hook (f, 0);
4629 f->pointer_invisible = 0;
4630 }
4631 }
4632
4633 DEFUN ("frame-pointer-visible-p", Fframe_pointer_visible_p,
4634 Sframe_pointer_visible_p, 0, 1, 0,
4635 doc: /* Return t if the mouse pointer displayed on FRAME is visible.
4636 Otherwise it returns nil. FRAME omitted or nil means the
4637 selected frame. This is useful when `make-pointer-invisible' is set. */)
4638 (Lisp_Object frame)
4639 {
4640 return decode_any_frame (frame)->pointer_invisible ? Qnil : Qt;
4641 }
4642
4643
4644 \f
4645 /***********************************************************************
4646 Multimonitor data
4647 ***********************************************************************/
4648
4649 #ifdef HAVE_WINDOW_SYSTEM
4650
4651 # if (defined HAVE_NS \
4652 || (!defined USE_GTK && (defined HAVE_XINERAMA || defined HAVE_XRANDR)))
4653 void
4654 free_monitors (struct MonitorInfo *monitors, int n_monitors)
4655 {
4656 int i;
4657 for (i = 0; i < n_monitors; ++i)
4658 xfree (monitors[i].name);
4659 xfree (monitors);
4660 }
4661 # endif
4662
4663 Lisp_Object
4664 make_monitor_attribute_list (struct MonitorInfo *monitors,
4665 int n_monitors,
4666 int primary_monitor,
4667 Lisp_Object monitor_frames,
4668 const char *source)
4669 {
4670 Lisp_Object attributes_list = Qnil;
4671 Lisp_Object primary_monitor_attributes = Qnil;
4672 int i;
4673
4674 for (i = 0; i < n_monitors; ++i)
4675 {
4676 Lisp_Object geometry, workarea, attributes = Qnil;
4677 struct MonitorInfo *mi = &monitors[i];
4678
4679 if (mi->geom.width == 0) continue;
4680
4681 workarea = list4i (mi->work.x, mi->work.y,
4682 mi->work.width, mi->work.height);
4683 geometry = list4i (mi->geom.x, mi->geom.y,
4684 mi->geom.width, mi->geom.height);
4685 attributes = Fcons (Fcons (Qsource, build_string (source)),
4686 attributes);
4687 attributes = Fcons (Fcons (Qframes, AREF (monitor_frames, i)),
4688 attributes);
4689 attributes = Fcons (Fcons (Qmm_size,
4690 list2i (mi->mm_width, mi->mm_height)),
4691 attributes);
4692 attributes = Fcons (Fcons (Qworkarea, workarea), attributes);
4693 attributes = Fcons (Fcons (Qgeometry, geometry), attributes);
4694 if (mi->name)
4695 attributes = Fcons (Fcons (Qname, make_string (mi->name,
4696 strlen (mi->name))),
4697 attributes);
4698
4699 if (i == primary_monitor)
4700 primary_monitor_attributes = attributes;
4701 else
4702 attributes_list = Fcons (attributes, attributes_list);
4703 }
4704
4705 if (!NILP (primary_monitor_attributes))
4706 attributes_list = Fcons (primary_monitor_attributes, attributes_list);
4707 return attributes_list;
4708 }
4709
4710 #endif /* HAVE_WINDOW_SYSTEM */
4711
4712 \f
4713 /***********************************************************************
4714 Initialization
4715 ***********************************************************************/
4716
4717 void
4718 syms_of_frame (void)
4719 {
4720 DEFSYM (Qframep, "framep");
4721 DEFSYM (Qframe_live_p, "frame-live-p");
4722 DEFSYM (Qframe_windows_min_size, "frame-windows-min-size");
4723 DEFSYM (Qexplicit_name, "explicit-name");
4724 DEFSYM (Qheight, "height");
4725 DEFSYM (Qicon, "icon");
4726 DEFSYM (Qminibuffer, "minibuffer");
4727 DEFSYM (Qmodeline, "modeline");
4728 DEFSYM (Qonly, "only");
4729 DEFSYM (Qnone, "none");
4730 DEFSYM (Qwidth, "width");
4731 DEFSYM (Qgeometry, "geometry");
4732 DEFSYM (Qicon_left, "icon-left");
4733 DEFSYM (Qicon_top, "icon-top");
4734 DEFSYM (Qtooltip, "tooltip");
4735 DEFSYM (Quser_position, "user-position");
4736 DEFSYM (Quser_size, "user-size");
4737 DEFSYM (Qwindow_id, "window-id");
4738 #ifdef HAVE_X_WINDOWS
4739 DEFSYM (Qouter_window_id, "outer-window-id");
4740 #endif
4741 DEFSYM (Qparent_id, "parent-id");
4742 DEFSYM (Qx, "x");
4743 DEFSYM (Qw32, "w32");
4744 DEFSYM (Qpc, "pc");
4745 DEFSYM (Qns, "ns");
4746 DEFSYM (Qvisible, "visible");
4747 DEFSYM (Qbuffer_predicate, "buffer-predicate");
4748 DEFSYM (Qbuffer_list, "buffer-list");
4749 DEFSYM (Qburied_buffer_list, "buried-buffer-list");
4750 DEFSYM (Qdisplay_type, "display-type");
4751 DEFSYM (Qbackground_mode, "background-mode");
4752 DEFSYM (Qnoelisp, "noelisp");
4753 DEFSYM (Qtty_color_mode, "tty-color-mode");
4754 DEFSYM (Qtty, "tty");
4755 DEFSYM (Qtty_type, "tty-type");
4756
4757 DEFSYM (Qface_set_after_frame_default, "face-set-after-frame-default");
4758
4759 DEFSYM (Qfullwidth, "fullwidth");
4760 DEFSYM (Qfullheight, "fullheight");
4761 DEFSYM (Qfullboth, "fullboth");
4762 DEFSYM (Qmaximized, "maximized");
4763 DEFSYM (Qx_resource_name, "x-resource-name");
4764 DEFSYM (Qx_frame_parameter, "x-frame-parameter");
4765
4766 DEFSYM (Qterminal, "terminal");
4767
4768 DEFSYM (Qworkarea, "workarea");
4769 DEFSYM (Qmm_size, "mm-size");
4770 DEFSYM (Qframes, "frames");
4771 DEFSYM (Qsource, "source");
4772
4773 DEFSYM (Qframe_position, "frame-position");
4774 DEFSYM (Qframe_outer_size, "frame-outer-size");
4775 DEFSYM (Qexternal_border_size, "external-border-size");
4776 DEFSYM (Qtitle_height, "title-height");
4777 DEFSYM (Qmenu_bar_external, "menu-bar-external");
4778 DEFSYM (Qmenu_bar_size, "menu-bar-size");
4779 DEFSYM (Qtool_bar_external, "tool-bar-external");
4780 DEFSYM (Qtool_bar_size, "tool-bar-size");
4781 DEFSYM (Qframe_inner_size, "frame-inner-size");
4782
4783 #ifdef HAVE_NS
4784 DEFSYM (Qns_parse_geometry, "ns-parse-geometry");
4785 #endif
4786
4787 DEFSYM (Qalpha, "alpha");
4788 DEFSYM (Qauto_lower, "auto-lower");
4789 DEFSYM (Qauto_raise, "auto-raise");
4790 DEFSYM (Qborder_color, "border-color");
4791 DEFSYM (Qborder_width, "border-width");
4792 DEFSYM (Qbottom_divider_width, "bottom-divider-width");
4793 DEFSYM (Qcursor_color, "cursor-color");
4794 DEFSYM (Qcursor_type, "cursor-type");
4795 DEFSYM (Qfont_backend, "font-backend");
4796 DEFSYM (Qfullscreen, "fullscreen");
4797 DEFSYM (Qhorizontal_scroll_bars, "horizontal-scroll-bars");
4798 DEFSYM (Qicon_name, "icon-name");
4799 DEFSYM (Qicon_type, "icon-type");
4800 DEFSYM (Qinternal_border_width, "internal-border-width");
4801 DEFSYM (Qleft_fringe, "left-fringe");
4802 DEFSYM (Qline_spacing, "line-spacing");
4803 DEFSYM (Qmenu_bar_lines, "menu-bar-lines");
4804 DEFSYM (Qmouse_color, "mouse-color");
4805 DEFSYM (Qname, "name");
4806 DEFSYM (Qright_divider_width, "right-divider-width");
4807 DEFSYM (Qright_fringe, "right-fringe");
4808 DEFSYM (Qscreen_gamma, "screen-gamma");
4809 DEFSYM (Qscroll_bar_background, "scroll-bar-background");
4810 DEFSYM (Qscroll_bar_foreground, "scroll-bar-foreground");
4811 DEFSYM (Qscroll_bar_height, "scroll-bar-height");
4812 DEFSYM (Qscroll_bar_width, "scroll-bar-width");
4813 DEFSYM (Qsticky, "sticky");
4814 DEFSYM (Qtitle, "title");
4815 DEFSYM (Qtool_bar_lines, "tool-bar-lines");
4816 DEFSYM (Qtool_bar_position, "tool-bar-position");
4817 DEFSYM (Qunsplittable, "unsplittable");
4818 DEFSYM (Qvertical_scroll_bars, "vertical-scroll-bars");
4819 DEFSYM (Qvisibility, "visibility");
4820 DEFSYM (Qwait_for_wm, "wait-for-wm");
4821
4822 {
4823 int i;
4824
4825 for (i = 0; i < ARRAYELTS (frame_parms); i++)
4826 {
4827 Lisp_Object v = (frame_parms[i].sym
4828 ? make_lisp_symbol (frame_parms[i].sym)
4829 : intern_c_string (frame_parms[i].name));
4830 Fput (v, Qx_frame_parameter, make_number (i));
4831 }
4832 }
4833
4834 #ifdef HAVE_WINDOW_SYSTEM
4835 DEFVAR_LISP ("x-resource-name", Vx_resource_name,
4836 doc: /* The name Emacs uses to look up X resources.
4837 `x-get-resource' uses this as the first component of the instance name
4838 when requesting resource values.
4839 Emacs initially sets `x-resource-name' to the name under which Emacs
4840 was invoked, or to the value specified with the `-name' or `-rn'
4841 switches, if present.
4842
4843 It may be useful to bind this variable locally around a call
4844 to `x-get-resource'. See also the variable `x-resource-class'. */);
4845 Vx_resource_name = Qnil;
4846
4847 DEFVAR_LISP ("x-resource-class", Vx_resource_class,
4848 doc: /* The class Emacs uses to look up X resources.
4849 `x-get-resource' uses this as the first component of the instance class
4850 when requesting resource values.
4851
4852 Emacs initially sets `x-resource-class' to "Emacs".
4853
4854 Setting this variable permanently is not a reasonable thing to do,
4855 but binding this variable locally around a call to `x-get-resource'
4856 is a reasonable practice. See also the variable `x-resource-name'. */);
4857 Vx_resource_class = build_string (EMACS_CLASS);
4858
4859 DEFVAR_LISP ("frame-alpha-lower-limit", Vframe_alpha_lower_limit,
4860 doc: /* The lower limit of the frame opacity (alpha transparency).
4861 The value should range from 0 (invisible) to 100 (completely opaque).
4862 You can also use a floating number between 0.0 and 1.0. */);
4863 Vframe_alpha_lower_limit = make_number (20);
4864 #endif
4865
4866 DEFVAR_LISP ("default-frame-alist", Vdefault_frame_alist,
4867 doc: /* Alist of default values for frame creation.
4868 These may be set in your init file, like this:
4869 (setq default-frame-alist '((width . 80) (height . 55) (menu-bar-lines . 1)))
4870 These override values given in window system configuration data,
4871 including X Windows' defaults database.
4872 For values specific to the first Emacs frame, see `initial-frame-alist'.
4873 For window-system specific values, see `window-system-default-frame-alist'.
4874 For values specific to the separate minibuffer frame, see
4875 `minibuffer-frame-alist'.
4876 The `menu-bar-lines' element of the list controls whether new frames
4877 have menu bars; `menu-bar-mode' works by altering this element.
4878 Setting this variable does not affect existing frames, only new ones. */);
4879 Vdefault_frame_alist = Qnil;
4880
4881 DEFVAR_LISP ("default-frame-scroll-bars", Vdefault_frame_scroll_bars,
4882 doc: /* Default position of vertical scroll bars on this window-system. */);
4883 #ifdef HAVE_WINDOW_SYSTEM
4884 #if defined (HAVE_NTGUI) || defined (NS_IMPL_COCOA) || (defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS))
4885 /* MS-Windows, Mac OS X, and GTK have scroll bars on the right by
4886 default. */
4887 Vdefault_frame_scroll_bars = Qright;
4888 #else
4889 Vdefault_frame_scroll_bars = Qleft;
4890 #endif
4891 #else
4892 Vdefault_frame_scroll_bars = Qnil;
4893 #endif
4894
4895 DEFVAR_BOOL ("scroll-bar-adjust-thumb-portion",
4896 scroll_bar_adjust_thumb_portion_p,
4897 doc: /* Adjust thumb for overscrolling for Gtk+ and MOTIF.
4898 Non-nil means adjust the thumb in the scroll bar so it can be dragged downwards
4899 even if the end of the buffer is shown (i.e. overscrolling).
4900 Set to nil if you want the thumb to be at the bottom when the end of the buffer
4901 is shown. Also, the thumb fills the whole scroll bar when the entire buffer
4902 is visible. In this case you can not overscroll. */);
4903 scroll_bar_adjust_thumb_portion_p = 1;
4904
4905 DEFVAR_LISP ("terminal-frame", Vterminal_frame,
4906 doc: /* The initial frame-object, which represents Emacs's stdout. */);
4907
4908 DEFVAR_LISP ("mouse-position-function", Vmouse_position_function,
4909 doc: /* If non-nil, function to transform normal value of `mouse-position'.
4910 `mouse-position' and `mouse-pixel-position' call this function, passing their
4911 usual return value as argument, and return whatever this function returns.
4912 This abnormal hook exists for the benefit of packages like `xt-mouse.el'
4913 which need to do mouse handling at the Lisp level. */);
4914 Vmouse_position_function = Qnil;
4915
4916 DEFVAR_LISP ("mouse-highlight", Vmouse_highlight,
4917 doc: /* If non-nil, clickable text is highlighted when mouse is over it.
4918 If the value is an integer, highlighting is only shown after moving the
4919 mouse, while keyboard input turns off the highlight even when the mouse
4920 is over the clickable text. However, the mouse shape still indicates
4921 when the mouse is over clickable text. */);
4922 Vmouse_highlight = Qt;
4923
4924 DEFVAR_LISP ("make-pointer-invisible", Vmake_pointer_invisible,
4925 doc: /* If non-nil, make pointer invisible while typing.
4926 The pointer becomes visible again when the mouse is moved. */);
4927 Vmake_pointer_invisible = Qt;
4928
4929 DEFVAR_LISP ("focus-in-hook", Vfocus_in_hook,
4930 doc: /* Normal hook run when a frame gains input focus. */);
4931 Vfocus_in_hook = Qnil;
4932 DEFSYM (Qfocus_in_hook, "focus-in-hook");
4933
4934 DEFVAR_LISP ("focus-out-hook", Vfocus_out_hook,
4935 doc: /* Normal hook run when a frame loses input focus. */);
4936 Vfocus_out_hook = Qnil;
4937 DEFSYM (Qfocus_out_hook, "focus-out-hook");
4938
4939 DEFVAR_LISP ("delete-frame-functions", Vdelete_frame_functions,
4940 doc: /* Functions run before deleting a frame.
4941 The functions are run with one arg, the frame to be deleted.
4942 See `delete-frame'.
4943
4944 Note that functions in this list may be called just before the frame is
4945 actually deleted, or some time later (or even both when an earlier function
4946 in `delete-frame-functions' (indirectly) calls `delete-frame'
4947 recursively). */);
4948 Vdelete_frame_functions = Qnil;
4949 DEFSYM (Qdelete_frame_functions, "delete-frame-functions");
4950
4951 DEFVAR_LISP ("menu-bar-mode", Vmenu_bar_mode,
4952 doc: /* Non-nil if Menu-Bar mode is enabled.
4953 See the command `menu-bar-mode' for a description of this minor mode.
4954 Setting this variable directly does not take effect;
4955 either customize it (see the info node `Easy Customization')
4956 or call the function `menu-bar-mode'. */);
4957 Vmenu_bar_mode = Qt;
4958
4959 DEFVAR_LISP ("tool-bar-mode", Vtool_bar_mode,
4960 doc: /* Non-nil if Tool-Bar mode is enabled.
4961 See the command `tool-bar-mode' for a description of this minor mode.
4962 Setting this variable directly does not take effect;
4963 either customize it (see the info node `Easy Customization')
4964 or call the function `tool-bar-mode'. */);
4965 #ifdef HAVE_WINDOW_SYSTEM
4966 Vtool_bar_mode = Qt;
4967 #else
4968 Vtool_bar_mode = Qnil;
4969 #endif
4970
4971 DEFVAR_LISP ("frame-initial-frame-tool-bar-height", Vframe_initial_frame_tool_bar_height,
4972 doc: /* Height of tool bar of initial frame. */);
4973 Vframe_initial_frame_tool_bar_height = make_number (0);
4974
4975 DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
4976 doc: /* Minibufferless frames use this frame's minibuffer.
4977 Emacs cannot create minibufferless frames unless this is set to an
4978 appropriate surrogate.
4979
4980 Emacs consults this variable only when creating minibufferless
4981 frames; once the frame is created, it sticks with its assigned
4982 minibuffer, no matter what this variable is set to. This means that
4983 this variable doesn't necessarily say anything meaningful about the
4984 current set of frames, or where the minibuffer is currently being
4985 displayed.
4986
4987 This variable is local to the current terminal and cannot be buffer-local. */);
4988
4989 DEFVAR_BOOL ("focus-follows-mouse", focus_follows_mouse,
4990 doc: /* Non-nil if window system changes focus when you move the mouse.
4991 You should set this variable to tell Emacs how your window manager
4992 handles focus, since there is no way in general for Emacs to find out
4993 automatically. See also `mouse-autoselect-window'. */);
4994 focus_follows_mouse = 0;
4995
4996 DEFVAR_BOOL ("frame-resize-pixelwise", frame_resize_pixelwise,
4997 doc: /* Non-nil means resize frames pixelwise.
4998 If this option is nil, resizing a frame rounds its sizes to the frame's
4999 current values of `frame-char-height' and `frame-char-width'. If this
5000 is non-nil, no rounding occurs, hence frame sizes can increase/decrease
5001 by one pixel.
5002
5003 With some window managers you may have to set this to non-nil in order
5004 to set the size of a frame in pixels, to maximize frames or to make them
5005 fullscreen. To resize your initial frame pixelwise, set this option to
5006 a non-nil value in your init file. */);
5007 frame_resize_pixelwise = 0;
5008
5009 DEFVAR_LISP ("frame-inhibit-implied-resize", frame_inhibit_implied_resize,
5010 doc: /* Whether frames should be resized implicitly.
5011 If this option is nil, setting font, menu bar, tool bar, internal
5012 borders, fringes or scroll bars of a specific frame may resize the frame
5013 in order to preserve the number of columns or lines it displays. If
5014 this option is `t', no such resizing is done. Note that the size of
5015 fullscreen and maximized frames, the height of fullheight frames and the
5016 width of fullwidth frames never change implicitly.
5017
5018 The value of this option can be also be a list of frame parameters. In
5019 this case, resizing is inhibited when changing a parameter that appears
5020 in that list. The parameters currently handled by this option include
5021 `font', `font-backend', `internal-border-width', `menu-bar-lines' and
5022 `tool-bar-lines'.
5023
5024 Changing any of the parameters `scroll-bar-width', `scroll-bar-height',
5025 `vertical-scroll-bars', `horizontal-scroll-bars', `left-fringe' and
5026 `right-fringe' is handled as if the frame contained just one live
5027 window. This means, for example, that removing vertical scroll bars on
5028 a frame containing several side by side windows will shrink the frame
5029 width by the width of one scroll bar provided this option is nil and
5030 keep it unchanged if this option is either `t' or a list containing
5031 `vertical-scroll-bars'.
5032
5033 The default value is '(tool-bar-lines) on Lucid, Motif and Windows
5034 \(which means that adding/removing a tool bar does not change the frame
5035 height), nil on all other window systems including GTK+ (which means
5036 that changing any of the parameters listed above may change the size of
5037 the frame), and `t' otherwise (which means the frame size never changes
5038 implicitly when there's no window system support).
5039
5040 Note that when a frame is not large enough to accommodate a change of
5041 any of the parameters listed above, Emacs may try to enlarge the frame
5042 even if this option is non-nil. */);
5043 #if defined (HAVE_WINDOW_SYSTEM)
5044 #if defined (USE_LUCID) || defined (USE_MOTIF) || defined (HAVE_NTGUI)
5045 frame_inhibit_implied_resize = list1 (Qtool_bar_lines);
5046 #else
5047 frame_inhibit_implied_resize = Qnil;
5048 #endif
5049 #else
5050 frame_inhibit_implied_resize = Qt;
5051 #endif
5052
5053 staticpro (&Vframe_list);
5054
5055 defsubr (&Sframep);
5056 defsubr (&Sframe_live_p);
5057 defsubr (&Swindow_system);
5058 defsubr (&Sframe_windows_min_size);
5059 defsubr (&Smake_terminal_frame);
5060 defsubr (&Shandle_switch_frame);
5061 defsubr (&Sselect_frame);
5062 defsubr (&Sselected_frame);
5063 defsubr (&Sframe_list);
5064 defsubr (&Snext_frame);
5065 defsubr (&Sprevious_frame);
5066 defsubr (&Slast_nonminibuf_frame);
5067 defsubr (&Sdelete_frame);
5068 defsubr (&Smouse_position);
5069 defsubr (&Smouse_pixel_position);
5070 defsubr (&Sset_mouse_position);
5071 defsubr (&Sset_mouse_pixel_position);
5072 #if 0
5073 defsubr (&Sframe_configuration);
5074 defsubr (&Srestore_frame_configuration);
5075 #endif
5076 defsubr (&Smake_frame_visible);
5077 defsubr (&Smake_frame_invisible);
5078 defsubr (&Siconify_frame);
5079 defsubr (&Sframe_visible_p);
5080 defsubr (&Svisible_frame_list);
5081 defsubr (&Sraise_frame);
5082 defsubr (&Slower_frame);
5083 defsubr (&Sx_focus_frame);
5084 defsubr (&Scan_run_window_configuration_change_hook);
5085 defsubr (&Sredirect_frame_focus);
5086 defsubr (&Sframe_focus);
5087 defsubr (&Sframe_parameters);
5088 defsubr (&Sframe_parameter);
5089 defsubr (&Smodify_frame_parameters);
5090 defsubr (&Sframe_char_height);
5091 defsubr (&Sframe_char_width);
5092 defsubr (&Sframe_pixel_height);
5093 defsubr (&Sframe_pixel_width);
5094 defsubr (&Sframe_text_cols);
5095 defsubr (&Sframe_text_lines);
5096 defsubr (&Sframe_total_cols);
5097 defsubr (&Sframe_total_lines);
5098 defsubr (&Sframe_text_width);
5099 defsubr (&Sframe_text_height);
5100 defsubr (&Sscroll_bar_width);
5101 defsubr (&Sscroll_bar_height);
5102 defsubr (&Sfringe_width);
5103 defsubr (&Sborder_width);
5104 defsubr (&Sright_divider_width);
5105 defsubr (&Sbottom_divider_width);
5106 defsubr (&Stool_bar_pixel_width);
5107 defsubr (&Sset_frame_height);
5108 defsubr (&Sset_frame_width);
5109 defsubr (&Sset_frame_size);
5110 defsubr (&Sset_frame_position);
5111 defsubr (&Sframe_pointer_visible_p);
5112
5113 #ifdef HAVE_WINDOW_SYSTEM
5114 defsubr (&Sx_get_resource);
5115 defsubr (&Sx_parse_geometry);
5116 #endif
5117
5118 }