A text view handled undo: and redo: and registered its changes even when allowsUndo was NO, so Edit > Undo stayed enabled and did nothing.
Behaviour now follows canonical Cocoa: a text view that does not allow undo registers nothing and passes undo: and redo: on to the window, and Undo and Redo are enabled only when there is a change to undo or redo.
* CPTextView/CPTextView.j: Register changes only when undo is allowed, stop responding to undo: and redo: when it is not, and validate the Undo and Redo items against the undo manager.
* CPWindow/CPWindow.j: Validate the Undo and Redo items against the window's undo manager.
* Tests/AppKit/CPTextViewTest.j: Add tests for responding to undo:, registering changes and validating the Undo item.
* Tests/Manual/TextEditor/DocumentWindowController.j: Add toggleAllowsUndo: and validateMenuItem:, so that undo can be turned on and off for the active document.
* Tests/Manual/TextEditor/Resources/MainMenu.xib, Resources/MainMenu.cib: Add Edit > Allow Undo.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, record Allow Undo as tested, and add the key equivalent behaviour of disabled menu items for discussion.
AppKit read only CPBundleName for the name that users see, so an application's display name was ignored. It now follows Cocoa, which shows CFBundleDisplayName and falls back to CFBundleName.
* CPApplication.j: Add _applicationName, which returns CPBundleDisplayName or, without one, CPBundleName, and use it as the About panel title.
* CPMenu/_CPMenuBarWindow.j: Use the display name in the browser tab title.
* Tests/Manual/TextEditor/Info.plist: Rename the display name key from CFBundleDisplayName to CPBundleDisplayName.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, and record the About panel as tested.
The Window menu never listed the application's windows, because AppKit had none of Cocoa's Windows menu support.
* CPApplication.j: Add windowsMenu, setWindowsMenu:, addWindowsItem:title:filename:, changeWindowsItem:title:filename:, removeWindowsItem:, updateWindowsItem: and arrangeInFront:; find the menu named _CPWindowsMenu in the main menu, and list the visible windows when the main menu is set.
* CPWindow/CPWindow.j: Add isExcludedFromWindowsMenu and setExcludedFromWindowsMenu:, and keep the window's item current when the window is ordered in or out, retitled, made main or no longer main, miniaturized, deminiaturized or closed.
* Tests/AppKit/CPApplicationWindowsMenuTest.j: Add tests for listing, retitling, exclusion, the main window check mark, separator handling, file name titles and moving items to another Windows menu.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this gap, and record the Window menu as tested.
The Show Toolbar menu item toggled the toolbar, but CPWindow did not validate it, so its title never changed and it stayed enabled in windows without a toolbar.
* CPWindow/CPWindow.j: Add validateUserInterfaceItem:, which sets the toggleToolbarShown: item's title to Hide Toolbar or Show Toolbar and enables it only when the window has a toolbar.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this defect, and record the menu item as tested.
The TextEditor work list recorded redo as unreliable. Retesting proved that undo and redo work correctly.
Supporting investigation disclosed an edge case in CPUndoManager: when undo ran in the same run loop cycle as the change it reverted, it closed the open event grouping itself, but the run loop's scheduled close still ran and raised CPInternalInconsistencyException because no grouping was open.
* Foundation/CPUndoManager.j: Cancel the run loop's scheduled close when undo closes the event grouping itself.
* Tests/Foundation/CPUndoManagerTest.j: Add a test that undoes a change in the same run loop cycle and then redoes it, and correct the doIt selector registered by the undoIt helper.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the redo entry recorded in error, and record undo and redo as tested.
A window stored the proposed size in its frame before asking its delegate through windowWillResize:toSize:, and gave the delegate's size only to the window view. When the delegate enlarged the size, hit testing used the smaller frame, so the window could no longer be moved or resized.
* CPWindow/CPWindow.j: Ask the delegate before storing the new size, and store the size it returns in the frame.
* CPWindow/_CPWindowView.j: Ask the delegate during a user resize, and move the origin by the delegate's adjustment when resizing from the left or top edge, so that the opposite edge stays in place.
* Tests/Manual/TextEditor/Resources/DocumentWindow.xib: Make the document window's content view resize with the window.
* Tests/Manual/TextEditor/WORKLIST.md: Remove the entry for this defect, record the minimum window size behaviour as tested, and add the content view resizing setting that does not reach the cib.
Add the AppKit gaps found since the work list was created, and describe the visible effect of the window resize defect.
* WORKLIST.md: Add entries for CPBundleDisplayName, which AppKit ignores, and for the Show Toolbar menu item, which never reflects the toolbar state; state that a window shrunk to its minimum size can no longer be moved or resized, because hit testing uses the unclamped frame.
Give TextEditor a display name and a real bundle identifier, and replace the template copyright and author placeholders.
* Info.plist: Set the bundle identifier to dev.cappuccino.TextEditor, add the display name TextEdit by Cappuccino, and state the MIT license in the copyright string.
* Jakefile: Set the same bundle identifier and remove the placeholder email.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Use the display name in the application menu, About and Help items.
Remove the conditional comments for Internet Explorer 8 and 9 that the capp gen template added, since no supported browser reads them.
* index.html, index-debug.html: Remove the X-UA-Compatible meta elements and their IE conditional comments.
Stop document windows from shrinking below a usable size, and record the AppKit gaps that TextEditor has found.
* DocumentWindowController.j: Implement windowWillResize:toSize: to keep the window at or above provisional minimum dimensions.
* WORKLIST.md: Add a work list of the AppKit gaps found by TextEditor, the planned additions to the app and the tests done.
Add the bundle package type and identifier to the TextEditor Info.plist, so that the build does not have to derive them.
* Info.plist: Add CPBundlePackageType APPL and CPBundleIdentifier.
Turn on the text view's horizontal ruler in code, because nib2cib does not carry the Interface Builder ruler settings into the cib.
* DocumentWindowController.j: Enable the horizontal ruler on the text view's enclosing scroll view in windowDidLoad, with a comment explaining why it is set up in code.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Remove the Insert Lorem Ipsum key equivalent, which duplicated File > New.
Give the document window a scrolling text view and a toolbar, and add an Edit menu item that inserts placeholder text into the active document.
* LoremIpsum.j: Add a class that supplies the traditional Lorem ipsum passage as static text.
* DocumentWindowController.j: Add a textView outlet and an insertLoremIpsum: action that inserts the placeholder text at the selection through insertText:, so the document's undo manager records it.
* Resources/DocumentWindow.xib, Resources/DocumentWindow.cib: Add a text view in a scroll view that resizes with the window, a toolbar with the default items, and the textView outlet connection.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Add an Insert Lorem Ipsum item to the Edit menu that sends insertLoremIpsum: to First Responder.
Move the main window out of MainMenu.xib into a document window owned by a window controller, so that each document opens in its own window.
* Document.j: Add a CPDocument subclass that creates a DocumentWindowController for each document.
* DocumentWindowController.j: Add a CPWindowController subclass that loads DocumentWindow.cib and sets itself as the window's delegate.
* Resources/DocumentWindow.xib, Resources/DocumentWindow.cib: Add the document window, with DocumentWindowController as File's Owner.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Remove the window, name the application menu Text Editor, rename Preferences to Settings, and remove Quit.
* AppController.j: Remove the window outlet and the code that made the window fill the browser.
* main.j: Import Document.j.
* Info.plist: Declare the Document type with Document as its document class.
Add a cib-based application generated by capp gen as the foundation for a document-based test application and tutorial, MIT licensed.
* The application is a starting point for new applications, so a permissive license lets developers copy its code into their own work without obligations beyond keeping the notice.
* AppController.j, main.j, Jakefile, index.html, index-debug.html: Replace the template header with an MIT header naming the author as copyright holder.
* main.j: Correct the file name in the header.
* Info.plist, Jakefile: Replace the template author placeholder with the author.
* LICENSE: Add the MIT License text.
* Resources/MainMenu.xib, Resources/MainMenu.cib: Add the template main menu.
CPScrollView's frame and content size calculations sized the vertical scroller with scrollerWidthForControlSize:, passing a scroller style, so it always took the legacy width.
* CPScrollView: Use scrollerWidthInStyle: for the vertical scroller in +contentSizeForFrameSize:… and +frameSizeForContentSize:….
* CPScrollViewTest: Add tests for both methods with a scroller whose widths differ by style.
CPDecimalAdd tested for underflow twice when reporting overflow of two negative operands, so the overflow was never swapped to underflow.
* CPDecimal: Swap CPCalculationOverflow to CPCalculationUnderflow for a negative result, matching CPDecimalSubtract.
* CPDecimalTest: Add a test that the overflow of two negative operands is reported as underflow.
Manual tests could only be provisioned with the legacy framework builds.
* Manual/Jakefile: Add configure-modern, which links every manual test's Frameworks and Frameworks/Debug to the capp-build package in Build/modern/Frameworks; share the provisioning with configure through provisionFrameworks.
- Add missing index-debug.html entry point to SmartFoldersDemo.
- Update Tests/Manual/Jakefile configure and clobber tasks to link Release and Debug framework variants (Objective-J, Foundation, AppKit, BlendKit) across all manual tests.
- Safeguard symlink replacement logic to correctly handle existing links while protecting physical asset directories.
CPDOMAvailable was read during load before it was assigned.
* CPCompatibility: Move the CPDOMAvailable assignment ahead of the engine detection, whose AppleWebKit case calls +[CPPlatform isBrowser], which reads it.
* CPCompatibilityTest: Add a test that re-executes CPCompatibility.j with an AppleWebKit user agent and CPDOMAvailable unset, failing on any exception.
- the 11 display-server primitives become plain functions in
Platform/DOM/CPDOMDisplayServer.j; bodies verbatim from the macro
definitions; the header was force-included into every AppKit
compilation by the legacy build and invisible to capp-build
- CPView.j, CPImageView.j, _CPDisplayServer.j import the new file;
this was the last header in either framework
- CPDOMDisplayServerTest: the raw #include replaced by the
framework-qualified import
- the six GET_LEVEL_INDICATOR_SEGMENT call sites become direct
layoutEphemeralSubviewNamed: messages; the macro was fully
parameterized with no ambient state
- the segment index is the literal 0 at every site, so the
concatenation folds to a constant string
- the warning comment about direct ephemeral-subview access is
retained
- the seven UIAssert call sites become direct
[self markTest:_cmd didPass:...] messages, matching the direct
calls already used elsewhere in the file
- the macro expanded to the same expression using the enclosing
method's _cmd, which the completion closures capture identically;
behavior unchanged
- CoreGraphics/CGContextVML.j removed; it implemented the CGContext
function family against Internet Explorer's VML, irrelevant in the
supported browser landscape for over a decade
- its self-replacing CGBitmapGraphicsContextCreate wrapper called
document.namespaces.add, an IE-only API — a latent crash on modern
browsers had the branch ever been selected
- CGContext.j: the CPVMLFeature branch of the load-time backend
selection removed; CPCompatibility.j: the CPVMLFeature constant and
its feature-table entry removed
- Tests/AppKit/CGContextTest.j: the vacuous VML-incompatibility
assertion removed
- the canvas backend and the no-canvas stubs are unchanged
- Update clean and clobber targets in Tests/Manual/Jakefile to enforce -mindepth 2 -maxdepth 2 traversal. This accurately purges subsidiary Build directories and Frameworks symlinks without triggering subjake dependency cycles.
- Inject explicit clean and clobber overrides into all 150+ subsidiary application Jakefiles. This forces local execution to wipe the top-level Build directory, bypassing applicationtask's default behavior of only targeting configuration-specific intermediate paths.
- Harmonizes artifact sweeping across both root-level orchestration and local leaf-level execution.
- Consolidate dual root `build` tasks into a unified target that initializes the build environment and spawns the orchestration pipeline cleanly.
- Replace individual test symlink creation in root `Jakefile` with an `assemble-frameworks` task that constructs a complete, portable `Build/Frameworks` directory.
- Update `Tests/Manual/Jakefile` `configure` task to target project root `Build/Frameworks` directly and streamline `clobber` operations.
Caveat: Tests/Manual subsidiary applications do not have functioning ‘clean’ and ‘clobber’ targets.
- Consolidate dual root `build` tasks into a unified target that initializes the build environment and spawns the orchestration pipeline cleanly.
- Replace individual test symlink creation in root `Jakefile` with an `assemble-frameworks` task that constructs a complete, portable `Build/Frameworks` directory.
- Update `Tests/Manual/Jakefile` `configure` task to target project root `Build/Frameworks` directly and streamline `clobber` operations
- Caveat: Jakefile in each subsidiary application does not include ‘clean’ and ‘clobber’ targets.
The legacy dist, debug, and release Jake targets have been deprecated in favor of a unified build command, aligning the repository with standard conventions.
Node toolchain execution is sufficiently fast to generate both release and debug artifacts simultaneously within a single pass.
The symlinks within Tests/Manual/.Frameworks have been redirected to point to the unified Build artifacts rather than the obsolete dist directory.
Repository reset operations have also been corrected to ensure comprehensive artifact removal.
The root Jakefile now explicitly projects clean and clobber tasks into Tests/Manual; the clobber task now correctly removes Tests/Manual/.Frameworks along with the Frameworks directories in each subsidiary test.
Transitioning to native JavaScript timezone APIs in CPTimeZone exposed latent defects in CPDateFormatter's token parsing and offset generation.
* Update CPDateFormatterTest to enforce strict UTC temporal baseline matching.
* Bypass unreliable host JavaScript local string parsing heuristics in `_dateFromTokens:dateComponents:` by implementing native `Date.UTC()` absolute timestamp construction.
* Fix GMT offset string generation for the `Z` token to correctly evaluate zero-offset timezones as positive, ensuring standard `+0000` formatting instead of `-0000`.
Expand test coverage for timezone parsing, offset evaluation, and GMT validation.
Establishes a strict temporal baseline and formally exposes existing logic flaws in CPTimeZone prior to applying implementation fixes.
Deletes the Python migration script and shell restoration utilities used to transition the Tests/Manual directory to the @objj/jake toolchain.
The subsidiary Jakefile migration is complete.
The scripts are removed from the active tree to prevent repository clutter, while their implementation details and exact transformation logic remain permanently verifiable in the git history.
Applies the transformation script across all applications in the Tests/Manual directory to eliminate Narwhal-era dependencies and establish compatibility with the modern Node-based runner.
* Removes explicit `require("jake")` calls in favor of the injected JAKE global.
* Replaces legacy `cappuccino/jake` application instantiation with the `CAPPUCCINO.Jake.applicationtask.app` hook.
* Substitutes archaic `system`, `file`, and `os` API calls with native Node `child_process`, `fs`, and `path` modules.
* Corrects package paths for nativehost deployment targets.
Commit the Python migration script and the shell restoration loop used to batch-process the transition of legacy test Jakefiles to the modern Node toolchain.
These scripts provide an auditable record of the automated transformations applied to the test suite and will be removed in a subsequent commit - once the migration is complete.
Updates the transformation script to target the modern Node-based Cappuccino toolchain, removing Narwhal-era APIs from test configurations.
* Replaces legacy `require("jake")` with the implicitly injected `JAKE` global.
* Routes application task instantiation through the modern `CAPPUCCINO.Jake.applicationtask.app` hook.
* Substitutes archaic `OS`, `FILE`, and `system` module calls with native Node `fs`, `path`, and `child_process` equivalents.
* Corrects package pathing for `nativehost` references.
Removes recursive JAKE.subjake calls from the root Jakefile, eliminating silent error masking and path evaluation failures during test suite compilation. Replace subjake with POSIX find.
* Replaces Node-based directory traversal with POSIX find and -execdir to guarantee correct working directory context and propagate standard output.
* Restricts the `clean` task strictly to the removal of build artifacts.
* Introduces a `clobber` task to remove Frameworks symlinks alongside build artifacts, restoring the test directories to a pristine state.
Ensure:
* CamelCase, ending in Test
* No hyphens, spaces, underscores or other non-alpha characters
Updated application directory names.
Update Jakefiles.
* Replace generic 'NewApplication' placeholder strings with specific product names.
* Extract target names from Jakefile and assert parity with Info.plist CPBundleName.
* Improve visual grounding during manual test suite auditing.