aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2019-04-07 14:34:33 +0100
committerRon Yorston <rmy@pobox.com>2019-04-07 14:34:33 +0100
commita33e3cb8e19b71ccf30f3dc4131eb0ba32b6d735 (patch)
treeed7cf5fd08f858ddd46b32f2b9b604d20e98c4d8
parent96ac4dc17b53f5bec3c4dd31b9b9a3c3e5fe3582 (diff)
downloadbusybox-w32-a33e3cb8e19b71ccf30f3dc4131eb0ba32b6d735.tar.gz
busybox-w32-a33e3cb8e19b71ccf30f3dc4131eb0ba32b6d735.tar.bz2
busybox-w32-a33e3cb8e19b71ccf30f3dc4131eb0ba32b6d735.zip
vi: use alternate screen buffer
Implement the "ESC[?1049h" and "ESC[?1049l" ANSI escape sequences to switch between the alternate and normal screen buffers. This allows vi to restore the original screen contents on exit.
-rw-r--r--editors/vi.c5
-rw-r--r--win32/winansi.c74
2 files changed, 68 insertions, 11 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 91a3e0ac1..a8b4dc5a4 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -1020,12 +1020,7 @@ static void refresh(int full_screen)
1020static void redraw(int full_screen) 1020static void redraw(int full_screen)
1021{ 1021{
1022 // cursor to top,left; clear to the end of screen 1022 // cursor to top,left; clear to the end of screen
1023#if !ENABLE_PLATFORM_MINGW32
1024 write1(ESC_SET_CURSOR_TOPLEFT ESC_CLEAR2EOS); 1023 write1(ESC_SET_CURSOR_TOPLEFT ESC_CLEAR2EOS);
1025#else
1026 write1(ESC_SET_CURSOR_TOPLEFT);
1027 reset_screen();
1028#endif
1029 screen_erase(); // erase the internal screen buffer 1024 screen_erase(); // erase the internal screen buffer
1030 last_status_cksum = 0; // force status update 1025 last_status_cksum = 0; // force status update
1031 refresh(full_screen); // this will redraw the entire display 1026 refresh(full_screen); // this will redraw the entire display
diff --git a/win32/winansi.c b/win32/winansi.c
index 38bd6824f..f5d836bd2 100644
--- a/win32/winansi.c
+++ b/win32/winansi.c
@@ -74,6 +74,67 @@ void set_title(const char *str)
74 SetConsoleTitle(str); 74 SetConsoleTitle(str);
75} 75}
76 76
77static HANDLE dup_handle(HANDLE h)
78{
79 HANDLE h2;
80
81 if (!DuplicateHandle(GetCurrentProcess(), h, GetCurrentProcess(),
82 &h2, 0, TRUE, DUPLICATE_SAME_ACCESS))
83 return INVALID_HANDLE_VALUE;
84 return h2;
85}
86
87static void use_alt_buffer(int flag)
88{
89 static HANDLE console_orig = INVALID_HANDLE_VALUE;
90 static int initialised = FALSE;
91 CONSOLE_SCREEN_BUFFER_INFO sbi;
92 HANDLE h;
93
94 init();
95
96 if (console == INVALID_HANDLE_VALUE)
97 return;
98
99 if (!initialised) {
100 console_orig = dup_handle(console);
101 initialised = TRUE;
102 }
103
104 if (console_orig == INVALID_HANDLE_VALUE)
105 return;
106
107 if (flag) {
108 SECURITY_ATTRIBUTES sa;
109
110 // handle should be inheritable
111 memset(&sa, 0, sizeof(sa));
112 sa.nLength = sizeof(sa);
113 /* sa.lpSecurityDescriptor = NULL; - memset did it */
114 sa.bInheritHandle = TRUE;
115
116 // create new alternate buffer
117 h = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
118 FILE_SHARE_READ|FILE_SHARE_WRITE, &sa,
119 CONSOLE_TEXTMODE_BUFFER, NULL);
120 if (h == INVALID_HANDLE_VALUE)
121 return;
122
123 if (GetConsoleScreenBufferInfo(console, &sbi))
124 SetConsoleScreenBufferSize(h, sbi.dwSize);
125 }
126 else {
127 // revert to original buffer
128 h = dup_handle(console_orig);
129 if (h == INVALID_HANDLE_VALUE)
130 return;
131 }
132
133 console = h;
134 SetConsoleActiveScreenBuffer(console);
135 close(STDOUT_FILENO);
136 _open_osfhandle((intptr_t)console, O_RDWR|O_BINARY);
137}
77 138
78#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) 139#define FOREGROUND_ALL (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE)
79#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE) 140#define BACKGROUND_ALL (BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE)
@@ -371,12 +432,13 @@ static char *process_escape(char *pos)
371 erase_in_line(); 432 erase_in_line();
372 break; 433 break;
373 case '?': 434 case '?':
374 /* skip this to avoid ugliness when vi is shut down */ 435 if (strncmp(str+1, "1049", 4) == 0 &&
375 ++str; 436 (str[5] == 'h' || str[5] == 'l') ) {
376 while (isdigit(*str)) 437 use_alt_buffer(str[5] == 'h');
377 ++str; 438 func = str + 5;
378 func = str; 439 break;
379 break; 440 }
441 /* fall through */
380 default: 442 default:
381 /* Unsupported code */ 443 /* Unsupported code */
382 return pos; 444 return pos;