Mercurial > vim
comparison src/os_win32.c @ 13314:65c3e8259124 v8.0.1531
patch 8.0.1531: cannot use 24 bit colors in MS-Windows console
commit https://github.com/vim/vim/commit/cafafb381a04e33f3ce9cd15dd9f94b73226831f
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Feb 22 21:07:09 2018 +0100
patch 8.0.1531: cannot use 24 bit colors in MS-Windows console
Problem: Cannot use 24 bit colors in MS-Windows console.
Solution: Add support for vcon. (Nobuhiro Takasaki, Ken Takasaki,
fixes #1270, fixes #2060)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 22 Feb 2018 21:15:05 +0100 |
parents | ee1a1276a759 |
children | 69517d67421f |
comparison
equal
deleted
inserted
replaced
13313:97fb19f36653 | 13314:65c3e8259124 |
---|---|
201 static int win32_getattrs(char_u *name); | 201 static int win32_getattrs(char_u *name); |
202 static int win32_setattrs(char_u *name, int attrs); | 202 static int win32_setattrs(char_u *name, int attrs); |
203 static int win32_set_archive(char_u *name); | 203 static int win32_set_archive(char_u *name); |
204 | 204 |
205 #ifndef FEAT_GUI_W32 | 205 #ifndef FEAT_GUI_W32 |
206 static int vtp_working = 0; | |
207 static void vtp_init(); | |
208 static void vtp_exit(); | |
209 static int vtp_printf(char *format, ...); | |
210 static void vtp_sgr_bulk(int arg); | |
211 static void vtp_sgr_bulks(int argc, int *argv); | |
212 | |
213 static guicolor_T save_console_bg_rgb; | |
214 static guicolor_T save_console_fg_rgb; | |
215 | |
216 # ifdef FEAT_TERMGUICOLORS | |
217 # define USE_VTP (vtp_working && p_tgc) | |
218 # else | |
219 # define USE_VTP 0 | |
220 # endif | |
221 | |
222 static void set_console_color_rgb(void); | |
223 static void reset_console_color_rgb(void); | |
224 #endif | |
225 | |
226 /* This flag is newly created from Windows 10 */ | |
227 #ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING | |
228 # define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 | |
229 #endif | |
230 | |
231 #ifndef FEAT_GUI_W32 | |
206 static int suppress_winsize = 1; /* don't fiddle with console */ | 232 static int suppress_winsize = 1; /* don't fiddle with console */ |
207 #endif | 233 #endif |
208 | 234 |
209 static char_u *exe_path = NULL; | 235 static char_u *exe_path = NULL; |
210 | 236 |
211 static BOOL win8_or_later = FALSE; | 237 static BOOL win8_or_later = FALSE; |
212 | 238 |
213 #ifndef FEAT_GUI_W32 | 239 #ifndef FEAT_GUI_W32 |
240 /* Dynamic loading for portability */ | |
241 typedef struct _DYN_CONSOLE_SCREEN_BUFFER_INFOEX | |
242 { | |
243 ULONG cbSize; | |
244 COORD dwSize; | |
245 COORD dwCursorPosition; | |
246 WORD wAttributes; | |
247 SMALL_RECT srWindow; | |
248 COORD dwMaximumWindowSize; | |
249 WORD wPopupAttributes; | |
250 BOOL bFullscreenSupported; | |
251 COLORREF ColorTable[16]; | |
252 } DYN_CONSOLE_SCREEN_BUFFER_INFOEX, *PDYN_CONSOLE_SCREEN_BUFFER_INFOEX; | |
253 typedef BOOL (WINAPI *PfnGetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX); | |
254 static PfnGetConsoleScreenBufferInfoEx pGetConsoleScreenBufferInfoEx; | |
255 typedef BOOL (WINAPI *PfnSetConsoleScreenBufferInfoEx)(HANDLE, PDYN_CONSOLE_SCREEN_BUFFER_INFOEX); | |
256 static PfnSetConsoleScreenBufferInfoEx pSetConsoleScreenBufferInfoEx; | |
257 static BOOL has_csbiex = FALSE; | |
258 | |
259 /* | |
260 * Get version number including build number | |
261 */ | |
262 typedef BOOL (WINAPI *PfnRtlGetVersion)(LPOSVERSIONINFOW); | |
263 # define MAKE_VER(major, minor, build) \ | |
264 (((major) << 24) | ((minor) << 16) | (build)) | |
265 | |
266 static DWORD | |
267 get_build_number(void) | |
268 { | |
269 OSVERSIONINFOW osver = {sizeof(OSVERSIONINFOW)}; | |
270 HMODULE hNtdll; | |
271 PfnRtlGetVersion pRtlGetVersion; | |
272 DWORD ver = MAKE_VER(0, 0, 0); | |
273 | |
274 hNtdll = GetModuleHandle("ntdll.dll"); | |
275 if (hNtdll != NULL) | |
276 { | |
277 pRtlGetVersion = | |
278 (PfnRtlGetVersion)GetProcAddress(hNtdll, "RtlGetVersion"); | |
279 pRtlGetVersion(&osver); | |
280 ver = MAKE_VER(min(osver.dwMajorVersion, 255), | |
281 min(osver.dwMinorVersion, 255), | |
282 min(osver.dwBuildNumber, 32767)); | |
283 } | |
284 return ver; | |
285 } | |
286 | |
287 | |
214 /* | 288 /* |
215 * Version of ReadConsoleInput() that works with IME. | 289 * Version of ReadConsoleInput() that works with IME. |
216 * Works around problems on Windows 8. | 290 * Works around problems on Windows 8. |
217 */ | 291 */ |
218 static BOOL | 292 static BOOL |
2535 if (cterm_normal_bg_color == 0) | 2609 if (cterm_normal_bg_color == 0) |
2536 cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1; | 2610 cterm_normal_bg_color = ((g_attrCurrent >> 4) & 0xf) + 1; |
2537 | 2611 |
2538 /* set termcap codes to current text attributes */ | 2612 /* set termcap codes to current text attributes */ |
2539 update_tcap(g_attrCurrent); | 2613 update_tcap(g_attrCurrent); |
2614 swap_tcap(); | |
2540 | 2615 |
2541 GetConsoleCursorInfo(g_hConOut, &g_cci); | 2616 GetConsoleCursorInfo(g_hConOut, &g_cci); |
2542 GetConsoleMode(g_hConIn, &g_cmodein); | 2617 GetConsoleMode(g_hConIn, &g_cmodein); |
2543 GetConsoleMode(g_hConOut, &g_cmodeout); | 2618 GetConsoleMode(g_hConOut, &g_cmodeout); |
2544 | 2619 |
2575 #endif | 2650 #endif |
2576 | 2651 |
2577 #ifdef FEAT_CLIPBOARD | 2652 #ifdef FEAT_CLIPBOARD |
2578 win_clip_init(); | 2653 win_clip_init(); |
2579 #endif | 2654 #endif |
2655 | |
2656 vtp_init(); | |
2580 } | 2657 } |
2581 | 2658 |
2582 /* | 2659 /* |
2583 * non-GUI version of mch_exit(). | 2660 * non-GUI version of mch_exit(). |
2584 * Shut down and exit with status `r' | 2661 * Shut down and exit with status `r' |
2586 */ | 2663 */ |
2587 void | 2664 void |
2588 mch_exit(int r) | 2665 mch_exit(int r) |
2589 { | 2666 { |
2590 exiting = TRUE; | 2667 exiting = TRUE; |
2668 | |
2669 vtp_exit(); | |
2591 | 2670 |
2592 stoptermcap(); | 2671 stoptermcap(); |
2593 if (g_fWindInitCalled) | 2672 if (g_fWindInitCalled) |
2594 settmode(TMODE_COOK); | 2673 settmode(TMODE_COOK); |
2595 | 2674 |
3799 ENABLE_ECHO_INPUT); | 3878 ENABLE_ECHO_INPUT); |
3800 #ifdef FEAT_MOUSE | 3879 #ifdef FEAT_MOUSE |
3801 if (g_fMouseActive) | 3880 if (g_fMouseActive) |
3802 cmodein |= ENABLE_MOUSE_INPUT; | 3881 cmodein |= ENABLE_MOUSE_INPUT; |
3803 #endif | 3882 #endif |
3804 cmodeout &= ~(ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); | 3883 cmodeout &= ~( |
3884 #ifdef FEAT_TERMGUICOLORS | |
3885 /* Do not turn off the ENABLE_PROCESSRD_OUTPUT flag when using | |
3886 * VTP. */ | |
3887 ((vtp_working) ? 0 : ENABLE_PROCESSED_OUTPUT) | | |
3888 #else | |
3889 ENABLE_PROCESSED_OUTPUT | | |
3890 #endif | |
3891 ENABLE_WRAP_AT_EOL_OUTPUT); | |
3805 bEnableHandler = TRUE; | 3892 bEnableHandler = TRUE; |
3806 } | 3893 } |
3807 else /* cooked */ | 3894 else /* cooked */ |
3808 { | 3895 { |
3809 cmodein |= (ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | | 3896 cmodein |= (ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | |
5446 * characteristics, including the buffer size and the window | 5533 * characteristics, including the buffer size and the window |
5447 * size. Since we will be redrawing the screen, we don't need | 5534 * size. Since we will be redrawing the screen, we don't need |
5448 * to restore the actual contents of the buffer. | 5535 * to restore the actual contents of the buffer. |
5449 */ | 5536 */ |
5450 RestoreConsoleBuffer(&g_cbTermcap, FALSE); | 5537 RestoreConsoleBuffer(&g_cbTermcap, FALSE); |
5538 reset_console_color_rgb(); | |
5451 SetConsoleWindowInfo(g_hConOut, TRUE, &g_cbTermcap.Info.srWindow); | 5539 SetConsoleWindowInfo(g_hConOut, TRUE, &g_cbTermcap.Info.srWindow); |
5452 Rows = g_cbTermcap.Info.dwSize.Y; | 5540 Rows = g_cbTermcap.Info.dwSize.Y; |
5453 Columns = g_cbTermcap.Info.dwSize.X; | 5541 Columns = g_cbTermcap.Info.dwSize.X; |
5454 } | 5542 } |
5455 else | 5543 else |
5458 * This is our first time entering termcap mode. Clear the console | 5546 * This is our first time entering termcap mode. Clear the console |
5459 * screen buffer, and resize the buffer to match the current window | 5547 * screen buffer, and resize the buffer to match the current window |
5460 * size. We will use this as the size of our editing environment. | 5548 * size. We will use this as the size of our editing environment. |
5461 */ | 5549 */ |
5462 ClearConsoleBuffer(g_attrCurrent); | 5550 ClearConsoleBuffer(g_attrCurrent); |
5551 set_console_color_rgb(); | |
5463 ResizeConBufAndWindow(g_hConOut, Columns, Rows); | 5552 ResizeConBufAndWindow(g_hConOut, Columns, Rows); |
5464 } | 5553 } |
5465 | 5554 |
5466 #ifdef FEAT_TITLE | 5555 #ifdef FEAT_TITLE |
5467 resettitle(); | 5556 resettitle(); |
5506 cb = exiting ? &g_cbOrig : &g_cbNonTermcap; | 5595 cb = exiting ? &g_cbOrig : &g_cbNonTermcap; |
5507 #else | 5596 #else |
5508 cb = &g_cbNonTermcap; | 5597 cb = &g_cbNonTermcap; |
5509 #endif | 5598 #endif |
5510 RestoreConsoleBuffer(cb, p_rs); | 5599 RestoreConsoleBuffer(cb, p_rs); |
5600 reset_console_color_rgb(); | |
5511 SetConsoleCursorInfo(g_hConOut, &g_cci); | 5601 SetConsoleCursorInfo(g_hConOut, &g_cci); |
5512 | 5602 |
5513 if (p_rs || exiting) | 5603 if (p_rs || exiting) |
5514 { | 5604 { |
5515 /* | 5605 /* |
5560 DWORD n) | 5650 DWORD n) |
5561 { | 5651 { |
5562 DWORD dwDummy; | 5652 DWORD dwDummy; |
5563 | 5653 |
5564 FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy); | 5654 FillConsoleOutputCharacter(g_hConOut, ' ', n, coord, &dwDummy); |
5565 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); | 5655 |
5656 if (!USE_VTP) | |
5657 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, n, coord, &dwDummy); | |
5658 else | |
5659 FillConsoleOutputAttribute(g_hConOut, 0, n, coord, &dwDummy); | |
5566 } | 5660 } |
5567 | 5661 |
5568 | 5662 |
5569 /* | 5663 /* |
5570 * Clear the screen | 5664 * Clear the screen |
5571 */ | 5665 */ |
5572 static void | 5666 static void |
5573 clear_screen(void) | 5667 clear_screen(void) |
5574 { | 5668 { |
5575 g_coord.X = g_coord.Y = 0; | 5669 g_coord.X = g_coord.Y = 0; |
5576 clear_chars(g_coord, Rows * Columns); | 5670 |
5671 if (!USE_VTP) | |
5672 clear_chars(g_coord, Rows * Columns); | |
5673 else | |
5674 { | |
5675 set_console_color_rgb(); | |
5676 gotoxy(1, 1); | |
5677 vtp_printf("\033[2J"); | |
5678 } | |
5577 } | 5679 } |
5578 | 5680 |
5579 | 5681 |
5580 /* | 5682 /* |
5581 * Clear to end of display | 5683 * Clear to end of display |
5582 */ | 5684 */ |
5583 static void | 5685 static void |
5584 clear_to_end_of_display(void) | 5686 clear_to_end_of_display(void) |
5585 { | 5687 { |
5586 clear_chars(g_coord, (Rows - g_coord.Y - 1) | 5688 COORD save = g_coord; |
5689 | |
5690 if (!USE_VTP) | |
5691 clear_chars(g_coord, (Rows - g_coord.Y - 1) | |
5587 * Columns + (Columns - g_coord.X)); | 5692 * Columns + (Columns - g_coord.X)); |
5693 else | |
5694 { | |
5695 set_console_color_rgb(); | |
5696 gotoxy(g_coord.X + 1, g_coord.Y + 1); | |
5697 vtp_printf("\033[0J"); | |
5698 | |
5699 gotoxy(save.X + 1, save.Y + 1); | |
5700 g_coord = save; | |
5701 } | |
5588 } | 5702 } |
5589 | 5703 |
5590 | 5704 |
5591 /* | 5705 /* |
5592 * Clear to end of line | 5706 * Clear to end of line |
5593 */ | 5707 */ |
5594 static void | 5708 static void |
5595 clear_to_end_of_line(void) | 5709 clear_to_end_of_line(void) |
5596 { | 5710 { |
5597 clear_chars(g_coord, Columns - g_coord.X); | 5711 COORD save = g_coord; |
5712 | |
5713 if (!USE_VTP) | |
5714 clear_chars(g_coord, Columns - g_coord.X); | |
5715 else | |
5716 { | |
5717 set_console_color_rgb(); | |
5718 gotoxy(g_coord.X + 1, g_coord.Y + 1); | |
5719 vtp_printf("\033[0K"); | |
5720 | |
5721 gotoxy(save.X + 1, save.Y + 1); | |
5722 g_coord = save; | |
5723 } | |
5598 } | 5724 } |
5599 | 5725 |
5600 | 5726 |
5601 /* | 5727 /* |
5602 * Scroll the scroll region up by `cLines' lines | 5728 * Scroll the scroll region up by `cLines' lines |
5631 | 5757 |
5632 g_srScrollRegion.Left = left; | 5758 g_srScrollRegion.Left = left; |
5633 g_srScrollRegion.Top = top; | 5759 g_srScrollRegion.Top = top; |
5634 g_srScrollRegion.Right = right; | 5760 g_srScrollRegion.Right = right; |
5635 g_srScrollRegion.Bottom = bottom; | 5761 g_srScrollRegion.Bottom = bottom; |
5762 | |
5763 if (USE_VTP) | |
5764 vtp_printf("\033[%d;%dr", top + 1, bottom + 1); | |
5636 } | 5765 } |
5637 | 5766 |
5638 | 5767 |
5639 /* | 5768 /* |
5640 * Insert `cLines' lines at the current cursor position | 5769 * Insert `cLines' lines at the current cursor position |
5652 source.Left = 0; | 5781 source.Left = 0; |
5653 source.Top = g_coord.Y; | 5782 source.Top = g_coord.Y; |
5654 source.Right = g_srScrollRegion.Right; | 5783 source.Right = g_srScrollRegion.Right; |
5655 source.Bottom = g_srScrollRegion.Bottom - cLines; | 5784 source.Bottom = g_srScrollRegion.Bottom - cLines; |
5656 | 5785 |
5657 fill.Char.AsciiChar = ' '; | 5786 if (!USE_VTP) |
5658 fill.Attributes = g_attrCurrent; | 5787 { |
5659 | 5788 fill.Char.AsciiChar = ' '; |
5660 ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); | 5789 fill.Attributes = g_attrCurrent; |
5790 | |
5791 ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); | |
5792 } | |
5793 else | |
5794 { | |
5795 set_console_color_rgb(); | |
5796 | |
5797 gotoxy(1, source.Top + 1); | |
5798 vtp_printf("\033[%dT", cLines); | |
5799 } | |
5661 | 5800 |
5662 /* Here we have to deal with a win32 console flake: If the scroll | 5801 /* Here we have to deal with a win32 console flake: If the scroll |
5663 * region looks like abc and we scroll c to a and fill with d we get | 5802 * region looks like abc and we scroll c to a and fill with d we get |
5664 * cbd... if we scroll block c one line at a time to a, we get cdd... | 5803 * cbd... if we scroll block c one line at a time to a, we get cdd... |
5665 * vim expects cdd consistently... So we have to deal with that | 5804 * vim expects cdd consistently... So we have to deal with that |
5694 source.Left = 0; | 5833 source.Left = 0; |
5695 source.Top = g_coord.Y + cLines; | 5834 source.Top = g_coord.Y + cLines; |
5696 source.Right = g_srScrollRegion.Right; | 5835 source.Right = g_srScrollRegion.Right; |
5697 source.Bottom = g_srScrollRegion.Bottom; | 5836 source.Bottom = g_srScrollRegion.Bottom; |
5698 | 5837 |
5699 fill.Char.AsciiChar = ' '; | 5838 if (!USE_VTP) |
5700 fill.Attributes = g_attrCurrent; | 5839 { |
5701 | 5840 fill.Char.AsciiChar = ' '; |
5702 ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); | 5841 fill.Attributes = g_attrCurrent; |
5842 | |
5843 ScrollConsoleScreenBuffer(g_hConOut, &source, NULL, dest, &fill); | |
5844 } | |
5845 else | |
5846 { | |
5847 set_console_color_rgb(); | |
5848 | |
5849 gotoxy(1, source.Top + 1); | |
5850 vtp_printf("\033[%dS", cLines); | |
5851 } | |
5703 | 5852 |
5704 /* Here we have to deal with a win32 console flake: If the scroll | 5853 /* Here we have to deal with a win32 console flake: If the scroll |
5705 * region looks like abc and we scroll c to a and fill with d we get | 5854 * region looks like abc and we scroll c to a and fill with d we get |
5706 * cbd... if we scroll block c one line at a time to a, we get cdd... | 5855 * cbd... if we scroll block c one line at a time to a, we get cdd... |
5707 * vim expects cdd consistently... So we have to deal with that | 5856 * vim expects cdd consistently... So we have to deal with that |
5733 return; | 5882 return; |
5734 | 5883 |
5735 /* external cursor coords are 1-based; internal are 0-based */ | 5884 /* external cursor coords are 1-based; internal are 0-based */ |
5736 g_coord.X = x - 1; | 5885 g_coord.X = x - 1; |
5737 g_coord.Y = y - 1; | 5886 g_coord.Y = y - 1; |
5738 SetConsoleCursorPosition(g_hConOut, g_coord); | 5887 |
5888 if (!USE_VTP) | |
5889 SetConsoleCursorPosition(g_hConOut, g_coord); | |
5890 else | |
5891 vtp_printf("\033[%d;%dH", y, x); | |
5739 } | 5892 } |
5740 | 5893 |
5741 | 5894 |
5742 /* | 5895 /* |
5743 * Set the current text attribute = (foreground | background) | 5896 * Set the current text attribute = (foreground | background) |
5755 static void | 5908 static void |
5756 textcolor(WORD wAttr) | 5909 textcolor(WORD wAttr) |
5757 { | 5910 { |
5758 g_attrCurrent = (g_attrCurrent & 0xf0) + (wAttr & 0x0f); | 5911 g_attrCurrent = (g_attrCurrent & 0xf0) + (wAttr & 0x0f); |
5759 | 5912 |
5760 SetConsoleTextAttribute(g_hConOut, g_attrCurrent); | 5913 if (!USE_VTP) |
5914 SetConsoleTextAttribute(g_hConOut, g_attrCurrent); | |
5915 else | |
5916 vtp_sgr_bulk(wAttr); | |
5761 } | 5917 } |
5762 | 5918 |
5763 | 5919 |
5764 static void | 5920 static void |
5765 textbackground(WORD wAttr) | 5921 textbackground(WORD wAttr) |
5766 { | 5922 { |
5767 g_attrCurrent = (g_attrCurrent & 0x0f) + ((wAttr & 0x0f) << 4); | 5923 g_attrCurrent = (g_attrCurrent & 0x0f) + ((wAttr & 0x0f) << 4); |
5768 | 5924 |
5769 SetConsoleTextAttribute(g_hConOut, g_attrCurrent); | 5925 if (!USE_VTP) |
5926 SetConsoleTextAttribute(g_hConOut, g_attrCurrent); | |
5927 else | |
5928 vtp_sgr_bulk(wAttr); | |
5770 } | 5929 } |
5771 | 5930 |
5772 | 5931 |
5773 /* | 5932 /* |
5774 * restore the default text attribute (whatever we started with) | 5933 * restore the default text attribute (whatever we started with) |
5775 */ | 5934 */ |
5776 static void | 5935 static void |
5777 normvideo(void) | 5936 normvideo(void) |
5778 { | 5937 { |
5779 textattr(g_attrDefault); | 5938 if (!USE_VTP) |
5939 textattr(g_attrDefault); | |
5940 else | |
5941 vtp_sgr_bulk(0); | |
5780 } | 5942 } |
5781 | 5943 |
5782 | 5944 |
5783 static WORD g_attrPreStandout = 0; | 5945 static WORD g_attrPreStandout = 0; |
5784 | 5946 |
5787 */ | 5949 */ |
5788 static void | 5950 static void |
5789 standout(void) | 5951 standout(void) |
5790 { | 5952 { |
5791 g_attrPreStandout = g_attrCurrent; | 5953 g_attrPreStandout = g_attrCurrent; |
5954 | |
5792 textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); | 5955 textattr((WORD) (g_attrCurrent|FOREGROUND_INTENSITY|BACKGROUND_INTENSITY)); |
5793 } | 5956 } |
5794 | 5957 |
5795 | 5958 |
5796 /* | 5959 /* |
5798 */ | 5961 */ |
5799 static void | 5962 static void |
5800 standend(void) | 5963 standend(void) |
5801 { | 5964 { |
5802 if (g_attrPreStandout) | 5965 if (g_attrPreStandout) |
5803 { | |
5804 textattr(g_attrPreStandout); | 5966 textattr(g_attrPreStandout); |
5805 g_attrPreStandout = 0; | 5967 |
5806 } | 5968 g_attrPreStandout = 0; |
5807 } | 5969 } |
5808 | 5970 |
5809 | 5971 |
5810 /* | 5972 /* |
5811 * Set normal fg/bg color, based on T_ME. Called when t_me has been set. | 5973 * Set normal fg/bg color, based on T_ME. Called when t_me has been set. |
5816 char_u *p; | 5978 char_u *p; |
5817 int n; | 5979 int n; |
5818 | 5980 |
5819 cterm_normal_fg_color = (g_attrDefault & 0xf) + 1; | 5981 cterm_normal_fg_color = (g_attrDefault & 0xf) + 1; |
5820 cterm_normal_bg_color = ((g_attrDefault >> 4) & 0xf) + 1; | 5982 cterm_normal_bg_color = ((g_attrDefault >> 4) & 0xf) + 1; |
5821 if (T_ME[0] == ESC && T_ME[1] == '|') | 5983 if ( |
5984 #ifdef FEAT_TERMGUICOLORS | |
5985 !p_tgc && | |
5986 #endif | |
5987 T_ME[0] == ESC && T_ME[1] == '|') | |
5822 { | 5988 { |
5823 p = T_ME + 2; | 5989 p = T_ME + 2; |
5824 n = getdigits(&p); | 5990 n = getdigits(&p); |
5825 if (*p == 'm' && n > 0) | 5991 if (*p == 'm' && n > 0) |
5826 { | 5992 { |
5827 cterm_normal_fg_color = (n & 0xf) + 1; | 5993 cterm_normal_fg_color = (n & 0xf) + 1; |
5828 cterm_normal_bg_color = ((n >> 4) & 0xf) + 1; | 5994 cterm_normal_bg_color = ((n >> 4) & 0xf) + 1; |
5829 } | 5995 } |
5830 } | 5996 } |
5997 #ifdef FEAT_TERMGUICOLORS | |
5998 cterm_normal_fg_gui_color = INVALCOLOR; | |
5999 cterm_normal_bg_gui_color = INVALCOLOR; | |
6000 #endif | |
5831 } | 6001 } |
5832 | 6002 |
5833 | 6003 |
5834 /* | 6004 /* |
5835 * visual bell: flash the screen | 6005 * visual bell: flash the screen |
5849 coordOrigin, &dwDummy); | 6019 coordOrigin, &dwDummy); |
5850 FillConsoleOutputAttribute(g_hConOut, attrFlash, Rows * Columns, | 6020 FillConsoleOutputAttribute(g_hConOut, attrFlash, Rows * Columns, |
5851 coordOrigin, &dwDummy); | 6021 coordOrigin, &dwDummy); |
5852 | 6022 |
5853 Sleep(15); /* wait for 15 msec */ | 6023 Sleep(15); /* wait for 15 msec */ |
5854 WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, | 6024 if (!USE_VTP) |
6025 WriteConsoleOutputAttribute(g_hConOut, oldattrs, Rows * Columns, | |
5855 coordOrigin, &dwDummy); | 6026 coordOrigin, &dwDummy); |
5856 vim_free(oldattrs); | 6027 vim_free(oldattrs); |
5857 } | 6028 } |
5858 | 6029 |
5859 | 6030 |
5899 } | 6070 } |
5900 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite, | 6071 MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)pchBuf, cbToWrite, |
5901 unicodebuf, unibuflen); | 6072 unicodebuf, unibuflen); |
5902 | 6073 |
5903 cells = mb_string2cells(pchBuf, cbToWrite); | 6074 cells = mb_string2cells(pchBuf, cbToWrite); |
5904 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells, | 6075 |
5905 coord, &written); | 6076 if (!USE_VTP) |
5906 /* When writing fails or didn't write a single character, pretend one | 6077 { |
5907 * character was written, otherwise we get stuck. */ | 6078 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cells, |
5908 if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length, | 6079 coord, &written); |
5909 coord, &cchwritten) == 0 | 6080 /* When writing fails or didn't write a single character, pretend one |
5910 || cchwritten == 0) | 6081 * character was written, otherwise we get stuck. */ |
5911 cchwritten = 1; | 6082 if (WriteConsoleOutputCharacterW(g_hConOut, unicodebuf, length, |
6083 coord, &cchwritten) == 0 | |
6084 || cchwritten == 0) | |
6085 cchwritten = 1; | |
6086 } | |
6087 else | |
6088 { | |
6089 if (WriteConsoleW(g_hConOut, unicodebuf, length, &cchwritten, | |
6090 NULL) == 0 || cchwritten == 0) | |
6091 cchwritten = 1; | |
6092 } | |
5912 | 6093 |
5913 if (cchwritten == length) | 6094 if (cchwritten == length) |
5914 { | 6095 { |
5915 written = cbToWrite; | 6096 written = cbToWrite; |
5916 g_coord.X += (SHORT)cells; | 6097 g_coord.X += (SHORT)cells; |
5925 } | 6106 } |
5926 } | 6107 } |
5927 else | 6108 else |
5928 #endif | 6109 #endif |
5929 { | 6110 { |
5930 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite, | 6111 if (!USE_VTP) |
5931 coord, &written); | 6112 { |
5932 /* When writing fails or didn't write a single character, pretend one | 6113 FillConsoleOutputAttribute(g_hConOut, g_attrCurrent, cbToWrite, |
5933 * character was written, otherwise we get stuck. */ | 6114 coord, &written); |
5934 if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite, | 6115 /* When writing fails or didn't write a single character, pretend one |
5935 coord, &written) == 0 | 6116 * character was written, otherwise we get stuck. */ |
5936 || written == 0) | 6117 if (WriteConsoleOutputCharacter(g_hConOut, (LPCSTR)pchBuf, cbToWrite, |
5937 written = 1; | 6118 coord, &written) == 0 |
6119 || written == 0) | |
6120 written = 1; | |
6121 } | |
6122 else | |
6123 { | |
6124 if (WriteConsole(g_hConOut, (LPCSTR)pchBuf, cbToWrite, &written, | |
6125 NULL) == 0 || written == 0) | |
6126 written = 1; | |
6127 } | |
5938 | 6128 |
5939 g_coord.X += (SHORT) written; | 6129 g_coord.X += (SHORT) written; |
5940 } | 6130 } |
5941 | 6131 |
5942 while (g_coord.X > g_srScrollRegion.Right) | 6132 while (g_coord.X > g_srScrollRegion.Right) |
6058 { | 6248 { |
6059 #ifdef MCH_WRITE_DUMP | 6249 #ifdef MCH_WRITE_DUMP |
6060 char_u *old_s = s; | 6250 char_u *old_s = s; |
6061 #endif | 6251 #endif |
6062 char_u *p; | 6252 char_u *p; |
6063 int arg1 = 0, arg2 = 0; | 6253 int arg1 = 0, arg2 = 0, argc = 0, args[16]; |
6064 | 6254 |
6065 switch (s[2]) | 6255 switch (s[2]) |
6066 { | 6256 { |
6067 /* one or two numeric arguments, separated by ';' */ | |
6068 | |
6069 case '0': case '1': case '2': case '3': case '4': | 6257 case '0': case '1': case '2': case '3': case '4': |
6070 case '5': case '6': case '7': case '8': case '9': | 6258 case '5': case '6': case '7': case '8': case '9': |
6071 p = s + 2; | 6259 p = s + 1; |
6072 arg1 = getdigits(&p); /* no check for length! */ | 6260 do |
6261 { | |
6262 ++p; | |
6263 args[argc] = getdigits(&p); | |
6264 argc += (argc < 15) ? 1 : 0; | |
6265 if (p > s + len) | |
6266 break; | |
6267 } while (*p == ';'); | |
6268 | |
6073 if (p > s + len) | 6269 if (p > s + len) |
6074 break; | 6270 break; |
6075 | 6271 |
6076 if (*p == ';') | 6272 arg1 = args[0]; |
6273 arg2 = args[1]; | |
6274 if (*p == 'm') | |
6077 { | 6275 { |
6078 ++p; | 6276 if (argc == 1 && args[0] == 0) |
6079 arg2 = getdigits(&p); /* no check for length! */ | 6277 normvideo(); |
6080 if (p > s + len) | 6278 else if (argc == 1) |
6081 break; | 6279 { |
6082 | 6280 if (USE_VTP) |
6083 if (*p == 'H') | 6281 textcolor((WORD) arg1); |
6084 gotoxy(arg2, arg1); | 6282 else |
6085 else if (*p == 'r') | 6283 textattr((WORD) arg1); |
6086 set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); | 6284 } |
6285 else if (USE_VTP) | |
6286 vtp_sgr_bulks(argc, args); | |
6087 } | 6287 } |
6088 else if (*p == 'A') | 6288 else if (argc == 2 && *p == 'H') |
6089 { | 6289 { |
6090 /* move cursor up arg1 lines in same column */ | 6290 gotoxy(arg2, arg1); |
6291 } | |
6292 else if (argc == 2 && *p == 'r') | |
6293 { | |
6294 set_scroll_region(0, arg1 - 1, Columns - 1, arg2 - 1); | |
6295 } | |
6296 else if (argc == 1 && *p == 'A') | |
6297 { | |
6091 gotoxy(g_coord.X + 1, | 6298 gotoxy(g_coord.X + 1, |
6092 max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); | 6299 max(g_srScrollRegion.Top, g_coord.Y - arg1) + 1); |
6093 } | 6300 } |
6094 else if (*p == 'C') | 6301 else if (argc == 1 && *p == 'b') |
6095 { | 6302 { |
6096 /* move cursor right arg1 columns in same line */ | 6303 textbackground((WORD) arg1); |
6304 } | |
6305 else if (argc == 1 && *p == 'C') | |
6306 { | |
6097 gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, | 6307 gotoxy(min(g_srScrollRegion.Right, g_coord.X + arg1) + 1, |
6098 g_coord.Y + 1); | 6308 g_coord.Y + 1); |
6099 } | 6309 } |
6100 else if (*p == 'H') | 6310 else if (argc == 1 && *p == 'f') |
6311 { | |
6312 textcolor((WORD) arg1); | |
6313 } | |
6314 else if (argc == 1 && *p == 'H') | |
6101 { | 6315 { |
6102 gotoxy(1, arg1); | 6316 gotoxy(1, arg1); |
6103 } | 6317 } |
6104 else if (*p == 'L') | 6318 else if (argc == 1 && *p == 'L') |
6105 { | 6319 { |
6106 insert_lines(arg1); | 6320 insert_lines(arg1); |
6107 } | 6321 } |
6108 else if (*p == 'm') | 6322 else if (argc == 1 && *p == 'M') |
6109 { | |
6110 if (arg1 == 0) | |
6111 normvideo(); | |
6112 else | |
6113 textattr((WORD) arg1); | |
6114 } | |
6115 else if (*p == 'f') | |
6116 { | |
6117 textcolor((WORD) arg1); | |
6118 } | |
6119 else if (*p == 'b') | |
6120 { | |
6121 textbackground((WORD) arg1); | |
6122 } | |
6123 else if (*p == 'M') | |
6124 { | 6323 { |
6125 delete_lines(arg1); | 6324 delete_lines(arg1); |
6126 } | 6325 } |
6127 | 6326 |
6128 len -= (int)(p - s); | 6327 len -= (int)(p - s); |
6129 s = p + 1; | 6328 s = p + 1; |
6130 break; | 6329 break; |
6131 | 6330 |
6132 | |
6133 /* Three-character escape sequences */ | |
6134 | |
6135 case 'A': | 6331 case 'A': |
6136 /* move cursor up one line in same column */ | |
6137 gotoxy(g_coord.X + 1, | 6332 gotoxy(g_coord.X + 1, |
6138 max(g_srScrollRegion.Top, g_coord.Y - 1) + 1); | 6333 max(g_srScrollRegion.Top, g_coord.Y - 1) + 1); |
6139 goto got3; | 6334 goto got3; |
6140 | 6335 |
6141 case 'B': | 6336 case 'B': |
6142 visual_bell(); | 6337 visual_bell(); |
6143 goto got3; | 6338 goto got3; |
6144 | 6339 |
6145 case 'C': | 6340 case 'C': |
6146 /* move cursor right one column in same line */ | |
6147 gotoxy(min(g_srScrollRegion.Right, g_coord.X + 1) + 1, | 6341 gotoxy(min(g_srScrollRegion.Right, g_coord.X + 1) + 1, |
6148 g_coord.Y + 1); | 6342 g_coord.Y + 1); |
6149 goto got3; | 6343 goto got3; |
6150 | 6344 |
6151 case 'E': | 6345 case 'E': |
7240 vim_free(envbuf); | 7434 vim_free(envbuf); |
7241 } | 7435 } |
7242 | 7436 |
7243 return 0; | 7437 return 0; |
7244 } | 7438 } |
7439 | |
7440 #ifndef FEAT_GUI_W32 | |
7441 | |
7442 /* | |
7443 * Support for 256 colors and 24-bit colors was added in Windows 10 | |
7444 * version 1703 (Creators update). | |
7445 */ | |
7446 # define VTP_FIRST_SUPPORT_BUILD MAKE_VER(10, 0, 15063) | |
7447 | |
7448 static void | |
7449 vtp_init(void) | |
7450 { | |
7451 DWORD ver, mode; | |
7452 HMODULE hKerneldll; | |
7453 DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; | |
7454 | |
7455 ver = get_build_number(); | |
7456 vtp_working = (ver >= VTP_FIRST_SUPPORT_BUILD) ? 1 : 0; | |
7457 GetConsoleMode(g_hConOut, &mode); | |
7458 mode |= (ENABLE_PROCESSED_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING); | |
7459 if (SetConsoleMode(g_hConOut, mode) == 0) | |
7460 vtp_working = 0; | |
7461 | |
7462 /* Use functions supported from Vista */ | |
7463 hKerneldll = GetModuleHandle("kernel32.dll"); | |
7464 if (hKerneldll != NULL) | |
7465 { | |
7466 pGetConsoleScreenBufferInfoEx = | |
7467 (PfnGetConsoleScreenBufferInfoEx)GetProcAddress( | |
7468 hKerneldll, "GetConsoleScreenBufferInfoEx"); | |
7469 pSetConsoleScreenBufferInfoEx = | |
7470 (PfnSetConsoleScreenBufferInfoEx)GetProcAddress( | |
7471 hKerneldll, "SetConsoleScreenBufferInfoEx"); | |
7472 if (pGetConsoleScreenBufferInfoEx != NULL | |
7473 && pSetConsoleScreenBufferInfoEx != NULL) | |
7474 has_csbiex = TRUE; | |
7475 } | |
7476 | |
7477 csbi.cbSize = sizeof(csbi); | |
7478 if (has_csbiex) | |
7479 pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); | |
7480 save_console_bg_rgb = (guicolor_T)csbi.ColorTable[0]; | |
7481 save_console_fg_rgb = (guicolor_T)csbi.ColorTable[7]; | |
7482 | |
7483 set_console_color_rgb(); | |
7484 } | |
7485 | |
7486 static void | |
7487 vtp_exit(void) | |
7488 { | |
7489 reset_console_color_rgb(); | |
7490 } | |
7491 | |
7492 static int | |
7493 vtp_printf( | |
7494 char *format, | |
7495 ...) | |
7496 { | |
7497 char_u buf[100]; | |
7498 va_list list; | |
7499 DWORD result; | |
7500 | |
7501 va_start(list, format); | |
7502 vim_vsnprintf((char *)buf, 100, (char *)format, list); | |
7503 va_end(list); | |
7504 WriteConsoleA(g_hConOut, buf, (DWORD)STRLEN(buf), &result, NULL); | |
7505 return (int)result; | |
7506 } | |
7507 | |
7508 static void | |
7509 vtp_sgr_bulk( | |
7510 int arg) | |
7511 { | |
7512 int args[1]; | |
7513 | |
7514 args[0] = arg; | |
7515 vtp_sgr_bulks(1, args); | |
7516 } | |
7517 | |
7518 static void | |
7519 vtp_sgr_bulks( | |
7520 int argc, | |
7521 int *args | |
7522 ) | |
7523 { | |
7524 /* 2('\033[') + 4('255.') * 16 + NUL */ | |
7525 char_u buf[2 + (4 * 16) + 1]; | |
7526 char_u *p; | |
7527 int i; | |
7528 | |
7529 p = buf; | |
7530 *p++ = '\033'; | |
7531 *p++ = '['; | |
7532 | |
7533 for (i = 0; i < argc; ++i) | |
7534 { | |
7535 p += vim_snprintf((char *)p, 4, "%d", args[i] & 0xff); | |
7536 *p++ = ';'; | |
7537 } | |
7538 p--; | |
7539 *p++ = 'm'; | |
7540 *p = NUL; | |
7541 vtp_printf((char *)buf); | |
7542 } | |
7543 | |
7544 static void | |
7545 set_console_color_rgb(void) | |
7546 { | |
7547 # ifdef FEAT_TERMGUICOLORS | |
7548 DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; | |
7549 int id; | |
7550 guicolor_T fg = INVALCOLOR; | |
7551 guicolor_T bg = INVALCOLOR; | |
7552 | |
7553 if (!USE_VTP) | |
7554 return; | |
7555 | |
7556 id = syn_name2id((char_u *)"Normal"); | |
7557 if (id > 0) | |
7558 syn_id2colors(id, &fg, &bg); | |
7559 if (fg == INVALCOLOR) | |
7560 fg = 0xc0c0c0; /* white text */ | |
7561 if (bg == INVALCOLOR) | |
7562 bg = 0x000000; /* black background */ | |
7563 fg = (GetRValue(fg) << 16) | (GetGValue(fg) << 8) | GetBValue(fg); | |
7564 bg = (GetRValue(bg) << 16) | (GetGValue(bg) << 8) | GetBValue(bg); | |
7565 | |
7566 csbi.cbSize = sizeof(csbi); | |
7567 if (has_csbiex) | |
7568 pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); | |
7569 | |
7570 csbi.cbSize = sizeof(csbi); | |
7571 csbi.srWindow.Right += 1; | |
7572 csbi.srWindow.Bottom += 1; | |
7573 csbi.ColorTable[0] = (COLORREF)bg; | |
7574 csbi.ColorTable[7] = (COLORREF)fg; | |
7575 if (has_csbiex) | |
7576 pSetConsoleScreenBufferInfoEx(g_hConOut, &csbi); | |
7577 # endif | |
7578 } | |
7579 | |
7580 static void | |
7581 reset_console_color_rgb(void) | |
7582 { | |
7583 # ifdef FEAT_TERMGUICOLORS | |
7584 DYN_CONSOLE_SCREEN_BUFFER_INFOEX csbi; | |
7585 | |
7586 csbi.cbSize = sizeof(csbi); | |
7587 if (has_csbiex) | |
7588 pGetConsoleScreenBufferInfoEx(g_hConOut, &csbi); | |
7589 | |
7590 csbi.cbSize = sizeof(csbi); | |
7591 csbi.srWindow.Right += 1; | |
7592 csbi.srWindow.Bottom += 1; | |
7593 csbi.ColorTable[0] = (COLORREF)save_console_bg_rgb; | |
7594 csbi.ColorTable[7] = (COLORREF)save_console_fg_rgb; | |
7595 if (has_csbiex) | |
7596 pSetConsoleScreenBufferInfoEx(g_hConOut, &csbi); | |
7597 # endif | |
7598 } | |
7599 | |
7600 void | |
7601 control_console_color_rgb(void) | |
7602 { | |
7603 if (USE_VTP) | |
7604 set_console_color_rgb(); | |
7605 else | |
7606 reset_console_color_rgb(); | |
7607 } | |
7608 | |
7609 int | |
7610 has_vtp_working(void) | |
7611 { | |
7612 return vtp_working; | |
7613 } | |
7614 | |
7615 int | |
7616 use_vtp(void) | |
7617 { | |
7618 return USE_VTP; | |
7619 } | |
7620 | |
7621 #endif |