From f8b37564dad6c76989b345b0a070b6f08c232b2c Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Fri, 16 Oct 2026 16:29:04 +0800 Subject: [PATCH] =?UTF-8?q?refactor(vpui):=20=E5=BC=95=E5=85=A5=20tkinter?= =?UTF-8?q?=20=E5=BC=8F=E7=B1=BB=E5=B1=82=E6=AC=A1=20Misc/Wm/BaseWidget/Wi?= =?UTF-8?q?dget=EF=BC=8C=E6=96=B0=E5=A2=9E=E5=AE=B9=E5=99=A8=E6=8E=A7?= =?UTF-8?q?=E4=BB=B6=20Frame?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 层次:Misc(mixin:master/tk + winfo_master/toplevel + bind/unbind) ├─ Tk(Wm, Misc) └─ BaseWidget(Misc) └─ Widget(BaseWidget) ← Label/Button/Entry/Scrollbar/FBCanvas/Text/Frame 全部继承 Widget。约束按 Test/MultiInheritTest 的布局模型:父类字段展平进子类、非首基类必须无字段(故 Wm 无字段)、基类方法内不做 self.<虚拟> 自我分派(多继承非最左基类的虚表索引会整体后移)。控件 master 由 Widget* 改为 Misc*(Tk* 成为合法上转型),原先 8 处 Tk*(self.master) 裸转改为 self.tk;事件派发统一走 BaseWidget.dispatch_event(先跑 bind 回调再 handle_event)。中文。 --- vpsdk/vpui.vp | 724 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 495 insertions(+), 229 deletions(-) diff --git a/vpsdk/vpui.vp b/vpsdk/vpui.vp index 4b49ad8..ff567bd 100644 --- a/vpsdk/vpui.vp +++ b/vpsdk/vpui.vp @@ -1,8 +1,6 @@ import vpsdk.window as window import vpsdk.process as process import vpsdk.syscall as _syscall -from stdint import * -import t, c import string define TITLE_H = 32 @@ -16,6 +14,7 @@ define WIDGET_ENTRY = 3 define WIDGET_TEXT = 4 define WIDGET_SCROLLBAR = 5 define WIDGET_FBCANVAS = 6 +define WIDGET_FRAME = 7 define VERTICAL = 1 define HORIZONTAL = 2 @@ -38,26 +37,26 @@ define STICKY_N = 4 define STICKY_S = 8 define STICKY_NSEW = 15 -_g_wl_type: t.CArray[int, MAX_WIDGETS] -_g_wl_side: t.CArray[int, MAX_WIDGETS] -_g_wl_fill: t.CArray[int, MAX_WIDGETS] -_g_wl_expand: t.CArray[int, MAX_WIDGETS] -_g_wl_padx: t.CArray[int, MAX_WIDGETS] -_g_wl_pady: t.CArray[int, MAX_WIDGETS] -_g_wl_row: t.CArray[int, MAX_WIDGETS] -_g_wl_col: t.CArray[int, MAX_WIDGETS] -_g_wl_rowspan: t.CArray[int, MAX_WIDGETS] -_g_wl_colspan: t.CArray[int, MAX_WIDGETS] -_g_wl_sticky: t.CArray[int, MAX_WIDGETS] +_g_wl_type: [MAX_WIDGETS]int +_g_wl_side: [MAX_WIDGETS]int +_g_wl_fill: [MAX_WIDGETS]int +_g_wl_expand: [MAX_WIDGETS]int +_g_wl_padx: [MAX_WIDGETS]int +_g_wl_pady: [MAX_WIDGETS]int +_g_wl_row: [MAX_WIDGETS]int +_g_wl_col: [MAX_WIDGETS]int +_g_wl_rowspan: [MAX_WIDGETS]int +_g_wl_colspan: [MAX_WIDGETS]int +_g_wl_sticky: [MAX_WIDGETS]int _g_layout_init: int -_hex_tbl: t.CArray[char, 17] = "0123456789ABCDEF" -_hex_buf: t.CArray[char, 20] = "0000000000000000000" +_hex_tbl: [17]char = "0123456789ABCDEF" +_hex_buf: [20]char = "0000000000000000000" def _serial_puts(s: const str): _syscall._syscall1(uint64(_syscall.SERIAL_PUTS), uint64(s)) -def _ptr_to_hex(val: uint64, buf: t.CPtr): +def _ptr_to_hex(val: uint64, buf: rawptr): buf[0] = 48 buf[1] = 120 i: int = 15 @@ -68,7 +67,7 @@ def _ptr_to_hex(val: uint64, buf: t.CPtr): i -= 1 buf[18] = 0 -def _fill_rect(fb: UINT32PTR, fw: int, fh: int, x1: int, y1: int, w: int, h: int, color: uint32): +def _fill_rect(fb: uint32*, fw: int, fh: int, x1: int, y1: int, w: int, h: int, color: uint32): if not fb: return if x1 < 0: w += x1; x1 = 0 if y1 < 0: h += y1; y1 = 0 @@ -79,14 +78,14 @@ def _fill_rect(fb: UINT32PTR, fw: int, fh: int, x1: int, y1: int, w: int, h: int if px >= 0 and px < fw: fb[py * fw + px] = color -def _draw_hline(fb: UINT32PTR, fw: int, fh: int, x1: int, y: int, w: int, color: uint32): +def _draw_hline(fb: uint32*, fw: int, fh: int, x1: int, y: int, w: int, color: uint32): if not fb: return if y < 0 or y >= fh: return for px in range(x1, x1 + w): if px >= 0 and px < fw: fb[y * fw + px] = color -def _draw_vline(fb: UINT32PTR, fw: int, fh: int, x: int, y1: int, h: int, color: uint32): +def _draw_vline(fb: uint32*, fw: int, fh: int, x: int, y1: int, h: int, color: uint32): if not fb: return if x < 0 or x >= fw: return for py in range(y1, y1 + h): @@ -112,138 +111,138 @@ def _darken(color: uint32, amount: int) -> uint32: return uint32(r | (g << 8) | (b << 16)) -font: t.CArray[t.CArray[uint8, 16], 256] = [ - {0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x02,0x56,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x42,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x55,0x55,0x57,0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x54,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x51,0x52,0x72,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x56,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x54,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x50,0x50,0x57,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x51,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x57,0x55,0x57,0x74,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x53,0x54,0x56,0x74,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x15,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x32,0x16,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x20,0x6E,0x22,0x2E,0x28,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x11,0x13,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x35,0x15,0x17,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x14,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x11,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x36,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x34,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x30,0x10,0x17,0x14,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x31,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x37,0x15,0x17,0x14,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x10,0x33,0x14,0x16,0x14,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, - {0x6C,0x6C,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x00,0x00,0x00}, - {0x0C,0x0C,0x3E,0x7F,0x68,0x68,0x3E,0x0B,0x0B,0x7F,0x3E,0x18,0x18,0x00,0x00,0x00}, - {0x60,0x60,0x66,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x66,0x06,0x06,0x00,0x00,0x00}, - {0x38,0x6C,0x6C,0x6C,0x6C,0x6C,0x38,0x6C,0x6D,0x66,0x66,0x6F,0x3B,0x00,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x1C,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00}, - {0x38,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x38,0x00,0x00}, - {0x00,0x00,0x18,0x18,0x7E,0x3C,0x3C,0x3C,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x18,0x18,0x18,0x7E,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x6E,0x6E,0x7E,0x76,0x76,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x18,0x38,0x78,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x06,0x0E,0x1C,0x38,0x70,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x06,0x1C,0x1C,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x0C,0x0C,0x1C,0x1C,0x3C,0x2C,0x6C,0x7E,0x7E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x06,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3C,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00}, - {0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x40,0x60,0x30,0x18,0x0C,0x06,0x06,0x0C,0x18,0x30,0x60,0x40,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x6E,0x6A,0x6A,0x6A,0x6E,0x60,0x60,0x7C,0x3C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7C,0x7C,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x78,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0x7C,0x78,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x60,0x6E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x3E,0x3E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x7C,0x38,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x6C,0x6C,0x78,0x78,0x78,0x6C,0x6C,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x76,0x76,0x7E,0x6E,0x6E,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x6A,0x6A,0x6C,0x7E,0x36,0x00,0x00,0x00}, - {0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x3C,0x7E,0x66,0x60,0x60,0x78,0x3C,0x0E,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, - {0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x77,0x77,0x22,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x66,0x66,0x66,0x66,0x7E,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, - {0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00}, - {0x78,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x78,0x00,0x00}, - {0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x0C,0x0C,0x06,0x06,0x03,0x03,0x00,0x00,0x00}, - {0x1E,0x1E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x1E,0x1E,0x00,0x00}, - {0x3C,0x7E,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00}, - {0x30,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x3E,0x06,0x3E,0x7E,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x06,0x06,0x06,0x06,0x3E,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x7E,0x7E,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x1C,0x3E,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x3E,0x3C,0x00}, - {0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x18,0x18,0x00,0x00,0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x0C,0x0C,0x00,0x00,0x3C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C,0x78,0x00}, - {0x60,0x60,0x60,0x60,0x66,0x66,0x6C,0x78,0x78,0x6C,0x6C,0x66,0x66,0x00,0x00,0x00}, - {0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x36,0x7F,0x6B,0x6B,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x00}, - {0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x07,0x07,0x00}, - {0x00,0x00,0x00,0x00,0x6C,0x7E,0x76,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x3C,0x7E,0x62,0x70,0x3C,0x0E,0x46,0x7E,0x3C,0x00,0x00,0x00}, - {0x30,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x7F,0x36,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x00,0x00,0x00}, - {0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x7E,0x7C,0x00}, - {0x00,0x00,0x00,0x00,0x7E,0x7E,0x0C,0x0C,0x18,0x30,0x30,0x7E,0x7E,0x00,0x00,0x00}, - {0x0E,0x1E,0x18,0x18,0x18,0x18,0x30,0x30,0x18,0x18,0x18,0x18,0x1E,0x0E,0x00,0x00}, - {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00}, - {0x70,0x78,0x18,0x18,0x18,0x18,0x0C,0x0C,0x18,0x18,0x18,0x18,0x78,0x70,0x00,0x00}, - {0x31,0x79,0x6B,0x4F,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, - {0x00,0x00,0x70,0x13,0x24,0x26,0x24,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, +font: [256][16]uint8 = [ + [0x00,0x00,0x00,0x00,0x00,0x40,0x55,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x55,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x02,0x56,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x42,0x56,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x55,0x55,0x57,0x71,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x54,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x51,0x52,0x72,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x55,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x55,0x57,0x71,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x56,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x54,0x54,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x50,0x50,0x57,0x74,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x51,0x51,0x57,0x75,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x57,0x55,0x57,0x74,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x53,0x54,0x56,0x74,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x15,0x15,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x32,0x16,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x20,0x6E,0x22,0x2E,0x28,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x11,0x13,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x35,0x15,0x17,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x14,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x11,0x12,0x12,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x15,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x15,0x17,0x11,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x36,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x34,0x14,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x30,0x10,0x17,0x14,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x31,0x11,0x17,0x15,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x37,0x15,0x17,0x14,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x10,0x33,0x14,0x16,0x14,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00], + [0x6C,0x6C,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x7F,0x7F,0x36,0x36,0x36,0x00,0x00,0x00], + [0x0C,0x0C,0x3E,0x7F,0x68,0x68,0x3E,0x0B,0x0B,0x7F,0x3E,0x18,0x18,0x00,0x00,0x00], + [0x60,0x60,0x66,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x66,0x06,0x06,0x00,0x00,0x00], + [0x38,0x6C,0x6C,0x6C,0x6C,0x6C,0x38,0x6C,0x6D,0x66,0x66,0x6F,0x3B,0x00,0x00,0x00], + [0x18,0x18,0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x1C,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00], + [0x38,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x38,0x00,0x00], + [0x00,0x00,0x18,0x18,0x7E,0x3C,0x3C,0x3C,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x18,0x18,0x18,0x7E,0x7E,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00], + [0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x00,0x00,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x6E,0x6E,0x7E,0x76,0x76,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x18,0x38,0x78,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x06,0x06,0x0E,0x1C,0x38,0x70,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x06,0x06,0x1C,0x1C,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x0C,0x0C,0x1C,0x1C,0x3C,0x2C,0x6C,0x7E,0x7E,0x0C,0x0C,0x0C,0x0C,0x00,0x00,0x00], + [0x7E,0x7E,0x60,0x60,0x7C,0x7E,0x06,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3C,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x30,0x00], + [0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0x60,0x30,0x18,0x0C,0x06,0x02,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x7E,0x7E,0x00,0x00,0x7E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x40,0x60,0x30,0x18,0x0C,0x06,0x06,0x0C,0x18,0x30,0x60,0x40,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x6E,0x6A,0x6A,0x6A,0x6E,0x60,0x60,0x7C,0x3C,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x7C,0x7E,0x66,0x66,0x66,0x7C,0x7C,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x78,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0x7C,0x78,0x00,0x00,0x00], + [0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00], + [0x7E,0x7E,0x60,0x60,0x60,0x7C,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x60,0x60,0x60,0x6E,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x66,0x7E,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00], + [0x3E,0x3E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x7C,0x38,0x00,0x00,0x00], + [0x66,0x66,0x66,0x6C,0x6C,0x78,0x78,0x78,0x6C,0x6C,0x66,0x66,0x66,0x00,0x00,0x00], + [0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00], + [0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x76,0x76,0x7E,0x6E,0x6E,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x6A,0x6A,0x6C,0x7E,0x36,0x00,0x00,0x00], + [0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x6C,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x3C,0x7E,0x66,0x60,0x60,0x78,0x3C,0x0E,0x06,0x06,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x7E,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00], + [0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x77,0x77,0x22,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x66,0x66,0x66,0x66,0x7E,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00], + [0x7E,0x7E,0x06,0x06,0x0C,0x0C,0x18,0x30,0x30,0x60,0x60,0x7E,0x7E,0x00,0x00,0x00], + [0x78,0x78,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x78,0x78,0x00,0x00], + [0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x0C,0x0C,0x06,0x06,0x03,0x03,0x00,0x00,0x00], + [0x1E,0x1E,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x1E,0x1E,0x00,0x00], + [0x3C,0x7E,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00], + [0x30,0x38,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3C,0x3E,0x06,0x3E,0x7E,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00], + [0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x7C,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x60,0x60,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x06,0x06,0x06,0x06,0x3E,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x7E,0x7E,0x60,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x1C,0x3E,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x3E,0x3C,0x00], + [0x60,0x60,0x60,0x60,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x18,0x18,0x00,0x00,0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00], + [0x0C,0x0C,0x00,0x00,0x3C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x7C,0x78,0x00], + [0x60,0x60,0x60,0x60,0x66,0x66,0x6C,0x78,0x78,0x6C,0x6C,0x66,0x66,0x00,0x00,0x00], + [0x38,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x7E,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x36,0x7F,0x6B,0x6B,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3C,0x7E,0x66,0x66,0x66,0x66,0x66,0x7E,0x3C,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x7C,0x7E,0x66,0x66,0x66,0x7E,0x7C,0x60,0x60,0x60,0x60,0x00], + [0x00,0x00,0x00,0x00,0x3E,0x7E,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x07,0x07,0x00], + [0x00,0x00,0x00,0x00,0x6C,0x7E,0x76,0x60,0x60,0x60,0x60,0x60,0x60,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x3C,0x7E,0x62,0x70,0x3C,0x0E,0x46,0x7E,0x3C,0x00,0x00,0x00], + [0x30,0x30,0x30,0x30,0x7C,0x7C,0x30,0x30,0x30,0x30,0x30,0x3C,0x1C,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x3C,0x18,0x18,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x7F,0x36,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x3C,0x18,0x3C,0x3C,0x66,0x66,0x00,0x00,0x00], + [0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x7E,0x3E,0x06,0x06,0x7E,0x7C,0x00], + [0x00,0x00,0x00,0x00,0x7E,0x7E,0x0C,0x0C,0x18,0x30,0x30,0x7E,0x7E,0x00,0x00,0x00], + [0x0E,0x1E,0x18,0x18,0x18,0x18,0x30,0x30,0x18,0x18,0x18,0x18,0x1E,0x0E,0x00,0x00], + [0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00], + [0x70,0x78,0x18,0x18,0x18,0x18,0x0C,0x0C,0x18,0x18,0x18,0x18,0x78,0x70,0x00,0x00], + [0x31,0x79,0x6B,0x4F,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], + [0x00,0x00,0x70,0x13,0x24,0x26,0x24,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00], ] -def _draw_char(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, ch: char, color: uint32): +def _draw_char(buf: uint32*, bw: int, bh: int, x: int, y: int, ch: char, color: uint32): if not buf: return if bw <= 0 or bh <= 0: return ci: uint8 = uint8(ch) @@ -264,7 +263,7 @@ def _draw_char(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, ch: char, color buf[(y + fy) * bw + px] = color fy += 1 -def _draw_text(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, s: const str, color: uint32): +def _draw_text(buf: uint32*, bw: int, bh: int, x: int, y: int, s: const str, color: uint32): if not buf: return if bw <= 0 or bh <= 0: return cx: int = x @@ -281,26 +280,219 @@ def _draw_text(buf: UINT32PTR, bw: int, bh: int, x: int, y: int, s: const str, c cx += 8 i += 1 -def _register_widget(master: t.CPtr, widget: Widget*) -> int: - tk: Tk* = t.CType(master, Tk, t.CPtr) +# ============================================================================ +# tkinter 风格的抽象基类层次(仿 tkinter 原始抽象) +# +# Misc(mixin:master/tk 公共状态 + winfo_master/toplevel、bind 等公共方法) +# ├─ Tk(Wm, Misc) 主窗口类(Wm 声明 WM 协议面,Tk 提供落地实现) +# └─ BaseWidget(Misc) +# └─ Widget(BaseWidget) 所有普通控件的抽象基类(Button/Label/Entry… 都继承 Widget) +# +# 字段模型(与 Test/MultiInheritTest 一致):父类字段被**展平**进子类,子类自己的方法可 +# 直接访问全部展平字段;字段偏移按"定义该方法的那一层"自己的展平布局计算(该测试里 +# ColoredCircle(ShapeM, ColorM) = (ptr, i32, f64):偏移 0 是唯一的共享 vptr,各基类字段依次 +# 跟在后面,虚表被合并)。由此有三条硬约束: +# ① Misc 的字段必须在所有派生类里落到同一偏移 —— 偏移 0 被共享 vptr 占用,Misc 的字段 +# 从 8 起,只要它前面没有"带字段的基类"就成立; +# ② 因此 `Wm`(Tk 的最左基类)必须**无字段**,否则会把 Misc 的字段整体后移,而 Misc 自己 +# 的方法仍按自身布局取偏移 ⇒ 静默错位; +# ③ 基类方法里**不要写 `self.<虚拟方法>()` 的自我分派**:多继承下非最左基类的方法在派生 +# 类的合并虚表里整体后移,而方法体内按"定义类自己的虚表"取索引 ⇒ 会指到别的槽位。 +# 所以 winfo_*/title 这类"需要看具体对象状态"的方法一律在 Misc / Wm 里只做声明,由 +# Tk / Widget 覆写实现;外部按具体类型调用即可正常走虚表。 +# ============================================================================ + +# ---- bind 回调注册表:按 (对象, 事件类型) 记录回调。 +# tkinter 用 这类字符串作为 sequence,这里改用 window.EVENT_TYPE_* 整型 +# (本运行时的事件类型就是这些整型,比较字符串在 VPC 模型下既慢又易错)。 +define MAX_BINDINGS = 64 + +_bind_obj: [MAX_BINDINGS]Misc* = [None] +_bind_seq: [MAX_BINDINGS]int = [0] +_bind_cb: [MAX_BINDINGS]rawptr = [None] + +def _bind_add(obj: Misc*, seq: int, func: rawptr) -> int: + i: int = 0 + while i < MAX_BINDINGS: + if _bind_obj[i] is None: + _bind_obj[i] = obj + _bind_seq[i] = seq + _bind_cb[i] = func + return i + i += 1 + return -1 + +def _bind_remove(obj: Misc*, seq: int) -> int: + i: int = 0 + while i < MAX_BINDINGS: + if _bind_obj[i] is obj and _bind_seq[i] == seq: + _bind_obj[i] = None + _bind_cb[i] = None + return 0 + i += 1 + return -1 + +def _bind_invoke(obj: Misc*, seq: int, evt: window.InputEvent*) -> int: + i: int = 0 + while i < MAX_BINDINGS: + if _bind_obj[i] is obj and _bind_seq[i] == seq: + cb: rawptr = _bind_cb[i] + if cb is None: return 0 + # 与 Button 回调同一约定:rawptr 是 VPC 生成的闭包对象 {fn, env}, + # fn 期望 rdi = env ⇒ 必须取 [cb+8] 传 rdi、再由 [cb] 调用。 + __asm__(f"""push r12 +push r13 +mov r13, {asminp(cb, ASM_DESCR.REG_ANY)} +mov rdi, qword ptr [r13 + 8] +mov r12, rsp +and rsp, -16 +call qword ptr [r13] +mov rsp, r12 +pop r13 +pop r12""", + op=[ASM_DESCR.CLOBBER_MEMORY, + ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, + ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RSI, + ASM_DESCR.CLOBBER_RDI, + ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9, + ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11]) + return 1 + i += 1 + return 0 + +# ---- Misc:Tk 与所有控件的公共 mixin ---- +# 只放"所有 Tk 对象都有的东西":公共状态(master/tk)、公共方法(winfo_master/toplevel、bind), +# 以及需要各具体类自己回答的查询(winfo_x/… 这里只声明,由 Tk / Widget 覆写)。 +# 约束:这里**不做 `self.<虚拟方法>()` 的自我分派**。多继承下非最左基类的方法在派生类的 +# 合并虚表里会整体后移,而方法体内按"定义类自己的虚表"取索引 ⇒ 会指到别的槽位。 +# 因此查询一律由具体类覆写、由外部按具体类型调用;Misc 自身只用自己声明的字段。 +virtual class Misc: + master: Misc* # 父容器;主窗口为 None + tk: Tk* # 所属顶层窗口;主窗口指向自身 + + # 公共状态初始化(各具体类的 __init__ 调用;不依赖基类 __init__ 链) + def _misc_setup(self, master: Misc* = None): + self.master = master + self.tk = None + if master is not None: + self.tk = master.tk + + # ---- winfo 系(tkinter Misc.winfo_* 的对应物)---- + def winfo_master(self) -> Misc*: + return self.master + + def winfo_toplevel(self) -> Tk*: + return self.tk + + # ---- bind 系(回调在 BaseWidget.dispatch_event 里派发)---- + def bind(self, seq: int, func: rawptr) -> int: + return _bind_add(Misc*(self), seq, func) + + def unbind(self, seq: int) -> int: + return _bind_remove(Misc*(self), seq) + + def _invoke_binding(self, seq: int, evt: window.InputEvent*) -> int: + return _bind_invoke(Misc*(self), seq, evt) + + # ---- 查询/生命周期:抽象,由 Tk / Widget 覆写 ---- + def winfo_exists(self) -> int: + return 0 + + def winfo_ismapped(self) -> int: + return 0 + + def winfo_x(self) -> int: + return 0 + + def winfo_y(self) -> int: + return 0 + + def winfo_width(self) -> int: + return 0 + + def winfo_height(self) -> int: + return 0 + + def destroy(self): + pass + + def update(self): + pass + +# ---- Wm:顶层窗口的"窗口管理器协议"(tkinter Wm 的对应物)---- +# 无字段(见文件头的布局约束),这里只**声明**协议面,落地实现由持有窗口状态的 Tk 覆写。 +# 同样不做自我分派(理由见 Misc 上方注释)。 +virtual class Wm: + def title(self, text: str): + pass + + def geometry(self, x: int, y: int, w: int, h: int): + pass + + def resizable(self, rw: int, rh: int): + pass + +# ---- BaseWidget:控件公共部分(tkinter BaseWidget 的对应物)---- +virtual class BaseWidget(Misc): + # 事件派发:先跑 bind 注册的回调,再交给控件自己的 handle_event。 + # 放在基类是为了让 Tk 的事件循环只调这一个入口,各控件无需关心 bind。 + def dispatch_event(self, evt: window.InputEvent*) -> int: + hit: int = self._invoke_binding(int(evt.type), evt) + handled: int = self.handle_event(evt) + if hit or handled: + return 1 + return 0 + + # 控件自身的事件处理(抽象,由具体控件覆写) + def handle_event(self, evt: window.InputEvent*) -> int: + return 0 + + # 抽象:具体控件在 Widget 层覆写(visible 是 Widget 的字段,不能在这里访问) + def destroy(self): + pass + +def _register_widget(master: Misc*, widget: Widget*) -> int: + tk: Tk* = master.tk + if tk is None: return -1 idx: int = tk.widget_count if idx < MAX_WIDGETS: tk.widgets[idx] = widget tk.widget_count = idx + 1 return idx -virtual class Widget: +virtual class Widget(BaseWidget): x: int y: int w: int h: int visible: int - master: t.CPtr widget_type: int focused: int hovered: int - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def destroy(self): + self.visible = 0 + + # ---- Misc 查询的覆写:控件用自己的几何信息回答 winfo_* ---- + def winfo_exists(self) -> int: + return self.visible + + def winfo_ismapped(self) -> int: + return self.visible + + def winfo_x(self) -> int: + return self.x + + def winfo_y(self) -> int: + return self.y + + def winfo_width(self) -> int: + return self.w + + def winfo_height(self) -> int: + return self.h + + def draw(self, fb: uint32*, fw: int, fh: int): pass def handle_event(self, evt: window.InputEvent*) -> int: @@ -319,17 +511,68 @@ virtual class Widget: if h > 0: self.h = h +# 容器中坐标叠加:master 不是顶层窗口(即 Frame 这类容器)时,子控件先按 Tk 的口径算位置, +# 再叠加容器自身原点 ⇒ 视觉上落在容器内部。本运行时的 pack/grid 是 Tk 级、按全局下标走, +# 所以这里只做"原点叠加"这一层,不做真正的嵌套布局。 +def _container_offset(root: Tk*, w: Widget*): + if w.master is None: return + if uint64(w.master) == uint64(root): return + pw: Widget* = Widget*(w.master) + if pw.widget_type == WIDGET_FRAME: + w.x += pw.x + w.y += pw.y + +# ---- Frame:容器控件(tkinter Frame 的对应物)---- +# 可作 master 使用:子控件经 _misc_setup 继承它的 tk,照常注册进顶层窗口;位置再叠加本 +# 容器原点(见 _container_offset)。 +virtual class Frame(Widget): + fill_color: uint32 + border_color: uint32 + border_w: int + + def __init__(self, master: Misc*, w: int, h: int): + self.x = 0 + self.y = 0 + self.w = w + self.h = h + self.visible = 1 + self._misc_setup(master) + self.widget_type = WIDGET_FRAME + self.focused = 0 + self.hovered = 0 + self.fill_color = uint32(0xFF2A2A3A) + self.border_color = uint32(0xFF505070) + self.border_w = 1 + _register_widget(master, Widget*(self)) + + def draw(self, fb: uint32*, fw: int, fh: int): + _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.fill_color) + if self.border_w > 0: + _draw_hline(fb, fw, fh, self.x, self.y, self.w, self.border_color) + _draw_hline(fb, fw, fh, self.x, self.y + self.h - 1, self.w, self.border_color) + _draw_vline(fb, fw, fh, self.x, self.y, self.h, self.border_color) + _draw_vline(fb, fw, fh, self.x + self.w - 1, self.y, self.h, self.border_color) + + def handle_event(self, evt: window.InputEvent*) -> int: + return 0 + + def config(self, fill_color: uint32 = None, border_color: uint32 = None): + if fill_color is not None: + self.fill_color = fill_color + if border_color is not None: + self.border_color = border_color + virtual class Label(Widget): - text: t.CArray[char, 64] + text: [64]char color: uint32 - def __init__(self, master: t.CPtr, text: str, color: uint32): + def __init__(self, master: Misc*, text: str, color: uint32): self.x = 0 self.y = 0 self.w = 0 self.h = 0 self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_LABEL self.focused = 0 self.hovered = 0 @@ -342,7 +585,7 @@ virtual class Label(Widget): self.text[i] = 0 _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): _draw_text(fb, fw, fh, self.x, self.y, &self.text[0], self.color) def handle_event(self, evt: window.InputEvent*) -> int: @@ -361,19 +604,19 @@ virtual class Label(Widget): self.color = color virtual class Button(Widget): - text: t.CArray[char, 32] + text: [32]char fill_color: uint32 text_color: uint32 pressed: int - callback: t.CPtr + callback: rawptr - def __init__(self, master: t.CPtr, w: int, h: int, text: str, callback: t.CPtr): + def __init__(self, master: Misc*, w: int, h: int, text: str, callback: rawptr): self.x = 0 self.y = 0 self.w = w self.h = h self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_BUTTON self.focused = 0 self.hovered = 0 @@ -389,7 +632,7 @@ virtual class Button(Widget): self.text[i] = 0 _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): fill: uint32 = self.fill_color border: uint32 = uint32(0x8080B0) if self.pressed: @@ -449,9 +692,9 @@ virtual class Button(Widget): # 闭包调用约定(VPC 生成):callback 是堆上的 {fn, env} 对象,fn 期望 rdi = env。 # 之前直接 `call r13`(r13 = 闭包对象地址)会跳到堆上执行 # (现场:rip=0x2040400a 在堆区、cr2=0x1、err=0x5)。 - c.Asm(f"""push r12 + __asm__(f"""push r12 push r13 -mov r13, {c.AsmInp(self.callback, t.ASM_DESCR.REG_ANY)} +mov r13, {asminp(self.callback, ASM_DESCR.REG_ANY)} mov rdi, qword ptr [r13 + 8] mov r12, rsp and rsp, -16 @@ -459,16 +702,16 @@ call qword ptr [r13] mov rsp, r12 pop r13 pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + op=[ASM_DESCR.CLOBBER_MEMORY, + ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, + ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RSI, + ASM_DESCR.CLOBBER_RDI, + ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9, + ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11]) return 1 return 0 - def config(self, text: const str = None, fill_color: uint32 = None, text_color: uint32 = None, callback: t.CPtr = None): + def config(self, text: const str = None, fill_color: uint32 = None, text_color: uint32 = None, callback: rawptr = None): if text is not None: i: int = 0 while i < 31: @@ -485,7 +728,7 @@ pop r12""", self.callback = callback virtual class Entry(Widget): - text: t.CArray[char, 64] + text: [64]char text_len: int cursor_pos: int max_len: int @@ -494,13 +737,13 @@ virtual class Entry(Widget): text_color: uint32 cursor_color: uint32 - def __init__(self, master: t.CPtr, w: int, h: int): + def __init__(self, master: Misc*, w: int, h: int): self.x = 0 self.y = 0 self.w = w self.h = h self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_ENTRY self.focused = 0 self.hovered = 0 @@ -515,7 +758,7 @@ virtual class Entry(Widget): self.text[i] = 0 _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): bg: uint32 = self.bg_color bdr: uint32 = self.border_color if self.focused: @@ -548,26 +791,26 @@ virtual class Entry(Widget): if self.contains(ex, ey): if not self.hovered: self.hovered = 1 - tk: Tk* = t.CType(self.master, Tk, t.CPtr) + tk: Tk* = self.tk window.set_cursor_type(tk.win_id, window.CURSOR_IBEAM) return 1 else: if self.hovered: self.hovered = 0 - tk2: Tk* = t.CType(self.master, Tk, t.CPtr) + tk2: Tk* = self.tk window.set_cursor_type(tk2.win_id, window.CURSOR_DEFAULT) return 1 elif etype == window.EVENT_TYPE_HOVER_LEAVE: if self.hovered: self.hovered = 0 - tk3: Tk* = t.CType(self.master, Tk, t.CPtr) + tk3: Tk* = self.tk window.set_cursor_type(tk3.win_id, window.CURSOR_DEFAULT) return 1 elif etype == window.EVENT_TYPE_CLICK: if self.contains(ex, ey): if not self.focused: self.focused = 1 - tk4: Tk* = t.CType(self.master, Tk, t.CPtr) + tk4: Tk* = self.tk tk4.focused_widget = Widget*(self) rel_x: int = ex - self.x - 6 if rel_x < 0: rel_x = 0 @@ -578,7 +821,7 @@ virtual class Entry(Widget): else: if self.focused: self.focused = 0 - tk5: Tk* = t.CType(self.master, Tk, t.CPtr) + tk5: Tk* = self.tk tk5.focused_widget = None return 1 elif etype == window.EVENT_TYPE_KEY: @@ -647,7 +890,7 @@ virtual class Entry(Widget): virtual class Scrollbar(Widget): orient: int - command: t.CPtr + command: rawptr slider_first: int slider_last: int action: int @@ -661,13 +904,13 @@ virtual class Scrollbar(Widget): arrow_color: uint32 slider_hover: int - def __init__(self, master: t.CPtr, w: int, h: int, orient: int): + def __init__(self, master: Misc*, w: int, h: int, orient: int): self.x = 0 self.y = 0 self.w = w self.h = h self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_SCROLLBAR self.focused = 0 self.hovered = 0 @@ -687,7 +930,7 @@ virtual class Scrollbar(Widget): self.slider_hover = 0 _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.trough_color) if self.orient != VERTICAL: return arrow_sz: int = self.w @@ -717,7 +960,7 @@ virtual class Scrollbar(Widget): _draw_vline(fb, fw, fh, self.x + 1, sl_y, sl_h, top_c) _draw_vline(fb, fw, fh, self.x + self.w - 2, sl_y, sl_h, bot_c) - def _draw_arrow_btn(self, fb: UINT32PTR, fw: int, fh: int, bx: int, by: int, bw: int, bh: int, direction: int, is_pressed: int): + def _draw_arrow_btn(self, fb: uint32*, fw: int, fh: int, bx: int, by: int, bw: int, bh: int, direction: int, is_pressed: int): color: uint32 = self.slider_color if is_pressed: color = _lighten(self.slider_color, 30) @@ -835,9 +1078,9 @@ virtual class Scrollbar(Widget): def _fire_command(self): if self.command is not None: # 同 Button.handle_event:command 是闭包 {fn, env},必须 rdi = env 后 call fn。 - c.Asm(f"""push r12 + __asm__(f"""push r12 push r13 -mov r13, {c.AsmInp(self.command, t.ASM_DESCR.REG_ANY)} +mov r13, {asminp(self.command, ASM_DESCR.REG_ANY)} mov rdi, qword ptr [r13 + 8] mov r12, rsp and rsp, -16 @@ -845,29 +1088,29 @@ call qword ptr [r13] mov rsp, r12 pop r13 pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + op=[ASM_DESCR.CLOBBER_MEMORY, + ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, + ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RSI, + ASM_DESCR.CLOBBER_RDI, + ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9, + ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11]) def set(self, first: int, last: int): self.slider_first = first self.slider_last = last virtual class FBCanvas(Widget): - _fb: UINT32PTR + _fb: uint32* _cw: int _ch: int - def __init__(self, master: t.CPtr, w: int, h: int): + def __init__(self, master: Misc*, w: int, h: int): self.x = 0 self.y = 0 self.w = w self.h = h self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_FBCANVAS self.focused = 0 self.hovered = 0 @@ -876,7 +1119,7 @@ virtual class FBCanvas(Widget): self._ch = h _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): if not self._fb: return if self._cw <= 0 or self._ch <= 0: return copy_w: int = self._cw @@ -894,12 +1137,12 @@ virtual class FBCanvas(Widget): def handle_event(self, evt: window.InputEvent*) -> int: return 0 - def set_fb(self, fb: UINT32PTR, cw: int, ch: int): + def set_fb(self, fb: uint32*, cw: int, ch: int): self._fb = fb self._cw = cw self._ch = ch - def get_fb(self) -> UINT32PTR: + def get_fb(self) -> uint32*: return self._fb def get_w(self) -> int: @@ -909,9 +1152,9 @@ virtual class FBCanvas(Widget): return self._ch virtual class Text(Widget): - lines: t.CArray[t.CArray[char, 80], TEXT_MAX_LINES] + lines: [TEXT_MAX_LINES][80]char line_count: int - input_buf: t.CArray[char, 80] + input_buf: [80]char input_len: int cursor_pos: int bg_color: uint32 @@ -919,21 +1162,21 @@ virtual class Text(Widget): prompt_color: uint32 cursor_color: uint32 border_color: uint32 - on_command: t.CPtr - history: t.CArray[t.CArray[char, 80], 16] + on_command: rawptr + history: [16][80]char history_count: int history_idx: int scroll_offset: int max_lines: int - yscrollbar: t.CPtr + yscrollbar: rawptr - def __init__(self, master: t.CPtr, w: int, h: int): + def __init__(self, master: Misc*, w: int, h: int): self.x = 0 self.y = 0 self.w = w self.h = h self.visible = 1 - self.master = master + self._misc_setup(master) self.widget_type = WIDGET_TEXT self.focused = 0 self.hovered = 0 @@ -958,7 +1201,7 @@ virtual class Text(Widget): self.input_buf[i] = 0 _register_widget(master, Widget*(self)) - def draw(self, fb: UINT32PTR, fw: int, fh: int): + def draw(self, fb: uint32*, fw: int, fh: int): self._update_scrollbar() _fill_rect(fb, fw, fh, self.x, self.y, self.w, self.h, self.bg_color) _fill_rect(fb, fw, fh, self.x, self.y + self.h - 2, self.w, 2, self.border_color) @@ -983,7 +1226,7 @@ virtual class Text(Widget): if self.contains(ex, ey): if not self.focused: self.focused = 1 - tk: Tk* = t.CType(self.master, Tk, t.CPtr) + tk: Tk* = self.tk tk.focused_widget = Widget*(self) prompt_y: int = self.y + self.h - CHAR_H - 4 if ey >= prompt_y and ey < prompt_y + CHAR_H: @@ -996,7 +1239,7 @@ virtual class Text(Widget): else: if self.focused: self.focused = 0 - tk2: Tk* = t.CType(self.master, Tk, t.CPtr) + tk2: Tk* = self.tk tk2.focused_widget = None return 1 elif etype == window.EVENT_TYPE_KEY: @@ -1126,12 +1369,12 @@ virtual class Text(Widget): self.history[15][k3] = self.input_buf[k3] self.history_idx = 0 - cmd: t.CPtr = self.on_command + cmd: rawptr = self.on_command if cmd is not None: # 同 Button.handle_event:on_command 是闭包 {fn, env},必须 rdi = env 后 call fn。 - c.Asm(f"""push r12 + __asm__(f"""push r12 push r13 -mov r13, {c.AsmInp(cmd, t.ASM_DESCR.REG_ANY)} +mov r13, {asminp(cmd, ASM_DESCR.REG_ANY)} mov rdi, qword ptr [r13 + 8] mov r12, rsp and rsp, -16 @@ -1139,12 +1382,12 @@ call qword ptr [r13] mov rsp, r12 pop r13 pop r12""", - op=[t.ASM_DESCR.CLOBBER_MEMORY, - t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, - t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RSI, - t.ASM_DESCR.CLOBBER_RDI, - t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, - t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) + op=[ASM_DESCR.CLOBBER_MEMORY, + ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, + ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_RSI, + ASM_DESCR.CLOBBER_RDI, + ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9, + ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11]) else: self.insert("(no callback)") @@ -1242,7 +1485,7 @@ pop r12""", if self.scroll_offset > max_off: self.scroll_offset = max_off if self.yscrollbar is not None: - sb: Scrollbar* = t.CType(self.yscrollbar, Scrollbar, t.CPtr) + sb: Scrollbar* = Scrollbar*(self.yscrollbar) if self.line_count <= vis: sb.set(0, 1000) else: @@ -1250,20 +1493,20 @@ pop r12""", last: int = (self.scroll_offset + vis) * 1000 / self.line_count sb.set(first, last) -@t.Object -class Tk: +# ---- Tk:主窗口类 = Wm(窗口管理器协议,无字段)+ Misc(公共状态/方法)---- +virtual class Tk(Wm, Misc): win_id: int - buf: UINT32PTR + buf: uint32* bw: int bh: int style: int bg_color: uint32 - widgets: t.CArray[Widget*, MAX_WIDGETS] + widgets: [MAX_WIDGETS]Widget* widget_count: int focused_widget: Widget* _win_x: int _win_y: int - _title: t.CArray[char, 32] + _title: [32]char resizable_w: int resizable_h: int _grid_rows: int @@ -1271,6 +1514,9 @@ class Tk: def __init__(self): global _g_layout_init + # Misc 的公共状态:主窗口没有父容器,tk 指向自身(控件经 _misc_setup 继承它) + self.master = None + self.tk = Tk*(self) self.widget_count = 0 self.focused_widget = None self.win_id = -1 @@ -1315,6 +1561,7 @@ class Tk: _g_wl_colspan[idx] = colspan _g_wl_sticky[idx] = sticky + # ---- Wm 协议的落地实现(Tk 持有窗口状态,覆写 Wm 声明的协议面)---- def title(self, text: str): i: int = 0 while i < 31: @@ -1438,6 +1685,7 @@ class Tk: w.w = ww w.h = wh cav_w -= ww + 2 * px + _container_offset(self, w) elif lt == 3: r: int = _g_wl_row[i] + _g_wl_rowspan[i] c: int = _g_wl_col[i] + _g_wl_colspan[i] @@ -1467,6 +1715,7 @@ class Tk: w.w = ww if (sticky & 2) != 0: w.h = wh + _container_offset(self, w) def update(self): self.redraw() @@ -1475,6 +1724,23 @@ class Tk: if self.win_id < 0: return 0 return window.is_active(self.win_id) + # ---- Misc 查询的覆写:主窗口用自己的窗口状态回答 winfo_* ---- + def winfo_ismapped(self) -> int: + if self.win_id < 0: return 0 + return window.is_active(self.win_id) + + def winfo_x(self) -> int: + return self._win_x + + def winfo_y(self) -> int: + return self._win_y + + def winfo_width(self) -> int: + return self.bw + + def winfo_height(self) -> int: + return self.bh + def mainloop(self): self.redraw() evt: window.InputEvent @@ -1494,7 +1760,7 @@ class Tk: need_redraw = 1 elif etype == window.EVENT_TYPE_KEY or etype == window.EVENT_TYPE_KEY_RELEASE: if self.focused_widget is not None: - handled: int = self.focused_widget.handle_event(&evt) + handled: int = self.focused_widget.dispatch_event(&evt) if handled: need_redraw = 1 else: if etype == window.EVENT_TYPE_HOVER: @@ -1502,7 +1768,7 @@ class Tk: while i >= 0: w: Widget* = self.widgets[i] if w.visible: - handled2: int = w.handle_event(&evt) + handled2: int = w.dispatch_event(&evt) if handled2: need_redraw = 1 break @@ -1511,7 +1777,7 @@ class Tk: for i in range(self.widget_count): w: Widget* = self.widgets[i] if w.visible: - handled2: int = w.handle_event(&evt) + handled2: int = w.dispatch_event(&evt) if handled2: need_redraw = 1 if need_redraw: self.redraw()