///////////////////////////////////////////////////////////////////////////////////////////
//
// This version of TL_hzinput.so is modified by Chinese 2000, Jacky Lau
// Jacky Lau can be contacted by this email : <zenithlau@sniic.com>
//
// UNICON - The Console Chinese & I18N
// Copyright (c) 1999-2002
//
// This file is part of UNICON, a console Chinese & I18N
//
// 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 2 of the License, 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.
//
// See the file COPYING directory of this archive
// Author: see CREDITS
//
///////////////////////////////////////////////////////////////////////////////////////////

#include	<stdio.h>
#include	<unistd.h>
#include	<stdlib.h>
#include	<stdarg.h>
#include	<string.h>
#include	<ctype.h>
#include	<time.h>
#include	<assert.h>
#include	<xl_hzinput.h>
#include	<xl_sysphrase.h>
#include	<xl_phrase.h>

static void ResetInput (HzInputTable_T *pClient);
static void dump_hz_input_table (hz_input_table *table);
static void dump_HzInputTable_T (HzInputTable_T *table);

static void FindMatchKey (HzInputTable_T *pClient);
static int  IsSelectDup (HzInputTable_T *pClient, int CurSelNum, char *szPhrase);
static void FillAssociateChars(HzInputTable_T *pClient, int index);
static int  qcmp (const void *t1, const void *t2);
static void SortAllOutput (HzInputTable_T *pClient);
static void FillAllMatchChars (HzInputTable_T *pClient, int j);
static void FillMatchChars (HzInputTable_T *pClient, int j);

///////////////////////////////////////////////////////////////////////////////////////////
// 
//                                 Declaring Variables
//
///////////////////////////////////////////////////////////////////////////////////////////

// Declaring an array of 6 bits mask
unsigned long mask[] =
{
   0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 
   0x3F000000, 0x3FFC0000, 0x3FFFF000, 0x3FFFFFC0, 0x3FFFFFFF, 0x3FFFFFFF,
   0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF
};

// For qcmp () and SortAllOut ()
static HzInputTable_T *pDefaultClient = NULL;

// This flag is used only for pingyin.
// In pingyin, user must enter a 'space', and start selecting char.
// But the current implementation in TL_hzinput.so doesn't care it.
// The flag will be reset in TL_InputInit.
// Conditionally set in TL_LoadMethod for pingyin.tab
// And check and make effect in TL_KeyFilter
// if (explicitSelectMode == 0) ==> Normal
// if (explicitSelectMode == 1) ==> PingYin only. Input Mode
// if (explicitSelectMode == 2) ==> PingYin only. Select Mode
static int explicitSelectMode;

///////////////////////////////////////////////////////////////////////////////////////////
// 
//                                  Static Functions
//
///////////////////////////////////////////////////////////////////////////////////////////
static void dump_hz_input_table (hz_input_table *table)
{
	printf ("Contents of hz_input_table.\n");
	printf ("selkey:               %s\n", table->selkey);
	printf ("lastfull:             %d\n", table->last_full);
	printf ("MaxDupSel:            %d\n", table->MaxDupSel);
	printf ("TotalKey:             %d\n", table->TotalKey);
	printf ("MaxPress:             %d\n", table->MaxPress);
	printf ("TotalChar:            %d\n", table->TotalChar);
	printf ("TotalPhrase:          %d\n", table->TotalPhrase);
	printf ("TotalAssociatePhrase: %d\n", table->TotalAssociatePhrase);
}

static void dump_HzInputTable_T (HzInputTable_T *table)
{
	printf ("Contents of HzInputTable_T.\n");
	printf ("IsHanziInput:               %d\n", table->IsHanziInput);
	printf ("IsFullChar:                 %d\n", table->IsFullChar);
	printf ("IsFullComma:                %d\n", table->IsFullComma);
	printf ("IsSysMenu:                  %d\n", table->IsSysMenu);
	printf ("IsHelpMenu:                 %d\n", table->IsHelpMenu);
	printf ("current_method:             %d\n", table->current_method);
	printf ("CurSelNum:                  %d\n", table->CurSelNum);
	printf ("InputCount:                 %d\n", table->InputCount);
	printf ("InputMatch:                 %d\n", table->InputMatch);
	printf ("StartKey:                   %d\n", table->StartKey);
	printf ("EndKey:                     %d\n", table->EndKey);
	printf ("NextPageIndex:              %d\n", table->NextPageIndex);
	printf ("CurrentPageIndex:           %d\n", table->CurrentPageIndex);
	printf ("MultiPageMode:              %d\n", table->MultiPageMode);
	printf ("IsAssociateMode:            %d\n", table->IsAssociateMode);
	printf ("UseAssociateMode:           %d\n", table->UseAssociateMode);
}

