• src/doors/clans-src/src/video.c win_wrappers.c

    From Deucе@VERT to Git commit to main/sbbs/master on Sat Apr 18 01:02:09 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/2f3f9d4d3693602292fa92f5
    Modified Files:
    src/doors/clans-src/src/video.c win_wrappers.c
    Log Message:
    More Win32 cleanups

    video.c:
    - ClearScrollRegion: anchor to srWindow.Top and use window height;
    dwSize.Y was the whole buffer, so the old formula overcleared into
    scrollback whenever the console buffer exceeded the visible window
    (default conhost has ~300-row buffer, 25-row window).
    - ScrollUp: same srWindow.Top anchoring; check
    GetConsoleScreenBufferInfo return; guard 1-row scroll regions that
    would otherwise build an inverted SMALL_RECT.
    - Video_Init: treat both INVALID_HANDLE_VALUE and NULL as handle
    failure; check GetConsoleScreenBufferInfo return; pin output CP to
    437 so CP437 box-drawing renders correctly on non-US locales and
    systems with "Use UTF-8 worldwide" enabled.
    - exit(0) -> exit(1) on error paths.

    win_wrappers.c:
    - display_win32_error: initialize message pointer, check
    FormatMessage return, use _sntprintf, explicit NUL terminator,
    skip LocalFree on NULL.
    - DirExists: switch to GetFileAttributesA; handles "C:\\" and other
    drive roots that the old stat + trailing-slash-strip mishandled.
    - FilesOrderedByDate: replace _findfirst/_findnext with
    FindFirstFileA/FindNextFileA. _findnext's errno behavior on
    end-of-iteration is CRT-dependent; Win32 GetLastError() ==
    ERROR_NO_MORE_FILES is deterministic. struct Sortable.wt widened
    to uint64_t (FILETIME 100-ns ticks).
    - plat_getftime: floor seconds instead of rounding up (tm_sec=59
    produced an out-of-range 30 that read back as invalid 60s).
    - plat_fsopen: add bounded retry on EACCES to approximate Unix
    F_SETLKW behavior -- _fsopen fails fast on sharing violation
    while fcntl(F_SETLKW) blocks, so transient contention (packet
    writes, log rotation) no longer surfaces as spurious open
    failures. Capped at 20 * 50ms = 1s before giving up.

    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

    ---
    ■ Synchronet ■ Vertrauen ■ Home of Synchronet ■ [vert/cvs/bbs].synchro.net