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