r956: README.BUILD - add more library recommendations
[cinelerra_cv/ct.git] / guicast / linklist.h
blob3227cd9a361aaab9303bce71e37126c3254158c7
1 #ifndef LINKLIST_H
2 #define LINKLIST_H
4 template<class TYPE>
5 class ListItem;
7 template<class TYPE>
8 class List // inherited by lists
10 public:
11 List();
12 virtual ~List();
13 // delete the item and the pointers to it
14 void remove(TYPE *item);
15 // remove the pointers to the item only
16 void remove_pointer(ListItem<TYPE> *item);
18 // these must be used to add an item to a list
19 TYPE *append(); // create new node and return pointer of it
20 TYPE *append(TYPE *new_item); // append the new pointer to the list
21 TYPE *insert_before(TYPE *item); // create new node and return pointer of it
22 TYPE *insert_before(TYPE *item, TYPE *new_item); // create new node and return pointer of it
23 TYPE *insert_after(TYPE *item);
24 TYPE *insert_after(TYPE *item, TYPE *new_item);
25 TYPE *get_item_number(int number);
26 int get_item_number(TYPE *item);
27 void swap(TYPE *item1, TYPE *item2);
29 // query the list
30 int total(); // total number of nodes
31 int number_of(TYPE *item);
33 // convenience macros
34 #define PREVIOUS current->previous
35 #define NEXT current->next
37 // references to list
38 TYPE *first;
39 TYPE *last;
42 template<class TYPE>
43 class ListItem // inherited by list items
45 public:
46 ListItem();
47 virtual ~ListItem();
49 int get_item_number();
50 TYPE *previous;
51 TYPE *next;
52 List<TYPE> *owner; // list that owns this item for deletion
55 template<class TYPE>
56 List<TYPE>::List()
58 last = first = 0;
61 template<class TYPE>
62 List<TYPE>::~List() // delete nodes
64 while(last)
66 delete last;
70 template<class TYPE>
71 int List<TYPE>::total() // total number of nodes
73 int total = 0;
74 TYPE* current;
76 for(current = first; current; current = NEXT)
78 total++;
80 return total;
83 template<class TYPE>
84 int List<TYPE>::number_of(TYPE *item)
86 TYPE* current;
87 int total = 0;
88 for(current = first; current; current = NEXT)
90 if(current == item) return total;
91 total++;
93 return 0;
96 template<class TYPE>
97 TYPE* List<TYPE>::get_item_number(int number)
99 TYPE* current;
100 int i;
101 for(i = 0, current = first; current && i < number; current = NEXT, i++)
105 return current;
108 template<class TYPE>
109 int List<TYPE>::get_item_number(TYPE *item)
111 TYPE* current;
112 int i;
113 for(i = 0, current = first; current && current != item; current = NEXT, i++)
117 return i;
121 template<class TYPE>
122 TYPE* List<TYPE>::append()
124 TYPE* current_item;
126 if(!last) // add first node
128 current_item = last = first = new TYPE;
129 current_item->previous = current_item->next = 0;
130 current_item->owner = this;
131 return current_item;
133 else
134 { // append node
135 current_item = last->next = new TYPE;
136 current_item->previous = last;
137 current_item->next = 0;
138 last = current_item;
139 current_item->owner = this;
140 return current_item;
144 template<class TYPE>
145 TYPE* List<TYPE>::append(TYPE *new_item)
147 TYPE* current_item;
149 if(!last) // add first node
151 current_item = last = first = new_item;
152 current_item->previous = current_item->next = 0;
153 current_item->owner = this;
154 return current_item;
156 else
157 { // append node
158 current_item = last->next = new_item;
159 current_item->previous = last;
160 current_item->next = 0;
161 last = current_item;
162 current_item->owner = this;
163 return current_item;
167 template<class TYPE>
168 TYPE* List<TYPE>::insert_before(TYPE *item)
170 TYPE* new_item = new TYPE;
171 return insert_before(item, new_item);
174 template<class TYPE>
175 TYPE* List<TYPE>::insert_before(TYPE *item, TYPE *new_item)
177 if(!item) return append(new_item); // if item is null, append
179 TYPE* current_item = new_item;
181 if(item == first) first = current_item; // set *first
183 current_item->previous = item->previous; // set this node's pointers
184 current_item->next = item;
186 if(current_item->previous) current_item->previous->next = current_item; // set previous node's pointers
188 if(current_item->next) current_item->next->previous = current_item; // set next node's pointers
190 current_item->owner = this;
191 return current_item;
194 template<class TYPE>
195 TYPE* List<TYPE>::insert_after(TYPE *item)
197 TYPE *new_item = new TYPE;
198 return insert_after(item, new_item);
201 template<class TYPE>
202 TYPE* List<TYPE>::insert_after(TYPE *item, TYPE *new_item)
204 if(!item) return append(new_item); // if item is null, append
206 TYPE* current_item = new_item;
208 if(item == last) last = current_item; // set *last
210 current_item->previous = item; // set this node's pointers
211 current_item->next = item->next;
213 if(current_item->previous) current_item->previous->next = current_item; // set previous node's pointers
215 if(current_item->next) current_item->next->previous = current_item; // set next node's pointers
217 current_item->owner = this;
218 return current_item;
221 template<class TYPE>
222 void List<TYPE>::swap(TYPE *item1, TYPE *item2)
224 TYPE **temp_array;
225 int total = this->total();
226 temp_array = new TYPE*[total];
227 // Copy entire list to a temp. This rewrites the pointers in the original items.
228 for(int i = 0; i < total; i++)
230 temp_array[i] = get_item_number(i);
232 while(last) remove_pointer(last);
233 for(int i = 0; i < total; i++)
235 if(temp_array[i] == item1) append(item2);
236 else
237 if(temp_array[i] == item2) append(item1);
238 else
239 append(temp_array[i]);
241 delete [] temp_array;
243 #if 0
244 TYPE *new_item0, *new_item1, *new_item2, *new_item3;
246 // old == item0 item1 item2 item3
247 // new == item0 item2 item1 item3
249 new_item0 = item1->previous;
250 new_item1 = item2;
251 new_item2 = item1;
252 new_item3 = item2->next;
254 if(new_item0)
255 new_item0->next = new_item1;
256 else
257 first = new_item1;
259 if(new_item1) new_item1->next = new_item2;
260 if(new_item2) new_item2->next = new_item3;
261 if(new_item3)
262 new_item3->previous = new_item2;
263 else
264 last = new_item2;
266 if(new_item2) new_item2->previous = new_item1;
267 if(new_item1) new_item1->previous = new_item0;
268 #endif
271 template<class TYPE>
272 void List<TYPE>::remove(TYPE *item)
274 if(!item) return;
275 delete item; // item calls back to remove pointers
278 template<class TYPE>
279 void List<TYPE>::remove_pointer(ListItem<TYPE> *item)
281 //printf("List<TYPE>::remove_pointer %x %x %x\n", item, last, first);
282 if(!item) return;
284 item->owner = 0;
286 if(item == last && item == first)
288 // last item
289 last = first = 0;
290 return;
293 if(item == last) last = item->previous; // set *last and *first
294 else
295 if(item == first) first = item->next;
297 if(item->previous) item->previous->next = item->next; // set previous node's pointers
299 if(item->next) item->next->previous = item->previous; // set next node's pointers
302 template<class TYPE>
303 ListItem<TYPE>::ListItem()
305 next = previous = 0;
306 // don't delete the pointer to this if it's not part of a list
307 owner = 0;
310 template<class TYPE>
311 ListItem<TYPE>::~ListItem()
313 // don't delete the pointer to this if it's not part of a list
314 if(owner) owner->remove_pointer(this);
317 template<class TYPE>
318 int ListItem<TYPE>::get_item_number()
320 return owner->get_item_number((TYPE*)this);
323 #endif