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