1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2010 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 */
20 #include "screen_find.h"
21 #include "screen_utils.h"
22 #include "screen_status.h"
23 #include "screen.h"
24 #include "i18n.h"
25 #include "options.h"
26 #include "ncmpc.h"
28 #define FIND_PROMPT _("Find")
29 #define RFIND_PROMPT _("Find backward")
30 #define JUMP_PROMPT _("Jump")
32 /* query user for a string and find it in a list window */
33 bool
34 screen_find(struct list_window *lw, command_t findcmd,
35 list_window_callback_fn_t callback_fn,
36 void *callback_data)
37 {
38 bool found;
39 const char *prompt = FIND_PROMPT;
41 const bool reversed =
42 findcmd == CMD_LIST_RFIND || findcmd == CMD_LIST_RFIND_NEXT;
43 if (reversed)
44 prompt = RFIND_PROMPT;
46 switch (findcmd) {
47 case CMD_LIST_FIND:
48 case CMD_LIST_RFIND:
49 if (screen.findbuf) {
50 g_free(screen.findbuf);
51 screen.findbuf=NULL;
52 }
53 /* continue... */
55 case CMD_LIST_FIND_NEXT:
56 case CMD_LIST_RFIND_NEXT:
57 if (!screen.findbuf) {
58 char *value = options.find_show_last_pattern
59 ? (char *) -1 : NULL;
60 screen.findbuf=screen_readln(prompt,
61 value,
62 &screen.find_history,
63 NULL);
64 }
66 if (screen.findbuf == NULL)
67 return 1;
69 found = reversed
70 ? list_window_rfind(lw,
71 callback_fn, callback_data,
72 screen.findbuf,
73 options.find_wrap,
74 options.bell_on_wrap)
75 : list_window_find(lw,
76 callback_fn, callback_data,
77 screen.findbuf,
78 options.find_wrap,
79 options.bell_on_wrap);
80 if (!found) {
81 screen_status_printf(_("Unable to find \'%s\'"),
82 screen.findbuf);
83 screen_bell();
84 }
85 return 1;
86 default:
87 break;
88 }
89 return 0;
90 }
92 /* query user for a string and jump to the entry
93 * which begins with this string while the users types */
94 void
95 screen_jump(struct list_window *lw,
96 list_window_callback_fn_t callback_fn,
97 list_window_paint_callback_t paint_callback,
98 void *callback_data)
99 {
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;
106 }
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;
123 }
124 /* if a control key was pressed, end loop */
125 else if (g_ascii_iscntrl(key) || key == KEY_NPAGE || key == KEY_PPAGE) {
126 break;
127 }
128 else {
129 *iter = key;
130 if (iter < screen.findbuf + WRLN_MAX_LINE_SIZE - 3)
131 ++iter;
132 }
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, callback_data);
138 else
139 list_window_paint(lw, callback_fn, callback_data);
140 wrefresh(lw->w);
141 }
143 /* ncmpc should get the command */
144 ungetch(key);
146 command_t cmd;
147 if ((cmd=get_keyboard_command()) != CMD_NONE)
148 do_input_event(cmd);
150 char *temp = g_strdup(search_str);
151 g_free(screen.findbuf);
152 screen.findbuf = temp;
153 }