frame.c 73.7 KB
Newer Older
Jim Blandy's avatar
Jim Blandy committed
1
/* Generic frame functions.
2 3
   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2001
   Free Software Foundation.
Jim Blandy's avatar
Jim Blandy committed
4 5 6 7 8

This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Jim Blandy's avatar
Jim Blandy committed
9
the Free Software Foundation; either version 2, or (at your option)
Jim Blandy's avatar
Jim Blandy committed
10 11 12 13 14 15 16 17 18
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
19 20
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.  */
Jim Blandy's avatar
Jim Blandy committed
21

22
#include <config.h>
23 24

#include <stdio.h>
25
#include "lisp.h"
Karl Heuer's avatar
Karl Heuer committed
26
#include "charset.h"
27
#ifdef HAVE_X_WINDOWS
Andreas Schwab's avatar
Andreas Schwab committed
28
#include "xterm.h"
Karl Heuer's avatar
Karl Heuer committed
29
#endif
Andrew Innes's avatar
Andrew Innes committed
30 31 32
#ifdef WINDOWSNT
#include "w32term.h"
#endif
33 34 35
#ifdef macintosh
#include "macterm.h"
#endif
36 37 38 39
#include "buffer.h"
/* These help us bind and responding to switch-frame events.  */
#include "commands.h"
#include "keyboard.h"
40
#include "frame.h"
41 42 43
#ifdef HAVE_WINDOW_SYSTEM
#include "fontset.h"
#endif
44
#include "termhooks.h"
Andreas Schwab's avatar
Andreas Schwab committed
45
#include "dispextern.h"
46
#include "window.h"
Morten Welinder's avatar
Morten Welinder committed
47 48
#ifdef MSDOS
#include "msdos.h"
49
#include "dosfns.h"
Morten Welinder's avatar
Morten Welinder committed
50
#endif
Jim Blandy's avatar
Jim Blandy committed
51

52
Lisp_Object Qframep;
Jim Blandy's avatar
Jim Blandy committed
53
Lisp_Object Qframe_live_p;
54 55
Lisp_Object Qheight;
Lisp_Object Qicon;
Jim Blandy's avatar
Jim Blandy committed
56
Lisp_Object Qminibuffer;
57 58 59 60
Lisp_Object Qmodeline;
Lisp_Object Qname;
Lisp_Object Qonly;
Lisp_Object Qunsplittable;
61
Lisp_Object Qmenu_bar_lines;
62
Lisp_Object Qtool_bar_lines;
63 64
Lisp_Object Qwidth;
Lisp_Object Qx;
65
Lisp_Object Qw32;
66
Lisp_Object Qpc;
67
Lisp_Object Qmac;
68
Lisp_Object Qvisible;
69
Lisp_Object Qbuffer_predicate;
70
Lisp_Object Qbuffer_list;
71
Lisp_Object Qtitle;
72
Lisp_Object Qdisplay_type;
73
Lisp_Object Qbackground_mode;
74
Lisp_Object Qinhibit_default_face_x_resources;
75 76
Lisp_Object Qleft_fringe;
Lisp_Object Qright_fringe;
77
Lisp_Object Qtty_color_mode;
Jim Blandy's avatar
Jim Blandy committed
78

79
Lisp_Object Vterminal_frame;
80
Lisp_Object Vdefault_frame_alist;
81
Lisp_Object Vmouse_position_function;
82 83 84 85 86 87 88 89

static void
set_menu_bar_lines_1 (window, n)
  Lisp_Object window;
  int n;
{
  struct window *w = XWINDOW (window);

90
  XSETFASTINT (w->last_modified, 0);
91 92
  XSETFASTINT (w->top, XFASTINT (w->top) + n);
  XSETFASTINT (w->height, XFASTINT (w->height) - n);
93 94 95 96 97
  
  if (INTEGERP (w->orig_top))
    XSETFASTINT (w->orig_top, XFASTINT (w->orig_top) + n);
  if (INTEGERP (w->orig_height))
    XSETFASTINT (w->orig_height, XFASTINT (w->orig_height) - n);
98 99 100 101 102 103 104 105 106 107 108 109 110

  /* Handle just the top child in a vertical split.  */
  if (!NILP (w->vchild))
    set_menu_bar_lines_1 (w->vchild, n);

  /* Adjust all children in a horizontal split.  */
  for (window = w->hchild; !NILP (window); window = w->next)
    {
      w = XWINDOW (window);
      set_menu_bar_lines_1 (window, n);
    }
}

111
void
112 113 114 115 116 117 118 119 120
set_menu_bar_lines (f, value, oldval)
     struct frame *f;
     Lisp_Object value, oldval;
{
  int nlines;
  int olines = FRAME_MENU_BAR_LINES (f);

  /* Right now, menu bars don't work properly in minibuf-only frames;
     most of the commands try to apply themselves to the minibuffer
Karl Heuer's avatar
Karl Heuer committed
121
     frame itself, and get an error because you can't switch buffers
122 123 124 125 126 127 128 129 130
     in or split the minibuffer window.  */
  if (FRAME_MINIBUF_ONLY_P (f))
    return;

  if (INTEGERP (value))
    nlines = XINT (value);
  else
    nlines = 0;

131 132 133 134 135 136
  if (nlines != olines)
    {
      windows_or_buffers_changed++;
      FRAME_WINDOW_SIZES_CHANGED (f) = 1;
      FRAME_MENU_BAR_LINES (f) = nlines;
      set_menu_bar_lines_1 (f->root_window, nlines - olines);
137
      adjust_glyphs (f);
138
    }
139 140 141 142 143
}

