(lm): Use "p" not "P" for interactive spec.
[bpt/emacs.git] / src / term.c
index 672eee2..4bd5f16 100644 (file)
@@ -1,5 +1,5 @@
 /* terminal control module for terminals described by TERMCAP
-   Copyright (C) 1985, 86, 87, 93, 94, 95, 98
+   Copyright (C) 1985, 86, 87, 93, 94, 95, 98, 2000, 2001
      Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -31,21 +31,33 @@ Boston, MA 02111-1307, USA.  */
 #include "lisp.h"
 #include "charset.h"
 #include "coding.h"
+#include "keyboard.h"
 #include "frame.h"
 #include "disptab.h"
 #include "termhooks.h"
-#include "keyboard.h"
 #include "dispextern.h"
 #include "window.h"
 
-#ifdef HAVE_TERMCAP_H
+/* For now, don't try to include termcap.h.  On some systems,
+   configure finds a non-standard termcap.h that the main build
+   won't find.  */
+
+#if defined HAVE_TERMCAP_H && 0
 #include <termcap.h>
+#else
+extern void tputs P_ ((const char *, int, int (*)(int)));
+extern int tgetent P_ ((char *, const char *));
+extern int tgetflag P_ ((char *id));
+extern int tgetnum P_ ((char *id));
 #endif
 
 #include "cm.h"
 #ifdef HAVE_X_WINDOWS
 #include "xterm.h"
 #endif
+#ifdef macintosh
+#include "macterm.h"
+#endif
 
 static void turn_on_face P_ ((struct frame *, int face_id));
 static void turn_off_face P_ ((struct frame *, int face_id));
@@ -412,7 +424,6 @@ extern char *tgetstr ();
 \f
 
 #ifdef WINDOWSNT
-
 /* We aren't X windows, but we aren't termcap either.  This makes me
    uncertain as to what value to use for frame.output_method.  For
    this file, we'll define FRAME_TERMCAP_P to be zero so that our
@@ -507,7 +518,7 @@ void
 update_end (f)
      FRAME_PTR f;
 {
-  if (! FRAME_TERMCAP_P (updating_frame))
+  if (! FRAME_TERMCAP_P (f))
     {
       (*update_end_hook) (f);
       updating_frame = 0;
@@ -610,6 +621,15 @@ turn_on_highlight ()
     }
 }
 
+static void
+toggle_highlight ()
+{
+  if (standout_mode)
+    turn_off_highlight ();
+  else
+    turn_on_highlight ();
+}
+
 
 /* Make cursor invisible.  */
 
@@ -704,7 +724,7 @@ reassert_line_highlight (highlight, vpos)
   else if (chars_wasted && chars_wasted[vpos] == 0)
     /* For terminals with standout markers, write one on this line
        if there isn't one already.  */
-    write_standout_marker (highlight, vpos);
+    write_standout_marker (inverse_video ? !highlight : highlight, vpos);
 }
 
 /* Call this when about to modify line at position VPOS
@@ -946,7 +966,6 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
   struct glyph *src_start = src, *src_end = src + src_len;
   unsigned char *dst_start = dst, *dst_end = dst + dst_len;
   register GLYPH g;
-  unsigned int c;
   unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
   int len;
   register int tlen = GLYPH_TABLE_LENGTH;
@@ -954,7 +973,10 @@ encode_terminal_code (src, dst, src_len, dst_len, consumed)
   int result;
   struct coding_system *coding;
 
-  coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
+  /* If terminal_coding does any conversion, use it, otherwise use
+     safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
+     because it always return 1 if the member src_multibyte is 1.  */
+  coding = (terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
            ? &terminal_coding
            : &safe_terminal_coding);
 
@@ -1042,6 +1064,8 @@ write_glyphs (string, len)
   int produced, consumed;
   struct frame *sf = XFRAME (selected_frame);
   struct frame *f = updating_frame ? updating_frame : sf;
+  unsigned char conversion_buffer[1024];
+  int conversion_buffer_size = sizeof conversion_buffer;
 
   if (write_glyphs_hook
       && ! FRAME_TERMCAP_P (f))
@@ -1050,7 +1074,6 @@ write_glyphs (string, len)
       return;
     }
 
-  highlight_if_desired ();
   turn_off_insert ();
 
   /* Don't dare write in last column of bottom line, if Auto-Wrap,
@@ -1080,13 +1103,14 @@ write_glyphs (string, len)
          break;
 
       /* Turn appearance modes of the face of the run on.  */
+      highlight_if_desired ();
       turn_on_face (f, face_id);
 
       while (n > 0)
        {
-         /* We use a shared conversion buffer of the current size
-            (1024 bytes at least).  Usually it is sufficient, but if
-            not, we just repeat the loop.  */
+         /* We use a fixed size (1024 bytes) of conversion buffer.
+            Usually it is sufficient, but if not, we just repeat the
+            loop.  */
          produced = encode_terminal_code (string, conversion_buffer,
                                           n, conversion_buffer_size,
                                           &consumed);
@@ -1105,6 +1129,7 @@ write_glyphs (string, len)
 
       /* Turn appearance modes off.  */
       turn_off_face (f, face_id);
+      turn_off_highlight ();
     }
   
   /* We may have to output some codes to terminate the writing.  */
