WinComm/delphi/KPCOMM.md
Scott Duensing ec6eebb2a5 Add TrueType font support with 4-tier font selection and documentation
Replace the inherited Font property with a FontSize property that drives
a multi-tier font selection strategy for pixel-perfect OEM rendering:
Terminal raster (exact size) > Perfect DOS VGA 437 (multiples of 8px) >
Terminal raster (nearest) > stock OEM fallback.  Add DxBuf uniform
character spacing to ExtTextOut for correct TrueType monospace rendering.
Bundle the Perfect DOS VGA 437 font (cmap converted from format 6 to
format 0 for Win 3.1 compatibility).  Size the test form dynamically
from terminal dimensions.  Add component documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:15:11 -06:00

139 lines
5.5 KiB
Markdown

# TKPComm - Serial Communications Component
TKPComm is a non-visual Delphi 1.0 component providing serial port access
via the Windows 3.1 comm API. It is a TComponent descendant that wraps
OpenComm, ReadComm, WriteComm, and related functions into a property-driven
interface. The application polls for received data; there is no event-driven
notification infrastructure (no hidden window, no WM_COMMNOTIFY, no
OnComm event).
Installs to the **KP** component palette tab.
## Properties
### Published (Design-Time and Runtime)
| Property | Type | Default | Description |
|---|---|---|---|
| CommPort | Integer | 1 | Port number 1-16 (1=COM1, 2=COM2, etc.). Cannot be changed while port is open. |
| Settings | string | '9600,N,8,1' | Baud rate, parity, data bits, stop bits. Format: `baud,parity,databits,stopbits`. Can be changed while port is open to reconfigure on the fly. |
| PortOpen | Boolean | False | Opens or closes the serial port. Setting True calls OpenComm, BuildCommDCB, and SetCommState; False calls CloseComm. |
| InBufferSize | Integer | 4096 | Receive ring buffer size in bytes (minimum 64). Cannot be changed while port is open. |
| OutBufferSize | Integer | 4096 | Transmit ring buffer size in bytes (minimum 64). Cannot be changed while port is open. |
| Handshaking | THandshaking | hsNone | Flow control method (see below). Can be changed while port is open. |
| InputLen | Integer | 0 | Maximum bytes returned per Input read. 0 means up to 255 bytes. |
| InputMode | TInputMode | imText | Data reading mode. imBinary preserves embedded null bytes. |
| DTREnable | Boolean | True | Assert Data Terminal Ready when True. Toggled immediately if port is open. |
| RTSEnable | Boolean | True | Assert Request To Send when True. Toggled immediately if port is open. |
| NullDiscard | Boolean | False | Strip null bytes from received data. |
| EOFEnable | Boolean | False | Enable EOF character detection. |
| ParityReplace | string | '?' | Character substituted for parity errors. Empty string disables replacement. |
### Public (Runtime Only)
| Property | Type | Access | Description |
|---|---|---|---|
| Input | string | Read | Reads available data from the receive buffer. Limited to 255 bytes per call (Delphi short string). Use ReadInputBuf for larger reads. |
| Output | string | Write | Writes data to the transmit buffer. Raises an exception if the port is not open or the write fails. |
| InBufferCount | Integer | Read | Bytes currently waiting in the receive buffer. |
| OutBufferCount | Integer | Read | Bytes currently waiting in the transmit buffer. |
| Break | Boolean | Read/Write | Asserts or clears the break signal via SetCommBreak/ClearCommBreak. |
## Methods
### Public
| Method | Description |
|---|---|
| Create(AOwner) | Constructor. Initializes defaults; FCommId set to -1 (closed). |
| Destroy | Destructor. Closes the port if still open. |
| ReadInputBuf(Buf, BufSize): Integer | Reads up to BufSize bytes into a caller-supplied PChar buffer. Returns the number of bytes actually read. Bypasses the 255-byte short string limit of the Input property. |
## Types
### THandshaking
```
hsNone No flow control
hsXonXoff Software XON/XOFF (XON=$11, XOFF=$13)
hsRtsCts Hardware RTS/CTS
hsBoth Combined RTS/CTS and XON/XOFF
```
### TInputMode
```
imText Text mode (default)
imBinary Binary mode (preserves embedded nulls)
```
## DCB Flag Constants
Bit masks for the packed TDCB.Flags field:
| Constant | Value | Description |
|---|---|---|
| dcbBinary | $0001 | Binary mode (always set) |
| dcbRtsDisable | $0002 | RTS disabled |
| dcbParity | $0004 | Parity check/replacement |
| dcbOutxCtsFlow | $0008 | CTS output flow control |
| dcbOutxDsrFlow | $0010 | DSR output flow control |
| dcbDtrDisable | $0020 | DTR disabled |
| dcbOutX | $0040 | XON/XOFF output flow control |
| dcbInX | $0080 | XON/XOFF input flow control |
| dcbPeChar | $0100 | Parity error character replacement |
| dcbNull | $0200 | Null byte stripping |
| dcbChEvt | $0400 | Character event notification |
| dcbDtrflow | $0800 | DTR flow control |
| dcbRtsflow | $1000 | RTS flow control |
## Port Lifecycle
1. Create the component and set properties (CommPort, Settings, buffer sizes,
Handshaking, etc.).
2. Set `PortOpen := True`. This calls OpenComm, builds the DCB from
the Settings string, applies flow control, null discard, parity replace,
and asserts DTR/RTS.
3. Poll `Input` or call `ReadInputBuf` in the application's main loop.
Set `Output` to send data.
4. Set `PortOpen := False` to close. DTR and RTS are cleared, break is
released, and CloseComm is called.
5. The destructor closes the port automatically if still open.
## Usage Example
```pascal
FComm := TKPComm.Create(Self);
FComm.CommPort := 1;
FComm.Settings := '115200,N,8,1';
FComm.PortOpen := True;
{ In the main loop: }
Len := FComm.ReadInputBuf(@Buf, SizeOf(Buf));
if Len > 0 then
ProcessData(@Buf, Len);
{ To send data: }
FComm.Output := 'AT' + #13;
```
## Platform Notes
- Targets Windows 3.1 using the 16-bit comm API (OpenComm, ReadComm,
WriteComm, GetCommState, SetCommState, GetCommError,
EscapeCommFunction, BuildCommDCB).
- No notification infrastructure. The application must poll for data.
There is no hidden window, no WM_COMMNOTIFY handling, and
EnableCommNotification is not used.
- The Input property is limited to 255 bytes by Delphi 1.0's short
string type. Use ReadInputBuf for bulk reads (2048+ bytes per call).
- EscapeCommFunction returns 0 on success in the 16-bit API (opposite
of the Win32 convention).
- Uses `{ }` comments (Delphi 1.0 does not support `//` comments).