| 3 |
* editor |
* editor |
| 4 |
* - user interactive full-screen text editor |
* - user interactive full-screen text editor |
| 5 |
* |
* |
| 6 |
* Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com> |
* Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com> |
| 7 |
*/ |
*/ |
| 8 |
|
|
| 9 |
|
#ifdef HAVE_CONFIG_H |
| 10 |
|
#include "config.h" |
| 11 |
|
#endif |
| 12 |
|
|
| 13 |
#include "bbs.h" |
#include "bbs.h" |
| 14 |
#include "common.h" |
#include "common.h" |
| 15 |
#include "editor.h" |
#include "editor.h" |
| 38 |
{ |
{ |
| 39 |
if (p_mp_data_line != NULL || p_mp_editor_data != NULL) |
if (p_mp_data_line != NULL || p_mp_editor_data != NULL) |
| 40 |
{ |
{ |
| 41 |
log_error("Editor mem pool already initialized\n"); |
log_error("Editor mem pool already initialized"); |
| 42 |
return -1; |
return -1; |
| 43 |
} |
} |
| 44 |
|
|
| 45 |
p_mp_data_line = memory_pool_init(MAX_EDITOR_DATA_LINE_LENGTH, EDITOR_MEM_POOL_LINE_PER_CHUNK, EDITOR_MEM_POOL_CHUNK_LIMIT); |
p_mp_data_line = memory_pool_init(MAX_EDITOR_DATA_LINE_LENGTH, EDITOR_MEM_POOL_LINE_PER_CHUNK, EDITOR_MEM_POOL_CHUNK_LIMIT); |
| 46 |
if (p_mp_data_line == NULL) |
if (p_mp_data_line == NULL) |
| 47 |
{ |
{ |
| 48 |
log_error("Memory pool init error\n"); |
log_error("Memory pool init error"); |
| 49 |
return -2; |
return -2; |
| 50 |
} |
} |
| 51 |
|
|
| 52 |
p_mp_editor_data = memory_pool_init(sizeof(EDITOR_DATA), 1, 1); |
p_mp_editor_data = memory_pool_init(sizeof(EDITOR_DATA), 1, 1); |
| 53 |
if (p_mp_editor_data == NULL) |
if (p_mp_editor_data == NULL) |
| 54 |
{ |
{ |
| 55 |
log_error("Memory pool init error\n"); |
log_error("Memory pool init error"); |
| 56 |
return -3; |
return -3; |
| 57 |
} |
} |
| 58 |
|
|
| 85 |
|
|
| 86 |
if (p_data == NULL) |
if (p_data == NULL) |
| 87 |
{ |
{ |
| 88 |
log_error("NULL pointer error\n"); |
log_error("NULL pointer error"); |
| 89 |
return NULL; |
return NULL; |
| 90 |
} |
} |
| 91 |
|
|
| 92 |
p_editor_data = memory_pool_alloc(p_mp_editor_data); |
p_editor_data = memory_pool_alloc(p_mp_editor_data); |
| 93 |
if (p_editor_data == NULL) |
if (p_editor_data == NULL) |
| 94 |
{ |
{ |
| 95 |
log_error("memory_pool_alloc() error\n"); |
log_error("memory_pool_alloc() error"); |
| 96 |
return NULL; |
return NULL; |
| 97 |
} |
} |
| 98 |
|
|
| 111 |
p_data_line = memory_pool_alloc(p_mp_data_line); |
p_data_line = memory_pool_alloc(p_mp_data_line); |
| 112 |
if (p_data_line == NULL) |
if (p_data_line == NULL) |
| 113 |
{ |
{ |
| 114 |
log_error("memory_pool_alloc() error: i = %d\n", i); |
log_error("memory_pool_alloc() error: i = %d", i); |
| 115 |
// Cleanup |
// Cleanup |
| 116 |
editor_data_cleanup(p_editor_data); |
editor_data_cleanup(p_editor_data); |
| 117 |
return NULL; |
return NULL; |
| 161 |
|
|
| 162 |
if (p_editor_data == NULL || p_data == NULL) |
if (p_editor_data == NULL || p_data == NULL) |
| 163 |
{ |
{ |
| 164 |
log_error("NULL pointer error\n"); |
log_error("NULL pointer error"); |
| 165 |
return -1; |
return -1; |
| 166 |
} |
} |
| 167 |
|
|
| 169 |
{ |
{ |
| 170 |
if (current_pos + p_editor_data->display_line_lengths[i] + 1 > buf_len) |
if (current_pos + p_editor_data->display_line_lengths[i] + 1 > buf_len) |
| 171 |
{ |
{ |
| 172 |
log_error("Data buffer not longer enough %d > %d\n", current_pos + p_editor_data->display_line_lengths[i] + 1, buf_len); |
log_error("Data buffer not longer enough %d > %d", current_pos + p_editor_data->display_line_lengths[i] + 1, buf_len); |
| 173 |
p_data[current_pos] = '\0'; |
p_data[current_pos] = '\0'; |
| 174 |
return -2; |
return -2; |
| 175 |
} |
} |
| 235 |
|
|
| 236 |
if (p_editor_data == NULL || p_last_updated_line == NULL) |
if (p_editor_data == NULL || p_last_updated_line == NULL) |
| 237 |
{ |
{ |
| 238 |
log_error("NULL pointer error\n"); |
log_error("NULL pointer error"); |
| 239 |
return -1; |
return -1; |
| 240 |
} |
} |
| 241 |
|
|
| 272 |
{ |
{ |
| 273 |
if (p_editor_data->display_line_total >= MAX_EDITOR_DATA_LINES) |
if (p_editor_data->display_line_total >= MAX_EDITOR_DATA_LINES) |
| 274 |
{ |
{ |
| 275 |
#ifdef _DEBUG |
log_debug("Split line error, display_line_total(%ld) reach limit(%d)", |
|
log_error("Split line error, display_line_total(%ld) reach limit(%d)\n", |
|
| 276 |
p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); |
p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); |
|
#endif |
|
| 277 |
|
|
| 278 |
return -2; |
return -2; |
| 279 |
} |
} |
| 282 |
p_data_line = memory_pool_alloc(p_mp_data_line); |
p_data_line = memory_pool_alloc(p_mp_data_line); |
| 283 |
if (p_data_line == NULL) |
if (p_data_line == NULL) |
| 284 |
{ |
{ |
| 285 |
log_error("memory_pool_alloc() error\n"); |
log_error("memory_pool_alloc() error"); |
| 286 |
return -2; |
return -2; |
| 287 |
} |
} |
| 288 |
|
|
| 367 |
// Insert blank display line after last_display_line |
// Insert blank display line after last_display_line |
| 368 |
if (p_editor_data->display_line_total >= MAX_EDITOR_DATA_LINES) |
if (p_editor_data->display_line_total >= MAX_EDITOR_DATA_LINES) |
| 369 |
{ |
{ |
| 370 |
#ifdef _DEBUG |
log_debug("display_line_total over limit %d >= %d", p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); |
|
log_error("display_line_total over limit %d >= %d\n", p_editor_data->display_line_total, MAX_EDITOR_DATA_LINES); |
|
|
#endif |
|
| 371 |
|
|
| 372 |
// Terminate prior display line with \n, to avoid error on cleanup |
// Terminate prior display line with \n, to avoid error on cleanup |
| 373 |
if (display_line + i - 1 >= 0 && p_editor_data->display_line_lengths[display_line + i - 1] > 0) |
if (display_line + i - 1 >= 0 && p_editor_data->display_line_lengths[display_line + i - 1] > 0) |
| 469 |
|
|
| 470 |
if (p_editor_data == NULL || p_last_updated_line == NULL) |
if (p_editor_data == NULL || p_last_updated_line == NULL) |
| 471 |
{ |
{ |
| 472 |
log_error("NULL pointer error\n"); |
log_error("NULL pointer error"); |
| 473 |
return -1; |
return -1; |
| 474 |
} |
} |
| 475 |
|
|
| 527 |
} |
} |
| 528 |
else |
else |
| 529 |
{ |
{ |
| 530 |
log_error("Some strange character at display_line %ld, offset %ld: %d %d\n", |
log_error("Some strange character at display_line %ld, offset %ld: %d %d", |
| 531 |
display_line, offset, p_data_line[offset_data_line], p_data_line[offset_data_line + 1]); |
display_line, offset, p_data_line[offset_data_line], p_data_line[offset_data_line + 1]); |
| 532 |
str_len = 1; |
str_len = 1; |
| 533 |
} |
} |
| 759 |
ch = igetch(100); // 0.1 second |
ch = igetch(100); // 0.1 second |
| 760 |
if (ch == KEY_NULL || ch == KEY_TIMEOUT) // Ignore received bytes if no futher input |
if (ch == KEY_NULL || ch == KEY_TIMEOUT) // Ignore received bytes if no futher input |
| 761 |
{ |
{ |
| 762 |
#ifdef _DEBUG |
log_debug("Ignore %d bytes of incomplete UTF8 character", str_len); |
|
log_error("Ignore %d bytes of incomplete UTF8 character\n", str_len); |
|
|
#endif |
|
| 763 |
str_len = 0; |
str_len = 0; |
| 764 |
break; |
break; |
| 765 |
} |
} |
| 773 |
// Refresh current action while user input |
// Refresh current action while user input |
| 774 |
if (user_online_update(NULL) < 0) |
if (user_online_update(NULL) < 0) |
| 775 |
{ |
{ |
| 776 |
log_error("user_online_update(NULL) error\n"); |
log_error("user_online_update(NULL) error"); |
| 777 |
} |
} |
| 778 |
|
|
| 779 |
if (str_len == 0) // ch >= 32 && ch < 127 |
if (str_len == 0) // ch >= 32 && ch < 127 |
| 794 |
if (editor_data_delete(p_editor_data, &display_line_out, &offset_out, |
if (editor_data_delete(p_editor_data, &display_line_out, &offset_out, |
| 795 |
&last_updated_line, 0) < 0) |
&last_updated_line, 0) < 0) |
| 796 |
{ |
{ |
| 797 |
log_error("editor_data_delete() error\n"); |
log_error("editor_data_delete() error"); |
| 798 |
} |
} |
| 799 |
} |
} |
| 800 |
|
|
| 801 |
if (editor_data_insert(p_editor_data, &display_line_out, &offset_out, |
if (editor_data_insert(p_editor_data, &display_line_out, &offset_out, |
| 802 |
input_str, str_len, &last_updated_line) < 0) |
input_str, str_len, &last_updated_line) < 0) |
| 803 |
{ |
{ |
| 804 |
log_error("editor_data_insert(str_len=%d) error\n", str_len); |
log_error("editor_data_insert(str_len=%d) error", str_len); |
| 805 |
} |
} |
| 806 |
else |
else |
| 807 |
{ |
{ |
| 844 |
{ |
{ |
| 845 |
if (mbstowcs(wcs, input_str, 1) == (size_t)-1) |
if (mbstowcs(wcs, input_str, 1) == (size_t)-1) |
| 846 |
{ |
{ |
| 847 |
log_error("mbstowcs() error\n"); |
log_error("mbstowcs() error"); |
| 848 |
} |
} |
| 849 |
col_pos += (str_len == 1 ? 1 : (UTF8_fixed_width ? 2 : wcwidth(wcs[0]))); |
col_pos += (str_len == 1 ? 1 : (UTF8_fixed_width ? 2 : wcwidth(wcs[0]))); |
| 850 |
} |
} |
| 877 |
// Refresh current action while user input |
// Refresh current action while user input |
| 878 |
if (user_online_update(NULL) < 0) |
if (user_online_update(NULL) < 0) |
| 879 |
{ |
{ |
| 880 |
log_error("user_online_update(NULL) error\n"); |
log_error("user_online_update(NULL) error"); |
| 881 |
} |
} |
| 882 |
|
|
| 883 |
del_line = 0; |
del_line = 0; |
| 916 |
if ((str_len = editor_data_delete(p_editor_data, &display_line_out, &offset_out, |
if ((str_len = editor_data_delete(p_editor_data, &display_line_out, &offset_out, |
| 917 |
&last_updated_line, del_line)) < 0) |
&last_updated_line, del_line)) < 0) |
| 918 |
{ |
{ |
| 919 |
log_error("editor_data_delete() error: %d\n", str_len); |
log_error("editor_data_delete() error: %d", str_len); |
| 920 |
} |
} |
| 921 |
else |
else |
| 922 |
{ |
{ |
| 968 |
switch (ch) |
switch (ch) |
| 969 |
{ |
{ |
| 970 |
case KEY_NULL: |
case KEY_NULL: |
| 971 |
log_error("KEY_NULL\n"); |
log_debug("KEY_NULL"); |
| 972 |
goto cleanup; |
goto cleanup; |
| 973 |
case KEY_TIMEOUT: |
case KEY_TIMEOUT: |
| 974 |
log_error("User input timeout\n"); |
log_debug("User input timeout"); |
| 975 |
goto cleanup; |
goto cleanup; |
| 976 |
case Ctrl('W'): |
case Ctrl('W'): |
| 977 |
case Ctrl('X'): |
case Ctrl('X'): |
| 1065 |
|
|
| 1066 |
if (str_len > 4) |
if (str_len > 4) |
| 1067 |
{ |
{ |
| 1068 |
log_error("Invalid UTF-8 data detected: str_len > 4\n"); |
log_error("Invalid UTF-8 data detected: str_len > 4"); |
| 1069 |
} |
} |
| 1070 |
|
|
| 1071 |
if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == |
if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == |
| 1072 |
(size_t)-1) |
(size_t)-1) |
| 1073 |
{ |
{ |
| 1074 |
log_error("mbstowcs() error\n"); |
log_error("mbstowcs() error"); |
| 1075 |
} |
} |
| 1076 |
wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); |
wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); |
| 1077 |
|
|
| 1124 |
|
|
| 1125 |
if (str_len > 4) |
if (str_len > 4) |
| 1126 |
{ |
{ |
| 1127 |
log_error("Invalid UTF-8 data detected: str_len > 4\n"); |
log_error("Invalid UTF-8 data detected: str_len > 4"); |
| 1128 |
} |
} |
| 1129 |
|
|
| 1130 |
if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == |
if (mbstowcs(wcs, p_editor_data->p_display_lines[line_current - output_current_row + row_pos] + offset_in, 1) == |
| 1131 |
(size_t)-1) |
(size_t)-1) |
| 1132 |
{ |
{ |
| 1133 |
log_error("mbstowcs() error\n"); |
log_error("mbstowcs() error"); |
| 1134 |
} |
} |
| 1135 |
wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); |
wc_len = (UTF8_fixed_width ? 2 : wcwidth(wcs[0])); |
| 1136 |
|
|
| 1229 |
// Refresh current action while user input |
// Refresh current action while user input |
| 1230 |
if (user_online_update(NULL) < 0) |
if (user_online_update(NULL) < 0) |
| 1231 |
{ |
{ |
| 1232 |
log_error("user_online_update(NULL) error\n"); |
log_error("user_online_update(NULL) error"); |
| 1233 |
} |
} |
| 1234 |
|
|
| 1235 |
if (input_ok) |
if (input_ok) |
| 1246 |
len = p_editor_data->display_line_lengths[line_current]; |
len = p_editor_data->display_line_lengths[line_current]; |
| 1247 |
if (len >= sizeof(buffer)) |
if (len >= sizeof(buffer)) |
| 1248 |
{ |
{ |
| 1249 |
log_error("Buffer overflow: len=%ld line=%ld \n", len, line_current); |
log_error("Buffer overflow: len=%ld line=%ld ", len, line_current); |
| 1250 |
len = sizeof(buffer) - 1; |
len = sizeof(buffer) - 1; |
| 1251 |
} |
} |
| 1252 |
else if (len < 0) |
else if (len < 0) |
| 1253 |
{ |
{ |
| 1254 |
log_error("Incorrect line offsets: len=%ld line=%ld \n", len, line_current); |
log_error("Incorrect line offsets: len=%ld line=%ld ", len, line_current); |
| 1255 |
len = 0; |
len = 0; |
| 1256 |
} |
} |
| 1257 |
|
|