@@ -1135,7 +1160,7 @@ insert_glyphs (start, len)
      register int len;
 {
   char *buf;
-  struct glyph *glyph;
+  struct glyph *glyph = NULL;
   struct frame *f, *sf;
 
   if (len <= 0)
@@ -1149,7 +1174,6 @@ insert_glyphs (start, len)
 
   sf = XFRAME (selected_frame);
   f = updating_frame ? updating_frame : sf;
-  highlight_if_desired ();
 
   if (TS_ins_multi_chars)
     {
@@ -1168,6 +1192,8 @@ insert_glyphs (start, len)
   while (len-- > 0)
     {
       int produced, consumed;
+      unsigned char conversion_buffer[1024];
+      int conversion_buffer_size = sizeof conversion_buffer;
 
       OUTPUT1_IF (TS_ins_char);
       if (!start)
@@ -1177,6 +1203,7 @@ insert_glyphs (start, len)
        }
       else
        {
+         highlight_if_desired ();
          turn_on_face (f, start->face_id);
          glyph = start;
          ++start;
@@ -1192,8 +1219,8 @@ insert_glyphs (start, len)
            /* This is the last glyph.  */
            terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
 
-         /* We use shared conversion buffer of the current size (1024
-            bytes at least).  It is surely sufficient for just one glyph.  */
+         /* The size of conversion buffer (1024 bytes) is surely
+            sufficient for just one glyph.  */
          produced = encode_terminal_code (glyph, conversion_buffer, 1,
                                           conversion_buffer_size, &consumed);
        }
@@ -1209,7 +1236,10 @@ insert_glyphs (start, len)
 
       OUTPUT1_IF (TS_pad_inserted_char);
       if (start)
-       turn_off_face (f, glyph->face_id);
+       {
+         turn_off_face (f, glyph->face_id);
+         turn_off_highlight ();
+       }
     }
   
   cmcheckmagic ();
@@ -1988,8 +2018,54 @@ turn_on_face (f, face_id)
      int face_id;
 {
   struct face *face = FACE_FROM_ID (f, face_id);
+  long fg = face->foreground;
+  long bg = face->background;
 
-  xassert (face != NULL);
+  /* Do this first because TS_end_standout_mode may be the same
+     as TS_exit_attribute_mode, which turns all appearances off. */
+  if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
+    {
+      if (TN_max_colors > 0)
+       {
+         if (fg >= 0 && bg >= 0)
+           {
+             /* If the terminal supports colors, we can set them
+                below without using reverse video.  The face's fg
+                and bg colors are set as they should appear on
+                the screen, i.e. they take the inverse-video'ness
+                of the face already into account.  */
+           }
+         else if (inverse_video)
+           {
+             if (fg == FACE_TTY_DEFAULT_FG_COLOR
+                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
+               toggle_highlight ();
+           }
+         else
+           {
+             if (fg == FACE_TTY_DEFAULT_BG_COLOR
+                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
+               toggle_highlight ();
+           }
+       }
+      else
+       {
+         /* If we can't display colors, use reverse video
+            if the face specifies that.  */
+         if (inverse_video)
+           {
+             if (fg == FACE_TTY_DEFAULT_FG_COLOR
+                 || bg == FACE_TTY_DEFAULT_BG_COLOR)
+               toggle_highlight ();
+           }
+         else
+           {
+             if (fg == FACE_TTY_DEFAULT_BG_COLOR
+                 || bg == FACE_TTY_DEFAULT_FG_COLOR)
+               toggle_highlight ();
+           }
+       }
+    }
 
   if (face->tty_bold_p)
     {
@@ -2015,32 +2091,20 @@ turn_on_face (f, face_id)
       && MAY_USE_WITH_COLORS_P (NC_UNDERLINE))
     OUTPUT1_IF (TS_enter_underline_mode);
 
-  if (MAY_USE_WITH_COLORS_P (NC_REVERSE))
-    if (face->tty_reverse_p
-       || face->foreground == FACE_TTY_DEFAULT_BG_COLOR
-       || face->background == FACE_TTY_DEFAULT_FG_COLOR)
-      OUTPUT1_IF (TS_enter_reverse_mode);
-
   if (TN_max_colors > 0)
     {
       char *p;
       
-      if (face->foreground != FACE_TTY_DEFAULT_COLOR
-         && face->foreground != FACE_TTY_DEFAULT_FG_COLOR
-         && face->foreground != FACE_TTY_DEFAULT_BG_COLOR
-         && TS_set_foreground)
+      if (fg >= 0 && TS_set_foreground)
        {
-         p = tparam (TS_set_foreground, NULL, 0, (int) face->foreground);
+         p = tparam (TS_set_foreground, NULL, 0, (int) fg);
          OUTPUT (p);
          xfree (p);
        }
 
-      if (face->background != FACE_TTY_DEFAULT_COLOR
-         && face->background != FACE_TTY_DEFAULT_BG_COLOR
-         && face->background != FACE_TTY_DEFAULT_FG_COLOR
-         && TS_set_background)
+      if (bg >= 0 && TS_set_background)
        {
-         p = tparam (TS_set_background, NULL, 0, (int) face->background);
+         p = tparam (TS_set_background, NULL, 0, (int) bg);
          OUTPUT (p);
          xfree (p);
        }
@@ -2070,7 +2134,11 @@ turn_off_face (f, face_id)
          || face->tty_alt_charset_p
          || face->tty_blinking_p
          || face->tty_underline_p)
-       OUTPUT1_IF (TS_exit_attribute_mode);
+       {
+         OUTPUT1_IF (TS_exit_attribute_mode);
+         if (strcmp (TS_exit_attribute_mode, TS_end_standout_mode) == 0)
+           standout_mode = 0;
+       }
 
       if (face->tty_alt_charset_p)
        OUTPUT_IF (TS_exit_alt_charset_mode);