w32console.c 19.8 KB
Newer Older
1
/* Terminal hooks for GNU Emacs on the Microsoft W32 API.
2
   Copyright (C) 1992, 1999 Free Software Foundation, Inc.
Richard M. Stallman's avatar
Richard M. Stallman committed
3

4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
This file is part of GNU Emacs.

GNU Emacs is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING.  If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Richard M. Stallman's avatar
Richard M. Stallman committed
20 21 22 23 24 25

   Tim Fleehart (apollo@online.com)		1-17-92
   Geoff Voelker (voelker@cs.washington.edu)	9-12-93
*/


26 27
#include <config.h>

Richard M. Stallman's avatar
Richard M. Stallman committed
28 29 30
#include <stdlib.h>
#include <stdio.h>
#include <windows.h>
31
#include <string.h>
Richard M. Stallman's avatar
Richard M. Stallman committed
32 33

#include "lisp.h"
Geoff Voelker's avatar
Geoff Voelker committed
34
#include "charset.h"
35
#include "coding.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
36 37
#include "disptab.h"
#include "termhooks.h"
38 39
#include "dispextern.h"
/* Disable features in frame.h that require a Window System.  */
40 41
#undef HAVE_WINDOW_SYSTEM
#include "frame.h"
Geoff Voelker's avatar
Geoff Voelker committed
42
#include "w32inevt.h"
Richard M. Stallman's avatar
Richard M. Stallman committed
43

Karl Heuer's avatar
Karl Heuer committed
44
/* from window.c */
Richard M. Stallman's avatar
Richard M. Stallman committed
45 46 47 48 49 50 51 52
extern Lisp_Object Frecenter ();

/* from keyboard.c */
extern int detect_input_pending ();

/* from sysdep.c */
extern int read_input_pending ();

53
extern struct frame * updating_frame;
Richard M. Stallman's avatar
Richard M. Stallman committed
54 55 56 57 58 59 60
extern int meta_key;

static void move_cursor (int row, int col);
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);
61 62
static void insert_glyphs (struct glyph *start, int len);
static void write_glyphs (struct glyph *string, int len);
Richard M. Stallman's avatar
Richard M. Stallman committed
63
static void delete_glyphs (int n);
64
void w32_sys_ring_bell (void);
Richard M. Stallman's avatar
Richard M. Stallman committed
65 66 67
static void reset_terminal_modes (void);
static void set_terminal_modes (void);
static void set_terminal_window (int size);
68 69
static void update_begin (struct frame * f);
static void update_end (struct frame * f);
70
static WORD w32_face_attributes (struct frame *f, int face_id);
Richard M. Stallman's avatar
Richard M. Stallman committed
71

72 73 74 75
static COORD	cursor_coords;
static HANDLE	prev_screen, cur_screen;
static WORD	char_attr_normal;
static DWORD   prev_console_mode;
Richard M. Stallman's avatar
Richard M. Stallman committed
76

77
#ifndef USE_SEPARATE_SCREEN
78
static CONSOLE_CURSOR_INFO prev_console_cursor;
79 80
#endif

81 82 83 84 85
/* 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;
86
HANDLE  keyboard_handle;
87

Richard M. Stallman's avatar
Richard M. Stallman committed
88 89

/* Setting this as the ctrl handler prevents emacs from being killed when
90 91 92
   someone hits ^C in a 'suspended' session (child shell).
   Also ignore Ctrl-Break signals.  */

