diff --git a/include/terminal.h b/include/terminal.h new file mode 100644 index 0000000..485591c --- /dev/null +++ b/include/terminal.h @@ -0,0 +1,173 @@ +//=-------------------------------------------------------------------------=// +// Terminal management tools // +// // +// Copyright © 2021 The Gem-graph Project // +// // +// This file is part of gem-graph. // +// // +// This program is free software: you can redistribute it and/or modify // +// it under the terms of the GNU Affero General Public License as // +// published by the Free Software Foundation, either version 3 of the // +// License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU Affero General Public License for more details. // +// // +// You should have received a copy of the GNU Affero General Public License // +// along with this program. If not, see . // +//=-------------------------------------------------------------------------=// + +#ifndef BASE_H + #include "../include/base.h" +#endif + +#include +#include +#include +#include + +#define C_CLEARSCREEN "\e[2J" +#define C_CLEARLINE "\e[2K" +#define C_CURSORLEFT "\e[1D" +#define C_CURSORRIGHT "\e[1C" +#define C_SAVE_CURSORPOS "\e7" +#define C_RESTORE_CURSORPOS "\e8" +#define C_COLOR_RED "\e[01;31m" +#define C_COLOR_YELLOW "\e[00;33m" +#define C_COLOR_GREEN "\e[00;32m" +#define C_COLOR_BLUE "\e[01;34m" +#define C_COLOR_REVERSE "\e[7m" +#define C_COLOR_NORMAL "\e[0m" +#define C_COLOR_BLACK_ON_GREEN "\e[30;42m" +#define C_COLOR_LIGHTWHITE_ON_GREEN "\e[47;42m" +#define C_COLOR_LIGHTWHITE_ON_GREY "\e[47;100m" +#define C_COLOR_BLACK_ON_LIGHTGREY "\e[30;102m" +#define C_COLOR_WHITE_ON_BLUE "\e[107;44m" + +#define NON_BLOCKING 1 + +volatile struct winsize terminalSize; + +// +// Get a character code from the keyboard +// +static inline int getch(bool nonBlocking) +{ + int buf = 0; + // old terminal + struct termios old = {0}; + + // force flush stdout + fflush(stdout); + + // Set non-blocking mode if asked + if(nonBlocking) + fcntl(0, F_SETFL, O_NONBLOCK); + + if(tcgetattr(0, &old) < 0) { + printLog("%sError getting terminal settings! (%s)\n", + C_COLOR_RED, + strerror(errno)); + return -1; + } + + old.c_lflag &= ~ICANON; // disable buffered I/O + old.c_lflag &= ~ECHO; // set no echo mode + + if(tcsetattr(0, TCSANOW, &old) < 0) { + printLog("%sError setting terminal settings! (%s)\n", + C_COLOR_RED, + strerror(errno)); + return -1; + } + + buf = getchar(); + if(buf < 0) { + // Check target busy (try again) + if(errno == EAGAIN) + return 0; + + printLog("%sError reading character! (%s)\n", + C_COLOR_RED, + strerror(errno)); + return -1; + } + + old.c_lflag |= ICANON; // enable buffered I/O + old.c_lflag |= ECHO; // set echo mode + + if(tcsetattr(0, TCSADRAIN, &old) < 0) { + printLog("%sError resetting terminal settings! (%s)\n", + C_COLOR_RED, + strerror(errno)); + return -1; + } + + // Reset blocking mode + if(nonBlocking) + fcntl(0, F_SETFL, 0); + + return buf; +} + +// +// Get the screen size +// +static inline void getScreenSize(int signum) +{ + // Get current terminal size + ioctl(STDOUT_FILENO, TIOCGWINSZ, &terminalSize); +} + +// +// Set cursor location +// +static inline void setCursorLocation(char x, char y) +{ + printf("\x1b[%d;%dH", y, x); +} + +// +// Save cursor location +// +static inline void saveCursorLocation(void) +{ + printf(C_SAVE_CURSORPOS); +} + +// +// Restore cursor location +// +static inline void restoreCursorLocation(void) +{ + printf(C_RESTORE_CURSORPOS); +} + +// +// Move cursor location to the right +// +static inline void moveCursorForward(void) +{ + printf(C_CURSORRIGHT); +} + +// +// Move cursor location to the left +// +static inline void moveCursorBackward(void) +{ + printf(C_CURSORLEFT); +} + +// +// Clear screen +// +static inline void clearScreen(void) +{ + printf(C_CLEARSCREEN); + setCursorLocation(1,1); + fflush(stdout); +} + diff --git a/src/cli.c b/src/cli.c index e9786e8..d3ebb32 100644 --- a/src/cli.c +++ b/src/cli.c @@ -85,36 +85,36 @@ void decorateMonitor(int signum) screenTitleText ); setCursorLocation(terminalSize.ws_col / 3 * 2, 2); - printf("%s%s (void)", + printf("%s%s", C_COLOR_NORMAL C_COLOR_BLACK_ON_GREEN, infosTitleText ); - setCursorLocation(terminalSize.ws_col / 3 * 2, 3); + setCursorLocation(terminalSize.ws_col / 3 * 2, 4); printf("%s%s%s (void)", C_COLOR_NORMAL C_COLOR_BLACK_ON_LIGHTGREY, infosNameText, C_COLOR_NORMAL ); - setCursorLocation(terminalSize.ws_col / 3 * 2, 4); + setCursorLocation(terminalSize.ws_col / 3 * 2, 6); printf("%s%s%s (void)", C_COLOR_BLACK_ON_GREEN, infosStatusText, C_COLOR_NORMAL ); - setCursorLocation(terminalSize.ws_col / 3 * 2, 5); + setCursorLocation(terminalSize.ws_col / 3 * 2, 8); printf("%s%s%s (void)", C_COLOR_BLACK_ON_LIGHTGREY, infosOwnerText, C_COLOR_NORMAL ); - setCursorLocation(terminalSize.ws_col / 3 * 2, 6); + setCursorLocation(terminalSize.ws_col / 3 * 2, 10); printf("%s%s%s (void)", C_COLOR_BLACK_ON_GREEN, infosSchedulerText, C_COLOR_NORMAL ); - setCursorLocation(terminalSize.ws_col / 3 * 2, 7); + setCursorLocation(terminalSize.ws_col / 3 * 2, 12); printf("%s%s%s (void)", C_COLOR_BLACK_ON_LIGHTGREY, infosScThreadsText, @@ -127,6 +127,13 @@ void decorateMonitor(int signum) printf(" "); } + setCursorLocation(1, terminalSize.ws_row); + printf(C_COLOR_NORMAL); + for (int i = 0; i < terminalSize.ws_col; i++) { + printf(" "); + } + + setCursorLocation(1, terminalSize.ws_row); printf("%sQ%s Quit\t%sS%s Start/Stop", C_COLOR_NORMAL C_COLOR_REVERSE, C_COLOR_NORMAL,