1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * phoimglist.c: list manipulation for PhoImage type.
4  *
5  * Copyright 2010 by Akkana Peck.
6  * You are free to use or modify this code under the Gnu Public License.
7  */
8 
9 /* A PhoImage is a doubly-linked list, with ->next and ->prev.
10  * The global gFirstImage marks the head of the list;
11  * the list is circular, so the last item has next = gFirstImage.
12  *
13  * gCurImage points to the current list item.
14  *
15  * List items are freed with FreePhoImage()
16  */
17 
18 #include "pho.h"
19 #include <stdlib.h>
20 
21 /* This routine exists to keep track of any allocated memory
22  * existing in the PhoImage structure.
23  */
FreePhoImage(PhoImage * img)24 static void FreePhoImage(PhoImage* img)
25 {
26     if (img->comment) free(img->comment);
27     free(img);
28 }
29 
printImageList()30 static void printImageList()
31 {
32     if (! gFirstImage) {
33         printf("  No images\n");
34         return;
35     }
36     PhoImage* im = gFirstImage;
37     PhoImage* lastIm = gFirstImage->prev;
38     while (im) {
39         if (im == gCurImage)
40             printf("> %s\n", im->filename);
41         else
42             printf("  %s\n", im->filename);
43         if (im == lastIm)
44             break;
45         im = im->next;
46     }
47     printf("\n");
48 }
49 
50 /* Delete an image from the image list (not from disk).
51  * Will use gCurImage if item == 0.
52  * Update gCurImage if needed.
53  */
DeleteItem(PhoImage * item)54 void DeleteItem(PhoImage* item)
55 {
56     if (gDebug) {
57         printf("Removing image %s from image list\n", item->filename);
58         printf("Image list before removal:\n");
59         printImageList();
60     }
61 
62     if (!item)
63         item = gCurImage;
64 
65     /* Is this the only image? */
66     if (item == gFirstImage && item->next == gFirstImage) {
67         gFirstImage = gCurImage = 0;
68     }
69     else {
70         /* Is it the first image? */
71         if (item == gFirstImage) {
72             if (gCurImage)
73                 gCurImage = item->next;
74             gFirstImage = item->next;
75         }
76 
77         /* Is it the last image? */
78         else if (item == gFirstImage->prev) {
79             gFirstImage->prev = item->prev;   // New last image
80             item->prev->next = gFirstImage;
81             if (gCurImage)
82                 gCurImage = item->prev;
83         }
84         else if (gCurImage)
85             gCurImage = item->next;
86 
87         item->next->prev = item->prev;
88         item->prev->next = item->next;
89     }
90 
91     /* It's disconnected.  Free all the memory */
92     FreePhoImage(item);
93 
94     /* What does the list look like now? */
95     if (gDebug) {
96         printf("Image list after removal:\n");
97         printImageList();
98     }
99 }
100 
101 /* Append an item to the end of the list */
AppendItem(PhoImage * item)102 void AppendItem(PhoImage* item)
103 {
104     PhoImage* last;
105 
106     if (!item)
107         return;
108 
109     /* Is the list empty? */
110     if (gFirstImage == 0) {
111         gFirstImage = item;
112         item->next = item->prev = item;
113         return;
114     }
115 
116     /* Is there only one item in the list? */
117     if (gFirstImage->next == gFirstImage) {
118         gFirstImage->next = gFirstImage->prev = item;
119         item->next = item->prev = gFirstImage;
120         return;
121     }
122 
123     last = gFirstImage->prev;
124     last->next = item;
125     item->prev = last;
126     item->next = gFirstImage;
127     gFirstImage->prev = item;
128 }
129 
130 /* Remove all images from the image list, to start fresh. */
ClearImageList()131 void ClearImageList()
132 {
133     PhoImage* img = gFirstImage;
134     do {
135         PhoImage* next = img->next;
136         FreePhoImage(img);
137         img = next;
138     } while (img && img != gFirstImage);
139 
140     gCurImage = gFirstImage = 0;
141 }
142 
143