📄 tranuc.cpp
字号:
//UCDOS输入法文本文件转换程序
#include "stdafx.h"
#include "windowsx.h"
#include "tranuc.h"
#include "csinput.h"
CTranUcdos OTranUcdos ;
//转换的接口
BOOL CTranUcdos::TranslateUcdos( CString pathName )
{
//组织库文件名
strcpy( m_sLibName , pathName ) ;
m_sLibName[strlen(m_sLibName)-3] ='\0' ;
strcat( m_sLibName , "iml" ) ;
//打开原文件
CFile file ;
if( !file.Open( pathName , CFile::modeRead|CFile::typeBinary ) )
{
AfxMessageBox( "Open file error" ) ;
return 0 ;
}
//得到文件长度
m_dwSourceLen =file.GetLength() ;
//分配地址空间
m_hpsSource =(char huge*)GlobalAllocPtr( GMEM_FIXED ,
m_dwSourceLen ) ;
if( !m_hpsSource )
{
AfxMessageBox( "GlobalAllocPtr error" ) ;
file.Close() ;
return 0 ;
}
//读出源文件内容
file.ReadHuge( m_hpsSource , m_dwSourceLen ) ;
//关闭文件
file.Close() ;
//对源库进行分析,以生成我的库
//设置初始值
//整个库所占字节数
inputLibHead.dwTotalBytes =sizeof( INPUT_LIB_HEAD ) ;
inputLibHead.dwTotalWords =0 ; //整个库中的词条数目
inputLibHead.sName[0] ='\0' ; //输入法名,以'\0'结束
inputLibHead.nFunctionKey =0 ; //功能键号
inputLibHead.nGodKey ='z' ; //万能键
inputLibHead.nMaxCodeLen =0 ; //最大码长
for( int i=0 ; i<CODE_CELL_NUM ; i++ )
{
inputLibHead.sCodeCells[i] =0 ;
inputLibHead.dwIndex[i] =0 ; //首码索引表
}
Analysis() ;
//释放申请的空间
GlobalFreePtr( m_hpsSource ) ;
//产生我的输入法文件
CreateMyLib() ;
return 1 ;
}
//创建我的输入法库
void CTranUcdos::CreateMyLib( void )
{
DWORD dwLibPoint =sizeof( INPUT_LIB_HEAD ) ; //库指针
char sFileName[13] ="a.tmp" ;
CFile file ;
DWORD dwFileLen ;
char huge *hpsFile ;
CFile libFile ; //库文件
if( !libFile.Open( m_sLibName , CFile::modeReadWrite|
CFile::modeCreate|
CFile::typeBinary ) )
{
AfxMessageBox( "创建.iml文件失败" ) ;
return ;
}
//将库头写入,主要是为了定位
libFile.Write( &inputLibHead , sizeof( INPUT_LIB_HEAD ) ) ;
INPUT_LIB_ITEM huge *pItem ;
DWORD j ;
DWORD dwItemNum ;
int nItemLen ;
for( int i=0 ; i<CODE_CELL_NUM ; i++ )
{
if( !inputLibHead.sCodeCells[i] ) //没有这个元
continue ;
//组织文件名
sFileName[0] =i+33 ;
//打开文件
if( !file.Open( sFileName , CFile::modeRead|CFile::typeBinary ) )
continue ; //可能该文件不存在
//得到文件长度
dwFileLen =file.GetLength() ;
if( dwFileLen % sizeof( INPUT_LIB_ITEM ) )
{
AfxMessageBox( "文件长度不对" ) ;
return ;
}
//分配空间
hpsFile =(char huge*)GlobalAllocPtr( GMEM_FIXED ,
dwFileLen ) ;
if( !hpsFile )
{
AfxMessageBox( "GlobalAllocPtr error" ) ;
return ;
}
//读出内容
file.ReadHuge( hpsFile , dwFileLen ) ;
//关闭文件
file.Close() ;
//删除该文件
remove( sFileName ) ;
//对该内容进行排序
SortContent( hpsFile , dwFileLen ) ;
//填写该码元检索表
inputLibHead.dwIndex[i] =dwLibPoint ;
//将排序结果写入库文件
dwItemNum =dwFileLen/sizeof( INPUT_LIB_ITEM) ;
pItem =(INPUT_LIB_ITEM huge*)hpsFile ;
for( j=0 ; j<dwItemNum ; j++ )
{
//项长度
nItemLen =1 + pItem->nEnglishLen + pItem->nChineseLen ;
dwLibPoint +=nItemLen ; //修改库指针
//写入项长度
libFile.Write( &nItemLen , 1 ) ;
//写入英文串
libFile.Write( pItem->sEnglish , pItem->nEnglishLen ) ;
//写入汉字串
libFile.Write( pItem->sChinese , pItem->nChineseLen ) ;
pItem++ ;
}
//释放空间
GlobalFreePtr( hpsFile ) ;
}
//定位到库开始,重新写入库头
libFile.SeekToBegin() ;
libFile.Write( &inputLibHead , sizeof( INPUT_LIB_HEAD ) ) ;
//关闭库文件
libFile.Close() ;
if( dwLibPoint != inputLibHead.dwTotalBytes )
AfxMessageBox( "dwLibPoint!==dwTotalBytes" ) ;
}
//对该内容进行排序
void CTranUcdos::SortContent( char huge *hpsFile , DWORD dwFileLen )
{
int nItemLen =sizeof( INPUT_LIB_ITEM ) ;
DWORD dwItemNum =dwFileLen/nItemLen ; //项数
INPUT_LIB_ITEM huge *pItem1 ;
INPUT_LIB_ITEM huge *pItem2 ; //排序用
INPUT_LIB_ITEM item ; //排序用缓冲区
DWORD i , j ;
int n ;
for( i=0 ; i<dwItemNum ; i++ )
{
pItem1 =(INPUT_LIB_ITEM huge*)( hpsFile + i*nItemLen ) ;
for( j=i+1 ; j<dwItemNum ; j++ )
{
pItem2 =(INPUT_LIB_ITEM huge*)( hpsFile + j*nItemLen ) ;
//比较两者的编码
n =_fstrncmp( pItem1->sEnglish , pItem2->sEnglish ,
min( pItem1->nEnglishLen , pItem2->nEnglishLen ) ) ;
if( !n ) //两者相等,长者在后,短者在前
{
if( pItem1->nEnglishLen > pItem2->nEnglishLen ) //交换
{
CopyInputItem( &item , pItem1 ) ;
CopyInputItem( pItem1 , pItem2 ) ;
CopyInputItem( pItem2 , &item ) ;
}
continue ;
}
if( n>0 ) //前者大,需要交换
{
CopyInputItem( &item , pItem1 ) ;
CopyInputItem( pItem1 , pItem2 ) ;
CopyInputItem( pItem2 , &item ) ;
}
//前者小,不需要交换
}
}
}
//拷贝输入项
void CTranUcdos::CopyInputItem( INPUT_LIB_ITEM huge *item1 ,
INPUT_LIB_ITEM huge *item2 )
{
item1->nEnglishLen =item2->nEnglishLen ;
item1->nChineseLen =item2->nChineseLen ;
_fstrncpy( item1->sEnglish , item2->sEnglish , item2->nEnglishLen ) ;
_fstrncpy( item1->sChinese , item2->sChinese , item2->nChineseLen ) ;
}
void CTranUcdos::ShowResult( CDC *pdc )
{
char sBuff[100] ;
int y =32 ;
wsprintf( sBuff , "输入法名:%s" , inputLibHead.sName ) ;
pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
y +=16 ;
wsprintf( sBuff , "功能键号:%c" , inputLibHead.nFunctionKey ) ;
pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
y +=16 ;
wsprintf( sBuff , "万能键:%c" , inputLibHead.nGodKey ) ;
pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
y +=16 ;
wsprintf( sBuff , "最大码长:%d" , inputLibHead.nMaxCodeLen ) ;
pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
y +=16 ;
wsprintf( sBuff , "总字节数:%lu 总行数:%lu 总词条数:%lu" ,
inputLibHead.dwTotalBytes ,
m_dwTotalLines , inputLibHead.dwTotalWords ) ;
pdc->TextOut( 0 , y , sBuff , strlen( sBuff ) ) ;
}
//得到一行
BOOL CTranUcdos::GetOneLine( char *sLineBuff )
{
if( m_dwSourcePoint >= m_dwSourceLen ) //完了
return 0 ;
int nLineLen =0 ; //行长度
for( ; m_dwSourcePoint < m_dwSourceLen ; m_dwSourcePoint++ )
{
if( m_dwSourcePoint < m_dwSourceLen-1 )
{
if( m_hpsSource[m_dwSourcePoint] == 0x0d &&
m_hpsSource[m_dwSourcePoint+1] == 0x0a ) //行结束
{
m_dwSourcePoint +=2 ;
break ;
}
}
sLineBuff[nLineLen++] =m_hpsSource[m_dwSourcePoint] ;
}
sLineBuff[nLineLen] ='\0' ;
return 1 ;
}
//分析源库文件(指UCDOS输入法文本文件格式)
BOOL CTranUcdos::Analysis( void )
{
char sLineBuff[201] ; //行缓冲
//------------------------------------------------------------------//
m_dwTotalLines =0 ;
m_dwSourcePoint =0 ; //源库指针指向库头
while( 1 )
{
//得到一行
if( !GetOneLine( sLineBuff ) ) //到达库尾
return 1 ;
m_dwTotalLines++ ;
if( sLineBuff[0] == '\0' || sLineBuff[0] == ' ' ) //行结束或空格
continue ; //放弃该行
if( sLineBuff[0] & 0x80 ) //是汉字
{
if( !AnalysisHead( sLineBuff ) ) //分析头
return 0 ;
}
else //头个字母是英文,说明这行是编码内容
{
inputLibHead.dwTotalWords++ ; //词数增加
if( !AnalysisContent( sLineBuff ) ) //分析编码项
return 0 ;
}
}
return 1 ;
}
BOOL CTranUcdos::AnalysisContent( char *psLine )
{
char sTmpFile[13] ="a.tmp" ; //临时文件名
CFile tmpFile ;
sTmpFile[0] =psLine[0] ; //构造文件名
//打开该文件
if( !tmpFile.Open( sTmpFile , CFile::modeReadWrite|CFile::typeBinary ) )
{
//创建该文件
if( !tmpFile.Open( sTmpFile , CFile::modeReadWrite|CFile::modeCreate|CFile::typeBinary ) )
{
AfxMessageBox( "创建文件失败" ) ;
return 0 ;
}
}
else
//定位到文件尾
tmpFile.SeekToEnd() ;
INPUT_LIB_ITEM item ; //英文,汉字对照项
item.nEnglishLen =0 ;
item.nChineseLen =0 ;
//去掉行首空格
for( ; (*psLine) == ' ' ; psLine++ )
;
//得到英文编码
for( ; (*psLine) && (*psLine)!=' ' ; psLine++ )
item.sEnglish[item.nEnglishLen++] =*psLine ;
//去掉空格
for( ; (*psLine) == ' ' ; psLine++ )
;
if( !(*psLine) ) //到达行尾
{
char sBuff[50] ;
wsprintf( sBuff , "第%d行只有编码,没有汉字" , m_dwTotalLines ) ;
AfxMessageBox( sBuff ) ;
return 0 ;
}
//得到汉字,直到行末
for( ; *psLine ; )
{
if( (*psLine) == ' ' )
{
item.sChinese[item.nChineseLen++] =' ' ;
//去掉其后的所有空 格
for( psLine++ ; (*psLine) && (*psLine)==' ' ; psLine ++ )
;
}
else
item.sChinese[item.nChineseLen++] =*psLine++ ;
}
//写入文件
tmpFile.Write( &item , sizeof( INPUT_LIB_ITEM ) ) ;
//关闭文件
tmpFile.Close() ;
int nBuffLen =1+item.nEnglishLen+item.nChineseLen ;
inputLibHead.dwTotalBytes +=nBuffLen ;
return 1 ;
}
//分析UCDOS输入法文本文件的头
BOOL CTranUcdos::AnalysisHead( char *psLine )
{
int nFlag ;
int nNameLen ; //等号后内容的长度
char *psNamePoint ; //等号后内容的名字
int i ;
nFlag =0 ;
if( !strncmp( "名称" , psLine , 4 ) ) //是输入法名称
{
nFlag =1 ;
psLine +=4 ;
}
else if( !strncmp( "功能键号" , psLine , 8 ) )
{
nFlag =2 ;
psLine +=8 ;
}
else if( !strncmp( "码元表" , psLine , 6 ) )
{
nFlag =3 ;
psLine +=6 ;
}
else if( !strncmp( "万能键" , psLine , 6 ) )
{
nFlag =4 ;
psLine +=6 ;
}
else if( !strncmp( "最大码长" , psLine , 8 ) )
{
nFlag =5 ;
psLine +=8 ;
}
if( !nFlag ) //不需要的东西
return 1 ;
//去掉空格和等号
for( ; (*psLine) == ' ' || (*psLine) == '=' ; psLine++ )
;
//得到下一串内容(在碰到空格或行结束之前)
psNamePoint =psLine ;
for( nNameLen=0 ; (*psLine) && (*psLine)!=' ' ;
nNameLen++,psLine++)
;
if( !nNameLen )
{
AfxMessageBox( "等号后没有东西" ) ;
return 0 ;
}
switch( nFlag )
{
case 1: //输入法名称
if( nNameLen > MAX_NAME_LEN ) //太长
{
AfxMessageBox( "文件名太长" ) ;
return 0 ;
}
//得到文件名
strncpy( inputLibHead.sName , psNamePoint , nNameLen ) ;
inputLibHead.sName[nNameLen] ='\0' ;
break ;
case 2: //功能键号
if( nNameLen > 1 )
{
AfxMessageBox( "功能键号不是个位数" ) ;
return 0 ;
}
inputLibHead.nFunctionKey =(int)(*psNamePoint) ;
break ;
case 3: //码元表
if( nNameLen > CODE_CELL_NUM )
{
AfxMessageBox( "码元太多了" ) ;
return 0 ;
}
for( i=0 ; i<nNameLen ; i++ ) //得到码元
{
if( psNamePoint[i] < 33 || psNamePoint[i] > 126 )
{
AfxMessageBox( "码元不合法" ) ;
return 0 ;
}
//设上标记
inputLibHead.sCodeCells[psNamePoint[i]-33] =1 ;
}
break ;
case 4: //万能键
if( nNameLen > 1 )
{
AfxMessageBox( "万能键不是一个键" ) ;
return 0 ;
}
inputLibHead.nGodKey =(int)(*psNamePoint) ;
break ;
case 5: //最大码长
psNamePoint[nNameLen] ='\0' ;
i =atoi( psNamePoint ) ; //将字符串转换成整数
if( i<=0 || i>MAX_CODE_LEN )
{
AfxMessageBox( "最大码长不对" ) ;
return 0 ;
}
inputLibHead.nMaxCodeLen =i ;
break ;
}
return 1 ;
}
#ifdef __cplusplus
extern "C" {
#endif
BOOL __export FAR PASCAL TranslateUcdos( LPCSTR pathName )
{
return OTranUcdos.TranslateUcdos( pathName ) ;
}
#ifdef __cplusplus
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -