Skip to content

Commit fc668e3

Browse files
committed
upgrade libvterm
1 parent 14e4afd commit fc668e3

File tree

3 files changed

+131
-34
lines changed

3 files changed

+131
-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: 123 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -609,15 +609,37 @@ 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+
term->title_changed = false;
638+
}
639+
term->title = concat(term->title, title, len, true);
640+
if (final) {
641+
term->title_changed = true;
616642
}
617-
term->title = malloc(sizeof(char) * (len + 1));
618-
strncpy(term->title, title, len);
619-
term->title[len] = 0;
620-
term->title_changed = true;
621643
return;
622644
}
623645

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

641663
break;
642664
case VTERM_PROP_TITLE:
643-
term_set_title(term, val->string);
665+
#ifdef VTermStringFragmentNotExists
666+
term_set_title(term, val->string, strlen(val->string), true, true);
667+
#else
668+
term_set_title(term, val->string.str, val->string.len, val->string.initial,
669+
val->string.final);
670+
#endif
644671
break;
645672
case VTERM_PROP_ALTSCREEN:
646673
invalidate_terminal(term, 0, term->height);
@@ -907,6 +934,11 @@ void term_finalize(void *object) {
907934
free(term->elisp_code);
908935
term->elisp_code = NULL;
909936
}
937+
if (term->cmd_buffer) {
938+
free(term->cmd_buffer);
939+
term->cmd_buffer = NULL;
940+
}
941+
910942
for (int i = 0; i < term->lines_len; i++) {
911943
if (term->lines[i] != NULL) {
912944
free_lineinfo(term->lines[i]);
@@ -924,29 +956,16 @@ void term_finalize(void *object) {
924956
free(term);
925957
}
926958

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') {
959+
static int handle_osc_cmd_51(Term *term, char subCmd, char *buffer) {
960+
if (subCmd == 'A') {
961+
/* "51;A" sets the current directory */
962+
/* "51;A" has also the role of identifying the end of the prompt */
944963
if (term->directory != NULL) {
945964
free(term->directory);
946965
term->directory = NULL;
947966
}
948-
term->directory = malloc(cmdlen - 4 + 1);
949-
strcpy(term->directory, &buffer[4]);
967+
term->directory = malloc(strlen(buffer) + 1);
968+
strcpy(term->directory, buffer);
950969
term->directory_changed = true;
951970

952971
for (int i = term->cursor.row; i < term->lines_len; i++) {
@@ -957,24 +976,52 @@ static int osc_callback(const char *command, size_t cmdlen, void *user) {
957976
if (term->lines[i]->directory != NULL) {
958977
free(term->lines[i]->directory);
959978
}
960-
term->lines[i]->directory = malloc(cmdlen - 4 + 1);
961-
strcpy(term->lines[i]->directory, &buffer[4]);
979+
term->lines[i]->directory = malloc(strlen(buffer) + 1);
980+
strcpy(term->lines[i]->directory, buffer);
962981
if (i == term->cursor.row) {
963982
term->lines[i]->prompt_col = term->cursor.col;
964983
} else {
965984
term->lines[i]->prompt_col = -1;
966985
}
967986
}
968987
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]);
988+
} else if (subCmd == 'E') {
989+
/* "51;E" executes elisp code */
990+
/* The elisp code is executed in term_redraw */
991+
term->elisp_code = malloc(strlen(buffer) + 1);
992+
strcpy(term->elisp_code, buffer);
973993
term->elisp_code_changed = true;
974994
return 1;
975995
}
976996
return 0;
977997
}
998+
static int handle_osc_cmd(Term *term, int cmd, char *buffer) {
999+
if (cmd == 51) {
1000+
char subCmd = '0';
1001+
if (strlen(buffer) == 0) {
1002+
return 0;
1003+
}
1004+
subCmd = buffer[0];
1005+
return handle_osc_cmd_51(term, subCmd, ++buffer);
1006+
}
1007+
return 0;
1008+
}
1009+
#ifdef VTermStringFragmentNotExists
1010+
static int osc_callback(const char *command, size_t cmdlen, void *user) {
1011+
Term *term = (Term *)user;
1012+
char buffer[cmdlen + 1];
1013+
buffer[cmdlen] = '\0';
1014+
memcpy(buffer, command, cmdlen);
1015+
1016+
if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' && buffer[2] == ';' &&
1017+
buffer[3] == 'A') {
1018+
return handle_osc_cmd_51(term, 'A', &buffer[4]);
1019+
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' &&
1020+
buffer[2] == ';' && buffer[3] == 'E') {
1021+
return handle_osc_cmd_51(term, 'E', &buffer[4]);
1022+
}
1023+
return 0;
1024+
}
9781025

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

9881076
emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
9891077
void *data) {
@@ -1041,6 +1129,8 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
10411129
term->elisp_code = NULL;
10421130
term->elisp_code_changed = false;
10431131

1132+
term->cmd_buffer = NULL;
1133+
10441134
term->lines = malloc(sizeof(LineInfo *) * rows);
10451135
term->lines_len = rows;
10461136
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)