Function: make-terminal-frame

make-terminal-frame is a function defined in frame.c.

Signature

(make-terminal-frame PARMS)

Documentation

Create an additional terminal frame, possibly on another terminal.

This function takes one argument, an alist specifying frame parameters.

You can create multiple frames on a single text terminal, but only one of them (the selected terminal frame) is actually displayed.

In practice, generally you don't need to specify any parameters, except when you want to create a new frame on another terminal. In that case, the tty parameter specifies the device file to open, and the tty-type parameter specifies the terminal type. Example:

   (make-terminal-frame '((tty . "/dev/pts/5") (tty-type . "xterm")))

Note that changing the size of one terminal frame automatically affects all frames on the same terminal device.

Probably introduced at or before Emacs version 23.1.

Source Code

// Defined in /usr/src/emacs/src/frame.c
{
  struct frame *f;
  struct terminal *t = NULL;
  Lisp_Object frame;
  struct frame *sf = SELECTED_FRAME ();

#ifdef MSDOS
  if (sf->output_method != output_msdos_raw
      && sf->output_method != output_termcap)
    emacs_abort ();
#else /* not MSDOS */

#ifdef WINDOWSNT                           /* This should work now! */
  if (sf->output_method != output_termcap)
    error ("Not using an ASCII terminal now; cannot make a new ASCII frame");
#endif
#endif /* not MSDOS */

  {
    Lisp_Object terminal;

    terminal = Fassq (Qterminal, parms);
    if (CONSP (terminal))
      {
        terminal = XCDR (terminal);
        t = decode_live_terminal (terminal);
      }
#ifdef MSDOS
    if (t && t != the_only_display_info.terminal)
      /* msdos.c assumes a single tty_display_info object.  */
      error ("Multiple terminals are not supported on this platform");
    if (!t)
      t = the_only_display_info.terminal;
#endif
  }

  if (!t)
    {
      char *name = 0, *type = 0;
      Lisp_Object tty, tty_type;
      USE_SAFE_ALLOCA;

      tty = get_future_frame_param
        (Qtty, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                       ? FRAME_TTY (XFRAME (selected_frame))->name
                       : NULL));
      if (!NILP (tty))
	SAFE_ALLOCA_STRING (name, tty);

      tty_type = get_future_frame_param
        (Qtty_type, parms, (FRAME_TERMCAP_P (XFRAME (selected_frame))
                            ? FRAME_TTY (XFRAME (selected_frame))->type
                            : NULL));
      if (!NILP (tty_type))
	SAFE_ALLOCA_STRING (type, tty_type);

      t = init_tty (name, type, 0); /* Errors are not fatal.  */
      SAFE_FREE ();
    }

  f = make_terminal_frame (t);

  {
    int width, height;
    get_tty_size (fileno (FRAME_TTY (f)->input), &width, &height);
    /* With INHIBIT 5 pass correct text height to adjust_frame_size.  */
    adjust_frame_size (f, width, height - FRAME_TOP_MARGIN (f),
		       5, 0, Qterminal_frame);
  }

  adjust_frame_glyphs (f);
  calculate_costs (f);
  XSETFRAME (frame, f);

  store_in_alist (&parms, Qtty_type, build_string (t->display_info.tty->type));
  store_in_alist (&parms, Qtty,
		  (t->display_info.tty->name
		   ? build_string (t->display_info.tty->name)
		   : Qnil));

  /* Make the frame face hash be frame-specific, so that each
     frame could change its face definitions independently.  */
  fset_face_hash_table (f, Fcopy_hash_table (sf->face_hash_table));
  /* Simple copy_hash_table isn't enough, because we need the contents of
     the vectors which are the values in face_hash_table to
     be copied as well.  */
  ptrdiff_t idx = 0;
  struct Lisp_Hash_Table *table = XHASH_TABLE (f->face_hash_table);
  for (idx = 0; idx < table->count; ++idx)
    set_hash_value_slot (table, idx, Fcopy_sequence (HASH_VALUE (table, idx)));

  /* On terminal frames the `minibuffer' frame parameter is always
     virtually t.  Avoid that a different value in parms causes
     complaints, see Bug#24758.  */
  store_in_alist (&parms, Qminibuffer, Qt);
  Fmodify_frame_parameters (frame, parms);

  f->can_set_window_size = true;
  f->after_make_frame = true;

  return frame;
}