[TRANSLATIONS] Update the email address and add a note in the Turkish translation...
[reactos.git] / base / shell / cmd / history.c
1 /*
2 * HISTORY.C - command line history.
3 *
4 *
5 * History:
6 *
7 * 14/01/95 (Tim Norman)
8 * started.
9 *
10 * 08/08/95 (Matt Rains)
11 * i have cleaned up the source code. changes now bring this source
12 * into guidelines for recommended programming practice.
13 *
14 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
15 * added config.h include
16 *
17 * 25-Jan-1999 (Eric Kohl)
18 * Cleanup!
19 * Unicode and redirection safe!
20 *
21 * 25-Jan-1999 (Paolo Pantaleo <paolopan@freemail.it>)
22 * Added lots of comments (beginning studying the source)
23 * Added command.com's F3 support (see cmdinput.c)
24 *
25 */
26
27
28
29 /*
30 * HISTORY.C - command line history. Second version
31 *
32 *
33 * History:
34 *
35 * 06/12/99 (Paolo Pantaleo <paolopan@freemail.it>)
36 * started.
37 *
38 */
39
40 #include "precomp.h"
41
42 #ifdef FEATURE_HISTORY
43
44 typedef struct tagHISTORY
45 {
46 struct tagHISTORY *prev;
47 struct tagHISTORY *next;
48 LPTSTR string;
49 } HIST_ENTRY, * LPHIST_ENTRY;
50
51 static INT size, max_size=100;
52
53 static LPHIST_ENTRY Top;
54 static LPHIST_ENTRY Bottom;
55
56 static LPHIST_ENTRY curr_ptr=0;
57
58 VOID InitHistory(VOID);
59 VOID History_move_to_bottom(VOID);
60 VOID History (INT dir, LPTSTR commandline);
61 VOID CleanHistory(VOID);
62 VOID History_del_current_entry(LPTSTR str);
63
64 /*service functions*/
65 static VOID del(LPHIST_ENTRY item);
66 static VOID add_at_bottom(LPTSTR string);
67 /*VOID add_before_last(LPTSTR string);*/
68 VOID set_size(INT new_size);
69
70
71 INT CommandHistory (LPTSTR param)
72 {
73 LPTSTR tmp;
74 INT tmp_int;
75 LPHIST_ENTRY h_tmp;
76 TCHAR szBuffer[2048];
77
78 tmp=_tcschr(param,_T('/'));
79
80 if (tmp)
81 {
82 param=tmp;
83 switch (_totupper(param[1]))
84 {
85 case _T('F'):/*delete history*/
86 CleanHistory();InitHistory();
87 break;
88
89 case _T('R'):/*read history from standard in*/
90 for(;;)
91 {
92 ConInString(szBuffer,sizeof(szBuffer)/sizeof(TCHAR));
93 if (*szBuffer!=_T('\0'))
94 History(0,szBuffer);
95 else
96 break;
97 }
98 break;
99
100 case _T('A'):/*add an antry*/
101 History(0,param+2);
102 break;
103
104 case _T('S'):/*set history size*/
105 if ((tmp_int=_ttoi(param+2)))
106 set_size(tmp_int);
107 break;
108
109 default:
110 return 1;
111 }
112 }
113 else
114 {
115 for (h_tmp = Top->prev; h_tmp != Bottom; h_tmp = h_tmp->prev)
116 ConErrPuts(h_tmp->string);
117 }
118 return 0;
119 }
120
121 VOID set_size(INT new_size)
122 {
123 while (new_size<size)
124 del(Top->prev);
125
126 max_size=new_size;
127 }
128
129
130 VOID InitHistory(VOID)
131 {
132 size=0;
133
134 Top = cmd_alloc(sizeof(HIST_ENTRY));
135 Bottom = cmd_alloc(sizeof(HIST_ENTRY));
136
137 Top->prev = Bottom;
138 Top->next = NULL;
139 Top->string = NULL;
140
141 Bottom->prev = NULL;
142 Bottom->next = Top;
143 Bottom->string = NULL;
144
145 curr_ptr=Bottom;
146 }
147
148
149 VOID CleanHistory(VOID)
150 {
151 while (Bottom->next!=Top)
152 del(Bottom->next);
153
154 cmd_free(Top);
155 cmd_free(Bottom);
156 }
157
158
159 VOID History_del_current_entry(LPTSTR str)
160 {
161 LPHIST_ENTRY tmp;
162
163 if (size == 0)
164 return;
165
166 if (curr_ptr == Bottom)
167 curr_ptr=Bottom->next;
168
169 if (curr_ptr == Top)
170 curr_ptr=Top->prev;
171
172
173 tmp = curr_ptr;
174 curr_ptr = curr_ptr->prev;
175 del(tmp);
176 History(-1, str);
177 }
178
179
180 static
181 VOID del(LPHIST_ENTRY item)
182 {
183 if (item==NULL || item==Top || item==Bottom)
184 {
185 TRACE ("del in " __FILE__ ": returning\n"
186 "item is 0x%08x (Bottom is0x%08x)\n",
187 item, Bottom);
188 return;
189 }
190
191 /*free string's mem*/
192 if (item->string)
193 cmd_free(item->string);
194
195 /*set links in prev and next item*/
196 item->next->prev=item->prev;
197 item->prev->next=item->next;
198
199 cmd_free(item);
200
201 size--;
202 }
203
204 static
205 VOID add_at_bottom(LPTSTR string)
206 {
207 LPHIST_ENTRY tmp;
208
209 /*delete first entry if maximum number of entries is reached*/
210 while(size>=max_size)
211 del(Top->prev);
212
213 while (_istspace(*string))
214 string++;
215
216 if (*string==_T('\0'))
217 return;
218
219 /*if new entry is the same than the last do not add it*/
220 if (size)
221 if (_tcscmp(string,Bottom->next->string)==0)
222 return;
223
224 /*fill bottom with string, it will become Bottom->next*/
225 Bottom->string=cmd_alloc((_tcslen(string)+1)*sizeof(TCHAR));
226 _tcscpy(Bottom->string,string);
227
228 /*save Bottom value*/
229 tmp=Bottom;
230
231 /*create new void Bottom*/
232 Bottom=cmd_alloc(sizeof(HIST_ENTRY));
233 Bottom->next=tmp;
234 Bottom->prev=NULL;
235 Bottom->string=NULL;
236
237 tmp->prev=Bottom;
238
239 /*set new size*/
240 size++;
241 }
242
243
244 VOID History_move_to_bottom(VOID)
245 {
246 curr_ptr=Bottom;
247 }
248
249 LPCTSTR PeekHistory(INT dir)
250 {
251 LPHIST_ENTRY entry = curr_ptr;
252
253 if (dir == 0)
254 return NULL;
255
256 if (dir < 0)
257 {
258 /* key up */
259 if (entry->next == Top || entry == Top)
260 {
261 #ifdef WRAP_HISTORY
262 entry = Bottom;
263 #else
264 return NULL;
265 #endif
266 }
267 entry = entry->next;
268 }
269 else
270 {
271 /* key down */
272 if (entry->next == Bottom || entry == Bottom)
273 {
274 #ifdef WRAP_HISTORY
275 entry = Top;
276 #else
277 return NULL;
278 #endif
279 }
280 entry = entry->prev;
281 }
282
283 return entry->string;
284 }
285
286 VOID History (INT dir, LPTSTR commandline)
287 {
288 if (dir==0)
289 {
290 add_at_bottom(commandline);
291 curr_ptr=Bottom;
292 return;
293 }
294
295 if (size==0)
296 {
297 commandline[0]=_T('\0');
298 return;
299 }
300
301 if (dir<0)/*key up*/
302 {
303 if (curr_ptr->next==Top || curr_ptr==Top)
304 {
305 #ifdef WRAP_HISTORY
306 curr_ptr=Bottom;
307 #else
308 curr_ptr=Top;
309 commandline[0]=_T('\0');
310 return;
311 #endif
312 }
313
314 curr_ptr = curr_ptr->next;
315 if (curr_ptr->string)
316 _tcscpy(commandline,curr_ptr->string);
317 }
318
319 if (dir>0)
320 {
321 if (curr_ptr->prev==Bottom || curr_ptr==Bottom)
322 {
323 #ifdef WRAP_HISTORY
324 curr_ptr=Top;
325 #else
326 curr_ptr=Bottom;
327 commandline[0]=_T('\0');
328 return;
329 #endif
330 }
331
332 curr_ptr=curr_ptr->prev;
333 if (curr_ptr->string)
334 _tcscpy(commandline,curr_ptr->string);
335 }
336 }
337
338 #endif //#if FEATURE_HISTORY