/*}}}*/ void prepend_child(struct node *child, struct node *parent)/*{{{*/ { child->parent = parent; if (parent) { prepend_node(child, &parent->kids); } else { struct node *narrow_top; narrow_top = get_narrow_top(); prepend_node(child, narrow_top ? &narrow_top->kids : &top); } }
/*}}}*/ struct node *lookup_node(char *path, int allow_zero_index, struct node **parent)/*{{{*/ { char *p = path; int n, nc, idx, tidx, aidx, ncomp, comp10; int direction; struct links *x; struct node *y = NULL; struct node *narrow_top; narrow_top = get_narrow_top(); if (narrow_top) { /* Special case to allow user to do operations on the node to which the * view is currently narrowed. (This doesn't apply to 'top' which is just a * skeleton entry.) */ if (!strcmp(path, ".")) { return narrow_top; } x = &(narrow_top->kids); } else { x = ⊤ } ncomp = 1; if (parent) *parent = NULL; while (*p) { n = sscanf(p, "%d%n", &idx, &nc); if (n != 1) { fprintf(stderr, "Bad path expression found, starting [%s]\n", p); return NULL; } p += nc; if (idx > 0) { direction = 1; aidx = idx; } else if (idx < 0) { direction = 0; aidx = -idx; } else { if (allow_zero_index) { if (*p) { fprintf(stderr, "Zero index only allowed as last component\n"); return NULL; } else { /* This is a special cheat to allow inserting entries at the start or end of a chain for the 'above' and 'below' commands */ return (struct node *) x; } } else { fprintf(stderr, "Zero in index not allowed\n"); return NULL; } } if (x->next == (struct node *) x) { fprintf(stderr, "Path [%s] doesn't exist - tree not that deep\n", path); return NULL; } comp10 = ncomp % 10; for (y = direction ? x->next : x->prev, tidx = aidx; --tidx;) { y = direction ? y->chain.next : y->chain.prev; if (y == (struct node *) x) { fprintf(stderr, "Can't find entry %d for %d%s component of path %s\n", idx, ncomp, (comp10 == 1) ? "st" : (comp10 == 2) ? "nd" : (comp10 == 3) ? "rd" : "th", path); return NULL; } } if (*p == '.') { p++; x = &y->kids; if (parent) *parent = y; } ncomp++; } return y; }
/*}}}*/ int process_list(char **x)/*{{{*/ { struct list_options options; int options_done = 0; int any_paths = 0; char index_buffer[256]; char *y; enum Priority prio = PRI_NORMAL, prio_to_use, node_prio; int prio_set = 0; time_t now = time(NULL); unsigned char *hits; int node_index, n_nodes; options.monochrome = 0; options.show_all = 0; options.show_postponed = 0; options.verbose = 0; options.set_depth = 0; if ( (getenv("TDL_LIST_MONOCHROME") != NULL) || (isatty(STDOUT_FILENO) == 0) ) { options.monochrome = 1; } /* Initialisation to support searching */ node_index = 0; allocate_indices(&top, &node_index); n_nodes = node_index; hits = n_nodes ? new_array(unsigned char, n_nodes) : NULL; /* all nodes match until proven otherwise */ memset(hits, 1, n_nodes); while ((y = *x) != 0) { /* An argument starting '1' or '+1' or '+-1' (or '-1' after '--') is * treated as the path of the top node to show */ if (isdigit(y[0]) || (y[0] == '.') || (options_done && (y[0] == '-') && isdigit(y[1])) || ((y[0] == '+') && (isdigit(y[1]) || ((y[1] == '-' && isdigit(y[2])))))) { struct node *n = lookup_node(y, 0, NULL); int summarise_kids; if (!n) return -1; any_paths = 1; index_buffer[0] = '\0'; strcat(index_buffer, y); summarise_kids = (options.set_depth && (options.depth==0)); if (hits[n->iscratch]) { print_details(n, 0, summarise_kids, &options, index_buffer, now); } if (!options.set_depth || (options.depth > 0)) { node_prio = n->priority; /* If the priority has been set on the cmd line, always use that. * Otherwise, use the priority from the specified node, _except_ when * that is higher than normal, in which case use normal. */ prio_to_use = (prio_set) ? prio : ((node_prio > prio) ? prio : node_prio); list_chain(&n->kids, INDENT_TAB, 0, &options, index_buffer, prio_to_use, now, hits); } } else if ((y[0] == '-') && (y[1] == '-')) { options_done = 1; } else if (y[0] == '-') { while (*++y) { switch (*y) { case 'v': options.verbose = 1; break; case 'a': options.show_all = 1; break; case 'm': options.monochrome = 1; break; case 'p': options.show_postponed = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': options.set_depth = 1; options.depth = (*y) - '1'; break; default: fprintf(stderr, "Unrecognized option : -%c\n", *y); break; } } } else if (y[0] == '/') { /* search expression */ merge_search_condition(hits, n_nodes, y+1); } else { int error; prio = parse_priority(y, &error); if (error < 0) return error; prio_set = 1; } x++; } colours_init(&options); if (!any_paths) { struct node *narrow_top = get_narrow_top(); if (narrow_top) { index_buffer[0] = 0; if (hits[narrow_top->iscratch]) { int summarise_kids = (options.set_depth && (options.depth==0)); print_details(narrow_top, 0, summarise_kids, &options, index_buffer, now); } if (!options.set_depth || (options.depth > 0)) { list_chain(&narrow_top->kids, 0, 1, &options, index_buffer, prio, now, hits); } } else { index_buffer[0] = 0; list_chain(&top, 0, 0, &options, index_buffer, prio, now, hits); } } if (hits) free(hits); return 0; }