Lisp_Object Vemacs_iconified;
Lisp_Object Vframe_list;

144 145
struct x_output tty_display;

Jim Blandy's avatar
Jim Blandy committed
146 147
extern Lisp_Object Vminibuffer_list;
extern Lisp_Object get_minibuffer ();
148 149
extern Lisp_Object Fhandle_switch_frame ();
extern Lisp_Object Fredirect_frame_focus ();
Karl Heuer's avatar
Karl Heuer committed
150
extern Lisp_Object x_get_focus_frame ();
Jim Blandy's avatar
Jim Blandy committed
151

Jim Blandy's avatar
Jim Blandy committed
152
DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
153 154 155 156 157 158 159 160
       doc: /* Return non-nil if OBJECT is a frame.
Value is t for a termcap frame (a character-only terminal),
`x' for an Emacs frame that is really an X window,
`w32' for an Emacs frame that is a window on MS-Windows display,
`mac' for an Emacs frame on a Macintosh display,
`pc' for a direct-write MS-DOS frame.
See also `frame-live-p'.  */)
     (object)
Jim Blandy's avatar
Jim Blandy committed
161
     Lisp_Object object;
Jim Blandy's avatar
Jim Blandy committed
162
{
163
  if (!FRAMEP (object))
Jim Blandy's avatar
Jim Blandy committed
164
    return Qnil;
Jim Blandy's avatar
Jim Blandy committed
165
  switch (XFRAME (object)->output_method)
Jim Blandy's avatar
Jim Blandy committed
166 167 168 169
    {
    case output_termcap:
      return Qt;
    case output_x_window:
170
      return Qx;
171 172
    case output_w32:
      return Qw32;
173 174
    case output_msdos_raw:
      return Qpc;
175 176
    case output_mac:
      return Qmac;
Jim Blandy's avatar
Jim Blandy committed
177 178 179 180 181
    default:
      abort ();
    }
}

Jim Blandy's avatar
Jim Blandy committed
182
DEFUN ("frame-live-p", Fframe_live_p, Sframe_live_p, 1, 1, 0,
183 184 185
       doc: /* Return non-nil if OBJECT is a frame which has not been deleted.
Value is nil if OBJECT is not a live frame.  If object is a live
frame, the return value indicates what sort of output device it is
Pavel Janík's avatar
Pavel Janík committed
186
displayed on.  See the documentation of `framep' for possible
Pavel Janík's avatar
Pavel Janík committed
187
return values.  */)
188
     (object)
Jim Blandy's avatar
Jim Blandy committed
189 190
     Lisp_Object object;
{
Jim Blandy's avatar
Jim Blandy committed
191 192 193
  return ((FRAMEP (object)
	   && FRAME_LIVE_P (XFRAME (object)))
	  ? Fframep (object)
Jim Blandy's avatar
Jim Blandy committed
194 195 196
	  : Qnil);
}

