Support mouse highlight on w32 text-mode frames.
[bpt/emacs.git] / src / w32console.c
index 34715cc..22f329e 100644 (file)
@@ -1,6 +1,5 @@
 /* Terminal hooks for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1992, 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-                 2008, 2009, 2010  Free Software Foundation, Inc.
+   Copyright (C) 1992, 1999, 2001-2012  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -25,10 +24,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <config.h>
 
-#include <stdlib.h>
 #include <stdio.h>
 #include <windows.h>
-#include <string.h>
 #include <setjmp.h>
 
 #include "lisp.h"
@@ -36,19 +33,14 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "coding.h"
 #include "disptab.h"
 #include "frame.h"
+#include "window.h"
 #include "termhooks.h"
 #include "termchar.h"
 #include "dispextern.h"
 #include "w32inevt.h"
 
 /* from window.c */
-extern Lisp_Object Frecenter ();
-
-/* from keyboard.c */
-extern int detect_input_pending ();
-
-/* from sysdep.c */
-extern int read_input_pending ();
+extern Lisp_Object Frecenter (Lisp_Object);
 
 static void w32con_move_cursor (struct frame *f, int row, int col);
 static void w32con_clear_to_end (struct frame *f);
@@ -68,19 +60,12 @@ static WORD w32_face_attributes (struct frame *f, int face_id);
 static COORD   cursor_coords;
 static HANDLE  prev_screen, cur_screen;
 static WORD    char_attr_normal;
-static DWORD   prev_console_mode;
+static DWORD   prev_console_mode;
 
 #ifndef USE_SEPARATE_SCREEN
 static CONSOLE_CURSOR_INFO prev_console_cursor;
 #endif
 
-extern Lisp_Object Vtty_defined_color_alist;
-
-/* 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;
 
 
@@ -268,7 +253,8 @@ scroll_line (struct frame *f, int dist, int direction)
 
 /* If start is zero insert blanks instead of a string at start ?. */
 static void
-w32con_insert_glyphs (struct frame *f, register struct glyph *start, register int len)
+w32con_insert_glyphs (struct frame *f, register struct glyph *start,
+                     register int len)
 {
   scroll_line (f, len, RIGHT);
 
@@ -286,9 +272,6 @@ w32con_insert_glyphs (struct frame *f, register struct glyph *start, register in
     }
 }
 
-extern unsigned char *encode_terminal_code (struct glyph *, int, 
-                                            struct coding_system *);
-
 static void
 w32con_write_glyphs (struct frame *f, register struct glyph *string,
                      register int len)
@@ -357,6 +340,84 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
     }
 }
 
+/* Used for mouse highlight.  */
+static void
+w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
+                              register struct glyph *string, register int len,
+                              register int face_id)
+{
+  unsigned char *conversion_buffer;
+  struct coding_system *coding;
+
+  if (len <= 0)
+    return;
+
+  /* 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 = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
+           ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
+  /* We are going to write the entire block of glyphs in one go, as
+     they all have the same face.  So this _is_ the last block.  */
+  coding->mode |= CODING_MODE_LAST_BLOCK;
+
+  conversion_buffer = encode_terminal_code (string, len, coding);
+  if (coding->produced > 0)
+    {
+      DWORD filled, written;
+      /* Compute the character attributes corresponding to the face.  */
+      DWORD char_attr = w32_face_attributes (f, face_id);
+      COORD start_coords;
+
+      start_coords.X = x;
+      start_coords.Y = y;
+      /* Set the attribute for these characters.  */
+      if (!FillConsoleOutputAttribute (cur_screen, char_attr,
+                                      coding->produced, start_coords,
+                                      &filled))
+       DebPrint (("Failed writing console attributes: %d\n", GetLastError ()));
+      else
+       {
+         /* Write the characters.  */
+         if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
+                                           filled, start_coords, &written))
+           DebPrint (("Failed writing console characters: %d\n",
+                      GetLastError ()));
+       }
+    }
+}
+
+/* Implementation of draw_row_with_mouse_face for W32 console.  */
+void
+tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
+                             int start_hpos, int end_hpos,
+                             enum draw_glyphs_face draw)
+{
+  int nglyphs = end_hpos - start_hpos;
+  struct frame *f = XFRAME (WINDOW_FRAME (w));
+  struct tty_display_info *tty = FRAME_TTY (f);
+  int face_id = tty->mouse_highlight.mouse_face_face_id;
+  int pos_x, pos_y;
+
+  if (end_hpos >= row->used[TEXT_AREA])
+    nglyphs = row->used[TEXT_AREA] - start_hpos;
+
+  pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
+  pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
+
+  if (draw == DRAW_MOUSE_FACE)
+    w32con_write_glyphs_with_face (f, pos_x, pos_y,
+                                  row->glyphs[TEXT_AREA] + start_hpos,
+                                  nglyphs, face_id);
+  else if (draw == DRAW_NORMAL_TEXT)
+    {
+      COORD save_coords = cursor_coords;
+
+      w32con_move_cursor (f, pos_y, pos_x);
+      write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
+      w32con_move_cursor (f, save_coords.Y, save_coords.X);
+    }
+}
 
 static void
 w32con_delete_glyphs (struct frame *f, int n)
