Skip to content
Ilia Maslakov edited this page Sep 2, 2026 · 2 revisions

Pull requests for v6.0.4

Source: closed pull requests in the Future Release milestone. Snapshot: 2026-08-31.

The source query contains 66 merged pull requests. This table includes the 57 entries without the infra label; all of them were authored by ilia-maslakov.

PR ID Summary Tags
#206 Shift-F3 diffs a file inside a commit and from the status panel. The key now reaches the plugin as CK_ViewRaw in both views that list files; commit or branch selection is still handled inside the plugin.

panel_key() previously retried with the raw KEY_F(13) only when handle_key() returned MC_PPR_NOT_SUPPORTED, but the view guard returned MC_PPR_FAILED so the retry never happened and the panel fell back to viewing the file. The retry logic has been adjusted so Shift-F3 reaches CK_ViewRaw from the status list and the commit file list, restoring the expected diff action.
Bug fix, Plugin, panel
#204 The host terminal is out of mc's hands while mcterm is up: a "clear and reset" from its own menu wipes cells that the screen library still counts as written. It sends only what it takes to be changed, so those cells stay wiped, and the panels come back with holes wherever they print a blank in the normal colour - the tail of the name field, the free area, the padding of the mini status.

Touch the screen on every switch between the panels and the terminal, and on both ends of the full-screen terminal the editor and the viewers reach with Ctrl-O.
Bug fix, core, mcterm
#203 The mcterm widget gets a keybar of its own. While it has the screen to itself the function keys.
Updated man page doc/man/mc.1.in, the The terminal section, gained the scrollback, who owns
which keys, and both key tables.
core, mcterm
#202 Ctrl+Alt+L (and Ctrl+Shift+L, where the terminal tells the two apart) clears the
screen and the scrollback both, the prompt line left where it is. Ctrl+L keeps
its own meaning: the screen goes into the history.

The key works whoever is typing, the command line included. The count of the rows
that ever left the screen is not reset, so what points at a row by number — the
mark, the line filter — keeps pointing at the same row.

New action ClearAll, bound in the [mcterm] section of the keymap.
Feature, core, mcterm
#201 Alt+Shift+S puts a line filter on right away, without a dialog. The pattern is the selection when it is one line of a sensible length, and the word under the cursor otherwise.

In the editor it reuses the existing line filter: the rows that do not match are folded away, and Alt+S lifts the filter as before.

The terminal had no filter at all, so it gets one. Only the rows that carry the text are drawn; the set is fixed when the filter goes on, so the view holds still while the shell keeps printing. The cursor, the mark and the mouse count the rows that stayed, and the view scrolls among them. Alt+S lifts the filter and puts the last one back on; a key typed at the shell lifts it too, the output going on below what it kept. Matching is a plain string of either case, the way the viewer's own filter looks for one.
Feature, mcedit, core, mcterm
#200 The editor opens the search dialog with the currently selected text as the initial search string. The selection is taken from the active editor buffer at the moment the dialog is invoked.

You can edit the pre-filled text in the dialog before starting the search.
Feature, mcedit
#199 Ctrl+F1 and Ctrl+F2 toggle the panels when focus is in the command line.

The command line previously forwarded all Control-key combinations to the shell, so those keys were treated as shell editing keys and did not toggle the panels. The command line now forwards only Control plus a character to the shell; Control plus a function key is handled by mc.
Bug fix, panel, core
#198 A command run from the panels put the terminal up and left it there: the panels never came back on their own, and the "Pause after run" option was not read on this path at all. Now, when the shell is back at its prompt after such a command, the panels come back the way the option asks: at once for "Never" (and for "On dumb terminals" in a real terminal), or after "Press any key to continue..." in the prompt row for "Always". Ctrl-O is not touched: a terminal opened by hand stays up. With the command line hidden there is no row for the message, so there is no pause either.

Enter in the command line sent a bare carriage return, so the shell was still counted as being at its prompt until its mark came back. It now goes through mcterm_send_line, which marks the shell busy at once.

The shell was started at MSG_INIT in the directory of the panel that was current then; which panel gets the focus is decided later and can be the other one, so the panels showed one directory and the shell sat in the other until the first Tab. At its first prompt the shell is now sent to the current panel. A mouse click on the other panel did not move the shell either; it does now.

Bringing the terminal up for a command may send the shell to the panel's directory first; the prompt that cd brought back must not pass for the end of the command. The command waits for that prompt, and the "back to the panels" flag is set only once the command has gone out.

Known, not in this PR: with fish, a line it refuses to parse gives no "command done" mark, and the terminal waits for one.
Bug fix, panel, core
#197 The terminal in mcterm never wrapped: a character past the last column went on into the row up to 4096 cells, mcterm drew only the visible width and the history kept only that width, so the tail of a long line was lost. A change of width left the history and the screen as they were: long lines stayed broken where the old width broke them.

Now vterm has autowrap (DECAWM) with the pending wrap of xterm, CSI ? 7 h/l turns it on and off. A row broken by the terminal carries a "wrapped" flag that moves with the row through scrolling, into the history and back.

On a change of width the rows the terminal broke are put back into their lines, the blank tail of each line is dropped, and the lines are broken again for the new width. The screen keeps the rows it showed as far as they fit, the cursor stays on its character, and the rest is the history. The pictures follow their rows. The alternate screen is left alone: the program on it draws itself again. mcterm maps the start of the typed line to its new place and drops the selection and the view cursor.

Autowrap is off by default and mcterm turns it on; the viewer keeps its old behaviour.

