2021-08-07 01:14:17 +02:00
|
|
|
//=-------------------------------------------------------------------------=//
|
|
|
|
// Terminal management tools //
|
|
|
|
// //
|
2021-10-13 09:44:00 +02:00
|
|
|
// Copyright © 2021 Libre en Communs (contact@a-lec.org) //
|
|
|
|
// Copyright © 2021 Adrien Bourmault (neox@a-lec.org) //
|
2021-08-07 01:14:17 +02:00
|
|
|
// //
|
|
|
|
// 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 <https://www.gnu.org/licenses/>. //
|
|
|
|
//=-------------------------------------------------------------------------=//
|
|
|
|
|
2021-09-15 18:25:35 +02:00
|
|
|
#pragma once
|
2021-08-07 01:14:17 +02:00
|
|
|
#ifndef BASE_H
|
|
|
|
#include "../include/base.h"
|
|
|
|
#endif
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
2021-08-07 01:14:17 +02:00
|
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
|
2024-03-10 21:19:12 +01:00
|
|
|
volatile struct winsize termWinSize;
|
2021-09-02 16:54:42 +02:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------------- */
|
2021-08-07 01:14:17 +02:00
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Get a character code from the keyboard //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline int term_getch(bool nonBlocking)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
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) {
|
2021-09-22 16:43:01 +02:00
|
|
|
printErr("%sError getting terminal settings! (%s)\n",
|
2021-08-07 01:14:17 +02:00
|
|
|
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) {
|
2021-09-22 16:43:01 +02:00
|
|
|
printErr("%sError setting terminal settings! (%s)\n",
|
2021-08-07 01:14:17 +02:00
|
|
|
C_COLOR_RED,
|
|
|
|
strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
buf = getchar();
|
|
|
|
if(buf < 0) {
|
|
|
|
// Check target busy (try again)
|
|
|
|
if(errno == EAGAIN)
|
|
|
|
return 0;
|
|
|
|
|
2021-09-22 16:43:01 +02:00
|
|
|
printErr("%sError reading character! (%s)\n",
|
2021-08-07 01:14:17 +02:00
|
|
|
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) {
|
2021-09-22 16:43:01 +02:00
|
|
|
printErr("%sError resetting terminal settings! (%s)\n",
|
2021-08-07 01:14:17 +02:00
|
|
|
C_COLOR_RED,
|
|
|
|
strerror(errno));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Reset blocking mode
|
|
|
|
if(nonBlocking)
|
|
|
|
fcntl(0, F_SETFL, 0);
|
|
|
|
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Get the screen size //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_get_screensize(int signum)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
// Get current terminal size
|
2024-03-10 21:19:12 +01:00
|
|
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &termWinSize);
|
2021-08-07 01:14:17 +02:00
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Set cursor location //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_set_cursor_location(char x, char y)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf("\x1b[%d;%dH", y, x);
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Save cursor location //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_save_cursor_location(void)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf(C_SAVE_CURSORPOS);
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Restore cursor location //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_restore_cursor_location(void)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf(C_RESTORE_CURSORPOS);
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Move cursor location to the right //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_move_cursor_forward(void)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf(C_CURSORRIGHT);
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Move cursor location to the left //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_move_cursor_backward(void)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf(C_CURSORLEFT);
|
|
|
|
}
|
|
|
|
|
2021-09-02 16:54:42 +02:00
|
|
|
// -------------------------------------------------------------------------- //
|
|
|
|
// Clear screen //
|
|
|
|
// -------------------------------------------------------------------------- //
|
2024-03-10 21:19:12 +01:00
|
|
|
static inline void term_clear_screen(void)
|
2021-08-07 01:14:17 +02:00
|
|
|
{
|
|
|
|
printf(C_CLEARSCREEN);
|
2024-03-10 21:19:12 +01:00
|
|
|
term_set_cursor_location(1,1);
|
2021-08-07 01:14:17 +02:00
|
|
|
fflush(stdout);
|
|
|
|
}
|
|
|
|
|