|
// Written by retoor@molodetz.nl
|
|
|
|
// This code implements terminal manipulation functions including getting terminal size, setting raw mode, handling cursor position, and
|
|
// capturing keyboard input. It allows navigation using arrow keys and displays typed characters on the screen, exiting on 'q' key press.
|
|
|
|
// External libraries used: <sys/ioctl.h> for interacting with terminal interfaces.
|
|
|
|
// The MIT License (MIT)
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
|
|
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
|
|
// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
|
|
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/ioctl.h>
|
|
#include <termios.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
void rget_terminal_size(int *x, int *y) {
|
|
struct winsize w;
|
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
|
int terminal_width = w.ws_col;
|
|
*x = w.ws_col;
|
|
*y = w.ws_row;
|
|
}
|
|
|
|
struct termios rorig_termios;
|
|
|
|
void reset_terminal_mode() { tcsetattr(STDIN_FILENO, TCSANOW, &rorig_termios); }
|
|
|
|
void set_raw_mode() {
|
|
struct termios new_termios;
|
|
tcgetattr(STDIN_FILENO, &rorig_termios);
|
|
atexit(reset_terminal_mode);
|
|
new_termios = rorig_termios;
|
|
new_termios.c_lflag &= ~(ICANON | ECHO);
|
|
new_termios.c_cc[VMIN] = 1;
|
|
new_termios.c_cc[VTIME] = 0;
|
|
tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);
|
|
}
|
|
|
|
unsigned int read_key() {
|
|
int nread;
|
|
char c;
|
|
if ((nread = read(STDIN_FILENO, &c, 1)) == -1)
|
|
return -1;
|
|
return c;
|
|
}
|
|
|
|
void rrclear() { printf("\033[2J"); }
|
|
|
|
void rset_cursor_position(int x, int y) { printf("\033[%d;%dH", y, x); }
|
|
|
|
void get_cursor_position(int *cols, int *rows) {
|
|
char buf[32];
|
|
unsigned int i = 0;
|
|
printf("\033[6n");
|
|
while (i < sizeof(buf) - 1) {
|
|
if (read(STDIN_FILENO, buf + i, 1) != 1)
|
|
break;
|
|
if (buf[i] == 'R')
|
|
break;
|
|
i++;
|
|
}
|
|
buf[i] = '\0';
|
|
if (buf[0] == '\033' && buf[1] == '[') {
|
|
sscanf(buf + 2, "%d;%d", rows, cols);
|
|
}
|
|
}
|
|
|
|
void run() {
|
|
int c;
|
|
int x = 3;
|
|
int y = 3;
|
|
int file_index = 0;
|
|
set_raw_mode();
|
|
printf("\033[2J");
|
|
rset_cursor_position(x, y);
|
|
char screen_data[1024];
|
|
|
|
int width, height;
|
|
rget_terminal_size(&width, &height);
|
|
|
|
memset(&screen_data, 0, 2048);
|
|
|
|
while (1) {
|
|
c = read_key();
|
|
if (c == '\033') {
|
|
if (read_key() == '[') {
|
|
rrclear();
|
|
c = read_key();
|
|
if (c == 'A' && y) {
|
|
y--;
|
|
rset_cursor_position(x, y);
|
|
} else if (c == 'B' && y) {
|
|
y++;
|
|
rset_cursor_position(x, y);
|
|
} else if (c == 'C') {
|
|
x++;
|
|
rset_cursor_position(x, y);
|
|
} else if (c == 'D') {
|
|
x--;
|
|
rset_cursor_position(x, y);
|
|
}
|
|
printf(screen_data);
|
|
}
|
|
} else if (c == 'q') {
|
|
break;
|
|
} else {
|
|
for (int i = 0; i < file_index; i++) {
|
|
if (screen_data[i] == '\0') {
|
|
screen_data[i] = ' ';
|
|
}
|
|
}
|
|
screen_data[file_index] = c;
|
|
get_cursor_position(&x, &y);
|
|
file_index = x * y;
|
|
x++;
|
|
rset_cursor_position(1, 1);
|
|
printf(screen_data);
|
|
rset_cursor_position(x, y);
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
}
|
|
|
|
int main() { run(); } |