/*********************************************************************** * ftermios.cpp - Provides access to POSIX tty I/O control * * * * This file is part of the FINAL CUT widget toolkit * * * * Copyright 2018-2020 Markus Gans * * * * FINAL CUT is free software; you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation; either version 3 of * * the License, or (at your option) any later version. * * * * FINAL CUT 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 Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this program. If not, see * * . * ***********************************************************************/ #if defined(__CYGWIN__) #undef __STRICT_ANSI__ // need for fileno #endif #include #include #include "final/ftermios.h" #include "final/fterm.h" namespace finalcut { // static class attributes int FTermios::stdin_no; int FTermios::stdout_no; int FTermios::stderr_no; bool FTermios::raw_mode; termios FTermios::term_init; //---------------------------------------------------------------------- // class FTermios //---------------------------------------------------------------------- // constructors and destructor //---------------------------------------------------------------------- FTermios::FTermios() { init(); } //---------------------------------------------------------------------- FTermios::~FTermios() // destructor { } // public methods of FTermios //---------------------------------------------------------------------- void FTermios::init() { // Assertion: programm start in cooked mode raw_mode = false; // Get file descriptor for standard input and standard output stdin_no = fileno(stdin); stdout_no = fileno(stdout); stderr_no = fileno(stderr); } //---------------------------------------------------------------------- termios FTermios::getTTY() { struct termios t{}; if ( tcgetattr(stdin_no, &t) == -1 ) throw std::system_error(errno, std::generic_category()); return t; } //---------------------------------------------------------------------- void FTermios::setTTY (const termios& t) { tcsetattr (stdin_no, TCSADRAIN, &t); } //---------------------------------------------------------------------- void FTermios::storeTTYsettings() { // Store termios settings try { term_init = getTTY(); } catch (const std::system_error&) { throw std::current_exception(); } } //---------------------------------------------------------------------- void FTermios::restoreTTYsettings() { // Restore termios settings setTTY (term_init); } //---------------------------------------------------------------------- void FTermios::setHardwareEcho() { // Info under: man 3 termios struct termios t{}; tcgetattr (stdin_no, &t); // local mode t.c_lflag &= uInt(ECHO | ECHONL); // input mode t.c_iflag &= uInt(ICRNL | INLCR | IGNCR); // output mode t.c_oflag &= uInt(ONLCR); // set the new termios settings setTTY (t); } //---------------------------------------------------------------------- void FTermios::unsetHardwareEcho() { // Info under: man 3 termios struct termios t{}; tcgetattr (stdin_no, &t); // local mode t.c_lflag &= uInt(~(ECHO | ECHONL)); // input mode t.c_iflag &= uInt(~(ICRNL | INLCR | IGNCR)); // output mode t.c_oflag &= uInt(~ONLCR); // set the new termios settings setTTY (t); } //---------------------------------------------------------------------- void FTermios::setCaptureSendCharacters() { struct termios t{}; tcgetattr (stdin_no, &t); t.c_lflag &= uInt(~(ICANON | ECHO)); t.c_cc[VTIME] = 1; // Timeout in deciseconds t.c_cc[VMIN] = 0; // Minimum number of characters tcsetattr (stdin_no, TCSANOW, &t); } //---------------------------------------------------------------------- void FTermios::unsetCaptureSendCharacters() { struct termios t{}; tcgetattr (stdin_no, &t); t.c_lflag |= uInt(ICANON | ECHO); t.c_cc[VTIME] = 0; // Timeout in deciseconds t.c_cc[VMIN] = 1; // Minimum number of characters setTTY (t); } //---------------------------------------------------------------------- bool FTermios::setRawMode (bool enable) { // set + unset flags for raw mode if ( raw_mode == enable ) return raw_mode; // Info under: man 3 termios struct termios t{}; tcgetattr (stdin_no, &t); if ( enable ) { // local mode #if DEBUG // Exit with ctrl-c only if compiled with "DEBUG" option t.c_lflag &= uInt(~(ICANON | IEXTEN)); #else t.c_lflag &= uInt(~(ICANON | ISIG | IEXTEN)); #endif // input mode t.c_iflag &= uInt(~(IXON | BRKINT | PARMRK)); // defines the terminal special characters for noncanonical read t.c_cc[VTIME] = 0; // Timeout in deciseconds t.c_cc[VMIN] = 1; // Minimum number of characters // set the new termios settings setTTY (t); raw_mode = true; } else { // local mode t.c_lflag |= uInt(ISIG | ICANON | (term_init.c_lflag & IEXTEN)); // input mode t.c_iflag |= uInt(IXON | BRKINT | PARMRK); // set the new termios settings setTTY (t); raw_mode = false; } return raw_mode; } //---------------------------------------------------------------------- uInt FTermios::getBaudRate() { std::unordered_map outspeed; outspeed[B0] = 0; // hang up outspeed[B50] = 50; // 50 baud outspeed[B75] = 75; // 75 baud outspeed[B110] = 110; // 110 baud outspeed[B134] = 134; // 134.5 baud outspeed[B150] = 150; // 150 baud outspeed[B200] = 200; // 200 baud outspeed[B300] = 300; // 300 baud outspeed[B600] = 600; // 600 baud outspeed[B1200] = 1200; // 1,200 baud outspeed[B1800] = 1800; // 1,800 baud outspeed[B2400] = 2400; // 2,400 baud outspeed[B4800] = 4800; // 4,800 baud outspeed[B9600] = 9600; // 9,600 baud outspeed[B19200] = 19200; // 19,200 baud outspeed[B38400] = 38400; // 38,400 baud outspeed[B57600] = 57600; // 57,600 baud outspeed[B115200] = 115200; // 115,200 baud outspeed[B230400] = 230400; // 230,400 baud if ( outspeed.find(cfgetospeed(&term_init)) != outspeed.end() ) return outspeed[cfgetospeed(&term_init)]; return 0; } } // namespace finalcut