Est. 1991 Intermediate

TSEPro Editor Macro

SAL, the SemWare Applications Language: the Pascal-flavoured macro language that Sammy Mitchell built into The SemWare Editor Professional in 1991, in which not only user macros but most of the editor's own menus, help screens, key bindings and file manager are written - and which is still being shipped and patched in 2026

Created by Sammy Mitchell, founder of The SemWare Corporation of Marietta, Georgia, who wrote QEdit in 1985 and designed and implemented SAL for its successor. The editor's licence is held jointly by Sammy and Bobbi Mitchell. Changes credited by name in the current read.me and in tse.ui include contributions and bug reports from Carlo Hogeveen, Knud van Eeden, H. Pikaar, Zhong Zhao, Eliyahu Trigoub and Michael Graham, but the language and its compiler are Mitchell's work

Paradigm Procedural scripting, embedded in and inseparable from a text editor. A SAL program is a collection of procedures (proc) that call the editor's own several-hundred-strong command set, plus four declarative constructs the compiler understands natively - keydef for key bindings, menu and menubar for pull-down menus, helpdef for help screens and datadef for embedded data. There are no objects, no closures and no first-class functions; recursion, pass-by-reference parameters, a C-style preprocessor and hooks into editor events are the tools it offers instead
Typing Static, strong, and deliberately tiny: SAL has exactly two data types. An integer is a 32-bit signed value between MININT (-2,147,483,648) and MAXINT (+2,147,483,647), writable in decimal, in hex (0ffh or 0xff) or in binary (11111111b). A string is a fixed-capacity character array whose maximum length is fixed at declaration and may not exceed MAXSTRINGLEN, which the manual states is 255. Every variable must be declared before use; declarations are either global (file-scoped, retained while the macro file stays loaded) or local to a procedure
First Appeared March 1991 in the first TSE Pro beta, per the version timeline in the Wikipedia article, which records that beta as containing the "first version of SAL" along with virtual memory, multifile and block support. The licence in the generated manual agrees: "(C) Copyright 1991-2026 by Sammy and Bobbi Mitchell". SAL reached the public in TSE Pro 1.0 in March 1993
Latest Version TSE Pro 4.50.26, dated 1 July 2026 on Carlo Hogeveen's mirror; semware.com itself was offering 4.50.23 of 30 April 2026 when checked. Both are published for Windows and Linux. The language proper has changed very little since 4.4 (2005) - the manual notes that TSE's help "has not been significantly updated since TSE 4.4" - but the compiler and the SAL sources that make up the editor's interface are still being edited: tse.ui in the current tarball carries a change dated 28 March 2026

SAL - the SemWare Applications Language - is what you get when a text editor’s macro facility is taken seriously enough to become the editor. It is a small, statically typed, Pascal-shaped procedural language, compiled to an object form the editor loads and executes, with exactly two data types and several hundred built-in commands, every one of them about moving a cursor, marking a block or opening a window. It first appeared in March 1991 in the initial beta of The SemWare Editor Professional, reached customers in TSE Pro 1.0 in March 1993, and is still being shipped, compiled and patched in 2026 - which makes the status “dormant”, under which this language is usually catalogued, one of the more inaccurate labels in the encyclopaedia.

The name it is catalogued under is itself an artefact. “TSEPro Editor Macro” is not what SemWare calls the language; it is the label on entry 466 of 99-bottles-of-beer.net, submitted by Sammy Mitchell - the editor’s own author - and stamped in his source header “Sammy Mitchell, Dec 9, 1998”. SemWare calls it SAL.

From QEdit to a language

SemWare’s first product was QEdit, released as MS-DOS shareware in November 1985 and written in Turbo Pascal. Its reputation was built on being small and quick: reviewing it for The Globe and Mail in January 1993, Bob Rife observed that it was “compact, taking only 50 KB of space, compared with many other editors that can be 10 times the size”. QEdit had keyboard macros - record a sequence of keystrokes, play it back - but nothing you could call programming.