static void ResetInput (HzInputTable_T *pClient)
{
    bzero (pClient->InpKey, sizeof(pClient->InpKey) );
    bzero (pClient->seltab, sizeof(pClient->seltab) );
    bzero (pClient->seltab_phrase, sizeof(pClient->seltab_phrase) );
    pClient->MultiPageMode = 0;
    pClient->CurrentPageIndex = 0;
    pClient->NextPageIndex = 0;
    pClient->CurSelNum = 0;
    pClient->InputCount = 0;
    pClient->InputMatch = 0;
    pClient->IsAssociateMode = 0;
}

//	After add/delete a char, search the matched char/phrase, update the
//	pClient->StartKey/pClient->EndKey key,  save the related keys at first, 
//	if no match is found, we may restore its original value
static void FindMatchKey (HzInputTable_T *pClient)
{
	pClient->save_StartKey			= pClient->StartKey;
	pClient->save_EndKey			= pClient->EndKey;
	pClient->save_MultiPageMode		= pClient->MultiPageMode;
	pClient->save_NextPageIndex		= pClient->NextPageIndex;
	pClient->save_CurrentPageIndex	= pClient->CurrentPageIndex;

	pClient->val1 = pClient->InpKey[4]
					| (pClient->InpKey[3] << 6)
					| (pClient->InpKey[2] << 12)
					| (pClient->InpKey[1] << 18)
					| (pClient->InpKey[0] << 24);
 
	pClient->val2 = pClient->InpKey[9]
					| (pClient->InpKey[8] << 6)
					| (pClient->InpKey[7] << 12)
					| (pClient->InpKey[6] << 18)
					| (pClient->InpKey[5] << 24);

//	printf ("key1 is 0x%lX, key2 is 0x%lX\n", pClient->val1, pClient->val2);

	if (pClient->InputCount == 1)
		pClient->StartKey = pClient->cur_table->KeyIndex[pClient->InpKey[0]];
	else
		pClient->StartKey = pClient->CharIndex[pClient->InputCount-1];

	pClient->EndKey = pClient->cur_table->KeyIndex[pClient->InpKey[0]+1];

	for (; pClient->StartKey < pClient->EndKey; pClient->StartKey++)
	{
		pClient->key1 = (pClient->cur_table->item[pClient->StartKey].key1 & 
						 mask[pClient->InputCount+5]);
		pClient->key2 = (pClient->cur_table->item[pClient->StartKey].key2 & 
						 mask[pClient->InputCount]);

		if (pClient->key1 > pClient->val1)
			break;
		if (pClient->key1 < pClient->val1)
			continue;
		if (pClient->key2 < pClient->val2)
			continue;
		break;
	}
	pClient->CharIndex[pClient->InputCount] = pClient->StartKey;

	// Add by Arthur Ma, 04-26-2000
	FillAllMatchChars (pClient, pClient->StartKey);
}

static int IsSelectDup (HzInputTable_T *pClient, int CurSelNum, char *szPhrase)
{
    int i;

    if (szPhrase[0] == '\0')
        return 1;

    for (i = 0; i < CurSelNum; i++)
       if (strcmp (pClient->seltab[i], szPhrase) == 0)
           return 1;
    return 0;
}

static void FillAssociateChars (HzInputTable_T *pClient, int index)
{
    unsigned char str[25];
    int CurLen = 0;
   
    pClient->CurSelNum = 0; 
    while (pClient->CurSelNum < pClient->cur_table->MaxDupSel && 
           index < pClient->EndKey)
    {
         u_long nPhrase;
         if (GetAssociatePhraseIndex (pClient, index, &nPhrase) == 0)
             continue;
         LoadPhrase (pClient, nPhrase, str); 
         if (IsSelectDup (pClient, pClient->CurSelNum, str) == 0)
         {
             CurLen += (strlen(str) + 2);
             if (CurLen >= pClient->MAX_SEL_LENGTH - 2)
                 break;
             strcpy(pClient->seltab[pClient->CurSelNum],str);
             pClient->seltab_phrase[pClient->CurSelNum] = nPhrase;
             CurLen += (strlen(pClient->seltab[pClient->CurSelNum++]) + 2);
         }
         index++;
    }

//	printf ("pClient->CurSelNum is %d\n", pClient->CurSelNum);

    /* check if more than one page */
    if (index < pClient->EndKey && 
        pClient->CurSelNum == pClient->cur_table->MaxDupSel)
    {
      /* has another matched key, so enter pClient->MultiPageMode, 
         has more pages */
        pClient->NextPageIndex = index;
        pClient->MultiPageMode = 1;
    }
    else if (pClient->MultiPageMode)
        pClient->NextPageIndex = pClient->StartKey; /* rotate selection */
    else 
        pClient->MultiPageMode = 0;
}

