1 /* Terminal hooks for Windows NT port of GNU Emacs.
2 Copyright (C) 1992 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any later
11 GNU Emacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 You should have received a copy of the GNU General Public License along
17 with GNU Emacs; see the file COPYING. If not, write to the Free Software
18 Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20 Tim Fleehart (apollo@online.com) 1-17-92
21 Geoff Voelker (voelker@cs.washington.edu) 9-12-93
35 #include "termhooks.h"
40 extern Lisp_Object
Frecenter ();
43 extern int detect_input_pending ();
46 extern int read_input_pending ();
48 extern FRAME_PTR updating_frame
;
51 static void move_cursor (int row
, int col
);
52 static void clear_to_end (void);
53 static void clear_frame (void);
54 static void clear_end_of_line (int);
55 static void ins_del_lines (int vpos
, int n
);
56 static void change_line_highlight (int, int, int);
57 static void reassert_line_highlight (int, int);
58 static void insert_glyphs (GLYPH
*start
, int len
);
59 static void write_glyphs (GLYPH
*string
, int len
);
60 static void delete_glyphs (int n
);
61 static void ring_bell (void);
62 static void reset_terminal_modes (void);
63 static void set_terminal_modes (void);
64 static void set_terminal_window (int size
);
65 static void update_begin (FRAME_PTR f
);
66 static void update_end (FRAME_PTR f
);
67 static void reset_kbd (void);
68 static void unset_kbd (void);
69 static int hl_mode (int new_highlight
);
76 /* Init hook called in init_keyboard. */
77 void (*keyboard_init_hook
)(void) = reset_kbd
;
80 HANDLE prev_screen
, cur_screen
;
81 UCHAR char_attr
, char_attr_normal
, char_attr_reverse
;
82 HANDLE keyboard_handle
;
85 /* Setting this as the ctrl handler prevents emacs from being killed when
86 * someone hits ^C in a 'suspended' session (child shell). */
88 ctrl_c_handler (unsigned long type
)
90 return (type
== CTRL_C_EVENT
) ? TRUE
: FALSE
;
93 /* If we're updating a frame, use it as the current frame
94 Otherwise, use the selected frame. */
95 #define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
97 /* Move the cursor to (row, col). */
99 move_cursor (int row
, int col
)
101 cursor_coords
.X
= col
;
102 cursor_coords
.Y
= row
;
104 if (updating_frame
== NULL
)
106 SetConsoleCursorPosition (cur_screen
, cursor_coords
);
110 /* Clear from cursor to end of screen. */
114 FRAME_PTR f
= PICK_FRAME ();
116 clear_end_of_line (FRAME_WIDTH (f
) - 1);
117 ins_del_lines (cursor_coords
.Y
, FRAME_HEIGHT (f
) - cursor_coords
.Y
- 1);
120 /* Clear the frame. */
127 FRAME_PTR f
= PICK_FRAME ();
132 scroll
.Bottom
= FRAME_HEIGHT (f
) - 1;
134 scroll
.Right
= FRAME_WIDTH (f
) - 1;
136 dest
.Y
= FRAME_HEIGHT (f
);
139 fill
.Char
.AsciiChar
= 0x20;
140 fill
.Attributes
= char_attr
;
142 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
147 static GLYPH glyph_base
[256];
148 static BOOL ceol_initialized
= FALSE
;
150 /* Clear from Cursor to end (what's "standout marker"?). */
152 clear_end_of_line (int end
)
154 if (!ceol_initialized
)
157 for (i
= 0; i
< 256; i
++)
159 glyph_base
[i
] = SPACEGLYPH
; /* empty space */
161 ceol_initialized
= TRUE
;
163 write_glyphs (glyph_base
, end
- cursor_coords
.X
); /* fencepost ? */
166 /* Insert n lines at vpos. if n is negative delete -n lines. */
168 ins_del_lines (int vpos
, int n
)
170 int i
, nb
, save_highlight
;
174 FRAME_PTR f
= PICK_FRAME ();
178 scroll
.Top
= vpos
- n
;
179 scroll
.Bottom
= FRAME_HEIGHT (f
);
185 scroll
.Bottom
= FRAME_HEIGHT (f
) - n
;
189 scroll
.Right
= FRAME_WIDTH (f
);
193 save_highlight
= hl_mode (0);
195 fill
.Char
.AsciiChar
= 0x20;
196 fill
.Attributes
= char_attr
;
198 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
200 /* Here we have to deal with a win32 console flake: If the scroll
201 region looks like abc and we scroll c to a and fill with d we get
202 cbd... if we scroll block c one line at a time to a, we get cdd...
203 Emacs expects cdd consistently... So we have to deal with that
204 here... (this also occurs scrolling the same way in the other
209 if (scroll
.Bottom
< dest
.Y
)
211 for (i
= scroll
.Bottom
; i
< dest
.Y
; i
++)
214 clear_end_of_line (FRAME_WIDTH (f
));
220 nb
= dest
.Y
+ (scroll
.Bottom
- scroll
.Top
) + 1;
224 for (i
= nb
; i
< scroll
.Top
; i
++)
227 clear_end_of_line (FRAME_WIDTH (f
));
233 cursor_coords
.Y
= vpos
;
235 hl_mode (save_highlight
);
238 /* Changes attribute to use when drawing characters to control. */
240 hl_mode (int new_highlight
)
242 static int highlight
= 0;
245 old_highlight
= highlight
;
246 highlight
= (new_highlight
!= 0);
249 char_attr
= char_attr_reverse
;
253 char_attr
= char_attr_normal
;
255 return old_highlight
;
258 /* Call this when about to modify line at position VPOS and change whether it
261 change_line_highlight (int new_highlight
, int vpos
, int first_unused_hpos
)
263 hl_mode (new_highlight
);
264 move_cursor (vpos
, 0);
265 clear_end_of_line (first_unused_hpos
);
268 /* External interface to control of standout mode. Call this when about to
269 * modify line at position VPOS and not change whether it is highlighted. */
271 reassert_line_highlight (int highlight
, int vpos
)
274 vpos
; /* pedantic compiler silencer */
283 scroll_line (int dist
, int direction
)
285 /* The idea here is to implement a horizontal scroll in one line to
286 implement delete and half of insert. */
290 FRAME_PTR f
= PICK_FRAME ();
292 scroll
.Top
= cursor_coords
.Y
;
293 scroll
.Bottom
= cursor_coords
.Y
;
295 if (direction
== LEFT
)
297 scroll
.Left
= cursor_coords
.X
+ dist
;
298 scroll
.Right
= FRAME_WIDTH (f
) - 1;
302 scroll
.Left
= cursor_coords
.X
;
303 scroll
.Right
= FRAME_WIDTH (f
) - dist
- 1;
306 dest
.X
= cursor_coords
.X
;
307 dest
.Y
= cursor_coords
.Y
;
309 fill
.Char
.AsciiChar
= 0x20;
310 fill
.Attributes
= char_attr
;
312 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
316 /* If start is zero insert blanks instead of a string at start ?. */
318 insert_glyphs (register GLYPH
*start
, register int len
)
320 scroll_line (len
, RIGHT
);
322 /* Move len chars to the right starting at cursor_coords, fill with blanks */
325 /* Print the first len characters of start, cursor_coords.X adjusted
328 write_glyphs (start
, len
);
332 clear_end_of_line (cursor_coords
.X
+ len
);
337 write_glyphs (register GLYPH
*string
, register int len
)
339 register unsigned int glyph_len
= GLYPH_TABLE_LENGTH
;
340 Lisp_Object
*glyph_table
= GLYPH_TABLE_BASE
;
341 FRAME_PTR f
= PICK_FRAME ();
348 attrs
= alloca (len
* sizeof (*attrs
));
349 chars
= alloca (len
* sizeof (*chars
));
350 if (attrs
== NULL
|| chars
== NULL
)
352 printf ("alloca failed in write_glyphs\n");
356 /* We have to deal with the glyph indirection...go over the glyph
357 buffer and extract the characters. */
363 if (glyph
> glyph_len
)
365 *ptr
++ = glyph
& 0xFF;
368 GLYPH_FOLLOW_ALIASES (glyph_table
, glyph_len
, glyph
);
369 if (GLYPH_FACE (fixfix
, glyph
) != 0)
370 printf ("Glyph face is %d\n", GLYPH_FACE (fixfix
, glyph
));
371 if (GLYPH_SIMPLE_P (glyph_table
, glyph_len
, glyph
))
373 *ptr
++ = glyph
& 0xFF;
376 for (i
= 0; i
< GLYPH_LENGTH (glyph_table
, glyph
); i
++)
378 *ptr
++ = (GLYPH_STRING (glyph_table
, glyph
))[i
];
382 /* Number of characters we have in the buffer. */
385 /* Fill in the attributes for these characters. */
386 memset (attrs
, char_attr
, len
*sizeof (*attrs
));
388 /* Write the attributes. */
389 if (!WriteConsoleOutputAttribute (cur_screen
, attrs
, len
, cursor_coords
, &i
))
391 printf ("Failed writing console attributes.\n");
395 /* Write the characters. */
396 if (!WriteConsoleOutputCharacter (cur_screen
, chars
, len
, cursor_coords
, &i
))
398 printf ("Failed writing console characters.\n");
402 cursor_coords
.X
+= len
;
403 move_cursor (cursor_coords
.Y
, cursor_coords
.X
);
407 delete_glyphs (int n
)
409 /* delete chars means scroll chars from cursor_coords.X + n to
410 cursor_coords.X, anything beyond the edge of the screen should
413 scroll_line (n
, LEFT
);
422 /* Reset to the original console mode but don't get rid of our console
423 For suspending emacs. */
425 restore_console (void)
428 SetConsoleActiveScreenBuffer (prev_screen
);
431 /* Put our console back up, for ending a suspended session. */
436 SetConsoleActiveScreenBuffer (cur_screen
);
440 reset_terminal_modes (void)
443 SetConsoleActiveScreenBuffer (prev_screen
);
444 CloseHandle (cur_screen
);
449 set_terminal_modes (void)
451 CONSOLE_CURSOR_INFO cci
;
453 if (cur_screen
== NULL
)
456 cur_screen
= CreateConsoleScreenBuffer (GENERIC_READ
| GENERIC_WRITE
,
458 CONSOLE_TEXTMODE_BUFFER
,
461 if (cur_screen
== INVALID_HANDLE_VALUE
)
463 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
464 printf ("LastError = 0x%lx\n", GetLastError ());
469 SetConsoleActiveScreenBuffer (cur_screen
);
471 /* make cursor big and visible */
474 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
478 /* hmmm... perhaps these let us bracket screen changes so that we can flush
479 clumps rather than one-character-at-a-time...
481 we'll start with not moving the cursor while an update is in progress. */
483 update_begin (FRAME_PTR f
)
488 update_end (FRAME_PTR f
)
490 SetConsoleCursorPosition (cur_screen
, cursor_coords
);
494 set_terminal_window (int size
)
501 SetConsoleMode (keyboard_handle
, ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
|
502 ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
);
508 keyboard_handle
= GetStdHandle (STD_INPUT_HANDLE
);
509 SetConsoleMode (keyboard_handle
, ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
512 typedef int (*term_hook
) ();
515 initialize_win_nt_display (void)
517 CONSOLE_SCREEN_BUFFER_INFO info
;
519 cursor_to_hook
= (term_hook
) move_cursor
;
520 raw_cursor_to_hook
= (term_hook
) move_cursor
;
521 clear_to_end_hook
= (term_hook
) clear_to_end
;
522 clear_frame_hook
= (term_hook
) clear_frame
;
523 clear_end_of_line_hook
= (term_hook
) clear_end_of_line
;
524 ins_del_lines_hook
= (term_hook
) ins_del_lines
;
525 change_line_highlight_hook
= (term_hook
) change_line_highlight
;
526 reassert_line_highlight_hook
= (term_hook
) reassert_line_highlight
;
527 insert_glyphs_hook
= (term_hook
) insert_glyphs
;
528 write_glyphs_hook
= (term_hook
) write_glyphs
;
529 delete_glyphs_hook
= (term_hook
) delete_glyphs
;
530 ring_bell_hook
= (term_hook
) ring_bell
;
531 reset_terminal_modes_hook
= (term_hook
) reset_terminal_modes
;
532 set_terminal_modes_hook
= (term_hook
) set_terminal_modes
;
533 set_terminal_window_hook
= (term_hook
) set_terminal_window
;
534 update_begin_hook
= (term_hook
) update_begin
;
535 update_end_hook
= (term_hook
) update_end
;
537 read_socket_hook
= win32_read_socket
;
538 mouse_position_hook
= win32_mouse_position
;
540 prev_screen
= GetStdHandle (STD_OUTPUT_HANDLE
);
542 set_terminal_modes ();
544 GetConsoleScreenBufferInfo (cur_screen
, &info
);
547 char_attr
= info
.wAttributes
& 0xFF;
548 char_attr_normal
= char_attr
;
549 char_attr_reverse
= ((char_attr
& 0xf) << 4) + ((char_attr
& 0xf0) >> 4);
551 FRAME_HEIGHT (selected_frame
) = info
.dwSize
.Y
; /* lines per page */
552 FRAME_WIDTH (selected_frame
) = info
.dwSize
.X
; /* characters per line */
559 DEFUN ("set-screen-color", Fset_screen_color
, Sset_screen_color
, 2, 2, 0,
560 "Set screen colors.")
561 (foreground
, background
)
562 Lisp_Object foreground
;
563 Lisp_Object background
;
565 char_attr_normal
= XFASTINT (foreground
) + (XFASTINT (background
) << 4);
566 char_attr_reverse
= XFASTINT (background
) + (XFASTINT (foreground
) << 4);
572 DEFUN ("set-cursor-size", Fset_cursor_size
, Sset_cursor_size
, 1, 1, 0,
577 CONSOLE_CURSOR_INFO cci
;
578 cci
.dwSize
= XFASTINT (size
);
580 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
586 pixel_to_glyph_coords (FRAME_PTR f
, int pix_x
, int pix_y
, int *x
, int *y
,
587 void *bounds
, int noclip
)
594 glyph_to_pixel_coords (FRAME_PTR f
, int x
, int y
, int *pix_x
, int *pix_y
)
603 defsubr (&Sset_screen_color
);
604 defsubr (&Sset_cursor_size
);