* sysdep.c (child_setup_tty): Remove duplicate settings for VQUIT
[bpt/emacs.git] / src / dispnew.c
index 7c9472e..ed392e0 100644 (file)
@@ -1,6 +1,5 @@
 /* Updating of data structures for redisplay.
-   Copyright (C) 1985, 1986, 1987, 1988, 1990, 
-   1992, 1993 Free Software Foundation, Inc.
+   Copyright (C) 1985, 1986, 1987, 1988, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -25,10 +24,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <stdio.h>
 #include <ctype.h>
 
+#include "lisp.h"
 #include "termchar.h"
 #include "termopts.h"
+#include "termhooks.h"
 #include "cm.h"
-#include "lisp.h"
 #include "dispextern.h"
 #include "buffer.h"
 #include "frame.h"
@@ -116,7 +116,7 @@ FRAME_PTR last_nonminibuf_frame;
    exist inside frame objects lives in the following structure instead.
 
    NOTE: the_only_frame is not checked for garbage collection; don't
-   store collectable objects in any of its fields!
+   store collectible objects in any of its fields!
 
    You're not/The only frame in town/...  */
 
@@ -164,21 +164,6 @@ DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
   return Qnil;
 }
 
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear and redisplay all visible frames."
-  ()
-{
-  Lisp_Object frame, tail;
-
-  for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
-    {
-      frame = XCONS (tail)->car;
-      if (FRAME_VISIBLE_P (XFRAME (frame)))
-       Fredraw_frame (frame);
-    }
-  return Qnil;
-}
-
 redraw_frame (f)
      FRAME_PTR f;
 {
@@ -187,11 +172,12 @@ redraw_frame (f)
   Fredraw_frame (frame);
 }
 
-#else /* not MULTI_FRAME */
+#else
 
-DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
-  "Clear screen and output again what is supposed to appear on it.")
-  ()
+DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, "",
+  "Clear frame FRAME and output again what is supposed to appear on it.")
+  (frame)
+     Lisp_Object frame;
 {
   update_begin (0);
   set_terminal_modes ();
@@ -206,7 +192,35 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
   return Qnil;
 }
 
-#endif /* not MULTI_FRAME */
+#endif
+
+DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
+  "Clear and redisplay all visible frames.")
+  ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+
+  return Qnil;
+}
+
+/* This is used when frame_garbaged is set.
+   Redraw the individual frames marked as garbaged.  */
+
+void
+redraw_garbaged_frames ()
+{
+  Lisp_Object tail, frame;
+
+  FOR_EACH_FRAME (tail, frame)
+    if (FRAME_VISIBLE_P (XFRAME (frame))
+       && FRAME_GARBAGED_P (XFRAME (frame)))
+      Fredraw_frame (frame);
+}
+
 \f
 static struct frame_glyphs *
 make_frame_glyphs (frame, empty)
@@ -268,26 +282,26 @@ free_frame_glyphs (frame, glyphs)
      struct frame_glyphs *glyphs;
 {
   if (glyphs->total_contents)
-    free (glyphs->total_contents);
+    xfree (glyphs->total_contents);
 
-  free (glyphs->used);
-  free (glyphs->glyphs);
-  free (glyphs->highlight);
-  free (glyphs->enable);
-  free (glyphs->bufp);
+  xfree (glyphs->used);
+  xfree (glyphs->glyphs);
+  xfree (glyphs->highlight);
+  xfree (glyphs->enable);
+  xfree (glyphs->bufp);
 
 #ifdef HAVE_X_WINDOWS
   if (FRAME_X_P (frame))
     {
-      free (glyphs->top_left_x);
-      free (glyphs->top_left_y);
-      free (glyphs->pix_width);
-      free (glyphs->pix_height);
-      free (glyphs->max_ascent);
+      xfree (glyphs->top_left_x);
+      xfree (glyphs->top_left_y);
+      xfree (glyphs->pix_width);
+      xfree (glyphs->pix_height);
+      xfree (glyphs->max_ascent);
     }
 #endif
 
-  free (glyphs);
+  xfree (glyphs);
 }
 
 static void
@@ -302,9 +316,20 @@ remake_frame_glyphs (frame)
     free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
 
   if (FRAME_MESSAGE_BUF (frame))