static int qcmp (const void *t1, const void *t2)
{
    long c1, c2, k1, k2;
    long *a = (long *) t1,
         *b = (long *) t2;
    int n1, n2, m1, m2;
    static char p1[256], p2[256];
	// pDefaultClient is static, declare at the begining of the code
    n1 = pDefaultClient->cur_table->item[*a].nPhrase;
    n2 = pDefaultClient->cur_table->item[*b].nPhrase;

    TL_GetPhrase (pDefaultClient->pSysPhrase, n1, p1);
    TL_GetPhrase (pDefaultClient->pSysPhrase, n2, p2);
    
    m1 = strlen (p1); 
    m2 = strlen (p2); 
    if (m1 > m2)
        return 1;
    else if (m1 < m2)
        return -1;

    TL_GetUserSelectPhraseCount (pDefaultClient->pSysPhrase, n1, &k1);
    TL_GetUserSelectPhraseCount (pDefaultClient->pSysPhrase, n2, &k2);
    if (k1 < k2)
        return 1;
    else if (k1 > k2)
        return -1;

    TL_GetPhraseFreq (pDefaultClient->pSysPhrase, n1, &c1);
    TL_GetPhraseFreq (pDefaultClient->pSysPhrase, n2, &c2);
    if (c1 < c2)
       return 1;
    else if (c1 > c2)
       return -1;
    return 0;
}

static void SortAllOutput (HzInputTable_T *pClient)
{
	// pDefaultClient is static, declare at the begining of the code
    pDefaultClient = pClient;
    if (strcmp (pClient->cur_table->ename, "simplex") == 0
        || strcmp (pClient->cur_table->ename, "simplexhk") == 0)
        qsort (pClient->OutputPhrase + 10, pClient->TotalOutputPhrase,  
               sizeof(long), qcmp);
    else
        qsort (pClient->OutputPhrase, pClient->TotalOutputPhrase,  
               sizeof(long), qcmp);
}

static void FillAllMatchChars (HzInputTable_T *pClient, int j)
{
    int i = 0;
    while ((pClient->cur_table->item[j].key1 &
                mask[pClient->InputCount+5]) == pClient->val1
			&& (pClient->cur_table->item[j].key2 &
                mask[pClient->InputCount]) == pClient->val2
			&& j < pClient->EndKey )
    {
        pClient->OutputPhrase[i++] = j++;
    }

    pClient->TotalOutputPhrase = i;
    SortAllOutput (pClient);
    pClient->EndKey = i;
    pClient->StartKey = 0;
}

static void FillMatchChars (HzInputTable_T *pClient, int j)
{
	int SelNum = 0, CurLen = 0;
	int n = j;

	do
	{
		if (n >= pClient->TotalOutputPhrase)
			break;

		j = pClient->OutputPhrase[n];
		if (SelNum < pClient->cur_table->MaxDupSel) 
		{
			LoadPhrase (pClient, 
					pClient->cur_table->item[j].nPhrase, 
					pClient->seltab[SelNum]);

		   if (IsSelectDup (pClient, SelNum, pClient->seltab[SelNum]) == 0)
		   {
				CurLen += (strlen(pClient->seltab[SelNum]) + 2);

				if (CurLen >= pClient->MAX_SEL_LENGTH - 2)
					break;

				// printf ("phase = %s\n", pClient->seltab[SelNum]);
				pClient->seltab_phrase[SelNum] = 
					pClient->cur_table->item[j].nPhrase;

				SelNum++;
			}
		}
		else
			break;

		n++;
	}
	while (1);

	// If no match, restore original setting
	if (SelNum == 0)
	{
		pClient->StartKey = pClient->save_StartKey;
		pClient->EndKey = pClient->save_EndKey;
		pClient->MultiPageMode = pClient->save_MultiPageMode;
		pClient->NextPageIndex = pClient->save_NextPageIndex;
		pClient->CurrentPageIndex = pClient->save_CurrentPageIndex;
		return;
	}

	pClient->CurSelNum = SelNum;

	for (SelNum = pClient->CurSelNum; SelNum < 16; SelNum++)
	{
	   pClient->seltab[SelNum][0] = '\0';    /* zero out the unused area */
	   pClient->seltab_phrase[SelNum] = -1;  /* zero out the unused area */
	}

	// Record down the Num of Input Key to make a match
	pClient->InputMatch = pClient->InputCount;

	// Check if more than one page
	if (n < pClient->TotalOutputPhrase)
	{
		pClient->NextPageIndex = n;
		pClient->MultiPageMode = 1;
	}  
	else if (pClient->MultiPageMode)
	{
		pClient->MultiPageMode = 1;
	}
	else
		pClient->MultiPageMode = 0;
}