Richard M. Stallman's avatar
Richard M. Stallman committed
93 94 95
BOOL
ctrl_c_handler (unsigned long type)
{
96 97 98
  /* Only ignore "interrupt" events when running interactively.  */
  return (!noninteractive
	  && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
Richard M. Stallman's avatar
Richard M. Stallman committed
99 100 101 102
}

/* If we're updating a frame, use it as the current frame
   Otherwise, use the selected frame.  */
103
#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
Richard M. Stallman's avatar
Richard M. Stallman committed
104 105 106 107 108 109 110 111

/* Move the cursor to (row, col).  */
void
move_cursor (int row, int col)
{
  cursor_coords.X = col;
  cursor_coords.Y = row;
  
112
  if (updating_frame == (struct frame *) NULL)
Richard M. Stallman's avatar
Richard M. Stallman committed
113 114 115 116 117 118 119 120 121
    {
      SetConsoleCursorPosition (cur_screen, cursor_coords);
    }
}

/* Clear from cursor to end of screen.  */
void
clear_to_end (void)
{
122
  struct frame * f = PICK_FRAME ();
Richard M. Stallman's avatar
Richard M. Stallman committed
123 124 125 126 127 128 129 130 131
  
  clear_end_of_line (FRAME_WIDTH (f) - 1);
  ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
}

/* Clear the frame.  */
void
clear_frame (void)
{
132
  struct frame *  f = PICK_FRAME ();
133
  COORD	     dest;
Andrew Innes's avatar
Andrew Innes committed
134 135
  int        n;
  DWORD      r;
136 137 138
  CONSOLE_SCREEN_BUFFER_INFO info;

  GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
139

140 141
  /* Remember that the screen buffer might be wider than the window.  */
  n = FRAME_HEIGHT (f) * info.dwSize.X;
142 143
  dest.X = dest.Y = 0;

144
  FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
145 146
  FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);

Richard M. Stallman's avatar
Richard M. Stallman committed
147 148 149 150
  move_cursor (0, 0);
}


151
static struct glyph glyph_base[256];
Richard M. Stallman's avatar
Richard M. Stallman committed
152 153 154 155 156 157 158 159 160 161 162
static BOOL  ceol_initialized = FALSE;

/* Clear from Cursor to end (what's "standout marker"?).  */
void
clear_end_of_line (int end)
{
  if (!ceol_initialized)
    {
      int i;
      for (i = 0; i < 256; i++)
        {
163
	  memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
Richard M. Stallman's avatar
Richard M. Stallman committed
164 165 166 167 168 169 170 171 172 173
        }
      ceol_initialized = TRUE;
    }
  write_glyphs (glyph_base, end - cursor_coords.X);	/* fencepost ?	*/
}

/* Insert n lines at vpos. if n is negative delete -n lines.  */
void
ins_del_lines (int vpos, int n)
{
174
  int	     i, nb;
Richard M. Stallman's avatar
Richard M. Stallman committed
175 176 177
  SMALL_RECT scroll;
  COORD	     dest;
  CHAR_INFO  fill;
178
  struct frame *  f = PICK_FRAME ();
Richard M. Stallman's avatar
Richard M. Stallman committed
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197

  if (n < 0)
    {
      scroll.Top = vpos - n;
      scroll.Bottom = FRAME_HEIGHT (f);
      dest.Y = vpos;
    }
  else
    {
      scroll.Top = vpos;
      scroll.Bottom = FRAME_HEIGHT (f) - n;
      dest.Y = vpos + n;
    }
  scroll.Left = 0;
  scroll.Right = FRAME_WIDTH (f);
  
  dest.X = 0;
  
  fill.Char.AsciiChar = 0x20;
198
  fill.Attributes = char_attr_normal;
Richard M. Stallman's avatar
Richard M. Stallman committed
199 200 201
  
  ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);

202
  /* Here we have to deal with a w32 console flake: If the scroll
Richard M. Stallman's avatar
Richard M. Stallman committed
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
     region looks like abc and we scroll c to a and fill with d we get
     cbd... if we scroll block c one line at a time to a, we get cdd...
     Emacs expects cdd consistently... So we have to deal with that
     here... (this also occurs scrolling the same way in the other
     direction.  */

  if (n > 0)
    {
      if (scroll.Bottom < dest.Y)
        {
	  for (i = scroll.Bottom; i < dest.Y; i++)
            {
	      move_cursor (i, 0);
	      clear_end_of_line (FRAME_WIDTH (f));
            }
        }
    }
  else
    {
      nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;

      if (nb < scroll.Top)
        { 
	  for (i = nb; i < scroll.Top; i++)
            {
	      move_cursor (i, 0);
	      clear_end_of_line (FRAME_WIDTH (f));
            }
        }
    }
  
  cursor_coords.X = 0;
  cursor_coords.Y = vpos;
}