Jim Blandy's avatar
Jim Blandy committed
197 198
struct frame *
make_frame (mini_p)
Jim Blandy's avatar
Jim Blandy committed
199 200
     int mini_p;
{
Jim Blandy's avatar
Jim Blandy committed
201 202
  Lisp_Object frame;
  register struct frame *f;
Jim Blandy's avatar
Jim Blandy committed
203 204
  register Lisp_Object root_window;
  register Lisp_Object mini_window;
205 206

  f = allocate_frame ();
207
  XSETFRAME (frame, f);
Jim Blandy's avatar
Jim Blandy committed
208

209 210 211 212 213 214
  f->desired_matrix = 0;
  f->current_matrix = 0;
  f->desired_pool = 0;
  f->current_pool = 0;
  f->glyphs_initialized_p = 0;
  f->decode_mode_spec_buffer = 0;
Jim Blandy's avatar
Jim Blandy committed
215
  f->visible = 0;
216
  f->async_visible = 0;
217
  f->output_data.nothing = 0;
Jim Blandy's avatar
Jim Blandy committed
218
  f->iconified = 0;
219
  f->async_iconified = 0;
Jim Blandy's avatar
Jim Blandy committed
220 221 222 223
  f->wants_modeline = 1;
  f->auto_raise = 0;
  f->auto_lower = 0;
  f->no_split = 0;
224
  f->garbaged = 1;
Jim Blandy's avatar
Jim Blandy committed
225
  f->has_minibuffer = mini_p;
226
  f->focus_frame = Qnil;
227
  f->explicit_name = 0;
228
  f->can_have_scroll_bars = 0;
229
  f->vertical_scroll_bar_type = vertical_scroll_bar_none;
Jim Blandy's avatar
Jim Blandy committed
230
  f->param_alist = Qnil;
231 232
  f->scroll_bars = Qnil;
  f->condemned_scroll_bars = Qnil;
233
  f->face_alist = Qnil;
234
  f->face_cache = NULL;
235
  f->menu_bar_items = Qnil;
236 237
  f->menu_bar_vector = Qnil;
  f->menu_bar_items_used = 0;
238
  f->buffer_predicate = Qnil;
239
  f->buffer_list = Qnil;
240 241 242
#ifdef MULTI_KBOARD
  f->kboard = initial_kboard;
#endif
243
  f->namebuf = 0;
244
  f->title = Qnil;
245
  f->menu_bar_window = Qnil;
246
  f->tool_bar_window = Qnil;
247
  f->tool_bar_items = Qnil;
248
  f->desired_tool_bar_string = f->current_tool_bar_string = Qnil;
249
  f->n_tool_bar_items = 0;
Jim Blandy's avatar
Jim Blandy committed
250

251
  root_window = make_window ();
Jim Blandy's avatar
Jim Blandy committed
252 253
  if (mini_p)
    {
254
      mini_window = make_window ();
Jim Blandy's avatar
Jim Blandy committed
255 256 257
      XWINDOW (root_window)->next = mini_window;
      XWINDOW (mini_window)->prev = root_window;
      XWINDOW (mini_window)->mini_p = Qt;
Jim Blandy's avatar
Jim Blandy committed
258 259
      XWINDOW (mini_window)->frame = frame;
      f->minibuffer_window = mini_window;
Jim Blandy's avatar
Jim Blandy committed
260 261 262 263 264
    }
  else
    {
      mini_window = Qnil;
      XWINDOW (root_window)->next = Qnil;
Jim Blandy's avatar
Jim Blandy committed
265
      f->minibuffer_window = Qnil;
Jim Blandy's avatar
Jim Blandy committed
266 267
    }

Jim Blandy's avatar
Jim Blandy committed
268
  XWINDOW (root_window)->frame = frame;
Jim Blandy's avatar
Jim Blandy committed
269 270 271

  /* 10 is arbitrary,
     just so that there is "something there."
Jim Blandy's avatar
Jim Blandy committed
272
     Correct size will be set up later with change_frame_size.  */
Jim Blandy's avatar
Jim Blandy committed
273

274
  SET_FRAME_WIDTH (f, 10);
Jim Blandy's avatar
Jim Blandy committed
275
  f->height = 10;
Jim Blandy's avatar
Jim Blandy committed
276

277 278
  XSETFASTINT (XWINDOW (root_window)->width, 10);
  XSETFASTINT (XWINDOW (root_window)->height, (mini_p ? 9 : 10));
Jim Blandy's avatar
Jim Blandy committed
279 280 281

  if (mini_p)
    {
282 283 284
      XSETFASTINT (XWINDOW (mini_window)->width, 10);
      XSETFASTINT (XWINDOW (mini_window)->top, 9);
      XSETFASTINT (XWINDOW (mini_window)->height, 1);
Jim Blandy's avatar
Jim Blandy committed
285 286
    }

Jim Blandy's avatar
Jim Blandy committed
287
  /* Choose a buffer for the frame's root window.  */
Jim Blandy's avatar
Jim Blandy committed
288 289 290 291 292 293 294 295
  {
    Lisp_Object buf;

    XWINDOW (root_window)->buffer = Qt;
    buf = Fcurrent_buffer ();
    /* If buf is a 'hidden' buffer (i.e. one whose name starts with
       a space), try to find another one.  */
    if (XSTRING (Fbuffer_name (buf))->data[0] == ' ')
296
      buf = Fother_buffer (buf, Qnil, Qnil);
297

298 299 300 301 302 303 304
    /* Use set_window_buffer, not Fset_window_buffer, and don't let
       hooks be run by it.  The reason is that the whole frame/window
       arrangement is not yet fully intialized at this point.  Windows
       don't have the right size, glyph matrices aren't initialized
       etc.  Running Lisp functions at this point surely ends in a
       SEGV.  */
    set_window_buffer (root_window, buf, 0);
305
    f->buffer_list = Fcons (buf, Qnil);
Jim Blandy's avatar
Jim Blandy committed
306 307
  }

Jim Blandy's avatar
Jim Blandy committed
308 309 310
  if (mini_p)
    {
      XWINDOW (mini_window)->buffer = Qt;
311 312 313 314 315
      set_window_buffer (mini_window,
			 (NILP (Vminibuffer_list)
			  ? get_minibuffer (0)
			  : Fcar (Vminibuffer_list)),
			 0);
Jim Blandy's avatar
Jim Blandy committed
316 317
    }

Jim Blandy's avatar
Jim Blandy committed
318 319
  f->root_window = root_window;
  f->selected_window = root_window;
Jim Blandy's avatar
Jim Blandy committed
320 321
  /* Make sure this window seems more recently used than
     a newly-created, never-selected window.  */
322
  XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
Jim Blandy's avatar
Jim Blandy committed
323

Jim Blandy's avatar
Jim Blandy committed
324
  return f;
Jim Blandy's avatar
Jim Blandy committed
325 326
}

