AWTK T9 输入法实现原理

在这里插入图片描述
在这里插入图片描述

1. T9 输入法的中文字典数据

网上可以找到 T9 输入法的中文字典数据,但是通常有两个问题:

  • 采用 GPL 协议,不太适合加入 AWTK。

  • 只支持单个汉字的输入,不支持词组的输入。

经过考虑之后,决定自己生成 T9 输入法的中文字典数据。AWTK 使用了谷歌拼音输入法作为缺省的拼音输入法,谷歌拼音输入法的字典数据质量还是不错的,写一个工具把谷歌拼音输入法的字典数据转换为 T9 输入法的中文字典数据即可。

谷歌拼音输入法的字典数据原始格式为:

汉字 频率 简体/繁体标志 拼音

如:

中 243213.912993 0 zhong

转换工具要做的事情的是:

  • 把拼音转换成对应的数字。比 zhong 对应的是 83553。

  • 生成适合查询的格式。本来想复用谷歌拼音输入的引擎,但是没有成功,最后决定自己写程序来查询。

转换工具完整的代码请参考:awtk/tools/t9_gen/to_t9_zh.js

如果需要对字典进行裁剪,可以先编辑原始数据,然后重新生成数据。

2. T9 输入法的英文字典数据

要生成英文字典数据,获取一个英文单词列表,并且按照单词的使用频率进行排序。找 github 上找到了这样的数据。

同样需要写个小工具,把该数据转成生成适合查询的格式。

转换工具完整的代码请参考:awtk/tools/t9_gen/to_t9_en.js

该工具应该同样适用于其它西文语言。

3. 对键盘、输入法框架和编辑器进行改进

为了支持 T9 输入法,需要对键盘、输入法框架和编辑器进行改进。

随便提一下,SOLID 原则中的开闭原则通常只存在于理想(简单)情况下,一种切实可行的方法是,在早期设计时要考虑将来的扩展,但也无需过度设计,而是每次扩展时都对框架进行完善,让它更适应于将来的扩展。

3.1 支持语言切换

同样是在中文环境下,你可能需要输入中文,也可能需要输入英文。在中文键盘下输入中文,在英文键盘下输入英文。 在键盘切换时需要让输入法引擎知道当前的语言。

3.1.1 键盘

如果需要切换语言,可以给键盘的页面设置一个 lang 属性,用于标识改键盘的语言,切换到该页面时,自动设置输入法引擎的语言。

如:

    <view name="chinese" lang="zh_cn" x="0" y="0" w="100%" h="100%" children_layout="default(r=4,c=4,s=2,m=2)"><button repeat="300" name="" text=""/><button repeat="300" name="key:1" text="ABC"/><button repeat="300" name="key:2" text="DEF"/><button repeat="300" name="key:backspace" style="highlight"><image draw_type="icon" image="backspace" x="center" y="middle" w="100%" h="100%"/></button><button repeat="300" name="key:3" text="GHI"/><button repeat="300" name="key:4" text="JKL"/><button repeat="300" name="key:5" text="MNO"/><button name="page:lower" style="highlight" text="abc"/><button repeat="300" name="key:6" text="PQRS"/><button repeat="300" name="key:7" text="TUV"/><button repeat="300" name="key:8" text="WXYZ"/><button name="page:symbols" style="highlight" text="#+="/><button repeat="300" name="opt:。?!" text="。?!"/><button repeat="300" name="space" text="Space"/><button name="action" style="highlight" text="Return"/><button name="page:number" style="highlight" text="123"/></view>

在切换键盘时,如果存在 lang 属性,将其设置到输入法。

    value_t v;widget_t* active = widget_get_child(iter, widget_get_value(iter));if (widget_get_prop(active, WIDGET_PROP_IM_LANG, &v) == RET_OK) {input_method_set_lang(input_method(), value_str(&v));}
