diff options
Diffstat (limited to 'libterm/term.c')
-rw-r--r-- | libterm/term.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/libterm/term.c b/libterm/term.c new file mode 100644 index 0000000..81d967e --- /dev/null +++ b/libterm/term.c @@ -0,0 +1,361 @@ +#include "term.h" + +#include "debug.h" + +#define T_ESC "\x1b" + +//setup initial terminal stuff +//this coulc act differently, becouse allways there is +//different terminal setting that should be default +int term_init( term_screen *term ) +{ + int ret=0; + + memset( term, 0, sizeof( term_screen )); + + if ( !isatty(STDIN_FILENO) ) + { + ERROR("isatty failed\n") + goto exit_error; + } + //!!!!!! + //register atexit + + term->ifd = STDIN_FILENO; + term->ofd = STDOUT_FILENO; + + //if you whant raw mode then you should set it man + if ( tcgetattr( term->ifd, &term->orig_i ) == -1 ) goto exit_error; + term->raw_i = term->orig_i; + if ( tcgetattr( term->ofd, &term->orig_o ) == -1 ) goto exit_error; + term->raw_o = term->orig_o; + + term->mode = SCREEN_MODE_80x25; + + return ret; + +exit_error: + errno = ENOTTY; + return -1; +} + +//set terminal speed return 0 if OK and 1 if not +//im trust to input arguments that they are ok +int term_set_speed( term_screen *ts, speed_t speed) +{ + int ret = cfsetospeed( &ts->raw_o, speed ); + ret = tcsetattr( ts->ofd, TCSANOW, &ts->raw_o ); + if ( ret != 0 ) + return 1; + + //if baudrate set to there then input speed same as + //output speed + cfsetispeed( &ts->raw_i, B0); + ret = tcsetattr( ts->ifd, TCSANOW, &ts->raw_i ); + if ( ret != 0 ) + return 1; + return 0; +} + +//get maximal number of columns setting up cursor to 999 column +//and getting on with place terminal have placed cursor and getting +//column on with terminal putted cursor +int term_get_maxcol( term_screen *ts ) +{ + int ret=-1; + int orig_c; + int cur_c; + + /* get initial cursor position */ + if ( (orig_c = term_cur_get_c( ts )) == -1 ) + goto exit_error; + + + /* go to right marging and get position */ + if ( write( ts->ofd, T_ESC "[999C", 6 ) != 6 ) + goto exit_error; + if ( (cur_c = term_cur_get_c( ts )) == -1 ) + goto exit_error; + ret = cur_c; + + /* restore position */ + { + char buf[32]; + snprintf( buf, 32, T_ESC "[" "%d" "D", cur_c-orig_c); + write( ts->ofd, buf, strlen(buf) ); + } + + return ret; + +exit_error: + return -1; + +} + +//try to setup far away line after that read position where +//terminal have putted cursor and read line of that postion +int term_get_maxrow( term_screen *ts ) +{ + int ret=-1; + int orig_r; + int cur_r; + + /* get initial cursor position */ + if ( (orig_r = term_cur_get_r( ts )) == -1 ) + goto exit_error; + + + /* go to right marging and get position */ + if ( write( ts->ofd, T_ESC "[999B", 6 ) != 6 ) + goto exit_error; + if ( (cur_r = term_cur_get_r( ts )) == -1 ) + goto exit_error; + ret = cur_r; + + /* restore position */ + { + char buf[32]; + snprintf( buf, 32, T_ESC "[" "%d" "A", cur_r-orig_r); + write( ts->ofd, buf, strlen(buf) ); + } + + return ret; + +exit_error: + return -1; +} + + + +int term_cur_get_c( term_screen *ts ) +{ + unsigned int i; + int row, col; + char buf[32]; + + if ( write( ts->ofd, "\x1b[6n", 4 ) != 4 ) goto exit_error; + + i = 0; + while (i < sizeof(buf)-1) + { + if ( read( ts->ifd, buf+i,1 ) != 1 ) break; + if (buf[i] == 'R') break; + i++; + } + buf[i] = '\0'; + + /* Parse terminal response */ + if ( buf[0] != '\x1b' || buf[1] != '[' ) goto exit_error; + if ( sscanf( buf+2, "%d;%d", &row, &col) != 2 ) goto exit_error; + + return col; +exit_error: + return -1; +} + + +int term_cur_get_r( term_screen *ts ) +{ + unsigned int i; + int row, col; + char buf[32]; + + if ( write( ts->ofd, "\x1b[6n", 4 ) != 4 ) goto exit_error; + + i = 0; + while (i < sizeof(buf)-1) + { + if ( read( ts->ifd, buf+i,1 ) != 1 ) break; + if (buf[i] == 'R') break; + i++; + } + buf[i] = '\0'; + + /* Parse terminal response */ + if ( buf[0] != '\x1b' || buf[1] != '[' ) goto exit_error; + if ( sscanf( buf+2, "%d;%d", &row, &col) != 2 ) goto exit_error; + + return row; +exit_error: + return -1; +} + +//set cursor column position +int term_cur_set_c( term_screen *ts, unsigned int pc ) +{ + int ret = 0; + int cur_r; + + /* go to right marging and get position */ + if ( (cur_r = term_cur_get_r( ts )) == -1 ) + goto exit_error; + /* set position */ + { + char buf[32]; + int l; + + snprintf( buf, 32, T_ESC "[%d;%dH", cur_r, pc); + l = strlen( buf ); + if ( write( ts->ofd, buf, l ) != l) + goto exit_error; + } + + return ret; + +exit_error: + return -1; +} + +//set cursor row/line position +int term_cur_set_r( term_screen *ts, unsigned int pr ) +{ + int ret = 0; + int cur_c; + + /* go to right marging and get position */ + if ( (cur_c = term_cur_get_c( ts )) == -1 ) + goto exit_error; + /* set position */ + { + char buf[32]; + int l; + + snprintf( buf, 32, T_ESC "[%d;%dH", pr, cur_c); + l = strlen( buf ); + if ( write( ts->ofd, buf, l ) != l) + goto exit_error; + } + + return ret; + +exit_error: + return -1; +} + +int term_cur_set_cr( term_screen *ts, unsigned int pc, unsigned int pr ) +{ + int ret = 0; + + /* set position */ + { + char buf[32]; + int l; + + snprintf( buf, 32, T_ESC "[%d;%dH", pr, pc); + l = strlen( buf ); + if ( write( ts->ofd, buf, l ) != l) + goto exit_error; + } + return ret; + +exit_error: + return -1; + +} + + +//clean terminal with escape command +int term_clr_scr( term_screen *ts ) +{ + int ret = 0; + + if ( write( ts->ofd, T_ESC "[H" T_ESC "[2J", 7 ) <= 0 ){}; + + return ret; +} + +//set terminal default input/output behavior +int term_set_raw_mode( term_screen *ts ) +{ + int ret = 0; + + if ( tcgetattr( ts->ifd, &ts->orig_i ) == -1 ) + { + ERROR("Cannot get input terminal attributes\n"); + goto exit_error; + } + + ts->raw_i = ts->orig_i; /* modify the original mode */ + /* input modes: no break, no CR to NL, no parity check, no strip char, + * no start/stop output control. */ + ts->raw_i.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); + /* output modes - disable post raw */ + ts->raw_i.c_oflag &= ~(OPOST); + /* control modes - set 8 bit chars */ + ts->raw_i.c_cflag |= (CS8); + /* local modes - choing off, canonical off, no extended functions, + * no signal chars (^Z,^C) */ + ts->raw_i.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG); + /* control chars - set return condition: min number of bytes and timer. + * We want read to return every single byte, without timeout. */ + ts->raw_i.c_cc[VMIN] = 1; + ts->raw_i.c_cc[VTIME] = 0; /* 1 byte, no timer */ + + /* put terminal in raw mode after flushing */ + if (tcsetattr( ts->ifd, TCSAFLUSH, &ts->raw_i) < 0) + { + ERROR("Cannot set new terminal input attribures\n"); + goto exit_error; + } + + return ret; + +exit_error: + errno = ENOTTY; + return -1; + +} + + +//if there is no mode with some rows/columns , then just show that no mode setet +// up and user should decide by his own what to do +int term_mode_rows( term_screen *ts ) +{ + int ret = -1; + + if ( ts == NULL) return -1; + + switch ( ts->mode ) + { + //--------------------- + case SCREEN_MODE_80x25: + ret = 25; + break; + //-------------------- + case SCREEN_MODE_NONE: + default: + ret = -1; + } + + return ret; +} + + +//if there is no mode with some rows/columns , then just show that no mode setet +// up and user should decide by his own what to do +int term_mode_columns( term_screen *ts ) +{ + int ret = -1; + + if ( ts == NULL) return -1; + + switch ( ts->mode ) + { + //--------------------- + case SCREEN_MODE_80x25: + ret = 80; + break; + //-------------------- + case SCREEN_MODE_NONE: + default: + ret = -1; + } + + return ret; +} + + +void term_set_orig_mode( term_screen *ts ) +{ + tcsetattr( ts->ifd, TCSAFLUSH, &ts->orig_i ); +}
\ No newline at end of file |