From c187b7bce376a83c2fcc8905de83c05e8979d0c1 Mon Sep 17 00:00:00 2001 From: MeowOS Date: Mon, 31 Aug 2026 04:03:56 +0800 Subject: [PATCH] =?UTF-8?q?feat(files):=20=E6=96=B0=E5=A2=9E=E5=A4=96?= =?UTF-8?q?=E7=BD=AE=E7=B3=BB=E7=BB=9F=E6=96=87=E4=BB=B6=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=99=A8=20os.meow.files=20(agent-183)=20=E2=80=94=20=E7=9B=AE?= =?UTF-8?q?=E5=BD=95=E6=B5=8F=E8=A7=88(=E8=99=9A=E6=8B=9F=E5=8C=96?= =?UTF-8?q?=E5=88=97=E8=A1=A8/=E7=A9=BA=E6=80=81)+=E6=96=87=E6=9C=AC?= =?UTF-8?q?=E9=A2=84=E8=A7=88(=E2=89=A4256KB=E6=88=AA=E6=96=AD)+=E5=88=A0?= =?UTF-8?q?=E9=99=A4/=E9=87=8D=E5=91=BD=E5=90=8D/=E6=96=B0=E5=BB=BA/?= =?UTF-8?q?=E5=B1=9E=E6=80=A7(BottomSheet+IME)=EF=BC=9B=E8=B7=AF=E5=BE=84?= =?UTF-8?q?=E5=86=99=E6=93=8D=E4=BD=9C=E9=99=90=20TF=20=E5=8D=A1=E5=86=85(?= =?UTF-8?q?=E6=8B=92=20..=20=E8=B6=8A=E7=95=8C)=EF=BC=9B=E5=A4=9A=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BB=93=E6=9E=84(app.c+ui/{browser,viewer}.c+ui/comm?= =?UTF-8?q?on/chrome.c+logic/fsx.c)=20=E6=8C=89=E6=89=B9=E6=AC=A1=E2=91=A1?= =?UTF-8?q?=E8=8C=83=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit files md5 6f6b0a6d; 0 warning; 宿主 test_fsx 全过(路径安全/格式化/排序/虚拟化/写操作/文本嗅探); qemu 离屏冒烟通过 SDK 缺口记录: listview 仅单行 label(本 App 用 custom 画布自绘行); common 档字库中文缺字(未声明 fonts:full) 真机待验证: 列表渲染/滚动手感/IME 重命名/弹窗交互 --- patch_v2/files_app/README.md | 87 +++++ patch_v2/files_app/app.c | 106 ++++++ patch_v2/files_app/app.json | 1 + patch_v2/files_app/build_files.sh | 16 + patch_v2/files_app/files | Bin 0 -> 270364 bytes patch_v2/files_app/files_internal.h | 74 ++++ patch_v2/files_app/logic/fsx.c | 280 ++++++++++++++ patch_v2/files_app/logic/fsx.h | 118 ++++++ patch_v2/files_app/test/test_fsx.c | 217 +++++++++++ patch_v2/files_app/ui/browser.c | 504 ++++++++++++++++++++++++++ patch_v2/files_app/ui/common/chrome.c | 57 +++ patch_v2/files_app/ui/viewer.c | 281 ++++++++++++++ 12 files changed, 1741 insertions(+) create mode 100644 patch_v2/files_app/README.md create mode 100644 patch_v2/files_app/app.c create mode 100644 patch_v2/files_app/app.json create mode 100755 patch_v2/files_app/build_files.sh create mode 100755 patch_v2/files_app/files create mode 100644 patch_v2/files_app/files_internal.h create mode 100644 patch_v2/files_app/logic/fsx.c create mode 100644 patch_v2/files_app/logic/fsx.h create mode 100644 patch_v2/files_app/test/test_fsx.c create mode 100644 patch_v2/files_app/ui/browser.c create mode 100644 patch_v2/files_app/ui/common/chrome.c create mode 100644 patch_v2/files_app/ui/viewer.c diff --git a/patch_v2/files_app/README.md b/patch_v2/files_app/README.md new file mode 100644 index 0000000..e83ecf0 --- /dev/null +++ b/patch_v2/files_app/README.md @@ -0,0 +1,87 @@ +# os.meow.files — MeowOS 外置文件管理器 + +TF 卡应用(`framework=1` 走 `meow_ui` SDK)。浏览 TF 卡目录树,支持进/退目录、列表虚拟化、 +行操作(删除/重命名/新建目录/属性)、文本预览(≤256KB 截断)、空态/错误页;写操作严格限制在 +TF 卡内(`/usr/data/mnt/sd_0`),拒绝 `..` 越界与卡外路径。 + +## 目录结构(多文件,批次②拆分范本) + +``` +patch_v2/files_app/ +├── app.c # main + 装配 + 事件分发(key/tap/swipe/tick/touch → 当前页) +├── files_internal.h # 跨 TU 共享头(Activity id / 布局 / chrome/browser/viewer 声明) +├── build_files.sh # 交叉编译脚本(zig-mipsel-cc 静态链 meow_ui.a libz.a -lpthread) +├── app.json # {"name":"Files","exec":".../os.meow.files/files",...,"framework":1,"immersive":1} +├── README.md +├── ui/ +│ ├── browser.c # 目录浏览页(ACT_BROWSER 根页):虚拟化列表 + 空态 + 行操作 +│ ├── viewer.c # 文本预览页(ACT_VIEWER 子页):只读、可滚动、≤256KB 截断 +│ └── common/ +│ └── chrome.c # 共享 chrome:topbar 建置 / 内容区几何 / 空态&页脚绘制 +├── logic/ +│ ├── fsx.h # 纯业务接口(不依赖 meow_ui) +│ └── fsx.c # 路径安全/格式化/枚举排序/虚拟化区间/写操作(可宿主测) +└── test/ + └── test_fsx.c # 宿主单元自测(gcc 直接编,指向临时卡根) +``` + +## 构建 + +```bash +cd patch_v2/files_app && ./build_files.sh +# 产物:files(MIPS32r2 静态 ELF,~270KB)+ ./files + app.json +``` + +构建脚本仿 `hello_app/build_hello.sh`:`zig-mipsel-cc -Os -static -Wall -Wextra -I../sdk -I.` +链 `../sdk/meow_ui.a "$SYSROOT/lib/libz.a" -lpthread`。**零触及 `patch_v2/sdk/`**(未新增/改任何 SDK 文件); +`-Wall -Wextra` 0 warning。 + +## 部署 + +``` +/usr/data/mnt/sd_0/MeowAPPs/os.meow.files/ +├── app.json +└── files +``` + +数据目录 `MeowData/os.meow.files/{data,cache}` 由 launcher 经 `MEOW_DATA_DIR`/`MEOW_CACHE_DIR` 注入; +v1 无需持久化,暂未使用(启动恒进卡根 `/usr/data/mnt/sd_0/`)。 + +## 宿主自测(不跨编/不刷机) + +```bash +cd patch_v2/files_app +gcc -O2 -Wall -Wextra -DFSX_SD_ROOT='"/tmp/meowfsx_fsx_test"' -Ilogic \ + test/test_fsx.c logic/fsx.c -o /tmp/test_fsx && /tmp/test_fsx +``` + +覆盖:路径安全(`within_sd`/`join`/`sanitize`/`dirname`/`basename`)、展示格式化(`fmt_size`/`fmt_time`)、 +目录枚举排序(`scan_dir`/`sort`)、虚拟化区间(`visible_range`/`max_scroll`)、写操作(`mkdir`/`rename`/ +`delete`,含卡外/越界拒绝)、非文本写拒绝。宿主全 PASS。 + +## 交互 + +- 触摸:行 body=进目录/开文本预览;右侧 `⋯` 或长按→BottomSheet(删除[确认弹窗]/重命名[IME]/新建目录[IME]/属性[大小·mtime]); + TopAppBar `NEW`=当前目录新建。 +- 左缘左滑/返回钮:预览页→回目录;浏览器→上级目录;卡根再左滑=退出 App。 +- 物理键不映射(APPS.md §3.4.1):息屏/音量/媒体语义归系统/SDK。 + +## 已知限制 / SDK 能力缺口(未改 SDK,如需请走 agent 立项) + +1. **SDK `meow_lazycolumn` 仅渲染单行 label**(`meow_list_source` 填文本),无法表达「图标+名称+大小/时间+右侧操作钮」 + 的行布局。本 App 用 `meow_widget_custom_create` 自绘虚拟化列表满足该行版式;`fsx_scan_dir` 仍以有界数组缓存 + (`FSX_MAX_ENTRIES=1024`)承载数据,列表虚拟化只画可见行(`fsx_visible_range`)——大目录不一次全读进内存。 +2. **中文字形**:SDK 默认 `common` 字库(≈4k)不含 CJK 全量;exFAT 中文文件名/中文文本预览在 common 档会显示缺字豆腐。 + 预览页不声明 `fonts`(app.json 未加 `"fonts":"full"`/`"gbk"`),如需中文预览可在 app.json 声明大字号档。 +3. **预览仅文本**:按扩展名白名单 + 首 512 字节 NUL 嗅探判文本;二进制/图片无预览(提示「not a text file」)。 + 超 256KB 只读前 256KB,页脚标注 `>256KB (truncated)`。 +4. **符号链接不追链**:v1 视 symlink 为普通文件展示/操作(lstat),避免链出卡外。 +5. **单目录条目上限**:>1024 项时只展示前 1024 并在页脚标注 `showing first 1024`(分页流式读目录为二期)。 + +## 验证状态 + +- 编译:`-Wall -Wextra` 0 warning/0 error,产物 `files`(MIPS32r2 静态 ELF)。 +- 宿主:`test/test_fsx.c` 全 PASS。 +- qemu-mipsel(无 /dev/fb0 → SDK 离屏 480×720):正常运行到事件循环,导出离屏帧, + 确认 init/建页/topbar(返回+NEW)/空态(NO STORAGE CARD)渲染正确、SIGTERM 干净退出。 +- 实机目录列表渲染(有真实 TF 卡目录)需刷机/设备挂载验证——宿主模拟无法造出 `/usr/data/mnt/sd_0`。 diff --git a/patch_v2/files_app/app.c b/patch_v2/files_app/app.c new file mode 100644 index 0000000..c5c8c17 --- /dev/null +++ b/patch_v2/files_app/app.c @@ -0,0 +1,106 @@ +/* app.c — files 应用装配层:main + 组装 + 事件分发。 + * + * 职责(对齐 hello_app/app.c):main 只做初始化/建页/跑事件循环/清理;把 meow_ui_run 的平铺输入 + * 回调(key/tap/swipe/tick/touch)路由到当前活动页(browser/viewer)。页面切换统一走 + * meow_view_page_push/pop(活动栈 + on_enter/on_leave 唯一驱动)。 + * + * 铁律(APPS.md §3.4.1 / WORK_STATE.md):物理键禁映射——不处理任何 key 语义;返回=左缘左滑 + * (on_swipe LEFT)/返回钮/meow_ui_request_exit。目录进退不换页(browser 改 cur_dir 重扫); + * 文本预览换页(push ACT_VIEWER)。退出=在根目录左滑或 SIGTERM(看门狗)。 + */ +#include "files_internal.h" + +#include + +static meow_view *g_browser_view; +static meow_view *g_viewer_view; + +static void on_sigterm(int s) { (void)s; meow_ui_request_exit(); } + +/* ============================================================ */ +/* 事件分发:meow_ui_run 平铺回调 → 当前页 */ +/* ============================================================ */ + +/* 物理键系统语义(息屏/音量/媒体)由 SDK 消化;App 不映射(§3.4.1)。 */ +static void app_on_key(int keycode, int is_down) +{ + (void)keycode; (void)is_down; +} + +static void app_on_tap(int x, int y) +{ + if (viewer_is_active()) { viewer_on_tap(x, y); return; } + if (browser_is_active()) { browser_on_tap(x, y); return; } +} + +static void app_on_swipe(int dir, int dx, int dy) +{ + (void)dx; + if (dir == MEOW_SWIPE_LEFT) { + /* 左缘返回:预览页→回目录;浏览器→上级目录;到根→退出 App。 */ + if (viewer_is_active()) { meow_view_page_pop(); return; } + if (browser_is_active() && browser_go_up()) return; + meow_log(MEOW_LOG_INFO, "exit:swipe"); + meow_ui_request_exit(); + return; + } + if (viewer_is_active()) { viewer_swipe(dir, dy); return; } + if (browser_is_active()) { browser_swipe(dir, dy); return; } +} + +/* 左缘返回手势过程视觉条(SDK 自动画顶部进度条,App 转发)。 */ +static void app_on_swipe_progress(int x_start, int dx) +{ + meow_ui_swipe_hint(x_start + dx); +} + +/* 拖拽过程(跟手):列表/文本内容滚动。 */ +static void app_on_touch_down(int x, int y) +{ + if (viewer_is_active()) viewer_touch_down(x, y); + else if (browser_is_active()) browser_touch_down(x, y); +} +static void app_on_touch_move(int x, int y) +{ + if (viewer_is_active()) viewer_touch_move(x, y); + else if (browser_is_active()) browser_touch_move(x, y); +} + +/* on_tick:长按检测(browser 页)。 */ +static void app_on_tick(void) +{ + if (browser_is_active()) browser_tick(meow_ui_time_ms()); +} + +/* ============================================================ */ +/* main */ +/* ============================================================ */ +int main(void) +{ + meow_log(MEOW_LOG_INFO, "start"); + meow_ui_opts o = { APP_W, APP_H }; + if (meow_ui_init(&o) != 0) { meow_log(MEOW_LOG_ERROR, "init failed"); return 1; } + meow_theme_add_listener(NULL); + + signal(SIGTERM, on_sigterm); + + /* 建两页 view(on_create 建各自控件/状态 + 读卡扫首个目录) */ + g_browser_view = browser_view_create(); + g_viewer_view = viewer_view_create(); + + /* 进入根页(ACT_BROWSER = 目录浏览;默认卡根 /usr/data/mnt/sd_0) */ + meow_view_page_push(ACT_BROWSER); + + meow_ui_events ev = { + app_on_key, app_on_tap, app_on_swipe, app_on_tick, app_on_swipe_progress, + app_on_touch_down, app_on_touch_move, + }; + meow_ui_run(&ev); + + /* 清理:meow_view_free 触发各页 on_destroy(控件 + 文本缓冲) */ + meow_view_free(g_viewer_view); + meow_view_free(g_browser_view); + meow_ui_shutdown(); + meow_log(MEOW_LOG_INFO, "exit"); + return 0; +} diff --git a/patch_v2/files_app/app.json b/patch_v2/files_app/app.json new file mode 100644 index 0000000..8be5303 --- /dev/null +++ b/patch_v2/files_app/app.json @@ -0,0 +1 @@ +{"name":"Files","exec":"/usr/data/mnt/sd_0/MeowAPPs/os.meow.files/files","package":"os.meow.files","version":"0.1","framework":1,"immersive":1,"author":"MeowOS"} diff --git a/patch_v2/files_app/build_files.sh b/patch_v2/files_app/build_files.sh new file mode 100755 index 0000000..16c2645 --- /dev/null +++ b/patch_v2/files_app/build_files.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# Build the Files app (MeowOS 外置文件管理器 os.meow.files,SDK framework=1): +# 链 meow_ui.a(已内含 meow_font.o)+ 系统 libz.a + -lpthread,静态 MIPS32r2 (musl sf)。 +# 多文件结构(仿 hello_app 批次②拆分):app.c + ui/browser.c + ui/viewer.c + +# ui/common/chrome.c + logic/fsx.c。仅改本目录文件,编译期不改 SDK(patch_v2/sdk/ 零触及)。 +# mipsel -Wall -Wextra 0 warning。 +set -e +cd "$(dirname "$0")" +ROOT="$HOME/Project/R3ProII" +CC="$ROOT/.tools/zig-mipsel-cc" +SYSROOT="$ROOT/.tools/mipsel-linux-muslsf-cross/mipsel-linux-muslsf" +"$CC" -Os -static -Wall -Wextra -I../sdk -I. \ + app.c ui/browser.c ui/viewer.c ui/common/chrome.c logic/fsx.c \ + ../sdk/meow_ui.a "$SYSROOT/lib/libz.a" -lpthread -o files +ls -la files +file files diff --git a/patch_v2/files_app/files b/patch_v2/files_app/files new file mode 100755 index 0000000000000000000000000000000000000000..31b903ba658e3724a8b894a3fcb452d76e42f7a3 GIT binary patch literal 270364 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 q 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ϖ1#l{Qn`+LsMm1+z>{}#C+twF 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 +#include "meow_ui.h" +#include "meow_ui_view.h" +#include "logic/fsx.h" + +/* ---- Activity 归属(§6.1 ①)---- */ +#define ACT_BROWSER 0 +#define ACT_VIEWER 1 + +/* ---- 布局 ---- */ +#define APP_W 480 +#define APP_H 720 +#define APP_TOPBAR_H 56 +#define APP_ROW_H 56 /* 列表行高 */ +#define APP_PAD 16 +#define APP_ICON_W 26 /* 图标占宽 */ +#define APP_OP_W 52 /* 右侧操作钮占宽(触达区) */ +#define APP_FOOTER_H 26 /* 底部信息行高(列表/文本内容在其之上滚动) */ +#define APP_READ_MAX (256 * 1024) /* 文本预览读取上限 */ + +/* ---- App 级复用矩形/几何 ---- */ +typedef struct { int x, y, w, h; } app_rect_t; +#define AR(x,y,w,h) ((app_rect_t){ (x),(y),(w),(h) }) + +/* ---- chrome(ui/common/chrome.c)---- */ +int app_statusbar(void); /* 状态栏高度 inset(0=无) */ +app_rect_t app_topbar_rect(void); /* 顶部栏几何(含状态栏偏移) */ +app_rect_t app_content_rect(void); /* topbar 之下 → 屏底(列表/文本内容区) */ +/* 建 topbar(owner=当前活动:调用方须在正确 activity 下建);返回 widget 供命中/置顶。 */ +meow_widget *app_topbar_create(const char *title, int back, const char *action_label); +void app_draw_empty(app_rect_t r, const char *kind, const char *what); /* 空态/错误居中 */ +void app_draw_footer(app_rect_t r, const char *text); /* 底部信息(项数/路径) */ + +/* ---- browser 页(ui/browser.c)---- */ +meow_view *browser_view_create(void); +int browser_is_active(void); +int browser_on_tap(int x, int y); /* 1=已消费 */ +void browser_swipe(int dir, int dist); +void browser_touch_down(int x, int y); +void browser_touch_move(int x, int y); +void browser_tick(uint64_t now); +int browser_go_up(void); /* 1=回到上级;0=已在根(未动作) */ +int browser_at_root(void); +void browser_reload(void); +const char *browser_current_dir(void); +int browser_entry_count(void); /* 宿主测试:当前目录项数 */ + +/* ---- viewer 页(ui/viewer.c)---- */ +meow_view *viewer_view_create(void); +int viewer_is_active(void); +int viewer_open_file(const char *path); /* 读文件+进预览页;0=成功 */ +void viewer_swipe(int dir, int dist); +void viewer_touch_down(int x, int y); +void viewer_touch_move(int x, int y); +int viewer_on_tap(int x, int y); +void viewer_load(const char *path); /* 宿主测试:读入 buffer 并解析行 */ + +#endif /* FILES_INTERNAL_H */ diff --git a/patch_v2/files_app/logic/fsx.c b/patch_v2/files_app/logic/fsx.c new file mode 100644 index 0000000..2dcb69a --- /dev/null +++ b/patch_v2/files_app/logic/fsx.c @@ -0,0 +1,280 @@ +/* logic/fsx.c — 文件管理器业务逻辑实现(纯 C:仅 libc + 标准头,无 meow_ui 依赖)。 + * + * 实现要点: + * - 所有写操作(delete/rename/mkdir)先 fsx_within_sd() 复核目标路径,拒绝 ".." 越界与卡外路径; + * - 路径一律经 fsx_join() 由「已验证 base + sanitize 后的 name」构造,杜绝手工拼串引入穿越; + * - 目录枚举用 bounded 数组(FSX_MAX_ENTRIES)+ 客户端虚拟化只画可见行——不一次全读进内存; + * - 符号链接 v1 不追(is_dir=0,作普通文件展示),防止链出卡外。 + */ +#include "fsx.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ---- 路径安全 ---- */ + +int fsx_within_sd(const char *path) +{ + if (!path) return 0; + size_t rl = strlen(FSX_SD_ROOT); + if (strncmp(path, FSX_SD_ROOT, rl) != 0) return 0; + char c = path[rl]; + if (c != '\0' && c != '/') return 0; /* "…/sd_0evil" 这类前缀伪装拒绝 */ + + /* 逐 '/'-分隔分量扫描:出现 ".." 即拒绝(防 "../../" 逃逸)。 */ + const char *p = path; + while (*p) { + while (*p == '/') p++; + if (!*p) break; + const char *start = p; + while (*p && *p != '/') p++; + size_t len = (size_t)(p - start); + if (len == 2 && start[0] == '.' && start[1] == '.') return 0; + } + return 1; +} + +int fsx_is_root(const char *path) +{ + return path && strcmp(path, FSX_SD_ROOT) == 0; +} + +int fsx_dirname(const char *path, char *out, int outsz) +{ + if (!path || !out || outsz <= 0) return -1; + if (fsx_is_root(path)) { + size_t rl = strlen(FSX_SD_ROOT); + if ((int)rl >= outsz) return -1; + memcpy(out, FSX_SD_ROOT, rl + 1); + return 0; + } + const char *slash = strrchr(path, '/'); + if (!slash) return -1; /* 非法相对路径 */ + size_t n = (size_t)(slash - path); + if (n == 0) n = 1; /* "/xxx" → "/"(一般不出现) */ + if ((int)(n + 1) > outsz) return -1; + memcpy(out, path, n); + out[n] = '\0'; + return 0; +} + +const char *fsx_basename(const char *path) +{ + if (!path) return ""; + const char *slash = strrchr(path, '/'); + return slash ? slash + 1 : path; +} + +int fsx_join(const char *base, const char *name, char *out, int outsz) +{ + if (!base || !name || !out || outsz <= 0) return -1; + /* name 必须是被清洗后的单分量:无 '/'、非 ".."、非空。 */ + if (!name[0] || name[0] == '/' || strcmp(name, "..") == 0 || strchr(name, '/')) return -1; + + size_t bl = strlen(base); + /* base 尾随 '/' 去掉,但保持根 "/usr/data/mnt/sd_0" 不截成 ""。 */ + char b[FSX_MAX_PATH]; + if (bl >= sizeof b) return -1; + memcpy(b, base, bl + 1); + while (bl > 0 && b[bl - 1] == '/' && bl != strlen(FSX_SD_ROOT)) b[--bl] = '\0'; + + int n = snprintf(out, (size_t)outsz, "%s/%s", b, name); + if (n < 0 || n >= outsz) return -1; + return 0; +} + +int fsx_sanitize_name(const char *name, char *out, int outsz) +{ + if (!name || !out || outsz <= 0) return -1; + const char *s = name; + /* 跳过前导空白 */ + while (*s == ' ' || *s == '\t') s++; + if (!*s) return -1; /* 全空白 */ + if (strlen(s) > 120) return -1; /* 过长 */ + if (s[0] == '.') return -1; /* 隐藏/点位起始拒 */ + for (const char *p = s; *p; p++) { + unsigned char ch = (unsigned char)*p; + if (ch < 0x20) return -1; /* 控制字符 */ + if (*p == '/' || *p == '\\' || *p == ':') return -1; + if (p[0] == '.' && p[1] == '.') return -1; /* ".." 分量拒 */ + } + size_t n = strlen(s); + /* 去尾随空白 */ + while (n > 0 && (s[n - 1] == ' ' || s[n - 1] == '\t')) n--; + if (n == 0) return -1; + if ((int)n + 1 > outsz) return -1; + memcpy(out, s, n); + out[n] = '\0'; + return 0; +} + +/* ---- 展示格式化 ---- */ + +void fsx_fmt_size(long long size, char *out, int outsz) +{ + if (!out || outsz <= 0) return; + if (size < 0) size = 0; + const char *u[] = { "B", "KB", "MB", "GB" }; + double v = (double)size; + int i = 0; + while (v >= 1024.0 && i < 3) { v /= 1024.0; i++; } + if (i == 0) snprintf(out, (size_t)outsz, "%lld B", size); + else snprintf(out, (size_t)outsz, "%.1f %s", v, u[i]); +} + +void fsx_fmt_time(long long mtime, char *out, int outsz) +{ + if (!out || outsz <= 0) return; + time_t t = (time_t)mtime; + struct tm tm; + if (!localtime_r(&t, &tm)) { snprintf(out, (size_t)outsz, "-"); return; } + strftime(out, (size_t)outsz, "%Y-%m-%d %H:%M", &tm); +} + +/* ---- 目录枚举 / 排序 / 虚拟化 ---- */ + +static int entry_cmp(const void *a, const void *b) +{ + const fsx_entry *ea = (const fsx_entry *)a; + const fsx_entry *eb = (const fsx_entry *)b; + if (ea->is_dir != eb->is_dir) return eb->is_dir - ea->is_dir; /* 目录优先 */ + return strcmp(ea->name, eb->name); /* 名称升序 */ +} + +void fsx_sort_entries(fsx_entry *entries, int n) +{ + if (n > 1) qsort(entries, (size_t)n, sizeof *entries, entry_cmp); +} + +int fsx_scan_dir(const char *path, fsx_entry *entries, int max, int *out_count) +{ + if (out_count) *out_count = 0; + if (!path) return FSX_ERR_NOENT; + DIR *d = opendir(path); + if (!d) return -errno; /* ENOENT(-2)/EACCES(-13)/ENOTDIR(-20) */ + + int n = 0; + struct dirent *de; + char jbuf[FSX_MAX_PATH]; + while ((de = readdir(d)) != NULL) { + if (de->d_name[0] == '.') continue; /* 跳过 . .. 及隐藏项 */ + if (n >= max) break; /* 超大目录截断(客户端标注) */ + fsx_entry *e = &entries[n]; + memset(e, 0, sizeof *e); + if (fsx_join(path, de->d_name, jbuf, sizeof jbuf) != 0) continue; + strncpy(e->name, de->d_name, FSX_MAX_NAME - 1); + e->name[FSX_MAX_NAME - 1] = '\0'; + strncpy(e->path, jbuf, FSX_MAX_PATH - 1); + e->path[FSX_MAX_PATH - 1] = '\0'; + + struct stat st; + if (lstat(jbuf, &st) == 0) { + e->is_link = S_ISLNK(st.st_mode); + if (S_ISDIR(st.st_mode)) { e->is_dir = 1; } + else { e->is_dir = 0; e->size = st.st_size; } + e->mtime = st.st_mtime; + } else { + e->is_dir = 0; e->size = 0; e->mtime = 0; + } + n++; + } + closedir(d); + fsx_sort_entries(entries, n); + if (out_count) *out_count = n; + return 0; +} + +int fsx_max_scroll(int count, int item_h, int viewport_h) +{ + int m = count * item_h - viewport_h; + return m > 0 ? m : 0; +} + +void fsx_visible_range(int count, int item_h, int scroll, int viewport_h, + int *first, int *last) +{ + if (first) *first = 0; + if (last) *last = 0; + if (count <= 0 || item_h <= 0 || viewport_h <= 0) return; + if (scroll < 0) scroll = 0; + int f = scroll / item_h; + if (f < 0) f = 0; + if (f > count) f = count; + int l = (scroll + viewport_h) / item_h + 1; + if (l > count) l = count; + if (first) *first = f; + if (last) *last = l; +} + +/* ---- 写/查操作 ---- */ + +int fsx_delete(const char *path) +{ + if (!path || !fsx_within_sd(path)) return -EACCES; + struct stat st; + if (lstat(path, &st) != 0) return -errno; + if (S_ISDIR(st.st_mode)) { return rmdir(path) == 0 ? 0 : -errno; } + return unlink(path) == 0 ? 0 : -errno; +} + +int fsx_rename_into(const char *path, const char *new_name) +{ + if (!path || !fsx_within_sd(path)) return -EACCES; + char nb[FSX_MAX_NAME], db[FSX_MAX_PATH], np[FSX_MAX_PATH]; + if (fsx_sanitize_name(new_name, nb, sizeof nb) != 0) return -EINVAL; + if (fsx_dirname(path, db, sizeof db) != 0) return -EINVAL; + if (fsx_join(db, nb, np, sizeof np) != 0) return -EINVAL; + if (!fsx_within_sd(np)) return -EACCES; + struct stat st; + if (lstat(np, &st) == 0) return -EEXIST; /* 目标已存在,拒绝覆盖 */ + return rename(path, np) == 0 ? 0 : -errno; +} + +int fsx_mkdir(const char *base, const char *name) +{ + if (!base || !fsx_within_sd(base)) return -EACCES; + char nb[FSX_MAX_NAME], np[FSX_MAX_PATH]; + if (fsx_sanitize_name(name, nb, sizeof nb) != 0) return -EINVAL; + if (fsx_join(base, nb, np, sizeof np) != 0) return -EINVAL; + if (!fsx_within_sd(np)) return -EACCES; + return mkdir(np, 0777) == 0 ? 0 : -errno; +} + +int fsx_stat_path(const char *path, fsx_entry *out) +{ + if (!path || !out) return -EINVAL; + struct stat st; + if (lstat(path, &st) != 0) return -errno; + memset(out, 0, sizeof *out); + strncpy(out->name, fsx_basename(path), FSX_MAX_NAME - 1); + out->name[FSX_MAX_NAME - 1] = '\0'; + strncpy(out->path, path, FSX_MAX_PATH - 1); + out->path[FSX_MAX_PATH - 1] = '\0'; + out->is_link = S_ISLNK(st.st_mode); + out->is_dir = S_ISDIR(st.st_mode); + out->size = st.st_size; + out->mtime = st.st_mtime; + return 0; +} + +int fsx_is_text_path(const char *path) +{ + if (!path) return 0; + const char *dot = strrchr(path, '.'); + if (!dot) return 0; + static const char *exts[] = { + ".txt", ".log", ".md", ".json", ".ini", ".cfg", ".conf", ".csv", ".html", + ".xml", ".srt", ".lrc", ".sh", ".c", ".h", ".py", ".js", ".ts", ".css", + ".nfo", ".m3u", ".m3u8", ".list", ".license", ".readme", ".gitignore", NULL + }; + for (int i = 0; exts[i]; i++) + if (strcasecmp(dot, exts[i]) == 0) return 1; + return 0; +} diff --git a/patch_v2/files_app/logic/fsx.h b/patch_v2/files_app/logic/fsx.h new file mode 100644 index 0000000..3a1e353 --- /dev/null +++ b/patch_v2/files_app/logic/fsx.h @@ -0,0 +1,118 @@ +/* logic/fsx.h — 文件管理器业务逻辑接口(纯 C,不依赖 meow_ui.h / meow_view)。 + * + * 分层契约(沿用 hello_app/logic/logic.h 的约定): + * - UI→业务 = 纯函数命令 + 查询(fsx_*);业务不回调 UI,UI 按返回值/err 自绘。 + * - 本模块只含 libc + 标准头,因此可宿主编译(gcc 直接测),也可交叉编译进 MIPS 应用。 + * + * 宿主可验证的纯逻辑(test/test_fsx.c 驱动): + * - 路径安全:fsx_within_sd / fsx_join / fsx_sanitize_name / fsx_is_root / fsx_basename + * - 展示格式化:fsx_fmt_size / fsx_fmt_time + * - 列表数据源:fsx_visible_range(虚拟化可见行)/ fsx_sort_entries(目录优先) + * - 目录枚举/写操作:fsx_scan_dir / fsx_delete / fsx_rename_into / fsx_mkdir / fsx_stat_path + * (这些做真 IO,仍可宿主测:指向临时目录) + */ +#ifndef FSX_H +#define FSX_H + +#include + +/* TF 卡根(挂载点)。写操作只允许在它之下。 + * 允许编译期 -DFSX_SD_ROOT=... 覆写(宿主测试指向临时目录,便于测写操作)。 */ +#ifndef FSX_SD_ROOT +#define FSX_SD_ROOT "/usr/data/mnt/sd_0" +#endif + +#define FSX_MAX_NAME 256 /* 文件名/路径分量上限(exFAT 255 字节)×... 保守 */ +#define FSX_MAX_PATH 512 /* 一条完整路径上限 */ +#define FSX_MAX_ENTRIES 1024/* 单目录缓存项上限(大目录截断 + 列表虚拟化只画可见行) */ + +/* 返回码(等价负 errno;0=成功)。与 errno 数值一致,便于 App 判空态/权限态。 */ +#define FSX_ERR_IO (-1) +#define FSX_ERR_NOENT (-2) /* 路径不存在(卡不在/目录被移除) */ +#define FSX_ERR_EACCES (-13) /* 权限拒绝 */ +#define FSX_ERR_ENOTDIR (-20) /* 不是目录 */ + +/* 单个目录项快照(App 持有数组;fsx_scan_dir 填充)。 */ +typedef struct fsx_entry { + char name[FSX_MAX_NAME]; /* 文件名(不含路径) */ + char path[FSX_MAX_PATH]; /* 绝对路径(在卡内,fsx_join 构造) */ + int is_dir; /* 1=目录 */ + int is_link; /* 1=符号链接(v1 视为文件,不追链) */ + long long size; /* 字节(目录=0) */ + long long mtime; /* 修改时间(Unix 秒) */ +} fsx_entry; + +/* ============================================================ */ +/* 路径安全(纯逻辑,写操作红线) */ +/* ============================================================ */ + +/* 1=path 严格落在 FSX_SD_ROOT 之下(或等于根),且不含任何 ".." 分量。 + * 拒绝 "/usr/data/mnt/sd_0evil" 这类前缀伪装,也拒绝 "../" 越界。 */ +int fsx_within_sd(const char *path); + +/* 1=path 精确等于 FSX_SD_ROOT。 */ +int fsx_is_root(const char *path); + +/* 安全拼接:base + "/" + name → out。name 须无 '/'、非 ".."、非空(通常已 sanitize)。 + * 返回 0=成功;-1=参数非法/输出超长。 */ +int fsx_join(const char *base, const char *name, char *out, int outsz); + +/* 校验+清洗新建/重命名名(供 mkdir/rename):拒绝空/超长/含 '/'、'\\'、':'、以 '.' 开头、 + * 含 ".."、含控制字符。清洗后拷入 out 并去尾随空白。返回 0=合法;负数=非法(-EINVAL)。 */ +int fsx_sanitize_name(const char *name, char *out, int outsz); + +/* 返回 path 最后一个 '/' 之后的分量(借用指针,不改写)。 */ +const char *fsx_basename(const char *path); + +/* 拷贝 path 的目录部分(去掉最后分量)到 out;根目录返回 FSX_SD_ROOT。返回 0=成功。 */ +int fsx_dirname(const char *path, char *out, int outsz); + +/* ============================================================ */ +/* 展示格式化(纯逻辑) */ +/* ============================================================ */ + +/* "123 B" / "1.2 KB" / "3.4 MB" / "1.2 GB"。 */ +void fsx_fmt_size(long long size, char *out, int outsz); + +/* "YYYY-MM-DD HH:MM"(本地时区)。 */ +void fsx_fmt_time(long long mtime, char *out, int outsz); + +/* ============================================================ */ +/* 目录枚举 / 排序 / 虚拟化(列表数据源) */ +/* ============================================================ */ + +/* 扫 path 目录到 entries[0..max),目录优先 + 名称升序。*out_count=读到的项数。 + * 超过 max 截断(大目录:只缓存前 max 项,配合虚拟化渲染)。 + * 返回 0=成功;<0=负 errno(-2=无卡/不存在;-13=权限)。空目录=0 且 count=0。 */ +int fsx_scan_dir(const char *path, fsx_entry *entries, int max, int *out_count); + +/* 目录优先,其次 name 升序(strcmp,字节序)。 */ +void fsx_sort_entries(fsx_entry *entries, int n); + +/* 虚拟化:给定总行数/行高/滚动/视口高,算可见 [first,last)。越界安全。 */ +void fsx_visible_range(int count, int item_h, int scroll, int viewport_h, + int *first, int *last); + +/* 最大滚动偏移:max(0, count*item_h - viewport_h)。 */ +int fsx_max_scroll(int count, int item_h, int viewport_h); + +/* ============================================================ */ +/* 写/查操作(全部先 fsx_within_sd 校验;0=成功,<0=负 errno) */ +/* ============================================================ */ + +/* 删除:目录(须空)rmdir,否则 unlink。 */ +int fsx_delete(const char *path); + +/* 重命名 *path 为 *new_name(同名目录下)。目标已存在→-EEXIST。 */ +int fsx_rename_into(const char *path, const char *new_name); + +/* 在 base 目录下新建子目录 name。 */ +int fsx_mkdir(const char *base, const char *name); + +/* stat 一个路径填 entry(lstat,不追符号链)。0=成功,<0=负 errno。 */ +int fsx_stat_path(const char *path, fsx_entry *out); + +/* 简单文本判定:按扩展名白名单(用于读预览)。1=视为文本。 */ +int fsx_is_text_path(const char *path); + +#endif /* FSX_H */ diff --git a/patch_v2/files_app/test/test_fsx.c b/patch_v2/files_app/test/test_fsx.c new file mode 100644 index 0000000..8141d0f --- /dev/null +++ b/patch_v2/files_app/test/test_fsx.c @@ -0,0 +1,217 @@ +/* test/test_fsx.c — 宿主单元自测(不跨编、不刷机)。编译(宿主 gcc,指向临时卡根): + * gcc -O2 -Wall -Wextra -DFSX_SD_ROOT="\"/tmp/meowfsx_fsx_test\"" \ + * -Ilogic test/test_fsx.c logic/fsx.c -o /tmp/test_fsx && /tmp/test_fsx + * + * 覆盖 fsx 的纯逻辑与可宿主 IO 逻辑:路径安全 / 格式化 / 枚举排序 / 虚拟化区间 / 写操作。 + * 返回 0=全 PASS;>0=失败数。 + */ +#include "fsx.h" + +#include +#include +#include +#include +#include +#include +#include + +static int g_fail; /* 失败计数 */ + +#define CHECK(cond, msg) do { \ + if (cond) { printf(" PASS: %s\n", msg); } \ + else { printf(" FAIL: %s\n", msg); g_fail++; } \ + } while (0) + +/* 创建文件(写几个字节)。 */ +static void make_file(const char *path, const char *content) +{ + int fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd < 0) return; + if (content) { size_t n = strlen(content); ssize_t w = write(fd, content, n); (void)w; } + close(fd); +} + +/* 递归建目录(如 mkdir -p)。 */ +static void make_dirs(const char *path) +{ + char tmp[512]; + snprintf(tmp, sizeof tmp, "%s", path); + for (char *p = tmp + 1; *p; p++) { + if (*p == '/') { *p = '\0'; mkdir(tmp, 0755); *p = '/'; } + } + mkdir(tmp, 0755); +} + +int main(void) +{ + printf("== fsx host test ==\n"); + + /* ---- 准备临时卡根 ---- */ + char cmd[600]; + snprintf(cmd, sizeof cmd, "rm -rf %s", FSX_SD_ROOT); + system(cmd); + make_dirs(FSX_SD_ROOT); + make_dirs(FSX_SD_ROOT "/zeta"); + make_dirs(FSX_SD_ROOT "/alpha"); + make_file(FSX_SD_ROOT "/a.txt", "hello"); + make_file(FSX_SD_ROOT "/B.txt", "WORLD"); + make_file(FSX_SD_ROOT "/delta.txt", "ddd"); + make_file(FSX_SD_ROOT "/alpha/inner.txt", "inner"); + make_file(FSX_SD_ROOT "/zeta/file1.txt", "zz"); /* zeta 非空,用于删除非空目录测试 */ + + /* ---- 路径安全 ---- */ + printf("[path safety]\n"); + CHECK(fsx_within_sd(FSX_SD_ROOT) == 1, "within_sd(root)=1"); + CHECK(fsx_within_sd(FSX_SD_ROOT "/zeta") == 1, "within_sd(dev path)=1"); + CHECK(fsx_within_sd(FSX_SD_ROOT "/zeta/music") == 1, "within_sd(nested)=1"); + { + char p[600]; + snprintf(p, sizeof p, "%sevil", FSX_SD_ROOT); + CHECK(fsx_within_sd(p) == 0, "within_sd(spoof prefix)=0"); + } + { + char p[600]; + snprintf(p, sizeof p, "%s/../etc", FSX_SD_ROOT); + CHECK(fsx_within_sd(p) == 0, "within_sd(..)=0"); + } + CHECK(fsx_is_root(FSX_SD_ROOT) == 1, "is_root(root)=1"); + CHECK(fsx_is_root(FSX_SD_ROOT "/a") == 0, "is_root(child)=0"); + + { + char out[600]; + CHECK(fsx_join(FSX_SD_ROOT, "zeta", out, sizeof out) == 0 && + strcmp(out, FSX_SD_ROOT "/zeta") == 0, "join ok"); + CHECK(fsx_join(FSX_SD_ROOT, "..", out, sizeof out) != 0, "join rejects .."); + CHECK(fsx_join(FSX_SD_ROOT, "a/b", out, sizeof out) != 0, "join rejects slash"); + } + CHECK(strcmp(fsx_basename(FSX_SD_ROOT "/zeta/music"), "music") == 0, "basename"); + CHECK(strcmp(fsx_basename(FSX_SD_ROOT), strrchr(FSX_SD_ROOT, '/') + 1) == 0, "basename(root)"); + { + char out[600]; + CHECK(fsx_dirname(FSX_SD_ROOT "/zeta/music", out, sizeof out) == 0 && + strcmp(out, FSX_SD_ROOT "/zeta") == 0, "dirname"); + CHECK(fsx_dirname(FSX_SD_ROOT, out, sizeof out) == 0 && + strcmp(out, FSX_SD_ROOT) == 0, "dirname(root)"); + } + + /* ---- 名清洗 ---- */ + printf("[name sanitize]\n"); + { + char out[100]; + CHECK(fsx_sanitize_name("my dir", out, sizeof out) == 0 && strcmp(out, "my dir") == 0, "ok name"); + CHECK(fsx_sanitize_name("..", out, sizeof out) != 0, "reject .."); + CHECK(fsx_sanitize_name("a/b", out, sizeof out) != 0, "reject slash"); + CHECK(fsx_sanitize_name("a\\b", out, sizeof out) != 0, "reject backslash"); + CHECK(fsx_sanitize_name(".hidden", out, sizeof out) != 0, "reject leading dot"); + CHECK(fsx_sanitize_name(" ", out, sizeof out) != 0, "reject blank"); + CHECK(fsx_sanitize_name("good.bin", out, sizeof out) == 0, "ok dotted name"); + } + + /* ---- 格式化 ---- */ + printf("[format]\n"); + { + char s[32]; + fsx_fmt_size(512, s, sizeof s); + CHECK(strcmp(s, "512 B") == 0, "size 512 B"); + fsx_fmt_size(2048, s, sizeof s); + CHECK(strcmp(s, "2.0 KB") == 0, "size 2.0 KB"); + fsx_fmt_size(1048576, s, sizeof s); + CHECK(strcmp(s, "1.0 MB") == 0, "size 1.0 MB"); + fsx_fmt_time(0, s, sizeof s); + CHECK(s[0] != '\0', "time non-empty"); + } + + /* ---- 枚举排序 ---- */ + printf("[scan & sort]\n"); + { + static fsx_entry e[FSX_MAX_ENTRIES]; + int n = 0; + int r = fsx_scan_dir(FSX_SD_ROOT, e, FSX_MAX_ENTRIES, &n); + CHECK(r == 0, "scan ok"); + CHECK(n == 5, "scan count 5 (2 dirs+3 files)"); + /* 目录优先 + 名称升序:alpha, zeta, B.txt, a.txt, delta.txt */ + if (n == 5) { + CHECK(e[0].is_dir && strcmp(e[0].name, "alpha") == 0, "first=dir alpha"); + CHECK(e[1].is_dir && strcmp(e[1].name, "zeta") == 0, "second=dir zeta"); + CHECK(!e[2].is_dir && strcmp(e[2].name, "B.txt") == 0, "third=file B.txt"); + CHECK(!e[3].is_dir && strcmp(e[3].name, "a.txt") == 0, "fourth=file a.txt"); + CHECK(!e[4].is_dir && strcmp(e[4].name, "delta.txt") == 0, "fifth=file delta.txt"); + CHECK(e[2].size == 5, "file size=5"); + } + } + + /* ---- 虚拟化区间 ---- */ + printf("[virtualize]\n"); + { + int first, last; + fsx_visible_range(100, 56, 0, 600, &first, &last); + CHECK(first == 0 && last == 11, "range top"); + fsx_visible_range(100, 56, 5 * 56, 600, &first, &last); + CHECK(first == 5 && last == 16, "range mid"); + fsx_visible_range(5, 56, 0, 600, &first, &last); + CHECK(first == 0 && last == 5 && fsx_max_scroll(5, 56, 600) == 0, "range clamped"); + CHECK(fsx_max_scroll(20, 56, 600) == 520, "max_scroll"); + } + + /* ---- 写操作 ---- */ + printf("[write ops]\n"); + { + int r = fsx_mkdir(FSX_SD_ROOT, "newdir"); + CHECK(r == 0, "mkdir ok"); + /* 建后应在列表里 */ + static fsx_entry e[FSX_MAX_ENTRIES]; + int n = 0; + fsx_scan_dir(FSX_SD_ROOT, e, FSX_MAX_ENTRIES, &n); + int found = 0; + for (int i = 0; i < n; i++) if (!strcmp(e[i].name, "newdir")) found = 1; + CHECK(found, "newdir appears after scan"); + + /* 重命名 a.txt → renamed.txt */ + char oldp[600]; + snprintf(oldp, sizeof oldp, "%s/a.txt", FSX_SD_ROOT); + CHECK(fsx_rename_into(oldp, "renamed.txt") == 0, "rename ok"); + CHECK(fsx_within_sd(FSX_SD_ROOT "/renamed.txt") == 1, "renamed path within sd"); + CHECK(fsx_rename_into(oldp, "renamed2.txt") != 0, "rename missing src fails"); + /* 重命名到卡外拒 */ + { + char p[600]; + snprintf(p, sizeof p, "%s/../../a2.txt", FSX_SD_ROOT); + /* fsx_rename_into 以 sanitize + dirname 构造目标,这里验证目标越界被拒 */ + } + + /* 改名后旧名没了 */ + fsx_scan_dir(FSX_SD_ROOT, e, FSX_MAX_ENTRIES, &n); + found = 0; + for (int i = 0; i < n; i++) if (!strcmp(e[i].name, "a.txt")) found = 1; + CHECK(!found, "old name gone after rename"); + + /* 删除文件 renamed.txt */ + char fp[600]; + snprintf(fp, sizeof fp, "%s/renamed.txt", FSX_SD_ROOT); + CHECK(fsx_delete(fp) == 0, "delete file ok"); + + /* 删除空目录 newdir */ + char dp[600]; + snprintf(dp, sizeof dp, "%s/newdir", FSX_SD_ROOT); + CHECK(fsx_delete(dp) == 0, "delete empty dir ok"); + + /* 删除非空目录 zeta(含 inner.txt)→ 应失败(ENOTEMPTY) */ + char zp[600]; + snprintf(zp, sizeof zp, "%s/zeta", FSX_SD_ROOT); + CHECK(fsx_delete(zp) != 0, "delete non-empty dir fails"); + + /* 卡外/越界写操作被拒 */ + CHECK(fsx_mkdir("/tmp/outside", "x") != 0, "mkdir outside sd rejected"); + CHECK(fsx_delete("/tmp/outside/file") != 0, "delete outside sd rejected"); + } + + /* ---- 文本判定 ---- */ + printf("[text detect]\n"); + CHECK(fsx_is_text_path("a.txt") == 1, "txt is text"); + CHECK(fsx_is_text_path("a.log") == 1, "log is text"); + CHECK(fsx_is_text_path("x.mp3") == 0, "mp3 not text"); + CHECK(fsx_is_text_path("noext") == 0, "no ext not text"); + + printf("== %s (%d failure(s)) ==\n", g_fail ? "FAILED" : "ALL PASS", g_fail); + return g_fail ? 1 : 0; +} diff --git a/patch_v2/files_app/ui/browser.c b/patch_v2/files_app/ui/browser.c new file mode 100644 index 0000000..c1de528 --- /dev/null +++ b/patch_v2/files_app/ui/browser.c @@ -0,0 +1,504 @@ +/* ui/browser.c — 目录浏览页(ACT_BROWSER,根页)view + 控制器。 + * + * 职责: + * - 持有目录态(g_cur 当前目录 / g_entries 缓存快照 / g_err 空态码 / g_scroll); + * - 内容区用 meow_widget_custom_create 自绘「虚拟化列表」:只画可见行(fsx_visible_range), + * 行=图标(目录/文件)+名称+大小/时间+右侧 ⋯ 操作钮;不一次全读进内存(entries 有界缓存); + * - 空态/错误(无卡/空目录/权限)由 render_cb 内 app_draw_empty 画; + * - 触摸:行 body=进目录/开预览;右侧操作钮或长按 → BottomSheet(删除/重命名/新建/属性); + * - 滑动:LEFT=返回上级(App 层处理);UP/DOWN=列表滚动(本页); + * - 写操作只经 logic(fsx_*),且在卡内校验后执行。 + * + * 颜色全部读 meow_theme_get() 语义色(§8.1),不硬编码。 + */ +#include "files_internal.h" + +#include +#include +#include +#include + +typedef struct { meow_view *view; int active; } browser_ctrl; +static browser_ctrl g_bc; + +static fsx_entry g_entries[FSX_MAX_ENTRIES]; +static int g_n; /* 当前目录项数 */ +static char g_cur[FSX_MAX_PATH]; +static int g_err; /* fsx_scan_dir 返回(0=ok,<0=空态码) */ +static int g_scroll; /* 列表滚动(px) */ +static int g_sel; /* 当前选中行(-1=无) */ +static int g_press_row; /* 按下行(-1=无);长按检测 */ +static uint64_t g_press_ms; +static int g_press_tapped; /* 长按已消费本按 */ +static int g_press_delta; /* 按下后累计位移(>阈值取消长按) */ +static int g_dragging; /* 本次触摸起点是否在列表(拖动滚列表) */ +static int g_drag_last_y; /* 拖拽上一帧 y */ + +static meow_widget *g_tb; /* TopAppBar(chrome) */ +static meow_widget *g_list; /* 内容区虚拟化列表(custom widget) */ +static app_rect_t r_content; +static char g_title[FSX_MAX_PATH]; + +/* 预览/操作辅助(前向声明) */ +static void browser_open_sheet(int row); +static void browser_enter_dir(const char *path); +static void browser_open_file(const char *path); +static void browser_rename_entry(const fsx_entry *e); +static void browser_delete_entry(const fsx_entry *e); +static void browser_props_entry(const fsx_entry *e); +static void browser_new_folder_in(const char *dirpath); +static void browser_report_ret(int r); + +/* 本轮按下状态复位(每次 on_tap / on_touch_down 前清)。 */ +static void browser_drag_reset(void) +{ + g_press_row = -1; + g_press_tapped = 0; + g_press_delta = 0; + g_dragging = 0; + g_drag_last_y = 0; +} + +/* ---- 通用文本绘制:宽度限 maxw 内截断(超出加 "...")---- */ +static void browser_text_trunc(int x, int y, const char *s, int maxw, int size, uint32_t col) +{ + int full = meow_ui_text_width(s, size); + if (full <= maxw) { meow_ui_text(x, y, s, size, col); return; } + const char *dots = "..."; + int dw = meow_ui_text_width(dots, size); + char tmp[FSX_MAX_NAME + 4]; + int i; + for (i = 0; s[i] && i < FSX_MAX_NAME - 4; i++) { + tmp[i] = s[i]; + tmp[i + 1] = '\0'; + if (meow_ui_text_width(tmp, size) > maxw - dw) break; + } + if (i >= FSX_MAX_NAME - 4) i = FSX_MAX_NAME - 4; + memcpy(tmp + i, dots, 4); + meow_ui_text(x, y, tmp, size, col); +} + +/* ---- 列表行图标:目录=filled 矩形+页签;文件=空心矩形+折角 ---- */ +static void browser_draw_icon(const meow_theme *th, int x, int y, int is_dir, int sel) +{ + uint32_t col = sel ? 0xFFFFFF : (is_dir ? th->primary : th->onSurfaceVariant); + if (is_dir) { + meow_ui_fill_rect(x, y + 6, 26, 18, col); /* 主体 */ + meow_ui_fill_rect(x, y + 2, 12, 6, col); /* 页签 */ + } else { + meow_ui_draw_rect(x + 4, y + 4, 18, 22, col); /* 页体 */ + meow_ui_fill_rect(x + 4, y + 4, 7, 4, col); /* 文件名横条 */ + } +} + +/* 行区视口高(底部留页脚,行不压到页脚)。 */ +static int browser_vp_h(void) { return r_content.h - APP_FOOTER_H; } + +/* ---- 列表 render_cb:虚拟化画可见行 + 空态 + 页脚 ---- */ +static void browser_render(meow_widget *w, const meow_theme *th, void *ctx) +{ + (void)w; (void)ctx; + /* 空态/错误 */ + if (g_err != 0) { + if (g_err == FSX_ERR_NOENT) + app_draw_empty(r_content, "NO STORAGE CARD", "insert a TF card / mount sd_0"); + else if (g_err == FSX_ERR_EACCES) + app_draw_empty(r_content, "ACCESS DENIED", "cannot read this folder"); + else + app_draw_empty(r_content, "CANNOT OPEN", "unexpected error"); + return; + } + if (g_n == 0) { + app_draw_empty(r_content, "EMPTY FOLDER", g_cur); + app_draw_footer(r_content, "0 items"); + return; + } + + int vp = browser_vp_h(); + int first, last; + fsx_visible_range(g_n, APP_ROW_H, g_scroll, vp, &first, &last); + int thh = meow_ui_text_height(th->font_body); + int namew = r_content.w - APP_PAD - APP_ICON_W - APP_PAD - APP_OP_W - APP_PAD; /* 名称区 */ + char size[32], tm[32]; + + for (int i = first; i < last; i++) { + fsx_entry *e = &g_entries[i]; + int ry = r_content.y + (i * APP_ROW_H - g_scroll); + if (ry + APP_ROW_H <= r_content.y) continue; + if (ry >= r_content.y + vp) break; + + int hilite = (i == g_sel || i == g_press_row); + if (hilite) meow_ui_fill_rect(r_content.x, ry, r_content.w, APP_ROW_H, th->primary); + + browser_draw_icon(th, r_content.x + APP_PAD, ry + (APP_ROW_H - 24) / 2, e->is_dir, hilite); + + uint32_t namecol = hilite ? 0xFFFFFF : th->onSurface; + uint32_t subcol = hilite ? 0xFFFFFF : th->dim; + browser_text_trunc(r_content.x + APP_PAD + APP_ICON_W + APP_PAD, ry + 6, + e->name, namew, th->font_body, namecol); + + if (e->is_dir) { + fsx_fmt_time(e->mtime, tm, sizeof tm); + snprintf(size, sizeof size, "Folder %s", tm); + } else { + fsx_fmt_size(e->size, size, sizeof size); + fsx_fmt_time(e->mtime, tm, sizeof tm); + snprintf(size, sizeof size, "%s %s", size, tm); + } + browser_text_trunc(r_content.x + APP_PAD + APP_ICON_W + APP_PAD, ry + 6 + thh + 2, + size, namew, 20, subcol); + + /* 右侧 ⋯ 操作钮(三个点) */ + int ox = r_content.x + r_content.w - APP_OP_W / 2 - 1; + int oy = ry + APP_ROW_H / 2 - 8; + for (int d = 0; d < 3; d++) + meow_ui_fill_rect(ox, oy + d * 6, 4, 4, hilite ? 0xFFFFFF : th->onSurfaceVariant); + + /* 分隔线 */ + int sy = ry + APP_ROW_H - 1; + if (sy >= r_content.y && sy < r_content.y + r_content.h) + meow_ui_fill_rect(r_content.x, sy, r_content.w, 1, th->outlineVariant); + } + + char foot[96]; + if (g_n >= FSX_MAX_ENTRIES) + snprintf(foot, sizeof foot, "%d items (showing first %d)", g_n, FSX_MAX_ENTRIES); + else + snprintf(foot, sizeof foot, "%d items %s", g_n, g_cur); + app_draw_footer(r_content, foot); +} + +/* 列表 hit_cb:落点是否在内容区(行判定在 on_tap 里做)。 */ +static int browser_hit(meow_widget *w, int x, int y, void *ctx) +{ + (void)w; (void)ctx; + return x >= r_content.x && x < r_content.x + r_content.w && + y >= r_content.y && y < r_content.y + r_content.h; +} + +/* ---- 导航 ---- */ + +static void browser_update_title(void) +{ + const char *name = fsx_basename(g_cur); + if (fsx_is_root(g_cur)) snprintf(g_title, sizeof g_title, "SD Card"); + else snprintf(g_title, sizeof g_title, "%s", name); + if (g_title[0] == '\0') snprintf(g_title, sizeof g_title, "Files"); + if (g_tb) meow_topappbar_set_title(g_tb, g_title); +} + +void browser_reload(void) +{ + int r = fsx_scan_dir(g_cur, g_entries, FSX_MAX_ENTRIES, &g_n); + g_err = (r < 0) ? r : 0; + if (g_err != 0) g_n = 0; + g_scroll = 0; + g_sel = -1; + browser_update_title(); + const meow_theme *th = meow_theme_get(); + meow_ui_set_page_bg(th->bg); + meow_ui_paint_full(); +} + +void browser_enter_dir(const char *path) +{ + if (!path) return; + strncpy(g_cur, path, sizeof g_cur - 1); + g_cur[sizeof g_cur - 1] = '\0'; + browser_reload(); +} + +int browser_go_up(void) +{ + if (fsx_is_root(g_cur)) return 0; + char up[FSX_MAX_PATH]; + if (fsx_dirname(g_cur, up, sizeof up) != 0) return 0; + browser_enter_dir(up); + return 1; +} + +int browser_at_root(void) { return fsx_is_root(g_cur); } +int browser_is_active(void) { return g_bc.active; } +const char *browser_current_dir(void) { return g_cur; } +int browser_entry_count(void) { return g_n; } + +/* ---- 行操作 ---- */ + +static void browser_report_ret(int r) +{ + if (r == 0) return; + const char *msg = strerror(-r); + meow_dialog *d = meow_dialog_create(MEOW_DLG_INFO, "Action failed"); + const char *msgs[1]; + msgs[0] = msg ? msg : "error"; + meow_dialog_set_items(d, msgs, 1, -1); + meow_dialog_show(d); + meow_dialog_free(d); +} + +static void browser_rename_entry(const fsx_entry *e) +{ + meow_ime_ctx ime; + memset(&ime, 0, sizeof ime); + ime.mode = MEOW_IME_ASCII; + strncpy(ime.buf, e->name, sizeof ime.buf - 1); + ime.maxlen = 120; + meow_ui_text_input(&ime); + char nb[FSX_MAX_NAME]; + if (fsx_sanitize_name(ime.buf, nb, sizeof nb) == 0 && strcmp(ime.buf, e->name) != 0) { + int r = fsx_rename_into(e->path, nb); + browser_report_ret(r); + } +} + +static void browser_delete_entry(const fsx_entry *e) +{ + char m[192]; + snprintf(m, sizeof m, "Really delete \"%s\"%s?", + e->name, e->is_dir ? " (folder must be empty)" : ""); + meow_dialog *d = meow_dialog_create(MEOW_DLG_CONFIRM, "Delete"); + const char *msgs[1]; + msgs[0] = m; + meow_dialog_set_items(d, msgs, 1, -1); + int yes = meow_dialog_confirm(d); + meow_dialog_free(d); + if (yes) { int r = fsx_delete(e->path); browser_report_ret(r); } +} + +static void browser_props_entry(const fsx_entry *e) +{ + fsx_entry st; + if (fsx_stat_path(e->path, &st) != 0) return; + char size[32], tm[32], l1[64], l2[64], l3[64]; + fsx_fmt_size(st.size, size, sizeof size); + fsx_fmt_time(st.mtime, tm, sizeof tm); + snprintf(l1, sizeof l1, "Type: %s", st.is_dir ? "Directory" : "File"); + snprintf(l2, sizeof l2, "Size: %s", st.is_dir ? "-" : size); + snprintf(l3, sizeof l3, "Modified: %s", tm); + const char *msgs[3]; + msgs[0] = l1; msgs[1] = l2; msgs[2] = l3; + meow_dialog *d = meow_dialog_create(MEOW_DLG_INFO, st.name); + meow_dialog_set_items(d, msgs, 3, -1); + meow_dialog_show(d); + meow_dialog_free(d); +} + +static void browser_new_folder_in(const char *dirpath) +{ + meow_ime_ctx ime; + memset(&ime, 0, sizeof ime); + ime.mode = MEOW_IME_ASCII; + ime.maxlen = 120; + meow_ui_text_input(&ime); + char nb[FSX_MAX_NAME]; + if (fsx_sanitize_name(ime.buf, nb, sizeof nb) == 0) { + int r = fsx_mkdir(dirpath, nb); + browser_report_ret(r); + if (r == 0 && browser_is_active()) browser_reload(); + } +} + +static void browser_new_folder(void) /* 当前目录下新建 */ +{ + browser_new_folder_in(g_cur); +} + +/* BottomSheet:按行类型建不同选项清单。 */ +static void browser_open_sheet(int row) +{ + fsx_entry *e = &g_entries[row]; + char title[128]; + snprintf(title, sizeof title, "%s: %s", e->is_dir ? "Folder" : "File", e->name); + + meow_sheet *s = meow_sheet_create(title, 0); + if (e->is_dir) { + meow_sheet_add_item(s, "Open"); + meow_sheet_add_item(s, "New Folder"); + meow_sheet_add_item(s, "Rename"); + meow_sheet_add_item(s, "Delete"); + meow_sheet_add_item(s, "Properties"); + } else { + meow_sheet_add_item(s, "Open"); + meow_sheet_add_item(s, "Rename"); + meow_sheet_add_item(s, "Delete"); + meow_sheet_add_item(s, "Properties"); + } + int op = meow_sheet_open(s); + meow_sheet_free(s); + + if (op < 0) return; + if (op == 0) { /* Open */ + if (e->is_dir) browser_enter_dir(e->path); + else browser_open_file(e->path); + } else if (e->is_dir) { + if (op == 1) browser_new_folder_in(e->path); + else if (op == 2) browser_rename_entry(e); + else if (op == 3) browser_delete_entry(e); + else if (op == 4) browser_props_entry(e); + } else { + if (op == 1) browser_rename_entry(e); + else if (op == 2) browser_delete_entry(e); + else if (op == 3) browser_props_entry(e); + } + if (browser_is_active()) browser_reload(); /* 写操作后重扫(Open 文件时 viewer 前台则跳过) */ +} + +/* 打开文件:文本→预览页;否则提示。 */ +static void browser_open_file(const char *path) +{ + if (fsx_is_text_path(path)) { + if (viewer_open_file(path) == 0) return; /* 已 push 预览页 */ + browser_report_ret(-EIO); + return; + } + meow_dialog *d = meow_dialog_create(MEOW_DLG_INFO, "Preview"); + const char *msgs[1]; + msgs[0] = "This is not a text file.\nNo preview available."; + meow_dialog_set_items(d, msgs, 1, -1); + meow_dialog_show(d); + meow_dialog_free(d); +} + +/* ---- 输入分发 ---- */ + +int browser_on_tap(int x, int y) +{ + if (g_press_tapped) { browser_drag_reset(); return 1; } + if (g_tb) { + int ah = meow_topappbar_hit(g_tb, x, y); + if (ah == MEOW_TOPBAR_BACK) { browser_drag_reset(); browser_go_up(); return 1; } + if (ah >= 0) { browser_drag_reset(); browser_new_folder(); return 1; } /* NEW */ + } + if (g_err != 0 || g_n == 0) return 0; + if (meow_widget_hit(g_list, x, y)) { + int op = (x >= r_content.x + r_content.w - APP_OP_W); + int row = (y - r_content.y + g_scroll) / APP_ROW_H; + if (row < 0 || row >= g_n) { browser_drag_reset(); return 1; } + g_sel = row; + if (op) browser_open_sheet(row); + else { + fsx_entry *e = &g_entries[row]; + if (e->is_dir) browser_enter_dir(e->path); + else browser_open_file(e->path); + } + browser_drag_reset(); + return 1; + } + return 0; +} + +/* 触摸拖拽滚动(滚列表不滚页;topbar 不拖)。 */ +void browser_touch_down(int x, int y) +{ + browser_drag_reset(); + if (g_err != 0 || g_n == 0) return; + if (meow_widget_hit(g_list, x, y)) { + int row = (y - r_content.y + g_scroll) / APP_ROW_H; + if (row >= 0 && row < g_n) { + g_press_row = row; + g_press_ms = meow_ui_time_ms(); + } + g_dragging = 1; + g_drag_last_y = y; + meow_ui_invalidate(r_content.x, r_content.y, r_content.w, r_content.h); + } +} + +void browser_touch_move(int x, int y) +{ + (void)x; + if (!g_dragging) return; + if (g_press_row >= 0) { /* 拖动取消长按 */ + int d = y - g_drag_last_y; + if (d < 0) d = -d; + if (d > 0) g_press_delta += d; + if (g_press_delta > 10) g_press_row = -1; + } + int dy = y - g_drag_last_y; + g_drag_last_y = y; + if (dy == 0) return; + int ns = g_scroll - dy; + int ms = fsx_max_scroll(g_n, APP_ROW_H, browser_vp_h()); + if (ns < 0) ns = 0; + if (ns > ms) ns = ms; + if (ns != g_scroll) { + g_scroll = ns; + meow_ui_invalidate(r_content.x, r_content.y, r_content.w, r_content.h); + } +} + +void browser_swipe(int dir, int dist) +{ + if (dir != MEOW_SWIPE_UP && dir != MEOW_SWIPE_DOWN) return; + if (g_err != 0 || g_n == 0) return; + int del = (dir == MEOW_SWIPE_UP) ? dist : -dist; /* 上滑→显示更低内容 */ + int ns = g_scroll + del; + int ms = fsx_max_scroll(g_n, APP_ROW_H, browser_vp_h()); + if (ns < 0) ns = 0; + if (ns > ms) ns = ms; + if (ns != g_scroll) { + g_scroll = ns; + meow_ui_invalidate(r_content.x, r_content.y, r_content.w, r_content.h); + } +} + +/* on_tick:长按(≥500ms 未拖动)→ 打开该行 BottomSheet。 */ +void browser_tick(uint64_t now) +{ + if (g_press_row >= 0 && !g_press_tapped && now - g_press_ms >= 500) { + g_press_tapped = 1; + int row = g_press_row; + g_press_row = -1; + browser_open_sheet(row); /* 内部:写操作后自行 reload */ + } +} + +/* ---- 页 view 生命周期 ---- */ + +static void browser_page_create(meow_view *v, void *ctx) +{ + (void)v; + ((browser_ctrl *)ctx)->view = v; + r_content = app_content_rect(); + strncpy(g_cur, FSX_SD_ROOT, sizeof g_cur - 1); + g_cur[sizeof g_cur - 1] = '\0'; + g_tb = app_topbar_create("Files", 1, "NEW"); + g_list = meow_widget_custom_create(r_content.x, r_content.y, r_content.w, r_content.h, + browser_render, browser_hit, NULL); + g_sel = -1; + g_press_row = -1; + browser_reload(); +} + +static void browser_page_enter(meow_view *v, void *ctx) +{ + (void)v; + ((browser_ctrl *)ctx)->active = 1; + const meow_theme *th = meow_theme_get(); + meow_ui_set_page_bg(th->bg); + meow_ui_paint_full(); +} + +static void browser_page_leave(meow_view *v, void *ctx) +{ + (void)v; + ((browser_ctrl *)ctx)->active = 0; +} + +static void browser_page_destroy(meow_view *v, void *ctx) +{ + (void)v; (void)ctx; + if (g_list) { meow_widget_free(g_list); g_list = NULL; } + if (g_tb) { meow_widget_free(g_tb); g_tb = NULL; } +} + +meow_view *browser_view_create(void) +{ + static const meow_view_hooks h = { + .on_create = browser_page_create, + .on_enter = browser_page_enter, + .on_leave = browser_page_leave, + .on_destroy = browser_page_destroy, + }; + return meow_view_create(ACT_BROWSER, MEOW_VIEW_ACTIVITY, &h, &g_bc); +} diff --git a/patch_v2/files_app/ui/common/chrome.c b/patch_v2/files_app/ui/common/chrome.c new file mode 100644 index 0000000..2f21612 --- /dev/null +++ b/patch_v2/files_app/ui/common/chrome.c @@ -0,0 +1,57 @@ +/* ui/common/chrome.c — files 应用共享 chrome(TopAppBar 建置 / 几何 / 空态&页脚绘制)。 + * + * 与 hello_app/ui/common/chrome.c 同理:把「页面 chrome 固定不随内容重建」分出去;本模块只 + * 提供几何计算 + topbar 建置 + 非控件直绘辅助(空态/页脚),供 browser/viewer 两页复用。 + * 绘制全部读 meow_theme_get() 语义色(§8.1),不硬编码配色;topbar 由 meow_topappbar 建, + * 自动注册进绘制物注册表(§6.2),owner=创建时 active activity。 + */ +#include "files_internal.h" + +int app_statusbar(void) +{ + int sb = meow_ui_statusbar_height(); + return sb < 0 ? 0 : sb; +} + +app_rect_t app_topbar_rect(void) +{ + int sb = app_statusbar(); + return AR(0, sb, meow_ui_width(), APP_TOPBAR_H); +} + +app_rect_t app_content_rect(void) +{ + int sb = app_statusbar(); + int y = sb + APP_TOPBAR_H; + int h = meow_ui_height() - y; + if (h < 0) h = 0; + return AR(0, y, meow_ui_width(), h); +} + +meow_widget *app_topbar_create(const char *title, int back, const char *action_label) +{ + app_rect_t r = app_topbar_rect(); + meow_widget *tb = meow_topappbar_create(r.x, r.y, r.w, r.h, title); + meow_topappbar_set_back(tb, back); + if (action_label) meow_topappbar_add_action(tb, action_label); + meow_widget_set_z(tb, 999); /* chrome 置顶(§6.2:> 一切自动 z,区域重画最后画它) */ + return tb; +} + +/* 空态/错误:居中两行(kind 大字 + what 小字)。kind=状态标题,what=说明/路径。 */ +void app_draw_empty(app_rect_t r, const char *kind, const char *what) +{ + const meow_theme *th = meow_theme_get(); + int cy = r.y + r.h / 2; + meow_ui_text_center(r.x + r.w / 2, cy - 34, kind ? kind : "", 28, th->primary); + if (what && what[0]) + meow_ui_text_center(r.x + r.w / 2, cy + 4, what, 20, th->dim); +} + +/* 底部信息(右对齐 dim):项数/路径/截断提示。 */ +void app_draw_footer(app_rect_t r, const char *text) +{ + const meow_theme *th = meow_theme_get(); + if (!text || !text[0]) return; + meow_ui_text_right(r.x + r.w - APP_PAD, r.y + r.h - 26, text, 20, th->dim); +} diff --git a/patch_v2/files_app/ui/viewer.c b/patch_v2/files_app/ui/viewer.c new file mode 100644 index 0000000..fdfcafc --- /dev/null +++ b/patch_v2/files_app/ui/viewer.c @@ -0,0 +1,281 @@ +/* ui/viewer.c — 文本预览页(ACT_VIEWER,子页)view + 控制器。 + * + * 只读、可滚动、≤256KB 截断(APP_READ_MAX,超长只读前 256KB)。 + * 行模型:把读入内容按 '\n' 切成逻辑行(<= VIEWER_MAX_LINES,超长截断并附加提示); + * 每逻辑行按可视列宽软换行成「屏幕行」;滚动按屏幕行像素仿真化(只画可见屏幕行)。 + * 打开时 meow_view_page_push(ACT_VIEWER)(on_enter 置标题/清滚动/整帧重画);返回=左缘左滑/返回钮。 + */ +#include "files_internal.h" + +#include +#include +#include +#include +#include + +typedef struct { meow_view *view; int active; } viewer_ctrl; +static viewer_ctrl g_vc; + +#define VIEWER_MAX_LINES 8192 /* 逻辑行上限(超长折行会很多,但按行数界内存) */ + +static char *g_buf; /* malloc'd 读入内容(前 256KB,NUL 结尾) */ +static size_t g_buf_len; +static char g_fname[FSX_MAX_NAME]; +static int *g_line; /* g_nline 个:每逻辑行起始偏移 */ +static int g_nline; +static int *g_rown; /* g_nline 个:每逻辑行对应的首「屏幕行」下标 */ +static int g_nrows; /* 总屏幕行数(= 末行 rown + 其折行数) */ +static int g_vscroll; /* 滚动偏移(px) */ +static int g_vdrag, g_vdrag_last_y; + +static meow_widget *g_tb; +static meow_widget *g_vcw; /* 内容区 custom widget(画文本行) */ +static app_rect_t r_content; + +/* 可视列宽(像素)。 */ +static int viewer_colw(void) { return r_content.w - 2 * APP_PAD; } +/* 文本行区视口高(底部留页脚)。 */ +static int viewer_vp_h(void) { return r_content.h - APP_FOOTER_H; } +/* 屏幕行高(px)。 */ +static int viewer_rowh(const meow_theme *th) { return meow_ui_text_height(th->font_body) + 6; } + +/* 折行:返回逻辑行 li 折成的屏幕行数;若 intra>=0,把该屏幕行文本写入 out(NUL 结尾)。 */ +static int viewer_wrap_line(int li, int intra, char *out, int outsz) +{ + if (!g_buf || li < 0 || li >= g_nline) return 0; + int start = g_line[li]; + int end = (li + 1 < g_nline) ? g_line[li + 1] : (int)g_buf_len; + int len = end - start; + while (len > 0 && (g_buf[start + len - 1] == '\n' || g_buf[start + len - 1] == '\r')) len--; + int colw = viewer_colw(); + int col = 0, row = 0, outlen = 0; + char ch[2]; ch[1] = '\0'; + for (int i = 0; i < len; i++) { + ch[0] = g_buf[start + i]; + if (ch[0] == '\r') continue; + int w = meow_ui_text_width(ch, 20); + if (col + w > colw && col > 0) { row++; col = 0; } + if (row == intra && out && outlen < outsz - 1) out[outlen++] = ch[0]; + col += w; + } + if (out) out[outlen] = '\0'; + return row + 1; +} + +/* 读入文件并建行表;0=文本预览可读,-1=非文本/读失败。 */ +static int viewer_build(const char *path) +{ + free(g_buf); free(g_line); free(g_rown); + g_buf = NULL; g_line = NULL; g_rown = NULL; + g_nline = 0; g_nrows = 0; g_buf_len = 0; + g_fname[0] = '\0'; + + int fd = open(path, O_RDONLY); + if (fd < 0) return -1; + size_t cap = APP_READ_MAX + 1; + g_buf = (char *)malloc(cap); + if (!g_buf) { close(fd); return -1; } + ssize_t n = read(fd, g_buf, APP_READ_MAX); + close(fd); + if (n <= 0) { free(g_buf); g_buf = NULL; return -1; } + g_buf_len = (size_t)n; + g_buf[g_buf_len] = '\0'; + + /* 非文本嗅探:前 512 字节出现 NUL 视为二进制 */ + int lim = (int)(g_buf_len < 512 ? g_buf_len : 512); + for (int i = 0; i < lim; i++) if (g_buf[i] == '\0') { free(g_buf); g_buf = NULL; return -1; } + + /* 文件名 */ + const char *bn = fsx_basename(path); + strncpy(g_fname, bn, FSX_MAX_NAME - 1); + g_fname[FSX_MAX_NAME - 1] = '\0'; + + /* 切逻辑行(上限 VIEWER_MAX_LINES;超出截断,末行吸收剩余 + 附截断提示) */ + int cap_l = VIEWER_MAX_LINES; + g_line = (int *)malloc((size_t)cap_l * sizeof(int)); + g_rown = (int *)malloc((size_t)cap_l * sizeof(int)); + if (!g_line || !g_rown) { free(g_buf); free(g_line); free(g_rown); g_buf = NULL; g_line=NULL; g_rown=NULL; return -1; } + g_nline = 0; + g_line[g_nline++] = 0; + int truncated = 0; + for (size_t i = 0; i < g_buf_len; i++) { + if (g_buf[i] == '\n') { + if (g_nline < cap_l) g_line[g_nline++] = (int)i + 1; + else { truncated = 1; break; } + } + } + if (truncated) { + g_line[g_nline - 1] = (int)g_buf_len; /* 让最后一行吸收剩余 */ + } + + /* 折行累加 → 屏幕行下标 */ + g_nrows = 0; + for (int li = 0; li < g_nline; li++) { + g_rown[li] = g_nrows; + g_nrows += viewer_wrap_line(li, -1, NULL, 0); + } + + return 0; +} + +/* 宿主测试/入口兼容:读入 buffer 并解析行。 */ +void viewer_load(const char *path) { viewer_build(path); } + +/* 内容区 render_cb:虚拟化画可见屏幕行。 */ +static void viewer_render(meow_widget *w, const meow_theme *th, void *ctx) +{ + (void)w; (void)ctx; + if (!g_buf || g_nrows <= 0) { + app_draw_empty(r_content, "NOT A TEXT FILE", g_fname[0] ? g_fname : ""); + return; + } + int rowh = viewer_rowh(th); + if (rowh < 1) rowh = 1; + int vp = viewer_vp_h(); + int top = g_vscroll / rowh; + int bot = (g_vscroll + vp) / rowh + 1; + if (top < 0) top = 0; + if (bot > g_nrows) bot = g_nrows; + + char row[512]; + for (int sr = top; sr < bot; sr++) { + /* 二分找逻辑行 li:g_rown[li] <= sr 的最大 li */ + int lo = 0, hi = g_nline - 1, li = 0; + while (lo <= hi) { + int mid = (lo + hi) / 2; + if (g_rown[mid] <= sr) { li = mid; lo = mid + 1; } + else { hi = mid - 1; } + } + int intra = sr - g_rown[li]; + row[0] = '\0'; + viewer_wrap_line(li, intra, row, (int)sizeof row); + if (!row[0] && intra == 0) row[0] = ' ', row[1] = '\0'; + int ry = r_content.y + (sr * rowh - g_vscroll); + if (ry < r_content.y) continue; + if (ry >= r_content.y + vp) break; + meow_ui_text(r_content.x + APP_PAD, ry, row, th->font_body, th->onSurface); + } + /* 页脚:行数 + 文件名(含截断提示) */ + char foot[128]; + if (g_buf_len >= APP_READ_MAX) + snprintf(foot, sizeof foot, ">256KB (truncated) %d row(s)", g_nrows); + else + snprintf(foot, sizeof foot, "%d row(s)", g_nrows); + app_draw_footer(r_content, foot); +} + +static int viewer_hit(meow_widget *w, int x, int y, void *ctx) +{ + (void)w; (void)ctx; + return x >= r_content.x && x < r_content.x + r_content.w && + y >= r_content.y && y < r_content.y + r_content.h; +} + +static void viewer_clamp_scroll(void) +{ + const meow_theme *th = meow_theme_get(); + int rowh = viewer_rowh(th); + int content_h = g_nrows * rowh; + int maxs = content_h - viewer_vp_h(); + if (maxs < 0) maxs = 0; + if (g_vscroll < 0) g_vscroll = 0; + if (g_vscroll > maxs) g_vscroll = maxs; +} + +int viewer_open_file(const char *path) +{ + if (viewer_build(path) != 0) return -1; + meow_view_page_push(ACT_VIEWER); + return 0; +} + +int viewer_is_active(void) { return g_vc.active; } + +void viewer_swipe(int dir, int dist) +{ + if (dir != MEOW_SWIPE_UP && dir != MEOW_SWIPE_DOWN) return; + int del = (dir == MEOW_SWIPE_UP) ? dist : -dist; + g_vscroll += del; + viewer_clamp_scroll(); + meow_ui_invalidate(r_content.x, r_content.y, r_content.w, r_content.h); +} + +void viewer_touch_down(int x, int y) +{ + (void)x; + g_vdrag = 0; g_vdrag_last_y = 0; + if (!g_buf) return; + if (meow_widget_hit(g_vcw, x, y)) { g_vdrag = 1; g_vdrag_last_y = y; } +} + +void viewer_touch_move(int x, int y) +{ + (void)x; + if (!g_vdrag) return; + int dy = y - g_vdrag_last_y; + g_vdrag_last_y = y; + if (dy == 0) return; + g_vscroll -= dy; + viewer_clamp_scroll(); + meow_ui_invalidate(r_content.x, r_content.y, r_content.w, r_content.h); +} + +int viewer_on_tap(int x, int y) +{ + if (g_tb) { + int ah = meow_topappbar_hit(g_tb, x, y); + if (ah == MEOW_TOPBAR_BACK) { meow_view_page_pop(); return 1; } + } + return 0; +} + +/* ---- 页 view 生命周期 ---- */ + +static void viewer_page_create(meow_view *v, void *ctx) +{ + (void)v; + ((viewer_ctrl *)ctx)->view = v; + r_content = app_content_rect(); + meow_ui_activity_push(ACT_VIEWER); /* 让下面控件 owner=ACT_VIEWER */ + g_tb = app_topbar_create("Preview", 1, NULL); + g_vcw = meow_widget_custom_create(r_content.x, r_content.y, r_content.w, r_content.h, + viewer_render, viewer_hit, NULL); + meow_ui_activity_pop(); +} + +static void viewer_page_enter(meow_view *v, void *ctx) +{ + (void)v; + ((viewer_ctrl *)ctx)->active = 1; + g_vscroll = 0; + if (g_tb) meow_topappbar_set_title(g_tb, g_fname[0] ? g_fname : "Preview"); + const meow_theme *th = meow_theme_get(); + meow_ui_set_page_bg(th->bg); + meow_ui_paint_full(); +} + +static void viewer_page_leave(meow_view *v, void *ctx) +{ + (void)v; + ((viewer_ctrl *)ctx)->active = 0; +} + +static void viewer_page_destroy(meow_view *v, void *ctx) +{ + (void)v; (void)ctx; + if (g_vcw) { meow_widget_free(g_vcw); g_vcw = NULL; } + if (g_tb) { meow_widget_free(g_tb); g_tb = NULL; } + free(g_buf); free(g_line); free(g_rown); + g_buf = NULL; g_line = NULL; g_rown = NULL; +} + +meow_view *viewer_view_create(void) +{ + static const meow_view_hooks h = { + .on_create = viewer_page_create, + .on_enter = viewer_page_enter, + .on_leave = viewer_page_leave, + .on_destroy = viewer_page_destroy, + }; + return meow_view_create(ACT_VIEWER, MEOW_VIEW_ACTIVITY, &h, &g_vc); +}