(face-valid-attribute-values): Make sure directories we search for
[bpt/emacs.git] / src / w32console.c
index 8aec923..55adc0d 100644 (file)
@@ -1,5 +1,5 @@
 /* Terminal hooks for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -28,13 +28,20 @@ Boston, MA 02111-1307, USA.
 #include <stdlib.h>
 #include <stdio.h>
 #include <windows.h>
+#include <string.h>
 
 #include "lisp.h"
 #include "charset.h"
-#include "frame.h"
+#include "coding.h"
 #include "disptab.h"
 #include "termhooks.h"
+/* Disable features in dispextern.h that require a Window System.  */
+#undef HAVE_WINDOW_SYSTEM
+#include "frame.h"
 #include "w32inevt.h"
+#include "dispextern.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
 
 /* from window.c */
 extern Lisp_Object Frecenter ();
@@ -45,7 +52,7 @@ extern int detect_input_pending ();
 /* from sysdep.c */
 extern int read_input_pending ();
 
-extern FRAME_PTR updating_frame;
+extern struct frame * updating_frame;
 extern int meta_key;
 
 static void move_cursor (int row, int col);
@@ -53,29 +60,36 @@ static void clear_to_end (void);
 static void clear_frame (void);
 static void clear_end_of_line (int);
 static void ins_del_lines (int vpos, int n);
-static void change_line_highlight (int, int, int);
+static void change_line_highlight (int, int, int, int);
 static void reassert_line_highlight (int, int);
-static void insert_glyphs (GLYPH *start, int len);
-static void write_glyphs (GLYPH *string, int len);
+static void insert_glyphs (struct glyph *start, int len);
+static void write_glyphs (struct glyph *string, int len);
 static void delete_glyphs (int n);
 void w32_sys_ring_bell (void);
 static void reset_terminal_modes (void);
 static void set_terminal_modes (void);
 static void set_terminal_window (int size);
-static void update_begin (FRAME_PTR f);
-static void update_end (FRAME_PTR f);
-static int  hl_mode (int new_highlight);
+static void update_begin (struct frame * f);
+static void update_end (struct frame * f);
+static WORD w32_face_attributes (struct frame *f, int face_id);
+static int hl_mode (int new_highlight);
 
-COORD  cursor_coords;
-HANDLE prev_screen, cur_screen;
-UCHAR  char_attr, char_attr_normal, char_attr_reverse;
-HANDLE  keyboard_handle;
-DWORD   prev_console_mode;
+static COORD   cursor_coords;
+static HANDLE  prev_screen, cur_screen;
+static WORD    char_attr_normal;
+static DWORD   prev_console_mode;
 
 #ifndef USE_SEPARATE_SCREEN
-CONSOLE_CURSOR_INFO prev_console_cursor;
+static CONSOLE_CURSOR_INFO prev_console_cursor;
 #endif
 
+/* Determine whether to make frame dimensions match the screen buffer,
+   or the current window size.  The former is desirable when running
+   over telnet, while the latter is more useful when working directly at
+   the console with a large scroll-back buffer.  */
+int w32_use_full_screen_buffer;
+HANDLE  keyboard_handle;
+
 
 /* Setting this as the ctrl handler prevents emacs from being killed when
    someone hits ^C in a 'suspended' session (child shell).
@@ -91,7 +105,7 @@ ctrl_c_handler (unsigned long type)
 
 /* If we're updating a frame, use it as the current frame
    Otherwise, use the selected frame.  */
-#define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
+#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
 
 /* Move the cursor to (row, col).  */
 void
@@ -100,7 +114,7 @@ move_cursor (int row, int col)
   cursor_coords.X = col;
   cursor_coords.Y = row;
   
-  if (updating_frame == (FRAME_PTR) NULL)
+  if (updating_frame == (struct frame *) NULL)
     {
       SetConsoleCursorPosition (cur_screen, cursor_coords);
     }