Known: after a resize bash redraws the prompt using the old row count and can leave a partial old prompt row above; same in other terminals with reflow.
Feature, core, mcterm
#196 Every directory under src/lua/examples/ was installed into $(lua_scripts_dir) and loaded at startup, so the four-line notify-editor-save demo ran on every F2 in mcedit and its mc.log.info line went to stderr straight over the curses screen.

Split the tree: src/lua/scripts/ holds the shipped plugins, installed to $(lua_scripts_dir) as before; src/lua/examples/ holds notify-editor-save and demo-panel, installed to
$(pkgdatadir)/lua/examples where the engine never looks.

runtime_host_log() no longer writes to stderr while a dialog is on screen; with the UI up the message goes to $MC_LOG_FILE when set.
Bug fix, Plugin, mcedit
#195 vterm implements ICH (CSI n @) and insert mode (CSI 4 h / CSI 4 l). ICH shifts the rest of the line right and fills the gap with blanks in the current attributes; characters pushed past the right edge are dropped. IRM (smir/rmir) is handled the same way for each printed character.

Previously, typing in the middle of a shell command line under Ctrl-O overwrote existing text because readline issues ICH to make room and the emulator ignored it. This change makes edits in the middle of a line render correctly (for example, Home + "222" previously showed "22211" while the shell buffer contained "22211111").
Bug fix, core, mcterm
#194 A viewer for dBase, FoxPro and Clipper tables, written in Lua on top of the screen widget: the file is decoded by the script itself, so nothing outside MC is needed. F3 or Enter on a .dbf opens it full screen — one row per record, one column per field, the first column the file's own deleted mark. Numbers sit to the right, dates read as YYYY-MM-DD, logical fields as T, F or ?, memo fields as their block number. The rows are read as the table scrolls, a page at a time, so a table of any size opens at once; records marked deleted are drawn in red, and F4 hides them.

Keys: F2 the structure of the table (header and field list), F3 or Enter the record as a card, one field per line, F5 the encoding — by the language driver byte of the header, or cp866, cp1251, cp1252, UTF-8 — F8 the file itself in the viewer, F1 the script's own help, F10 back to the panel. Left and Right scroll the columns when they do not fit.

Memo texts in .dbt and .fpt are not read. The magic.ini rule binds .dbf to the script for Open and View, whatever the case of the suffix.
Feature, Plugin, mcview, lua
#193 A screen is a full-screen dialog a Lua script describes and drives: the status line on top, the keys as the button bar at the bottom, and between them a grid of rows and cells laid out by height or weight, one native widget per cell - table, text, label, status, separator, input, checkbox. Lua draws nothing: it hands over data and gets events back.

Tables pull their rows page by page through the screen's dispatch (rows(first, count)), the host keeps the pages seen recently, a cell color without a background lands on the table's own. screen:run() blocks until the screen closes; screen:update() and screen:status() change it while it runs; the script hears keys, Enter, the actions of its keys list, row changes, check toggles, resize and close.

ABI: screen_run, screen_update, screen_close in the host services, the screen descriptor with its dispatch, control types TABLE, STATUS, TEXT. Widgets: WTable gains a header row, sized and scrollable columns, a prefetch hook and a cell color hook (existing callers keep their fixed layout); WView gains an embedded shape for text cells; tty_color_pair_background() looks up the background of a pair.

Also: a file handler may return { handled = true } without a controller; panel:chdir() to a plugin location activates the plugin; runtime plugins are looked for in ~/.local/lib/mc6/runtime-plugins first. Fixes found on the way: mc.source.bytes() copied a buffer of unspecified length, panel views with column values were rejected (a key left on the Lua stack), a failing file handler popped the error twice, the documented user scripts directory was wrong, and src/.gitignore hid src/lua/examples/mc6/.
Feature, Plugin
#192 The editor line filter now feeds each line to the search engine through the same buffer callback that normal search uses, so NUL bytes no longer truncate lines and nothing is copied. A status message shows progress and lets the user cancel a long run; a cancelled filter leaves the view unchanged. Applying a filter clears found_len so a previous search highlight is removed.

A search error from the filter is withheld while the status message is shown and displayed after the status message is taken down, and the obsolete MC_SEARCH_E_ABORT check has been removed. FilterToggle is bound to Alt-S in the built-in editor keymap so the key works with --nokeymap, and tests now mock status_msg_init/status_msg_deinit (the filter also zeroes its status message so an untouched one is harmless).
Chore, mcedit
#191 The Search dialog (F7) gets a Filter button next to Find all. It hides every line that does not match the search string, using the dialog's own type, case, whole-word and charset settings. Line numbers stay original; the line-state gutter marks each hidden run.

The hidden set is a snapshot taken when the button is pressed. Editing never re-applies the match: split, joined and newly typed lines stay visible. A string that matches nothing leaves the view untouched.

Alt-S toggles the filter: lifts an active one, or puts the last search back on as a filter. "Toggle line filter" in the Search menu and "Unfold all" do the same.

Built on the existing code folds. A hidden run may now start at the top of the file with no header line, and edit_fold_inc/dec shift a run instead of growing it at a filter boundary. Filter folds draw no "...}" indicator. The cursor snap out of hidden lines also runs after a command, so Ctrl-Home or a search landing on a hidden line is corrected at once.

A mouse click with hidden lines below the cursor used to select a range: the handler counted screen rows as buffer lines. The row is now resolved to the line shown there.

