From 43f490c377cb05d1ac6e7d2c27a06ae940e2c047 Mon Sep 17 00:00:00 2001 Message-Id: <43f490c377cb05d1ac6e7d2c27a06ae940e2c047.1746226592.git.mdw@distorted.org.uk> From: Mark Wooding Date: Fri, 25 Apr 2025 10:02:03 +0100 Subject: [PATCH] @@@ more tty mess Organization: Straylight/Edgeware From: Mark Wooding --- ui/tty.c | 108 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 26 deletions(-) diff --git a/ui/tty.c b/ui/tty.c index 001878c..ff24256 100644 --- a/ui/tty.c +++ b/ui/tty.c @@ -294,13 +294,11 @@ static void common_init(struct tty *tty, FILE *fp) * weird code, so we have to convert it into an actual rate in bits per * second. */ - if (!fp || tcgetattr(fileno(fp), &c)) - tty->baud = 0; - else { + tty->baud = 0; tty->wd = tty->ht = 0; + if (fp && !tcgetattr(fileno(fp), &c)) { code = cfgetospeed(&c); for (b = baudtab; b->baud; b++) if (b->code == code) { tty->baud = b->baud; goto found_baud; } - tty->baud = 0; found_baud: tty_resized(tty); } @@ -774,13 +772,17 @@ static void clamp_attr(struct tty_attr *a_out, if (acaps&TTACF_INVV) ff |= f&TTAF_INVV; /* Foreground and background colours. */ - if (acaps&TTACF_FG) { + if (!(acaps&TTACF_FG)) + a_out->fg = 0; + else { clamp_colours(&t, &a_out->fg, (f&TTAF_FGSPCMASK) >> TTAF_FGSPCSHIFT, a ? a->fg : 0, acaps); ff |= t << TTAF_FGSPCSHIFT; } - if (acaps&TTACF_BG) { + if (!(acaps&TTACF_BG)) + a_out->bg = 0; + else { clamp_colours(&t, &a_out->bg, (f&TTAF_BGSPCMASK) >> TTAF_BGSPCSHIFT, a ? a->bg : 0, acaps); @@ -1098,6 +1100,13 @@ struct tty_capslots { #undef DEF_BOOLCAP #undef DEF_INTCAP #undef DEF_STRCAP +#define LEN_BOOLCAP(uix, info, cap) +#define LEN_INTCAP(uix, info, cap) +#define LEN_STRCAP(uix, info, cap) unsigned info##_cost; + ATTRCAPS(LEN_BOOLCAP, LEN_INTCAP, LEN_STRCAP) +#undef LEN_BOOLCAP +#undef LEN_INTCAP +#undef LEN_STRCAP }; #define TTY_CAPSPFX \ struct tty tty; \ @@ -1141,10 +1150,21 @@ static void init_caps(struct tty_caps *t) #undef GETINT #undef GETSTR +#define COST_BOOLCAP(uix, info, cap_) +#define COST_INTCAP(uix, info, cap_) +#define COST_STRCAP(uix, info, cap_) \ + if (!t->cap.info) t->cap.info##_cost = -1; \ + else t->cap.info##_cost = \ + strlen(tgoto(t->cap.info, 0, t->cap.colors - 1)); + ATTRCAPS(COST_BOOLCAP, COST_INTCAP, COST_STRCAP) +#undef COST_BOOLCAP +#undef COST_INTCAP +#undef COST_STRCAP + #define CLEAR_BOOL(uix, info, cap_) t->cap.info = 0; #define CLEAR_INT(uix, info, cap_) t->cap.info = 0; #define CLEAR_STR(uix, info, cap_) t->cap.info = 0; -#define CLEAR_CAPS(caplist) \ +#define CLEARCAPS(caplist) \ do { caplist(CLEAR_BOOL, CLEAR_INT, CLEAR_STR) } while (0) /* Basic capabilities. */ @@ -1152,18 +1172,21 @@ static void init_caps(struct tty_caps *t) if (!t->cap.nel) t->cap.nel = "\r\n"; /* Attribute capabilities. */ - if (ops->cap.intcap(&t->tty, CAP_XMC) > 0 || !t->cap.sgr0) - CLEAR_CAPS(ATTRCAPS); + if (ops->cap.intcap(&t->tty, CAP_XMC) > 0) + CLEARCAPS(ATTRCAPS); else { - if (t->cap.smul) t->tty.acaps |= TTACF_ULINE; - if (t->cap.bold) t->tty.acaps |= TTACF_BOLD; - if (t->cap.dim) t->tty.acaps |= TTACF_DIM; - if (t->cap.sitm) t->tty.acaps |= TTACF_ITAL; - if (t->cap.rev) t->tty.acaps |= TTACF_INVV; - - if (!t->cap.op || (!t->cap.setaf && !t->cap.setab)) - CLEAR_CAPS(COLOURCAPS); - else { + if (t->cap.smul && (t->cap.rmul || t->cap.sgr0)) + t->tty.acaps |= TTACF_ULINE; + if (t->cap.bold && t->cap.sgr0) + t->tty.acaps |= TTACF_BOLD; + if (t->cap.dim && t->cap.sgr0) + t->tty.acaps |= TTACF_DIM; + if (t->cap.sitm && (t->cap.ritm || t->cap.sgr0)) + t->tty.acaps |= TTACF_ITAL; + if (t->cap.rev && t->cap.sgr0) + t->tty.acaps |= TTACF_INVV; + + if ((t->cap.setaf || t->cap.setab) && (t->cap.op || t->cap.sgr0)) { if (t->cap.setaf) t->tty.acaps |= TTACF_FG; if (t->cap.setab) t->tty.acaps |= TTACF_BG; t->tty.acaps |= TTACF_1BPC; @@ -1225,6 +1248,11 @@ static void init_caps(struct tty_caps *t) { wd = ops->cap.intcap(&t->tty, CAP_WD); if (wd > 0) t->tty.wd = wd; } if (!t->tty.ht) { ht = ops->cap.intcap(&t->tty, CAP_HT); if (ht > 0) t->tty.ht = ht; } + +#undef CLEAR_BOOL +#undef CLEAR_INT +#undef CLEAR_STR +#undef CLEARCAPS } /* Macros for formatting capabilities. */ @@ -1282,6 +1310,8 @@ static int caps_setattr_internal(struct tty_caps *t, const struct tty_capops *ops = (const struct tty_capops *)t->tty.ops; uint32 diff; int rc; + unsigned c, z, f = 0; +#define f_clrall 1u /* Work out what needs doing. */ diff = a->f ^ t->tty.st.attr.f; @@ -1293,11 +1323,36 @@ static int caps_setattr_internal(struct tty_caps *t, * to do that, we need to restore the other active attributes, so we must * check up front. */ - if (((diff&TTAF_LNMASK) && !(a->f&TTAF_LNMASK) && !t->cap.rmul) || - ((diff&TTAF_WTMASK) && !(a->f&TTAF_WTMASK)) || - ((diff&~a->f&TTAF_ITAL) && !t->cap.ritm) || - (diff&~a->f&TTAF_INVV)) - { PUT0(0, sgr0); diff = a->f; } + + c = 0; +#define CLEARP(mask) ((diff&(mask)) && !(a->f&(mask))) +#define ADDCOST(cap_) do { \ + if (t->cap.cap_) c += t->cap.cap_##_cost; \ + else f |= f_clrall; \ +} while (0) + if (CLEARP(TTAF_LNMASK)) ADDCOST(rmul); + if (CLEARP(TTAF_WTMASK)) f |= f_clrall; + if (diff&~a->f&TTAF_INVV) f |= f_clrall; + if (diff&~a->f&TTAF_ITAL) ADDCOST(ritm); + if (CLEARP(TTAF_FGSPCMASK) || CLEARP(TTAF_BGSPCMASK)) ADDCOST(op); +#undef CLEARP +#undef ADDCOST + + z = 0; + switch ((a->f&TTAF_LNMASK) >> TTAF_LNSHIFT) { + case TTLN_ULINE: z += t->cap.smul_cost; break; + } + switch ((a->f&TTAF_WTMASK) >> TTAF_WTSHIFT) { + case TTWT_BOLD: z += t->cap.bold_cost; break; + case TTWT_DIM: z += t->cap.dim_cost; break; + } + if (a->f&TTAF_INVV) z += t->cap.rev_cost; + if (a->f&TTAF_ITAL) z += t->cap.sitm_cost; + if (a->f&TTAF_FGSPCMASK) z += t->cap.setaf_cost; + if (a->f&TTAF_BGSPCMASK) z += t->cap.setab_cost; + + if ((t->cap.sgr0 && z + t->cap.sgr0_cost < c) || (f&f_clrall)) + { PUT0(0, sgr0); diff = a->f; t->tty.st.attr.fg = t->tty.st.attr.bg; } /* Line style. */ if (diff&TTAF_LNMASK) @@ -1319,11 +1374,11 @@ static int caps_setattr_internal(struct tty_caps *t, } /* Other text effects. */ + if (diff&a->f&TTAF_INVV) PUT0(0, rev); if (diff&TTAF_ITAL) { if (a->f&TTAF_ITAL) PUT0(0, sitm); else PUT0(0, ritm); } - if (diff&a->f&TTAF_INVV) PUT0(0, rev); /* Colours. */ if (((diff&TTAF_FGSPCMASK) && !(a->f&TTAF_FGSPCMASK)) || @@ -1347,6 +1402,8 @@ static int caps_setattr_internal(struct tty_caps *t, rc = 0; end: t->tty.st.attr = *a; return (rc); + +#undef f_clrall } static int caps_setattr(struct tty *tty, @@ -2259,7 +2316,7 @@ static int ansi_setattr(struct tty *tty, PUTLIT("\33["); - if (z <= c) + if (z < c || (c && !(t->ansi.f&TAF_CNCATTR))) { SEMI; diff = a->f; t->tty.st.attr.fg = t->tty.st.attr.bg = 0; } if (diff&TTAF_LNMASK) @@ -2833,7 +2890,6 @@ void tty_close(struct tty *tty) } } - int tty_resized(struct tty *tty) { struct winsize ws; -- [mdw]