comparison src/w32console.c @ 27395:fe54558f20d8

(turn_on_face, turn_off_face): New functions. (change_line_highlight): New prototype for new redisplay. (write_glyphs): Support multibyte text. Support faces.
author Jason Rumney <jasonr@gnu.org>
date Sun, 23 Jan 2000 03:16:02 +0000
parents a4c871b96d4b
children ff2e0205b5a0
comparison
equal deleted inserted replaced
27394:06b36e62c2b8 27395:fe54558f20d8
1 /* Terminal hooks for GNU Emacs on the Microsoft W32 API. 1 /* Terminal hooks for GNU Emacs on the Microsoft W32 API.
2 Copyright (C) 1992 Free Software Foundation, Inc. 2 Copyright (C) 1992, 1999 Free Software Foundation, Inc.
3 3
4 This file is part of GNU Emacs. 4 This file is part of GNU Emacs.
5 5
6 GNU Emacs is free software; you can redistribute it and/or modify 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 7 it under the terms of the GNU General Public License as published by
27 27
28 #include <stdlib.h> 28 #include <stdlib.h>
29 #include <stdio.h> 29 #include <stdio.h>
30 #include <windows.h> 30 #include <windows.h>
31 31
32 /* Disable features in headers that require a Window System for
33 console mode. */
34 #undef HAVE_WINDOW_SYSTEM
35
32 #include "lisp.h" 36 #include "lisp.h"
33 #include "charset.h" 37 #include "charset.h"
38 #include "coding.h"
34 #include "frame.h" 39 #include "frame.h"
35 #include "disptab.h" 40 #include "disptab.h"
36 #include "termhooks.h" 41 #include "termhooks.h"
37 #include "w32inevt.h" 42 #include "w32inevt.h"
43 #include "dispextern.h"
38 44
39 /* from window.c */ 45 /* from window.c */
40 extern Lisp_Object Frecenter (); 46 extern Lisp_Object Frecenter ();
41 47
42 /* from keyboard.c */ 48 /* from keyboard.c */
43 extern int detect_input_pending (); 49 extern int detect_input_pending ();
44 50
45 /* from sysdep.c */ 51 /* from sysdep.c */
46 extern int read_input_pending (); 52 extern int read_input_pending ();
47 53
48 extern FRAME_PTR updating_frame; 54 extern struct frame * updating_frame;
49 extern int meta_key; 55 extern int meta_key;
50 56
51 static void move_cursor (int row, int col); 57 static void move_cursor (int row, int col);
52 static void clear_to_end (void); 58 static void clear_to_end (void);
53 static void clear_frame (void); 59 static void clear_frame (void);
54 static void clear_end_of_line (int); 60 static void clear_end_of_line (int);
55 static void ins_del_lines (int vpos, int n); 61 static void ins_del_lines (int vpos, int n);
56 static void change_line_highlight (int, int, int); 62 static void change_line_highlight (int, int, int, int);
57 static void reassert_line_highlight (int, int); 63 static void reassert_line_highlight (int, int);
58 static void insert_glyphs (GLYPH *start, int len); 64 static void insert_glyphs (struct glyph *start, int len);
59 static void write_glyphs (GLYPH *string, int len); 65 static void write_glyphs (struct glyph *string, int len);
60 static void delete_glyphs (int n); 66 static void delete_glyphs (int n);
61 void w32_sys_ring_bell (void); 67 void w32_sys_ring_bell (void);
62 static void reset_terminal_modes (void); 68 static void reset_terminal_modes (void);
63 static void set_terminal_modes (void); 69 static void set_terminal_modes (void);
64 static void set_terminal_window (int size); 70 static void set_terminal_window (int size);
65 static void update_begin (FRAME_PTR f); 71 static void update_begin (struct frame * f);
66 static void update_end (FRAME_PTR f); 72 static void update_end (struct frame * f);
67 static int hl_mode (int new_highlight); 73 static int hl_mode (int new_highlight);
74 static void turn_on_face P_ ((struct frame *, int face_id));
75 static void turn_off_face P_ ((struct frame *, int face_id));
68 76
69 COORD cursor_coords; 77 COORD cursor_coords;
70 HANDLE prev_screen, cur_screen; 78 HANDLE prev_screen, cur_screen;
71 UCHAR char_attr, char_attr_normal, char_attr_reverse; 79 UCHAR char_attr, char_attr_normal, char_attr_reverse;
72 HANDLE keyboard_handle; 80 HANDLE keyboard_handle;
95 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)); 103 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
96 } 104 }
97 105
98 /* If we're updating a frame, use it as the current frame 106 /* If we're updating a frame, use it as the current frame
99 Otherwise, use the selected frame. */ 107 Otherwise, use the selected frame. */
100 #define PICK_FRAME() (updating_frame ? updating_frame : selected_frame) 108 #define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
101 109
102 /* Move the cursor to (row, col). */ 110 /* Move the cursor to (row, col). */
103 void 111 void
104 move_cursor (int row, int col) 112 move_cursor (int row, int col)
105 { 113 {
106 cursor_coords.X = col; 114 cursor_coords.X = col;
107 cursor_coords.Y = row; 115 cursor_coords.Y = row;
108 116
109 if (updating_frame == (FRAME_PTR) NULL) 117 if (updating_frame == (struct frame *) NULL)
110 { 118 {
111 SetConsoleCursorPosition (cur_screen, cursor_coords); 119 SetConsoleCursorPosition (cur_screen, cursor_coords);
112 } 120 }
113 } 121 }
114 122
115 /* Clear from cursor to end of screen. */ 123 /* Clear from cursor to end of screen. */
116 void 124 void
117 clear_to_end (void) 125 clear_to_end (void)
118 { 126 {
119 FRAME_PTR f = PICK_FRAME (); 127 struct frame * f = PICK_FRAME ();
120 128
121 clear_end_of_line (FRAME_WIDTH (f) - 1); 129 clear_end_of_line (FRAME_WIDTH (f) - 1);
122 ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1); 130 ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
123 } 131 }
124 132
125 /* Clear the frame. */ 133 /* Clear the frame. */
126 void 134 void
127 clear_frame (void) 135 clear_frame (void)
128 { 136 {
129 FRAME_PTR f = PICK_FRAME (); 137 struct frame * f = PICK_FRAME ();
130 COORD dest; 138 COORD dest;
131 int n, r; 139 int n, r;
132 CONSOLE_SCREEN_BUFFER_INFO info; 140 CONSOLE_SCREEN_BUFFER_INFO info;
133 141
134 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info); 142 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
144 152
145 move_cursor (0, 0); 153 move_cursor (0, 0);
146 } 154 }
147 155
148 156
149 static GLYPH glyph_base[256]; 157 static struct glyph glyph_base[256];
150 static BOOL ceol_initialized = FALSE; 158 static BOOL ceol_initialized = FALSE;
151 159
152 /* Clear from Cursor to end (what's "standout marker"?). */ 160 /* Clear from Cursor to end (what's "standout marker"?). */
153 void 161 void
154 clear_end_of_line (int end) 162 clear_end_of_line (int end)
156 if (!ceol_initialized) 164 if (!ceol_initialized)
157 { 165 {
158 int i; 166 int i;
159 for (i = 0; i < 256; i++) 167 for (i = 0; i < 256; i++)
160 { 168 {
161 glyph_base[i] = SPACEGLYPH; /* empty space */ 169 memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
162 } 170 }
163 ceol_initialized = TRUE; 171 ceol_initialized = TRUE;
164 } 172 }
165 write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */ 173 write_glyphs (glyph_base, end - cursor_coords.X); /* fencepost ? */
166 } 174 }
171 { 179 {
172 int i, nb, save_highlight; 180 int i, nb, save_highlight;
173 SMALL_RECT scroll; 181 SMALL_RECT scroll;
174 COORD dest; 182 COORD dest;
175 CHAR_INFO fill; 183 CHAR_INFO fill;
176 FRAME_PTR f = PICK_FRAME (); 184 struct frame * f = PICK_FRAME ();
177 185
178 if (n < 0) 186 if (n < 0)
179 { 187 {
180 scroll.Top = vpos - n; 188 scroll.Top = vpos - n;
181 scroll.Bottom = FRAME_HEIGHT (f); 189 scroll.Bottom = FRAME_HEIGHT (f);
258 } 266 }
259 267
260 /* Call this when about to modify line at position VPOS and change whether it 268 /* Call this when about to modify line at position VPOS and change whether it
261 is highlighted. */ 269 is highlighted. */
262 void 270 void
263 change_line_highlight (int new_highlight, int vpos, int first_unused_hpos) 271 change_line_highlight (int new_highlight, int vpos, int y,
272 int first_unused_hpos)
264 { 273 {
265 hl_mode (new_highlight); 274 hl_mode (new_highlight);
266 move_cursor (vpos, 0); 275 move_cursor (vpos, 0);
267 clear_end_of_line (first_unused_hpos); 276 clear_end_of_line (first_unused_hpos);
268 } 277 }
287 /* The idea here is to implement a horizontal scroll in one line to 296 /* The idea here is to implement a horizontal scroll in one line to
288 implement delete and half of insert. */ 297 implement delete and half of insert. */
289 SMALL_RECT scroll; 298 SMALL_RECT scroll;
290 COORD dest; 299 COORD dest;
291 CHAR_INFO fill; 300 CHAR_INFO fill;
292 FRAME_PTR f = PICK_FRAME (); 301 struct frame * f = PICK_FRAME ();
293 302
294 scroll.Top = cursor_coords.Y; 303 scroll.Top = cursor_coords.Y;
295 scroll.Bottom = cursor_coords.Y; 304 scroll.Bottom = cursor_coords.Y;
296 305
297 if (direction == LEFT) 306 if (direction == LEFT)
315 } 324 }
316 325
317 326
318 /* If start is zero insert blanks instead of a string at start ?. */ 327 /* If start is zero insert blanks instead of a string at start ?. */
319 void 328 void
320 insert_glyphs (register GLYPH *start, register int len) 329 insert_glyphs (register struct glyph *start, register int len)
321 { 330 {
322 scroll_line (len, RIGHT); 331 scroll_line (len, RIGHT);
323 332
324 /* Move len chars to the right starting at cursor_coords, fill with blanks */ 333 /* Move len chars to the right starting at cursor_coords, fill with blanks */
325 if (start) 334 if (start)
334 clear_end_of_line (cursor_coords.X + len); 343 clear_end_of_line (cursor_coords.X + len);
335 } 344 }
336 } 345 }
337 346
338 void 347 void
339 write_glyphs (register GLYPH *string, register int len) 348 write_glyphs (register struct glyph *string, register int len)
340 { 349 {
341 register unsigned int glyph_len = GLYPH_TABLE_LENGTH; 350 int produced, consumed, i;
342 Lisp_Object *glyph_table = GLYPH_TABLE_BASE; 351 struct frame * f = PICK_FRAME ();
343 FRAME_PTR f = PICK_FRAME (); 352
344 register char *ptr; 353 /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
345 GLYPH glyph; 354 the tail. */
346 char *chars; 355 terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
347 int i; 356
348 357 while (len > 0)
349 if (len <= 0) 358 {
350 return; 359 /* Identify a run of glyphs with the same face. */
351 360 int face_id = string->face_id;
352 chars = alloca (len * sizeof (*chars)); 361 int n;
353 if (chars == NULL) 362
354 { 363 for (n = 1; n < len; ++n)
355 printf ("alloca failed in write_glyphs\n"); 364 if (string[n].face_id != face_id)
356 return; 365 break;
357 } 366
358 367 /* Turn appearance modes of the face of the run on. */
359 /* We have to deal with the glyph indirection...go over the glyph 368 turn_on_face (f, face_id);
360 buffer and extract the characters. */ 369
361 ptr = chars; 370 while (n > 0)
362 while (--len >= 0)
363 {
364 glyph = *string++;
365
366 if (glyph > glyph_len)
367 { 371 {
368 *ptr++ = glyph & 0xFF; 372 /* We use a shared conversion buffer of the current size
369 continue; 373 (1024 bytes at least). Usually it is sufficient, but if
370 } 374 not, we just repeat the loop. */
371 GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph); 375 produced = encode_terminal_code (string, conversion_buffer,
372 #ifndef HAVE_NTGUI 376 n, conversion_buffer_size,
373 if (GLYPH_FACE (fixfix, glyph) != 0) 377 &consumed);
374 printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph)); 378 if (produced > 0)
375 #endif /* !HAVE_NTGUI */ 379 {
376 if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph)) 380 /* Set the attribute for these characters. */
381 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
382 produced, cursor_coords, &i))
383 {
384 printf ("Failed writing console attributes: %d\n",
385 GetLastError ());
386 fflush (stdout);
387 }
388
389 /* Write the characters. */
390 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
391 produced, cursor_coords, &i))
392 {
393 printf ("Failed writing console characters: %d\n",
394 GetLastError ());
395 fflush (stdout);
396 }
397
398 cursor_coords.X += produced;
399 move_cursor (cursor_coords.Y, cursor_coords.X);
400 }
401 len -= consumed;
402 n -= consumed;
403 string += consumed;
404 }
405
406 /* Turn appearance modes off. */
407 turn_off_face (f, face_id);
408 }
409
410 /* We may have to output some codes to terminate the writing. */
411 if (CODING_REQUIRE_FLUSHING (&terminal_coding))
412 {
413 terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
414 encode_coding (&terminal_coding, "", conversion_buffer,
415 0, conversion_buffer_size);
416 if (terminal_coding.produced > 0)
377 { 417 {
378 *ptr++ = glyph & 0xFF; 418 if (!FillConsoleOutputAttribute (cur_screen, char_attr,
379 continue; 419 terminal_coding.produced,
380 } 420 cursor_coords, &i))
381 for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++) 421 {
382 { 422 printf ("Failed writing console attributes: %d\n",
383 *ptr++ = (GLYPH_STRING (glyph_table, glyph))[i]; 423 GetLastError ());
384 } 424 fflush (stdout);
385 } 425 }
386 426
387 /* Number of characters we have in the buffer. */ 427 /* Write the characters. */
388 len = ptr-chars; 428 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
389 429 produced, cursor_coords, &i))
390 /* Set the attribute for these characters. */ 430 {
391 if (!FillConsoleOutputAttribute (cur_screen, char_attr, len, cursor_coords, &i)) 431 printf ("Failed writing console characters: %d\n",
392 { 432 GetLastError ());
393 printf ("Failed writing console attributes: %d\n", GetLastError ()); 433 fflush (stdout);
394 fflush (stdout); 434 }
395 } 435 }
396 436 }
397 /* Write the characters. */ 437 }
398 if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i)) 438
399 {
400 printf ("Failed writing console characters: %d\n", GetLastError ());
401 fflush (stdout);
402 }
403
404 cursor_coords.X += len;
405 move_cursor (cursor_coords.Y, cursor_coords.X);
406 }
407 439
408 void 440 void
409 delete_glyphs (int n) 441 delete_glyphs (int n)
410 { 442 {
411 /* delete chars means scroll chars from cursor_coords.X + n to 443 /* delete chars means scroll chars from cursor_coords.X + n to
497 /* hmmm... perhaps these let us bracket screen changes so that we can flush 529 /* hmmm... perhaps these let us bracket screen changes so that we can flush
498 clumps rather than one-character-at-a-time... 530 clumps rather than one-character-at-a-time...
499 531
500 we'll start with not moving the cursor while an update is in progress. */ 532 we'll start with not moving the cursor while an update is in progress. */
501 void 533 void
502 update_begin (FRAME_PTR f) 534 update_begin (struct frame * f)
503 { 535 {
504 } 536 }
505 537
506 void 538 void
507 update_end (FRAME_PTR f) 539 update_end (struct frame * f)
508 { 540 {
509 SetConsoleCursorPosition (cur_screen, cursor_coords); 541 SetConsoleCursorPosition (cur_screen, cursor_coords);
510 } 542 }
511 543
512 void 544 void
513 set_terminal_window (int size) 545 set_terminal_window (int size)
514 { 546 {
515 } 547 }
516 548
549 /***********************************************************************
550 Faces
551 ***********************************************************************/
552
553
554 /* Turn appearances of face FACE_ID on tty frame F on. */
555
556 static void
557 turn_on_face (f, face_id)
558 struct frame *f;
559 int face_id;
560 {
561 struct face *face = FACE_FROM_ID (f, face_id);
562
563 xassert (face != NULL);
564
565 char_attr = char_attr_normal;
566
567 if (face->foreground != FACE_TTY_DEFAULT_COLOR)
568 char_attr = (char_attr & 0xf0) + face->foreground;
569
570 if (face->background != FACE_TTY_DEFAULT_COLOR)
571 char_attr = (face->background << 4) + char_attr & 0x0f;
572
573 if (face->tty_reverse_p)
574 char_attr = ((char_attr & 0x0f) << 4) + ((char_attr & 0xf0) >> 4);
575
576 /* Ensure readability */
577 if (((char_attr & 0xf0) >> 4) == (char_attr * 0x0f))
578 char_attr ^= 0x0f;
579 }
580
581
582 /* Turn off appearances of face FACE_ID on tty frame F. */
583
584 static void
585 turn_off_face (f, face_id)
586 struct frame *f;
587 int face_id;
588 {
589 if (hl_mode (0))
590 hl_mode (1);
591 }
592
517 typedef int (*term_hook) (); 593 typedef int (*term_hook) ();
518 594
519 void 595 void
520 initialize_w32_display (void) 596 initialize_w32_display (void)
521 { 597 {
539 update_begin_hook = update_begin; 615 update_begin_hook = update_begin;
540 update_end_hook = update_end; 616 update_end_hook = update_end;
541 617
542 read_socket_hook = w32_console_read_socket; 618 read_socket_hook = w32_console_read_socket;
543 mouse_position_hook = w32_console_mouse_position; 619 mouse_position_hook = w32_console_mouse_position;
620 estimate_mode_line_height_hook = 0;
544 621
545 /* Initialize interrupt_handle. */ 622 /* Initialize interrupt_handle. */
546 init_crit (); 623 init_crit ();
547 624
548 /* Remember original console settings. */ 625 /* Remember original console settings. */
610 char_attr_normal = char_attr; 687 char_attr_normal = char_attr;
611 char_attr_reverse = ((char_attr & 0xf) << 4) + ((char_attr & 0xf0) >> 4); 688 char_attr_reverse = ((char_attr & 0xf) << 4) + ((char_attr & 0xf0) >> 4);
612 689
613 if (w32_use_full_screen_buffer) 690 if (w32_use_full_screen_buffer)
614 { 691 {
615 FRAME_HEIGHT (selected_frame) = info.dwSize.Y; /* lines per page */ 692 FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
616 SET_FRAME_WIDTH (selected_frame, info.dwSize.X); /* characters per line */ 693 SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
617 } 694 }
618 else 695 else
619 { 696 {
620 /* Lines per page. Use buffer coords instead of buffer size. */ 697 /* Lines per page. Use buffer coords instead of buffer size. */
621 FRAME_HEIGHT (selected_frame) = 1 + info.srWindow.Bottom - 698 FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
622 info.srWindow.Top; 699 info.srWindow.Top;
623 /* Characters per line. Use buffer coords instead of buffer size. */ 700 /* Characters per line. Use buffer coords instead of buffer size. */
624 SET_FRAME_WIDTH (selected_frame, 1 + info.srWindow.Right - 701 SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right -
625 info.srWindow.Left); 702 info.srWindow.Left);
626 } 703 }
627 } 704 }
628 705
629 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0, 706 DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0,
652 return Qt; 729 return Qt;
653 } 730 }
654 731
655 #ifndef HAVE_NTGUI 732 #ifndef HAVE_NTGUI
656 void 733 void
657 pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y, 734 pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
658 void *bounds, int noclip) 735 void *bounds, int noclip)
659 { 736 {
660 *x = pix_x; 737 *x = pix_x;
661 *y = pix_y; 738 *y = pix_y;
662 } 739 }
663 740
664 void 741 void
665 glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y) 742 glyph_to_pixel_coords (struct frame * f, int x, int y, int *pix_x, int *pix_y)
666 { 743 {
667 *pix_x = x; 744 *pix_x = x;
668 *pix_y = y; 745 *pix_y = y;
669 } 746 }
670 #endif /* !HAVE_NTGUI */ 747 #endif /* !HAVE_NTGUI */