#include #include #include "slc.hh" #include "screen.hh" #include "history.hh" Screen::Screen() {} void Screen::init() { // Init ncurses initscr(); // register end stop ncurses before exit atexit((void (*)(void)) endwin); // Set good parameters cbreak(); noecho(); keypad(stdscr, TRUE); refresh(); //wrefresh(stdscr); // Get term dimension int row, col; getmaxyx(stdscr, row, col); // Create msg window msg_ = newwin(row - 3, col, 0, 0); box(msg_, 0, 0); wrefresh(msg_); // Create cmd window cmd_ = newwin(3, col, row - 3, 0); box(cmd_, 0 , 0); // set buf value *cmd_buffer_ = 0; cmd_buf_off_ = 0; cmd_win_off_ = 0; cmd_win_size_ = col - 2; cmd_history_off_ = 0; wmove(cmd_, 1, 1); wrefresh(cmd_); //register sigwinch } void Screen::run() { while (1) { int key = getch(); switch(key) { // KEY UP case KEY_UP: if (cmd_history_off_ + 1 > H.size()) break; if (cmd_history_off_ == 0) memcpy(cmd_history_buffer_, cmd_buffer_, CMD_BUFFER_SIZE); strncpy(cmd_buffer_, H.get(cmd_history_off_++).c_str(), CMD_BUFFER_SIZE); cmd_buffer_[CMD_BUFFER_SIZE - 1] = 0; cmd_buf_off_ = strlen(cmd_buffer_); cmd_win_off_ = 0; break; // 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_, CMD_BUFFER_SIZE); else { strncpy(cmd_buffer_, H.get(cmd_history_off_ - 1).c_str(), CMD_BUFFER_SIZE); cmd_buffer_[CMD_BUFFER_SIZE - 1] = 0; } cmd_buf_off_ = strlen(cmd_buffer_); cmd_win_off_ = 0; break; // KEY LEFT case KEY_LEFT: if (cmd_buf_off_ > 0) --cmd_buf_off_; break; // KEY RIGHT case KEY_RIGHT: if ((size_t) cmd_buf_off_ < strlen(cmd_buffer_)) ++cmd_buf_off_; break; case KEY_HOME: cmd_buf_off_ = 0; break; case KEY_END: cmd_buf_off_ = strlen(cmd_buffer_); break; case 10: // save buffer in history H.add(cmd_buffer_); // send buffer wprintw(msg_, "%s\n", cmd_buffer_); wrefresh(msg_); // purge buffer *cmd_buffer_ = 0; cmd_buf_off_ = 0; cmd_win_off_ = 0; cmd_history_off_ = 0; break; case KEY_BACKSPACE: if (cmd_buf_off_ == 0) break; if (del_char(cmd_buffer_, cmd_buf_off_ - 1, CMD_BUFFER_SIZE)) --cmd_buf_off_; break; case KEY_DC: del_char(cmd_buffer_, cmd_buf_off_, CMD_BUFFER_SIZE); break; default: if (!isprint(key)) break; if (add_char(key, cmd_buffer_, cmd_buf_off_, CMD_BUFFER_SIZE)) ++cmd_buf_off_; } cmd_draw(); } } void Screen::cmd_draw() { char print_buf[CMD_BUFFER_SIZE]; // clean and redraw the cmd box werase(cmd_); box(cmd_, 0, 0); wmove(cmd_, 1, 1); // check cur pos is in screen if ((ssize_t) cmd_buf_off_ > (ssize_t) cmd_win_off_ + (ssize_t) cmd_win_size_ - 1) cmd_win_off_ = cmd_buf_off_ - cmd_win_size_ + 1; else if (cmd_buf_off_ < cmd_win_off_) cmd_win_off_ = cmd_buf_off_; // copy part of buffer in print buffer size_t minsize = (CMD_BUFFER_SIZE < cmd_win_size_) ? CMD_BUFFER_SIZE : cmd_win_size_; 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_); wrefresh(cmd_); } /*! ** Add a char in a buffer ** ** @param c char to add ** @param offset where add in the buffer */ bool Screen::add_char(char c, char *string, ssize_t offset, size_t buf_len) { assert(string); size_t len = strlen(string); // 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) return false; // move one char every char for (ssize_t i = len; i >= offset; --i) string[i + 1] = string[i]; string[offset] = c; return true; } 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) return false; // check if offset is good if (offset >= (ssize_t) buf_len - 1 || offset < 0) return false; // move one char every char for (; string[offset] != 0; ++offset) string[offset] = string[offset + 1]; return true; } void sigwinch(int) { return; } Screen &operator<< (Screen &scr, const string &s) { wprintw(scr.msg_, "%s", s.c_str()); wrefresh(scr.msg_); return scr; } Screen &operator<< (Screen &scr, int i) { wprintw(scr.msg_, "%d", i); wrefresh(scr.msg_); return scr; }