2 * Copyright (c) 2006-2009 Ed Schouten <ed@80386.nl>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * @brief File browser in textual user interface.
35 #include "gui_internal.h"
36 #include "gui_vfslist.h"
41 * @brief Reference to window with pathname of current folder.
43 static WINDOW
*win_dirname
;
45 * @brief Reference to VFS object that is currently shown.
47 static struct vfsref
*vr_curdir
= NULL
;
49 * @brief List we use when displaying a file instead of a directory,
50 * containing only the file itself.
52 static struct vfslist vl_flist
= VFSLIST_INITIALIZER
;
54 * @brief Reference to window used as the file browser.
56 static struct gui_vfslist
*win_browser
;
58 * @brief The current filtering string that's being applied.
60 static char *locatestr
= NULL
;
63 * @brief Refresh the bar above the filebrowser to contain the proper
64 * filename and percentage.
67 gui_browser_dirname_refresh(void)
75 if (vr_curdir
!= NULL
) {
76 mvwaddstr(win_dirname
, 0, 1, vfs_filename(vr_curdir
));
77 if (locatestr
!= NULL
) {
78 waddstr(win_dirname
, " (");
79 waddstr(win_dirname
, _("filter"));
80 waddstr(win_dirname
, ": ");
81 waddstr(win_dirname
, locatestr
);
82 waddstr(win_dirname
, ")");
86 percent
= gui_vfslist_getpercentage(win_browser
);
87 plen
= strlen(percent
);
88 mvwaddstr(win_dirname
, 0, COLS
- plen
, percent
);
89 wnoutrefresh(win_dirname
);
95 * @brief Clean up our pseudo-directory data.
98 gui_browser_cleanup_flist(void)
102 /* Close our fake view */
103 while ((vr
= vfs_list_first(&vl_flist
)) != NULL
) {
104 vfs_list_remove(&vl_flist
, vr
);
113 gui_browser_init(void)
118 win_dirname
= newwin(1, 0, GUI_SIZE_BROWSER_DIRNAME_TOP
, 0);
119 clearok(win_dirname
, TRUE
);
121 wbkgdset(win_dirname
, COLOR_PAIR(GUI_COLOR_BAR
));
123 wbkgdset(win_dirname
, A_REVERSE
);
125 win_browser
= gui_vfslist_new(0);
126 gui_vfslist_setfocus(win_browser
, 1);
127 gui_vfslist_setcallback(win_browser
, gui_browser_dirname_refresh
);
128 gui_browser_dirname_refresh();
130 defdir
= config_getopt("gui.browser.defaultpath");
131 if (defdir
[0] != '\0') {
132 /* Open predefined directory */
133 vr_curdir
= vfs_lookup(defdir
, NULL
, NULL
, 0);
135 /* Open current directory */
136 cwd
= g_get_current_dir();
137 vr_curdir
= vfs_lookup(cwd
, NULL
, NULL
, 1);
141 if (vr_curdir
!= NULL
) {
142 vfs_populate(vr_curdir
);
143 gui_vfslist_setlist(win_browser
, vfs_population(vr_curdir
));
145 gui_msgbar_warn(_("Unable to open initial directory."));
147 gui_vfslist_move(win_browser
, 0, GUI_SIZE_BROWSER_TOP
,
148 COLS
, GUI_SIZE_BROWSER_HEIGHT
);
152 gui_browser_destroy(void)
155 gui_vfslist_destroy(win_browser
);
157 /* Clean up our mess */
158 gui_browser_cleanup_flist();
159 if (vr_curdir
!= NULL
)
160 vfs_close(vr_curdir
);
164 gui_browser_resize(void)
167 wresize(win_dirname
, 1, COLS
);
168 mvwin(win_dirname
, GUI_SIZE_BROWSER_DIRNAME_TOP
, 0);
169 clearok(win_dirname
, TRUE
);
172 gui_vfslist_move(win_browser
, 0, GUI_SIZE_BROWSER_TOP
,
173 COLS
, GUI_SIZE_BROWSER_HEIGHT
);
177 * Cursor manipulation
181 gui_browser_cursor_up(void)
183 gui_vfslist_cursor_up(win_browser
);
187 gui_browser_cursor_down(void)
189 gui_vfslist_cursor_down(win_browser
, 0);
193 gui_browser_cursor_pageup(void)
195 gui_vfslist_cursor_pageup(win_browser
);
199 gui_browser_cursor_pagedown(void)
201 gui_vfslist_cursor_pagedown(win_browser
);
205 gui_browser_cursor_head(void)
207 gui_vfslist_cursor_head(win_browser
);
211 gui_browser_cursor_tail(void)
213 gui_vfslist_cursor_tail(win_browser
);
217 * Change current directory
221 gui_browser_gotofile(struct vfsref
*vr
)
223 struct vfsref
*vrp
, *vrn
;
226 if ((vrp
= vfs_lookup("..", NULL
, vfs_filename(vr
), 1)) == NULL
)
228 if (vfs_populate(vrp
) != 0) {
229 /* Permission denied? */
234 for (vrn
= vfs_list_first(vfs_population(vrp
)), idx
= 1;
235 vrn
!= NULL
; vrn
= vfs_list_next(vrn
), idx
++) {
236 /* Select the previous directory */
237 if (strcmp(vfs_name(vr
), vfs_name(vrn
)) == 0)
241 /* Change the directory */
242 gui_browser_cleanup_flist();
243 vfs_close(vr_curdir
);
245 gui_vfslist_setlist(win_browser
, vfs_population(vr_curdir
));
248 gui_vfslist_setselected(win_browser
, vrn
, idx
);
252 gui_msgbar_warn(_("Unable to enter the parent directory."));
256 gui_browser_dir_parent(void)
259 if (vr_curdir
== NULL
)
262 if (locatestr
!= NULL
) {
263 /* First unset the filter if we have one */
264 gui_browser_cleanup_flist();
265 gui_vfslist_setlist(win_browser
, vfs_population(vr_curdir
));
269 gui_browser_gotofile(vr_curdir
);
273 gui_browser_dir_enter(void)
277 if (gui_vfslist_warn_isempty(win_browser
))
280 vr
= vfs_dup(gui_vfslist_getselected(win_browser
));
281 if (vfs_populate(vr
) != 0) {
282 if (vfs_populatable(vr
)) {
283 /* Permission denied? */
284 gui_msgbar_warn(_("Unable to enter the "
285 "selected directory."));
291 /* Change the directory */
292 gui_browser_cleanup_flist();
293 vfs_close(vr_curdir
);
295 gui_vfslist_setlist(win_browser
, vfs_population(vr_curdir
));
299 * Playlist manipulation
303 gui_browser_playq_add_tail(void)
307 if (gui_vfslist_warn_isempty(win_browser
))
310 vr
= gui_vfslist_getselected(win_browser
);
311 playq_song_add_tail(vr
);
312 gui_vfslist_cursor_down(win_browser
, 1);
316 gui_browser_playq_add_head(void)
320 if (gui_vfslist_warn_isempty(win_browser
))
323 vr
= gui_vfslist_getselected(win_browser
);
324 playq_song_add_head(vr
);
325 gui_vfslist_cursor_down(win_browser
, 1);
329 gui_browser_playq_add_after(void)
333 if (gui_vfslist_warn_isempty(win_browser
))
336 vr
= gui_vfslist_getselected(win_browser
);
337 gui_playq_song_add_after(vr
);
338 gui_vfslist_cursor_down(win_browser
, 1);
342 gui_browser_playq_add_before(void)
346 if (gui_vfslist_warn_isempty(win_browser
))
349 vr
= gui_vfslist_getselected(win_browser
);
350 gui_playq_song_add_before(vr
);
351 gui_vfslist_cursor_down(win_browser
, 1);
355 gui_browser_searchnext(const struct vfsmatch
*vm
)
357 return gui_vfslist_searchnext(win_browser
, vm
);
361 * @brief Change to a specified directory.
364 gui_browser_do_chdir(const char *path
)
369 if (vr_curdir
!= NULL
) {
370 /* Relative to the current node */
371 vr
= vfs_lookup(path
, NULL
, vfs_filename(vr_curdir
), 0);
373 /* Relative to the root */
374 vr
= vfs_lookup(path
, NULL
, NULL
, 0);
378 if (vfs_populate(vr
) == 0)
380 else if (!vfs_playable(vr
))
383 /* Replace old directory */
384 gui_browser_cleanup_flist();
385 if (vr_curdir
!= NULL
)
386 vfs_close(vr_curdir
);
390 /* Go inside the directory */
391 gui_vfslist_setlist(win_browser
,
394 /* Create a fake directory */
395 vfs_list_insert_tail(&vl_flist
, vfs_dup(vr
));
396 gui_vfslist_setlist(win_browser
, &vl_flist
);
402 bad
: gui_msgbar_warn(_("Unable to display the file or directory."));
408 gui_browser_chdir(void)
411 const char *curwd
= NULL
;
413 if (vr_curdir
!= NULL
)
414 curwd
= vfs_filename(vr_curdir
);
416 path
= gui_input_askstring(_("Change directory"), curwd
, NULL
);
420 gui_browser_do_chdir(path
);
425 gui_browser_setfocus(int focus
)
427 gui_vfslist_setfocus(win_browser
, focus
);
431 gui_browser_write_playlist(void)
436 fn
= gui_input_askstring(_("Write playlist to file"), NULL
, NULL
);
440 vr
= vfs_write_playlist(&playq_list
, vr_curdir
, fn
);
445 gui_msgbar_warn(_("Unable to write playlist."));
450 /* Replace old directory */
451 gui_browser_cleanup_flist();
452 if (vr_curdir
!= NULL
)
453 vfs_close(vr_curdir
);
456 /* Go inside the directory */
457 gui_vfslist_setlist(win_browser
, vfs_population(vr
));
461 gui_browser_fullpath(void)
463 gui_vfslist_fullpath(win_browser
);
467 gui_browser_locate(const struct vfsmatch
*vm
)
469 struct vfslist vl
= VFSLIST_INITIALIZER
;
471 if (vr_curdir
== NULL
)
474 /* Perform a search on the query */
475 vfs_locate(&vl
, vr_curdir
, vm
);
476 if (vfs_list_empty(&vl
))
479 gui_browser_cleanup_flist();
480 locatestr
= g_strdup(vfs_match_value(vm
));
481 vfs_list_move(&vl_flist
, &vl
);
482 gui_vfslist_setlist(win_browser
, &vl_flist
);
488 gui_browser_gotofolder(void)
491 if (gui_vfslist_warn_isempty(win_browser
))
494 gui_browser_gotofile(gui_vfslist_getselected(win_browser
));
498 gui_browser_gotohome(void)
500 gui_browser_do_chdir("~");