2 * HISTORY.C - command line history.
7 * 14/01/95 (Tim Norman)
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.
14 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
15 * added config.h include
17 * 25-Jan-1999 (Eric Kohl <ekohl@abo.rhein-zeitung.de>)
19 * Unicode and redirection safe!
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)
30 * HISTORY.C - command line history. Second version
35 * 06/12/99 (Paolo Pantaleo <paolopan@freemail.it>)
48 #ifdef FEATURE_HISTORY
59 typedef struct tagHISTORY
61 struct tagHISTORY *prev;
62 struct tagHISTORY *next;
64 } HIST_ENTRY, * LPHIST_ENTRY;
71 static LPHIST_ENTRY Top;
72 static LPHIST_ENTRY Bottom;
75 static LPHIST_ENTRY curr_ptr=0;
78 VOID InitHistory(VOID);
79 VOID History_move_to_bottom(VOID);
80 VOID History (INT dir, LPTSTR commandline);
81 VOID CleanHistory(VOID);
82 VOID History_del_current_entry(LPTSTR str);
85 static VOID del(LPHIST_ENTRY item);
86 static VOID add_at_bottom(LPTSTR string);
87 /*VOID add_before_last(LPTSTR string);*/
88 VOID set_size(INT new_size);
92 INT CommandHistory (LPTSTR cmd, LPTSTR param)
99 tmp=_tcschr(param,_T('/'));
104 switch (_totupper(param[1]))
106 case _T('F'):/*delete history*/
107 CleanHistory();InitHistory();
110 case _T('R'):/*read history from standard in*/
111 //hIn=GetStdHandle (STD_INPUT_HANDLE);
115 ConInString(szBuffer,sizeof(szBuffer)/sizeof(TCHAR));
116 if (*szBuffer!=_T('\0'))
123 case _T('A'):/*add an antry*/
127 case _T('S'):/*set history size*/
128 if ((tmp_int=_ttoi(param+2)))
138 for(h_tmp=Top->prev;h_tmp!=Bottom;h_tmp=h_tmp->prev)
139 ConErrPuts(h_tmp->string);
144 VOID set_size(INT new_size)
155 VOID InitHistory(VOID)
160 Top = malloc(sizeof(HIST_ENTRY));
161 Bottom = malloc(sizeof(HIST_ENTRY));
171 Bottom->string = NULL;
179 VOID CleanHistory(VOID)
182 while (Bottom->next!=Top)
191 VOID History_del_current_entry(LPTSTR str)
199 curr_ptr=Bottom->next;
206 curr_ptr=curr_ptr->prev;
214 VOID del(LPHIST_ENTRY item)
217 if( item==NULL || item==Top || item==Bottom )
220 DebugPrintf("del in " __FILE__ ": retrning\n"
221 "item is 0x%08x (Bottom is0x%08x)\n",
230 /*free string's mem*/
238 /*set links in prev and next item*/
239 item->next->prev=item->prev;
240 item->prev->next=item->next;
250 VOID add_before_last(LPTSTR string)
253 LPHIST_ENTRY tmp,before,after;
256 /*delete first entry if maximum number of entries is reached*/
257 while(size>=max_size)
260 while (_istspace(*string))
263 if (*string==_T('\0'))
268 /*allocte entry and string*/
269 tmp=malloc(sizeof(HIST_ENTRY));
270 tmp->string=malloc(_tcslen(string)+1);
271 _tcscpy(tmp->string,string);
298 VOID add_at_bottom(LPTSTR string)
305 /*delete first entry if maximum number of entries is reached*/
306 while(size>=max_size)
309 while (_istspace(*string))
312 if (*string==_T('\0'))
316 /*if new entry is the same than the last do not add it*/
318 if(_tcscmp(string,Bottom->next->string)==0)
322 /*fill bottom with string, it will become Bottom->next*/
323 Bottom->string=malloc(_tcslen(string)+1);
324 _tcscpy(Bottom->string,string);
326 /*save Bottom value*/
330 /*create new void Bottom*/
331 Bottom=malloc(sizeof(HIST_ENTRY));
345 VOID History_move_to_bottom(VOID)
352 VOID History (INT dir, LPTSTR commandline)
357 add_at_bottom(commandline);
364 commandline[0]=_T('\0');
371 if (curr_ptr->next==Top || curr_ptr==Top)
377 commandline[0]=_T('\0');
383 curr_ptr = curr_ptr->next;
385 _tcscpy(commandline,curr_ptr->string);
396 if (curr_ptr->prev==Bottom || curr_ptr==Bottom)
402 commandline[0]=_T('\0');
407 curr_ptr=curr_ptr->prev;
409 _tcscpy(commandline,curr_ptr->string);
421 LPTSTR history = NULL; /*buffer to sotre all the lines*/
422 LPTSTR lines[MAXLINES]; /*array of pointers to each line(entry)*/
423 /*located in history buffer*/
425 INT curline = 0; /*the last line recalled by user*/
426 INT numlines = 0; /*number of entries, included the last*/
429 INT maxpos = 0; /*index of last byte of last entry*/
433 VOID History (INT dir, LPTSTR commandline)
436 INT count; /*used in for loops*/
437 INT length; /*used in the same loops of count*/
438 /*both to make room when is full
439 either history or lines*/
441 /*first time History is called allocate mem*/
444 history = malloc (history_size * sizeof (TCHAR));
452 if (curline < numlines)
457 if (curline == numlines)
463 _tcscpy (commandline, lines[curline]);
474 _tcscpy (commandline, lines[curline]);
479 /* remove oldest string until there's enough room for next one */
480 /* strlen (commandline) must be less than history_size! */
481 while ((maxpos + (INT)_tcslen (commandline) + 1 > history_size) || (numlines >= MAXLINES))
483 length = _tcslen (lines[0]) + 1;
485 for (count = 0; count < maxpos && count + (lines[1] - lines[0]) < history_size; count++)
487 history[count] = history[count + length];
492 for (count = 0; count <= numlines && count < MAXLINES; count++)
494 lines[count] = lines[count + 1] - length;
499 ConOutPrintf (_T("Reduced size: %ld lines\n"), numlines);
501 for (count = 0; count < numlines; count++)
503 ConOutPrintf (_T("%d: %s\n"), count, lines[count]);
508 /*copy entry in the history bufer*/
509 _tcscpy (lines[numlines], commandline);
512 /*set last lines[numlines] pointer next the end of last, valid,
513 just setted entry (the two lines above)*/
514 lines[numlines] = lines[numlines - 1] + _tcslen (commandline) + 1;
515 maxpos += _tcslen (commandline) + 1;
516 /* last line, empty */