#undef	LEFT
#undef	RIGHT
#define	LEFT	1
#define	RIGHT	0

void
scroll_line (int dist, int direction)
{
  /* The idea here is to implement a horizontal scroll in one line to
     implement delete and half of insert.  */
  SMALL_RECT scroll;
  COORD	     dest;
  CHAR_INFO  fill;
251
  struct frame *  f = PICK_FRAME ();
Richard M. Stallman's avatar
Richard M. Stallman committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  
  scroll.Top = cursor_coords.Y;
  scroll.Bottom = cursor_coords.Y;
  
  if (direction == LEFT)
    {
      scroll.Left = cursor_coords.X + dist;
      scroll.Right = FRAME_WIDTH (f) - 1;
    }
  else
    {
      scroll.Left = cursor_coords.X;
      scroll.Right = FRAME_WIDTH (f) - dist - 1;
    }
  
  dest.X = cursor_coords.X;
  dest.Y = cursor_coords.Y;
  
  fill.Char.AsciiChar = 0x20;
271 272
  fill.Attributes = char_attr_normal;

Richard M. Stallman's avatar
Richard M. Stallman committed
273 274 275 276 277 278
  ScrollConsoleScreenBuffer (cur_screen, &scroll, NULL, dest, &fill);
}


/* If start is zero insert blanks instead of a string at start ?. */
void
279
insert_glyphs (register struct glyph *start, register int len)
Richard M. Stallman's avatar
Richard M. Stallman committed
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
{
  scroll_line (len, RIGHT);

  /* Move len chars to the right starting at cursor_coords, fill with blanks */
  if (start)
    {
      /* Print the first len characters of start, cursor_coords.X adjusted
	 by write_glyphs.  */
	
      write_glyphs (start, len);
    }
  else
    {
      clear_end_of_line (cursor_coords.X + len);
    }
}

void
298
write_glyphs (register struct glyph *string, register int len)
Richard M. Stallman's avatar
Richard M. Stallman committed
299
{
Andrew Innes's avatar
Andrew Innes committed
300 301
  int produced, consumed;
  DWORD r;
302
  struct frame * f = PICK_FRAME ();
303
  WORD char_attr;
304 305
  unsigned char conversion_buffer[1024];
  int conversion_buffer_size = sizeof conversion_buffer;
306 307 308

  if (len <= 0)
    return;
309

310 311 312
  /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
     the tail.  */
  terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
Richard M. Stallman's avatar
Richard M. Stallman committed
313

314
  while (len > 0)
Richard M. Stallman's avatar
Richard M. Stallman committed
315
    {
316 317 318 319 320 321 322 323 324
      /* 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.  */
325
      char_attr = w32_face_attributes (f, face_id);
326 327 328

      while (n > 0)
        {
329 330 331
	  /* We use a fixed size (1024 bytes) of conversion buffer.
	     Usually it is sufficient, but if not, we just repeat the
	     loop.  */
332 333 334 335 336 337 338
	  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,
Andrew Innes's avatar
Andrew Innes committed
339
                                               produced, cursor_coords, &r)) 
340 341 342 343 344 345 346 347
                {
                  printf ("Failed writing console attributes: %d\n",
                          GetLastError ());
                  fflush (stdout);
                }

              /* Write the characters.  */
              if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
Andrew Innes's avatar
Andrew Innes committed
348
                                                produced, cursor_coords, &r))
349 350 351 352 353 354 355 356 357 358 359 360 361
                {
                  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;
        }
Richard M. Stallman's avatar
Richard M. Stallman committed
362 363
    }

364 365
  /* We may have to output some codes to terminate the writing.  */
  if (CODING_REQUIRE_FLUSHING (&terminal_coding))
Richard M. Stallman's avatar
Richard M. Stallman committed
366
    {
367 368 369 370 371
      terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
      encode_coding (&terminal_coding, "", conversion_buffer,
		     0, conversion_buffer_size);
      if (terminal_coding.produced > 0)
        {
372
          if (!FillConsoleOutputAttribute (cur_screen, char_attr_normal,
373
                                           terminal_coding.produced,
Andrew Innes's avatar
Andrew Innes committed
374
                                           cursor_coords, &r)) 
375 376 377 378 379 380 381 382
            {
              printf ("Failed writing console attributes: %d\n",
                      GetLastError ());
              fflush (stdout);
            }

          /* Write the characters.  */
          if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
Andrew Innes's avatar
Andrew Innes committed
383
                                            produced, cursor_coords, &r))
