*** empty log message ***
[bpt/emacs.git] / src / frame.c
index e5f80fd..0a8ac6a 100644 (file)
@@ -1,5 +1,5 @@
 /* Generic frame functions.
-   Copyright (C) 1993, 1994, 1995, 1997, 1999 Free Software Foundation.
+   Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000 Free Software Foundation.
 
 This file is part of GNU Emacs.
 
@@ -26,6 +26,9 @@ Boston, MA 02111-1307, USA.  */
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
+#ifdef WINDOWSNT
+#include "w32term.h"
+#endif
 #include "frame.h"
 #ifdef HAVE_WINDOW_SYSTEM
 #include "fontset.h"
@@ -100,6 +103,7 @@ Lisp_Object Qtitle;
 
 Lisp_Object Vterminal_frame;
 Lisp_Object Vdefault_frame_alist;
+Lisp_Object Vmouse_position_function;
 
 static void
 syms_of_frame_1 ()
@@ -170,6 +174,11 @@ set_menu_bar_lines_1 (window, n)
   XSETFASTINT (w->last_modified, 0);
   XSETFASTINT (w->top, XFASTINT (w->top) + n);
   XSETFASTINT (w->height, XFASTINT (w->height) - n);
+  
+  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);
 
   /* Handle just the top child in a vertical split.  */
   if (!NILP (w->vchild))
@@ -222,6 +231,8 @@ 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 ();
@@ -232,6 +243,8 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
   "Return non-nil if OBJECT is a frame.\n\
 Value is t for a termcap frame (a character-only terminal),\n\
 `x' for an Emacs frame that is really an X window,\n\
+`w32' for an Emacs frame that is a window on MS-Windows display,\n\
+`mac' for an Emacs frame on a Macintosh display,\n\
 `pc' for a direct-write MS-DOS frame.\n\
 See also `frame-live-p'.")
   (object)
@@ -304,7 +317,7 @@ make_frame (mini_p)
   f->auto_raise = 0;
   f->auto_lower = 0;
   f->no_split = 0;
-  f->garbaged = 0;
+  f->garbaged = 1;
   f->has_minibuffer = mini_p;
   f->focus_frame = Qnil;
   f->explicit_name = 0;
@@ -404,10 +417,6 @@ make_frame (mini_p)
      a newly-created, never-selected window.  */
   XSETFASTINT (XWINDOW (f->selected_window)->use_time, ++window_select_count);
 
-#ifdef HAVE_WINDOW_SYSTEM
-  f->fontset_data = alloc_fontset_data ();
-#endif
-
   return f;
 }
 \f
@@ -545,9 +554,13 @@ make_terminal_frame ()
   f->async_visible = 1;                /* Don't let visible be cleared later. */
 #ifdef MSDOS
   f->output_data.x = &the_only_x_display;
-  f->output_method = output_msdos_raw;
-#endif /* MSDOS */
-
+  if (!inhibit_window_system
+      && (!FRAMEP (selected_frame) || !FRAME_LIVE_P (XFRAME (selected_frame))
+         || XFRAME (selected_frame)->output_method == output_msdos_raw))
+    f->output_method = output_msdos_raw;
+  else
+    f->output_method = output_termcap;
+#else
 #ifdef macintosh
   f->output_data.mac = NewMacWindow(f);
   f->output_data.mac->background_pixel = 0xffffff;
@@ -559,16 +572,15 @@ make_terminal_frame ()
   f->auto_raise = 1;
   f->auto_lower = 1;
   init_frame_faces (f);
-#endif /* macintosh */
+#else  /* !macintosh */
+  f->output_data.x = &tty_display;
+#endif /* !macintosh */
+#endif /* MSDOS */
 
-#ifndef MSDOS
 #ifndef macintosh
-  f->output_data.nothing = 1;  /* Nonzero means frame isn't deleted.  */
-#endif
-#endif
-
   if (!noninteractive)
     init_frame_faces (f);
+#endif
   return f;
 }
 
@@ -587,7 +599,8 @@ Note that changing the size of one terminal frame automatically affects all.")
   struct frame *sf = SELECTED_FRAME ();
 
 #ifdef MSDOS
-  if (sf->output_method != output_msdos_raw)
+  if (sf->output_method != output_msdos_raw
+      && sf->output_method != output_termcap)
     abort ();
 #else /* not MSDOS */
 
