linux console: shim in half blocks #201

pull/803/head
nick black 4 years ago committed by Nick Black
parent a009eb946c
commit eaa1c28756

@ -814,7 +814,7 @@ int get_controlling_tty(void);
if((nc)->loglevel >= NCLOGLEVEL_ERROR){ \
nclog("%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__); } }while(0);
#define logwarning(nc, fmt, ...) do{ \
#define logwarn(nc, fmt, ...) do{ \
if((nc)->loglevel >= NCLOGLEVEL_WARNING){ \
nclog("%s:%d:" fmt, __func__, __LINE__, ##__VA_ARGS__); } }while(0);

@ -129,6 +129,21 @@ shim_lower_right_quad(struct consolefontdesc* cfd, unsigned idx){
return 0;
}
// add UCS2 codepoint |w| to |map| for font idx |fidx|
static int
add_to_map(const notcurses* nc, struct unimapdesc* map, wchar_t w, unsigned fidx){
logdebug(nc, "Adding mapping U+%04x -> %03u\n", w, fidx);
struct unipair* tmp = realloc(map->entries, sizeof(*map->entries) * (map->entry_ct + 1));
if(tmp == NULL){
return -1;
}
map->entries = tmp;
map->entries[map->entry_ct].unicode = w;
map->entries[map->entry_ct].fontpos = fidx;
++map->entry_ct;
return 0;
}
static int
program_line_drawing_chars(const notcurses* nc, struct unimapdesc* map){
struct simset {
@ -185,27 +200,21 @@ program_line_drawing_chars(const notcurses* nc, struct unimapdesc* map){
if(fontidx > -1){
for(size_t widx = 0 ; widx < wcslen(s->ws) ; ++widx){
if(!found[widx]){
logdebug(nc, "Adding mapping U+%04x -> %03u\n", s->ws[widx], fontidx);
struct unipair* tmp = realloc(map->entries, sizeof(*map->entries) * (map->entry_ct + 1));
if(tmp == NULL){
if(add_to_map(nc, map, s->ws[widx], fontidx)){
return -1;
}
map->entries = tmp;
map->entries[map->entry_ct].unicode = s->ws[widx];
map->entries[map->entry_ct].fontpos = fontidx;
++map->entry_ct;
++toadd;
}
}
}else{
logwarning(nc, "Couldn't find any glyphs for set %zu\n", sidx);
logwarn(nc, "Couldn't find any glyphs for set %zu\n", sidx);
}
}
if(toadd == 0){
return 0;
}
if(ioctl(nc->ttyfd, PIO_UNIMAP, map)){
logwarning(nc, "Error setting kernel unicode map (%s)\n", strerror(errno));
logwarn(nc, "Error setting kernel unicode map (%s)\n", strerror(errno));
return -1;
}
loginfo(nc, "Successfully added %d kernel unicode mapping%s\n",
@ -219,18 +228,59 @@ program_block_drawing_chars(const notcurses* nc, struct consolefontdesc* cfd,
struct shimmer {
int (*glyphfxn)(struct consolefontdesc* cfd, unsigned idx);
wchar_t w;
bool found;
} shimmers[] = {
{ .glyphfxn = shim_upper_half_block, .w = L'', },
{ .glyphfxn = shim_lower_half_block, .w = L'', },
{ .glyphfxn = shim_left_half_block, .w = L'', },
{ .glyphfxn = shim_right_half_block, .w = L'', },
{ .glyphfxn = shim_upper_half_block, .w = L'', .found = false, },
{ .glyphfxn = shim_lower_half_block, .w = L'', .found = false, },
{ .glyphfxn = shim_left_half_block, .w = L'', .found = false, },
{ .glyphfxn = shim_right_half_block, .w = L'', .found = false, },
// FIXME more
};
int toadd = 0;
// FIXME need a table of functions + UCS2
// first, take a pass to see which glyphs we already have
for(unsigned i = 0 ; i < cfd->charcount ; ++i){
if(map->entries[i].unicode >= 0x2580 && map->entries[i].unicode <= 0x259f){
for(size_t s = 0 ; s < sizeof(shimmers) / sizeof(*shimmers) ; ++s){
if(map->entries[i].unicode == shimmers[s].w){
logdebug(nc, "Found %lc at fontidx %u\n", shimmers[s].w, i);
shimmers[s].found = true;
break;
}
}
}
}
int added = 0;
unsigned candidate = cfd->charcount;
for(size_t s = 0 ; s < sizeof(shimmers) / sizeof(*shimmers) ; ++s){
if(!shimmers[s].found){
while(--candidate){
if(map->entries[candidate].unicode < 0x2580 || map->entries[candidate].unicode > 0x259f){
break;
}
}
if(candidate == 0){
logwarn(nc, "Ran out of replaceable glyphs for U+%04x\n", shimmers[s].w);
return -1;
}
if(shimmers[s].glyphfxn(cfd, candidate)){
logwarn(nc, "Error replacing glyph for U+%04x at %u\n", shimmers[s].w, candidate);
return -1;
}
if(add_to_map(nc, map, shimmers[s].w, candidate)){
return -1;
}
++added;
}
}
if(ioctl(nc->ttyfd, PIO_FONTX, cfd)){
logwarn(nc, "Error programming kernel font (%s)\n", strerror(errno));
return -1;
}
if(ioctl(nc->ttyfd, PIO_UNIMAP, map)){
logwarn(nc, "Error setting kernel unicode map (%s)\n", strerror(errno));
return -1;
}
loginfo(nc, "Successfully added %d kernel font glyph%s\n",
toadd, toadd == 1 ? "" : "s");
added, added == 1 ? "" : "s");
return 0;
}
@ -238,17 +288,17 @@ static int
reprogram_linux_font(const notcurses* nc, struct consolefontdesc* cfd,
struct unimapdesc* map){
if(ioctl(nc->ttyfd, GIO_FONTX, cfd)){
logwarning(nc, "Error reading Linux kernelfont (%s)\n", strerror(errno));
logwarn(nc, "Error reading Linux kernelfont (%s)\n", strerror(errno));
return -1;
}
loginfo(nc, "Kernel font size (glyphcount): %hu\n", cfd->charcount);
loginfo(nc, "Kernel font character geometry: 8x%hu\n", cfd->charheight);
if(cfd->charcount > 512){
logwarning(nc, "Warning: kernel returned excess charcount\n");
logwarn(nc, "Warning: kernel returned excess charcount\n");
return -1;
}
if(ioctl(nc->ttyfd, GIO_UNIMAP, map)){
logwarning(nc, "Error reading Linux unimap (%s)\n", strerror(errno));
logwarn(nc, "Error reading Linux unimap (%s)\n", strerror(errno));
return -1;
}
loginfo(nc, "Kernel Unimap size: %hu/%hu\n", map->entry_ct, USHRT_MAX);
@ -270,7 +320,7 @@ reprogram_console_font(const notcurses* nc){
size_t totsize = 32 * cfd.charcount;
cfd.chardata = malloc(totsize);
if(cfd.chardata == NULL){
logwarning(nc, "Error acquiring %zub for font descriptors (%s)\n", totsize, strerror(errno));
logwarn(nc, "Error acquiring %zub for font descriptors (%s)\n", totsize, strerror(errno));
return -1;
}
struct unimapdesc map = {};
@ -278,7 +328,7 @@ reprogram_console_font(const notcurses* nc){
totsize = map.entry_ct * sizeof(struct unipair);
map.entries = malloc(totsize);
if(map.entries == NULL){
logwarning(nc, "Error acquiring %zub for Unicode font map (%s)\n", totsize, strerror(errno));
logwarn(nc, "Error acquiring %zub for Unicode font map (%s)\n", totsize, strerror(errno));
free(cfd.chardata);
return -1;
}

@ -735,7 +735,7 @@ get_tty_fd(notcurses* nc, FILE* ttyfp){
int fd = -1;
if(ttyfp){
if((fd = fileno(ttyfp)) < 0){
logwarning(nc, "No file descriptor was available in outfp %p\n", ttyfp);
logwarn(nc, "No file descriptor was available in outfp %p\n", ttyfp);
}else{
if(isatty(fd)){
fd = dup(fd);
@ -748,7 +748,7 @@ get_tty_fd(notcurses* nc, FILE* ttyfp){
if(fd < 0){
fd = open("/dev/tty", O_RDWR | O_CLOEXEC);
if(fd < 0){
logwarning(nc, "Error opening /dev/tty (%s)\n", strerror(errno));
logwarn(nc, "Error opening /dev/tty (%s)\n", strerror(errno));
}
}
return fd;

Loading…
Cancel
Save