From 99b47c9a291956566ebcafe3925ca44f5ce90e93 Mon Sep 17 00:00:00 2001 From: David Richardson Date: Thu, 22 Oct 2026 12:35:00 -0600 Subject: [PATCH 1/3] Foundation: Fix CPDecimalAdd overflow sign swap 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. --- Foundation/CPDecimal.j | 2 +- Tests/Foundation/CPDecimalTest.j | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Foundation/CPDecimal.j b/Foundation/CPDecimal.j index 54bb53353..98669882d 100644 --- a/Foundation/CPDecimal.j +++ b/Foundation/CPDecimal.j @@ -608,7 +608,7 @@ function CPDecimalAdd(result, leftOperand, rightOperand, roundingMode, longMode) // swap sign over over/underflow exception if (CPCalculationUnderflow == adderror) adderror = CPCalculationOverflow; - else if (CPCalculationUnderflow == adderror) + else if (CPCalculationOverflow == adderror) adderror = CPCalculationUnderflow; } else diff --git a/Tests/Foundation/CPDecimalTest.j b/Tests/Foundation/CPDecimalTest.j index 2c17741c7..3326d628d 100644 --- a/Tests/Foundation/CPDecimalTest.j +++ b/Tests/Foundation/CPDecimalTest.j @@ -468,6 +468,12 @@ d1 = CPDecimalMakeWithString(@"1e127"); d2 = CPDecimalMakeWithString(@"99999999999999999999999999999999999999e127"); [self assert:CPDecimalAdd(d1, d1, d2, CPRoundPlain) equals:CPCalculationOverflow message:"CPDecimalAdd() Tao1: addition loss of precision"]; + + // Overflow of two negative operands is reported as underflow + d1 = CPDecimalMakeWithString(@"-1e127"); + d2 = CPDecimalMakeWithString(@"-99999999999999999999999999999999999999e127"); + [self assert:CPCalculationUnderflow equals:CPDecimalAdd(d1, d1, d2, CPRoundPlain) message:"CPDecimalAdd() Tao2: negative overflow is reported as underflow"]; + [self assert:YES equals:d1._isNegative message:"CPDecimalAdd() Tao2: sign"]; } - (void)testSubtract From 203bf38b210cc2782812ca61ba91f71ac7d149f2 Mon Sep 17 00:00:00 2001 From: David Richardson Date: Thu, 22 Oct 2026 12:36:32 -0600 Subject: [PATCH 2/3] AppKit: Size vertical scrollers by scroller style in CPScrollView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- AppKit/CPScrollView.j | 4 +-- Tests/AppKit/CPScrollViewTest.j | 43 +++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/AppKit/CPScrollView.j b/AppKit/CPScrollView.j index 45f98d5f0..716d34550 100644 --- a/AppKit/CPScrollView.j +++ b/AppKit/CPScrollView.j @@ -207,7 +207,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, bounds.size.height -= [horizontalScrollerClass scrollerWidthInStyle:scrollerStyle]; if (verticalScrollerClass) - bounds.size.width -= [verticalScrollerClass scrollerWidthForControlSize:scrollerStyle]; + bounds.size.width -= [verticalScrollerClass scrollerWidthInStyle:scrollerStyle]; return bounds.size; } @@ -240,7 +240,7 @@ var CPScrollerStyleGlobal = CPScrollerStyleOverlay, frameSize.height += [horizontalScrollerClass scrollerWidthInStyle:scrollerStyle]; if (verticalScrollerClass) - frameSize.width += [verticalScrollerClass scrollerWidthForControlSize:scrollerStyle]; + frameSize.width += [verticalScrollerClass scrollerWidthInStyle:scrollerStyle]; return frameSize; } diff --git a/Tests/AppKit/CPScrollViewTest.j b/Tests/AppKit/CPScrollViewTest.j index be937a1c9..15ee3ec5c 100644 --- a/Tests/AppKit/CPScrollViewTest.j +++ b/Tests/AppKit/CPScrollViewTest.j @@ -379,5 +379,48 @@ [self assertSize:expected.size equals:actual.size message:message] } +- (void)testFrameSizeForContentSizeUsesScrollerStyleForBothScrollers +{ + var frameSize = [CPScrollView frameSizeForContentSize:CGSizeMake(100.0, 100.0) + horizontalScrollerClass:[_CPScrollViewTestScroller class] + verticalScrollerClass:[_CPScrollViewTestScroller class] + borderType:CPNoBorder + controlSize:CPRegularControlSize + scrollerStyle:CPScrollerStyleOverlay]; + + [self assertSize:CGSizeMake(105.0, 105.0) equals:frameSize message:@"both scroller widths come from scrollerWidthInStyle:"]; +} + +- (void)testContentSizeForFrameSizeUsesScrollerStyleForBothScrollers +{ + var contentSize = [CPScrollView contentSizeForFrameSize:CGSizeMake(100.0, 100.0) + horizontalScrollerClass:[_CPScrollViewTestScroller class] + verticalScrollerClass:[_CPScrollViewTestScroller class] + borderType:CPNoBorder + controlSize:CPRegularControlSize + scrollerStyle:CPScrollerStyleOverlay]; + + [self assertSize:CGSizeMake(95.0, 95.0) equals:contentSize message:@"both scroller widths come from scrollerWidthInStyle:"]; +} + @end + +/*! + A scroller whose widths differ by style, and whose control-size width differs + from both, so a size calculation that uses the wrong method is detectable + regardless of the theme. +*/ +@implementation _CPScrollViewTestScroller : CPScroller + ++ (float)scrollerWidthInStyle:(CPScrollerStyle)aStyle +{ + return aStyle === CPScrollerStyleOverlay ? 5.0 : 20.0; +} + ++ (float)scrollerWidthForControlSize:(CPControlSize)aControlSize +{ + return 99.0; +} + +@end From ac709c97bf0a00dcd1153284ab52a8ab3c83166b Mon Sep 17 00:00:00 2001 From: David Richardson Date: Thu, 22 Oct 2026 12:37:02 -0600 Subject: [PATCH 3/3] AppKit: Document CPAlert's return code as the clicked button's tag CPAlert's documentation described the return code as the button index, which is only its default tag. * CPAlert: Document the alert return code as the clicked button's tag, which is its index unless changed. --- AppKit/CPAlert.j | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AppKit/CPAlert.j b/AppKit/CPAlert.j index 08c4fa030..1f6fe0c8b 100644 --- a/AppKit/CPAlert.j +++ b/AppKit/CPAlert.j @@ -137,7 +137,8 @@ var bottomHeight = 71; @delegate -(void)alertDidEnd:(CPAlert)theAlert returnCode:(int)returnCode; Called when the user dismisses the alert by clicking one of the buttons. @param theAlert the alert panel that the user dismissed - @param returnCode the index of the button that the user clicked (starting from 0, + @param returnCode the tag of the button that the user clicked. Unless a button's + tag has been changed, it is the button's index (starting from 0, representing the first button added to the alert which appears on the right, 1 representing the next button to the left and so on) */