TP3-EDITOR.md 4.4 KB

How the original TP3 editor works (from TPSRC5/TPSRC6)

Entry (TPSRC5:917)

E calls kgetfn for the file name, then editor2. It appends CR LF to the text end, clears the status flag, sets dislin=1 (full redraw), points sepptr at the word-separator table eseptab (<>,[].*+-/$:=(){}^#'), clears the screen, and positions into the text. The entry stack arg is a text position — #$FFFF means "current cursor keep", but compiler error jumps pass a line offset so it reopens at the error line.

Text model

One big buffer [txbeg..txend], lines separated by CR (LF only kept at the end as a terminator). The current line is edited in a separate small buffer line: eflush (TPSRC6:1089) copies line back into the text — computes old-vs-new length, calls echgsize to expand/shrink the buffer, copies chars, and while copying remaps the block markers bkbegl/bkendl (line-buffer positions) onto bkbeg/bkend (text positions). Every movement command (edn, eup, edellin, epagup, search…) flushes first.

Main loop edmain (TPSRC5:932)

  1. eredispl — redraw window,
  2. erase stale status junk if statera set,
  3. estat — paint the status line,
  4. edproc — read a key, dispatch or return "insert this char",
  5. edput inserts/overwrites into line at lnpos (bails with "line full" at lineend0, i.e. the "Line too long - CR inserted" case; einsch makes room in insert mode), then erepos maps buffer offset→screen and loops.

Command dispatch edproc (TPSRC5:981) is table-driven

  • keyget reads a key; if AL >= #$20 (and not 7F DEL) it's not a command → return carry clear (→ insert char).
  • Control keys go into cmdbuf [len, chars…] and are matched against two compressed tables. ecmd1 is multi-key sequences (arrow keys / ESC [ K/M/…); ecmd2 is single-key prefixes (^S, ^D, …; the table's CH=#$1F mask makes the second key case-insensitive, so ^D and D both work after ^Q).
  • A $01/$02 prefix byte = 1- or 2-char command; the table value is a command number. Unrecognized → JZ edmain (TP3 just ignores it).
  • Command number indexes ejmptab (TPSRC6:1575) — 45 WORD targets in manual order: CR, e-left, e-left, e-right, ^A word-left, ^F word-right, ^E up, ^X down, ^W up-scroll, ^Z, ^R, ^C page, ^Q-S/D/E/X/R/C/B/K, ^Q-P, ^V, ^N, ^Y, ^QY, ^T, ^G, DEL…, ^K-B/K, ^K-T, ^K-H, ^K-C/V/Y/R/W, ^K-D, ^I tab, ^Q-I, ^QL, ^Q-F, ^Q-A, ^L, ^P.
  • MSB bit on the address marks a "text changed" command (linins2, edellin2, edeleol2, etab2, block ops, search/replace): ednochg sets txchg=#$FF and txcomp=#$00 (invalidates compiled code) and masks it off before the jump.
  • It pushes edmain as return address, copies an 8-byte "position FIFO" (pfifosrc→pfifodst, the ^Q-P last-position stack), then jumps through the selected address — each command RETs straight back into the loop.
  • Multi-key commands echo onto the status line via eddiscmd ("^K" display, with control chars drawn as ^X).

Status line estat (TPSRC5:1104)

Repaints every loop: Line n, Col n, Insert vs Overwrite, Indent when set, and the work file name at the right if the screen is ≥56 cols (txwinx2 >= #$38). Only the Col number is redrawn each pass (horscr+phcol); the Line number only when the text position moved.

Text operations

All built on the same primitives: echgsize (expand/shrink by moving the tail, TPSRC6:1163) + block moves. ^Q-F search (efind) builds a pattern in srrepl, applies options in sropt (bit flags: backward $10, case U, whole-word W via etstsep/eseptab, Nth), and uses ejnbeg-style line walking. Block ^K-C/V/Y = etstblk (check hidden), echgsize, then copy/delete. ^K-W/^K-R do DOS open/write/close with fnbuf. ^K-D (ekd) closes the editor.

Display

Draws via the edmalin/edllp scan of edpos forward, using esetatt/esetblk to invert block chars (or not, when bkhide), high-bit "bold" chars for menu letters, escrolup for ^W/^R scrolling, and skips writing while keys are pending in eredispl (edisp1 polls ekbdstat) — same "don't paint if a key is waiting" trick at estat:1105.

Net effect

A tight wait-loop operating on one big CR-separated buffer with a per-line edit cache, key-driven by two compact command tables, whose 45 handlers are plain jumps returning to the single main loop. Our shell/Editor.mod mirrors exactly this structure.