Separate frame-local, tty-dependent parameters from tty-local parameters.
[bpt/emacs.git] / src / frame.c
index 98b3e70..af2cd20 100644 (file)
@@ -42,6 +42,8 @@ Boston, MA 02111-1307, USA.  */
 #include "fontset.h"
 #endif
 #include "blockinput.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
+#include "termchar.h"
 #include "termhooks.h"
 #include "dispextern.h"
 #include "window.h"
@@ -106,14 +108,14 @@ Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
 Lisp_Object Qleft_fringe, Qright_fringe;
 Lisp_Object Qbuffer_predicate, Qbuffer_list;
 Lisp_Object Qtty_color_mode;
+Lisp_Object Qtty, Qtty_type;
 
 Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
 
 Lisp_Object Qface_set_after_frame_default;
 
-
-Lisp_Object Vterminal_frame;
 Lisp_Object Vdefault_frame_alist;
+Lisp_Object Vdefault_frame_scroll_bars;
 Lisp_Object Vmouse_position_function;
 Lisp_Object Vmouse_highlight;
 Lisp_Object Vdelete_frame_functions;
@@ -179,8 +181,6 @@ set_menu_bar_lines (f, value, oldval)
 Lisp_Object Vemacs_iconified;
 Lisp_Object Vframe_list;
 
-struct x_output tty_display;
-
 extern Lisp_Object Vminibuffer_list;
 extern Lisp_Object get_minibuffer ();
 extern Lisp_Object Fhandle_switch_frame ();
@@ -473,17 +473,19 @@ make_minibuffer_frame ()
 }
 #endif /* HAVE_WINDOW_SYSTEM */
 \f
-/* Construct a frame that refers to the terminal (stdin and stdout).  */
+/* Construct a frame that refers to a terminal.  */
 
 static int terminal_frame_count;
 
 struct frame *
-make_terminal_frame ()
+make_terminal_frame (tty_name, tty_type)
+     char *tty_name;
+     char *tty_type;
 {
   register struct frame *f;
   Lisp_Object frame;
   char name[20];
-
+  
 #ifdef MULTI_KBOARD
   if (!initial_kboard)
     {
@@ -536,12 +538,35 @@ make_terminal_frame ()
 #else
 #ifdef WINDOWSNT
   f->output_method = output_termcap;
-  f->output_data.x = &tty_display;
+  f->output_data.x = &tty_display; /* XXX */
 #else
 #ifdef MAC_OS8
   make_mac_terminal_frame (f);
 #else
-  f->output_data.x = &tty_display;
+  {
+    struct tty_display_info *tty;
+    f->output_method = output_termcap;
+
+    f->output_data.tty = (struct tty_output *) xmalloc (sizeof (struct tty_output));
+    bzero (f->output_data.tty, sizeof (struct tty_output));
+
+    FRAME_FOREGROUND_PIXEL (f) = FACE_TTY_DEFAULT_FG_COLOR;
+    FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
+    
+    if (initialized)
+      {
+        /* Note that term_init may signal an error, but then it is its
+           responsibility to make sure this frame is deleted. */
+        f->output_data.tty->display_info = term_init (frame, tty_name, tty_type);
+      }
+    else
+      {
+        /* init_display() will reinitialize the terminal with correct values after dump. */
+        f->output_data.tty->display_info = term_dummy_init ();
+      }
+    FRAME_TTY (f)->reference_count++;
+  }
+  
 #ifdef CANNOT_DUMP
   FRAME_FOREGROUND_PIXEL(f) = FACE_TTY_DEFAULT_FG_COLOR;
   FRAME_BACKGROUND_PIXEL(f) = FACE_TTY_DEFAULT_BG_COLOR;
@@ -558,11 +583,19 @@ make_terminal_frame ()
 
 DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame,
        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.
+       doc: /* Create an additional terminal frame, possibly on another terminal.
 This function takes one argument, an alist specifying frame parameters.
-In practice, generally you don't need to specify any parameters.
+
+You can create multiple frames on a single text-only 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.  */)
      (parms)
      Lisp_Object parms;
@@ -586,10 +619,54 @@ Note that changing the size of one terminal frame automatically affects all.  */
 #endif
 #endif /* not MSDOS */
 
-  f = make_terminal_frame ();
+  { 
+    Lisp_Object tty, tty_type;
+    char *name = 0, *type = 0;
+
+    /* XXX Ugh, there must be a better way to do this. */
+    tty = Fassq (Qtty, parms);
+    if (EQ (tty, Qnil))
+      tty = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (EQ (tty, Qnil))
+      tty = Fassq (Qtty, Vdefault_frame_alist);
+    if (! EQ (tty, Qnil))
+      tty = XCDR (tty);
+    if (EQ (tty, Qnil) || !STRINGP (tty))
+      tty = Qnil;
+
+    tty_type = Fassq (Qtty_type, parms);
+    if (EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty_type, Vdefault_frame_alist);
+    if (EQ (tty_type, Qnil))
+      tty_type = Fassq (Qtty, XFRAME (selected_frame)->param_alist);
+    if (! EQ (tty_type, Qnil))
+      tty_type = XCDR (tty_type);
+    if (EQ (tty_type, Qnil) || !STRINGP (tty_type))
+      tty_type = Qnil;
+
+    if (! EQ (tty, Qnil))
+      {
+        name = (char *) alloca (SBYTES (tty) + 1);
+        strncpy (name, SDATA (tty), SBYTES (tty));
+        name[SBYTES (tty)] = 0;
+      }
+
+    if (! EQ (tty_type, Qnil))
+      {
+        type = (char *) alloca (SBYTES (tty_type) + 1);
+        strncpy (type, SDATA (tty_type), SBYTES (tty_type));
+        type[SBYTES (tty_type)] = 0;
+      }
+
+    f = make_terminal_frame (name, type);
+  }
 
-  change_frame_size (f, FRAME_LINES (sf),
-                    FRAME_COLS (sf), 0, 0, 0);
+  {
+    int width, height;
+    get_tty_size (fileno (TTY_INPUT (FRAME_TTY (f))), &width, &height);
+    change_frame_size (f, height, width, 0, 0, 0);
+  }
+  
   adjust_glyphs (f);
   calculate_costs (f);
   XSETFRAME (frame, f);
@@ -693,6 +770,15 @@ do_switch_frame (frame, track, for_deletion)
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
 
+  if (FRAME_TERMCAP_P (XFRAME (selected_frame))
+      && FRAME_TERMCAP_P (XFRAME (frame))
+      && FRAME_TTY (XFRAME (selected_frame)) == FRAME_TTY (XFRAME (frame)))
+    {
+      XFRAME (selected_frame)->async_visible = 2; /* obscured */
+      XFRAME (frame)->async_visible = 1;
+      FRAME_TTY (XFRAME (frame))->top_frame = frame;
+    }
+
   selected_frame = frame;
   if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame)))
     last_nonminibuf_frame = XFRAME (selected_frame);
