/* parc * Copyright (C) 2025 Ekaitz Zarraga * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * XTERM escape sequence reference: * https://invisible-island.net/xterm/ctlseqs/ctlseqs.html * Good summary: * https://en.wikipedia.org/wiki/ANSI_escape_code * * also: * man console_codes */ #include #include #include #include #include "tui-internals.h" #define ESC '\x1b' const char CSI_LEAD[3] = { ESC, '[', '\0'}; void tui_cursor_save (void) { printf ("%ss", CSI_LEAD); fflush (stdout); } void tui_cursor_restore (void) { printf ("%su", CSI_LEAD); fflush (stdout); } void tui_mouse_enable (void) { printf ("%s?1000h", CSI_LEAD); fflush (stdout); } void tui_mouse_disable (void) { printf ("%s?1000l", CSI_LEAD); fflush (stdout); } void tui_cursor_move (int x, int y) { /* * Also valid with CSI;f being and line number and column * number respectively. In ttys, cursor starts at 1,1 */ printf ("%s%d;%dH", CSI_LEAD, y, x); fflush (stdout); } void tui_cursor_show (void) { printf ("%s?25h", CSI_LEAD); fflush (stdout); } void tui_cursor_hide (void) { printf ("%s?25l", CSI_LEAD); fflush (stdout); } void tui_screen_erase (void) { printf ("%s2J", CSI_LEAD); fflush (stdout); } void tui_alternate_buffer_enable (void) { printf ("%s?1049h", CSI_LEAD); fflush (stdout); } void tui_alternate_buffer_disable (void) { printf ("%s?1049l", CSI_LEAD); fflush (stdout); } tui * tui_create (void) { tui *ui = malloc (sizeof *ui); /* Get interface configuration to reset it later */ tcgetattr (0, &ui->term_old_config); /* Get interface configuration to edit */ tcgetattr (0, &ui->term_config); /* Set the new configuration */ ui->term_config.c_lflag &= ~ (ECHO | ECHONL | ICANON | IEXTEN | ISIG); ui->term_config.c_cc[VMIN] = 1; /* Wait until 1 character is in buffer */ ui->term_config.c_cc[VTIME] = 0; /* Wait indefinitely */ /* TCSANOW makes the change occur immediately */ tcsetattr (0, TCSANOW, &ui->term_config); tui_alternate_buffer_enable (); tui_cursor_move (0, 0); tui_mouse_enable (); return ui; } void tui_destroy (tui *ui) { /* Set old configuration again and exit. */ /* If it's not set back the normal configuration of the */ /* terminal will be broken later! */ tcsetattr (0, TCSANOW, &ui->term_old_config); tui_alternate_buffer_disable (); free (ui); } void tui_input_sequence_consume (void) { int c, x, y; c = getchar (); if (ESC == c) { /* TODO: parse escape sequence */ c = getchar (); if (c == '[') { c = getchar (); switch (c) { case 'M': /*https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Normal-tracking-mode*/ /* They add 32 to the coordinates */ c = getchar () - 32; x = getchar () - 32; y = getchar () - 32; printf ("%d, %d, %d\n", c, x, y); break; case 'I': /* Gained focus */ break; case 'O': /* Lost focus */ break; default: break; } } } else ; /* return key event */ } void tui_loop (tui *ui) { char input_buf [100]; memset (input_buf, 0, 100); while (1) { tui_input_sequence_consume (); } }