• Reset terminal scroll region (and origin/wrap modes) after external pr

    From Rob Swindell@1:103/705 to GitLab issue in main/sbbs on Mon Jun 8 17:37:45 2026
    open https://gitlab.synchro.net/main/sbbs/-/issues/1161

    ## Summary

    After running an external program (door), Synchronet resets the user's **text attributes** but not other terminal **modes** the door may have changed — notably the **DECSTBM scroll region**, **origin mode (DECOM)**, and **autowrap**. A door that sets one of these and exits without clearing it leaves the BBS session in that state, corrupting everything Synchronet draws afterward (menus, prompts, etc.).

    ## Current behavior

    `sbbs_t::external()` does, on the way out (both the Unix and Win32 paths):

    ```c
    curatr = ~0; // Can't guarantee current attributes
    attr(LIGHTGRAY); // Force to "normal"
    ```

    `xtrn.cpp` ~line 926 (Unix) and ~line 2084 (Win32). The `// Can't guarantee current attributes` comment already acknowledges the door may have left the terminal dirty — but only the SGR attributes are reconciled.

    ## The problem

    If a door sets `CSI top;bottom r` (DECSTBM) to confine scrolling to a sub-region and doesn't emit `CSI r` before exit, the region persists. The next thing Synchronet prints (e.g. the external-programs menu) then scrolls **inside that region**, leaving the rows above frozen and large gaps/garbled numbering in the menu. Origin mode (DECOM) and autowrap have the same hazard.

    **Concrete example:** a v6 Z-machine graphics door that uses a DECSTBM scroll region to protect a pinned pixel image from text scrolling. If it exits abnormally (or simply forgets the reset), the corrupted door menu is immediately visible. (The door has since been fixed to always emit `CSI r` on exit, but the broader point is that the BBS shouldn't depend on every door being well-behaved.)

    ## Suggested fix

    Alongside the existing `attr(LIGHTGRAY)` in both `external()` paths, defensively reset the common stateful modes — gated on the user being ANSI-capable so non-ANSI terminals don't receive the bytes:

    ```c
    if (term_supports(ANSI))
    rputs("\x1b[r" // reset scroll region (DECSTBM)
    "\x1b[?6l" // origin mode off (DECOM)
    "\x1b[?7h"); // autowrap on (the default)
    ```

    (Exact raw-output call / helper is your call.) Deliberately **not** a full `RIS` (`ESC c`) — that clears the screen and resets fonts/charset, which is too heavy to do after every door.

    This makes each door start (and the menus after it) from a known scrolling/origin/wrap state regardless of what the previous program left behind.

    — *Authored by Claude (Claude Code), on behalf of @rswindell*
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)
  • From Deucе@1:103/705 to GitLab note in main/sbbs on Tue Jun 9 13:38:39 2026
    https://gitlab.synchro.net/main/sbbs/-/issues/1161#note_9313

    Honestly, a `RIS` then restore what you want is the right move. Hacking at various private modes is as likely to cause issues in old terminals as it is to fix issues in new terminals.
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)