Skip to content

Commit

Permalink
NCSTYLE_UNDERCURL #1758
Browse files Browse the repository at this point in the history
  • Loading branch information
dankamongmen committed Jun 18, 2021
1 parent 04c3dcc commit 5559bbb
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 54 deletions.
1 change: 1 addition & 0 deletions include/notcurses/notcurses.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ API void nccell_release(struct ncplane* n, nccell* c);
#define NCSTYLE_PROTECT 0x0001u
#define NCSTYLE_ITALIC 0x0100u
#define NCSTYLE_STRUCK 0x0200u
#define NCSTYLE_UNDERCURL 0x0400u
#define NCSTYLE_NONE 0

// Set the specified style bits for the nccell 'c', whether they're actively
Expand Down
5 changes: 5 additions & 0 deletions src/lib/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,11 @@ int ncdirect_on_styles(ncdirect* n, unsigned stylebits){
get_escape(&n->tcache, ESCAPE_RMXX))){
return -1;
}
if(term_setstyle(n->ttyfp, n->stylemask, stylemask, NCSTYLE_UNDERCURL,
get_escape(&n->tcache, ESCAPE_SMULX),
get_escape(&n->tcache, ESCAPE_RMXX))){
return -1;
}
n->stylemask = stylemask;
return 0;
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/render.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,6 +616,9 @@ term_setstyles(FILE* out, notcurses* nc, const nccell* c){
ret |= term_setstyle(out, nc->rstate.curattr, cellattr, NCSTYLE_STRUCK,
get_escape(&nc->tcache, ESCAPE_SMXX),
get_escape(&nc->tcache, ESCAPE_RMXX));
ret |= term_setstyle(out, nc->rstate.curattr, cellattr, NCSTYLE_UNDERCURL,
get_escape(&nc->tcache, ESCAPE_SMULX),
get_escape(&nc->tcache, ESCAPE_SMULNOX));
nc->rstate.curattr = cellattr;
if(normalized){
nc->rstate.fgdefelidable = true;
Expand Down
130 changes: 77 additions & 53 deletions src/lib/termdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,72 @@ match_termname(const char* termname, queried_terminals_e* qterm){
return 0;
}

void free_terminfo_cache(tinfo* ti){
free(ti->esctable);
ncinputlayer_stop(&ti->input);
}

// tlen -- size of escape table. tused -- used bytes in same.
// returns -1 if the starting location is >= 65535. otherwise,
// copies tstr into the table, and sets up 1-biased index.
static int
grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
size_t* tlen, size_t* tused){
if(*tused >= 65535){ // we only have 16 bits for the index
fprintf(stderr, "Can't add escape %d to full table\n", esc);
return -1;
}
if(ti->escindices[esc] > 0){
fprintf(stderr, "Already defined escape %d (%s)\n",
esc, get_escape(ti, esc));
return -1;
}
size_t slen = strlen(tstr) + 1; // count the nul term
if(*tlen - *tused < slen){
// guaranteed to give us enough space to add tstr (and then some)
size_t newsize = *tlen + 4020 + slen; // don't pull two pages ideally
char* tmp = realloc(ti->esctable, newsize);
if(tmp == NULL){
return -1;
}
ti->esctable = tmp;
*tlen = newsize;
}
// we now are guaranteed sufficient space to copy tstr
memcpy(ti->esctable + *tused, tstr, slen);
ti->escindices[esc] = *tused + 1; // one-bias
*tused += slen;
return 0;
}

static int
init_terminfo_esc(tinfo* ti, const char* name, escape_e idx,
size_t* tablelen, size_t* tableused){
char* tstr;
if(terminfostr(&tstr, name) == 0){
if(grow_esc_table(ti, tstr, idx, tablelen, tableused)){
return -1;
}
}else{
ti->escindices[idx] = 0;
}
return 0;
}

static int
add_smulx_escapes(tinfo* ti, size_t* tablelen, size_t* tableused){
if(grow_esc_table(ti, "\x1b[4:3m", ESCAPE_SMULX, tablelen, tableused) ||
grow_esc_table(ti, "\x1b[4:0m", ESCAPE_SMULNOX, tablelen, tableused)){
return -1;
}
return 0;
}

// Qui si convien lasciare ogne sospetto; ogne viltà convien che qui sia morta.
static int
apply_term_heuristics(tinfo* ti, const char* termname, int fd,
queried_terminals_e qterm){
queried_terminals_e qterm,
size_t* tablelen, size_t* tableused){
if(!termname){
// setupterm interprets a missing/empty TERM variable as the special value “unknown”.
termname = "unknown";
Expand All @@ -106,6 +168,9 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
ti->caps.quadrants = true;
ti->caps.rgb = true;
setup_kitty_bitmaps(ti, fd);
if(add_smulx_escapes(ti, tablelen, tableused)){
return -1;
}
}else if(qterm == TERMINAL_ALACRITTY){
termname = "Alacritty";
ti->caps.quadrants = true;
Expand All @@ -131,6 +196,11 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
const char* termver = getenv("TERM_PROGRAM_VERSION");
if(termver && strcmp(termver, "20210610") >= 0){
ti->caps.sextants = true; // good caps.sextants as of 2021-06-10
if(add_smulx_escapes(ti, tablelen, tableused)){
return -1;
}
}else{
termname = "XTerm";
}
}else if(qterm == TERMINAL_XTERM){
termname = "XTerm";
Expand Down Expand Up @@ -158,52 +228,6 @@ apply_term_heuristics(tinfo* ti, const char* termname, int fd,
return 0;
}

void free_terminfo_cache(tinfo* ti){
free(ti->esctable);
ncinputlayer_stop(&ti->input);
}

// tlen -- size of escape table. tused -- used bytes in same.
// returns -1 if the starting location is >= 65535. otherwise,
// copies tstr into the table, and sets up 1-biased index.
static int
grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
size_t* tlen, size_t* tused){
if(*tused >= 65535){
return -1;
}
size_t slen = strlen(tstr) + 1; // count the nul term
if(*tlen - *tused < slen){
// guaranteed to give us enough space to add tstr (and then some)
size_t newsize = *tlen + 4020 + slen; // don't pull two pages ideally
char* tmp = realloc(ti->esctable, newsize);
if(tmp == NULL){
return -1;
}
ti->esctable = tmp;
*tlen = newsize;
}
// we now are guaranteed sufficient space to copy tstr
memcpy(ti->esctable + *tused, tstr, slen);
ti->escindices[esc] = *tused + 1; // one-bias
*tused += slen;
return 0;
}

static int
init_terminfo_esc(tinfo* ti, const char* name, escape_e idx,
size_t* tablelen, size_t* tableused){
char* tstr;
if(terminfostr(&tstr, name) == 0){
if(grow_esc_table(ti, tstr, idx, tablelen, tableused)){
return -1;
}
}else{
ti->escindices[idx] = 0;
}
return 0;
}

// Device Attributes; replies with (depending on decTerminalID resource):
// ⇒ CSI ? 1 ; 2 c ("VT100 with Advanced Video Option")
// ⇒ CSI ? 1 ; 0 c ("VT101 with No Options")
Expand Down Expand Up @@ -305,6 +329,8 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
{ ESCAPE_SMKX, "smkx", },
{ ESCAPE_SMXX, "smxx", },
{ ESCAPE_RMXX, "rmxx", },
{ ESCAPE_SMUL, "smul", },
{ ESCAPE_RMUL, "rmul", },
{ ESCAPE_SC, "sc", },
{ ESCAPE_RC, "rc", },
{ ESCAPE_CLEAR, "clear", },
Expand Down Expand Up @@ -360,9 +386,9 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
}
// we don't actually use the bold capability -- we use sgr exclusively.
// but we use the presence of the bold capability to determine whether
// we think sgr supports bold, which...might be valid? i'm unsure. futher,
// some terminals cannot combine certain styles with colors. don't
// advertise support for the style in that case.
// we think sgr supports bold, which...might be valid? i'm unsure.
// further, some terminals cannot combine certain styles with colors.
// don't advertise support for the style in that case.
const struct style {
unsigned s; // NCSTYLE_* value
const char* tinfo; // terminfo capability for conditional permit
Expand All @@ -377,7 +403,6 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
{ NCSTYLE_ITALIC, "sitm", A_ITALIC },
{ NCSTYLE_INVIS, "invis", A_INVIS },
{ NCSTYLE_PROTECT, "prot", A_PROTECT },
{ NCSTYLE_STRUCK, "smxx", 0 },
{ 0, NULL, 0 }
};
int nocolor_stylemask = tigetnum("ncv");
Expand Down Expand Up @@ -434,8 +459,7 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
}
}
}
//fprintf(stderr, "DETECTED TERM: %d\n", detected);
if(apply_term_heuristics(ti, termname, fd, detected)){
if(apply_term_heuristics(ti, termname, fd, detected, &tablelen, &tableused)){
ncinputlayer_stop(&ti->input);
goto err;
}
Expand Down
4 changes: 4 additions & 0 deletions src/lib/termdesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ typedef enum {
ESCAPE_SMCUP, // "smcup" enter alternate screen
ESCAPE_RMCUP, // "rmcup" leave alternate screen
ESCAPE_SMXX, // "smxx" start struckout
ESCAPE_SMUL, // "smul" start underline
ESCAPE_RMUL, // "rmul" end underline
ESCAPE_SMULX, // "Smulx" deparameterized: start extended underline
ESCAPE_SMULNOX, // "Smulx" deparameterized: kill underline
ESCAPE_RMXX, // "rmxx" end struckout
ESCAPE_SC, // "sc" push the cursor onto the stack
ESCAPE_RC, // "rc" pop the cursor off the stack
Expand Down
2 changes: 1 addition & 1 deletion src/poc/sgr-direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ int main(void){
return EXIT_FAILURE;
}
int e = 0;
for(unsigned i = 0 ; i < (NCSTYLE_STRUCK << 1u) ; ++i){
for(unsigned i = 0 ; i < (NCSTYLE_UNDERCURL << 1u) ; ++i){
if((ncdirect_supported_styles(nc) & i) == i){
if(ncdirect_set_styles(nc, i)){
ncdirect_stop(nc);
Expand Down
9 changes: 9 additions & 0 deletions src/poc/sgr-full.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ int main(void){
ncplane_putstr_yx(n, y++, 0, "a ═ italic reverse");
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERLINE);
ncplane_putstr_yx(n, y++, 0, "a ═ italic underline");
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_UNDERCURL);
ncplane_putstr_yx(n, y++, 0, "a ═ italic undercurl");
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_BLINK);
ncplane_putstr_yx(n, y++, 0, "a ═ italic blink");
ncplane_set_styles(n, NCSTYLE_ITALIC | NCSTYLE_STRUCK);
Expand All @@ -46,17 +48,24 @@ int main(void){
ncplane_putstr_yx(n, y++, 0, "a ═ struck reverse");
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERLINE);
ncplane_putstr_yx(n, y++, 0, "a ═ struck underline");
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_UNDERCURL);
ncplane_putstr_yx(n, y++, 0, "a ═ struck undercurl");
ncplane_set_styles(n, NCSTYLE_STRUCK | NCSTYLE_BLINK);
ncplane_putstr_yx(n, y++, 0, "a ═ struck blink");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_REVERSE);
ncplane_putstr_yx(n, y++, 0, "a ═ bold reverse");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERLINE);
ncplane_putstr_yx(n, y++, 0, "a ═ bold underline");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_UNDERCURL);
ncplane_putstr_yx(n, y++, 0, "a ═ bold undercurl");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_BLINK);
ncplane_putstr_yx(n, y++, 0, "a ═ bold blink");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_REVERSE | NCSTYLE_UNDERLINE |
NCSTYLE_BLINK | NCSTYLE_ITALIC | NCSTYLE_STRUCK);
ncplane_putstr_yx(n, y++, 0, "a ═ whoomp! there it is");
ncplane_set_styles(n, NCSTYLE_BOLD | NCSTYLE_REVERSE | NCSTYLE_UNDERCURL |
NCSTYLE_BLINK | NCSTYLE_ITALIC | NCSTYLE_STRUCK);
ncplane_putstr_yx(n, y++, 0, "a ═ whoomp! there it curls");

ncplane_set_styles(n, NCSTYLE_NONE);
if(notcurses_render(nc)){
Expand Down

0 comments on commit 5559bbb

Please sign in to comment.