root/src/w32console.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ctrl_c_handler
  2. w32con_move_cursor
  3. w32con_hide_cursor
  4. w32con_show_cursor
  5. w32con_clear_to_end
  6. w32con_clear_frame
  7. w32con_clear_end_of_line
  8. w32con_ins_del_lines
  9. scroll_line
  10. w32con_insert_glyphs
  11. w32con_write_glyphs
  12. w32con_write_glyphs_with_face
  13. tty_draw_row_with_mouse_face
  14. w32con_delete_glyphs
  15. w32con_reset_terminal_modes
  16. w32con_set_terminal_modes
  17. w32con_update_begin
  18. w32con_update_end
  19. sys_tputs
  20. sys_tgetstr
  21. evalcost
  22. cmputc
  23. cmcheckmagic
  24. cmcostinit
  25. cmgoto
  26. Wcm_clear
  27. cursorX
  28. cursorY
  29. w32_face_attributes
  30. initialize_w32_display
  31. DEFUN
  32. DEFUN
  33. syms_of_ntterm

     1 /* Terminal hooks for GNU Emacs on the Microsoft Windows API.
     2    Copyright (C) 1992, 1999, 2001-2023 Free Software Foundation, Inc.
     3 
     4 This file is part of GNU Emacs.
     5 
     6 GNU Emacs is free software: you can redistribute it and/or modify
     7 it under the terms of the GNU General Public License as published by
     8 the Free Software Foundation, either version 3 of the License, or (at
     9 your option) any later version.
    10 
    11 GNU Emacs is distributed in the hope that it will be useful,
    12 but WITHOUT ANY WARRANTY; without even the implied warranty of
    13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14 GNU General Public License for more details.
    15 
    16 You should have received a copy of the GNU General Public License
    17 along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
    18 
    19 /*
    20    Tim Fleehart (apollo@online.com)             1-17-92
    21    Geoff Voelker (voelker@cs.washington.edu)    9-12-93
    22 */
    23 
    24 
    25 #include <config.h>
    26 
    27 #include <stdio.h>
    28 #include <windows.h>
    29 
    30 #include "lisp.h"
    31 #include "coding.h"
    32 #include "termchar.h"   /* for FRAME_TTY */
    33 #include "dispextern.h" /* for tty_defined_color */
    34 #include "menu.h"       /* for tty_menu_show */
    35 #include "w32term.h"
    36 #include "w32common.h"  /* for os_subtype */
    37 #include "w32inevt.h"
    38 
    39 #ifdef WINDOWSNT
    40 #include "w32.h"        /* for syms_of_ntterm */
    41 #endif
    42 
    43 static void w32con_move_cursor (struct frame *f, int row, int col);
    44 static void w32con_clear_to_end (struct frame *f);
    45 static void w32con_clear_frame (struct frame *f);
    46 static void w32con_clear_end_of_line (struct frame *f, int);
    47 static void w32con_ins_del_lines (struct frame *f, int vpos, int n);
    48 static void w32con_insert_glyphs (struct frame *f, struct glyph *start, int len);
    49 static void w32con_write_glyphs (struct frame *f, struct glyph *string, int len);
    50 static void w32con_delete_glyphs (struct frame *f, int n);
    51 static void w32con_reset_terminal_modes (struct terminal *t);
    52 static void w32con_set_terminal_modes (struct terminal *t);
    53 static void w32con_update_begin (struct frame * f);
    54 static void w32con_update_end (struct frame * f);
    55 static WORD w32_face_attributes (struct frame *f, int face_id);
    56 
    57 static COORD    cursor_coords;
    58 static HANDLE   prev_screen, cur_screen;
    59 static WORD     char_attr_normal;
    60 static DWORD    prev_console_mode;
    61 
    62 static CONSOLE_CURSOR_INFO console_cursor_info;
    63 #ifndef USE_SEPARATE_SCREEN
    64 static CONSOLE_CURSOR_INFO prev_console_cursor;
    65 #endif
    66 
    67 HANDLE  keyboard_handle;
    68 int w32_console_unicode_input;
    69 
    70 
    71 /* Setting this as the ctrl handler prevents emacs from being killed when
    72    someone hits ^C in a 'suspended' session (child shell).
    73    Also ignore Ctrl-Break signals.  */
    74 
    75 BOOL ctrl_c_handler (unsigned long);
    76 
    77 BOOL
    78 ctrl_c_handler (unsigned long type)
    79 {
    80   /* Only ignore "interrupt" events when running interactively.  */
    81   return (!noninteractive
    82           && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
    83 }
    84 
    85 
    86 /* Move the cursor to (ROW, COL) on FRAME.  */
    87 static void
    88 w32con_move_cursor (struct frame *f, int row, int col)
    89 {
    90   cursor_coords.X = col;
    91   cursor_coords.Y = row;
    92 
    93   /* TODO: for multi-tty support, cur_screen should be replaced with a
    94      reference to the terminal for this frame.  */
    95   SetConsoleCursorPosition (cur_screen, cursor_coords);
    96 }
    97 
    98 void
    99 w32con_hide_cursor (void)
   100 {
   101   GetConsoleCursorInfo (cur_screen, &console_cursor_info);
   102   console_cursor_info.bVisible = FALSE;
   103   SetConsoleCursorInfo (cur_screen, &console_cursor_info);
   104 }
   105 
   106 void
   107 w32con_show_cursor (void)
   108 {
   109   GetConsoleCursorInfo (cur_screen, &console_cursor_info);
   110   console_cursor_info.bVisible = TRUE;
   111   SetConsoleCursorInfo (cur_screen, &console_cursor_info);
   112 }
   113 
   114 /* Clear from cursor to end of screen.  */
   115 static void
   116 w32con_clear_to_end (struct frame *f)
   117 {
   118   w32con_clear_end_of_line (f, FRAME_COLS (f) - 1);
   119   w32con_ins_del_lines (f, cursor_coords.Y, FRAME_TOTAL_LINES (f) - cursor_coords.Y - 1);
   120 }
   121 
   122 /* Clear the frame.  */
   123 static void
   124 w32con_clear_frame (struct frame *f)
   125 {
   126   COORD      dest;
   127   int        n;
   128   DWORD      r;
   129   CONSOLE_SCREEN_BUFFER_INFO info;
   130 
   131   GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
   132 
   133   /* Remember that the screen buffer might be wider than the window.  */
   134   n = FRAME_TOTAL_LINES (f) * info.dwSize.X;
   135   dest.X = dest.Y = 0;
   136 
   137   FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
   138   FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
   139 
   140   w32con_move_cursor (f, 0, 0);
   141 }
   142 
   143 
   144 static struct glyph glyph_base[80];
   145 static struct glyph *glyphs = glyph_base;
   146 static size_t glyphs_len = ARRAYELTS (glyph_base);
   147 static BOOL  ceol_initialized = FALSE;
   148 
   149 /* Clear from Cursor to end (what's "standout marker"?).  */
   150 static void
   151 w32con_clear_end_of_line (struct frame *f, int end)
   152 {
   153   /* Time to reallocate our "empty row"?  With today's large screens,
   154      it is not unthinkable to see TTY frames well in excess of
   155      80-character width.  */
   156   if (end - cursor_coords.X > glyphs_len)
   157     {
   158       if (glyphs == glyph_base)
   159         glyphs = NULL;
   160       glyphs = xrealloc (glyphs, FRAME_COLS (f) * sizeof (struct glyph));
   161       glyphs_len = FRAME_COLS (f);
   162       ceol_initialized = FALSE;
   163     }
   164   if (!ceol_initialized)
   165     {
   166       int i;
   167       for (i = 0; i < glyphs_len; i++)
   168         {
   169           memcpy (&glyphs[i], &space_glyph, sizeof (struct glyph));
   170         }
   171       ceol_initialized = TRUE;
   172     }
   173   w32con_write_glyphs (f, glyphs, end - cursor_coords.X);
   174 }
   175 
   176 /* Insert n lines at vpos. if n is negative delete -n lines.  */
   177 static void
   178 w32con_ins_del_lines (struct frame *f, int vpos, int n)
   179 {
   180   int        i, nb;
   181   SMALL_RECT scroll;
   182   SMALL_RECT clip;
   183   COORD      dest;
   184   CHAR_INFO  fill;
   185 
   186   if (n < 0)
   187     {
   188       scroll.Top = vpos - n;
   189       scroll.Bottom = FRAME_TOTAL_LINES (f);
   190       dest.Y = vpos;
   191     }
   192   else
   193     {
   194       scroll.Top = vpos;
   195       scroll.Bottom = FRAME_TOTAL_LINES (f) - n;
   196       dest.Y = vpos + n;
   197     }
   198   clip.Top = clip.Left = scroll.Left = 0;
   199   clip.Right = scroll.Right = FRAME_COLS (f);
   200   clip.Bottom = FRAME_TOTAL_LINES (f);
   201 
   202   dest.X = 0;
   203 
   204   fill.Char.AsciiChar = 0x20;
   205   fill.Attributes = char_attr_normal;
   206 
   207   ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
   208 
   209   /* Here we have to deal with a w32 console flake: If the scroll
   210      region looks like abc and we scroll c to a and fill with d we get
   211      cbd... if we scroll block c one line at a time to a, we get cdd...
   212      Emacs expects cdd consistently... So we have to deal with that
   213      here... (this also occurs scrolling the same way in the other
   214      direction.  */
   215 
   216   if (n > 0)
   217     {
   218       if (scroll.Bottom < dest.Y)
   219         {
   220           for (i = scroll.Bottom; i < dest.Y; i++)
   221             {
   222               w32con_move_cursor (f, i, 0);
   223               w32con_clear_end_of_line (f, FRAME_COLS (f));
   224             }
   225         }
   226     }
   227   else
   228     {
   229       nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
   230 
   231       if (nb < scroll.Top)
   232         {
   233           for (i = nb; i < scroll.Top; i++)
   234             {
   235               w32con_move_cursor (f, i, 0);
   236               w32con_clear_end_of_line (f, FRAME_COLS (f));
   237             }
   238         }
   239     }
   240 
   241   cursor_coords.X = 0;
   242   cursor_coords.Y = vpos;
   243 }
   244 
   245 #undef  LEFT
   246 #undef  RIGHT
   247 #define LEFT    1
   248 #define RIGHT   0
   249 
   250 static void
   251 scroll_line (struct frame *f, int dist, int direction)
   252 {
   253   /* The idea here is to implement a horizontal scroll in one line to
   254      implement delete and half of insert.  */
   255   SMALL_RECT scroll, clip;
   256   COORD      dest;
   257   CHAR_INFO  fill;
   258 
   259   clip.Top = scroll.Top = clip.Bottom = scroll.Bottom = cursor_coords.Y;
   260   clip.Left = 0;
   261   clip.Right = FRAME_COLS (f);
   262 
   263   if (direction == LEFT)
   264     {
   265       scroll.Left = cursor_coords.X + dist;
   266       scroll.Right = FRAME_COLS (f) - 1;
   267     }
   268   else
   269     {
   270       scroll.Left = cursor_coords.X;
   271       scroll.Right = FRAME_COLS (f) - dist - 1;
   272     }
   273 
   274   dest.X = cursor_coords.X;
   275   dest.Y = cursor_coords.Y;
   276 
   277   fill.Char.AsciiChar = 0x20;
   278   fill.Attributes = char_attr_normal;
   279 
   280   ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
   281 }
   282 
   283 
   284 /* If start is zero insert blanks instead of a string at start ?. */
   285 static void
   286 w32con_insert_glyphs (struct frame *f, register struct glyph *start,
   287                       register int len)
   288 {
   289   scroll_line (f, len, RIGHT);
   290 
   291   /* Move len chars to the right starting at cursor_coords, fill with blanks */
   292   if (start)
   293     {
   294       /* Print the first len characters of start, cursor_coords.X adjusted
   295          by write_glyphs.  */
   296 
   297       w32con_write_glyphs (f, start, len);
   298     }
   299   else
   300     {
   301       w32con_clear_end_of_line (f, cursor_coords.X + len);
   302     }
   303 }
   304 
   305 static void
   306 w32con_write_glyphs (struct frame *f, register struct glyph *string,
   307                      register int len)
   308 {
   309   DWORD r;
   310   WORD char_attr;
   311   LPCSTR conversion_buffer;
   312   struct coding_system *coding;
   313 
   314   if (len <= 0)
   315     return;
   316 
   317   /* If terminal_coding does any conversion, use it, otherwise use
   318      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
   319      because it always return 1 if the member src_multibyte is 1.  */
   320   coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
   321             ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
   322   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
   323      the tail.  */
   324   coding->mode &= ~CODING_MODE_LAST_BLOCK;
   325 
   326   while (len > 0)
   327     {
   328       /* Identify a run of glyphs with the same face.  */
   329       int face_id = string->face_id;
   330       int n;
   331 
   332       for (n = 1; n < len; ++n)
   333         if (string[n].face_id != face_id)
   334           break;
   335 
   336       /* Turn appearance modes of the face of the run on.  */
   337       char_attr = w32_face_attributes (f, face_id);
   338 
   339       if (n == len)
   340         /* This is the last run.  */
   341         coding->mode |= CODING_MODE_LAST_BLOCK;
   342       conversion_buffer = (LPCSTR) encode_terminal_code (string, n, coding);
   343       if (coding->produced > 0)
   344         {
   345           /* Set the attribute for these characters.  */
   346           if (!FillConsoleOutputAttribute (cur_screen, char_attr,
   347                                            coding->produced, cursor_coords,
   348                                            &r))
   349             {
   350               printf ("Failed writing console attributes: %lu\n",
   351                       GetLastError ());
   352               fflush (stdout);
   353             }
   354 
   355           /* Write the characters.  */
   356           if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
   357                                             coding->produced, cursor_coords,
   358                                             &r))
   359             {
   360               printf ("Failed writing console characters: %lu\n",
   361                       GetLastError ());
   362               fflush (stdout);
   363             }
   364 
   365           cursor_coords.X += coding->produced;
   366           w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
   367         }
   368       len -= n;
   369       string += n;
   370     }
   371 }
   372 
   373 /* Used for mouse highlight.  */
   374 static void
   375 w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
   376                                register struct glyph *string, register int len,
   377                                register int face_id)
   378 {
   379   LPCSTR conversion_buffer;
   380   struct coding_system *coding;
   381 
   382   if (len <= 0)
   383     return;
   384 
   385   /* If terminal_coding does any conversion, use it, otherwise use
   386      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
   387      because it always return 1 if the member src_multibyte is 1.  */
   388   coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
   389             ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
   390   /* We are going to write the entire block of glyphs in one go, as
   391      they all have the same face.  So this _is_ the last block.  */
   392   coding->mode |= CODING_MODE_LAST_BLOCK;
   393 
   394   conversion_buffer = (LPCSTR) encode_terminal_code (string, len, coding);
   395   if (coding->produced > 0)
   396     {
   397       DWORD filled, written;
   398       /* Compute the character attributes corresponding to the face.  */
   399       DWORD char_attr = w32_face_attributes (f, face_id);
   400       COORD start_coords;
   401 
   402       start_coords.X = x;
   403       start_coords.Y = y;
   404       /* Set the attribute for these characters.  */
   405       if (!FillConsoleOutputAttribute (cur_screen, char_attr,
   406                                        coding->produced, start_coords,
   407                                        &filled))
   408         DebPrint (("Failed writing console attributes: %d\n", GetLastError ()));
   409       else
   410         {
   411           /* Write the characters.  */
   412           if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
   413                                             filled, start_coords, &written))
   414             DebPrint (("Failed writing console characters: %d\n",
   415                        GetLastError ()));
   416         }
   417     }
   418 }
   419 
   420 /* Implementation of draw_row_with_mouse_face for W32 console.  */
   421 void
   422 tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
   423                               int start_hpos, int end_hpos,
   424                               enum draw_glyphs_face draw)
   425 {
   426   int nglyphs = end_hpos - start_hpos;
   427   struct frame *f = XFRAME (WINDOW_FRAME (w));
   428   struct tty_display_info *tty = FRAME_TTY (f);
   429   int face_id = tty->mouse_highlight.mouse_face_face_id;
   430   int pos_x, pos_y;
   431 
   432   if (end_hpos >= row->used[TEXT_AREA])
   433     nglyphs = row->used[TEXT_AREA] - start_hpos;
   434 
   435   pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
   436   pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
   437 
   438   if (draw == DRAW_MOUSE_FACE)
   439     w32con_write_glyphs_with_face (f, pos_x, pos_y,
   440                                    row->glyphs[TEXT_AREA] + start_hpos,
   441                                    nglyphs, face_id);
   442   else if (draw == DRAW_NORMAL_TEXT)
   443     {
   444       COORD save_coords = cursor_coords;
   445 
   446       w32con_move_cursor (f, pos_y, pos_x);
   447       write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
   448       w32con_move_cursor (f, save_coords.Y, save_coords.X);
   449     }
   450 }
   451 
   452 static void
   453 w32con_delete_glyphs (struct frame *f, int n)
   454 {
   455   /* delete chars means scroll chars from cursor_coords.X + n to
   456      cursor_coords.X, anything beyond the edge of the screen should
   457      come out empty...  */
   458 
   459   scroll_line (f, n, LEFT);
   460 }
   461 
   462 
   463 static void
   464 w32con_reset_terminal_modes (struct terminal *t)
   465 {
   466   COORD dest;
   467   CONSOLE_SCREEN_BUFFER_INFO info;
   468   int n;
   469   DWORD r;
   470 
   471   /* Clear the complete screen buffer.  This is required because Emacs
   472      sets the cursor position to the top of the buffer, but there might
   473      be other output below the bottom of the Emacs frame if the screen buffer
   474      is larger than the window size.  */
   475   GetConsoleScreenBufferInfo (cur_screen, &info);
   476   dest.X = 0;
   477   dest.Y = 0;
   478   n = info.dwSize.X * info.dwSize.Y;
   479 
   480   FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
   481   FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
   482   /* Now that the screen is clear, put the cursor at the top.  */
   483   SetConsoleCursorPosition (cur_screen, dest);
   484 
   485 #ifdef USE_SEPARATE_SCREEN
   486   SetConsoleActiveScreenBuffer (prev_screen);
   487 #else
   488   SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
   489 #endif
   490 
   491   SetConsoleMode (keyboard_handle, prev_console_mode);
   492 }
   493 
   494 static void
   495 w32con_set_terminal_modes (struct terminal *t)
   496 {
   497   CONSOLE_CURSOR_INFO cci;
   498 
   499   /* make cursor big and visible (100 on Windows 95 makes it disappear)  */
   500   cci.dwSize = 99;
   501   cci.bVisible = TRUE;
   502   (void) SetConsoleCursorInfo (cur_screen, &cci);
   503 
   504   SetConsoleActiveScreenBuffer (cur_screen);
   505 
   506   /* If Quick Edit is enabled for the console, it will get in the way
   507      of receiving mouse events, so we disable it.  But leave the
   508      Insert Mode as it was set by the user.  */
   509   DWORD new_console_mode
   510     = ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT | ENABLE_EXTENDED_FLAGS;
   511   if ((prev_console_mode & ENABLE_INSERT_MODE) != 0)
   512     new_console_mode |= ENABLE_INSERT_MODE;
   513   SetConsoleMode (keyboard_handle, new_console_mode);
   514 
   515   /* Initialize input mode: interrupt_input off, no flow control, allow
   516      8 bit character input, standard quit char.  */
   517   Fset_input_mode (Qnil, Qnil, make_fixnum (2), Qnil);
   518 }
   519 
   520 /* hmmm... perhaps these let us bracket screen changes so that we can flush
   521    clumps rather than one-character-at-a-time...
   522 
   523    we'll start with not moving the cursor while an update is in progress.  */
   524 static void
   525 w32con_update_begin (struct frame * f)
   526 {
   527 }
   528 
   529 static void
   530 w32con_update_end (struct frame * f)
   531 {
   532   SetConsoleCursorPosition (cur_screen, cursor_coords);
   533 }
   534 
   535 /***********************************************************************
   536                         stubs from termcap.c
   537  ***********************************************************************/
   538 
   539 void sys_tputs (char *, int, int (*) (int));
   540 
   541 void
   542 sys_tputs (char *str, int nlines, int (*outfun) (int))
   543 {
   544 }
   545 
   546 char *sys_tgetstr (char *, char **);
   547 
   548 char *
   549 sys_tgetstr (char *cap, char **area)
   550 {
   551   return NULL;
   552 }
   553 
   554 
   555 /***********************************************************************
   556                         stubs from cm.c
   557  ***********************************************************************/
   558 
   559 struct tty_display_info *current_tty = NULL;
   560 int cost = 0;
   561 
   562 int evalcost (int);
   563 
   564 int
   565 evalcost (int c)
   566 {
   567   return c;
   568 }
   569 
   570 int cmputc (int);
   571 
   572 int
   573 cmputc (int c)
   574 {
   575   return c;
   576 }
   577 
   578 void cmcheckmagic (struct tty_display_info *);
   579 
   580 void
   581 cmcheckmagic (struct tty_display_info *tty)
   582 {
   583 }
   584 
   585 void cmcostinit (struct tty_display_info *);
   586 
   587 void
   588 cmcostinit (struct tty_display_info *tty)
   589 {
   590 }
   591 
   592 void cmgoto (struct tty_display_info *, int, int);
   593 
   594 void
   595 cmgoto (struct tty_display_info *tty, int row, int col)
   596 {
   597 }
   598 
   599 void Wcm_clear (struct tty_display_info *);
   600 
   601 void
   602 Wcm_clear (struct tty_display_info *tty)
   603 {
   604 }
   605 
   606 
   607 /* Report the current cursor position.  The following two functions
   608    are used in term.c's tty menu code, so they are not really
   609    "stubs".  */
   610 int
   611 cursorX (struct tty_display_info *tty)
   612 {
   613   return cursor_coords.X;
   614 }
   615 
   616 int
   617 cursorY (struct tty_display_info *tty)
   618 {
   619   return cursor_coords.Y;
   620 }
   621 
   622 /***********************************************************************
   623                                 Faces
   624  ***********************************************************************/
   625 
   626 
   627 /* Turn appearances of face FACE_ID on tty frame F on.  */
   628 
   629 static WORD
   630 w32_face_attributes (struct frame *f, int face_id)
   631 {
   632   WORD char_attr;
   633   struct face *face = FACE_FROM_ID (f, face_id);
   634 
   635   char_attr = char_attr_normal;
   636 
   637   /* Reverse the default color if requested. If background and
   638      foreground are specified, then they have been reversed already.  */
   639   if (face->tty_reverse_p)
   640     char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
   641       + ((char_attr & 0x00f0) >> 4);
   642 
   643   /* Before the terminal is properly initialized, all colors map to 0.
   644      Don't try to resolve them.  */
   645   if (NILP (Vtty_defined_color_alist))
   646     return char_attr;
   647 
   648   /* Colors should be in the range 0...15 unless they are one of
   649      FACE_TTY_DEFAULT_COLOR, FACE_TTY_DEFAULT_FG_COLOR or
   650      FACE_TTY_DEFAULT_BG_COLOR.  Other out of range colors are
   651      invalid, so it is better to use the default color if they ever
   652      get through to here.  */
   653   if (face->foreground >= 0 && face->foreground < 16)
   654     char_attr = (char_attr & 0xfff0) + face->foreground;
   655 
   656   if (face->background >= 0 && face->background < 16)
   657     char_attr = (char_attr & 0xff0f) + (face->background << 4);
   658 
   659   return char_attr;
   660 }
   661 
   662 void
   663 initialize_w32_display (struct terminal *term, int *width, int *height)
   664 {
   665   CONSOLE_SCREEN_BUFFER_INFO    info;
   666 
   667   term->rif = 0; /* No window based redisplay on the console.  */
   668   term->cursor_to_hook          = w32con_move_cursor;
   669   term->raw_cursor_to_hook      = w32con_move_cursor;
   670   term->clear_to_end_hook       = w32con_clear_to_end;
   671   term->clear_frame_hook        = w32con_clear_frame;
   672   term->clear_end_of_line_hook  = w32con_clear_end_of_line;
   673   term->ins_del_lines_hook      = w32con_ins_del_lines;
   674   term->insert_glyphs_hook      = w32con_insert_glyphs;
   675   term->write_glyphs_hook       = w32con_write_glyphs;
   676   term->delete_glyphs_hook      = w32con_delete_glyphs;
   677   term->ring_bell_hook          = w32_sys_ring_bell;
   678   term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
   679   term->set_terminal_modes_hook = w32con_set_terminal_modes;
   680   term->set_terminal_window_hook = NULL;
   681   term->update_begin_hook       = w32con_update_begin;
   682   term->update_end_hook         = w32con_update_end;
   683 
   684   term->defined_color_hook = &tty_defined_color; /* xfaces.c */
   685   term->read_socket_hook = w32_console_read_socket;
   686   term->mouse_position_hook = w32_console_mouse_position;
   687   term->menu_show_hook = tty_menu_show;
   688 
   689   /* The following are not used on the console.  */
   690   term->frame_rehighlight_hook = 0;
   691   term->frame_raise_lower_hook = 0;
   692   term->set_vertical_scroll_bar_hook = 0;
   693   term->set_horizontal_scroll_bar_hook = 0;
   694   term->condemn_scroll_bars_hook = 0;
   695   term->redeem_scroll_bar_hook = 0;
   696   term->judge_scroll_bars_hook = 0;
   697   term->frame_up_to_date_hook = 0;
   698 
   699   /* Initialize the mouse-highlight data.  */
   700   reset_mouse_highlight (&term->display_info.tty->mouse_highlight);
   701 
   702   /* Initialize interrupt_handle.  */
   703   init_crit ();
   704 
   705   /* Remember original console settings.  */
   706   keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
   707   GetConsoleMode (keyboard_handle, &prev_console_mode);
   708 
   709   prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
   710 
   711 #ifdef USE_SEPARATE_SCREEN
   712   cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
   713                                           0, NULL,
   714                                           CONSOLE_TEXTMODE_BUFFER,
   715                                           NULL);
   716 
   717   if (cur_screen == INVALID_HANDLE_VALUE)
   718     {
   719       printf ("CreateConsoleScreenBuffer failed in initialize_w32_display\n");
   720       printf ("LastError = 0x%lx\n", GetLastError ());
   721       fflush (stdout);
   722       exit (1);
   723     }
   724 #else
   725   cur_screen = prev_screen;
   726   GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
   727 #endif
   728 
   729   /* Respect setting of LINES and COLUMNS environment variables.  */
   730   {
   731     char * lines = getenv ("LINES");
   732     char * columns = getenv ("COLUMNS");
   733 
   734     if (lines != NULL && columns != NULL)
   735       {
   736         SMALL_RECT new_win_dims;
   737         COORD new_size;
   738 
   739         new_size.X = atoi (columns);
   740         new_size.Y = atoi (lines);
   741 
   742         GetConsoleScreenBufferInfo (cur_screen, &info);
   743 
   744         /* Shrink the window first, so the buffer dimensions can be
   745            reduced if necessary.  */
   746         new_win_dims.Top = 0;
   747         new_win_dims.Left = 0;
   748         new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
   749         new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
   750         SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
   751 
   752         SetConsoleScreenBufferSize (cur_screen, new_size);
   753 
   754         /* Set the window size to match the buffer dimension.  */
   755         new_win_dims.Top = 0;
   756         new_win_dims.Left = 0;
   757         new_win_dims.Bottom = new_size.Y - 1;
   758         new_win_dims.Right = new_size.X - 1;
   759         SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
   760       }
   761   }
   762 
   763   if (!GetConsoleScreenBufferInfo (cur_screen, &info))
   764     {
   765       printf ("GetConsoleScreenBufferInfo failed in initialize_w32_display\n");
   766       printf ("LastError = 0x%lx\n", GetLastError ());
   767       fflush (stdout);
   768       exit (1);
   769     }
   770 
   771   char_attr_normal = info.wAttributes;
   772 
   773   /* Determine if the info returned by GetConsoleScreenBufferInfo
   774      is realistic.  Old MS Telnet servers used to only fill out
   775      the dwSize portion, even modern one fill the whole struct with
   776      garbage when using non-MS telnet clients.  */
   777   if ((w32_use_full_screen_buffer
   778        && (info.dwSize.Y < 20 || info.dwSize.Y > 100
   779            || info.dwSize.X < 40 || info.dwSize.X > 200))
   780       || (!w32_use_full_screen_buffer
   781           && (info.srWindow.Bottom - info.srWindow.Top < 20
   782               || info.srWindow.Bottom - info.srWindow.Top > 100
   783               || info.srWindow.Right - info.srWindow.Left < 40
   784               || info.srWindow.Right - info.srWindow.Left > 100)))
   785     {
   786       *height = 25;
   787       *width = 80;
   788     }
   789 
   790   else if (w32_use_full_screen_buffer)
   791     {
   792       *height = info.dwSize.Y;  /* lines per page */
   793       *width = info.dwSize.X;   /* characters per line */
   794     }
   795   else
   796     {
   797       /* Lines per page.  Use buffer coords instead of buffer size.  */
   798       *height = 1 + info.srWindow.Bottom - info.srWindow.Top;
   799       /* Characters per line.  Use buffer coords instead of buffer size.  */
   800       *width = 1 + info.srWindow.Right - info.srWindow.Left;
   801     }
   802 
   803   /* Force reinitialization of the "empty row" buffer, in case they
   804      dumped from a running session.  */
   805   if (glyphs != glyph_base)
   806     {
   807       glyphs = NULL;
   808       glyphs_len = 0;
   809       ceol_initialized = FALSE;
   810     }
   811 
   812   if (os_subtype == OS_SUBTYPE_NT)
   813     w32_console_unicode_input = 1;
   814   else
   815     w32_console_unicode_input = 0;
   816 
   817   /* Setup w32_display_info structure for this frame. */
   818   w32_initialize_display_info (build_string ("Console"));
   819 
   820   /* Set up the keyboard hook.  */
   821   setup_w32_kbdhook ();
   822 }
   823 
   824 
   825 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
   826        doc: /* Set screen foreground and background colors.
   827 
   828 Arguments should be indices between 0 and 15, see w32console.el.  */)
   829   (Lisp_Object foreground, Lisp_Object background)
   830 {
   831   char_attr_normal = XFIXNAT (foreground) + (XFIXNAT (background) << 4);
   832 
   833   Frecenter (Qnil, Qt);
   834   return Qt;
   835 }
   836 
   837 DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 0, 0,
   838        doc: /* Get color indices of the current screen foreground and background.
   839 
   840 The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND).
   841 See w32console.el and `tty-defined-color-alist' for mapping of indices
   842 to colors.  */)
   843   (void)
   844 {
   845   return Fcons (make_fixnum (char_attr_normal & 0x000f),
   846                 Fcons (make_fixnum ((char_attr_normal >> 4) & 0x000f), Qnil));
   847 }
   848 
   849 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
   850        doc: /* Set cursor size.  */)
   851   (Lisp_Object size)
   852 {
   853   CONSOLE_CURSOR_INFO cci;
   854   cci.dwSize = XFIXNAT (size);
   855   cci.bVisible = TRUE;
   856   (void) SetConsoleCursorInfo (cur_screen, &cci);
   857 
   858   return Qt;
   859 }
   860 
   861 void
   862 syms_of_ntterm (void)
   863 {
   864   DEFVAR_BOOL ("w32-use-full-screen-buffer",
   865                w32_use_full_screen_buffer,
   866                doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
   867 This is desirable when running Emacs over telnet.
   868 A value of nil means use the current console window dimensions; this
   869 may be preferable when working directly at the console with a large
   870 scroll-back buffer.  */);
   871   w32_use_full_screen_buffer = 0;
   872 
   873   defsubr (&Sset_screen_color);
   874   defsubr (&Sget_screen_color);
   875   defsubr (&Sset_cursor_size);
   876 }

/* [<][>][^][v][top][bottom][index][help] */