Small clean up to http_open()
[cmus.git] / search_mode.c
blob60834ced6a29a0b42c8bc06a1b43814196eb4c6f
1 /*
2 * Copyright 2004 Timo Hirvonen
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
17 * 02111-1307, USA.
20 #include "search_mode.h"
21 #include "cmdline.h"
22 #include "history.h"
23 #include "ui_curses.h"
24 #include "search.h"
25 #include "xmalloc.h"
26 #include "xstrjoin.h"
27 #include "misc.h"
28 #include "lib.h"
30 #include <ctype.h>
32 #if defined(__sun__)
33 #include <ncurses.h>
34 #else
35 #include <curses.h>
36 #endif
38 /* this is set in ui_curses.c */
39 enum search_direction search_direction = SEARCH_FORWARD;
41 /* current search string, this is set _only_ when user presses enter
42 * this string is used when 'n' or 'N' is pressed
43 * incremental search does not use this, it uses cmdline.line directly
45 char *search_str = NULL;
46 int search_restricted = 0;
48 static int search_found = 0;
49 static struct history search_history;
50 static char *search_history_filename;
51 static char *history_search_text = NULL;
53 static void update_search_line(const char *text, int restricted)
55 int len = strlen(text);
56 char ch = search_direction == SEARCH_FORWARD ? '/' : '?';
57 char *buf, *ptr;
59 buf = xnew(char, len + 2);
60 ptr = buf;
61 if (restricted)
62 *ptr++ = ch;
63 memcpy(ptr, text, len + 1);
64 cmdline_set_text(buf);
65 free(buf);
68 static int search_line_empty(void)
70 char ch;
72 if (cmdline.clen == 0)
73 return 1;
74 if (cmdline.clen > 1)
75 return 0;
76 ch = search_direction == SEARCH_FORWARD ? '/' : '?';
77 return cmdline.line[0] == ch;
80 static void parse_line(const char **text, int *restricted)
82 char ch = search_direction == SEARCH_FORWARD ? '/' : '?';
83 int r = 0;
85 if (cmdline.line[0] == ch) {
86 /* //WORDS or ??WORDS */
87 r = 1;
89 *text = cmdline.line + r;
90 *restricted = r;
93 static void reset_history_search(void)
95 history_reset_search(&search_history);
96 free(history_search_text);
97 history_search_text = NULL;
100 static void backspace(void)
102 if (cmdline.clen > 0) {
103 cmdline_backspace();
104 } else {
105 input_mode = NORMAL_MODE;
109 static void delete(void)
111 /* save old value */
112 int restricted = search_restricted;
113 const char *text;
115 cmdline_delete_ch();
116 parse_line(&text, &search_restricted);
117 if (text[0])
118 search_found = search(searchable, text, search_direction, 0);
120 /* restore old value */
121 search_restricted = restricted;
124 void search_mode_ch(uchar ch)
126 const char *text;
127 int restricted;
129 switch (ch) {
130 case 0x01: // ^A
131 cmdline_move_home();
132 break;
133 case 0x02: // ^B
134 cmdline_move_left();
135 break;
136 case 0x04: // ^D
137 delete();
138 break;
139 case 0x05: // ^E
140 cmdline_move_end();
141 break;
142 case 0x06: // ^F
143 cmdline_move_right();
144 break;
145 case 0x03: // ^C
146 case 0x07: // ^G
147 case 0x1B: // ESC
148 parse_line(&text, &restricted);
149 if (text[0]) {
150 history_add_line(&search_history, text);
151 cmdline_clear();
153 input_mode = NORMAL_MODE;
154 break;
155 case 0x0A:
156 parse_line(&text, &restricted);
157 if (text[0] == 0) {
158 /* cmdline is "/", "?", "//" or "??" */
159 if (search_str) {
160 /* use old search string */
161 search_restricted = restricted;
162 search_found = search_next(searchable, search_str, search_direction);
164 } else {
165 /* set new search string and add it to the history */
166 free(search_str);
167 search_str = xstrdup(text);
168 history_add_line(&search_history, text);
170 /* search not yet done if up or down arrow was pressed */
171 search_restricted = restricted;
172 search_found = search(searchable, search_str, search_direction, 0);
174 cmdline_clear();
175 if (!search_found)
176 search_not_found();
177 input_mode = NORMAL_MODE;
178 break;
179 case 0x0B:
180 cmdline_clear_end();
181 break;
182 case 0x15:
183 cmdline_backspace_to_bol();
184 break;
185 case 0x08: // ^H
186 case 127:
187 backspace();
188 break;
189 default:
190 if (ch < 0x20) {
191 return;
192 } else {
193 /* start from beginning if this is first char */
194 int beginning = search_line_empty();
196 /* save old value
198 * don't set search_{str,restricted} here because
199 * search can be cancelled by pressing ESC
201 restricted = search_restricted;
203 cmdline_insert_ch(ch);
204 parse_line(&text, &search_restricted);
205 search_found = search(searchable, text, search_direction, beginning);
207 /* restore old value */
208 search_restricted = restricted;
210 break;
212 reset_history_search();
215 void search_mode_key(int key)
217 const char *text;
218 int restricted;
220 switch (key) {
221 case KEY_DC:
222 delete();
223 break;
224 case KEY_BACKSPACE:
225 backspace();
226 break;
227 case KEY_LEFT:
228 cmdline_move_left();
229 return;
230 case KEY_RIGHT:
231 cmdline_move_right();
232 return;
233 case KEY_HOME:
234 cmdline_move_home();
235 return;
236 case KEY_END:
237 cmdline_move_end();
238 return;
239 case KEY_UP:
240 parse_line(&text, &restricted);
241 if (history_search_text == NULL)
242 history_search_text = xstrdup(text);
243 text = history_search_forward(&search_history, history_search_text);
244 if (text)
245 update_search_line(text, restricted);
246 return;
247 case KEY_DOWN:
248 if (history_search_text) {
249 parse_line(&text, &restricted);
250 text = history_search_backward(&search_history, history_search_text);
251 if (text) {
252 update_search_line(text, restricted);
253 } else {
254 update_search_line(history_search_text, restricted);
257 return;
258 default:
259 return;
261 reset_history_search();
264 void search_mode_init(void)
266 search_history_filename = xstrjoin(cmus_config_dir, "/search-history");
267 history_load(&search_history, search_history_filename, 100);
270 void search_mode_exit(void)
272 history_save(&search_history);
273 free(search_history_filename);