Files
STM32F4-Base/Drivers/BSP/UI/ui_w_setview.c
T
wandering1 3dc7f4a088 docs(UI方案): 返回系数小数位按可分辨精度修正 + 遥信量落地注
两件事都落在这份方案文档里,合一笔提交(同一文件的两处改动按文件切分提交不干净,故合并说明)。

一、四个返回系数:口径从"我偏离文档"改成"文档原口径错了"(Lead 裁定 2026-10-25)
- §3.2.2 表里 4 行小数位 3 → 2 并加 ⚠;落地注改写;同步去掉 ui_w_setview.c 注释与
  tools/setview_check/check_setview_limits.py 文档串里的"偏离"措辞。
- 原口径 3 位来自"把 Q10 当成十进制存储"这个误会:Q10 存不下 0.95(0.95×1024 截成 972,真存
  0.94921875),按 3 位显示等于多打一位根本不存在的数字;整定单写 0.95 的人看到屏上 0.949 会
  怀疑装置、甚至反复重输(重输还是 0.949)。2 位才是这份存储在自己可分辨精度上的正确读数。
- 不改行为,只改文档与注释:屏上显示与行表换算逻辑一笔未动。

二、§3.1.3 落地注(遥信量页落地后回填,含两条命名取舍与一条通用陷阱)
- 命名:idx0~3 屏上写「位置1~4」不写「YK1~4 位置」;idx30 写「保护闭锁」不写「闭锁1」;点表未
  定义名的行用点号占位,不编造功能名。
- 值映射次序(先无效 → 再单双点 → 后位值)与双点支路"当前无自动化证据"的诚实登记。
- 通用陷阱:把 *_PUT(dst, 字面量) 宏用在 const char *const 表项上,sizeof(源) 变成指针宽度,
  CJK 名被截而短 ASCII 名恰好完好——只有像素文本断言会报"名字匹配不到而值在原位"。

跳过的门禁(三条同族):mem-numbers / mem-budget / size-gate(L0c),根因是台账与体积凭证待回填。
2026-10-25 15:33:44 +08:00