Documented in the help and in mcedit(1).
Feature, mcedit, core
#190 - mcterm: a prompt printed afresh moves the typed line's start — after Ctrl-O → Enter → Ctrl-O, Enter on a directory hid the panels and went to the shell. An empty Enter in the terminal prints a new prompt without running a command; the 133;B mark was ignored while the shell already counted as at its prompt, so the typed-line start stayed on the old row and the new prompt's text was read back as a command. Now every 133;B (except while a command is awaited) updates the line's start.
- mcterm: an open menu takes its keys before the terminal does — with panels hidden, F9 focused the menubar but mcterm_overlay_handle_key ran first and fed every key to the shell (menu frozen, in drop-down mode typing invisible). The overlay handler now yields while the menubar is focused.

Also diagnosed (no code change): the undefined symbol: ext_archivers / "arcmc:open cannot open" errors come from building master in a stale build dir after arcmc-ext.c was added to Makefile.am — a clean build (or autoreconf + config.status --recheck) fixes it. mcstruct is a leftover plugin from ~/dev/mc and should be removed from /usr/lib/mc/panel-plugin
Bug fix, core, mcterm
#189 mcstruct shows a binary file as a tree of named fields driven by a text def-file (STL5, compatible with Struct Look 4.00 def-files). It runs as a panel plugin with its own screen: a structure tree, a hex strip and the def-file, all in sync. Fields can be edited in place and written back; tables, arrays and #repeat rows open as a grid.

Core changes:
- panel-plugin: SHOW file operation (API 15) and mc_panel_plugin_load_named()
- widget: new WHexStrip; WTable gets a cell color callback, color overrides, zero-width columns and a scrollbar on the frame line

mcstruct:
- STL5 parser, expressions and evaluator; STL 4.00 files in compatibility mode, STL 5.00 adds 64-bit types, byte order, #repeat, #set, #include, check fields, strings, varints, absolute seeks, titles read from the file
- def-files for zip, exe, dbf, elf, mbr, fat_boot, uimage, dtb, png, bmp, wav, sqlite, written from public specs, plus stl.als with name patterns and signatures
- the screen: tree, hex, def-file zones; edit (F4/F2), structure at offset (F3), goto (F5), def-file pick (F6), search (F7), errors (F9), calculator (Alt-=), zoom (Alt-F9), help file (F1)
- entry points: mcstruct FILE [DEF] symlink, F9 -> Command -> Struct look, magic.ini groups for uImage, DTB and MBR, settings dialog in Manage plugins
- skins: [mcstruct-tree], [mcstruct-hex], [mcstruct-def] sections in default and darkfar
- viewer: Shift-F4 opens the file in mcstruct at the current offset and back; F10 closes both
- mcedit syntax highlighting for .stl, README entry
- tests: parser, evaluator, reader, edit, extensions, shipped def-files, hexstrip, table datasource
Feature, Plugin, mcstruct
#188 The Permissions highlight marks the one rwx triplet that applies to the user and leaves the other two alone. This adds a second panel option, Permission colors (permission_colors in ini), that gives every character of the perm field a color of its own kind, the way eza does: r, w, x, s/t and - each stand in their own color, the file type character keeps the row's color.

Both options combine: the user's triplet keeps the marked color on top of the bit colors. The cursor row and marked rows keep their colors whole, as they do over a highlighted file name. The octal mode field is untouched.

The colors come from five new keys in the skin's [core] section - permread, permwrite, permexec, permspecial, permnone. They are optional: a skin that names none of them gets yellow, bright red, bright green, bright magenta and gray on its own background, so every shipped skin works without changes; default.ini carries them as the reference. Documented in mc.1 (the File highlight paragraph, which also said selected where marked is used) and misc/skins/README.txt.
Feature, panel, core
#187 - Load external archive formats from arcmc.ini, allowing new extensions, tools, arguments, and extfs helpers without
recompilation.

- Keep built-in defaults, including Inno Setup support via innoextract.
- Add CdChild magic actions so archives can open with Ctrl+PgDn without changing Enter behavior.
- Support external helpers for file-backed plugin streams.
- Add the uinno extfs helper and tests for runtime-defined archive formats.

Testing

- Full build completed successfully.
- arcmc, magic.ini, and extfs-helper tests pass.
- Verified Ctrl+PgDn with both the default .exe format and a custom .pkgx format defined only in configuration.
Bug fix, Plugin, panel
#186 F3 on a picture used to print the whole exif/exiftool dump and draw the picture in the rows left under it, which for a JPEG with an ICC profile was two rows.

lua-sixel, lua-chafa
- 'F3' prints one line about the picture (identify's format, size, depth and frames; file's description without ImageMagick) and draws the picture in the rest.
- 'i' switches between the picture and its full properties.

lua image viewers

- show a concise image description above the chafa/sixel rendering instead of a full properties dump
- use i to switch between the picture and full image properties
- add dedicated F1 help for the lua-chafa and lua-sixel viewers
- resolve relative Lua help files from the package directory
- allow script and plugin help to link and fall back to nodes in mc.hlp
- preserve the originating help file in navigation history
- update Lua API documentation and tests
Feature, Plugin, mcview
#184 User files now live in ~/.config/mc6, ~/.local/share/mc6 and ~/.cache/mc6. On the first start, if the new directory does not exist and the old ~/.config/mc (or share/cache) does, its contents are copied over. The old directory is left as is.

Man pages, help files and comments updated to the new paths.
Feature, core
#183 mcterm now moves focus to the typing widget before hiding the panels when an overlay opens. The active panel remains selected while the overlay is open.