327
#ifdef HAVE_WINDOW_SYSTEM
Jim Blandy's avatar
Jim Blandy committed
328
/* Make a frame using a separate minibuffer window on another frame.
Jim Blandy's avatar
Jim Blandy committed
329 330 331
   MINI_WINDOW is the minibuffer window to use.  nil means use the
   default (the global minibuffer).  */

Jim Blandy's avatar
Jim Blandy committed
332
struct frame *
333
make_frame_without_minibuffer (mini_window, kb, display)
Jim Blandy's avatar
Jim Blandy committed
334
     register Lisp_Object mini_window;
335
     KBOARD *kb;
336
     Lisp_Object display;
Jim Blandy's avatar
Jim Blandy committed
337
{
Jim Blandy's avatar
Jim Blandy committed
338
  register struct frame *f;
339
  struct gcpro gcpro1;
Jim Blandy's avatar
Jim Blandy committed
340

341
  if (!NILP (mini_window))
342
    CHECK_LIVE_WINDOW (mini_window);
Jim Blandy's avatar
Jim Blandy committed
343

344
#ifdef MULTI_KBOARD
345 346
  if (!NILP (mini_window)
      && XFRAME (XWINDOW (mini_window)->frame)->kboard != kb)
347 348 349
    error ("frame and minibuffer must be on the same display");
#endif

Jim Blandy's avatar
Jim Blandy committed
350 351
  /* Make a frame containing just a root window.  */
  f = make_frame (0);
Jim Blandy's avatar
Jim Blandy committed
352

353 354 355 356 357 358
  if (NILP (mini_window))
    {
      /* Use default-minibuffer-frame if possible.  */
      if (!FRAMEP (kb->Vdefault_minibuffer_frame)
	  || ! FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame)))
	{
359 360 361 362
          Lisp_Object frame_dummy;

          XSETFRAME (frame_dummy, f);
          GCPRO1 (frame_dummy);
363
	  /* If there's no minibuffer frame to use, create one.  */
364 365 366
	  kb->Vdefault_minibuffer_frame =
	    call1 (intern ("make-initial-minibuffer-frame"), display);
          UNGCPRO;
367
	}
368
   
369 370
      mini_window = XFRAME (kb->Vdefault_minibuffer_frame)->minibuffer_window;
    }
371

Jim Blandy's avatar
Jim Blandy committed
372
  f->minibuffer_window = mini_window;
373 374 375 376 377 378 379 380

  /* Make the chosen minibuffer window display the proper minibuffer,
     unless it is already showing a minibuffer.  */
  if (NILP (Fmemq (XWINDOW (mini_window)->buffer, Vminibuffer_list)))
    Fset_window_buffer (mini_window,
			(NILP (Vminibuffer_list)
			 ? get_minibuffer (0)
			 : Fcar (Vminibuffer_list)));
Jim Blandy's avatar
Jim Blandy committed
381
  return f;
Jim Blandy's avatar
Jim Blandy committed
382 383
}

Jim Blandy's avatar
Jim Blandy committed
384
/* Make a frame containing only a minibuffer window.  */
Jim Blandy's avatar
Jim Blandy committed
385

Jim Blandy's avatar
Jim Blandy committed
386 387
struct frame *
make_minibuffer_frame ()
Jim Blandy's avatar
Jim Blandy committed
388
{
Jim Blandy's avatar
Jim Blandy committed
389
  /* First make a frame containing just a root window, no minibuffer.  */
Jim Blandy's avatar
Jim Blandy committed
390

Jim Blandy's avatar
Jim Blandy committed
391
  register struct frame *f = make_frame (0);
Jim Blandy's avatar
Jim Blandy committed
392
  register Lisp_Object mini_window;
Jim Blandy's avatar
Jim Blandy committed
393
  register Lisp_Object frame;
Jim Blandy's avatar
Jim Blandy committed
394

395
  XSETFRAME (frame, f);
Jim Blandy's avatar
Jim Blandy committed
396

397
  f->auto_raise = 0;
Jim Blandy's avatar
Jim Blandy committed
398 399 400 401
  f->auto_lower = 0;
  f->no_split = 1;
  f->wants_modeline = 0;
  f->has_minibuffer = 1;
Jim Blandy's avatar
Jim Blandy committed
402 403 404 405 406

  /* Now label the root window as also being the minibuffer.
     Avoid infinite looping on the window chain by marking next pointer
     as nil. */

Jim Blandy's avatar
Jim Blandy committed
407
  mini_window = f->minibuffer_window = f->root_window;
Jim Blandy's avatar
Jim Blandy committed
408 409
  XWINDOW (mini_window)->mini_p = Qt;
  XWINDOW (mini_window)->next = Qnil;
410
  XWINDOW (mini_window)->prev = Qnil;
Jim Blandy's avatar
Jim Blandy committed
411
  XWINDOW (mini_window)->frame = frame;
Jim Blandy's avatar
Jim Blandy committed
412 413 414 415

  /* Put the proper buffer in that window.  */

  Fset_window_buffer (mini_window,
Jim Blandy's avatar
Jim Blandy committed
416
		      (NILP (Vminibuffer_list)
Jim Blandy's avatar
Jim Blandy committed
417 418
		       ? get_minibuffer (0)
		       : Fcar (Vminibuffer_list)));
Jim Blandy's avatar
Jim Blandy committed
419
  return f;
Jim Blandy's avatar
Jim Blandy committed
420
}
421
#endif /* HAVE_WINDOW_SYSTEM */
Jim Blandy's avatar
Jim Blandy committed
422

