Skip to content

Optimized performance for low-bit-rate terminals. #199

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 65 additions & 33 deletions cmatrix.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ int console = 0;
int xwindow = 0;
int lock = 0;
cmatrix **matrix = (cmatrix **) NULL;
cmatrix **omatrix = (cmatrix **) NULL;
int *length = NULL; /* Length of cols in each line */
int *spaces = NULL; /* Spaces left to fill */
int *updates = NULL; /* What does this do again? */
Expand Down Expand Up @@ -196,12 +197,17 @@ void var_init() {
if (matrix != NULL) {
free(matrix[0]);
free(matrix);
free(omatrix[0]);
free(omatrix);
}

matrix = nmalloc(sizeof(cmatrix *) * (LINES + 1));
omatrix = nmalloc(sizeof(cmatrix *) * (LINES + 1));
matrix[0] = nmalloc(sizeof(cmatrix) * (LINES + 1) * COLS);
omatrix[0] = nmalloc(sizeof(cmatrix) * (LINES + 1) * COLS);
for (i = 1; i <= LINES; i++) {
matrix[i] = matrix[i - 1] + COLS;
omatrix[i] = omatrix[i - 1] + COLS;
}

if (length != NULL) {
Expand All @@ -223,6 +229,7 @@ void var_init() {
for (i = 0; i <= LINES; i++) {
for (j = 0; j <= COLS - 1; j += 2) {
matrix[i][j].val = -1;
omatrix[i][j].val = -1;
}
}

Expand Down Expand Up @@ -333,6 +340,7 @@ int main(int argc, char *argv[]) {
int changes = 0;
char *msg = "";
char *tty = NULL;
NCURSES_ATTR_T oattr = 0;

srand((unsigned) time(NULL));
setlocale(LC_ALL, "");
Expand Down Expand Up @@ -754,24 +762,54 @@ if (console) {
}
}
}
/* A simple hack */
if (!oldstyle) {
y = 1;
z = LINES;
} else {
y = 0;
z = LINES - 1;
}
for (i = y; i <= z; i++) {
move(i - y, j);
}

/* A simple hack */
if (!oldstyle) {
y = 1;
z = LINES;
} else {
y = 0;
z = LINES - 1;
}

// Update horizontally so that we can omit a move() if the last
// insertion already advanced the cursor to there.

int ox = -1, oy = -1;
for (i = y; i <= z; i++) {
for (j = 0; j <= COLS - 1; j += 2) {

if (omatrix[i][j].val == matrix[i][j].val &&
omatrix[i][j].is_head == matrix[i][j].is_head) {
continue;
}

omatrix[i][j] = matrix[i][j];

// Move to the next column using a space instead of "\e[24;80H"
if (ox == j - 1 && oy == i - y) {
addch(' ');
} else {
move(i - y, j);
}

ox = j + 1;
oy = i - y;

NCURSES_ATTR_T attr = 0;

if (matrix[i][j].val == 0 || (matrix[i][j].is_head && !rainbow)) {
if (console || xwindow) {
attron(A_ALTCHARSET);
attr |= A_ALTCHARSET;
}
attron(COLOR_PAIR(COLOR_WHITE));
attr |= COLOR_PAIR(COLOR_WHITE);
if (bold) {
attron(A_BOLD);
attr |= A_BOLD;
}
if (attr != oattr) {
attrset(attr);
oattr = attr;
}
if (matrix[i][j].val == 0) {
if (console || xwindow) {
Expand All @@ -785,13 +823,6 @@ if (console) {
addch(matrix[i][j].val);
}

attroff(COLOR_PAIR(COLOR_WHITE));
if (bold) {
attroff(A_BOLD);
}
if (console || xwindow) {
attroff(A_ALTCHARSET);
}
} else {
if (rainbow) {
int randomColor = rand() % 6;
Expand All @@ -817,27 +848,36 @@ if (console) {
break;
}
}
attron(COLOR_PAIR(mcolor));
attr |= COLOR_PAIR(mcolor);
if (matrix[i][j].val == 1) {
if (bold) {
attron(A_BOLD);
attr |= A_BOLD;
}
addch('|');
if (bold) {
attroff(A_BOLD);
attr |= A_BOLD;
}
} else {
if (console || xwindow) {
attron(A_ALTCHARSET);
attr |= A_ALTCHARSET;
}
if (bold == 2 ||
(bold == 1 && matrix[i][j].val % 2 == 0)) {
attron(A_BOLD);
attr |= A_BOLD;
}
if (attr != oattr) {
attrset(attr);
oattr = attr;
}
if (matrix[i][j].val == -1) {
addch(' ');
} else if (lambda && matrix[i][j].val != ' ') {
addstr("λ");
} else if (matrix[i][j].val < 0xFF) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be < 0x7f instead? That's where UTF-8 goes multibyte. I think this will mis-display characters in the Latin-1 block.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are 32 bit Unicode characters, not multi-byte UTF-8 sequences.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"These" are indeed wchar_t but addch says vaguely it expects a "character" (but takes a single byte) and so it's not clear to me whether we can write ¶ the pilcrow or similar which are outside ASCII though fit in a single byte. If the terminal speaks UTF-8 (as a modern terminal probably does) then there needs to be 2 bytes emitted by the curses implementation to make that symbol.

I tried to see what happens here and discovered that I'm sufficiently rusty that I wasn't able to write a working test (the painkillers and/or broken left hand may not have helped but eh) but if it does work to emit addch a value like 0xB4 on an UTF-8 terminal that probably deserves a comment.

// If it's not a unichar, write it the easy way.
// Valgrind tells me that addwstr is doing an
// invalid read on Rasperry Pi + Debian 12.
addch(matrix[i][j].val);
} else {
/* addch doesn't seem to work with unicode
* characters and there was no direct equivalent.
Expand All @@ -849,15 +889,7 @@ if (console) {
char_array[1] = 0;
addwstr(char_array);
}
if (bold == 2 ||
(bold == 1 && matrix[i][j].val % 2 == 0)) {
attroff(A_BOLD);
}
if (console || xwindow) {
attroff(A_ALTCHARSET);
}
}
attroff(COLOR_PAIR(mcolor));
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,13 @@ then
AC_CHECK_LIB(tinfo, tgetent, CURSES_LIB="-ltinfo" CURSES_LIB_NAME=tinfo)
fi

dnl If this is ncurses, waddnwstr might be in ncursesw instead.
if eval "test x$CURSES_LIB_NAME = xncurses"
then
AC_CHECK_LIB(ncurses, waddnwstr, [],
AC_CHECK_LIB(ncursesw, waddnwstr, CURSES_LIB="$CURSES_LIB -lncursesw"))
fi

if eval "test x$CURSES_LIB_NAME = x"
then
AC_MSG_WARN([
Expand Down