Skip to content

Commit e4ed7c7

Browse files
committed
upgrade libvterm
1 parent 14e4afd commit e4ed7c7

File tree

3 files changed

+130
-34
lines changed

3 files changed

+130
-34
lines changed

CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ if (USE_SYSTEM_LIBVTERM)
3636
# vterm.h is found.
3737
if (LIBVTERM_INCLUDE_DIR)
3838
message(STATUS "System libvterm detected")
39+
execute_process(COMMAND grep -c "VTermStringFragment" "${LIBVTERM_INCLUDE_DIR}/vterm.h" OUTPUT_VARIABLE VTermStringFragmentExists)
40+
if (${VTermStringFragmentExists} EQUAL "0")
41+
# add_compile_definitions(VTermStringFragmentNotExists)
42+
add_definitions(-DVTermStringFragmentNotExists)
43+
endif()
3944
else()
4045
message(STATUS "System libvterm not found: libvterm will be downloaded and compiled as part of the build process")
4146
endif()
@@ -58,7 +63,7 @@ else()
5863

5964
ExternalProject_add(libvterm
6065
GIT_REPOSITORY https://github.com/neovim/libvterm.git
61-
GIT_TAG 65dbda3ed214f036ee799d18b2e693a833a0e591
66+
GIT_TAG 54c03b21f763fa775a4c0643a9d8326342873179
6267
CONFIGURE_COMMAND ""
6368
BUILD_COMMAND ${LIBVTERM_BUILD_COMMAND} "CFLAGS='-fPIC'"
6469
BUILD_IN_SOURCE ON

vterm-module.c

Lines changed: 122 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -609,15 +609,36 @@ static bool is_key(unsigned char *key, size_t len, char *key_description) {
609609
memcmp(key, key_description, len) == 0);
610610
}
611611

