Code

Bugfix from Niko Tyni, survive find operations on empty search results
[ncmpc.git] / src / screen_search.c
1 /* 
2  * $Id$
3  *
4  * (c) 2004 by Kalle Wallin <kaw@linux.se>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  *
19  */
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <glib.h>
25 #include <ncurses.h>
27 #include "config.h"
28 #ifndef DISABLE_SEARCH_SCREEN
29 #include "ncmpc.h"
30 #include "options.h"
31 #include "support.h"
32 #include "mpdclient.h"
33 #include "strfsong.h"
34 #include "command.h"
35 #include "screen.h"
36 #include "screen_utils.h"
37 #include "screen_browse.h"
39 #define SEARCH_TITLE  0
40 #define SEARCH_ARTIST 1
41 #define SEARCH_ALBUM  2
42 #define SEARCH_FILE   3
44 typedef struct {
45   int table;
46   char *label;
47 } search_type_t;
49 static search_type_t mode[] = {
50   { MPD_TABLE_TITLE,    N_("Title") },
51   { MPD_TABLE_ARTIST,   N_("Artist") },
52   { MPD_TABLE_ALBUM,    N_("Album") },
53   { MPD_TABLE_FILENAME, N_("Filename") },
54   { 0, NULL }
55 };
57 static list_window_t *lw = NULL;
58 static mpdclient_filelist_t *filelist = NULL;
59 static gchar *pattern = NULL;
61 /* the playlist have been updated -> fix highlights */
62 static void 
63 playlist_changed_callback(mpdclient_t *c, int event, gpointer data)
64 {
65   if( filelist==NULL )
66     return;
67   D("screen_search.c> playlist_callback() [%d]\n", event);
68   switch(event)
69     {
70     case PLAYLIST_EVENT_CLEAR:
71       clear_highlights(filelist);
72       break;
73     default:
74       sync_highlights(c, filelist);
75       break;
76     }
77 }
79 /* sanity check search mode value */
80 static void
81 search_check_mode(void)
82 {
83   int max = 0;
85   while( mode[max].label != NULL )
86     max++;
87   if( options.search_mode<0 )
88     options.search_mode = 0;
89   else if( options.search_mode>=max )
90     options.search_mode = max-1;
91 }
93 static void
94 search_clear(screen_t *screen, mpdclient_t *c, gboolean clear_pattern)
95 {
96   if( filelist )
97     {
98       mpdclient_remove_playlist_callback(c, playlist_changed_callback);
99       filelist = mpdclient_filelist_free(filelist);
100     }
101   if( clear_pattern && pattern )
102     {
103       g_free(pattern);
104       pattern = NULL;
105     }
108 static void
109 search_new(screen_t *screen, mpdclient_t *c)
111   search_clear(screen, c, TRUE);
112   
113   pattern = screen_readln(screen->status_window.w, 
114                           _("Search: "),
115                           NULL,
116                           NULL,
117                           NULL);
119   if( pattern && strcmp(pattern,"")==0 )
120     {
121       g_free(pattern);
122       pattern=NULL;
123     }
124   
125   if( pattern==NULL )
126     {
127       list_window_reset(lw);
128       return;
129     }
131   filelist = mpdclient_filelist_search(c, 
132                                        mode[options.search_mode].table,
133                                        pattern);
134   sync_highlights(c, filelist);
135   mpdclient_install_playlist_callback(c, playlist_changed_callback);
136   list_window_check_selected(lw, filelist->length);
139 static void
140 init(WINDOW *w, int cols, int rows)
142   lw = list_window_init(w, cols, rows);
145 static void
146 quit(void)
148   if( filelist )
149     filelist = mpdclient_filelist_free(filelist);
150   list_window_free(lw);
151   if( pattern )
152     g_free(pattern);
153   pattern = NULL;
156 static void
157 open(screen_t *screen, mpdclient_t *c)
159   if( pattern==NULL )
160     search_new(screen, c);
161   else
162     screen_status_printf(_("Press %s for a new search"),
163                          get_key_names(CMD_SCREEN_SEARCH,0));
164   search_check_mode();
167 static void
168 resize(int cols, int rows)
170   lw->cols = cols;
171   lw->rows = rows;
174 static void
175 close(void)
179 static void 
180 paint(screen_t *screen, mpdclient_t *c)
182   lw->clear = 1;
183   
184   if( filelist )
185     {
186       list_window_paint(lw, browse_lw_callback, (void *) filelist);
187       filelist->updated = FALSE;
188     }
189   else
190     {
191       wmove(lw->w, 0, 0);
192       wclrtobot(lw->w);
193     }
194   wnoutrefresh(lw->w);
197 void 
198 update(screen_t *screen, mpdclient_t *c)
200   if( filelist==NULL || filelist->updated )
201     {
202       paint(screen, c);
203       return;
204     }
205   list_window_paint(lw, browse_lw_callback, (void *) filelist);
206   wnoutrefresh(lw->w);
209 static char *
210 get_title(char *str, size_t size)
212   if( pattern )
213     g_snprintf(str, size, 
214                _("Search: Results for %s [%s]"), 
215                pattern,
216                _(mode[options.search_mode].label));
217   else
218     g_snprintf(str, size, _("Search: Press %s for a new search [%s]"),
219                get_key_names(CMD_SCREEN_SEARCH,0),
220                _(mode[options.search_mode].label));
221                
222   return str;
225 static list_window_t *
226 get_filelist_window()
228   return lw;
231 static int 
232 search_cmd(screen_t *screen, mpdclient_t *c, command_t cmd)
234   switch(cmd)
235     {
236     case CMD_PLAY:
237        browse_handle_enter(screen, c, lw, filelist);
238       return 1;
240     case CMD_SELECT:
241       if( browse_handle_select(screen, c, lw, filelist) == 0 )
242         {
243           /* continue and select next item... */
244           cmd = CMD_LIST_NEXT;
245         }
246       return 1;
248     case CMD_SEARCH_MODE:
249       options.search_mode++;
250       if( mode[options.search_mode].label == NULL )
251         options.search_mode = 0;
252       screen_status_printf(_("Search mode: %s"), 
253                            _(mode[options.search_mode].label));
254       /* continue and update... */
255     case CMD_SCREEN_UPDATE:
256       if( pattern )
257         {
258           search_clear(screen, c, FALSE);
259           filelist = mpdclient_filelist_search(c, 
260                                                mode[options.search_mode].table,
261                                                pattern);
262           sync_highlights(c, filelist);
263         }
264       return 1;
266     case CMD_SCREEN_SEARCH:
267       search_new(screen, c);
268       return 1;
270     case CMD_CLEAR:
271       search_clear(screen, c, TRUE);
272       list_window_reset(lw);
273       return 1;
275     case CMD_LIST_FIND:
276     case CMD_LIST_RFIND:
277     case CMD_LIST_FIND_NEXT:
278     case CMD_LIST_RFIND_NEXT:
279       if( filelist )
280         return screen_find(screen, c, 
281                            lw, filelist->length,
282                            cmd, browse_lw_callback, (void *) filelist);
283       else
284         return 1;
286     case CMD_MOUSE_EVENT:
287       return browse_handle_mouse_event(screen,c,lw,filelist);
289     default:
290       if( filelist )
291         return list_window_cmd(lw, filelist->length, cmd);
292     }
293   
294   return 0;
297 screen_functions_t *
298 get_screen_search(void)
300   static screen_functions_t functions;
302   memset(&functions, 0, sizeof(screen_functions_t));
303   functions.init   = init;
304   functions.exit   = quit;
305   functions.open   = open;
306   functions.close  = close;
307   functions.resize = resize;
308   functions.paint  = paint;
309   functions.update = update;
310   functions.cmd    = search_cmd;
311   functions.get_lw = get_filelist_window;
312   functions.get_title = get_title;
314   return &functions;
318 #endif /* ENABLE_SEARCH_SCREEN */