--- lbbs/src/editor.c 2025/11/04 14:58:56 1.52 +++ lbbs/src/editor.c 2025/11/08 12:32:16 1.56 @@ -16,11 +16,16 @@ #include "str_process.h" #include #include +#include #include -#define EDITOR_ESC_DISPLAY_STR "\033[32m*\033[m" -#define EDITOR_MEM_POOL_LINE_PER_CHUNK 1000 -#define EDITOR_MEM_POOL_CHUNK_LIMIT (MAX_EDITOR_DATA_LINES / EDITOR_MEM_POOL_LINE_PER_CHUNK + 1) +enum _editor_constant_t +{ + EDITOR_MEM_POOL_LINE_PER_CHUNK = 1000, + EDITOR_MEM_POOL_CHUNK_LIMIT = (MAX_EDITOR_DATA_LINES / EDITOR_MEM_POOL_LINE_PER_CHUNK + 1), +}; + +static const char EDITOR_ESC_DISPLAY_STR[] = "\033[32m*\033[m"; static MEMORY_POOL *p_mp_data_line; static MEMORY_POOL *p_mp_editor_data; @@ -624,7 +629,8 @@ static int editor_display_key_handler(in { case 0: // Set msg snprintf(p_ctx->msg, sizeof(p_ctx->msg), - "| 退出[\033[32mCtrl-W\033[33m] |"); + "| 退出[\033[32mCtrl-W\033[33m] | [\033[32m%s\033[33m]", + (UTF8_fixed_width ? "定宽" : "变宽")); break; case KEY_CSI: *p_key = KEY_ESC; @@ -640,9 +646,11 @@ int editor_display(EDITOR_DATA *p_editor char buffer[MAX_EDITOR_DATA_LINE_LENGTH]; EDITOR_CTX ctx; int ch = 0; - char input_str[4]; - char c; + char input_str[5]; int str_len = 0; + wchar_t wcs[2]; + int wc_len; + char c; int input_ok; const int screen_begin_row = 1; const int screen_row_total = SCREEN_ROWS - screen_begin_row; @@ -700,7 +708,7 @@ int editor_display(EDITOR_DATA *p_editor iflush(); str_len = 0; - ch = igetch_t(MAX_DELAY_TIME); + ch = igetch_t(BBS_max_user_idle_time); while (!SYS_server_exit) { if (ch != KEY_NULL && ch != KEY_TIMEOUT) @@ -740,6 +748,7 @@ int editor_display(EDITOR_DATA *p_editor break; } } + input_str[str_len] = '\0'; } if ((ch >= 32 && ch < 127) || str_len >= 2 || // Printable character or multi-byte character @@ -817,7 +826,11 @@ int editor_display(EDITOR_DATA *p_editor } if (offset_out > 0) { - col_pos += (str_len == 1 ? 1 : 2); + if (mbstowcs(wcs, input_str, 1) == (size_t)-1) + { + log_error("mbstowcs() error\n"); + } + col_pos += (str_len == 1 ? 1 : (UTF8_fixed_width ? 2 : wcwidth(wcs[0]))); } } } @@ -855,15 +868,7 @@ int editor_display(EDITOR_DATA *p_editor offset_in = split_line(p_editor_data->p_display_lines[line_current - output_current_row + row_pos], (int)col_pos - 1, &eol, &display_len, 0); - if (offset_in >= 1 && p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in - 1] < 0) // UTF8 - { - col_pos = display_len - 1; - } - else - { - col_pos = display_len; - } - + col_pos = display_len; if (col_pos < 1 && line_current - output_current_row + row_pos >= 0) { row_pos--; @@ -1020,13 +1025,38 @@ int editor_display(EDITOR_DATA *p_editor case KEY_LEFT: offset_in = split_line(p_editor_data->p_display_lines[line_current - output_current_row + row_pos], (int)col_pos - 1, &eol, &display_len, 0); - if (offset_in >= 1 && p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in - 1] < 0) // UTF8 - { - col_pos = display_len - 1; - } - else + col_pos = display_len; + if (offset_in > 0) { - col_pos = display_len; + str_len = 1; + offset_in--; + if (p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] < 0 || + p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] > 127) // UTF8 + { + while (offset_in > 0 && + (p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] & 0xc0) != 0xc0) + { + str_len++; + offset_in--; + } + + if (str_len > 4) + { + log_error("Invalid UTF-8 data detected: str_len > 4\n"); + } + + if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == + (size_t)-1) + { + log_error("mbstowcs() error\n"); + } + wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); + + if (wc_len == 2) + { + col_pos--; + } + } } if (col_pos >= 1) { @@ -1055,14 +1085,42 @@ int editor_display(EDITOR_DATA *p_editor case KEY_RIGHT: offset_in = split_line(p_editor_data->p_display_lines[line_current - output_current_row + row_pos], (int)col_pos - 1, &eol, &display_len, 0); - if (offset_in < p_editor_data->display_line_lengths[line_current - output_current_row + row_pos] && - p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] < 0) // UTF8 - { - col_pos = display_len + 3; - } - else + col_pos = display_len + 2; + if (offset_in < p_editor_data->display_line_lengths[line_current - output_current_row + row_pos]) { - col_pos = display_len + 2; + str_len = 0; + if ((p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] & 0x80) == + 0x80) // head of multi-byte character + { + c = (char)(p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in] & 0xf0); + while (c & 0x80) + { + str_len++; + c = (c & 0x7f) << 1; + } + + if (str_len > 4) + { + log_error("Invalid UTF-8 data detected: str_len > 4\n"); + } + + if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == + (size_t)-1) + { + log_error("mbstowcs() error\n"); + } + wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); + + if (wc_len == 2) + { + col_pos++; + } + } + else + { + str_len = 1; + } + offset_in += str_len; } if (col_pos <= p_editor_data->display_line_widths[line_current - output_current_row + row_pos]) { @@ -1156,7 +1214,7 @@ int editor_display(EDITOR_DATA *p_editor break; } - ch = igetch_t(MAX_DELAY_TIME); + ch = igetch_t(BBS_max_user_idle_time); } continue;