@@ -110,7 +124,7 @@ move_cursor (int row, int col)
 void
 clear_to_end (void)
 {
-  FRAME_PTR f = PICK_FRAME ();
+  struct frame * f = PICK_FRAME ();
   
   clear_end_of_line (FRAME_WIDTH (f) - 1);
   ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
@@ -120,23 +134,28 @@ clear_to_end (void)
 void
 clear_frame (void)
 {
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
   COORD             dest;
-  int        n, r;
+  int        n;
+  DWORD      r;
+  CONSOLE_SCREEN_BUFFER_INFO info;
+
+  GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
 
   hl_mode (0);
-  
-  n = FRAME_HEIGHT (f) * FRAME_WIDTH (f);
+
+  /* Remember that the screen buffer might be wider than the window.  */
+  n = FRAME_HEIGHT (f) * info.dwSize.X;
   dest.X = dest.Y = 0;
 
-  FillConsoleOutputAttribute (cur_screen, char_attr, n, dest, &r);
+  FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
   FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
 
   move_cursor (0, 0);
 }
 
 
-static GLYPH glyph_base[256];
+static struct glyph glyph_base[256];
 static BOOL  ceol_initialized = FALSE;
 
 /* Clear from Cursor to end (what's "standout marker"?).  */
@@ -148,7 +167,7 @@ clear_end_of_line (int end)
       int i;
       for (i = 0; i < 256; i++)
         {
-         glyph_base[i] = SPACEGLYPH;   /* empty space  */
+         memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
         }
       ceol_initialized = TRUE;
     }
@@ -163,7 +182,7 @@ ins_del_lines (int vpos, int n)
   SMALL_RECT scroll;
   COORD             dest;
   CHAR_INFO  fill;
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
 
   if (n < 0)
     {
@@ -185,7 +204,7 @@ ins_del_lines (int vpos, int n)
   save_highlight = hl_mode (0);
   
   fill.Char.AsciiChar = 0x20;
-  fill.Attributes = char_attr;
+  fill.Attributes = char_attr_normal;
   
   ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
 
@@ -236,21 +255,15 @@ hl_mode (int new_highlight)
   
   old_highlight = highlight;
   highlight = (new_highlight != 0);
-  if (highlight)
-    {
-      char_attr = char_attr_reverse;
-    }
-  else
-    {
-      char_attr = char_attr_normal;
-    }
+
   return old_highlight;
 }
 
 /* Call this when about to modify line at position VPOS and change whether it
    is highlighted.  */
 void
-change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
+change_line_highlight (int new_highlight, int vpos, int y, 
+                       int first_unused_hpos)
 {
   hl_mode (new_highlight);
   move_cursor (vpos, 0);
@@ -279,7 +292,7 @@ scroll_line (int dist, int direction)
   SMALL_RECT scroll;
   COORD             dest;
   CHAR_INFO  fill;
-  FRAME_PTR  f = PICK_FRAME ();
+  struct frame *  f = PICK_FRAME ();
   
   scroll.Top = cursor_coords.Y;
   scroll.Bottom = cursor_coords.Y;
@@ -299,15 +312,15 @@ scroll_line (int dist, int direction)
   dest.Y = cursor_coords.Y;
   
   fill.Char.AsciiChar = 0x20;
-  fill.Attributes = char_attr;
-  
+  fill.Attributes = char_attr_normal;
+
   ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
 }
 
 
 /* If start is zero insert blanks instead of a string at start ?. */
 void
-insert_glyphs (register GLYPH *start, register int len)
+insert_glyphs (register struct glyph *start, register int len)
 {
   scroll_line (len, RIGHT);
 
@@ -326,81 +339,102 @@ insert_glyphs (register GLYPH *start, register int len)
 }
 
 void
