# weather.py —— 常用小程序②：**天气**（联网抓一周预报 → 存文件 → 彩色显示）
# weather.py -- Everyday utility #2: **weather** (fetch a one-week forecast, save it, then show it)
#
# 四段：① 裸套接字取回 api.open-meteo.com 的预报（明文 HTTP，80 端口 —— VM 里没有 TLS）；
# Four stages: (1) fetch the forecast from api.open-meteo.com over a raw socket (plain HTTP on port
# 80 -- there is no TLS in the VM); (2) strip the response headers and write the body into
# weather.txt (**relative path**: on the phone the sandbox root is the workspace);
# ② 剥掉响应头，把正文写进 weather.txt（**相对路径**：手机上沙箱根 = 工作区）；
# (2) strip the response headers and write the body into weather.txt (**a relative path**: on the
# phone the sandbox root is the workspace and absolute paths are rejected);
# ③ 解析 CSV（**要 `format=csv`**，比 JSON 少一整层解析）；④ 画一张彩色的周预报。
# (3) parse the CSV (**ask for `format=csv`**, which saves a whole parsing layer over JSON);
# (4) draw a colour week card.
#
# 这是 `Examples/c/app/weather.c` 的 Python 移植：联网那部分**照搬**（DNS → 裸套接字 → 明文
# This is the Python port of `Examples/c/app/weather.c`: the networking is ported as is
# (DNS -> raw socket -> plain HTTP on port 80 -> `format=csv`), and so is the offline fallback.
# HTTP 80 → `format=csv`），离线回落读 `weather.txt` 也照搬。
# The offline fallback reads `weather.txt` exactly like the C version does.
#
# ## Python 前端没有 `asm()` ⇒ 系统调用只能走共享库的包装（**都实测过**）
# ## This front end has no `asm()`, so syscalls go through the shared library's wrappers
#
# `Lib/python/shared.py` 里那套 `net_*` / `vml_dns_resolve` / `vml_file_*` 就是 `svc` 号
# The `net_*` / `vml_dns_resolve` / `vml_file_*` set in `Lib/python/shared.py` are thin wrappers
# 的薄包装（`net_connect` = SYSCALL #330 + #334、`net_recv` = #336、`vml_file_read` = #112 …），
# over the syscall numbers (`net_connect` = #330 + #334, `net_recv` = #336, `vml_file_read` = #112),
# 与 C 版自己包的那层 `sys_*` 一一对应。
# one for one with the `sys_*` layer the C version wraps itself.
# ⚠ 域名仍然**不能直接连**：宿主 #334 内部是 `IPAddress.Parse` ⇒ 必须先 `vml_dns_resolve`。
# ⚠ A hostname still **cannot be connected directly**: host #334 uses `IPAddress.Parse` inside, so
#   `vml_dns_resolve` has to run first.
#
# ## 收数据这一步是本移植最别扭的地方（原因不是"想不到"，是**没得选**）
# ## Reading the response back is the awkward part of this port (not by choice)
#
# 本语言**没有取地址、没有 `peek`/`poke`**（`peekb(x)` 会编成 `CALL vml_peekb`，而 `Lib/` 下
# This language has **no address-of and no `peek`/`poke`** (`peekb(x)` compiles to `CALL vml_peekb`,
# 没有这个标签 —— 实测 `error: 未定义的函数 'vml_peekb'`），所以"往缓冲里收、再逐字节读回来"
# and no such label exists under `Lib/` -- measured: `error: undefined function 'vml_peekb'`), so
# 只能借共享库的两件工具：
# "receive into a buffer, then read it back byte by byte" has to lean on two shared-library tools:
#   · `str_charat(addr, i)` —— 按**地址**取一个字节（C 里叫 `buf[i]`）；
#   · `str_charat(addr, i)` -- one byte **by address** (what C writes as `buf[i]`);
#   · `str_substr(dst, src, pos, count)` —— 从地址抄一段到另一个地址（C 里叫"取子串"）。
#   · `str_substr(dst, src, pos, count)` -- copy a slice from one address to another.
# 收来的字节因此**从头到尾都以地址形式流动**：`ui_2d_text` 要的也是地址，两者正好同源。
# The received bytes therefore stay **addresses end to end**, which is also what `ui_2d_text`
# wants -- the two agree.
# ⚠ 代价：`str_substr` 的边界靠 `strlen(src)` 定，所以**每写一段都要自己在缓冲尾补一个 0**
# ⚠ The cost: `str_substr` bounds itself by `strlen(src)`, so **every write must NUL-terminate the
# （本文件里就是 `memset(RBUF + TOTAL, 0, 1)` 那几处）。
# buffer tail first** (the `memset(RBUF + TOTAL, 0, 1)` calls in this file).
#
# ## 为什么"空闲 8 秒就自己退出"
# ## Why it exits by itself after 8 seconds of idling
#
# 例程要能被**自动验收**（`scripts/vmlcli` 加 `--frame` 出一张图就够了），所以循环必须有界。
# Samples have to be **automatically verifiable** (one `scripts/vmlcli` run with `--frame` is
# enough), so the loop must be bounded.

