/
tintin++/
tintin++/docs/
tintin++/src/support/
/* 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);
}