2 $Header: /cvs/src/tdl/move.c,v 1.8.2.2 2004/01/07 00:09:05 richard Exp $
4 tdl - A console program for managing to-do lists
5 Copyright (C) 2001-2004 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 static int is_ancestor(struct node *anc, struct node *dec)/*{{{*/
27 /* Check includes whether the two nodes are the same */
29 for (parent = dec; parent != NULL; parent = parent->parent) {
38 static int process_move_internal(char **x, int below_not_above, int into_parent)/*{{{*/
40 /* x is the argument list
41 * below_not_above is true to insert below x[0], false to insert above
42 * into_parent means an implicit .0 is appended to x[0] to get the path
46 struct links *insert_point;
48 struct node *insert_parent, *insert_peer=NULL, *parent;
52 option = below_not_above ? "below" : "above";
56 fprintf(stderr, "Usage: %s <index_to_insert_%s> <index_to_move> ...\n",
63 insert_parent = lookup_node(x[0], 0, NULL);
64 if (!insert_parent) return -1;
65 insert_point = &insert_parent->kids;
67 insert_peer = lookup_node(x[0], 1, &insert_parent); /* Allow final component to be zero */
68 insert_point = (struct links *) &insert_peer->chain;
69 if (!insert_point) return -1;
71 table = new_array(struct node *, n);
74 /* Have to do the move in 2 passes, otherwise the indices of the entries
75 could change in mid-lookup. */
77 table[i] = lookup_node(x[i], 0, NULL); /* Don't allow zero for this */
78 if (!table[i]) return -1; /* memory leak */
80 /* Check for an attempt to move a node onto one of its own descendents */
81 if (is_ancestor(table[i], insert_parent)) {
82 fprintf(stderr, "Can't re-parent entry %s onto a descendent of itself\n", x[i]);
88 /* Unlink from its current location */
89 struct node *prev, *next;
91 if (table[i] == insert_peer) {
92 fprintf(stderr, "Can't move %s relative to itself\n", x[0]);
96 next = table[i]->chain.next;
97 prev = table[i]->chain.prev;
98 prev->chain.next = next;
99 next->chain.prev = prev;
101 (below_not_above ? append_node : prepend_node) (table[i], insert_point);
103 table[i]->parent = insert_parent;
105 /* in this case 'insert_peer' is just the one we're putting things above
106 * or below, i.e. the entries being moved will be siblings of it and will
107 * share its parent. */
108 table[i]->parent = insert_peer->parent;
111 /* To insert the nodes in the command line order */
112 if (below_not_above) insert_point = &table[i]->chain;
113 /* if inserting above something, the insertion point stays fixed */
115 /* Clear done status of insertion point and its ancestors */
116 if (table[i]->done == 0) {
117 parent = insert_parent;
120 parent = parent->parent;
128 int process_above(char **x)/*{{{*/
130 return process_move_internal(x, 0, 0);
133 int process_below(char **x)/*{{{*/
135 return process_move_internal(x, 1, 0);
138 int process_into(char **x)/*{{{*/
140 return process_move_internal(x, 0, 1);