# ── 显式引用：`ui_*` 来自共享调用库 `vmlui.vml`；套接字/文件/字符串助手来自共享库 ──
# ── explicit references: `ui_*` from the shared call library `vmlui.vml`; the socket/file/string
#    helpers from the shared library ──
import vml_ui
import shared

HOST = "api.open-meteo.com"
PORT = 80
OUTFILE = "weather.txt"

BUFCAP = 8192            # 响应缓冲：CSV 正文实测 ~250 字节，8K 绰绰有余
                         # Response buffer: the CSV body measures ~250 bytes, so 8K is plenty.
MAXROUNDS = 64           # 读循环上限：防"对端不关连接"时死读
                         # Read-loop cap: stops an endless read when the peer never closes.
IDLE_EXIT_MS = 8000

# 配色（真彩 AA RRGGBB）
# Colours (true colour AA RRGGBB)
C_BG = 0xFF0E1116
C_CARD = 0xFF1A1F28
C_TITLE = 0xFFE8E8F0
C_DIM = 0xFF9AA0B0
C_HI = 0xFFE06C50
C_LO = 0xFF4A90D9
C_TRACK = 0xFF2A3038
C_WARN = 0xFFE0A040

# 请求正文。C 版一段一段 `strcat` 拼（前端没有字符串拼接），本语言的字符串字面量**直接支持**
# The request body. The C version stitches it together with `strcat` because its front end has no
# string concatenation; here a plain string literal works.
# `\r\n` 转义（实测 `strlen` 对得上、服务端也认）。**必须写在一行**：本语言不做相邻字面量拼接
# (`strlen` matches and the server accepts it, measured). It **must stay on one line**: adjacent
# string literals are not concatenated here (measured: `"x" "y"` compiles down to `"x"`).
# ⚠ `format=csv` 是这一版的关键：open-meteo 支持直接回 CSV，省掉一整层 JSON 解析。
# ⚠ `format=csv` is the crux here: open-meteo can return CSV directly, saving a JSON layer.
# ⚠ 现在只留**请求路径**：请求行与那套头由库里的 `http_get_to` 拼（它那份与本例程原先手写的逐字相同）。
# ⚠ Only the **path** is kept now: `http_get_to` in the library builds the request line and headers.
PATH = "/v1/forecast?latitude=22.54&longitude=114.06&daily=temperature_2m_max,temperature_2m_min,weather_code&forecast_days=7&timezone=Asia/Shanghai&format=csv"

# ── 缓冲与状态 ────────────────────────────────────────
# ── buffers and state ─────────────────────────────────
RBUF = vml_alloc(BUFCAP)     # 整个 HTTP 响应（头 + 正文），离线时当缓存正文用
                             # The whole HTTP response (headers plus body), and the cache body when offline
S_NUM = vml_alloc(16)        # 整数转字符串 / 切字段用
                             # scratch for `itoa` and for a cut-out field
S_TB = vml_alloc(24)         # "19.8~28.1" 这种温度串
                             # the "19.8~28.1" temperature line
D_DATES = vml_alloc(96)      # 7 天 × 12 字节（只存 `MM-DD`，长度足够放下 7 段）
                             # 7 days x 12 bytes (only `MM-DD` is stored, room enough for seven)

# 画布尺寸（由顶层算好，函数只读）
# Canvas size (computed at top level, only read inside functions)
SW = 0
SH = 0
LANG = 0
OFFLINE = 0                  # 1 = 没连上，显示的是本地缓存
                             # 1 = offline, showing the local cache
