// ---------------------------------------------------------------------------
// - ctrm.cxx -
// - standard system library : c terminal function implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - 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. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "csio.hpp"
#include "cstr.hpp"
#include "ccnv.hpp"
#include "ctrm.hpp"
#include "ctrm.hxx"
#ifdef AFNIX_HAVE_NONCONST_TIGET
namespace afnix {
// get capability flag
static bool c_tigetflag (const char* capname) {
char* buf = const_cast <char*> (capname);
int val = tigetflag (buf);
return (val <= 0) ? false : true;
}
// get capability string
static char* c_tigetstr (const char* capname) {
char* buf = const_cast <char*> (capname);
char* ptr = tigetstr (buf);
return (ptr == (char*)-1) ? nilp : ptr;
}
}
#else
namespace afnix {
// get capability flag
static bool c_tigetflag (const char* capname) {
int val = tigetflag (capname);
return (val <= 0) ? false : true;
}
// get capability string
static char* c_tigetstr (const char* capname) {
char* ptr = tigetstr (capname);
return (ptr == (char*)-1) ? nilp : ptr;
}
}
#endif
#ifdef AFNIX_HAVE_COMPLEX_TPARM
namespace afnix {
static char* c_tparm_0 (char* data) {
return tparm (data,0,0,0,0,0,0,0,0,0);
}
static char* c_tparm_1 (char* data, long p0) {
return tparm (data,p0,0,0,0,0,0,0,0,0);
}
}
#else
namespace afnix {
static char* c_tparm_0 (char* data) {
return tparm (data);
}
static char* c_tparm_1 (char* data, long p0) {
return tparm (data, p0);
}
}
#endif
#ifdef AFNIX_DELETE_ISBS
namespace afnix {
// change the backspace setting
static void set_delete_isbs (char** tinfo) {
tinfo[ITERM_BACKSPACE] = c_strmak (delc);
}
}
#else
namespace afnix {
// change the backspace setting
static void set_delete_isbs (char** tinfo) {
if (tinfo[ITERM_BACKSPACE] == nilp)
tinfo[ITERM_BACKSPACE] = c_strmak (bspc);
}
}
#endif
namespace afnix {
// check if the stream id is a terminal
bool c_istty (const int sid) {
return (isatty (sid) == 1) ? true : false;
}
// get the terminal attributes
void* c_gtattr (const int sid) {
struct termios* tattr = new struct termios;
// check for terminal first
if (c_istty (sid) == false) return nilp;
// get the terminal attributes
if (tcgetattr (sid, tattr) != 0) return nilp;
return tattr;
}
// set the terminal attributes
void c_stattr (const int sid, void* tattr) {
// check for structure and tty
if (tattr == nilp) return;
if (c_istty (sid) == false) return;
// set terminal attributes
tcsetattr (sid, TCSANOW, (struct termios*) tattr);
}
// reset terminal mode - put in non canonical mode
bool c_stcanon (const int sid) {
// check for terminal first
if (c_istty (sid) == false) return false;
// reset canonical mode and echo
struct termios tattr;
tcgetattr (STDIN_FILENO, &tattr);
tattr.c_lflag &= ~(ICANON|ECHO);
tattr.c_cc[VMIN] = 1;
tattr.c_cc[VTIME] = 0;
if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr) != 0) return false;
return true;
}
// this function checks if a string is bounded in the tinfo array
static bool check_tinfo (char** tinfo, long size, const char* name) {
for (long i = 0; i < size; i++)
if (c_strcmp (tinfo[i], name) == true) return true;
return false;
}
// these functions fix some inconsistencies in the terminfo/termcap world
// this is only coming from various experiments
static char** fix_tinfo_input (char** tinfo) {
// fix delete character
set_delete_isbs (tinfo);
// fix arrows and delete
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_ARROW_UP) == false)
tinfo[ITERM_STD_UP] = c_strdup (XTERM_ARROW_UP);
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_ARROW_DOWN) == false)
tinfo[ITERM_STD_DOWN] = c_strdup (XTERM_ARROW_DOWN);
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_ARROW_RIGHT) == false)
tinfo[ITERM_STD_RIGHT] = c_strdup (XTERM_ARROW_RIGHT);
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_ARROW_LEFT) == false)
tinfo[ITERM_STD_LEFT ] = c_strdup (XTERM_ARROW_LEFT);
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_DELETE_KEY) == false)
tinfo[ITERM_STD_DELETE] = c_strdup (XTERM_DELETE_KEY);
if (check_tinfo (tinfo, ITERM_PARMS_MAX, XTERM_INSERT_KEY) == false)
tinfo[ITERM_STD_INSERT] = c_strdup (XTERM_INSERT_KEY);
// and hopefully, it is working
return tinfo;
}
static char** fix_tinfo_output (char** tinfo) {
// check for cub1 - if not set we use arrow left
if (c_strlen (tinfo[OTERM_MOVE_LEFT]) == 0)
tinfo[OTERM_MOVE_LEFT] = c_strdup (XTERM_ARROW_LEFT);
// check for cuf1 - if not set we use the standard right arrow
if (c_strlen (tinfo[OTERM_MOVE_RIGHT]) == 0)
tinfo[OTERM_MOVE_RIGHT] = c_strdup (XTERM_ARROW_RIGHT);
// check for cuu1 - if not set we use the standard up arrow
if (c_strlen (tinfo[OTERM_MOVE_UP]) == 0)
tinfo[OTERM_MOVE_UP] = c_strdup (XTERM_ARROW_UP);
// check for cud1 - if not set we use the standard up arrow
if (c_strlen (tinfo[OTERM_MOVE_DOWN]) == 0)
tinfo[OTERM_MOVE_DOWN] = c_strdup (XTERM_ARROW_DOWN);
// check that we can fix background colors
if (c_strlen (tinfo[OTERM_RESET_COLOR]) == 0) {
delete [] tinfo[OTERM_SETFG_MODE];
delete [] tinfo[OTERM_RESET_COLOR];
tinfo[OTERM_SETFG_MODE] = nilp;
tinfo[OTERM_RESET_COLOR] = nilp;
}
// hopefully, we are set
return tinfo;
}
// return an array of terminal capabilities
char** c_tinfo (bool imode) {
int status = 0;
// read terminfo database
if (setupterm (getenv ("TERM"),STDOUT_FILENO,&status) != OK) return nilp;
// create an array of capabilities and initialize it
long len = imode ? ITERM_PARMS_MAX : OTERM_PARMS_MAX;
char** result = new char*[len];
for (long i = 0; i < len; i++) result[i] = nilp;
// query input capabilities
if (imode == true) {
result[ITERM_BACKSPACE] = c_strdup (c_tigetstr ("kbs"));
result[ITERM_DELETE] = c_strdup (c_tigetstr ("kdch1"));
result[ITERM_ARROW_UP] = c_strdup (c_tigetstr ("kcuu1"));
result[ITERM_ARROW_DOWN] = c_strdup (c_tigetstr ("kcud1"));
result[ITERM_ARROW_LEFT] = c_strdup (c_tigetstr ("kcub1"));
result[ITERM_ARROW_RIGHT] = c_strdup (c_tigetstr ("kcuf1"));
result[ITERM_INSERT_KEY] = c_strdup (c_tigetstr ("kich1"));
result[ITERM_STD_UP] = nilp;
result[ITERM_STD_DOWN] = nilp;
result[ITERM_STD_RIGHT] = nilp;
result[ITERM_STD_LEFT] = nilp;
result[ITERM_STD_DELETE] = nilp;
result[ITERM_STD_INSERT] = nilp;
} else {
result[OTERM_DELETE_CHAR] = c_strdup (c_tigetstr ("dch1"));
result[OTERM_MOVE_LEFT] = c_strdup (c_tigetstr ("cub1"));
result[OTERM_MOVE_RIGHT] = c_strdup (c_tigetstr ("cuf1"));
result[OTERM_MOVE_UP] = c_strdup (c_tigetstr ("cuu1"));
result[OTERM_MOVE_DOWN] = c_strdup (c_tigetstr ("cud1"));
result[OTERM_MOVE_BOL] = c_strdup (c_tigetstr ("cr"));
result[OTERM_INSERT_CHAR] = c_strdup (c_tigetstr ("ich1"));
result[OTERM_IMODE_START] = c_strdup (c_tigetstr ("smir"));
result[OTERM_IMODE_END] = c_strdup (c_tigetstr ("rmir"));
result[OTERM_SETFG_MODE] = c_strdup (c_tigetstr ("setaf"));
result[OTERM_RESET_COLOR] = c_strdup (c_tigetstr ("oc"));
result[OTERM_CLEAR_SCREEN] = c_strdup (c_tigetstr ("clear"));
// local fix for color
if (c_strlen (result[OTERM_RESET_COLOR]) == 0)
result[OTERM_RESET_COLOR] = c_strdup (c_tigetstr ("op"));
}
// here is our array
return imode ? fix_tinfo_input (result) : fix_tinfo_output (result);
}
// return an array of terminal capabilities flag
bool* c_tbool (void) {
int status = 0;
// read terminfo database
if (setupterm (getenv ("TERM"),STDOUT_FILENO,&status) != OK) return nilp;
// create an array of capabilities and initialize it
bool* result = new bool [BTERM_PARMS_MAX];
// query capabilities
result[BTERM_AUTO_WRAP] = c_tigetflag ("am") && c_tigetflag ("xn");
// the array of capabilities
return result;
}
// return true if a parameter is valid
bool c_tpvld (char** tinfo, const long index, const bool mode) {
// check terminal info and index
if ((tinfo == nilp) || (index < 0)) return false;
// check bound based on mode
if ((mode == true) && (index >= OTERM_PARMS_MAX)) return false;
if ((mode == false) && (index >= ITERM_PARMS_MAX)) return false;
// check parameter
if (c_strlen (tinfo[index]) == 0) return false;
return true;
}
// send a character to the standard output
void c_tparm (const int sid, char** tinfo, const long index) {
if ((tinfo == nilp) || (index < 0) || (index >= OTERM_PARMS_MAX)) return;
char* data = tinfo[index];
if (data == nilp) return;
char* buffer = c_tparm_0 (data);
long length = c_strlen (buffer);
c_write (sid,buffer,length);
}
// turn on/off the terminal error mode
void c_temode (const int sid, char** tinfo, const bool mode) {
if (tinfo == nilp) return;
char* setaf = tinfo[OTERM_SETFG_MODE];
char* rstaf = tinfo[OTERM_RESET_COLOR];
if ((setaf == nilp) || (rstaf == nilp)) return;
char* buffer = mode ? c_tparm_1 (setaf,1) : c_tparm_0 (rstaf);
long length = c_strlen (buffer);
c_write (sid,buffer,length);
}
}
#ifdef AFNIX_HAVE_WINSIZE
namespace afnix {
// get the number of columns for a tty
long c_getcols (const int sid) {
// try ioctl first
if (c_istty (sid) == true) {
struct winsize size;
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &size) == 0) {
long cols = (long) size.ws_col;
if (cols != 0) return cols;
}
}
// may be the environment will help us !!!
bool status = true;
long cols = c_atoll (getenv ("COLUMNS"), status);
if ((status == true) && (cols != 0)) return cols;
// nothing match so we return 0
return 0;
}
}
#endif
#ifdef AFNIX_HAVE_DELTERM
namespace afnix {
// free the terminal attributes structure
void c_ftattr (void* ptr) {
struct termios* tattr = (struct termios*) ptr;
delete tattr;
del_curterm (cur_term);
}
}
#else
namespace afnix {
// free the terminal attributes structure
void c_ftattr (void* ptr) {
struct termios* tattr = (struct termios*) ptr;
delete tattr;
}
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1