⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gethz.cpp

📁 支持Windows 3.x、Windows 9x平台上的中文(GB、Big5)、日文(Shift JIS、EUC JIS)、韩文(KS C 5601)、HZ码的显示与输入,智能内码识别
💻 CPP
字号:
//根据输入的英文编码串,得到其汉字
#include	"stdafx.h"
#include	<windowsx.h>

#include	"gethz.h"
#include	"csinput.h"

CInputLib	OInputLib ;		//输入法库对象

CInputLib::CInputLib( void )
{
	m_hpsLib	=NULL ;
	m_dwLibLen	=0 ;
	m_lpLibHead	=NULL ;
}

CInputLib::~CInputLib( void )
{
	if( m_hpsLib )
		GlobalFreePtr( m_hpsLib ) ;
}

//装入输入法库
BOOL	CInputLib::LoadInputLib( LPCSTR lpsLibName )
{
	CFile	file ;

	//打开输入法文件	
	if( !file.Open( lpsLibName , CFile::modeRead|CFile::typeBinary ) )
	{
		AfxMessageBox( "输入法文件打开出错" ) ;
		return	0 ;
	}
	//得到文件长度
	m_dwLibLen	=file.GetLength() ;
	if( m_dwLibLen < sizeof( INPUT_LIB_HEAD ) )
	{
		AfxMessageBox( "文件长度不对!" ) ;
		file.Close() ;
		return	0 ;
	}
	//分配库所需的空间
	m_hpsLib	=(char huge*)GlobalAllocPtr( GMEM_FIXED , 
							m_dwLibLen ) ;
	if( !m_hpsLib )
	{
		AfxMessageBox( "内存不够,无法装入输入法库!" ) ;
		file.Close() ;
		return	0 ;
	}
	//读出输入法库
	file.ReadHuge( m_hpsLib , m_dwLibLen ) ;
	//关闭文件
	file.Close() ;
	
	//库头
	m_lpLibHead	=(INPUT_LIB_HEAD far*)m_hpsLib ;
	
	return	1 ;
}

//卸掉输入法库
void	CInputLib::UnloadInputLib( void )
{
	if( m_hpsLib )
	{
		GlobalFreePtr( m_hpsLib ) ;
		m_hpsLib	=NULL ;
		m_dwLibLen	=0 ;
	}
}

//-------------------------------------------------------------------------//

