aboutsummaryrefslogblamecommitdiffstats
path: root/libterm/term.c
blob: 81d967e26fb694ab8d2d7e9d89b7bdea88c7896d (plain) (tree)








































































































































































































































































































































































                                                                                
#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 );
}