////////////////////////////////////////////////////////////////////////////////
//                                
//                               Public Function
//
////////////////////////////////////////////////////////////////////////////////
void TL_InputInit (HzInputTable_T *p)
{
    p->TotalOutputPhrase = 0;
    p->IsHanziInput = 0;	// default is ascii input 
    p->IsFullCharBackup = 0;
    p->IsFullCommaInEnglish = 0; 
    p->IsFullChar = 0;
    p->IsFullCommaInChinese = 0;
    p->IsFullComma = 0;
    p->current_method = 0;
    p->cur_table = NULL;
    p->CurSelNum = 0; 
    p->UseAssociateMode = 0;
    p->IsHanziInputBackup = 0;
    p->IsSysMenu = 0;
    p->IsHelpMenu = 0;
    p->MaxSelectLen = 72;
    p->MAX_SEL_LENGTH = p->MaxSelectLen - 16;
    p->InputCount = 0;
	explicitSelectMode = 0;
}

hz_input_table* TL_LoadMethod (char *szName)
{
    hz_input_table *p;
    p = LoadInputMethod (szName);
//	printf ("In TL_LoadMethod, MaxPress = %d\n", p->MaxPress);
//	printf ("In TL_LoadMethod, MaxDupSel = %d\n", p->MaxDupSel);
	if (!strcmp (p->ename, "phone"))
	{
//		printf ("Set explicitSelectMode to 1\n");
		explicitSelectMode = 1;
	}
	else
	{
//		printf ("Set explicitSelectMode to 0\n");
		explicitSelectMode = 0;
	}
    return p;
}

void TL_UnloadMethod (hz_input_table *p)
{
    UnloadInputMethod (p);
}