384 385 386 387 388 389
            {
              printf ("Failed writing console characters: %d\n",
                      GetLastError ());
              fflush (stdout);
            }
        }
Richard M. Stallman's avatar
Richard M. Stallman committed
390 391 392
    }
}

393

Richard M. Stallman's avatar
Richard M. Stallman committed
394 395 396 397 398 399 400 401 402 403
void
delete_glyphs (int n)
{
  /* delete chars means scroll chars from cursor_coords.X + n to 
     cursor_coords.X, anything beyond the edge of the screen should 
     come out empty...  */

  scroll_line (n, LEFT);
}

Karl Heuer's avatar
Karl Heuer committed
404
static unsigned int sound_type = 0xFFFFFFFF;
405
#define MB_EMACS_SILENT (0xFFFFFFFF - 1)
Karl Heuer's avatar
Karl Heuer committed
406

Richard M. Stallman's avatar
Richard M. Stallman committed
407
void
408
w32_sys_ring_bell (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
409
{
Karl Heuer's avatar
Karl Heuer committed
410
  if (sound_type == 0xFFFFFFFF) 
411
    {
Karl Heuer's avatar
Karl Heuer committed
412
      Beep (666, 100);
413 414 415 416 417
    }
  else if (sound_type == MB_EMACS_SILENT)
    {
      /* Do nothing.  */
    }
Karl Heuer's avatar
Karl Heuer committed
418
  else
419
    MessageBeep (sound_type);
Richard M. Stallman's avatar
Richard M. Stallman committed
420 421
}

Karl Heuer's avatar
Karl Heuer committed
422
DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
423 424 425 426 427
       doc: /* Set the sound generated when the bell is rung.
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.  */)
Karl Heuer's avatar
Karl Heuer committed
428 429
     (sound)
     Lisp_Object sound;
Richard M. Stallman's avatar
Richard M. Stallman committed
430
{
431
  CHECK_SYMBOL (sound);
Karl Heuer's avatar
Karl Heuer committed
432 433 434 435 436 437 438 439 440 441 442 443 444

  if (NILP (sound)) 
      sound_type = 0xFFFFFFFF;
  else if (EQ (sound, intern ("asterisk")))
      sound_type = MB_ICONASTERISK;
  else if (EQ (sound, intern ("exclamation"))) 
      sound_type = MB_ICONEXCLAMATION;
  else if (EQ (sound, intern ("hand"))) 
      sound_type = MB_ICONHAND;
  else if (EQ (sound, intern ("question"))) 
      sound_type = MB_ICONQUESTION;
  else if (EQ (sound, intern ("ok"))) 
      sound_type = MB_OK;
445 446
  else if (EQ (sound, intern ("silent")))
      sound_type = MB_EMACS_SILENT;
Karl Heuer's avatar
Karl Heuer committed
447 448 449 450
  else
      sound_type = 0xFFFFFFFF;

  return sound;
Richard M. Stallman's avatar
Richard M. Stallman committed
451 452 453 454 455
}
   
void
reset_terminal_modes (void)
{
456
#ifdef USE_SEPARATE_SCREEN
Richard M. Stallman's avatar
Richard M. Stallman committed
457
  SetConsoleActiveScreenBuffer (prev_screen);
458 459 460 461
#else
  SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
#endif
  SetConsoleMode (keyboard_handle, prev_console_mode);
Richard M. Stallman's avatar
Richard M. Stallman committed
462 463 464 465 466 467 468
}