Two changes made SAL possible. In February 1990, QEdit 2.1 was rewritten from Turbo Pascal into C, giving the product a native core that could host an interpreter. Then, in March 1991, SemWare shipped the first beta of a new, larger editor, The SemWare Editor Professional, which added virtual memory, multifile editing, block support - and, per the version timeline maintained on Wikipedia, the “first version of SAL”. In 1992 the line split formally: QEdit was renamed TSE Jr, and TSE Pro went its own way. TSE Pro 1.0 shipped in March 1993.

The migration path was taken seriously. SemWare still ships doc/jr2pro.txt, a command-by-command translation table from the Junior editor’s flat command names into SAL calls, and it reads like a small manifesto for what had changed:

    TSE Jr Command              TSE Pro Command
    --------------------        ---------------
    addline                     AddLine()
    align                       ExecMacro("Align")
    altwordset                  Set(WordSet, ChrSet("0-9A-Za-z_!#$%&`'()-./\@{}~:^"))
    dirtree                     ExecMacro("Tree")

A command had become a function call; a mode had become a call with an argument; a feature had become a macro you loaded.

What the language looks like

SAL uses proc ... end, if ... endif, for ... endfor, case ... endcase - Pascal’s shape, with C’s comment syntax (// and /* */) and C’s preprocessor (#include, #ifdef, #define) grafted on. Mitchell’s own beer-song macro from December 1998 is a fair sample of the whole language:

// return "n bottles", "1 bottle", or "no more..." based on num_bottles
string proc bottles(integer num_bottles)
    case num_bottles
        when 0    return ("no more bottles of beer")
        when 1    return ("1 bottle of beer")
    endcase
    return (Str(num_bottles) + " bottles of beer")
end

// display the beer song in a pop-up window
proc main()
    if PopWinOpen(1, 1, 40, Query(ScreenRows),
                1, "Sing along...", Color(Bright Yellow on Blue))
        Set(Attr, Color(Bright Yellow on Blue))
        ClrScr()
        Sing()
        GetKey()
        PopWinClose()
    endif
end

Note what the language spends its vocabulary on. PopWinOpen, Color(Bright Yellow on Blue), Query(ScreenRows), Set(Attr, ...), GetKey - a colour expression is part of the grammar, and the standard library is a text editor. (Mitchell’s original also separates some WriteLine arguments with ; rather than ,; the current manual documents only the comma form, so the semicolon appears to be a legacy spelling that survived in his own code.)

Two types, and no more

SAL’s type system is as small as a type system gets while still being one:

TypeRange or limit
integer32-bit signed, MININT (-2,147,483,648) to MAXINT (+2,147,483,647); decimal, hex (0ffh or 0xff) or binary (11111111b) literals
stringfixed capacity chosen at declaration, up to MAXSTRINGLEN, which the manual gives as 255

Strings are declared with their capacity in brackets, and the compiler will compute it for you if you initialise the variable:

string  Astring[10],              // reserve 10 characters
    Hello[] = "Hello, world",     // creates 12-character string
    fn[_MAXPATH_]                 // as long as this build allows for a path

+ concatenates; s[n] indexes a single character; the editor’s own line length limit lives in the constant MAXLINELEN, which the manual gives as 30,000 - so a line of text can be longer than any string that could hold it, and macros that process long lines have to work in pieces. Variables are global (file-scoped, and alive as long as their macro file stays loaded) or local to a procedure; procedures take parameters by value or by reference (VAR STRING s), return values, and may recurse.

The constructs that are not procedures

Where SAL departs most sharply from a general-purpose language is in the four declarative forms the compiler understands directly, because they exist to build an editor’s furniture:

  • keydef - a named block of key bindings that can be enabled and disabled at runtime, so a macro can install a temporary keymap while a pick-list is up.
  • menu and menubar - pull-down menus as a language construct, with forward declaration (forward menu MouseMenu()) for mutual references.
  • helpdef - help screens compiled into the macro that needs them.
  • datadef - arbitrary data embedded in the compiled macro.

The Hook() mechanism completes the picture: macros attach themselves to editor events - _ON_EDITOR_STARTUP_, _AFTER_FILE_SAVE_, _PRE_UPDATE_ALL_WINDOWS_ and others added in 3.0 - and Unhook()/BreakHookChain() let them detach or stop the chain.

Compiling and debugging

Macros are written in .s files (or .ui files for user interfaces) and compiled by sc32, the SAL compiler, into .mac object files, either from a shell or from inside the editor with Ctrl-F9. External macros are loaded with LoadMacro, run with ExecMacro, and can be purged again; each is classified as Main, Public, WhenLoaded or WhenPurged, which determines when its procedures fire. A user-interface macro, by contrast, is installed into the editor and cannot be purged - it is the editor’s interface.

There is a real interactive debugger, invoked with the Debug command: it compiles the source if needed, then hands you control of the running macro so you can single-step it, inspect buffers and variables, and modify variables mid-run.

Reaching outside

For anything the editor cannot do, SAL has a foreign function interface. The DLL directive declares procedures living in a Windows DLL:

DLL "<user32.dll>"
    integer proc MessageBox(integer hwnd, string txt, string caption,
                            integer utype) : "MessageBoxA"
end

Angle brackets around the file name send the loader to the system search path; the : "name" form supplies the real export name when it differs from the SAL identifier, which it usually does thanks to Windows’ A/W suffixes. The manual is explicit that DLL procedures returning strings are not supported - integers only. This is also the part of the system that has aged least well: the roadmap in the shipped read.me lists “Need new FFI” against every build target Mitchell is working towards.

Evolution

SAL’s growth follows the editor’s, and it is a story of accretion rather than redesign. TSE Pro 3.0 (April 2001) is the high-water mark for the language: its notes advertise “over 500 native commands that can be called by user-written macros”, introduce the EDITOR_VERSION and MAXSTRINGLEN constants, and add four hookable events. 4.0 (May 2002) turned TSE into a real GUI application and gave macros font control plus isGUI() to tell the builds apart. 4.2 (February 2004) added file-system and clipboard commands. 4.4 (May 2005) is where the documentation effectively stops - the generated manual carries the warning that TSE’s help “has not been significantly updated since TSE 4.4 (2005)”, pointing readers at read.me and an “Undocumented Features” page for anything later.

The code, however, did not stop. In 2021 the licence changed: TSE became freeware under a two-clause BSD licence, over the copyright line “(C) Copyright 1991-2026 by Sammy and Bobbi Mitchell” that the generated manual still carries (the shipped read.me now reads “(C) Copyright 1991-2025 SemWare”). Releases have continued at a steady, unhurried clip since - 4.42 in January 2022, 4.49 in January 2023, 4.50.23 on 30 April 2026, 4.50.26 on 1 July 2026 - each for Windows and Linux, each crediting the same handful of long-time users by name, and each still adding the occasional SAL command - GetSynQuote() and GetSynMultiLnDlmt() arrived in 4.49.00 in January 2023, FFisExec() in 4.50.22 in March 2026. The file ui/tse.ui in the current tarball carries a change entry dated 28 March 2026. Whatever else it is, this is not a dormant language.

Running SAL today

There is no Docker image, no package in the mainstream Linux distributions' repositories, and no public source repository for the editor itself; SemWare distributes a Windows installer and a Linux tarball from semware.com, with Carlo Hogeveen mirroring both. The Linux build is a self-contained directory: unpack it, add it to your PATH, and run e. Both the editor and sc32 are statically linked 32-bit x86 ELF binaries, which on modern 64-bit Linux means you need 32-bit support installed; 64-bit builds are on Mitchell’s roadmap but, as of the current read.me, unticked, along with UTF-8 support and code folding. A DOS build (2.50e, 1997) is also still on the download page.

Why it matters

SAL belongs to a family of editor languages - Emacs Lisp, Vim script, BRIEF’s macro language, EDT and TPU on VMS - and among them it makes an unusually clean argument. Its designer took a fast C editor and pushed the boundary between “the program” and “the configuration” as far towards the configuration as he could: the menus, the help, the key bindings, the file manager, the calculator, the grep, the emulations of four rival editors, all of it lives in .s and .ui files that ship as source next to their compiled form, and all of it is written in the same language the user gets. That is roughly 88,000 lines of SAL in the current release, in the same files a user may edit and recompile.

The cost of that design is visible too. Two types and 255-character strings are a 1991 budget, not a 2026 one, and thirty-five years of accretion has left a language whose grammar is Pascal, whose comments are C, and whose foreign function interface is a Win32 artefact awaiting replacement. But the trade Mitchell made - a small language, deeply wired into one domain, shipped as the implementation of the product rather than as a bolted-on courtesy - is the same trade Emacs made, and it has kept a shareware editor from 1985 alive, in active maintenance, under a BSD licence, into its fifth decade.

Timeline

1985
QEdit 1.0, written in Turbo Pascal, is released as shareware in November - SemWare's first product and SAL's ancestor. Its selling point was size and speed: The Globe and Mail, reviewing it in January 1993, noted that it took "only 50 KB of space, compared with many other editors that can be 10 times the size". QEdit had keyboard macros but no programming language
1990
QEdit 2.1, in February, is converted from Turbo Pascal to C, and the first OS/2 version appears. The move to C is what makes the next step possible: a native core with a compiled scripting layer bolted onto it
1991
March: the first beta of The SemWare Editor Professional, containing what Wikipedia's timeline calls the "first version of SAL", together with virtual memory support, multifile editing and block support. This is the year SemWare still stamps on the product - the licence in the 2026 generated manual reads "(C) Copyright 1991-2026 by Sammy and Bobbi Mitchell"
1992
The product line splits in two: QEdit becomes TSE Jr, and the new, scriptable editor becomes TSE Pro. From here the two products diverge, and SemWare later ships doc/jr2pro.txt, a translation table mapping every TSE Jr command onto its SAL equivalent - addline becomes AddLine(), dirtree becomes ExecMacro("Tree"), altwordset becomes a Set(WordSet, ChrSet(...)) call
1993
March: TSE Pro 1.0, the first shipping release with SAL in it. Reviewing it in Popular Electronics in April 1994, Jeff Holtzman put the trade-off plainly - "TSE is relatively speedy, although it's not as fast as QEdit", QEdit being strictly RAM-based, "on the other hand, TSE has numerous powerful features", among them column-mode operations, regular expression search and replace and the ability to run external programs
1994
September: TSE Pro 2.0 adds the online help system and history lists. Both are things SAL can reach into: helpdef makes help screens a language construct, and later versions expose the history lists to macros as named objects
1995
September: TSE Pro 2.5 brings multifile find and saved state, and is the last DOS version of the Professional edition. The DOS build (2.50e, 1997) is still on SemWare's download page in 2026
1996
October: TSE Pro 2.6, the first Win32 version, still a console application built on the Win32 console API. SAL macros written for DOS largely carried over - compatibility between releases is a recurring theme of the What's New notes
1997
June: TSE Pro 2.8 adds colour syntax highlighting, driven by external .syn files. The current release ships fifty-six of them, from ada.syn and asm.syn to 4dos.syn
1998
9 December: Sammy Mitchell writes a SAL rendering of the beer song, opening a pop-up window and counting down from 99. It later becomes entry 466 at 99-bottles-of-beer.net under the name "TSEPro Editor Macro" - the name by which this language is catalogued to this day, including on this site
2001
April: TSE Pro 3.0 adds undo and redo, and is the release where SAL grows visibly. Its notes record "over 500 native commands that can be called by user-written macros", new pre-defined constants EDITOR_VERSION and MAXSTRINGLEN, and four new hookable editor events including _ON_EDITOR_STARTUP_ and _AFTER_FILE_SAVE_
2002
May: TSE Pro 4.0, the first GUI version - a genuine Win32 GDI application that merely looks textual, a point the Wikipedia article is at pains to make. SAL gains font commands (ChooseFont(), GetFont(), SetFont(), ResizeFont()), an isGUI() predicate so macros can tell which build they are running under, and new editor variables for fonts and GUI startup flags
2004
February: TSE Pro 4.2, adding SAL commands for the clipboard (PasteReplace()), the file system (CopyFile(), MoveFile(), MkDir(), RmDir()), syntax highlighting (GetSynLanguageType(), GetSynToEOL()) and the colour table, and raising the window limit from 9 to 20. In October of the same year the first Linux beta appears
2005
May: TSE Pro 4.4. This is effectively where the documentation stops - the generated manual notes that TSE's help "has not been significantly updated since TSE 4.4 (2005)" - even though the code did not
2021
TSE becomes free software. The licence shipped with the editor is now a two-clause BSD licence - the Wikipedia infobox dates the change to 2021 - and the shipped read.me opens "TSE Pro for Windows and/or Linux is now freeware". Version 4.42, for Windows and Linux, follows in January 2022, and 4.49 in January 2023
2026
Still shipping. 4.50.23 is dated 30 April 2026 and 4.50.26 1 July 2026, both Windows and Linux; the 4.50.23 notes credit Carlo Hogeveen, and the change list for the recent releases as a whole credits Hogeveen, Knud van Eeden, H. Pikaar, Zhong Zhao and Eliyahu Trigoub; 4.50.22, of 28 March 2026, added the command FFisExec() and the Sort() option _ASCENDING_, and updated tse.ui and win.ui. The roadmap in read.me is honest about what remains: 64-bit builds, a new FFI, UTF-8 support and folding are all unticked boxes, and the editor is still a 32-bit binary that "can only use about 3.9 GB of memory"

Notable Uses & Legacy

The SemWare Editor itself

The strongest claim for SAL is that the editor is largely written in it. The manual states flatly that "much of the editor itself has been implemented internally using the macro language" and that "many of the built-in native commands in the editor are actually macros written in SAL". In the 4.50.23 Linux tarball, ui/tse.ui - the standard user interface, comprising the menus, help screen, key assignments and a good many commands - is 2,567 lines of SAL

The bundled macro library and the Potpourri

The same tarball carries 117 SAL source files under mac/ (109 .s and 8 .si), 75,297 lines in all, most with a compiled .mac beside them: the file manager (f.s, 3,250 lines), grep, a calendar, an expression evaluator, file comparison, sorting, ASCII charts, an autosave, and a shelf of games from Tetris to Star Trek. Many are reachable from the Potpourri PickList, TSE's menu of optional macros

Editor emulations

TSE's ability to impersonate other editors is implemented as interchangeable SAL user-interface files rather than as C code. The shipped ui/ directory contains brief.ui, ws.ui (WordStar), tsejr.ui (the QEdit-descended Junior interface) and win.ui (CUA/Windows) alongside the native tse.ui - 13,322 lines of SAL in that directory between them

Carlo Hogeveen's TSE tools (ecarlo.nl/tse)

A long-running third-party collection of SAL extensions, including Context (context-sensitive helper), a documentation generator and the Hlp2txt macro that converts TSE's interactive help into the HTML manual most people now read - the version of that manual cited on this page was produced by Hlp2txt 3.0.3 on 18 July 2026. Hogeveen also mirrors SemWare's releases and is credited by name in the vendor's own change lists

Knud van Eeden's TSE knowledge base

A large public archive of SAL macros and TSE notes, linked from semware.com's own front page, which lists it among its "cool places"; van Eeden is likewise credited in the shipped read.me for bug reports against recent releases

Rosetta Code

SAL has a small but real presence outside the editor's own ecosystem: approximately seventeen tasks were solved under Category:TSE SAL when it was checked in September 2026, from Ackermann function and Levenshtein distance to HTTP and 100 doors. SemWare links the category from its home page, reportedly with the note "Please add more!"

Language Influence

Influenced By

Pascal C QEdit

Running Today

Run examples using the official Docker image:

docker pull
Last updated: