@@ -1244,7 +1244,7 @@ END_ALLOW_CASE_RANGE
12441244 handle_esc_mode_char(screen, codepoint, dump_callback); \
12451245 break; \
12461246 case CSI: \
1247- if (accumulate_csi(screen, codepoint, dump_callback)) { dispatch_csi(screen, dump_callback); SET_STATE(0); } \
1247+ if (accumulate_csi(screen, codepoint, dump_callback)) { dispatch_csi(screen, dump_callback); SET_STATE(0); watch_for_pending; } \
12481248 break; \
12491249 case OSC: \
12501250 if (accumulate_osc(screen, codepoint, dump_callback)) { dispatch_osc(screen, dump_callback); SET_STATE(0); } \
@@ -1316,78 +1316,110 @@ FLUSH_DRAW;
13161316}
13171317
13181318
1319- static inline size_t
1319+ static size_t
13201320_queue_pending_bytes (Screen * screen , const uint8_t * buf , size_t len , PyObject * dump_callback DUMP_UNUSED ) {
13211321 size_t pos = 0 ;
1322- enum STATE { NORMAL , MAYBE_DCS , IN_DCS , EXPECTING_DATA , EXPECTING_SLASH };
1323- enum STATE state = screen -> pending_mode .state ;
1324- #define COPY (what ) screen->pending_mode.buf[screen->pending_mode.used++] = what
1325- #define COPY_STOP_BUF { \
1326- COPY(0x1b); COPY('P'); COPY(PENDING_MODE_CHAR); \
1327- for (size_t i = 0; i < screen->pending_mode.stop_buf_pos; i++) { \
1328- COPY(screen->pending_mode.stop_buf[i]); \
1322+ enum STATE { NORMAL , MAYBE_DCS_OR_CSI , IN_DCS , IN_CSI , EXPECTING_DATA , EXPECTING_CSI_DATA , EXPECTING_SLASH };
1323+ #define pm screen->pending_mode
1324+ enum STATE state = pm .state ;
1325+ #define stop_pending_mode \
1326+ if (state == EXPECTING_CSI_DATA) { REPORT_COMMAND(screen_reset_mode, 2026, 1); } \
1327+ else { REPORT_COMMAND(screen_stop_pending_mode); } \
1328+ pm.activated_at = 0; \
1329+ goto end;
1330+ #define start_pending_mode \
1331+ if (state == EXPECTING_CSI_DATA) { REPORT_COMMAND(screen_set_mode, 2026, 1); } \
1332+ else { REPORT_COMMAND(screen_start_pending_mode); } \
1333+ pm.activated_at = monotonic();
1334+ #define COPY (what ) pm.buf[pm.used++] = what
1335+ #define COPY_STOP_BUF (for_dcs ) { \
1336+ COPY(0x1b); \
1337+ if (for_dcs) { COPY('P'); COPY(PENDING_MODE_CHAR); } \
1338+ else { COPY('['); COPY('?'); } \
1339+ for (size_t i = 0; i < pm.stop_buf_pos; i++) { \
1340+ COPY(pm.stop_buf[i]); \
13291341 } \
1330- screen->pending_mode .stop_buf_pos = 0;}
1342+ pm .stop_buf_pos = 0;}
13311343
13321344 while (pos < len ) {
13331345 uint8_t ch = buf [pos ++ ];
13341346 switch (state ) {
13351347 case NORMAL :
1336- if (ch == ESC ) state = MAYBE_DCS ;
1348+ if (ch == ESC ) state = MAYBE_DCS_OR_CSI ;
13371349 else COPY (ch );
13381350 break ;
1339- case MAYBE_DCS :
1351+ case MAYBE_DCS_OR_CSI :
13401352 if (ch == 'P' ) state = IN_DCS ;
1353+ else if (ch == '[' ) state = IN_CSI ;
13411354 else {
13421355 state = NORMAL ;
13431356 COPY (0x1b ); COPY (ch );
13441357 }
13451358 break ;
13461359 case IN_DCS :
1347- if (ch == PENDING_MODE_CHAR ) { state = EXPECTING_DATA ; screen -> pending_mode .stop_buf_pos = 0 ; }
1360+ if (ch == PENDING_MODE_CHAR ) { state = EXPECTING_DATA ; pm .stop_buf_pos = 0 ; }
13481361 else {
13491362 state = NORMAL ;
13501363 COPY (0x1b ); COPY ('P' ); COPY (ch );
13511364 }
13521365 break ;
1366+ case IN_CSI :
1367+ if (ch == '?' ) { state = EXPECTING_CSI_DATA ; pm .stop_buf_pos = 0 ; }
1368+ else {
1369+ state = NORMAL ;
1370+ COPY (0x1b ); COPY ('[' ); COPY (ch );
1371+ }
1372+ break ;
1373+ case EXPECTING_CSI_DATA :
1374+ if (ch == 'h' || ch == 'l' ) {
1375+ if (pm .stop_buf_pos == 4 && memcmp (pm .stop_buf , "2026" , 4 ) == 0 ) {
1376+ if (ch == 'h' ) { start_pending_mode } else { stop_pending_mode }
1377+ } else {
1378+ COPY_STOP_BUF (false); COPY (ch );
1379+ }
1380+ state = NORMAL ;
1381+ } else {
1382+ pm .stop_buf [pm .stop_buf_pos ++ ] = ch ;
1383+ if (pm .stop_buf_pos >= sizeof (pm .stop_buf )) {
1384+ state = NORMAL ;
1385+ COPY_STOP_BUF (false);
1386+ }
1387+ }
1388+ break ;
13531389 case EXPECTING_DATA :
1390+ pm .stop_buf [pm .stop_buf_pos ++ ] = ch ;
13541391 if (ch == 0x1b ) state = EXPECTING_SLASH ;
13551392 else {
1356- screen -> pending_mode .stop_buf [screen -> pending_mode .stop_buf_pos ++ ] = ch ;
1357- if (screen -> pending_mode .stop_buf_pos >= sizeof (screen -> pending_mode .stop_buf )) {
1393+ if (pm .stop_buf_pos >= sizeof (pm .stop_buf )) {
13581394 state = NORMAL ;
1359- COPY_STOP_BUF ;
1395+ COPY_STOP_BUF (true) ;
13601396 }
13611397 }
13621398 break ;
13631399 case EXPECTING_SLASH :
13641400 if (
13651401 ch == '\\' &&
1366- screen -> pending_mode .stop_buf_pos >= 2 &&
1367- (screen -> pending_mode .stop_buf [0 ] == '1' || screen -> pending_mode .stop_buf [0 ] == '2' ) &&
1368- screen -> pending_mode .stop_buf [1 ] == 's'
1402+ pm .stop_buf_pos >= 2 &&
1403+ (pm .stop_buf [0 ] == '1' || pm .stop_buf [0 ] == '2' ) &&
1404+ pm .stop_buf [1 ] == 's'
13691405 ) {
13701406 // We found a pending mode sequence
1371- if (screen -> pending_mode .stop_buf [0 ] == '2' ) {
1372- REPORT_COMMAND (screen_stop_pending_mode );
1373- screen -> pending_mode .activated_at = 0 ;
1374- goto end ;
1375- } else {
1376- REPORT_COMMAND (screen_start_pending_mode );
1377- screen -> pending_mode .activated_at = monotonic ();
1378- }
1407+ if (pm .stop_buf [0 ] == '2' ) { stop_pending_mode } else { start_pending_mode }
13791408 } else {
1380- state = NORMAL ;
1381- COPY_STOP_BUF ; COPY (ch );
1409+ COPY_STOP_BUF (true); COPY (ch );
13821410 }
1411+ state = NORMAL ;
13831412 break ;
13841413 }
13851414 }
13861415end :
1387- screen -> pending_mode .state = state ;
1416+ pm .state = state ;
13881417 return pos ;
13891418#undef COPY
13901419#undef COPY_STOP_BUF
1420+ #undef stop_pending_mode
1421+ #undef start_pending_mode
1422+ #undef pm
13911423}
13921424
13931425static inline void
0 commit comments