Hiding the focused panel previously caused the panel group to select the other panel as current_panel. On overlay close the shell cwd was applied to that other panel, causing the right panel to get the left panel's path and focus. The correct panel keeps its selection and receives the shell cwd on overlay close.
Bug fix, panel, mcterm
#181 Pictures drawn in sixel now show inside mc where a program's output is shown: in mcterm and in the terminal mode of the viewer. Before, the emulator dropped the DCS and the screen library had no cell to put a picture in.

vterm keeps a sixel DCS as a picture: its place in cells at the cursor, its size from the raster attributes or from the data itself, and the DCS as it arrived. The cursor goes below it, a picture past the bottom scrolls the region, pictures move with their rows and leave with them, and erasing the screen or entering the alternate screen takes them.

The picture is written to the terminal behind the screen library's back: a painter runs after tty_refresh() and writes the DCS with tty_raw_write() at the rows the cells were drawn on. The cells under a picture are written every time, so the terminal erases the pixels of a picture that moved or went; a widget hidden or destroyed with pictures on the screen has the whole screen written again. Both the ncurses and the S-Lang backends have tty_touch_area() for that.

At startup the terminal is asked whether it draws sixel (DA1, attribute 4) and how big a cell is (XTWINOPS 16); TIOCGWINSZ pixels come first when the kernel has them. MC_SIXEL=0 or 1 overrides; TERM of screen or tmux means no sixel unless forced. The program in mcterm is told the same: pixel sizes in the pty (TIOCSWINSZ), sixel in the Device Attributes, XTWINOPS 14/16/18 answered.

Lua viewer sources get an options key (options_key in mc.viewer_source.define) that calls options(), after which a viewport source is built again with what options() returned; the viewport carries pixel_width and pixel_height where the terminal draws sixel.

lua-sixel: F3 on a picture prints what image.sh printed (exif or exiftool, one line of identify) and draws the picture with chafa in sixel where the terminal draws it, in characters otherwise; Alt-O switches between the two. The picture takes the rows left under the properties. The script is installed and magic.ini sends pictures to it whether chafa is present or not: without chafa it prints the properties and, in place of the picture, "Install chafa to see the picture here." lua-chafa stays as the characters-only viewer for those who turn lua-sixel off; exif, exiftool and identify are optional, as they were in image.sh.

Notes: chafa without a terminal to ask needs --font-ratio=1/1 for sixel, or it flattens the picture by half; a picture that does not fit whole in the widget is not painted, sixel cannot be cut. Not in this change: pictures in the scrollback and the alternate screen, DECSDM, kitty/iTerm2 graphics.
Feature, Plugin, mcview
#180 The chafa viewer now prints what the F3 action of misc/ext.d/image.sh used to print before the rendered picture: exif output, or exiftool when exif is missing or fails, then an identify summary.

identify is asked for a single line (format, size, depth, frame count) via -ping instead of its default output, which is one line per frame and ran to a hundred lines for an animated GIF.

chafa is called with --animate=off: by default it plays the animation, emitting every frame with cursor-movement escapes, and the viewer showed them one after another as garbage. Now a single still frame is rendered.

The chafa call is wrapped in sh -c with the path and viewport size passed as arguments, so file names with spaces or quotes are safe.
Feature, Plugin, mcview
#179 When entering a plugin subdirectory the panel now lands the cursor on .. if the plugin does not name an item to focus. panel_plugin_reload previously preserved the cursor name across the reload, which could match a different entry in the new directory and move focus to the wrong file.

