Three fixes: 1. Cursor font mismatch: cursor overlay TextOut used the default DC font instead of FPaintFont (OEM_CHARSET). The wrong font size left residual pixels that buffer BitBlt didn't fully cover. Fix: select FPaintFont + OPAQUE BkMode into the CS_OWNDC screen DC once in RecalcCellSize, and re-assert before cursor TextOut in case VCL Paint altered the DC state. 2. WM_TIMER starvation: on Win16, WM_TIMER is lowest-priority and never dispatched while WM_COMMNOTIFY floods the queue. Fix: render from EndUpdate using GetTickCount throttle (no timer dependency). The timer remains as fallback for idle blink and trailing data. 3. Scroll performance: restore deferred ScrollDC at render time (not during parsing) so only newly-revealed rows need PaintLine instead of all 25. Dirty flags shift with each DoScrollUp to track the correct logical line positions after scroll. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| KPANSI.PAS | ||
| KPCOMM.PAS | ||
| KPTEST.DPR | ||
| README.md | ||
| TESTMAIN.PAS | ||
KP Serial Components for Delphi 1.0
Native Delphi 1.0 components for serial communications and ANSI BBS terminal emulation under Windows 3.1. Both components install to the KP component palette tab.
Components
TKPComm — Serial Communications (KPCOMM.PAS)
Non-visual TComponent descendant providing RS-232 serial I/O via the
Windows 3.1 comm API (OpenComm, BuildCommDCB, SetCommState,
EnableCommNotification, etc.).
Published properties:
| Property | Type | Default | Description |
|---|---|---|---|
| CommPort | Integer | 1 | COM port number (1–16) |
| Settings | string | 9600,N,8,1 |
Baud, parity, data bits, stop bits |
| PortOpen | Boolean | False | Open/close the port |
| InBufferSize | Integer | 4096 | Receive buffer size (bytes) |
| OutBufferSize | Integer | 4096 | Transmit buffer size (bytes) |
| RThreshold | Integer | 0 | Receive notification threshold (0 = disabled) |
| SThreshold | Integer | 0 | Send notification threshold (0 = disabled) |
| Handshaking | THandshaking | hsNone | Flow control (hsNone, hsXonXoff, hsRtsCts, hsBoth) |
| InputLen | Integer | 0 | Max bytes per Input read (0 = all available) |
| InputMode | TInputMode | imText | imText or imBinary |
| DTREnable | Boolean | True | Assert DTR on open |
| RTSEnable | Boolean | True | Assert RTS on open |
| NullDiscard | Boolean | False | Discard received null bytes |
| EOFEnable | Boolean | False | Treat Ctrl-Z as EOF |
| ParityReplace | string | ? |
Replacement char for parity errors |
| OnComm | TNotifyEvent | nil | Fired on comm events (receive, send, modem line changes, errors) |
Public runtime properties:
| Property | Type | Description |
|---|---|---|
| Input | string | Read received data from the buffer |
| Output | string | Write data to the transmit buffer |
| InBufferCount | Integer | Bytes waiting in receive buffer |
| OutBufferCount | Integer | Bytes waiting in transmit buffer |
| CTSHolding | Boolean | CTS line state (shadow, toggled on transitions) |
| DSRHolding | Boolean | DSR line state |
| CDHolding | Boolean | CD/RLSD line state |
| Break | Boolean | Set/clear break condition |
| CommEvent | Integer | Last event code (comEvReceive, comEvCTS, comEvtBreak, etc.) |
Usage:
Comm := TKPComm.Create(Self);
Comm.CommPort := 1;
Comm.Settings := '9600,N,8,1';
Comm.RThreshold := 1;
Comm.OnComm := CommEvent;
Comm.PortOpen := True;
{ Send data }
Comm.Output := 'ATZ' + #13;
{ In OnComm handler }
if Comm.CommEvent = comEvReceive then
Data := Comm.Input;
TKPAnsi — ANSI BBS Terminal Emulator (KPANSI.PAS)
Visual TCustomControl descendant providing a full ANSI terminal display with
scrollback, blinking cursor, 16-color palette, and ANSI music.
Published properties:
| Property | Type | Default | Description |
|---|---|---|---|
| Cols | Integer | 80 | Terminal width in columns (1–256) |
| Rows | Integer | 25 | Terminal height in rows (1–255) |
| ScrollbackSize | Integer | 500 | Maximum scrollback lines |
| CursorVisible | Boolean | True | Show/hide blinking block cursor |
| Font | TFont | Terminal 9pt | Monospace font for rendering |
| Color | TColor | clBlack | Default background color |
| TabStop | Boolean | True | Accept keyboard focus |
| OnKeyData | TKeyDataEvent | nil | Fired when user presses a key |
Public methods and properties:
| Member | Kind | Description |
|---|---|---|
| Write(const S: string) | method | Feed data to the terminal for parsing and display |
| Clear | method | Move screen to scrollback, blank the display, home cursor |
| Reset | method | Reset all attributes, clear screen, home cursor |
| CursorRow | Integer | Current cursor row (0-based, read-only) |
| CursorCol | Integer | Current cursor column (0-based, read-only) |
Supported ANSI escape sequences:
CSI (ESC[) sequences:
| Sequence | Name | Action |
|---|---|---|
| ESC[nA | CUU | Cursor up n rows |
| ESC[nB | CUD | Cursor down n rows |
| ESC[nC | CUF | Cursor forward n columns |
| ESC[nD | CUB | Cursor back n columns |
| ESC[r;cH | CUP | Cursor position (1-based row;col) |
| ESC[r;cf | HVP | Same as CUP |
| ESC[nJ | ED | Erase display (0=below, 1=above, 2=all) |
| ESC[nK | EL | Erase line (0=right, 1=left, 2=all) |
| ESC[nS | SU | Scroll up n lines |
| ESC[nT | SD | Scroll down n lines |
| ESC[nL | IL | Insert n blank lines at cursor |
| ESC[nM | DL | Delete n lines at cursor |
| ESC[n@ | ICH | Insert n blank characters at cursor |
| ESC[nP | DCH | Delete n characters at cursor |
| ESC[paramsm | SGR | Set graphic rendition (see below) |
| ESC[s | SCP | Save cursor position |
| ESC[u | RCP | Restore cursor position |
| ESC[c | DA | Device Attributes — responds ESC[?1;0c (VT100) |
| ESC[5n | DSR | Device Status Report — responds ESC[0n (OK) |
| ESC[6n | CPR | Cursor Position Report — responds ESC[row;colR |
SGR codes:
| Code | Effect |
|---|---|
| 0 | Reset all attributes |
| 1 | Bold (bright foreground) |
| 5 | Blink (rendered as bright background) |
| 7 | Reverse video |
| 22 | Cancel bold |
| 25 | Cancel blink |
| 27 | Cancel reverse |
| 30–37 | Foreground color (ANSI 0–7) |
| 40–47 | Background color (ANSI 0–7) |
DEC private modes:
| Sequence | Effect |
|---|---|
| ESC[?7h | Enable line wrap (default) |
| ESC[?7l | Disable line wrap |
| ESC[?25h | Show cursor |
| ESC[?25l | Hide cursor |
Control characters:
| Char | Effect |
|---|---|
| CR (#13) | Carriage return |
| LF (#10) | Line feed (scrolls at bottom) |
| BS (#8) | Backspace (no erase) |
| TAB (#9) | Tab to next 8-column stop |
| ENQ (#5) | Answerback — responds ESC[?1;0c (VT100) |
| BEL (#7) | System beep |
ANSI Music:
Detected by ESC[M followed by a music string terminated by Ctrl-N (#14).
Syntax: T<tempo> L<length> O<octave> <notes> where notes are A–G with
optional sharp (#/+) or flat (-), duration (1/2/4/8/16), and dot (.)
for dotted notes. P inserts a rest. > and < shift octave. Played
asynchronously via the Windows 3.1 Sound API.
Keyboard mapping (via OnKeyData):
| Key | Output |
|---|---|
| Printable chars | The character itself |
| Enter | CR (#13) |
| Backspace | BS (#8) |
| Tab | TAB (#9) |
| Escape | ESC (#27) |
| Arrow Up/Down/Right/Left | ESC[A / ESC[B / ESC[C / ESC[D |
| Home / End | ESC[H / ESC[K |
| Page Up / Page Down | ESC[V / ESC[U |
| Insert / Delete | ESC[@ / ESC DEL |
| F1–F4 | ESC OP / OQ / OR / OS |
| F5–F10 | ESC Ot / Ou / Ov / Ow / Ox / Oy |
Test Application
KPTEST.DPR / TESTMAIN.PAS — a minimal terminal application that wires the
two components together. The form is created entirely in code (no DFM).
Layout: A toolbar row at the top with port number, settings, Open/Close buttons, and a status label. The TKPAnsi terminal fills the rest of the form.
Wiring:
TKPComm.OnCommhandler readsInputand passes it toTKPAnsi.WriteTKPAnsi.OnKeyDatahandler sends keystrokes toTKPComm.Output
Building
Requires Delphi 1.0.
- Open
KPTEST.DPRin the Delphi IDE - Compile and run (F9)
To install the components for design-time use:
- Component > Install Component
- Add
KPCOMM.PASandKPANSI.PAS - Both appear on the KP palette tab
Files
| File | Description |
|---|---|
KPCOMM.PAS |
TKPComm serial communications component |
KPANSI.PAS |
TKPAnsi ANSI terminal emulator component |
KPTEST.DPR |
Test application project file |
TESTMAIN.PAS |
Test application main form unit |