@@ -631,9 +644,9 @@ do_switch_frame (frame, no_enter, track)
   /* If FRAME is a switch-frame event, extract the frame we should
      switch to.  */
   if (CONSP (frame)
-      && EQ (XCONS (frame)->car, Qswitch_frame)
-      && CONSP (XCONS (frame)->cdr))
-    frame = XCONS (XCONS (frame)->cdr)->car;
+      && EQ (XCAR (frame), Qswitch_frame)
+      && CONSP (XCDR (frame)))
+    frame = XCAR (XCDR (frame));
 
   /* 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,
@@ -659,17 +672,17 @@ do_switch_frame (frame, no_enter, track)
     {
       Lisp_Object tail;
 
-      for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
        {
          Lisp_Object focus;
 
-         if (!FRAMEP (XCONS (tail)->car))
+         if (!FRAMEP (XCAR (tail)))
            abort ();
 
-         focus = FRAME_FOCUS_FRAME (XFRAME (XCONS (tail)->car));
+         focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
 
          if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
-           Fredirect_frame_focus (XCONS (tail)->car, frame);
+           Fredirect_frame_focus (XCAR (tail), frame);
        }
     }
 #else /* ! 0 */
@@ -893,11 +906,11 @@ next_frame (frame, minibuf)
   CHECK_LIVE_FRAME (frame, 0);
 
   while (1)