int TL_KeyFilter (HzInputTable_T *pClient, u_char key, char *buf, int *len)
{
	// Return 1 for truncate the input key; i.e. just eat it.
	// Return 0 for passing the input key to client, we are not interested on it
	// Return 2 for passing back mutli-byte char, also set the 'len'.
	int inkey = 0;
	char *is_sel_key = NULL;

	// Fix me. I do this, because, explicitSelectMode is always 0 at here
	if (explicitSelectMode == 0)
	{
		if (strcmp (pClient->cur_table->ename, "phone") == 0)
		{
			explicitSelectMode = 1;
		}
	}

//	printf ("TL_KeyFilter: explicitSelectMode is %d\n", explicitSelectMode);

//	if (isalnum (key) || ispunct (key))
//		printf ("Key Filtered : \"%c\"\n", key);
//	else
//		printf ("Key Filtered : \"%#2x\"\n", key);

	inkey = pClient->cur_table->KeyMap[key];
	is_sel_key = strchr( pClient->cur_table->selkey, key);

	if (!inkey && !is_sel_key)
	{
		switch (key)
		{
			case '\010':	// BackSpace	0x08
			case '\177':	// Delete		0x7F
			   if ( pClient->InputCount > 0 )
			   {
				   if (explicitSelectMode == 2)
				   {
					   // In explicitSelectMode, Backspace, just cancel the 
					   // select mode and back to input mode
					   explicitSelectMode = 1;
					   return 1;
				   }
				   pClient->InpKey[--pClient->InputCount]=0;
				   if (pClient->InputCount == 0)
				   {
					   ResetInput (pClient);
				   }
				   else if (pClient->InputCount < pClient->InputMatch)
				   {
					   FindMatchKey (pClient);
					   pClient->MultiPageMode = 0;
					   pClient->CurrentPageIndex = pClient->StartKey;
					   FillMatchChars (pClient, pClient->StartKey);
				   }
				   return 1;
			   }
			   else 
				   return 0;
			case '\033':	// Escape		0x1B
				if (pClient->InputCount > 0)
				{
					if (explicitSelectMode == 2)
						explicitSelectMode = 1;
					ResetInput (pClient);
					return 1;
				}
				else 
					return 0;
			case '<':
				if (pClient->InputCount == 0 || explicitSelectMode == 1)
					return 0;
				if ( pClient->MultiPageMode )
				{
					if (pClient->CurrentPageIndex > pClient->StartKey)
					{
						pClient->CurrentPageIndex = pClient->CurrentPageIndex - 
												 pClient->cur_table->MaxDupSel;
						if (pClient->CurrentPageIndex < pClient->StartKey)
							pClient->CurrentPageIndex = pClient->StartKey;
					}
					else 
						pClient->CurrentPageIndex = pClient->StartKey;
					if (pClient->IsAssociateMode)
						FillAssociateChars (pClient, pClient->CurrentPageIndex);
					else 
						FillMatchChars (pClient, pClient->CurrentPageIndex);
					return 1;
				}
				else 
					return 1;
				break;
			case '>':
				if (pClient->InputCount == 0 || explicitSelectMode == 1)
					return 0;
				if ( pClient->MultiPageMode )
				{
					pClient->CurrentPageIndex = pClient->NextPageIndex;
					if (pClient->IsAssociateMode)
						FillAssociateChars (pClient, pClient->CurrentPageIndex);
					else 
						FillMatchChars (pClient, pClient->CurrentPageIndex);
					return 1;
				}
				else 
					return 1;
			case ' ':
				if (pClient->CurSelNum == 0)
					return 0;

				// Dirty code, there is no enough time to make a better 
				// solution, but I have to do it...
				// For all simplex like IM, space should be used for 
				// scroll the available words, but not for select 'A' word
				// In simplex, only use number digit to select.
				if (strstr (pClient->cur_table->ename, "implex") != NULL)
				{ 
					if ( pClient->MultiPageMode )
					{
						if ((pClient->CurrentPageIndex
								+ pClient->cur_table->MaxDupSel)
								>= pClient->EndKey)
							pClient->CurrentPageIndex = pClient->StartKey;
						else
							pClient->CurrentPageIndex = pClient->NextPageIndex;
						if (pClient->IsAssociateMode)
							FillAssociateChars (pClient, pClient->CurrentPageIndex);
						else 
							FillMatchChars (pClient, pClient->CurrentPageIndex);
						return 1;
					}
				}
				else if (explicitSelectMode == 1)
				{
					// Enter Select Mode
//					printf ("Set explicitSelectMode to 2\n");
					explicitSelectMode = 2;
					return 1;
				}
				else if ( pClient->seltab[0][0] )
				{
					strcpy (buf, pClient->seltab[0]);
					*len = strlen (buf);
					// If cur im is not cangjei or cangjei, we Adjust the Order
					// In other words, CangJei is no need to do phrase sorting.
					if (strcmp (pClient->cur_table->ename, "cangjei")
							&& strcmp (pClient->cur_table->ename, "cangjeihk"))
						AdjustPhraseOrder (pClient, pClient->seltab_phrase[0]);
					ResetInput (pClient);
					if (explicitSelectMode == 2)
						explicitSelectMode = 1;
					return 2;
				}
				return 0;
			default:
				return 0;
		}
	}
	else
	{
		int vv;

		if (pClient->InputCount >= MAX_INPUT_LENGTH)
			return 1;

		// inkey   = pClient->cur_table->KeyMap[key];
		// is_sel_key = strchr( pClient->cur_table->selkey, key);
		vv = is_sel_key - pClient->cur_table->selkey;
		// selkey index, strchr may return NULL
		// if a key is simultaneously inkey & is_sel_key, 
		// then selkey first?
		if (!inkey && is_sel_key)
		{
			if (explicitSelectMode == 1)
				return 1;

			if (pClient->CurSelNum == 0 || pClient->seltab[vv][0] == 0)
			{
				ResetInput (pClient);
				return 0;
			}
			else if (pClient->CurSelNum && pClient->seltab[vv][0])
			{
				strcpy (buf, pClient->seltab[vv]);
				*len = strlen (buf);
				// If cur im is not cangjei or cangjei, we Adjust the Order
				// In other words, CangJei is no need to do phrase sorting.
				if (strcmp (pClient->cur_table->ename, "cangjei")
						&& strcmp (pClient->cur_table->ename, "cangjeihk"))
					AdjustPhraseOrder (pClient, pClient->seltab_phrase[vv]);
				ResetInput (pClient);
				return 2;
			}
			else
			{
				printf ("Error in TL_KeyFilter () : "
						"CurSelNum not agree with pClient->seltab[vv][0]\n");
				return -1;
			}
		}

		// Select mode for pingyin!
		if (explicitSelectMode == 2)
		{
			if (is_sel_key && pClient->CurSelNum && pClient->seltab[vv][0])
			{
//				printf ("vv is %d\n", vv);
				strcpy (buf, pClient->seltab[vv]);
				*len = strlen (buf);
//				AdjustPhraseOrder (pClient, pClient->seltab_phrase[vv]);
				ResetInput (pClient);
				explicitSelectMode = 1;
				return 2;
			}
			else // !is_sel_key
			{
				return 1;
			}
		}
		
		// Key must be input key, while is may also be a select key
		pClient->InpKey[pClient->InputCount++] = inkey;

		if (pClient->InputCount <= pClient->InputMatch+1)
		{
			FindMatchKey (pClient);
			pClient->CurrentPageIndex = pClient->StartKey;
			FillMatchChars (pClient, pClient->StartKey);

			// last_full may be useful for simplex.
			if (pClient->InputCount >= pClient->cur_table->MaxPress
					&& pClient->CurSelNum == 1
					&& pClient->cur_table->last_full
                    && strcmp (pClient->cur_table->ename, "cangjei")
                    && strcmp (pClient->cur_table->ename, "cangjeihk"))
			{  // left only one selection
				strcpy (buf, pClient->seltab[0]);
				*len = strlen (buf);
				ResetInput (pClient);
				return 2;
			}
			return 1;
		}
		return 1;
	}
}