D_N = 0                      # 解析出几天
                             # how many days were parsed
# 每天的最低/最高/天气代码。C 版是定长数组，本语言有列表 ⇒ 直接摆列表（函数里读、顶层写）。
# Low/high/weather code per day. The C version uses fixed arrays; this language has lists, so the
# lists are written at top level and read inside functions.
D_LO = [0, 0, 0, 0, 0, 0, 0, 0]
D_HI = [0, 0, 0, 0, 0, 0, 0, 0]
D_CODE = [0, 0, 0, 0, 0, 0, 0, 0]


# ── 小工具 ────────────────────────────────────────────
# ── small helpers ─────────────────────────────────────

# ⚠ 这里原先有两个手写的协议辅助：`find_body`（找 `\r\n\r\n`）与 `http_code`（解析状态码）——
#   库 `Lib/shared/src/http.c` 的 `http_get_to` 已经把剥头与状态码都做了，只往回装**正文**。
# The two hand-written protocol helpers used to live here; `http_get_to` covers both.
# 一个字节是不是十进制数字
# Is one byte a decimal digit
def is_digit_at(at):
    c = str_charat(RBUF, at)
    if c >= 48 and c <= 57:
        return 1
    return 0


# WMO 天气代码 → 一句话。代码表来自 open-meteo 的文档：
# WMO weather code -> a short phrase. The table follows open-meteo's docs:
# 0 晴 / 1-3 云 / 45 雾 / 5x 毛毛雨 / 6x 雨 / 7x 雪 / 8x 阵雨 / 9x 雷暴。
# 0 clear / 1-3 cloud / 45 fog / 5x drizzle / 6x rain / 7x snow / 8x showers / 9x thunderstorm.
def wmo_label(code, lg):
    if code == 0:
        return "晴" if lg == 0 else "clear"
    if code == 1 or code == 2:
        return "多云" if lg == 0 else "cloudy"
    if code == 3:
        return "阴" if lg == 0 else "overcast"
    if code == 45 or code == 48:
        return "雾" if lg == 0 else "fog"
    if code >= 51 and code <= 57:
        return "毛毛雨" if lg == 0 else "drizzle"
    if code >= 61 and code <= 67:
        return "雨" if lg == 0 else "rain"
    if code >= 71 and code <= 77:
        return "雪" if lg == 0 else "snow"
    if code >= 80 and code <= 82:
        return "阵雨" if lg == 0 else "showers"
    if code >= 95:
        return "雷暴" if lg == 0 else "storm"
    return "未知" if lg == 0 else "unknown"


# ── 绘制 ──────────────────────────────────────────────
# ── drawing ───────────────────────────────────────────
def draw():
    cx = SW // 2
    pad = SW // 18
    top = 0
    avail = 0
    cardh = 0
    i = 0
    y = 0
    h = 0
    midy = 0
    innerw = 0
    barw = 0
    n = D_N

    if pad < 6:
        pad = 6
    top = pad + 58                    # 标题两行
    # room for the two heading lines
    avail = SH - top - 40
    if n <= 0:
        n = 1
    cardh = avail // n

    ui_2d_clear(C_BG)
    ui_2d_text_styled(cx, pad, "一周预报" if LANG == 0 else "One-week forecast",
                      C_TITLE, 17, VML_ANCHOR_CENTER, VML_FONT_BOLD)
    if OFFLINE != 0:
        ui_2d_text(cx, pad + 26, "离线：读本地缓存 weather.txt" if LANG == 0
                   else "offline: local cache weather.txt", C_WARN, 11, VML_ANCHOR_CENTER)
    else:
        ui_2d_text(cx, pad + 26, "数据源 api.open-meteo.com" if LANG == 0
                   else "source api.open-meteo.com", C_DIM, 11, VML_ANCHOR_CENTER)

    i = 0
    while i < D_N:
        y = top + i * cardh
        h = cardh - 6
        midy = y + h // 2

        ui_2d_rect(pad, y, SW - pad * 2, h, C_CARD, 1, 0, 8)

        # 日期：`D_DATES + i * 12` 就是第 i 天那 5 个字节的**地址**，`ui_2d_text` 直接收
        # The date: `D_DATES + i * 12` is the **address** of that day's five bytes and
        # （C 版是"从扁平缓冲搬进一个小局部串"——本语言连这步都不用）。
        # `ui_2d_text` takes it as is (the C version first copies it into a local string).
        ui_2d_text(pad + 12, midy - 8, D_DATES + i * 12, C_TITLE, 14, VML_ANCHOR_LEFT)

        # 天气一句话
        # The condition in words
        ui_2d_text(SW - pad - 12, midy - 7, wmo_label(D_CODE[i], LANG), C_DIM, 12,
                   VML_ANCHOR_RIGHT)

        # 最低~最高 + 温度条（10℃ 起，34℃ 满条）
        # Low~high plus a temperature bar (starts at 10 C and fills at 34 C)
        itoa(D_LO[i], S_NUM)
        strcpy(S_TB, S_NUM)
        strcat(S_TB, "~")
        itoa(D_HI[i], S_NUM)
        strcat(S_TB, S_NUM)
        ui_2d_text(pad + 12, midy + 10, S_TB, C_LO, 12, VML_ANCHOR_LEFT)

        innerw = SW - pad * 2 - 24
        if innerw < 40:
            innerw = 40
        barw = (D_HI[i] - 10) * innerw // 24
        if barw < 8:
            barw = 8
        if barw > innerw:
            barw = innerw
        ui_2d_rect(pad + 12, midy + 26, innerw, 6, C_TRACK, 1, 0, 3)
        if D_HI[i] >= 30:
            ui_2d_rect(pad + 12, midy + 26, barw, 6, C_HI, 1, 0, 3)
        else:
            ui_2d_rect(pad + 12, midy + 26, barw, 6, C_LO, 1, 0, 3)

        i = i + 1

    ui_2d_present()          # ⚠ 不调这句 = 黑屏
                             # ⚠ without this call you get a black screen