-    FRAME_MESSAGE_BUF (frame)
-      = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
-                          FRAME_WIDTH (frame) + 1);
+    {
+      /* Reallocate the frame's message buffer; remember that
+        echo_area_glyphs may be pointing here.  */
+      char *old_message_buf = FRAME_MESSAGE_BUF (frame);
+
+      FRAME_MESSAGE_BUF (frame)
+       = (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
+                            FRAME_WIDTH (frame) + 1);
+
+      if (echo_area_glyphs == old_message_buf)
+       echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
+      if (previous_echo_glyphs == old_message_buf)
+       previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
+    }
   else
     FRAME_MESSAGE_BUF (frame)
       = (char *) xmalloc (FRAME_WIDTH (frame) + 1);
@@ -721,7 +746,8 @@ preserve_other_columns (w)
              int len;
 
              bcopy (current_frame->glyphs[vpos],
-                    desired_frame->glyphs[vpos], start);
+                    desired_frame->glyphs[vpos],
+                    start * sizeof (current_frame->glyphs[vpos]));
              len = min (start, current_frame->used[vpos]);
              if (desired_frame->used[vpos] < len)
                desired_frame->used[vpos] = len;
@@ -734,7 +760,8 @@ preserve_other_columns (w)
                  = SPACEGLYPH;
              bcopy (current_frame->glyphs[vpos] + end,
                     desired_frame->glyphs[vpos] + end,
-                    current_frame->used[vpos] - end);
+                    ((current_frame->used[vpos] - end)
+                     * sizeof (current_frame->glyphs[vpos])));
              desired_frame->used[vpos] = current_frame->used[vpos];
            }
        }
@@ -849,7 +876,16 @@ direct_output_for_insert (g)
       || (MINI_WINDOW_P (w) && echo_area_glyphs))
     return 0;
 
-  current_frame->glyphs[vpos][hpos] = g;
+  {
+#ifdef HAVE_X_WINDOWS
+    int dummy;
+    int face = compute_char_face (frame, w, point, -1, -1, &dummy);
+#else
+    int face = 0;
+#endif
+                                 
+    current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (g, face);
+  }
   unchanged_modified = MODIFF;
   beg_unchanged = GPT - BEG;
   XFASTINT (w->last_point) = point;
@@ -885,6 +921,10 @@ direct_output_forward_char (n)
       || cursor_in_echo_area)
     return 0;
 
+  /* Can't use direct output if highlighting a region.  */
+  if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
+    return 0;
+
   FRAME_CURSOR_X (frame) += n;
   XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
   XFASTINT (w->last_point) = point;
@@ -915,6 +955,9 @@ update_frame (f, force, inhibit_hairy_id)
   register int downto, leftmost;
 #endif
 
+  if (preempt_count <= 0)
+    preempt_count = 1;
+
   if (FRAME_HEIGHT (f) == 0) abort (); /* Some bug zeros some core */
 
   detect_input_pending ();
@@ -985,7 +1028,8 @@ update_frame (f, force, inhibit_hairy_id)
                        outq = PENDING_OUTPUT_COUNT (stdout);
 #endif
                      outq *= 10;
-                     sleep (outq / baud_rate);
+                     if (baud_rate > 0)
+                       sleep (outq / baud_rate);
                    }
                }
              if ((i - 1) % preempt_count == 0)
@@ -1191,7 +1235,7 @@ buffer_posn_from_coords (window, col, line)
   posn = compute_motion (startp, 0,
                         (window == XWINDOW (minibuf_window) && startp == 1
                          ? minibuf_prompt_width : 0),
-                        ZV, line, col - window_left,
+                        ZV, line, col,
                         window_width, XINT (window->hscroll), 0);
 
   current_buffer = old_current_buffer;
@@ -1228,7 +1272,7 @@ count_match (str1, str2)
 /* Char insertion/deletion cost vector, from term.c */
 extern int *char_ins_del_vector;
 
-#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_HEIGHT((f))])
+#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WIDTH((f))])
 
 static void
 update_line (frame, vpos)
