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. */
129 FRAME_PTR f
= PICK_FRAME ();
134 scroll
.Bottom
= FRAME_HEIGHT (f
) - 1;
136 scroll
.Right
= FRAME_WIDTH (f
) - 1;
138 dest
.Y
= FRAME_HEIGHT (f
);
141 fill
.Char
.AsciiChar
= 0x20;
142 fill
.Attributes
= char_attr
;
144 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
149 static GLYPH glyph_base
[256];
150 static BOOL ceol_initialized
= FALSE
;
152 /* Clear from Cursor to end (what's "standout marker"?). */
154 clear_end_of_line (int end
)
156 if (!ceol_initialized
)
159 for (i
= 0; i
< 256; i
++)
161 glyph_base
[i
] = SPACEGLYPH
; /* empty space */
163 ceol_initialized
= TRUE
;
165 write_glyphs (glyph_base
, end
- cursor_coords
.X
); /* fencepost ? */
168 /* Insert n lines at vpos. if n is negative delete -n lines. */
170 ins_del_lines (int vpos
, int n
)
172 int i
, nb
, save_highlight
;
176 FRAME_PTR f
= PICK_FRAME ();
180 scroll
.Top
= vpos
- n
;
181 scroll
.Bottom
= FRAME_HEIGHT (f
);
187 scroll
.Bottom
= FRAME_HEIGHT (f
) - n
;
191 scroll
.Right
= FRAME_WIDTH (f
);
195 save_highlight
= hl_mode (0);
197 fill
.Char
.AsciiChar
= 0x20;
198 fill
.Attributes
= char_attr
;
200 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
202 /* Here we have to deal with a win32 console flake: If the scroll
203 region looks like abc and we scroll c to a and fill with d we get
204 cbd... if we scroll block c one line at a time to a, we get cdd...
205 Emacs expects cdd consistently... So we have to deal with that
206 here... (this also occurs scrolling the same way in the other
211 if (scroll
.Bottom
< dest
.Y
)
213 for (i
= scroll
.Bottom
; i
< dest
.Y
; i
++)
216 clear_end_of_line (FRAME_WIDTH (f
));
222 nb
= dest
.Y
+ (scroll
.Bottom
- scroll
.Top
) + 1;
226 for (i
= nb
; i
< scroll
.Top
; i
++)
229 clear_end_of_line (FRAME_WIDTH (f
));
235 cursor_coords
.Y
= vpos
;
237 hl_mode (save_highlight
);
240 /* Changes attribute to use when drawing characters to control. */
242 hl_mode (int new_highlight
)
244 static int highlight
= 0;
247 old_highlight
= highlight
;
248 highlight
= (new_highlight
!= 0);
251 char_attr
= char_attr_reverse
;
255 char_attr
= char_attr_normal
;
257 return old_highlight
;
260 /* Call this when about to modify line at position VPOS and change whether it
263 change_line_highlight (int new_highlight
, int vpos
, int first_unused_hpos
)
265 hl_mode (new_highlight
);
266 move_cursor (vpos
, 0);
267 clear_end_of_line (first_unused_hpos
);
270 /* External interface to control of standout mode. Call this when about to
271 * modify line at position VPOS and not change whether it is highlighted. */
273 reassert_line_highlight (int highlight
, int vpos
)
276 vpos
; /* pedantic compiler silencer */
285 scroll_line (int dist
, int direction
)
287 /* The idea here is to implement a horizontal scroll in one line to
288 implement delete and half of insert. */
292 FRAME_PTR f
= PICK_FRAME ();
294 scroll
.Top
= cursor_coords
.Y
;
295 scroll
.Bottom
= cursor_coords
.Y
;
297 if (direction
== LEFT
)
299 scroll
.Left
= cursor_coords
.X
+ dist
;
300 scroll
.Right
= FRAME_WIDTH (f
) - 1;
304 scroll
.Left
= cursor_coords
.X
;
305 scroll
.Right
= FRAME_WIDTH (f
) - dist
- 1;
308 dest
.X
= cursor_coords
.X
;
309 dest
.Y
= cursor_coords
.Y
;
311 fill
.Char
.AsciiChar
= 0x20;
312 fill
.Attributes
= char_attr
;
314 ScrollConsoleScreenBuffer (cur_screen
, &scroll
, NULL
, dest
, &fill
);
318 /* If start is zero insert blanks instead of a string at start ?. */
320 insert_glyphs (register GLYPH
*start
, register int len
)
322 scroll_line (len
, RIGHT
);
324 /* Move len chars to the right starting at cursor_coords, fill with blanks */
327 /* Print the first len characters of start, cursor_coords.X adjusted
330 write_glyphs (start
, len
);
334 clear_end_of_line (cursor_coords
.X
+ len
);
339 write_glyphs (register GLYPH
*string
, register int len
)
341 register unsigned int glyph_len
= GLYPH_TABLE_LENGTH
;
342 Lisp_Object
*glyph_table
= GLYPH_TABLE_BASE
;
343 FRAME_PTR f
= PICK_FRAME ();
350 attrs
= alloca (len
* sizeof (*attrs
));
351 chars
= alloca (len
* sizeof (*chars
));
352 if (attrs
== NULL
|| chars
== NULL
)
354 printf ("alloca failed in write_glyphs\n");
358 /* We have to deal with the glyph indirection...go over the glyph
359 buffer and extract the characters. */
365 if (glyph
> glyph_len
)
367 *ptr
++ = glyph
& 0xFF;
370 GLYPH_FOLLOW_ALIASES (glyph_table
, glyph_len
, glyph
);
372 if (GLYPH_FACE (fixfix
, glyph
) != 0)
373 printf ("Glyph face is %d\n", GLYPH_FACE (fixfix
, glyph
));
374 #endif /* !HAVE_NTGUI */
375 if (GLYPH_SIMPLE_P (glyph_table
, glyph_len
, glyph
))
377 *ptr
++ = glyph
& 0xFF;
380 for (i
= 0; i
< GLYPH_LENGTH (glyph_table
, glyph
); i
++)
382 *ptr
++ = (GLYPH_STRING (glyph_table
, glyph
))[i
];
386 /* Number of characters we have in the buffer. */
389 /* Fill in the attributes for these characters. */
390 for (i
= 0; i
< len
; i
++)
391 attrs
[i
] = char_attr
;
393 /* Write the attributes. */
394 if (!WriteConsoleOutputAttribute (cur_screen
, attrs
, len
, cursor_coords
, &i
))
396 printf ("Failed writing console attributes: %d\n", GetLastError ());
400 /* Write the characters. */
401 if (!WriteConsoleOutputCharacter (cur_screen
, chars
, len
, cursor_coords
, &i
))
403 printf ("Failed writing console characters: %d\n", GetLastError ());
407 cursor_coords
.X
+= len
;
408 move_cursor (cursor_coords
.Y
, cursor_coords
.X
);
412 delete_glyphs (int n
)
414 /* delete chars means scroll chars from cursor_coords.X + n to
415 cursor_coords.X, anything beyond the edge of the screen should
418 scroll_line (n
, LEFT
);
421 static unsigned int sound_type
= 0xFFFFFFFF;
426 if (sound_type
== 0xFFFFFFFF)
429 MessageBeep (sound_type
);
432 DEFUN ("set-message-beep", Fset_message_beep
, Sset_message_beep
, 1, 1, 0,
433 "Set the sound generated when the bell is rung.\n\
434 SOUND is 'asterisk, 'exclamation, 'hand, 'question, or 'ok\n\
435 to use the corresponding system sound for the bell.\n\
436 SOUND is nil to use the normal beep.")
440 CHECK_SYMBOL (sound
, 0);
443 sound_type
= 0xFFFFFFFF;
444 else if (EQ (sound
, intern ("asterisk")))
445 sound_type
= MB_ICONASTERISK
;
446 else if (EQ (sound
, intern ("exclamation")))
447 sound_type
= MB_ICONEXCLAMATION
;
448 else if (EQ (sound
, intern ("hand")))
449 sound_type
= MB_ICONHAND
;
450 else if (EQ (sound
, intern ("question")))
451 sound_type
= MB_ICONQUESTION
;
452 else if (EQ (sound
, intern ("ok")))
455 sound_type
= 0xFFFFFFFF;
460 /* Put our console back up, for ending a suspended session. */
465 SetConsoleActiveScreenBuffer (cur_screen
);
469 reset_terminal_modes (void)
472 SetConsoleActiveScreenBuffer (prev_screen
);
476 set_terminal_modes (void)
478 CONSOLE_CURSOR_INFO cci
;
480 if (cur_screen
== NULL
)
483 cur_screen
= CreateConsoleScreenBuffer (GENERIC_READ
| GENERIC_WRITE
,
485 CONSOLE_TEXTMODE_BUFFER
,
488 if (cur_screen
== INVALID_HANDLE_VALUE
)
490 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
491 printf ("LastError = 0x%lx\n", GetLastError ());
496 SetConsoleActiveScreenBuffer (cur_screen
);
498 /* make cursor big and visible (100 on Win95 makes it disappear) */
501 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
505 /* hmmm... perhaps these let us bracket screen changes so that we can flush
506 clumps rather than one-character-at-a-time...
508 we'll start with not moving the cursor while an update is in progress. */
510 update_begin (FRAME_PTR f
)
515 update_end (FRAME_PTR f
)
517 SetConsoleCursorPosition (cur_screen
, cursor_coords
);
521 set_terminal_window (int size
)
528 SetConsoleMode (keyboard_handle
, ENABLE_PROCESSED_INPUT
| ENABLE_LINE_INPUT
|
529 ENABLE_ECHO_INPUT
| ENABLE_MOUSE_INPUT
);
535 keyboard_handle
= GetStdHandle (STD_INPUT_HANDLE
);
536 SetConsoleMode (keyboard_handle
, ENABLE_MOUSE_INPUT
| ENABLE_WINDOW_INPUT
);
539 typedef int (*term_hook
) ();
542 initialize_win_nt_display (void)
544 CONSOLE_SCREEN_BUFFER_INFO info
;
546 cursor_to_hook
= (term_hook
) move_cursor
;
547 raw_cursor_to_hook
= (term_hook
) move_cursor
;
548 clear_to_end_hook
= (term_hook
) clear_to_end
;
549 clear_frame_hook
= (term_hook
) clear_frame
;
550 clear_end_of_line_hook
= (term_hook
) clear_end_of_line
;
551 ins_del_lines_hook
= (term_hook
) ins_del_lines
;
552 change_line_highlight_hook
= (term_hook
) change_line_highlight
;
553 reassert_line_highlight_hook
= (term_hook
) reassert_line_highlight
;
554 insert_glyphs_hook
= (term_hook
) insert_glyphs
;
555 write_glyphs_hook
= (term_hook
) write_glyphs
;
556 delete_glyphs_hook
= (term_hook
) delete_glyphs
;
557 ring_bell_hook
= (term_hook
) nt_ring_bell
;
558 reset_terminal_modes_hook
= (term_hook
) reset_terminal_modes
;
559 set_terminal_modes_hook
= (term_hook
) set_terminal_modes
;
560 set_terminal_window_hook
= (term_hook
) set_terminal_window
;
561 update_begin_hook
= (term_hook
) update_begin
;
562 update_end_hook
= (term_hook
) update_end
;
564 read_socket_hook
= win32_read_socket
;
565 mouse_position_hook
= win32_mouse_position
;
567 prev_screen
= GetStdHandle (STD_OUTPUT_HANDLE
);
569 set_terminal_modes ();
571 GetConsoleScreenBufferInfo (cur_screen
, &info
);
574 char_attr
= info
.wAttributes
& 0xFF;
575 char_attr_normal
= char_attr
;
576 char_attr_reverse
= ((char_attr
& 0xf) << 4) + ((char_attr
& 0xf0) >> 4);
578 FRAME_HEIGHT (selected_frame
) = info
.dwSize
.Y
; /* lines per page */
579 FRAME_WIDTH (selected_frame
) = info
.dwSize
.X
; /* characters per line */
586 DEFUN ("set-screen-color", Fset_screen_color
, Sset_screen_color
, 2, 2, 0,
587 "Set screen colors.")
588 (foreground
, background
)
589 Lisp_Object foreground
;
590 Lisp_Object background
;
592 char_attr_normal
= XFASTINT (foreground
) + (XFASTINT (background
) << 4);
593 char_attr_reverse
= XFASTINT (background
) + (XFASTINT (foreground
) << 4);
599 DEFUN ("set-cursor-size", Fset_cursor_size
, Sset_cursor_size
, 1, 1, 0,
604 CONSOLE_CURSOR_INFO cci
;
605 cci
.dwSize
= XFASTINT (size
);
607 (void) SetConsoleCursorInfo (cur_screen
, &cci
);
614 pixel_to_glyph_coords (FRAME_PTR f
, int pix_x
, int pix_y
, int *x
, int *y
,
615 void *bounds
, int noclip
)
622 glyph_to_pixel_coords (FRAME_PTR f
, int x
, int y
, int *pix_x
, int *pix_y
)
627 #endif /* !HAVE_NTGUI */
632 defsubr (&Sset_screen_color
);
633 defsubr (&Sset_cursor_size
);
634 defsubr (&Sset_message_beep
);