Branch: development (switch to
stable),
SWI-Prolog Changelog from version 9.3.31 to 10.1.10
[Jun 25 2026]
- ENHANCED: call_with_inference_limit/2: avoid pushing a bignum for
"no limit" This fixes this predicate for systems compiled without
bignum support (rarely used these days) and reduces stack usage on
systems with bignum support.
- CLEANUP: static int -> bool for is_or/del_attr/has_attributes_after
Three attvar helpers were declared static int but their bodies use
only succeed/fail/return true/return false:
- CLEANUP: static int -> bool/boolex_t for type-test and visited helpers
Type-test helpers used by the compiler and the cycle detector were
declared `static int` but only ever return true or false:
- CLEANUP: type local variables holding bool returns as bool, not int
Several local rc/rval variables hold the result of a function that
returns bool (PL_unify_*, PL_is_*, PL_error) but are declared int.
This is a pure cleanup — no behaviour change. Updated sites and
the related helpers:
- CLEANUP: type local variables holding boolex_t as boolex_t, not int
Several functions return boolex_t (true/false plus negative *_OVERFLOW
codes) but callers stored the result in `int rc`. No data loss
occurred because both happen to be the same width, but the type was
misleading and a future change to the boolex_t representation could
silently break callers that switch on specific overflow codes.
[Jun 24 2026]
- CLEANUP: consistent bool/boolex_t typing for ensure*Space and put_*
family User-visible fixes (only triggered on no-bignum builds,
i.e. neither GMP nor libbf):
- FIXED: PL_unify_int64() and related functions may signal false stack
overflow These functions called
put_int64() without allowing GC,
but not handling the overflow properly.
[Jun 23 2026]
- FIXED: prolog_close_source/1: close on hooked (xref) open. The xref
hooks do not refine closing and the standard close should happen.
- BUILD: Do not try to install these .qlf files
- DOC: Merge all write predicates into one description.
[Jun 22 2026]
- FIXED: tidg/1: meta predicate declaration.
[Jun 21 2026]
- BUILD: Added cmake option
-DCHANGELOG=ON
- BUILD: Make SWI-Prolog runs during build halt the build system on
error messages
[Jun 20 2026]
[Jun 19 2026]
- DOC: add SECURITY, PRIVACY and CODE_SIGNING policies; rename CoC [no
ci] Prepares the repository for the SignPath Foundation code-signing
application: add a security-reporting address, a privacy statement,
and a code-signing policy describing the planned signed Windows
release flow. Also rename Code-of-Conduct.md to CODE_OF_CONDUCT.md
so GitHub's Community Standards detect it.
[Jun 18 2026]
- CI: extract only the Windows installer from the build container docker
cp on newer engines refuses to write symlinks whose target escapes the
destination, which made the whole-build.win64 copy fail on a relative
symlink under home/app/. Switch to the tar-stream form of docker cp
and extract only the swipl-*-*.x64.exe.
- FIXED: pkg_doc(DEPENDS ...) now applies to .tex generation, not just
html/pdf The DEPENDS list passed to
pkg_doc() was only forwarded to
the per-package .html / .pdf rules. The pldoc / doc2tex / txt2tex
commands that produce the .tex files saw no such dependency, so
e.g. packages/cql/cqldoc.tex could be built before chr was installed
in the build home, and `library('cql/cql')' would fail to load
library(chr/chr_translate) at .tex-generation time.
- CI: log in to GHCR before pulling the MinGW build
image Required so the release workflow can pull a private
ghcr.io/swi-prolog/swipl-mingw-build when org policy disallows public
packages. Harmless once/if the image is made public.
- CI: add Windows installer release workflow Triggered on V* tags
(and manually via workflow_dispatch), this job pulls the pre-built
MinGW cross-compile image from GHCR, clones and builds swipl inside
the container via the image's --win64-from-git entrypoint mode,
extracts the NSIS installer with docker cp, and attaches it to the
GitHub Release for the tag.
[Jun 16 2026]
- FIXED: Include <poll.h> based on HAVE_POLL instead of HAVE_POLL_H
The streams/I/O code includes <poll.h> guarded by HAVE_POLL_H,
but decides whether to actually call
poll() and use `struct pollfd`
based on HAVE_POLL. These come from two independent configure probes
(check_include_file vs check_function_exists). When they disagree --
e.g. the poll() function is detected (HAVE_POLL) but the header probe
for poll.h fails for an unrelated reason -- <poll.h> is omitted while
poll() is still compiled, producing:
- BUILD: serialise Wine swipl.exe runs via a Ninja job pool When
cross-building for Windows on Linux, every swipl.exe step (qlf
compiles, library indices, man index) runs under Wine through a
single wineserver. Parallel
ninja over-saturates wineserver,
occasionally deadlocking client requests and hanging the build.
Define a swipl_run=1 Ninja job pool on the cross-build path and apply
it to the custom commands that invoke swipl; native builds expand
the JOB_POOL keyword to nothing and are unaffected.
[Jun 15 2026]
- ENHANCED: listing/2 using
source(true): show source location as URL.
- ENHANCED: Windows installer optionally associates .pl with
swipl-win.exe Adds an "Open .pl files with SWI-Prolog" checkbox to
the installer's Install Options page (alongside the desktop icon
option). When ticked, registers the SWIProlog.SourceFile ProgID so
.pl files double-click to open in swipl-win.exe. Uninstall removes
the association only if it still points at our ProgID.
[Jun 14 2026]
- MODIFIED: current_input/1 and current_output/1 diagnostics According
the the ISO standard, these predicates shall raise a domain error
for stream aliases and shall fail if the argument is a closed stream.
- FIXED: Ensure shifting stacks properly resizes the local stack.
Due to a typo, the system could get into a state with many very small
local stacks enlargements, almost grinding to a halt.
[Jun 7 2026]
- ENHANCED: doc2tex --xpce recognises Class->Sel arrow refs Add a CLI
flag that turns on three extra recogniser clauses for
Class->Sel,
Class<-Sel and Class<->Sel in plain prose; they emit
\classsend{C}{S} / \classget{C}{S} / \classboth{C}{S}
respectively. Selectors may start with _ for private slots. The
- (instance variable) and . (class variable) shapes are
left alone because they collide with ordinary hyphenation and
end-of-sentence punctuation in English prose; callers wanting those
links should write the macro explicitly.
[May 30 2026]
- TEST: Disable tcmalloc when using ASAN. Can lead to conflicts
- FIXED: #1497 libbf mpz_import: stack overread when leading bytes
are zero The byte-count for the import loop was captured before
the leading-zero strip, so when OP began with zero bytes the loop
read that many bytes past the end of the input buffer. Triggered by
seed_from_dev() seeding the random state from /dev/urandom in libbf
builds.
[May 29 2026]
- MODIFIED: macOS: name the installer swipl-<version>-1.<arch>.pkg Adds
the `-1' package revision before the architecture suffix so the .pkg
matches the Windows swipl-<version>-1.x64.exe naming convention.
[May 28 2026]
- DOC: macOS .pkg installer build, signing, notarization and cert
renewal Add doc/MacOSXInstaller.md: an end-to-end, reproducible
guide to building the signed and notarized macOS .pkg --- one-time
keychain and Developer-ID/notarytool setup, the build invocation,
result verification, certificate renewal, and the failure modes hit
on the Apple-Silicon + macOS 26 host.
- ADDED: macOS: `ninja pkg' builds a signed, notarized split-layout .pkg
installer Add a `pkg' target producing a single Developer-ID-signed
and Apple-notarized .pkg that delivers swipl-win.app to /Applications
and swipl.framework to /Library/Frameworks.
- ADDED: macOS: swipl.framework and the split swipl-win.app bundle
layout Package the macOS runtime as a standalone swipl.framework and
arrange the split bundle layout the installer ships: swipl-win.app
in /Applications, swipl.framework in /Library/Frameworks.
[May 25 2026]
- FIXED: Reset cached JIT index decisions when the supervisor changes.
The per-argument
assessed flags, jiti_tried, pindex_verified,
fixed_indexes and unindexed memoize index decisions for the current
clause shape. A supervisor change is the signal that this shape has
changed enough that those verdicts may be stale. Without a reset,
a "not indexable" verdict made on a transient state (e.g., while an
autoload triggered through trapUndefined() re-enters Prolog) could
stick and disable JIT indexing for the eventual stable clause set.
[May 18 2026]
- MODIFIED: PL_predicate() now takes UTF-8 strings as argument.
- DOC: Modernized calc.c, cacl.pl example. Replaceing PR 1493
[May 17 2026]
- DOC: Unicode bracket-pair atoms are consistent with {} Document
that an empty Unicode bracket pair (optionally layout-only) reads
as the two-character atom, that atom before '(' is a functor, and
'<open><close>'(X) writes as <open>X<close> with the bare atom
unquoted, all governed by the brace_terms write option.
- TEST: Unicode bracket-pair atoms (read/write consistency with {})
Covers empty/layout pair reading as the atom, '<o><c>'(X) as a
compound, unquoted bare-atom output, write_canonical functor form,
round-tripping and that {} is unchanged.
- ENHANCED: Make Unicode bracket-pair atoms consistent with {} A matching
Unicode bracket pair (Ps/Pe) now behaves like {}: an empty pair,
optionally with layout in between, reads as the atom '<open><close>'
(and as a functor when followed by '('), while '<open><close>'(X)
writes as <open>X<close> and the bare atom is written unquoted.
E.g. ⟨⟩ reads as '⟨⟩', ⟨⟩(x) as '⟨⟩'(x), and
'⟨⟩'(hello) writes as ⟨hello⟩.
[May 15 2026]
- FIXED: Avoid crash trying to destroy a running engine from another
thread.
[May 13 2026]
- ADDED: code_type/2 and char_type/2 property pattern_syntax Exposes
Unicode UAX #31 Pattern_Syntax membership through the standard ctype
dispatch. Useful for libraries that want to align tokenisation
or quoting with the immutable syntax set, and for inspecting which
code points the write_term/2 pattern_syntax_solo option will treat
as stable.
- ADDED: write_term/2 option pattern_syntax_solo, used by
write_canonical/1 A new boolean write_term/2 option quotes
single-character atoms whose code point is not in the immutable UAX
#31 Pattern_Syntax set, so atoms like '€', '·', '🎉' round-trip
safely across Unicode versions instead of relying on classifications
that may shift in future releases. write_canonical/1 enables the
option by default; plain write/1 and writeq/1 are unchanged.
- FIXED: compare/3 on wide atoms must order by code point, not code
unit On platforms with 16-bit wchar_t (Windows), a supplementary
character is stored as a UTF-16 surrogate pair whose lead unit lives
in U+D800..U+DBFF.
compareUCSAtom() compared raw wchar_t values, so
a non-BMP atom like '\U0001D11E' wrongly ordered below BMP atoms in
U+DC00..U+FFFF — e.g. compare(C, '\U0001D11E', '豈') (with U+F900)
returned < on Windows where Linux (32-bit wchar_t) gave the correct
>.
- FIXED: Reject surrogate code points in UTF-8 and UTF-16 stream
decoders. A well-formed UTF-8 sequence never encodes a surrogate
(RFC 3629), and a well-formed UTF-16 sequence never produces a
lone trail surrogate. Both decoders previously let such malformed
input through, so a file containing the bytes ED A0 80 read with
encoding(utf8) would deliver U+D800 as a code point — leaking an
invalid Unicode value into atoms and strings even though the new
PL_get_char / Sputcode checks reject surrogates everywhere else.
- FIXED: Reject UTF-16 surrogate code points at every Prolog API surface.
Extends the recent fix to atom_codes/2 to put_code/1,2, put_char/1,2,
put/1,2 and the format/2,3 ~c directive: PL_get_char() and the ~c
argument check now use VALID_CODE_POINT(), so a lone surrogate is
rejected with
type_error(character_code, Code) (or format_argument_type
for ~c) before it can reach the stream layer. As defence in depth,
Sputcode() in pl-stream.c now calls reperror() on a surrogate before
encoding-specific handling, preventing foreign callers from emitting
invalid UTF-8 or raw-wchar bytes via Sputcode(0xD800, s).
- FIXED: Do not allow surrogate pair code points in atom_codes/2.
[May 12 2026]
- FIXED: Solo characters do not needs quotes
- MODIFIED: Code walker not to track below call/1. This allows using
call(Goal) in places that are false possitives for the detection of
undefined predicates.
[May 11 2026]
- FIXED: Confusable detection when using zero-arity compounds.
- ENHANCED: char_type/2 and code_type/2 accept prolog_solo The kernel has
a
f_is_prolog_solo helper (and a corresponding SOLO category in the
syntax map) but did not expose it through the char_type/2 catalogue.
Register prolog_solo alongside prolog_symbol, prolog_atom_start
and friends in src/os/pl-ctype.c, with a new atom in src/ATOMS,
and document the class in the char_type/2 reference (man/builtin.plx).
- ENHANCED: library(check) gets list_confusable_identifiers/{0,1}
A new consistency check that walks every clause in the modules in
module_class (default [user]) and warns on atoms whose written
form is a UTS #39 spoof:
- ENHANCED: '\''$needs_quotes'\''/1 + fix unquoted_atom for
UCS atoms Exposes the kernel's own quote decision as a semidet
'\''$needs_quotes'\''/1 so library code (notably library(check)'s
confusable-identifier linter) can ask "would writeq quote this
atom?" without re-parsing the name.
[May 10 2026]
- SUBMODULES: Bump pldoc for help/1 UTF-8 fix Co-Authored-By: Claude
Opus 4.7 (1M context) <noreply@anthropic.com>
- SUBMODULES: Bump pointers for documentation rework 34 submodules
carry the .doc -> .plx LaTeX-source rename; ltx2htm additionally
carries the UTF-8 awareness (PL_unify_chars REP_UTF8 on input,
PL_get_chars REP_UTF8 + PL_UTF8_STRING on output, charset meta tag
in HTML). Companion to the master-side switch to lualatex and the
Unicode-Prolog-source examples in overview.plx.
- RENAME: SWI manual sources .doc -> .plx The '.doc' extension predates
Microsoft Word's appropriation of it and confuses file managers,
editors (no LaTeX syntax highlighting), and new contributors. Rename
to '.plx' (Prolog LaTeX) — single extension, no collision inside
SWI-Prolog, .gitattributes maps it to TeX for editor support and
diff hunks.
- DOC: Use literal Unicode in the Unicode Prolog source section Drop
the {...} urldef wrappers around literal characters described in
the section (², ³, ¹, ⁰..⁹, ₀..₉, Dž, «hello, world»,
«»). Add a code block at the end of the section with concrete,
runnable ?- queries covering: superscript variables, Devanagari Nd
via atom_number/2, Unicode symbols as solo atoms, bracket pairs Ps/Pe,
quote pairs Pi/Pf.
- DOC: overview.doc: use literal Unicode characters Smoke test for the
new UTF-8 pipeline: drop the {...} urldef wrapping around ≤, €,
and ·. Both lualatex and ltx2htm now read these bytes directly. The
rendered output (PDF and HTML) is unchanged.
- DOC: Move lualatex font setup from main.doc into pl.sty ltx2htm
parses main.doc as TeX and emits warnings for unknown commands like
\ifdefined and \directlua. .sty files are not parsed as TeX (they
are only read for urldef extraction), so the conditional becomes
invisible. Also override fontspec's \strong via providecommand +
renewcommand so pl.sty's bold-strong definition wins under lualatex.
- DOC: Build PDF manual with lualatex instead of pdflatex Switches the
PDF documentation toolchain to lualatex. The engine swap is the first
step of a wider effort to allow literal Unicode in .doc and Markdown
sources (currently routed through urldef in pl.sty).
- WASM: Included
library(unicode)
[May 7 2026]
[May 8 2026]
- DOC: PIP §4.11 — describe the four-mode unicode_atoms policy
as shipped The §4.11 "Pluggable Unicode normalisation" body
still described the old design — a Boolean read_term/2 option
normalize(Bool) backed by a Boolean Prolog flag unicode_normalize
— neither of which exist in the current implementation. What
actually shipped is the four-mode unicode_atoms family (accept /
nfc / error / reject), surfaced through:
- ENHANCED: code_type/2 prolog_layout + prolog_end_of_line; rebind
end_of_line The Pattern_White_Space set used by the Prolog reader for
layout had no user-facing accessor in code_type/2 / char_type/2. The
existing end_of_line was extended in the line-termination commit
to the seven Pattern_White_Space line-terminator-like code points;
that broadened the ISO Prolog meaning silently.
[May 7 2026]
- DOC: stray-character policy; quoted material accepts any Unicode scalar
After Stage 4's cat-direct dispatch refactor, the parser's default
arm of the c >= 0x80 switch raises
syntax_error(illegal_character)
for every U_CAT_OTHER code point. That is broader than what
man/overview.doc still claimed ("Control and unassigned (C*) characters
produce a syntax error ... outside quoted atoms/strings and outside
comments"), and narrower than what the section claimed about quoted
material (it was silent on what is allowed there).
- DOC: lock atom_number/2 family Unicode policy with tests + manual
prose Empirical audit of
str_number() in pl-read.c against the policy
documented in plan A's M2 doc fix confirms the kernel already enforces
both rules:
- DOC: PIP §4.4.1 — line termination on Pattern_White_Space
line-enders Add a subsection to White space recording the seven
line-terminator-like Pattern_White_Space code points (LF, VT,
FF, CR, NEL, LS, PS) and the three places they apply: %-comment
termination, source-position line counter, and backslash-newline
continuation in quoted strings. Calls out that the remaining four
Pattern_White_Space members (SPACE, LRM, RLM) are layout but not
line-enders. Cross-references
code_type(C, end_of_line) / char_type(C,
end_of_line) for user-code access to the same set.
- DOC: document the seven line-terminator-like Pattern_White_Space
chars Two manual updates to match the implementation:
- ENHANCED: terminate %-comments on every Pattern_White_Space line-ender
The %-comment scanner, the line-counter, the block-comment LF
preservation, the \\<newline> continuation in raw_read_quoted, the
ensure_space whitespace-collapsing macro, and the escape_char \\<EOL>*
skip-blanks site all checked
c == '\n' (LF only). Three of the seven
Pattern_White_Space line-terminator-like code points were silently
ignored: NEL (U+0085), LS (U+2028), PS (U+2029). ASCII CR / VT /
FF were also missed by the comment scanner.
- DOC: PIP unicode.md — paired delimiters and PL_wcwidth vs POSIX
Sync the PIP draft with the design landed on this branch.
- ENHANCED: dispatch tokeniser directly on u_category; drop uflagsW The
uflags_map byte already carried the u_category enum, but every read of
it went through cat_to_flags[] back to the legacy U_* bitmask, then a
Pl*W macro tested specific bits. The cat_to_flags indirection forced
PlSoloW to match four distinct categories (U_CAT_SOLO, U_CAT_BRACKET,
U_CAT_QUOTE, U_CAT_ID_CONTINUE_SOLO), which is why case_solo had a
post-hoc pl_pair_lookup demux to re-separate brackets from quotes
from solo atoms.
- TYPE: pl_pair_lookup is_open is bool; clean up generator function
layout Two cleanups:
- ENHANCED: extend code_type/2
paren(Close) and add a matching
quote(Close) paren(Close) used to know only the three ASCII bracket
pairs (), {} and []; quote(Close) didn't exist at all. Both now back
onto the same pl_pair_table that drives the parser, so they cover
the full Unicode Ps/Pe and Pi/Pf sets out of the box.
- ENHANCED: read Unicode quote pairs (Pi/Pf) as literal strings Quote
pairs were previously parsed like brackets — content was interpreted
as a Prolog term and wrapped in '<open><close>'/1. That is the wrong
shape for quotation marks, where the contained text is naturally
literal (cf. ASCII '...', "...",
...).
- ENHANCED: drop mk_wcwidth.c; PL_wcwidth replaces it everywhere After
Stage 5 PL_wcwidth() reads its values directly from the per-code-point
width slot in uflags_map, leaving mk_wcwidth.c as a thin wrapper that
just forwarded to PL_wcwidth. With no remaining internal nor submodule
callers (the libedit and xpce typedefs of uchar_t are local to those
packages), the wrapper is pure dead weight.
- DOC: paired delimiters, wcwidth source, prolog_syntax_map.pl header
(Stage 7) Three doc updates that close the loop on the Unicode-syntax
refactor:
- ENHANCED: parse Unicode bracket pairs as '<open><close>'/1 compounds
Lift the existing {Term} ⇒ '{}'(Term) reader path to a generic
paired-delimiter routine and wire every Unicode bracket pair through
it.
- ENHANCED: pack uflags_map into 4-bit category enum + 2-bit wcwidth
slot The per-code-point byte in uflags_map was a bag of 8 disjoint U_*
flag bits, almost full (7 of 8 used). Repack the same byte:
- DOC: NBSP is no longer whitespace; document Pattern_White_Space-only
layout The previous text claimed SWI-Prolog kept treating U+00A0 as
whitespace for backward compatibility with ISO Latin-1. That was true
under the legacy 256-entry _PL_char_types[] table; with the parser
cutoff moved to < 0x80 the Unicode flag table is the single source
of truth, and NBSP (which is not in Pattern_White_Space) raises a
stray-character syntax error outside quoted material.
- ENHANCED: classify code points >= 0x80 via the Unicode flag table The
legacy ISO Latin-1 _PL_char_types[] used to extend to 256 entries,
giving an SWI-specific opinion about each byte 0x80..0xff. Those
entries duplicated and occasionally disagreed with the Unicode flag
table (uflags_map[0]) that already covers the same code points
correctly per UAX #31. Two parallel mechanisms in the 0x80..0xff
range invited drift.
- DOC: align manual with implemented Unicode source syntax Two small
documentation updates that bring man/ and src/Unicode/ in sync with
the parser's actual behaviour:
[May 6 2026]
[May 5 2026]
- UNICODE: Updated unicode_block/3 to Unicode 17.0
- FIXED: Windows init_locale also sets LC_CTYPE to UTF-8 Forcing
LD->encoding to ENC_UTF8 unconditionally on Windows in the prior commit
left the C runtime's LC_CTYPE locale at its default ("C" locale)
— and so mbrtowc / wcrtomb were ASCII-only. Any UTF-8 byte above
0x7F flowing through a path that uses mbrtowc to canonicalise text
(PL_canonicalise_text in pl-text.c) returned EILSEQ, surfacing as a
"Syntax error: illegal_multibyte_sequence" the moment a user typed
an emoji or other non-ASCII char in the libedit prompt.
[May 4 2026]
- ENHANCED: default encoding to UTF-8 on Windows The system locale
on Windows usually reports a legacy codepage (Windows-1252 or
similar), making the default Prolog flag
encoding ANSI/Latin-1.
This caused UTF-8 source files to be read as their byte-wise Latin-1
interpretation. UTF-8 is the de-facto encoding for source files and
the Windows C runtime's locale-based wide-character functions are
weaker than the Unicode tables Prolog uses internally, so always use
UTF-8 as the default on Windows.
[May 3 2026]
- TYPE: PL_is_id_start, PL_is_id_continue, PL_is_uppercase,
PL_is_decimal, PL_is_layout return bool Pure predicates; bool conveys
the contract better than int.
- ADDED: PL_is_id_start, PL_is_id_continue, PL_is_uppercase,
PL_is_decimal, PL_is_layout Thin shims around the
existing
uflagsW() table (src/pl-umap.c, generated from
src/Unicode/derived_core_properties.pl) so foreign extensions and
embedded toolkits — notably xpce — classify code points exactly
as SWI-Prolog does, without needing the locale-dependent POSIX iswX()
or inventing their own tables. Documented in man/foreign.doc.
- ENHANCED: Use
mk_wcwidth() in the kernel for locale-independent
width Switch every kernel caller (pl-read, pl-write, pl-fli, pl-fmt,
pl-stream, pl-ctype) and PL_wcwidth() to the bundled mk_wcwidth()
instead of the system wcwidth(3), which under C/POSIX returns -1 for
non-ASCII on glibc. Always link mk_wcwidth.c (drop the HAVE_WCWIDTH
guard) and add the modern emoji wide ranges (Kana Supplement,
Mahjong/Domino, Misc Symbols & Pictographs, Symbols & Pictographs
Ext-A) so column counts match what xpce already returns.
- FIXED: unload_file/1: clear isfile so use_module/1 reloads
unloadFile() left sf->isfile set, so a subsequent use_module/1 saw
the file as already loaded and skipped its directives — notably :-
use_foreign_library/1. Reset isfile, move garbage_collect_clauses
to Prolog (unload_file/1) and call '$clear_source_admin'/1 there.
- DOC: atom_normalize_hook Prolog flag Add a concise entry for the new
atom_normalize_hook flag and note in the unicode_atoms entry that
mode
error falls back to the wcwidth-based check when the hook is
not registered, which can over-reject scripts (e.g. Thai) that use
combining marks in NFC.
- TEST: syntax_unicode_atoms: use atom_normalize_hook and term_string
Replace
current_module(unicode) hook-state probes with the new
atom_normalize_hook Prolog flag (reliable across rerun). Switch the
suite to term_string/3 with explicit string literals throughout,
add a thai_hello_world/1 helper to demonstrate the wcwidth-fallback
false-positive on NFC Thai text and verify that the precise utf8proc
check accepts it.
- ADDED: foreign_library_property/2 to query foreign library properties
[May 2 2026]
- DOC: PL_wcwidth() in foreign.doc Co-Authored-By: Claude Opus 4.7
(1M context) <noreply@anthropic.com>
- ADDED: PL_wcwidth() — locale-portable display-column width for a
code point Add PL_wcwidth(int) to libswipl so foreign extensions and
embedded GUI toolkits can ask for the column width of a Unicode code
point with the same answer as the rest of SWI-Prolog, regardless of
the process LC_CTYPE or platform. On Unix/macOS it forwards to system
wcwidth(3); on Windows it goes through Markus Kuhn's mk_wcwidth()
table.
- ENHANCED: Fold error and auto-load into atom_to_unicode_atoms_ex
Rename atom_to_unicode_atoms to atom_to_unicode_atoms_ex (the _ex
suffix marks helpers that raise Prolog exceptions on failure) and
absorb the boilerplate every caller had to write:
[May 1 2026]
- ENHANCED: Cache hook-load attempt to avoid repeated
retries
ensure_unicode_normalize_hook(false) was retrying
'$install_unicode_normalize_hook'/0 on every call once the load had
failed. Track the attempt in GD->atoms.normalize_hook_load_attempted
so subsequent calls fall through immediately. PL_cleanup re-zeroes
GD on next initialisation, so the cache resets across an embedded
Prolog teardown/restart cycle (a static would not).
- ENHANCED: Auto-load library(unicode) for
unicode_atoms(nfc) at
every entry point The Prolog flag's active setter has auto-loaded
library(unicode) for modes nfc/error since the original landing,
but read_term/2,3 and read_clause/2,3 with unicode_atoms(nfc) were
left to error with existence_error(hook, unicode_normalize) when
the library was not already loaded. set_stream/2 and open/4 had the
auto-load logic duplicated inline.
- ENHANCED: Loosen
unicode_atoms(error) and centralise the value docs
Per PIP review:
- ENHANCED: Multi-valued unicode_atoms policy and Trojan-source
bidi reject Replace the boolean unicode_normalize flag and the
normalize(Bool) read_term option with a single multi-valued
unicode_atoms policy that follows the same three-tier hierarchy
as encoding (Prolog flag -> stream property -> per-call option),
and unconditionally reject Unicode bidi-override / isolate code
points (U+202A..U+202E and U+2066..U+2069) in source tokens, quoted
strings and comments as a defence against the Trojan-source attack
(CVE-2021-42574).
[Apr 30 2026]
- ENHANCED: Pluggable Unicode normalisation in reader and writer Add
a kernel-level callback for Unicode normalisation, and use it to
give read_term/2,3 and read_clause/2,3 a
normalize(Bool) option
that NFC-normalises the text of unquoted atoms before interning.
Quoted atoms and string literals are byte-faithful and not touched.
Also force-quote atoms holding combining marks under writeq's
quoted(true), which makes denormalised text visible and is independent
of the normalisation library (it uses wcwidth only).
- DOC: Route non-ASCII Unicode in manual prose through urldefs Add a
block of \urldef{\Sname}\satom{<char>} entries to man/pl.sty for the
super-/subscript digits and a handful of math and typographic symbols
used in §sec:unicodesyntax (≤, «, €, ·, Dž). With these in
place, man/doc2tex.pl auto-translates the literal {<char>} forms in
overview.doc to {\Sname} in the generated .tex, so the .tex stays
ASCII-only and no longer triggers ltx2htm's non-ASCII-byte warnings.
- DOC: Update Unicode syntax section Rewrite man/overview.doc
§sec:unicodesyntax to reflect the new rules: XID_Start/XID_Continue
identifiers, super- and subscript digits as identifier-continue
extension, Pattern_White_Space layout set, all-S?/P? as solo
(with a note that this is a deliberate break from the previous
glueing behaviour), Lu-only uppercase (so Lt letters now start
atoms), and a hedge that NBSP is still treated as whitespace by the
legacy ISO Latin-1 table. Add a flag entry for the new read-only
unicode_syntax_version and fix a "curently" typo in max_char_code.
- TEST: Add Unicode syntax tests and a demo source file
tests/core/test_syntax_unicode.pl exercises the new XID-based
identifier rules, super- and subscript continuation, Pattern_White_
Space layout (LRM), all-S?/P? as solo (≤, ≤≤, «, €), Lt
starting an atom (Dž), mixed-script number rejection, same-script
Devanagari digits, and the new unicode_syntax_version flag.
Auto-discovered by tests/test.pl; runs as part of swipl:core.
- ENHANCED: Wire subscript digits and add unicode_syntax_version
flag Wire subscript digits (₀..₉) as XID_Continue extension
in prolog_syntax_map.pl, alongside the existing superscripts, and
regenerate pl-umap.c. Read the Unicode version from the header
of DerivedCoreProperties.txt and emit a tiny pl-umap-version.h
header with UNICODE_SYNTAX_VERSION. Register a read-only Prolog
flag
unicode_syntax_version in pl-prologflag.c, distinct from
unicode:unicode_version/1 (which reports the linked utf8proc's view
of Unicode and may differ from the kernel classifier's).
- DOC: Flag
max_code_point is 0x10ffff on all platforns for a while.
[Apr 29 2026]
- MODIFIED: Unicode interpretation and updated to Unicode 17 (was 14).
[Apr 30 2026]
[Apr 23 2026]
- ADDED: el_get/2 and runtime bracketed_paste control el_get(Stream,
editor(?Editor)) reads the current libedit editor (
emacs / vi).
el_set/2 and el_get/2 grow a bracketed_paste(?Bool) property, and
editline.pl routes it through a new enable_bracketed_paste/1 helper
that skips (and unbinds) in vi mode.
[Apr 22 2026]
- CI: Added utf8proc as dependency
- ENHANCED: mkchangelog stops changelog entries at the first blank line
A blank line in a commit body now terminates that commit's changelog
entry. Subject + first body paragraph become the entry; deeper detail
stays visible in `git log` but is hidden from the generated changelog.
[Apr 21 2026]
- TEST: write_size/4 — max_width, max_height, Unicode combining,
wide chars New write_size unit in tests/core/test_write.pl covers:
- ADDED:
write_size(+Term, -Width, -Height, +Options) write_size/4
replaces the now-deprecated write_length/3. It returns both the
maximum line Width and the Height (line count) the term would occupy
when printed with write_term. Options max_width(+N) and max_height(+N)
cap the computation — the underlying Swrite_lss aborts as soon
as either threshold would be exceeded, bounding the runtime for
huge terms.
- CLEANUP: pl_write_term refactored to PRED_IMPL; foreign_t → bool
Convert pl_write_term2 / pl_write_term3 (and pl_print2) from the
legacy foreign_t/pl_* calling convention to PRED_IMPL, and change
pl_write_term3's signature to return bool. Also drop its entries
from the foreigns[] table in pl-ext.c now that they are registered
via PRED_DEF in pl-write.c.
- CLEANUP: bool return types for pl-text and pl-string APIs Convert
int → bool for PL_unify_text_range, PL_promote_text, PL_mb_text,
PL_canonicalise_text_ex, PL_concat_text, PL_save_text, PL_text_recode,
and the return path of several PRED_IMPL functions in pl-string.c.
Introduce get_text_t / cmp_t enums for the tri-valued get/compare
cases so the type tells the reader what to expect instead of relying
on int conventions.
- ENHANCED: Make format/2 position logic aware of Unicode column logic.
- ADDED: Unicode-aware Supdatepos() using
wcwidth() Supdatepos()
now counts double-width characters (CJK, emoji) as 2 columns and
combining marks as 0, via wcwidth(). On systems lacking a native
wcwidth() we fall back to the embedded mk_wcwidth.c from Markus Kuhn's
public-domain implementation; src/CMakeLists.txt adds it to SRC_CORE
when HAVE_WCWIDTH is false.
[Apr 20 2026]
- ADDED: code_type/2:
code_type(Code, width(W)) Provides an interface
to wcwidth().
- UNICODE: Fixed reading in
DerivedCoreProperties.txt for Unicode-17.0.
Required to update our tables to Unicode version 17.
[Apr 5 2026]
- FIXED: Missing declaation of listing/2 for option
source(+Boolean)
[Apr 2 2026]
- FIXED: #1483
<base>' numbers can be misread. A possible read
buffer reallocation can cause misreading the base and result in a
syntax error or wrong value.
- FIXED: WASM: Convert class and property names with Unicode.
[Apr 1 2026]
- CLEANUP: Remove sigaction configuration
[Mar 30 2026]
- FIXED: GC error If a non-deterministic foreign predicate triggers a
constraint wakeup.
[Mar 16 2026]
- FIXED: spy/1 to enable debug mode again
[Mar 14 2026]
- PORT: Fix cmake SDL3 import handling for non-standard configurations
(PGO)
[Mar 11 2026]
- ENHANCED: Messages to use DCG Name//Arity when applicable.
- FIXED: QLF compilation: preserve
non_terminal predicate_property/2.
- ADDED:
library(tableutil): toplevel utilities This library provides
toplevel utilities to dump tables, their relations and statistics.
- PORT: #1481 Removed RETSIGTYPE configuration The CMake config seems
broken for gentoo using C23. As there are no systems that use
int for signal handler return value, there is no need for this
configuration.
- FIXED: Make compile again for single threaded and WASM targets.
- CLEANUP: Prolog flag handling. Cleanup the implementation, mostly
by splitting too large functions. Clarified documentation with
respect to thread interaction. Added an option
local(true)
to create_prolog_flag/3 which create a flag only for the calling
thread. Clarified and fixed default behaviour, which is for
create_prolog_flag/3 to set the flag globally, i.e., make it
available with this value for any thread. This now updates both the
local and global flag table (before it updated only the global table).
[Mar 8 2026]
[Mar 6 2026]
[Mar 5 2026]
- ADDED: Assign threads the notion of a class. This is notably
intended to control debugging. Possibly this can be extended to
other features such as memory management policies, termination, etc.
Future versions may also allow for multiple classes. Related changes
[Mar 6 2026]
- ADDED: PL_current_prolog_flag(): type PL_BOOL
- MODIFIED: visible/1: default to include
cut_call This shows calls
to ! in the tracer.
- FIXED: thread_property/2:
system_thread_id on Linux Failed to
initialize this on systems with the getid() function (primarily Linux,
but possibly other platforms using glibc).
- FIXED: Make
updateAlerted() thread-safe Could lead to race conditions
when this function is called from multiple threads (usually the target
and some external thread).
[Mar 4 2026]
- ADDED: prolog:complete_input/4: enhanced CLI TAB completion - Complete
variables in the query using Emacs dabrev completion - Complete
in $Var for saved toplevel variables.
[Mar 1 2026]
- BUILD: Fixed PGO compilation for non-MSVC
- TEST: empty file position tests.
[Feb 27 2026]
- CMAKE: Add MSVC support for Profile-Guided Optimization
[Mar 1 2026]
[Feb 28 2026]
- FIXED: #1478 LibBF
mpz_import() emulation for leading zero-bytes.
Lead to undefined behaviour in random number generation.
- UBAN: #1478 Avoid undefined arithmetic on NULL pointer (benign).
[Feb 24 2026]
[Feb 23 2026]
- PPA: Fixup generating PPAs for both SDL and non-SDL versions.
[Feb 21 2026]
- PORT: Exclude jvm.dll from CPack runtime dependencies
[Feb 19 2026]
- ENHANCED: Command line (tab) completion - Tag directories with a
trailing / - Do file name completion on
[prefix<tab> - Do
library completion on library(prefix<tab>.
[Feb 17 2026]
- ENHANCED: error/warning messages for swipl-ld
[Feb 18 2026]
- BUILD: We no longer need `cmake -E env ...` to run Prolog This seems
to cause a hang in the Windows build xpce steps. Quite unclear why.
- FIXED: ansi_get_color/2: not supported on Windows.
- PPA: Added Ubuntu 26.04 (Resolute Raccoon)
[Feb 17 2026]
[Feb 18 2026]
[Feb 17 2026]
- TEST: Fixed Debug build test on Windows to avoid C stack overflow.
Based on PR by Eric Tauber. This replacement builds on the new Prolog
flag
build_type and rewrites the test suite to use PlUnit.
- ADDED: Prolog flag
build_type, representing the CMake build type
used.
- FIXED: library(main): make spy options default to the user module.
[Feb 15 2026]
- BUILD: added comments to scripts/configure
- BUILD: added comments to CMakeLists.txt for protobufs test
[Jan 23 2026]
- DOC: clarified details of heap allocation
[Feb 16 2026]
- PORT: Minimize C stack on MSVC debug builds.
[Feb 15 2026]
- TEST: Skip test_thread_exit if alert signal == 0
- PORT: Include platform pthread headers and includes for pthread config.
- FIXED: #1465 Overflow issue in trie handling. This is the result of
replacing an
int incorrectly with bool.
[Feb 14 2026]
- FIXED: PThreads4W exit crash in MSVC Debug builds Without this,
the system crashes during process exit.
- ENHANCED: listing/1,2: show number of clauses in other threads.
[Feb 13 2026]
- ADDED: listing/2: option
thread(+ThreadId) This lists the clauses
for a thread-local predicate as they can be seen for the given thread
(rather than the calling thread).
- MODIFIED: Modified PL_put_dict() to be a
bool function. All usage
in packages assumed bool and this is a more consistent interface.
Invalid keys now generate a fatal ABI error and dupiicate keys a normal
Prolog exception. As this function is not used much and there is no
clean way to fix the current bugs without changing the API we will
backport this to the stable series as is.
- FIXED: dict_pairs/3 could create dicts with duplicate keys.
Mistake changing types to
bool. This changes the dict ordering
functions to return _PL_dict_status_t, which is now also returned
by PL_put_dict().
- CLEANUP: Avoid unreferenced variable warning for MSVC
[Feb 12 2026]
- BUILD: MSVC Sanitize build
- TEST: Windows pipe test by using absolute batch file path The pipe:cat1
test was failing because the batch file path was relative. cmd /c
couldn't find pltest-XXXX.bat. Fixed using absolute_file_name/2.
- BUILD: Use proper CMake dependencies for building the
INDEX.pl
files Since we no longer merge the package library files with the
main library and since CMake has evolved, we can get rid of the ugly
"run always" approach to building the INDEX.pl files and create
a proper custom rule with the proper dependencies.
[Feb 11 2026]
- FIXED: Hashing over uninitialized memory on 32-bit systems. On 32-bit
systems, clause references are created in part from unitialized memory.
This leads to crashes in atom-gc for clause references.
- TEST: Add alternative bitint term hash for 32 bit engines.
- PORT: Remove /D_DEBUG and /DO_DEBUG from MSVC Sanitize build flags
MSVC AddressSanitizer requires the release CRT (/MD), but /D_DEBUG
causes the STL to reference debug-CRT symbols (_CrtDbgReport) and
makes Python headers demand python3XX_d.lib.
[Feb 10 2026]
- PORT: MSVC debug build CRT mismatch for plugins
- PORT: MSVC debug build: variadic macros and PRETTY_FUNCTION
- PORT: Set CMAKE_MSVC_RUNTIME_LIBRARY globally for MSVC builds
- PORT: Fix MSVC C4334 warning in pl-buffer.c
- PORT: Drop xpce on < 64 bit platforms.
- BUILD: Extend build_home.pl to support multi-config generators There
was specific code to support Microsoft Visual Studio. This patch
supports multi-config generators on platforms that leave the modules
in the package directories such as
ninja -G "Ninja Multi-Config"
[Feb 9 2026]
- PORT: Avoid undefined
ms_snprintf() and renamed to c99_snprintf().
[Feb 8 2026]
- PORT: Add /EHsc to MAKE_CXX_FLAGS for MSVC. Thanks to Eric Tauber.
- CLEANUP: Avoid implict enum conversion warnings. Based on #1445 by
Eric Tauber.
[Feb 6 2026]
- FIXED: Make
PL_query(PL_QUERY_HALTING) return true inside atexit()
handlers. This addresses the cleanup in package nlp cleanup issues.
[Feb 5 2026]
- PORT: Make
exit() work properly in Windows with Asan and Debug enabled.
Thanks to Eric Tauber.
[Feb 4 2026]
- PORT: Avoid calling
sleep() after Lsan detects a leak.
- PORT: Updated scripts/macos-deps.h for SDL3 Updated version and build
instructions for building a universal binary.
- ADDED: check_installation/0: report OpenSSL version
[Feb 2 2026]
- PORT: Exclude LeakSanitizer code on Windows (MSVC ASan lacks LSan
support)
[Feb 3 2026]
- FIXED: Bignum allocation issues. This may lead to memory corruption
on LibBF as well as using GMP on arithmetic errors. Found by Eric
Taucher while debugging the MSVC compiled version.
[Feb 1 2026]
- FIXED: Tabling with attributed variables: memory management. Make sure
avm in trie_lookup_abstract() never points below the allocated
buffer. It is not clear to me whether that is strictly necessary,
but MSYS-2 using clang and Asan suggests it is. I do not understand
why this is not reported using Asan under Linux. Surely this prevents
reading below the buffer, causing a SEGV if it is tried anyway.
[Jan 31 2026]
- TEST: term_hash/2 for indirect data types (bigints, floats) term_hash/2
is platform dependent as it hashes the binary representations of
indirect types (big int, rational, float). The test succeeds if
the produced hash is one of a set. When using LibBF, the hash also
depends on whether the limb size is 32 bits or 64 bits. The C
compiler must support a twice as wide integer type, i.e., the choice
depends on
HAVE_INT128.
- FIXED: term_hash/2: exception when exhausting memory. Also cleanup
types.
- CLEANUP: Avoid reading uninitialized local variable. Not entirely sure
why the
popSegStack() can fail. Surely it does on the XSB tests from
tests/xsb/sub_tests/xsb_test_sub.pl. In debug mode we set dstate
such that accessing it crashes. This seems not to be the case.
- FIXED: Windows: ms_snprintf null-termination bug for edge case
[Jan 30 2026]
- PORT: Ensure default 4Mb C-stack on Windows Otherwise the default is
2Mb for MinGW and 1Mb for MSVC
- FIXED: When specified, also set the C-stack limit for
swipl-win
[Jan 29 2026]
- PORT: Compile MacOSX bundle using gcc. This provides about 40%
performance improvement.
[Jan 27 2026]
- PORT: Support CMake < 3.24 Using CMake < 3.24 the build was broken due
to the usage of
cmake -E env ... -- ... We now omit that for older
cmake version. This implies that building in e.g build.gcc=14
does not work for these versions.
[Jan 24 2026]
- FIXED: write_term/2: handle
partial(true) for backquoted text.
- FIXED: write_term/2 using option
partial(true) to separate quoted
objects. Found by Joachim Schimpf
- DOC: write_term/2: handling of
back_quotes and module options
[Jan 23 2026]
- FIXED: write_term/3 and friends to get default back_quotes from flags.
[Jan 22 2026]
- PORT: Better support for Homebrew dependencies (MacOS) This ensures
SDL3 comes from Homebrew if both provided by Macports and Homebrew and
configure maps gcc=14 to Homebrew gcc.
- PORT: Make configure work for
build.gcc=15 on MacOS. Compiler is
called gcc-mp-15 and it does not support -g3.
[Jan 21 2026]
- ENHANCED: edit/1: merging module and file. If a spec resolves to a
file and module with the same name, edit the module.
[Jan 19 2026]
- FIXED: Allow building only the core system (no packages at all).
Stop installing libraries that depend on packages and do not warn if
library(editline) is not present.
- FIXED: #1436 check_installation/0: check editline, also on Windows.
- FIXED: CpuCount() typing
[Jan 18 2026]
- FIXED: Type issues on 32 bit platforms
[Jan 15 2026]
- CLEANUP: Types Restore API affecting type changes of
-Wconversion
cleanup, introduce new integer aliases and enums to replace int
with more appropriate types. Propagate these through the system
(incomplete).
[Jan 10 2026]
- CLEANUP: Make likely/unlikely silent.
[Jan 5 2026]
- FIXED: #1431 format/2: handling
~d on gmp evaluation returning
a small int.
[Dec 31 2025]
- ENHANCED: edit/1: if multiple hits are in the same file, take most
specific. Thus, if both the file and some object inside the file
match, use the object. Also xpce classes are more specific that the
module they are contained in.
[Dec 25 2025]
- FIXED: edit/1 for normal predicates. Broken after integrating
foreign predicates.
[Dec 23 2025]
- FIXED: UBSAN: Calling event handler with too many arguments.
[Dec 22 2025]
- UBSAN: Avoid offset to NULL pointer
- UBSAN: Possible increment of NULL pointer This is benign, but
officially undefined.
- FIXED: Type handling for PL_thread_at_exit(). Resulted in reported
undefined behaviour due to non-matching function prototype.
[Dec 18 2025]
- CLEANUP: Unconditionally use
fpclassify() This is available on any
system providing C99 and we already demand C11.
[Dec 17 2025]
- PORT: Make compile using Emscripten
- ADDED: Extract the source location of foreign predicates. Added
'$foreign_predicate_source'/2. Requires debug symbols and
addr2line or similar.
[Dec 16 2025]
- THEME: Support PceEmacs bookmark view in the dark theme,
[Dec 15 2025]
[Dec 14 2025]
- UBSAN: Avoid bit shift ==
sizeof(x) The proposed change is not pretty,
but it avoids another UBSAN error if low (64 bit) is << by 64 bits.
[Dec 12 2025]
- UBSAN: Avoid bit shifts in MT RNG
[Dec 10 2025]
- FIX: UBSAN check Avoid
memcpy(NULL, _, 0)
[Dec 9 2025]
- FIXED: bigint cache allocation error Can lead to buffer overflow.
[Dec 7 2025]
- CLEANUP: use snprintf to avoid deprecation warnings
- PORT: replace sprintf by snprintf to avoid deprecation warnings
[Dec 4 2025]
- BUILD: Updated
scripts/configure Simplified, added --help
option and allow for both extracting features from the name and using
commandline arguments.
- FIXED: Undefined ep_has_console/1 message when enabling the debugger.
[Dec 3 2025]
- CLEANUP: Remove traces of GNU readline
[Dec 2 2025]
- BUILD: Include script to build gcc version on MacOS
- PORT: Support older gcc and clang versions that do not provide
__auto_type
[Nov 30 2025]
- ENHANCED: On ELF systems that have
objcopy, add the state as an
ELF section. This makes the system a valid ELF executable on which
all ELF tools work normally.
- ADDED: qsave_program/2: option
zip(true) to create a clean .zip file.
- FIXED: #1414 crash in C_CUT due to reset clause pointer from undo/1.
[Nov 24 2025]
- MODIFIED: PIP-0105: write_term/2 option
max_text to exclude ellipsis.
As we already exclude the quotes and escape sequences, excluding the
ellipsis is more consistent. After remarks by Joachim Schimpf.
- FIXED: #1411 Windows issue for handling max_text on UTF-16 pairs.
- TEST: Relax thread queue timeout tests and provide more accurate
failure feedback.
[Nov 23 2025]
- FIXED: Save history for new directory using
swipl-win
- ENHANCED: On (Linux/Unix) systems with hot-pluggable CPU or running as
virtual machines, the cpu_count Prolog flag should be set to the number
of online processors (SC_NPROCESSORS_ONLN) instead of the configured
maximum number (SC_NPROCESSORS_CONF). Using the online count avoids
situations where cpu_count reflects offline or non-present CPUs. If
SC_NPROCESSORS_ONLN is not defined by the system, we fall back to
the old SWI-Prolog behaviour.
[Nov 21 2025]
- BUILD: show options in generated file
- MODIFIED: write_term/2:
max_depth(+Depth) to use Unicode …
If the encoding of the output supports Unicode. Otherwise the ASCII
sequence ... is emitted.
- ADDED: write_term/2: support
max_text(+Length) for quoted output.
[Nov 20 2025]
- ADDED: PIP-0105: write_term/2 support for
max_text(+Length) Actually
called text_max in the proposal. Considering all other options
and flags are named `max_*`, I think this should change.
- FIXED: with_tty_raw/1: kept lock on stream.
- ADDED: PIP-0105: write_term/2 option
truncated(-Bool). Bool
is unified to true if the term has been truncated due to the
max_depth option.
- ADDED: PIP-0105 write_term/2 option
portable(Bool)
- DOC: Update CMAKE.md, section components
- TEST: saved_states, disable timeout under MSYS2 (#1406) * TEST:
saved_states, disable timeout under Windows
[Nov 19 2025]
- DIST: Added packages/libedit/libedit to tar archive
- ADDED: Using the option
--home=dir, set SWI_HOME_DIR.
This ensures that sub processes can access Prolog's home and, when
calling Prolog, execute the same Prolog system.
- TEST: Base saved-state tests on new
prolog(Tool) option of
process_create/3.
- FIXED: Allow
swipl -o exe -c input.pl to pass --home=dir
option.
[Nov 18 2025]
- PORT: Properly install runtime dependencies for MSVC build This now
depends in CMake > 3.21
install() option RUNTIME_DEPENDENCY_SET
[Nov 17 2025]
- PORT: Build
swipl-win.exe under MSVC Now compiles cleanly.
swipl.exe runs fine, including line editing. The GUI is unresponsive
though.
[Nov 14 2025]
- FIXED: format/1-3: reset last tab stop on a newline. Spotted by
Joachim Schimpf with the PIP tests.
- ADDED: ansi_format/4, formatting with colours to a stream.
- PORT: MSVC
- MODIFIED: format/2 handling of non-list arguments Now, the second
argument is only considered a single argument if it is not [] or [_|_].
Notable partial lists or lists not ending in
[] are now threaded as
(invalid) argument list.
- ENHANCED: Errors for arithmetic expression
[Code] if list holds no
single code.
- PORT: MSVC compatibility.
- TEST: Fixed test for format/2 `~6s`.
- DOC: format and friends. Move documentation of deprecated writef/2
and friends to the library documentation. Updated the format/1-3
documentation.
- PIP: PIP-0110: make `~<n>s` emit padding if text is too short.
[Nov 11 2025]
- TEST: Use
swipl.bat for testing saved states on Windows. 1. allows
for "external" swipl.bat under Windows (see swipl.sh in l. 133)
- invokes saved state with -x if swipl.bat is used
[Nov 13 2025]
- PORT: Work around broken MSVC
- TEST: PIP-0110: added PIP format/2 tests.
- COMPAT: Extended ECLiPSe test driver to accept
should_output
- MODIFIED: PIP-0110: format/2 using
~N to ignore the argument.
Most implementations ignore the argument. Others interpret it
inconsistently. New code should use ~N~2n as replacement for
~3N.
- MODIFIED: PIP-0110: distributing extra spaces over `~t` Used to
distribute these spaces from the middle. Now distributes them from
the right, compliant with SICStus and ECLiPSe.
- ADDED: PIP-0110: format/2 format specifier
F. This is like f,
but using uppercase letters for non-normal floats.
- PIP: PIP-0110: format/2: `~a` to only accept atoms and compact strings.
- PIP: PIP-0110 (format) compatibility: handle expressions for
*
[Nov 12 2025]
- PORT: Better MacOS Homebrew support
[Nov 11 2025]
- FIXED: Typo in updated history code. Caused !/0 to be redefined ...
[Nov 7 2025]
- FIXED:
!<num> history handling if command contains a . in the
middle.
[Nov 5 2025]
[Nov 3 2025]
- MODIFIED: Use
bool types for profiling API Should have low impact.
Used by xpce.
- FIXED: Disable Epilog if threads in single threaded version.
- MODIFIED: halt/1: forward to main thread. If halt/1 is initiated
from a thread other than
main, main is signalled to terminate
the process. If the main thread does not do so within the time
specified by the Prolog flag halt_grace_time (default 1 second),
the process is forcefully terminated.
[Nov 2 2025]
- MODIFIED: Commandline history handling. Comandline history handling
used a double administration, both saving command as Prolog facts and
in the commandline editor. Now the commandline editor is in charge.
Visible changes to the user:
[Oct 27 2025]
- COMPAT: Use new message_action/2
- ADDED: message_action/2 hook. This separates side effects on
messages from printing messages, allowing side effects to take place
even if an earlier print hook suppresses the message.
- FIXED: Use library broadcast to tell other components of modified
break-points.
- TEST: Do not run the "unprotected" tests if
protect_static_code
is set.
- FIXED:
'$clause_from_source'/4, used for setting break-points.
[Oct 26 2025]
- DOC: Do not run test_installation twice
- ENHANCED: xref_source/2: emit warning on late meta_predicate/1 This
directive must appear before the predicate is being used (called).
[Oct 24 2025]
- PPA: Added Ubuntu 25.10 (Questing Quokka)
- FIXED: Install of non-qlf json compatibility wrappers.
- ADDED: packages/json
[Oct 23 2025]
[Oct 21 2025]
- DOC: term_size/2: cells are always 8 bit in recent versions.
[Oct 20 2025]
- ENHANCED: Messages for managing spy points.
[Oct 14 2025]
- ENHANCED: listing/0,1,2 to respect the terminal width. If the output
is a terminal, tty_size/2 is used to determine the line width.
[Oct 12 2025]
[Oct 7 2025]
- ADDED: Implement read_term/1: implement reading attributed and
labeled terms. This patch supports Var{Attr: Value, ...} if the
Prolog flag
var_tag is set to attvar. This allows reading terms
with attributes. It also supports labeled subterms that allows to
read terms that are directed graphs rather than trees. This includes
cyclic terms. For this we reserve the attributed =. For example
[Oct 6 2025]
- DOC: Updates documentation for using of # anonymous dicts.
- TEST: Update tests for use of # anonymous dicts
- MODIFIED:
Dict.put(Path, Value): create new dicts as #{...}.
- MODIFIED: select_dict/3 handling of
# tag The # tag matches any tag
at the other end and the dict holding the remainder has the # tag.
[Oct 3 2025]
- MODIFIED: write_term/2 using
attributes(write) This now writes
Var{Att1: Value1, Att2: Value2, ...}, which is valid syntax for
read_term/2 if the Prolog flag var_tag is attvar.
[Oct 2 2025]
- ADDED: read_term/2 and friends to respect the new
var_tag flag.
- ADDED: Prolog flag
var_tag Defines how Var{...} terms are
interpreted. This commit only implements setting and getting the flag.
[Oct 1 2025]
- MODIFIED: :</2 and >:</2: match
# tag The tag # matches any
tag on the other side without instantiating the tag.
[Oct 8 2025]
[Oct 2 2025]
- FIXED: Exception details from
'$tmp_file_stream'/4
[Oct 1 2025]
- ERROR: Domain error: `encoding' expected, found `txt'
- CLEANUP: Fixed more compilation warnings when using -O3
[Sep 30 2025]
- BUILD: Fix PGO building for AppleClang
- BUILD: Fix PGO build for Clang. This now does optimize.
- BUILD: Changed default optimization for gcc to -O3 Earlier tests showed
no noticeable difference, but using gcc-15 and
setjmp()/longjmp out
of the way we get about 15% improvement.
- SANDBOX: Declare string quasi quotation syntax as safe.
[Sep 29 2025]
- TEST: Fix format_time/3 tests by setting correct timezone.
- WASM: Set defaults for best performant build.
- ENHANCED: Move
setjmp() out of the VM main function Using setjmp()
harms register allocation, which slows down the VM. Some data points:
Clang: 6% (Clang-17 on Apple M1 as well as Clang-20 on AMD3950X),
GCC: 13% (GCC-15 on AMD3950X), WASM: 35% (Emscripten 4.0.15 on Node.js
22.19 on AMD3950X). MinGW-14: 18% (Windows binary running on AMD3950X
under Wine).
- TEST: Fixed ration number writing test to work regardless of flags.
Test failed when run with
rational_syntax set to natural.
[Sep 28 2025]
- ENHANCED: Get rid of setjmp/
longjmp() in PL_next_solutions() This
improves performance by about 12%. It does make a couple of scenarios
for stack overflow handling impossible though. This patch merely
introduces O_THROW as C macro to enable/disable this.
[Sep 26 2025]
- WASM: Make setting CFLAGS and LDFLAGS in BuildType.cmake work The
if/elseif/... selection triggered on Clang.
- WASM: Compile VM using
-O2 This produces a smaller binary with
slightly better performance.
- WASM: When using a monolithic PL_next_solution(), use
-O1 in
Debug mode Otherwise local variables with non-overlapping scope are
not merge, causing an Emscripten compiler error
- WASM: Do not build
swipl-win Also cleanup handling platform-dependent
cmake options
[Sep 25 2025]
[Sep 24 2025]
- FIXED: When a REPL loop receives the halt/0,1 exception, make
it return. Before, if non-threaded or the REPL loop runs in the
main thread, terminate the process. Otherwise halt/0 was ignored.
The behaviour for the main thread is still the same, but prolog/0
succeeds in other threads if the thread calls halt/0.
Package debian
[Apr 20 2026]
- ADDED: libutf8proc-dev as new dependency.
[Feb 23 2026]
- PPA: Dropped libedit. Using bundled version.
Package PDT
[May 10 2026]
- RENAME: PDT.doc -> PDT.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package RDF
[May 10 2026]
- RENAME: RDF.doc -> RDF.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package archive
[May 10 2026]
- RENAME: archive.doc -> archive.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package bdb
[May 10 2026]
- RENAME: bdb.doc -> bdb.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 22 2026]
- CLEANUP: Avoid -Wconversion warnings You might wish to check if the
assertions are needed/solve a problem.
[Nov 12 2025]
- PORT: Honour
LIBBDB_ROOT_DIR cmake variable
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package chr
[Oct 27 2025]
Package clib
[May 28 2026]
- FIXED: bsd-crypt.c: unconditional include of "crypt.h" breaks build
when no system crypt.h is available On glibc >= 2.39 the
crypt()
function is no longer in libc; when libcrypt-dev is also absent
(e.g. some PPA build chroots), CMake's HAVE_CRYPT and HAVE_LIBCRYPT
both fail and the build falls back to the bsd-crypt.c implementation,
which then failed because it unconditionally included "crypt.h".
The DES_ONLY define already excludes the only consumers of anything
declared there, so guard the include with HAVE_CRYPT_H, matching the
pattern in crypt.c.
[May 10 2026]
- RENAME: clib.doc -> clib.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Feb 19 2026]
- TEST: Raise timeout for UDP tests. Could fail.
[Feb 8 2026]
- CLEANUP: Bool types and avoid conversion warnings for Windows
[Jan 31 2026]
- PORT: Ensure
ssize_t is defined when using MSVC
[Jan 18 2026]
- ENHANCE: use size_t to avoid -Wconversion errors I also added a few
casts I considered safe. Dubious casts are highlighted.
[Nov 20 2025]
- DOC: minor fix in comment
[Dec 7 2025]
- PORT: replace sprintf by snprintf to avoid deprecation warnings
[Nov 19 2025]
- ADDED: process_create/3: specify program as
prolog(Tool) This allows
Prolog running one of its tools, with the guarantee that we use the
tools from the same version. This provides a hook prolog:prolog_tool/4
that allows embedded systems to redefine how the Prolog tools should
be executed.
[Nov 6 2025]
- FIXED: Make library(uuid) work properly if autoloading is disabled.
[Oct 20 2025]
- DOC: Document some types for
lirary(uri).
[Oct 10 2025]
- FIXED: crypt/2 on Windows using bsd-crypt.c: possible memory
corruption.
[Oct 9 2025]
- FIXED:
urn-schema URIs can have a query and fragment field.
[Oct 8 2025]
- MODIFIED: library(uri) to raise more exceptions and support URNs.
[Jun 9 2023]
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package cpp
[Jun 20 2026]
- FIXED: PlRegister constructors must take size_t arity to match macros
The previous commit changed the PREDICATE/PREDICATE_NONDET trampoline
signatures to (term_t, size_t, control_t) but left the PlRegister
constructors taking (term_t, int, control_t), breaking every user of
the macros.
- UBSAN: use size_t instead of int for arity That is the error
[May 31 2026]
- FIXED: macOS GCC build aborting on std::bad_alloc from over-sized
new On macOS a foreign extension built with GCC links libstdc++,
while the process also loads the system libc++/libc++abi via the
system frameworks. As operator new is a coalesced weak symbol it
resolves to libc++, so
new throws a libc++ std::bad_alloc whose
type_info differs from the libstdc++ one named in PREDICATE_CATCH's
catch(const std::bad_alloc&). That handler misses and, lacking a
catch-all, the exception reaches std::terminate() and aborts the
process (e.g. test_cpp.pl cpp:malloc).
[May 19 2026]
- DOC: document the PlEncoding API in pl2cpp.plx Document the
PlEncoding enum and the ENC_INPUT/ENC_OUTPUT defaults, the
trailing-PlEncoding constructor/method forms and the deprecated
argument-order constructors. Add a PlFunctor section and state that
PlModule/PlPredicate/PlFunctor/PlCompound functor names are UTF-8.
Replace the stale EncLatin1/EncUTF8/EncLocale enumerators, correct
the unify_*() wrapper descriptions and escape & for the PDF build.
[May 10 2026]
- RENAME: pl2cpp.doc -> pl2cpp.plx (LaTeX manual source) Update pkg_doc
SOURCES reference. Co-Authored-By: Claude Opus 4.7 (1M context)
<noreply@anthropic.com>
[May 4 2026]
- ENHANCED: PlTerm::
unify_blob() takes std::unique_ptr<T> for any T
derived from PlBlob The unique_ptr<PlBlob> overload became a function
template unify_blob(std::unique_ptr<T>*) with a static_assert that T
derives from PlBlob. Callers can now pass std::unique_ptr<MyBlob>*
directly without an upcast through std::unique_ptr<PlBlob>; the
obsolete make_unique() workaround in the docs is removed.
[Jan 23 2026]
- ENHANCED: make it easier to generate the standard form of exceptions
[Jan 22 2026]
- CLEANUP: add more default qid=0
[Jan 21 2026]
- CLEANUP: Plx_exception() has default qid=0
[Jan 20 2026]
- CLEANUP: change PL_exception() to Plx_exception()
[Jan 12 2026]
[Jan 9 2026]
[Dec 4 2025]
- DOC: fix description of PlQuery::
next_solution()
[Nov 24 2025]
- FIXED: compiler warnings for print formats
Package cql
[May 10 2026]
- RENAME: cql.doc -> cql.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package http
[May 31 2026]
- TEST: proxy: pick the `unused' port from below the ephemeral range
The previous fix reserved the `unused' port by holding a socket
bound but not listening, so that
connect() attempts are refused
while no concurrent ctest job can grab the port via bind(0). On
Linux/Windows a bound, non-listening socket is refused promptly,
but on macOS connecting to such a socket blocks for several seconds
before failing. As several tests connect to the unused port, the
suite took ~30s on macOS instead of a fraction of a second.
[May 28 2026]
- TEST: proxy: reserve the `unused' port by holding a bound (unlistened)
socket Concurrent ctest jobs that allocate ports dynamically (bind to
port 0) could grab the port the proxy tests had pre-allocated for the
`unused' role, causing connections that should be refused to instead
succeed against an unrelated test server. Keeping a bound socket
on that port for the duration of the suite reserves the port number
while still producing ECONNREFUSED on
connect(), since no tcp_listen/2
is called. SO_REUSEADDR is intentionally omitted on the held socket.
[May 10 2026]
- RENAME: http.doc -> http.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Mar 6 2026]
- ADDED: Set class property for created threads.
[Feb 10 2026]
- BUILD: Add zlib to doc generation dependencies
[Jan 25 2026]
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Dec 16 2025]
[Nov 23 2025]
[Oct 27 2025]
[Oct 24 2025]
- PACKAGE: Remove JSON files from this package The JSON support is
moved into a new package
json
[Oct 17 2025]
- ADDED: Support
HttpOnly and Secure cookie properties
in http_session.pl http_set_session_options/1 now supports the
http_only(true) and secure(true) options, adding these properties to
the session cookie. Both default to false for compatibility reasons.
[Sep 30 2025]
- FIXED: Possible uninitialized variable (in error case)
- SANDBOX: Declare Quasi Quotations for json, html and javascript
as safe.
[Sep 28 2025]
- ADDED: json quasiquotation syntax This allows for embedding JSON
documents represented as a Prolog dict using e.g.
Package jpl
[May 10 2026]
- RENAME: jpl.doc -> jpl.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 24 2026]
- CLEANUP: avoid -Wconversion, improve UTF16 support On systems with
wchar_t is 4 bytes (pretty much anything but Windows), convert
Prolog Unicode code points > 0xffff to/from UTF-16.
Package libedit
[May 20 2026]
- ADDED: Bind Ctrl+Left/Right to word motion Maps the xterm sequences
ESC[1;5D and ESC[1;5C, sent by the Epilog terminal, to ed-prev-word
and em-next-word. In vi mode the same sequences are also bound in
the command (alternative) keymap to vi-prev-word and vi-next-word.
[May 10 2026]
- RENAME: libedit.doc -> libedit.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[May 6 2026]
- ADDED: bind ^Z to send EOF on Windows Matches the platform convention
for end-of-file (Unix uses ^D). Routed through libedit's built-in
em-delete-or-list / vi-list-or-eof, which already return CC_EOF on
an empty line.
[May 5 2026]
- FIXED:
el_cursor() takes wchar_t units, electric() hands code points
The Prolog electric() handler computes Move = Index - Len, where both
Index (matching_open's position) and Len (string_length of Before) are
CODE-POINT counts. The C wrapper passed Move straight to el_cursor(),
which adds it to el_line.cursor as wchar_t units.
- ENHANCED: install PL_wcwidth as libedit's wcwidth implementation
libedit no longer ships its own mk_wcwidth table;
el_set(EL_WCWIDTH,
fn) injects one. Wire PL_wcwidth here so swipl and swipl-win share the
kernel's src/mk_wcwidth.c with pl-write, pl-fmt, xpce — one table,
one source of truth, no more drift between layers.
- FIXED: pl_line and el_history_encoded use REP_EL not REP_MB
PL_unify_chars(PL_STRING|REP_MB, ...) decodes the bytes via the
C runtime's mbrtowc. On Windows with the legacy ANSI codepage as
LC_CTYPE that fails for any byte above 0x7F — and libedit hands us
UTF-8 bytes there (ct_encode_char unconditionally calls utf8_put_char
on Windows).
[Apr 23 2026]
- ADDED: bracketed_paste(?Boolean) property to el_set/2 and el_get/2
Bracketed paste mode is now tracked per el_context and can be toggled
at runtime. el_set/2 immediately emits the enable (ESC[?2004h) or
disable (ESC[?2004l) sequence when the value changes; el_get/2 reads
the current state.
- ADDED: el_get/2 to query editline properties Initially supports
editor(?Editor), unifying with
emacs or vi via EL_EDITOR.
Unknown properties raise a domain_error(editline_property, _).
[Apr 20 2026]
- FIXED: swipl.exe console uses ReadConsoleInputW (Unicode) for input
libedit4pl.c's Windows console read_char called ReadConsoleInput,
which without UNICODE/_UNICODE defined expands to the ANSI variant
ReadConsoleInputA. The A variant fills uChar.AsciiChar as a CP_437
/ CP_ACP byte. We then read uChar.UnicodeChar from the same union,
which gets at best a low-byte-truncated value (the A-call leaves the
high byte of UnicodeChar undefined; in practice it's 0, so the byte
value is read as a BMP code point of the same numeric value).
- FIXED: pl_getc reassembles UTF-16 surrogate pair on Windows
editline.pl's bracketed_paste/3 handler collects pasted bytes
with el_getc/2 (foreign pl_getc) and then calls string_codes/2 on
the result. On Windows wchar_t is a 16-bit UTF-16 code unit, so a
supplementary code point (emoji like 🤩, most non-BMP CJK) lives in
the line buffer as a surrogate pair and el_wgetc returned each half
as its own int. The resulting code list contained lone surrogates,
and string_codes/2 aborted with
[Apr 19 2026]
- ENHANCED: libedit4pl.c — reassemble supplementary code points on
read (Windows) On Windows wchar_t is a 16-bit UTF-16 code unit, but
read_char read one UTF-8 code point at a time and stored it directly
in a wchar_t:
[Apr 15 2026]
- ADDED: Use "bracketed paste mode" in the terminal. This avoids
interpreting TAB as completion and speeds up long paste in Windows.
[Jan 5 2026]
- FIXED: Build on Windows for enhanced background write handling.
[Jan 3 2026]
- ENHANCED: Refreshing the terminal on background writes.
[Nov 17 2025]
- PORT: Clean compilation on MSVC
[Nov 16 2025]
- PORT: Allow using bundled libedit This is the default. The system
version can be selected using
cmake -DSYSTEM_LIBEDIT=ON.
This should simplify building
[Nov 12 2025]
- ADDED: el_set/2 to set the word characters This replies on
el_wset()
using EL_WORDCHARS that is provided in some recent copies of
libedit. When available, it is used to set the word chars to only
"_" (in addition to iswalnum()).
[Nov 11 2025]
- FIXED: Avoid full refresh in Epilog windows on each action. Failed to
reset the refresh request. Refreshing causes issues with wrapped
lines.
- FIXED: Synchronise Epilog window size changes with libedit.
[Nov 3 2025]
- FIXED: Signal handling Detecting this is the main stdin we are reading
from failed since we use
dup() on the file handles to avoid closing
them. We now add this fact to the context, initiated before the dup().
[Nov 2 2025]
[Nov 1 2025]
- ADDED: Extended el_history/2 with more actions. This allows for
querying individual events, setting the notion of current, and
searching the history.
[Oct 31 2025]
- ENHANCED: Read old
swipl-win.exe history data in current version.
- MODIFIED: el_read_history/2 to raise an error if the history file
is invalid.
[Oct 29 2025]
- PORT: Compile if H_SAVE_FP is lacking
[Oct 28 2025]
[Oct 23 2025]
- ENHANCED: Support thread signal processing while reading from
Epilog. This is required to prevent the Debug menu of Epilog
from deadlocking the application. It also allows e.g., timers to
function in Epilog consoles. Note that signal processing already
worked in non-Windows environments.
[Oct 17 2025]
- ADDED: el_version/1 to get the version of the editline library used.
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package ltx2htm
[Jun 10 2026]
- ENHANCED: \classsuffix{Slug}{Display} for case-preserving class-name
refs
- ENHANCED: hyperlink global object refs (@pce, @nil, ...) to
their section The objectname macro now emits an \lref into
sec:object-<safe> mirroring the section anchors doc_latex generates
for the {#object-<name>} headings in objects.md. If no such section
exists, ltx2htm leaves the inner bold @<name> visible unchanged.
- FIXED: inline <-> ref resolves when only send/get methods are defined
\sendmethod and \getmethod now emit a class-C-both-N anchor in addition
to their own class-C-send-N / class-C-get-N anchors, mirroring
the alias \bothmethod already provided. An inline \classboth{C}{N}
reference (the inline
<->protect form) therefore lands on the
first of the send/get method's <dt> when no bothmethod or ivar carrying
that name exists.
- FIXED: keep underscores in member-anchor selectors so _free and
free differ
[Jun 9 2026]
- ENHANCED: add classivar*method commands for xpce ivars Defines
\ivarbothmethod / \ivargetmethod / \ivarsendmethod / \ivarnonemethod
alongside the existing \sendmethod / \getmethod / \bothmethod
/ \classvarmethod. Each variant renders with the documented
side-effect-free access and indexes the member under
xpce(Class, ivar,
Name), so the manindex sees one bucket per ivar regardless of which
arrow notation the source .md picked. \classinstvar inline links are
rerouted to the ivar anchor.
- BUILD: silence \_word + tokenise \date{} arg before translate Two
follow-ups to the previous noise cleanup:
- BUILD: define preamble dummies and \_word escape in latex.cmd /
latex2html A clean build of the xpce manual emitted 5 'Failed to
translate' preamble warnings for \RequirePackage, \newenvironment,
\excludecomment, \date, \today (all general LaTeX, not xpce-specific)
and another 4 for \_method, \_manager, \_check and \_sink (the
C-side tokeniser greedily reads an underscore after \ as part of
the command name, so 'class object->\_check' in the .tex parses as
a single \_check command).
- FIXED: tokenise Args atom before #
var(+Args) in sendmethod et al.
ltx2htm's translate/3 only handles list inputs; sty_xpce passed the
raw Args atom via #var(+Args), so every xpce method whose argument
spec had punctuation other than identifiers (name=name, [int],
\Sbar{}, ...) emitted
- BUILD: drop autoload for delete/3 and friends in sty_xpce A
clean build hit 'Unknown procedure: delete/3' from
clean_anchor_part/2 before library_index/INDEX.pl had been built, so
the autoload couldn't fire. Use use_module/2 for maplist/3, append/3
and delete/3 instead so the imports don't depend on the autoload index.
[Jun 7 2026]
- ENHANCED: \errid renders as anchored link Wrap the
!<id>
bold-code in #lref so prose references to !already_has_parent,
!argument_type, ... navigate to the error's card. The label
matches the sec:error-<id> slug pce_html_manual computes from a
live error instance.
- FIXED: classinstvar/classvar text bold like classsend/get/both
The previous emission wrapped Class+separator+Var in a single
#code, so the whole link rendered in monospace; the rest of the
xpce link macros use bold for the names and only #code for the
arrow / separator. Restructure to match that pattern so all six
member-reference forms style consistently.
- ENHANCED: \classinstvar and \classvar render as anchored links Like
\classsend / \classget / \classboth, the two slot-reference macros now
wrap their bold-code rendering in a #lref so the HTML output points
at the corresponding member's anchor (class-C-both-V for instance
variables, class-C-classvar-V for class variables). Falls back to
plain bold-code when the target isn't indexed -- e.g. for private
slots that have no member card.
- ENHANCED: bothmethod registers send/get anchor aliases Emit two
empty
<a id="class-C-send-N"> / <a id="class-C-get-N">
labels next to the canonical class-C-both-N anchor on
every \bothmethod{C}{N}{...} so cross-references written as
\classsend{C}{N} or \classget{C}{N} (the natural form in
prose) resolve onto the bothmethod entry. Without these aliases the
lref to send-form fell back to plain bold-code because no label by
that name existed.
[Jun 6 2026]
- ENHANCED: add classvarmethod and quote member data-obj attributes *
Add
\classvarmethod{C}{V}{Args} as the HTML counterpart of
xpce.sty's new macro. Emits the same <dt class="pubdef"> +
hidden <a data-obj="xpce(C,classvar,V)"> shape the send /
get / both macros produce so manindex.db's SGML walker captures
the entry. * The member data-obj attribute now writes the class
name and
selector with ~q, so selectors starting with underscore
(object->_check, object<-_arg, ...) round-trip cleanly
through atom_to_object/2 instead of being read as Prolog
variables.
- ENHANCED: emit pubdef + data-obj on xpce method <dt> Change
sendmethod/getmethod/bothmethod to render
<dt class="pubdef"> with
a hidden <a data-obj="xpce(Class,Kind,Selector)"> preceding the
visible #label anchor. The SGML walker in packages/pldoc/man_index.pl
picks up the data-obj on the first nested <a>, so the entries
land in manindex.db keyed by the xpce(C,K,S) compound that PlDoc's
search/page hooks understand.
- ENHANCED: ltx2htm picks up \getmethod's 4th arg and the text-mode
brackets - xpce.cmd: \getmethod takes 4 args (Class, Sel, Args,
RetType), not
- With the prior 3-arg declaration ltx2htm parsed the 4th brace
group as stray content, swallowing successive tokens until EOF.
- sty_xpce.pl: \getmethod{C}{S}{A}{R} -> <dt>C<-S: A -> R</dt>.
- latex.cmd: declare \textless and \textgreater so the C-side
tokeniser knows they take zero args (the Prolog dispatcher rule
landed in Phase 4b; the tokeniser needs its own declaration).
- FIXED: clean_name accepts \textgreater / \textless PlDoc emits operator
names like ->/2 through print_char/2 with the text-mode \textgreater{}
/ \textless{} escapes that ltx2htm's \textgreater handler turns into
> / < entities. clean_name/2 runs on those names when rendering
predicate / infix-operator entries (\infixtermitem etc.); the existing
clauses didn't know about the LaTeX commands, so any predicate using ->
in its operator-form was failing to translate ("Failed to translate
\infixtermitem in mode description"). Two extra clauses fold them
back to the bare > and < chars.
- ADDED: \textless and \textgreater emit < / > entities PlDoc now
escapes < / > as \textless / \textgreater (so they're safe inside
hyperref PDF bookmark strings); teach ltx2htm to translate them to
the matching HTML entities. Without this they showed up as "Failed
to translate" warnings on every chapter that mentioned a class with
angle brackets in its prose (369 in our reference manual corpus).
- ENHANCED: xpce ltx2htm rules for the .md-driven reference manual -
Add cmd declarations and HTML emitters for \classinstvar and
\errid (introduced in TeX/xpce.sty for the .md-driven
reference manual). - Switch the cross-reference anchor scheme for
\class{X} / \classs{X}
from "class:X" to "sec:class-X" so the section labels PlDoc emits
from "# class X {#class-X}" headings resolve as link targets.
Strip underscores from the link target to match PlDoc's
delete_unsafe_label_chars/2 behaviour on the corresponding
\label{...} statement (so "class foo_bar" links to
"sec:class-foobar"). - Switch from
autoload(library(ltx2htm/latex2html)) to
use_module(latex2html) so sty_xpce.pl loads cleanly when invoked
outside an installed environment with the matching library path
alias.
[May 12 2026]
- FIXED: #8 Handling e.g.,
\\const{\%h}
[May 10 2026]
- RENAME: ltx2htm.doc -> ltx2htm.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- ENHANCED: ltx2htm: TOK_VERB / TOK_VERBATIM use UTF-8 round-trip The
verbatim/verb code paths still passed body strings through PL_CHARS /
PL_STRING (Latin-1), which double-encoded UTF-8 bytes when combined
with the new REP_UTF8 output side: a literal \verb= 'X²' = in source
rendered as 'X²' in HTML.
- ENHANCED: Make ltx2htm UTF-8 aware The tokenizer used to read .tex
files as raw bytes and warn for every byte >= 128, and the HTML writer
used PL_atom_chars which is Latin-1 only. As a result, .tex authors
had to route every non-ASCII glyph through urldef in pl.sty.
[Apr 30 2026]
- ENHANCED: Render non-ASCII urldefs as numeric HTML entities Adds
a block of \urldef{\Sname}\satom{<char>} entries to pl.sty for the
super-/subscript digits and a handful of math and typographic symbols
(≤, ≥, «, », €, ·, Dž), registers each \Sname in pldoc.cmd
as a known no-arg command, and adds explicit cmd/2 handlers in
sty_pldoc.pl that emit numeric HTML entities for these names.
Package mqi
[May 10 2026]
- RENAME: mqi.doc -> mqi.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Sep 27 2025]
- PORT: Search for python3 executable to try python3 and then python.
Modern systems are beginning to install only
python, which is
Python3.
Package nlp
[May 10 2026]
- RENAME: nlp.doc -> nlp.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Feb 6 2026]
- FIXED: Crash during cleanup on Windows This patch replaces the
pthread specific handling of the thread specific stemmers with
__thread__ and using Prolog's ``PL_thread_at_exit'' to clean
stemmers for terminated threads.
Package odbc
[May 10 2026]
- RENAME: odbc.doc -> odbc.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3 Also replaces local
error functions with calls to PL_*_error()
Package paxos
[May 10 2026]
- RENAME: paxos.doc -> paxos.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package pcre
[May 10 2026]
- RENAME: pcre.doc -> pcre.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package pengines
[May 10 2026]
- RENAME: pengines.doc -> pengines.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package pldoc
[Jun 24 2026]
- ADDED: doc_man: integrate xpce reference manual into PlDoc Make
xpce class members and their manual pages reachable from PlDoc:
hook xpce into the navigation tree, resolve xpce in-page links
(#class-... and #sec:...), render ivar object links, and add
pldoc_synopsis_spec/2 to rewrite the pce_principal synopsis
to
library(pce).
[Jun 23 2026]
- ADDED: Add a history section to a predicate block The relevant
history facts are extracted from git. This information is collected
at build time if the cmake option
-DCHANGELOG=ON is given.
[Jun 21 2026]
- ADDED: library(pldoc/doc_changes): machine readable access
to changelog. This library is installed when the cmake option
-DCHANGELOG=ON is given. That also triggers building the database
when SWI-Prolog is built.
[Jun 9 2026]
- ENHANCED: accept
xpce(C, ivar, N) in manindex.db Recognise the new
"ivar" kind so xpce class instance variables indexed via sty_xpce's
classivar emission survive the round-trip through atom_to_object/2.
- ENHANCED: swi_man_xpce ->
swi('xpce/man/refmanual') The xpce
refman HTML is now staged and installed under the xpce home
tree (swi('xpce/man/refmanual') = <prefix>/lib/swipl/xpce/man/
refmanual/), alongside the rest of the xpce data files (bitmaps,
prolog/, appl-help/, man/faq/, ...). Update the file_search_path so
save_man_index/0 picks up the .html chunks from the new location and
manual_object/5 returns file paths that actually exist after install.
[Jun 7 2026]
- FIXED: {#anchor} parser accepts `_' as a token The wiki tokenizer
breaks
{#object-_not_returned} into ['{', '#', w(object), -, '_',
w(not_returned), '}'], but the section-label parser's label_cont
rule only accepted - and w(Name) tokens, dropping anchors
that contain a _ immediately after a separator. Add an explicit
clause for the bare _ token so such anchors are recognised.
[Jun 6 2026]
- ENHANCED: index XPCE class-member entries in manindex.db Recognise
xpce(Class,Kind,Name) compounds emitted by the ltx2htm xpce backend
(see sty_xpce.pl) so the new XPCE refman HTML lands in the same
machinery PlDoc uses for the core manual:
- FIXED: escape < > with \textless / \textgreater instead of math mode
print_char/2 used to emit \$<\$ and \$>\$, which break hyperref's
PDF bookmark string generation ("Token not allowed in a PDF string:
removing 'math shift'") and don't survive any subsequent text-mode
context cleanly. Switching to the text-mode commands lets hyperref
embed them in bookmarks unchanged and renders identically in normal
text.
- FIXED: tags environment uses ##1 to escape nested newcommand
parameter \newenvironment{tags}{...}{...} previously had
\newcommand{\tag}[1]{\item[#1]} inside the begin body. Modern LaTeX
interprets the bare #1 as a parameter of the surrounding environment
(which has none), giving "Illegal parameter number in definition
of \tags". Doubling to ##1 lets the inner \newcommand reach its
own parameter.
- FIXED: @tag block no longer swallows following section headers
rest_tag/4 used to read continuation lines for a tag until the next
@tag or end of input, which meant a following ## section heading became
part of the last tag's value. Now also terminates at any section header
(twiki or markdown atx/setext).
[May 18 2026]
- CLEANUP: As we go through luatex, we no longer need utf8proc as
dependency
[May 10 2026]
- FIXED: help/1: tell SGML parser the manual is UTF-8 load_man_object/4
opens the HTML file in binary mode (so byte offsets stay meaningful
for seek/3) and feeds the bytes to sgml_parse/2 directly. Without an
explicit encoding option the parser defaults to ISO-8859-1, so UTF-8
multi-byte sequences in the manual were read as Latin-1 codepoints
—
help(unicodesyntax) then displayed X² as X² and so on.
- RENAME: pldoc.doc -> pldoc.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Apr 30 2026]
- DOC: Add urldefs for non-ASCII Unicode characters used in manual
prose Adds a block of \urldef{\Sname}\satom{<char>} entries for the
super-/subscript digits and a handful of mathematical and typographic
symbols (≤, ≥, «, », €, ·, Dž). This lets doc2tex.pl in
swipl-devel translate `{<char>}` in .doc to
{\Sname} in .tex,
keeping the .tex ASCII-only and avoiding the non-ASCII warnings from
ltx2htm's tex.c reader.
[Apr 22 2026]
- ENHANCED: doc_latex translates common Unicode punctuation to LaTeX
pdflatex under T1 encoding rejects non-ASCII bytes, so any PlDoc
comment containing an em-dash, arrow, fancy quote or ellipsis produced
hundreds of "non-ASCII character" warnings and the glyph often did
not render.
[Nov 19 2025]
- FIXED: Emit LaTeX for markdown code text that holds
% in tables.
[Nov 3 2025]
- FIXED: Load when threads are disabled.
[Oct 27 2025]
Package plunit
[May 10 2026]
- RENAME: plunit.doc -> plunit.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Dec 10 2025]
- FIXED: Allow for concurrent loading of unit test files.
[Oct 27 2025]
Package protobufs
[May 10 2026]
- RENAME: protobufs.doc -> protobufs.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Mar 10 2026]
- CLEANUP: reformat with pprint:print_term (changed whitespace)
- CLEANUP: fix some typos
[Feb 27 2026]
- CLEANUP: remove absolute path from generated _pb.pl, fix typos
[Feb 22 2026]
- TEST: fixed typo that prevent interop test from running
- PORT: python3 might not be present and Python is not needed to build
the package
[Feb 19 2026]
- TEST: ensure tests are run sequentially
- ENHANCED: protoc 3.21.12 (unverified_lazy field)
Package redis
[May 10 2026]
- RENAME: redis.doc -> redis.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package semweb
[May 10 2026]
- RENAME: semweb.doc and rdflib.doc -> .plx (LaTeX manual source)
Update pkg_doc SOURCES reference. Co-Authored-By: Claude Opus 4.7
(1M context) <noreply@anthropic.com>
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package sgml
[May 10 2026]
- RENAME: sgml.doc -> sgml.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Dec 7 2025]
- CLEANUP: Use snprintf to avoid deprecation warnings
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package ssl
[Jun 17 2026]
- TEST: regression for #175 ecdsa_sign/4 + ecdsa_verify/4 Sign
and verify with a hard-coded prime256v1 SEC1 PEM key, and check
that a verification of tampered data fails. Also asserts that
load_private_key/3 returns the expected ec/3 shape, since the
load_private_key/3 path was broken by the same OpenSSL 3 cleanup that
broke ecdsa.
- FIXED: #175 ecdsa_sign/4 and ecdsa_verify/4 with OpenSSL 3 On OpenSSL
3, ecdsa_sign/4 always failed silently and any verification produced
wrong results. Two bugs in the USE_EVP_API path:
- FIXED: load_private_key/3 corrupting EC keys with OpenSSL 3 In the
USE_EVP_API path,
unify_ec() left priv_bn uninitialised when passed
to EVP_PKEY_get_bn_param(), queried OSSL_PKEY_PARAM_GROUP_NAME as
an octet string (it is UTF-8), and never checked any return values.
The resulting ec(Priv,Pub,Curve) term contained a garbage curve
name and an undefined private-key field, breaking every subsequent
ecdsa_sign/4 and ecdsa_verify/4 call.
[May 10 2026]
- RENAME: ssl.doc and crypto.doc -> .plx (LaTeX manual source) Update
pkg_doc SOURCES reference. Co-Authored-By: Claude Opus 4.7 (1M context)
<noreply@anthropic.com>
[Apr 14 2026]
- PORT: Update for openssl 4.0
[Mar 15 2026]
- CLEANUP: Remove dead conditional code. Now only support OpenSSL
1.1.1 and LibreSSL.
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package stomp
[May 10 2026]
- RENAME: stomp.doc -> stomp.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package sweep
[May 10 2026]
- RENAME: sweep.doc -> sweep.plx (LaTeX manual source) Update pkg_doc
SOURCES reference. Co-Authored-By: Claude Opus 4.7 (1M context)
<noreply@anthropic.com>
Package swipy
[Jun 25 2026]
- FIXED: Respect
const char* return from PyUnicode_AsUTF8AndSize()
Old code changed the / into r and back. Should be safe in a single
thraeded context, but might cause problems with free threaded Python.
[Jun 24 2026]
- FIXED: #19 pip/uv install toggling for janus-swi 1.5.2 The setup.py
was duplicating fields already declared in pyproject.toml (author,
author_email, url, description, license). With recent setuptools
this causes the generated metadata to mark them as "Dynamic: author"
and "Dynamic: home-page" (Metadata-Version 2.2), which some pip/uv
versions handle by writing partial RECORD files. The next install
then complains the package is distutils-installed and cannot be
uninstalled, producing the alternating succeed/fail pattern reported
in packages-swipy#19 and Popper#144.
[May 10 2026]
- RENAME: swipy.doc -> swipy.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Package table
[May 10 2026]
- RENAME: table.doc -> table.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Dec 7 2025]
- FIXED: Windows: close memory leak after error.
- CLEANUP: use snprintf to avoid deprecation warnings
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package tipc
[May 10 2026]
- RENAME: tipc.doc -> tipc.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 23 2026]
- CLEANUP: Modernise exception handling, use
bool and update PlDoc
- CLEANUP: avoid -Wconversion warnings
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
Package utf8proc
[May 29 2026]
- FIXED: install additional file in tests folder needed for the runtime
unit tests
[May 17 2026]
- ADDED: library(uniname) exporting unicode_name/2 Wraps the compact
name table in a SWI plugin (uniname4pl.c) and a library (uniname.pl).
unicode_name(?CodePoint, ?Name) is nondet: (+,-) is the semidet forward
name, (-,+) the semidet reverse lookup, and (-,-) enumerates every
named code point on backtracking via a stateful foreign iterator
(no quadratic blow-up; >100k solutions in ~50 ms). Registered as
the utf8proc:uniname ctest.
- ADDED: Prototype compact Unicode code-point -> name table Adds
etc/gen_uniname.pl, the generated uniname_data.{c,h} and a small
decoder (uniname.c) implementing the ICU / GNU libunistring scheme:
algorithmic ranges (Hangul synthesised from Jamo; CJK/Tangut and every
PREFIX-<cphex> family derived from the code point) carry no per-code-
point data, and the remaining ~34.6k names are stored as a flat LEB128
stream of a code-point delta plus frequency-ordered word ids into a
shared word table.
[May 11 2026]
- TEST: extend confusable_demo.pl with non-predicate-name cases
Adds clauses that put confusable atoms in argument positions, in
nested compound functors, in list elements, and in clause bodies,
so list_confusable_identifiers/0 exercises every code path of its
sub_term/2 walk:
- CHANGE: move list_confusable_identifiers/0 into library(check)
The hook was duplicated from library(check)'s existing list_*
checkers and didn't share their per-atom source-location walking.
Move the predicate to library(check) directly, guarded by
:-
if(exists_source(library(unicode_security))), so it uses the
same prolog_program_clause/2 + message_context/4 infrastructure as
list_strings/0 and friends.
- ENHANCED: hook list_confusable_identifiers/0 into library(check)
Adds a linter that walks predicates of every user-class module and
flags two UTS #39 concerns:
- DOC: fix PlDoc Markdown conventions in unicode_security.pl PlDoc
Markdown is not LaTeX:
- CHANGE: unicode_script_extensions/2 and unicode_identifier_status/2
are semidet Follow-up to commit 8f00f14, applying the same "no info ->
fail" rule to the remaining per-code-point predicates:
- CHANGE: unicode_script/2 and unicode_identifier_type/2 are now semidet
Previously both predicates absorbed missing entries with a default:
unicode_script/2 fell through to 'common' for unassigned code points,
and unicode_identifier_type/2 returned [] for code points without a
listing in IdentifierType.txt. Both also raised a domain_error for
code points outside U+0000..U+10FFFF.
- CHANGE: don't vendor UCD source files; add fetch instructions The
generator etc/gen_uts39.pl runs only on demand (regen-uts39 target)
and the checked-in uts39_data.{c,h} are authoritative for default
builds, so keeping the .txt inputs in the repo just bloats history.
Remove them, add data/*.txt to .gitignore, and add a data/README.md
that says where to obtain them.
- ENHANCED: unify range tables as (start, len, value) All UTS #39 / UAX
#24 range tables (script, scx, idstatus, idtype) now share one type:
- DOC: predicate docstrings and README paragraph for unicode_security
PlDoc comments for each exported predicate in unicode_security.pl,
plus a one-paragraph README pointer to library(unicode_security)
and the regen-uts39 workflow.
- TEST: add PLUnit suite for library(unicode_security) Covers all
eight predicates: unicode_script/2, unicode_script_extensions/2,
unicode_identifier_status/2, unicode_identifier_type/2,
unicode_skeleton/2, unicode_confusable/{2,3},
unicode_resolved_scripts/2 and unicode_restriction_level/2.
- ENHANCED: implement UTS #39 runtime in library(unicode_security)
Implements the runtime algorithms over the generated tables and
exports the public Prolog API:
- ENHANCED: add UTS #39 / UAX #24 generator and generated tables
etc/gen_uts39.pl reads the vendored UCD files under data/ and writes
uts39_data.{c,h}. The output is deterministic, so re-running the
generator on unchanged inputs produces a zero diff.
- ENHANCED: scaffold library(unicode_security) plugin Adds an empty
second plugin alongside unicode4pl in the same package. The plugin
compiles, the Prolog module loads, the doc section is generated and
linked into utf8proc.tex. No predicates yet; this is the integration
scaffold for the upcoming UTS #39 implementation.
- ENHANCED: vendor UTS #39 and UAX #24 data files for unicode_security
Source files for the upcoming library(unicode_security) generator:
[May 10 2026]
- RENAME: utf8proc.doc -> utf8proc.plx (LaTeX manual source)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- PORT: Fix detection and avoid dependency on
ssize_t
[May 4 2026]
- FIXED: Safe unification for unicode enum values.
[Apr 30 2026]
- ASAN: Add obsolete boundclasses The change is needed to establish the
1:1 correspondence to the boundclasses in the original utf8proc.h.
Prevents an ASAN error on my system.
[May 1 2026]
- TEST: Migrate normalize-hook tests to the unicode_atoms vocabulary
Rename the suite from utf8proc_normalize_hook to utf8proc_unicode_atoms
and reshape its tests to use the multi-valued unicode_atoms policy
that replaces the boolean unicode_normalize flag and
normalize(true)
read_term option. Cover all four modes (accept / nfc / error /
reject), stream_property/2 read-back, the flag-driven default, the
writeq combining-mark force-quoting (independent of this library),
and Trojan-source bidi-override rejection in unquoted atoms, quoted
atoms, and via \u escape bypass.
- DOC:
category(Cat) using Upper-lower
[Apr 30 2026]
- ENHANCED: Register utf8proc as the kernel's Unicode NFC hook
Loading library(unicode) now installs an NFC normaliser into
the SWI-Prolog kernel via PL_atom_normalize_hook(), enabling the
normalize(true) option of read_term/2,3 and read_clause/2,3 and the
default value of the unicode_normalize Prolog flag. The callback
uses utf8proc_map with STABLE|COMPOSE in place: NFC is always shorter
than or equal to the input, so the caller's buffer suffices and there
is no malloc/free dance. Also extend test_utf8proc.pl with a new
utf8proc_normalize_hook suite covering the round-trip, the per-call
option vs. flag-default override, the quoted-atom isolation rule,
and the writer's combining-mark force-quoting.
- DOC: Cross-reference unicode_syntax_version Prolog flag Note in
unicode_version/1 that the Unicode version reported by the library
may differ from the version of the SWI-Prolog source syntax classifier
exposed via the new read-only Prolog flag unicode_syntax_version.
[Apr 23 2026]
- SANDBOX: Declare the Unicode API as safe.
[Apr 22 2026]
- BUILD: Probe optional libutf8proc features and gate on HAVE_UTF8PROC_*
Older distro libutf8proc (Ubuntu LTS) ships a version that
predates charwidth, ambiguous_width, indic_conjunct_break,
the EXTENDED_PICTOGRAPHIC boundclass, and single-codepoint case
mappings. The binding now probes those at configure time via
check_c_source_compiles / check_symbol_exists and emits HAVE_UTF8PROC_*
macros in config.h; unicode_property/2 branches and the associated
foreign registrations are guarded by the matching #ifdef, so the
binding compiles against any utf8proc version from 2.4 onwards.
- TEST: Full regression suite for library(unicode) Replace the stub
test_utf8proc.pl with a plunit suite covering the features introduced
in the previous commit:
- ENHANCED: Review unicode_property/2, add grapheme and casefold APIs
Rewrite unicode4pl.c around the current utf8proc property struct
and use SWI-Prolog's public PL_type_error / PL_domain_error /
PL_resource_error helpers and
bool return types.
- BUILD: Use external libutf8proc via pkg-config The package used to
bundle utf8proc.c (plus its generated utf8proc_data.c), a local
Makefile, a Ruby gem wrapper, and PostgreSQL binding code —
all inherited from a pre-Julia upstream that no longer matches the
maintained library. utf8proc is now maintained by the Julia project
at https://github.com/JuliaStrings/utf8proc and ships in every major
package manager, so there is no reason to vendor it here.
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
[Dec 23 2025]
- FIXED: #1 UBSAN: adding to NULL pointer.
[Nov 14 2025]
Package xpce
[Jun 24 2026]
- DOC: Update ->fill references to reflect colour-only support The
->fill instance variable on box, arc, arrow, circle, ellipse and
path is implemented as a colour (with the special names foreground
and background); image/bitmap fill patterns are no longer supported.
The manual still described filling with images, patterns and bitmaps.
[Jun 23 2026]
- BUILD: Fix building xpce docs when there is no display
[Jun 16 2026]
- DOC: ->initialise / ->_execute for classes \\== and ?, class spatial.
- FIXED: HTML manual lookup for symbolic xpce classes (==, :=, ...)
The runtime extracts the live class name from the xpce object,
but the HTML index and anchors are keyed on the safe file-base form
(equal, binding, noteq, ...). Map class names through classmap on
the way out of object_spec so
manpce(==) -> click on a method finds
the matching <dt>/<dd> chunk.
[Jun 15 2026]
- ADDED: Support
edit(class(Class)) to edit built-in xpce classes.
- FIXED: black fringes left when graphicals are moved Inflate the dirty
rectangle reported by ->changed_image by 1 pixel in each direction.
Antialiased strokes and primitives drawn at non-integer coordinates
can paint just outside the integer bounding box; without slop, those
pixels are not repainted when the graphical moves, leaving fringes.
- FIXED: heap-use-after-free in updatePointedDevice during event dispatch
Use for_chain instead of for_cell for the three chain iterations
in updatePointedDevice. generateEventGraphical can dispatch Prolog
handlers that mutate the chain (e.g. an ->expose on a connection
removes a cell from dev->graphicals), which for_cell cannot tolerate.
- ADDED: Epilog key bindings
Shift-ctrl-{V,C} for copy/paste
- ENHANCED: Multi-file drop on PceEmacs opens each file in a new tab
Drop one or more files on a PceEmacs editor to open each as a new tab.
Show a faint centered hint during the drag.
- ENHANCED: Multi-file drop on Epilog with overlay feedback Drop one or
more files on an Epilog terminal to consult all Prolog source files
in a single consult/1 call. Show a faint centered hint during the
drag and briefly flag any non-Prolog files in red.
- ADDED:
library(pce_drop_target) for SDL3 drop overlays A small helper
that turns the SDL3 drop_position / drop_file / drop_complete lifecycle
delivered to an xpce graphical into a single callback receiving the
list of dropped OS paths, with a centred bordered hint overlay shown
on the target's window during the drag. Transient state lives in
xpce object attributes, so consumers need no class variables.
[Jun 14 2026]
- CLEANUP: misc Smaller, independent cleanups that surfaced during the
larger work:
- ADDED: Epilog XPCE menu with the core manpce/0 tools A new "XPCE" popup
before Help in Epilog's menu bar covers the File/Demo programs entry,
all Browsers entries and the first three Tools entries from manpce/0.
All tool entries route through the existing send(@manual, start_tool,
Tool) hook, which creates @manual silently (no expose), so users do
not have to call manpce/0 first. "Inspect GUI hierarchy" moves from
the Tools menu to the new XPCE menu.
- ADDED: OS file/text drag-and-drop events via SDL3 Surface SDL3
file/text drop events as xpce events. src/sdl/sdlevent.c translates
SDL_DROPFILE / SDL_DROPTEXT into a pair of new event names that the
kernel and class event recognise. prolog/demo/dragdrop_file.pl ships
a small drag-and-drop demo and the pce_demo entry registers it in
the demo set.
- CLEANUP: drop image ->invert, ->invert_pixel, ->and, ->or, ->xor Five
send-methods on class image were stubs that did nothing. Remove the
SM entries, the C bodies (invertImage, invertPixelImage, opImage,
orImage, andImage, xorImage), the matching backend stubs r_op_image
and r_complement_pixel in sdldraw, and the unused T_image_atADpointD
type decl. image<-rotate documentation is updated to advertise the
figure + transform idiom (see the markdown sources commit).
- CLEANUP: reduce dialog_item look domain to {xpce,win} The look slot
on class dialog_item used to admit four values: open_look, motif,
win and gtk. open_look and motif are legacy look-and-feels nobody
runs anymore; gtk was the working Unix default and is renamed to xpce
(a neutral name not tied to a host toolkit). The domain narrows to
{xpce,win}, with xpce default on non-Windows and win on Windows.
- REMOVED: class c, class c_pointer and the public C/C++ embedding API
xpce now embeds only via pl2xpce.so; the old C/C++ host classes and
the XPCE_* embedding API are unused and removed.
- CHANGED: manpce/0 modernization for the markdown manual The manpce/0
tool moves from the .doc card database to the markdown-generated HTML
chunks served by
library(pce_html_manual). The main changes:
- ENHANCED: HTML manual viewer (pbox selection, code blocks, scroll
clamp) doc_window grows the affordances needed to host the new
HTML manual:
- REMOVED: legacy .doc reference manual sources Drop man/reference/*.doc
-- the old binary-encoded card database that backed the .doc-format
reference manual. Replaced by the markdown sources under
man/refmanual/md/ that the new pipeline renders into the manpce/0
card viewer and the published HTML/PDF manuals.
- ADDED: markdown reference manual sources Add man/refmanual/md/*.md
as the new home for the xpce reference manual. Each class, group of
error codes and special section gets a PlDoc-flavoured markdown file
with stable {#class-<name>} (and similar) anchors that the new build
pipeline turns into both the LaTeX manual and the HTML chunks served
to the manpce/0 card viewer.
- BUILD: markdown-based reference manual pipeline Introduces a refman
pipeline that renders the xpce reference manual from markdown sources
via PlDoc (with xpce-specific extensions) into the existing TeX/HTML
manual:
[Jun 4 2026]
- ADDED: London tube demo Interactive map of the London tube network:
zoom and pan, search stations, toggle lines on or off, hover to
highlight every line through a station or segment. Demonstrates
figure transforms, recognisers, the report system and connection
routing via handles.
- ADDED:
library(pan_zoom) Reusable recogniser that handles
wheel-zoom-around-cursor and left-drag pan by editing the receiver
figure's transform. A global @pan_zoom_recogniser is provided for
class-wide reuse.
[Jun 2 2026]
- FIXED: terminal_image: initialise <-armed_link to @off The slot has
type bool (not bool*), so the implicit @nil left at construction
tripped the object base check.
- FIXED: font: align C struct field order with vardecl The fontobj
C struct ordered fixed_width before ex/avg_char_width, while the
vardecl ordered ex/avg_char_width before fixed_width. Since slot
indices come from the vardecl but
assign() writes through the C field,
slot values landed at the wrong index, producing object base check
warnings such as `Illegal value in slot ex: off and Illegal value
in slot fixed_width: 11`.
- FIXED: transform: silence maybe-uninitialized warning under -O2
tuple_to_nums() only assigns *first/*second on success and TRY()
returns from initialiseTransform() on failure, so the success path
is well-defined. GCC's -Wmaybe-uninitialized can't see through the
macro and warns at -O2. Initialise the locals to ZERO to silence it
without changing behaviour.
- ENHANCED: demo: interactive opacity demo Adds a pcedemo entry `Opacity'
that opens a frame with six labelled cells and a single slider driving
the opacity of every foreground graphical at once. The cells cover:
- DOC: userguide: document <-opacity on graphical Adds a short Opacity
section to the Simple graphics chapter, explaining the group-composite
semantics on a device or figure and contrasting it with per-pixel
colour alpha. Points at the demo for the visual comparison.
The class-card database under man/reference remains untouched; the
slot's own docstring is reachable via manpce.
- ENHANCED: graphical: composite with alpha when <-opacity < 1.0
RedrawArea now wraps the per-class redraw in a cairo group when the
graphical's opacity is below 1.0, then paints the group onto the parent
surface with that alpha. For a single primitive this is equivalent
to using an alpha-bearing colour; for devices and figures it gives
the correct CSS-style opacity, where overlapping children composite
fully opaque first and the whole group is then blended.
- ENHANCED: sdldraw: add r_push_group / r_pop_group_with_alpha Thin
wrappers around cairo_push_group / cairo_pop_group_to_source +
cairo_paint_with_alpha. Used by the next commit to composite a
graphical's drawing onto its parent with a single alpha modulation,
giving correct CSS-style opacity for overlapping children of a group.
- ENHANCED: graphical: add <-opacity slot (Num, 0.0..1.0, default 1.0)
Per-graphical opacity for compositing. The slot is declared on class
graphical so it applies uniformly to primitives, dialog items, devices
and figures. Values outside [0.0, 1.0] are clamped on assignment.
Rendering itself is wired up in a follow-up commit; this change only
adds the slot, the accessors and request-redraw on change.
- FIXED: Image viewer demo.
- ENHANCED: demo/transform: use figure shortcuts and a single rebuild
Each slider now sends `->rebuild' instead of a per-slider callback;
->rebuild reads all three slider values from the dialog and composes
the scene's transform via the new figure shortcuts (->translate,
->scale, ->rotate, ->shear), starting from a fresh identity.
- FIXED: transform: validate tuple slots in ->initialise
scale :=
tuple(Sx, Sy) and `shear := tuple(Kx, Ky)' previously cast the tuple's
slots straight to Num without checking; passing a non-numeric value
silently produced a garbage matrix. Add a small tuple_to_nums()
helper that runs each slot through TypeNum (so any xpce-convertible
numeric value is accepted) and raises the standard unexpected-type
error otherwise.
- ENHANCED: figure: ->translate / ->scale / ->rotate / ->shear
Composing transform shortcuts on class figure. Each method composes
the corresponding operation into the figure's transform, allocating
an identity transform on demand if the figure currently has none.
The same `self := self * Op' rule as on class transform applies,
so calling these in sequence pre-composes from the inside out.
- ENHANCED: transform: rotate/scale/shear initialise; ->set for
coefficients Replaces the 6-coefficient ->initialise with a high-level
form:
[Jun 1 2026]
- BUILD: install demo/transform.pl with the demo data files
XPCE_DATA_prolog_demo is an explicit list; without this entry
demo/transform.pl is not copied to the install tree and pcedemo fails
with `source_sink
demo(transform) does not exist'.
- ENHANCED: pce_demo: register figure->transform demo Adds the Transform
entry to the XPCE demo browser (pcedemo/0) so the new demo/transform.pl
shows up in the standard demo list.
- FIXED: handle.c: drop unused Int x, y from getXYHandle Leftover
declarations from the pre-transform-aware version; the rewrite uses
hx/hy and gx/gy only.
- FIXED: transformed figure: pass children pre-transform area for
paint RedrawTransformedChildren handed each child the dirty rect
coming from the parent, which after EnterRedrawAreaDevice is in the
figure's POST-transform local coord (where the rotated pixel AABB
lives). But each child's gr->area slot is in PRE-transform local
coord, so the overlap test in RedrawArea mis-clipped: children whose
pre-transform position fell outside the post-transform AABB (e.g. a
text label below the bounding box that rotates to above it at 180°,
or any child past a heavy scale-down) were silently skipped — text
vanished at rotate ±180° and at scales below 50%.
- FIXED: figure->transform: always repaint, even on same object The
setter previously short-circuited when the assigned transform was the
same object as the current one. That broke the common pattern of
mutating a single transform in place (e.g. from a slider callback)
and re-assigning it: the figure kept the cached bounding box and
skipped the repaint.
- ENHANCED: demo/transform.pl: live figure->transform demo Opens a
window with a small scene (yellow box, red diagonal, green circle,
text label) inside a figure that carries an editable transform.
Sliders below the picture drive rotation (-180..180), scale (25..250%),
and horizontal shear (-100..100%) around the scene's centre; a reset
button restores identity.
- ENHANCED: absolute area, handles, flash route through transforms
graphicalToDeviceCoord / graphicalToDeviceAreaAABB compose the affine
that maps a graphical's local coord into any specific ancestor device's
children-coord, taking figure->transforms along the chain into account.
[May 31 2026]
- ENHANCED: damage propagation through transformed figures Adds
deviceLocalAreaToWindowAABB to coords.c (corner-by-corner walk through
the device chain producing an outward-rounded integer AABB).
- ENHANCED: events: route through transform-aware coord mapping
get_xy_event_device and get_xy_event_graphical now consult the new
windowToDeviceLocalCoord / windowToGraphicalCoord helpers whenever
the device chain contains a non-identity figure->transform. An event
delivered to a child of a rotated or scaled figure now arrives in
the child's actual local frame instead of being computed with the
un-transformed integer offset.
- ENHANCED: graphical: transform-aware coord mapping Adds
src/gra/coords.c with a small 2D affine composition that walks the
device chain from a graphical (or device) up to its window, applying
figure->transform at each step. Five C-level entry points are exposed:
- TEST: Add tests/test_figure_transform.pl Plunit-style tests for class
figure's transform slot and bounding box semantics: identity fast-path,
rotation 90/180/270, scale (uniform and non-uniform), translate-only,
empty figure, multiple children, border interaction, and recompute on
transform set/clear/replace. Also verifies that <-local_area stays
in un-transformed children-coords as the transform changes.
- ENHANCED: figure: parent-coord bounding box follows transform A
transformed figure's <-area is now the AABB of the transformed
children, while a new <-local_area slot keeps the un-transformed
children union in figure-local coordinates. computeBoundingBoxFigure
first lets computeBoundingBoxDevice fill area as today, then projects
the local box through f->transform when present and re-rounds the
result to integer.
- ENHANCED: figure: paint children under f->transform Adds
r_push_transform / r_pop_transform to the SDL backend. Pushing absorbs
the current integer pen offset into the cairo transform, then composes
the figure's affine matrix and resets the integer offset to zero so
that r_* primitives feed their coordinates directly into the matrix.
- ENHANCED: figure: add optional transform slot Adds a transform slot to
class figure, default @nil, with a setter that requests recompute and
full repaint when changed. Painting, hit testing and bounding-box
math will start consulting the transform in the following commits;
for now any figure without a transform behaves exactly as before.
- TEST: Add tests/test_transform.pl Plunit-style tests for class
transform covering construction (defaults, explicit coefficients,
set/copy/identity), the basic ops (translate, scale, rotate, shear),
cairo-style composition order, invert/inverse (including singular
detection and round-trip identity), and <-apply on points and areas.
- ENHANCED: Add transform class for 2D affine transformations A
`transform' instance holds a 2x3 affine matrix (xx, xy, yx, yy, tx,
ty) stored as Num slots and provides methods to compose translation,
scale, rotate, shear and matrix multiplication, plus an inverse and
a <-apply that maps a point or the AABB of an area through the matrix.
[Jun 2 2026]
- FIXED: Graphical ->flash: account for window scroll_offset The flash
overlay was rendered in the window's logical (client) coordinate
system, while Cairo draws graphicals translated by sw->scroll_offset
(see
d_window() / Translate()). Windows whose origin is not at (0,0)
-- e.g. a workspace with origin (0, h/2) -- made the flash land at the
wrong screen position. Apply the same scroll_offset before passing
the rect to flashWindow().
[Jun 1 2026]
- FIXED: ws_event_in_subwindow: translate ev->x/ev->y to frame
coordinates When called with a frame argument, the function descended
event_window() using ev->x/ev->y as if they were frame-relative.
They are relative to ev->window though, which during a drag stays
on the original receiver (the mouse_tracking_window). The position
was therefore shifted by the tracking window's offset in the frame,
so dragging out of e.g. the top-left subwindow into the top-right
kept reporting the top-left.
- FIXED: SDL: stale modifier bit could leak into mouse clicks After
a Ctrl-Shift-<key> binding (e.g. Ctrl-Shift-O to split an Epilog
window), the next left click was treated as Shift-click and extended
the selection instead of starting a new one.
- ENHANCED: demo/arc: show three arrowed arcs in the arrows cell
Demonstrates that the wing midpoint lands on the arc across a range
of curvatures and sweep directions.
- ENHANCED: arc: align attached arrow wings with the arc's curvature The
arc's first_arrow/second_arrow used to be aimed along the tangent at
the endpoint, so the wing line — l1 pixels behind the tip — sat on
a straight line that the arc had already curved away from. The visible
offset was about l1^2/(2*radius) (≈1.9px for the demo arc).
- ENHANCED: arrow: accept Num for tip/reference and wing/length
pointsArrow, ->tip_x/y, ->reference_x/y, ->length, ->wing and the
corresponding getters now declare and pass Num rather than Int,
so arrow geometry set programmatically (e.g. from class arc) keeps
sub-pixel precision end-to-end. Round the bounding area set by
->compute with floor/ceil so the area still encloses the triangle
when the points are non-integer.
- ENHANCED: arc: carry sub-pixel precision through geometry and rendering
points_arc, RedrawAreaArc, includeArrowsInAreaArc, computeArc and
the <-start/<-end getters now use double for the computed sx/sy/ex/ey
coordinates and pass them to attached arrows via
toNum() without an
integer round-trip. r_arc takes its bounding rectangle and angles as
double, so drawArcGraphical (->draw_arc) and the arc class no longer
truncate angles to int before handing them to cairo. The bounding
area set on the arc is still rounded — out to floor/ceil with the
existing 1-pixel margin — because Area itself is integer.
- ENHANCED: demo: add an arc gallery demo Shows the main usage patterns
of class arc — angles, close modes, ->points, ->connect_angle,
arrows, elliptic <-size, over-wound sweep, CW vs CCW direction,
and a tiny pie chart.
- ENHANCED: arc: use Num for start_angle and size_angle Class arc
stored its two angle slots as Real. The Num type is a better fit:
it accepts both integers and floats, returns naturally to Prolog as a
number, and avoids the heavier Real object identity. The on-the-wire
behaviour is unchanged.
- FIXED: r_arc: pass arc size_angle correctly to cairo The 2nd integer
argument to r_arc has always been size_angle (relative sweep),
per the X11/xpce convention shared by all callers. The SDL/cairo
backend treated it as an absolute end angle and ignored that cairo's
angle direction is opposite to xpce's (cairo angles go clockwise on
screen because cairo's y axis points down). As a result class arc
and ->draw_arc drew unrelated arcs.
[May 31 2026]
- ENHANCED: terminal: strikethrough support (SGR 9 /
Style->strikethrough) text_char gains a strike bit (from the reserved
word in the bitfield, no struct growth). SGR 9 sets it, SGR 29 clears
it. paint_chunks threads the resolved strike+strike_texture pair to
a new r_strikethrough in sdldraw, drawn through Pango's strikethrough
metrics (pango_font_metrics_get_strikethrough_{position,thickness}
stored on WsFont next to ul_*).
- ENHANCED: terminal: dotted underline by default for hyperlinks
(line-texture) Style->underline now accepts a texture_name
(none/dotted/dashed/dashdot/ dashdotted/longdash) on top of the
existing Bool|Colour, both in the class declaration and in the
initialise argument vector. r_underline gains a `Name texture`
parameter so the dash pattern survives until the line is drawn
(previously hard-coded to none). paint_chunks threads the resolved
texture from effective_style_for through to r_underline.
- ENHANCED: terminal: per-link armed style (link_armed_style) Add a
link_armed_style slot on TerminalImage (default: blue + underline,
same as link_style for now) and wire it into the paint loop. Hover
detection tracks the specific href node the mouse is over on b->
armed_href;
effective_style_for(b, flags, armed) overlays the armed
style only on cells inside that href, falling back to link_style for
other links on screen. The chunk grouper now splits on the armed
boundary, so a partially-hovered link renders correctly when adjacent
to a second link.
- ENHANCED: terminal: drive hyperlink rendering from a link_style object
Add a link_style slot on TerminalImage (default: blue + underline),
set via ->link_style and class variable link_style, parallel to the
existing selection_style and nfd_style. Paint resolves per-cell
fg/bg/underline/ bold through a new
effective_style_for() helper that
overlays link_style on cells whose link bit is set. rlc_put_link no
longer forces SGR 34/4 into b->sgr_flags — the colour and underline
come from the style, so applications can carry their own fg/bg through
the link label.
- TEST: terminal: visual demo of all SGR attributes the
xpce terminal renders demo_terminal/0 walks through styles
(bold/underline/inverse/link), the 16 ANSI colors via fg/bg/hfg/hbg,
the xterm-256 cube and grayscale ramp, 24-bit channel ramps + HSV
rainbow, mixed style+color, and an OSC 8 hyperlink. All output goes
through library(ansi_term) so the same goal also exercises any other
ANSI terminal.
- ENHANCED: terminal: support xterm-256 and 24-bit (truecolor) SGR
sequences CSI 'm' now walks its argument list, consuming 38;5;N /
48;5;N for xterm-256 colors and 38;2;R;G;B / 48;2;R;G;B for 24-bit
truecolor. Colors land in a per-buffer palette[] (slots 0..15 still
alias ti->ansi_colours; 16..4094 are interned via an open-addressed
COLORRGBA hashtable). On overflow (4095 distinct truecolors), new
requests fall back to the nearest existing entry by RGB Euclidean
distance.
- ENHANCED: terminal: repack per-cell metadata to make room for a
color palette Restructure text_flags as a 32-bit tagged union (raw +
bitfield struct): width:2, bold:1, underline:1, inverse:1, link:1,
reserved:2, fg:12, bg:12. The width byte on text_char is gone;
text_char stays 64 bits. fg/bg now hold palette indices (sentinel
PAL_DEFAULT = 4095) instead of 5-bit ANSI codes, opening 4096 slots
per slot for the upcoming 256-color and truecolor support.
[May 29 2026]
- FIXED:
newdir icon (used by Browse in PceEmacs file prompter)
- FIXED: Mixup of port and action toolbutton images (fail) for tracer.
[May 25 2026]
- FIXED: Hold a code reference on Frame across the FLASH_END SDL event
flash_end_callback() pushes MY_EVENT_FLASH_END carrying a raw FrameObj
pointer. Same UAF shape as the Timer case: if the frame is destroyed
and reused before the consumer in CtoEvent() runs, the F_FREED check
reads stale memory. Take a code reference around the queue and skip
the push entirely when the frame is already being freed.
- FIXED: Hold a code reference on Timer across the SDL event queue
tm_callback() pushes MY_EVENT_TIMER carrying a raw Timer pointer.
If the Timer is destroyed and its memory freed/reused before the
main thread consumes the event, the F_FREEING|F_FREED check in
sdl_timer_event() reads stale memory. Mirror the FDWatch pattern:
addCodeReference() before SDL_PushEvent(), delCodeReference() in the
consumer so the object stays in F_FREEING (memory alive) until the
queued event is drained.
- FIXED: Register Epilog pty slave_fd as a drainable console (POSIX) So
that
ws_discard_input() drops keystrokes the user typed at an Epilog
terminal window while a modal confirmer is up. Uses tcflush(TCIFLUSH)
on the slave fd, which drops kernel-buffered bytes without consuming
them and therefore does not race with the Prolog engine reading the
same fd.
- FIXED: Register stdin as a drainable console when it is a terminal So
that
ws_discard_input() drops pending bytes typed at the terminal while
a modal confirmer is up. Skipped silently when stdin is redirected
(e.g. Epilog spawning swipl with stdin closed).
- FIXED:
ws_discard_input() reads stale fd after socket-based dispatch
hook Replace the static dispatch_fd cache with a small console
registry, populated by the host on init (stdin) and by terminal.c for
Epilog ptys. ws_dispatch() now only watches an fd transiently for the
duration of one call, never caching it as a global; ws_discard_input()
iterates the registry and uses tcflush()/FlushConsoleInputBuffer()
instead of read(), avoiding races with engines reading the same fd.
[May 20 2026]
- ADDED: Send xterm Ctrl+Left/Right escape sequences from the terminal
Ctrl modifier on cursorLeft/cursorRight now produces ESC[1;5D /
ESC[1;5C so libedit (or any xterm-compatible reader) can bind these
to word motion.
[May 17 2026]
- ADDED: PceEmacs: normalize_region/normalize_buffer M-x commands to
apply a Unicode normalization form (nfc, nfd, nfkc, nfkd) to the region
or the whole buffer. Conditional on the optional library(unicode).
- ADDED: PceEmacs/epilog: insert_symbol command (C-x 8 RET / C-x 8 s)
C-x 8 is a prefix in PceEmacs and the epilog terminal; it opens the
symbol picker targeting the invoking editor/terminal.
- ADDED:
library(pce_symbol_picker) for picking Unicode symbols A
non-modal singleton (and modal pick_symbol/1) to browse Unicode blocks
and curated code ranges, type the picked symbol into the focused
window, and remember recents. Supports code_range/3 user ranges,
matching pairs, and a filter that searches either block names or
Unicode character names.
- FIXED: man class hierarchy: correct builtin/user class icons
- ADDED: display_manager <->focus_message: hook on keyboard-focus change
Fires the given message when a frame gains or loses the keyboard focus,
so tools can track the active application window.
- ENHANCED: text<-pointed: add round option (caret vs hit-test)
<-pointed takes an extra argument selecting caret-style rounding
(snap to nearest gap) versus exact hit-testing.
- ENHANCED: text_item: optional clear-field image Add a ->clear_image
slot to class text_item. When set (use @default for the standard
clear-text.svg icon), a clickable image appears at the right of the
entry field while it is non-empty; clicking it clears the field.
The space is reserved as soon as the image is set so the field does
not reflow when the icon appears. Restricted to style `normal'.
[May 15 2026]
- ADDED: window->pdf: print the full window contents Graphical->pdf
saves <-area, i.e. only the visible part of a window. Override it on
window to use <-bounding_box (the union of all graphicals) so scrolled
or oversized content is printed in full, with the page offset so the
bounding box maps onto the page.
- FIXED: graphical->pdf: negate the page offset
pdfGraphical() created
a page sized to <-area but set d_offset() to +area->x,+area->y.
Since drawing primitives add the offset, a graphical at a non-zero
position was shifted off the page, producing a blank PDF. Negate the
offset so the graphical's area maps onto the page origin.
- FIXED: text<-pointed: hit-test with Pango layout, not per-char c_width
get_pointed_text() summed c_width() per character to map a click to
a character index. For proportional fonts and strings needing font
fallback (e.g. the symbol picker showing emoji/Greek/math), that sum
drifts from the actual rendered glyph positions, so clicks selected
the wrong symbol.
[May 14 2026]
- FIXED: xpce printf %c: handle non-ASCII code points Routed %c through
snprintf which collapses the int argument to a single byte and produced
invalid UTF-8 for any code point above 0x7F. Handle %c separately:
Put() takes a uchar_t (uint32_t) which already carries a full code
point, and put_void_str promotes the target string to wide as needed.
Width and left-align flags from the format spec are still honoured.
[May 10 2026]
- RENAME: xpce LaTeX manual sources .doc -> .plx Renames the
63 LaTeX .doc files under man/{course,interface,userguide}
and prolog/lib/{draw,trace/doc} to .plx, leaving the XPCE
man-card binary database under man/reference/ untouched. Updates
man/userguide/Makefile suffix rule. Co-Authored-By: Claude Opus 4.7
(1M context) <noreply@anthropic.com>
[May 8 2026]
- FIXED: Thread monitor icons Reported by Mike Elston.
[May 6 2026]
- MODIFIED: auto-copy behaviour Added the class variable auto_copy
to class
terminal_image as well. It now appears on text_item,
editor and terminal_image. It now defaults to @off for Windows
and MacOS and for now to @on for other platforms. To switch, use
this in the preferences file (or @off to disable on Linux, etc.).
- ENHANCED: SDL backend Windows font specs cover Thai and Yi Add
Leelawadee UI (Thai/Lao, ships since Windows 8) and Microsoft Yi
Baiti (Yi syllables, ships since Vista) to the mono, sans and serif
fallback chains.
- FIXED: PceEmacs class menu to edit a class raised a type error.
- FIXED: XPCE native finder icons.
- ENHANCED: SDL backend Windows font specs include CJK and symbol
fallbacks Pango uses the comma-separated family list as an explicit
fallback chain; it does not synthesise script-based fallbacks the way
Windows DirectWrite does for Notepad. The previous mono/sans/serif
specs covered only Latin, so Korean (Hangul), Japanese, Chinese and
many symbol/emoji glyphs rendered as tofu on Windows.
- ENHANCED: display: expose SDL on-screen-keyboard control Add three
methods on class display so the Prolog side can both control and
observe SDL's on-screen-keyboard policy without recompiling for
DEBUG output:
- ENHANCED: font <-domain unions Pango fontset coverage Drop the
vestigial X11-era
which argument (the row/column selector of
2D charset fonts) and replace it with family=[bool], mirroring
the new font ->member argument. The default takes the union of
PangoCoverage across the requested font and its fallback chain, so
the returned envelope is consistent with `->member`: a code point
outside the domain reliably fails `->member`, while emoji and other
fallback-covered ranges are now inside it. The full-unicode scan is
cached on the WsFont, so the cost is paid once per font.
- ENHANCED: font ->member walks Pango fallback chain
font ->member:
char consulted only the primary PangoFont, so it returned @off for
code points (e.g. U+1F600) that the system can in fact render via
Pango fallback. Walk a PangoFontset for the font's description by
default, and add an optional family=[bool] argument so callers can
force the old "primary font only" check.
[May 5 2026]
- DEBUG: optional terminal trace under -DXPCE_TERM_TRACE Build with
-DXPCE_TERM_TRACE to compile in caret / byte-stream diagnostic logging.
At runtime set XPCE_TERM_TRACE=<file> (or "1" for xpce-terminal.log
in CWD) to capture activity. Inert and zero-cost without the macro:
tlog collapses to ((void)0).
- FIXED: str_ring_alloc no longer marks the result s_readonly s_readonly
was an overload: most call sites (str_set_static, staticCtoString,
the "(nil)" sentinel) used it to mean "permanent, shareable storage"
and rely on initialiseCharArray's fast-path to share the pointer.
str_ring_alloc, in contrast, hands out a temporary slot that the
next 16 ring allocations recycle — sharing that pointer is fatal.
- TEST: SMP code-point fragment positions and round-trip
test_fragment_smp.pl exercises text_buffer indexing and fragment
start/length values on supplementary-plane code points. 10 tests
covering buffer size in code points,
get(_,character,Pos,_) at and
after an SMP slot, fragment start/length pointing past or spanning
an SMP code point (emoji and CJK Ext B), shift_fragments accounting
on insert before/across an SMP, a 10-cluster stress, and save/load
round-trip through the textbuffer file format.
- CLEANUP: drop now-dead surrogate-aware paths - u16_range_length:
the SIZEOF_WCHAR_T == 2 branch returned
len
unchanged because Windows used to store UTF-16 in the buffer, so a
range of N code units held N UTF-16 units. charW is now uint32_t on
Windows too; each SMP code point in the range needs to count as 2
UTF-16 units regardless of platform.
[May 4 2026]
- FIXED: replace wint_t with uchar_t (or int) for code-point holders
MinGW's wint_t is unsigned short (16 bits), so any code-point value
flowing through a wint_t variable on Windows truncates SMP code points
to their low 16 bits. This was the actual cause of emoji rendering
as PUA glyphs (U+1F30F shown as U+F30F): not the storage type, but
the many `wint_t c =
str_fetch(...)` and similar declarations between
the buffer and the rendering call.
- FIXED: c_width takes uchar_t (full code point) not wint_t MinGW's
wint_t is unsigned short (16 bits), so the (wint_t) casts at the
textimage do_fill_line call sites truncated the supplementary- plane
code points stored in tc->value.c (now charW = uint32_t on Windows).
The result: emoji rendered as their PUA-area low 16 bits (e.g. U+1F30F
shown as U+F30F) and produced .notdef glyphs from Pango.
- FIXED: F_UTF8_ENCLENW iterates code points, not wchar_t units The
previous loop encoded each wchar_t as a separate UTF-8 sequence.
On 16-bit wchar_t platforms (Windows) a supplementary-plane code
point arrives as a UTF-16 surrogate pair, so each half emitted its own
3-byte UTF-8 sequence (and the surrogate's encoding form is invalid
UTF-8 anyway). Use
get_wchar() to combine pairs first; on 32-bit
wchar_t platforms get_wchar is a per-element copy.
- ENHANCED: regex CHR width matches charW unconditionally Previously
CHRBITS / CHR_MAX were 16 / 0xffff under WINDOWS and 32 /
0x3fffffff elsewhere, because chr typedef'd to charW (=wchar_t)
which is 16-bit on MinGW. charW is now uint32_t on platforms where
wchar_t is too narrow (Windows), so the regex chr can hold the full
Unicode code-point range there too. The colormap is a sparse trie
(NBYTS = 4 levels), so the larger CHR_MAX does not bloat memory.
- FIXED: ENC_WCHAR stream read paths emit wchar_t, not charW Sread_object
(iostream.c) and pceRead's wide branch (asfile.c) wrote the internal
charW buffer into the stream's wchar_t-typed output buf and reported
the byte count as wchar_t-units. When charW is wider than wchar_t
(Windows post-flip) that wrote 4-byte values into a 2-byte-per-unit
buffer. Convert at the boundary: assign wchar_t per charA-source
char; surrogate-encode via charW_to_wchar for charW sources. When the
typedef equality holds (Linux always; Windows when charW falls back
to wchar_t) the conversion folds to a per-element copy.
- FIXED: route wchar_t<->charW boundary conversions through charW.h charW
is now uint32_t when wchar_t is too narrow (Windows). Adjust the
few sites where wchar_t (caller) meets charW (storage) so neither
side silently truncates supplementary-plane code points:
- ENHANCED: charW falls back to uint32_t when wchar_t is too narrow
On Windows wchar_t is 16-bit UTF-16; storing a supplementary-plane
code point as a surrogate pair across two slots is the source of the
fragment-indexing bug fixed in subsequent commits. Pick uint32_t for
charW when WCHAR_MAX <= 0xFFFF, and otherwise keep charW as wchar_t
— on Linux/macOS the typedef stays exactly as it was, so the pair
of boundary conversions added alongside fold to compile-time identity
and the binary is unchanged.
- ADDED: charW.h boundary helpers between wchar_t and internal charW
Adds wchar_to_charW / charW_to_wchar inlines (and length variants).
Used at the few external boundaries where xpce sees wchar_t buffers
from outside (host embedding API, ENC_WCHAR streams, Win32 file APIs).
Internal text-handling will keep its charW typing.
- FIXED: c_width returns reasonable width for UTF-16 surrogate halves On
Windows (wchar_t==16) supplementary-plane code points reach c_width as
surrogate halves. Encoding a lone surrogate as UTF-8 and asking Pango
for its advance returned the .notdef-glyph width — typically much
wider than the actual emoji or wide glyph the paired UTF-8 renders.
The accumulated x in do_fill_line then over-advanced past where the
glyph was painted, leaving a multi-cell whitespace gap to the right
of each emoji. Account the cluster's width once on the lead (two
average char widths, matching uchar_display_width's column count of
2 for SMP wide glyphs) and let the trail contribute zero.
- ENHANCED: uchar_display_width recognises UTF-16 surrogate halves
On Windows (wchar_t==16) supplementary-plane code points appear
as surrogate pairs in xpce's wide-char buffers. Treat the lead as
double-width (the SMP ranges xpce typically encounters — emoji,
CJK Extensions B-G — are all wide) and the trail as zero-width so
each pair contributes exactly two columns to vcol, the per-cluster
painter groups the pair as one wide cluster, and grapheme_cluster_end /
_start advance by exactly one emoji per arrow press.
- FIXED: textbuffer file load/save handles UTF-16 surrogate pairs On
Windows (wchar_t==16) a supplementary-plane code point is stored as a
UTF-16 surrogate pair in the wide-char buffer. insert_file_textbuffer
truncated SMP code points by direct assignment; save_textbuffer fed
each surrogate half to Sputcode separately, producing invalid UTF-8.
Use put_wchar / get_wchar so loaded files contain proper pairs
and saved files emit the combined code point. No-op on Linux
(wchar_t==32).
[May 3 2026]
- ENHANCED: route THasSyntaxEx fallbacks through the host Add
five callback slots to pce_callback_functions — is_letter,
is_word_char, is_layout, is_digit, is_endsline — named after xpce's
own syntax-table categories. Returning bool, since they are pure
predicates. Host wrappers in itf/interface.c; swipl/interface.c maps
each to one or more PL_is_* shims (and hard-codes is_endsline's seven
line-terminator codepoints, which need no Prolog API of their own).
- FIXED: terminal paint_chunks splits per cluster for non-ASCII text When
the system fixed-width font has no glyphs for a script (e.g. Thai),
Pango falls back to a proportional font and shapes a multi-char run at
its natural advance. A line painted as one Pango call rendered fine,
but with a selection — three chunks (before-sel / sel / after-sel)
— each chunk reshaped independently and the after-sel half drifted
right because it started at a column-grid x rather than where the
unselected line had placed those glyphs.
[May 2 2026]
- ENHANCED: route
uchar_display_width()'s wcwidth fallback through the
host Add a wcwidth slot to pce_callback_functions (replacing pad17),
expose hostWcWidth() in itf/interface.c, and let h/charwidth.h's static
inline delegate to it instead of calling system wcwidth(3) directly.
The swipl-side callback registers PL_wcwidth(), so xpce now uses
the same implementation as pl-read.c / pl-write.c regardless of the
process LC_CTYPE.
- FIXED: convert sel_*_char from cell index to visual column when
painting In rlc_redraw the selection bounds (sel_start_char /
sel_end_char) are cell indices — they index tl->text[] in
rlc_set_selection's snap helpers and in rlc_read_from_window, and
they're already documented that way at the call sites of rlc_snap_start
/ rlc_snap_end. rlc_paint_text in contrast takes visual-column
bounds (see its own header comment). On a line without combining
marks the two are interchangeable, so this never showed up before;
on NFD content (e.g. Thai with U+0E31, U+0E35) the cell index drifts
ahead of the visual column by one per combining mark, and the painted
selection extends past where the user dragged.
[Apr 28 2026]
- FIXED: forward/backward char and delete move by grapheme cluster not
code point For NFD text a visible character may span multiple code
points (a base followed by one or more combining marks). The four
basic editing operations previously stepped one code point at a time,
leaving the caret stranded inside a cluster or deleting only part of
a grapheme.
- TEST: unicode_heavy.pl — Prolog test file for NFD and wide-char
rendering Add tests/unicode_heavy.pl with syntactically valid Prolog
that stresses editor and terminal rendering of:
- ADDED: nfd_style instance variable for visual NFD cluster highlighting
Add an
nfd_style instance variable (Style*) to both Editor and
TerminalImage, mirroring the existing selection_style pattern.
When set to a style with a background colour, every NFD grapheme
cluster — a base character followed by one or more zero-width
combining marks — is drawn with that background. The default is @nil
(disabled), so existing editors are unaffected.
[Apr 27 2026]
- FIXED: paint_line renders Unicode highlights without visual drift
Four related fixes across txt/textimage.c and sdl/sdldraw.c:
- FIXED: Snap selection endpoints to grapheme cluster boundaries
selectionExtendEditor computes the selection from/to from the mouse
click position. If that position falls inside a combining-mark cluster
(e.g. a Thai vowel sign such as ◌ั following its base consonant),
the raw character index points mid-cluster: the base character's
x position is shared by the following zero-advance combiners, so
selecting or deselecting just the combiner produces a mis-sized
highlight.
- FIXED: Selection drag corrupts text at grapheme cluster boundaries
When a mouse selection boundary fell inside a grapheme cluster
(a base character followed by one or more zero-advance combining
marks, such as the Thai above-base vowel signs ั ี ่ ้ in
สวัสดีชาวโลก), the
paint_line() run-grouping
loop split the cluster across two separate s_printW() calls.
Pango then rendered base and combining mark as independent glyphs,
causing visual corruption visible whenever the TXT_HIGHLIGHTED
attribute changed between the base and its mark.
- TEST: Add unicode_heavy.pl — public domain Unicode stress test
Valid Prolog file using NFD combining marks (acute, diaeresis, tilde,
cedilla, circumflex) as literal UTF-8 bytes alongside East-Asian
double-width characters (CJK ideographs, hiragana, katakana, hangul).
- TEST: Add test_editor_unicode.pl for Unicode visual-column tracking
Five PLUnit tests exercise the new Editor <-visual_column getter:
- FIXED: editor column functions account for CJK wide and combining
chars
getColumnEditor() and getColumnLocationEditor() previously
counted every non-tab character as one visual column. This broke
caret positioning after CJK double-width characters (each counts as 2)
and after combining marks (each counts as 0).
- ENHANCED: Add vcol visual-column cache to TextChar; populate in
do_fill_line() struct text_char gains a `short vcol` field that
records the 0-based visual column of each character on a displayed
line. do_fill_line() fills it alongside the existing pixel-x field,
advancing current_vcol by uchar_display_width() for each character
(0 for combining marks, 2 for CJK wide chars, 1 for everything else).
- REFACTOR: Extract
uchar_display_width() into shared h/charwidth.h Move
the Unicode display-width logic (combining=0, CJK wide=2, other=1)
from a static function in txt/terminal.c into a new static-inline
header h/charwidth.h. This makes the same function available to
txt/textimage.c and txt/editor.c without code duplication.
[Apr 26 2026]
- FIXED: Both set primary and secoodary selection in
display->copy
[Apr 21 2026]
- FIXED: rlc_resize, rlc_shift_lines_up, rlc_clear_from_cursor +
tests Three related fixes to the xpce ring-buffer terminal and a new
regression-test unit that exercises them:
[Apr 20 2026]
- FIXED: terminal paints each wide-char cluster at its column-grid
x Pango's natural advance for an emoji (or other wide glyph) runs
a pixel or two wider than the 2*cw the terminal grid allocates.
Feeding a long same-flags run like "sskll😀😀😀😀😀😀😀"
as a single s_print_utf8 call made each emoji nudge the subsequent
glyphs rightward, so the rendered text drifted past the column-grid
cursor that rlc_paint_text walks in integer cell units. With the
caret walked to the end the text and the caret no longer meet, and
a selected "see😀" left the trailing "aap" shifted left.
- FIXED: s_print_utf8 reads baseline from the new text, not the stale
layout s_print_utf8 was calling pango_layout_get_baseline BEFORE
pango_layout_set_text, so
baseline reflected whatever text was in
the cached PangoLayout from the previous call. Consecutive calls
with different scripts (e.g. an emoji glyph followed by plain ASCII)
baseline-aligned each draw against the previous call's text, so
the second draw could land a few pixels above or below the intended
baseline.
- FIXED: raise META_OFFSET above Unicode range META_OFFSET (used to
tag Meta-prefixed key events in the same integer space as character
code points) was 1<<16 = 65536. Any non-BMP code point (emoji like
🤩 U+1F612, most supplementary-plane characters) is >= 65536 and
collided with the Meta flag.
[Apr 19 2026]
- TEST: terminal_non_bmp — exercise supplementary-plane code points
Add five tests covering the non-BMP path that matters most on Windows,
where wchar_t is 16-bit UTF-16 and a single code point (U+10000 and
above) occupies two buffer slots as a surrogate pair. Linux stores
the same code point in one wchar_t; these tests pin both platforms
to the same observable behaviour:
- TEST: extend random-test model to multi-row layout Teach
test_terminal_random's pure-Prolog model to lay clusters out across
rows (model_layout/8) so it can verify content that legitimately wraps.
Rows are grouped by the row they occupy and each row is compared
to xpce's <-row. The per-session content cap is lifted from one
row to 900 visual columns so random sessions routinely exercise the
libedit+xpce wrap path.
[Apr 18 2026]
- TEST: regression for re_refresh wide-at-cursor using visual column
Locks in the libedit fix: long NFD content + emoji at cursor must
not bump the computed cursor row based on code-point count.
- FIXED: rlc_insert must not clamp tl->size to b->width rlc_insert
extended the line's cell size only up to b->width when opening a gap
for the inserted character. For a line whose content is NFD-heavy
(combining marks occupy cell slots but zero visual columns) the cell
count can legitimately exceed b->width while the visible content still
fits, and clamping trimmed the trailing cells — most visibly the
final cluster's combining mark, which disappeared from the display
after a mid-line insert.
- FIXED: ANSI column positioners must not clamp caret_x to width-1
rlc_set_caret (CUP / HVP) and rlc_set_caret_x (CHA / HPA) clamped the
resulting caret_x to b->width-1 after converting the requested visual
column via rlc_vcol_to_cell. For plain narrow content that's a no-op,
but for rows containing combining marks or wide characters the cell
index at visual column K legitimately exceeds K (a base + combiner
occupies two cells for one column). The clamp silently snapped the
caret back to the middle of the row, so libedit's re_refresh_cursor
—which uses CHA to position after cross-wrap moves — landed at
the physical midpoint of an NFD-filled line instead of its right edge.
- FIXED: count wide-char clusters as 2 visual columns in DCH
rlc_delete_chars decremented its visual-column budget by the base
cell's per-cell width (1), which is wrong for a wide char: the cluster
spans base + placeholder = 2 visual columns. So a DCH with count=2
only removed one wide cluster plus a character from the next cluster,
instead of a single wide cluster.
- FIXED: preserve cell content when rlc_put lands a combiner mid-line
rlc_put's combining-mark branch used to write the combiner into the
cell at caret_x and advance. For a re-render that inserts an NFD
cluster with libedit's T_IC + overwrite, the overwrite's combining
mark clobbered the base that T_IC had just shifted into place,
dropping the following character from the visible row.
- TEST: add test_terminal_random/2,3 and first regression it surfaced
Introduces a random driver that types and edits through libedit and
after each command verifies the cursor and row text against a pure-
Prolog model of where they should be. Single-row v1 (buffer capped
to fit on one row). On the first divergence the driver prints the
seed, the full session command history, and the expected/actual state,
then throws.
- TEST: Added terminal test framework.
- ADDED: epilog/1 option
object(-Ref) Get the xpce object reference of
the new terminal.
[Apr 15 2026]
- ENHANCED: Unicode-aware terminal cell model Teach the xpce terminal's
line buffer to store Unicode content by code point, with per-cell
display width, and to move the caret by grapheme clusters or by visual
columns as the context requires. Summary of the model:
[Apr 17 2026]
- ADDED:
terminal_image<-cursor_position and terminal_image<-row
This allows for writing terminal handling tests.
[Apr 16 2026]
- ADDED:
text_item->placeholder Modernizing the UI
[Apr 15 2026]
- ADDED:
library(pce_backcomp): Provide better backward compatibility
- MODIDIED: Renamed
->fill_pattern to ->fill Only filling with
colours is currently supported. Even if we re-introduce filling with
images, the name fill_pattern is not accurate.
[Apr 10 2026]
- MODIFIED: Use .SVG images for most of the icons of the development
tools This patch replaces most 16x16 .PNG image files with .SVG files,
most of which are scaled to the context, e.g., the line height.
Furthermore
[Apr 9 2026]
- ADDED: Support loading
image objects from SVG data
[Apr 14 2026]
- FIXED: Windows
display<-selection to return canonical newlines.
This patch also fixes a memory leak: the selection string as obtained
from SDL3 was not freed. The leak applies to all platforms.
- FIXED:
figure->shadow rendering.
[Apr 13 2026]
- FIXED:
image<-clip and image<-scale to same size Preserve
transparency of the source.
[Apr 9 2026]
- ADDED: Support loading images from SVG files. This uses the SDL-Image
library support for nano-svg. This is a subset of SVG.
- MODIFIED: Deleted
image<-monochrome. This is a bit outdated.
Use <-grayscale instead.
- SDL: Implemented
image<-rotate.
- ENHANCED: Allow resizing tool button images.
- SDL: Implemented
image<-scale.
- ENHANCED: Several PceDraw issues.
- ENHANCED: Default arrow size.
- FIXED:
ellipse->shadow drawing.
[Apr 8 2026]
- ENHANCED: Slider look handling. Now implements
gtk and motif
Deleted old open_look and win (black-and-white) looks.
- FIXED: Pen+-fill handling for box and arc/ellipse
- FIXED: Properly draw 3D elevated triangles
- ENHANCED: sizing 3D triangles to indicate popup menus based on the
font metrics.
[Apr 7 2026]
- FIXED: draw 3D triangle correctly.
- FIXED: Dynamic switching
menu_bar->look.
[Apr 4 2026]
- FIXED: Use 64-bit millisecond timer Now uses SDL_GetTick() for
portability and consistently type as
int64_t. This avoids 49 days
overflow on Windows.
- SDL: Implemented
@pce<-user.
- MODIFIED: Deleted console methods on
@pce This deletes
@pce->`console_label`, @pce->expose_console,
@pce->iconify_console and @pce->show_console``.
- FIXED: Edit menu from profiler.
[Apr 3 2026]
- ADDED: PceEmacs find_references (M-?) to reuse the window unless
pinned.
- SDL: Implemented
frame<-image.
- SDL: Implemented
window->flash.
- MODIFIED: Deleted
window->grab_keyboard Modern GUI frameworks no
longer allow global grabbing of the keyboard.
- SDL: Added enable/disable screen saver.
- SDL: Implemented
display->bell Was a stub. Now generates a
sentesized beep.
- SDL: Re-implement reading images from arbitrary streams.
- SDL: Re-added support for images in saves objects.
[Apr 2 2026]
- SDL: Support
image->save Currently only for PNG format and only
to a file.
- SDL: Implemented
image<-pixel. This patch also introduces @rgba,
a hash table that maps RGBA quadruples into existing colour objects.
- SDL: Implemented
window->pointer (was a dummy) Does not work on
all platforms. Still succeeds silently.
- FIXED:
frame->background for open frames.
- FIXED: Help menu of Profiler to open correct page.
[Apr 1 2026]
- CLEANUP: Remove RCS version control on classes.
- MODIFIED: Deleted
display->open SDL has no such notion. It could
be in headless mode, but then it still has a display that can be
considered "open".
- MODIFIED: Deleted unimplemented methods on class
frame: These methods
have been removed as there is no cross-platform support for them:
- MODIFIED: Deleted
frame<-thread All windows are managed by the
SDL main thread.
- DELETED:
frame->grab_pointer. This is not supported by
security-aware window systems.
- MODIFIED: Deleted
frame<->border.
- MODIFIED: Deleted
frame->hide. This commit removes several
low-level bindings that are not supported by SDL and typically
considered outdated.
- CLEANUP: Remove left overs of built-in XBM images
- CLEANUP: Remove X11 resource reference database.
- CLEANUP: Remove
SDL_GRAPHICS macro (now unconditionally)
- CLEANUP: Remove
WIN32_GRAPHICS configuration
- CLEANUP: Remove configuration for sigaction and union wait.
[Mar 31 2026]
- FIXED: Use a safe way to send messages from a singal handler. This is
used to inform xpce when the status of a child process has changed.
- CLEANUP: Remove CMake define
USE_SIGINFO
- CLEANUP: Remove various X11 traces
[Mar 15 2026]
- PORT: Support SDL < 3.2.12, which does not provide accumulative
wheel events.
[Mar 12 2026]
- FIXED: Windows:
frame<-{open,save}_file work around for SDL3.4.0
bug.
[Mar 11 2026]
- PORT: Windows: get rid of remaining XBM images. Fixes
XopenImage(@ms_left_arrow_image/image)
message and shows correct left arrow for pullright menus.
- ENHANCED: Capture
main thread messages to current Epilog using
hyperlinks.
- ADDED: PceEmacs Prolog mode: set spy point from goal and head popup.
- PORT: Removed RETSIGTYPE config Outdates as any reasonable still
alive system uses
void.
[Mar 8 2026]
- FIXED: Epilog: Possible access to freed object when closing.
[Mar 7 2026]
- ENHANCED: Thread monitor Show more of the status of threads and improve
popup menu actions. Improve disabling popup entries and add an entry
to toggle debug mode for classes of threads.
[Mar 6 2026]
- ENCHANCED: GUI tracer control.
- ADDED: Epilog: use thread classes.
[Mar 2 2026]
- FIXED: PceEmacs: possible infinite loop in
dabbrev_expand.
editor->dabbrev_expand can loop if a secondary or ternary search
for candidates only results in candidates that are already rejected
by the user from earlier candidate searches.
[Feb 26 2026]
- ENHANCED: Improve scroll wheel handling. Notably get more natural
scroll speed on MacOS trackpads
- FIX: Pass image (not surf) to my_cairo_check_surface in
ws_load_image_file
[Feb 23 2026]
- BUILD: Build in headless mode.
[Feb 13 2026]
- ENHANCED: PceEmacs to list thread-local clauses. If a PceEmacs window
is embedded in the debugger, fetch the target debug thread and list
the clauses as the debuggee sees them.
[Feb 10 2026]
- FIXED: undefined Dprintf and _T symbols in terminal.c debug code
- FIXED: MSVC C4319 warning and potential bug in
clearDFlagProgramObject() Cast mask to uintptr_t before applying
bitwise NOT. Without this, ~mask produces a 32-bit result on Win64
(unsigned long is 32 bits) that gets zero-extended to 64-bit uintptr_t,
incorrectly clearing the upper 32 bits of dflags.
[Feb 5 2026]
- CLEANUP: Remove old deprecated usage of SunOS
on_exit()
[Feb 2 2026]
- ADDED: implementation for 3d rounded corners box
r_3d_box()
- ENHANCED: 3d effect rendering. Notably makes scrollbars look better.
- PORT: Support MSVC
- FIXED: GUI Tracer: remove non-functioning Help menu entries. Links to
the manual and notably xpce manual seem unnecessary. Also removed
the About as it is all part of the integrated Prolog IDE tools.
[Jan 28 2026]
- ADDED: PceEmacs: associate
emacs_<mode>_mode module with mode.
And define style/2 and def_style/2 for style mapping. This is used
by the experimental LSP client and should be used by the other modes,
notably the Prolog mode.
[Jan 26 2026]
- CLEANUP: Avoid suspicious
sizeof() handling warning by clangd
[Jan 22 2026]
- FIXED: Use `font<-average_char_width` for width computations This
used to be `font<-ex`, but this is the height of the
x character.
This notably fixes the default width of PceEmacs windows to hold 80
characters rather than a few less (depending on the font).
- FIXED: PceEmacs Prolog mode: find-references to avoid duplicates.
[Jan 21 2026]
- FIXED: class
text_buffer: LSP position reporting for wide-character
buffers.
- FIXED: Epilog: underline could continue in scrollbar.
[Jan 19 2026]
- FIXED:
text->underline. Underline was relative to top instead
of base.
[Jan 13 2026]
- ENHANCED: When opening one of xpce's manual tools, do not show @manual.
This additional window is often needed and especially on systems that
do not allow for window placement, this is annoying.
[Jan 7 2026]
- ENHANCED: Make most errors that result from buggy program print
a backtrace
[Jan 5 2026]
- ADDED: PceEmacs: (empty) markdown mode. Allows for user extension,
so we can play with markdown LSP servers.
[Dec 31 2025]
- ENHANCED:
editor->align: minimize the change This reduces
change/undo info and keeps the buffer marked clean if no change
happens.
- FIXED: Collecting LSP change message could corrupt edit modifications.
- ADDED: Broadcast
pce_emacs(saved(Buffer)) when a buffer was saved.
Can be used to trigger an LSP didSave() event, automatically recompile,
etc.
[Dec 29 2025]
- FIXED: Avoid undefined
@nil->update in bookmark handling.
[Dec 25 2025]
- ENHANCED: Only display output from help/1 in GUI when invoked from
the gui.
[Dec 24 2025]
- ADDED:
error->feedback type backtrace to force errors to dump
a backtrace.
[Dec 23 2025]
- FIXED: Avoid memory corruption when ->initialise fails. The partial
object may have references. If so, leave its final destruction to
the reference count dropping to zero.
[Dec 18 2025]
- CLEANUP: Replace all calls to
sprintf() with snprintf()
- FIXED: Thread monitor. Broken due to changes to class image.
New code is simplified by using
image->fill and num rather than
int|real type.
- FIXED:
image->fill to accept a colour. Filling with images is
currently not supported.
[Dec 17 2025]
- ADDED: Exploit features to edit foreign predicates directly.
- FIXED:
swipl-win: deadlock when trying to attach a console to
the xpce (main) thread.
- FIXED: Underline colour when using default underline. If a line
contains two fragments with different colour and underline, the first
used the colour of the second.
[Dec 16 2025]
- ADDED: Update bookmarks both when saving and colouring.
- FIXED: PceEmacs bookmarks: update when saving the buffer.
- ADDED: PceEmacs Prolog mode:
find_references (Alt-?)
- FIXED: PceEmacs bookmarks displaying the full path.
[Dec 14 2025]
- ENHANCED: PceEmacs bookmark list Create nodes per file and provide
proper highlighting
- ADDED: Class
grbox: allow for baseline vertical aligment.
- FIXED: Class
grbox was not displaying
- ADDED:
parbox->initialise: allow adding content
- FIXED: Class
parbox redraw handling for opacity.
[Dec 13 2025]
- ENHANCED: Style PceEmacs bookmarks
- ADDED: Support background of style in class
tbox.
[Dec 12 2025]
- ENHANCED: PceEmacs bookmark handling. Allow bookmarks on a selection
inside a line. Working on a non-persistent bookmark instance that we
can use for dynamic sets such as search hits, references, errors, etc.
- ENHANCED:
@emacs->goto_source_location: use new line_pos and
length
- ADDED: Class
source_location: line_pos and length fields.
[Dec 11 2025]
- ADDED: PceEmacs: allow adding new type-based prompting.
[Dec 10 2025]
- ADDED:
editor<-dabbrev_candidates: mode user0 This mode allows
completion that is more targeted than searching the current buffer.
It is intended to support intelligent completion using M-/.
- MODIFIED: Removed
image<->foreground and image<->background.
Also removes corresponding initialization arguments from class pixmap
and image->set_pixel and image->clear_pixel.
- CLEANUP: Remove
bitmap<-display. Bitmaps are no longer related
to a specific display.
- CLEANUP: Removed
image<->depth All our images are now 32-bit RGBA
- MODIFIED: Removed
bitmap<->transparent No longer needed. This also
removes the second argument from ->initialise.
- CLEANUP: Removed
image->mask Since we have an alpha channel on
images this is no longer needed.
- ADDED: Icons for LSP fix and tweak operations
- ADDED: class
label: allow image selection to be scaled using
->width
- ADDED:
image->resize. Now only sets the width and height.
- CLEANUP: Removed a lot of outdated image code
- FIXED: LSP change message for consecutive backward delete.
- FIXED: class
text_buffer: undo handling. Undo may be lost if two
consecutive changes that can be merged are executed on a virgin buffer.
[Dec 9 2025]
- FIXED:
r_3d_box(): device offset for filling the box was applied twice.
[Dec 8 2025]
- ADDED: PceEmacs: support hovering fragment icons.
- ADDED: PceEmacs: quick action for commenting xpce get methods.
- FIXED: Class editor: align line spacing between normal and bold fonts.
- ENHANCED: Moved font ascent and descent to main object. This allows
for adjusting the line spacing of a font, such that we can ensure
consistent line spacing for normal and bold font in editors.
- ENHANCED: Class
font: properly compute ex Instead of using
simulation, being 1/2*h.
- ADDED: ``editor->hover_fragment_icon: fragment*, [area]'' Called from
the margin to act on hovering the margin icons.
[Dec 7 2025]
- FIXED: Underline in class
tbox
[Dec 6 2025]
- FIXED: PceEmacs: keep LSP servers in sync on M-x revert
- ENHANCED:
text_margin: indicate that a fragment icon can be clicked.
- FIXED:
text_margin: display fragment that appears on first line
- ADDED:
text_margin->icon_size to scale icons.
- ADDED: Margin icons for LSP diagnostic types
[Dec 5 2025]
- FIXED: Broadcast changes due to white space normalisation while saving
- ENHANCED: Class
editor: use real bold font instead of simulated.
This results in cleaner and more efficient rendering.
[Dec 4 2025]
- ADDED:
style->underline is now either a boolean or a colour
Colour is also supported by text->underline. Future versions may
also add names for specific underline styles.
- FIXED: Re-implement
style->grey Was lost in conversion to SDL.
- FIXED: Avoid warning on freed object when closing a PceEmacs window
This is harmless, but annoying.
[Dec 2 2025]
- ADDED: PceEmacs C-mode: declaration of keywords.
- ADDED:
syntax_table->keywords to register known keywords for
a syntax
[Dec 1 2025]
- MODIFIED: Generalised
text_buffer->for_all_comments Replaced by
text_buffer->for_all_syntax, which qualifies additional syntax
types. Currently only quoted material.
- ADDED: Support for multi-character line comment lead-in (e.g. //
comment)
- MODIFIED:
syntax_table->prolog: bool replaced by
syntax_table->language
- ADDED: `text_buffer<-
lsp_offset(line,character) --> offset Translate
position in LSP notation to an offset.
- ADDED:
text_buffer<-lsp_column Produces the character field
of an LSP range start/end. This is the position inside the line in
UTF-16 code points.
[Nov 29 2025]
- ENHANCED:
editor->align_line to avoid modifications if alignment
is already satisfied.
- FIXED: text_buffer->insert not to set modified if we insert 0 times.
- ADDED: PceEmacs: M-x idle-timeout seconds Sets the time we wait before
re-running semantic highlighting.
[Nov 28 2025]
- ADDED: PceEmacs: hooks to allow syncing to an LSP server
[Nov 24 2025]
- ADDED: Class
text_buffer to allow forwarding changes incrementally
This implements methods to generate LSP (Language Server Protocol)
compatible incremental change events. The basic method is
`text_buffer<-lsp_changes`, which returns a chain of text_change
objects that provide the changed range and replacement text.
[Nov 17 2025]
- PORT: Fixed emulation of C11
atomic_compare_exchange_strong()
[Nov 14 2025]
- PORT: Compilation in MSVC This is only a partial port to MSVC.
It does fix several issues though.
- FIXED: If there is no gui, do not setup xpce for lazy loading.
[Nov 12 2025]
- PORT: Hack around MacOS oddities to get
SIGWINCH
- PORT: Make compilation succeed if SIGWINCH is not defined.
- FIXED: Message handling. Broke emacs/0. Reported by @mike.elston
[Nov 11 2025]
- FIXED:
swipl-win to handle interrupt in the console that started
swipl-win. What should we do if there is no terminal, i.e., if
swipl-win is started as app directly from the GUI? It should not
get interrupt signals in that case, but what if it gets one anyway?
- ADDED: Epilog: use
pthread_kill() to update client thread of window
size change. This fixes resizing Epilog windows cooperation with
libedit. To work correctly, the libedit package must be updated
as well.
[Nov 9 2025]
- ENHANCED: Detection of when to load
library(pce).
[Nov 7 2025]
- ADDED: Epilog: Shift-Ctrl-M to inject make/0.
- MODIFIED: Removed all PostScript related support This was
non-functional anyway. The Cairo graphics is used to implement
graphical->pdf for generating PDF. This functionality is still
rather minimal. It will be extended in the future.
- FIXED: Colour for class
int_item up/down arrows. And some code
cleanup.
[Nov 6 2025]
- ENHANCED: class
font_item to reflect current possibilities better.
- ENHANCED: Updated PceDraw - Use native file dialog for save, load
and export - Remove windows metafile support - Replace Postscript
output with PDF - Disable printing. Not supported by SDL and not
very important.
[Nov 5 2025]
- DOC: Revive the XPCE User Guide This commit re-adds the
Makefile,
updates the Prolog helpers and minimal updates to reflect some aspects
of XPCE version 7 in the documentation.
- ADDED:
graphical->pdf to write PDF to a file
- FIXED: Always enable color on the Epilog consoles.
[Nov 4 2025]
- ENHANCED: Start Epilog file dialog in working directory.
- ENHANCED: Make Quit Prolog the default button for confirming close
with open windows.
- ADDED: Allow inspecting the GUI hierarchy from Epilog.
- ADDED: pce_show_visual_tool/0 to
library(man/v_visual). This allows
showing the GUI inspector stand-alone.
- FIXED: Block other Prolog threads while a window is being redrawn.
Modifying graphics while a redraw is in progress may result in
inconsistent graphics or crashes.
[Nov 3 2025]
- FIXED: Thread specific module and context object. These two global
variables are used in the xpce interface predicates to keep track of
the context. As xpce allows access from multiple threads they must
be thread specific.
- FIXED: Exclude files that require threads for single threaded version.
[Nov 2 2025]
- FIXED: Ensure Prolog exceptions are propagated through xpce.
- FIXED: Epilog: save history in all scenarios This covers closing the
main window using the menu, window close button, Ctrl-D, Shift-Ctrl-W.
[Oct 31 2025]
- ENHANCED: Epilog: use native file dialog
[Oct 30 2025]
- ADDED:
frame<-open_file and frame<-save_file: use OS dialog
to prompt for a file. These new methods use SDL3's interface to file
dialog windows to ask for a file for reading or writing. Tested to
work on MacOS, Windows and Fedora using Gnome.
[Oct 28 2025]
- ENHANCED: Do not load theme based on `display<-theme` if a theme was
already loaded.
- FIXED: Use-after-free in `frame<-confirm` Also allows this method to
run from any thread.
[Oct 27 2025]
- ENHANCED: Show fragment icons vertically aligned in the line.
- COMPAT: Use new message_action/2
- FIXED: Show breakpoints in PceEmacs and GUI tracer No longer rely
on messages. There is a problem with the message system where
user:message_hook/3 is both used to redirect messages and to act
on messages. The latter are hooks that fail, the first are hooks
that succeed. It might be better to have two hooks.
- FIXED: Possible use-after-free
[Oct 26 2025]
- MODIFIED: Epilog terminal to follow links on Ctrl-click Used
to be simple click. This causes too much unintended actions.
Using Ctrl-click is consistent with other terminal emulators.
[Oct 24 2025]
- FIXED: Use-after-free
graphical->unlink destroys its
`<-layout_interface`, i.e., the table_cell. Using a code reference
delays the actual deallocation.
[Oct 23 2025]
- ENHANCED: Avoid deadlocking Epilog if thread is not sensitive to
signals.
- MODIFIED: Windows: open Epilog pipe in client using
FILE_FLAG_OVERLAPPED This patch must be combined with updating the
libedit package.
- FIXED: Thread-safety for passing raw Prolog terms through xpce
[Oct 22 2025]
- FIXED: Erroneous transfer for xpce references.
- FIXED: Allow
frame->wait to be called from any thread.
- FIXED: Make the AnswerStack thread local.
[Oct 21 2025]
- FIXED: Invalidate source location cache after reloading a file.
Broken after introduction of atomic reconsult that preserves clauses
as much as possible.
- FIXED: Memory management for `frame<-confirm` and friends.
- ADDED: GUI Tracer to show details and copy constraints Cycles and
constraints displayed in the Bindings sub-window now support the
Details and Copy functionality.
[Oct 20 2025]
- ENHANCED: do not trace switching the GUI tracer on/off.
- ADDED: Epilog:
Debug menu.
- ENHANCED: Epilog message capturing.
swipl-win: make sure all
messages printed to the main thread end up in an Epilog window.
- FIXED: Possible use-after-free
- FIXED: Possible use-after-free
[Oct 16 2025]
- FIXED: Read beyond the end of local array. May lead to invalid UTF-8
sequences and corrupted terminal output.
- FIXED: Possible memory corruption.
[Oct 12 2025]
- FIXED: Epilog: correctly handle
\e[@. This escape sequence is
used for inserting into the commandline. Its default should be 1 rather
than 0. This fixes inserting into the commandline, notably on Windows.
- FIXED: Various encoding issues in class
file.
[Oct 7 2025]
- FIXED: Lazy binding of Prolog methods was not thread-safe.
[Oct 1 2025]
- FIXED: Make double and triple click in Epilog copy the selection
properly. This set the selection twice from an event, which apparently
causes SDL3 to reset the selection.
- FIXED: Incremental search backspace handling
[Sep 30 2025]
- CLEANUP: Avoid undefined warnings for
gcc -O3
[Sep 26 2025]
- FIXED: Emacs mark+move cursor to maintain an active selection.
[Sep 24 2025]
- FIXED: Correctly handle UTF-8 console output if the buffer ends with
an incomplete UTF-8 character.
[Sep 23 2025]
- FIXED: PceEmacs: make shift-caret movement extend the selection.
Selection is now deactivated without shift.
- FIXED: Resizing the thread monitor too small leads to a type error.
Reported by @mike.elston
Package yaml
[May 10 2026]
- RENAME: yaml.doc -> yaml.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[Jan 22 2026]
- CLEANUP: avoid -Wconversion warnings
Package zlib
[May 10 2026]
- RENAME: zlib.doc -> zlib.plx (LaTeX manual source) Co-Authored-By:
Claude Opus 4.7 (1M context) <noreply@anthropic.com>