-write_glyphs (register GLYPH *string, register int len)
+write_glyphs (register struct glyph *string, register int len)
 {
-  register unsigned int glyph_len = GLYPH_TABLE_LENGTH;
-  Lisp_Object *glyph_table = GLYPH_TABLE_BASE;
-  FRAME_PTR f = PICK_FRAME ();
-  register char *ptr;
-  GLYPH glyph;
-  WORD *attrs;
-  char *chars;
-  int i;
-  
+  int produced, consumed;
+  DWORD r;
+  struct frame * f = PICK_FRAME ();
+  WORD char_attr;
+  unsigned char conversion_buffer[1024];
+  int conversion_buffer_size = sizeof conversion_buffer;
+
   if (len <= 0)
     return;
 
-  attrs = alloca (len * sizeof (*attrs));
-  chars = alloca (len * sizeof (*chars));
-  if (attrs == NULL || chars == NULL)
-    {
-      printf ("alloca failed in write_glyphs\n");
-      return;
-    }
-  
-  /* We have to deal with the glyph indirection...go over the glyph
-     buffer and extract the characters.  */
-  ptr = chars;
-  while (--len >= 0)
-    {
-      glyph = *string++;
+  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+     the tail.  */
+  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
 
-      if (glyph > glyph_len)
-        {
-         *ptr++ = glyph & 0xFF;
-         continue;
-       }
-      GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph);
-#ifndef HAVE_NTGUI
-      if (GLYPH_FACE (fixfix, glyph) != 0)
-       printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph));
-#endif /* !HAVE_NTGUI */
-      if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph))
-        {
-         *ptr++ = glyph & 0xFF;
-         continue;
-       }
-      for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++)
-        {
-         *ptr++ = (GLYPH_STRING (glyph_table, glyph))[i];
-       }
-    }
-  
-  /* Number of characters we have in the buffer.  */
-  len = ptr-chars;
-  
-  /* Fill in the attributes for these characters.  */
-  for (i = 0; i < len; i++)
-    attrs[i] = char_attr;
-  
-  /* Write the attributes.  */
-  if (!WriteConsoleOutputAttribute (cur_screen, attrs, len, cursor_coords, &i))
+  while (len > 0)
     {
-      printf ("Failed writing console attributes: %d\n", GetLastError ());
-      fflush (stdout);
+      /* Identify a run of glyphs with the same face.  */
+      int face_id = string->face_id;
+      int n;
+      
+      for (n = 1; n < len; ++n)
+       if (string[n].face_id != face_id)
+         break;
+
+      /* Turn appearance modes of the face of the run on.  */
+      char_attr = w32_face_attributes (f, face_id);
+
+      while (n > 0)
+        {
+         /* 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);
+         if (produced > 0)
+           {
+              /* Set the attribute for these characters.  */
+              if (!FillConsoleOutputAttribute (cur_screen, char_attr,
+                                               produced, cursor_coords, &r)) 
+                {
+                  printf ("Failed writing console attributes: %d\n",
+                          GetLastError ());
+                  fflush (stdout);
+                }
+
+              /* Write the characters.  */
+              if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+                                                produced, cursor_coords, &r))
+                {
+                  printf ("Failed writing console characters: %d\n",
+                          GetLastError ());
+                  fflush (stdout);
+                }
+
+              cursor_coords.X += produced;
+              move_cursor (cursor_coords.Y, cursor_coords.X);
+            }    
+          len -= consumed;
+          n -= consumed;
+          string += consumed;
+        }
     }
 
-  /* Write the characters.  */
-  if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i))
+  /* We may have to output some codes to terminate the writing.  */
+  if (CODING_REQUIRE_FLUSHING (&terminal_coding))
     {
-      printf ("Failed writing console characters: %d\n", GetLastError ());
-      fflush (stdout);
+      terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
+      encode_coding (&terminal_coding, "", conversion_buffer,
+                    0, conversion_buffer_size);
+      if (terminal_coding.produced > 0)
+        {
+          if (!FillConsoleOutputAttribute (cur_screen, char_attr_normal,
+                                           terminal_coding.produced,
+                                           cursor_coords, &r)) 
+            {
+              printf ("Failed writing console attributes: %d\n",
+                      GetLastError ());
+              fflush (stdout);
+            }
+
+          /* Write the characters.  */
+          if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+                                            produced, cursor_coords, &r))
+            {
+              printf ("Failed writing console characters: %d\n",
+                      GetLastError ());
+              fflush (stdout);
+            }
+        }
     }
-  
-  cursor_coords.X += len;
-  move_cursor (cursor_coords.Y, cursor_coords.X);
 }
 
+
 void
 delete_glyphs (int n)
 {
@@ -412,20 +446,28 @@ delete_glyphs (int n)
 }
 
 static unsigned int sound_type = 0xFFFFFFFF;
