Fall back on index for sort if the due date is the same, not just if both due dates...
[tdl.git] / list.c
CommitLineData
7024e37b
JW
1/*
2 $Header: /cvs/src/tdl/list.c,v 1.20.2.1 2004/01/07 00:09:05 richard Exp $
3
4 tdl - A console program for managing to-do lists
5 Copyright (C) 2001,2002,2003,2004,2005 Richard P. Curnow
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20 */
21
22#include <time.h>
23#include <string.h>
24#include <assert.h>
25#include <ctype.h>
26#include <unistd.h>
27#include "tdl.h"
28
29struct list_options {
30 unsigned monochrome:1;
31 unsigned show_all:1;
32 unsigned show_postponed:1;
33 unsigned verbose:1;
34 unsigned set_depth:1;
35 int depth;
36};
37
38#define INDENT_TAB 3
39
40/*{{{ Colour definitions */
41#define RED "\e[31m\e[1m"
42#define GREEN "\e[32m"
43#define YELLOW "\e[33m\e[1m"
44#define BLUE "\e[34m"
45#define MAGENTA "\e[35m"
46#define CYAN "\e[36m"
47#define NORMAL "\e[0m"
48#define DIM "\e[37m\e[2m"
49#define DIMCYAN "\e[36m\e[2m"
50
51/* Table to map priority levels to colours */
52static char *colour_table[] = {
53 NORMAL, BLUE, CYAN, NORMAL, YELLOW, RED
54};
55
56static char *priority_text[] = {
57 "UNKNOWN!", "verylow", "low", "normal", "high", "urgent"
58};
59
60/*}}}*/
61void do_indent(int indent)/*{{{*/
62{
63 int i;
64 for (i=0; i<indent; i++) putchar(' ');
65}
66/*}}}*/
67void do_bullet_indent(int indent)/*{{{*/
68{
69 int i;
70 int n;
71 n = indent - 2;
72 for (i=0; i<indent; i++) putchar((i == n) ? '-' : ' ');
73}
74/*}}}*/
75static void print_timestamp(int timestamp, char *leader, int indent, int monochrome)/*{{{*/
76{
77 char buffer[32];
78 time_t now, timestamp2;
79 long diff, days_ago, days_ahead;
80
81 now = time(NULL);
82 diff = now - timestamp;
83 days_ago = (diff + ((diff > 0) ? 43200 : -43200)) / 86400;
84 timestamp2 = (time_t) timestamp;
85 strftime(buffer, sizeof(buffer), "%a %d %b %Y %H:%M",
86 localtime(&timestamp2));
87 do_indent(indent+2);
88 if (days_ago < 0) {
89 days_ahead = - days_ago;
90 if (monochrome) {
91 printf("%s: %s (%ld day%s ahead)\n", leader, buffer, days_ago, (days_ahead == 1) ? "" : "s");
92 } else {
93 printf("%s%s:%s %s %s(%ld day%s ahead)%s\n", GREEN, leader, NORMAL, buffer, MAGENTA, days_ahead, (days_ahead == 1) ? "" : "s", NORMAL);
94 }
95 } else {
96 if (monochrome) {
97 printf("%s: %s (%ld day%s ago)\n", leader, buffer, days_ago, (days_ago == 1) ? "" : "s");
98 } else {
99 printf("%s%s:%s %s (%ld day%s ago)\n", GREEN, leader, NORMAL, buffer, days_ago, (days_ago == 1) ? "" : "s");
100 }
101 }
102}
103/*}}}*/
104static void count_kids(struct links *x, int *n_kids, int *n_done_kids, int *n_open_kids)/*{{{*/
105{
106 int nk, ndk;
107 struct node *y;
108
109 nk = ndk = 0;
110 for (y = x->next;
111 y != (struct node *) x;
112 y = y->chain.next) {
113 if (y->done) ndk++;
114 nk++;
115 }
116
117 if (n_kids) *n_kids = nk;
118 if (n_done_kids) *n_done_kids = ndk;
119 if (n_open_kids) *n_open_kids = (nk - ndk);
120 return;
121}
122/*}}}*/
123static void print_details(struct node *y, int indent, int summarise_kids, const struct list_options *options, char *index_buffer, time_t now)/*{{{*/
124{
125 int is_done;
126 int is_ignored;
127 int is_postponed;
128 int is_deferred;
129 char *p;
130 int n_kids, n_open_kids;
131 int show_state;
132 char *narrow_prefix;
133 int index_buffer_len;
134
135 is_done = (y->done > 0);
136 is_ignored = (y->done == IGNORED_TIME);
137 is_postponed = (y->arrived == POSTPONED_TIME);
138 is_deferred = (y->arrived > now);
139 if (!options->show_all && is_done) return;
140
141 do_indent(indent);
142 count_kids(&y->kids, &n_kids, NULL, &n_open_kids);
143 show_state = options->show_all || options->show_postponed;
144 index_buffer_len = strlen(index_buffer);
145 narrow_prefix = get_narrow_prefix();
146
147 if (narrow_prefix) {
148 if (options->monochrome) printf("%s%s", narrow_prefix, index_buffer_len ? "." : "");
149 else printf("%s%s%s%s", BLUE, narrow_prefix, index_buffer_len ? "." : "", NORMAL);
150 }
151
152 if (options->monochrome) printf("%s", index_buffer);
153 else printf("%s%s%s", GREEN, index_buffer, NORMAL);
154
155 if (summarise_kids && (n_kids > 0)) {
156 if (options->monochrome) printf(" [%d/%d]", n_open_kids, n_kids);
157 else printf(" %s[%d/%d]%s", CYAN, n_open_kids, n_kids, NORMAL);
158 }
159
160 if (show_state && !options->verbose) {
161 if (is_ignored) {
162 if (options->monochrome) printf(" (IGNORED)");
163 else printf(" %s(IGNORED)%s", BLUE, NORMAL);
164 } else if (is_done) {
165 if (options->monochrome) printf(" (DONE)");
166 else printf(" %s(DONE)%s", CYAN, NORMAL);
167 } else if (is_postponed) {
168 if (options->monochrome) printf(" (POSTPONED)");
169 else printf(" %s(POSTPONED)%s", MAGENTA, NORMAL);
170 } else if (is_deferred) {
171 if (options->monochrome) printf(" (DEFERRED)");
172 else printf(" %s(DEFERRED)%s", MAGENTA, NORMAL);
173 }
174 printf(" : ");
175 } else {
176 printf(" ");
177 }
178
179 if (!options->monochrome) printf("%s", is_done ? CYAN : is_postponed ? MAGENTA : colour_table[y->priority]);
180
181#if 0
182
183 if (summarise_kids && (n_kids > 0)) {
184 if (options->monochrome) {
185 printf("%s [%d/%d] %s", index_buffer, n_open_kids, n_kids,
186 (show_state && !options->verbose && is_ignored) ? "(IGNORED) : " :
187 (show_state && !options->verbose && is_done) ? "(DONE) : " :
188 (show_state && !options->verbose && is_done) ? "(DONE) : " :
189 (show_state && !options->verbose && (y->arrived > now)) ? "(DEFERRED) : " : ": ");
190 } else {
191 printf("%s%s %s[%d/%d]%s %s%s", GREEN, index_buffer, CYAN, n_open_kids, n_kids, NORMAL,
192 (show_state && !options->verbose && is_ignored) ? BLUE "(IGNORED) " NORMAL :
193 (show_state && !options->verbose && is_done) ? CYAN "(DONE) " NORMAL :
194 (show_state && !options->verbose && is_postponed) ? MAGENTA "(POSTPONED) " :
195 (show_state && !options->verbose && (y->arrived > now)) ? MAGENTA "(DEFERRED) " : "",
196 is_done ? CYAN : is_postponed ? MAGENTA : colour_table[y->priority]);
197 }
198 } else {
199 if (options->monochrome) {
200 printf("%s %s", index_buffer,
201 (show_state && !options->verbose && is_ignored) ? "(IGNORED) : " :
202 (show_state && !options->verbose && is_done) ? "(DONE) : " :
203 (show_state && !options->verbose && is_postponed) ? "(POSTPONED) : " :
204 (show_state && !options->verbose && (y->arrived > now)) ? "(DEFERRED) : " : ": ");
205 } else {
206 printf("%s%s%s %s%s", GREEN, index_buffer, NORMAL,
207 (show_state && !options->verbose && is_ignored) ? BLUE "(IGNORED) " NORMAL :
208 (show_state && !options->verbose && is_done) ? CYAN "(DONE) " NORMAL :
209 (show_state && !options->verbose && is_postponed) ? MAGENTA "(POSTPONED) " :
210 (show_state && !options->verbose && (y->arrived > now)) ? MAGENTA "(DEFERRED) " : "",
211 is_done ? CYAN : is_postponed ? MAGENTA : colour_table[y->priority]);
212 }
213 }
214#endif
215 for (p = y->text; *p; p++) {
216 putchar(*p);
217 if (*p == '\n') {
218 do_indent(indent + 5);
219 }
220 }
221 if (!options->monochrome) printf("%s", NORMAL);
7f4872bd
JW
222 if (y->required_by > 0) {
223 time_t delta = y->required_by - time(NULL);
224 if (delta < 0) {
225 printf(options->monochrome ?
226 " [OVERDUE]" :
227 RED " [OVERDUE]" NORMAL);
228 } else if (delta < 24*60*60) {
229 printf(options->monochrome ?
230 " [due <24hr]" :
231 RED " [due <24hr]" NORMAL);
232 } else if (delta < 2*24*60*60) {
233 printf(options->monochrome ?
234 " [due <2d]" :
235 RED " [due <2d]" NORMAL);
236 } else if (delta < 3*24*60*60) {
237 printf(options->monochrome ?
238 " [due <3d]" :
239 YELLOW " [due <3d]" NORMAL);
240 } else if (delta < 4*24*60*60) {
241 printf(options->monochrome ?
242 " [due <4d]" :
243 YELLOW " [due <4d]" NORMAL);
244 } else if (delta < 5*24*60*60) {
245 printf(options->monochrome ?
246 " [due <5d]" :
247 GREEN " [due <5d]" NORMAL);
248 }
249 }
7024e37b
JW
250 printf("\n");
251
252 if (options->verbose) {
253 print_timestamp(y->arrived, "Arrived", indent, options->monochrome);
254 do_indent(indent + 2);
255 if (options->monochrome) {
256 printf("Priority: %s\n", priority_text[y->priority]);
257 } else {
258 printf("%sPriority: %s%s%s\n",
259 GREEN, colour_table[y->priority], priority_text[y->priority], NORMAL);
260 }
261 if (y->required_by > 0) print_timestamp(y->required_by, "Required by", indent, options->monochrome);
262 if (y->done > 0) print_timestamp(y->done, "Completed", indent, options->monochrome);
263 printf("\n");
264 }
265
266}
267/*}}}*/
9d5bee3b
JW
268/* 1 if x has lower priority than y. */
269static int node_lessthan(struct node *x, struct node *y)/*{{{*/
270{
9d5bee3b 271 if (x->priority > y->priority)
2f9132d3
JW
272 return 1;
273 if (x->priority < y->priority)
9d5bee3b 274 return 0;
aee3c241 275 if (x->required_by == y->required_by)
9d5bee3b
JW
276 return (x->idx > y->idx);
277 if (y->required_by == 0)
278 return 1;
279 if (x->required_by == 0)
280 return 0;
281 return x->required_by < y->required_by;
282}
283/*}}}*/
284static void sort_chain(struct links *x)/*{{{*/
285{
286 struct links new;
287 struct node *y, *ynext, *yprev;
288 int idx;
289
290 new.next = NULL;
291 new.prev = NULL;
292
293 /* Stupidsort. */
294 for (y = x->next, idx = 1; y != (struct node *) x; y = ynext, ++idx) {
295 /* y is now the current node; go insert it into its rightful place in
296 * the new chain. */
297 struct node **nextp = &(new.next);
298 struct node *ins;
299 for (ins = new.next; ins && node_lessthan(ins, y); nextp = &(ins->chain.next), ins = ins->chain.next)
300 ;
301 y->chain.next->chain.prev = y->chain.prev;
302 y->chain.prev->chain.next = y->chain.next;
303 ynext = y->chain.next;
304 y->chain.next = *nextp;
305 *nextp = y;
306 y->idx = idx;
307 }
308
309 /* Now clean up the new links. */
310 yprev = (struct node *)x;
311 for (y = new.next; y; yprev = y, y = y->chain.next) {
312 y->chain.prev = yprev;
313 }
314 yprev->chain.next = (struct node *)x;
315 new.prev = y;
316
317 if (new.next == NULL) {
318 x->next = (struct node *)x;
319 x->prev = (struct node *)x;
320 } else {
321 x->next = new.next;
322 x->prev = new.prev;
323 }
324}
325/*}}}*/
7024e37b
JW
326static void list_chain(struct links *x, int indent, int depth, const struct list_options *options, char *index_buffer, enum Priority prio, time_t now, unsigned char *hits)/*{{{*/
327{
328 struct node *y;
9d5bee3b 329 int is_done, is_deferred, is_postponed;
7024e37b
JW
330 int show_node;
331 char component_buffer[8];
332 char new_index_buffer[64];
333
9d5bee3b
JW
334 sort_chain(x);
335
336 for (y = x->next;
7024e37b 337 y != (struct node *) x;
9d5bee3b 338 y = y->chain.next) {
7024e37b
JW
339
340 is_done = (y->done > 0);
341 is_postponed = (y->arrived == POSTPONED_TIME);
342 is_deferred = (y->arrived > now);
343 show_node = options->show_all
344 || (options->show_postponed && !is_done)
345 || (!is_deferred && !is_postponed);
346 if (!show_node) continue;
347
9d5bee3b 348 sprintf(component_buffer, "%d", y->idx);
7024e37b
JW
349 strcpy(new_index_buffer, index_buffer);
350 if (strlen(new_index_buffer) > 0) {
351 strcat(new_index_buffer, ".");
352 }
353 strcat(new_index_buffer, component_buffer);
354
355 if (y->priority >= prio) {
356 int summarise_kids = (options->set_depth && (options->depth == depth));
357 if (hits[y->iscratch]) {
358 print_details(y, indent, summarise_kids, options, new_index_buffer, now);
359 }
360 }
361
362 /* Maybe list children regardless of priority assigned to parent. */
363 if (!options->set_depth || (depth < options->depth)) {
364 list_chain(&y->kids, indent + INDENT_TAB, depth + 1, options, new_index_buffer, prio, now, hits);
365 }
366
367 }
368 return;
369}
370/*}}}*/
371static void allocate_indices(struct links *x, int *idx)/*{{{*/
372{
373 struct node *y;
374 for (y = x->next;
375 y != (struct node *) x;
376 y = y->chain.next) {
377
378 y->iscratch = *idx;
379 ++*idx;
380 allocate_indices(&y->kids, idx);
381 }
382}
383/*}}}*/
384static void search_node(struct links *x, int max_errors, unsigned long *vecs, unsigned long hitvec, unsigned char *hits)/*{{{*/
385{
386 struct node *y;
387 char *p;
388 char *token;
389 int got_hit;
390 unsigned long r0, r1, r2, r3, nr0, nr1, nr2;
391
392 for (y = x->next;
393 y != (struct node *) x;
394 y = y->chain.next) {
395
396 token = y->text;
397
398 switch (max_errors) {
399 /* optimise common cases for few errors to allow optimizer to keep bitmaps
400 * in registers */
401 case 0:/*{{{*/
402 r0 = ~0;
403 got_hit = 0;
404 for(p=token; *p; p++) {
405 int idx = (unsigned int) *(unsigned char *)p;
406 r0 = (r0<<1) | vecs[idx];
407 if (~(r0 | hitvec)) {
408 got_hit = 1;
409 break;
410 }
411 }
412 break;
413 /*}}}*/
414 case 1:/*{{{*/
415 r0 = ~0;
416 r1 = r0<<1;
417 got_hit = 0;
418 for(p=token; *p; p++) {
419 int idx = (unsigned int) *(unsigned char *)p;
420 nr0 = (r0<<1) | vecs[idx];
421 r1 = ((r1<<1) | vecs[idx]) & ((r0 & nr0) << 1) & r0;
422 r0 = nr0;
423 if (~((r0 & r1) | hitvec)) {
424 got_hit = 1;
425 break;
426 }
427 }
428 break;
429 /*}}}*/
430 case 2:/*{{{*/
431 r0 = ~0;
432 r1 = r0<<1;
433 r2 = r1<<1;
434 got_hit = 0;
435 for(p=token; *p; p++) {
436 int idx = (unsigned int) *(unsigned char *)p;
437 nr0 = (r0<<1) | vecs[idx];
438 nr1 = ((r1<<1) | vecs[idx]) & ((r0 & nr0) << 1) & r0;
439 r2 = ((r2<<1) | vecs[idx]) & ((r1 & nr1) << 1) & r1;
440 r0 = nr0;
441 r1 = nr1;
442 if (~((r0 & r1& r2) | hitvec)) {
443 got_hit = 1;
444 break;
445 }
446 }
447 break;
448 /*}}}*/
449 case 3:/*{{{*/
450 r0 = ~0;
451 r1 = r0<<1;
452 r2 = r1<<1;
453 r3 = r2<<1;
454 got_hit = 0;
455 for(p=token; *p; p++) {
456 int idx = (unsigned int) *(unsigned char *)p;
457 nr0 = (r0<<1) | vecs[idx];
458 nr1 = ((r1<<1) | vecs[idx]) & ((r0 & nr0) << 1) & r0;
459 nr2 = ((r2<<1) | vecs[idx]) & ((r1 & nr1) << 1) & r1;
460 r3 = ((r3<<1) | vecs[idx]) & ((r2 & nr2) << 1) & r2;
461 r0 = nr0;
462 r1 = nr1;
463 r2 = nr2;
464 if (~((r0 & r1 & r2 & r3) | hitvec)) {
465 got_hit = 1;
466 break;
467 }
468 }
469 break;
470 /*}}}*/
471 default:
472 assert(0); /* not allowed */
473 break;
474 }
475 if (got_hit) {
476 hits[y->iscratch] = 1;
477 }
478 search_node(&y->kids, max_errors, vecs, hitvec, hits);
479 }
480}
481/*}}}*/
482static void merge_search_condition(unsigned char *hits, int n_nodes, char *cond)/*{{{*/
483{
484 /* See "Fast text searching with errors, Sun Wu and Udi Manber, TR 91-11,
485 University of Arizona. I have been informed that this algorithm is NOT
486 patented. This implementation of it is entirely the work of Richard P.
487 Curnow - I haven't looked at any related source (webglimpse, agrep etc) in
488 writing this.
489 */
490
491 int max_errors;
492 char *slash;
493 char *substring;
494 unsigned long a[256];
495 unsigned long hit;
496 int len, i;
497 char *p;
498 unsigned char *hit0;
499
500 slash = strchr(cond, '/');
501 if (!slash) {
502 max_errors = 0;
503 substring = cond;
504 } else {
505 substring = new_string(cond);
506 substring[slash-cond] = '\0';
507 max_errors = atoi(slash+1);
508 if (max_errors > 3) {
509 fprintf(stderr, "Can only match with up to 3 errors, ignoring patterh <%s>\n", cond);
510 goto get_out;
511 }
512 }
513
514 len = strlen(substring);
515 if (len < 1 || len > 31) {
516 fprintf(stderr, "Pattern must be between 1 and 31 characters\n");
517 goto get_out;
518 }
519
520 /* Set array 'a' to all -1 values */
521 memset(a, 0xff, 256 * sizeof(unsigned long));
522 for (p=substring, i=0; *p; p++, i++) {
523 unsigned char pc;
524 pc = *(unsigned char *) p;
525 a[(unsigned int) pc] &= ~(1UL << i);
526 /* Make search case insensitive */
527 if (isupper(pc)) {
528 a[tolower((unsigned int) pc)] &= ~(1UL << i);
529 }
530 if (islower(pc)) {
531 a[toupper((unsigned int) pc)] &= ~(1UL << i);
532 }
533 }
534 hit = ~(1UL << (len-1));
535
536 hit0 = new_array(unsigned char, n_nodes);
537 memset(hit0, 0, n_nodes);
538
539 /* Now scan each node against this match criterion */
540 search_node(&top, max_errors, a, hit, hit0);
541 for (i=0; i<n_nodes; i++) {
542 hits[i] &= hit0[i];
543 }
544 free(hit0);
545
546get_out:
547 if (substring != cond) {
548 free(substring);
549 }
550 return;
551}
552/*}}}*/
553int process_list(char **x)/*{{{*/
554{
555 struct list_options options;
556 int options_done = 0;
557 int any_paths = 0;
558 char index_buffer[256];
559 char *y;
560 enum Priority prio = PRI_NORMAL, prio_to_use, node_prio;
561 int prio_set = 0;
562 time_t now = time(NULL);
563
564 unsigned char *hits;
565 int node_index, n_nodes;
566
567 options.monochrome = 0;
568 options.show_all = 0;
569 options.show_postponed = 0;
570 options.verbose = 0;
571 options.set_depth = 0;
572
573 if ( (getenv("TDL_LIST_MONOCHROME") != NULL) ||
574 (isatty(STDOUT_FILENO) == 0) ) {
575 options.monochrome = 1;
576 }
577
578 /* Initialisation to support searching */
579 node_index = 0;
580 allocate_indices(&top, &node_index);
581 n_nodes = node_index;
582
583 hits = n_nodes ? new_array(unsigned char, n_nodes) : NULL;
584
585 /* all nodes match until proven otherwise */
586 memset(hits, 1, n_nodes);
587
588 while ((y = *x) != 0) {
589 /* An argument starting '1' or '+1' or '+-1' (or '-1' after '--') is
590 * treated as the path of the top node to show */
591 if (isdigit(y[0]) ||
592 (y[0] == '.') ||
593 (options_done && (y[0] == '-') && isdigit(y[1])) ||
594 ((y[0] == '+') &&
595 (isdigit(y[1]) ||
596 ((y[1] == '-' && isdigit(y[2])))))) {
597
598 struct node *n = lookup_node(y, 0, NULL);
599 int summarise_kids;
600
601 if (!n) return -1;
602
603 any_paths = 1;
604 index_buffer[0] = '\0';
605 strcat(index_buffer, y);
606 summarise_kids = (options.set_depth && (options.depth==0));
607 if (hits[n->iscratch]) {
608 print_details(n, 0, summarise_kids, &options, index_buffer, now);
609 }
610 if (!options.set_depth || (options.depth > 0)) {
611 node_prio = n->priority;
612
613 /* If the priority has been set on the cmd line, always use that.
614 * Otherwise, use the priority from the specified node, _except_ when
615 * that is higher than normal, in which case use normal. */
616 prio_to_use = (prio_set) ? prio : ((node_prio > prio) ? prio : node_prio);
617 list_chain(&n->kids, INDENT_TAB, 0, &options, index_buffer, prio_to_use, now, hits);
618 }
619 } else if ((y[0] == '-') && (y[1] == '-')) {
620 options_done = 1;
621 } else if (y[0] == '-') {
622 while (*++y) {
623 switch (*y) {
624 case 'v':
625 options.verbose = 1;
626 break;
627 case 'a':
628 options.show_all = 1;
629 break;
630 case 'm':
631 options.monochrome = 1;
632 break;
633 case 'p':
634 options.show_postponed = 1;
635 break;
636 case '1': case '2': case '3':
637 case '4': case '5': case '6':
638 case '7': case '8': case '9':
639 options.set_depth = 1;
640 options.depth = (*y) - '1';
641 break;
642 default:
643 fprintf(stderr, "Unrecognized option : -%c\n", *y);
644 break;
645 }
646 }
647 } else if (y[0] == '/') {
648 /* search expression */
649 merge_search_condition(hits, n_nodes, y+1);
650
651 } else {
652 int error;
653 prio = parse_priority(y, &error);
654 if (error < 0) return error;
655 prio_set = 1;
656 }
657
658 x++;
659 }
660
661 if (!any_paths) {
662 struct node *narrow_top = get_narrow_top();
663 if (narrow_top) {
664 index_buffer[0] = 0;
665 if (hits[narrow_top->iscratch]) {
666 int summarise_kids = (options.set_depth && (options.depth==0));
667 print_details(narrow_top, 0, summarise_kids, &options, index_buffer, now);
668 }
669 if (!options.set_depth || (options.depth > 0)) {
670 list_chain(&narrow_top->kids, 0, 1, &options, index_buffer, prio, now, hits);
671 }
672 } else {
673 index_buffer[0] = 0;
674 list_chain(&top, 0, 0, &options, index_buffer, prio, now, hits);
675 }
676 }
677
678 if (hits) free(hits);
679
680 return 0;
681}
682/*}}}*/
This page took 0.103623 seconds and 4 git commands to generate.