2 $Header: /cvs/src/tdl/util.c,v 1.8.2.1 2004/01/07 00:09:05 richard Exp $
4 tdl - A console program for managing to-do lists
5 Copyright (C) 2001,2002,2003,2004,2005 Richard P. Curnow
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.
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.
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
25 int count_args(char **x)/*{{{*/
35 int include_descendents(char *x)/*{{{*/
37 /* Check if string ends in ... . If it does, truncate that off. */
42 if (!strcmp(x + (len-3), "...")) {
50 static char *ordinal(int n)/*{{{*/
62 struct node *lookup_node(char *path, int allow_zero_index, struct node **parent)/*{{{*/
65 int n, nc, idx, tidx, aidx, ncomp;
68 struct node *y = NULL;
69 struct node *narrow_top;
71 narrow_top = get_narrow_top();
73 /* Special case to allow user to do operations on the node to which the
74 * view is currently narrowed. (This doesn't apply to 'top' which is just a
76 if (!strcmp(path, ".")) {
79 x = &(narrow_top->kids);
85 if (parent) *parent = NULL;
87 /* Skip leading '.', if any. */
91 if ((p[0] == '-') || isdigit(p[0])) {
92 n = sscanf(p, "%d%n", &idx, &nc);
94 fprintf(stderr, "Bad path expression found, starting [%s]\n", p);
102 } else if (idx < 0) {
106 if (allow_zero_index) {
108 fprintf(stderr, "Zero index only allowed as last component\n");
111 /* This is a special cheat to allow inserting entries at
112 the start or end of a chain for the 'above' and
114 return (struct node *) x;
117 fprintf(stderr, "Zero in index not allowed\n");
122 if (x->next == (struct node *) x) {
123 fprintf(stderr, "Path [%s] doesn't exist - tree not that deep\n", path);
127 for (y = direction ? x->next : x->prev, tidx = aidx; --tidx;) {
129 y = direction ? y->chain.next : y->chain.prev;
131 if (y == (struct node *) x) {
132 fprintf(stderr, "Can't find entry %d for %d%s component of path %s\n",
133 idx, ncomp, ordinal(ncomp), path);
138 /* Lookup by start of node text. */
142 dot = strchr(p, '.');
143 if (!dot) { /* final component. */
149 for (y = x->next; y != (struct node *) x; y = y->chain.next) {
150 if (!strncasecmp(y->text, p, len)) {
152 fprintf(stderr, "Ambiguous match for %d%s component (",
153 ncomp, ordinal(ncomp));
154 fwrite(p, 1, len, stderr);
155 fprintf(stderr, ") of path %s\n", path);
162 fprintf(stderr, "Can't find entry for %d%s component (",
163 ncomp, ordinal(ncomp));
164 fwrite(p, 1, len, stderr);
165 fprintf(stderr, ") of path %s\n", path);
175 if (parent) *parent = y;
184 enum Priority parse_priority(char *priority, int *error)/*{{{*/
186 enum Priority result;
194 is_digit = isdigit(priority[0]);
197 int value = atoi(priority);
198 result = (value >= PRI_URGENT) ? PRI_URGENT :
199 (value <= PRI_VERYLOW) ? PRI_VERYLOW :
200 (enum Priority) value;
202 int len = strlen(priority);
203 if (!strncmp(priority, "urgent", len)) {
205 } else if (!strncmp(priority, "high", len)) {
207 } else if (!strncmp(priority, "normal", len)) {
209 } else if (!strncmp(priority, "low", len)) {
211 } else if (!strncmp(priority, "verylow", len)) {
212 result = PRI_VERYLOW;
214 fprintf(stderr, "Can't parse priority '%s'\n", priority);
216 return PRI_UNKNOWN; /* bogus */
224 void clear_flags(struct links *x)/*{{{*/
227 for (y = x->next; y != (struct node *) x; y = y->chain.next) {
230 clear_flags(&y->kids);
235 void mark_all_descendents(struct node *n)/*{{{*/
238 for (y = n->kids.next; y != (struct node *) &n->kids; y = y->chain.next) {
241 mark_all_descendents(y);
246 int has_kids(struct node *x)/*{{{*/
248 return (x->kids.next != (struct node *) &x->kids);
251 struct node *new_node(void)/*{{{*/
253 struct node *result = new (struct node);
254 result->parent = NULL;
256 result->priority = PRI_NORMAL;
257 result->arrived = result->required_by = result->done = 0U;
258 result->kids.next = result->kids.prev = (struct node *) &result->kids;
259 result->chain.next = result->chain.prev = (struct node *) &result->chain;
263 void free_node(struct node *x)/*{{{*/
265 /* FIXME : To be written */
270 void append_node(struct node *n, struct links *l)/*{{{*/
272 n->chain.next = l->next;
273 n->chain.prev = (struct node *) l;
274 l->next->chain.prev = n;
278 void prepend_node(struct node *n, struct links *l)/*{{{*/
280 n->chain.prev = l->prev;
281 n->chain.next = (struct node *) l;
282 l->prev->chain.next = n;
286 void prepend_child(struct node *child, struct node *parent)/*{{{*/
288 child->parent = parent;
290 prepend_node(child, &parent->kids);
292 struct node *narrow_top;
293 narrow_top = get_narrow_top();
294 prepend_node(child, narrow_top ? &narrow_top->kids : &top);