@@ -1578,14 +1622,13 @@ window_change_signal ()
      later outside of the signal handler.  */
 
   {
-    Lisp_Object tail;
-    FRAME_PTR f;
+    Lisp_Object tail, frame;
 
-    FOR_EACH_FRAME (tail, f)
+    FOR_EACH_FRAME (tail, frame)
       {
-       if (FRAME_TERMCAP_P (f))
+       if (FRAME_TERMCAP_P (XFRAME (frame)))
          {
-           change_frame_size (f, height, width, 0, 1);
+           change_frame_size (XFRAME (frame), height, width, 0, 1);
            break;
          }
       }
@@ -1604,20 +1647,18 @@ do_pending_window_change ()
   /* If window_change_signal should have run before, run it now.  */
   while (delayed_size_change)
     {
-      Lisp_Object tail;
-      FRAME_PTR f;
+      Lisp_Object tail, frame;
 
       delayed_size_change = 0;
 
-      FOR_EACH_FRAME (tail, f)
+      FOR_EACH_FRAME (tail, frame)
        {
+         FRAME_PTR f = XFRAME (frame);
+
          int height = FRAME_NEW_HEIGHT (f);
          int width = FRAME_NEW_WIDTH (f);
-           
-         FRAME_NEW_HEIGHT (f) = 0;
-         FRAME_NEW_WIDTH (f) = 0;
 
-         if (height != 0)
+         if (height != 0 || width != 0)
            change_frame_size (f, height, width, 0, 0);
        }
     }
@@ -1649,7 +1690,7 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
   FRAME_NEW_HEIGHT (frame) = 0;
   FRAME_NEW_WIDTH  (frame) = 0;
 
-  /* If an arguments is zero, set it to the current value.  */
+  /* If an argument is zero, set it to the current value.  */
   newheight || (newheight = FRAME_HEIGHT (frame));
   newwidth  || (newwidth  = FRAME_WIDTH  (frame));
 
@@ -1668,14 +1709,15 @@ change_frame_size (frame, newheight, newwidth, pretend, delay)
        {
          /* Frame has both root and minibuffer.  */
          set_window_height (FRAME_ROOT_WINDOW (frame),
-                            newheight - 1, 0);
+                            newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
          XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top)
            = newheight - 1;
          set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
        }
       else
        /* Frame has just one top-level window.  */
-       set_window_height (FRAME_ROOT_WINDOW (frame), newheight, 0);
+       set_window_height (FRAME_ROOT_WINDOW (frame),
+                          newheight - FRAME_MENU_BAR_LINES (frame), 0);
 
       if (FRAME_TERMCAP_P (frame) && !pretend)
        FrameRows = newheight;
