# Ann: SWI-Prolog 10.1.14

**URL:** <https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803>\
**Category:** Releases\
**Created:** [August 30, 2026, 12:21pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803 "2026-08-30T12:21:23Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [August 30, 2026, 12:21pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803/1 "2026-08-30T12:21:23Z")

</div>

Dear SWI-Prolog user,

SWI-Prolog 10.1.14 is ready for download. There are a large number of  
changes. Some bug fixes and notably a lot of work improving the  
development tools. Highlights:

- Bug in atom-GC for dying threads that unregister atoms after tearing  
down the Prolog engine. This notably concerns thread-local predicates  
and local tables.
- Fix handling very large integers on Windows. Here we have, besides the  
memory limit, a 512Mb limit inside libGMP. Also fixes several integer  
operations for values \> 2^{31}, silently truncating. Note that these  
issues only appear on Windows because he C type `long` is 32 bits there.  
It also only affects libGMP integers. The libBF API uses `int64_t` and  
is thus not affected.
- Avoid child processes inheriting socket file descriptors.
- Fixes to halting Prolog from various locations (menus, threads, etc.)

**Development tools**

- Introduced more theme support and TTY links in Prolog messages. Pretty  
much any reference to a predicate is now a link. When tracing, the goal  
is a link to the call-site. This means (typically) Ctrl-click on a goal  
in the debugger edits the call-site. This works in Epilog as well as  
any terminal that supports OSC 8 escape sequences.

- Introduce OSC 133 semantic marks. These allow the terminal to distinguish  
prompts, user input and command output. These are handled by Epilog,  
providing folding of the output of commands as well as copying the command,  
its output or both. Using the resource `prolog_terminal.fold_previous: @on`,  
old commands are automatically folded, leaving only commands and the output  
of the last command visible. Please try! Various modern terminals also  
support OSC 133 (e.g., iTerm2 on MacOS).

- Many fixes and enhancements to Epilog.

# SWI-Prolog Changelog since version 10.1.13

- MAINTENANCE: Added scripts/submodule-update Updates the submodules  
like `git submodule update`, but pulls a submodule that is on a branch  
tracking a remote branch instead of detaching its HEAD.

- FIXED: only write OSC 8 hyperlinks to a terminal ansi\_hyperlink/3  
wrote the escape sequence whenever the hyperlink\_term flag was set,  
also when the stream was a memory stream. A message captured with  
with\_output\_to/2 then came back with the escapes in it, which broke  
test\_messages.pl for anyone running with hyperlinks enabled.

- TEST: split tests/core into tests/core\_text and tests/core\_lang  
tests/core was the longest running swipl test at 13.8 seconds,  
holding back “ctest -j”. Split it in two along the obvious line:  
core\_text holds the tests for characters, strings, encodings, syntax,  
read/write and stream I/O, core\_lang the tests for terms, arithmetic,  
control, compilation and the runtime.

- TEST: test\_agc\_margin: build the filler atom once per size atom\_of/3  
rebuilt a 100,000 element code list for each of the 200 atoms in  
every trigger test, which made this file 10.7 of the 16.4 seconds of  
the core test suite. The list only depends on the requested size,  
so build one per size and share it. Runs in 0.1 second now; the  
atoms it creates are still distinct and still 100kB each.

- ENHANCED: locale independent character classification and case  
conversion code\_type/2, char\_type/2, upcase\_atom/2, downcase\_atom/2 and  
the other text primitives no longer call \<wctype.h\>. Character classes  
and case conversion are derived from the Unicode Character Database  
at build time, so they answer the same in every locale and on every  
C library, cover the full Unicode range also on Windows where wint\_t  
is 16 bits, and agree with the classification read/1 uses.

- FIXED: #1517 crash in atom-GC while destroying a thread or engine  
Destroying a thread or engine that holds many atoms, notably in  
its private tables, could crash in PL\_unregister\_atom() if the atom  
garbage collector reclaimed one of these atoms concurrently.

- FIXED: normalize\_space/2 to normalize Unicode separator characters  
normalize\_space/2 used unicode\_separator(), which implements the  
UAX #31 Pattern\_White\_Space set used by the Prolog reader. As a  
result it did not normalize the Unicode separator characters such  
as U+00A0 (no-break space) or U+3000 (ideographic space), while it  
did replace the invisible bidi format characters U+200E and U+200F  
by a space. It now uses fiswspace(), i.e., the same classification  
as code\_type(Code, space).

- DOC: document the maximum size of unbounded integers Unbounded integers  
are limited by the global stack limit and, if the system is built  
using GMP on a platform where `long` is 32 bits (i.e., Windows),  
to 512Mb. Document this in \secref{morelimits} and refer to it from  
the description of \*\*/2.

- FIXED: Windows crash creating very large integers If `long` is 32 bits,  
as on Windows, GMP integers are limited to 512Mb and GMP calls abort()  
if we ask for more. Our checks only verified the result fits in the  
global stack limit (1Gb by default), so for example `X is 2^4294967294`  
took the entire process down. In addition, the exponent was truncated  
to `unsigned long`, which made `X is 2^4294967296` silently evaluate  
to 1.

- CMAKE: test\_libs() and test\_lib() take OPTIONS Commandline options  
for swipl itself, handed to it before the test is loaded: a -D flag  
the test needs set before its libraries are, a -p that only it wants,  
and the like. There was nowhere to put such a thing: the command is  
built inside test\_lib(), so a package that needed one had to register  
its tests by hand.

- ADDED: PL\_prompt\_is\_continuation() Says whether the prompt that  
comes next continues an input that was started earlier, which is what  
prompt1/1 and PrologPrompt() already decide between: the prompt of a  
first line is handed out once, and everything after it is the prompt  
of prompt/2.

- FIXED: crash when a second Epilog window is deleted Updates xpce.  
The terminals share the interned Colour objects of their palette but  
held them with a flag rather than a count, so deleting one Epilog  
window freed colours the others were still painting with.

- ADDED: el\_set/2 prompt\_marks(Boolean) Updates libedit and xpce.  
Turns the OSC 133 prompt marks off for a terminal that would print  
them rather than read them. They are on by default.

- ADDED: OSC 133 semantic prompt marks Updates libedit and xpce.  
The commandline editor marks its prompts and the line it reads with the  
FinalTerm OSC 133 sequences, and the Epilog terminal reads them: it now  
knows when there is a line being edited and where it starts, rather than  
deducing it from bracketed paste. That gives click-to-move-the-caret  
back to vi mode, and terminals with shell integration (iTerm2, kitty,  
WezTerm, VS Code) get prompt navigation over a swipl session for free.

- FIXED: a click in the Epilog terminal disturbed a single character  
read Updates libedit and xpce. A click in the line being edited asks  
the client to move its caret with cursor keys; a client reading a  
single character answered with the ESC of the first of them, which  
made the command line tracer print “Unknown option (h for help)”  
when a link in its port message was clicked.

- FIXED: Missing empty line after a bullet list in help/1 output A list  
nested in the body of a definition list (`dd`) was formatted as a nested  
list, losing the empty lines that separate it from the surrounding text.

- DOC: ansi\_format/3: use code markup for the ‘#RGB’ colour names These  
are Prolog atoms, so they belong in code markup. This also avoids  
the LaTeX translation of the quotes into typographic quotes.

- FIXED: Spacing of infix operators in term description items  
A comma binds to the left operand and is followed by a space.  
Adds \infixopsep{Op}, used by \infixterm and \infixtermitem, which  
also keeps a module qualifier free of surrounding spaces.

- ADDED: Epilog terminal: highlight the other occurrences of the  
selection Updated xpce. The dark theme had no isearch styles for  
terminal\_image, so the pale turquoise of the other matches was drawn  
with the terminal’s white foreground; both are now given colour :=  
black, as the editor entry already does.

- FIXED: user streams lose FD\_CLOEXEC when restore\_ctty() reconnects  
them dup2() does not carry the flag over, so after a child revoked  
our controlling terminal and restore\_ctty() opened it again, the  
standard streams were inherited by the next process we start.

- MODIFIED: ansi\_get\_color/2 now reports floats in 0.0..1.0 The  
components of the rgb/3 term were integers in the range 0..65535.  
That range is ambiguous with the rgb/3 term of win\_window\_color/2,  
whose components are in 0..255, and it suggested a precision the  
terminal does not offer: it reports one to four hexadecimal digits  
per component, which we scaled up to 16 bits. A component is now  
the fraction of its maximum, which needs no scale to be agreed upon.  
This is an incompatible change to a predicate that is rarely used  
outside library(theme/auto).

- ENHANCED: Hyperlink and stripe the goals printed by the debugger Goals  
printed by the debugger are now a hyperlink to their call site, i.e.,  
the position in the clause of the parent frame from which the goal  
is called. They also carry the new colour class goal(Port, Parity),  
where Parity alternates over the steps of a trace. This allows themes  
to separate successive steps using a soft background colour and/or  
to colour the goal by port. The dark and light themes stripe the goals.

- ENHANCED: Centralise predicate references in messages and make them  
links boot/messages.pl formatted a predicate reference in some forty  
places, using four different module-hiding policies, three copies of  
the source location lookup and a mix of ~q and ~p. Only one of them  
produced a link. All of them now go through predicate\_reference//1,2,  
which prints the predicate indicator using the `code` class and turns  
it into a hyperlink to its definition when the location is known.  
Messages that list candidates, such as the alternatives for an unknown  
procedure, tag each predicate with its kind using predicate\_kind/2  
and the new themeable class predicate(Kind).

- ENHANCED: Central source location for predicates, including C predicates  
Added ‘$predicate\_source\_location’/2, which resolves a predicate  
to File:Line. It follows imported\_from/1 to the module that defines  
the predicate and falls back to the location of the implementing C  
function for foreign predicates. The (expensive) foreign lookup runs  
`addr2line` or `atos` in a child process and is therefore memoised.

- ENHANCED: Hook prolog:line\_editor\_attributes/2 Tell the line editor how  
to switch the decoration of the input line off and on again. It must  
switch these off before erasing the rows the line no longer uses,  
as erasing paints with the current background colour. Called each  
time we build a prompt, so a theme loaded at run time is picked up.

- FIXED: ansi\_get\_color/2: accept the colour replies terminals really  
send The reply was matched against a fixed pattern of exactly four  
hex digits per component terminated by BEL, which is what xterm sends.  
An X11 colour specification allows one to four digits per component and  
the string may be terminated by BEL or ST, which made ansi\_get\_color/2  
fail on terminals that answer the query perfectly well. The Epilog  
terminal is one of these: it replies with two digits and ST.

- ENHANCED: Colour the toplevel prompt, the typed query and the answers  
The interactive toplevel now decorates the prompt, the text typed by  
the user and the answers using the theme classes `prompt`, `input`,  
`answer(Parity)` and `binding(name)`. `Parity` is `odd` or `even` and  
alternates over the answers of a single query, which allows a theme to  
_stripe_ the answers of a non-deterministic query. The default theme  
only makes the prompt and the variable names bold; the background  
colours are defined by library(theme/dark) and library(theme/light)  
as these require knowing the background colour of the terminal.

- SUBMODULE: xpce: background colour erase and terminal identification  
Provides two fixes needed by the coloured toplevel:

- CMAKE: Create .dSYM bundles on macOS On macOS the DWARF stays  
in the object files and the linked binary only carries a debug  
map that points at them. atos(1) follows that map, which is how  
‘$foreign\_predicate\_source’/2 finds the source of a predicate defined  
in C, used by edit/1 and for the links in messages. The map breaks  
when the objects are removed and some toolchains produce one atos  
cannot follow: a MacPorts gcc build resolves no source line at all.  
Running dsymutil(1) after the link collects the DWARF into a .dSYM  
bundle, which atos locates by UUID, and fixes both.

- FIXED: addr2line: do not report “at” without a source location  
Without source line information atos(1) emits “func (in lib.dylib) +  
0” and addr2line(1) emits “??:0”. We turned both into "func() at ",  
which is worse than the bare “func()”. The " at " is now only added  
once we know a location follows.

- FIXED: halt/0 from an event callback did not take effect until input  
arrived With the SDL backend XPCE has no separate `pce` thread, so  
events for the main thread are dispatched from PL\_dispatch() while  
the toplevel waits for terminal input. A callback such as Epilog’s  
“Halt Prolog” therefore raises unwind(halt(Status)) in the waiting  
thread itself, but the wait loop only asked PL\_handle\_signals(), which  
returns 0 when no signal is pending. Dispatching continued until  
the user typed a character, and $raw\_read/2 then returned end\_of\_file  
with the exception still pending, printing “did not clear exception:  
unwind(halt(0))”.

- FIXED: Windows: Control-C only interrupted the first computation  
#1515 The console control handler runs on a thread of its own, which  
has no Prolog engine, so PL\_raise() had nothing to raise SIGINT on.  
It should call PL\_w32thread\_raise(), but the `#ifdef O_PLMT` guarding  
that never held: pl-main.c does not see config.h. What made ^C work  
at all was the C runtime’s own handler, installed when PL\_initialise()  
calls signal(SIGINT, …) and therefore called first. As it resets  
the handler to SIG\_DFL before calling it, it only answered the first ^C.

- FIXED: Print and link the column of a source location counting from 1.  
The column of a syntax error and of the hyperlinks we emit for a  
location was taken from the `line_position` of the stream, which  
counts from 0, while the C compiler, ripgrep, editors and edit/1 all  
count the first column as 1.

- ADDED: shell\_command/1: find the preferred interactive shell executable.

- PORT: #1514 Windows: make sure PROC\_THREAD\_ATTRIBUTE\_PSEUDOCONSOLE  
is defined.

- FIXED: library(prolog\_xref): track prolog\_listen/2 properly.  
Created called heads with arity 0, as in `p()` rather than `p`.

- ADDED: `ls/1`: tag links with `@`

- DOC: Include library(shell) into the documentation.

- MODIFIED: library(www\_browser): use desktop\_open/2 from library(desktop)  
If library(desktop) is available, www\_open\_url/1 now lets the desktop  
open the URL rather than searching for a browser itself. On Windows  
we use win\_shell/2 if library(desktop) is not available.

## Package clib

- FIXED: sockets are inherited by processes we start A socket that lacks  
FD\_CLOEXEC goes to every process we exec. A child that inherits a  
listening socket keeps its port in use for as long as it lives, so  
an HTTP server does not come back after a restart, and the child may  
accept connections meant for us. Prolog streams get the flag from  
Snew(), but a socket is a plain OS handle until it is turned into a  
stream, and a server socket never is.

- ADDED: library(desktop): desktop\_open/1,2 to open a file, directory  
or URL desktop\_open/1,2 hands a document over to the application the  
desktop associates with it, e.g., a PDF viewer for a `.pdf` file or a  
file browser for a directory. It uses the Windows ShellExecute() API,  
`open` on MacOS and one of `xdg-open`, `gio`, `kde-open`,  
etc. on other systems. The Prolog flag `desktop_opener` and the  
option opener(Command) allow selecting the command explicitly.

- ENHANCED: process\_create/3: detached(true) no longer waits for the  
process If detached(true) is used without process(PID) and without  
pipes, process\_create/3 now returns as soon as the process is started  
instead of waiting for its completion. On POSIX systems this uses  
a second fork(), such that the process is inherited by `init` and  
we do not have to reclaim it. On Windows we close the process and  
job handles.

## Package http

- FIXED: HTML rendering of url/2 message elements The HTML message  
renderer passed the URL of an url/2 element straight into href, which  
raises a type error if it is a File:Line source location rather than a  
web link, and it wrote the label as-is, which is wrong now that a label  
may be a Format-Args pair or an ansi/3 term. Labels are now rendered to  
text and a source location prints as text rather than as a broken link.

## Package libedit

- FIXED: a prompt the program wrote itself was lost on a redraw A read  
that starts where the output left the caret has no prompt of its own:  
`format("name: "), read_line_to_string(user_input, S)' puts those six columns on the screen as ordinary output and then reads. libedit is handed an empty prompt and takes the line to start in column 0, six columns to the left of where it does. While it moves the caret relatively that goes unseen, but a full refresh -- a SIGWINCH, a resize it notices at a keypress, ^L -- redraws the input over `name:  
’ and leaves the caret six columns out.

- ADDED: OSC 133: mark the end of the output and a continuation prompt  
The prompt, the input and the start of the output were marked; where  
the output ended was left for the reader to guess from the prompt  
after it, and a term typed over several lines was marked as several  
commands because every line got the mark that starts one.

- ADDED: el\_set/2 and el\_get/2 prompt\_marks(Boolean) Turns the OSC 133  
prompt marks off for a terminal that would print them rather than  
read them. They are on by default. The marks live in the prompt  
string, so setting the option throws the cached prompt away for  
update\_prompt() to build again.

- ADDED: mark the prompt and the input with OSC 133 While reading a  
line, surround the prompt and the input with the FinalTerm “semantic  
prompt” marks: `A' before the prompt, `B’ before the input and `C’  
when the line was entered. A terminal that reads them – Epilog,  
iTerm2, kitty, WezTerm, VS Code – can tell prompt, input and output  
apart, and so jump between prompts, act on the output of one command,  
or move the caret to a click in the line being edited.

- FIXED: no bracketed paste while reading a single character Bracketed  
paste (DEC private mode 2004) says that a line editor owns the input.  
A read that asks for one character – get\_single\_char/1, the tracer  
at its `? ’ prompt, with\_tty\_raw/1 – is not such a read, so turn  
the mode off for its duration.

- FIXED: resize of a wrapped input line missed when SIGWINCH is lost  
Resizing an Epilog window while editing a line that wraps could leave  
libedit painting on rows that hold something else: the next key moved  
the caret by rows and columns computed from the width the terminal  
no longer had, and the repaint left a copy of the first row behind.

- ENHANCED: Do not leave the input decoration on the rows libedit  
erases The toplevel decorates the line being edited by leaving the  
attributes of the colour class `input` in effect while the user  
is typing. If that class has a background colour, the rows libedit  
erases because the line got shorter were painted with it and stayed  
that way: unwrap a long line or move from a multi-line history entry  
to a shorter one and a coloured bar was left below the line.

- FIXED: Do not decorate completions and incremental search as input  
The toplevel decorates the input line by leaving the attributes of the  
colour class `input` in effect while the user is typing. The completion  
alternatives and the incremental search prompt are written while these  
are active, so they were coloured as input. Worse, `input` may have  
a background colour, which the `\e[0K' used by the search prompt then paints to the right margin. Both now reset the attributes first; the `redisplay’ that ends these commands re-installs the decoration.

- FIXED: honour a PL\_dispatch() exception before reading the terminal  
The PL\_RAWTTY/PL\_NOTTY branch of Sread\_libedit() ignored the result  
of PL\_dispatch() and blocked in read(2), so an exception raised by a  
signal or an event callback was only noticed after the user typed a  
character. Hand it to the stream instead, as read\_char() already does.

- FIXED: Windows: do not report a modifier key press as a NUL character  
Windows queues a key-down event for the modifier of every combination  
typed. Reporting it to libedit as a character handed it a NUL.  
For ^C that NUL was answered to the interrupt handler’s “Action (h  
for help) ?” prompt, which printed “Unknown option” before the user  
had touched a key. See swipl-devel issue #1515.

## Package ltx2htm

- FIXED: Spacing of infix operators in term description items A comma  
binds to the left operand and is followed by a space. Rendering it  
with a symmetric separator turned e.g. the ansi\_format/3 attributes into  
`fg(Color) , bg(Color),hfg(Color),hbg(Color)`. Replaces nospace\_op/1  
with op\_spacing/4 and adds the LaTeX \infixopsep{Op} to do the same  
for the printed manual.

- FIXED: Preserve spaces around single and back quotes The LaTeX tokenizer  
classifies `'` and ``` as words. As spaces between two adjacent  
words are dropped on input and regenerated on output this loses the  
spaces around them: the translation turns the quotes into the HTML  
entities `&lsquo;` and `&rsquo;` and such command tokens do not take  
part in the regeneration. Tokenize the quotes as TOK\_NOSPACEWORD  
such that the surrounding spaces are preserved in the token list.

## Package pengines

- FIXED: HTML rendering of url/2 message elements The HTML message  
renderer passed the URL of an url/2 element straight into href, which  
is wrong if it is a File:Line source location rather than a web link,  
and it wrote the label as-is, which is wrong now that a label may  
be a Format-Args pair or an ansi/3 term. Labels are now rendered to  
text and a source location prints as text rather than as a broken link.

## Package pldoc

- FIXED: Spacing of infix operators in term description items  
A comma binds to the left operand and is followed by a space.  
Adds \infixopsep{Op}, used by \infixterm and \infixtermitem, which  
also keeps a module qualifier free of surrounding spaces.

## Package xpce

- FIXED: print dialog proposed a printer queue named `postscript' When $PRINTER is not set, <-print_command_template now proposes plain ``lpr``, letting lpr(1) pick the default queue, rather than expanding %p to the bogus queue name `postscript’. That name was also a leftover  
from printing PostScript.

- FIXED: resources referring to .png icons that were replaced by .svg  
Several libraries still referred to 16x16 and 32x32 .png icons that  
were removed when the development tools moved to .svg. Notably,  
this made the PceEmacs buffer menu fail to open.

- MODIFIED: print graphics as PDF rather than PostScript  
`graphical<-postscript` and class `win_printer` are gone, leaving  
both library(print\_graphics) and PceDraw unable to print. Both now  
render to a temporary PDF file and hand that to the print spooler.

- REMOVED: PceDraw and grapher Windows metafile support Class  
`win_metafile` and `display->selection_owner` no longer exist  
and the clipboard handles text only, so none of this can work.  
Removes the PceDraw clipboard menu with its -\>export\_win\_metafile  
and -\>import\_win\_metafile, the `draw_metafile` shape and  
`grapher->copy_graph`.

- FIXED: PceEmacs C mode: GDB commands called a non-existing method The  
method is `->tell_gdb_warn`; only -\>break\_at\_line used the right name.

- FIXED: calls to the deleted `graphical->synchronise` Both callers  
only wanted the pending changes to become visible, which is what  
`window->flush` does.

- FIXED: the Dialog Editor used the deleted `display<-visual_type`  
Colour is now always available, so the monochrome alternatives and  
the ifcolour/2 helper selecting between them are dropped.

- FIXED: PceEmacs buffer menu and Dialog Editor used deleted frame  
methods `frame<->icon` and `frame<->icon_label` were deleted,  
but two callers were missed. As a result, opening the PceEmacs buffer  
menu reported an error and failed to create the window.

- FIXED: crash when -\>initialise fails on a class with non-slot C fields  
Instance prototypes initialise the declared slots only, leaving C fields  
such as `file.fd` filled with uninitialised memory. As a failed  
-\>initialise still sends -\>unlink, `new(_, file(SomeFileObject))`  
crashed in Sclose().

- ENHANCED: Epilog: toggle fold\_previous from the Settings menu Added  
a marked “Fold previous command” item to the Settings submenu that  
toggles the fold\_previous setting of the current terminal. As with  
the Debug menu items, a condition updates the mark from the terminal  
state each time the menu is opened.

- FIXED: Epilog: a window row is not a buffer line under a closed fold  
Writing below a closed fold scrolled the window although it had room  
for the caret still, taking what was above the fold off the top,  
and a client that placed its caret with CUP landed in the text the  
fold hides, where what it wrote next never showed. Both counted  
lines where the window counts rows.

- FIXED: Epilog: the alternate screen over a closed fold Entering the  
alternate screen saved one line per row of the window, but a closed  
fold hides lines the window does not show and the erase that follows  
takes those away too: what came back after e.g. help/0 was the text  
the fold hid, with everything below it gone. The window is now saved  
in the lines its rows cover, and the blocks that name them stay while  
the application owns the window, so the folds close again over the  
text that comes back.

- TEST: terminal: wait for the echo of a repeated command The fixed  
pause was never long enough on Windows, where the input reaches the  
client over a pipe a character to the dispatch round.

- FIXED: terminal: let go of a block whose end was erased An erase takes  
the lines below the caret and leaves the ones above, so a block can  
keep its prompt and lose the mark that closed it. It can no longer  
say how far it reaches, but rlc\_sweep\_blocks() kept it as long as one  
anchor was live and ED 0 did not sweep at all. Windows hit this on  
every ^L: libedit’s built-in termcap clears the screen with CUP home +  
ED 0, and the stale blocks broke terminal\_blocks.

- TEST: terminal: a C0 control around an OSC 133 mark is not printed

- FIXED: terminal: ignore unhandled C0 control characters Characters  
below 0x20 that have no VT100 meaning were rendered as glyphs.  
A bash PS0 carrying readline’s […] markers, for example, makes  
bash emit \001 and \002 verbatim before every command’s output.  
Real terminals discard such controls.

- ENHANCED: Use -\>opacity to grey out an inactive terminal.

- ADDED: terminal\_image -\>input\_focus: bool Handling the keyboard  
focus is now a method of its own rather than inline code in -\>event,  
allowing subclasses to react on gaining or losing the focus.

- TEST: terminal: a prompt the program wrote survives a resize Resize  
while a read that started where the output left the caret is pending,  
and check that the row is unchanged, that the caret stayed put and  
that ^A goes to the start of the input rather than to column 0.

- TEST: terminal: dump the screen when the no-prompt click misses  
click\_moves\_the\_caret\_without\_a\_prompt asserted the caret column with  
a bare comparison, which says `4=:=10' and nothing about how the caret got there. It is the one caret assertion in the suite a redraw can move: the prompt is the program's own output, so libedit takes the line to start at column 0, and a full refresh paints the input over `name: ’ and leaves the caret six columns to the left of the click.  
assert\_cursor/3 reports the row and the screen, on which that is plain.

- TEST: terminal: sample the terminal rather than the frame chrome  
term\_screenshot/2 read the top 41 pixel rows of `frame \<-image’,  
where the Epilog menu bar sits: the terminal starts 38 pixels down.  
Every shot therefore sampled the same unchanging chrome, two  
shots compared equal whatever the terminal was told to paint, and  
terminal\_attributes failed on each of its “must differ” assertions  
from the day it was added.

- ADDED: Epilog: hide and show the output of every command from the  
menu The menu of a fold marker gains Hide/Show all outputs, and Remove  
moves up beside the folding it belongs with.

- ADDED: the xpce\_defaults flag: decline the user’s Defaults file  
XPCE read the class variable defaults on the first lookup of a class  
variable, wherever in the program that happened to fall, and read the  
file belonging to whoever was running it along with them. A test suite  
or an application that must not depend on the preferences of its user  
had no way to say so: by the time it could speak they had been read.  
This is not hypothetical – a terminal test failed here because the  
author had turned a mode on in his own Defaults.

- ADDED: Epilog: close the previous command as one is entered Reading an  
OSC 133 mark was a static function with nowhere to put a policy, and the  
policy this wanted is not the terminal’s. It becomes -\>prompt\_mark,  
sent from the OSC decoder as -\>window\_label and -\>working\_directory  
already are, with the letters decoded to what they mean here: where  
a prompt starts, where the line the user edits starts, where that  
line was entered and its output begins, and where the output ends.  
The default implementation is what read them before.

- ADDED: terminal\_block-\>remove: take a command out of the buffer  
Folding hides the output of a command; this takes the whole of it away.  
The lines it covers go and the text under them moves up into the gap,  
which for an input typed over several lines is all of them at once –  
they are one block, so they go as one.

- ADDED: Epilog: act on the command the mouse or the caret is on The  
terminal knows what its window has been used for; this is what it  
takes to reach that. Right-clicking a command offers to copy it,  
to copy what it printed, or to hide that output; \C-\S-h folds the  
command being edited, and \C-\S-\<cursor\_up\> and \C-\S-\<cursor\_down\>  
walk the prompts, as terminals with shell integration do.

- ADDED: Epilog terminal: commands as terminal\_block objects, and  
folding The OSC 133 marks were read for the one thing the mouse needed  
and thrown away. They say more: `A' is where a prompt starts, `B’  
where the line the user edits starts, `C' where it was entered and the output begins, and `D’ where that output ends. Kept, they are  
a model of what the window has been used for, and \<-blocks hands it  
over as a chain of terminal\_block objects, oldest first.

- FIXED: xpce terminal: XPCE\_TERM\_TRACE printed the wrong parser state  
The name table in rlc\_putansi() still held the seven states of an older  
ansi\_state, in the wrong order, so every trace line past CMD\_ESC named  
a state the parser was not in. It now lists all twelve in enum order.

- FIXED: xpce terminal: ESC \> (DECKPNM) left the keypad in application  
mode Both ESC = and ESC \> set app\_keypad\_mode to true, so leaving  
application keypad mode never took effect. Nothing reads the flag yet,  
which is why this went unnoticed.

- FIXED: xpce terminal: enabled the ptsname() NULL check  
rlc\_open\_pty\_pair() passed the result of ptsname() straight to strncpy()  
because the guard against it returning NULL sat in an #if 0. The name  
it reports, NAME\_cannotPtsname, is already in the generated table,  
so the check only had to be turned back on.

- CLEANUP: xpce terminal: removed the dead Windows-console API terminal.h  
still declared the plterm.dll console interface the emulator grew out  
of: the Rlc_Hook typedefs and their setters, rlc\_read/write/ close,  
getch/kbhit, ScreenCols/ScreenRows, the line-edit and completion  
structs, the history ring buffer and the lqueued/user\_data types.  
None of it was ever defined. With them go the five LINE-READ SUPPORT  
functions in terminal.c that had no callers, rlc\_caret\_forward()  
which only rlc\_goto\_mark() used, the rlc\_data fields for colours and  
scrollbar state that ti-\> and the palette replaced, and the unused  
GWL\_DATA, IMODE\__ and OPT\_\* macros – the last two also shadowed the  
OPT\_SIZE enum of SWI-Prolog.h.

- FIXED: xpce terminal: a second terminal took the palette Colours with  
it A terminal resolves the colour cube and the 24 bit colours of its  
client to Colour objects and holds them in its palette between paints.  
It held them with -\>lock\_object, whose F\_LOCKED is a flag rather than  
a count, while ws\_pixel\_to\_colour() hands every terminal that resolves  
an RGBA value the same interned Colour. The first terminal to go  
therefore took the protection of all the others with it: deleting a  
second Epilog window freed a Colour the first still had in its palette,  
and the next paint that used that colour handed r\_clear() a Colour  
that was gone. Which is a crash in r\_set\_fill\_fgbg(), as reported.

- TEST: terminal: a click with nothing to say a line is being edited  
Exercises el\_set/2 prompt\_marks(false): with the marks and bracketed  
paste both off the client says nothing about the line it is editing,  
and the caret stays where it is.

- ADDED: Epilog terminal: read the OSC 133 semantic prompt marks A client  
that marks its prompts says outright what the terminal could until now  
only guess: between `B' and `C’ there is a line being edited, and `B’  
landed where it starts. That is what a click needs to know before  
it asks the client to move its caret there, and a click in front of  
the input now stops at the input rather than walking into the prompt.

- FIXED: Epilog terminal: click sent cursor keys at a single char read  
A click in the line being edited asks the client to move its caret, by  
sending as many cursor keys as there are grapheme clusters in between.  
A client that reads a single character has no caret to move and  
answers with the ESC of the first of them: clicking the source link  
in a port message of the command line tracer made it print “Unknown  
option (h for help)”.

- TEST: run the terminal resize tests with SIGWINCH held back  
EPILOG\_NO\_SIGWINCH keeps rlc\_resize\_pty() from raising the signal  
on the client thread, which leaves libedit where a Windows console  
always is and where a lost signal puts us: with nothing but the size  
on the pty to go on. That is the path the three resize tests that  
press a key were failing on about one run in five, and the only way  
to reach it deliberately.

- FIXED: xpce: crash when the window system has no display On a machine  
where SDL\_Init() fails – headless, or no DISPLAY – xpce loads without  
a display object and `new(F, frame(hello))’ then stored a display  
that is not there. Reading it crashed the process, in -\>create, in  
\<-display, or in the first window that wanted its default colours.  
Say it instead: with no display there is no frame, and no window either.

- TEST: move the alternate screen background erase test to the bce suite  
It belongs with the other background colour erase tests, and it runs  
there without a pty and without libedit: the whole file takes a second,  
where the terminal suite is off unless asked for. Reading pixels is  
still the only way to see the painted tail, so the window is sized  
to its terminal and the test lets the paint happen before it samples.

- FIXED: xpce: a freed colour left a dangling entry in @rgba A Colour  
registers itself in @colours, by name, and in @rgba, by its encoded  
RGBA value. Both hold their members with `refer' none, so neither keeps the Colour alive, but ->unlink only took the @colours entry out. The @rgba entry then pointed at memory that had been handed out again, and the next lookup of that colour value returned it: `Image \<-pixel’  
does one per pixel it reads, `Colour \<-lookup’ one per new/2 on a colour  
with an RGB value, and the terminal one per palette slot it resolves.  
This crashed the xpce terminal test suite in about half of its runs.

- FIXED: Epilog terminal: background colour erase lost over the alternate  
screen The full-line background of the input lines disappeared after  
help/1, and only the text kept its background. The tail of such a  
line is painted from the background colour erase (bce) that `\e[K’  
records on the line rather than from cells, and rlc\_copy\_line()  
did not carry that record along when smcup saved the screen.

- FIXED: Epilog: warning when inserting a non-ASCII character Typing a  
character above 127 into a terminal\_image, e.g. using the Unicode symbol  
picker, reported “Cannot construct 1-th argument for -\>insert\_self”.  
The key binding maps any character \>= 128 to -\>insert\_self and fills  
the argument from the event id, which requires the declared type to  
include `char` or `event_id`. terminal\_image declared it as the int  
range “0..”.

- ADDED: Epilog terminal: a double-clicked word is matched as a word  
Picking a word with a double click says to look for that word, not for  
the letters it happens to be made of: a double click on `Bar' passes over `Barn’ while dragging over the same three characters does not.  
It also makes a one-character word worth looking for, which a single  
character picked any other way is not. A search seeded from such  
a selection with ^S or ^R keeps it; one started with \C-\S-f has no  
selection to take it from.

- ADDED: Epilog terminal: ^S and ^R search on from the selection With  
a selection whose other occurrences are highlighted, ^S and ^R start  
an incremental search for what it holds, from where it is, and step  
to the next resp. previous match at once – so the matches that are  
already lit up are the ones they walk. From there it is the ordinary  
search: repeats, Backspace to widen, M-c and M-w, Escape to leave the  
hit selected. ^G gives back the view and the selection the search  
started from, so a search one did not mean to start costs nothing.

- ADDED: Epilog terminal: highlight the other occurrences of the selection  
Selecting text in an Epilog terminal now says what to look for as well  
as what to copy: the other places the selected text occurs on the page  
are painted in \<-isearch\_other\_style, the way the other matches of an  
incremental search are, and the bar reports which of them the selection  
is and how many there are, as `Selection: Bar (1/5)'. Picking out  
a variable or an atom finds the rest of them without typing it again.

- TEST: terminal: sync with the client before handing out a new terminal  
The first test of a unit could find the prompt back on top of what  
it painted: the window sends the client a SIGWINCH while it is still  
settling on its size, and the client answers that with a redraw of  
its input line. Neither wait\_for\_prompt/1 nor wait\_settled/1 covers  
that redraw – it paints the prompt where the prompt already is,  
so it leaves the screen exactly as it found it.

- TEST: terminal: check that SGR attributes select a font New unit  
terminal\_attributes. It paints the same glyphs wrapped in each  
SGR sequence, samples the window through the new term\_screenshot/2  
primitive and compares the samples: two shots of the same text differ  
exactly when it was painted in a different font, so the test need  
not know which font the painter chose.

- ENHANCED: terminal: render italic text (SGR 3) The terminal now draws  
italic (SGR 3) text in a slanted font and turns it off again on SGR  
23, and combines italic with bold. Epilog claims to be an xterm,  
whose terminfo advertises sitm/ritm, so programs were already sending  
the sequence and it was being dropped.

- ENHANCED: class style: added -\>italic and \<-italic A style can now  
ask for slanted text through an attribute, the way it already asks  
for bold, instead of having to name an italic font in its -\>font slot.

- FIXED: class style: setting a second attribute had no effect A style  
that already carried one of -\>bold, -\>highlight, -\>grey or -\>hidden  
silently ignored requests to set or clear another one.

- FIXED: build on Linux: O\_CLOEXEC undeclared in the xpce terminal The  
pty code asks for `_XOPEN_SOURCE 600` to get the pty API, and glibc  
hides everything newer than POSIX 2001 once that macro is set by hand,  
O\_CLOEXEC among it. The close-on-exec flags added by the previous  
commit therefore did not compile on Linux. MacOS declares the symbol  
at any level because this file also defines `_DARWIN_C_SOURCE`,  
which is why it went unnoticed.

- FIXED: shell of an Epilog window survives halting Prolog The  
pty descriptors were inherited by every process the client starts.  
The client hands its own three to a shell of shell/0 or process\_create/3  
as stdin, stdout and stderr, and those it is welcome to, but a copy of  
the master is another matter: as long as the child holds it, closing our  
side is not the last reference and the pty never hangs up. The shell  
is then never sent the SIGHUP that closing the master owes it, and it  
stays behind, holding whatever else it inherited, after Prolog is gone.

- FIXED: epilog: describe this terminal to the programs that run in it  
Epilog claims to be an xterm compatible terminal by setting `TERM`,  
but left `TERM_PROGRAM` at the value it inherited from the terminal  
it was started from, and run\_shell/0 let the shell inherit both.  
Programs run from an Epilog window or its shell therefore applied the  
quirks of that other terminal to ours. Notably ansi\_get\_color/2 does  
not query a terminal that says it is `Apple_Terminal`, so no program  
started from an Epilog window could find out the colours of the window  
it runs in, which is what library(theme/auto) uses to pick a theme.

- FIXED: terminal: paint the erased tail of a line with the background  
(bce) `ESC [ K` (_Erase in Line_) dropped the cells to the right of  
the caret rather than painting them with the background colour that  
is in effect. As a result a coloured block, such as the striped  
answers of the interactive toplevel, only covered its own text and  
stopped short of the right margin.

- FIXED: destroying a frame leaked the backing store of its windows  
unlinkFrame() uncreated the frame before it freed its members, but  
ws\_created\_window() is false from the moment the frame is uncreated.  
uncreateWindow(), reached from freeObject() on each member, therefore  
skipped ws\_uncreate\_window() and leaked the Cairo backing surface  
and the WsWindow of every window of every destroyed frame.

- FIXED: SDL: dangling pointer to the window holding the pointer  
grab grabbing\_window held a bare pointer, so a window that grabbed  
the pointer and then destroyed itself – Epilog’s “Halt Prolog”  
menu item does exactly that – was unallocated while the event loop  
still referred to it. Hold a code reference as we do for the mouse  
tracking window, which also makes the F\_FREED test a valid read,  
and report the recovery under DEBUG(event) rather than on the console.

- FIXED: Epilog: “Halt Prolog” when Epilog runs inside a Prolog toplevel  
The menu item asserted quit\_requested/0, which is only examined  
by ep\_wait\_\_/0, i.e., when Epilog is the main goal. Started using  
epilog/0 from a running Prolog there is no such loop and the item  
did nothing. Track whether ep\_wait/1 is active in ep\_main\_running/0  
and call halt/0 directly if it is not.

- FIXED: gcc -Wstringop-truncation warning on MacOS and FreeBSD. The path  
fields of the OS structs used to find the working directory of the  
foreground process are fixed size arrays that need not be terminated.  
Bound the copy by the field size and fail if the path does not fit  
rather than returning a truncated one.

- ADDED: Epilog profile/2: a profile/1 option to refine another profile.  
A profile that gives profile(Super) takes Super’s options for the ones  
it does not give itself, so a profile can be a shell in a particular  
directory or a toplevel with a particular background without repeating  
what it inherits. This is the option epilog/1 already takes to pick  
a profile, now meaningful in a profile of its own.

- ADDED: epilog/1: inject(Spec) option to type at a new terminal.  
Spec is an item or a list of items. A string is typed as a line of  
text, any other item as a Prolog goal, using -\>inject. As we cannot  
tell whether the terminal runs a shell or Prolog, the caller says so  
by choosing the type.

- ADDED: xpce timer -\>start: number of times to fire, and \<-times.  
A timer started as -\>start(repeat, N) fires N times and goes idle.  
\<-times is what is left of that, counted off before the message runs,  
so a message that sees 0 knows it was the last one and may start the  
timer again, as it may for a `once’ timer. Without the argument a  
timer repeats as before.

- FIXED: xpce terminal -\>send: write to a pty we never opened or  
already closed. rlc\_send() tested the master fd for non-zero.  
The struct is zeroed before the pty is opened, so “never opened”  
was caught, but rlc\_close\_connection() leaves -1, which passed the  
test and reached write(-1, …).

- PORT: Make compile on MacOS again.

- FIXED: Epilog and PceEmacs: the column of a source location  
counts from 1. Clicking a link with a column, e.g., produced by  
`rg --hyperlink-format=file://{path}#L{line}:{column}`, placed  
the caret one character to the right, as the `line_pos` of an xpce  
source\_location counts from 0 while edit/1 and the tools that emit  
such links count from 1. Epilog now also accepts the `#L<line>`  
form used by GitHub and rg.

- FIXED: xpce terminal: a coloured hyperlink label kept the colours  
of its client. The `link_style` colours now only apply to cells  
for which the client did not select a colour itself. A client that  
colours its links, e.g., `rg --hyperlink-format=...`, had its colours  
replaced by the link style. The underline of the link style still  
marks the link, and the `link_armed_style` used while hovering keeps  
replacing the colours: that is transient feedback which must show on  
a coloured link as well.

- MODIFIED: PceEmacs File/Shell now starts a shell in an Epilog window.

- FIXED: xpce terminal: translating a click to a cell was one cell off.  
Clicking the last character of a hyperlink did not open it and clicking  
the cell before it did, as the pixel of a click was mapped to the  
cell boundary at or after it rather than to the cell containing it.

- FIXED: xpce terminal: process escape sequences inside an OSC  
8 hyperlink. An OSC 8 hyperlink is a state rather than a self  
contained sequence: the label between `ESC ] 8 ; <params> ; <URL> ST` and the same sequence with an empty URL is ordinary output that  
may carry SGR sequences. We used to collect the label as text, so  
a client that colours its links, e.g., `rg --hyperlink-format=...`,  
painted the escape sequences on the screen. Parameters such as `id=`  
are now accepted as well.

- ADDED: library(epilog): profiles for new terminal windows. A profile  
is a named set of options for epilog/1. The built-in profiles are  
`prolog`, which runs the Prolog top level, and `shell`, which runs an  
interactive OS shell in the terminal. New and split windows inherit  
the profile and start in the working directory reported by the window  
they were created from. Profiles are added using the multifile hook  
epilog:profile/2.

- ADDED: xpce terminal\_image \<-working\_directory, \<-foreground\_directory  
and \<-host A client that reports its directory using OSC 7 (ESC ] 7 ;  
file://host/path ST), which shells emit from their prompt hook, or  
using OSC 9;9, the Windows spelling, now updates \<-working\_directory  
and \<-host. \<-foreground\_directory instead asks the OS where  
\<-foreground\_process is, which needs no cooperation from the client,  
but only works on Linux, macOS, FreeBSD, NetBSD and Solaris.

- FIXED: terminal: pass Ctrl+Z to a process running in the terminal  
Ctrl+Z was dropped unconditionally, so a shell started on a terminal  
could not suspend its jobs.

- FIXED: Ctrl+, Ctrl+], Ctrl+^ and Ctrl+\_ to produce a control character  
These keys were passed on as the plain punctuation character, so a  
program running in a terminal could not be sent SIGQUIT with Ctrl+.

- FIXED: terminal: clear(1) left the old screen behind ED 3 (erase saved  
lines) rebased the ring on slot 0 when the window was already empty,  
but left the text of those slots and the caret where they were, so  
the screen came back with old content. `clear’ sends ED 2 before ED  
3 and hit exactly that.

- ADDED: epilog:profile/2 Multifile hook. This hook can be used to  
define new Epilog profiles. For example `epilog:profile(shell, [title('Shell'), goal(shell)])`.

- ADDED: epilog: a bar over the terminal for messages and search options  
The incremental search says what it is looking for, how many there  
are and whether it found anything; until now nothing in an epilog  
window could show that. Its frame has no reporter, so the -\>report  
calls already there – the ones the font commands make – went nowhere.

- ADDED: terminal\_image: Emacs style incremental search on Ctrl-Shift-F  
Type and the terminal highlights what it finds and scrolls to it.  
^S and ^R walk the matches, backspace widens the search again, ESC  
leaves the hit where it is and ^G gives back the view the search  
started from. As in class editor, a focus function sits in the way  
of -\>typed and sees every key until the search ends.

- ADDED: terminal\_image: search the buffer with \<-find \<-find, \<-length  
and \<-contents address the terminal’s buffer as a flat sequence  
of characters, and -\>selection and -\>scroll\_to take an index in  
that same space, so a hit can be highlighted and brought into view.  
\<-find follows text\_buffer\<-find in its arguments, its defaults and  
in failing rather than raising when there is no match.

- ADDED: epilog/1: option background(Colour).

- ADDED: epilog/1: option goal\_split(Goal) to determine the goal to  
run in a new splitted terminal.

- MODIFIED: Class `terminal_image`: first try to process Shift-Ctrl-Key  
or Gui-Key as accelerator

- TEST: terminal: wait for the shell of shell/1 to be reading  
start\_interactive\_shell/1 slept a second and hoped; it now waits for  
the shell’s prompt. What is typed next then reaches a shell that  
is reading, and ^D in particular is no longer lost: on an empty line  
it is end of input to the line discipline, which hands it to whoever  
reads next as a zero-length read. A shell that has not put its own  
line editor on the terminal yet is not reading, and by the time it  
does the terminal is in raw mode, where the ^D the line discipline  
already consumed cannot come back.

---

<div class="post-metadata">

**Author:** ![z5h](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/z5h/32/5445_2.png) [@z5h](https://swi-prolog.discourse.group/u/z5h)\
**Post date:** [August 30, 2026, 3:17pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803/2 "2026-08-30T15:17:24Z")

</div>

Hi Jan. I reported the atom-GC bug, and I’m happy to report that 10.1.14 runs my code with no issues. (8 cores, as many threads, 100s of long-lived engines accessed from multiple threads, tabling, workloads lasting 15-20 minutes). As always, thank you for your attention and quick responses to issues and bugs.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [August 31, 2026, 10:25pm UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803/3 "2026-08-31T22:25:58Z")

</div>

Great! Some predicates are failing for local text help but work if Pred/N notation is used:

```prolog
69 ?- help(broadcast/1).

true.

70 ?- help(broadcast).

ERROR: http_handler_id `manual_file' does not exist

ERROR: In:

ERROR: [74] throw(error(existence_error(http_handler_id,manual_file),_7032))

ERROR: [72] http_dispatch:http_location_by_id(manual_file,-,_7072) at /tmp/swipl-devel/b.native/home/library/ext/http/http/http_dispatch.pl:677

ERROR: [70] http_dispatch:http_link_to_id(manual_file,[],_7106) at /tmp/swipl-devel/b.native/home/library/ext/http/http/http_dispatch.pl:797

ERROR: [69] pldoc_man:dom_element(img,[src='broadcast.png'],[],'/tmp/swipl-devel/b.native/man/Manual/broadcast.html',[no_manual(fail),...|...],_7146,_7148) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:886

ERROR: [67] pldoc_man:dom_list('<garbage_collected>','/tmp/swipl-devel/b.native/man/Manual/broadcast.html',[no_manual(fail),...|...],'<garbage_collected>',_7214) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:834

ERROR: [66] pldoc_man:dom_element(div,'<garbage_collected>','<garbage_collected>','/tmp/swipl-devel/b.native/man/Manual/broadcast.html','<garbage_collected>','<garbage_collected>',_7272) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:909

ERROR: [64] pldoc_man:dom_list('<garbage_collected>','/tmp/swipl-devel/b.native/man/Manual/broadcast.html',[no_manual(fail),...|...],'<garbage_collected>',_7310) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:834

ERROR: [53] pldoc_man:dom_list('<garbage_collected>','/tmp/swipl-devel/b.native/man/Manual/broadcast.html',[no_manual(fail),...|...],'<garbage_collected>',_7364) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:834

ERROR: [49] pldoc_man:dom_list('<garbage_collected>','/tmp/swipl-devel/b.native/man/Manual/broadcast.html',[no_manual(fail),...|...],'<garbage_collected>',_7418) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:834

ERROR: [47] pldoc_man:man_matches_nt('<garbage_collected>',section(2,'A.5','sec:broadcast','/tmp/swipl-devel/b.native/man/Manual/broadcast.html'),'<garbage_collected>','<garbage_collected>',_7472) at /tmp/swipl-devel/b.native/home/library/ext/pldoc/pldoc/doc_man.pl:762

ERROR: [44] prolog_help:man_pages('<garbage_collected>',[no_manual(fail),...|...],[mailbox(head,...),...|...],_7518) at /tmp/swipl-devel/b.native/home/library/help.pl:230

ERROR: [43] html_write:do_expand('<garbage_collected>',prolog_help,'<garbage_collected>','<garbage_collected>') at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:426

ERROR: [42] html_write:html_expand(\man_pages(...,...),prolog_help,[mailbox(head,...),...|...],_7624) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:405

ERROR: [39] html_write:do_expand('<garbage_collected>',prolog_help,'<garbage_collected>',_7688) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:463

ERROR: [38] html_write:html_expand(dl(\ ...),prolog_help,[nl(2),<|...],_7724) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:405

ERROR: [37] html_write:qhtml('<garbage_collected>',prolog_help,'<garbage_collected>',_7784) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:394

ERROR: [34] html_write:do_expand('<garbage_collected>',prolog_help,'<garbage_collected>',_7820) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:463

ERROR: [33] html_write:html_expand(body([...|...]),prolog_help,[nl(1),<|...],_7856) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:405

ERROR: [32] html_write:qhtml('<garbage_collected>',prolog_help,'<garbage_collected>',_7918) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:394

ERROR: [29] html_write:do_expand('<garbage_collected>',prolog_help,'<garbage_collected>',_7954) at /tmp/swipl-devel/b.native/home/library/ext/http/http/html_write.pl:463

ERROR: 

ERROR: Note: some frames are missing due to last-call optimization.

ERROR: Re-run your program in debug mode (:- debug.) to get more detail.

```

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [September 1, 2026, 9:37am UTC](https://swi-prolog.discourse.group/t/ann-swi-prolog-10-1-14/9803/4 "2026-09-01T09:37:17Z")

</div>

> [@swi](#):
>
> ```prolog
> 70 ?- help(broadcast).
> 
> ERROR: http_handler_id `manual_file' does not exist
> 
> ```

Thanks. The page contains an image and that was not handled correctly. Now images are ignored in the terminal version. The rest of the page shows fine.