3.1.2 输入法提供设置语言的函数
/*** @method input_method_set_lang* 设置语言。** > 有的输入法,同时支持输入多种语言。* > 比如 T9,可以同时支持中文和英文输入,配合软键盘随时切换输入的语言。** @annotation ["scriptable"]* @param {input_method_t*} im 输入法对象。* @param {const char*} lang 语言。** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t input_method_set_lang(input_method_t* im, const char* lang);
3.1.3 输入法引擎提供设置语言的函数
/*** @engine input_engine_set_lang* 设置语言。* @annotation ["scriptable"]* @param {input_engine_t*} engine 输入法引擎对象。* @param {const char*} lang 语言。** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t input_engine_set_lang(input_engine_t* engine, const char* lang);

3.2 支持预编辑状态 (preedit)

预编辑状态是在文本真正提交到编辑器之前的状态,在预编辑状态下输入的文本,可以被后面的输入覆盖。比如软键盘上,一个按键有 ABC 三个字符,按一下输入 A,再按一下输入 B,继续按钮输入 C,在指定时间内没有按,则提交当前的字符到编辑器。

在这里插入图片描述

3.2.1 软键盘

键盘的按钮名称以"opt:"开头的按钮,表示这个按钮需要预编辑处理。为了支持预编辑输入,软键盘在按钮事件处理函数中,要做下列处理:

  • 当前不在预编辑状态时,则进入预编辑状态,并启动定时器,把当前字符的序数设置为 0,并提交字符到编辑器。

  • 当前在预编辑状态,更新定时器,把字符的序数设置为下一个,并提交字符到编辑器。

  • 定时器超时或点击其它按钮,退出预编辑。

详情参考函数:keyboard_on_button_click

3.2.2 输入法

输入法需要提供几个函数用于中转消息:

/*** @method input_method_dispatch_preedit* 分发进入预编辑状态的事件。* @annotation ["scriptable"]* @param {input_method_t*} im 输入法对象。** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t input_method_dispatch_preedit(input_method_t* im);/*** @method input_method_dispatch_preedit_confirm* 分发确认预编辑状态的事件(提交预编辑内容,退出预编辑状态)。* @annotation ["scriptable"]* @param {input_method_t*} im 输入法对象。** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t input_method_dispatch_preedit_confirm(input_method_t* im);/*** @method input_method_dispatch_preedit_abort* 分发取消预编辑状态的事件(提交预编辑内容,退出预编辑状态)。* @annotation ["scriptable"]* @param {input_method_t*} im 输入法对象。** @return {ret_t} 返回 RET_OK 表示成功,否则表示失败。*/
ret_t input_method_dispatch_preedit_abort(input_method_t* im);
3.2.3 编辑器

编辑器需要处理相关事件:

    case EVT_IM_PREEDIT: {text_edit_preedit(edit->model);break;}case EVT_IM_PREEDIT_CONFIRM: {text_edit_preedit_confirm(edit->model);break;}case EVT_IM_PREEDIT_ABORT: {text_edit_preedit_abort(edit->model);break;}

具体请参考:edit.c/mledit.c

4. T9 输入法引擎的实现

T9 输入法引擎的实现很简单,不到 300 行代码。查找算法为:先精确查找,如果找到,将其添加到候选字列表中,否则使用前缀查找,在满足前缀的候选字中,挑选词频最高的,放到候选字列表中。

详情参考:input_engine_t9.c/t9.c

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/767368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mamba复现与代码解读

文章目录 环境配置demo推理源码解析参数解读Mamba块&#xff08;Mamba Block&#xff09;状态空间模型(SSM)选择性扫描算法&#xff08;selective_scan&#xff09;前向传播&#xff08;forward&#xff09; 均方根归一化 &#xff08;RMSNorm&#xff09;残差块&#xff08;Re…

集成学习 | 集成学习思想:Boosting

目录 一. Boosting思想1. Adaboost 算法1.1 Adaboost算法构建流程1.2 sklearn库参数说明 2. Gradient Boosting 算法2.1 Gradient Boosting算法构建流程2.2 Gradient Boosting算法的回归与分类问题2.2.1 Gradient Boosting回归算法均方差损失函数绝对误差损失函数 2.2.2 Gradie…

CAS(Compare-And-Swap)机制介绍

一、概念介绍 CAS&#xff08;Compare-And-Swap&#xff09;机制在C中是一种用于实现并发编程中同步和互斥的重要技术。CAS机制提供了一种原子操作&#xff0c;允许程序在不使用锁的情况下对共享变量进行读取、修改和写入。这种机制的核心思想是先比较再设置&#xff0c;即在修…

理论学习:ground-truth labels在深度学习中是什么意思

在深度学习中&#xff0c;"ground-truth labels"&#xff08;真值标签&#xff09;是指数据集中每个样本的正确答案或真实状态。这些标签是由人类专家提供的&#xff0c;代表了我们希望模型学习预测的准确结果。在训练深度学习模型时&#xff0c;真值标签被用作参照点…

【Linux】进程地址空间详解

前言 在我们学习C语言或者C时肯定都听过老师讲过地址的概念而且老师肯定还会讲栈区、堆区等区域的概念&#xff0c;那么这个地址是指的物理内存地址吗&#xff1f;这里这些区域又是如何划分的呢&#xff1f; 我们在使用C语言的malloc或者C的new函数开辟空间时&#xff0c;开辟…

Median of an Array(贪心策略,编程技巧)

文章目录 题目描述输入格式输出格式样例输入样例输出提交链接提示 解析参考代码 题目描述 给你一个由 n n n 个整数组成的数组 a a a 。 数组 q 1 , q 2 , … , q k q_1,q_2,…,q_k q1​,q2​,…,qk​ 的中位数是 p ⌈ k 2 ⌉ p⌈\frac {k}{2}⌉ p⌈2k​⌉ &#xff0c;其…

可解释性AI(XAI)