# ── 主流程 ────────────────────────────────────────────
# ── main flow ─────────────────────────────────────────

LANG = ui_scr_get_language()
TOTAL = 0
HEAD = 0
BLEN = 0
FAIL = 0
IP = 0
FD = -1
N = 0
WANT = 0
ROUNDS = 0
CODE = 0
FH = 0
WROTE = 0

print_str("=== VML 天气预报 ===\n" if LANG == 0 else "=== VML Weather Report ===\n")
print_str("主机 " if LANG == 0 else "Host ")
print_str(HOST)
print_str("  文件 " if LANG == 0 else "  file ")
print_str(OUTFILE)
print_str("\n")

# ① 域名 → IP（宿主不解析域名）
# ① Hostname to IP (the host does not resolve names)
# ⚠ 解析失败时宿主把 R0 置 **-1**（不是 0），所以判据是 `<= 0`；只判 `== 0` 会把 -1
# ⚠ On a failed lookup the host sets R0 to **-1** (not 0), so the test is `<= 0`; testing only
#   `== 0` would hand -1 to the next call as if it were an address (measured on the C side).
#   as if it were an address (measured on the C side: a "memory error", not a DNS failure).
IP = vml_dns_resolve(HOST)
if IP <= 0:
    print_str("[警告] DNS 解析失败（转为离线）\n" if LANG == 0
              else "[WARN] DNS lookup failed (going offline)\n")
    OFFLINE = 1
else:
    print_str("[1/4] DNS  ")
    print_str(IP)
    print_str("\n")

# ②③ 抓数据 —— 建套接字、连接、发请求、收完整响应、剥头、状态码**全在库里**
#   ⚠ 用 `http_get_to` 而不是 `http_get`：后者把「连哪儿」与「Host 写什么」交给**同一个参数**，
#     传域名连不上（#334 不解析域名）、传 IP 则 Host 头成了 IP ⇒ 虚拟主机按 Host 路由返回 **404**。
# The rest of the fetch lives in the library's `http_get_to` (connect to the IP, `Host:` carries the name).
if OFFLINE == 0:
    CODE = http_get_to(IP, PORT, HOST, PATH, RBUF, BUFCAP)
    if CODE != 200:
        print_str("[警告] 抓取失败（转为离线）\n" if LANG == 0
                  else "[WARN] fetch failed (going offline)\n")
        OFFLINE = 1
    else:
        BLEN = strlen(RBUF)          # `http_get_to` 只往回装**正文**（头已经剥掉了）
        # it stores **only the body**; headers are already stripped
        HEAD = 0
        print_str("[3/4] HTTP ")
        print_int(CODE)
        print_str("  正文 " if LANG == 0 else "  body ")
        print_int(BLEN)
        print_str(" 字节\n" if LANG == 0 else " bytes\n")

