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 339