window: use readline for handling line input
This commit is contained in:
10
configure.ac
10
configure.ac
@@ -181,6 +181,16 @@ PKG_CHECK_MODULES([libmpdclient], [libmpdclient >= 2.8], [
|
||||
AC_MSG_ERROR([libmpdclient >= 2.8 is required!])
|
||||
)
|
||||
|
||||
dnl =========================
|
||||
dnl = checking for readline =
|
||||
dnl =========================
|
||||
AC_CHECK_HEADERS([readline/readline.h readline/history.h],
|
||||
AC_CHECK_LIB(readline, rl_initialize, LDFLAGS="$LDFLAGS -lreadline",
|
||||
AC_MSG_ERROR([readline headers found but there is no readline library to make use of])
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
dnl ========================
|
||||
dnl = checking for pthread =
|
||||
dnl ========================
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <readline/readline.h>
|
||||
|
||||
#include "actions.h"
|
||||
#include "charset.h"
|
||||
@@ -191,6 +192,7 @@ void resizeScreen(bool reload_main_window)
|
||||
// update internal screen dimensions
|
||||
if (reload_main_window)
|
||||
{
|
||||
rl_resize_terminal();
|
||||
endwin();
|
||||
refresh();
|
||||
}
|
||||
@@ -1189,7 +1191,7 @@ void SetCrossfade::run()
|
||||
|
||||
Statusbar::lock();
|
||||
Statusbar::put() << "Set crossfade to: ";
|
||||
std::string crossfade = wFooter->getString(3);
|
||||
std::string crossfade = wFooter->getString();
|
||||
Statusbar::unlock();
|
||||
int cf = fromString<unsigned>(crossfade);
|
||||
lowerBoundCheck(cf, 1);
|
||||
@@ -1203,7 +1205,7 @@ void SetVolume::run()
|
||||
|
||||
Statusbar::lock();
|
||||
Statusbar::put() << "Set volume to: ";
|
||||
std::string strvolume = wFooter->getString(3);
|
||||
std::string strvolume = wFooter->getString();
|
||||
Statusbar::unlock();
|
||||
int volume = fromString<unsigned>(strvolume);
|
||||
boundsCheck(volume, 0, 100);
|
||||
@@ -1765,7 +1767,7 @@ void ApplyFilter::run()
|
||||
|
||||
Statusbar::lock();
|
||||
Statusbar::put() << NC::Format::Bold << "Apply filter: " << NC::Format::NoBold;
|
||||
wFooter->setGetStringHelper(Statusbar::Helpers::ApplyFilterImmediately(f, ToWString(filter)));
|
||||
wFooter->setGetStringHelper(Statusbar::Helpers::ApplyFilterImmediately(f, filter));
|
||||
wFooter->getString(filter);
|
||||
wFooter->setGetStringHelper(Statusbar::Helpers::getString);
|
||||
Statusbar::unlock();
|
||||
|
||||
@@ -53,6 +53,7 @@ namespace
|
||||
{
|
||||
std::ofstream errorlog;
|
||||
std::streambuf *cerr_buffer;
|
||||
bool run_resize_screen = false;
|
||||
|
||||
# if !defined(WIN32)
|
||||
void sighandler(int signal)
|
||||
@@ -63,7 +64,7 @@ namespace
|
||||
}
|
||||
else if (signal == SIGWINCH)
|
||||
{
|
||||
Actions::resizeScreen(true);
|
||||
run_resize_screen = true;
|
||||
}
|
||||
}
|
||||
# endif // !WIN32
|
||||
@@ -153,7 +154,6 @@ int main(int argc, char **argv)
|
||||
wFooter = new NC::Window(0, Actions::FooterStartY, COLS, Actions::FooterHeight, "", Config.statusbar_color, NC::Border::None);
|
||||
wFooter->setTimeout(500);
|
||||
wFooter->setGetStringHelper(Statusbar::Helpers::getString);
|
||||
wFooter->createHistory();
|
||||
|
||||
// initialize global timer
|
||||
gettimeofday(&Timer, 0);
|
||||
@@ -225,6 +225,12 @@ int main(int argc, char **argv)
|
||||
}
|
||||
|
||||
Status::trace();
|
||||
|
||||
if (run_resize_screen)
|
||||
{
|
||||
Actions::resizeScreen(true);
|
||||
run_resize_screen = false;
|
||||
}
|
||||
|
||||
// header stuff
|
||||
if (((Timer.tv_sec == past.tv_sec && Timer.tv_usec >= past.tv_usec+500000) || Timer.tv_sec > past.tv_sec)
|
||||
|
||||
@@ -118,7 +118,7 @@ void Status::handleServerError(MPD::ServerError &e)
|
||||
{
|
||||
wFooter->setGetStringHelper(nullptr);
|
||||
Statusbar::put() << "Password: ";
|
||||
Mpd.SetPassword(wFooter->getString(-1, 0, 1));
|
||||
Mpd.SetPassword(wFooter->getString(0, true));
|
||||
Mpd.SendPassword();
|
||||
Statusbar::msg("Password accepted");
|
||||
wFooter->setGetStringHelper(Statusbar::Helpers::getString);
|
||||
|
||||
@@ -189,13 +189,13 @@ void Statusbar::Helpers::mpd()
|
||||
Status::update(Mpd.noidle());
|
||||
}
|
||||
|
||||
bool Statusbar::Helpers::getString(const std::wstring &)
|
||||
bool Statusbar::Helpers::getString(const char *)
|
||||
{
|
||||
Status::trace();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &ws)
|
||||
bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const char *s)
|
||||
{
|
||||
using Global::myScreen;
|
||||
// if input queue is not empty, we don't want to update filter since next
|
||||
@@ -205,10 +205,10 @@ bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &
|
||||
// is next in queue, so its effects will be seen.
|
||||
if (wFooter->inputQueue().empty() || wFooter->inputQueue().front() == KEY_ENTER)
|
||||
{
|
||||
if (m_ws != ws)
|
||||
if (m_s != s)
|
||||
{
|
||||
m_ws = ws;
|
||||
m_f->applyFilter(ToString(m_ws));
|
||||
m_s = s;
|
||||
m_f->applyFilter(m_s);
|
||||
myScreen->refreshWindow();
|
||||
}
|
||||
Status::trace();
|
||||
@@ -216,13 +216,13 @@ bool Statusbar::Helpers::ApplyFilterImmediately::operator()(const std::wstring &
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Statusbar::Helpers::TryExecuteImmediateCommand::operator()(const std::wstring &ws)
|
||||
bool Statusbar::Helpers::TryExecuteImmediateCommand::operator()(const char *s)
|
||||
{
|
||||
bool continue_ = true;
|
||||
if (m_ws != ws)
|
||||
if (m_s != s)
|
||||
{
|
||||
m_ws = ws;
|
||||
auto cmd = Bindings.findCommand(ToString(m_ws));
|
||||
m_s = s;
|
||||
auto cmd = Bindings.findCommand(m_s);
|
||||
if (cmd && cmd->immediate())
|
||||
continue_ = false;
|
||||
}
|
||||
|
||||
@@ -71,27 +71,28 @@ namespace Helpers {//
|
||||
void mpd();
|
||||
|
||||
/// called each time user types another character while inside Window::getString
|
||||
bool getString(const std::wstring &);
|
||||
bool getString(const char *);
|
||||
|
||||
/// called each time user changes current filter (while being inside Window::getString)
|
||||
struct ApplyFilterImmediately
|
||||
{
|
||||
ApplyFilterImmediately(Filterable *f, const std::wstring &filter)
|
||||
: m_f(f), m_ws(filter) { }
|
||||
template <typename StringT>
|
||||
ApplyFilterImmediately(Filterable *f, StringT &&filter)
|
||||
: m_f(f), m_s(std::forward<StringT>(filter)) { }
|
||||
|
||||
bool operator()(const std::wstring &ws);
|
||||
bool operator()(const char *s);
|
||||
|
||||
private:
|
||||
Filterable *m_f;
|
||||
std::wstring m_ws;
|
||||
std::string m_s;
|
||||
};
|
||||
|
||||
struct TryExecuteImmediateCommand
|
||||
{
|
||||
bool operator()(const std::wstring &ws);
|
||||
bool operator()(const char *s);
|
||||
|
||||
private:
|
||||
std::wstring m_ws;
|
||||
std::string m_s;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
386
src/window.cpp
386
src/window.cpp
@@ -18,8 +18,12 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
|
||||
#ifdef WIN32
|
||||
# include <winsock.h>
|
||||
@@ -33,6 +37,111 @@
|
||||
#include "utility/wide_string.h"
|
||||
#include "window.h"
|
||||
|
||||
namespace {
|
||||
namespace rl {
|
||||
|
||||
NC::Window *w;
|
||||
size_t start_x;
|
||||
size_t start_y;
|
||||
size_t width;
|
||||
bool encrypted;
|
||||
const char *base;
|
||||
|
||||
int read_key(FILE *)
|
||||
{
|
||||
int result;
|
||||
do
|
||||
{
|
||||
w->runGetStringHelper(rl_line_buffer);
|
||||
w->refresh();
|
||||
result = w->readKey();
|
||||
}
|
||||
while (result == ERR);
|
||||
return result;
|
||||
}
|
||||
|
||||
void display_string()
|
||||
{
|
||||
auto print_char = [](wchar_t wc) {
|
||||
if (encrypted)
|
||||
*w << '*';
|
||||
else
|
||||
*w << wc;
|
||||
};
|
||||
auto print_string = [](wchar_t *ws, size_t len) {
|
||||
if (encrypted)
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
*w << '*';
|
||||
else
|
||||
*w << ws;
|
||||
};
|
||||
|
||||
char pt = rl_line_buffer[rl_point];
|
||||
rl_line_buffer[rl_point] = 0;
|
||||
wchar_t pre_pos[rl_point+1];
|
||||
pre_pos[mbstowcs(pre_pos, rl_line_buffer, rl_point)] = 0;
|
||||
rl_line_buffer[rl_point] = pt;
|
||||
|
||||
int pos = wcswidth(pre_pos, rl_point);
|
||||
assert(pos >= 0);
|
||||
if (pos < 0)
|
||||
pos = rl_point;
|
||||
|
||||
mvwhline(w->raw(), start_y, start_x, ' ', width+1);
|
||||
w->goToXY(start_x, start_y);
|
||||
if (size_t(pos) <= width)
|
||||
{
|
||||
print_string(pre_pos, pos);
|
||||
|
||||
wchar_t post_pos[rl_end-rl_point+1];
|
||||
post_pos[mbstowcs(post_pos, rl_line_buffer+rl_point, rl_end-rl_point)] = 0;
|
||||
|
||||
size_t cpos = pos;
|
||||
for (wchar_t *c = post_pos; *c != 0; ++c)
|
||||
{
|
||||
int n = wcwidth(*c);
|
||||
if (n < 0)
|
||||
{
|
||||
print_char(L'.');
|
||||
++cpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpos+n > width)
|
||||
break;
|
||||
cpos += n;
|
||||
print_char(*c);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wchar_t *mod_pre_pos = pre_pos;
|
||||
while (*mod_pre_pos != 0)
|
||||
{
|
||||
++mod_pre_pos;
|
||||
int n = wcwidth(*mod_pre_pos);
|
||||
if (n < 0)
|
||||
--pos;
|
||||
else
|
||||
pos -= n;
|
||||
if (size_t(pos) <= width)
|
||||
break;
|
||||
}
|
||||
print_string(mod_pre_pos, pos);
|
||||
}
|
||||
w->goToXY(start_x+pos, start_y);
|
||||
}
|
||||
|
||||
int add_base()
|
||||
{
|
||||
rl_insert_text(base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace NC {//
|
||||
|
||||
void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors)
|
||||
@@ -64,6 +173,12 @@ void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors)
|
||||
noecho();
|
||||
cbreak();
|
||||
curs_set(0);
|
||||
|
||||
rl_initialize();
|
||||
// overwrite readline callbacks
|
||||
rl_getc_function = rl::read_key;
|
||||
rl_redisplay_function = rl::display_string;
|
||||
rl_startup_hook = rl::add_base;
|
||||
}
|
||||
|
||||
void destroyScreen()
|
||||
@@ -93,7 +208,6 @@ Window::Window(size_t startx,
|
||||
m_border(border),
|
||||
m_get_string_helper(0),
|
||||
m_title(title),
|
||||
m_history(0),
|
||||
m_bold_counter(0),
|
||||
m_underline_counter(0),
|
||||
m_reverse_counter(0),
|
||||
@@ -145,7 +259,6 @@ Window::Window(const Window &rhs)
|
||||
, m_color_stack(rhs.m_color_stack)
|
||||
, m_input_queue(rhs.m_input_queue)
|
||||
, m_fds(rhs.m_fds)
|
||||
, m_history(rhs.m_history ? new std::list<std::wstring>(*rhs.m_history) : 0)
|
||||
, m_bold_counter(rhs.m_bold_counter)
|
||||
, m_underline_counter(rhs.m_underline_counter)
|
||||
, m_reverse_counter(rhs.m_reverse_counter)
|
||||
@@ -171,7 +284,6 @@ Window::Window(Window &&rhs)
|
||||
, m_color_stack(std::move(rhs.m_color_stack))
|
||||
, m_input_queue(std::move(rhs.m_input_queue))
|
||||
, m_fds(std::move(rhs.m_fds))
|
||||
, m_history(rhs.m_history)
|
||||
, m_bold_counter(rhs.m_bold_counter)
|
||||
, m_underline_counter(rhs.m_underline_counter)
|
||||
, m_reverse_counter(rhs.m_reverse_counter)
|
||||
@@ -179,7 +291,6 @@ Window::Window(Window &&rhs)
|
||||
{
|
||||
rhs.m_window = 0;
|
||||
rhs.m_border_window = 0;
|
||||
rhs.m_history = 0;
|
||||
}
|
||||
|
||||
Window &Window::operator=(Window rhs)
|
||||
@@ -201,7 +312,6 @@ Window &Window::operator=(Window rhs)
|
||||
std::swap(m_color_stack, rhs.m_color_stack);
|
||||
std::swap(m_input_queue, rhs.m_input_queue);
|
||||
std::swap(m_fds, rhs.m_fds);
|
||||
std::swap(m_history, rhs.m_history);
|
||||
std::swap(m_bold_counter, rhs.m_bold_counter);
|
||||
std::swap(m_underline_counter, rhs.m_underline_counter);
|
||||
std::swap(m_reverse_counter, rhs.m_reverse_counter);
|
||||
@@ -213,7 +323,6 @@ Window::~Window()
|
||||
{
|
||||
delwin(m_window);
|
||||
delwin(m_border_window);
|
||||
delete m_history;
|
||||
}
|
||||
|
||||
void Window::setColor(Color fg, Color bg)
|
||||
@@ -286,18 +395,6 @@ void Window::setTitle(const std::string &new_title)
|
||||
m_title = new_title;
|
||||
}
|
||||
|
||||
void Window::createHistory()
|
||||
{
|
||||
if (!m_history)
|
||||
m_history = new std::list<std::wstring>;
|
||||
}
|
||||
|
||||
void Window::deleteHistory()
|
||||
{
|
||||
delete m_history;
|
||||
m_history = 0;
|
||||
}
|
||||
|
||||
void Window::recreate(size_t width, size_t height)
|
||||
{
|
||||
delwin(m_window);
|
||||
@@ -481,229 +578,39 @@ void Window::pushChar(int ch)
|
||||
m_input_queue.push(ch);
|
||||
}
|
||||
|
||||
std::string Window::getString(const std::string &base, size_t length_, size_t width, bool encrypted)
|
||||
std::string Window::getString(const std::string &base, size_t width, bool encrypted)
|
||||
{
|
||||
int input;
|
||||
size_t beginning, maxbeginning, minx, x, real_x, y, maxx, real_maxx;
|
||||
|
||||
getyx(m_window, y, x);
|
||||
minx = real_maxx = maxx = real_x = x;
|
||||
|
||||
rl::w = this;
|
||||
getyx(m_window, rl::start_y, rl::start_x);
|
||||
rl::width = width;
|
||||
rl::encrypted = encrypted;
|
||||
rl::base = base.c_str();
|
||||
|
||||
width--;
|
||||
if (width == size_t(-1))
|
||||
width = m_width-x-1;
|
||||
|
||||
rl::width = m_width-rl::start_x-1;
|
||||
else
|
||||
rl::width = width;
|
||||
|
||||
mmask_t oldmask;
|
||||
std::string result;
|
||||
|
||||
curs_set(1);
|
||||
|
||||
std::wstring wbase = ToWString(base);
|
||||
std::wstring *tmp = &wbase;
|
||||
std::list<std::wstring>::iterator history_it = m_history->end();
|
||||
|
||||
std::string tmp_in;
|
||||
wchar_t wc_in;
|
||||
bool gotoend = 1;
|
||||
bool block_scrolling = 0;
|
||||
|
||||
// disable scrolling if wide chars are used
|
||||
for (std::wstring::const_iterator it = tmp->begin(); it != tmp->end(); ++it)
|
||||
if (wcwidth(*it) > 1)
|
||||
block_scrolling = 1;
|
||||
|
||||
beginning = -1;
|
||||
|
||||
do
|
||||
{
|
||||
if (tmp->empty())
|
||||
block_scrolling = 0;
|
||||
|
||||
maxbeginning = block_scrolling ? 0 : (tmp->length() < width ? 0 : tmp->length()-width);
|
||||
maxx = minx + (wideLength(*tmp) < width ? wideLength(*tmp) : width);
|
||||
|
||||
real_maxx = minx + (tmp->length() < width ? tmp->length() : width);
|
||||
|
||||
if (beginning > maxbeginning)
|
||||
beginning = maxbeginning;
|
||||
|
||||
if (gotoend)
|
||||
{
|
||||
size_t real_real_maxx = minx;
|
||||
size_t biggest_x = minx+width;
|
||||
|
||||
if (block_scrolling && maxx >= biggest_x)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (std::wstring::const_iterator it = tmp->begin(); i < width; ++it, ++real_real_maxx)
|
||||
i += wcwidth(*it);
|
||||
}
|
||||
else
|
||||
real_real_maxx = real_maxx;
|
||||
|
||||
real_x = real_real_maxx;
|
||||
x = block_scrolling ? (maxx > biggest_x ? biggest_x : maxx) : maxx;
|
||||
beginning = maxbeginning;
|
||||
gotoend = 0;
|
||||
}
|
||||
|
||||
mvwhline(m_window, y, minx, ' ', width+1);
|
||||
|
||||
if (!encrypted)
|
||||
mvwprintw(m_window, y, minx, "%ls", tmp->substr(beginning, width+1).c_str());
|
||||
else
|
||||
mvwhline(m_window, y, minx, '*', maxx-minx);
|
||||
|
||||
if (m_get_string_helper)
|
||||
{
|
||||
if (!m_get_string_helper(*tmp))
|
||||
break;
|
||||
}
|
||||
|
||||
wmove(m_window, y, x);
|
||||
prefresh(m_window, 0, 0, m_start_y, m_start_x, m_start_y+m_height-1, m_start_x+m_width-1);
|
||||
input = readKey();
|
||||
|
||||
switch (input)
|
||||
{
|
||||
case ERR:
|
||||
case KEY_MOUSE:
|
||||
break;
|
||||
case KEY_UP:
|
||||
if (m_history && !encrypted && history_it != m_history->begin())
|
||||
{
|
||||
while (--history_it != m_history->begin())
|
||||
if (!history_it->empty())
|
||||
break;
|
||||
tmp = &*history_it;
|
||||
gotoend = 1;
|
||||
}
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
if (m_history && !encrypted && history_it != m_history->end())
|
||||
{
|
||||
while (++history_it != m_history->end())
|
||||
if (!history_it->empty())
|
||||
break;
|
||||
tmp = &(history_it == m_history->end() ? wbase : *history_it);
|
||||
gotoend = 1;
|
||||
}
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
{
|
||||
if (x < maxx)
|
||||
{
|
||||
real_x++;
|
||||
x += std::max(wcwidth((*tmp)[beginning+real_x-minx-1]), 1);
|
||||
}
|
||||
else if (beginning < maxbeginning)
|
||||
beginning++;
|
||||
break;
|
||||
}
|
||||
case KEY_CTRL_H:
|
||||
case KEY_BACKSPACE:
|
||||
case KEY_BACKSPACE_2:
|
||||
{
|
||||
if (x <= minx && !beginning)
|
||||
break;
|
||||
}
|
||||
case KEY_LEFT:
|
||||
{
|
||||
if (x > minx)
|
||||
{
|
||||
real_x--;
|
||||
x -= std::max(wcwidth((*tmp)[beginning+real_x-minx]), 1);
|
||||
}
|
||||
else if (beginning > 0)
|
||||
beginning--;
|
||||
if (input != KEY_CTRL_H && input != KEY_BACKSPACE && input != KEY_BACKSPACE_2)
|
||||
break; // backspace = left & delete.
|
||||
}
|
||||
case KEY_DC:
|
||||
{
|
||||
if ((real_x-minx)+beginning == tmp->length())
|
||||
break;
|
||||
tmp->erase(tmp->begin()+(real_x-minx)+beginning);
|
||||
if (beginning && beginning == maxbeginning && real_x < maxx)
|
||||
{
|
||||
real_x++;
|
||||
x++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case KEY_HOME:
|
||||
{
|
||||
real_x = x = minx;
|
||||
beginning = 0;
|
||||
break;
|
||||
}
|
||||
case KEY_END:
|
||||
{
|
||||
gotoend = 1;
|
||||
break;
|
||||
}
|
||||
case KEY_ENTER:
|
||||
break;
|
||||
case KEY_CTRL_U:
|
||||
tmp->clear();
|
||||
real_maxx = maxx = real_x = x = minx;
|
||||
maxbeginning = beginning = 0;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if (tmp->length() >= length_)
|
||||
break;
|
||||
|
||||
tmp_in += input;
|
||||
if (int(mbrtowc(&wc_in, tmp_in.c_str(), MB_CUR_MAX, 0)) < 0)
|
||||
break;
|
||||
|
||||
int wcwidth_res = wcwidth(wc_in);
|
||||
if (wcwidth_res > 1)
|
||||
block_scrolling = 1;
|
||||
|
||||
if (wcwidth_res > 0) // is char printable? we want to ignore things like Ctrl-?, Fx etc.
|
||||
{
|
||||
if ((real_x-minx)+beginning >= tmp->length())
|
||||
{
|
||||
tmp->push_back(wc_in);
|
||||
if (!beginning)
|
||||
{
|
||||
real_x++;
|
||||
x += wcwidth(wc_in);
|
||||
}
|
||||
beginning++;
|
||||
gotoend = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp->insert(tmp->begin()+(real_x-minx)+beginning, wc_in);
|
||||
if (x < maxx)
|
||||
{
|
||||
real_x++;
|
||||
x += wcwidth(wc_in);
|
||||
}
|
||||
else if (beginning < maxbeginning)
|
||||
beginning++;
|
||||
}
|
||||
}
|
||||
tmp_in.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
while (input != KEY_ENTER);
|
||||
keypad(m_window, 0);
|
||||
mousemask(0, &oldmask);
|
||||
char *input = readline(nullptr);
|
||||
mousemask(oldmask, nullptr);
|
||||
keypad(m_window, 1);
|
||||
curs_set(0);
|
||||
|
||||
if (m_history && !encrypted)
|
||||
if (input != nullptr)
|
||||
{
|
||||
if (history_it != m_history->end())
|
||||
{
|
||||
m_history->push_back(*history_it);
|
||||
tmp = &m_history->back();
|
||||
m_history->erase(history_it);
|
||||
}
|
||||
else
|
||||
m_history->push_back(*tmp);
|
||||
if (input[0] != 0)
|
||||
add_history(input);
|
||||
result = input;
|
||||
free(input);
|
||||
}
|
||||
|
||||
return ToString(*tmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Window::goToXY(int x, int y)
|
||||
@@ -739,6 +646,17 @@ bool Window::hasCoords(int &x, int &y)
|
||||
# endif
|
||||
}
|
||||
|
||||
bool Window::runGetStringHelper(const char *arg) const
|
||||
{
|
||||
if (m_get_string_helper)
|
||||
{
|
||||
m_get_string_helper(arg);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Window::getWidth() const
|
||||
{
|
||||
if (m_border != Border::None)
|
||||
|
||||
26
src/window.h
26
src/window.h
@@ -132,7 +132,7 @@ enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
||||
/// Helper function that is invoked each time one will want
|
||||
/// to obtain string from Window::getString() function
|
||||
/// @see Window::getString()
|
||||
typedef std::function<bool(const std::wstring &)> GetStringHelper;
|
||||
typedef std::function<bool(const char *)> GetStringHelper;
|
||||
|
||||
/// Initializes curses screen and sets some additional attributes
|
||||
/// @param window_title title of the window (has an effect only if pdcurses lib is used)
|
||||
@@ -163,7 +163,7 @@ struct XY
|
||||
/// Main class of NCurses namespace, used as base for other specialized windows
|
||||
struct Window
|
||||
{
|
||||
Window() : m_window(0), m_border_window(0), m_history(0) { }
|
||||
Window() : m_window(0), m_border_window(0) { }
|
||||
|
||||
/// Constructs an empty window with given parameters
|
||||
/// @param startx X position of left upper corner of constructed window
|
||||
@@ -229,14 +229,13 @@ struct Window
|
||||
/// @see setGetStringHelper()
|
||||
/// @see SetTimeout()
|
||||
/// @see CreateHistory()
|
||||
std::string getString(const std::string &base, size_t length_ = -1,
|
||||
size_t width = 0, bool encrypted = 0);
|
||||
std::string getString(const std::string &base, size_t width = 0, bool encrypted = 0);
|
||||
|
||||
/// Wrapper for above function that doesn't take base string (it will be empty).
|
||||
/// Taken parameters are the same as for above.
|
||||
std::string getString(size_t length_ = -1, size_t width = 0, bool encrypted = 0)
|
||||
std::string getString(size_t width = 0, bool encrypted = 0)
|
||||
{
|
||||
return getString("", length_, width, encrypted);
|
||||
return getString("", width, encrypted);
|
||||
}
|
||||
|
||||
/// Moves cursor to given coordinates
|
||||
@@ -262,6 +261,11 @@ struct Window
|
||||
/// @param helper pointer to function that matches getStringHelper prototype
|
||||
/// @see getString()
|
||||
void setGetStringHelper(GetStringHelper helper) { m_get_string_helper = helper; }
|
||||
|
||||
/// Run current GetString helper function (if defined).
|
||||
/// @see getString()
|
||||
/// @return true if helper was run, false otherwise
|
||||
bool runGetStringHelper(const char *arg) const;
|
||||
|
||||
/// Sets window's base color
|
||||
/// @param fg foregound base color
|
||||
@@ -280,13 +284,6 @@ struct Window
|
||||
/// @param new_title new title for window
|
||||
void setTitle(const std::string &new_title);
|
||||
|
||||
/// Creates internal container that stores all previous
|
||||
/// strings that were edited using this window.
|
||||
void createHistory();
|
||||
|
||||
/// Deletes container with all previous history entries
|
||||
void deleteHistory();
|
||||
|
||||
/// Refreshed whole window and its border
|
||||
/// @see refresh()
|
||||
void display();
|
||||
@@ -509,9 +506,6 @@ private:
|
||||
typedef std::vector< std::pair<int, void (*)()> > FDCallbacks;
|
||||
FDCallbacks m_fds;
|
||||
|
||||
/// pointer to container used as history
|
||||
std::list<std::wstring> *m_history;
|
||||
|
||||
/// counters for format flags
|
||||
int m_bold_counter;
|
||||
int m_underline_counter;
|
||||
|
||||
Reference in New Issue
Block a user