void
set_terminal_modes (void)
{
  CONSOLE_CURSOR_INFO cci;

469 470 471 472
  /* make cursor big and visible (100 on Win95 makes it disappear)  */
  cci.dwSize = 99;
  cci.bVisible = TRUE;
  (void) SetConsoleCursorInfo (cur_screen, &cci);
Richard M. Stallman's avatar
Richard M. Stallman committed
473

474
  SetConsoleActiveScreenBuffer (cur_screen);
Richard M. Stallman's avatar
Richard M. Stallman committed
475

476
  SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
Richard M. Stallman's avatar
Richard M. Stallman committed
477

478 479 480
  /* Initialize input mode: interrupt_input off, no flow control, allow
     8 bit character input, standard quit char.  */
  Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
Richard M. Stallman's avatar
Richard M. Stallman committed
481 482 483 484 485 486 487
}

/* hmmm... perhaps these let us bracket screen changes so that we can flush
   clumps rather than one-character-at-a-time...
   
   we'll start with not moving the cursor while an update is in progress.  */
void
488
update_begin (struct frame * f)
Richard M. Stallman's avatar
Richard M. Stallman committed
489 490 491 492
{
}

void
493
update_end (struct frame * f)
Richard M. Stallman's avatar
Richard M. Stallman committed
494 495 496 497 498 499 500 501 502
{
  SetConsoleCursorPosition (cur_screen, cursor_coords);
}

void
set_terminal_window (int size)
{
}

503 504 505 506 507 508 509
/***********************************************************************
				Faces
 ***********************************************************************/


/* Turn appearances of face FACE_ID on tty frame F on.  */

510 511
static WORD
w32_face_attributes (f, face_id)
512 513 514
     struct frame *f;
     int face_id;
{
515
  WORD char_attr;
516 517 518 519 520 521
  struct face *face = FACE_FROM_ID (f, face_id);

  xassert (face != NULL);

  char_attr = char_attr_normal;

522 523 524 525 526 527
  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)
528
    char_attr = (char_attr & 0xff0f) + ((face->background % 16) << 4); 
529

530

531 532 533
  /* NTEMACS_TODO: Faces defined during startup get both foreground
     and background of 0. Need a better way around this - for now detect
     the problem and invert one of the faces to make the text readable. */
534 535
  if (((char_attr & 0x00f0) >> 4) == (char_attr & 0x000f))
    char_attr ^= 0x0007;
536

537
  if (face->tty_reverse_p)
538 539
    char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
      + ((char_attr & 0x00f0) >> 4);
540

541
  return char_attr;
542 543 544
}


545
/* Emulation of some X window features from xfns.c and xfaces.c.  */
546

547 548 549 550 551 552
extern char unspecified_fg[], unspecified_bg[];


/* Given a color index, return its standard name.  */
Lisp_Object
vga_stdcolor_name (int idx)
553
{
554 555 556 557 558 559 560 561 562 563 564 565 566 567
  /* 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 */
568
}
569

Richard M. Stallman's avatar
Richard M. Stallman committed
570 571 572
typedef int (*term_hook) ();

void
573
initialize_w32_display (void)
Richard M. Stallman's avatar
Richard M. Stallman committed
574 575 576
{
  CONSOLE_SCREEN_BUFFER_INFO	info;
  
577 578 579 580 581 582 583 584 585 586 587 588 589 590 591
  cursor_to_hook		= move_cursor;
  raw_cursor_to_hook		= move_cursor;
  clear_to_end_hook		= clear_to_end;
  clear_frame_hook		= clear_frame;
  clear_end_of_line_hook	= clear_end_of_line;
  ins_del_lines_hook		= ins_del_lines;
  insert_glyphs_hook		= insert_glyphs;
  write_glyphs_hook		= write_glyphs;
  delete_glyphs_hook		= delete_glyphs;
  ring_bell_hook		= w32_sys_ring_bell;
  reset_terminal_modes_hook	= reset_terminal_modes;
  set_terminal_modes_hook	= set_terminal_modes;
  set_terminal_window_hook	= set_terminal_window;
  update_begin_hook		= update_begin;
  update_end_hook		= update_end;
Richard M. Stallman's avatar
Richard M. Stallman committed
592
  
593
  read_socket_hook = w32_console_read_socket;
594
  mouse_position_hook = w32_console_mouse_position;
595
  estimate_mode_line_height_hook = 0;
596

597 598 599
  /* Initialize interrupt_handle.  */
  init_crit ();

600 601 602 603
  /* Remember original console settings.  */
  keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
  GetConsoleMode (keyboard_handle, &prev_console_mode);

Richard M. Stallman's avatar
Richard M. Stallman committed
604 605
  prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
  
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
#ifdef USE_SEPARATE_SCREEN
  cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
					  0, NULL,
					  CONSOLE_TEXTMODE_BUFFER,
					  NULL);

  if (cur_screen == INVALID_HANDLE_VALUE)
    {
      printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
      printf ("LastError = 0x%lx\n", GetLastError ());
      fflush (stdout);
      exit (0);
    }
