From a0cbd8fc3211d409f57924914785a615dfed5d6c Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sat, 9 May 2009 21:57:55 +0200 Subject: [PATCH] new feature: input text history --- src/ncmpcpp.cpp | 1 + src/window.cpp | 94 ++++++++++++++++++++++++++++++++++++++----------- src/window.h | 6 ++++ 3 files changed, 81 insertions(+), 20 deletions(-) diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index 2daf8bcd..f11cd943 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -161,6 +161,7 @@ int main(int argc, char *argv[]) wFooter = new Window(0, footer_start_y, COLS, footer_height, "", Config.statusbar_color, brNone); wFooter->SetTimeout(ncmpcpp_window_timeout); wFooter->SetGetStringHelper(StatusbarGetStringHelper); + wFooter->CreateHistory(); *wFooter << fmtBold; // bold by default myScreen = myPlaylist; diff --git a/src/window.cpp b/src/window.cpp index 934fa6ed..dfbc7df8 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -93,7 +93,8 @@ Window::Window(size_t startx, itsBaseColor(color), itsBgColor(clDefault), itsBaseBgColor(clDefault), - itsBorder(border) + itsBorder(border), + itsHistory(0) { if (itsStartX > size_t(COLS) || itsStartY > size_t(LINES) @@ -150,6 +151,7 @@ Window::~Window() { delwin(itsWindow); delwin(itsWinBorder); + delete itsHistory; } void Window::SetColor(Color col, Color background) @@ -222,6 +224,18 @@ void Window::SetTitle(const string &newtitle) itsTitle = newtitle; } +void Window::CreateHistory() +{ + if (!itsHistory) + itsHistory = new std::deque; +} + +void Window::DeleteHistory() +{ + delete itsHistory; + itsHistory = 0; +} + void Window::Recreate() { delwin(itsWindow); @@ -378,7 +392,10 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e width = itsWidth-x-1; curs_set(1); - std::wstring tmp = ToWString(base); + + std::wstring wbase = ToWString(base); + std::wstring *tmp = &wbase; + size_t history_offset = itsHistory ? itsHistory->size() : -1; string tmp_in; wchar_t wc_in; @@ -386,7 +403,7 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e bool block_scrolling = 0; // disable scrolling if wide chars are used - for (wstring::const_iterator it = tmp.begin(); it != tmp.end(); it++) + for (wstring::const_iterator it = tmp->begin(); it != tmp->end(); it++) if (wcwidth(*it) > 1) block_scrolling = 1; @@ -394,13 +411,13 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e do { - if (tmp.empty()) + if (tmp->empty()) block_scrolling = 0; - maxbeginning = block_scrolling ? 0 : (tmp.length() < width ? 0 : tmp.length()-width); - maxx = minx + (Length(tmp) < width ? Length(tmp) : width); + maxbeginning = block_scrolling ? 0 : (tmp->length() < width ? 0 : tmp->length()-width); + maxx = minx + (Length(*tmp) < width ? Length(*tmp) : width); - real_maxx = minx + (tmp.length() < width ? tmp.length() : width); + real_maxx = minx + (tmp->length() < width ? tmp->length() : width); if (beginning > maxbeginning) beginning = maxbeginning; @@ -413,7 +430,7 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e if (block_scrolling && maxx >= biggest_x) { size_t i = 0; - for (wstring::const_iterator it = tmp.begin(); i < width; it++, real_real_maxx++) + for (wstring::const_iterator it = tmp->begin(); i < width; it++, real_real_maxx++) i += wcwidth(*it); } else @@ -428,12 +445,12 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e mvwhline(itsWindow, y, minx, 32, width+1); if (!encrypted) - mvwprintw(itsWindow, y, minx, "%ls", tmp.substr(beginning, width+1).c_str()); + mvwprintw(itsWindow, y, minx, "%ls", tmp->substr(beginning, width+1).c_str()); else mvwhline(itsWindow, y, minx, '*', maxx-minx); if (itsGetStringHelper) - itsGetStringHelper(tmp); + itsGetStringHelper(*tmp); wmove(itsWindow, y, x); prefresh(itsWindow, 0, 0, itsStartY, itsStartX, itsStartY+itsHeight-1, itsStartX+itsWidth-1); @@ -452,14 +469,37 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e { case ERR: case KEY_UP: + if (itsHistory && history_offset > 0) + { + do + tmp = &(*itsHistory)[--history_offset]; + while (tmp->empty() && history_offset); + gotoend = 1; + } + break; case KEY_DOWN: + if (itsHistory && itsHistory->size() > 0) + { + if (history_offset < itsHistory->size()-1) + { + do + tmp = &(*itsHistory)[++history_offset]; + while (tmp->empty() && history_offset < itsHistory->size()-1); + } + else if (history_offset == itsHistory->size()-1) + { + tmp = &wbase; + history_offset++; + } + gotoend = 1; + } break; case KEY_RIGHT: { if (x < maxx) { real_x++; - x += wcwidth(tmp[beginning+real_x-minx-1]); + x += wcwidth((*tmp)[beginning+real_x-minx-1]); } else if (beginning < maxbeginning) beginning++; @@ -475,7 +515,7 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e if (x > minx) { real_x--; - x -= wcwidth(tmp[beginning+real_x-minx]); + x -= wcwidth((*tmp)[beginning+real_x-minx]); } else if (beginning > 0) beginning--; @@ -484,9 +524,9 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e } case KEY_DC: { - if ((real_x-minx)+beginning == tmp.length()) + if ((real_x-minx)+beginning == tmp->length()) break; - tmp.erase(tmp.begin()+(real_x-minx)+beginning); + tmp->erase(tmp->begin()+(real_x-minx)+beginning); if (beginning && beginning == maxbeginning && real_x < maxx) { real_x++; @@ -508,13 +548,13 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e case 10: break; case 21: // CTRL+U - tmp.clear(); + tmp->clear(); real_maxx = maxx = real_x = x = minx; maxbeginning = beginning = 0; break; default: { - if (tmp.length() >= length) + if (tmp->length() >= length) break; tmp_in += input; @@ -524,9 +564,9 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e if (wcwidth(wc_in) > 1) block_scrolling = 1; - if ((real_x-minx)+beginning >= tmp.length()) + if ((real_x-minx)+beginning >= tmp->length()) { - tmp.push_back(wc_in); + tmp->push_back(wc_in); if (!beginning) { real_x++; @@ -537,7 +577,7 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e } else { - tmp.insert(tmp.begin()+(real_x-minx)+beginning, wc_in); + tmp->insert(tmp->begin()+(real_x-minx)+beginning, wc_in); if (x < maxx) { real_x++; @@ -553,7 +593,21 @@ string Window::GetString(const string &base, size_t length, size_t width, bool e while (input != 10); curs_set(0); - return ToString(tmp); + if (itsHistory) + { + size_t old_size = itsHistory->size(); + if (!tmp->empty() && (itsHistory->empty() || itsHistory->back() != *tmp)) + itsHistory->push_back(*tmp); + if (old_size > 1 && history_offset < old_size) + { + std::deque::iterator it = itsHistory->begin()+history_offset; + wbase = *it; + tmp = &wbase; + itsHistory->erase(it); + } + } + + return ToString(*tmp); } void Window::GetXY(int &x, int &y) diff --git a/src/window.h b/src/window.h index bf252f6e..1d748054 100644 --- a/src/window.h +++ b/src/window.h @@ -27,6 +27,7 @@ #include "curses.h" +#include #include #include #include @@ -113,6 +114,8 @@ namespace NCurses void SetBorder(Border); void SetTimeout(int); void SetTitle(const std::string &); + void CreateHistory(); + void DeleteHistory(); void Hide(char = 32) const; void Bold(bool) const; @@ -188,6 +191,9 @@ namespace NCurses Color itsBaseBgColor; Border itsBorder; + + private: + std::deque *itsHistory; }; }