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 */