Skip to content

Commit

Permalink
microsoft terminal escape database #2014
Browse files Browse the repository at this point in the history
  • Loading branch information
dankamongmen committed Aug 3, 2021
1 parent ea9d121 commit 06f2397
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 89 deletions.
6 changes: 3 additions & 3 deletions src/lib/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
#include <errno.h>
#include <string.h>
#include <unistd.h>
#ifdef USE_READLINE
#include <readline/readline.h>
#endif
#include "version.h"
#include "visual-details.h"
#include "notcurses/direct.h"
#include "internal.h"
#ifdef USE_READLINE
#include <readline/readline.h>
#endif

// conform to the foreground and background channels of 'channels'
static int
Expand Down
5 changes: 2 additions & 3 deletions src/lib/fbuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ extern "C" {
#include <string.h>
#include <stdint.h>
#include <inttypes.h>
#include "internal.h"
#include "logging.h"
#include "compat/compat.h"

// a growable buffer into which one can perform formatted i/o, like the
// ten thousand that came before it, and the ten trillion which shall
Expand Down Expand Up @@ -218,7 +217,7 @@ fbuf_emit(fbuf* f, const char* esc){
return -1;
}
if(fbuf_puts(f, esc) < 0){
logerror("error emitting escape (%s)\n", strerror(errno));
//logerror("error emitting escape (%s)\n", strerror(errno));
return -1;
}
return 0;
Expand Down
1 change: 1 addition & 0 deletions src/lib/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ typedef enum {
TERMINAL_ITERM, // XTVERSION == 'iTerm2 [ver]'
TERMINAL_TERMINOLOGY, // TDA: "~~TY"
TERMINAL_APPLE, // Terminal.App, determined by TERM_PROGRAM + macOS
TERMINAL_MSTERMINAL, // Microsoft Windows Terminal
} queried_terminals_e;

// sets up the input layer, building a trie of escape sequences and their
Expand Down
135 changes: 52 additions & 83 deletions src/lib/termdesc.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,47 +149,6 @@ query_rgb(void){
return rgb;
}

static int
terminfostr(char** gseq, const char* name){
*gseq = tigetstr(name);
if(*gseq == NULL || *gseq == (char*)-1){
*gseq = NULL;
return -1;
}
// terminfo syntax allows a number N of milliseconds worth of pause to be
// specified using $<N> syntax. this is then honored by tputs(). but we don't
// use tputs(), instead preferring the much faster stdio+tiparm() (at the
// expense of terminals which do require these delays). to avoid dumping
// "$<N>" sequences all over stdio, we chop them out. real text can follow
// them, so we continue on, copying back once out of the delay.
char* wnext = NULL; // NULL until we hit a delay, then place to write
bool indelay = false; // true iff we're in a delay section
// we consider it a delay as soon as we see '$', and the delay ends at '>'
for(char* cur = *gseq ; *cur ; ++cur){
if(!indelay){
// if we're not in a delay section, make sure we're not starting one,
// and otherwise copy the current character back (if necessary).
if(*cur == '$'){
wnext = cur;
indelay = true;
}else{
if(wnext){
*wnext++ = *cur;
}
}
}else{
// we are in a delay section. make sure we're not ending one.
if(*cur == '>'){
indelay = false;
}
}
}
if(wnext){
*wnext = '\0';
}
return 0;
}

// we couldn't get a terminal from interrogation, so let's see if the TERM
// matches any of our known terminals. this can only be as accurate as the
// TERM setting is (and as up-to-date and complete as we are).
Expand Down Expand Up @@ -260,38 +219,58 @@ compare_versions(const char* restrict v1, const char* restrict v2){
return 0;
}

// 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){
// the actual table can grow past 64KB, but we can't start there, as
// we only have 16-bit indices.
if(*tused >= 65535){
fprintf(stderr, "Can't add escape %d to full table\n", esc);
static inline int
terminfostr(char** gseq, const char* name){
*gseq = tigetstr(name);
if(*gseq == NULL || *gseq == (char*)-1){
*gseq = NULL;
return -1;
}
if(get_escape(ti, esc)){
fprintf(stderr, "Already defined escape %d (%s)\n",
esc, get_escape(ti, esc));
return -1;
// terminfo syntax allows a number N of milliseconds worth of pause to be
// specified using $<N> syntax. this is then honored by tputs(). but we don't
// use tputs(), instead preferring the much faster stdio+tiparm() (at the
// expense of terminals which do require these delays). to avoid dumping
// "$<N>" sequences all over stdio, we chop them out. real text can follow
// them, so we continue on, copying back once out of the delay.
char* wnext = NULL; // NULL until we hit a delay, then place to write
bool indelay = false; // true iff we're in a delay section
// we consider it a delay as soon as we see '$', and the delay ends at '>'
for(char* cur = *gseq ; *cur ; ++cur){
if(!indelay){
// if we're not in a delay section, make sure we're not starting one,
// and otherwise copy the current character back (if necessary).
if(*cur == '$'){
wnext = cur;
indelay = true;
}else{
if(wnext){
*wnext++ = *cur;
}
}
}else{
// we are in a delay section. make sure we're not ending one.
if(*cur == '>'){
indelay = false;
}
}
}
if(wnext){
*wnext = '\0';
}
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 0;
}

static inline 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;
}
ti->esctable = tmp;
*tlen = newsize;
}else{
ti->escindices[idx] = 0;
}
// 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;
}