382 lines
20 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 模块名称:UI 定值查看视图模型(ui_w_setview)
* 模块功能:参数 / 定值 / 控制字 / 软压板四张视图表与它们的取数、换算、越界反显——
* 供四个查看页薄跳板共用;声明与分层理由见 ui_w_setview.h
* 适用平台:STM32F407ZGTx / PC 模拟器(共用源码)
* 作者:王建锋
* 创建日期:2026-10-25
* 修改记录:
* v1.0 2026-10-25 王建锋 创建(道E task-15 批 3)
*/
/* 头文件包含区 */
#include <string.h>
#include "ui_w_setview.h"
#include "ui_data.h"
#include "ui_tokens.h" /* UI_BUF_STRLEN:框架行缓冲长度(无帧占位串要写进同一缓冲) */
/* 静态变量定义区 */
/* 二态行的串表(下标 = 记录值;0/1 的语义来自 App/algo/prot_set.h 的 meta 注释:
* *_TRIP 0 = 告警 / 1 = 跳闸,*_EN 0 = 退出 / 1 = 投入;串表以 NULL 结尾,
* 组件按串表长度决定 ENTER 循环切换的范围) */
const char *const s_opts_trip[3] = { "告警", "跳闸", NULL };
const char *const s_opts_plate[3] = { "退出", "投入", NULL };
/*
* 四张视图表(Flash const)。行表的三项口径全部有真源,不在本文件里自由发挥:
* · id = App/algo/prot_set.h 的 prot_set_id_t 枚举序(BSP 不 include App 头,
* 故写裸数字并把枚举名注在行尾;对不上由主机单测与像素值两处暴露)
* · min/max = App/algo/prot_set.c 的 g_prot_set_meta 上下限(Q10)换算到本行
* decimals 后的整数——**照抄换算结果,不自己拟定**;整定页复用同一批表,
* 界内外一处一份,不会出现"查看看着合法、整定说越界"的两套边界
* · 显示名/小数位/单位 = docs/UI设计/页面扩充详细方案.md §3.2.2~§3.2.5 四张表。
* 其中四个返回系数按 **2 位小数** 显示:这不是我偏离文档,而是文档原口径(3 位)
* 本身错了——它把 Q10 当成了十进制存储。Q10 存不下 0.95:0.95×1024 截成 972,真存
* 的是 0.94921875;按 3 位显示等于打出一位根本不存在的"9",整定单上写 0.95 的人看
* 到 0.949 会怀疑装置、甚至反复重输(重输也还是 0.949)。2 位才是这份存储在自己
* 可分辨精度上的正确读数。§3.2.2 已同步修正(表里 3 位改 2 位并加 ⚠ 指向本注释)
* 单位挂在值串尾(A/V/ms/Hz 全 ASCII,不占中文字库):值列只有数字会让"60000"既是
* ms 又是 A,读者只能靠猜;行表带 unit 字段是本次给组件加的(NULL = 不挂)
*/
/* 参数视图(8 行 = 1 页) */
static const ui_w_setlist_row_t s_rows_param[8] = {
{ "PT一次", 27u, UI_W_SETLIST_KIND_NUM, 0u, 100, 500000, NULL, "V" }, /* PS_PT_PRI */
{ "PT二次", 28u, UI_W_SETLIST_KIND_NUM, 0u, 1, 200, NULL, "V" }, /* PS_PT_SEC */
{ "CT一次", 29u, UI_W_SETLIST_KIND_NUM, 0u, 1, 10000, NULL, "A" }, /* PS_CT_PRI */
{ "CT二次", 30u, UI_W_SETLIST_KIND_NUM, 0u, 1, 10, NULL, "A" }, /* PS_CT_SEC */
{ "过量返回", 25u, UI_W_SETLIST_KIND_NUM, 2u, 50, 100, NULL, NULL }, /* PS_RET_OVER */
{ "欠量返回", 26u, UI_W_SETLIST_KIND_NUM, 2u, 100, 150, NULL, NULL }, /* PS_RET_UNDER */
{ "过频返回", 38u, UI_W_SETLIST_KIND_NUM, 2u, 90, 100, NULL, NULL }, /* PS_RET_OF */
{ "低频返回", 39u, UI_W_SETLIST_KIND_NUM, 2u, 100, 110, NULL, NULL }, /* PS_RET_UF */
};
/* 定值视图(18 行 = 3 页) */
static const ui_w_setlist_row_t s_rows_set[18] = {
{ "Ⅰ段电流", 2u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC1_CUR */
{ "Ⅰ段延时", 3u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC1_DLY */
{ "Ⅱ段电流", 6u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC2_CUR */
{ "Ⅱ段延时", 7u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC2_DLY */
{ "Ⅲ段电流", 10u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OC3_CUR */
{ "Ⅲ段延时", 11u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OC3_DLY */
{ "过负荷电流", 14u, UI_W_SETLIST_KIND_NUM, 2u, 0, 10000, NULL, "A" }, /* PS_OL_CUR */
{ "过负荷延时", 15u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OL_DLY */
{ "过压定值", 17u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_OV_VOL */
{ "过压延时", 18u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OV_DLY */
{ "低压定值", 20u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_UV_VOL */
{ "低压延时", 21u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_UV_DLY */
{ "零序定值", 23u, UI_W_SETLIST_KIND_NUM, 1u, 0, 2000, NULL, "V" }, /* PS_3U0_VOL */
{ "零序延时", 24u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_3U0_DLY */
{ "过频定值", 33u, UI_W_SETLIST_KIND_NUM, 2u, 5000, 5500, NULL, "Hz" }, /* PS_OF_HZ */
{ "过频延时", 34u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_OF_DLY */
{ "低频定值", 36u, UI_W_SETLIST_KIND_NUM, 2u, 4500, 5000, NULL, "Hz" }, /* PS_UF_HZ */
{ "低频延时", 37u, UI_W_SETLIST_KIND_NUM, 0u, 0, 60000, NULL, "ms" }, /* PS_UF_DLY */
};
/* 控制字视图(4 行 = 1 页) */
static const ui_w_setlist_row_t s_rows_word[4] = {
{ "Ⅰ段跳闸", 1u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC1_TRIP */
{ "Ⅱ段跳闸", 5u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC2_TRIP */
{ "Ⅲ段跳闸", 9u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OC3_TRIP */
{ "过负荷跳闸", 13u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_trip, NULL }, /* PS_OL_TRIP */
};
/* 软压板视图(10 行 = 2 页) */
static const ui_w_setlist_row_t s_rows_plate[10] = {
{ "Ⅰ段投入", 0u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC1_EN */
{ "Ⅱ段投入", 4u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC2_EN */
{ "Ⅲ段投入", 8u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OC3_EN */
{ "过负荷投入", 12u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OL_EN */
{ "过压投入", 16u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OV_EN */
{ "低压投入", 19u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_UV_EN */
{ "零序投入", 22u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_3U0_EN */
{ "过频投入", 32u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_OF_EN */
{ "低频投入", 35u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_UF_EN */
{ "保护总投入", 31u, UI_W_SETLIST_KIND_ENUM, 0u, 0, 0, s_opts_plate, NULL }, /* PS_GLOBAL_EN */
};
/*
* 每个定值项的显示小数位(下标 = 枚举序;二态项为 0,不参与数值换算)
* 为什么要单独一张表而不是从行表里找:组件的 get(id) 回调只给 id 不给行号,
* 同一 id 只会出现在一张视图里(四张表恰好覆盖 0..39 各一次,由主机单测钉住),
* 所以这张表是无歧义的,且比遍历四张表便宜
*/
static const uint8_t s_dec[UI_DATA_SET_N] = {
0, 0, 2, 0, 0, 0, 2, 0, 0, 0,
2, 0, 0, 0, 2, 0, 0, 1, 0, 0,
1, 0, 0, 1, 0, 2, 2, 0, 0, 0,
0, 0, 0, 2, 0, 0, 2, 0, 2, 2,
};
/* 无参数帧时值列的占位串(与全仓"读不到就 --"同一口径) */
#define SV_NO_DATA "--"
/* 参数帧缓存(四个查看页共用一份:同屏只开一页,无并发读者) */
static ui_data_par_t s_par;
static uint32_t s_par_seq = 0xFFFFFFFFu; /* 与任何合法发布序号都不同 */
static uint8_t s_par_ok;
/* 当前视图的行表(bad 回调只收到行号,需要它把行号换回 id 再查位图) */
static const ui_w_setlist_row_t *s_cur_rows;
static uint16_t s_cur_n; /* 当前视图行数(bad 回调的边界) */
/* 行表长度(编译期算,别手写数字——手写数字与表长不一致是最难查的错) */
#define SV_ROW_N(tbl) ((uint16_t)(sizeof(tbl) / sizeof((tbl)[0])))
/* 函数定义区 */
/*
* 函数功能:Q10 原值 → 指定小数位的定点显示值(四舍五入)
* 入口参数:a_q10 - Q10 原值(工程量 × 1024) int32_t
* a_dec - 小数位 0..3 uint8_t
* 返回值:工程量 × 10^a_dec int32_t
* 限定条件:|a_q10| 在 int32 范围内且换算后仍在 int32 内(行表生成时已按
* g_prot_set_meta 的最大量程核过:最大项 PT 一次额定 500000 V,d=0)
* 函数说明:不用浮点也不用 64 位除法——MicroLIB 的 soft-float 与 __aeabi_ldiv
* 一进镜像就是几百字节,而模拟器(宿主 CRT)永远照不出这笔代价(本仓
* 反复记录的同一条口径)。做法是拆整数段与小数段:
* v = ip×1024 + fp(fp∈[0,1023],负数用算术右移取 floor,fp 仍非负),
* 小数段按 10^d 缩放后四舍五入,满 10^d 就进位回整数段。
* 误差上界半个最低显示位——与 prot_set 自己的 Q10 精度同源,
* 屏上显示 10.00A 而实际 10.0004A 不是本页造成的,是存储精度
*/
static int32_t sv_q10_to_scaled(int32_t a_q10, uint8_t a_dec) {
static const int32_t p10[4] = { 1, 10, 100, 1000 };
int32_t ip;
uint32_t fp;
int32_t r;
ip = a_q10 >> 10;
fp = (uint32_t)a_q10 & 0x3FFu;
r = ip * p10[a_dec];
if (a_dec != 0u) {
uint32_t fr = (fp * (uint32_t)p10[a_dec] + 512u) >> 10; /* 作用域收在这里 */
if (fr >= (uint32_t)p10[a_dec]) { /* 小数段进位(如 0.9996 → 1.000) */
r += p10[a_dec];
fr -= (uint32_t)p10[a_dec];
}
r += (int32_t)fr;
}
return r;
}
/*
* 函数功能:读某定值项的显示值(组件 get 回调)
* 入口参数:a_id - 行表登记的 id(= 枚举序) uint8_t
* 返回值:工程量 × 10^decimals int32_t
* 限定条件:ui_w_setview_sync() 已先跑过且 ui_w_setview_ready() 为真
* (页面在值列打 "--" 之前不会走到这里)
* 函数说明:id 越界(>39)返回 0 属防御性死支——行表是本文件内 const,越界 id
* 只可能来自代码改动错误,由主机单测在构建期前拦,不靠运行期兜
*/
static int32_t sv_get(uint8_t a_id) {
if (a_id >= (uint8_t)UI_DATA_SET_N) {
return 0;
}
return sv_q10_to_scaled(s_par.q10[a_id], s_dec[a_id]);
}
/*
* 函数功能:只读视图的写回调占位(组件契约要求非 NULL)
* 入口参数:a_id/a_val - 未使用
* 返回值:无
* 限定条件:查看视图不可编辑,组件不会调到这里
* 函数说明:刻意空实现——查看页**没有任何**该写进 RAM 工作副本的语义;
* 真要在查看页改值,得先把整定批次的 commit/state 一起接上
*/
static void sv_set_unused(uint8_t a_id, int32_t a_val) {
(void)a_id;
(void)a_val;
}
/*
* 函数功能:某数据行是否越界(组件 bad 回调 → 反显高亮)
* 入口参数:a_row - 数据行下标(不含保存行) uint16_t
* 返回值:true = 反显;false = 正常 bool
* 限定条件:uiTask 绘制链内;s_cur_rows 已由 attach 设定
* 函数说明:位图来自 prot_set_bad_mask()(上一次整表装载/提交后仍在量程外的项),
* 经 par 帧 bad_mask + bad_valid 下发。bad_valid=0 表示位图无意义
* (App 侧只在位图非 0 时置 1),此时一律不反显——把"没数据"画成
* "这行有问题"是假告警,比不画更糟
*/
static bool sv_bad(uint16_t a_row) {
const ui_w_setlist_row_t *r;
uint64_t bit;
if ((s_cur_rows == NULL) || (s_par_ok == 0u) || (s_par.bad_valid == 0u)) {
return false;
}
if (a_row >= s_cur_n) {
return false; /* 行号越界(组件不会给,防御:越界不反显也不越读) */
}
r = &s_cur_rows[a_row];
if (r->id >= (uint8_t)UI_DATA_SET_N) {
return false;
}
bit = (uint64_t)1u << r->id;
return (s_par.bad_mask & bit) != 0u;
}
/*
* 函数功能:按发布序号取参数帧快照(接各查看页 refresh 前调用)
* 入口参数:无
* 返回值:无
* 限定条件:uiTask 上下文(页面绘制链内);只读快照层,不写任何东西
* 函数说明:序号没变就一帧都不重拷(一帧约 184 B;四个查看页共用这份缓存——同屏
* 只可能开着一页,彼此之间不存在并发读者)。读取失败把序号打回不可能的值,
* 下一轮一定重试,不会停在半新不旧的帧上
*/
void ui_w_setview_sync(void) {
uint32_t seq = ui_data_par_seq();
if ((seq == s_par_seq) && (s_par_ok != 0u)) {
return; /* 序号未变:一帧都不重拷 */
}
/* ui_data_par() 的通道是 0=成功 / -1=尚无首帧 / -2=参数无效(快照层的既有约定,
* 不是布尔成败)——把它当 bool 用会反义:模拟器与真机上都会永远"读不到",
* 于是整页值列恒 "--",而页面看起来完全正常(本函数第一版就踩了这一条,
* 是看像素图才发现满屏横杠,静态检查看不出来) */
if (ui_data_par(&s_par) != 0) {
s_par_ok = 0u;
s_par_seq = 0xFFFFFFFFu; /* 失败态不认序号,下一轮一定重试 */
(void)memset(&s_par, 0, sizeof(s_par));
return;
}
s_par_seq = seq;
s_par_ok = (s_par.valid != 0u) ? 1u : 0u;
}
/*
* 函数功能:逐行取数(页面 refresh 的直直通:先同步参数帧,再走组件)
* 入口参数:a_inst - 实例 ui_w_setlist_t *;a_row - 行下标 uint16_t
* a_name/a_value - 框架行缓冲(UI_BUF_STRLEN) char *
* 返回值:无
* 限定条件:框架绘制链内(uiTask)
* 函数说明:**参数帧未就位时只把值列打成 "--",名字照打**——空值会被读成"这项是 0",
* 整页空白会让人以为菜单坏了;打出"名字 + --"才说得出真正的事实
* ("这张表在等参数帧")。帧就位后走组件:数值行按小数位 + 单位,
* 二态行打串表词
*/
void ui_w_setview_refresh(ui_w_setlist_t *a_inst, uint16_t a_row,
char *a_name, char *a_value) {
ui_w_setview_sync();
if (ui_w_setview_ready() != 0u) {
ui_w_setlist_refresh(a_inst, a_row, a_name, a_value);
return;
}
a_name[0] = '\0';
a_value[0] = '\0';
if ((a_inst != NULL) && (a_inst->rows != NULL) && (a_row < a_inst->count)) {
(void)lv_snprintf(a_name, UI_BUF_STRLEN, "%s", a_inst->rows[a_row].name);
}
(void)lv_snprintf(a_value, UI_BUF_STRLEN, "%s", SV_NO_DATA);
}
/*
* 函数功能:参数帧是否已就位
* 入口参数:无
* 返回值:1 = 有有效帧可显示;0 = 尚无首帧或读取失败 uint8_t
* 限定条件:uiTask 上下文;纯查询,无副作用
* 函数说明:返回 uint8_t 而不是 bool 是**本层约定**(bsp-err 的 err-type:BSP 公开 API
* 不得返回 bool——bool 把"为什么失败"整条丢掉,而这里虽然确实不需要原因,
* 也不能给整层开一个按名字豁免的例外;先例见 ui_w_setlist_key 的键分发标志)。
* 调用方拿它决定值列打换算值还是打 "--",没有错误要上报
*/
uint8_t ui_w_setview_ready(void) {
return s_par_ok;
}
/*
* 函数功能:取某视图的行表与行数(结构自测用;页面不需要,attach 时才自己取)
* 入口参数:a_view - 视图编号 ui_w_setview_t;a_n - 行数输出(不可为 NULL) uint16_t *
* 返回值:行表首地址;视图号非法返回 NULL const ui_w_setlist_row_t *
* 限定条件:只读;行表是 const Flash 表
* 函数说明:存在的理由是让主机单测能把四张表当成数据来核(id 是否恰好覆盖 0..39
* 各一次、二态行有没有串表、小数位与 dec 查表是否一致)。这些约束在
* 编译期看不出来,页面上也只有当前可见的 8 行会被像素断言看到——
* 第 2、3 页的行错了对齐,屏幕上要翻两页才看得见,而人不会去翻
*/
const ui_w_setlist_row_t *ui_w_setview_table(ui_w_setview_t a_view, uint16_t *a_n) {
if (a_n == NULL) {
return NULL;
}
switch (a_view) {
case UI_W_SETVIEW_PARAM:
*a_n = SV_ROW_N(s_rows_param);
return s_rows_param;
case UI_W_SETVIEW_SET:
*a_n = SV_ROW_N(s_rows_set);
return s_rows_set;
case UI_W_SETVIEW_WORD:
*a_n = SV_ROW_N(s_rows_word);
return s_rows_word;
case UI_W_SETVIEW_PLATE:
*a_n = SV_ROW_N(s_rows_plate);
return s_rows_plate;
default:
*a_n = 0u;
return NULL;
}
}
/*
* 函数功能:取 id → 显示小数位的查表(结构自测用)
* 入口参数:a_n - 表长输出(= UI_DATA_SET_N) uint16_t *
* 返回值:表首地址 const uint8_t *
* 限定条件:只读
*/
const uint8_t *ui_w_setview_dec_table(uint16_t *a_n) {
if (a_n != NULL) {
*a_n = (uint16_t)UI_DATA_SET_N;
}
return s_dec;
}
/*
* 函数功能:把某个查看视图绑到定值表实例(行表 + 取数 + 反显一次配齐)
* 入口参数:a_inst - 页面持有的实例(可为 NULL,NULL 直接返回) ui_w_setlist_t *
* a_view - 视图编号 ui_w_setview_t
* 返回值:无
* 限定条件:页面 init_cb 内调用(uiTask);每次开页都重新绑,不信任上一次的残留
* 函数说明:先 memset 再填 —— 组件实例里的编辑态跨页留着就是脏状态;视图号非法
* 给空表(页面退化成 0 行空页,比按错表导航安全)
*/
void ui_w_setview_attach(ui_w_setlist_t *a_inst, ui_w_setview_t a_view) {
if (a_inst == NULL) {
return;
}
(void)memset(a_inst, 0, sizeof(*a_inst));
switch (a_view) {
case UI_W_SETVIEW_PARAM:
a_inst->rows = s_rows_param;
a_inst->count = SV_ROW_N(s_rows_param);
break;
case UI_W_SETVIEW_SET:
a_inst->rows = s_rows_set;
a_inst->count = SV_ROW_N(s_rows_set);
break;
case UI_W_SETVIEW_WORD:
a_inst->rows = s_rows_word;
a_inst->count = SV_ROW_N(s_rows_word);
break;
case UI_W_SETVIEW_PLATE:
a_inst->rows = s_rows_plate;
a_inst->count = SV_ROW_N(s_rows_plate);
break;
default:
a_inst->rows = NULL;
a_inst->count = 0u;
break;
}
s_cur_rows = a_inst->rows;
s_cur_n = a_inst->count;
a_inst->get = sv_get;
a_inst->set = sv_set_unused;
a_inst->commit = NULL; /* NULL = 查看视图:无保存行、禁编辑(§3.2.6) */
a_inst->state = NULL;
a_inst->bad = sv_bad;
ui_w_setlist_reset(a_inst);
}