From f6cae753e292db5693924393435a658b95795492 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Sat, 25 Aug 2012 06:50:27 +0200 Subject: [PATCH] implement input character queue and add PushCharacters macro utility --- src/Makefile.am | 7 +++--- src/actions.cpp | 10 ++++----- src/actions.h | 1 + src/macro_utilities.h | 51 +++++++++++++++++++++++++++++++++++++++++++ src/playlist.cpp | 6 ----- src/playlist.h | 1 - src/screen.h | 14 +----------- src/window.cpp | 26 +++++++++++++++------- src/window.h | 23 +++++++++++-------- 9 files changed, 94 insertions(+), 45 deletions(-) create mode 100644 src/macro_utilities.h diff --git a/src/Makefile.am b/src/Makefile.am index cb271920..cab6dac9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,6 +14,7 @@ INCLUDES= $(all_includes) ncmpcpp_LDFLAGS = $(all_libraries) noinst_HEADERS = browser.h charset.h clock.h conv.h curl_handle.h display.h \ error.h global.h help.h helpers.h lastfm.h lastfm_service.h lyrics.h \ - lyrics_fetcher.h media_library.h menu.h mpdpp.h outputs.h playlist_editor.h screen.h \ - scrollpad.h search_engine.h sel_items_adder.h server_info.h settings.h song.h \ - song_info.h tag_editor.h tiny_tag_editor.h tolower.h visualizer.h window.h + lyrics_fetcher.h macro_utilities.h media_library.h menu.h mpdpp.h outputs.h \ + playlist_editor.h screen.h scrollpad.h search_engine.h sel_items_adder.h server_info.h \ + settings.h song.h song_info.h tag_editor.h tiny_tag_editor.h tolower.h \ + visualizer.h window.h diff --git a/src/actions.cpp b/src/actions.cpp index a6267908..16a8e1c3 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -66,7 +66,7 @@ Action::Key Action::ReadKey(Window &w) int input; while (true) { - w.ReadKey(input); + input = w.ReadKey(); if (input == ERR) return NoOp; if (input > 255) @@ -407,7 +407,7 @@ bool Action::AskYesNoQuestion(const std::string &question, void (*callback)()) { if (callback) callback(); - wFooter->ReadKey(answer); + answer = wFooter->ReadKey(); } while (answer != 'y' && answer != 'n'); UnlockStatusbar(); @@ -2103,7 +2103,7 @@ void ToggleReplayGainMode::Run() do { TraceMpdStatus(); - wFooter->ReadKey(answer); + answer = wFooter->ReadKey(); } while (answer != 'o' && answer != 't' && answer != 'a'); UnlockStatusbar(); @@ -2147,7 +2147,7 @@ void AddRandomItems::Run() do { TraceMpdStatus(); - wFooter->ReadKey(answer); + answer = wFooter->ReadKey(); } while (answer != 's' && answer != 'a' && answer != 'b'); UnlockStatusbar(); @@ -2210,7 +2210,7 @@ void ToggleLibraryTagType::Run() do { TraceMpdStatus(); - wFooter->ReadKey(answer); + answer = wFooter->ReadKey(); } while (answer != 'a' && answer != 'A' && answer != 'y' && answer != 'g' && answer != 'c' && answer != 'p'); UnlockStatusbar(); diff --git a/src/actions.h b/src/actions.h index 4f97b6f0..b54b45d0 100644 --- a/src/actions.h +++ b/src/actions.h @@ -27,6 +27,7 @@ enum ActionType { + aMacroUtility, aMouseEvent, aScrollUp, aScrollDown, aScrollUpArtist, aScrollUpAlbum, aScrollDownArtist, aScrollDownAlbum, aPageUp, aPageDown, aMoveHome, aMoveEnd, aToggleInterface, aJumpToParentDir, aPressEnter, aPressSpace, aPreviousColumn, aNextColumn, aMasterScreen, aSlaveScreen, aVolumeUp, diff --git a/src/macro_utilities.h b/src/macro_utilities.h new file mode 100644 index 00000000..35af60e2 --- /dev/null +++ b/src/macro_utilities.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2008-2012 by Andrzej Rybczak * + * electricityispower@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + +#include "actions.h" + +struct PushCharacters : public Action +{ + template PushCharacters(Window **w, Iterator first, Iterator last) : Action(aMacroUtility, "") + { + construct(w, first, last); + } + + PushCharacters(Window **w, const std::initializer_list &v) : Action(aMacroUtility, "") + { + construct(w, v.begin(), v.end()); + } + + virtual void Run() + { + for (auto it = itsQueue.begin(); it != itsQueue.end(); ++it) + (*itsWindow)->PushChar(*it); + } + + private: + template void construct(Window **w, Iterator first, Iterator last) + { + itsWindow = w; + for (; first != last; ++first) + itsQueue.push_back(*first); + } + + Window **itsWindow; + std::vector itsQueue; +}; diff --git a/src/playlist.cpp b/src/playlist.cpp index 62c64bc9..2e2ff6e4 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -205,12 +205,6 @@ void Playlist::SpacePressed() } } -void Playlist::ReadKey(int &key) -{ - w->ReadKey(key); - UpdateTimer(); -} - void Playlist::MouseButtonPressed(MEVENT me) { if (w == Items && !Items->Empty() && Items->hasCoords(me.x, me.y)) diff --git a/src/playlist.h b/src/playlist.h index 9d634f9d..9d8fa5ea 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -42,7 +42,6 @@ class Playlist : public Screen virtual void EnterPressed(); virtual void SpacePressed(); - virtual void ReadKey(int &); virtual void MouseButtonPressed(MEVENT); virtual bool isTabbable() { return true; } diff --git a/src/screen.h b/src/screen.h index a73ac4fc..a1f0e3c0 100644 --- a/src/screen.h +++ b/src/screen.h @@ -75,10 +75,6 @@ class BasicScreen /// virtual void RefreshWindow() = 0; - /// see Screen::ReadKey() - /// - virtual void ReadKey(int &key) = 0; - /// @see Screen::Scroll() /// virtual void Scroll(Where where) = 0; @@ -204,10 +200,7 @@ template class Screen : public BasicScreen /// virtual void RefreshWindow(); - /// Reads a key from the screen - /// - virtual void ReadKey(int &key); - + /// Scrolls the screen by given amount of lines and /// if fancy scrolling feature is disabled, enters the /// loop that holds main loop until user releases the key @@ -250,11 +243,6 @@ template void Screen::RefreshWindow() w->Display(); } -template void Screen::ReadKey(int &key) -{ - w->ReadKey(key); -} - template void Screen::Scroll(Where where) { w->Scroll(where); diff --git a/src/window.cpp b/src/window.cpp index f954140a..47038599 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -371,8 +371,17 @@ bool Window::FDCallbacksListEmpty() const return itsFDs.empty(); } -void Window::ReadKey(int &read_key) const +int Window::ReadKey() { + int result; + // if there are characters in input queue, get them and + // return immediately. + if (!itsInputQueue.empty()) + { + result = itsInputQueue.front(); + itsInputQueue.pop(); + return result; + } // in pdcurses polling stdin doesn't work, so we can't poll // both stdin and other file descriptors in one select. the // workaround is to set the timeout of select to 0, poll @@ -401,7 +410,7 @@ void Window::ReadKey(int &read_key) const if (select(fd_max+1, &fdset, 0, 0, itsWindowTimeout < 0 ? 0 : &timeout) > 0) { # if !defined(USE_PDCURSES) - read_key = FD_ISSET(STDIN_FILENO, &fdset) ? wgetch(itsWindow) : ERR; + result = FD_ISSET(STDIN_FILENO, &fdset) ? wgetch(itsWindow) : ERR; # endif // !USE_PDCURSES for (FDCallbacks::const_iterator it = itsFDs.begin(); it != itsFDs.end(); ++it) if (FD_ISSET(it->first, &fdset)) @@ -409,18 +418,19 @@ void Window::ReadKey(int &read_key) const } # if !defined(USE_PDCURSES) else - read_key = ERR; + result = ERR; # else - read_key = wgetch(itsWindow); + result = wgetch(itsWindow); # endif + return result; } -void Window::ReadKey() const +void Window::PushChar(int ch) { - wgetch(itsWindow); + itsInputQueue.push(ch); } -std::string Window::GetString(const std::string &base, size_t length, size_t width, bool encrypted) const +std::string Window::GetString(const std::string &base, size_t length, size_t width, bool encrypted) { int input; size_t beginning, maxbeginning, minx, x, real_x, y, maxx, real_maxx; @@ -495,7 +505,7 @@ std::string Window::GetString(const std::string &base, size_t length, size_t wid wmove(itsWindow, y, x); prefresh(itsWindow, 0, 0, itsStartY, itsStartX, itsStartY+itsHeight-1, itsStartX+itsWidth-1); - ReadKey(input); + input = ReadKey(); switch (input) { diff --git a/src/window.h b/src/window.h index f047c72a..eeb5e6ec 100644 --- a/src/window.h +++ b/src/window.h @@ -36,6 +36,7 @@ #include #include #include +#include // define some Ctrl-? keys #define KEY_CTRL_A 1 @@ -275,12 +276,12 @@ namespace NCurses /// @see CreateHistory() /// std::string GetString(const std::string &base, size_t length = -1, - size_t width = 0, bool encrypted = 0) const; + 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) const + std::string GetString(size_t length = -1, size_t width = 0, bool encrypted = 0) { return GetString("", length, width, encrypted); } @@ -407,14 +408,13 @@ namespace NCurses /// bool FDCallbacksListEmpty() const; - /// Reads key from standard input and writes it into read_key variable - /// @param read_key variable for read key to be written into it + /// Reads key from standard input (or takes it from input queue) + /// and writes it into read_key variable /// - void ReadKey(int &read_key) const; + int ReadKey(); - /// Waits until user press a key. - /// - void ReadKey() const; + /// Push single character into input queue, so it can get consumed by ReadKey + void PushChar(int ch); /// Scrolls the window by amount of lines given in its parameter /// @param where indicates how many lines it has to scroll @@ -611,12 +611,17 @@ namespace NCurses int itsX; int itsY; - /// window's title + /// window title std::string itsTitle; /// stack of colors std::stack itsColors; + /// input queue of a window. you can put characters there using + /// PushChar and they will be immediately consumed and + /// returned by ReadKey + std::queue itsInputQueue; + /// containter used for additional file descriptors that have /// to be polled in ReadKey() and correspondent callbacks that /// are invoked if there is data available in them