Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381/* * HISTORY.C - command line history. * * * History: * * 14/01/95 (Tim Norman) * started. * * 08/08/95 (Matt Rains) * i have cleaned up the source code. changes now bring this source * into guidelines for recommended programming practice. * * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) * added config.h include * * 25-Jan-1999 (Eric Kohl) * Cleanup! * Unicode and redirection safe! * * 25-Jan-1999 (Paolo Pantaleo <paolopan@freemail.it>) * Added lots of comments (beginning studying the source) * Added command.com's F3 support (see cmdinput.c) * */
/* * HISTORY.C - command line history. Second version * * * History: * * 06/12/99 (Paolo Pantaleo <paolopan@freemail.it>) * started. * */
#include "precomp.h"
#ifdef FEATURE_HISTORY
typedef struct tagHISTORY{ struct tagHISTORY *prev; struct tagHISTORY *next; LPTSTR string;} HIST_ENTRY, * LPHIST_ENTRY;
static INT size, max_size = 100;
static LPHIST_ENTRY Top = NULL;static LPHIST_ENTRY Bottom = NULL;
static LPHIST_ENTRY curr_ptr = NULL;
VOID InitHistory(VOID);VOID History_move_to_bottom(VOID);VOID History(INT dir, LPTSTR commandline);VOID CleanHistory(VOID);VOID History_del_current_entry(LPTSTR str);
/*service functions*/static VOID del(LPHIST_ENTRY item);static VOID add_at_bottom(LPTSTR string);/*VOID add_before_last(LPTSTR string);*/VOID set_size(INT new_size);
INT CommandHistory(LPTSTR param){ LPTSTR tmp; INT tmp_int; LPHIST_ENTRY h_tmp; TCHAR szBuffer[2048];
tmp=_tcschr(param,_T('/'));
if (tmp) { param=tmp; switch (_totupper(param[1])) { case _T('F'):/*delete history*/ CleanHistory();InitHistory(); break;
case _T('R'):/*read history from standard in*/ for(;;) { ConInString(szBuffer,sizeof(szBuffer)/sizeof(TCHAR)); if (*szBuffer!=_T('\0')) History(0,szBuffer); else break; } break;
case _T('A'):/*add an antry*/ History(0,param+2); break;
case _T('S'):/*set history size*/ if ((tmp_int=_ttoi(param+2))) set_size(tmp_int); break;
default: return 1; } } else { for (h_tmp = Top->prev; h_tmp != Bottom; h_tmp = h_tmp->prev) ConOutPrintf(_T("%s\n"), h_tmp->string); } return 0;}
VOID set_size(INT new_size){ ASSERT(Top && Bottom);
while (new_size<size) del(Top->prev);
max_size=new_size;}
VOID InitHistory(VOID){ size = 0;
Top = cmd_alloc(sizeof(HIST_ENTRY)); if (!Top) { WARN("Cannot allocate memory for Top!\n"); return; } Bottom = cmd_alloc(sizeof(HIST_ENTRY)); if (!Bottom) { WARN("Cannot allocate memory for Bottom!\n"); cmd_free(Top); Top = NULL; return; }
Top->prev = Bottom; Top->next = NULL; Top->string = NULL;
Bottom->prev = NULL; Bottom->next = Top; Bottom->string = NULL;
curr_ptr = Bottom;}
VOID CleanHistory(VOID){ ASSERT(Top && Bottom);
while (Bottom->next != Top) del(Bottom->next);
cmd_free(Top); cmd_free(Bottom);}
VOID History_del_current_entry(LPTSTR str){ LPHIST_ENTRY tmp;
ASSERT(Top && Bottom);
if (size == 0) return;
if (curr_ptr == Bottom) curr_ptr = Bottom->next;
if (curr_ptr == Top) curr_ptr = Top->prev;
tmp = curr_ptr; curr_ptr = curr_ptr->prev; del(tmp); History(-1, str);}
staticVOID del(LPHIST_ENTRY item){ ASSERT(Top && Bottom);
if (item==NULL || item==Top || item==Bottom) { TRACE ("del in " __FILE__ ": returning\n" "item is 0x%08x (Bottom is0x%08x)\n", item, Bottom); return; }
/*free string's mem*/ if (item->string) cmd_free(item->string);
/*set links in prev and next item*/ item->next->prev=item->prev; item->prev->next=item->next;
cmd_free(item);
size--;}
staticVOID add_at_bottom(LPTSTR string){ LPHIST_ENTRY tmp;
ASSERT(Top && Bottom);
/*delete first entry if maximum number of entries is reached*/ while (size>=max_size) del(Top->prev);
while (_istspace(*string)) string++;
if (*string==_T('\0')) return;
/*if new entry is the same than the last do not add it*/ if (size) { if (_tcscmp(string,Bottom->next->string)==0) return; }
/*create new empty Bottom*/ tmp = cmd_alloc(sizeof(HIST_ENTRY)); if (!tmp) { WARN("Cannot allocate memory for new Bottom!\n"); return; }
/*fill old bottom with string, it will become new Bottom->next*/ Bottom->string = cmd_alloc((_tcslen(string)+1)*sizeof(TCHAR)); if (!Bottom->string) { WARN("Cannot allocate memory for Bottom->string!\n"); cmd_free(tmp); return; } _tcscpy(Bottom->string,string);
tmp->next = Bottom; tmp->prev = NULL; tmp->string = NULL;
Bottom->prev = tmp;
/*save the new Bottom value*/ Bottom = tmp;
/*set new size*/ size++;}
VOID History_move_to_bottom(VOID){ ASSERT(Top && Bottom);
curr_ptr = Bottom;}
LPCTSTR PeekHistory(INT dir){ LPHIST_ENTRY entry = curr_ptr;
ASSERT(Top && Bottom);
if (dir == 0) return NULL;
if (dir < 0) { /* key up */ if (entry->next == Top || entry == Top) {#ifdef WRAP_HISTORY entry = Bottom;#else return NULL;#endif } entry = entry->next; } else { /* key down */ if (entry->prev == Bottom || entry == Bottom) {#ifdef WRAP_HISTORY entry = Top;#else return NULL;#endif } entry = entry->prev; }
return entry->string;}
VOID History(INT dir, LPTSTR commandline){ ASSERT(Top && Bottom);
if (dir==0) { add_at_bottom(commandline); curr_ptr = Bottom; return; }
if (size==0) { commandline[0]=_T('\0'); return; }
if (dir<0)/*key up*/ { if (curr_ptr->next==Top || curr_ptr==Top) {#ifdef WRAP_HISTORY curr_ptr = Bottom;#else curr_ptr = Top; commandline[0]=_T('\0'); return;#endif }
curr_ptr = curr_ptr->next; if (curr_ptr->string) _tcscpy(commandline,curr_ptr->string); }
if (dir>0) { if (curr_ptr->prev==Bottom || curr_ptr==Bottom) {#ifdef WRAP_HISTORY curr_ptr = Top;#else curr_ptr = Bottom; commandline[0]=_T('\0'); return;#endif }
curr_ptr = curr_ptr->prev; if (curr_ptr->string) _tcscpy(commandline,curr_ptr->string); }}
#endif //#if FEATURE_HISTORY