diff --git a/tmux.h b/tmux.h index 93e178e1..02f9bbd0 100644 --- a/tmux.h +++ b/tmux.h @@ -195,9 +195,15 @@ enum tty_code_code { TTYC_CNORM, /* cursor_normal, ve */ TTYC_COLORS, /* max_colors, Co */ TTYC_CSR, /* change_scroll_region, cs */ + TTYC_CUB, /* parm_left_cursor, LE */ + TTYC_CUB1, /* cursor_left, le */ TTYC_CUD, /* parm_down_cursor, DO */ TTYC_CUD1, /* cursor_down, do */ + TTYC_CUF, /* parm_right_cursor, RI */ + TTYC_CUF1, /* cursor_right, nd */ TTYC_CUP, /* cursor_address, cm */ + TTYC_CUU, /* parm_up_cursor, UP */ + TTYC_CUU1, /* cursor_up, up */ TTYC_DCH, /* parm_dch, DC */ TTYC_DCH1, /* delete_character, dc */ TTYC_DIM, /* enter_dim_mode, mh */ @@ -206,6 +212,8 @@ enum tty_code_code { TTYC_EL, /* clr_eol, ce */ TTYC_EL1, /* clr_bol, cb */ TTYC_ENACS, /* ena_acs, eA */ + TTYC_HOME, /* cursor_home, ho */ + TTYC_HPA, /* column_address, ch */ TTYC_ICH, /* parm_ich, IC */ TTYC_ICH1, /* insert_character, ic */ TTYC_IL, /* parm_insert_line, IL */ @@ -232,8 +240,8 @@ enum tty_code_code { TTYC_KF17, /* key_f17, F7 */ TTYC_KF18, /* key_f18, F8 */ TTYC_KF19, /* key_f19, F9 */ - TTYC_KF20, /* key_f20, F10 */ TTYC_KF2, /* key_f2, k2 */ + TTYC_KF20, /* key_f20, F10 */ TTYC_KF3, /* key_f3, k3 */ TTYC_KF4, /* key_f4, k4 */ TTYC_KF5, /* key_f5, k5 */ @@ -262,6 +270,7 @@ enum tty_code_code { TTYC_SMKX, /* keypad_xmit, ks */ TTYC_SMSO, /* enter_standout_mode, so */ TTYC_SMUL, /* enter_underline_mode, us */ + TTYC_VPA, /* row_address, cv */ TTYC_XENL, /* eat_newline_glitch, xn */ }; #define NTTYCODE (TTYC_XENL + 1) diff --git a/tty-term.c b/tty-term.c index dd3e8e00..02dece6e 100644 --- a/tty-term.c +++ b/tty-term.c @@ -43,9 +43,15 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = { { TTYC_CNORM, TTYCODE_STRING, "cnorm" }, { TTYC_COLORS, TTYCODE_NUMBER, "colors" }, { TTYC_CSR, TTYCODE_STRING, "csr" }, + { TTYC_CUB, TTYCODE_STRING, "cub" }, + { TTYC_CUB1, TTYCODE_STRING, "cub1" }, { TTYC_CUD, TTYCODE_STRING, "cud" }, { TTYC_CUD1, TTYCODE_STRING, "cud1" }, + { TTYC_CUF, TTYCODE_STRING, "cuf" }, + { TTYC_CUF1, TTYCODE_STRING, "cuf1" }, { TTYC_CUP, TTYCODE_STRING, "cup" }, + { TTYC_CUU, TTYCODE_STRING, "cuu" }, + { TTYC_CUU1, TTYCODE_STRING, "cuu1" }, { TTYC_DCH, TTYCODE_STRING, "dch" }, { TTYC_DCH1, TTYCODE_STRING, "dch1" }, { TTYC_DIM, TTYCODE_STRING, "dim" }, @@ -54,6 +60,8 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = { { TTYC_EL, TTYCODE_STRING, "el" }, { TTYC_EL1, TTYCODE_STRING, "el1" }, { TTYC_ENACS, TTYCODE_STRING, "enacs" }, + { TTYC_HOME, TTYCODE_STRING, "home" }, + { TTYC_HPA, TTYCODE_STRING, "hpa" }, { TTYC_ICH, TTYCODE_STRING, "ich" }, { TTYC_ICH1, TTYCODE_STRING, "ich1" }, { TTYC_IL, TTYCODE_STRING, "il" }, @@ -80,8 +88,8 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = { { TTYC_KF17, TTYCODE_STRING, "kf17" }, { TTYC_KF18, TTYCODE_STRING, "kf18" }, { TTYC_KF19, TTYCODE_STRING, "kf19" }, - { TTYC_KF20, TTYCODE_STRING, "kf20" }, { TTYC_KF2, TTYCODE_STRING, "kf2" }, + { TTYC_KF20, TTYCODE_STRING, "kf20" }, { TTYC_KF3, TTYCODE_STRING, "kf3" }, { TTYC_KF4, TTYCODE_STRING, "kf4" }, { TTYC_KF5, TTYCODE_STRING, "kf5" }, @@ -110,6 +118,7 @@ struct tty_term_code_entry tty_term_codes[NTTYCODE] = { { TTYC_SMKX, TTYCODE_STRING, "smkx" }, { TTYC_SMSO, TTYCODE_STRING, "smso" }, { TTYC_SMUL, TTYCODE_STRING, "smul" }, + { TTYC_VPA, TTYCODE_STRING, "vpa" }, { TTYC_XENL, TTYCODE_FLAG, "xenl" }, }; diff --git a/tty.c b/tty.c index f7ef8c0d..4172e38c 100644 --- a/tty.c +++ b/tty.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -916,13 +917,14 @@ tty_region(struct tty *tty, u_int rupper, u_int rlower) tty->rupper = rupper; tty->rlower = rlower; - + tty->cx = 0; tty->cy = 0; tty_putcode2(tty, TTYC_CSR, tty->rupper, tty->rlower); } +/* Move cursor inside pane. */ void tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy) { @@ -931,17 +933,122 @@ tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy) tty_cursor(tty, wp->xoff + cx, wp->yoff + cy); } +/* Move cursor to absolute position. */ void tty_cursor(struct tty *tty, u_int cx, u_int cy) { - if (cx == 0 && tty->cx != 0 && tty->cy == cy) { - tty->cx = 0; - tty_putc(tty, '\r'); - } else if (tty->cx != cx || tty->cy != cy) { - tty->cx = cx; - tty->cy = cy; - tty_putcode2(tty, TTYC_CUP, tty->cy, tty->cx); + struct tty_term *term = tty->term; + u_int thisx, thisy; + int change; + + if (cx > tty->sx - 1) + cx = tty->sx - 1; + + thisx = tty->cx; + if (thisx > tty->sx - 1) + thisx = tty->sx - 1; + thisy = tty->cy; + + /* No change. */ + if (cx == thisx && cy == thisy) + return; + + /* Move to home position (0, 0). */ + if (cx == 0 && cy == 0 && tty_term_has(term, TTYC_HOME)) { + tty_putcode(tty, TTYC_HOME); + goto out; } + + /* Zero on the next line. */ + if (cx == 0 && cy == thisy + 1) { + tty_putc(tty, '\r'); + tty_putc(tty, '\n'); + goto out; + } + + /* Row staying the same. */ + if (cy == thisy) { + /* To left edge. */ + if (cx == 0) { + tty_putc(tty, '\r'); + goto out; + } + + /* One to the left. */ + if (cx == thisx - 1 && tty_term_has(term, TTYC_CUB1)) { + tty_putcode(tty, TTYC_CUB1); + goto out; + } + + /* One to the right. */ + if (cx == thisx + 1 && tty_term_has(term, TTYC_CUF1)) { + tty_putcode(tty, TTYC_CUF1); + goto out; + } + + /* Calculate difference. */ + change = thisx - cx; /* +ve left, -ve right */ + + /* + * Use HPA if change is larger than absolute, otherwise move + * the cursor with CUB/CUF. + */ + if (abs(change) > cx && tty_term_has(term, TTYC_HPA)) { + tty_putcode1(tty, TTYC_HPA, cx); + goto out; + } else if (change > 0 && tty_term_has(term, TTYC_CUB)) { + tty_putcode1(tty, TTYC_CUB, change); + goto out; + } else if (change < 0 && tty_term_has(term, TTYC_CUF)) { + tty_putcode1(tty, TTYC_CUF, -change); + goto out; + } + } + + /* Column staying the same. */ + if (cx == thisx ) { + /* One above. */ + if (cy != tty->rupper && + cy == thisy - 1 && tty_term_has(term, TTYC_CUU1)) { + tty_putcode(tty, TTYC_CUU1); + goto out; + } + + /* One below. */ + if (cy != tty->rlower && + cy == thisy + 1 && tty_term_has(term, TTYC_CUD1)) { + tty_putcode(tty, TTYC_CUD1); + goto out; + } + + /* Calculate difference. */ + change = thisy - cy; /* +ve up, -ve down */ + + /* + * Use VPA if change is larger than absolute or if this change + * would cross the scroll region, otherwise use CUU/CUD. + */ + if ((abs(change) > cy || + (change < 0 && cy - change > tty->rlower) || + (change > 0 && cy - change < tty->rupper)) && + tty_term_has(term, TTYC_VPA)) { + tty_putcode1(tty, TTYC_VPA, cy); + goto out; + } else if (change > 0 && tty_term_has(term, TTYC_CUU)) { + tty_putcode1(tty, TTYC_CUU, change); + goto out; + } else if (change < 0 && tty_term_has(term, TTYC_CUD)) { + tty_putcode1(tty, TTYC_CUD, -change); + goto out; + } + } + + /* Absolute movement. */ + tty_putcode2(tty, TTYC_CUP, cy, cx); + +out: + tty->cx = cx; + tty->cy = cy; } void