/* New for v2.0: readline support -- daw */
/* all the tab completion support is here in this one file */
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <stdio.h>
#include <ctype.h>
extern char *mystrdup();
typedef struct list_s {
char *word;
struct list_s *next;
} list_t;
static list_t *complist = 0; /* tab completion list */
/*
* the completion generation function for readline.
* this function will be called repeatedly with the
* same s -- state=0 the first time, and state!=0 the
* rest of the time.
*
* it returns a pointer to a match each time, and a
* (char *) 0 pointer when it's done.
*/
char *
rltab_generate(s, state)
char *s;
int state;
{
static list_t *p;
char *match;
if (state == 0) {
if (complist == 0)
return ((char *) 0);
p = complist->next;
}
for (; p; p = p->next)
if (strncasecmp(s, p->word, strlen(s)) == 0) {
match = mystrdup(p->word);
p = p->next;
return (match);
}
return ((char *) 0);
}
static void rltab_add(word)
char *word;
{
list_t *p;
if (complist == 0) {
/* add dummy header node */
if ((complist = (list_t *) malloc(sizeof(list_t))) == 0)
syserr("rltab_add: malloc");
complist->word = 0;
if ((complist->next = (list_t *) malloc(sizeof(list_t))) == 0)
syserr("rltab_add: malloc");
p = complist->next;
p->word = mystrdup(word);
p->next = 0;
return;
}
/* avoid duplicates */
for (p = complist->next; p; p = p->next)
if (strcasecmp(p->word, word) == 0)
return;
/* add to head of list */
if ((p = (list_t *) malloc(sizeof(list_t))) == 0)
syserr("rltab_add: malloc");
p->word = mystrdup(word);
p->next = complist->next;
complist->next = p;
}
void rltab_delete(word)
char *word;
{
list_t *p, *q;
if (complist == 0) {
tintin_puts("#Delete failed: empty completion list.", 0);
return;
}
for (p = complist; p->next; p = p->next)
if (strcasecmp(p->next->word, word) == 0) {
q = p->next;
p->next = p->next->next;
free(q->word);
free(q);
tintin_puts("#Ok, deleted.", 0);
return;
}
tintin_puts("#Delete failed: word not in completion list.", 0);
}
void rltab_list( /* void */ )
{
list_t *p;
int col = 0, ncols = 4;
char line[128];
if (complist == 0 || complist->next == 0) {
tintin_puts("#Empty completion list.", 0);
return;
}
line[0] = '\0';
for (p = complist->next; p; p = p->next) {
sprintf(line + strlen(line), "%15.15s ", p->word);
if (++col == ncols) {
tintin_puts(line, 0);
col = 0;
line[0] = '\0';
}
}
if (line[0])
tintin_puts(line, 0);
}
static void rltab_purge( /* void */ )
{
list_t *p, *q;
if (complist == 0) {
if ((complist = (list_t *) malloc(sizeof(list_t))) == 0)
syserr("rltab_purge: malloc");
complist->word = 0;
complist->next = 0;
return;
}
for (p = complist->next; p; p = q) {
q = p->next;
free(p->word);
free(p);
}
complist->next = 0;
}
void rltab_read( /* void */ )
{
FILE *f;
char *s, *t, line[128];
if ((f = fopen("tab.txt", "r")) == 0) {
tintin_puts("#Couldn't open tab.txt", 0);
return;
}
rltab_purge();
while (fgets(line, sizeof(line), f)) {
/* delete leading and trailing whitespace */
for (s = line; isspace(*s); s++);
for (t = s; *t && !isspace(*t); t++);
*t = '\0';
rltab_add(s);
}
fclose(f);
tintin_puts("#Read tab.txt, completion list initialized.", 0);
}
void do_tabadd(arg)
char *arg;
{
char buf[128];
if (arg == 0 || *arg == '\0') {
tintin_puts("#Add failed: no word specified.", 0);
return;
}
get_arg_in_braces(arg, buf, 1);
rltab_add(buf);
tintin_puts("#Added.", 0);
}
void do_tabdel(arg)
char *arg;
{
char buf[128];
if (arg == 0 || *arg == '\0') {
tintin_puts("#Delete failed: no word specified.", 0);
return;
}
get_arg_in_braces(arg, buf, 1);
rltab_delete(buf);
}
void do_tabsave( /* void */ )
{
FILE *f;
list_t *p;
if (complist == 0 || complist->next == 0) {
tintin_puts("#Empty completion list, nothing to save.", 0);
return;
}
if ((f = fopen("tab.txt", "w")) == 0) {
tintin_puts("#Couldn't open tab.txt", 0);
return;
}
for (p = complist->next; p; p = p->next)
fprintf(f, "%s\n", p->word);
fclose(f);
tintin_puts("#Saved to tab.txt.", 0);
}