1 /* o_buflist.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
11 #include "o_buflist.h"
12
13 #include "i_modelview.h"
14 #include "i_view.h"
15 #include "s_string.h"
16 #include "s_util.h"
17 #include "sysdep.h"
18
19 #include <stdio.h>
20
21 BufferView *BufferList = 0;
22
BufferView(int createFlags,EModel ** ARoot)23 BufferView::BufferView(int createFlags, EModel **ARoot) :
24 EList(createFlags, ARoot, "Buffers"),
25 BList(0),
26 BCount(0),
27 SearchLen(0)
28 {
29 ModelNo = 0; // trick
30 }
31
~BufferView()32 BufferView::~BufferView() {
33 if (BList) {
34 for (int i = 0; i < BCount; i++)
35 if (BList[i])
36 free(BList[i]);
37 free(BList);
38 }
39 BufferList = 0;
40 }
41
GetEventMap()42 EEventMap *BufferView::GetEventMap() {
43 return FindEventMap("BUFFERS");
44 }
45
GetContext()46 int BufferView::GetContext() {
47 return CONTEXT_BUFFERS;
48 }
49
DrawLine(PCell B,int Line,int Col,ChColor color,int Width)50 void BufferView::DrawLine(PCell B, int Line, int Col, ChColor color, int Width) {
51 if (Line < BCount)
52 if (Col < int(strlen(BList[Line])))
53 MoveStr(B, 0, Width, BList[Line] + Col, color, Width);
54 }
55
FormatLine(int Line)56 char* BufferView::FormatLine(int Line) {
57 return strdup(BList[Line]);
58 }
59
UpdateList()60 void BufferView::UpdateList() {
61 EModel *B = ActiveModel;
62 int No;
63 char s[512] = "";
64
65 if (BList) {
66 for (int i = 0; i < BCount; i++)
67 if (BList[i])
68 free(BList[i]);
69 free(BList);
70 }
71 BList = 0;
72 BCount = 0;
73 while (B) {
74 BCount++;
75 B = B->Next;
76 if (B == ActiveModel) break;
77 }
78 BList = (char **) malloc(sizeof(char *) * BCount);
79 assert(BList != 0);
80 B = ActiveModel;
81 No = 0;
82 while (B) {
83 B->GetInfo(s, sizeof(s) - 1);
84 BList[No++] = strdup(s);
85 B = B->Next;
86 if (B == ActiveModel) break;
87 if (No >= BCount) break;
88 }
89 Count = BCount;
90 NeedsUpdate = 1;
91 }
92
GetBufferById(int No)93 EModel *BufferView::GetBufferById(int No) {
94 EModel *B;
95
96 B = ActiveModel;
97 while (B) {
98 if (No == 0) {
99 return B;
100 }
101 No--;
102 B = B->Next;
103 if (B == ActiveModel) break;
104 }
105 return 0;
106 }
107
ExecCommand(ExCommands Command,ExState & State)108 int BufferView::ExecCommand(ExCommands Command, ExState &State) {
109
110 switch (Command) {
111 case ExCloseActivate:
112 {
113 EModel *B;
114
115 CancelSearch();
116 B = GetBufferById(Row);
117 if (B && B != this) {
118 View->SwitchToModel(B);
119 delete this;
120 return 1;
121 }
122 }
123 return 0;
124 case ExBufListFileClose:
125 {
126 EModel *B = GetBufferById(Row);
127
128 CancelSearch();
129 if (B && B != this && Count > 1) {
130 if (B->ConfQuit(View->MView->Win)) {
131 View->DeleteModel(B);
132 }
133 UpdateList();
134 return 1;
135 }
136 }
137 return 0;
138 case ExBufListFileSave:
139 {
140 EModel *B = GetBufferById(Row);
141
142 if (B && B->GetContext() == CONTEXT_FILE)
143 if (((EBuffer *)B)->Save())
144 return 1;
145 }
146 return 0;
147
148 case ExActivateInOtherWindow:
149 {
150 EModel *B = GetBufferById(Row);
151
152 CancelSearch();
153 if (B) {
154 View->Next->SwitchToModel(B);
155 return 1;
156 }
157 }
158 return 0;
159 case ExBufListSearchCancel:
160 CancelSearch();
161 return 1;
162 case ExBufListSearchNext:
163 // Find next matching line
164 if (SearchLen) {
165 int i = Row + 1;
166 i = getMatchingLine(i == BCount ? 0 : i, 1);
167 // Never returns -1 since something already found before call
168 Row = SearchPos[SearchLen] = i;
169 }
170 return 1;
171 case ExBufListSearchPrev:
172 // Find prev matching line
173 if (SearchLen) {
174 int i = Row - 1;
175 i = getMatchingLine(i == -1 ? BCount - 1 : i, -1);
176 // Never returns -1 since something already found before call
177 Row = SearchPos[SearchLen] = i;
178 }
179 return 1;
180 default:
181 ;
182 }
183 return EList::ExecCommand(Command, State);
184 }
185
HandleEvent(TEvent & Event)186 void BufferView::HandleEvent(TEvent &Event) {
187 int resetSearch = 1;
188 EModel::HandleEvent(Event);
189 switch (Event.What) {
190 case evKeyUp:
191 resetSearch = 0;
192 break;
193 case evKeyDown:
194 switch (kbCode(Event.Key.Code)) {
195 case kbBackSp:
196 resetSearch = 0;
197 if (SearchLen > 0) {
198 SearchString[--SearchLen] = 0;
199 Row = SearchPos[SearchLen];
200 Msg(S_INFO, "Search: [%s]", SearchString);
201 } else
202 Msg(S_INFO, "");
203 break;
204 case kbEsc:
205 Msg(S_INFO, "");
206 break;
207 default:
208 resetSearch = 0;
209 if (isAscii(Event.Key.Code) && (SearchLen < ExISearch::MAXISEARCH)) {
210 char Ch = (char) Event.Key.Code;
211
212 SearchPos[SearchLen] = Row;
213 SearchString[SearchLen] = Ch;
214 SearchString[++SearchLen] = 0;
215 int i = getMatchingLine(Row, 1);
216 if (i == -1)
217 SearchString[--SearchLen] = 0;
218 else
219 Row = i;
220 Msg(S_INFO, "Search: [%s]", SearchString);
221 }
222 break;
223 }
224 }
225 if (resetSearch)
226 SearchLen = 0;
227 }
228
229 /**
230 * Search for next line containing SearchString starting from line 'start'.
231 * Direction should be 1 for ascending and -1 for descending.
232 * Returns line found or -1 if none.
233 */
getMatchingLine(int start,int direction)234 int BufferView::getMatchingLine (int start, int direction) {
235 int i = start;
236 do {
237 // Find SearchString at any place in string for line i
238 for(int j = 0; BList[i][j]; j++)
239 if (BList[i][j] == SearchString[0] && strnicmp(SearchString, BList[i]+j, SearchLen) == 0) {
240 return i;
241 }
242 i += direction;
243 if (i == BCount) i = 0; else if (i == -1) i = BCount - 1;
244 } while (i != start);
245 return -1;
246 }
247
Activate(int No)248 int BufferView::Activate(int No) {
249 EModel *B;
250
251 CancelSearch();
252 B = GetBufferById(No);
253 if (B) {
254 View->SwitchToModel(B);
255 return 1;
256 }
257 return 0;
258 }
259
CancelSearch()260 void BufferView::CancelSearch() {
261 SearchLen = 0;
262 Msg(S_INFO, "");
263 }
264
GetInfo(char * AInfo,size_t MaxLen)265 void BufferView::GetInfo(char *AInfo, size_t MaxLen) {
266 snprintf(AInfo, MaxLen, "%2d %04d/%03d Buffers", ModelNo, Row + 1, Count);
267 }
268
GetTitle(char * ATitle,size_t MaxLen,char * ASTitle,size_t SMaxLen)269 void BufferView::GetTitle(char *ATitle, size_t MaxLen, char *ASTitle, size_t SMaxLen) {
270 strlcpy(ATitle, "Buffers", MaxLen);
271 strlcpy(ASTitle, "Buffers", SMaxLen);
272 }
273