[ncplane_put] admit tab characters #1233

pull/2623/head
nick black 2 years ago committed by nick black
parent b326d43885
commit 7c8cf1e6e8

@ -2165,8 +2165,9 @@ ncplane_putc(struct ncplane* n, const nccell* c){
}
// Replace the cell at the specified coordinates with the provided 7-bit char
// 'c'. Advance the cursor by 1. On success, returns 1. On failure, returns -1.
// This works whether the underlying char is signed or unsigned.
// 'c'. Advance the cursor by 1. On success, returns the number of columns the
// cursor was advanced. On failure, returns -1. This works whether the
// underlying char is signed or unsigned.
static inline int
ncplane_putchar_yx(struct ncplane* n, int y, int x, char c){
nccell ce = NCCELL_INITIALIZER((uint32_t)c, ncplane_styles(n), ncplane_channels(n));

@ -19,6 +19,7 @@
#include "banner.h"
#define ESC "\x1b"
#define TABSTOP 8
void notcurses_version_components(int* major, int* minor, int* patch, int* tweak){
*major = NOTCURSES_VERNUM_MAJOR;
@ -1858,8 +1859,6 @@ ncplane_put(ncplane* n, int y, int x, const char* egc, int cols,
}
if(*egc == '\n'){
scroll_down(n);
}else if(*egc == '\t'){
// FIXME do what, exactly?
}
// A wide character obliterates anything to its immediate right (and marks
// that cell as wide). Any character placed atop one cell of a wide character
@ -1884,13 +1883,30 @@ ncplane_put(ncplane* n, int y, int x, const char* egc, int cols,
}
targ->stylemask = stylemask;
targ->channels = channels;
if(cell_load_direct(n, targ, egc, bytes, cols) < 0){
return -1;
// tabs get replaced with spaces, up to the next tab stop. we always try to
// write at least one. if there are no more tabstops on the current line, if
// autogrowing to the right, extend as necessary. otherwise, if scrolling,
// move to the next line. otherwise, simply fill any spaces we can. this has
// already taken place by the time we get here, if it ought have happened.
if(*egc == '\t'){
if(n->x >= n->lenx){
if(!n->scrolling && n->autogrow){
// FIXME might need autogrow to the next tab stop out
}
}
if(cell_load_direct(n, targ, egc, bytes, cols) < 0){
return -1;
}
cols = (n->x + TABSTOP) / TABSTOP * TABSTOP;
}else{
if(cell_load_direct(n, targ, egc, bytes, cols) < 0){
return -1;
}
}
//fprintf(stderr, "%08x %016lx %c %d %d\n", targ->gcluster, targ->channels, nccell_double_wide_p(targ) ? 'D' : 'd', bytes, cols);
// must set our right hand sides wide, and check for further damage
if(*egc != '\n'){
++n->x;
// if wide, set our right hand columns wide, and check for further damage
for(int i = 1 ; i < cols ; ++i){
nccell* candidate = &n->fb[nfbcellidx(n, n->y, n->x)];
int off = nccell_cols(candidate);

@ -1,6 +1,8 @@
#include <cstdlib>
#include "main.h"
constexpr int TABWIDTH = 8;
TEST_CASE("TaBs") { // refreshing and delicious
auto nc_ = testing_notcurses();
if(!nc_){
@ -15,10 +17,31 @@ TEST_CASE("TaBs") { // refreshing and delicious
nopts.cols = 80;
auto n = ncplane_create(n_, &nopts);
unsigned y, x;
CHECK(1 == ncplane_putchar(n, '\t'));
CHECK(TABWIDTH == ncplane_putchar(n, '\t'));
ncplane_cursor_yx(n, &y, &x);
CHECK(y == 0);
CHECK(x == 8);
CHECK(x == TABWIDTH);
for(unsigned i = 0 ; i < x ; ++i){
char* c = ncplane_at_yx(n, 0, i, nullptr, nullptr);
REQUIRE(c);
CHECK(0 == strcmp(c, " "));
free(c);
}
}
SUBCASE("PutXoffsetTaBs") {
struct ncplane_options nopts{};
nopts.rows = 2;
nopts.cols = TABWIDTH;
auto n = ncplane_create(n_, &nopts);
unsigned y, x;
for(int i = 0 ; i < TABWIDTH ; ++i){
CHECK(TABWIDTH - i == ncplane_putchar(n, '\t'));
ncplane_cursor_yx(n, &y, &x);
CHECK(y == 0);
CHECK(x == TABWIDTH - i);
CHECK(0 == ncplane_cursor_move_yx(n, 0, i + 1));
}
for(unsigned i = 0 ; i < x ; ++i){
char* c = ncplane_at_yx(n, 0, i, nullptr, nullptr);
REQUIRE(c);
@ -30,13 +53,13 @@ TEST_CASE("TaBs") { // refreshing and delicious
SUBCASE("PutwcTaB") {
struct ncplane_options nopts{};
nopts.rows = 2;
nopts.cols = 80;
nopts.cols = TABWIDTH;
auto n = ncplane_create(n_, &nopts);
unsigned y, x;
CHECK(1 == ncplane_putwc(n, L'\t'));
CHECK(TABWIDTH == ncplane_putwc(n, L'\t'));
ncplane_cursor_yx(n, &y, &x);
CHECK(y == 0);
CHECK(x == 8);
CHECK(x == TABWIDTH);
for(unsigned i = 0 ; i < x ; ++i){
char* c = ncplane_at_yx(n, 0, i, nullptr, nullptr);
REQUIRE(c);
@ -48,14 +71,14 @@ TEST_CASE("TaBs") { // refreshing and delicious
SUBCASE("PutCellTaB") {
struct ncplane_options nopts{};
nopts.rows = 2;
nopts.cols = 80;
nopts.cols = TABWIDTH;
auto n = ncplane_create(n_, &nopts);
nccell c = NCCELL_CHAR_INITIALIZER('\t');
unsigned y, x;
CHECK(1 == ncplane_putc(n, &c));
ncplane_cursor_yx(n, &y, &x);
CHECK(y == 0);
CHECK(x == 8);
CHECK(x == TABWIDTH);
for(unsigned i = 0 ; i < x ; ++i){
char* s = ncplane_at_yx(n, 0, i, nullptr, nullptr);
REQUIRE(s);
@ -67,7 +90,7 @@ TEST_CASE("TaBs") { // refreshing and delicious
SUBCASE("PutMultipleTaBs") {
struct ncplane_options nopts{};
nopts.rows = 2;
nopts.cols = 80;
nopts.cols = TABWIDTH;
auto n = ncplane_create(n_, &nopts);
unsigned y, x;
CHECK(1 == ncplane_putstr(n, "\t\t"));
@ -85,7 +108,7 @@ TEST_CASE("TaBs") { // refreshing and delicious
SUBCASE("PutRowOfTaBs") {
struct ncplane_options nopts{};
nopts.rows = 2;
nopts.cols = 80;
nopts.cols = TABWIDTH;
auto n = ncplane_create(n_, &nopts);
unsigned y, x;
CHECK(1 == ncplane_putstr(n, "\t\t\t\t\t\t\t\t\t\t"));

Loading…
Cancel
Save