main: check for strfsong() failure, add fallback
[ncmpc.git] / src / screen_find.c
blobb838421f4f94eadae78b382a7f086ec656f44925
1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2017 The Music Player Daemon Project
3 * Project homepage: http://musicpd.org
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.
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.
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.
20 #include "screen_find.h"
21 #include "screen_utils.h"
22 #include "screen_status.h"
23 #include "screen.h"
24 #include "keyboard.h"
25 #include "i18n.h"
26 #include "options.h"
27 #include "ncmpc.h"
29 #define FIND_PROMPT _("Find")
30 #define RFIND_PROMPT _("Find backward")
31 #define JUMP_PROMPT _("Jump")
33 /* query user for a string and find it in a list window */
34 bool
35 screen_find(struct list_window *lw, command_t findcmd,
36 list_window_callback_fn_t callback_fn,
37 void *callback_data)
39 bool found;
40 const char *prompt = FIND_PROMPT;
42 const bool reversed =
43 findcmd == CMD_LIST_RFIND || findcmd == CMD_LIST_RFIND_NEXT;
44 if (reversed)
45 prompt = RFIND_PROMPT;
47 switch (findcmd) {
48 case CMD_LIST_FIND:
49 case CMD_LIST_RFIND:
50 if (screen.findbuf) {
51 g_free(screen.findbuf);
52 screen.findbuf=NULL;
54 /* fall through */
56 case CMD_LIST_FIND_NEXT:
57 case CMD_LIST_RFIND_NEXT:
58 if (!screen.findbuf) {
59 char *value = options.find_show_last_pattern
60 ? (char *) -1 : NULL;
61 screen.findbuf=screen_readln(prompt,
62 value,
63 &screen.find_history,
64 NULL);
67 if (screen.findbuf == NULL)
68 return 1;
70 found = reversed
71 ? list_window_rfind(lw,
72 callback_fn, callback_data,
73 screen.findbuf,
74 options.find_wrap,
75 options.bell_on_wrap)
76 : list_window_find(lw,
77 callback_fn, callback_data,
78 screen.findbuf,
79 options.find_wrap,
80 options.bell_on_wrap);
81 if (!found) {
82 screen_status_printf(_("Unable to find \'%s\'"),
83 screen.findbuf);
84 screen_bell();
86 return 1;
87 default:
88 break;
90 return 0;
93 /* query user for a string and jump to the entry
94 * which begins with this string while the users types */
95 void
96 screen_jump(struct list_window *lw,
97 list_window_callback_fn_t callback_fn, void *callback_data,
98 list_window_paint_callback_t paint_callback, void *paint_data)
100 const int WRLN_MAX_LINE_SIZE = 1024;
101 int key = 65;
103 if (screen.findbuf) {
104 g_free(screen.findbuf);
105 screen.findbuf = NULL;
107 screen.findbuf = g_malloc0(WRLN_MAX_LINE_SIZE);
108 /* In screen.findbuf is the whole string which is displayed in the status_window
109 * and search_str is the string the user entered (without the prompt) */
110 char *search_str = screen.findbuf + g_snprintf(screen.findbuf, WRLN_MAX_LINE_SIZE, "%s: ", JUMP_PROMPT);
111 char *iter = search_str;
113 while(1) {
114 key = screen_getch(screen.findbuf);
115 /* if backspace or delete was pressed, process instead of ending loop */
116 if (key == KEY_BACKSPACE || key == KEY_DC) {
117 int i;
118 if (search_str <= g_utf8_find_prev_char(screen.findbuf, iter))
119 iter = g_utf8_find_prev_char(screen.findbuf, iter);
120 for (i = 0; *(iter + i) != '\0'; i++)
121 *(iter + i) = '\0';
122 continue;
124 /* if a control key was pressed, end loop */
125 else if (g_ascii_iscntrl(key) || key == KEY_NPAGE || key == KEY_PPAGE) {
126 break;
128 else {
129 *iter = key;
130 if (iter < screen.findbuf + WRLN_MAX_LINE_SIZE - 3)
131 ++iter;
133 list_window_jump(lw, callback_fn, callback_data, search_str);
135 /* repaint the list_window */
136 if (paint_callback != NULL)
137 list_window_paint2(lw, paint_callback, paint_data);
138 else
139 list_window_paint(lw, callback_fn, callback_data);
140 wrefresh(lw->w);
143 char *temp = g_strdup(search_str);
144 g_free(screen.findbuf);
145 screen.findbuf = temp;
147 /* ncmpc should get the command */
148 keyboard_unread(key);