@@ -926,7 +1012,10 @@ next_frame (frame, minibuf)
        f = XCAR (tail);
 
        if (passed
-           && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+           && ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+                 && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+                || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+                    && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame)))))
          {
            /* Decide whether this frame is eligible to be returned.  */
 
@@ -1003,7 +1092,10 @@ prev_frame (frame, minibuf)
       if (EQ (frame, f) && !NILP (prev))
        return prev;
 
-      if (FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+      if ((!FRAME_TERMCAP_P (XFRAME (f)) && !FRAME_TERMCAP_P (XFRAME (frame))
+           && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
+          || (FRAME_TERMCAP_P (XFRAME (f)) && FRAME_TERMCAP_P (XFRAME (frame))
+              && FRAME_TTY (XFRAME (f)) == FRAME_TTY (XFRAME (frame))))
        {
          /* Decide whether this frame is eligible to be returned,
             according to minibuf.  */
@@ -1230,7 +1322,7 @@ The functions are run with one arg, the frame to be deleted.  */)
        {
          FOR_EACH_FRAME (tail, frame1)
            {
-             if (! EQ (frame, frame1))
+             if (! EQ (frame, frame1) && FRAME_LIVE_P (XFRAME (frame1)))
                break;
            }
        }
@@ -1278,6 +1370,8 @@ The functions are run with one arg, the frame to be deleted.  */)
 
   if (f->namebuf)
     xfree (f->namebuf);
+  if (f->decode_mode_spec_buffer)
+    xfree (f->decode_mode_spec_buffer);
   if (FRAME_INSERT_COST (f))
     xfree (FRAME_INSERT_COST (f));
   if (FRAME_DELETEN_COST (f))
@@ -1301,7 +1395,24 @@ The functions are run with one arg, the frame to be deleted.  */)
     x_destroy_window (f);
 #endif
 
-  f->output_data.nothing = 0;
+  if (FRAME_TERMCAP_P (f))
+    {
+      int delete = 1;
+      struct tty_display_info *tty = FRAME_TTY (f);
+
+      if (! --tty->reference_count)
+        {
+          /* delete_tty would call us recursively if we don't kill the
+             frame now. */
+          xfree (f->output_data.tty);
+          f->output_data.nothing = 0;
+          delete_tty (tty);
+        }
+    }
+  else
+    {
+      f->output_data.nothing = 0;
+    }
 
   /* If we've deleted the last_nonminibuf_frame, then try to find
      another one.  */
@@ -2015,7 +2126,7 @@ store_frame_param (f, prop, val)
   if (EQ (prop, Qminibuffer) && WINDOWP (val))
     {
       if (! MINI_WINDOW_P (XWINDOW (val)))
-       error ("Surrogate minibuffer windows must be minibuffer windows.");
+       error ("Surrogate minibuffer windows must be minibuffer windows");
 
       if ((FRAME_HAS_MINIBUF_P (f) || FRAME_MINIBUF_ONLY_P (f))
          && !EQ (val, f->minibuffer_window))
@@ -2590,32 +2701,6 @@ x_fullscreen_adjust (f, width, height, top_pos, left_pos)
 }
 
 
-/* Really try to move where we want to be in case of fullscreen.  Some WMs
-   moves the window where we tell them.  Some (mwm, twm) moves the outer
-   window manager window there instead.
-   Try to compensate for those WM here. */
-
-static void
-x_fullscreen_move (f, new_top, new_left)
-     struct frame *f;
-     int new_top;
-     int new_left;
-{
-  if (new_top != f->top_pos || new_left != f->left_pos)
-    {
-      int move_x = new_left;
-      int move_y = new_top;
-
-#ifdef HAVE_X_WINDOWS
-      move_x += FRAME_X_OUTPUT (f)->x_pixels_outer_diff;
-      move_y += FRAME_X_OUTPUT (f)->y_pixels_outer_diff;
-#endif
-
-      f->want_fullscreen |= FULLSCREEN_MOVE_WAIT;
-      x_set_offset (f, move_x, move_y, 1);
-    }
-}
-
 /* Change the parameters of frame F as specified by ALIST.
    If a parameter is not specially recognized, do nothing special;
    otherwise call the `x_set_...' function for that parameter.
@@ -2811,7 +2896,8 @@ x_set_frame_parameters (f, alist)
       int new_left, new_top;
 
       x_fullscreen_adjust (f, &width, &height, &new_top, &new_left);
-      x_fullscreen_move (f, new_top, new_left);
+      if (new_top != f->top_pos || new_left != f->left_pos)
+        x_set_offset (f, new_left, new_top, 1);
     }
 #endif
 
@@ -3217,13 +3303,11 @@ x_set_vertical_scroll_bars (f, arg, oldval)
           ? vertical_scroll_bar_left
           : EQ (Qright, arg)
           ? vertical_scroll_bar_right
-#ifdef HAVE_NTGUI
-          /* MS-Windows has scroll bars on the right by default.  */
-          : vertical_scroll_bar_right
-#else
-          : vertical_scroll_bar_left
-#endif
-          );
+          : EQ (Qleft, Vdefault_frame_scroll_bars)
+          ? vertical_scroll_bar_left
+          : EQ (Qright, Vdefault_frame_scroll_bars)
+          ? vertical_scroll_bar_right
+          : vertical_scroll_bar_none);
 
       /* We set this parameter before creating the X window for the
         frame, so we can get the geometry right from the start.
@@ -3961,6 +4045,10 @@ syms_of_frame ()
   staticpro (&Qbackground_mode);
   Qtty_color_mode = intern ("tty-color-mode");
   staticpro (&Qtty_color_mode);
+  Qtty = intern ("tty");
+  staticpro (&Qtty);
+  Qtty_type = intern ("tty-type");
+  staticpro (&Qtty_type);
 
   Qface_set_after_frame_default = intern ("face-set-after-frame-default");
   staticpro (&Qface_set_after_frame_default);
@@ -4032,13 +4120,23 @@ The `menu-bar-lines' element of the list controls whether new frames
 Setting this variable does not affect existing frames, only new ones.  */);
   Vdefault_frame_alist = Qnil;
 
