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