Add cyan.theme
[cmus.git] / search_mode.c
blobad595126abc90e13927a389c4dbd6009720ab026
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 <curses.h>
31 #include <ctype.h>
33 /* this is set in ui_curses.c */
34 enum search_direction search_direction = SEARCH_FORWARD;
36 /* current search string, this is set _only_ when user presses enter
37 * this string is used when 'n' or 'N' is pressed
38 * incremental search does not use this, it uses cmdline.line directly
40 char *search_str = NULL;
41 int search_restricted = 0;
43 static int search_found = 0;
44 static struct history search_history;
45 static char *search_history_filename;
46 static char *history_search_text = NULL;
48 static void update_search_line(const char *text, int restricted)
50 int len = strlen(text);
51 char ch = search_direction == SEARCH_FORWARD ? '/' : '?';
52 char *buf, *ptr;
54 buf = xnew(char, len + 2);
55 ptr = buf;
56 if (restricted)
57 *ptr++ = ch;
58 memcpy(ptr, text, len + 1);
59 cmdline_set_text(buf);
60 free(buf);
63 static int search_line_empty(void)
65 char ch;
67 if (cmdline.clen == 0)
68 return 1;
69 if (cmdline.clen > 1)
70 return 0;
71 ch = search_direction == SEARCH_FORWARD ? '/' : '?';
72 return cmdline.line[0] == ch;
75 static void parse_line(const char **text, int *restricted)
77 char ch = search_direction == SEARCH_FORWARD ? '/' : '?';
78 int r = 0;
80 if (cmdline.line[0] == ch) {
81 /* //WORDS or ??WORDS */
82 r = 1;
84 *text = cmdline.line + r;
85 *restricted = r;
88 static void reset_history_search(void)
90 history_reset_search(&search_history);
91 free(history_search_text);
92 history_search_text = NULL;
95 static void backspace(void)
97 if (cmdline.clen > 0) {
98 cmdline_backspace();
99 } else {
100 input_mode = NORMAL_MODE;
104 void search_mode_ch(uchar ch)
106 const char *text;
107 int restricted;
109 switch (ch) {
110 case 0x03: // ^C
111 case 0x07: // ^G
112 case 0x1B: // ESC
113 parse_line(&text, &restricted);
114 if (text[0]) {
115 history_add_line(&search_history, text);
116 cmdline_clear();
118 input_mode = NORMAL_MODE;
119 break;
120 case 0x0A:
121 parse_line(&text, &restricted);
122 if (text[0] == 0) {
123 /* cmdline is "/", "?", "//" or "??" */
124 if (search_str) {
125 /* use old search string */
126 search_restricted = restricted;
127 search_found = search_next(searchable, search_str, search_direction);
129 } else {
130 /* set new search string and add it to the history */
131 free(search_str);
132 search_str = xstrdup(text);
133 history_add_line(&search_history, text);
135 /* search not yet done if up or down arrow was pressed */
136 search_restricted = restricted;
137 search_found = search(searchable, search_str, search_direction, 0);
139 cmdline_clear();
140 if (!search_found)
141 search_not_found();
142 input_mode = NORMAL_MODE;
143 break;
144 case 127:
145 backspace();
146 break;
147 default:
148 if (ch < 0x20) {
149 return;
150 } else {
151 /* start from beginning if this is first char */
152 int beginning = search_line_empty();
154 /* save old value
156 * don't set search_{str,restricted} here because
157 * search can be cancelled by pressing ESC
159 restricted = search_restricted;
161 cmdline_insert_ch(ch);
162 parse_line(&text, &search_restricted);
163 search_found = search(searchable, text, search_direction, beginning);
165 /* restore old value */
166 search_restricted = restricted;
168 break;
170 reset_history_search();
173 void search_mode_key(int key)
175 const char *text;
176 int restricted;
178 switch (key) {
179 case KEY_DC:
180 /* save old value */
181 restricted = search_restricted;
183 cmdline_delete_ch();
184 parse_line(&text, &search_restricted);
185 if (text[0])
186 search_found = search(searchable, text, search_direction, 0);
188 /* restore old value */
189 search_restricted = restricted;
190 break;
191 case KEY_BACKSPACE:
192 backspace();
193 break;
194 case KEY_LEFT:
195 cmdline_move_left();
196 return;
197 case KEY_RIGHT:
198 cmdline_move_right();
199 return;
200 case KEY_HOME:
201 cmdline_move_home();
202 return;
203 case KEY_END:
204 cmdline_move_end();
205 return;
206 case KEY_UP:
207 parse_line(&text, &restricted);
208 if (history_search_text == NULL)
209 history_search_text = xstrdup(text);
210 text = history_search_forward(&search_history, history_search_text);
211 if (text)
212 update_search_line(text, restricted);
213 return;
214 case KEY_DOWN:
215 if (history_search_text) {
216 parse_line(&text, &restricted);
217 text = history_search_backward(&search_history, history_search_text);
218 if (text) {
219 update_search_line(text, restricted);
220 } else {
221 update_search_line(history_search_text, restricted);
224 return;
225 default:
226 return;
228 reset_history_search();
231 void search_mode_init(void)
233 search_history_filename = xstrjoin(cmus_config_dir, "/search-history");
234 history_load(&search_history, search_history_filename, 100);
237 void search_mode_exit(void)
239 history_save(&search_history);
240 free(search_history_filename);