*** empty log message ***
[bpt/emacs.git] / src / dispnew.c
index 25eccf9..06dcebc 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,11 +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"
@@ -37,6 +36,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "commands.h"
 #include "disptab.h"
 #include "indent.h"
+#include "intervals.h"
 
 #include "systty.h"
 #include "systime.h"
@@ -117,7 +117,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/...  */
 
@@ -202,26 +202,26 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
   Lisp_Object tail, frame;
 
   FOR_EACH_FRAME (tail, frame)
-    /* If we simply redrew all visible frames, whether or not they
-       were garbaged, then this would make all frames clear and
-       nredraw whenever a new frame is created or an existing frame
-       is de-iconified; those events set the global frame_garbaged
-       flag, to which redisplay responds by calling this function.
-       
-       This used to redraw all visible frames; the only advantage of
-       that approach is that if a frame changes from invisible to
-       visible without setting its garbaged flag, it still gets
-       redisplayed.  But that should never happen; since invisible
-       frames are not updated, they should always be marked as
-       garbaged when they become visible again.  If that doesn't
-       happen, it's a bug in the visibility code, not a bug here.  */
-    if (FRAME_VISIBLE_P (XFRAME (frame))
-       && FRAME_GARBAGED_P (XFRAME (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)
@@ -283,26 +283,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
@@ -747,7 +747,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;
@@ -760,7 +761,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];
            }
        }
@@ -871,11 +873,31 @@ direct_output_for_insert (g)
   /* Give up if buffer appears in two places.  */
       || buffer_shared > 1
 
+#ifdef USE_TEXT_PROPERTIES
+  /* Intervals have already been adjusted, point is after the
+     character that was just inserted. */
+  /* Give up if character has is invisible. */
+  /* Give up if character has a face property.
+     At the moment we only lose at end of line or end of buffer
+     and only with faces that have some background */
+  /* Instead of wasting time, give up if character has any text properties */
+      || ! NILP (Ftext_properties_at (XFASTINT (point - 1), Qnil))
+#endif
+
   /* Give up if w is minibuffer and a message is being displayed there */
       || (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, -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;
@@ -901,7 +923,8 @@ direct_output_forward_char (n)
 {
   register FRAME_PTR frame = selected_frame;
   register struct window *w = XWINDOW (selected_window);
-
+  int position;
+  
   /* Avoid losing if cursor is in invisible text off left margin
      or about to go off either side of window.  */
   if ((FRAME_CURSOR_X (frame) == XFASTINT (w->left)
@@ -910,12 +933,36 @@ direct_output_forward_char (n)
          && (FRAME_CURSOR_X (frame) + 1 >= window_internal_width (w) - 1))
       || 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;
+
+#ifdef USE_TEXT_PROPERTIES
+  /* Don't use direct output next to an invisible character
+     since we might need to do something special.  */
+
+  XFASTINT (position) = point;
+  if (XFASTINT (position) < ZV
+      && ! NILP (Fget_text_property (position,
+                                    Qinvisible,
+                                    Fcurrent_buffer ())))
+    return;
+
+  XFASTINT (position) = point - 1;
+  if (XFASTINT (position) >= BEGV
+      && ! NILP (Fget_text_property (position,
+                                    Qinvisible,
+                                    Fcurrent_buffer ())))
+    return;
+#endif
 
   FRAME_CURSOR_X (frame) += n;
   XFASTINT (w->last_point_x) = FRAME_CURSOR_X (frame);
   XFASTINT (w->last_point) = point;
   cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
   fflush (stdout);
+
   return 1;
 }
 \f
@@ -941,6 +988,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 ();
@@ -1011,7 +1061,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)
@@ -1217,7 +1268,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;
@@ -1356,6 +1407,25 @@ update_line (frame, vpos)
     {
       int i,j;
 
+#if 0
+      if (FRAME_X_P (frame))
+       {
+         /* Under X, erase everything we are going to rewrite,
+            and rewrite everything from the first char that's changed.
+            This is part of supporting fonts like Courier
+            whose chars can overlap outside the char width.  */
+         for (i = 0; i < nlen; i++)
+           if (i >= olen || nbody[i] != obody[i])
+             break;
+
+         cursor_to (vpos, i);
+         if (i != olen)
+           clear_end_of_line (olen);
+         write_glyphs (nbody + i, nlen - i);
+       }
+      else
+       {}
+#endif /* 0 */
       for (i = 0; i < nlen; i++)
        {
          if (i >= olen || nbody[i] != obody[i])    /* A non-matching char. */
@@ -1639,11 +1709,8 @@ do_pending_window_change ()
 
          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);
        }
     }
@@ -1675,7 +1742,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));
 
@@ -1794,22 +1861,32 @@ bitch_at_user ()
 
 DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
   "Pause, without updating display, for SECONDS seconds.\n\
-Optional second arg MILLISECONDS specifies an additional wait period,\n\
-in milliseconds.\n\
-\(Not all operating systems support milliseconds.)")
+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 sec, usec;
 
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-  
   if (NILP (milliseconds))
     XSET (milliseconds, Lisp_Int, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
-  usec = XINT (milliseconds);
+  usec = XINT (milliseconds) * 1000;
+
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
+#else
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
+#endif
 
 #ifndef EMACS_HAS_USECS
   if (sec == 0 && usec != 0)
@@ -1934,9 +2011,11 @@ sit_for (sec, usec, reading, display)
 
 DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
   "Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
-Optional second arg MILLISECONDS specifies an additional wait period, in\n\
-milliseconds.\n\
-\(Not all operating systems support milliseconds.)\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\
@@ -1946,14 +2025,22 @@ Value is t if waited the full time with no input arriving.")
 {
   int sec, usec;
 
-  CHECK_NUMBER (seconds, 0);
-  sec = XINT (seconds);
-
   if (NILP (milliseconds))
     XSET (milliseconds, Lisp_Int, 0);
   else
     CHECK_NUMBER (milliseconds, 1);
-  usec = XINT (milliseconds);
+  usec = XINT (milliseconds) * 1000;
+
+#ifdef LISP_FLOAT_TYPE
+  {
+    double duration = extract_float (seconds);
+    sec = (int) duration;
+    usec += (duration - sec) * 1000000;
+  }
+#else
+  CHECK_NUMBER (seconds, 0);
+  sec = XINT (seconds);
+#endif
 
 #ifndef EMACS_HAS_USECS
   if (usec != 0 && sec == 0)
@@ -1997,10 +2084,11 @@ init_display ()
   if (! display_arg)
     {
 #ifdef VMS
-      display_arg = getenv ("DECW$DISPLAY");
+      display_arg = (getenv ("DECW$DISPLAY") != 0);
 #else
-      display_arg = getenv ("DISPLAY");
+      display_arg = (getenv ("DISPLAY") != 0);
 #endif
+    }
 
   if (!inhibit_window_system && display_arg)
     {