]> Joshua Wise's Git repositories - tdl.git/blame - move.c
Initial import of tdl-1.6-pre1
[tdl.git] / move.c
CommitLineData
7024e37b
JW
1/*
2 $Header: /cvs/src/tdl/move.c,v 1.8.2.2 2004/01/07 00:09:05 richard Exp $
3
4 tdl - A console program for managing to-do lists
5 Copyright (C) 2001-2004 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 "tdl.h"
23
24
25static int is_ancestor(struct node *anc, struct node *dec)/*{{{*/
26{
27 /* Check includes whether the two nodes are the same */
28 struct node *parent;
29 for (parent = dec; parent != NULL; parent = parent->parent) {
30 if (parent == anc) {
31 return 1;
32 }
33 }
34 return 0;
35}
36/*}}}*/
37
38static int process_move_internal(char **x, int below_not_above, int into_parent)/*{{{*/
39{
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
43 */
44
45 int argc, i, n;
46 struct links *insert_point;
47 struct node **table;
48 struct node *insert_parent, *insert_peer=NULL, *parent;
49
50 char *option;
51
52 option = below_not_above ? "below" : "above";
53
54 argc = count_args(x);
55 if (argc < 2) {
56 fprintf(stderr, "Usage: %s <index_to_insert_%s> <index_to_move> ...\n",
57 option, option);
58 return -1;
59 }
60
61 n = argc - 1;
62 if (into_parent) {
63 insert_parent = lookup_node(x[0], 0, NULL);
64 if (!insert_parent) return -1;
65 insert_point = &insert_parent->kids;
66 } else {
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;
70 }
71 table = new_array(struct node *, n);
72 x++;
73
74 /* Have to do the move in 2 passes, otherwise the indices of the entries
75 could change in mid-lookup. */
76 for (i=0; i<n; i++) {
77 table[i] = lookup_node(x[i], 0, NULL); /* Don't allow zero for this */
78 if (!table[i]) return -1; /* memory leak */
79
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]);
83 return -1;
84 }
85 }
86
87 for (i=0; i<n; i++) {
88 /* Unlink from its current location */
89 struct node *prev, *next;
90
91 if (table[i] == insert_peer) {
92 fprintf(stderr, "Can't move %s relative to itself\n", x[0]);
93 continue;
94 }
95
96 next = table[i]->chain.next;
97 prev = table[i]->chain.prev;
98 prev->chain.next = next;
99 next->chain.prev = prev;
100
101 (below_not_above ? append_node : prepend_node) (table[i], insert_point);
102 if (into_parent) {
103 table[i]->parent = insert_parent;
104 } else {
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;
109 }
110
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 */
114
115 /* Clear done status of insertion point and its ancestors */
116 if (table[i]->done == 0) {
117 parent = insert_parent;
118 while (parent) {
119 parent->done = 0;
120 parent = parent->parent;
121 }
122 }
123 }
124
125 return 0;
126}
127/*}}}*/
128int process_above(char **x)/*{{{*/
129{
130 return process_move_internal(x, 0, 0);
131}
132/*}}}*/
133int process_below(char **x)/*{{{*/
134{
135 return process_move_internal(x, 1, 0);
136}
137/*}}}*/
138int process_into(char **x)/*{{{*/
139{
140 return process_move_internal(x, 0, 1);
141}
142/*}}}*/
This page took 0.033171 seconds and 4 git commands to generate.