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