char *TL_GetSelItem (HzInputTable_T *pClient, int idx)
{
     if (idx >= 0
			 && pClient -> CurSelNum > 0
			 && idx <= pClient -> CurSelNum
			 && pClient -> seltab [idx][0])
	 {
          return pClient -> seltab [idx];
	 }

     return NULL;
}

int TL_ConfigureInputArea (HzInputTable_T *p, int MaxSelectLen)
{
//	printf ("MaxSelectLen is %d\n", MaxSelectLen);
    p->MaxSelectLen = MaxSelectLen;
    p->MAX_SEL_LENGTH = p->MaxSelectLen - 8;
    return 1;
}

int TL_GetInputDisplay (HzInputTable_T * p, char *buf, long buflen)
{
	int i, len = buflen;
	unsigned char c[3];
	char *q = buf;

	if (p->InputCount == 0)
		return 0; 

	// initialize the array
	*q = '\0';
	for (i = 0; i <= len && i < p->InputCount ; i++)
	{
		strncpy (c, p->cur_table->KeyName[p->InpKey[i]], 3);

		if (i == p->InputMatch && p->InputCount > p->InputMatch)
			*q++ = '-';

		strncat (q, c, 2);
		q += strlen (p->cur_table->KeyName[p->InpKey[i]]);
	}
	*q = '\0';

	return 1;
}

// Return no. of available selection.
// The no is depends on CurSelNum
int TL_GetSelectDisplay (HzInputTable_T * p, char *buffer)
{
    int i;
    char tmpStr[256];
    
//	printf ("p->CurSelNum is %d\n", p->CurSelNum);

    buffer[0] = '\0';
    if (p->CurSelNum == 0)
         return 0;

    /* not first page */
    if (p->MultiPageMode && p->CurrentPageIndex != p->StartKey)
        strcat (buffer, "< ");

	// By the structure of this 'for loop', CurSelNum must <= 10
    for (i = 0; i < p->CurSelNum; i++)
    {
        if (i != 9) // So i = 0 ~ 8
            sprintf (tmpStr, "%d%s ", i + 1, p->seltab[i]);
        else // i = 9
            sprintf (tmpStr, "0%s ", p->seltab[i]);

        strcat (buffer, tmpStr);
    }

    /* not last page */
    if (p->MultiPageMode && p->NextPageIndex != p->StartKey)
        strcat (buffer, "> ");

    return i;
}
