Platform: CP/M 2.2, Intel 8080 Assembler: Microsoft M80 / L80 Terminal: VT100 / ANSI Editing Model: Full-screen, ESC-menu driven, WordStar-compatible control keys Version: 1.27
SEDIT is a full-screen plain-text editor for CP/M 2.2 written in Intel 8080 assembly language, assembled with M80 and linked with L80. It supports VT100/ANSI, VT52, ADM-31, and Cromemco 3102 terminals. Navigation and editing use WordStar-style Ctrl-key bindings as the default set; bindings are user-configurable via an external key binding file (SEDIT.KEY). Pressing ESC opens an interactive menu for file, navigation, and block operations.
- Fast, responsive screen editing on a 2 MHz 8080 system
- Single edit buffer with full TPA utilization; virtual buffer mode for files larger than RAM
- ESC-driven command menu with keyboard navigation
- Find text search
- Block mark, copy, paste, and delete
- Optional syntax highlighting for assembly language (
.MAC,.ASM,.INC) and C (.C,.H) files (compile-time option) - User-configurable key bindings loaded from
SEDIT.KEYon startup - Horizontal scrolling for lines wider than the visible text area
- Auto-indent on Enter (copies leading whitespace from the current line)
- Clean return to CP/M on exit; no file corruption on abort
- Mouse support
- Undo history
- Binary file editing
- Subdirectory file paths (CP/M 2.2 is flat)
VT100 terminal, 80 or 132 columns (auto-detected at startup, togglable via ESC menu). Row count is auto-detected (24-30+ rows supported). The screen is divided into five zones; the edit area grows dynamically with terminal height.
Row 1 +-- Info bar ----------------------------------------------------------------+
Row 2 | Tab stop ruler |
Row 3 | +== edit area top ======================================================+ |
... | || text lines (rows 3-22) || |
Row 22 | +== edit area bottom ===================================================+ |
Row 23 | ========================================================================== |
Row 24 +-- Status / operation bar --------------------------------------------------+
Displays file metadata for the active buffer.
A:MAIN .MAC* Lines:1024 Row: 142 Col: 35 [INS]
B3:TEST .C * Lines: 50 Row: 12 Col: 1 [INS]
| Field | Description |
|---|---|
| Drive + filename | A:MAIN.MAC or B3:TEST.C — CP/M drive letter, optional user number (0-15), and 8.3 filename (magenta if COLOR enabled) |
* after filename |
Shown when the buffer has unsaved changes |
Lines:nnnn |
Total number of lines in the file (blue if COLOR enabled) |
Row:nnnn |
Current cursor line, 1-based (blue) |
Col:nnnn |
Current cursor column within the text, 1-based, tabs expanded (blue) |
[INS] / [OVR] |
Insert mode (green) or Overwrite mode (red) |
[Free:nnnnn] |
Free buffer space in bytes (non-virtual mode) |
[Vssss,eeee] |
Virtual buffer line range (virtual mode) |
All numeric fields are 4-digit, right-justified with leading spaces (max 9999). If no file is loaded, the filename area shows [No Name]. Drive byte 0 (default) queries the current disk via BDOS.
A ruler showing tab stop positions within the text area (rendered dim if COLOR enabled).
: : : : : : : : : : : : : : :
- Each
:marks a tab stop (every 4 columns, TABWID=4) - Ruler starts at column TXTFCOL (6), aligned with the text area
Each row shows one line of text in the following fixed format:
COL: 1 2 3 4 5 6 ---------------------------------------------------- 80
| | | | | |
+--line no--+ sp +------------- up to 73 characters of text -----------+
| Columns | Content |
|---|---|
| 1-4 | Line number, right-justified, space-padded (4-digit field) |
| 5 | Single space separator |
| 6-80 | Text content — up to 73 visible characters per line (TXTCOLS=73) |
- Line numbers are right-justified in a 4-character field (columns 1-4)
- Lines 1-9999 display as
1,42,9999 - The current cursor line's number is displayed in bold (SGR 1)
- Lines within a marked block have their line numbers displayed in reverse video (SGR 7)
- Line number gutter is bold green if COLOR is enabled
- Maximum stored line width: 255 characters (MAXCOLS=255, excluding line terminator)
- Visible text area: 73 columns (TXTCOLS=73, terminal columns 6-78)
- Lines longer than the visible area are handled by horizontal scrolling (HSCROL variable)
- Horizontal scroll auto-adjusts as the cursor moves beyond the visible range
- On disk, each line is stored as characters followed by
0DH 0AH(CR/LF)
- Tab characters (
09H) in the buffer are expanded to spaces at the next tab stop (TABWID=4) - Tab expansion is display-only; the stored byte is a literal
09H
A full 80-character line of = characters (drawn dim if COLOR enabled). In virtual buffer mode, shows the line ranges above and below the edit buffer (e.g., ^^^ Lines 1-938 above === Lines 1877-3279 below vvv).
Used for two purposes:
-
Status messages — transient informational text:
Saving file... File saved. Not found. Buffer full. -
Input prompts — when a menu operation requires text input:
Find text: _ Open file: _ Save as: _ Go to line: _
Pressing ESC at any time opens the command menu. The menu overlays the edit area with a bordered panel; the edit area is restored when the menu is dismissed.
+==========================+
| SEDIT MENU |
+==========================+
| 1. Open File |
| 2. Save File |
| 3. Save As... |
| 4. Find text... |
| 5. Go To Line... |
| 6. Help |
| 7. About |
| 8. Toggle 80/132 col |
| 9. Exit |
+==========================+
Menu geometry: top-left at row 6/col 28, bottom-right at row 18/col 54.
| Key | Action |
|---|---|
Up / Down arrow, ^E / ^X, K / J |
Move highlight |
Enter or digit 1-9 |
Execute item |
| Shortcut letter (O/S/A/F/G/H/B/W/X/Q) | Execute item directly |
| ESC | Cancel menu, return to editing |
- Prompt on row 24:
Open file: _ - User types drive + filename (8.3 format)
- File is loaded into the buffer; if file does not exist, opens an empty buffer with the given name
- Status:
New fileif file not found
- Save active buffer to its filename
- Creates a
.BAKbackup of the previous version before saving - Uses BDOS F_DELETE + F_MAKE + sequential F_WRITE
- Status:
Saving file...thenFile saved. - If filename is
[No Name], prompts for a filename first (Save As behavior)
- Prompt:
Save as: _ - User enters a new filename; saves buffer under the new name
- Updates the buffer's filename after save
- Prompt:
Find text: _ - User enters search string (max 64 characters); Enter to search
- Search begins from cursor position, wraps to top of file if not found before EOF
- Cursor placed at match start if found
- Status:
Found at line norNot found
- Prompt:
Go to line: _ - User enters a decimal line number; cursor moves to that line
- Uses GBGOTOL for fast bulk cursor movement
- Displays a full-screen key reference overlay (see section 4)
- Press any key to return to editing; the footer prompt is cleared on dismiss
- Displays
SEDIT v1.27 CP/M Screen Editoron the status bar - Press any key to dismiss
- Toggles between 80 and 132 column display modes via VT100 DECCOLM escape sequences
- Editor auto-detects the current column mode at startup; the toggle switches between the two modes
- Restores terminal to the column mode detected at startup
- If buffer is modified, prompts to save
- Clears screen and warm boots via
JMP 0000H
These bindings are active with the default configuration. ESC always opens the menu and is not rebindable.
| Key | Action |
|---|---|
^E / Up arrow |
Cursor up (sticky column) |
^X / Down arrow |
Cursor down (sticky column) |
^S / Left arrow |
Cursor left |
^D / Right arrow |
Cursor right |
^A |
Previous word |
^F |
Next word |
^R / PgUp |
Page up |
^C / PgDn |
Page down |
^W |
Scroll screen up one line |
^Z |
Scroll screen down one line |
^QS / Home |
Jump to start of line |
^QD / End |
Jump to end of line |
^QR |
Jump to top of file |
^QC |
Jump to end of file |
Sticky column: When moving up or down, the cursor maintains its original column position across consecutive vertical moves. If a line is shorter than the remembered column, the cursor moves to the end of that line but resumes the original column on subsequent lines that are long enough. Any non-vertical action (typing, left/right, etc.) resets the sticky column.
| Key | Action |
|---|---|
| Printable character | Insert (Insert mode) or Overwrite |
^H / Backspace |
Delete character left |
^G / Delete |
Delete character at cursor |
^T |
Delete word right |
^Y |
Delete current line |
^I / Tab |
Insert tab |
^M / Enter |
Insert newline with auto-indent |
^V / Insert |
Toggle Insert / Overwrite mode |
Auto-indent: When Enter is pressed, the new line automatically inherits the leading whitespace (spaces and tabs) from the current line. This applies to all file types.
| Key | Action |
|---|---|
^KB / F3 |
Toggle block mark (start -> end -> clear) |
^KC |
Copy marked block to clipboard |
^O |
Copy marked block (alternate) |
^KD |
Delete marked block |
^KP |
Paste clipboard at cursor |
| Key | Action |
|---|---|
^KS / F2 |
Save file |
^KX |
Exit (with save prompt) |
^KQ |
Quit (with save prompt) |
^QF |
Find text (prompt for search string) |
^QA |
Find and replace (interactive Y/N/A/Esc per match) |
^L / F1 |
Find next occurrence |
^Q[ or ^Q] |
Jump to matching {/} or (/) |
| ESC / F4 | Open menu |
| Key | Action |
|---|---|
| F1 | Find next |
| F2 | Save file |
| F3 | Block mark |
| F4 | Open menu |
The key decoder handles both ANSI (CSI) and application (SS3) cursor key modes:
| Sequence | Action |
|---|---|
ESC [ A / ESC O A |
Cursor up |
ESC [ B / ESC O B |
Cursor down |
ESC [ C / ESC O C |
Cursor right |
ESC [ D / ESC O D |
Cursor left |
ESC [ H / ESC [ 1 ~ |
Home (line start) |
ESC [ F / ESC [ 4 ~ |
End (line end) |
ESC [ 2 ~ |
Insert (toggle mode) |
ESC [ 3 ~ |
Delete right |
ESC [ 5 ~ |
Page up |
ESC [ 6 ~ |
Page down |
ESC disambiguation: polls console status ~500 times (~1 ms at 2 MHz) before deciding a standalone ESC is a menu request.
SEDIT loads SEDIT.KEY from the current drive at startup. If the file is not present, the compiled-in default bindings (section 4) are used.
Plain text, one binding per line. Lines beginning with ; are comments. Blank lines are ignored.
; SEDIT.KEY - Custom key bindings
; Format: TYPE PARAM ACTION
; Control key bindings (0-31)
CTRL 5 CURUP ; ^E = cursor up
CTRL 24 CURDN ; ^X = cursor down
CTRL 19 CURLT ; ^S = cursor left
CTRL 4 CURRT ; ^D = cursor right
| Keyword | Format | Description |
|---|---|---|
CTRL |
CTRL <n> <action> |
Bind Ctrl key (0-31) to action |
CSI |
CSI <byte> <param> <action> |
Bind CSI escape sequence |
SS3 |
SS3 <byte> <action> |
Bind SS3 escape sequence |
CTK |
CTK <char> <action> |
Bind Ctrl-K prefix sequence |
CTQ |
CTQ <char> <action> |
Bind Ctrl-Q prefix sequence |
Action names are case-insensitive. Supported names:
| Action | Description |
|---|---|
CURUP |
Cursor up |
CURDN |
Cursor down |
CURLT |
Cursor left |
CURRT |
Cursor right |
WRDPV |
Previous word |
WRDNX |
Next word |
PGUP |
Page up |
PGDN |
Page down |
SCRUP |
Scroll screen up |
SCRDN |
Scroll screen down |
LINST |
Line start |
LINEN |
Line end |
FTOP |
File top |
FEND |
File end |
DELLF |
Delete left (backspace) |
DELRT |
Delete right |
DELWD |
Delete word right |
DELLN |
Delete line |
INSTB |
Insert tab |
INSNL |
Insert newline |
TOGIN |
Toggle insert/overwrite |
LITNX |
Literal next character |
FNDNX |
Find next |
FSAVE |
Save file |
FOPEN |
Open file |
FEXIT |
Exit editor |
BLKMK |
Block mark |
BLKCP |
Block copy |
BLKDL |
Block delete |
BLKPS |
Block paste |
MENU |
Open ESC menu |
FIND |
Find text (always prompt) |
REPL |
Find and replace |
JMPM |
Jump to matching brace |
The edit buffer uses a gap buffer: a flat RAM array with a movable hole at the cursor position.
Memory: [pre-gap text R1][---GAP---][post-gap text R2]
base GAPBG GAPEN base+BSIZE
- R1 = base .. base+GAPBG-1 (text before cursor)
- R2 = base+GAPEN .. base+BSIZE-1 (text after cursor)
- Cursor is always at the gap. Insert = write at GAPBG, advance GAPBG.
- Line delimiter: LF (
0AH) in buffer. Files stored as CR+LF on disk, LF-only internally.
Offset Size Field Description
------ ---- ---------- ---------------------------------------------------
0 2 BD_BSTAR Buffer base address in RAM
2 2 BD_BSIZE Total buffer capacity in bytes
4 2 BD_GAPBG Offset: start of gap (first unused byte)
6 2 BD_GAPEN Offset: end of gap (first text byte after gap)
8 2 BD_TXEND Logical text length (total chars in buffer)
10 2 BD_TOPLN Line number at top of visible screen (0-based)
12 1 BD_CSROW Cursor row on screen (0-based, 0-19)
13 1 BD_CSCOL Cursor column within text (0-based)
14 2 BD_CSOFF Cursor byte offset in logical text
16 2 BD_MRKBG Block mark start offset (FFFFH = no mark)
18 2 BD_MRKEN Block mark end offset (FFFFH = no mark)
20 1 BD_MODIF Non-zero if buffer has unsaved changes
21 1 BD_SYNMD Syntax mode: 0=plain, 1=ASM, 2=C
22 12 BD_FNAME Drive (1) + name (8) + ext (3)
BD_FNAME layout: byte 0 = drive (0=default, 1=A, 2=B, etc.), bytes 1-8 = filename (space-padded), bytes 9-11 = extension (space-padded).
| Function | Description |
|---|---|
| GBINIT | Initialize empty buffer with base address and size |
| GBINSRT | Insert character at cursor; auto-increments line count on LF |
| GBDLFT | Delete character left (backspace); auto-absorbs preceding CR when deleting LF |
| GBDELRT | Delete character right |
| GBMVUP/DN/LT/RT | Move cursor one line/character |
| GBMLNS/GBMLNE | Move cursor to line start/end |
| GBMVTOP/GBMVEND | Move cursor to file top/end |
| GBPGUP/GBPGDN | Page up/down (EDITROW lines) |
| GBDLLN | Delete entire current line |
| GBWRDPV/GBWRDNX | Move to previous/next word boundary |
| GBCURLN | Get current line text (O(line_length), scans backward from gap) |
| GBGETLN | Get line N text (O(line_number), scans from offset 0) |
| GBCNTLN | Count total lines in buffer (cached) |
| GBGOTOL | Go to line N (fast bulk move: moves to top, then forward-scans for N LFs) |
| GBRDLNO | Read line at a given logical offset |
| GBLOGRD | Read logical byte at offset HL (handles gap transparently) |
| GBFNDCS | Find TOPLN offset via backward scan from cursor |
Single-buffer configuration. All available TPA is used for the edit buffer.
FFFF +-------------------------------------------+
| CP/M (BIOS + BDOS + CCP) | ~8 KB
+-------------------------------------------+ TPATOP (from 0006H)
| |
| Gap buffer (single edit buffer) | All remaining TPA
| |
+-------------------------------------------+ BMDATEND
| SEDIT code (CSEG) + data (DSEG) | ~20-22 KB
0100 +-------------------------------------------+
- BMDATEND is defined at the end of SEHELP.MAC's CSEG (the last linked module)
- Buffer base = BMDATEND, buffer size = TPATOP - BMDATEND
- Minimum 9 KB free memory beyond the editor binary (MINMEM = 9*1024); refuses to run if less
- Typical usable buffer: ~30-38 KB on a 64K system
Two compile-time options control feature inclusion:
| Option | Values | Effect |
|---|---|---|
COLOR |
0 or 1 | Color SGR strings for info bar, gutter, ruler, separator |
SYNHI |
0, 1, or 2 | Syntax highlighting (0=none, 1=ASM, 2=C) |
These are defined as EQU constants in the inlined SEDIT.INC within SESCREEN.MAC and SESYNTAX.MAC. Code is conditionally assembled with IF COLOR, IF SYNHI, and IF COLOR+SYNHI guards.
When SYNHI=1, the following ASM token classes are highlighted:
| Token Type | SGR | Color/Style |
|---|---|---|
| Label (col 1 identifier) | 33 | Yellow |
| Opcode / mnemonic | 93 | Bright yellow |
| Directive (EQU, EXTRN, PUBLIC, ORG, CSEG, DSEG, DB, DW, DS, IF, ENDIF, END, etc.) | 34 | Blue |
| Register (A B C D E H L M SP PC HL DE BC AF) | 36 | Cyan |
| Numeric literal | 34 | Blue |
String literal ('...' or "...") |
35 | Magenta |
Comment (; to EOL) |
32 | Green |
| Normal text | 0 | Normal |
When SYNHI=2, the following C token classes are highlighted:
| Token Type | SGR | Color/Style |
|---|---|---|
| Keyword | 93 | Bright yellow |
Preprocessor directive (#) |
35 | Magenta |
| String / character literal | 33 | Yellow |
| Numeric literal | 34 | Blue |
Comment (// or /* ... */) |
32 | Green |
| Open/close brace (depth 0) | 91 | Bright red |
| Open/close brace (depth 1) | 92 | Bright green |
| Open/close brace (depth 2) | 94 | Bright blue |
| Normal text | 0 | Normal |
Braces ({ and }) are colored by nesting depth, cycling through red, green, and blue (depth mod 3). A closing brace matches the color of its corresponding opening brace. Brace nesting depth is tracked across lines via a pre-scan from the start of the file.
Syntax mode is set automatically by SYNINIT based on file extension (.MAC, .ASM, .INC -> SYN_ASM; .C, .H -> SYN_C; all others -> SYN_NONE).
A>SEDIT Start with empty buffer
A>SEDIT MYFILE.TXT Open file on current drive and user area
A>SEDIT C:MYFILE.TXT Open file on drive C:
A>SEDIT B3:MYFILE.TXT Open file on drive B:, user area 3
A>SEDIT 11:MYFILE.TXT Open file on current drive, user area 11
A>SEDIT C11:MYFILE.TXT F: Drive C: user 11, virtual temp on F:
The command tail is parsed directly (not via the CCP default FCB) to support the d[u]: prefix format where d is a drive letter (A-P) and u is an optional user number (0-15). The second argument specifies the virtual temp file drive; user numbers are not allowed on the temp drive.
If a user number is specified, SEDIT switches to that user area (BDOS function 32) for all file operations on the edited file, and restores the original user area when done. Virtual temp files are always created in the current user area on the temp drive.
- Build FCB from filename; save filename into BD_FNAME
- Switch to file's user area if specified (BDOS 32)
- Initialize gap buffer to empty
- Open via BDOS BF_FOPEN
- If not found: proceed as new empty file with
New filestatus - Read 128-byte records (BF_FREAD) sequentially into buffer:
- Skip CPMEOF (
1AH) markers - CR stored as-is (invisible in display)
- LF marks line boundary
- Lines wider than MAXCOLS (255) chars generate a warning
- Skip CPMEOF (
- Close file; restore original user area
- Move cursor to top; clear MODIFIED flag
- If virtual mode was activated during loading, rebalance the buffer around line 1 via VIGOTO to provide ~4 KB of editing headroom
- Call SYNINIT to detect syntax mode from extension
- Check BD_MODIF — skip if buffer is clean
- Switch to file's user area if specified (BDOS 32)
- Build FCB from BD_FNAME
- Rename existing file to
.BAK(delete old .BAK first) - Create new file via BDOS BF_FMAKE
- Write buffer contents record-by-record via GBLOGRD:
- Convert LF to CR+LF on output
- Pad final 128-byte record with zeros
- Append CPMEOF marker
- Close file; restore original user area; clear MODIFIED flag
A keyboard mapping file SEDIT.CNF is included for Tera Term users. To install:
- Copy
SEDIT.CNFto your Tera Term directory - In Tera Term: Setup -> Keyboard -> Read keyboard file -> select
SEDIT.CNF(or setKeyCnfFN=SEDIT.CNFinTERATERM.INI)
This maps PC keyboard keys (arrows, Home, End, PgUp, PgDn, Insert, Delete, F1-F4) to the VT100 escape sequences SEDIT expects.
ESC [ row ; col H (rows and cols are 1-based)
ESC [ 0 m reset
ESC [ 1 m bold
ESC [ 2 m dim
ESC [ 7 m reverse video
ESC [ 3n m foreground color n (0-7)
The main loop uses a two-flag dirty system to minimize screen updates:
| DIRTY | DRTLINE | Action |
|---|---|---|
| 1 | * | SCRDRAW: full 20-line redraw + ruler + separator + status clear |
| 0 | 1 | SCREDCL: current line only (uses GBCURLN for O(line_length) access) |
| 0 | 0 | No content redraw (cursor-only move) |
INFOBAR and CURPOS always run regardless of dirty flags.
Reads BDOS BF_RAWIO in non-blocking mode. Seven states:
| State | Description |
|---|---|
| KST_IDL (0) | Idle — no prefix active |
| KST_ESC (1) | Received ESC — waiting for [, O, or timeout |
| KST_CSI (2) | Received ESC [ — waiting for final byte |
| KST_SS3 (3) | Received ESC O — waiting for final byte |
| KST_CSP (4) | CSI with parameter digits accumulating |
| KST_CTK (5) | Ctrl-K prefix active — waiting for second key |
| KST_CTQ (6) | Ctrl-Q prefix active — waiting for second key |
Returns: B = key type (KT_NONE, KT_ACT, KT_CHAR), C = action code or ASCII character.
All source files follow CP/M 8.3 naming. SEDIT is built from 12 modules plus a shared include file.
| Source File | Purpose |
|---|---|
SEDIT.MAC |
Entry point, main loop, action dispatch, command-line parsing, memory allocation |
SEDIT.INC |
Shared equates included via M80 INCLUDE |
SESCREEN.MAC |
VT100 output, screen rendering, info bar, cursor positioning, terminal size detection (DETSIZ) |
SEKEY.MAC |
Key input, VT100 escape sequence decoder, dispatch tables |
SEGAPBUF.MAC |
Gap buffer text engine |
SEFILEIO.MAC |
File load/save, FCB management, .BAK backup, user area switching |
SEMENU.MAC |
ESC menu overlay, item dispatch, row 24 prompts |
SESEARCH.MAC |
Find and replace |
SEBLOCK.MAC |
Block mark, copy, delete, paste, clipboard buffer |
SESYNTAX.MAC |
Syntax highlighting tokenizer, ASM and C keyword tables |
SEKEYBND.MAC |
Key binding init from SEDIT.KEY |
SEVIRTIO.MAC |
Virtual buffer I/O for large files |
SEHELP.MAC |
Help screen overlay, BMDATEND marker |
Alternate terminal drivers (replace SESCREEN/SEMENU/SEHELP in link command):
| Source File | Purpose |
|---|---|
SEADM31.MAC |
ADM-31 terminal driver (replaces SESCREEN.MAC) |
SEC3102.MAC |
Cromemco 3102 terminal driver (replaces SESCREEN.MAC) |
SEVT52.MAC |
VT52 terminal driver (replaces SESCREEN.MAC) |
SEMENVT.MAC |
VT52 menu module (replaces SEMENU.MAC) |
SEHELVT.MAC |
VT52 help screen (replaces SEHELP.MAC; linked last) |
Terminal size detection (DETSIZ) is provided by each terminal driver: SESCREEN.MAC uses VT100 DSR for auto-detection; alternate drivers hardcode 80x24.
Standalone utility: SEPATCH.MAC patches SECONFIG.INC for variant builds on CP/M.
; Preprocess (inlines SEDIT.INC, normalizes CR+LF, appends Ctrl-Z EOF):
python CPMFMT.PY *.MAC
; Assemble each module:
M80 =SEDIT
M80 =SESCREEN
M80 =SEKEY
M80 =SEGAPBUF
M80 =SEFILEIO
M80 =SEMENU
M80 =SESEARCH
M80 =SEBLOCK
M80 =SESYNTAX
M80 =SEKEYBND
M80 =SEVIRTIO
M80 =SEHELP
; Link (SEHELP must be last — BMDATEND is at end of its CSEG):
L80 SEDIT,SESCREEN,SEKEY,SEGAPBUF,SEFILEIO,SEMENU,SESEARCH,SEBLOCK,SESYNTAX,SEKEYBND,SEVIRTIO,SEHELP,SEDIT/N/E
On CP/M, each variant has its own .SUB build script (runs SEPATCH + M80 + L80):
SUBMIT SEDIT Mono (SEDIT.COM)
SUBMIT SEDITCL Color (SEDIT-CL.COM)
SUBMIT SEDITA ASM highlighting (SEDIT-A.COM)
SUBMIT SEDITC C highlighting (SEDIT-C.COM)
SUBMIT SEADM31 ADM-31 (SEADM31.COM)
SUBMIT SEC3102 Cromemco 3102 (SEC3102.COM)
SUBMIT SEVT52 VT52 (SEVT52.COM)
SUBMIT SEPATCH SEPATCH utility only
VT52 variant (replaces SESCREEN, SEMENU, SEHELP with VT52-specific modules):
M80 =SEVT52
M80 =SEMENVT
M80 =SEHELVT
L80 SEDIT,SEVT52,SEKEY,SEGAPBUF,SEFILEIO,SEMENVT,SESEARCH,SEBLOCK,SESYNTAX,SEKEYBND,SEVIRTIO,SEHELVT,SEVT52/N/E
SEHELP must be the last module in the link order. BMDATEND EQU $ is defined at the end of SEHELP's CSEG section. L80 lays out [DSEG][CSEG] per module in link order, so BMDATEND must be in CSEG of the last module to capture all code and data. The gap buffer starts at BMDATEND.
- Save incoming stack pointer; set local stack
- Save current user number (BDOS 32) for restore on exit
- Read BDOS address from
0006H; compute TPA top - Calculate available RAM (TPATOP - BMDATEND); if < 9 KB, refuse to run
- Initialize single gap buffer (base = BMDATEND, size = available RAM)
- Set up buffer descriptor (BDESC0); fill BD_FNAME with spaces
- Load and parse
SEDIT.KEY; fall back to compiled-in defaults if not found - Detect terminal size via VT100 DSR: query row count and column width; set 132-column mode if detected; compute dynamic edit area rows; save initial column mode for restore on exit
- Initialize screen: clear, draw info bar, ruler, separator
- Parse command tail for filename (with optional
d[u]:prefix) and temp drive - If a filename was given, load file (switching user area if specified)
- Draw initial edit area; position cursor at line 1, col 1
- Enter main edit loop
- If buffer is modified, prompt user to save
- Save as directed
- Restore original user area (BDOS 32)
- Restore terminal to column mode detected at startup (DECCOLM)
- Clear screen (
ESC [ 2 J ESC [ H) - Warm boot via
JMP 0000H
| Condition | Response |
|---|---|
| Buffer full | BEL; status message |
| File load: line > 255 chars | Warning in status bar |
| Disk full on save | Disk error in status bar; buffer stays modified |
| Disk full during virtual-buffer load | Disk full loading file. Press any key. in status bar; temps cleaned up; warm-boot on key |
| File not found on open | Open empty buffer; New file in status bar |
| TPA too small (< 9 KB) | Print message to console; exit immediately |
| Not found (search) | Not found in status bar; cursor unchanged |
| SEDIT.KEY parse error | Ignored; uses defaults |
- Maximum stored line length: 255 characters (MAXCOLS)
- Maximum visible line width: 73 characters without scrolling (TXTCOLS)
- Maximum file size: in-memory limited by available TPA (~30-38 KB typical); virtual buffer mode supports larger files by paging to disk (requires ~3x the file size in disk space)
- Single edit buffer (no split view or buffer switching)
- No undo
- CP/M 8.3 filenames only; no subdirectories
- No binary file support (NUL bytes not handled)
- Line numbers display up to 9999
- Brace matching (
^Q[) only scans within the in-memory buffer; in virtual buffer mode, a match in the BEFORE or AFTER temp file will not be found