-/* Forward Declarations */
-
-static void clear_children(struct choosenode *cn);
-static struct choosenode *newnode(struct choosenode *parent,
- const char *path,
- const char *display,
- const char *sort,
- unsigned flags,
- void (*fill)(struct choosenode *));
-static void fill_root_node(struct choosenode *cn);
-static void fill_directory_node(struct choosenode *cn);
-static void got_files(void *v, int nvec, char **vec);
-static void got_resolved_file(void *v, const char *error, const char *track);
-static void got_dirs(void *v, int nvec, char **vec);
-
-static void expand_node(struct choosenode *cn, int contingent);
-static void contract_node(struct choosenode *cn);
-static void updated_node(struct choosenode *cn, int redisplay,
- const char *why);
-
-static void display_selection(struct choosenode *cn);
-static void clear_selection(struct choosenode *cn);
-
-static void redisplay_tree(const char *why);
-static struct displaydata display_tree(struct choosenode *cn, int x, int y);
-static void undisplay_tree(struct choosenode *cn);
-static void initiate_search(void);
-static void delete_widgets(struct choosenode *cn);
-static void expand_from(struct choosenode *cn);
-static struct choosenode *first_search_result(struct choosenode *cn);
-
-static void clicked_choosenode(GtkWidget attribute((unused)) *widget,
- GdkEventButton *event,
- gpointer user_data);
-
-static void activate_track_play(GtkMenuItem *menuitem, gpointer user_data);
-static void activate_track_properties(GtkMenuItem *menuitem, gpointer user_data);
-
-static gboolean sensitive_track_play(struct choosenode *cn);
-static gboolean sensitive_track_properties(struct choosenode *cn);
-
-static void activate_dir_play(GtkMenuItem *menuitem, gpointer user_data);
-static void activate_dir_properties(GtkMenuItem *menuitem, gpointer user_data);
-static void activate_dir_select(GtkMenuItem *menuitem, gpointer user_data);
-
-static gboolean sensitive_dir_play(struct choosenode *cn);
-static gboolean sensitive_dir_properties(struct choosenode *cn);
-static gboolean sensitive_dir_select(struct choosenode *cn);
-
-/** @brief Track menu items */
-static struct choose_menuitem track_menuitems[] = {
- { "Play track", activate_track_play, sensitive_track_play, 0, 0 },
- { "Track properties", activate_track_properties, sensitive_track_properties, 0, 0 },
- { 0, 0, 0, 0, 0 }
-};
-
-/** @brief Directory menu items */
-static struct choose_menuitem dir_menuitems[] = {
- { "Play all tracks", activate_dir_play, sensitive_dir_play, 0, 0 },
- { "Track properties", activate_dir_properties, sensitive_dir_properties, 0, 0 },
- { "Select all tracks", activate_dir_select, sensitive_dir_select, 0, 0 },
- { 0, 0, 0, 0, 0 }
-};
-
-/* Maintaining the data structure ------------------------------------------ */
-
-static char *cnflags(const struct choosenode *cn) {
- unsigned f = cn->flags, n;
- struct dynstr d[1];
-
- static const char *bits[] = {
- "expandable",
- "expanded",
- "displayed",
- "selected",
- "getting_files",
- "resolving_files",
- "getting_dirs",
- "contingent"
- };
-#define NBITS (sizeof bits / sizeof *bits)
-
- dynstr_init(d);
- if(!f)
- dynstr_append(d, '0');
- else {
- for(n = 0; n < NBITS; ++n) {
- const unsigned bit = 1 << n;
- if(f & bit) {
- if(d->nvec)
- dynstr_append(d, '|');
- dynstr_append_string(d, bits[n]);
- f ^= bit;
- }
- }
- if(f) {
- char buf[32];
- if(d->nvec)
- dynstr_append(d, '|');
- sprintf(buf, "%#x", f);
- dynstr_append_string(d, buf);
- }
- }
- dynstr_terminate(d);
- return d->vec;
-}
-
-/** @brief Create a new node */
-static struct choosenode *newnode(struct choosenode *parent,
- const char *path,
- const char *display,
- const char *sort,
- unsigned flags,
- void (*fill)(struct choosenode *)) {
- struct choosenode *const n = xmalloc(sizeof *n);
-
- D(("newnode %s %s", path, display));
- if(flags & CN_EXPANDABLE)
- assert(fill);
- else
- assert(!fill);
- n->parent = parent;
- n->path = path;
- n->display = display;
- n->sort = sort;
- n->flags = flags;
- nodevector_init(&n->children);
- n->fill = fill;
- if(parent)
- nodevector_append(&parent->children, n);
- return n;
-}
-
-/** @brief Called when a node has been filled
- *
- * Response for calling @c whenfilled.
- */
-static void filled(struct choosenode *cn) {
- when_filled_callback *const whenfilled = cn->whenfilled;
-
- if(whenfilled) {
- cn->whenfilled = 0;
- whenfilled(cn, cn->wfu);
- }
- if(nsearchvisible < nsearchresults) {
- /* There is still search expansion work to do */
- D(("filled %s %d/%d", cn->path, nsearchvisible, nsearchresults));
- expand_from(cn);
- }
- if(gets_in_flight == 0 && nsearchvisible < nsearchresults)
- expand_from(root);
-}
-
-/** @brief Fill the root */
-static void fill_root_node(struct choosenode *cn) {
- struct callbackdata *cbd;
-
- D(("fill_root_node"));
- clear_children(cn);
- /* More de-duping possible here */
- if(cn->flags & CN_GETTING_ANY)
- return;
- gtk_label_set_text(GTK_LABEL(report_label), "getting files");
- cbd = xmalloc(sizeof *cbd);
- cbd->u.choosenode = cn;
- disorder_eclient_dirs(client, got_dirs, "", 0, cbd);
- cbd = xmalloc(sizeof *cbd);
- cbd->u.choosenode = cn;
- disorder_eclient_files(client, got_files, "", 0, cbd);
- cn->flags |= CN_GETTING_FILES|CN_GETTING_DIRS;
- gets_in_flight += 2;
-}
-
-/** @brief Delete all the widgets owned by @p cn */
-static void delete_cn_widgets(struct choosenode *cn) {
- if(cn->arrow) {
- DW(arrow);
- gtk_widget_destroy(cn->arrow);
- cn->arrow = 0;
- }
- if(cn->label) {
- DW(label);
- gtk_widget_destroy(cn->label);
- cn->label = 0;
- }
- if(cn->marker) {
- DW(image);
- gtk_widget_destroy(cn->marker);
- cn->marker = 0;
- }
- if(cn->hbox) {
- DW(hbox);
- gtk_widget_destroy(cn->hbox);
- cn->hbox = 0;
- }
- if(cn->container) {
- DW(event_box);
- gtk_widget_destroy(cn->container);
- cn->container = 0;
- }