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

SWI-Prolog Changelog from version 10.1.8 to 10.1.9

[Jun 15 2026]

  • 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.

Package cpp

[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).

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.

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.

Package pldoc

[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).

Package utf8proc

[May 29 2026]

  • FIXED: install additional file in tests folder needed for the runtime unit tests

Package xpce

[Jun 15 2026]

  • 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.