+  DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
+              doc: /* Default position of scroll bars on this window-system.  */);
+#ifdef HAVE_WINDOW_SYSTEM
+#if defined(HAVE_NTGUI) || defined(HAVE_CARBON)
+  /* MS-Windows has scroll bars on the right by default.  */
+  Vdefault_frame_scroll_bars = Qright;
+#else
+  Vdefault_frame_scroll_bars = Qleft;
+#endif
+#else
+  Vdefault_frame_scroll_bars = Qnil;
+#endif
+
   Qinhibit_default_face_x_resources
     = intern ("inhibit-default-face-x-resources");
   staticpro (&Qinhibit_default_face_x_resources);
 
-  DEFVAR_LISP ("terminal-frame", &Vterminal_frame,
-              doc: /* The initial frame-object, which represents Emacs's stdout.  */);
-
   DEFVAR_LISP ("emacs-iconified", &Vemacs_iconified,
               doc: /* Non-nil if all of emacs is iconified and frame updates are not needed.  */);
   Vemacs_iconified = Qnil;
@@ -4134,3 +4232,6 @@ This variable is local to the current terminal and cannot be buffer-local.  */);
 #endif
 
 }
+
+/* arch-tag: 7dbf2c69-9aad-45f8-8296-db893d6dd039
+   (do not change this comment) */