amiga-bootcamp/10_devices/console.md
2026-04-26 14:46:18 -04:00

244 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[← Home](../README.md) · [Devices](README.md)
# console.device — Text Terminal I/O
## Overview
`console.device` provides an ANSI-compatible text terminal within Intuition windows. It handles:
- **Input**: translating raw keycodes from `input.device` into ASCII/ANSI characters
- **Output**: rendering text, parsing escape sequences for cursor control, color, and formatting
- **Clipboard**: cut/copy/paste integration
Every CLI/Shell window is backed by a console.device unit. Applications can open their own console units in any Intuition window for text I/O without implementing their own keyboard translation or cursor rendering.
```mermaid
flowchart LR
KB["Keyboard<br/>(raw keycodes)"] --> INPUT["input.device"]
INPUT --> CON["console.device"]
CON -->|"Read: ASCII chars"| APP["Application"]
APP -->|"Write: text + ESC sequences"| CON
CON -->|"Renders text via<br/>RastPort drawing"| WIN["Intuition Window"]
style CON fill:#e8f4fd,stroke:#2196f3,color:#333
style WIN fill:#c8e6c9,stroke:#2e7d32,color:#333
```
---
## Opening
```c
struct MsgPort *conPort = CreateMsgPort();
struct IOStdReq *con = (struct IOStdReq *)
CreateIORequest(conPort, sizeof(struct IOStdReq));
/* Attach to an Intuition window: */
con->io_Data = (APTR)window;
con->io_Length = sizeof(struct Window);
if (OpenDevice("console.device", CONU_STANDARD, (struct IORequest *)con, 0))
{
/* error — can't open console */
}
```
### Unit Types
| Unit | Constant | Description |
|---|---|---|
| 0 | `CONU_STANDARD` | Full-feature console with cursor and scrolling |
| 1 | `CONU_CHARMAP` | Character-mapped console (OS 3.0+) — faster for full-screen updates |
| 3 | `CONU_SNIPMAP` | Snip-mapped: supports clipboard cut/paste (OS 3.0+) |
| -1 | `CONU_LIBRARY` | Library mode — no window, just keymap translation |
---
## Writing Text and Escape Sequences
```c
/* Write text to the console window: */
void ConPuts(struct IOStdReq *con, char *str)
{
con->io_Command = CMD_WRITE;
con->io_Data = (APTR)str;
con->io_Length = -1; /* -1 = null-terminated */
DoIO((struct IORequest *)con);
}
/* Usage: */
ConPuts(con, "Hello, Amiga!\n");
ConPuts(con, "\033[1mBold text\033[0m\n"); /* bold on/off */
ConPuts(con, "\033[33mYellow text\033[0m\n"); /* color */
ConPuts(con, "\033[10;20HText at row 10 col 20"); /* absolute position */
```
---
## Reading Input
```c
/* Read characters (blocking): */
char buffer[256];
con->io_Command = CMD_READ;
con->io_Data = (APTR)buffer;
con->io_Length = sizeof(buffer);
DoIO((struct IORequest *)con);
/* con->io_Actual = number of bytes read */
/* Non-blocking read via SendIO + WaitPort: */
con->io_Command = CMD_READ;
con->io_Data = (APTR)buffer;
con->io_Length = 1; /* read 1 char at a time */
SendIO((struct IORequest *)con);
/* Wait for input alongside other events: */
ULONG consoleSig = 1 << conPort->mp_SigBit;
ULONG windowSig = 1 << window->UserPort->mp_SigBit;
ULONG sigs = Wait(consoleSig | windowSig);
if (sigs & consoleSig)
{
WaitIO((struct IORequest *)con);
char ch = buffer[0];
/* process character... */
}
```
---
## ANSI Escape Sequences
Console.device supports a rich subset of ANSI/VT100 escape sequences (CSI = `\033[` = ESC + `[`):
### Cursor Movement
| Sequence | Description | Example |
|---|---|---|
| `\033[nA` | Cursor up n lines | `\033[5A` = up 5 |
| `\033[nB` | Cursor down n lines | |
| `\033[nC` | Cursor right n columns | |
| `\033[nD` | Cursor left n columns | |
| `\033[y;xH` | Move to row y, column x (1-based) | `\033[1;1H` = home |
| `\033[H` | Home cursor (top-left) | |
| `\033[6n` | Report cursor position → replies `\033[y;xR` | |
| `\033[s` | Save cursor position | |
| `\033[u` | Restore cursor position | |
### Erasing
| Sequence | Description |
|---|---|
| `\033[J` | Clear from cursor to end of screen |
| `\033[1J` | Clear from start of screen to cursor |
| `\033[2J` | Clear entire screen |
| `\033[K` | Clear from cursor to end of line |
| `\033[1K` | Clear from start of line to cursor |
| `\033[2K` | Clear entire line |
### Text Attributes (SGR)
| Sequence | Effect |
|---|---|
| `\033[0m` | Reset all attributes |
| `\033[1m` | **Bold** (high intensity) |
| `\033[3m` | *Italic* |
| `\033[4m` | <u>Underline</u> |
| `\033[7m` | Inverse video (swap fg/bg) |
| `\033[22m` | Normal intensity (cancel bold) |
| `\033[23m` | Cancel italic |
| `\033[24m` | Cancel underline |
### Colors
| Sequence | Foreground | Background |
|---|---|---|
| `\033[30m` / `\033[40m` | Black | Black |
| `\033[31m` / `\033[41m` | Red | Red |
| `\033[32m` / `\033[42m` | Green | Green |
| `\033[33m` / `\033[43m` | Yellow/Brown | Yellow/Brown |
| `\033[34m` / `\033[44m` | Blue | Blue |
| `\033[35m` / `\033[45m` | Magenta | Magenta |
| `\033[36m` / `\033[46m` | Cyan | Cyan |
| `\033[37m` / `\033[47m` | White | White |
| `\033[39m` / `\033[49m` | Default | Default |
> [!NOTE]
> Color indices map to the **Intuition pen palette** of the window's screen, not absolute colors. Pen 0 = background, pen 1 = foreground by default.
### Amiga-Specific Extensions
| Sequence | Description |
|---|---|
| `\033[>1h` | Enable auto-scroll |
| `\033[>1l` | Disable auto-scroll |
| `\033[ p` | Enable cursor |
| `\033[0 p` | Disable cursor |
| `\033[t` / `\033[b` | Set top/bottom scroll margins |
| `\033[20h` | Linefeed mode (LF = CR+LF) |
---
## Raw Key Events
In addition to ASCII, console.device reports **special keys** as multi-byte escape sequences:
| Key | Sequence Received |
|---|---|
| Cursor Up | `\033[A` |
| Cursor Down | `\033[B` |
| Cursor Right | `\033[C` |
| Cursor Left | `\033[D` |
| Shift+Up | `\033[T` |
| Shift+Down | `\033[S` |
| F1F10 | `\033[0~` `\033[9~` |
| Shift+F1F10 | `\033[10~` `\033[19~` |
| Help | `\033[?~` |
---
## Proper Shutdown
```c
/* Must abort any pending read before closing: */
if (!CheckIO((struct IORequest *)con))
{
AbortIO((struct IORequest *)con);
WaitIO((struct IORequest *)con);
}
CloseDevice((struct IORequest *)con);
DeleteIORequest((struct IORequest *)con);
DeleteMsgPort(conPort);
```
---
## CON: and RAW: Handlers
The AmigaDOS file handlers `CON:` and `RAW:` are wrappers around console.device:
| Handler | Description |
|---|---|
| `CON:` | Line-buffered console — input is buffered until Enter is pressed. Supports line editing. |
| `RAW:` | Raw console — each keypress is delivered immediately. No line editing. |
```c
/* Open a CON: window from DOS: */
BPTR fh = Open("CON:0/0/640/200/My Window/CLOSE", MODE_OLDFILE);
FPuts(fh, "Type something: ");
char buf[80];
FGets(fh, buf, sizeof(buf));
Close(fh);
/* RAW: for unbuffered key-by-key input: */
BPTR raw = Open("RAW:0/0/640/200/Raw Input", MODE_OLDFILE);
/* Each Read returns immediately with 1 char */
```
---
## References
- NDK39: `devices/conunit.h`, `devices/console.h`
- ADCD 2.1: console.device autodocs
- See also: [keyboard.md](keyboard.md) — raw keycode to console.device pipeline
- See also: [input.md](input.md) — input handler chain