/*
    Pirate Bulletin Board System
    Copyright (C) 1990, Edward Luke

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 1, or (at your option)
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


    Email address:
    lush@Athena.EE.MsState.EDU
*/
#include "io.h"

#define STRLEN (80)

struct word {
	char *word ;
	struct word *next ;
} ;

struct word *toplev = NULL, *current = NULL ;

FreeNameList() 
{
	struct word *p ;

	for(p=toplev;p!=NULL;p=p->next) {
		free(p->word) ;
		free(p) ;
	}
}

CreateNameList()
{
	if(toplev)
	  FreeNameList() ;
	toplev = NULL ;
	current = NULL ;
}

AddNameList(name)
char *name ;
{
	void *valloc() ;
	struct word *node ;

	node = (struct word *) valloc(sizeof(struct word)) ;
	node->next = NULL ;
	node->word = (char *) valloc(strlen(name)+1) ;
	strcpy(node->word,name) ;
	if(toplev) {
		current->next = node ;
		current = node ;
		return ;
	}
	toplev = node ;
	current = node ;
	return ;
}

NumInList(list)
register struct word *list ;
{
	register int i ;
	
	for(i=0;list != NULL;i++,list = list->next)
	  /*Null Statement*/ ;
	return i ;
}

ApplyToNameList(fptr)
int ((*fptr)()) ;
{
	struct word *p ;

	for(p = toplev;p!=NULL;p = p->next)
	  (*fptr)(p->word) ;
}


chkstr(tag,name)
char *tag, *name ;
{
	while(*tag != '\0') {
		if((*tag) != (*name))
		  return 0 ;
		tag++ ;
		name++ ;
	}
	return 1 ;
}

struct word *
GetSubList(tag,list)
register char *tag ;
register struct word *list ;
{
	struct word *wlist,*wcurr ;
    extern void *valloc() ;

	wlist = NULL ;
	wcurr = NULL ;
	while(list != NULL) {
		if(chkstr(tag,list->word)) {
			register struct word *node ;
			void *valloc() ;
			
			node = (struct word *)valloc(sizeof(struct word)) ;
			node->word = list->word ;
			node->next = NULL ;
			if(wlist)
			  wcurr->next = node ;
			else
			  wlist = node ;
			wcurr = node ;
		}
		list = list->next ;
	}
	return wlist ;
}

ClearSubList(list)
struct word *list ;
{
	while(list) {
		free(list) ;
		list = list->next ;
	}
}

MaxLen(list,count)
struct word *list ;
{
	int len = strlen(list->word) ;
	
	while(list!=NULL && count) {
		int t = strlen(list->word) ;
		if(t > len)
		  len = t ;
		list=list->next ;
		count-- ;
	}
	return len ;
}

#define NUMLINES (19)

namecomplete(prompt,data)
char *prompt, *data ;
{
	char *temp, *strchr() ;
	int ch ;
	int count = 0 ;
    int clearbot = NA ;

	if(scrint) {
		struct word *cwlist,*morelist ;
		int x,y ;

		if(prompt != NULL) {
			prints("%s",prompt) ;
			clrtoeol() ;
		}
		temp = data ;
		
		if(toplev == NULL)
		  AddNameList("") ;
		cwlist = GetSubList("",toplev) ;
		morelist = NULL ;
		getyx(&y,&x) ;
		while((ch = igetch()) != EOF)
		  {
			  if(ch == '\n' || ch == '\r') {
				  *temp = '\0' ;
				  prints("\n") ;
				  if(NumInList(cwlist) == 1) {
					strcpy(data,cwlist->word) ; }
				  ClearSubList(cwlist) ;
				  break ;
			  }
			  if(ch == ' ') {
				  int col,len ;
				  
				  if(NumInList(cwlist) == 1) {
					  strcpy(data,cwlist->word) ;
					  move(y,x) ;
					  prints("%s",data+count) ;
					  count = strlen(data) ;
					  temp = data + count ;
					  getyx(&y,&x) ;
					  continue ;
				  }
                  clearbot = YEA ;
				  col = 0 ;
				  if(!morelist)
					morelist = cwlist ;
				  len = MaxLen(morelist,NUMLINES) ;
				  move(3,0) ;
				  clrtobot() ;
				  standout() ;
				  prints(
"------------------------------- Completion List -------------------------------") ;
				  standend() ;
				  while(len+col < 80) {
					  int i ;
					  for(i=NUMLINES;(morelist)&&(i>0);i--,morelist=morelist->next) {
						  move(4+(NUMLINES - i),col) ;
						  prints("%s",morelist->word) ;
					  }
					  col += len+2 ;
					  if(!morelist)
						break ;
					  len = MaxLen(morelist,NUMLINES) ;
				  }
				  if(morelist) {
					  move(23,0) ;
					  standout() ;
					  prints("-- More --") ;
					  standend() ;
				  }
				  move(y,x) ;
				  continue ;
			  }
			  if(ch == '\177' || ch == '\010') {

				  if(temp == data)
					continue ;
				  temp-- ;
				  count-- ;
				  *temp = '\0' ;
				  ClearSubList(cwlist) ;
				  cwlist = GetSubList(data,toplev) ;
				  morelist = NULL ;
				  x-- ;
				  move(y,x) ;
				  addch(' ') ;
				  move(y,x) ;
				  continue ;
			  }
			  if(count < STRLEN) {
				  struct word *node ;

				  *temp++ = ch ;
				  count++ ;
				  *temp = '\0' ;
				  node = GetSubList(data,cwlist) ;
				  if(node == NULL) {
					  bell() ;
					  temp-- ;
					  *temp = '\0' ;
					  count-- ;
					  continue ;
				  }
				  ClearSubList(cwlist) ;
				  cwlist = node ;
				  morelist = NULL ;
				  move(y,x) ;
				  addch(ch) ;
				  x++ ;
			  }
		  }
		if(ch == EOF)
		  generic_abort() ;
        prints("\n") ;
        refresh() ;
        if(clearbot) {
            move(3,0) ;
            clrtobot() ;
        }
		return 0 ;
	}
	if(prompt != NULL) {
		printf("%s",prompt) ;
		fflush(stdout) ;
	}
	if(!fgets(data,STRLEN,stdin))
	  generic_abort() ;
	if(temp = strchr(data,'\n'))
	  *temp = '\0' ;
	return 0 ;
}