@@ -1766,29 +1808,53 @@ bitch_at_user ()
 }
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
-  "Pause, without updating display, for ARG seconds.\n\
-Optional second arg non-nil means ARG is measured in milliseconds.\n\
-\(Not all operating systems support milliseconds.)")
-  (arg, millisec)
-     Lisp_Object arg, millisec;
+  "Pause, without updating display, for SECONDS seconds.\n\
+SECONDS may be a floating-point value, meaning that you can wait for a\n\
+fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
+additional wait period, in milliseconds; this may be useful if your\n\
+Emacs was built without floating point support.\n\
+\(Not all operating systems support waiting for a fraction of a second.)")
+  (seconds, milliseconds)
+     Lisp_Object seconds, milliseconds;
 {
-  int usec = 0;
-  int sec;
+  int sec, usec;
 
-  CHECK_NUMBER (arg, 0);
-  sec = XINT (arg);
-  if (sec <= 0)
-    return Qnil;
+  if (NILP (milliseconds))
+    XSET (milliseconds, Lisp_Int, 0);
+  else
+    CHECK_NUMBER (milliseconds, 1);
+  usec = XINT (milliseconds) * 1000;
 
-  if (!NILP (millisec))
-    {
-#ifndef EMACS_HAS_USECS
-      error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
 #else
-      usec = sec % 1000 * 1000;
-      sec /= 1000;
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
 #endif
+
+#ifndef EMACS_HAS_USECS
+  if (sec == 0 && usec != 0)
+    error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
+#endif
+
+  /* Assure that 0 <= usec < 1000000.  */
+  if (usec < 0)
+    {
+      /* We can't rely on the rounding being correct if user is negative.  */
+      if (-1000000 < usec)
+       sec--, usec += 1000000;
+      else
+       sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
     }
+  else
+    sec += usec / 1000000, usec %= 1000000;
+
+  if (sec < 0)
+    return Qnil;
 
   {
     Lisp_Object zero;
@@ -1797,7 +1863,10 @@ Optional second arg non-nil means ARG is measured in milliseconds.\n\
     wait_reading_process_input (sec, usec, zero, 0);
   }
 
-#if 0 /* No wait_reading_process_input */
+  /* We should always have wait_reading_process_input; we have a dummy
+     implementation for systems which don't support subprocesses.  */
+#if 0
+  /* No wait_reading_process_input */
   immediate_quit = 1;
   QUIT;
 
@@ -1853,14 +1922,18 @@ sit_for (sec, usec, reading, display)
     return Qt;
 
 #ifdef SIGIO
-  gobble_input ();
+  gobble_input (0);
 #endif
 
   XSET (read_kbd, Lisp_Int, reading ? -1 : 1);
   wait_reading_process_input (sec, usec, read_kbd, display);
 
 
-#if 0 /* No wait_reading_process_input available.  */
+  /* wait_reading_process_input should always be available now; it is
+     simulated in a simple way on systems that don't support
+     subprocesses.  */
+#if 0
+  /* No wait_reading_process_input available.  */
   immediate_quit = 1;
   QUIT;
 
@@ -1885,52 +1958,44 @@ sit_for (sec, usec, reading, display)
 }
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
-  "Perform redisplay, then wait for ARG seconds or until input is available.\n\
-Optional second arg non-nil means ARG counts in milliseconds.\n\
+  "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
+SECONDS may be a floating-point value, meaning that you can wait for a\n\
+fraction of a second.  Optional second arg MILLISECONDS specifies an\n\
+additional wait period, in milliseconds; this may be useful if your\n\
+Emacs was built without floating point support.\n\
+\(Not all operating systems support waiting for a fraction of a second.)\n\
 Optional third arg non-nil means don't redisplay, just wait for input.\n\
 Redisplay is preempted as always if input arrives, and does not happen\n\
 if input is available before it starts.\n\
 Value is t if waited the full time with no input arriving.")
-  (arg, millisec, nodisp)
-     Lisp_Object arg, millisec, nodisp;
+  (seconds, milliseconds, nodisp)
+     Lisp_Object seconds, milliseconds, nodisp;
 {
-  int usec = 0;
-  int sec;
+  int sec, usec;
 
-  CHECK_NUMBER (arg, 0);
-  sec = XINT (arg);
+  if (NILP (milliseconds))
+    XSET (milliseconds, Lisp_Int, 0);
+  else
+    CHECK_NUMBER (milliseconds, 1);
+  usec = XINT (milliseconds) * 1000;
 
-  if (!NILP (millisec))
-    {
-#ifndef EMACS_HAS_USECS
-      error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
 #else
-      usec = (sec % 1000) * 1000;
-      sec /= 1000;
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
 #endif
-    }
-
-  return sit_for (sec, usec, 0, NILP (nodisp));
-}
-
-DEFUN ("sleep-for-millisecs", Fsleep_for_millisecs, Ssleep_for_millisecs,
-  1, 1, 0,
-  "Pause, without updating display, for ARG milliseconds.")
-  (arg)
-     Lisp_Object arg;
-{
-  Lisp_Object zero;
 
 #ifndef EMACS_HAS_USECS
-  error ("sleep-for-millisecs not supported on %s", SYSTEM_TYPE);
-#else
-  CHECK_NUMBER (arg, 0);
+  if (usec != 0 && sec == 0)
+    error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
+#endif
 
-  XFASTINT (zero) = 0;
-  wait_reading_process_input (XINT (arg) / 1000, XINT (arg) % 1000 * 1000,
-                             zero, 0);
-  return Qnil;
-#endif /* EMACS_HAS_USECS */
+  return sit_for (sec, usec, 0, NILP (nodisp));
 }
 \f
 char *terminal_type;
@@ -1951,20 +2016,29 @@ init_display ()
   cursor_in_echo_area = 0;
   terminal_type = (char *) 0;
 
-  /* If the DISPLAY environment variable is set, try to use X, and
-     die with an error message if that doesn't work.  */
+  /* Now is the time to initialize this; it's used by init_sys_modes
+     during startup.  */
+  Vwindow_system = Qnil;
 
-  /* Check if we're using a window system here before trying to
-     initialize the terminal.  If we check the terminal first,
+  /* If the user wants to use a window system, we shouldn't bother
+     initializing the terminal.  This is especially important when the
+     terminal is so dumb that emacs gives up before and doesn't bother
+     using the window system.
 
-     If someone has indicated that they want
-     to use a window system, we shouldn't bother initializing the
-     terminal.  This is especially important when the terminal is so
-     dumb that emacs gives up before  and doesn't bother using the window
-     system.  */
+     If the DISPLAY environment variable is set, try to use X, and die
+     with an error message if that doesn't work.  */
 
 #ifdef HAVE_X_WINDOWS
-  if (!inhibit_window_system && (display_arg || getenv ("DISPLAY")))
+  if (! display_arg)
+    {
+#ifdef VMS
+      display_arg = (getenv ("DECW$DISPLAY") != 0);
+#else
+      display_arg = (getenv ("DISPLAY") != 0);
+#endif
+    }
+
+  if (!inhibit_window_system && display_arg)
     {
       Vwindow_system = intern ("x");
 #ifdef HAVE_X11