/** /* $Id: readln.c,v 1.3 1998/02/13 08:58:05 falcon Exp $ /* Readline functions, soon to be replaced with gnu readline /**/ #include "config.h" #include #include #include #include "defs.h" void scrub_free ( void*, int ); extern char commandchar; extern int nomore; /* character pressed at [=more=] prompt */ extern int spat; char *cmdlog[CMDLOGLEN]; int index_cl; /* index to last line inserted to log */ int temp_cl; /* index to line currently being edited */ /* ttk here -- I'll finish the command history stuff later */ #define TABSLOTS 20 char *tabhis[TABSLOTS]; /* tab history table; list of names */ int thstate; /* incremented as user hits tab; indexes the tab history */ int thend = 0; /* number of names stored in tabhis */ extern int no_tabhistory; /* if 1, do not save /m in tab history */ void init_tabhistory() { /* called from main() in orcus.c */ int i; for ( i = 0; i < TABSLOTS; i++ ) tabhis[i] = NULL; thstate = 0; thend = 0; } void uninit_tabhistory() { /* called from main() in orcus.c */ int i; for ( i = 0; i < TABSLOTS; i++ ) if ( tabhis[i] != NULL ) free ( tabhis[i] ); thstate = 0; thend = 0; } void dump_tabhistory ( int x ) { int i, k; if ( x == 0 ) k = thend; else k = TABSLOTS; for ( i = 0; i < k; i++ ) if ( tabhis[i] == NULL ) oprint ( "[+Tab %2d+] '%s'\n", i, "NULL" ); else oprint ( "[+Tab %2d+] '%s'\n", i, tabhis[i] ); } /* We handle the tab history here. Note that it's up to */ /* the writepriv() function to insert/rearrange names in */ /* the tab history file and increment thend by calling */ /* the insert_tabhis() function. */ void handle_tab( buf, blen, curp ) char *buf; int blen, curp; { char *temp; char *foo; size_t i,k; if ( !thend ) return; buf[blen] = 0; /* forcing the issue */ if ( tabhis[thstate] == NULL ) thstate = 0; if ( tabhis[thstate] == NULL ) return; /* trouble! */ k = strlen ( tabhis[thstate] ) + blen + 6; temp = (char*) malloc ( k ); /* DO NOT overwrite k! we use it later */ strcpy ( temp, (const char*)"/m " ); temp[0] = commandchar; strcat ( temp, tabhis[thstate] ); strcat ( temp, " " ); i = 0; /* we will copy from buf[i] to buf[blen] into temp, but */ /* first we have to increment i enough to strip pre-existing */ /* commands like "/w" or "/exclude chrisb" etc. */ if ( buf[0] == commandchar ) { while ( ( i < blen ) && ( buf[i] != ' ' ) ) i++; foo = (char*) malloc ( i + 1 ); strncpy ( foo, buf, i ); foo[i] = 0; if ( foo[0] == commandchar ) foo[0] = '/'; while ( ( i < blen ) && ( buf[i] == ' ' ) ) i++; if ( !strcmp ( foo, "/m" ) || !strcmp ( foo, "/exclude" ) || !strcmp ( foo, "/g" ) || !strcmp ( foo, "/boot" ) || !strcmp ( foo, "/nick" ) || !strcmp ( foo, "/name" ) || !strcmp ( foo, "/p" ) || !strcmp ( foo, "/notify" ) || !strcmp ( foo, "/hush" ) || !strcmp ( foo, "/unhush" ) || !strcmp ( foo, "/pass" ) || !strcmp ( foo, "/write" ) || !strcmp ( foo, "//whap" ) ) { /* if any of these commands were in buf, skip the next word */ while ( ( i < blen ) && ( buf[i] != ' ' ) ) i++; while ( ( i < blen ) && ( buf[i] == ' ' ) ) i++; } /* end of if */ scrub_free ( foo, i ); } /* end of if ( buf[0] == commandchar ) */ /* use "&(buf[i])" to be 64-bit safe; "buf+i" is not! */ if ( i < blen ) strcat ( temp, &(buf[i]) ); strcpy ( buf, temp ); scrub_free ( temp, k ); /* safe now to overwrite k */ k = strlen ( buf ); /* now we have to erase the old line and draw the new one */ for ( i = curp; i; i-- ) printf ("%c",8); while ( i < blen ) { printf (" "); i++; } for ( ; i; i-- ) printf ("%c",8); printf ("%s",buf); fflush (stdout); thstate++; /* increment the index into the tab history */ if ( thstate >= thend ) thstate = 0; if ( tabhis[thstate] == NULL ) thstate = 0; } /* end of function handle_tab() */ /* called by writepriv() to insert a /m argument to the tab history */ void insert_tabhis ( newname ) char *newname; { int i; int really_is_new = 1; int switchum = 0; char *t; if ( no_tabhistory ) { no_tabhistory = 0; return; } for ( i = 0; i < thend; i++ ) if ( tabhis[i] != NULL ) if ( strcmp ( newname, tabhis[i] ) == 0 ) { really_is_new = 0; switchum = i; } /* brute force is okay */ if ( really_is_new ) { if ( tabhis[thend] != NULL ) scrub_free ( tabhis[thend], strlen ( tabhis[thend] ) ); for ( i = thend; i > 0; i-- ) tabhis[i] = tabhis[i-1]; tabhis[0] = strdup ( newname ); if ( thend < (TABSLOTS-1) ) thend++; return; } /* if it already exists, we move everyone else down, and */ /* then re-insert it at the top (maintaining LRU struct) */ t = tabhis[switchum]; if ( t == NULL ) return; /* just being paranoid */ for ( i = switchum; i > 0; i-- ) tabhis[i] = tabhis[i-1]; tabhis[0] = t; } /* end of function insert_tabhis() */ void emacs_readln ( buf ) char *buf; { char shut = ' '; long i = 0; /* current cursor position in buf */ long j; long len = 0; /* length of buf */ char bup[3] = { 8, ' ', 8 }; char sbup[1] = { 8 }; char sp[1] = { ' ' }; int place; thstate = 0; buf[0] = 0; while ( shut != '\n' ) { if ( nomore ) { shut = ( nomore & 255 ); nomore = 0; } else read ( 0, &shut, 1 ); switch ( shut ) { case '\n' : buf[len] = 0; write ( 1, "\n", 1 ); break; case 1 : /* ctl-A, move to beginning of line */ while ( i > 0 ) { i--; write ( 1, sbup, 1 ); } break; case 2 : /* ctl-B, move back one character */ if ( i > 0 ) { i--; write ( 1, sbup, 1 ); } break; case 4 : /* ctl-D, erase character under cursor */ if ( i == len ) break; for ( j = i; j < len; j++ ) { buf[j] = buf[j+1]; write ( 1, buf+j, 1 ); } write ( 1, sp, 1 ); for ( ; j > i; j-- ) write ( 1, sbup, 1 ); len--; break; case 5 : /* ctl-E, move to end of line */ for ( ; i < len; i++ ) write ( 1, buf+i, 1 ); break; case 6 : /* ctl-F, move forward one character */ if ( i < len ) { write ( 1, buf+i, 1 ); i++; } break; case 8 : /* ctl-H, destructive backspace */ case 127 : /* ctrl-?, destructive backspace */ if ( i > 0 ) { i--; len--; if ( i == len ) { write ( 1, bup, 3 ); } else { write ( 1, sbup, 1 ); for ( j = i; j < len; j++ ) { buf[j] = buf[j+1]; write ( 1, buf+j, 1 ); } write ( 1, sp, 1 ); write ( 1, sbup, 1 ); for ( ; j > i; j-- ) write ( 1, sbup, 1 ); } buf[len] = 0; } break; case 9 : /* ctl-I, TAB, history key for "/m" */ handle_tab ( buf, len, i ); len = strlen ( buf ); i = len; break; case 11 : /* ctl-K, delete to EOL */ place = i; for ( ; i < len; i++ ) write ( 1, buf+i, 1 ); while ( i > place ) { i--; len--; if ( i == len ) { write ( 1, bup, 3 ); } else { write ( 1, sbup, 1 ); for ( j = i; j < len; j++ ) { buf[j] = buf[j+1]; write ( 1, buf+j, 1 ); } write ( 1, sp, 1 ); write ( 1, sbup, 1 ); for ( ; j > i; j-- ) write ( 1, sbup, 1 ); } buf[len] = 0; } break; case 14 : /* ctl-N, move fwrd one line in cmd history */ break; case 16 : /* ctl-P, move back one line in cmd history */ break; case 21 : /* ctl-U, delete entire line */ while ( i < len ) { write ( 1, buf+i, 1 ); i++; } while ( i > 0 ) { i--; len--; write ( 1, bup, 3 ); } buf[0] = 0; break; default : if ( ( shut < ' ' ) || ( shut > '~' ) ) break; if ( i == len ) { buf[i] = shut; write ( 1, &shut, 1 ); i++; len++; buf[len] = 0; } else { for ( j = len; j > i; j-- ) buf[j] = buf[j-1]; buf[i] = shut; write ( 1, &shut, 1 ); i++; len++; for ( j = i; j < len; j++ ) write ( 1, buf+j, 1 ); for ( ; j > i; j-- ) write ( 1, sbup, 1 ); buf[len] = 0; } break; } /* END of switch */ if ( len <= 0 ) { buf[0] = 0; shut = '\n'; } } /* END of while */ if ( buf[0] != 0 ) spat = 0; } /* END of function readln() */ /* for debugging purposes: main() { char foo[70]; int i; sttyinputset(); readln ( foo ); for ( i = 0; i < 70; i++ ) if ( i % 5 ) printf ("."); else printf ("!"); printf ("\n"); printf ("%s\n",foo); sttyinputreset(); } */