OSDN Git Service

Update CWindowsManagerDialog - check some pointers for null and made … (#824) (2)
[winmerge-jp/winmerge-jp.git] / Src / DiffItem.cpp
1 /**
2  *  @file DiffItem.cpp
3  *
4  *  @brief Implementation of DIFFITEM
5  */ 
6
7 #include "pch.h"
8 #include "DiffItem.h"
9 #include "paths.h"
10 #include "DebugNew.h"
11
12 DIFFITEM DIFFITEM::emptyitem;
13
14 /** @brief DIFFITEM's destructor */
15 DIFFITEM::~DIFFITEM()
16 {
17         RemoveChildren();
18         assert(children == nullptr);
19 }
20
21 /** @brief Return path to left/right file, including all but file name */
22 String DIFFITEM::getFilepath(int nIndex, const String &sRoot) const
23 {
24         if (diffcode.exists(nIndex))
25         {
26                 return paths::ConcatPath(sRoot, diffFileInfo[nIndex].path);
27         }
28         return _T("");
29 }
30
31 /** @brief Return depth of path */
32 int DIFFITEM::GetDepth() const
33 {
34         const DIFFITEM *cur;
35         int depth;
36         for (depth = 0, cur = parent; cur->parent != nullptr; depth++, cur = cur->parent)
37                 ;
38         return depth;
39 }
40
41 /**
42  * @brief Return whether the specified item is an ancestor of the current item
43  */
44 bool DIFFITEM::IsAncestor(const DIFFITEM *pdi) const
45 {
46         const DIFFITEM *cur;
47         for (cur = this; cur->parent != nullptr; cur = cur->parent)
48         {
49                 if (cur->parent == pdi)
50                         return true;
51         }
52         return false;
53 }
54
55 /** @brief Remove and delete all children DIFFITEM entries */
56 void DIFFITEM::RemoveChildren()
57 {
58         DIFFITEM *pRem = children;
59         while (pRem != nullptr)
60         {
61                 assert(pRem->parent == this);
62                 DIFFITEM *pNext = pRem->Flink;
63                 delete pRem;
64                 pRem = pNext;
65         }
66         children = nullptr;
67 }
68
69 /** @brief Swap two items in `diffFileInfo[]`.  Used when swapping GUI panes. */
70 void DIFFITEM::Swap(int idx1, int idx2)
71 {
72         std::swap(diffFileInfo[idx1], diffFileInfo[idx2]);
73         diffcode.swap(idx1, idx2);
74         if (HasChildren())
75         {
76                 for (DIFFITEM *p = children; p != nullptr; p = p->Flink)
77                         p->Swap(idx1, idx2);
78         }
79 }
80
81
82 /* static */
83 DIFFITEM *DIFFITEM::GetEmptyItem()  
84
85         // TODO: It would be better if there were individual items
86         // (for whatever these special items are?) because here we 
87         // have to *hope* client does not modify this static (shared) item
88
89         assert(emptyitem.parent == nullptr);
90         assert(emptyitem.Flink == nullptr);
91         assert(emptyitem.Blink == nullptr);
92         assert(emptyitem.children == nullptr);
93         assert(emptyitem.nidiffs == -1);
94         assert(emptyitem.nsdiffs == -1);
95         assert(emptyitem.customFlags == ViewCustomFlags::INVALID_CODE);
96         assert(emptyitem.diffcode.diffcode == 0);
97
98         return &emptyitem; 
99 }
100
101  
102 /**
103 * @brief Add Sibling item
104 * @param [in] p The item to be added
105 */
106 void DIFFITEM::AppendSibling(DIFFITEM *p)
107 {
108         assert(parent->children == this);
109
110         // Two situations
111
112         if (Blink == nullptr)
113         {
114                 // Insert first sibling (besides ourself)
115                 assert(Flink == nullptr);
116                 p->Flink = nullptr;
117                 p->Blink = this;
118                 Flink = p;
119         }
120         else
121         {
122                 // Insert additional siblings
123                 assert(Flink != nullptr);
124                 p->Flink = nullptr;
125                 p->Blink = Blink;
126                 Blink->Flink = p;
127         }
128         Blink = p;
129 }
130
131 void DIFFITEM::AddChildToParent(DIFFITEM *p)
132 {
133         p->parent = this;
134         if (children == nullptr)
135                 // First child
136                 children = p;
137         else
138                 // More siblings
139                 children->AppendSibling(p);
140 }
141
142 void DIFFITEM::DelinkFromSiblings()
143 {
144         if (parent != nullptr && parent->children != nullptr)
145         {
146                 // If `this` is at end of Sibling linkage, fix First Child's end link
147                 if (parent->children->Blink == this)
148                 {
149                         assert(Flink == nullptr);
150                         parent->children->Blink = Blink;
151                         if (Blink == this)
152                                 Blink = nullptr;
153                 }
154                 // If `this` is the First Child, link parent to next Sibling
155                 if (parent->children == this)
156                 {
157                         parent->children = Flink;
158                 }
159         }
160         if (Blink != nullptr && Blink->Flink != nullptr)
161                 Blink->Flink = Flink;
162         if (Flink != nullptr)
163                 Flink->Blink = Blink;
164         Flink = Blink = nullptr;
165 }
166
167 void DIFFCODE::swap(int idx1, int idx2)
168 {
169         bool e[3] = { false, false, false };
170         for (int i = 0; i < 3; ++i)
171                 e[i] = exists(i);
172         std::swap(e[idx1], e[idx2]);
173         setSideNone();
174         for (int i = 0; i < 3; ++i)
175                 if (e[i]) setSideFlag(i);
176         bool binflag1 = (diffcode & (BINSIDE1 << idx1));
177         bool binflag2 = (diffcode & (BINSIDE1 << idx2));
178         Set(BINSIDE1 << idx1, binflag2 ? (BINSIDE1 << idx1) : 0);
179         Set(BINSIDE1 << idx2, binflag1 ? (BINSIDE1 << idx2) : 0);
180         if ((diffcode & THREEWAY) != 0)
181         {
182                 int idx = -1;
183                 switch (diffcode & COMPAREFLAGS3WAY)
184                 {
185                 case DIFF1STONLY:
186                         if (idx1 == 0 || idx2 == 0)
187                                 idx = (idx1 == 0) ? idx2 : idx1;
188                         break;
189                 case DIFF2NDONLY:
190                         if (idx1 == 1 || idx2 == 1)
191                                 idx = (idx1 == 1) ? idx2 : idx1;
192                         break;
193                 case DIFF3RDONLY:
194                         if (idx1 == 2 || idx2 == 2)
195                                 idx = (idx1 == 2) ? idx2 : idx1;
196                         break;
197                 }
198                 if (idx == 0)
199                         Set(COMPAREFLAGS3WAY, DIFF1STONLY);
200                 else if (idx == 1)
201                         Set(COMPAREFLAGS3WAY, DIFF2NDONLY);
202                 else if (idx == 2)
203                         Set(COMPAREFLAGS3WAY, DIFF3RDONLY);
204         }
205 }