Did you know ... Search Documentation:
Title for pldoc(default)
Branch: development (switch to stable),
version to version

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)
    1. 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]

  • ASAN: add comment

[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]

  • ENHANCED: http_post_data/3 to raise an exception if the data is not recognised.

[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
    1. 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 &gt; / &lt; 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 &lt; / &gt; 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]

[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]

  • PORT: Compile using MSVC

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>