etext — a Tk text widget with nestable, editable blocks

etext is Ilya Zakharevich's extension of the Tk text widget (1995–1997): in addition to tags, marks and embedded windows, a text can contain blocks — annotations with an internal tree structure whose geometry is managed by a callback written in the scripting language. With a few dozen lines of Perl per block type this gives editable fractions, radicals, super/subscripts, labeled equations, tables, delimiters that grow with their contents, and so on, all living inside an ordinary text widget where every editing command keeps working. See doc/etext.pod for the full description and demo/etext.pl for a demonstration (with a small TeX import/export).

The last release on CPAN was etext 1.6.2 (1997), written against the tk4.0b3 text widget and the Perl/Tk b9 glue. The first commit of the Git repository (https://github.com/ilyaz-ai/etext) is that release, untouched. Everything after it is the modernization described below.

Status (version 2.01, 2026)

Building and testing

perl Makefile.PL
make
make test            # needs an X display; "xvfb-run make test" works too
make install

(In the Git repository the distribution lives in eText/: cd eText first.)

Requirements: Perl 5.8+, Perl/Tk 804.027+ (with its headers installed, as every Perl/Tk installation does), a C compiler. Test::LeakTrace is optional (the leak test skips part of itself without it).

The interactive demo:

perl -Mblib demo/etext.pl        # before "make install"
perl demo/etext.pl               # after "make install"

The demo's helper modules FreezeThaw and Text::TeX are bundled under utils/ (they are also on CPAN; the bundled copies are not installed).

The memory leaks

The leak reported for the widget (growing memory while the text just sits there with the insertion cursor blinking in a formula) came from the block layout callback: every call built the argument list for the Perl callback with a fresh reference to the widget object, and that reference was never released. The cursor blink re-lays-out the display line holding the cursor, so with the cursor inside a block the callback runs twice per second, forever. A refcount leak of this kind cannot be seen by counting SVs; it shows up as the widget's Perl object never being freed, which is what t/leak.t checks.

Further leaks found and fixed along the way:

A review of the port (six independent readers, each finding verified) also turned up inherited bugs that were fixed: tag prevrange crashed unless the tag ended on the first line of its B-tree node (and could not look into or out of blocks), search -nocase corrupted the heap on long lines, a layout callback returning a single row was rejected, window cget -align died, and a few more; see Changes. t/regress.t covers them.

What is not a leak of this widget: with an extreme blink rate and no X round trips at all, Perl/Tk 804 itself accumulates Tk_CreateErrorHandler records (also with a plain Tk::Text); Tk frees them lazily after the next round trip with the server.

Layout of the distribution

README.md, Changes, BUGS       this file, the change log, known problems
doc/etext.pod  the documentation of the widget, blocks and -layoutcmd
eText.pm, eText.xs, Makefile.PL, tkText*.c, tkText.h, pperl.h, ...
eTextSyms.PL, eTextSyms.h      the symbol-prefix header (committed)
t/             tests
demo/          the Perl demo and a sample document
utils/         FreezeThaw and Text::TeX for the demo

The Git repository holds, besides this directory (eText/), the original 1997 top-level files and the Tcl/Tk flavour (historical), the records of the modernization (HANDOVER.md, the CONVERSATION-*.md files) and the Perl/Tk and Tcl/Tk defects met on the way (TK_BUGS.md; reports ready for filing in UPSTREAM.md and upstream/). An below refers to the entries of TK_BUGS.md.

Differences from Tk::Text