@@ -2586,9 +2586,21 @@ static bool zr_emit_el0_clear_line_tail(zr_sb_t* sb) {
25862586
25872587 Why: EL and any LF scroll fill use the *current* background (BCE), so the
25882588 style must be the blank baseline before either runs. CR re-anchors column 0
2589- and cancels pending autowrap from full-width rows.
2589+ and cancels pending autowrap from full-width rows. When the row ended on a
2590+ drift-capable glyph (cursor position invalidated), the cursor is first
2591+ re-anchored to the intended end column with absolute-column CHA so EL
2592+ erases from the painted edge rather than a drifted terminal column.
25902593*/
2591- static zr_result_t zr_diff_commit_finish_row (zr_diff_ctx_t * ctx ) {
2594+ static zr_result_t zr_diff_commit_finish_row (zr_diff_ctx_t * ctx , uint32_t row_end_col ) {
2595+ if (!zr_term_cursor_pos_is_valid (& ctx -> ts )) {
2596+ if (!zr_diff_write_csi (& ctx -> sb ) || !zr_sb_write_u32_dec (& ctx -> sb , row_end_col + 1u ) ||
2597+ !zr_sb_write_u8 (& ctx -> sb , ZR_CSI_FINAL_CHA )) {
2598+ return ZR_ERR_LIMIT ;
2599+ }
2600+ ctx -> ts .cursor_x = row_end_col ;
2601+ ctx -> ts .flags |= ZR_TERM_STATE_CURSOR_POS_VALID ;
2602+ }
2603+
25922604 const zr_result_t link_rc = zr_diff_emit_link_transition (ctx , 0u );
25932605 if (link_rc != ZR_OK ) {
25942606 return link_rc ;
@@ -2644,7 +2656,7 @@ zr_result_t zr_diff_render_commit(const zr_fb_t* content, const plat_caps_t* cap
26442656 zr_diff_zero_outputs (out_len , out_final_term_state , NULL );
26452657 return rc ;
26462658 }
2647- rc = zr_diff_commit_finish_row (& ctx );
2659+ rc = zr_diff_commit_finish_row (& ctx , paint_cols );
26482660 if (rc != ZR_OK ) {
26492661 zr_diff_zero_outputs (out_len , out_final_term_state , NULL );
26502662 return rc ;
0 commit comments