#ifdef	__cplusplus
extern	"C"	{
#endif

//装入输入法库
BOOL __export FAR PASCAL LoadInputLib( LPCSTR lpsLibName )
{
	return	OInputLib.LoadInputLib( lpsLibName ) ;
}

//卸掉输入法库
void __export FAR PASCAL	UnloadInputLib( void )
{
	OInputLib.UnloadInputLib() ;
}

//根据输入的英文编码,得到汉字
//nFlag=0,从头开始查,设置翻页指针
//nFlag=1,从以前的继续查,设置翻页指针
//nFlag=2,往回走一个字母,设置翻页指针
//nFlag=3,向下翻页,只改变翻页指针,但不改变查找用的指针
//nFlag=4,向上翻页
//返回0:出错
//返回1:只可以向下翻页
//返回2:只可以向上翻页
//返回3:可以向下也可以向上翻页
//返回4:不能进行翻页
int	__export	FAR PASCAL	GetOutputHz( 
						LPCSTR lpsEnglish , int nEnglishLen ,
						LPSTR lpsChinese , int	nMaxChinese ,
						LPINT lpnChineseLen , int nFlag )
{
	int	i , n , nNum ;

	if( nFlag == 3 || nFlag == 4 )	//只是翻页而已
		//组织返回汉字串
		return	ArrangeOutHz( lpsEnglish , nEnglishLen ,
								lpsChinese , nMaxChinese , lpnChineseLen ,
											nFlag ) ;
	
	if( !CheckInput( lpsEnglish , nEnglishLen ) )	//检查输入串的合法性
		return	0 ;		//不合法
	if( !OInputLib.m_lpLibHead->dwIndex[lpsEnglish[0]-START_CODE] )
		goto l100 ;	//没有该项

	if( nFlag == 2 )	//往回走一个字母
	{
		if( !OInputLib.m_nCheckedNum )	//没有字母被检索过
		{
			AfxMessageBox( "还没有字母被检索过呢,就要往回走了?" ) ;
			return	0 ;
		}
		OInputLib.m_nCheckedNum-- ;		//减少检索过的字母
		if( !OInputLib.m_nCheckedNum )		//只有一个检索过的字母
		{
			AfxMessageBox( "只检索过一个字母,不应该让我处理的!" ) ;
			*lpnChineseLen	=0 ;
			return	1 ;
		}
		
		//重新设置内容指针
		OInputLib.m_dwContent	=
					OInputLib.m_dwContentPoint[OInputLib.m_nCheckedNum-1] ;
		OInputLib.m_hpsContent	=OInputLib.m_hpsLib +
													OInputLib.m_dwContent ;
						
		//设置页指针
		OInputLib.m_hpsPage	=OInputLib.m_hpsContent ;
		OInputLib.m_dwPage	=OInputLib.m_dwContent ;
		OInputLib.m_nScrolledPage	=0 ;	//已经翻过的页数
	
		//组织返回汉字串
		return	ArrangeOutHz( lpsEnglish , nEnglishLen ,
								lpsChinese , nMaxChinese , lpnChineseLen ,
											3 ) ;		//向下翻页
	}
		
	if( !nFlag )		//表示根据英文编码,从头查
	{
		OInputLib.m_dwContent	=OInputLib.m_lpLibHead->
									dwIndex[lpsEnglish[0]-START_CODE] ;
		//设置好库内容指针
		OInputLib.m_hpsContent	=OInputLib.m_hpsLib + 
													OInputLib.m_dwContent ;

		//记录内容指针位置
		OInputLib.m_dwContentPoint[0]	=OInputLib.m_dwContent ;									
		OInputLib.m_nCheckedNum	=1 ;	//已经检索过的字母数
	}
	
	//检索余下的字母
	nNum	=nEnglishLen-OInputLib.m_nCheckedNum ;	//剩余的字母数
	if( !nNum )	//已经没有剩余字母
	{
		//设置翻页指针,从头翻起
		OInputLib.m_dwPage	=OInputLib.m_dwContent ;
		OInputLib.m_hpsPage	=OInputLib.m_hpsContent ;
		//记录翻页指针位置
		OInputLib.m_nScrolledPage	=0 ;	//已经翻过的页数
		//组织返回汉字串
		return	ArrangeOutHz( lpsEnglish , nEnglishLen ,
							lpsChinese , nMaxChinese , lpnChineseLen ,
											3 ) ;	//向下翻页
	}

	for( i=0 ; i<nNum ; i++ )	//对剩余的字母一一进行检索
	{
		//判断是否到达库尾
		while( OInputLib.m_dwContent < OInputLib.m_dwLibLen )
    	{
    		if( OInputLib.m_hpsContent[OInputLib.m_nCheckedNum+1] & 0x80 )
    		{	
				//是汉字,库中的串较小,往下走指针
				OInputLib.m_dwContent	+=(BYTE)(*OInputLib.m_hpsContent) ;
				OInputLib.m_hpsContent	+=(BYTE)(*OInputLib.m_hpsContent) ;
				continue ;
			}
    
    		//进行比较
			n	=hstrncmp( OInputLib.m_hpsContent+1 ,	//库中的英文串
									(char huge*)lpsEnglish , OInputLib.m_nCheckedNum+1 ) ;
			if( !n )		//匹配成功
			{
				//设置内容指针,为了以后回溯
				OInputLib.m_dwContentPoint[OInputLib.m_nCheckedNum++]	=
					OInputLib.m_dwContent ;
				if( i<nNum-1 )	//还没到最后一个字母,继续检索
					break ;	//进入下一循环
														
				//已经是最后一个字母,设置翻页指针
				OInputLib.m_hpsPage	=OInputLib.m_hpsContent ;
				OInputLib.m_dwPage	=OInputLib.m_dwContent ;
				OInputLib.m_nScrolledPage	=0 ;	//已经翻过的页数
				//组织返回汉字串
				return	ArrangeOutHz( lpsEnglish , nEnglishLen ,
								lpsChinese , nMaxChinese , lpnChineseLen ,
													3 ) ;		//向下翻页
			}

			if( n>0 )		//库中的串较大,说明不可能匹配
				goto	l100 ;
				
			//库中的串较小,往下走指针
			OInputLib.m_dwContent	+=(BYTE)(*OInputLib.m_hpsContent) ;
			OInputLib.m_hpsContent	+=(BYTE)(*OInputLib.m_hpsContent) ;
		}
	}
	
	//找不到
l100:	OInputLib.m_nCheckedNum	=nEnglishLen ;
	*lpnChineseLen	=0 ;
	return 4 ;
}

//组织返回汉字串
//nFlag=3,向下翻页
//nFlag=4,向上翻页
//返回0:出错
//返回1:只可以向下翻页
//返回2:只可以向上翻页
//返回3:可以向下也可以向上翻页
//返回4:不能进行翻页
int	ArrangeOutHz( LPCSTR lpsEnglish , int nEnglishLen ,
							LPSTR lpsChinese , int nMaxChinese , 
							LPINT lpnChineseLen , int nFlag )
{
	if( nFlag == 4 )	//向上翻页
	{
		if( OInputLib.m_nScrolledPage<=1 )		//无页可翻
		{
			AfxMessageBox( "到头了,你还让我翻?" ) ;
			return	0 ;
		}
		
		OInputLib.m_nScrolledPage-- ;	//往回翻
		//调整页指针
		OInputLib.m_dwPage	=
				OInputLib.m_dwPagePoint[OInputLib.m_nScrolledPage-1] ;
		OInputLib.m_hpsPage	=OInputLib.m_hpsLib + OInputLib.m_dwPage ;

		//读取汉字串
		SetHzString( lpsEnglish , nEnglishLen ,
							lpsChinese , nMaxChinese , lpnChineseLen ) ;
		if( OInputLib.m_nScrolledPage<=1 )	//已经到头了
			return	1 ;		//只可以向下翻了
			
		return	3 ;		//可以前后翻
	}
	
	//是向下翻页
	//设置翻页指针
	OInputLib.m_dwPagePoint[OInputLib.m_nScrolledPage++]	=
		OInputLib.m_dwPage ;
	//读取汉字串		
	if( !SetHzString( lpsEnglish , nEnglishLen ,	//已经到底
								lpsChinese , nMaxChinese , lpnChineseLen ) )
	{								
		if( OInputLib.m_nScrolledPage <= 1 )	//只有一页
			return	4 ;		//不能进行翻页
		return	2 ;		//只能往上翻页
	}

	if( OInputLib.m_nScrolledPage <= 1 )	//只有一页,即当前显示页
		return	1 ;	//只能往后翻页
	
	if( OInputLib.m_nScrolledPage >= MAX_PAGE )	//已经到最大页数
		return	2 ;	//只能往前翻页
		
	return	3 ;		//可以前后翻页
}

//读取汉字串		
//返回0:已经到底
//返回1:没有到底
/*int	SetHzString( LPCSTR lpsEnglish , int nEnglishLen ,
							LPSTR lpsChinese , int nMaxChinese , 
							LPINT lpnChineseLen ) 
{
	char huge	*hps ;	//指向项汉字
	int		nItemLen ;	//项汉字长度	
	int		i , j , n ;

	int	nReturnLen	=0 ;	//返回的汉字串长度
	char	cWordNum	='1'  ;	//词数
	//判断是否到达库尾
	while( OInputLib.m_dwPage < OInputLib.m_dwLibLen )
    {
    	hps	=OInputLib.m_hpsPage+2 ;	//指向汉字串
    	nItemLen	=(BYTE)(*OInputLib.m_hpsPage)-2 ;	//汉字串长度
    	//去掉英文
    	for( ; !( (*hps)&0x80 ) ; nItemLen-- , hps++ )	//是英文
    		;
    	if( nItemLen < 2 )
    	{
    		AfxMessageBox( "库中的汉字项不对!" ) ;
    		return	0 ;
    	}
    	//分析汉字串
    	//计算汉字串中有几种汉字词组(词组之间以空格格开)
    	j	=1 ;	//至少一个
    	for( i=2 ; i<nItemLen ; i++ )
    		if( hps[i] == ' ' )
    			j++ ;
		//判断长度是否已经超出
		if( nReturnLen+nItemLen+j > nMaxChinese )	//长度已经超出
		{
			*lpnChineseLen	=nReturnLen ;
			return	1 ;		//没有到底
		}
		//长度没有超出,得到这些词组
		lpsChinese[nReturnLen++]	=cWordNum++ ;	//序号
		for( i=0 ; i<nItemLen ; i++ )
		{
			lpsChinese[nReturnLen++]	=hps[i] ;
			if( hps[i] == ' ' )
				lpsChinese[nReturnLen++]	=cWordNum++ ;	//序号
		}
		//往下走页指针
		OInputLib.m_dwPage	+=(BYTE)*OInputLib.m_hpsPage ;
		OInputLib.m_hpsPage	=hps+nItemLen ;

		//判断新的项是否满足要求
	   	//进行比较
		n	=hstrncmp( OInputLib.m_hpsPage + 1 ,	//库中的英文串
								(char huge*)lpsEnglish , nEnglishLen ) ;
		if( n )		//不相等,说明不可能再匹配,也不能再往下翻了
		{
			*lpnChineseLen	=nReturnLen ;
			return	0 ;
		}
		
		if( nReturnLen >= nMaxChinese )	//长度到头了
		{
			*lpnChineseLen	=nReturnLen ;
			return	1 ;
		}
			
		//两者相等,得到这些内容
		lpsChinese[nReturnLen++]	=' ' ;		//加一个空格
	}
	
	*lpnChineseLen	=nReturnLen ;
	return	0 ;		//库结束了
}
*/
int	SetHzString( LPCSTR lpsEnglish , int nEnglishLen ,
							LPSTR lpsChinese , int nMaxChinese , 
							LPINT lpnChineseLen ) 
{
	char huge	*hps ;	//指向项汉字
	int		nItemLen ;	//项汉字长度	
	int		i , j , k , n , nFlag ;

	int	nReturnLen	=0 ;	//返回的汉字串长度
	char	cWordNum	='1'  ;	//词数
	//判断是否到达库尾
	while( OInputLib.m_dwPage < OInputLib.m_dwLibLen )
    {
    	hps	=OInputLib.m_hpsPage ;
    	//直到碰到汉字为止
    	nItemLen	=0 ;
    	for( ; !( (*hps)&0x80 ) || !( (*(hps+1))&0x80 ); hps++ , nItemLen++)
    		;		//不是汉字
    	//分析该汉字串,碰到非汉字时结束
		for( i=2 ; (hps[i]&0x80)&&(hps[i+1]&0x80) ; i++ , i++ )
			;
		//判断长度是否超出
		if( nReturnLen+i+2 > nMaxChinese )	//长度已经超出
		{
			*lpnChineseLen	=nReturnLen ;
			return	1 ;		//没有到底
		}
		//长度没有超出,得到该词组
		nFlag	=1 ;	//标记可以加入词组
		for( j=1 ; j<nReturnLen ; )	//判断是否已经有词组了
		{
			for( k=j+2 ; k<nReturnLen ; k+=2 )
				if( lpsChinese[k]==' ' )
					break ;
			if( k>nReturnLen )
				break ;
			//找到一个词组
			if( !hstrncmp( lpsChinese+j , hps , k-j ) )	//相等
			{
				nFlag	=0 ;
				break ;
			}
			j	=k+2 ;	//跳过空格和下一个标号
		}
		
		if( nFlag )	//可以加入该词组
		{		
			if( nReturnLen )	//不是开始,加空格
				lpsChinese[nReturnLen++]	=' ' ;
			lpsChinese[nReturnLen++]	=cWordNum++ ;	//序号
			for( j=0 ; j<i ; j++ )
				lpsChinese[nReturnLen++]	=hps[j] ;
		}

		//往下走页指针
		OInputLib.m_dwPage	+=nItemLen + i ;
		OInputLib.m_hpsPage	=hps+i ;

		//判断是空格结束还是一项结束
		if( hps[i+1] & 0x80 )		//是空格结束
			continue ;
			
		//判断新的项是否满足要求
	   	//进行比较
		n	=hstrncmp( OInputLib.m_hpsPage + 1 ,	//库中的英文串
								(char huge*)lpsEnglish , nEnglishLen ) ;
		if( n )		//不相等,说明不可能再匹配,也不能再往下翻了
		{
			*lpnChineseLen	=nReturnLen ;
			return	0 ;
		}
		
		if( nReturnLen >= nMaxChinese )	//长度到头了
		{
			*lpnChineseLen	=nReturnLen ;
			return	1 ;
		}
	}
	
	*lpnChineseLen	=nReturnLen ;
	return	0 ;		//库结束了
}

//检查输入串的合法性
int __export FAR PASCAL	CheckInput( LPCSTR lpsEnglish , 
																int nEnglishLen )
{
	if( !OInputLib.m_dwLibLen )		//当前没有装入输入法库
	{
		AfxMessageBox( "还没有装入输入法库!" ) ;
		return	0 ;
	}
	
	if( nEnglishLen<=0 )
	{
		AfxMessageBox( "输入串长度不对!" ) ;
		return	0 ;
	}

	int	n ;		
	for( int i=0 ; i<nEnglishLen ; i++ )
	{
		n	=lpsEnglish[i] - START_CODE ;
		if( n<0 || n>=CODE_CELL_NUM )		//超出了规定的字符范围
		{
//			AfxMessageBox( "输入串不合法!" ) ;
			return	0 ;
		}

		//当前输入法没有该字符			 
		if( !OInputLib.m_lpLibHead->sCodeCells[n] )	
			return	0 ;
	}
			
	return	1 ;
}

//得到有关输入法库的信息
void	__export	FAR PASCAL	GetInputMethodName( LPSTR lpsName , 
								int	nMaxNameLen )
{
	if( !OInputLib.m_hpsLib )		//还没有安装库
	{
		AfxMessageBox( "还没有安装库呢!请先安装输入法库!" ) ;
		*lpsName	='\0' ;
		return	;
	}

	//长度	
	int		n	=min( nMaxNameLen-1 , 
							strlen(OInputLib.m_lpLibHead->sName));
	_fstrncpy( lpsName , OInputLib.m_lpLibHead->sName , n ) ;
	lpsName[n]	='\0' ;		//结束
}

//得到输入法最大输入长度								
int	__export FAR PASCAL GetInputMethodMaxLen( void )
{
	if( !OInputLib.m_hpsLib )		//还没有安装库
	{
		AfxMessageBox( "还没有安装库呢!请先安装输入法库!" ) ;
		return	0 ;
	}

	return	OInputLib.m_lpLibHead->nMaxCodeLen ;
}

//比较两个huge指针所指的字符串
int	hstrncmp( char huge *s1 , char huge *s2 , int n )
{
	for( int i=0 ; i<n ; i++ )
	{                                              
		if( s1[i] == s2[i] )
			continue ;
		if( s1[i] < s2[i] )		//s1比s2小
			return	-1 ;
		return	1 ;				//s1比s2大
	}
	return	0 ;		//两者相等
}
	
#ifdef	__cplusplus
}
#endif
							

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -