GETHZ.CPP
上传用户:zhang8947
上传日期:2007-01-08
资源大小:1910k
文件大小:13k
源码类别:

多国语言处理

开发平台:

Visual C++

  1. //根据输入的英文编码串,得到其汉字
  2. #include "stdafx.h"
  3. #include <windowsx.h>
  4. #include "gethz.h"
  5. #include "csinput.h"
  6. CInputLib OInputLib ; //输入法库对象
  7. CInputLib::CInputLib( void )
  8. {
  9. m_hpsLib =NULL ;
  10. m_dwLibLen =0 ;
  11. m_lpLibHead =NULL ;
  12. }
  13. CInputLib::~CInputLib( void )
  14. {
  15. if( m_hpsLib )
  16. GlobalFreePtr( m_hpsLib ) ;
  17. }
  18. //装入输入法库
  19. BOOL CInputLib::LoadInputLib( LPCSTR lpsLibName )
  20. {
  21. CFile file ;
  22. //打开输入法文件
  23. if( !file.Open( lpsLibName , CFile::modeRead|CFile::typeBinary ) )
  24. {
  25. AfxMessageBox( "输入法文件打开出错" ) ;
  26. return 0 ;
  27. }
  28. //得到文件长度
  29. m_dwLibLen =file.GetLength() ;
  30. if( m_dwLibLen < sizeof( INPUT_LIB_HEAD ) )
  31. {
  32. AfxMessageBox( "文件长度不对!" ) ;
  33. file.Close() ;
  34. return 0 ;
  35. }
  36. //分配库所需的空间
  37. m_hpsLib =(char huge*)GlobalAllocPtr( GMEM_FIXED , 
  38. m_dwLibLen ) ;
  39. if( !m_hpsLib )
  40. {
  41. AfxMessageBox( "内存不够,无法装入输入法库!" ) ;
  42. file.Close() ;
  43. return 0 ;
  44. }
  45. //读出输入法库
  46. file.ReadHuge( m_hpsLib , m_dwLibLen ) ;
  47. //关闭文件
  48. file.Close() ;
  49. //库头
  50. m_lpLibHead =(INPUT_LIB_HEAD far*)m_hpsLib ;
  51. return 1 ;
  52. }
  53. //卸掉输入法库
  54. void CInputLib::UnloadInputLib( void )
  55. {
  56. if( m_hpsLib )
  57. {
  58. GlobalFreePtr( m_hpsLib ) ;
  59. m_hpsLib =NULL ;
  60. m_dwLibLen =0 ;
  61. }
  62. }
  63. //-------------------------------------------------------------------------//
  64. #ifdef __cplusplus
  65. extern "C" {
  66. #endif
  67. //装入输入法库
  68. BOOL __export FAR PASCAL LoadInputLib( LPCSTR lpsLibName )
  69. {
  70. return OInputLib.LoadInputLib( lpsLibName ) ;
  71. }
  72. //卸掉输入法库
  73. void __export FAR PASCAL UnloadInputLib( void )
  74. {
  75. OInputLib.UnloadInputLib() ;
  76. }
  77. //根据输入的英文编码,得到汉字
  78. //nFlag=0,从头开始查,设置翻页指针
  79. //nFlag=1,从以前的继续查,设置翻页指针
  80. //nFlag=2,往回走一个字母,设置翻页指针
  81. //nFlag=3,向下翻页,只改变翻页指针,但不改变查找用的指针
  82. //nFlag=4,向上翻页
  83. //返回0:出错
  84. //返回1:只可以向下翻页
  85. //返回2:只可以向上翻页
  86. //返回3:可以向下也可以向上翻页
  87. //返回4:不能进行翻页
  88. int __export FAR PASCAL GetOutputHz( 
  89. LPCSTR lpsEnglish , int nEnglishLen ,
  90. LPSTR lpsChinese , int nMaxChinese ,
  91. LPINT lpnChineseLen , int nFlag )
  92. {
  93. int i , n , nNum ;
  94. if( nFlag == 3 || nFlag == 4 ) //只是翻页而已
  95. //组织返回汉字串
  96. return ArrangeOutHz( lpsEnglish , nEnglishLen ,
  97. lpsChinese , nMaxChinese , lpnChineseLen ,
  98. nFlag ) ;
  99. if( !CheckInput( lpsEnglish , nEnglishLen ) ) //检查输入串的合法性
  100. return 0 ; //不合法
  101. if( !OInputLib.m_lpLibHead->dwIndex[lpsEnglish[0]-START_CODE] )
  102. goto l100 ; //没有该项
  103. if( nFlag == 2 ) //往回走一个字母
  104. {
  105. if( !OInputLib.m_nCheckedNum ) //没有字母被检索过
  106. {
  107. AfxMessageBox( "还没有字母被检索过呢,就要往回走了?" ) ;
  108. return 0 ;
  109. }
  110. OInputLib.m_nCheckedNum-- ; //减少检索过的字母
  111. if( !OInputLib.m_nCheckedNum ) //只有一个检索过的字母
  112. {
  113. AfxMessageBox( "只检索过一个字母,不应该让我处理的!" ) ;
  114. *lpnChineseLen =0 ;
  115. return 1 ;
  116. }
  117. //重新设置内容指针
  118. OInputLib.m_dwContent =
  119. OInputLib.m_dwContentPoint[OInputLib.m_nCheckedNum-1] ;
  120. OInputLib.m_hpsContent =OInputLib.m_hpsLib +
  121. OInputLib.m_dwContent ;
  122. //设置页指针
  123. OInputLib.m_hpsPage =OInputLib.m_hpsContent ;
  124. OInputLib.m_dwPage =OInputLib.m_dwContent ;
  125. OInputLib.m_nScrolledPage =0 ; //已经翻过的页数
  126. //组织返回汉字串
  127. return ArrangeOutHz( lpsEnglish , nEnglishLen ,
  128. lpsChinese , nMaxChinese , lpnChineseLen ,
  129. 3 ) ; //向下翻页
  130. }
  131. if( !nFlag ) //表示根据英文编码,从头查
  132. {
  133. OInputLib.m_dwContent =OInputLib.m_lpLibHead->
  134. dwIndex[lpsEnglish[0]-START_CODE] ;
  135. //设置好库内容指针
  136. OInputLib.m_hpsContent =OInputLib.m_hpsLib + 
  137. OInputLib.m_dwContent ;
  138. //记录内容指针位置
  139. OInputLib.m_dwContentPoint[0] =OInputLib.m_dwContent ;
  140. OInputLib.m_nCheckedNum =1 ; //已经检索过的字母数
  141. }
  142. //检索余下的字母
  143. nNum =nEnglishLen-OInputLib.m_nCheckedNum ; //剩余的字母数
  144. if( !nNum ) //已经没有剩余字母
  145. {
  146. //设置翻页指针,从头翻起
  147. OInputLib.m_dwPage =OInputLib.m_dwContent ;
  148. OInputLib.m_hpsPage =OInputLib.m_hpsContent ;
  149. //记录翻页指针位置
  150. OInputLib.m_nScrolledPage =0 ; //已经翻过的页数
  151. //组织返回汉字串
  152. return ArrangeOutHz( lpsEnglish , nEnglishLen ,
  153. lpsChinese , nMaxChinese , lpnChineseLen ,
  154. 3 ) ; //向下翻页
  155. }
  156. for( i=0 ; i<nNum ; i++ ) //对剩余的字母一一进行检索
  157. {
  158. //判断是否到达库尾
  159. while( OInputLib.m_dwContent < OInputLib.m_dwLibLen )
  160.      {
  161.      if( OInputLib.m_hpsContent[OInputLib.m_nCheckedNum+1] & 0x80 )
  162.      {
  163. //是汉字,库中的串较小,往下走指针
  164. OInputLib.m_dwContent +=(BYTE)(*OInputLib.m_hpsContent) ;
  165. OInputLib.m_hpsContent +=(BYTE)(*OInputLib.m_hpsContent) ;
  166. continue ;
  167. }
  168.     
  169.      //进行比较
  170. n =hstrncmp( OInputLib.m_hpsContent+1 , //库中的英文串
  171. (char huge*)lpsEnglish , OInputLib.m_nCheckedNum+1 ) ;
  172. if( !n ) //匹配成功
  173. {
  174. //设置内容指针,为了以后回溯
  175. OInputLib.m_dwContentPoint[OInputLib.m_nCheckedNum++] =
  176. OInputLib.m_dwContent ;
  177. if( i<nNum-1 ) //还没到最后一个字母,继续检索
  178. break ; //进入下一循环
  179. //已经是最后一个字母,设置翻页指针
  180. OInputLib.m_hpsPage =OInputLib.m_hpsContent ;
  181. OInputLib.m_dwPage =OInputLib.m_dwContent ;
  182. OInputLib.m_nScrolledPage =0 ; //已经翻过的页数
  183. //组织返回汉字串
  184. return ArrangeOutHz( lpsEnglish , nEnglishLen ,
  185. lpsChinese , nMaxChinese , lpnChineseLen ,
  186. 3 ) ; //向下翻页
  187. }
  188. if( n>0 ) //库中的串较大,说明不可能匹配
  189. goto l100 ;
  190. //库中的串较小,往下走指针
  191. OInputLib.m_dwContent +=(BYTE)(*OInputLib.m_hpsContent) ;
  192. OInputLib.m_hpsContent +=(BYTE)(*OInputLib.m_hpsContent) ;
  193. }
  194. }
  195. //找不到
  196. l100: OInputLib.m_nCheckedNum =nEnglishLen ;
  197. *lpnChineseLen =0 ;
  198. return 4 ;
  199. }
  200. //组织返回汉字串
  201. //nFlag=3,向下翻页
  202. //nFlag=4,向上翻页
  203. //返回0:出错
  204. //返回1:只可以向下翻页
  205. //返回2:只可以向上翻页
  206. //返回3:可以向下也可以向上翻页
  207. //返回4:不能进行翻页
  208. int ArrangeOutHz( LPCSTR lpsEnglish , int nEnglishLen ,
  209. LPSTR lpsChinese , int nMaxChinese , 
  210. LPINT lpnChineseLen , int nFlag )
  211. {
  212. if( nFlag == 4 ) //向上翻页
  213. {
  214. if( OInputLib.m_nScrolledPage<=1 ) //无页可翻
  215. {
  216. AfxMessageBox( "到头了,你还让我翻?" ) ;
  217. return 0 ;
  218. }
  219. OInputLib.m_nScrolledPage-- ; //往回翻
  220. //调整页指针
  221. OInputLib.m_dwPage =
  222. OInputLib.m_dwPagePoint[OInputLib.m_nScrolledPage-1] ;
  223. OInputLib.m_hpsPage =OInputLib.m_hpsLib + OInputLib.m_dwPage ;
  224. //读取汉字串
  225. SetHzString( lpsEnglish , nEnglishLen ,
  226. lpsChinese , nMaxChinese , lpnChineseLen ) ;
  227. if( OInputLib.m_nScrolledPage<=1 ) //已经到头了
  228. return 1 ; //只可以向下翻了
  229. return 3 ; //可以前后翻
  230. }
  231. //是向下翻页
  232. //设置翻页指针
  233. OInputLib.m_dwPagePoint[OInputLib.m_nScrolledPage++] =
  234. OInputLib.m_dwPage ;
  235. //读取汉字串
  236. if( !SetHzString( lpsEnglish , nEnglishLen , //已经到底
  237. lpsChinese , nMaxChinese , lpnChineseLen ) )
  238. {
  239. if( OInputLib.m_nScrolledPage <= 1 ) //只有一页
  240. return 4 ; //不能进行翻页
  241. return 2 ; //只能往上翻页
  242. }
  243. if( OInputLib.m_nScrolledPage <= 1 ) //只有一页,即当前显示页
  244. return 1 ; //只能往后翻页
  245. if( OInputLib.m_nScrolledPage >= MAX_PAGE ) //已经到最大页数
  246. return 2 ; //只能往前翻页
  247. return 3 ; //可以前后翻页
  248. }
  249. //读取汉字串
  250. //返回0:已经到底
  251. //返回1:没有到底
  252. /*int SetHzString( LPCSTR lpsEnglish , int nEnglishLen ,
  253. LPSTR lpsChinese , int nMaxChinese , 
  254. LPINT lpnChineseLen ) 
  255. {
  256. char huge *hps ; //指向项汉字
  257. int nItemLen ; //项汉字长度
  258. int i , j , n ;
  259. int nReturnLen =0 ; //返回的汉字串长度
  260. char cWordNum ='1'  ; //词数
  261. //判断是否到达库尾
  262. while( OInputLib.m_dwPage < OInputLib.m_dwLibLen )
  263.     {
  264.      hps =OInputLib.m_hpsPage+2 ; //指向汉字串
  265.      nItemLen =(BYTE)(*OInputLib.m_hpsPage)-2 ; //汉字串长度
  266.      //去掉英文
  267.      for( ; !( (*hps)&0x80 ) ; nItemLen-- , hps++ ) //是英文
  268.      ;
  269.      if( nItemLen < 2 )
  270.      {
  271.      AfxMessageBox( "库中的汉字项不对!" ) ;
  272.      return 0 ;
  273.      }
  274.      //分析汉字串
  275.      //计算汉字串中有几种汉字词组(词组之间以空格格开)
  276.      j =1 ; //至少一个
  277.      for( i=2 ; i<nItemLen ; i++ )
  278.      if( hps[i] == ' ' )
  279.      j++ ;
  280. //判断长度是否已经超出
  281. if( nReturnLen+nItemLen+j > nMaxChinese ) //长度已经超出
  282. {
  283. *lpnChineseLen =nReturnLen ;
  284. return 1 ; //没有到底
  285. }
  286. //长度没有超出,得到这些词组
  287. lpsChinese[nReturnLen++] =cWordNum++ ; //序号
  288. for( i=0 ; i<nItemLen ; i++ )
  289. {
  290. lpsChinese[nReturnLen++] =hps[i] ;
  291. if( hps[i] == ' ' )
  292. lpsChinese[nReturnLen++] =cWordNum++ ; //序号
  293. }
  294. //往下走页指针
  295. OInputLib.m_dwPage +=(BYTE)*OInputLib.m_hpsPage ;
  296. OInputLib.m_hpsPage =hps+nItemLen ;
  297. //判断新的项是否满足要求
  298.     //进行比较
  299. n =hstrncmp( OInputLib.m_hpsPage + 1 , //库中的英文串
  300. (char huge*)lpsEnglish , nEnglishLen ) ;
  301. if( n ) //不相等,说明不可能再匹配,也不能再往下翻了
  302. {
  303. *lpnChineseLen =nReturnLen ;
  304. return 0 ;
  305. }
  306. if( nReturnLen >= nMaxChinese ) //长度到头了
  307. {
  308. *lpnChineseLen =nReturnLen ;
  309. return 1 ;
  310. }
  311. //两者相等,得到这些内容
  312. lpsChinese[nReturnLen++] =' ' ; //加一个空格
  313. }
  314. *lpnChineseLen =nReturnLen ;
  315. return 0 ; //库结束了
  316. }
  317. */
  318. int SetHzString( LPCSTR lpsEnglish , int nEnglishLen ,
  319. LPSTR lpsChinese , int nMaxChinese , 
  320. LPINT lpnChineseLen ) 
  321. {
  322. char huge *hps ; //指向项汉字
  323. int nItemLen ; //项汉字长度
  324. int i , j , k , n , nFlag ;
  325. int nReturnLen =0 ; //返回的汉字串长度
  326. char cWordNum ='1'  ; //词数
  327. //判断是否到达库尾
  328. while( OInputLib.m_dwPage < OInputLib.m_dwLibLen )
  329.     {
  330.      hps =OInputLib.m_hpsPage ;
  331.      //直到碰到汉字为止
  332.      nItemLen =0 ;
  333.      for( ; !( (*hps)&0x80 ) || !( (*(hps+1))&0x80 ); hps++ , nItemLen++)
  334.      ; //不是汉字
  335.      //分析该汉字串,碰到非汉字时结束
  336. for( i=2 ; (hps[i]&0x80)&&(hps[i+1]&0x80) ; i++ , i++ )
  337. ;
  338. //判断长度是否超出
  339. if( nReturnLen+i+2 > nMaxChinese ) //长度已经超出
  340. {
  341. *lpnChineseLen =nReturnLen ;
  342. return 1 ; //没有到底
  343. }
  344. //长度没有超出,得到该词组
  345. nFlag =1 ; //标记可以加入词组
  346. for( j=1 ; j<nReturnLen ; ) //判断是否已经有词组了
  347. {
  348. for( k=j+2 ; k<nReturnLen ; k+=2 )
  349. if( lpsChinese[k]==' ' )
  350. break ;
  351. if( k>nReturnLen )
  352. break ;
  353. //找到一个词组
  354. if( !hstrncmp( lpsChinese+j , hps , k-j ) ) //相等
  355. {
  356. nFlag =0 ;
  357. break ;
  358. }
  359. j =k+2 ; //跳过空格和下一个标号
  360. }
  361. if( nFlag ) //可以加入该词组
  362. {
  363. if( nReturnLen ) //不是开始,加空格
  364. lpsChinese[nReturnLen++] =' ' ;
  365. lpsChinese[nReturnLen++] =cWordNum++ ; //序号
  366. for( j=0 ; j<i ; j++ )
  367. lpsChinese[nReturnLen++] =hps[j] ;
  368. }
  369. //往下走页指针
  370. OInputLib.m_dwPage +=nItemLen + i ;
  371. OInputLib.m_hpsPage =hps+i ;
  372. //判断是空格结束还是一项结束
  373. if( hps[i+1] & 0x80 ) //是空格结束
  374. continue ;
  375. //判断新的项是否满足要求
  376.     //进行比较
  377. n =hstrncmp( OInputLib.m_hpsPage + 1 , //库中的英文串
  378. (char huge*)lpsEnglish , nEnglishLen ) ;
  379. if( n ) //不相等,说明不可能再匹配,也不能再往下翻了
  380. {
  381. *lpnChineseLen =nReturnLen ;
  382. return 0 ;
  383. }
  384. if( nReturnLen >= nMaxChinese ) //长度到头了
  385. {
  386. *lpnChineseLen =nReturnLen ;
  387. return 1 ;
  388. }
  389. }
  390. *lpnChineseLen =nReturnLen ;
  391. return 0 ; //库结束了
  392. }
  393. //检查输入串的合法性
  394. int __export FAR PASCAL CheckInput( LPCSTR lpsEnglish , 
  395. int nEnglishLen )
  396. {
  397. if( !OInputLib.m_dwLibLen ) //当前没有装入输入法库
  398. {
  399. AfxMessageBox( "还没有装入输入法库!" ) ;
  400. return 0 ;
  401. }
  402. if( nEnglishLen<=0 )
  403. {
  404. AfxMessageBox( "输入串长度不对!" ) ;
  405. return 0 ;
  406. }
  407. int n ;
  408. for( int i=0 ; i<nEnglishLen ; i++ )
  409. {
  410. n =lpsEnglish[i] - START_CODE ;
  411. if( n<0 || n>=CODE_CELL_NUM ) //超出了规定的字符范围
  412. {
  413. // AfxMessageBox( "输入串不合法!" ) ;
  414. return 0 ;
  415. }
  416. //当前输入法没有该字符  
  417. if( !OInputLib.m_lpLibHead->sCodeCells[n] )
  418. return 0 ;
  419. }
  420. return 1 ;
  421. }
  422. //得到有关输入法库的信息
  423. void __export FAR PASCAL GetInputMethodName( LPSTR lpsName , 
  424. int nMaxNameLen )
  425. {
  426. if( !OInputLib.m_hpsLib ) //还没有安装库
  427. {
  428. AfxMessageBox( "还没有安装库呢!请先安装输入法库!" ) ;
  429. *lpsName ='' ;
  430. return ;
  431. }
  432. //长度
  433. int n =min( nMaxNameLen-1 , 
  434. strlen(OInputLib.m_lpLibHead->sName));
  435. _fstrncpy( lpsName , OInputLib.m_lpLibHead->sName , n ) ;
  436. lpsName[n] ='' ; //结束
  437. }
  438. //得到输入法最大输入长度
  439. int __export FAR PASCAL GetInputMethodMaxLen( void )
  440. {
  441. if( !OInputLib.m_hpsLib ) //还没有安装库
  442. {
  443. AfxMessageBox( "还没有安装库呢!请先安装输入法库!" ) ;
  444. return 0 ;
  445. }
  446. return OInputLib.m_lpLibHead->nMaxCodeLen ;
  447. }
  448. //比较两个huge指针所指的字符串
  449. int hstrncmp( char huge *s1 , char huge *s2 , int n )
  450. {
  451. for( int i=0 ; i<n ; i++ )
  452. {                                              
  453. if( s1[i] == s2[i] )
  454. continue ;
  455. if( s1[i] < s2[i] ) //s1比s2小
  456. return -1 ;
  457. return 1 ; //s1比s2大
  458. }
  459. return 0 ; //两者相等
  460. }
  461. #ifdef __cplusplus
  462. }
  463. #endif