I am trying to write a simple text editor in C++.
One of the features that I am trying to implement is dynamic resizing of the text when the window size changes. To do this, I am using a signal handler for SIGWINCH with sigaction which updates the number of rows and columns of a global config object as follows
void registerHandler() {
struct sigaction resize;
memset(&resize, '\0', sizeof(resize));
resize.sa_handler = handleWINCH;
sigaction(SIGWINCH, &resize, NULL);
}
void getTerminalSize() {
winsize w;
ioctl(STDIN_FILENO, TIOCGWINSZ, &w);
config.nCols = w.ws_col;
config.nRows = w.ws_row;
}
void handleWINCH(int) {
getTerminalSize();
draw();
}
Right now, I am just displaying the number of columns stored in a global config object using the draw method, as such
void draw() {
std::cout << ERASESCREEN << HOME << std::flush;
std::cout << config.nRows;
}
The problem is that this code acts very unreliably. Sometimes it works and sometimes it crashes prematurely and outputs a "%" character for seemingly no reason.
The terminal is in raw mode, enabled with cfmakeraw
void enableRawMode() {
tcgetattr(STDIN_FILENO, &config.initalConfig);
atexit(disableRawMode);
termios raw = config.initalConfig;
cfmakeraw(&raw);
tcsetattr(STDERR_FILENO, TCSAFLUSH, &raw);
}
HOME and ERASESCREEN are ANSI escape sequences to reset the cursor and clear the screen, defined as follows
#define ERASESCREEN "\x1b[2J"
#define HOME "\x1b[H"
Lastly, I enabled the std::unitbuf to hopefully mitigate any issues caused from the output buffering of cout.
std::cout << std::unitbuf << HOME << ERASESCREEN <<std::flush;
Furthermore, I've noticed that this issue with outputting and signal handling only happens in raw mode. Otherwise, the program seems to respond to the WINCH signal normally. I suspect there might be an issue with the output stream, which is why I keep trying to flush manually, but I don't know C++ and UNIX programming well enough to be able to guess any further.
I've uploaded the full code as well in case I did not include something important.
Thanks in advance!