handle:处理窗口尺寸变化后多行显示崩溃问题。

This commit is contained in:
taynpg 2025-01-09 10:15:28 +08:00
parent 1122154e32
commit 16b040363f
4 changed files with 116 additions and 76 deletions

41
.vscode/settings.json vendored
View File

@ -5,7 +5,7 @@
"terminal.integrated.fontFamily": "Source Code Pro", "terminal.integrated.fontFamily": "Source Code Pro",
"cmake.configureOnOpen": true, "cmake.configureOnOpen": true,
"cmake.debugConfig": { "cmake.debugConfig": {
"console": "integratedTerminal", "console": "externalTerminal",
"setupCommands": [ "setupCommands": [
{ {
"description": "-gdb-set charset utf-8", "description": "-gdb-set charset utf-8",
@ -33,5 +33,44 @@
"ja": true, "ja": true,
"zh-hant": true, "zh-hant": true,
"zh-hans": true "zh-hans": true
},
"files.associations": {
"cmath": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"cwchar": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"ostream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"utility": "cpp",
"vector": "cpp",
"xfacet": "cpp",
"xiosbase": "cpp",
"xlocale": "cpp",
"xlocinfo": "cpp",
"xlocnum": "cpp",
"xmemory": "cpp",
"xmemory0": "cpp",
"xstddef": "cpp",
"xstring": "cpp",
"xtr1common": "cpp",
"xutility": "cpp"
} }
} }

View File

@ -69,18 +69,39 @@
#define SPACE 32 #define SPACE 32
#define TAB 9 #define TAB 9
constexpr int buf_size = 1024 * 100;
static std::vector<std::vector<char>> buf{}; static std::vector<std::vector<char>> buf{};
static std::vector<char> word{}; static std::vector<char> word{};
static size_t wo{}; static size_t wo{};
static size_t len{}; static size_t len{};
static short cy{};
static short cx{};
short terminal_width();
void clear_line(); void clear_line();
void set_cursor_x(short x); void set_cursor_x(short x);
short get_cursor_y(); short get_cursor_y();
char* readline(); char* fc_readline();
void color_print(char* text, COLOR_TYPE color); void color_print(char* text, COLOR_TYPE color);
std::pair<short, short> get_wh()
{
HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE);
if (h_console == NULL) {
fprintf(stderr, "[ERROR] Couldn't handle terminal\n");
exit(1);
}
CONSOLE_SCREEN_BUFFER_INFO console_info;
if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) {
fprintf(stderr, "[ERROR] Couldn't get terminal info\n");
exit(1);
}
int cw = console_info.srWindow.Right - console_info.srWindow.Left + 1;
int ch = console_info.srWindow.Bottom - console_info.srWindow.Top + 1;
auto w = static_cast<short>(cw);
auto h = static_cast<short>(ch);
return std::make_pair(w, h);
}
void supply(std::vector<char>& wch, char ch) void supply(std::vector<char>& wch, char ch)
{ {
wch.push_back(ch); wch.push_back(ch);
@ -91,42 +112,11 @@ void supply(std::vector<char>& wch, char ch)
wch.push_back(tch); wch.push_back(tch);
} }
short terminal_width()
{
#if defined(OS_WINDOWS)
// Handle current terminal
HANDLE h_console = GetStdHandle(STD_OUTPUT_HANDLE);
if (h_console == NULL) {
fprintf(stderr, "[ERROR] Couldn't handle terminal\n");
exit(1);
}
// Get current attributes
CONSOLE_SCREEN_BUFFER_INFO console_info;
if (GetConsoleScreenBufferInfo(h_console, &console_info) == 0) {
fprintf(stderr, "[ERROR] Couldn't get terminal info\n");
exit(1);
}
// Return current width
return console_info.dwSize.X;
#elif defined(OS_UNIX)
struct winsize t_size;
if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &t_size) == -1) {
fprintf(stderr, "[ERROR] Couldn't get terminal info\n");
exit(1);
}
return (short)t_size.ws_col;
#endif
}
void clear_line() void clear_line()
{ {
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
// Get current terminal width // Get current terminal width
short width = terminal_width(); short width = get_wh().first;
if (width < 1) { if (width < 1) {
fprintf(stderr, "[ERROR] Size of terminal is too small\n"); fprintf(stderr, "[ERROR] Size of terminal is too small\n");
exit(1); exit(1);
@ -139,11 +129,11 @@ void clear_line()
empty[width - 1] = '\0'; empty[width - 1] = '\0';
} }
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo; CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hConsole, &cursorInfo); GetConsoleCursorInfo(hConsole, &cursorInfo);
cursorInfo.bVisible = FALSE; cursorInfo.bVisible = FALSE;
SetConsoleCursorInfo(hConsole, &cursorInfo); SetConsoleCursorInfo(hConsole, &cursorInfo);
// Clear line // Clear line
printf("\r%s\r", empty); printf("\r%s\r", empty);
@ -164,14 +154,19 @@ void set_cursor_x(short x)
exit(1); exit(1);
} }
auto wh = get_wh();
// Create position // Create position
COORD xy; COORD xy;
xy.X = x - 1;
xy.Y = get_cursor_y(); xy.Y = get_cursor_y();
short px = x % wh.first - 1;
xy.X = px < 0 ? 0 : px;
// Set cursor position // Set cursor position
if (SetConsoleCursorPosition(h_console, xy) == 0) { if (SetConsoleCursorPosition(h_console, xy) == 0) {
fprintf(stderr, "[ERROR] Couldn't set terminal cursor position\n"); auto code = GetLastError();
fprintf(stderr,
"[ERROR] Couldn't set terminal cursor position, err=%lu\n",
code);
exit(1); exit(1);
} }
#elif defined(OS_UNIX) #elif defined(OS_UNIX)
@ -254,17 +249,14 @@ short get_cursor_y()
#endif #endif
} }
char* readline() char* fc_readline()
{ {
short buff_cap = terminal_width(); char* buffer = (char*)calloc((size_t)buf_size, sizeof(char));
char* buffer = (char*)calloc((size_t)buff_cap, sizeof(char));
if (buffer == NULL) { if (buffer == NULL) {
fprintf(stderr, "[ERROR] Couldn't allocate memory for buffer\n"); fprintf(stderr, "[ERROR] Couldn't allocate memory for buffer\n");
exit(1); exit(1);
} }
short buff_len = 0;
// Current hint number // Current hint number
int hint_num = 0; int hint_num = 0;
while (1) { while (1) {
@ -275,11 +267,11 @@ char* readline()
color_print(buffer, DEFAULT_MAIN_COLOR); color_print(buffer, DEFAULT_MAIN_COLOR);
// Move cursor // Move cursor
int cur_pos{}; int cur_pos{};
for (int i = 0; i < buf.size() && i < wo; ++i) { for (int i = 0; i < buf.size() && i < wo; ++i) {
cur_pos += static_cast<int>(buf[i].size()); cur_pos += static_cast<int>(buf[i].size());
} }
set_cursor_x(cur_pos + 1); set_cursor_x(cur_pos + 1);
// Read character from console // Read character from console
int ch = _getch(); int ch = _getch();
@ -322,7 +314,7 @@ char* readline()
wo = wo < 1 ? 0 : (--wo); wo = wo < 1 ? 0 : (--wo);
break; break;
case RIGHT: case RIGHT:
wo = wo >= len ? len : (++wo); wo = wo >= len ? len : (++wo);
break; break;
case UP: case UP:
break; break;
@ -343,20 +335,19 @@ char* readline()
} }
default: { default: {
supply(word, ch); supply(word, ch);
if (wo < buf.size()) { if (wo < buf.size()) {
if (len >= buf.size()) { if (len >= buf.size()) {
buf.resize(buf.size() * 2); buf.resize(buf.size() * 2);
} }
if (len > 0) { if (len > 0) {
for (size_t i = len - 1; i >= wo; --i) { for (size_t i = len - 1; i >= wo; --i) {
buf[i + 1] = buf[i]; buf[i + 1] = buf[i];
} }
buf[wo] = word; buf[wo] = word;
} }
} } else {
else { buf.push_back(word);
buf.push_back(word); }
}
++wo; ++wo;
++len; ++len;
break; break;
@ -366,6 +357,11 @@ char* readline()
return buffer; return buffer;
} }
void fc_free(char* str)
{
free(str);
}
void color_print(char* text, COLOR_TYPE color) void color_print(char* text, COLOR_TYPE color)
{ {
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
@ -384,6 +380,8 @@ void color_print(char* text, COLOR_TYPE color)
exit(1); exit(1);
} }
auto wh = get_wh();
backup = console_info.wAttributes; backup = console_info.wAttributes;
// Print colored text // Print colored text
@ -403,11 +401,11 @@ void color_print(char* text, COLOR_TYPE color)
tbuf.push_back('\0'); tbuf.push_back('\0');
printf("%s", tbuf.c_str()); printf("%s", tbuf.c_str());
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo; CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hConsole, &cursorInfo); GetConsoleCursorInfo(hConsole, &cursorInfo);
cursorInfo.bVisible = TRUE; cursorInfo.bVisible = TRUE;
SetConsoleCursorInfo(hConsole, &cursorInfo); SetConsoleCursorInfo(hConsole, &cursorInfo);
// Restore original color // Restore original color
if (SetConsoleTextAttribute(h_console, backup) == 0) { if (SetConsoleTextAttribute(h_console, backup) == 0) {

View File

@ -1,3 +1,4 @@
#pragma once #pragma once
char* readline(); char* fc_readline();
void fc_free(char* str);

View File

@ -4,11 +4,13 @@
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
std::cout << "PreContent1 " << std::endl;
std::cout << "PreContent2 " << std::endl;
while (1) { while (1) {
char* content = readline(); char* content = fc_readline();
if (content) { if (content) {
std::cout << std::string(content) << std::endl; std::cout << std::string(content) << std::endl;
free(content); fc_free(content);
} }
} }
return 0; return 0;