# ④ 剥头 → 写文件（离线时跳过）
# ④ Strip the headers and write the file (skipped when offline)
if OFFLINE == 0:
    FH = vml_file_open(OUTFILE, 1)      # 1 = 只写（FileMode.Create）
    # 1 = write only
    if FH < 0:
        print_str("[警告] 打不开 " if LANG == 0 else "[WARN] cannot open ")
        print_str(OUTFILE)
        print_str("（手机上路径必须是相对的）\n" if LANG == 0
                  else " (paths must be relative on the phone)\n")
    else:
        WROTE = vml_file_write(FH, RBUF + HEAD, BLEN)
        vml_file_close(FH)
        print_str("[4/4] HTTP ")
        print_int(CODE)
        print_str("  正文 " if LANG == 0 else "  body ")
        print_int(BLEN)
        print_str(" 字节" if LANG == 0 else " bytes")
        print_str("  写入 " if LANG == 0 else "  wrote ")
        print_int(WROTE)
        print_str(" 字节 -> " if LANG == 0 else " bytes -> ")
        print_str(OUTFILE)
        print_str("\n")

# ⑤ 离线回落：读上一次留下的 weather.txt（相对路径，各宿主自己解析）
# ⑤ Offline fallback: read the weather.txt left by the last run (a relative path each host resolves)
# ⚠ `mode = 0` 是**只读**：写成 1 会把缓存文件清空再读，拿到一份空数据。
# ⚠ `mode = 0` is **read-only**: passing 1 would truncate the cache file first and hand back nothing.
if OFFLINE != 0:
    FH = vml_file_open(OUTFILE, 0)
    if FH < 0:
        print_str("[失败] 离线且没有本地缓存 " if LANG == 0 else "[FAIL] offline and no local cache ")
        print_str(OUTFILE)
        print_str(" —— 先在联网的机器上跑一次，或把预报 CSV 放到同目录。\n" if LANG == 0
                  else " -- run this once on a networked machine, or drop the forecast CSV next to it.\n")
        FAIL = 1
    else:
        BLEN = vml_file_read(FH, RBUF, BUFCAP - 1)
        vml_file_close(FH)
        if BLEN <= 0:
            print_str("[失败] 缓存文件是空的\n" if LANG == 0 else "[FAIL] the cache file is empty\n")
            FAIL = 1
        else:
            memset(RBUF + BLEN, 0, 1)
            HEAD = 0                 # 缓存里没有响应头，正文从 0 开始
            # the cache has no headers