This prevents cases such as a Dir/ directory that also contains a Dir binary, where focus erroneously landed on the binary instead of ... When no focus is provided after chdir the cursor is placed on the first entry to make post-chdir focus predictable.
Bug fix, Plugin, panel
#178 Marking the output with the mouse:
- A double click marks the word under the mouse, delimited the way mcedit delimits one (is_break_char set: whitespace and {}<>=|/!?~-+'",.;:#$%^&*`); a delimiter or a blank is a word of its own. A triple click marks the row without its trailing blanks.
- The reading cursor lands on the end of the mark, so a drag or Shift-arrows carry on from there.
- With the terminal focused and something marked, Enter copies the mark like Ctrl-Insert ([mcterm] Store = ctrl-insert; enter); with nothing marked it reaches the shell as before.

Ctrl-L ([mcterm] Clear = ctrl-l):
- Works like a page of newlines: the whole screen scrolls up into the history and the prompt with whatever is typed on it (or the row a program is printing on) stays at the bottom of the blank screen. Nothing is sent to the shell and nothing is erased one turn of the wheel brings the old output back row by row.
- The key is the terminal's whoever is typing, like the scroll keys; in panel mode it stays Refresh, and an alternate-screen application gets it as before.
- mcview_vterm_page_up() in vterm does the scrolling, keeping the rows of the prompt line out of the history.

Tests: word/row marking and the break set in tests/src/mcterm_select.c; page-up (history contents, a multi-row line, alternate screen) in tests/src/viewer/vterm_terminal.c.

Note: the new bindings come from mc.default.keymap, so an installed copy needs updating.
Feature, mcterm
#177 The configure script now requires libssh2 1.9.0 because versions before 1.9 implement only the ssh-rsa and ssh-dss host key algorithms while OpenSSH 8.8 and later do not offer those; libssh2 1.9 adds ECDSA and ed25519 and is present in the target distributions (Debian 11, Ubuntu 22.04 and newer).

The sftp plugin now reports which step failed when a connection cannot be established — socket, handshake, authentication, or SFTP session — and shows the library's error text to explain the failure. A cancelled password prompt is no longer treated as a failure to report.
Bug fix, Chore, Plugin
#176 The build was adjusted so mc6 can compile against the GLib version the configure script requires (2.58). lib/glibcompat.h provides g_memdup2 on GLib < 2.68 and maps g_spawn_check_wait_status to g_spawn_check_exit_status on GLib < 2.70, and the source files that need them include the header. This addresses three calls that were newer than the minimum: g_memdup2 used in the runtime host, viewer cache and Lua bridge, g_spawn_check_wait_status used in the docker, k8s and git plugins, and g_string_new_take which already had a fallback in the panel and editor search.

Three calls were newer than the minimum: g_memdup2 (2.68) in the runtime host, the viewer cache and the Lua bridge, g_spawn_check_wait_status (2.70) in the docker, k8s and git plugins, and g_string_new_take (2.77) in the panel and the editor search. The last one already had a fallback in lib/glibcompat.h that those files did not include.

glibcompat gets g_memdup2 for GLib before 2.68 and maps g_spawn_check_wait_status to g_spawn_check_exit_status before 2.70; the files that need them include the header. Checked on Debian 10 (GLib 2.58.3): the tree builds and the panel plugins load.
Bug fix, Chore, core
#175 The Quick cd box (Alt-C) is now a one-line input drawn in place of the
mini status of the current panel instead of a popup dialog.

- Tab and Shift-Tab complete the directory name; the list opens above
the input inside the panel. Alt-Tab from the keymap keeps working.
- Up and Down walk the input history.
- Only directories are offered. INPUT_COMPLETE_CD without
INPUT_COMPLETE_FILENAMES now means "a directory name": no "cd "
prefix is looked for and files are filtered out. Quick cd uses this
mode; CDPATH is searched for a bare name, as on the command line.
- Esc cancels and the mini status is redrawn.
Feature, core
#174 The ls helper sends the owner after the mode as numeric "uid.gid", but the parser read the mode alone, so every file on a shell link showed as root's. Read the numbers into st_uid/st_gid; the panel names them locally, as it does for sftp. shfs-tool -l prints them as well. Verified against a live host: user files show uid 1000, /etc/ssh shows root, matching ls -lan on the remote.

Closes MidnightCommander/mc#1407
Bug fix, Plugin, panel
#173 The shell's line editor is the command line in both views as soon as the shell is at its prompt. mc's own input is active only while the shell has no prompt and returns any typed text when the prompt appears; keys not consumed by mc are forwarded to the shell and interpreted via the command line's keymap so modifier-based cursor and word motions follow the command line mapping (Alt-b/Alt-f for word motion). When panels are visible an empty line leaves Enter to the panel, cd and exit are handled by mc as before, and other commands run in the shell with the terminal brought up.

When mc sends a command to the shell (for example the cd after leaving a panel) the user's line is removed first and then retyped at the next prompt with cursor position preserved; the terminal is read back (waiting up to 150 ms) so echoed characters are handled correctly. The completion list is now refilled and narrowed on every typed character (and widened on deletions), typed characters are not overwritten by a longer common match, a single remaining match is accepted automatically, and cursor-key encoder and the command line history button are adjusted to match the terminal redraws.
Feature, mcterm
#172 Add a Lua file handler for viewing ELF metadata with readelf. MIME detection now follows symbolic links, allowing ELF
symlinks to use the same viewer as their targets.

- Detect ELF files through libmagic MIME types.
- Follow symbolic links when determining MIME types.
- Run readelf directly with argv, without a shell.
- Display ELF headers, sections, segments, and dynamic information.
- Support Viewer, Quick View, and cyclic F8 generated/raw switching.
- Show progress and failure indicators.
- Add Lua runtime and MIME regression tests.
Feature, Plugin, mcview
#171 The CtagsComplete action in the ctags plugin is now passed through for selected text.
Selection-based invocations of CtagsComplete are forwarded to the usual handlers instead of being intercepted by the plugin.

- Stop the CtagsComplete action from consuming its key when text is selected.
- Allow selected text to use Shift-Tab for block unindent.
- Preserve Ctags completion behavior when no text is selected.
Feature, Bug fix, Plugin, mcedit
#170 Add Lua-based Procyon Java class viewer

- Added Java class viewing through a Lua file handler.
- Integrated Procyon CLI using terminal-backed viewer sources.
- Preserved colored output and terminal scrollback.
- Added decompilation progress and failure indicators.
- Detected successful processes producing no output.
- Added reusable viewer-source lifecycle output metadata.
- Added cyclic F8 switching between generated and raw views.
- Extended raw-view switching to the Chafa image viewer.
- Kept Java handler selection limited to .class files.
- Added Lua runtime and viewer regression tests.
Feature, Plugin, mcview
#169 This implements the Quick Filter interaction model proposed by @GfEW in #2697 issuecomment 3358293597: Quick Search and Quick Filter share the same pattern and users can switch between them without losing it.

This change introduces an interactive filter-as-you-type mode for file panels. Unlike quick search, which moves the cursor through matching entries while keeping the complete list visible, quick filter temporarily hides non-matching entries. Both modes share the same pattern and allow switching between searching and filtering without retyping it.

- Add a quick filter mode bound to Alt-Shift-S.
- Share the pattern between quick search and quick filter.
- Use implicit pattern matching for quick filter while preserving prefix matching for quick search.
- Keep filtering active during navigation, mouse scrolling, selection, and listing-format changes.
- Preserve marks for filtered-out files and show them as “N marked (+M more)”.
- Restore the complete file list immediately on Ctrl-G.
- Avoid copying and scanning the directory list unnecessarily.

Closes MidnightCommander/mc#2697
Feature, panel, core
#168 Runtime file handlers are added. They allow registering file handlers while mc is running.

A Chafa viewer is added and integrated into the viewer subsystem. It renders images using the Chafa library.
Feature, mcview, panel
#167 Improve the mcterm busy prompt by showing the currently running command instead of the generic background label.

Examples:

text<br> (make ⠋) /home/user/project/<br> (tail ⠋) /home/user/project/<br> (g++ ... ⠋) /home/user/project/<br> (python3 sup... ⠋) /home/user/project/<br>
On Linux, the command is obtained from the foreground process group of the shell PTY. Commands submitted directly by mc are retained as a fallback until their process becomes available.

Long command names are shortened to keep the prompt compact. Interpreter commands may also include a shortened script name.

This intentionally does not enumerate the shell job table or track commands after the shell has returned to its prompt.

Tested with real PTY sessions using:

- sleep;
- a long Python script name;
- tail -f;
- make;
- a long g++ command.

All mcterm tests passed (38 tests), as did the filemanager test suite (10 tests).
Feature, mcterm
#166 This fixes character rendering in the editor and viewer when MC runs in a non-UTF-8 terminal locale.

The viewer incorrectly assumed that charset conversion always returned a Unicode code point. On an 8-bit display, however, it returns a byte in the terminal

The second part fixes a regression introduced by 1e0e6b5e1e3236023eb20bb8ab33ab9fd7d984e3.

This fixes a regression introduced by 1e0e6b5e
(charset: rename IBM866 to CP866 for iconv and adjust charset names for codeset).

Closes MidnightCommander/mc#4668

## Testing

Tested in Docker with:
- terminal locales: UTF-8 and CP866;
- file encodings: UTF-8, IBM866, CP1251 and KOI8-R;
- both mcedit and mcview;
- lowercase and uppercase Cyrillic text.

All 16 combinations passed. The library, editor and viewer test suites also passed (72 tests total).

The 8-bit terminal path was additionally tested manually using PuTTY configured for KOI8-R.
Bug fix, core
#165 Fix rendering of files using 8-bit encodings on UTF-8 terminals.

After converting a character from the selected source encoding to Unicode, mcedit still checked its printability using the 8-bit is_printable() function. Unicode code points whose low byte falls within the control-character range were therefore displayed as dots.

Use g_unichar_isprint() whenever the display encoding is UTF-8.

Reproduced and verified with CP1251 and KOI8-R files in Docker. The editor test suite passes.

## Details

Closes MidnightCommander/mc#4668

Commit that introduced the regression: f4ef5c64a (https://github.com/MidnightCommander/mc/commit/f4ef5c64a4dcf078b6dc1336ab6dbb121d83d485)
Bug fix, mcedit
#164 mcterm keeps the terminal cursor and the command-line state in sync. The cursor position is updated when the command-line buffer changes, and the command-line buffer is updated when the cursor moves in the terminal.

The change applies to the embedded terminal's command-line editing and cursor handling. No new user-visible options are introduced.
Bug fix, mcterm
#163 The build now requires glib 2.58 and gmodule 2.58, and doc/INSTALL is updated to match. Configure checks the raised minimum and will refuse older glib versions.

The code calls g_ptr_array_steal_index unconditionally, and that function was introduced in glib 2.58. The previous declared minimum of 2.32 no longer matched what actually builds, which caused compile-time failures on systems with older glib. Raising the minimum surfaces the incompatibility at configure time instead of during compilation.
Feature, Chore, core
#162 This PR introduces a complete Lua extension platform for Midnight Commander. Lua scripts receive a stable, typed ABI for working with the editor, panels, viewer, UI, processes, and events without implementing extension-specific features directly in the mc core.

### Main changes

- Added the Lua runtime and a common extension ABI with lifecycle, capability, error, and version management.
- Implemented the editor ABI: documents, cursor, selections, buffers, transactions, saving, and events.
- Implemented the panel provider ABI for virtual panels, connections, file operations, data streams, and contextual help.
- Added the viewer-source ABI for generated content, files, and command output.
- Added mc.ui, dialogs, menus, status indicators, completion/history, and process execution.
- Added Lua script management under Options \ Lua scripts.
- Added editor extension examples: Base64, paragraph formatting, sorting, date/time and literal insertion, command output, and table drawing.
- Added API annotations and automatic Markdown and JSON reference generation.
- Expanded test coverage for the runtime, events, editor ABI, and panel providers.
- Prevented duplicate panel plugins from loading from both system and user directories.
Feature, Plugin, core
#160 This change completes the removal of mc's old subshell mechanism and replaces it with integration through mcterm. When the user's shell is already running in the embedded terminal, mc now sends commands directly to that shell instead of creating and maintaining a separate parallel subshell. The command-prompt widget renders the shell's own prompt row, so typing starts at the actual shell cursor and preserves the shell's colors and prompt formatting. When the panels are hidden and the user runs mc from that shell, the child mc sends SIGUSR1 to the parent and exits, causing the parent to restore the panels instead of launching a nested mc. The shell receives MC_PID and MC_TTY in its environment.

The terminal stack now tracks OSC 133 and OSC 7 marks using a session token and delivers OSC 133 events to the host, allowing mc to follow the shell through prompt, busy, and exit states. mcterm keeps overlay focus and the completion position until typing begins. Key handling and memory bugs were also fixed: sequence codes are now stored only on the final trie node, and key-trie pointers are cleared to prevent use-after-free crashes.
Feature, core, mcterm
#159 The embedded terminal can mark output with the mouse or Shift-arrows, and Ctrl-Ins writes the selection to the clipfile and the system clipboard; the mark is anchored to terminal row indices so new output or scrolling does not move it. Marking is disabled while a panel covers the terminal or an application uses the alternate screen. A dedicated [mcterm] keymap lets the terminal receive keys such as Shift-arrows and Ctrl-Ins instead of those keys being swallowed by the shell.

The terminal gains its own cursor and a focus model that decides whether keys go to the terminal or to the command line; Tab, Shift-Tab and mouse move the focus and scrolling keys work regardless of focus so you can look back while typing. The change also creates the clipfile directory on demand, adds a [mcterm] skin section (black by default), and fixes vterm to erase the held-back row using the default ANSI state so terminal backgrounds render correctly.

- Marking the output. With the mouse by dragging, the view following past the edge of the window; with the keys by holding shift and moving with the arrows, the pages, Home and End. Ctrl-Ins puts what is marked on the clipfile and on the external clipboard, through the same events the editor and the command line use, so the text pastes straight into mcedit.
- A mark stays where it was put. A row of output is named by a number of its own rather than by where it sits on the screen, so neither new output, nor scrolling, nor a resized window moves what is already marked.
- A cursor of its own, and a focus. The terminal has a cursor now, and one can see it; the focus moves between the terminal and the command line with Tab, with Shift-Tab, and with the mouse. Typing hands the focus back to the command line, and the character with it.
- A [mcterm] keymap section. The cursor, the marking and the view: all of it rebinds.
- A [mcterm] skin section. Its own background and mark colour, apart from mcview.
Feature, core, mcterm
#158 The list of found files shows the file info, not just the name: the modification time, the size and the permissions. Looking at a result you now know what has been found: whether the file is fresh or a year old, empty or a gigabyte long, yours or someone else's, without opening it and without going back to the panel. The columns use the same formatting as the file panel (file_date(), size_trunc_len(), string_perm()), so the date honours the time format setting and the size honours the SI units switch. The columns are separated by the vertical line of the skin; on a narrow terminal they are dropped one by one, the permissions first and then the date, so that the file name stays intact. The directory the files below belong to is drawn with the title color, which keeps the groups visible.

Searching file contents now groups multiple matches from the same file. Previously, each match was displayed as a separate item, so a file with two hundred matches produced two hundred entries in the results. Now each file is shown once: a single match is displayed with its line number (config.log:133), while multiple matches are represented by their count and a [+] marker. For example, a search that previously returned 321 items now shows 3 files.

The matches are shown on demand. The Left key or a click on the [+] mark opens the list of the matches of the file: the number of the line and the line itself, not the bare numbers that tell nothing. From there Enter goes to the file, F3 views it and F4 edits it, all at the chosen match. The lines themselves are not kept anywhere, they are read from the file by the offsets of the matches when the window is opened.

The state of the search has moved to the header of the dialog (Finished, Selow the list shows the hint how to see the matches; the hint appears onlywhen there is something to expand. The counter now tells about the files as well: Found: 321 in 3 files.
Feature, core
#155 vterm keeps lines that scroll off the top of the screen in a bounded history. Each row is stored at terminal width, history limits are enforced by rows and by cells so long lines cannot consume unbounded memory, and the buffer contracts when the terminal is resized to avoid reads of rows no longer on-screen.

mcterm lets the user scroll back through terminal output with PgUp/PgDn, Shift+arrow, the mouse wheel and Home/End; typing returns the view to the live output and navigation keys that cannot move the view are passed to the running program. New output no longer drags the view to the end while the user is reading, and alt-screen applications and panels that share the screen still receive keystrokes themselves.
Feature, mcterm
#152 Panel plugins can now hand an input stream - a byte source with open/read/seek/close that owns its session - to other plugins so a plugin can read a file another plugin holds. The stream stays valid after the source panel is replaced and supports seeking so formats that keep their directory at the end of the file (for example 7z) can be read without pre-downloading.

The core hands a stream to the first plugin that accepts it, and file-to-plugin associations move into magic.ini as %plugin{name:operation} directives so Open requests go to plugins that declare they open panels while viewers are not chosen by mistake; mc.ext.ini remains the fallback. The sftp plugin now supplies get_input_stream() that clones the panel session and performs real seeks, the build adds --enable-panel-plugin-sftp, and a Docker sandbox exercises remote protocols and edge-case archives to catch regressions.
Feature, Plugin, panel, core
#149 A panel plugin that opens an SQLite database as a directory tree, read-only.
Enter on a database file gives the panel, F3 gives its schema, and both come from magic.ini rather than from a name the core knows.

The database is walked as directories: database -> table or view -> page of rows -> row. A row is shown as JSON, and JSON stored inside a text column is unfolded on F3, while Shift-F3 keeps showing the stored text as it is.

## Details

### Browsing

- Every level carries a schema.sql entry with the CREATE statements for what
is below it.
- A page holds at most 200 rows, so a table of a million rows does not build an
unusable listing.
- Rowid tables are read in rowid order. Views and WITHOUT ROWID tables are read
one page per query instead of sorting the whole object for every row.
- A long scan runs with the interrupt key enabled, so Ctrl-C stops it, and a
reload does nothing when PRAGMA data_version says the database has not
changed.
- BLOB values are shown as a hexadecimal preview with their byte length, and
invalid UTF-8 in a TEXT value as byte escapes.

### magic.ini

The plugin publishes an Open and a View file operation, and configure installs
two rules:

[sqlite.database]
Type=^SQLite 3\.x database
Open=%plugin{sqlite:open}
View=%plugin{sqlite:view}

[sqlite.database-name]
Regex=\.(sqlite|sqlite3|sqlitedb)$
RegexIgnoreCase=true
Open=%plugin{sqlite:open}
View=%plugin{sqlite:view}

The type rule opens a database whatever its name is; the name rule covers the
case where file(1) is not consulted. .db is deliberately left out of the name
rule, so a Berkeley DB file keeps its mc.ext.ini handling. A user can point
other names or types here from ~/.config/mc/magic.ini.

Before this, panel.c asked for the plugin by name and offered it every file
the user pressed Enter on, while F3 on the same file went the mc.ext.ini way
and shelled out to sqlite3. The core now knows no plugin by name.
Feature, Plugin, panel
#148 Closes: #144

F5 on a directory in a plugin panel wrote a file of zero length named after the directory, or nothing at all. The copy loop never asked whether the source was a directory: plugin_panel_collect_names() dropped the mode the panel already
held, and get_local_copy hands back one file, which a directory does not have. F6 did the same and then deleted the source.

A directory goes to the plugin first, since one that can hand over a whole subtree does it in a single pass -- arcmc says so with MC_PPF_COPY_TREE. Without that flag the core walks the directory itself with what every navigable plugin already provides: chdir in, get_items, copy the leaves, chdir back. Nothing new is asked of a plugin, and ten of them stop writing zero length files: docker, ftp, git, k8s, mongo, s3, samba, sftp, shell-link, systemd.

Files also get the mode from the listing instead of the 0600 of the temp file they travelled in.
Bug fix, Plugin, panel
#147 S-F4 in a plugin's top listing now creates the appropriate item (connection, context, repository) instead of prompting for a file name, and those list-type plugins report cancelled dialogs as MC_PPR_SKIPPED. Plugins that do not recognise a key continue to return MC_PPR_FAILED so the panel leaves the key alone, avoiding undesired fall-through behavior. Feature, Plugin, panel
#146 The drive menu had only Alt-F1 and Alt-F2 to reach it.
The keymap already binds both commands, so the menu shows the shortcut it has.
Feature, panel, core
#143 Closes: #142

F5 on a directory in the archive panel left a file of zero length named after the directory, and said nothing about it. mc asked the plugin for a local copy, which hands back a single file; a directory entry has no data in the archive, so the temp file stayed empty and was copied as it was.

Serve copy_to_local in the plugin. A directory is unpacked with the whole subtree below it, a file still goes through get_local_copy and then takes the mode the archive holds instead of the 0600 of the temp file.

F6 takes the same path and is fixed with it.
Bug fix, Plugin, panel
#141 Closes: #140

ESC came back from a peek-ahead read at once, so ESC 1 did not open help and a double ESC gave two escapes. ESC now goes down the key trie and waits according to the Esc key mode setting. S-Lang only, ncurses was never hit.

In the ncurses build a typed character showed up only after the next key. getch_with_delay() waited in select(), which does not see input already buffered by the screen library. It asks the library first now.
Bug fix, core
#139 Closes: https://github.com/blue-panels/mc6/issues/134

Packaging now lists Ubuntu 26.04 as a target for the Mongo plugin. Package metadata and build configuration were adjusted so the Mongo plugin builds and packages cleanly on 26.04.

The CI and packaging scripts include 26.04 in the build matrix so artifacts are produced for that release. This ensures users on Ubuntu 26.04 can install the Mongo plugin from our packages and prevents platform-specific build regressions by exercising the packaging path in CI.
Bug fix, Chore, Plugin
#138 Closes: https://github.com/blue-panels/mc6/issues/135

Encrypted 7z archives are now created with the external 7z program (using -mhe=on for header encryption) and opened through the u7z helper, which takes the passphrase from MC_EXTFS_PASSWORD; read commands always pass -p (empty when unset) so 7z reports an error instead of prompting on the terminal. When the 7z program is missing the archive plugin reports that explicitly instead of repeatedly asking for a password that cannot work. The create dialog stops comparing the password with the verify field while "Show password" is set, refuses a password for formats that cannot encrypt, and asks for a password when an encryption checkbox is checked.

Builtin archive formats now expose per-format backends in the settings dialog: Pack and Unpack choose one of builtin, both, extern or off, where "both" means libarchive with the external tool as fallback (used for 7z encryption); the u7z helper takes its program from MC_EXTFS_P7ZIP and program lookups in PATH are cached. The table widget used by these dialogs now accepts hotkeys and delivers Enter to the focused row, supports left/right column movement and a new choice column where space steps values, and the scrollbar can be drawn on the dialog frame.
Bug fix, Plugin, panel
#137 Closes: https://github.com/blue-panels/mc6/issues/136

Serbian man pages now respect the project's build options. They are generated conditionally so the installed pages match the features enabled at build time.

The change is limited to documentation and does not alter runtime behavior.
Bug fix, mcedit
#132 The filemanager avoids buffer overflow when constructing extension cd paths. Path building now checks lengths and uses bounded writes so extension cd path strings cannot be written past the destination buffer and remain NUL-terminated.

This prevents crashes and potential security issues caused by overly long paths. It makes changing directory via extensions more robust.
Bug fix, core

Clone this wiki locally