+#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
 
 void
 w32_sys_ring_bell (void)
 {
   if (sound_type == 0xFFFFFFFF) 
+    {
       Beep (666, 100);
+    }
+  else if (sound_type == MB_EMACS_SILENT)
+    {
+      /* Do nothing.  */
+    }
   else
-      MessageBeep (sound_type);
+    MessageBeep (sound_type);
 }
 
 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
        "Set the sound generated when the bell is rung.\n\
-SOUND is 'asterisk, 'exclamation, 'hand, 'question, or 'ok\n\
-to use the corresponding system sound for the bell.\n\
+SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent\n\
+to use the corresponding system sound for the bell.  The 'silent sound\n\
+prevents Emacs from making any sound at all.\n\
 SOUND is nil to use the normal beep.")
      (sound)
      Lisp_Object sound;
@@ -444,6 +486,8 @@ SOUND is nil to use the normal beep.")
       sound_type = MB_ICONQUESTION;
   else if (EQ (sound, intern ("ok"))) 
       sound_type = MB_OK;
+  else if (EQ (sound, intern ("silent")))
+      sound_type = MB_EMACS_SILENT;
   else
       sound_type = 0xFFFFFFFF;
 
@@ -453,6 +497,8 @@ SOUND is nil to use the normal beep.")
 void
 reset_terminal_modes (void)
 {
+  hl_mode (0);
+
 #ifdef USE_SEPARATE_SCREEN
   SetConsoleActiveScreenBuffer (prev_screen);
 #else
@@ -466,6 +512,8 @@ set_terminal_modes (void)
 {
   CONSOLE_CURSOR_INFO cci;
 
+  hl_mode (0);
+
   /* make cursor big and visible (100 on Win95 makes it disappear)  */
   cci.dwSize = 99;
   cci.bVisible = TRUE;
@@ -485,13 +533,15 @@ set_terminal_modes (void)
    
    we'll start with not moving the cursor while an update is in progress.  */
 void
-update_begin (FRAME_PTR f)
+update_begin (struct frame * f)
 {
+  hl_mode (0);
 }
 
 void
-update_end (FRAME_PTR f)
+update_end (struct frame * f)
 {
+  hl_mode (0);
   SetConsoleCursorPosition (cur_screen, cursor_coords);
 }
 
@@ -500,6 +550,75 @@ set_terminal_window (int size)
 {
 }
 
+/***********************************************************************
+                               Faces
+ ***********************************************************************/
+
+
+/* Turn appearances of face FACE_ID on tty frame F on.  */
+
+static WORD
+w32_face_attributes (f, face_id)
+     struct frame *f;
+     int face_id;
+{
+  WORD char_attr;
+  int highlight_on_p;
+  struct face *face = FACE_FROM_ID (f, face_id);
+
+  highlight_on_p = hl_mode (0);
+  hl_mode (highlight_on_p);
+
+  xassert (face != NULL);
+
+  char_attr = char_attr_normal;
+
+  if (face->foreground != FACE_TTY_DEFAULT_FG_COLOR
+      && face->foreground != FACE_TTY_DEFAULT_COLOR)
+    char_attr = (char_attr & 0xfff0) + (face->foreground % 16);
+
+  if (face->background != FACE_TTY_DEFAULT_BG_COLOR
+      && face->background != FACE_TTY_DEFAULT_COLOR)
+    char_attr = (char_attr & 0xff0f) + ((face->background % 16) * 16); 
+
+
+  /* Ensure readability (temporary measure until this all works) */
+  if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
+    char_attr ^= 0x0007;
+
+  if (face->tty_reverse_p || highlight_on_p)
+    char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
+      + ((char_attr & 0x00f0) >> 4);
+
+  return char_attr;
+}
+
+
+/* Emulation of some X window features from xfns.c and xfaces.c.  */
+
+extern char unspecified_fg[], unspecified_bg[];
+
+
+/* Given a color index, return its standard name.  */
+Lisp_Object
+vga_stdcolor_name (int idx)
+{
+  /* Standard VGA colors, in the order of their standard numbering
+     in the default VGA palette.  */
+  static char *vga_colors[16] = {
+    "black", "blue", "green", "cyan", "red", "magenta", "brown",
+    "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
+    "lightred", "lightmagenta", "yellow", "white"
+  };
+
+  extern Lisp_Object Qunspecified;
+
+  if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
+    return build_string (vga_colors[idx]);
+  else
+    return Qunspecified;       /* meaning the default */
+}
+
 typedef int (*term_hook) ();
 
 void
@@ -527,6 +646,10 @@ initialize_w32_display (void)
   
   read_socket_hook = w32_console_read_socket;
   mouse_position_hook = w32_console_mouse_position;
+  estimate_mode_line_height_hook = 0;
+
+  /* Initialize interrupt_handle.  */
+  init_crit ();
 
   /* Remember original console settings.  */
   keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
@@ -552,19 +675,65 @@ initialize_w32_display (void)
   GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
 #endif
 
+  /* Respect setting of LINES and COLUMNS environment variables.  */
+  {
+    char * lines = getenv("LINES");
+    char * columns = getenv("COLUMNS");
+
+    if (lines != NULL && columns != NULL)
+      {
+       SMALL_RECT new_win_dims;
+       COORD new_size;
+
+       new_size.X = atoi (columns);
+       new_size.Y = atoi (lines);
+
+       GetConsoleScreenBufferInfo (cur_screen, &info);
+
+       /* Shrink the window first, so the buffer dimensions can be
+           reduced if necessary.  */
+       new_win_dims.Top = 0;
+       new_win_dims.Left = 0;
+       new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
+       new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
+       SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
+
+       SetConsoleScreenBufferSize (cur_screen, new_size);
+
+       /* Set the window size to match the buffer dimension.  */
+       new_win_dims.Top = 0;
+       new_win_dims.Left = 0;
+       new_win_dims.Bottom = new_size.Y - 1;
+       new_win_dims.Right = new_size.X - 1;
+       SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
+      }
+  }
+
   GetConsoleScreenBufferInfo (cur_screen, &info);
   
   meta_key = 1;
-  char_attr = info.wAttributes & 0xFF;
-  char_attr_normal = char_attr;
-  char_attr_reverse = ((char_attr & 0xf) << 4) + ((char_attr & 0xf0) >> 4);
-  
-  FRAME_HEIGHT (selected_frame) = info.dwSize.Y;       /* lines per page */
-  SET_FRAME_WIDTH (selected_frame, info.dwSize.X); /* characters per line */
-  
-//  move_cursor (0, 0);
-  
-//  clear_frame ();
+  char_attr_normal = info.wAttributes;
+  hl_mode (0);
+
+  if (w32_use_full_screen_buffer)
+    {
+      FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y;        /* lines per page */
+      SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X);  /* characters per line */
+    }
+  else
+    {
+      /* Lines per page.  Use buffer coords instead of buffer size.  */
+      FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom - 
+       info.srWindow.Top; 
+      /* Characters per line.  Use buffer coords instead of buffer size.  */
+      SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right - 
+                      info.srWindow.Left);
+    }
+
+  /* Setup w32_display_info structure for this frame. */
+
+  w32_initialize_display_info (build_string ("Console"));
+
 }
 
 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
@@ -574,7 +743,6 @@ DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
     Lisp_Object background;
 {
   char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
-  char_attr_reverse = XFASTINT (background) + (XFASTINT (foreground) << 4);
 
   Frecenter (Qnil);
   return Qt;
@@ -595,7 +763,7 @@ DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
 
 #ifndef HAVE_NTGUI
 void
-pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
+pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
                      void *bounds, int noclip)
 {
   *x = pix_x;
@@ -603,7 +771,7 @@ pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
 }
 
 void
-glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
+glyph_to_pixel_coords (struct window * f, int x, int y, int *pix_x, int *pix_y)
 {
   *pix_x = x;
   *pix_y = y;
@@ -613,6 +781,15 @@ glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
 void
 syms_of_ntterm ()
 {
+  DEFVAR_BOOL ("w32-use-full-screen-buffer",
+               &w32_use_full_screen_buffer,
+  "Non-nil means make terminal frames use the full screen buffer dimensions.\n\
+This is desirable when running Emacs over telnet, and is the default.\n\
+A value of nil means use the current console window dimensions; this\n\
+may be preferrable when working directly at the console with a large\n\
+scroll-back buffer.");
+  w32_use_full_screen_buffer = 1;
+
   defsubr (&Sset_screen_color);
   defsubr (&Sset_cursor_size);
   defsubr (&Sset_message_beep);