612-
static void term_set_title(Term *term, char *title) {
613-
size_t len = strlen(title);
614-
if (term->title) {
612+
/* str1=concat(str1,str2,str2_len,true); */
613+
/* str1 can be NULL */
614+
static char *concat(char *str1, const char *str2, size_t str2_len,
615+
bool free_str1) {
616+
if (str1 == NULL) {
617+
str1 = malloc(str2_len + 1);
618+
memcpy(str1, str2, str2_len);
619+
str1[str2_len] = '\0';
620+
return str1;
621+
}
622+
size_t str1_len = strlen(str1);
623+
char *buf = malloc(str1_len + str2_len + 1);
624+
memcpy(buf, str1, str1_len);
625+
memcpy(&buf[str1_len], str2, str2_len);
626+
buf[str1_len + str2_len] = '\0';
627+
if (free_str1) {
628+
free(str1);
629+
}
630+
return buf;
631+
}
632+
static void term_set_title(Term *term, const char *title, size_t len,
633+
bool initial, bool final) {
634+
if (term->title && initial) {
615635
free(term->title);
636+
term->title = NULL;
637+
}
638+
term->title = concat(term->title, title, len, true);
639+
if (final) {
640+
term->title_changed = true;
616641
}
617-
term->title = malloc(sizeof(char) * (len + 1));
618-
strncpy(term->title, title, len);
619-
term->title[len] = 0;
620-
term->title_changed = true;
621642
return;
622643
}
623644

@@ -640,7 +661,12 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *user_data) {
640661

641662
break;
642663
case VTERM_PROP_TITLE:
643-
term_set_title(term, val->string);
664+
#ifdef VTermStringFragmentNotExists
665+
term_set_title(term, val->string, strlen(val->string), true, true);
666+
#else
667+
term_set_title(term, val->string.str, val->string.len, val->string.initial,
668+
val->string.final);
669+
#endif
644670
break;
645671
case VTERM_PROP_ALTSCREEN:
646672
invalidate_terminal(term, 0, term->height);
@@ -907,6 +933,11 @@ void term_finalize(void *object) {
907933
free(term->elisp_code);
908934
term->elisp_code = NULL;
909935
}
936+
if (term->cmd_buffer) {
937+
free(term->cmd_buffer);
938+
term->cmd_buffer = NULL;
939+
}
940+
910941
for (int i = 0; i < term->lines_len; i++) {
911942
if (term->lines[i] != NULL) {
912943
free_lineinfo(term->lines[i]);
@@ -924,29 +955,16 @@ void term_finalize(void *object) {
924955
free(term);
925956
}
926957

927-
static int osc_callback(const char *command, size_t cmdlen, void *user) {
928-
/* osc_callback (OSC = Operating System Command) */
929-
930-
/* We interpret escape codes that start with "51;" */
931-
/* "51;A" sets the current directory */
932-
/* "51;A" has also the role of identifying the end of the prompt */
933-
/* "51;E" executes elisp code */
934-
/* The elisp code is executed in term_redraw */
935-
936-
Term *term = (Term *)user;
937-
char buffer[cmdlen + 1];
938-
939-
buffer[cmdlen] = '\0';
940-
memcpy(buffer, command, cmdlen);
941-
942-
if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' && buffer[2] == ';' &&
943-
buffer[3] == 'A') {
958+
static int handle_osc_cmd_51(Term *term, char subCmd, char *buffer) {
959+
if (subCmd == 'A') {
960+
/* "51;A" sets the current directory */
961+
/* "51;A" has also the role of identifying the end of the prompt */
944962
if (term->directory != NULL) {
945963
free(term->directory);
946964
term->directory = NULL;
947965
}
948-
term->directory = malloc(cmdlen - 4 + 1);
949-
strcpy(term->directory, &buffer[4]);
966+
term->directory = malloc(strlen(buffer) + 1);
967+
strcpy(term->directory, buffer);
950968
term->directory_changed = true;
951969

952970
for (int i = term->cursor.row; i < term->lines_len; i++) {
@@ -957,24 +975,52 @@ static int osc_callback(const char *command, size_t cmdlen, void *user) {
957975
if (term->lines[i]->directory != NULL) {
958976
free(term->lines[i]->directory);
959977
}
960-
term->lines[i]->directory = malloc(cmdlen - 4 + 1);
961-
strcpy(term->lines[i]->directory, &buffer[4]);
978+
term->lines[i]->directory = malloc(strlen(buffer) + 1);
979+
strcpy(term->lines[i]->directory, buffer);
962980
if (i == term->cursor.row) {
963981
term->lines[i]->prompt_col = term->cursor.col;
964982
} else {
965983
term->lines[i]->prompt_col = -1;
966984
}
967985
}
968986
return 1;
969-
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' &&
970-
buffer[2] == ';' && buffer[3] == 'E') {
971-
term->elisp_code = malloc(cmdlen - 4 + 1);
972-
strcpy(term->elisp_code, &buffer[4]);
987+
} else if (subCmd == 'E') {
988+
/* "51;E" executes elisp code */
989+
/* The elisp code is executed in term_redraw */
990+
term->elisp_code = malloc(strlen(buffer) + 1);
991+
strcpy(term->elisp_code, buffer);
973992
term->elisp_code_changed = true;
974993
return 1;
975994
}
976995
return 0;
977996
}
997+
static int handle_osc_cmd(Term *term, int cmd, char *buffer) {
998+
if (cmd == 51) {
999+
char subCmd = '0';
1000+
if (strlen(buffer) == 0) {
1001+
return 0;
1002+
}
1003+
subCmd = buffer[0];
1004+
return handle_osc_cmd_51(term, subCmd, ++buffer);
1005+
}
1006+
return 0;
1007+
}
1008+
#ifdef VTermStringFragmentNotExists
1009+
static int osc_callback(const char *command, size_t cmdlen, void *user) {
1010+
Term *term = (Term *)user;
1011+
char buffer[cmdlen + 1];
1012+
buffer[cmdlen] = '\0';
1013+
memcpy(buffer, command, cmdlen);
1014+
1015+
if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' && buffer[2] == ';' &&
1016+
buffer[3] == 'A') {
1017+
return handle_osc_cmd_51(term, 'A', &buffer[4]);
1018+
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' &&
1019+
buffer[2] == ';' && buffer[3] == 'E') {
1020+
return handle_osc_cmd_51(term, 'E', &buffer[4]);
1021+
}
1022+
return 0;
1023+
}
9781024

9791025
static VTermParserCallbacks parser_callbacks = {
9801026
.text = NULL,
@@ -984,6 +1030,47 @@ static VTermParserCallbacks parser_callbacks = {
9841030
.osc = &osc_callback,
9851031
.dcs = NULL,
9861032
};
1033+
#else
1034+
1035+
static int osc_callback(int cmd, VTermStringFragment frag, void *user) {
1036+
/* osc_callback (OSC = Operating System Command) */
1037+
1038+
/* We interpret escape codes that start with "51;" */
1039+
/* "51;A" sets the current directory */
1040+
/* "51;A" has also the role of identifying the end of the prompt */
1041+
/* "51;E" executes elisp code */
1042+
/* The elisp code is executed in term_redraw */
1043+
1044+
Term *term = (Term *)user;
1045+
1046+
if (frag.initial) {
1047+
/* drop old fragment,because this is a initial fragment */
1048+
if (term->cmd_buffer) {
1049+
free(term->cmd_buffer);
1050+
term->cmd_buffer = NULL;
1051+
}
1052+
}
1053+
1054+
if (!frag.initial && !frag.final && frag.len == 0) {
1055+
return 0;
1056+
}
1057+
1058+
term->cmd_buffer = concat(term->cmd_buffer, frag.str, frag.len, true);
1059+
if (frag.final) {
1060+
handle_osc_cmd(term, cmd, term->cmd_buffer);
1061+
free(term->cmd_buffer);
1062+
term->cmd_buffer = NULL;
1063+
}
1064+
return 0;
1065+
}
1066+
static VTermStateFallbacks parser_callbacks = {
1067+
.control = NULL,
1068+
.csi = NULL,
1069+
.osc = &osc_callback,
1070+
.dcs = NULL,
1071+
};
1072+
1073+
#endif
9871074

9881075
emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
9891076
void *data) {
@@ -1041,6 +1128,8 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
10411128
term->elisp_code = NULL;
10421129
term->elisp_code_changed = false;
10431130

1131+
term->cmd_buffer = NULL;
1132+
10441133
term->lines = malloc(sizeof(LineInfo *) * rows);
10451134
term->lines_len = rows;
10461135
for (int i = 0; i < rows; i++) {

vterm-module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ typedef struct Term {
8686
bool disable_underline;
8787
bool disable_inverse_video;
8888

89+
char *cmd_buffer;
90+
8991
int pty_fd;
9092
} Term;
9193

0 commit comments

Comments
 (0)