1 #include "e_mark.h"
2 #include "s_util.h"
3 #include "sysdep.h"
4
5 #include <ctype.h>
6
7 EMarkIndex markIndex;
8
EMark(const char * aName,const char * aFileName,EPoint aPoint,EBuffer * aBuffer)9 EMark::EMark(const char *aName, const char *aFileName,
10 EPoint aPoint, EBuffer *aBuffer) :
11 Name(aName),
12 FileName(aFileName),
13 Point(aPoint),
14 Buffer(0)
15 {
16 if (!aBuffer)
17 aBuffer = FindFile(aFileName);
18 if (aBuffer && aBuffer->Loaded)
19 SetBuffer(aBuffer);
20 }
21
~EMark()22 EMark::~EMark() {
23 if (Buffer)
24 RemoveBuffer(Buffer);
25 }
26
SetBuffer(EBuffer * aBuffer)27 int EMark::SetBuffer(EBuffer *aBuffer) {
28 assert(aBuffer != 0);
29 assert(filecmp(aBuffer->FileName, FileName.c_str()) == 0);
30
31 if (Point.Row >= aBuffer->RCount)
32 Point.Row = aBuffer->RCount - 1;
33 if (Point.Row < 0)
34 Point.Row = 0;
35
36 if (aBuffer->PlaceBookmark(Name.c_str(), Point) == 1) {
37 Buffer = aBuffer;
38 return 1;
39 }
40 return 0;
41 }
42
RemoveBuffer(EBuffer * aBuffer)43 int EMark::RemoveBuffer(EBuffer *aBuffer) {
44 assert(aBuffer != 0);
45 if (Buffer == 0 || Buffer != aBuffer)
46 return 0;
47 assert(filecmp(aBuffer->FileName, FileName.c_str()) == 0);
48
49 if (!Buffer->GetBookmark(Name.c_str(), Point))
50 return 0;
51 if (!Buffer->RemoveBookmark(Name.c_str()))
52 return 0;
53
54 Buffer = 0;
55 return 1;
56 }
57
GetPoint()58 EPoint &EMark::GetPoint() {
59 if (Buffer) {
60 assert(Buffer->GetBookmark(Name.c_str(), Point) != 0);
61 }
62 return Point;
63 }
64
EMarkIndex()65 EMarkIndex::EMarkIndex() {
66 }
67
~EMarkIndex()68 EMarkIndex::~EMarkIndex() {
69 vector_iterate(EMark*, Marks, it)
70 delete (*it);
71 }
72
insert(const char * aName,const char * aFileName,EPoint aPoint,EBuffer * aBuffer)73 EMark *EMarkIndex::insert(const char *aName, const char *aFileName, EPoint aPoint, EBuffer *aBuffer) {
74
75 assert(aName != 0 && aName[0] != 0);
76 assert(aFileName != 0 && aFileName[0] != 0);
77
78 size_t L = 0, R = Marks.size();
79
80 while (L < R) {
81 size_t M = (L + R) / 2;
82 int cmp = strcmp(aName, Marks[M]->GetName());
83 if (cmp == 0)
84 return 0;
85 if (cmp > 0)
86 L = M + 1;
87 else
88 R = M;
89 }
90
91 EMark* m = new EMark(aName, aFileName, aPoint, aBuffer);
92 Marks.insert(Marks.begin() + L, m);
93 return m;
94 }
95
insert(const char * aName,EBuffer * aBuffer,EPoint aPoint)96 EMark *EMarkIndex::insert(const char *aName, EBuffer *aBuffer, EPoint aPoint) {
97 assert(aName != 0 && aName[0] != 0);
98 assert(aBuffer != 0);
99 assert(aBuffer->FileName != 0);
100
101 return insert(aName, aBuffer->FileName, aPoint, aBuffer);
102 }
103
locate(const char * aName)104 EMark *EMarkIndex::locate(const char *aName) {
105 assert(aName != 0 && aName[0] != 0);
106
107 size_t L = 0, R = Marks.size();
108
109 while (L < R) {
110 size_t M = (L + R) / 2;
111 int cmp = strcmp(aName, Marks[M]->GetName());
112 if (cmp == 0)
113 return Marks[M];
114 else if (cmp > 0)
115 L = M + 1;
116 else
117 R = M;
118 }
119 return 0;
120 }
121
remove(const char * aName)122 int EMarkIndex::remove(const char *aName) {
123 assert(aName != 0 && aName[0] != 0);
124
125 size_t L = 0, R = Marks.size();
126
127 while (L < R) {
128 size_t M = (L + R) / 2;
129 int cmp = strcmp(aName, Marks[M]->GetName());
130 if (cmp == 0) {
131 delete Marks[M];
132 Marks.erase(Marks.begin() + M);
133 return 1;
134 } else if (cmp > 0)
135 L = M + 1;
136 else
137 R = M;
138 }
139 return 0;
140 }
141
view(EView * aView,const char * aName)142 int EMarkIndex::view(EView *aView, const char *aName) {
143 EMark *m = locate(aName);
144 if (m) {
145 EBuffer *b = m->GetBuffer();
146 if (b == 0) {
147 if (!FileLoad(0, m->GetFileName(), 0, aView))
148 return 0;
149 if (!retrieveForBuffer((EBuffer *)ActiveModel))
150 return 0;
151 b = (EBuffer *)ActiveModel;
152 }
153 aView->SwitchToModel(b);
154 return b->GotoBookmark(m->GetName());
155 }
156 return 0;
157 }
158
retrieveForBuffer(EBuffer * aBuffer)159 int EMarkIndex::retrieveForBuffer(EBuffer *aBuffer) {
160 vector_iterate(EMark*, Marks, it)
161 if (((*it)->GetBuffer() == 0)
162 && (filecmp(aBuffer->FileName, (*it)->GetFileName()) == 0))
163 if (!(*it)->SetBuffer(aBuffer))
164 return 0;
165 return 1;
166 }
167
storeForBuffer(EBuffer * aBuffer)168 int EMarkIndex::storeForBuffer(EBuffer *aBuffer) {
169 vector_iterate(EMark*, Marks, it)
170 if (((*it)->GetBuffer() == aBuffer)
171 && ((*it)->RemoveBuffer(aBuffer) == 0))
172 return 0;
173 return 1;
174 }
175
saveToDesktop(FILE * fp)176 int EMarkIndex::saveToDesktop(FILE *fp) {
177 vector_iterate(EMark*, Marks, it)
178 // ??? file of buffer or of mark? (different if file renamed) ???
179 // perhaps marks should be duplicated?
180 if (fprintf(fp, "M|%d|%d|%s|%s\n",
181 (*it)->GetPoint().Row,
182 (*it)->GetPoint().Col,
183 (*it)->GetName(),
184 (*it)->GetFileName()) < 0)
185 return 0;
186
187 return 1;
188 }
189
190 // needs performance fixes (perhaps a redesign ?)
191
pushMark(EBuffer * aBuffer,EPoint P)192 EMark *EMarkIndex::pushMark(EBuffer *aBuffer, EPoint P) {
193 int stackTop = -1;
194
195 vector_iterate(EMark*, Marks, it) {
196 const char *name = (*it)->GetName();
197 if (name && name[0] == '#' && isdigit(name[1])) {
198 int no = atoi(name + 1);
199 if (no > stackTop)
200 stackTop = no;
201 }
202 }
203 char name[20];
204 sprintf(name, "#%d", stackTop + 1);
205 return insert(name, aBuffer, P);
206 }
207
popMark(EView * aView)208 int EMarkIndex::popMark(EView *aView) {
209 int stackTop = -1;
210
211 vector_iterate(EMark*, Marks, it) {
212 const char *name = (*it)->GetName();
213 if (name && name[0] == '#' && isdigit(name[1])) {
214 int no = atoi(name + 1);
215 if (no > stackTop)
216 stackTop = no;
217 }
218 }
219 if (stackTop == -1)
220 return 0;
221 char name[20];
222 sprintf(name, "#%d", stackTop);
223 if (!view(aView, name))
224 return 0;
225 assert(remove(name) == 1);
226 return 1;
227 }
228