aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorewantown2025-10-12 07:23:53 -0700
committerEli Zaretskii2026-04-08 15:12:14 +0300
commit2bca4ac0ed7f9911c5d1443615ec3e1ac3364a8d (patch)
tree77583a72152db370e2430a2f110c5f063f933fb4 /src
parent9b8361d9abddb32a343ba325421bad13be2837b8 (diff)
downloademacs-2bca4ac0ed7f9911c5d1443615ec3e1ac3364a8d.tar.gz
emacs-2bca4ac0ed7f9911c5d1443615ec3e1ac3364a8d.zip
Support 24-bit TrueColor on MS-Windows console
* src/w32console.c (DEFAULTP, SSPRINTF, w32con_write_vt_seq) (w32con_get_cursor_coords): New functions and macros. (w32con_write_glyphs): Hide cursor before writing to the console. Add code for writing in virtual-terminal mode when 'w32_use_virtual_terminal' is non-zero. (w32con_write_glyphs_with_face): Add code for writing in virtual-terminal mode when 'w32_use_virtual_terminal' is non-zero. (w32con_setup_virtual_terminal): New function. (w32con_set_terminal_modes): Call it. (turn_on_face, turn_off_face): New functions. (initialize_w32_display): Save background and foreground, and the current TTY. (Fset_screen_color): Accept an additional optional argument VTP; if non-nil, arrange for 24-bit display to use the specified colors. (Fget_screen_color): Accept an additional optional argument VTP; if non-nil, return colors used by 24-bit display. (Fw32_use_virtual_terminal, Fw32_use_virtual_terminal_p): New functions. * src/term.c (tty_setup_colors) [WINDOWSNT]: Set up virtual-terminal sequences for colors. (init_tty) [WINDOWSNT]: Set up terminfo capabilities for Windows virtual-terminal. * src/xdisp.c (redisplay_internal): Don't call set_tty_color_mode for WINDOWSNT. * lisp/term/w32console.el (w32-tty-set-base-colors) (w32-tty-define-base-colors, w32-tty-define-8bit-colors) (w32-tty-define-24bit-colors, w32-tty-get-pixel): New functions. (terminal-init-w32console): Remove color setup. (w32-tty-setup-colors): New function. * lisp/term/tty-colors.el (tty-color-mode-alist): Add --color modes for 256 and 24-bit color modes. * lisp/startup.el (tty-handle-args): Fix --color handling. * lisp/faces.el (tty-set-up-initial-frame-faces): Set up colors for MS-Windows consoles. * etc/NEWS: * doc/emacs/msdos.texi (Windows Misc): * doc/emacs/cmdargs.texi (Colors X): Document 24-bit color support on MS-Windows. (Bug#79298)
Diffstat (limited to 'src')
-rw-r--r--src/term.c51
-rw-r--r--src/termchar.h2
-rw-r--r--src/w32console.c348
-rw-r--r--src/xdisp.c2
4 files changed, 339 insertions, 64 deletions
diff --git a/src/term.c b/src/term.c
index b5cf418450f..766eeebe5e8 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2207,7 +2207,7 @@ TERMINAL does not refer to a text terminal. */)
2207 return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0); 2207 return make_fixnum (t ? t->display_info.tty->TN_max_colors : 0);
2208} 2208}
2209 2209
2210#if !defined DOS_NT && !defined HAVE_ANDROID 2210#if !defined MSDOS && !defined HAVE_ANDROID
2211 2211
2212/* Declare here rather than in the function, as in the rest of Emacs, 2212/* Declare here rather than in the function, as in the rest of Emacs,
2213 to work around an HPUX compiler bug (?). See 2213 to work around an HPUX compiler bug (?). See
@@ -2246,7 +2246,7 @@ tty_default_color_capabilities (struct tty_display_info *tty, bool save)
2246 MODE's value is generally the number of colors which we want to 2246 MODE's value is generally the number of colors which we want to
2247 support; zero means set up for the default capabilities, the ones 2247 support; zero means set up for the default capabilities, the ones
2248 we saw at init_tty time; -1 means turn off color support. */ 2248 we saw at init_tty time; -1 means turn off color support. */
2249static void 2249void
2250tty_setup_colors (struct tty_display_info *tty, int mode) 2250tty_setup_colors (struct tty_display_info *tty, int mode)
2251{ 2251{
2252 /* Canonicalize all negative values of MODE. */ 2252 /* Canonicalize all negative values of MODE. */
@@ -2269,6 +2269,10 @@ tty_setup_colors (struct tty_display_info *tty, int mode)
2269#ifdef TERMINFO 2269#ifdef TERMINFO
2270 tty->TS_set_foreground = "\033[3%p1%dm"; 2270 tty->TS_set_foreground = "\033[3%p1%dm";
2271 tty->TS_set_background = "\033[4%p1%dm"; 2271 tty->TS_set_background = "\033[4%p1%dm";
2272#elif WINDOWSNT
2273 tty->TS_orig_pair = "\x1b[39m\x1b[49m";
2274 tty->TS_set_foreground = "\x1b[%lum";
2275 tty->TS_set_background = "\x1b[%lum";
2272#else 2276#else
2273 tty->TS_set_foreground = "\033[3%dm"; 2277 tty->TS_set_foreground = "\033[3%dm";
2274 tty->TS_set_background = "\033[4%dm"; 2278 tty->TS_set_background = "\033[4%dm";
@@ -2276,6 +2280,26 @@ tty_setup_colors (struct tty_display_info *tty, int mode)
2276 tty->TN_max_colors = 8; 2280 tty->TN_max_colors = 8;
2277 tty->TN_no_color_video = 0; 2281 tty->TN_no_color_video = 0;
2278 break; 2282 break;
2283#ifdef WINDOWSNT
2284 case 16:
2285 tty->TN_max_colors = 16;
2286 tty->TS_set_foreground = "\x1b[%lum";
2287 tty->TS_set_background = "\x1b[%lum";
2288 tty->TN_no_color_video = 0;
2289 break;
2290 case 256:
2291 tty->TN_max_colors = 256;
2292 tty->TS_set_foreground = "\x1b[38;5;%lum";
2293 tty->TS_set_background = "\x1b[48;5;%lum";
2294 tty->TN_no_color_video = 0;
2295 break;
2296 case 16777216:
2297 tty->TN_max_colors = 16777216;
2298 tty->TS_set_foreground = "\x1b[38;2;%lu;%lu;%lum";
2299 tty->TS_set_background = "\x1b[48;2;%lu;%lu;%lum";
2300 tty->TN_no_color_video = 0;
2301 break;
2302#endif
2279 } 2303 }
2280} 2304}
2281 2305
@@ -2312,7 +2336,7 @@ set_tty_color_mode (struct tty_display_info *tty, struct frame *f)
2312 } 2336 }
2313} 2337}
2314 2338
2315#endif /* !DOS_NT && !HAVE_ANDROID */ 2339#endif /* !MSDOS && !HAVE_ANDROID */
2316 2340
2317char * 2341char *
2318tty_type_name (Lisp_Object terminal) 2342tty_type_name (Lisp_Object terminal)
@@ -4644,6 +4668,22 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4644 4668
4645 initialize_w32_display (terminal, &width, &height); 4669 initialize_w32_display (terminal, &width, &height);
4646 4670
4671 tty->TN_no_color_video = 0;
4672 tty->TN_max_colors = 16777216;
4673 tty->TS_orig_pair = "\x1b[39m\x1b[49m";
4674 tty->TS_set_foreground = "\x1b[38;2;%lu;%lu;%lum";
4675 tty->TS_set_background = "\x1b[48;2;%lu;%lu;%lum";
4676
4677 /* Save default color capabilities */
4678 tty_default_color_capabilities (tty, 1);
4679
4680 tty->TS_enter_bold_mode = "\x1b[1m";
4681 tty->TS_enter_italic_mode = "\x1b[3m";
4682 tty->TS_enter_strike_through_mode = "\x1b[9m";
4683 tty->TS_enter_underline_mode = "\x1b[4m";
4684 tty->TS_enter_reverse_mode = "\x1b[7m";
4685 tty->TS_exit_attribute_mode = "\x1b[0m";
4686
4647 FrameRows (tty) = height; 4687 FrameRows (tty) = height;
4648 FrameCols (tty) = width; 4688 FrameCols (tty) = width;
4649 tty->specified_window = height; 4689 tty->specified_window = height;
@@ -4689,7 +4729,6 @@ use the Bourne shell command 'TERM=...; export TERM' (C-shell:\n\
4689 don't think we're losing anything by turning it off. */ 4729 don't think we're losing anything by turning it off. */
4690 tty->line_ins_del_ok = 0; 4730 tty->line_ins_del_ok = 0;
4691 4731
4692 tty->TN_max_colors = 16; /* Must be non-zero for tty-display-color-p. */
4693#endif /* DOS_NT */ 4732#endif /* DOS_NT */
4694 4733
4695#ifdef HAVE_GPM 4734#ifdef HAVE_GPM
@@ -5205,11 +5244,11 @@ non-nil to enable this optimization. */);
5205 defsubr (&Stty_display_pixel_width); 5244 defsubr (&Stty_display_pixel_width);
5206 defsubr (&Stty_display_pixel_height); 5245 defsubr (&Stty_display_pixel_height);
5207 5246
5208#if !defined DOS_NT && !defined HAVE_ANDROID 5247#if !defined MSDOS && !defined HAVE_ANDROID
5209 default_orig_pair = NULL; 5248 default_orig_pair = NULL;
5210 default_set_foreground = NULL; 5249 default_set_foreground = NULL;
5211 default_set_background = NULL; 5250 default_set_background = NULL;
5212#endif /* !DOS_NT && !HAVE_ANDROID */ 5251#endif /* !MSDOS && !HAVE_ANDROID */
5213 5252
5214#ifndef HAVE_ANDROID 5253#ifndef HAVE_ANDROID
5215 encode_terminal_src = NULL; 5254 encode_terminal_src = NULL;
diff --git a/src/termchar.h b/src/termchar.h
index 9d7c3a2a555..9a9001d5cef 100644
--- a/src/termchar.h
+++ b/src/termchar.h
@@ -249,4 +249,6 @@ struct input_event;
249extern Lisp_Object tty_handle_tab_bar_click (struct frame *, int, int, bool, 249extern Lisp_Object tty_handle_tab_bar_click (struct frame *, int, int, bool,
250 struct input_event *); 250 struct input_event *);
251 251
252extern void tty_setup_colors (struct tty_display_info *tty, int mode);
253
252#endif /* EMACS_TERMCHAR_H */ 254#endif /* EMACS_TERMCHAR_H */
diff --git a/src/w32console.c b/src/w32console.c
index be5e0b92072..b0a2f0c1c0e 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -19,6 +19,9 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
19/* 19/*
20 Tim Fleehart (apollo@online.com) 1-17-92 20 Tim Fleehart (apollo@online.com) 1-17-92
21 Geoff Voelker (voelker@cs.washington.edu) 9-12-93 21 Geoff Voelker (voelker@cs.washington.edu) 9-12-93
22 Ewan Townshend (ewan@etown.dev) 2025-08
23 * c. ~ 2025: 24bit RGB support in Windows (10+) Terminal
24 * https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
22*/ 25*/
23 26
24 27
@@ -53,11 +56,17 @@ static void w32con_set_terminal_modes (struct terminal *t);
53static void w32con_update_begin (struct frame * f); 56static void w32con_update_begin (struct frame * f);
54static void w32con_update_end (struct frame * f); 57static void w32con_update_end (struct frame * f);
55static WORD w32_face_attributes (struct frame *f, int face_id); 58static WORD w32_face_attributes (struct frame *f, int face_id);
59static int w32con_write_vt_seq (const char *);
60static void turn_on_face (struct frame *, int face_id);
61static void turn_off_face (struct frame *, int face_id);
62static COORD w32con_get_cursor_coords ();
56 63
57static COORD cursor_coords; 64static COORD cursor_coords;
58static HANDLE prev_screen, cur_screen; 65static HANDLE prev_screen, cur_screen;
59static WORD char_attr_normal; 66static WORD char_attr_normal;
60static DWORD prev_console_mode; 67static DWORD prev_console_mode;
68static int bg_normal;
69static int fg_normal;
61 70
62static CONSOLE_CURSOR_INFO console_cursor_info; 71static CONSOLE_CURSOR_INFO console_cursor_info;
63#ifndef USE_SEPARATE_SCREEN 72#ifndef USE_SEPARATE_SCREEN
@@ -67,7 +76,10 @@ static CONSOLE_CURSOR_INFO prev_console_cursor;
67extern HANDLE keyboard_handle; 76extern HANDLE keyboard_handle;
68HANDLE keyboard_handle; 77HANDLE keyboard_handle;
69int w32_console_unicode_input; 78int w32_console_unicode_input;
70 79extern int w32_use_virtual_terminal;
80int w32_use_virtual_terminal = 1;
81extern struct tty_display_info *current_tty;
82struct tty_display_info *current_tty = NULL;
71 83
72/* Setting this as the ctrl handler prevents emacs from being killed when 84/* Setting this as the ctrl handler prevents emacs from being killed when
73 someone hits ^C in a 'suspended' session (child shell). 85 someone hits ^C in a 'suspended' session (child shell).
@@ -83,6 +95,38 @@ ctrl_c_handler (unsigned long type)
83 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT)); 95 && (type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT));
84} 96}
85 97
98#define DEFAULTP(p) \
99 (p == FACE_TTY_DEFAULT_COLOR \
100 || p == FACE_TTY_DEFAULT_FG_COLOR \
101 || p == FACE_TTY_DEFAULT_BG_COLOR)
102
103#define SEQMAX 256 /* Arbitrary upper limit on VT sequence size */
104
105#define SSPRINTF(buf, i, sz, fmt, ...) \
106 do { \
107 eassert (*i < sz && sz <= SEQMAX); \
108 if (fmt && *i < sz && sz <= SEQMAX) \
109 *i += snprintf (buf + *i, sz - *i, fmt, __VA_ARGS__); \
110 } while (0)
111
112/* Writes virtual terminal sequence to screen */
113static int
114w32con_write_vt_seq (const char *seq)
115{
116 char buf[SEQMAX];
117 DWORD n = 0, k = 0;
118 SSPRINTF (buf, &n, SEQMAX, seq, NULL);
119 if (n) WriteConsole (cur_screen, (LPCSTR) buf, n, &k, NULL);
120 return k;
121}
122
123static COORD
124w32con_get_cursor_coords ()
125{
126 CONSOLE_SCREEN_BUFFER_INFO info;
127 GetConsoleScreenBufferInfo (GetStdHandle (STD_OUTPUT_HANDLE), &info);
128 return info.dwCursorPosition;
129}
86 130
87/* Move the cursor to (ROW, COL) on FRAME. */ 131/* Move the cursor to (ROW, COL) on FRAME. */
88static void 132static void
@@ -309,10 +353,11 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
309 register int len) 353 register int len)
310{ 354{
311 DWORD r; 355 DWORD r;
312 WORD char_attr;
313 LPCSTR conversion_buffer; 356 LPCSTR conversion_buffer;
314 struct coding_system *coding; 357 struct coding_system *coding;
315 358
359 w32con_hide_cursor();
360
316 if (len <= 0) 361 if (len <= 0)
317 return; 362 return;
318 363
@@ -342,8 +387,6 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
342 387
343 /* w32con_clear_end_of_line sets frame of glyphs to NULL. */ 388 /* w32con_clear_end_of_line sets frame of glyphs to NULL. */
344 struct frame *attr_frame = face_id_frame ? face_id_frame : f; 389 struct frame *attr_frame = face_id_frame ? face_id_frame : f;
345 /* Turn appearance modes of the face of the run on. */
346 char_attr = w32_face_attributes (attr_frame, face_id);
347 390
348 if (n == len) 391 if (n == len)
349 /* This is the last run. */ 392 /* This is the last run. */
@@ -351,31 +394,45 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
351 conversion_buffer = (LPCSTR) encode_terminal_code (string, n, coding); 394 conversion_buffer = (LPCSTR) encode_terminal_code (string, n, coding);
352 if (coding->produced > 0) 395 if (coding->produced > 0)
353 { 396 {
354 /* Compute the string's width on display by accounting for 397 if (w32_use_virtual_terminal)
355 character's width. FIXME: this doesn't handle character
356 compositions. */
357 ptrdiff_t ncols = strwidth (coding->source, coding->src_bytes);
358 /* Set the attribute for these characters. */
359 if (!FillConsoleOutputAttribute (cur_screen, char_attr, ncols,
360 cursor_coords, &r))
361 { 398 {
362 printf ("Failed writing console attributes: %lu\n", 399 turn_on_face (f, face_id);
363 GetLastError ()); 400 WriteConsole (cur_screen, conversion_buffer,
364 fflush (stdout); 401 coding->produced, &r, NULL);
402 turn_off_face (f, face_id);
403 cursor_coords = w32con_get_cursor_coords ();
365 } 404 }
366 405 else
367 /* Write the characters. */
368 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
369 coding->produced, cursor_coords,
370 &r))
371 { 406 {
372 printf ("Failed writing console characters: %lu\n", 407 /* Account for character width.
373 GetLastError ()); 408 FIXME: this doesn't handle character compositions. */
374 fflush (stdout); 409 ptrdiff_t ncols = strwidth (coding->source, coding->src_bytes);
375 } 410
411 /* Turn appearance modes of the face of the run on. */
412 WORD char_attr = w32_face_attributes (attr_frame, face_id);
376 413
377 cursor_coords.X += ncols; 414 /* Set the attribute for these characters. */
378 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X); 415 if (!FillConsoleOutputAttribute (cur_screen, char_attr, ncols,
416 cursor_coords, &r))
417 {
418 printf ("Failed writing console attributes: %lu\n",
419 GetLastError ());
420 fflush (stdout);
421 }
422
423 /* Write the characters. */
424 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
425 coding->produced, cursor_coords,
426 &r))
427 {
428 printf ("Failed writing console characters: %lu\n",
429 GetLastError ());
430 fflush (stdout);
431 }
432
433 cursor_coords.X += ncols;
434 w32con_move_cursor (f, cursor_coords.Y, cursor_coords.X);
435 }
379 } 436 }
380 len -= n; 437 len -= n;
381 string += n; 438 string += n;
@@ -391,6 +448,8 @@ w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
391 LPCSTR conversion_buffer; 448 LPCSTR conversion_buffer;
392 struct coding_system *coding; 449 struct coding_system *coding;
393 450
451 w32con_hide_cursor();
452
394 if (len <= 0) 453 if (len <= 0)
395 return; 454 return;
396 455
@@ -407,28 +466,42 @@ w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
407 if (coding->produced > 0) 466 if (coding->produced > 0)
408 { 467 {
409 DWORD filled, written; 468 DWORD filled, written;
410 /* Compute the character attributes corresponding to the face. */ 469 if (w32_use_virtual_terminal)
411 DWORD char_attr = w32_face_attributes (f, face_id); 470 {
412 COORD start_coords; 471 COORD saved_coords = cursor_coords;
413 /* Compute the string's width on display by accounting for 472 w32con_move_cursor(f, y, x);
414 character's width. FIXME: this doesn't handle character 473 turn_on_face (f, face_id);
415 compositions. */ 474 WriteConsole (cur_screen, conversion_buffer,
416 ptrdiff_t ncols = strwidth (coding->source, coding->src_bytes); 475 coding->produced, &written, NULL);
417 476 turn_off_face (f, face_id);
418 start_coords.X = x; 477 w32con_move_cursor(f, saved_coords.Y, saved_coords.X);
419 start_coords.Y = y; 478 }
420 /* Set the attribute for these characters. */
421 if (!FillConsoleOutputAttribute (cur_screen, char_attr, ncols,
422 start_coords, &filled))
423 DebPrint (("Failed writing console attributes: %d\n", GetLastError ()));
424 else 479 else
425 { 480 {
426 /* Write the characters. */ 481 /* Compute the character attributes corresponding to the face. */
427 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer, 482 DWORD char_attr = w32_face_attributes (f, face_id);
428 coding->produced, start_coords, 483 COORD start_coords;
429 &written)) 484
430 DebPrint (("Failed writing console characters: %d\n", 485 start_coords.X = x;
431 GetLastError ())); 486 start_coords.Y = y;
487
488 /* Account for character width.
489 FIXME: this doesn't handle character compositions. */
490 ptrdiff_t ncols = strwidth (coding->source, coding->src_bytes);
491
492 /* Set the attribute for these characters. */
493 if (!FillConsoleOutputAttribute (cur_screen, char_attr, ncols,
494 start_coords, &filled))
495 DebPrint (("Failed writing console attributes: %d\n", GetLastError ()));
496 else
497 {
498 /* Write the characters. */
499 if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
500 coding->produced, start_coords,
501 &written))
502 DebPrint (("Failed writing console characters: %d\n",
503 GetLastError ()));
504 }
432 } 505 }
433 } 506 }
434} 507}
@@ -529,6 +602,33 @@ w32con_delete_glyphs (struct frame *f, int n)
529 scroll_line (f, n, LEFT); 602 scroll_line (f, n, LEFT);
530} 603}
531 604
605static void
606w32con_setup_virtual_terminal (void)
607{
608 /* Disable unless 24bit color is supported (v. > 10.0.15063). */
609 w32_use_virtual_terminal = w32_use_virtual_terminal
610 && (w32_major_version > 10
611 || (w32_major_version == 10
612 && (w32_minor_version > 0 || w32_build_number > 15063)));
613
614 DWORD out_mode;
615 GetConsoleMode (cur_screen, &out_mode);
616 out_mode |= ENABLE_PROCESSED_OUTPUT;
617 out_mode |= DISABLE_NEWLINE_AUTO_RETURN;
618
619 if (w32_use_virtual_terminal)
620 out_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
621 else
622 out_mode &= ~ENABLE_VIRTUAL_TERMINAL_PROCESSING;
623
624 int out_mode_set = SetConsoleMode (cur_screen, out_mode);
625 w32_use_virtual_terminal = w32_use_virtual_terminal && out_mode_set;
626
627 int max_colors = w32_use_virtual_terminal ? 16777216 : 16;
628 tty_setup_colors (current_tty, max_colors);
629
630 safe_calln (Qtty_set_up_initial_frame_faces);
631}
532 632
533static void 633static void
534w32con_reset_terminal_modes (struct terminal *t) 634w32con_reset_terminal_modes (struct terminal *t)
@@ -585,6 +685,7 @@ w32con_set_terminal_modes (struct terminal *t)
585 /* Initialize input mode: interrupt_input off, no flow control, allow 685 /* Initialize input mode: interrupt_input off, no flow control, allow
586 8 bit character input, standard quit char. */ 686 8 bit character input, standard quit char. */
587 Fset_input_mode (Qnil, Qnil, make_fixnum (2), Qnil); 687 Fset_input_mode (Qnil, Qnil, make_fixnum (2), Qnil);
688 w32con_setup_virtual_terminal ();
588} 689}
589 690
590/* hmmm... perhaps these let us bracket screen changes so that we can flush 691/* hmmm... perhaps these let us bracket screen changes so that we can flush
@@ -631,8 +732,6 @@ sys_tgetstr (char *cap, char **area)
631 stubs from cm.c 732 stubs from cm.c
632 ***********************************************************************/ 733 ***********************************************************************/
633 734
634extern struct tty_display_info *current_tty;
635struct tty_display_info *current_tty = NULL;
636extern int cost; 735extern int cost;
637int cost = 0; 736int cost = 0;
638 737
@@ -736,6 +835,87 @@ w32_face_attributes (struct frame *f, int face_id)
736 return char_attr; 835 return char_attr;
737} 836}
738 837
838static void
839turn_on_face (struct frame *f, int face_id)
840{
841 struct face *face = FACE_FROM_ID (f, face_id);
842 struct tty_display_info *tty = FRAME_TTY (f);
843 unsigned long fg = face->foreground;
844 unsigned long bg = face->background;
845
846 /* construct combined VT sequence for face attributes */
847 DWORD n = 0;
848 size_t sz = SEQMAX;
849 char seq[sz];
850 sz--;
851
852 if (face->tty_bold_p)
853 SSPRINTF (seq, &n, sz, tty->TS_enter_bold_mode, NULL);
854 if (face->tty_italic_p)
855 SSPRINTF (seq, &n, sz, tty->TS_enter_italic_mode, NULL);
856 if (face->tty_strike_through_p)
857 SSPRINTF (seq, &n, sz, tty->TS_enter_strike_through_mode, NULL);
858 if (face->underline != 0)
859 SSPRINTF (seq, &n, sz, tty->TS_enter_underline_mode, NULL);
860 /* Note: when face->tty_reverse_p != 0 and fg and bg are specified,
861 their values are already swapped and reversing them here would swap
862 them back, but we need to handle the reversal when unspecified. */
863 if (face->tty_reverse_p && DEFAULTP (fg) && DEFAULTP (bg))
864 SSPRINTF (seq, &n, sz, tty->TS_enter_reverse_mode, NULL);
865
866 if (DEFAULTP (fg)) fg = fg_normal;
867 if (DEFAULTP (bg)) bg = bg_normal;
868
869 const char *set_fg = tty->TS_set_foreground;
870 const char *set_bg = tty->TS_set_background;
871 if (tty->TN_max_colors == 8 || tty->TN_max_colors == 16)
872 {
873 /* fg and bg are indices into 16 base colors (see link at top). */
874 unsigned long fgi = 0, bgi = 0;
875
876 fgi = (fg >= 0 && fg < 8)
877 ? fg + 30
878 : (fg >= 8 && fg < 16)
879 ? fg - 8 + 90
880 : 0;
881 if (fgi)
882 SSPRINTF (seq, &n, sz, set_fg, fgi);
883
884 bgi = (bg >= 0 && bg < 8)
885 ? bg + 40
886 : (bg >= 8 && bg < 16)
887 ? bg - 8 + 100
888 : 0;
889 if (bgi)
890 SSPRINTF (seq, &n, sz, set_bg, bgi);
891 }
892 else if (tty->TN_max_colors == 256)
893 {
894 /* fg and bg are xterm indices. */
895 if (fg >= 0 && fg < 256)
896 SSPRINTF (seq, &n, sz, set_fg, fg);
897
898 if (bg >= 0 && bg < 256)
899 SSPRINTF (seq, &n, sz, set_bg, bg);
900 }
901 else if (tty->TN_max_colors == 16777216)
902 {
903 /* fg and bg are pixel values -- decompose to rgb triples. */
904 unsigned long rf = fg/65536, gf = (fg/256)&255, bf = fg&255;
905 unsigned long rb = bg/65536, gb = (bg/256)&255, bb = bg&255;
906 SSPRINTF (seq, &n, sz, set_fg, rf, gf, bf);
907 SSPRINTF (seq, &n, sz, set_bg, rb, gb, bb);
908 }
909 w32con_write_vt_seq ((const char *) seq);
910}
911
912static void
913turn_off_face (struct frame *f, int face_id)
914{
915 struct tty_display_info *tty = FRAME_TTY (f);
916 w32con_write_vt_seq (tty->TS_exit_attribute_mode);
917}
918
739/* The IME window is needed to receive the session notifications 919/* The IME window is needed to receive the session notifications
740 required to reset the low level keyboard hook state. */ 920 required to reset the low level keyboard hook state. */
741 921
@@ -868,6 +1048,8 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
868 } 1048 }
869 1049
870 char_attr_normal = info.wAttributes; 1050 char_attr_normal = info.wAttributes;
1051 fg_normal = char_attr_normal & 0x000f;
1052 bg_normal = (char_attr_normal >> 4) & 0x000f;
871 1053
872 /* Determine if the info returned by GetConsoleScreenBufferInfo 1054 /* Determine if the info returned by GetConsoleScreenBufferInfo
873 is realistic. Old MS Telnet servers used to only fill out 1055 is realistic. Old MS Telnet servers used to only fill out
@@ -921,31 +1103,81 @@ initialize_w32_display (struct terminal *term, int *width, int *height)
921 1103
922 /* Set up the keyboard hook. */ 1104 /* Set up the keyboard hook. */
923 setup_w32_kbdhook (hwnd); 1105 setup_w32_kbdhook (hwnd);
1106
1107 /* Set current_tty to the tty of this terminal */
1108 current_tty = term->display_info.tty;
924} 1109}
925 1110
926 1111
927DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 2, 0, 1112DEFUN ("set-screen-color", Fset_screen_color, Sset_screen_color, 2, 3, 0,
928 doc: /* Set screen foreground and background colors. 1113 doc: /* Set screen foreground and background colors.
929 1114
930Arguments should be indices between 0 and 15, see w32console.el. */) 1115Arguments should be indices for colors in the list returned by `tty-color-alist'.
931 (Lisp_Object foreground, Lisp_Object background) 1116If VTP is non-nil, settings affect virtual terminal processing only.
1117Otherwise, arguments should be between 0 and 15, and settings will
1118be effective only when virtual terminal processing is disabled.
1119
1120See w32console.el and the documentation for `w32-use-virtual-terminal'. */)
1121 (Lisp_Object foreground, Lisp_Object background, Lisp_Object vtp)
932{ 1122{
933 char_attr_normal = XFIXNAT (foreground) + (XFIXNAT (background) << 4); 1123 int fg = XFIXNAT (foreground);
1124 int bg = XFIXNAT (background);
1125
1126 if (NILP (vtp))
1127 {
1128 char_attr_normal = fg + (bg << 4);
1129 }
1130 else
1131 {
1132 fg_normal = fg;
1133 bg_normal = bg;
1134 }
934 1135
935 Frecenter (Qnil, Qt); 1136 Frecenter (Qnil, Qt);
936 return Qt; 1137 return Qt;
937} 1138}
938 1139
939DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 0, 0, 1140DEFUN ("get-screen-color", Fget_screen_color, Sget_screen_color, 0, 1, 0,
940 doc: /* Get color indices of the current screen foreground and background. 1141 doc: /* Get color indices of the current screen foreground and background.
941 1142
942The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND). 1143The colors are returned as a list of 2 indices (FOREGROUND BACKGROUND) for
943See w32console.el and `tty-defined-color-alist' for mapping of indices 1144colors in the list returned by `tty-color-alist`.
944to colors. */) 1145
1146If VTP is non-nil, returns settings effective when virtual terminal
1147processing is enabled. Otherwise, returns settings effective when
1148virtual terminal processing is disabled.
1149
1150See w32console.el and the documentation for `w32-use-virtual-terminal'. */)
1151 (Lisp_Object vtp)
1152{
1153 int fg = NILP (vtp) ? char_attr_normal & 0x000f : fg_normal;
1154 int bg = NILP (vtp) ? (char_attr_normal >> 4) & 0x000f : bg_normal;
1155
1156 return Fcons (make_fixnum (fg), Fcons (make_fixnum (bg), Qnil));
1157}
1158
1159DEFUN ("w32-use-virtual-terminal", Fw32_use_virtual_terminal, Sw32_use_virtual_terminal, 1, 1, 0,
1160 doc: /* Enables (disables) virtual terminal sequence processing if argument is t (nil). */)
1161 (Lisp_Object arg)
1162{
1163 if (EQ (arg, Qt))
1164 w32_use_virtual_terminal = 1;
1165 else if (EQ (arg, Qnil))
1166 w32_use_virtual_terminal = 0;
1167 else {
1168 error ("Invalid argument: expects t or nil.");
1169 return Qnil;
1170 }
1171
1172 w32con_setup_virtual_terminal ();
1173 return Qt;
1174}
1175
1176DEFUN ("w32-use-virtual-terminal-p", Fw32_use_virtual_terminal_p, Sw32_use_virtual_terminal_p, 0, 0, 0,
1177 doc: /* Returns t (nil) if virtual terminal sequence processing is enabled (disabled). */)
945 (void) 1178 (void)
946{ 1179{
947 return Fcons (make_fixnum (char_attr_normal & 0x000f), 1180 return w32_use_virtual_terminal ? Qt : Qnil;
948 Fcons (make_fixnum ((char_attr_normal >> 4) & 0x000f), Qnil));
949} 1181}
950 1182
951DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0, 1183DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
@@ -974,5 +1206,7 @@ scroll-back buffer. */);
974 1206
975 defsubr (&Sset_screen_color); 1207 defsubr (&Sset_screen_color);
976 defsubr (&Sget_screen_color); 1208 defsubr (&Sget_screen_color);
1209 defsubr (&Sw32_use_virtual_terminal);
1210 defsubr (&Sw32_use_virtual_terminal_p);
977 defsubr (&Sset_cursor_size); 1211 defsubr (&Sset_cursor_size);
978} 1212}
diff --git a/src/xdisp.c b/src/xdisp.c
index 6f06206b43e..99474d7abdc 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -17387,7 +17387,7 @@ redisplay_internal (void)
17387 area, displaying a different frame means redisplay the 17387 area, displaying a different frame means redisplay the
17388 whole thing. */ 17388 whole thing. */
17389 SET_FRAME_GARBAGED (sf); 17389 SET_FRAME_GARBAGED (sf);
17390#if !defined DOS_NT && !defined HAVE_ANDROID 17390#if !defined MSDOS && !defined HAVE_ANDROID
17391 set_tty_color_mode (FRAME_TTY (sf), sf); 17391 set_tty_color_mode (FRAME_TTY (sf), sf);
17392#endif 17392#endif
17393 } 17393 }