Jim Blandy's avatar
Jim Blandy committed
423
/* Construct a frame that refers to the terminal (stdin and stdout).  */
Jim Blandy's avatar
Jim Blandy committed
424

425 426
static int terminal_frame_count;

Jim Blandy's avatar
Jim Blandy committed
427 428
struct frame *
make_terminal_frame ()
Jim Blandy's avatar
Jim Blandy committed
429
{
Jim Blandy's avatar
Jim Blandy committed
430
  register struct frame *f;
431
  Lisp_Object frame;
432 433
  char name[20];

434 435 436 437 438
#ifdef MULTI_KBOARD
  if (!initial_kboard)
    {
      initial_kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
      init_kboard (initial_kboard);
439 440
      initial_kboard->next_kboard = all_kboards;
      all_kboards = initial_kboard;
441 442 443
    }
#endif

444 445 446
  /* The first call must initialize Vframe_list.  */
  if (! (NILP (Vframe_list) || CONSP (Vframe_list)))
    Vframe_list = Qnil;
Jim Blandy's avatar
Jim Blandy committed
447 448

  f = make_frame (1);
449

450
  XSETFRAME (frame, f);
451 452
  Vframe_list = Fcons (frame, Vframe_list);

453
  terminal_frame_count++;
454 455
  sprintf (name, "F%d", terminal_frame_count);
  f->name = build_string (name);
456 457 458

  f->visible = 1;		/* FRAME_SET_VISIBLE wd set frame_garbaged. */
  f->async_visible = 1;		/* Don't let visible be cleared later. */
459 460
#ifdef MSDOS
  f->output_data.x = &the_only_x_display;
461 462 463
  if (!inhibit_window_system
      && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
	  || XFRAME (selected_frame)->output_method == output_msdos_raw))
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
    {
      f->output_method = output_msdos_raw;
      /* This initialization of foreground and background pixels is
	 only important for the initial frame created in temacs.  If
	 we don't do that, we get black background and foreground in
	 the dumped Emacs because the_only_x_display is a static
	 variable, hence it is born all-zeroes, and zero is the code
	 for the black color.  Other frames all inherit their pixels
	 from what's already in the_only_x_display.  */
      if ((!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame)))
	  && f->output_data.x->background_pixel == 0
	  && f->output_data.x->foreground_pixel == 0)
	{
	  f->output_data.x->background_pixel = FACE_TTY_DEFAULT_BG_COLOR;
	  f->output_data.x->foreground_pixel = FACE_TTY_DEFAULT_FG_COLOR;
	}
    }
481 482 483
  else
    f->output_method = output_termcap;
#else
484
#ifdef WINDOWSNT
485
  f->output_method = output_termcap;
486 487
  f->output_data.x = &tty_display;
#else
488
#ifdef macintosh
489 490
  make_mac_terminal_frame (f);
#else
491
  f->output_data.x = &tty_display;
492
#endif /* macintosh */
493
#endif /* WINDOWSNT */
494
#endif /* MSDOS */
495

496 497
  if (!noninteractive)
    init_frame_faces (f);
498

Jim Blandy's avatar
Jim Blandy committed
499
  return f;
Jim Blandy's avatar
Jim Blandy committed
500
}
501 502

DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
503 504 505 506 507 508 509 510
       1, 1, 0,
       doc: /* Create an additional terminal frame.
You can create multiple frames on a text-only terminal in this way.
Only the selected terminal frame is actually displayed.
This function takes one argument, an alist specifying frame parameters.
In practice, generally you don't need to specify any parameters.
Note that changing the size of one terminal frame automatically affects all.  */)
     (parms)
511 512 513
     Lisp_Object parms;
{
  struct frame *f;
514
  Lisp_Object frame, tem;
515
  struct frame *sf = SELECTED_FRAME ();
516

517
#ifdef MSDOS
518 519
  if (sf->output_method != output_msdos_raw
      && sf->output_method != output_termcap)
520
    abort ();
521 522 523
#else /* not MSDOS */

#ifdef macintosh
524
  if (sf->output_method != output_mac)
525
    error ("Not running on a Macintosh screen; cannot make a new Macintosh frame");
526
#else
527
  if (sf->output_method != output_termcap)
528
    error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
529
#endif
530
#endif /* not MSDOS */
531 532

  f = make_terminal_frame ();
533

534 535
  change_frame_size (f, FRAME_HEIGHT (sf),
		     FRAME_WIDTH (sf), 0, 0, 0);
536
  adjust_glyphs (f);
537 538
  calculate_costs (f);
  XSETFRAME (frame, f);
539
  Fmodify_frame_parameters (frame, Vdefault_frame_alist);
540
  Fmodify_frame_parameters (frame, parms);
541 542 543

  /* Make the frame face alist be frame-specific, so that each
     frame could change its face definitions independently.  */
544
  f->face_alist = Fcopy_alist (sf->face_alist);
545 546 547 548
  /* Simple Fcopy_alist isn't enough, because we need the contents of
     the vectors which are the CDRs of associations in face_alist to
     be copied as well.  */
  for (tem = f->face_alist; CONSP (tem); tem = XCDR (tem))
549
    XSETCDR (XCAR (tem), Fcopy_sequence (XCDR (XCAR (tem))));
550 551
  return frame;
}
552

