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