diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index 4b2b60a1f..ed93a9df4 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -1506,10 +1506,11 @@ int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t // figure how much text to output on this line mbstate_t mbstate = {}; int width; - // verified columns thus far (carried, and through breaker) - size_t verifiedcols = x; + // let it go all the way through to dimx. on that last hit of dimx, we + // might catch a space, in which case we want breaker updated. if it's + // not a space, it won't be printed, and we carry the word forward. // FIXME what ought be done with \n or multiple spaces? - while(*text && x < dimx){ + while(*text && x <= dimx){ wchar_t w; size_t consumed = mbrtowc(&w, text, MB_CUR_MAX, &mbstate); if(consumed == (size_t)-2 || consumed == (size_t)-1){ @@ -1530,7 +1531,6 @@ int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t // FIXME use the more advanced unicode functionality to break lines if(iswspace(w)){ breaker = text; - verifiedcols = x; } if(x + width > dimx){ break; @@ -1539,16 +1539,17 @@ int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t text += consumed; } int carrycols = 0; - if(x >= dimx){ - // the last character was one past the amount we can print. set linestart - // back to breaker, set carrycols to the amount since breaker - carrycols = x - verifiedcols; + if(x > dimx){ + // the last character was one past the amount we can print. + // set carrycols to the amount since breaker. + carrycols = text - breaker; } - totalcols += verifiedcols; + totalcols += (breaker - linestart); const int xpos = ncplane_align(n, align, x); if(!*text || breaker == NULL){ breaker = text; } + // blows out if we supply a y beyond leny if(ncplane_putnstr_yx(n, y, xpos, breaker - linestart, linestart) < 0){ if(bytes){ *bytes = linestart - beginning; diff --git a/tests/layout.cpp b/tests/layout.cpp index ee0a9f967..40cc98759 100644 --- a/tests/layout.cpp +++ b/tests/layout.cpp @@ -65,6 +65,26 @@ TEST_CASE("TextLayout") { ncplane_destroy(sp); } + // lay out text where a word ends on the boundary + SUBCASE("LayoutOnBoundary") { + auto sp = ncplane_new(nc_, 2, 10, 0, 0, nullptr); + REQUIRE(sp); + size_t bytes; + const char boundstr[] = "my nuclear arms"; + CHECK(0 < ncplane_puttext(sp, 0, NCALIGN_CENTER, boundstr, &bytes)); + CHECK(0 == notcurses_render(nc_)); + CHECK(bytes == strlen(boundstr)); + char* line = ncplane_contents(sp, 0, 0, 1, 10); + REQUIRE(line); + CHECK(0 == strcmp(line, "my nuclear")); + free(line); + line = ncplane_contents(sp, 1, 0, 1, 10); + REQUIRE(line); + CHECK(0 == strcmp(line, "arms")); + free(line); + ncplane_destroy(sp); + } + CHECK(0 == notcurses_stop(nc_)); }