#help_index "AutoComplete/Dictionary"

acd.has_words = FileFind(ACD_WORD_FILENAME);
acd.has_defs  = FileFind(ACD_DEF_FILENAME);

public U0 ACDWordsLoad()
{//Put words from word list into hash table.
	I64			  size;
	CHashGeneric *tmph;
	U8			 *in_ptr, *in_start, *st2;
	U16			 *d;

	acd.num_words = 0;

	if (in_ptr = FileRead(ACD_WORD_FILENAME, &size))
	{
		in_start = in_ptr;
		Free(acd.word_list);
		acd.word_list = ZMAlloc(size);
		MemCopy(acd.word_list, in_start, size);
		acd.word_list_size = size;

		while (in_ptr < in_start + size)
		{
			if (*in_ptr == ACD_WORD_CHAR)
				in_ptr++;
			if (*in_ptr)
			{
				st2 = MStrUtil(in_ptr, SUF_TO_UPPER);
				tmph = ZCAlloc(sizeof(CHashGeneric) + StrLen(st2) + 1);
				StrCopy(tmph + 1, st2);
				Free(st2);
				in_ptr += StrLen(in_ptr) + 1;
				tmph->str = tmph + 1;
				tmph->use_count = 1;
				tmph->type = HTT_DICT_WORD;
				d = in_ptr;
				tmph->user_data0 = *d;
				in_ptr += 2;
				HashAdd(tmph, ac.hash_table);
				acd.num_words++;
			}
			else
				in_ptr += 3;
		}
		Free(in_start);
	}
}

#help_index "AutoComplete"
CHashAC *ACHashAdd(U8 *w)
{
	CHashAC *tmpw = HashFind(w, ac.hash_table, HTT_WORD);

	if (tmpw)
	{
		tmpw->hits++;
		return tmpw;
	}
	tmpw = ZCAlloc(sizeof(CHashAC));
	tmpw->str		= ZStrNew(w);
	tmpw->type		= HTT_WORD;
	tmpw->use_count	= 1;
	tmpw->hits		= 1;
	HashAdd(tmpw, ac.hash_table);
	ac.num_words++;
	return tmpw;
}

U0 ACSingleFileAdd(U8 *buf)
{
	I64 ch;
	U8 *ptr = buf, *ptr2, *ptr3;

	while (TRUE)
	{
		while (TRUE)
		{
			if (ch = *ptr++)
			{
				if (Bt(char_bmp_alpha_numeric, ch))
					break;
			}
			else
				return;
		}
		ptr3 = ptr;
		ptr2 = ptr;
		ptr--;

		while (TRUE)
		{
			if (ch = *ptr2++)
			{
				if (Bt(char_bmp_alpha_numeric, ch))
					*ptr3++ = ch;
				else if (ch != CH_CURSOR)
					break;
			}
			else
			{
				ptr2--;
				break;
			}
		}
		*ptr3 = 0;
		ACHashAdd(ptr);
		ptr = ptr2;
	}
}

U0 ACMainFileListTraverse(U8 *files_find_mask)
{
	U8		  *buf;
	CDirEntry *tmpde, *tmpde1;

	try
	{
		tmpde = tmpde1 = FilesFind(files_find_mask, FUF_RECURSE | FUF_JUST_TXT | FUF_JUST_FILES | FUF_CLUS_ORDER);
		while (tmpde)
		{
			"%s\n", tmpde->full_name;
			buf = FileRead(tmpde->full_name);
			ACSingleFileAdd(buf);
			Free(buf);
			tmpde = tmpde->next;
		}
	}
	catch
		Fs->catch_except = TRUE;

	DirTreeDel(tmpde1);
}

public U0 ACInit(U8 *mask=NULL)
{//Read files and build AutoComplete statistics.
	LBtr(&sys_run_level, RLf_AUTOCOMPLETE);
	AutoComplete;
	while (LBts(&ac.flags, ACf_INIT_IN_PROGRESS))
		Yield;

	HashTableDel(ac.hash_table);
	ac.hash_table = HashTableNew(2048, zenith_task);

	ac.num_words = 0;
	Free(ac.cur_word);
	ac.cur_word = NULL;

	if (mask)
		ACMainFileListTraverse(mask);

	ACDWordsLoad;
	RegDefault("AutoComplete", "ac.col = TEXT_COLS-30;ac.row = TEXT_ROWS/5+4;");
	RegExe("AutoComplete");
	LBtr(&ac.flags, ACf_INIT_IN_PROGRESS);
	LBts(&sys_run_level, RLf_AUTOCOMPLETE);
	AutoComplete(ON);
}

I64 AutoCompleteSize()
{
	if (ac.hash_table)
		return HashTableSize2(ac.hash_table) + MSize2(acd.word_list);
	else
		return 0;
}
