Bindings: GetKeyNames() returns std::string
[ncmpc-debian.git] / src / HelpPage.cxx
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2018 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19
20 #include "HelpPage.hxx"
21 #include "PageMeta.hxx"
22 #include "ListPage.hxx"
23 #include "ListRenderer.hxx"
24 #include "ListText.hxx"
25 #include "screen_find.hxx"
26 #include "paint.hxx"
27 #include "Bindings.hxx"
28 #include "GlobalBindings.hxx"
29 #include "config.h"
30 #include "i18n.h"
31 #include "util/Macros.hxx"
32 #include "util/StringUTF8.hxx"
33
34 #include <assert.h>
35
36 struct HelpRow {
37         signed char highlight;
38         Command command;
39         const char *text;
40
41         constexpr HelpRow(signed char _highlight,
42                           Command _command,
43                           const char *_text=nullptr)
44                 :highlight(_highlight), command(_command), text(_text) {}
45
46         constexpr HelpRow(Command _command,
47                           const char *_text=nullptr)
48                 :HelpRow(0, _command, _text) {}
49 };
50
51 static constexpr HelpRow HLINE{2, Command::NONE};
52
53 static constexpr HelpRow
54 Heading(const char *text)
55 {
56         return {1, Command::NONE, text};
57 }
58
59 static constexpr HelpRow help_text[] = {
60         Heading(N_("Movement")),
61         HLINE,
62         Command::LIST_PREVIOUS,
63         Command::LIST_NEXT,
64         Command::LIST_TOP,
65         Command::LIST_MIDDLE,
66         Command::LIST_BOTTOM,
67         Command::LIST_PREVIOUS_PAGE,
68         Command::LIST_NEXT_PAGE,
69         Command::LIST_FIRST,
70         Command::LIST_LAST,
71         Command::LIST_RANGE_SELECT,
72         Command::LIST_SCROLL_UP_LINE,
73         Command::LIST_SCROLL_DOWN_LINE,
74         Command::LIST_SCROLL_UP_HALF,
75         Command::LIST_SCROLL_DOWN_HALF,
76         Command::NONE,
77
78         Command::SCREEN_PREVIOUS,
79         Command::SCREEN_NEXT,
80         Command::SCREEN_SWAP,
81         Command::SCREEN_HELP,
82         Command::SCREEN_PLAY,
83         Command::SCREEN_FILE,
84 #ifdef ENABLE_ARTIST_SCREEN
85         Command::SCREEN_ARTIST,
86 #endif
87 #ifdef ENABLE_SEARCH_SCREEN
88         Command::SCREEN_SEARCH,
89 #endif
90 #ifdef ENABLE_LYRICS_SCREEN
91         Command::SCREEN_LYRICS,
92 #endif
93 #ifdef ENABLE_OUTPUTS_SCREEN
94         Command::SCREEN_OUTPUTS,
95 #endif
96 #ifdef ENABLE_CHAT_SCREEN
97         Command::SCREEN_CHAT,
98 #endif
99 #ifdef ENABLE_KEYDEF_SCREEN
100         Command::SCREEN_KEYDEF,
101 #endif
102
103         Command::NONE,
104         Command::NONE,
105         Heading(N_("Global")),
106         HLINE,
107         Command::STOP,
108         Command::PAUSE,
109         Command::CROP,
110         Command::TRACK_NEXT,
111         Command::TRACK_PREVIOUS,
112         Command::SEEK_FORWARD,
113         Command::SEEK_BACKWARD,
114         Command::VOLUME_DOWN,
115         Command::VOLUME_UP,
116         Command::NONE,
117         Command::REPEAT,
118         Command::RANDOM,
119         Command::SINGLE,
120         Command::CONSUME,
121         Command::CROSSFADE,
122         Command::SHUFFLE,
123         Command::DB_UPDATE,
124         Command::NONE,
125         Command::LIST_FIND,
126         Command::LIST_RFIND,
127         Command::LIST_FIND_NEXT,
128         Command::LIST_RFIND_NEXT,
129         Command::LIST_JUMP,
130         Command::TOGGLE_FIND_WRAP,
131         Command::LOCATE,
132 #ifdef ENABLE_SONG_SCREEN
133         Command::SCREEN_SONG,
134 #endif
135         Command::NONE,
136         Command::QUIT,
137
138         Command::NONE,
139         Command::NONE,
140         Heading(N_("Queue screen")),
141         HLINE,
142         { Command::PLAY, N_("Play") },
143         Command::DELETE,
144         Command::CLEAR,
145         Command::LIST_MOVE_UP,
146         Command::LIST_MOVE_DOWN,
147         Command::ADD,
148         Command::SAVE_PLAYLIST,
149         { Command::SCREEN_UPDATE, N_("Center") },
150         Command::SELECT_PLAYING,
151         Command::TOGGLE_AUTOCENTER,
152
153         Command::NONE,
154         Command::NONE,
155         Heading(N_("Browse screen")),
156         HLINE,
157         { Command::PLAY, N_("Enter directory/Select and play song") },
158         Command::SELECT,
159         Command::ADD,
160         Command::SAVE_PLAYLIST,
161         { Command::DELETE, N_("Delete playlist") },
162         Command::GO_PARENT_DIRECTORY,
163         Command::GO_ROOT_DIRECTORY,
164         Command::SCREEN_UPDATE,
165
166 #ifdef ENABLE_SEARCH_SCREEN
167         Command::NONE,
168         Command::NONE,
169         Heading(N_("Search screen")),
170         HLINE,
171         { Command::SCREEN_SEARCH, N_("New search") },
172         { Command::PLAY, N_("Select and play") },
173         Command::SELECT,
174         { Command::ADD, N_("Append song to queue") },
175         Command::SELECT_ALL,
176         Command::SEARCH_MODE,
177 #endif
178 #ifdef ENABLE_LYRICS_SCREEN
179         Command::NONE,
180         Command::NONE,
181         Heading(N_("Lyrics screen")),
182         HLINE,
183         { Command::SCREEN_LYRICS, N_("View Lyrics") },
184         { Command::SELECT, N_("(Re)load lyrics") },
185         /* to translators: this hotkey aborts the retrieval of lyrics
186            from the server */
187         { Command::INTERRUPT, N_("Interrupt retrieval") },
188         { Command::LYRICS_UPDATE, N_("Download lyrics for currently playing song") },
189         { Command::EDIT, N_("Add or edit lyrics") },
190         { Command::SAVE_PLAYLIST, N_("Save lyrics") },
191         { Command::DELETE, N_("Delete saved lyrics") },
192 #endif
193 #ifdef ENABLE_OUTPUTS_SCREEN
194         Command::NONE,
195         Command::NONE,
196         Heading(N_("Outputs screen")),
197         HLINE,
198         { Command::PLAY, N_("Enable/disable output") },
199 #endif
200 #ifdef ENABLE_CHAT_SCREEN
201         Command::NONE,
202         Command::NONE,
203         Heading(N_("Chat screen")),
204         HLINE,
205         { Command::PLAY, N_("Write a message") },
206 #endif
207 #ifdef ENABLE_KEYDEF_SCREEN
208         Command::NONE,
209         Command::NONE,
210         Heading(N_("Keydef screen")),
211         HLINE,
212         { Command::PLAY, N_("Edit keydefs for selected command") },
213         { Command::DELETE, N_("Remove selected keydef") },
214         { Command::ADD, N_("Add a keydef") },
215         { Command::GO_PARENT_DIRECTORY, N_("Go up a level") },
216         { Command::SAVE_PLAYLIST, N_("Apply and save changes") },
217 #endif
218 };
219
220 class HelpPage final : public ListPage, ListRenderer, ListText {
221         ScreenManager &screen;
222
223 public:
224         HelpPage(ScreenManager &_screen, WINDOW *w, Size size)
225                 :ListPage(w, size), screen(_screen) {
226                 lw.hide_cursor = true;
227                 lw.SetLength(ARRAY_SIZE(help_text));
228         }
229
230 public:
231         /* virtual methods from class ListRenderer */
232         void PaintListItem(WINDOW *w, unsigned i,
233                            unsigned y, unsigned width,
234                            bool selected) const noexcept override;
235
236         /* virtual methods from class ListText */
237         const char *GetListItemText(char *buffer, size_t size,
238                                     unsigned i) const noexcept override;
239
240         /* virtual methods from class Page */
241         void Paint() const noexcept override;
242         bool OnCommand(struct mpdclient &c, Command cmd) override;
243
244         const char *GetTitle(char *, size_t) const noexcept override {
245                 return _("Help");
246         }
247 };
248
249 const char *
250 HelpPage::GetListItemText(char *, size_t, unsigned i) const noexcept
251 {
252         const auto *row = &help_text[i];
253
254         assert(i < ARRAY_SIZE(help_text));
255
256         if (row->text != nullptr)
257                 return gettext(row->text);
258
259         if (row->command != Command::NONE)
260                 return get_key_description(row->command);
261
262         return "";
263 }
264
265 static std::unique_ptr<Page>
266 help_init(ScreenManager &screen, WINDOW *w, Size size)
267 {
268         return std::make_unique<HelpPage>(screen, w, size);
269 }
270
271 void
272 HelpPage::PaintListItem(WINDOW *w, unsigned i,
273                         unsigned y, unsigned width,
274                         gcc_unused bool selected) const noexcept
275 {
276         const auto *row = &help_text[i];
277
278         assert(i < ARRAY_SIZE(help_text));
279
280         row_color(w, row->highlight ? Style::LIST_BOLD : Style::LIST, false);
281
282         wclrtoeol(w);
283
284         if (row->command == Command::NONE) {
285                 if (row->text != nullptr)
286                         mvwaddstr(w, y, 6, gettext(row->text));
287                 else if (row->highlight == 2)
288                         mvwhline(w, y, 3, ACS_HLINE, width - 6);
289         } else {
290                 const auto key =
291                         GetGlobalKeyBindings().GetKeyNames(row->command);
292
293                 if (utf8_width(key.c_str()) < 20)
294                         wmove(w, y, 20 - utf8_width(key.c_str()));
295                 waddstr(w, key.c_str());
296                 mvwaddch(w, y, 21, ':');
297                 mvwaddstr(w, y, 23,
298                           row->text != nullptr
299                           ? gettext(row->text)
300                           : get_key_description(row->command));
301         }
302 }
303
304 void
305 HelpPage::Paint() const noexcept
306 {
307         lw.Paint(*this);
308 }
309
310 bool
311 HelpPage::OnCommand(struct mpdclient &c, Command cmd)
312 {
313         if (ListPage::OnCommand(c, cmd))
314                 return true;
315
316         lw.SetCursor(lw.start);
317         if (screen_find(screen, &lw, cmd, *this)) {
318                 /* center the row */
319                 lw.Center(lw.selected);
320                 SetDirty();
321                 return true;
322         }
323
324         return false;
325 }
326
327 const PageMeta screen_help = {
328         "help",
329         N_("Help"),
330         Command::SCREEN_HELP,
331         help_init,
332 };