Skip to content

Commit 4aac66e

Browse files
committed
upgrade libvterm
1 parent 14e4afd commit 4aac66e

File tree

3 files changed

+96
-29
lines changed

3 files changed

+96
-29
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: 88 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -609,8 +609,7 @@ 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);
612+
static void term_set_title(Term *term, const char *title, size_t len) {
614613
if (term->title) {
615614
free(term->title);
616615
}
@@ -640,7 +639,11 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *user_data) {
640639

641640
break;
642641
case VTERM_PROP_TITLE:
643-
term_set_title(term, val->string);
642+
#ifdef VTermStringFragmentNotExists
643+
term_set_title(term, val->string, strlen(val->string));
644+
#else
645+
term_set_title(term, val->string.str, val->string.len);
646+
#endif
644647
break;
645648
case VTERM_PROP_ALTSCREEN:
646649
invalidate_terminal(term, 0, term->height);
@@ -907,6 +910,11 @@ void term_finalize(void *object) {
907910
free(term->elisp_code);
908911
term->elisp_code = NULL;
909912
}
913+
if (term->cmd_buffer) {
914+
free(term->cmd_buffer);
915+
term->cmd_buffer = NULL;
916+
}
917+
910918
for (int i = 0; i < term->lines_len; i++) {
911919
if (term->lines[i] != NULL) {
912920
free_lineinfo(term->lines[i]);
@@ -924,29 +932,16 @@ void term_finalize(void *object) {
924932
free(term);
925933
}
926934

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') {
935+
static int handle_osc_cmd_51(Term *term, char subCmd, char *buffer) {
936+
if (subCmd == 'A') {
937+
/* "51;A" sets the current directory */
938+
/* "51;A" has also the role of identifying the end of the prompt */
944939
if (term->directory != NULL) {
945940
free(term->directory);
946941
term->directory = NULL;
947942
}
948-
term->directory = malloc(cmdlen - 4 + 1);
949-
strcpy(term->directory, &buffer[4]);
943+
term->directory = malloc(strlen(buffer) + 1);
944+
strcpy(term->directory, buffer);
950945
term->directory_changed = true;
951946

952947
for (int i = term->cursor.row; i < term->lines_len; i++) {
@@ -957,24 +952,52 @@ static int osc_callback(const char *command, size_t cmdlen, void *user) {
957952
if (term->lines[i]->directory != NULL) {
958953
free(term->lines[i]->directory);
959954
}
960-
term->lines[i]->directory = malloc(cmdlen - 4 + 1);
961-
strcpy(term->lines[i]->directory, &buffer[4]);
955+
term->lines[i]->directory = malloc(strlen(buffer) + 1);
956+
strcpy(term->lines[i]->directory, buffer);
962957
if (i == term->cursor.row) {
963958
term->lines[i]->prompt_col = term->cursor.col;
964959
} else {
965960
term->lines[i]->prompt_col = -1;
966961
}
967962
}
968963
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]);
964+
} else if (subCmd == 'E') {
965+
/* "51;E" executes elisp code */
966+
/* The elisp code is executed in term_redraw */
967+
term->elisp_code = malloc(strlen(buffer) + 1);
968+
strcpy(term->elisp_code, buffer);
973969
term->elisp_code_changed = true;
974970
return 1;
975971
}
976972
return 0;
977973
}
974+
static int handle_osc_cmd(Term *term, int cmd, char *buffer) {
975+
if (cmd == 51) {
976+
char subCmd = '0';
977+
if (strlen(buffer) == 0) {
978+
return 0;
979+
}
980+
subCmd = buffer[0];
981+
return handle_osc_cmd_51(term, subCmd, ++buffer);
982+
}
983+
return 0;
984+
}
985+
#ifdef VTermStringFragmentNotExists
986+
static int osc_callback(const char *command, size_t cmdlen, void *user) {
987+
Term *term = (Term *)user;
988+
char buffer[cmdlen + 1];
989+
buffer[cmdlen] = '\0';
990+
memcpy(buffer, command, cmdlen);
991+
992+
if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' && buffer[2] == ';' &&
993+
buffer[3] == 'A') {
994+
return handle_osc_cmd_51(term, 'A', &buffer[4]);
995+
} else if (cmdlen > 4 && buffer[0] == '5' && buffer[1] == '1' &&
996+
buffer[2] == ';' && buffer[3] == 'E') {
997+
return handle_osc_cmd_51(term, 'E', &buffer[4]);
998+
}
999+
return 0;
1000+
}
9781001

9791002
static VTermParserCallbacks parser_callbacks = {
9801003
.text = NULL,
@@ -984,6 +1007,41 @@ static VTermParserCallbacks parser_callbacks = {
9841007
.osc = &osc_callback,
9851008
.dcs = NULL,
9861009
};
1010+
#else
1011+
1012+
static int osc_callback(int cmd, VTermStringFragment frag, void *user) {
1013+
/* osc_callback (OSC = Operating System Command) */
1014+
Term *term = (Term *)user;
1015+
size_t oldlen = 0;
1016+
if (term->cmd_buffer) {
1017+
oldlen = strlen(term->cmd_buffer);
1018+
}
1019+
char *buffer = malloc(oldlen + frag.len + 1);
1020+
buffer[oldlen + frag.len] = '\0';
1021+
if (term->cmd_buffer) {
1022+
memcpy(buffer, term->cmd_buffer, oldlen);
1023+
memcpy(&buffer[oldlen], frag.str, frag.len);
1024+
free(term->cmd_buffer);
1025+
term->cmd_buffer = NULL;
1026+
} else {
1027+
memcpy(buffer, frag.str, frag.len);
1028+
}
1029+
term->cmd_buffer = buffer;
1030+
if (frag.final) {
1031+
handle_osc_cmd(term, cmd, buffer);
1032+
free(term->cmd_buffer);
1033+
term->cmd_buffer = NULL;
1034+
}
1035+
return 0;
1036+
}
1037+
static VTermStateFallbacks parser_callbacks = {
1038+
.control = NULL,
1039+
.csi = NULL,
1040+
.osc = &osc_callback,
1041+
.dcs = NULL,
1042+
};
1043+
1044+
#endif
9871045

9881046
emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
9891047
void *data) {
@@ -1041,6 +1099,8 @@ emacs_value Fvterm_new(emacs_env *env, ptrdiff_t nargs, emacs_value args[],
10411099
term->elisp_code = NULL;
10421100
term->elisp_code_changed = false;
10431101

1102+
term->cmd_buffer = NULL;
1103+
10441104
term->lines = malloc(sizeof(LineInfo *) * rows);
10451105
term->lines_len = rows;
10461106
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)