1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
19
20 21 22 23
24
25
26 #include <config.h>
27
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <windows.h>
31 #include <string.h>
32 #include <setjmp.h>
33
34 #include "lisp.h"
35 #include "character.h"
36 #include "coding.h"
37 #include "disptab.h"
38 #include "frame.h"
39 #include "termhooks.h"
40 #include "termchar.h"
41 #include "dispextern.h"
42 #include "w32inevt.h"
43
44
45 extern Lisp_Object Frecenter ();
46
47
48 extern int detect_input_pending ();
49
50
51 extern int read_input_pending ();
52
53 static void w32con_move_cursor (struct frame *f, int row, int col);
54 static void w32con_clear_to_end (struct frame *f);
55 static void w32con_clear_frame (struct frame *f);
56 static void w32con_clear_end_of_line (struct frame *f, int);
57 static void w32con_ins_del_lines (struct frame *f, int vpos, int n);
58 static void w32con_insert_glyphs (struct frame *f, struct glyph *start, int len);
59 static void w32con_write_glyphs (struct frame *f, struct glyph *string, int len);
60 static void w32con_delete_glyphs (struct frame *f, int n);
61 static void w32con_reset_terminal_modes (struct terminal *t);
62 static void w32con_set_terminal_modes (struct terminal *t);
63 static void w32con_set_terminal_window (struct frame *f, int size);
64 static void w32con_update_begin (struct frame * f);
65 static void w32con_update_end (struct frame * f);
66 static WORD w32_face_attributes (struct frame *f, int face_id);
67
68 static COORD cursor_coords;
69 static HANDLE prev_screen, cur_screen;
70 static WORD char_attr_normal;
71 static DWORD prev_console_mode;
72
73 #ifndef USE_SEPARATE_SCREEN
74 static CONSOLE_CURSOR_INFO prev_console_cursor;
75 #endif
76
77 extern Lisp_Object Vtty_defined_color_alist;
78
79 80 81 82
83 int w32_use_full_screen_buffer;
84 HANDLE keyboard_handle;
85
86
87 88 89
90
91 BOOL
92 ctrl_c_handler (unsigned long type)
93 {
94
95 return (!noninteractive
96 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
97 }
98
99
100
101 static void
102 w32con_move_cursor (struct frame *f, int row, int col)
103 {
104 cursor_coords.X = col;
105 cursor_coords.Y = row;
106
107 108
109 SetConsoleCursorPosition (cur_screen, cursor_coords);
110 }
111
112
113 static void
114 w32con_clear_to_end (struct frame *f)
115 {
116 w32con_clear_end_of_line (f, FRAME_COLS (f) - 1);
117 w32con_ins_del_lines (f, cursor_coords.Y, FRAME_LINES (f) - cursor_coords.Y - 1);
118 }
119
120
121 static void
122 w32con_clear_frame (struct frame *f)
123 {
124 COORD dest;
125 int n;
126 DWORD r;
127 CONSOLE_SCREEN_BUFFER_INFO info;
128
129 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
130
131
132 n = FRAME_LINES (f) * info.dwSize.X;
133 dest.X = dest.Y = 0;
134
135 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
136 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
137
138 w32con_move_cursor (f, 0, 0);
139 }
140
141
142 static struct glyph glyph_base[256];
143 static BOOL ceol_initialized = FALSE;
144
145
146 static void
147 w32con_clear_end_of_line (struct frame *f, int end)
148 {
149 if (!ceol_initialized)
150 {
151 int i;
152 for (i = 0; i < 256; i++)
153 {
154 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
155 }
156 ceol_initialized = TRUE;
157 }
158 w32con_write_glyphs (f, glyph_base, end - cursor_coords.X);
159 }
160
161
162 static void
163 w32con_ins_del_lines (struct frame *f, int vpos, int n)
164 {
165 int i, nb;
166 SMALL_RECT scroll;
167 SMALL_RECT clip;
168 COORD dest;
169 CHAR_INFO fill;
170
171 if (n < 0)
172 {
173 scroll.Top = vpos - n;
174 scroll.Bottom = FRAME_LINES (f);
175 dest.Y = vpos;
176 }
177 else
178 {
179 scroll.Top = vpos;
180 scroll.Bottom = FRAME_LINES (f) - n;
181 dest.Y = vpos + n;
182 }
183 clip.Top = clip.Left = scroll.Left = 0;
184 clip.Right = scroll.Right = FRAME_COLS (f);
185 clip.Bottom = FRAME_LINES (f);
186
187 dest.X = 0;
188
189 fill.Char.AsciiChar = 0x20;
190 fill.Attributes = char_attr_normal;
191
192 ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
193
194 195 196 197 198 199
200
201 if (n > 0)
202 {
203 if (scroll.Bottom < dest.Y)
204 {
205 for (i = scroll.Bottom; i < dest.Y; i++)
206 {
207 w32con_move_cursor (f, i, 0);
208 w32con_clear_end_of_line (f, FRAME_COLS (f));
209 }
210 }
211 }
212 else
213 {
214 nb = dest.Y + (scroll.Bottom - scroll.Top) + 1;
215
216 if (nb < scroll.Top)
217 {
218 for (i = nb; i < scroll.Top; i++)
219 {
220 w32con_move_cursor (f, i, 0);
221 w32con_clear_end_of_line (f, FRAME_COLS (f));
222 }
223 }
224 }
225
226 cursor_coords.X = 0;
227 cursor_coords.Y = vpos;
228 }
229
230 #undef LEFT
231 #undef RIGHT
232 #define LEFT 1
233 #define RIGHT 0
234
235 static void
236 scroll_line (struct frame *f, int dist, int direction)
237 {
238 239
240 SMALL_RECT scroll, clip;
241 COORD dest;
242 CHAR_INFO fill;
243
244 clip.Top = scroll.Top = clip.Bottom = scroll.Bottom = cursor_coords.Y;
245 clip.Left = 0;
246 clip.Right = FRAME_COLS (f);
247
248 if (direction == LEFT)
249 {
250 scroll.Left = cursor_coords.X + dist;
251 scroll.Right = FRAME_COLS (f) - 1;
252 }
253 else
254 {
255 scroll.Left = cursor_coords.X;
256 scroll.Right = FRAME_COLS (f) - dist - 1;
257 }
258
259 dest.X = cursor_coords.X;
260 dest.Y = cursor_coords.Y;
261
262 fill.Char.AsciiChar = 0x20;
263 fill.Attributes = char_attr_normal;
264
265 ScrollConsoleScreenBuffer (cur_screen, &scroll, &clip, dest, &fill);
266 }
267
268
269
270 static void
271 w32con_insert_glyphs (struct frame *f, register struct glyph *start, register int len)
272 {
273 scroll_line (f, len, RIGHT);
274
275
276 if (start)
277 {
278 279
280
281 w32con_write_glyphs (f, start, len);
282 }
283 else
284 {
285 w32con_clear_end_of_line (f, cursor_coords.X + len);
286 }
287 }
288
289 extern unsigned char *encode_terminal_code P_ ((struct glyph *, int,
290 struct coding_system *));
291
292 static void
293 w32con_write_glyphs (struct frame *f, register struct glyph *string,
294 register int len)
295 {
296 DWORD r;
297 WORD char_attr;
298 unsigned char *conversion_buffer;
299 struct coding_system *coding;
300
301 if (len <= 0)
302 return;
303
304 305 306
307 coding = (FRAME_TERMINAL_CODING (f)->common_flags & CODING_REQUIRE_ENCODING_MASK
308 ? FRAME_TERMINAL_CODING (f) : &safe_terminal_coding);
309 310
311 coding->mode &= ~CODING_MODE_LAST_BLOCK;
312
313 while (len > 0)
314 {
315
316 int face_id = string->face_id;
317 int n;
318
319 for (n = 1; n < len; ++n)
320 if (string[n].face_id != face_id)
321 break;
322
323
324 char_attr = w32_face_attributes (f, face_id);
325
326 if (n == len)
327
328 coding->mode |= CODING_MODE_LAST_BLOCK;
329 conversion_buffer = encode_terminal_code (string, n, coding);
330 if (coding->produced > 0)
331 {
332
333 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
334 coding->produced, cursor_coords,
335 &r))
336 {
337 printf ("Failed writing console attributes: %d\n",
338 GetLastError ());
339 fflush (stdout);
340 }
341
342
343 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
344 coding->produced, cursor_coords,
345 &r))
346 {
347 printf ("Failed writing console characters: %d\n",
348 GetLastError ());
349 fflush (stdout);
350 }
351
352 cursor_coords.X += coding->produced;
353 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
354 }
355 len -= n;
356 string += n;
357 }
358 }
359
360
361 static void
362 w32con_delete_glyphs (struct frame *f, int n)
363 {
364 365 366
367
368 scroll_line (f, n, LEFT);
369 }
370
371 static unsigned int sound_type = 0xFFFFFFFF;
372 #define MB_EMACS_SILENT (0xFFFFFFFF - 1)
373
374 void
375 w32_sys_ring_bell (struct frame *f)
376 {
377 if (sound_type == 0xFFFFFFFF)
378 {
379 Beep (666, 100);
380 }
381 else if (sound_type == MB_EMACS_SILENT)
382 {
383
384 }
385 else
386 MessageBeep (sound_type);
387 }
388
389 DEFUN ("set-message-beep", Fset_message_beep, Sset_message_beep, 1, 1, 0,
390 doc: 391 392 393 394 )
395 (sound)
396 Lisp_Object sound;
397 {
398 CHECK_SYMBOL (sound);
399
400 if (NILP (sound))
401 sound_type = 0xFFFFFFFF;
402 else if (EQ (sound, intern ("asterisk")))
403 sound_type = MB_ICONASTERISK;
404 else if (EQ (sound, intern ("exclamation")))
405 sound_type = MB_ICONEXCLAMATION;
406 else if (EQ (sound, intern ("hand")))
407 sound_type = MB_ICONHAND;
408 else if (EQ (sound, intern ("question")))
409 sound_type = MB_ICONQUESTION;
410 else if (EQ (sound, intern ("ok")))
411 sound_type = MB_OK;
412 else if (EQ (sound, intern ("silent")))
413 sound_type = MB_EMACS_SILENT;
414 else
415 sound_type = 0xFFFFFFFF;
416
417 return sound;
418 }
419
420 static void
421 w32con_reset_terminal_modes (struct terminal *t)
422 {
423 COORD dest;
424 CONSOLE_SCREEN_BUFFER_INFO info;
425 int n;
426 DWORD r;
427
428 429 430 431
432 GetConsoleScreenBufferInfo (cur_screen, &info);
433 dest.X = 0;
434 dest.Y = 0;
435 n = info.dwSize.X * info.dwSize.Y;
436
437 FillConsoleOutputAttribute (cur_screen, char_attr_normal, n, dest, &r);
438 FillConsoleOutputCharacter (cur_screen, ' ', n, dest, &r);
439
440 SetConsoleCursorPosition (cur_screen, dest);
441
442 #ifdef USE_SEPARATE_SCREEN
443 SetConsoleActiveScreenBuffer (prev_screen);
444 #else
445 SetConsoleCursorInfo (prev_screen, &prev_console_cursor);
446 #endif
447
448 SetConsoleMode (keyboard_handle, prev_console_mode);
449 }
450
451 static void
452 w32con_set_terminal_modes (struct terminal *t)
453 {
454 CONSOLE_CURSOR_INFO cci;
455
456
457 cci.dwSize = 99;
458 cci.bVisible = TRUE;
459 (void) SetConsoleCursorInfo (cur_screen, &cci);
460
461 SetConsoleActiveScreenBuffer (cur_screen);
462
463 SetConsoleMode (keyboard_handle, ENABLE_MOUSE_INPUT | ENABLE_WINDOW_INPUT);
464
465 466
467 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
468 }
469
470 471 472 473
474 static void
475 w32con_update_begin (struct frame * f)
476 {
477 }
478
479 static void
480 w32con_update_end (struct frame * f)
481 {
482 SetConsoleCursorPosition (cur_screen, cursor_coords);
483 }
484
485 static void
486 w32con_set_terminal_window (struct frame *f, int size)
487 {
488 }
489
490 491 492
493
494 void
495 sys_tputs (char *str, int nlines, int (*outfun)())
496 {
497 }
498
499 char *
500 sys_tgetstr (char *cap, char **area)
501 {
502 return NULL;
503 }
504
505
506 507 508
509
510 struct tty_display_info *current_tty = NULL;
511 int cost = 0;
512
513 int
514 evalcost (char c)
515 {
516 return c;
517 }
518
519 int
520 cmputc (char c)
521 {
522 return c;
523 }
524
525 void
526 cmcheckmagic (struct tty_display_info *tty)
527 {
528 }
529
530 void
531 cmcostinit (struct tty_display_info *tty)
532 {
533 }
534
535 void
536 cmgoto (struct tty_display_info *tty, int row, int col)
537 {
538 }
539
540 void
541 Wcm_clear (struct tty_display_info *tty)
542 {
543 }
544
545
546 547 548
549
550
551
552
553 static WORD
554 w32_face_attributes (f, face_id)
555 struct frame *f;
556 int face_id;
557 {
558 WORD char_attr;
559 struct face *face = FACE_FROM_ID (f, face_id);
560
561 xassert (face != NULL);
562
563 char_attr = char_attr_normal;
564
565 566
567 if (face->tty_reverse_p)
568 char_attr = (char_attr & 0xff00) + ((char_attr & 0x000f) << 4)
569 + ((char_attr & 0x00f0) >> 4);
570
571 572
573 if (NILP (Vtty_defined_color_alist))
574 return char_attr;
575
576 577 578 579 580
581 if (face->foreground >= 0 && face->foreground < 16)
582 char_attr = (char_attr & 0xfff0) + face->foreground;
583
584 if (face->background >= 0 && face->background < 16)
585 char_attr = (char_attr & 0xff0f) + (face->background << 4);
586
587 return char_attr;
588 }
589
590
591
592
593 Lisp_Object
594 vga_stdcolor_name (int idx)
595 {
596 597
598 static char *vga_colors[16] = {
599 "black", "blue", "green", "cyan", "red", "magenta", "brown",
600 "lightgray", "darkgray", "lightblue", "lightgreen", "lightcyan",
601 "lightred", "lightmagenta", "yellow", "white"
602 };
603
604 extern Lisp_Object Qunspecified;
605
606 if (idx >= 0 && idx < sizeof (vga_colors) / sizeof (vga_colors[0]))
607 return build_string (vga_colors[idx]);
608 else
609 return Qunspecified;
610 }
611
612 typedef int (*term_hook) ();
613
614 void
615 initialize_w32_display (struct terminal *term)
616 {
617 CONSOLE_SCREEN_BUFFER_INFO info;
618
619 term->rif = 0;
620 term->cursor_to_hook = w32con_move_cursor;
621 term->raw_cursor_to_hook = w32con_move_cursor;
622 term->clear_to_end_hook = w32con_clear_to_end;
623 term->clear_frame_hook = w32con_clear_frame;
624 term->clear_end_of_line_hook = w32con_clear_end_of_line;
625 term->ins_del_lines_hook = w32con_ins_del_lines;
626 term->insert_glyphs_hook = w32con_insert_glyphs;
627 term->write_glyphs_hook = w32con_write_glyphs;
628 term->delete_glyphs_hook = w32con_delete_glyphs;
629 term->ring_bell_hook = w32_sys_ring_bell;
630 term->reset_terminal_modes_hook = w32con_reset_terminal_modes;
631 term->set_terminal_modes_hook = w32con_set_terminal_modes;
632 term->set_terminal_window_hook = w32con_set_terminal_window;
633 term->update_begin_hook = w32con_update_begin;
634 term->update_end_hook = w32con_update_end;
635
636 term->read_socket_hook = w32_console_read_socket;
637 term->mouse_position_hook = w32_console_mouse_position;
638
639
640 term->frame_rehighlight_hook = 0;
641 term->frame_raise_lower_hook = 0;
642 term->set_vertical_scroll_bar_hook = 0;
643 term->condemn_scroll_bars_hook = 0;
644 term->redeem_scroll_bar_hook = 0;
645 term->judge_scroll_bars_hook = 0;
646 term->frame_up_to_date_hook = 0;
647
648
649 init_crit ();
650
651
652 keyboard_handle = GetStdHandle (STD_INPUT_HANDLE);
653 GetConsoleMode (keyboard_handle, &prev_console_mode);
654
655 prev_screen = GetStdHandle (STD_OUTPUT_HANDLE);
656
657 #ifdef USE_SEPARATE_SCREEN
658 cur_screen = CreateConsoleScreenBuffer (GENERIC_READ | GENERIC_WRITE,
659 0, NULL,
660 CONSOLE_TEXTMODE_BUFFER,
661 NULL);
662
663 if (cur_screen == INVALID_HANDLE_VALUE)
664 {
665 printf ("CreateConsoleScreenBuffer failed in ResetTerm\n");
666 printf ("LastError = 0x%lx\n", GetLastError ());
667 fflush (stdout);
668 exit (0);
669 }
670 #else
671 cur_screen = prev_screen;
672 GetConsoleCursorInfo (prev_screen, &prev_console_cursor);
673 #endif
674
675
676 {
677 char * lines = getenv("LINES");
678 char * columns = getenv("COLUMNS");
679
680 if (lines != NULL && columns != NULL)
681 {
682 SMALL_RECT new_win_dims;
683 COORD new_size;
684
685 new_size.X = atoi (columns);
686 new_size.Y = atoi (lines);
687
688 GetConsoleScreenBufferInfo (cur_screen, &info);
689
690 691
692 new_win_dims.Top = 0;
693 new_win_dims.Left = 0;
694 new_win_dims.Bottom = min (new_size.Y, info.dwSize.Y) - 1;
695 new_win_dims.Right = min (new_size.X, info.dwSize.X) - 1;
696 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
697
698 SetConsoleScreenBufferSize (cur_screen, new_size);
699
700
701 new_win_dims.Top = 0;
702 new_win_dims.Left = 0;
703 new_win_dims.Bottom = new_size.Y - 1;
704 new_win_dims.Right = new_size.X - 1;
705 SetConsoleWindowInfo (cur_screen, TRUE, &new_win_dims);
706 }
707 }
708
709 GetConsoleScreenBufferInfo (cur_screen, &info);
710
711 char_attr_normal = info.wAttributes;
712
713 714 715 716
717 if ((w32_use_full_screen_buffer
718 && (info.dwSize.Y < 20 || info.dwSize.Y > 100
719 || info.dwSize.X < 40 || info.dwSize.X > 200))
720 || (!w32_use_full_screen_buffer
721 && (info.srWindow.Bottom - info.srWindow.Top < 20
722 || info.srWindow.Bottom - info.srWindow.Top > 100
723 || info.srWindow.Right - info.srWindow.Left < 40
724 || info.srWindow.Right - info.srWindow.Left > 100)))
725 {
726 FRAME_LINES (SELECTED_FRAME ()) = 25;
727 SET_FRAME_COLS (SELECTED_FRAME (), 80);
728 }
729
730 else if (w32_use_full_screen_buffer)
731 {
732 FRAME_LINES (SELECTED_FRAME ()) = info.dwSize.Y;
733 SET_FRAME_COLS (SELECTED_FRAME (), info.dwSize.X);
734 }
735 else
736 {
737
738 FRAME_LINES (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
739 info.srWindow.Top;
740
741 SET_FRAME_COLS (SELECTED_FRAME (), 1 + info.srWindow.Right -
742 info.srWindow.Left);
743 }
744
745
746
747 w32_initialize_display_info (build_string ("Console"));
748
749 }
750
751
752 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
753 doc: )
754 (foreground, background)
755 Lisp_Object foreground;
756 Lisp_Object background;
757 {
758 char_attr_normal = XFASTINT (foreground) + (XFASTINT (background) << 4);
759
760 Frecenter (Qnil);
761 return Qt;
762 }
763
764 DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
765 doc: )
766 (size)
767 Lisp_Object size;
768 {
769 CONSOLE_CURSOR_INFO cci;
770 cci.dwSize = XFASTINT (size);
771 cci.bVisible = TRUE;
772 (void) SetConsoleCursorInfo (cur_screen, &cci);
773
774 return Qt;
775 }
776
777 void
778 syms_of_ntterm ()
779 {
780 DEFVAR_BOOL ("w32-use-full-screen-buffer",
781 &w32_use_full_screen_buffer,
782 doc: 783 784 785 786 );
787 w32_use_full_screen_buffer = 0;
788
789 defsubr (&Sset_screen_color);
790 defsubr (&Sset_cursor_size);
791 defsubr (&Sset_message_beep);
792 }
793
794 795