mirror of
https://github.com/dankamongmen/notcurses
synced 2025-03-09 17:19:03 -04:00
notcurses_puttext: use libunistring for wordbreaking #772
This commit is contained in:
parent
0ba1512d68
commit
604747c8f2
@ -79,18 +79,24 @@ elseif(${USE_OIIO})
|
|||||||
pkg_check_modules(OIIO REQUIRED OpenImageIO>=2.1)
|
pkg_check_modules(OIIO REQUIRED OpenImageIO>=2.1)
|
||||||
endif()
|
endif()
|
||||||
find_library(MATH_LIBRARIES m)
|
find_library(MATH_LIBRARIES m)
|
||||||
# don't cache this, or installing it requires clearing the cache to be found
|
if(${USE_DOCTEST})
|
||||||
|
find_package(doctest 2.3.5 REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# don't cache these, or installing them requires clearing the cache to be found.
|
||||||
|
# this is going to be true for anything lacking pkg-config/CMake support.
|
||||||
unset(HAVE_QRCODEGEN_H CACHE)
|
unset(HAVE_QRCODEGEN_H CACHE)
|
||||||
check_include_file("qrcodegen/qrcodegen.h" HAVE_QRCODEGEN_H)
|
check_include_file("uniwbrk.h" HAVE_UNISTRING_H)
|
||||||
|
if(NOT "${HAVE_UNISTRING_H}")
|
||||||
|
message(FATAL_ERROR "Couldn't find uniwbrk.h from GNU libunistring")
|
||||||
|
endif()
|
||||||
if("${USE_QRCODEGEN}")
|
if("${USE_QRCODEGEN}")
|
||||||
|
check_include_file("qrcodegen/qrcodegen.h" HAVE_QRCODEGEN_H)
|
||||||
if(NOT "${HAVE_QRCODEGEN_H}")
|
if(NOT "${HAVE_QRCODEGEN_H}")
|
||||||
message(FATAL_ERROR "USE_QRCODEGEN is active, but couldn't find qrcodegen.h")
|
message(FATAL_ERROR "USE_QRCODEGEN is active, but couldn't find qrcodegen.h")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
find_library(LIBRT rt)
|
find_library(LIBRT rt)
|
||||||
if(${USE_DOCTEST})
|
|
||||||
find_package(doctest 2.3.5 REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# libnotcurses (core shared library and static library)
|
# libnotcurses (core shared library and static library)
|
||||||
file(GLOB NCSRCS CONFIGURE_DEPENDS src/lib/*.c src/lib/*.cpp)
|
file(GLOB NCSRCS CONFIGURE_DEPENDS src/lib/*.c src/lib/*.cpp)
|
||||||
@ -129,6 +135,7 @@ target_link_libraries(notcurses
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
"${TERMINFO_LIBRARIES}"
|
"${TERMINFO_LIBRARIES}"
|
||||||
"${LIBRT}"
|
"${LIBRT}"
|
||||||
|
unistring
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
@ -136,6 +143,7 @@ target_link_libraries(notcurses-static
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
"${TERMINFO_STATIC_LIBRARIES}"
|
"${TERMINFO_STATIC_LIBRARIES}"
|
||||||
"${LIBRT}"
|
"${LIBRT}"
|
||||||
|
unistring
|
||||||
PUBLIC
|
PUBLIC
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
)
|
)
|
||||||
|
3
NEWS.md
3
NEWS.md
@ -1,6 +1,9 @@
|
|||||||
This document attempts to list user-visible changes and any major internal
|
This document attempts to list user-visible changes and any major internal
|
||||||
rearrangements of Notcurses.
|
rearrangements of Notcurses.
|
||||||
|
|
||||||
|
* 1.6.7 (not yet released)
|
||||||
|
* GNU libunistring is now required to build/load Notcurses.
|
||||||
|
|
||||||
* 1.6.6 (2020-07-19)
|
* 1.6.6 (2020-07-19)
|
||||||
* `notcurses-pydemo` is now only installed alongside the Python module,
|
* `notcurses-pydemo` is now only installed alongside the Python module,
|
||||||
using setuptools. CMake no longer installs it.
|
using setuptools. CMake no longer installs it.
|
||||||
|
@ -114,6 +114,7 @@ that fine library.
|
|||||||
* (build) A C11 and a C++17 compiler
|
* (build) A C11 and a C++17 compiler
|
||||||
* (build) CMake 3.14.0+
|
* (build) CMake 3.14.0+
|
||||||
* (build+runtime) From NCURSES: terminfo 6.1+
|
* (build+runtime) From NCURSES: terminfo 6.1+
|
||||||
|
* (build+runtime) GNU libunistring 0.9.10+
|
||||||
* (OPTIONAL) (build+runtime) From QR-Code-generator: [libqrcodegen](https://github.com/nayuki/QR-Code-generator) 1.5.0+
|
* (OPTIONAL) (build+runtime) From QR-Code-generator: [libqrcodegen](https://github.com/nayuki/QR-Code-generator) 1.5.0+
|
||||||
* (OPTIONAL) (build+runtime) From [FFmpeg](https://www.ffmpeg.org/): libswscale 5.0+, libavformat 57.0+, libavutil 56.0+
|
* (OPTIONAL) (build+runtime) From [FFmpeg](https://www.ffmpeg.org/): libswscale 5.0+, libavformat 57.0+, libavutil 56.0+
|
||||||
* (OPTIONAL) (build+runtime) [OpenImageIO](https://github.com/OpenImageIO/oiio) 2.15.0+
|
* (OPTIONAL) (build+runtime) [OpenImageIO](https://github.com/OpenImageIO/oiio) 2.15.0+
|
||||||
|
@ -341,7 +341,7 @@ nc_err_e ncdirect_render_image(ncdirect* n, const char* file, ncalign_e align,
|
|||||||
struct ncplane* faken = ncplane_create(nullptr, nullptr,
|
struct ncplane* faken = ncplane_create(nullptr, nullptr,
|
||||||
disprows / encoding_y_scale(bset),
|
disprows / encoding_y_scale(bset),
|
||||||
dispcols / encoding_x_scale(bset),
|
dispcols / encoding_x_scale(bset),
|
||||||
0, 0, nullptr);
|
0, 0, nullptr, nullptr);
|
||||||
if(faken == nullptr){
|
if(faken == nullptr){
|
||||||
return NCERR_NOMEM;
|
return NCERR_NOMEM;
|
||||||
}
|
}
|
||||||
|
@ -80,6 +80,7 @@ typedef struct ncplane {
|
|||||||
cell basecell; // cell written anywhere that fb[i].gcluster == 0
|
cell basecell; // cell written anywhere that fb[i].gcluster == 0
|
||||||
struct notcurses* nc; // notcurses object of which we are a part
|
struct notcurses* nc; // notcurses object of which we are a part
|
||||||
bool scrolling; // is scrolling enabled? always disabled by default
|
bool scrolling; // is scrolling enabled? always disabled by default
|
||||||
|
char* name; // used only for debugging
|
||||||
} ncplane;
|
} ncplane;
|
||||||
|
|
||||||
#include "blitset.h"
|
#include "blitset.h"
|
||||||
@ -782,7 +783,7 @@ calc_gradient_channels(uint64_t* channels, uint64_t ul, uint64_t ur,
|
|||||||
// ncvisual_render(), and thus calls these low-level internal functions.
|
// ncvisual_render(), and thus calls these low-level internal functions.
|
||||||
// they are not for general use -- check ncplane_new() and ncplane_destroy().
|
// they are not for general use -- check ncplane_new() and ncplane_destroy().
|
||||||
ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
||||||
int yoff, int xoff, void* opaque);
|
int yoff, int xoff, void* opaque, const char* name);
|
||||||
void free_plane(ncplane* p);
|
void free_plane(ncplane* p);
|
||||||
|
|
||||||
// heap-allocated formatted output
|
// heap-allocated formatted output
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <uniwbrk.h>
|
||||||
#include <langinfo.h>
|
#include <langinfo.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
@ -265,6 +266,7 @@ void free_plane(ncplane* p){
|
|||||||
p->nc->stats.fbbytes -= sizeof(*p->fb) * p->leny * p->lenx;
|
p->nc->stats.fbbytes -= sizeof(*p->fb) * p->leny * p->lenx;
|
||||||
}
|
}
|
||||||
egcpool_dump(&p->pool);
|
egcpool_dump(&p->pool);
|
||||||
|
free(p->name);
|
||||||
free(p->fb);
|
free(p->fb);
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
@ -281,7 +283,7 @@ void free_plane(ncplane* p){
|
|||||||
// ncplane created by ncdirect for rendering visuals. in that case (and only in
|
// ncplane created by ncdirect for rendering visuals. in that case (and only in
|
||||||
// that case), nc is NULL.
|
// that case), nc is NULL.
|
||||||
ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
||||||
int yoff, int xoff, void* opaque){
|
int yoff, int xoff, void* opaque, const char* name){
|
||||||
if(rows <= 0 || cols <= 0){
|
if(rows <= 0 || cols <= 0){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -299,6 +301,7 @@ ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
|||||||
p->x = p->y = 0;
|
p->x = p->y = 0;
|
||||||
p->logrow = 0;
|
p->logrow = 0;
|
||||||
p->blist = NULL;
|
p->blist = NULL;
|
||||||
|
p->name = name ? strdup(name) : NULL;
|
||||||
if( (p->boundto = n) ){
|
if( (p->boundto = n) ){
|
||||||
p->absx = xoff + n->absx;
|
p->absx = xoff + n->absx;
|
||||||
p->absy = yoff + n->absy;
|
p->absy = yoff + n->absy;
|
||||||
@ -339,7 +342,8 @@ ncplane* ncplane_create(notcurses* nc, ncplane* n, int rows, int cols,
|
|||||||
static ncplane*
|
static ncplane*
|
||||||
create_initial_ncplane(notcurses* nc, int dimy, int dimx){
|
create_initial_ncplane(notcurses* nc, int dimy, int dimx){
|
||||||
nc->stdplane = ncplane_create(nc, NULL, dimy - (nc->margin_t + nc->margin_b),
|
nc->stdplane = ncplane_create(nc, NULL, dimy - (nc->margin_t + nc->margin_b),
|
||||||
dimx - (nc->margin_l + nc->margin_r), 0, 0, NULL);
|
dimx - (nc->margin_l + nc->margin_r), 0, 0, NULL,
|
||||||
|
"std");
|
||||||
return nc->stdplane;
|
return nc->stdplane;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,16 +356,17 @@ const ncplane* notcurses_stdplane_const(const notcurses* nc){
|
|||||||
}
|
}
|
||||||
|
|
||||||
ncplane* ncplane_new(notcurses* nc, int rows, int cols, int yoff, int xoff, void* opaque){
|
ncplane* ncplane_new(notcurses* nc, int rows, int cols, int yoff, int xoff, void* opaque){
|
||||||
return ncplane_create(nc, NULL, rows, cols, yoff, xoff, opaque);
|
return ncplane_create(nc, NULL, rows, cols, yoff, xoff, opaque, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ncplane* ncplane_bound(ncplane* n, int rows, int cols, int yoff, int xoff, void* opaque){
|
ncplane* ncplane_bound(ncplane* n, int rows, int cols, int yoff, int xoff, void* opaque){
|
||||||
return ncplane_create(n->nc, n, rows, cols, yoff, xoff, opaque);
|
return ncplane_create(n->nc, n, rows, cols, yoff, xoff, opaque, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
ncplane* ncplane_aligned(ncplane* n, int rows, int cols, int yoff,
|
ncplane* ncplane_aligned(ncplane* n, int rows, int cols, int yoff,
|
||||||
ncalign_e align, void* opaque){
|
ncalign_e align, void* opaque){
|
||||||
return ncplane_create(n->nc, n, rows, cols, yoff, ncplane_align(n, align, cols), opaque);
|
return ncplane_create(n->nc, n, rows, cols, yoff,
|
||||||
|
ncplane_align(n, align, cols), opaque, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ncplane_home(ncplane* n){
|
void ncplane_home(ncplane* n){
|
||||||
@ -408,7 +413,8 @@ ncplane* ncplane_dup(const ncplane* n, void* opaque){
|
|||||||
const struct notcurses* nc = ncplane_notcurses_const(n);
|
const struct notcurses* nc = ncplane_notcurses_const(n);
|
||||||
const int placey = n->absy - nc->margin_t;
|
const int placey = n->absy - nc->margin_t;
|
||||||
const int placex = n->absx - nc->margin_l;
|
const int placex = n->absx - nc->margin_l;
|
||||||
ncplane* newn = ncplane_create(n->nc, n->boundto, dimy, dimx, placey, placex, opaque);
|
ncplane* newn = ncplane_create(n->nc, n->boundto, dimy, dimx,
|
||||||
|
placey, placex, opaque, n->name);
|
||||||
if(newn){
|
if(newn){
|
||||||
if(egcpool_dup(&newn->pool, &n->pool)){
|
if(egcpool_dup(&newn->pool, &n->pool)){
|
||||||
ncplane_destroy(newn);
|
ncplane_destroy(newn);
|
||||||
@ -1595,10 +1601,10 @@ int ncplane_hline_interp(ncplane* n, const cell* c, int len,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME there are more advanced means of wordbreaking within unicode; use them
|
|
||||||
static bool
|
static bool
|
||||||
iswordbreak(wchar_t w){
|
iswordbreak(wchar_t wchar){
|
||||||
return iswspace(w);
|
int w = uc_wordbreak_property(wchar);
|
||||||
|
return (w == WBP_OTHER || w == WBP_NEWLINE || w == WBP_CR || w == WBP_LF);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@ -1623,6 +1629,7 @@ overlong_word(const char* text, int dimx){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME probably best to use u8_wordbreaks() and get all wordbreaks at once...
|
||||||
int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t* bytes){
|
int ncplane_puttext(ncplane* n, int y, ncalign_e align, const char* text, size_t* bytes){
|
||||||
int totalcols = 0;
|
int totalcols = 0;
|
||||||
// save the beginning for diagnostic
|
// save the beginning for diagnostic
|
||||||
|
@ -498,6 +498,7 @@ TEST_CASE("NCPlane") {
|
|||||||
ncplane_cursor_yx(n_, &y, &x);
|
ncplane_cursor_yx(n_, &y, &x);
|
||||||
REQUIRE(1 == y);
|
REQUIRE(1 == y);
|
||||||
REQUIRE(dimx == x);
|
REQUIRE(dimx == x);
|
||||||
|
// this ought not print anything, since we're at the end of the row
|
||||||
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
||||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
||||||
@ -534,6 +535,7 @@ TEST_CASE("NCPlane") {
|
|||||||
ncplane_cursor_yx(n_, &y, &x);
|
ncplane_cursor_yx(n_, &y, &x);
|
||||||
REQUIRE(1 == y);
|
REQUIRE(1 == y);
|
||||||
REQUIRE(dimx == x);
|
REQUIRE(dimx == x);
|
||||||
|
// this ought not print anything, since we're at the end of the row
|
||||||
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
REQUIRE(0 == ncplane_putstr(n_, STR3));
|
||||||
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
REQUIRE(0 == ncplane_cursor_move_yx(n_, 0, 0));
|
||||||
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
REQUIRE(0 < ncplane_at_cursor_cell(n_, &testcell)); // want first char of STR1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user