fix LayoutFillsPlaneNoSpaces problems #815

This commit is contained in:
nick black 2020-07-23 15:13:09 -04:00 committed by Nick Black
parent 1664e64617
commit 243cbd6a92
2 changed files with 19 additions and 17 deletions

View File

@ -1662,7 +1662,8 @@ int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t
const char* linestart = text; const char* linestart = text;
int x = 0; // number of columns consumed for this line int x = 0; // number of columns consumed for this line
do{ do{
const char* breaker = NULL; const char* breaker = NULL; // where the last wordbreaker starts
int breakercol = 0; // column of the last wordbreaker
// figure how much text to output on this line // figure how much text to output on this line
mbstate_t mbstate = {}; mbstate_t mbstate = {};
int width; int width;
@ -1671,7 +1672,7 @@ int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t
// not a space, it won't be printed, and we carry the word forward. // not a space, it won't be printed, and we carry the word forward.
// FIXME what ought be done with \n or multiple spaces? // FIXME what ought be done with \n or multiple spaces?
while(*text && x <= dimx){ while(*text && x <= dimx){
fprintf(stderr, "laying out [%s] at %d <= %d, %zu\n", linestart, x, dimx, text - linestart); //fprintf(stderr, "laying out [%s] at %d <= %d, %zu\n", linestart, x, dimx, text - linestart);
wchar_t w; wchar_t w;
size_t consumed = mbrtowc(&w, text, MB_CUR_MAX, &mbstate); size_t consumed = mbrtowc(&w, text, MB_CUR_MAX, &mbstate);
if(consumed == (size_t)-2 || consumed == (size_t)-1){ if(consumed == (size_t)-2 || consumed == (size_t)-1){
@ -1689,10 +1690,11 @@ fprintf(stderr, "laying out [%s] at %d <= %d, %zu\n", linestart, x, dimx, text -
continue; // don't emit leading whitespace, or count it continue; // don't emit leading whitespace, or count it
}else{ }else{
breaker = text; breaker = text;
breakercol = x;
} }
} }
width = wcwidth(w); width = wcwidth(w);
fprintf(stderr, "have char %lc (%d)\n", w, width); //fprintf(stderr, "have char %lc (%d) (%zu)\n", w, width, text - linestart);
if(width < 0){ if(width < 0){
width = 0; width = 0;
} }
@ -1702,31 +1704,30 @@ fprintf(stderr, "have char %lc (%d)\n", w, width);
x += width; x += width;
text += consumed; text += consumed;
} }
fprintf(stderr, "OUT! %s %zu\n", linestart, text - linestart); //fprintf(stderr, "OUT! %s %zu %d\n", linestart, text - linestart, x);
int carrybytes = 0;
bool overlong = false; // ugh bool overlong = false; // ugh
// if we have no breaker, we got a single word that was longer than our // if we have no breaker, we got a single word that was longer than our
// line. print what we can and move along. if *text is nul, we're done. // line. print what we can and move along. if *text is nul, we're done.
if(!*text || breaker == NULL){ if(!*text || breaker == NULL){
breaker = text/* + 1*/; breaker = text;
breakercol = dimx;
}else{ }else{
// if the word on which we ended is overlong (longer than the plane is // if the word on which we ended is overlong (longer than the plane is
// wide), go ahead and start printing it where it starts. otherwise, punt // wide), go ahead and start printing it where it starts. otherwise, punt
// it to the next line, to avoid breaking it across lines. // it to the next line, to avoid breaking it across lines.
if(overlong_word(breaker + 1, dimx)){ if(overlong_word(breaker + 1, dimx)){
breaker = text; breaker = text;
breakercol = dimx;
overlong = true; overlong = true;
fprintf(stderr, "NEW BREAKER: %s\n", breaker); //fprintf(stderr, "NEW BREAKER: %s\n", breaker);
}else{
carrybytes = text - breaker;
} }
} }
fprintf(stderr, "exited at %d (%d) %zu looking at [%.*s]\n", x, dimx, breaker - linestart, (int)(breaker - linestart), linestart); //fprintf(stderr, "exited at %d (%d) %zu looking at [%.*s]\n", x, dimx, breaker - linestart, (int)(breaker - linestart), linestart);
if(breaker != linestart){ if(breaker != linestart){
totalcols += x; totalcols += breakercol;
const int xpos = ncplane_align(n, align, x); const int xpos = ncplane_align(n, align, breakercol);
// blows out if we supply a y beyond leny // blows out if we supply a y beyond leny
fprintf(stderr, "y: %d %ld %.*s\n", y, breaker - linestart, (int)(breaker - linestart), linestart); //fprintf(stderr, "y: %d %ld %.*s\n", y, breaker - linestart, (int)(breaker - linestart), linestart);
if(ncplane_putnstr_yx(n, y, xpos, breaker - linestart, linestart) <= 0){ if(ncplane_putnstr_yx(n, y, xpos, breaker - linestart, linestart) <= 0){
if(bytes){ if(bytes){
*bytes = linestart - beginning; *bytes = linestart - beginning;
@ -1734,7 +1735,8 @@ fprintf(stderr, "y: %d %ld %.*s\n", y, breaker - linestart, (int)(breaker - line
return -1; return -1;
} }
} }
x = carrybytes; //fprintf(stderr, "x gets breakercol: %d\n", breakercol);
x = breakercol;
if(breaker == text || overlong){ if(breaker == text || overlong){
linestart = breaker; linestart = breaker;
}else{ }else{
@ -2458,7 +2460,7 @@ int ncplane_putnstr_aligned(struct ncplane* n, int y, ncalign_e align, size_t s,
int ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters){ int ncplane_putnstr_yx(struct ncplane* n, int y, int x, size_t s, const char* gclusters){
int ret = 0; int ret = 0;
fprintf(stderr, "PUT %zu at %d/%d [%.*s]\n", s, y, x, (int)s, gclusters); //fprintf(stderr, "PUT %zu at %d/%d [%.*s]\n", s, y, x, (int)s, gclusters);
// FIXME speed up this blissfully naive solution // FIXME speed up this blissfully naive solution
while((size_t)ret < s && *gclusters){ while((size_t)ret < s && *gclusters){
int wcs; int wcs;

View File

@ -90,13 +90,13 @@ TEST_CASE("TextLayout") {
auto sp = ncplane_new(nc_, 2, 6, 0, 0, nullptr); auto sp = ncplane_new(nc_, 2, 6, 0, 0, nullptr);
REQUIRE(sp); REQUIRE(sp);
size_t bytes; size_t bytes;
const char boundstr[] = "a 血的神 m公"; const char boundstr[] = "a 血的神";
CHECK(0 < ncplane_puttext(sp, 0, NCALIGN_CENTER, boundstr, &bytes)); CHECK(0 < ncplane_puttext(sp, 0, NCALIGN_CENTER, boundstr, &bytes));
CHECK(0 == notcurses_render(nc_)); CHECK(0 == notcurses_render(nc_));
CHECK(bytes == strlen(boundstr)); CHECK(bytes == strlen(boundstr));
char* line = ncplane_contents(sp, 0, 0, -1, -1); char* line = ncplane_contents(sp, 0, 0, -1, -1);
REQUIRE(line); REQUIRE(line);
CHECK(0 == strcmp(line, "a 血的神 m公")); CHECK(0 == strcmp(line, "a血的神"));
free(line); free(line);
ncplane_destroy(sp); ncplane_destroy(sp);
} }