Newer
Older
/*
*********************************************************************************
*************************************** PUBLIC **********************************
*********************************************************************************
*/
/*!
** Screen constructor
*/
*cmd_buffer_ = 0;
cmd_buf_off_ = 0;
cmd_win_off_ = 0;
cmd_history_off_ = 0;
}
void Screen::init() {
// Init ncurses
initscr();
// register end stop ncurses before exit
atexit((void (*)(void)) endwin);
// Set good parameters
cbreak();
keypad(stdscr, TRUE);
// refresh parameters (needed by ncurses)
/*!
** Create windows clear the screen, destroy already existing windows,
** create windows with good size and draw it.
*/
// Check screen size
if (LINES < 6 || COLS < 3) {
std::cerr << "Screen is too small." << std::endl;
exit(ERR_SCREENSZ);
}
if ((size_t) LINES * 2 > O.history_size)
O.history_size = 2 * LINES;
noecho();
clear();
refresh();
// msg window
if (msg_)
delwin(msg_);
msg_ = newwin(LINES - 3, COLS, 0, 0);
msg_draw();
// cmd window
if (cmd_)
delwin(cmd_);
cmd_ = newwin(3, COLS, LINES - 3, 0);
cmd_draw();
}
/*!
** Swith into login window mode and
** manage the login/pass ask processus
*/
void Screen::login() {
char *buf;
int size;
const char *smsg;
clear();
box(stdscr, 0,0);
move(1, 1);
// ask login
if (O.login.empty()) {
smsg = "Login: ";
size = COLS - 2 - strlen(smsg);
buf = new char[size + 1];
echo();
printw(smsg);
refresh();
getnstr(buf, size);
buf[size] = 0;
O.login = buf;
delete [] buf;
move(2,1);
}
// ask password
smsg = "Password: ";
size = COLS - 2 - strlen(smsg);
buf = new char[size + 1];
printw(smsg);
noecho();
refresh();
getnstr(buf, size);
buf[size] = 0;
O.login = buf;
delete [] buf;
//nominal screen nom
create_windows();
/*!
** Wait keyboard events and act accordingly
*/
// --------------------------- KEY UP ------------------------------------
memcpy(cmd_history_buffer_, cmd_buffer_, MAX_LINE_SIZE);
strncpy(cmd_buffer_, H.get(cmd_history_off_++).c_str(), MAX_LINE_SIZE);
cmd_buf_off_ = strlen(cmd_buffer_);
// --------------------------- KEY DOWN ----------------------------------
case KEY_DOWN:
if (cmd_history_off_ == 0)
break;
--cmd_history_off_;
if (cmd_history_off_ == 0)
memcpy(cmd_buffer_, cmd_history_buffer_, MAX_LINE_SIZE);
strncpy(cmd_buffer_, H.get(cmd_history_off_ - 1).c_str(), MAX_LINE_SIZE);
cmd_buf_off_ = strlen(cmd_buffer_);
// --------------------------- KEY LEFT ----------------------------------
// --------------------------- KEY RIGHT ---------------------------------
if ((size_t) cmd_buf_off_ < strlen(cmd_buffer_))
++cmd_buf_off_;
// --------------------------- KEY HOME ----------------------------------
// --------------------------- KEY END -----------------------------------
case KEY_END:
cmd_buf_off_ = strlen(cmd_buffer_);
// --------------------------- KEY RETURN --------------------------------
// print to msg
msg_print(cmd_buffer_);
// print result
cmd_draw();
// --------------------------- KEY BACKSPACE------------------------------
if (del_char(cmd_buffer_, cmd_buf_off_ - 1, MAX_LINE_SIZE))
--cmd_buf_off_;
cmd_draw();
// --------------------------- KEY DELETE --------------------------------
del_char(cmd_buffer_, cmd_buf_off_, MAX_LINE_SIZE);
// --------------------------- KEY RESIZE --------------------------------
case KEY_RESIZE:
create_windows();
// --------------------------- KEY EOF -----------------------------------
// -------------------------ALL OTHERS KEYS ------------------------------
if (add_char(key, cmd_buffer_, cmd_buf_off_, MAX_LINE_SIZE))
/*!
** Print a message in msg window
**
** @param s message to print
*/
void Screen::msg_print(const string &s) {
msg_add(s);
msg_draw();
}
/*
*********************************************************************************
************************************** PRIVATE **********************************
*********************************************************************************
*/
/*!
** Draw the content of the cmd window
*/
// clean and redraw the cmd box
werase(cmd_);
box(cmd_, 0, 0);
wmove(cmd_, 1, 1);
if (cmd_buf_off_ + 1 > (size_t) COLS - 2 + cmd_win_off_)
cmd_win_off_ = cmd_buf_off_ + 1 - (COLS - 2) ;
else if (cmd_buf_off_ < cmd_win_off_)
cmd_win_off_ = cmd_buf_off_;
size_t minsize = (MAX_LINE_SIZE < COLS - 2) ? MAX_LINE_SIZE : COLS - 2;
strncpy(print_buf, cmd_buffer_ + cmd_win_off_, minsize);
print_buf[minsize - 1] = 0;
// print print buffer
wattron(cmd_, A_BOLD);
wprintw(cmd_, "%s", print_buf);
wattroff(cmd_, A_BOLD);
// move cursor to right pos
wmove(cmd_, 1, 1 + cmd_buf_off_ - cmd_win_off_);
/*!
** Draw the content of the msg window
*/
void Screen::msg_draw() {
werase(msg_);
box(msg_, 0, 0);
wrefresh(msg_);
}
** Add char @param c in a @param string buffer at offset @param offset.
** @param buf_len is the size of the buffer
*/
bool Screen::add_char(char c, char *string, ssize_t offset, size_t buf_len) {
// check if add one char is in range
if (len + 1 > buf_len - 1)
return false;
// check if offset is good
if (offset >= (ssize_t) buf_len - 1 || offset < 0)
// move one char every char
for (ssize_t i = len; i >= offset; --i)
string[i + 1] = string[i];
string[offset] = c;
/*!
** Del a char from @param string at offset @param offset.
** @param buf_len is the buffer size
**
** @return
*/
bool Screen::del_char(char *string, ssize_t offset, size_t buf_len) {
assert(string);
size_t len = strlen(string);
// check if del one char is possible
if (len == 0)
// check if offset is good
if (offset >= (ssize_t) buf_len - 1 || offset < 0)
// move one char every char
for (; string[offset] != 0; ++offset)
string[offset] = string[offset + 1];
void Screen::msg_add(const string &s) {
assert(strchr(s.c_str(), '\n') == 0);
if (s.empty())
return;
if (msg_table_.size() >= O.history_size)
msg_table_.resize(O.history_size);
msg_table_.push_front(s);
/*!
** Retrieve @param i th msg from msg list
** @return string corresponding to @param i in msg list
*/
const string &Screen::msg_get(size_t i) const {
assert(i < msg_table_.size());
t_lines::const_iterator it;
size_t pos;
static string empty;
for (pos = 0, it = msg_table_.begin();
it != msg_table_.end();
++pos, ++it)
if (pos == i)
return *it;
return empty;
/*!
** Compute the size of msg list
**
** @return count of message in msg list
*/
size_t Screen::msg_size() const {
return msg_table_.size();
}
/*!
** Load msg list from a file @param filename
*/
void Screen::msg_load(const string &filename) {
ifstream fs;
t_lines::const_iterator it;
char buf[MAX_LINE_SIZE];
fs.open(filename.c_str(), ifstream::in);
if (!fs.is_open())
return;
while (!fs.eof()) {
if (fs.fail())
throw Error(ERR_FILE, "Unable to load history");
fs.getline(buf, MAX_LINE_SIZE);
msg_add(buf);
}
fs.close();
}
/*!
** Save msg list to a file @param filename
*/
void Screen::msg_save(const string &filename) const {
ofstream fs;
t_lines::const_reverse_iterator rit;
fs.open(filename.c_str(), ostream::out | ostream::trunc);
if (!fs.is_open())
throw Error(ERR_FILE, "Unable to open history file");
for (rit = msg_table_.rbegin(); rit != msg_table_.rend(); ++rit) {
fs.write((*rit).c_str(), (*rit).length());
fs.put('\n');
if (fs.fail())
throw Error(ERR_FILE, "Unable to save history");
}
fs.close();
}
/*!
** This is a sugar to print msg on msg window
**
** @param scr A Screen
** @param s string to print
**
** @return @param scr
*/
Screen &operator<< (Screen &scr, const string &s) {
scr.msg_print(s);