#else
  cur_screen = prev_screen;
  GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
#endif

624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
  /* 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);
      }
  }

Richard M. Stallman's avatar
Richard M. Stallman committed
658 659 660
  GetConsoleScreenBufferInfo (cur_screen, &info);
  
  meta_key = 1;
661
  char_attr_normal = info.wAttributes;
662

663 664
  if (w32_use_full_screen_buffer)
    {
665 666
      FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y;	/* lines per page */
      SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X);  /* characters per line */
667 668 669 670
    }
  else
    {
      /* Lines per page.  Use buffer coords instead of buffer size.  */
671
      FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom - 
672 673
	info.srWindow.Top; 
      /* Characters per line.  Use buffer coords instead of buffer size.  */
674
      SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right - 
675 676
		       info.srWindow.Left);
    }
677 678 679 680 681

  /* Setup w32_display_info structure for this frame. */

  w32_initialize_display_info (build_string ("Console"));

Richard M. Stallman's avatar
Richard M. Stallman committed
682 683 684
}

DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
685
       doc: /* Set screen colors.  */)
Richard M. Stallman's avatar
Richard M. Stallman committed
686 687 688 689 690 691 692 693 694 695 696
    (foreground, background)
    Lisp_Object foreground;
    Lisp_Object background;
{
  char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);

  Frecenter (Qnil);
  return Qt;
}

DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
697
       doc: /* Set cursor size.  */)
Richard M. Stallman's avatar
Richard M. Stallman committed
698 699 700 701 702 703 704 705 706 707 708
    (size)
    Lisp_Object size;
{
  CONSOLE_CURSOR_INFO cci;
  cci.dwSize = XFASTINT (size);
  cci.bVisible = TRUE;
  (void) SetConsoleCursorInfo (cur_screen, &cci);
  
  return Qt;
}

709
#ifndef HAVE_NTGUI
Richard M. Stallman's avatar
Richard M. Stallman committed
710
void
711
pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
Richard M. Stallman's avatar
Richard M. Stallman committed
712 713 714 715 716 717 718
		      void *bounds, int noclip)
{
  *x = pix_x;
  *y = pix_y;
}

void
719
glyph_to_pixel_coords (struct window * f, int x, int y, int *pix_x, int *pix_y)
Richard M. Stallman's avatar
Richard M. Stallman committed
720 721 722 723
{
  *pix_x = x;
  *pix_y = y;
}
724
#endif /* !HAVE_NTGUI */
Richard M. Stallman's avatar
Richard M. Stallman committed
725

Karl Heuer's avatar
Karl Heuer committed
726
void
Richard M. Stallman's avatar
Richard M. Stallman committed
727 728
syms_of_ntterm ()
{
729 730
  DEFVAR_BOOL ("w32-use-full-screen-buffer",
               &w32_use_full_screen_buffer,
731 732 733 734 735
	       doc: /* Non-nil means make terminal frames use the full screen buffer dimensions.
This is desirable when running Emacs over telnet, and is the default.
A value of nil means use the current console window dimensions; this
may be preferrable when working directly at the console with a large
scroll-back buffer.  */);
736 737
  w32_use_full_screen_buffer = 1;

Richard M. Stallman's avatar
Richard M. Stallman committed
738 739
  defsubr (&Sset_screen_color);
  defsubr (&Sset_cursor_size);
Karl Heuer's avatar
Karl Heuer committed
740
  defsubr (&Sset_message_beep);
Richard M. Stallman's avatar
Richard M. Stallman committed
741
}