
This page is for developers. A UI/extension plugin adds commands to the host's Plugins menu and, through a host-provided API, reads and writes calibration data and paints live overlays. The contract is one pure-C header, te_uiplugin.h; plugins are plain C/C++ with no Qt. The Live Cell Highlighter is the worked example.
te_uiplugin_abi_version — return the ABI major.te_uiplugin_describe — return a static descriptor (id, name, vendor, version, capabilities, menu items); must be safe to call before init, since the host reads your menu at load time.te_uiplugin_init — called once with the host API and a context handle; stash both.te_uiplugin_invoke — a menu command fired (by command id).te_uiplugin_event — a host event.te_uiplugin_shutdown — stop background work and never call the host again.init hands you a vtable of function pointers, each taking an opaque context first: context and enumeration, preferences, whole-slot binaries, maps, cells and axes, the live overlay, and logging/status. Its first field is the host's struct_size; because the vtable only ever grows, refuse to run if it is smaller than what you were built to call. The copy-out getters all write up to a cap and report the full length needed, so check for truncation and re-call with a bigger buffer if necessary.
There are two write paths:
begin_undo … end_undo and the whole batch becomes one undo step on that map's editor. Axis writes only work on a ROM-backed axis — check first; a synthetic axis is denied. Physical values in, physical values out.highlight_cells paints a non-destructive overlay on a map across the table, 2D and 3D views at once, keyed by an explicit target (the host auto-opens that editor if needed); clear_highlights removes it. These are asynchronous — the host coalesces the latest request per target and flushes at about 30 Hz — so you can call them as fast as you like and drive many maps at once.
Warning —invokeandeventrun on the host UI thread, and most host functions marshal to it and block. From a worker thread you may call onlyhighlight_cells/clear_highlights; calling any other host function from a worker while the UI thread joins it will deadlock. Resolve everything you need on the UI thread, capture it, then let the worker only paint.
Preferences are per-collection UTF-8 string values — namespace your keys. Events delivered to te_uiplugin_event include context changes, collection open/close, editor open/close and DATA_CHANGED.
Note — DATA_CHANGED is a notification, not a flash trigger. Writing to the ECU stays an explicit command you expose; the plugin decides when and whether to do it.
The descriptor's capabilities are informational (the host trusts installed plugins and only shows them in the plugin list). Menu items carry a submenu path, a label, a stable command id echoed back to invoke, and an optional shortcut. The host refuses a plugin whose ABI major differs from its own; minor versions may differ because structs and the vtable only grow, and the struct_size check covers the rest.
Include te_uiplugin.h by bare name and let the build supply the path (default the host tree, overridable with -DTUNINGEDITOR_DIR=). Build the shared library, drop it into plugins/ and use Help › Installed Plugins › Rescan. You can sanity-check that all six symbols are exported, but the overlay, undo grouping and preferences are only meaningful against a live collection.
Tip — the host API has no prompt or picker (it is output-only: log and status). A plugin that needs to ask the user brings its own dialog; the example uses a native list and falls back to the active map elsewhere.
The example source is published on GitHub at github.com/mtx-electronics under a permissive licence (0BSD). Start from its skeleton/, read the worked plugin, and see its PLUGIN_DEVELOPMENT.md for the complete contract.
A hex editor built specifically for editing EEPROM data in automotive ECUs. With real-time checksum correction, side-by-side file comparison, and plugin support for automated tasks it's the ultimate tool for professionals.