-    for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+    for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
       {
        Lisp_Object f;
 
-       f = XCONS (tail)->car;
+       f = XCAR (tail);
 
        if (passed
            && FRAME_KBOARD (XFRAME (f)) == FRAME_KBOARD (XFRAME (frame)))
@@ -968,11 +981,11 @@ prev_frame (frame, minibuf)
     abort ();
 
   prev = Qnil;
-  for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
       Lisp_Object f;
 
-      f = XCONS (tail)->car;
+      f = XCAR (tail);
       if (!FRAMEP (f))
        abort ();
 
@@ -1087,11 +1100,11 @@ other_visible_frames (f)
 
       for (frames = Vframe_list;
           CONSP (frames);
-          frames = XCONS (frames)->cdr)
+          frames = XCDR (frames))
        {
          Lisp_Object this;
 
-         this = XCONS (frames)->car;
+         this = XCAR (frames);
          /* Verify that the frame's window still exists
             and we can still talk to it.  And note any recent change
             in visibility.  */
@@ -1148,7 +1161,7 @@ but if the second optional argument FORCE is non-nil, you may do so.")
 #if 0
   /* This is a nice idea, but x_connection_closed needs to be able
      to delete the last frame, if it is gone.  */
-  if (NILP (XCONS (Vframe_list)->cdr))
+  if (NILP (XCDR (Vframe_list)))
     error ("Attempt to delete the only frame");
 #endif
 
@@ -1160,10 +1173,10 @@ but if the second optional argument FORCE is non-nil, you may do so.")
 
       for (frames = Vframe_list;
           CONSP (frames);
-          frames = XCONS (frames)->cdr)
+          frames = XCDR (frames))
        {
          Lisp_Object this;
-         this = XCONS (frames)->car;
+         this = XCAR (frames);
 
          if (! EQ (this, frame)
              && EQ (frame,
@@ -1210,6 +1223,10 @@ but if the second optional argument FORCE is non-nil, you may do so.")
        Fselect_window (minibuf_window);
     }
 
+  /* Don't let echo_area_window to remain on a deleted frame.  */
+  if (EQ (f->minibuffer_window, echo_area_window))
+    echo_area_window = sf->minibuffer_window;
+
   /* Clear any X selections for this frame.  */
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (f))
@@ -1243,11 +1260,6 @@ but if the second optional argument FORCE is non-nil, you may do so.")
   if (FRAME_MESSAGE_BUF (f))
     xfree (FRAME_MESSAGE_BUF (f));
 
-#ifdef HAVE_WINDOW_SYSTEM
-  /* Free all fontset data.  */
-  free_fontset_data (FRAME_FONTSET_DATA (f));
-#endif
-
   /* Since some events are handled at the interrupt level, we may get
      an event for f at any time; if we zero out the frame's display
      now, then we may trip up the event-handling code.  Instead, we'll
@@ -1280,9 +1292,9 @@ but if the second optional argument FORCE is non-nil, you may do so.")
 
       for (frames = Vframe_list;
           CONSP (frames);
-          frames = XCONS (frames)->cdr)
+          frames = XCDR (frames))
        {
-         f = XFRAME (XCONS (frames)->car);
+         f = XFRAME (XCAR (frames));
          if (!FRAME_MINIBUF_ONLY_P (f))
            {
              last_nonminibuf_frame = f;
@@ -1308,12 +1320,12 @@ but if the second optional argument FORCE is non-nil, you may do so.")
 
       for (frames = Vframe_list;
           CONSP (frames);
-          frames = XCONS (frames)->cdr)
+          frames = XCDR (frames))
        {
          Lisp_Object this;
          struct frame *f1;
 
-         this = XCONS (frames)->car;
+         this = XCAR (frames);
          if (!FRAMEP (this))
            abort ();
          f1 = XFRAME (this);
@@ -1364,15 +1376,18 @@ The position is given in character cells, where (0, 0) is the\n\
 upper-left corner.\n\
 If Emacs is running on a mouseless terminal or hasn't been programmed\n\
 to read the mouse position, it returns the selected frame for FRAME\n\
-and nil for X and Y.")
+and nil for X and Y.\n\
+Runs the abnormal hook `mouse-position-function' with the normal return\n\
+value as argument.")
   ()
 {
   FRAME_PTR f;
   Lisp_Object lispy_dummy;
   enum scroll_bar_part party_dummy;
-  Lisp_Object x, y;
+  Lisp_Object x, y, retval;
   int col, row;
   unsigned long long_dummy;
+  struct gcpro gcpro1;
 
   f = SELECTED_FRAME ();
   x = y = Qnil;
@@ -1394,7 +1409,11 @@ and nil for X and Y.")
     }
 #endif
   XSETFRAME (lispy_dummy, f);
-  return Fcons (lispy_dummy, Fcons (x, y));
+  retval = Fcons (lispy_dummy, Fcons (x, y));
+  GCPRO1 (retval);
+  if (!NILP (Vmouse_position_function))
+    retval = call1 (Vmouse_position_function, retval);
+  RETURN_UNGCPRO (retval);
 }
 
 DEFUN ("mouse-pixel-position", Fmouse_pixel_position,
@@ -1662,9 +1681,9 @@ DEFUN ("visible-frame-list", Fvisible_frame_list, Svisible_frame_list,
   Lisp_Object value;
 
   value = Qnil;
-  for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
+  for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
     {
-      frame = XCONS (tail)->car;
+      frame = XCAR (tail);
       if (!FRAMEP (frame))
        continue;
       f = XFRAME (frame);
@@ -1845,9 +1864,13 @@ frames_bury_buffer (buffer)
 
   FOR_EACH_FRAME (tail, frame)
     {
-      XFRAME (frame)->buffer_list
-       = nconc2 (Fdelq (buffer, XFRAME (frame)->buffer_list),
-                 Fcons (buffer, Qnil));
+      struct frame *f = XFRAME (frame);
+      Lisp_Object found;
+      
+      found = Fmemq (buffer, f->buffer_list);
+      if (!NILP (found))
+       f->buffer_list = nconc2 (Fdelq (buffer, f->buffer_list),
+                                Fcons (buffer, Qnil));
     }
 }
 
@@ -1933,20 +1956,41 @@ store_frame_param (f, prop, val)
      struct frame *f;
      Lisp_Object prop, val;
 {
-  register Lisp_Object tem;
+  register Lisp_Object old_alist_elt;
 
+  /* The buffer-alist parameter is stored in a special place and is
+     not in the alist.  */
   if (EQ (prop, Qbuffer_list))
     {
       f->buffer_list = val;
       return;
     }
 
-  tem = Fassq (prop, f->param_alist);
-  if (EQ (tem, Qnil))
+  /* If PROP is a symbol which is supposed to have frame-local values,
+     and it is set up based on this frame, switch to the global
+     binding.  That way, we can create or alter the frame-local binding
+     without messing up the symbol's status.  */
+  if (SYMBOLP (prop))
+    {
+      Lisp_Object valcontents;
+      valcontents = XSYMBOL (prop)->value;
+      if ((BUFFER_LOCAL_VALUEP (valcontents)
+          || SOME_BUFFER_LOCAL_VALUEP (valcontents))
+         && XBUFFER_LOCAL_VALUE (valcontents)->check_frame
+         && XFRAME (XBUFFER_LOCAL_VALUE (valcontents)->frame) == f)
+       swap_in_global_binding (prop);
+    }
+
+  /* Update the frame parameter alist.  */
+  old_alist_elt = Fassq (prop, f->param_alist);
+  if (EQ (old_alist_elt, Qnil))
     f->param_alist = Fcons (Fcons (prop, val), f->param_alist);
   else
-    Fsetcdr (tem, val);
+    Fsetcdr (old_alist_elt, val);
 
+  /* Update some other special parameters in their special places
+     in addition to the alist.  */
+  
   if (EQ (prop, Qbuffer_predicate))
     f->buffer_predicate = val;
 
@@ -1983,6 +2027,7 @@ If FRAME is omitted, return information on the currently selected frame.")
   Lisp_Object alist;
   FRAME_PTR f;
   int height, width;
+  struct gcpro gcpro1;
 
   if (EQ (frame, Qnil))
     frame = selected_frame;
@@ -1994,23 +2039,22 @@ If FRAME is omitted, return information on the currently selected frame.")
     return Qnil;
 
   alist = Fcopy_alist (f->param_alist);
-#ifdef MSDOS
-  if (FRAME_MSDOS_P (f))
+  GCPRO1 (alist);
+  
+  if (!FRAME_WINDOW_P (f))
     {
       int fg = FRAME_FOREGROUND_PIXEL (f);
       int bg = FRAME_BACKGROUND_PIXEL (f);
-      Lisp_Object qreverse = intern ("reverse");
-      int rv =
-       !NILP (Fassq (qreverse, alist))
-       || !NILP (Fassq (qreverse, Vdefault_frame_alist));
 
       store_in_alist (&alist, intern ("foreground-color"),
-                     build_string (msdos_stdcolor_name (rv ? bg : fg)));
+                     tty_color_name (f, fg));
       store_in_alist (&alist, intern ("background-color"),
-                     build_string (msdos_stdcolor_name (rv ? fg : bg)));
+                     tty_color_name (f, bg));
+      store_in_alist (&alist, intern ("font"),
+                     build_string (FRAME_MSDOS_P (f)
+                                   ? "ms-dos"
+                                   : FRAME_W32_P (f) ? "w32term" : "tty"));
     }
-  store_in_alist (&alist, intern ("font"), build_string ("ms-dos"));
-#endif
   store_in_alist (&alist, Qname, f->name);
   height = (FRAME_NEW_HEIGHT (f) ? FRAME_NEW_HEIGHT (f) : FRAME_HEIGHT (f));
   store_in_alist (&alist, Qheight, make_number (height));
@@ -2037,6 +2081,8 @@ If FRAME is omitted, return information on the currently selected frame.")
       XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f));
       store_in_alist (&alist, Qmenu_bar_lines, lines);
     }
+
+  UNGCPRO;
   return alist;
 }
 
@@ -2047,7 +2093,11 @@ ALIST is an alist of parameters to change and their new values.\n\
 Each element of ALIST has the form (PARM . VALUE), where PARM is a symbol.\n\
 The meaningful PARMs depend on the kind of frame.\n\
 Undefined PARMs are ignored, but stored in the frame's parameter list\n\
-so that `frame-parameters' will return them.")
+so that `frame-parameters' will return them.\n\
+\n\
+The value of frame parameter FOO can also be accessed\n\
+as a frame-local binding for the variable FOO, if you have\n\
+enabled such bindings for that variable with `make-variable-frame-local'.")
   (frame, alist)
      Lisp_Object frame, alist;
 {
@@ -2331,6 +2381,12 @@ syms_of_frame ()
     "Non-nil if all of emacs is iconified and frame updates are not needed.");
   Vemacs_iconified = Qnil;
 
+  DEFVAR_LISP ("mouse-position-function", &Vmouse_position_function,
+    "If non-nil, function applied to the normal result of `mouse-position'.\n\
+This abnormal hook exists for the benefit of packages like XTerm-mouse\n\
+which need to do mouse handling at the Lisp level.");
+  Vmouse_position_function = Qnil;
+
   DEFVAR_KBOARD ("default-minibuffer-frame", Vdefault_minibuffer_frame,
     "Minibufferless frames use this frame's minibuffer.\n\
 \n\