# ⑥ 解析成结构化的"天"
# ⑥ Parse the CSV into structured days
# ⚠ C 版先切好 `line[96]` 再 `split_csv`，本语言直接在缓冲上按**下标**做（`str_charat` 读、
# ⚠ The C version copies each line into `line[96]` and calls `split_csv`; here the buffer is walked
#   by index instead (`str_charat` to read, `str_substr` to cut a field out).
#   by index instead (`str_charat` reads, `str_substr` cuts a field out).
# ⚠ 只认「日期形状」的行：第 1 段必须是 `YYYY-MM-DD`。别只判"数字开头" —— open-meteo 的 CSV
# ⚠ Only lines shaped like a date count: the first field must be `YYYY-MM-DD`. Do not settle for
#   "starts with a digit" -- line 2 of open-meteo's CSV is the latitude/longitude row
#   **第 2 行是经纬度那行**（`22.530754,114.08714,...`），数字开头，判错了会多出一行"日期"。
#   (`22.530754,114.08714,...`), which starts with a digit and would add a bogus "day".
if FAIL == 0:
    D_N = 0
    LI = HEAD
    LE = HEAD
    C1 = 0
    C2 = 0
    C3 = 0
    while LI < HEAD + BLEN:
        LE = LI
        while LE < HEAD + BLEN:
            if str_charat(RBUF, LE) == 10:
                break
            LE = LE + 1
        if LE > LI:
            if is_digit_at(LI) == 1:
                if str_charat(RBUF, LI + 4) == 45 and str_charat(RBUF, LI + 7) == 45:
                    C1 = LI
                    while C1 < LE:
                        if str_charat(RBUF, C1) == 44:
                            break
                        C1 = C1 + 1
                    C2 = C1 + 1
                    while C2 < LE:
                        if str_charat(RBUF, C2) == 44:
                            break
                        C2 = C2 + 1
                    C3 = C2 + 1
                    while C3 < LE:
                        if str_charat(RBUF, C3) == 44:
                            break
                        C3 = C3 + 1
                    if C3 < LE and D_N < 7:
                        str_substr(S_NUM, RBUF, C1 + 1, C2 - C1 - 1)
                        D_HI[D_N] = atoi(S_NUM)
                        str_substr(S_NUM, RBUF, C2 + 1, C3 - C2 - 1)
                        D_LO[D_N] = atoi(S_NUM)
                        str_substr(S_NUM, RBUF, C3 + 1, LE - C3 - 1)
                        D_CODE[D_N] = atoi(S_NUM)
                        # 日期只留 `MM-DD`（年前两位对一周预报没意义，省下的宽度留给温度）
                        # Keep only `MM-DD` from the date (the century is noise for a week)
                        str_substr(D_DATES + D_N * 12, RBUF, LI + 5, 5)
                        memset(D_DATES + D_N * 12 + 5, 0, 1)
                        D_N = D_N + 1
        LI = LE + 1

    if D_N == 0:
        print_str("[失败] 没解析出数据行（CSV 格式变了吗？）\n" if LANG == 0
                  else "[FAIL] no data rows parsed (did the CSV format change?)\n")
        FAIL = 1
    else:
        print_str("解析 " if LANG == 0 else "parsed ")
        print_int(D_N)
        print_str(" 天：\n" if LANG == 0 else " days:\n")
        I = 0
        while I < D_N:
            print_str("  ")
            print_str(D_DATES + I * 12)
            print_str("  ")
            itoa(D_LO[I], S_NUM)
            print_str(S_NUM)
            print_str("~")
            itoa(D_HI[I], S_NUM)
            print_str(S_NUM)
            print_str("  code=")
            itoa(D_CODE[I], S_NUM)
            print_str(S_NUM)
            print_str("\n")
            I = I + 1

# ⑦ 开窗 → 画 → 消息循环
# ⑦ Open a window, draw, then run the message loop
# ⚠ 版面那几项是**模块级标量**，赋值只能写在顶层（函数里写就是新建局部量，实测）。
# ⚠ The layout values are **module-level scalars**, so the assignments live at the top level
#   (inside a function they would only create locals, measured).
if FAIL == 0:
    # 开窗时传 0：尺寸交给宿主（用真实可用区）；开窗后再问一次真实画布（见下）。
    # Open with 0 so the host decides the size (the real usable area), then ask the real canvas
    # again below.
    ui_win_open_ex("weather.py", 0, 0, VML_WIN_ROTATABLE, VML_WIN_NO_GAMEPAD)
    # 开窗后再问一次 —— 画布尺寸与开窗前的估算**可能不同**
    # Ask again after opening: the canvas may differ from the pre-open estimate
    SW = ui_scr_get_w()
    SH = ui_scr_get_h()
    if SW <= 0:
        SW = 360
    if SH <= 0:
        SH = 620
    draw()

    T0 = ui_time_get_ms()
    DONE = 0
    while DONE == 0 and ui_win_is_closed() == 0:
        T = ui_msg_fetch_wait(200)
        if T == VML_MSG_NONE:
            if ui_time_get_ms() - T0 > IDLE_EXIT_MS:
                DONE = 1                 # 空闲超时（验收用）
                # idle timeout (for automated checks)
        elif T == VML_MSG_KEYDOWN:
            K = ui_msg_get_a()
            T0 = ui_time_get_ms()
            if K == VML_KEY_ESCAPE or K == 113 or K == 81:
                DONE = 1
            elif K == VML_KEY_LEFT or K == VML_KEY_RIGHT:
                draw()
            elif K == VML_KEY_UP or K == VML_KEY_DOWN:
                draw()
        elif T == VML_MSG_WINDOWORIENT or T == VML_MSG_WINDOWRESIZE:
            SW = ui_scr_get_w()
            SH = ui_scr_get_h()
            if SW <= 0:
                SW = 360
            if SH <= 0:
                SH = 620
            draw()
        elif T == VML_MSG_WINDOWCLOSE:
            DONE = 1