可解释性AI&#xff08;XAI&#xff09;旨在提高人工智能系统的透明度和可理解性&#xff0c;使人们更好地理解AI的决策过程和原理。随着AI技术的广泛应用&#xff0c;XAI成为了一个备受关注的重要领域。它不仅有助于建立人们对AI的信任&#xff0c;还可以帮助解决AI伦理和偏见…

解锁隐私计算力量:一站式掌握SecretFlow安装与双模式部署实践

1.SecretFlow的安装 1.SecretFlow运行要求 SecretFlow作为一个隐私保护的数据分析和机器学习框架&#xff0c;其运行要求可能涉及以下方面&#xff1a; 操作系统&#xff1a; 能够支持Docker运行的环境&#xff0c;因为SecretFlow可能通过Docker容器来管理执行环境的一致性和…

Python Flask 自定义404错误

from flask import Flask, abort, make_response, request, render_templateapp Flask(__name__)# 重定向到百度 app.route(/index, methods["GET", "POST"]) def index():if request.method "GET":return render_template("index.html&q…

敏捷开发最佳实践:组织架构实践案例之构建软硬件融合部落

本节所选案例对于软硬件均有的企业具有重要借鉴意义&#xff0c;通过学习某一线制造行业合资企业如何解决软硬件部门之间的技术鸿沟和部门墙&#xff0c;以及全球分布的多支敏捷团队的协作难题&#xff0c;为所在企业在“组织架构”层面进行有效敏捷实践打开思路。 本实践节选…

推荐一款制造执行系统(MES)国内比较好的实施厂家

什么是MES 制造执行系统&#xff08;MES&#xff09;是一种用于监控、控制和优化制造过程的软件系统。它通过与企业资源计划&#xff08;ERP&#xff09;系统和自动化系统的集成&#xff0c;实现对生产过程的管理和监测&#xff0c;包括生产计划、生产过程和生产数据。 MES可…

小白入门赛8

小白入门赛8 1 #include<bits/stdc.h> using namespace std;int main(){puts("5060");return 0; } 2 只考虑两个字符串a&#xff0c;b的情况下&#xff0c;优先让 a b ab ab 或 b a ba ba 中最小的放前面&#xff0c;据此排序 int n; string s[200010]…

BUG未解之谜01-指针引用之谜

在leetcode里面刷题出现的问题&#xff0c;当我在sortedArrayToBST里面给root赋予初始值NULL之后&#xff0c;问题得到解决&#xff01; 理论上root是未初始化的变量&#xff0c;然后我进入insert函数之后&#xff0c;root引用的内容也是未知值&#xff0c;因此无法给原来的二叉…

鸿蒙开发学习【地图位置服务组件】

简介 移动终端设备已经深入人们日常生活的方方面面&#xff0c;如查看所在城市的天气、新闻轶事、出行打车、旅行导航、运动记录。这些习以为常的活动&#xff0c;都离不开定位用户终端设备的位置。 当用户处于这些丰富的使用场景中时&#xff0c;系统的位置定位能力可以提供…

map 添加 访问 遍历

#include<iostream> #include<vector> #include<set> #include<map> using namespace std; int main() { //创建 map<string, int>m; //添加 m["hello"] 2; m["ijii"] 1; //访问 如果存在返回值,不…

[HackMyVM]靶场 Submissions

kali:192.168.56.104 靶机:192.168.56.131 端口扫描 # nmap 192.168.56.131 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-03-24 11:32 CST Nmap scan report for 192.168.56.131 Host is up (…

【Python】基础语法(一)

文章目录 1.注释2.关键字与标识符2.1关键字2.2标识符 3.变量4.数据类型4.1数字类型4.2类型转换函数4.3布尔类型 5.输入(input)与输出(print)5.1输入函数(input)5.2输出函数(print) 6.运算符6.1算术运算符6.2比较运算符6.3赋值运算符6.4逻辑运算符6.5运算符优先级 7.字符串7.1字…

JMH微基准测试框架学习笔记

一、简介 JMH&#xff08;Java Microbenchmark Harness&#xff09;是一个用于编写、构建和运行Java微基准测试的框架。它提供了丰富的注解和工具&#xff0c;用于精确控制测试的执行和结果测量&#xff0c;从而帮助我们深入了解代码的性能特性。 二、案例实战 在你的pom文件…

MySQL 排序的那些事儿

书接上回 上次发了几张图&#xff0c;给了几个MySQL Explain的场景&#xff0c;链接在这儿&#xff1a;你是不是MySQL老司机&#xff1f;来看看这些explain结果你能解释吗&#xff1f;MySQL 夺命6连问 我们依次来分析下这6个问题。 在分析之前&#xff0c;我们先来了解一下M…

【C++】学习记录--condition_variable 的使用

condition_variable使用步骤如下&#xff1a;创建一个condition_variable对象创建一个互斥锁mutex对象&#xff0c;用来保护共享资源的访问在需要等待条件变量的地方&#xff0c;使用unique_lock<mutec>对象锁定互斥锁并调用condition_variable::wait()、condition_varia…