@@ -392,8 +453,7 @@ SOUND is 'asterisk, 'exclamation, 'hand, 'question, 'ok, or 'silent
 to use the corresponding system sound for the bell.  The 'silent sound
 prevents Emacs from making any sound at all.
 SOUND is nil to use the normal beep.  */)
-     (sound)
-     Lisp_Object sound;
+  (Lisp_Object sound)
 {
   CHECK_SYMBOL (sound);
 
@@ -438,7 +498,7 @@ w32con_reset_terminal_modes (struct terminal *t)
   FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
   /* Now that the screen is clear, put the cursor at the top.  */
   SetConsoleCursorPosition (cur_screen, dest);
-  
+
 #ifdef USE_SEPARATE_SCREEN
   SetConsoleActiveScreenBuffer (prev_screen);
 #else
@@ -492,7 +552,7 @@ w32con_set_terminal_window (struct frame *f, int size)
  ***********************************************************************/
 
 void
-sys_tputs (char *str, int nlines, int (*outfun)())
+sys_tputs (char *str, int nlines, int (*outfun) (int))
 {
 }
 
@@ -511,13 +571,13 @@ struct tty_display_info *current_tty = NULL;
 int cost = 0;
 
 int
-evalcost (char c)
+evalcost (int c)
 {
   return c;
 }
 
 int
-cmputc (char c)
+cmputc (int c)
 {
   return c;
 }
@@ -551,9 +611,7 @@ Wcm_clear (struct tty_display_info *tty)
 /* 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;
+w32_face_attributes (struct frame *f, int face_id)
 {
   WORD char_attr;
   struct face *face = FACE_FROM_ID (f, face_id);
@@ -587,50 +645,27 @@ w32_face_attributes (f, face_id)
   return char_attr;
 }
 
-
-
-/* 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
 initialize_w32_display (struct terminal *term)
 {
   CONSOLE_SCREEN_BUFFER_INFO   info;
+  Mouse_HLInfo *hlinfo;
 
   term->rif = 0; /* No window based redisplay on the console.  */
   term->cursor_to_hook         = w32con_move_cursor;
-  term->raw_cursor_to_hook             = w32con_move_cursor;
-  term->clear_to_end_hook              = w32con_clear_to_end;
-  term->clear_frame_hook               = w32con_clear_frame;
+  term->raw_cursor_to_hook     = w32con_move_cursor;
+  term->clear_to_end_hook      = w32con_clear_to_end;
+  term->clear_frame_hook       = w32con_clear_frame;
   term->clear_end_of_line_hook = w32con_clear_end_of_line;
-  term->ins_del_lines_hook             = w32con_ins_del_lines;
-  term->insert_glyphs_hook             = w32con_insert_glyphs;
-  term->write_glyphs_hook              = w32con_write_glyphs;
-  term->delete_glyphs_hook             = w32con_delete_glyphs;
+  term->ins_del_lines_hook     = w32con_ins_del_lines;
+  term->insert_glyphs_hook     = w32con_insert_glyphs;
+  term->write_glyphs_hook      = w32con_write_glyphs;
+  term->delete_glyphs_hook     = w32con_delete_glyphs;
   term->ring_bell_hook         = w32_sys_ring_bell;
-  term->reset_terminal_modes_hook      = w32con_reset_terminal_modes;
+  term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
   term->set_terminal_modes_hook        = w32con_set_terminal_modes;
-  term->set_terminal_window_hook       = w32con_set_terminal_window;
-  term->update_begin_hook              = w32con_update_begin;
+  term->set_terminal_window_hook = w32con_set_terminal_window;
+  term->update_begin_hook      = w32con_update_begin;
   term->update_end_hook                = w32con_update_end;
 
   term->read_socket_hook = w32_console_read_socket;
@@ -645,6 +680,15 @@ initialize_w32_display (struct terminal *term)
   term->judge_scroll_bars_hook = 0;
   term->frame_up_to_date_hook = 0;
 
+  /* Initialize the mouse-highlight data.  */
+  hlinfo = &term->display_info.tty->mouse_highlight;
+  hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+  hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+  hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
+  hlinfo->mouse_face_mouse_frame = NULL;
+  hlinfo->mouse_face_window = Qnil;
+  hlinfo->mouse_face_hidden = 0;
+
   /* Initialize interrupt_handle.  */
   init_crit ();
 
@@ -674,8 +718,8 @@ initialize_w32_display (struct terminal *term)
 
   /* Respect setting of LINES and COLUMNS environment variables.  */
   {
-    char * lines = getenv("LINES");
-    char * columns = getenv("COLUMNS");
+    char * lines = getenv ("LINES");
+    char * columns = getenv ("COLUMNS");
 
     if (lines != NULL && columns != NULL)
       {
@@ -750,10 +794,10 @@ initialize_w32_display (struct terminal *term)
 
 
 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
-       doc: /* Set screen colors.  */)
-    (foreground, background)
-    Lisp_Object foreground;
-    Lisp_Object background;
+       doc: /* Set screen foreground and background colors.
+
+Arguments should be indices between 0 and 15, see w32console.el.  */)
+  (Lisp_Object foreground, Lisp_Object background)
 {
   char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
 
@@ -761,10 +805,21 @@ DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
   return Qt;
 }
 
+DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 0, 0,
+       doc: /* Get color indices of the current screen foreground and background.
+
+The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND).
+See w32console.el and `tty-defined-color-alist' for mapping of indices
+to colors.  */)
+  (void)
+{
+  return Fcons (make_number (char_attr_normal & 0x000f),
+               Fcons (make_number ((char_attr_normal >> 4) & 0x000f), Qnil));
+}
+
 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
        doc: /* Set cursor size.  */)
-    (size)
-    Lisp_Object size;
+  (Lisp_Object size)
 {
   CONSOLE_CURSOR_INFO cci;
   cci.dwSize = XFASTINT (size);
@@ -775,21 +830,19 @@ DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
 }
 
 void
-syms_of_ntterm ()
+syms_of_ntterm (void)
 {
   DEFVAR_BOOL ("w32-use-full-screen-buffer",
-               &w32_use_full_screen_buffer,
+               w32_use_full_screen_buffer,
               doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
 This is desirable when running Emacs over telnet.
 A value of nil means use the current console window dimensions; this
-may be preferrable when working directly at the console with a large
+may be preferable when working directly at the console with a large
 scroll-back buffer.  */);
   w32_use_full_screen_buffer = 0;
 
   defsubr (&Sset_screen_color);
+  defsubr (&Sget_screen_color);
   defsubr (&Sset_cursor_size);
   defsubr (&Sset_message_beep);
 }
-
-/* arch-tag: a390a07f-f661-42bc-aeb4-e6d8bf860337
-   (do not change this comment) */