Jim Blandy's avatar
Jim Blandy committed
553

554 555 556 557 558 559 560 561 562 563 564 565 566
/* Perform the switch to frame FRAME.

   If FRAME is a switch-frame event `(switch-frame FRAME1)', use
   FRAME1 as frame.

   If TRACK is non-zero and the frame that currently has the focus
   redirects its focus to the selected frame, redirect that focused
   frame's focus to FRAME instead.

   FOR_DELETION non-zero means that the selected frame is being
   deleted, which includes the possibility that the frame's display
   is dead.  */

567
Lisp_Object
568 569 570
do_switch_frame (frame, track, for_deletion)
     Lisp_Object frame;
     int track, for_deletion;
Jim Blandy's avatar
Jim Blandy committed
571
{
572 573
  struct frame *sf = SELECTED_FRAME ();
  
574 575 576
  /* If FRAME is a switch-frame event, extract the frame we should
     switch to.  */
  if (CONSP (frame)
577 578 579
      && EQ (XCAR (frame), Qswitch_frame)
      && CONSP (XCDR (frame)))
    frame = XCAR (XCDR (frame));
580

581 582 583
  /* This used to say CHECK_LIVE_FRAME, but apparently it's possible for
     a switch-frame event to arrive after a frame is no longer live,
     especially when deleting the initial frame during startup.  */
584
  CHECK_FRAME (frame);
585 586
  if (! FRAME_LIVE_P (XFRAME (frame)))
    return Qnil;
Jim Blandy's avatar
Jim Blandy committed
587

588
  if (sf == XFRAME (frame))
Jim Blandy's avatar
Jim Blandy committed
589
    return frame;
Jim Blandy's avatar
Jim Blandy committed
590

591 592 593
  /* This is too greedy; it causes inappropriate focus redirection
     that's hard to get rid of.  */
#if 0
594 595 596 597 598 599 600
  /* If a frame's focus has been redirected toward the currently
     selected frame, we should change the redirection to point to the
     newly selected frame.  This means that if the focus is redirected
     from a minibufferless frame to a surrogate minibuffer frame, we
     can use `other-window' to switch between all the frames using
     that minibuffer frame, and the focus redirection will follow us
     around.  */
601 602 603
  if (track)
    {
      Lisp_Object tail;
604

605
      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
606 607
	{
	  Lisp_Object focus;
608

609
	  if (!FRAMEP (XCAR (tail)))
610
	    abort ();
611

612
	  focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
613

614
	  if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
615
	    Fredirect_frame_focus (XCAR (tail), frame);
616 617 618 619
	}
    }
#else /* ! 0 */
  /* Instead, apply it only to the frame we're pointing to.  */
620
#ifdef HAVE_WINDOW_SYSTEM
621
  if (track && FRAME_WINDOW_P (XFRAME (frame)))
622 623 624
    {
      Lisp_Object focus, xfocus;

625
      xfocus = x_get_focus_frame (XFRAME (frame));
626 627 628
      if (FRAMEP (xfocus))
	{
	  focus = FRAME_FOCUS_FRAME (XFRAME (xfocus));
629
	  if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
630 631 632 633 634
	    Fredirect_frame_focus (xfocus, frame);
	}
    }
#endif /* HAVE_X_WINDOWS */
#endif /* ! 0 */
635

636
  if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
637 638
    resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);

639 640 641
  selected_frame = frame;
  if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
    last_nonminibuf_frame = XFRAME (selected_frame);
Jim Blandy's avatar
Jim Blandy committed
642

Jim Blandy's avatar
Jim Blandy committed
643
  Fselect_window (XFRAME (frame)->selected_window);
Jim Blandy's avatar
Jim Blandy committed
644

645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
#ifndef WINDOWSNT
  /* Make sure to switch the tty color mode to that of the newly
     selected frame.  */
  sf = SELECTED_FRAME ();
  if (FRAME_TERMCAP_P (sf))
    {
      Lisp_Object color_mode_spec, color_mode;

      color_mode_spec = assq_no_quit (Qtty_color_mode, sf->param_alist);
      if (CONSP (color_mode_spec))
	color_mode = XCDR (color_mode_spec);
      else
	color_mode = make_number (0);
      set_tty_color_mode (sf, color_mode);
    }
#endif /* !WINDOWSNT */

662
  /* We want to make sure that the next event generates a frame-switch
663
     event to the appropriate frame.  This seems kludgy to me, but
664 665 666 667
     before you take it out, make sure that evaluating something like
     (select-window (frame-root-window (new-frame))) doesn't end up
     with your typing being interpreted in the new frame instead of
     the one you're actually typing in.  */
668
  internal_last_event_frame = Qnil;
669

Jim Blandy's avatar
Jim Blandy committed
670
  return frame;
Jim Blandy's avatar
Jim Blandy committed
671 672
}

