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
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
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.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
21 Tim Fleehart (apollo@online.com) 1-17-92
22 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 void nt_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).
87 Also ignore Ctrl-Break signals. */
90 ctrl_c_handler (unsigned long type
)
92 return (type
== CTRL_C_EVENT
|| type
== CTRL_BREAK_EVENT
);
95 /* If we're updating a frame, use it as the current frame
96 Otherwise, use the selected frame. */
97 #define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
99 /* Move the cursor to (row, col). */
101 move_cursor (int row
, int col
)
103 cursor_coords
.X
= col
;
104 cursor_coords
.Y
= row
;
106 if (updating_frame
== (FRAME_PTR
) NULL
)
108 SetConsoleCursorPosition (cur_screen
, cursor_coords
);
112 /* Clear from cursor to end of screen. */
116 FRAME_PTR f
= PICK_FRAME ();
118 clear_end_of_line (FRAME_WIDTH (f
) - 1);
119 ins_del_lines (cursor_coords
.Y
, FRAME_HEIGHT (f
) - cursor_coords
.Y
- 1);
122 /* Clear the frame. */
126 FRAME_PTR f
= PICK_FRAME ();
132 n
= FRAME_HEIGHT (f
) * FRAME_WIDTH (f
);
135 FillConsoleOutputAttribute (cur_screen
, char_attr
, n
, dest
, &r
);
136 FillConsoleOutputCharacter (cur_screen
, ' ', n
, dest
, &r
);
142 static GLYPH glyph_base
[256];
143 static BOOL ceol_initialized
= FALSE
;
145 /* Clear from Cursor to end (what's "standout marker"?). */
147 clear_end_of_line (int end
)
149 if (!ceol_initialized
)
152 for (i
= 0; i
< 256; i
++)
154 glyph_base
[i
] = SPACEGLYPH
; /* empty space */
156 ceol_initialized
= TRUE
;
158 write_glyphs (glyph_base
, end
- cursor_coords
.X
); /* fencepost ? */
161 /* Insert n lines at vpos. if n is negative delete -n lines. */
163 ins_del_lines (int vpos
, int n
)
165 int i
, nb
, save_highlight
;
169 FRAME_PTR f
= PICK_FRAME ();
173 scroll
.Top
= vpos
- n
;
174 scroll
.Bottom
= FRAME_HEIGHT (f
);
180 scroll
.Bottom
= FRAME_HEIGHT (f
) - n
;
184 scroll
.Right
= FRAME_WIDTH (f
);
188 save_highlight
= hl_mode (0);
190 fill
.Char
.AsciiChar
= 0x20;
191 fill
.Attributes
= char_attr
;
193 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
195 /* Here we have to deal with a win32 console flake: If the scroll
196 region looks like abc and we scroll c to a and fill with d we get
197 cbd... if we scroll block c one line at a time to a, we get cdd...
198 Emacs expects cdd consistently... So we have to deal with that
199 here... (this also occurs scrolling the same way in the other
204 if (scroll
.Bottom
< dest
.Y
)
206 for (i
= scroll
.Bottom
; i
< dest
.Y
; i
++)
209 clear_end_of_line (FRAME_WIDTH (f
));
215 nb
= dest
.Y
+ (scroll
.Bottom
- scroll
.Top
) + 1;
219 for (i
= nb
; i
< scroll
.Top
; i
++)
222 clear_end_of_line (FRAME_WIDTH (f
));
228 cursor_coords
.Y
= vpos
;
230 hl_mode (save_highlight
);
233 /* Changes attribute to use when drawing characters to control. */
235 hl_mode (int new_highlight
)
237 static int highlight
= 0;
240 old_highlight
= highlight
;
241 highlight
= (new_highlight
!= 0);
244 char_attr
= char_attr_reverse
;
248 char_attr
= char_attr_normal
;
250 return old_highlight
;
253 /* Call this when about to modify line at position VPOS and change whether it
256 change_line_highlight (int new_highlight
, int vpos
, int first_unused_hpos
)
258 hl_mode (new_highlight
);
259 move_cursor (vpos
, 0);
260 clear_end_of_line (first_unused_hpos
);
263 /* External interface to control of standout mode. Call this when about to
264 * modify line at position VPOS and not change whether it is highlighted. */
266 reassert_line_highlight (int highlight
, int vpos
)
269 vpos
; /* pedantic compiler silencer */
278 scroll_line (int dist
, int direction
)
280 /* The idea here is to implement a horizontal scroll in one line to
281 implement delete and half of insert. */
285 FRAME_PTR f
= PICK_FRAME ();
287 scroll
.Top
= cursor_coords
.Y
;
288 scroll
.Bottom
= cursor_coords
.Y
;
290 if (direction
== LEFT
)
292 scroll
.Left
= cursor_coords
.X
+ dist
;
293 scroll
.Right
= FRAME_WIDTH (f
) - 1;
297 scroll
.Left
= cursor_coords
.X
;
298 scroll
.Right
= FRAME_WIDTH (f
) - dist
- 1;
301 dest
.X
= cursor_coords
.X
;
302 dest
.Y
= cursor_coords
.Y
;
304 fill
.Char
.AsciiChar
= 0x20;
305 fill
.Attributes
= char_attr
;
307 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
311 /* If start is zero insert blanks instead of a string at start ?. */
313 insert_glyphs (register GLYPH
*start
, register int len
)
315 scroll_line (len
, RIGHT
);
317 /* Move len chars to the right starting at cursor_coords, fill with blanks */
320 /* Print the first len characters of start, cursor_coords.X adjusted
323 write_glyphs (start
, len
);
327 clear_end_of_line (cursor_coords
.X
+ len
);
332 write_glyphs (register GLYPH
*string
, register int len
)
334 register unsigned int glyph_len
= GLYPH_TABLE_LENGTH
;
335 Lisp_Object
*glyph_table
= GLYPH_TABLE_BASE
;
336 FRAME_PTR f
= PICK_FRAME ();
346 attrs
= alloca (len
* sizeof (*attrs
));
347 chars
= alloca (len
* sizeof (*chars
));
348 if (attrs
== NULL
|| chars
== NULL
)
350 printf ("alloca failed in write_glyphs\n");
354 /* We have to deal with the glyph indirection...go over the glyph
355 buffer and extract the characters. */
361 if (glyph
> glyph_len
)
363 *ptr
++ = glyph
& 0xFF;
366 GLYPH_FOLLOW_ALIASES (glyph_table
, glyph_len
, glyph
);
368 if (GLYPH_FACE (fixfix
, glyph
) != 0)
369 printf ("Glyph face is %d\n", GLYPH_FACE (fixfix
, glyph
));
370 #endif /* !HAVE_NTGUI */
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 for (i
= 0; i
< len
; i
++)
387 attrs
[i
] = char_attr
;
389 /* Write the attributes. */
390 if (!WriteConsoleOutputAttribute (cur_screen
, attrs
, len
, cursor_coords
, &i
))
392 printf ("Failed writing console attributes: %d\n", GetLastError ());
396 /* Write the characters. */
397 if (!WriteConsoleOutputCharacter (cur_screen
, chars
, len
, cursor_coords
, &i
))
399 printf ("Failed writing console characters: %d\n", GetLastError ());
403 cursor_coords
.X
+= len
;
404 move_cursor (cursor_coords
.Y
, cursor_coords
.X
);
408 delete_glyphs (int n
)
410 /* delete chars means scroll chars from cursor_coords.X + n to
411 cursor_coords.X, anything beyond the edge of the screen should
414 scroll_line (n
, LEFT
);
417 static unsigned int sound_type
= 0xFFFFFFFF;
422 if (sound_type
== 0xFFFFFFFF)
425 MessageBeep (sound_type
);
428 DEFUN ("set-message-beep", Fset_message_beep
, Sset_message_beep
, 1, 1, 0,
429 "Set the sound generated when the bell is rung.\n\
430 SOUND is 'asterisk, 'exclamation, 'hand, 'question, or 'ok\n\
431 to use the corresponding system sound for the bell.\n\
432 SOUND is nil to use the normal beep.")
436 CHECK_SYMBOL (sound
, 0);
439 sound_type
= 0xFFFFFFFF;
440 else if (EQ (sound
, intern ("asterisk")))
441 sound_type
= MB_ICONASTERISK
;
442 else if (EQ (sound
, intern ("exclamation")))
443 sound_type
= MB_ICONEXCLAMATION
;
444 else if (EQ (sound
, intern ("hand")))
445 sound_type
= MB_ICONHAND
;
446 else if (EQ (sound
, intern ("question")))
447 sound_type
= MB_ICONQUESTION
;
448 else if (EQ (sound
, intern ("ok")))
451 sound_type
= 0xFFFFFFFF;
456 /* Put our console back up, for ending a suspended session. */
461 SetConsoleActiveScreenBuffer (cur_screen
);
465 reset_terminal_modes (void)
468 SetConsoleActiveScreenBuffer (prev_screen
);
472 set_terminal_modes (void)
474 CONSOLE_CURSOR_INFO cci
;
476 if (cur_screen
== NULL
)
479 cur_screen
= CreateConsoleScreenBuffer (GENERIC_READ
| GENERIC_WRITE
,
481 CONSOLE_TEXTMODE_BUFFER
,
484 if (cur_screen
== INVALID_HANDLE_VALUE
)
486 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
487 printf ("LastError = 0x%lx\n", GetLastError ());
492 SetConsoleActiveScreenBuffer (cur_screen
);
494 /* make cursor big and visible (100 on Win95 makes it disappear) */
497 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
501 /* hmmm... perhaps these let us bracket screen changes so that we can flush
502 clumps rather than one-character-at-a-time...
504 we'll start with not moving the cursor while an update is in progress. */
506 update_begin (FRAME_PTR f
)
511 update_end (FRAME_PTR f
)
513 SetConsoleCursorPosition (cur_screen
, cursor_coords
);
517 set_terminal_window (int size
)
524 SetConsoleMode (keyboard_handle
, ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
|
525 ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
);
531 keyboard_handle
= GetStdHandle (STD_INPUT_HANDLE
);
532 SetConsoleMode (keyboard_handle
, ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
535 typedef int (*term_hook
) ();
538 initialize_win_nt_display (void)
540 CONSOLE_SCREEN_BUFFER_INFO info
;
542 cursor_to_hook
= (term_hook
) move_cursor
;
543 raw_cursor_to_hook
= (term_hook
) move_cursor
;
544 clear_to_end_hook
= (term_hook
) clear_to_end
;
545 clear_frame_hook
= (term_hook
) clear_frame
;
546 clear_end_of_line_hook
= (term_hook
) clear_end_of_line
;
547 ins_del_lines_hook
= (term_hook
) ins_del_lines
;
548 change_line_highlight_hook
= (term_hook
) change_line_highlight
;
549 reassert_line_highlight_hook
= (term_hook
) reassert_line_highlight
;
550 insert_glyphs_hook
= (term_hook
) insert_glyphs
;
551 write_glyphs_hook
= (term_hook
) write_glyphs
;
552 delete_glyphs_hook
= (term_hook
) delete_glyphs
;
553 ring_bell_hook
= (term_hook
) nt_ring_bell
;
554 reset_terminal_modes_hook
= (term_hook
) reset_terminal_modes
;
555 set_terminal_modes_hook
= (term_hook
) set_terminal_modes
;
556 set_terminal_window_hook
= (term_hook
) set_terminal_window
;
557 update_begin_hook
= (term_hook
) update_begin
;
558 update_end_hook
= (term_hook
) update_end
;
560 read_socket_hook
= win32_read_socket
;
561 mouse_position_hook
= win32_mouse_position
;
563 prev_screen
= GetStdHandle (STD_OUTPUT_HANDLE
);
565 set_terminal_modes ();
567 GetConsoleScreenBufferInfo (cur_screen
, &info
);
570 char_attr
= info
.wAttributes
& 0xFF;
571 char_attr_normal
= char_attr
;
572 char_attr_reverse
= ((char_attr
& 0xf) << 4) + ((char_attr
& 0xf0) >> 4);
574 FRAME_HEIGHT (selected_frame
) = info
.dwSize
.Y
; /* lines per page */
575 FRAME_WIDTH (selected_frame
) = info
.dwSize
.X
; /* characters per line */
582 DEFUN ("set-screen-color", Fset_screen_color
, Sset_screen_color
, 2, 2, 0,
583 "Set screen colors.")
584 (foreground
, background
)
585 Lisp_Object foreground
;
586 Lisp_Object background
;
588 char_attr_normal
= XFASTINT (foreground
) + (XFASTINT (background
) << 4);
589 char_attr_reverse
= XFASTINT (background
) + (XFASTINT (foreground
) << 4);
595 DEFUN ("set-cursor-size", Fset_cursor_size
, Sset_cursor_size
, 1, 1, 0,
600 CONSOLE_CURSOR_INFO cci
;
601 cci
.dwSize
= XFASTINT (size
);
603 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
610 pixel_to_glyph_coords (FRAME_PTR f
, int pix_x
, int pix_y
, int *x
, int *y
,
611 void *bounds
, int noclip
)
618 glyph_to_pixel_coords (FRAME_PTR f
, int x
, int y
, int *pix_x
, int *pix_y
)
623 #endif /* !HAVE_NTGUI */
628 defsubr (&Sset_screen_color
);
629 defsubr (&Sset_cursor_size
);
630 defsubr (&Sset_message_beep
);