/* * input_with_history() function * * Copyright (C) 1997 by Sony Computer Entertainment * All rights Reserved */ #include #include #include #include #include "lineedit.h" #include "inputhis.h" /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= * USER customize section */ #define LOCALHISTORYCMD #define MAXHISTORY 50 char cmdchars[] = { 'S'-'@', /* move left */ 'D'-'@', /* move right */ 'A'-'@', /* move begin of line */ 'F'-'@', /* move end of line */ 'H'-'@', /* back and delete */ 'G'-'@', /* delete */ 'K'-'@', /* right all delete */ 'Y'-'@', /* all delete */ 0}; char endchars[] = { '\r', /* normal return */ 'E'-'@', /* up history */ 'X'-'@', /* down history */ 'I'-'@', /* search up history */ 'J'-'@', /* search down history */ 'Y'-'@', /* cancel history pointer */ '\033', /* push history */ 0}; #define DISPCH dispch #define CLREOL() disps("\033[K") extern disps(char *); /* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */ extern DISPCH(); #define NORMAL_END (endchars[0]) #define UP_HIS (endchars[1]) #define DOWN_HIS (endchars[2]) #define UP_SEAR (endchars[3]) #define DOWN_SEAR (endchars[4]) #define CAN_HISP (endchars[5]) #define PUSH_HIS (endchars[6]) extern int ctrlcflag; typedef struct HIST { struct HIST *next,*prev; char str[2]; } hist; static char searchbuf[100] = {0}; static int hisnum = 0; static int hiscnt = 0; static int offset = 0; static hist *htop = NULL; static hist *hbtm = NULL; static void displine(char *cp) { while( *cp ) DISPCH(*cp++); } static char dispbuf[100]; static void dispf(va_alist) va_dcl { va_list args; char *format; va_start(args); format = va_arg(args, char*); vsprintf(dispbuf,format,args); va_end(args); printf(dispbuf); } static int alineoffset(int offset) { if( offset < (-hiscnt) ) offset += hiscnt; if( offset >= 0 ) offset -= hiscnt; return(offset); } static void uphistory() { offset = alineoffset(offset-1); } static void downhistory() { offset = alineoffset(offset+1); } static int notbrank(char *b) { while( *b ) { if( *b != 0 && *b != ' ' ) return(1); b++; } return(0); } static int isbrank(char *b) { return(!notbrank(b)); } static void put_history(char *c) { hist *new; int i; new = NULL; if( hiscnt > 0 ) { for( i=0 , new=hbtm ; i < hiscnt ; i++, new=new->prev ) { if( strcmp( new->str,c) == 0 ) { if( new->prev == NULL ) htop = new->next; else new->prev->next = new->next; if( new->next == NULL ) hbtm = new->prev; else new->next->prev = new->prev; i = -1; break; } } if( i >= 0 ) new = NULL; } if( new == NULL ) { new = malloc(sizeof(hist)+strlen(c)); if( new == NULL ) { puts("history buffer full !"); return; } strcpy(new->str,c); hiscnt++; } new->next = NULL; new->prev = NULL; if( htop == NULL ) { htop = hbtm = new; } else { hbtm->next = new; new->prev = hbtm; hbtm = new; } hisnum++; if( hiscnt > MAXHISTORY ) { hiscnt--; new = htop->next; free(htop); htop = new; htop->prev = NULL; } } static void get_hisory(char *b, int maxsize) { hist *hp; char *s; int c; int of; if( hiscnt == 0 ) { strcpy(b,""); offset = 0; } else { of = (-offset)-1; for( c = 0, hp = hbtm ; c < of ; c++ ) hp = hp->prev; for( c = 0, s = hp->str; *s && c < maxsize-1 ; c++ ) { *b++ = *s++; *b = 0; } } } void upsearch(char *s, char *b) { hist *hp,*shp; int c; int of; if( hiscnt == 0 ) { strcpy(b,""); offset = 0; return; } if( isbrank(s) ) { return; } of = (-alineoffset(offset-1))-1; for( c = 0, hp = hbtm ; c < of ; c++ ) hp = hp->prev; for( of = alineoffset(offset-1), shp = hp ; shp ; shp = shp->prev , of = alineoffset(of-1) ) { if( strncmp(shp->str,s,strlen(s)) == 0 ) { offset = of; strcpy(b,shp->str); return; } } } void downsearch(char *s, char *b) { hist *hp,*shp; int c; int of; if( hiscnt == 0 ) { strcpy(b,""); offset = 0; return; } if( isbrank(s) ) { return; } of = (-alineoffset(offset+1))-1; for( c = 0, hp = hbtm ; c < of ; c++ ) hp = hp->prev; for( of = alineoffset(offset+1), shp = hp ; shp ; shp = shp->next , of = alineoffset(of+1) ) { if( strncmp(shp->str,s,strlen(s)) == 0 ) { offset = of; strcpy(b,shp->str); return; } } } void set_keyin_history(FILE *fp) { char linebuf[512]; int pos; while( fgets(linebuf,510,fp) ) { pos = strlen(linebuf)-1; while( pos >= 0 && linebuf[pos] < ' ' ) { linebuf[pos--] = 0; } if( pos >= 0 ) put_history(linebuf); } } void dump_keyin_history(FILE *fp) { hist *dp; for( dp = htop; dp ; dp = dp->next ) fprintf(fp,"%s\n",dp->str); } char *input_with_history(char *prompt, char *inputbuf, int maxchar, int flags) { hist *dp; char promptsub[80]; int i; int ec = 0; offset = 0; searchbuf[0] = 0; inputbuf[0] = 0; while( 1 ) { if( offset ) sprintf( promptsub, "[%d/%d]",hisnum+offset+1,hisnum); else sprintf( promptsub, "[%d]",hisnum+1); dispf(prompt,promptsub); ec = line_edit(inputbuf, maxchar, cmdchars, endchars, flags); if( ec == PUSH_HIS || ec == CAN_HISP ) { if ( notbrank(inputbuf) && ec == PUSH_HIS ){ displine("\r\n"); CLREOL(); displine(" push to history buffer !\n"); put_history(inputbuf); } displine("\r"); CLREOL(); inputbuf[0] = 0; offset = 0; } else if( ec == UP_HIS || ec == DOWN_HIS ) { if( hiscnt > 0 ) { if( ec == UP_HIS ) uphistory(); else downhistory(); } displine("\r"); CLREOL(); get_hisory(inputbuf,maxchar); } else if( ec == UP_SEAR || ec == DOWN_SEAR ) { if( hiscnt > 0 ) { if( offset == 0 ) { strcpy(searchbuf,inputbuf); } if( ec == UP_SEAR ) upsearch(searchbuf,inputbuf); else downsearch(searchbuf,inputbuf); } displine("\r"); CLREOL(); } else if( ec == NORMAL_END ) { if( flags & WITHCR ) displine("\r\n"); #ifdef LOCALHISTORYCMD if( hiscnt > 0 && (strcmp(inputbuf,"his")== 0 || strcmp(inputbuf,"HIS")== 0) ) { if( !(flags & WITHCR) ) displine("\r\n"); for( i = hisnum-hiscnt+1 , dp = htop; dp ; dp = dp->next, i++ ) dispf("%4d: %s\n\r",i,dp->str); inputbuf[0] = 0; offset = 0; } else { #endif if ( notbrank(inputbuf) ){ put_history(inputbuf); } break; /* end of input */ } } else if( ec >= 0x7f && ( flags & RETILL )) { if( notbrank(inputbuf) ) put_history(inputbuf); inputbuf[0] = (char)ec; inputbuf[1] = 0; break; /* end of input */ } } return inputbuf; }