673
DEFUN ("select-frame", Fselect_frame, Sselect_frame, 1, 2, "e",
674 675 676 677 678
       doc: /* Select the frame FRAME.
Subsequent editing commands apply to its selected window.
The selection of FRAME lasts until the next time the user does
something to select a different frame, or until the next time this
function is called.  */)
679 680 681
  (frame, no_enter)
    Lisp_Object frame, no_enter;
{
682
  return do_switch_frame (frame, 1, 0);
683 684 685 686
}


DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 2, "e",
687 688 689 690 691 692 693 694 695
       doc: /* Handle a switch-frame event EVENT.
Switch-frame events are usually bound to this function.
A switch-frame event tells Emacs that the window manager has requested
that the user's events be directed to the frame mentioned in the event.
This function selects the selected window of the frame of EVENT.

If EVENT is frame object, handle it as if it were a switch-frame event
to that frame.  */)
     (event, no_enter)
696
     Lisp_Object event, no_enter;
697
{
698 699
  /* Preserve prefix arg that the command loop just cleared.  */
  current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
700
  call1 (Vrun_hooks, Qmouse_leave_buffer_hook);
701
  return do_switch_frame (event, 0, 0);
702 703
}

704
DEFUN ("ignore-event", Fignore_event, Signore_event, 0, 0, "",
705 706
       doc: /* Do nothing, but preserve any prefix argument already specified.
This is a suitable binding for iconify-frame and make-frame-visible.  */)
707 708 709 710 711
     ()
{
  current_kboard->Vprefix_arg = Vcurrent_prefix_arg;
  return Qnil;
}
712

Jim Blandy's avatar
Jim Blandy committed
713
DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
714 715
       doc: /* Return the frame that is now selected.  */)
     ()
Jim Blandy's avatar
Jim Blandy committed
716
{
717
  return selected_frame;
Jim Blandy's avatar
Jim Blandy committed
718
}
719

Jim Blandy's avatar
Jim Blandy committed
720
DEFUN ("window-frame", Fwindow_frame, Swindow_frame, 1, 1, 0,
721 722
       doc: /* Return the frame object that window WINDOW is on.  */)
     (window)
Jim Blandy's avatar
Jim Blandy committed
723 724
     Lisp_Object window;
{
725
  CHECK_LIVE_WINDOW (window);
Jim Blandy's avatar
Jim Blandy committed
726
  return XWINDOW (window)->frame;
Jim Blandy's avatar
Jim Blandy committed
727 728
}

729
DEFUN ("frame-first-window", Fframe_first_window, Sframe_first_window, 0, 1, 0,
730 731 732
       doc: /* Returns the topmost, leftmost window of FRAME.
If omitted, FRAME defaults to the currently selected frame.  */)
     (frame)
733 734 735 736 737
     Lisp_Object frame;
{
  Lisp_Object w;

  if (NILP (frame))
738
    w = SELECTED_FRAME ()->root_window;
739 740
  else
    {
741
      CHECK_LIVE_FRAME (frame);
742 743 744 745 746 747 748 749 750 751 752 753 754 755
      w = XFRAME (frame)->root_window;
    }
  while (NILP (XWINDOW (w)->buffer))
    {
      if (! NILP (XWINDOW (w)->hchild))
	w = XWINDOW (w)->hchild;
      else if (! NILP (XWINDOW (w)->vchild))
	w = XWINDOW (w)->vchild;
      else
	abort ();
    }
  return w;
}

756 757
DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
       Sactive_minibuffer_window, 0, 0, 0,
758 759
       doc: /* Return the currently active minibuffer window, or nil if none.  */)
     ()
760 761 762 763
{
  return minibuf_level ? minibuf_window : Qnil;
}

Jim Blandy's avatar
Jim Blandy committed
764
DEFUN ("frame-root-window", Fframe_root_window, Sframe_root_window, 0, 1, 0,
765 766 767
       doc: /* Returns the root-window of FRAME.
If omitted, FRAME defaults to the currently selected frame.  */)
     (frame)
Jim Blandy's avatar
Jim Blandy committed
768
     Lisp_Object frame;
Jim Blandy's avatar
Jim Blandy committed
769
{
770 771
  Lisp_Object window;
  
Jim Blandy's avatar
Jim Blandy committed
772
  if (NILP (frame))
773
    window = SELECTED_FRAME ()->root_window;
Jim Blandy's avatar
Jim Blandy committed
774
  else
775
    {
776
      CHECK_LIVE_FRAME (frame);
777 778 779 780
      window = XFRAME (frame)->root_window;
    }
  
  return window;
Jim Blandy's avatar
Jim Blandy committed
781 782
}

Jim Blandy's avatar
Jim Blandy committed
783 784
DEFUN ("frame-selected-window", Fframe_selected_window,
       Sframe_selected_window, 0, 1, 0,
785 786 787
       doc: /* Return the selected window of frame object FRAME.
If omitted, FRAME defaults to the currently selected frame.  */)
     (frame)
Jim Blandy's avatar
Jim Blandy committed
788
     Lisp_Object frame;
