@@ -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
9791025static 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
9881075emacs_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 ++ ) {
0 commit comments