--- lbbs/src/editor.c 2025/11/08 08:21:31 1.55 +++ lbbs/src/editor.c 2025/11/10 07:23:16 1.58 @@ -23,6 +23,7 @@ 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), + TAB_SIZE = 4, }; static const char EDITOR_ESC_DISPLAY_STR[] = "\033[32m*\033[m"; @@ -77,6 +78,7 @@ EDITOR_DATA *editor_data_load(const char long line_offsets[MAX_EDITOR_DATA_LINES + 1]; long current_data_line_length = 0; long i; + int j; if (p_data == NULL) { @@ -123,6 +125,15 @@ EDITOR_DATA *editor_data_load(const char memcpy(p_editor_data->p_display_lines[i], p_data + line_offsets[i], (size_t)p_editor_data->display_line_lengths[i]); current_data_line_length += p_editor_data->display_line_lengths[i]; + // Convert \t to single space + for (j = 0; j < p_editor_data->display_line_lengths[i]; j++) + { + if (p_editor_data->p_display_lines[i][j] == '\t') + { + p_editor_data->p_display_lines[i][j] = ' '; + } + } + // Trim \n from last line if (i + 1 == p_editor_data->display_line_total && p_editor_data->display_line_lengths[i] > 0 && @@ -647,9 +658,10 @@ int editor_display(EDITOR_DATA *p_editor EDITOR_CTX ctx; int ch = 0; char input_str[5]; + int str_len = 0; wchar_t wcs[2]; + int wc_len; char c; - int str_len = 0; int input_ok; const int screen_begin_row = 1; const int screen_row_total = SCREEN_ROWS - screen_begin_row; @@ -668,6 +680,7 @@ int editor_display(EDITOR_DATA *p_editor int i, j; char *p_str; int del_line; + int tab_width = 0; clrline(output_current_row, SCREEN_ROWS); @@ -706,6 +719,7 @@ int editor_display(EDITOR_DATA *p_editor moveto((int)row_pos, (int)col_pos); iflush(); + tab_width = 0; str_len = 0; ch = igetch_t(BBS_max_user_idle_time); while (!SYS_server_exit) @@ -721,6 +735,12 @@ int editor_display(EDITOR_DATA *p_editor goto cleanup; } + if (ch == '\t') + { + ch = ' '; + tab_width = TAB_SIZE - ((int)(col_pos - 1) % TAB_SIZE) - 1; + } + if (ch < 256 && (ch & 0x80)) // head of multi-byte character { str_len = 0; @@ -839,10 +859,17 @@ int editor_display(EDITOR_DATA *p_editor break; } - ch = igetch(0); - if (ch == KEY_NULL || ch == KEY_TIMEOUT) // Output if no futher input + if (ch == ' ' && tab_width > 0) { - break; + tab_width--; + } + else + { + ch = igetch(0); + if (ch == KEY_NULL || ch == KEY_TIMEOUT) // Output if no futher input + { + break; + } } str_len = 0; @@ -1025,13 +1052,36 @@ 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); col_pos = display_len; - if (offset_in >= 1 && p_editor_data->p_display_lines[line_current - output_current_row + row_pos][offset_in - 1] < 0) // UTF8 + if (offset_in > 0) { - split_line(p_editor_data->p_display_lines[line_current - output_current_row + row_pos], - (int)col_pos - 1, &eol, &display_len, 0); - if (display_len == col_pos - 2) + 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 { - col_pos--; + 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) @@ -1062,15 +1112,41 @@ 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); col_pos = display_len + 2; - 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 + if (offset_in < p_editor_data->display_line_lengths[line_current - output_current_row + row_pos]) { - split_line(p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, - 1, &eol, &display_len, 0); - if (display_len == 0) + 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 { - col_pos++; + str_len = 1; } + offset_in += str_len; } if (col_pos <= p_editor_data->display_line_widths[line_current - output_current_row + row_pos]) {