Jim Blandy's avatar
Jim Blandy committed
789
{
790 791
  Lisp_Object window;
  
Jim Blandy's avatar
Jim Blandy committed
792
  if (NILP (frame))
793
    window = SELECTED_FRAME ()->selected_window;
Jim Blandy's avatar
Jim Blandy committed
794
  else
795
    {
796
      CHECK_LIVE_FRAME (frame);
797 798
      window = XFRAME (frame)->selected_window;
    }
Jim Blandy's avatar
Jim Blandy committed
799

800
  return window;
Jim Blandy's avatar
Jim Blandy committed
801 802
}

803 804
DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
       Sset_frame_selected_window, 2, 2, 0,
805 806 807 808
       doc: /* Set the selected window of frame object FRAME to WINDOW.
If FRAME is nil, the selected frame is used.
If FRAME is the selected frame, this makes WINDOW the selected window.  */)
     (frame, window)
809 810 811
     Lisp_Object frame, window;
{
  if (NILP (frame))
812 813
    frame = selected_frame;
  
814 815
  CHECK_LIVE_FRAME (frame);
  CHECK_LIVE_WINDOW (window);
816 817 818 819

  if (! EQ (frame, WINDOW_FRAME (XWINDOW (window))))
    error ("In `set-frame-selected-window', WINDOW is not on FRAME");

820
  if (EQ (frame, selected_frame))
821 822 823 824 825
    return Fselect_window (window);

  return XFRAME (frame)->selected_window = window;
}

Jim Blandy's avatar
Jim Blandy committed
826
DEFUN ("frame-list", Fframe_list, Sframe_list,
Jim Blandy's avatar
Jim Blandy committed
827
       0, 0, 0,
828 829
       doc: /* Return a list of all frames.  */)
     ()
Jim Blandy's avatar
Jim Blandy committed
830
{
831 832
  Lisp_Object frames;
  frames = Fcopy_sequence (Vframe_list);
833
#ifdef HAVE_WINDOW_SYSTEM
834 835
  if (FRAMEP (tip_frame))
    frames = Fdelq (tip_frame, frames);
836
#endif
837
  return frames;
Jim Blandy's avatar
Jim Blandy committed
838 839
}

Jim Blandy's avatar
Jim Blandy committed
840 841
/* Return the next frame in the frame list after FRAME.
   If MINIBUF is nil, exclude minibuffer-only frames.
842 843
   If MINIBUF is a window, include only its own frame
   and any frame now using that window as the minibuffer.
844
   If MINIBUF is `visible', include all visible frames.
845
   If MINIBUF is 0, include all visible and iconified frames.
846 847
   Otherwise, include all frames.  */

Jim Blandy's avatar
Jim Blandy committed
848
Lisp_Object
Jim Blandy's avatar
Jim Blandy committed
849 850
next_frame (frame, minibuf)
     Lisp_Object frame;
Jim Blandy's avatar
Jim Blandy committed
851
     Lisp_Object minibuf;
Jim Blandy's avatar
Jim Blandy committed
852 853 854 855
{
  Lisp_Object tail;
  int passed = 0;

Jim Blandy's avatar
Jim Blandy committed
856 857
  /* There must always be at least one frame in Vframe_list.  */
  if (! CONSP (Vframe_list))
Jim Blandy's avatar
Jim Blandy committed
858 859
    abort ();

Jim Blandy's avatar
Jim Blandy committed
860 861
  /* If this frame is dead, it won't be in Vframe_list, and we'll loop
     forever.  Forestall that.  */
862
  CHECK_LIVE_FRAME (frame);
Jim Blandy's avatar
Jim Blandy committed
863

Jim Blandy's avatar
Jim Blandy committed
864
  while (1)
865
    for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
Jim Blandy's avatar
Jim Blandy committed
866
      {
867
	Lisp_Object f;
868

869
	f = XCAR (tail);
870 871 872

	if (passed
	    && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
Jim Blandy's avatar
Jim Blandy committed
873
	  {
874 875 876 877 878 879 880 881 882 883 884 885 886
	    /* Decide whether this frame is eligible to be returned.  */

	    /* If we've looped all the way around without finding any
	       eligible frames, return the original frame.  */
	    if (EQ (f, frame))
	      return f;

	    /* Let minibuf decide if this frame is acceptable.  */
	    if (NILP (minibuf))
	      {
		if (! FRAME_MINIBUF_ONLY_P (XFRAME (f)))
		  return f;
	      }
887 888 889 890 891 892
	    else if (EQ (minibuf, Qvisible))
	      {
		FRAME_SAMPLE_VISIBILITY (XFRAME (f));
		if (FRAME_VISIBLE_P (XFRAME (f)))
		  return f;
	      }
893
	    else if (INTEGERP (minibuf) && XINT (minibuf) == 0)
894 895 896 897 898 899
	      {
		FRAME_SAMPLE_VISIBILITY (XFRAME (f));
		if (FRAME_VISIBLE_P (XFRAME (f))
		    || FRAME_ICONIFIED_P (XFRAME (f)))
		  return f;
	      }
900
	    else if (WINDOWP (minibuf))
901
	      {
902
		if (EQ (FRAME_MINIBUF_WINDOW (XFRAME (f)), minibuf)
Gerd Moellmann's avatar