1 /*    e_line.cpp
2  *
3  *    Copyright (c) 1994-1996, Marko Macek
4  *
5  *    You may distribute under the terms of either the GNU General Public
6  *    License or the Artistic License, as specified in the README file.
7  *
8  */
9 
10 #include "o_buflist.h"
11 #include "sysdep.h"
12 
ELine(size_t ACount,const char * AChars)13 ELine::ELine(size_t ACount, const char *AChars) :
14     Count(ACount),
15     Chars(NULL)
16 #ifdef CONFIG_SYNTAX_HILIT
17     , StateE(0)
18 #endif
19 {
20     Allocate(Count);
21     if (AChars)
22         memcpy(Chars, AChars, Count);
23     else
24         memset(Chars, ' ', Count);
25 }
26 
ELine(char * AChars,size_t ACount)27 ELine::ELine(char *AChars, size_t ACount) :
28     Count(ACount),
29     Chars(AChars)
30 #ifdef CONFIG_SYNTAX_HILIT
31     , StateE(0)
32 #endif
33 {
34 }
35 
~ELine()36 ELine::~ELine() {
37     free(Chars);
38 }
39 
Allocate(size_t Bytes)40 int ELine::Allocate(size_t Bytes) {
41     Chars = (char*)realloc(Chars, Bytes | CHAR_TRESHOLD);
42     return (Chars != NULL);
43 }
44 
ScreenPos(ELine * L,int Offset)45 int EBuffer::ScreenPos(ELine *L, int Offset) {
46     int ExpandTabs = BFI(this, BFI_ExpandTabs);
47     int TabSize = BFI(this, BFI_TabSize);
48 
49     if (!ExpandTabs)
50         return Offset;
51 
52     char *p = L->Chars;
53     int Len = L->Count;
54     int Pos = 0;
55     int Ofs = Offset;
56 
57     if (Ofs > Len) {
58         while (Len > 0) {
59             if (*p++ != '\t')
60                 Pos++;
61             else
62                 Pos = NextTab(Pos, TabSize);
63             Len--;
64         }
65         Pos += Ofs - L->Count;
66     } else
67         while (Ofs > 0) {
68             if (*p++ != '\t')
69                 Pos++;
70             else
71                 Pos = NextTab(Pos, TabSize);
72             Ofs--;
73         }
74 
75     return Pos;
76 }
77 
CharOffset(ELine * L,int ScreenPos)78 int EBuffer::CharOffset(ELine *L, int ScreenPos) {
79     int ExpandTabs = BFI(this, BFI_ExpandTabs);
80     int TabSize = BFI(this, BFI_TabSize);
81 
82     if (!ExpandTabs)
83         return ScreenPos;
84 
85     int Pos = 0;
86     int Ofs = 0;
87     char *p = L->Chars;
88     int Len = L->Count;
89 
90     while (Len > 0) {
91         if (*p++ != '\t')
92             Pos++;
93         else
94             Pos = NextTab(Pos, TabSize);
95         if (Pos > ScreenPos)
96             return Ofs;
97         Ofs++;
98         Len--;
99     }
100 
101     return Ofs + ScreenPos - Pos;
102 }
103 
Allocate(int ACount)104 int EBuffer::Allocate(int ACount) {
105     PELine *L;
106 
107     if (ACount > 10 * 1024 * 1024) // FIXME: - let's crash, before OOOM kills us
108         return 0;
109 
110     L = (PELine *) realloc(LL, sizeof(PELine) * (ACount + 1));
111     if (!L && ACount != 0)
112         return 0;
113     RAllocated = ACount;
114     LL = L;
115 
116     return 1;
117 }
118 
MoveRGap(int RPos)119 int EBuffer::MoveRGap(int RPos) {
120     int GapSize = RAllocated - RCount;
121 
122     if (RGap == RPos)
123         return 1;
124     if (RPos < 0 || RPos > RCount)
125         return 0;
126 
127     if (RGap < RPos) {
128         if (RPos - RGap == 1)
129             LL[RGap] = LL[RGap + GapSize];
130         else
131             memmove(LL + RGap,
132                 LL + RGap + GapSize,
133                 sizeof(PELine) * (RPos - RGap));
134     } else {
135         if (RGap - RPos == 1)
136             LL[RPos + GapSize] = LL[RPos];
137         else
138             memmove(LL + RPos + GapSize,
139                     LL + RPos,
140                     sizeof(PELine) * (RGap - RPos));
141     }
142     RGap = RPos;
143 
144     return 1;
145 }
146 
AllocVis(int ACount)147 int EBuffer::AllocVis(int ACount) {
148     int *V = (int *) realloc(VV, sizeof(int) * (ACount + 1));
149     if (!V && ACount != 0)
150         return 0;
151     VAllocated = ACount;
152     VV = V;
153 
154     return 1;
155 }
156 
MoveVGap(int VPos)157 int EBuffer::MoveVGap(int VPos) {
158     int GapSize = VAllocated - VCount;
159 
160     if (VGap == VPos) return 1;
161     if (VPos < 0 || VPos > VCount) return 0;
162 
163     if (VGap < VPos) {
164         if (VPos - VGap == 1)
165             VV[VGap] = VV[VGap + GapSize];
166         else
167             memmove(VV + VGap,
168                     VV + VGap + GapSize,
169                     sizeof(VV[0]) * (VPos - VGap));
170     } else {
171         if (VGap - VPos == 1) {
172             VV[VPos + GapSize] = VV[VPos];
173         } else {
174             memmove(VV + VPos + GapSize,
175                     VV + VPos,
176                     sizeof(VV[0]) * (VGap - VPos));
177         }
178     }
179     VGap = VPos;
180     return 1;
181 }
182 
RToV(int No)183 int EBuffer::RToV(int No) {
184     int L = 0, R = VCount, M, V;
185 
186     if (No > Vis(VCount - 1) + VCount - 1)   // beyond end
187         return -1;
188     if (No < VCount) // no folds before (direct match)
189         if (Vis(No) == 0) return No;
190 
191     while (L < R) {
192         M = (L + R) / 2;
193         V = Vis(M) + M;
194         if (V == No)
195             return M;
196         if (V > No)
197             R = M;
198         else
199             L = M + 1;
200     }
201     return -1;
202 }
203 
RToVN(int No)204 int EBuffer::RToVN(int No) {
205     int L = 0, R = VCount, M, V;
206 
207     if (No == RCount)
208         return VCount;
209     if (No > Vis(VCount - 1) + VCount - 1)
210         return VCount - 1;
211     if (No < VCount)
212         if (Vis(No) == 0) return No;
213 
214     while (L < R) {
215         M = (L + R) / 2;
216         V = Vis(M) + M;
217         if (V == No)
218             return M;
219         else if (V > No)
220             R = M;
221         else {
222             if (M == VCount - 1)
223                 return M;
224             else if (Vis(M + 1) + M + 1 > No)
225                 return M;
226             L = M + 1;
227         }
228     }
229     return R;
230 }
231