Expand Down Expand Up @@ -386,20 +365,6 @@ send_initial_queries(int fd, bool minimal){
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;
}

// if we get a response to the standard cursor locator escape, we know this
// terminal supports it, hah.
static int
Expand Down Expand Up @@ -698,8 +663,12 @@ int interrogate_terminfo(tinfo* ti, int fd, const char* termname, unsigned utf8,
memset(ti, 0, sizeof(*ti));
#ifdef __APPLE__
qterm = macos_early_matches(termname);
#endif
#ifdef __linux__
#elif defined(__MINGW64__)
if(prepare_windows_terminal(ti)){
return -1;
}
qterm = TERMINAL_MSTERMINAL;
#elif defined(__linux__)
ti->linux_fb_fd = -1;
ti->linux_fbuffer = MAP_FAILED;
// we might or might not program quadrants into the console font
Expand Down
35 changes: 35 additions & 0 deletions src/lib/termdesc.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,41 @@ char* termdesc_longterm(const tinfo* ti);

int locate_cursor(tinfo* ti, int* cursor_y, int* cursor_x);

// 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 inline int
grow_esc_table(tinfo* ti, const char* tstr, escape_e esc,
size_t* tlen, size_t* tused){
// the actual table can grow past 64KB, but we can't start there, as
// we only have 16-bit indices.
if(*tused >= 65535){
fprintf(stderr, "Can't add escape %d to full table\n", esc);
return -1;
}
if(get_escape(ti, esc)){
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 = (char*)realloc(ti->esctable, newsize); // cast for c++
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;
}

#ifdef __cplusplus
}
#endif
Expand Down
28 changes: 28 additions & 0 deletions src/lib/windows.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "termdesc.h"
#include "internal.h"
#include "windows.h"

// ti has been memset to all zeroes. windows configuration is static.
int prepare_windows_terminal(tinfo* ti, size_t* tablelen, size_t* tableused){
const struct wtermdesc {
escape_e esc;
const char* tinfo;
} wterms[] = {
{ ESCAPE_CUP, "\\E[%i%p1%d;%p2%dH", },
{ ESCAPE_RMKX, "\\E[?1l", },
{ ESCAPE_SMKX, "\\E[?1h", },
{ ESCAPE_VPA, "\\E[%i%p1%dd", },
{ ESCAPE_HPA, "\\E[%i%p1%dG", }, { ESCAPE_SC, "\\E[s", },
{ ESCAPE_RC, "\\E[u", },
{ ESCAPE_CLEAR, "\\E[2J", },
{ ESCAPE_SMCUP, "\\E[?1049h", },
{ ESCAPE_RMCUP, "\\E[?1049l", },
{ ESCAPE_MAX, NULL, }
}, *w;
for(w = wterms ; w->tinfo; ++w){
if(grow_esc_table(ti, w->tinfo, w->esc, tablelen, tableused)){
return -1;
}
}
return 0;
}
18 changes: 18 additions & 0 deletions src/lib/windows.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef NOTCURSES_WINDOWS
#define NOTCURSES_WINDOWS

#ifdef __cplusplus
extern "C" {
#endif

struct tinfo;

// ti has been memset to all zeroes. windows configuration is static.
int prepare_windows_terminal(struct tinfo* ti, size_t* tablelen,
size_t* tableused);

#ifdef __cplusplus
}
#endif

#endif

0 comments on commit 06f2397

Please sign in to comment.