All relevant changes from testplant/eggplant/keysight since the divergence from on gnustep_testplant_branch some comments are in https://github.com/gnustep/libs-gui/pull/111

This commit is contained in:
Gregory John Casamento 2021-10-05 11:49:11 -04:00
parent dae13af553
commit 41c25f7d79
14 changed files with 296 additions and 195 deletions

View file

@ -18,13 +18,6 @@
2021-10-27 Gregory John Casamento <greg.casamento@gmail.com>
* Source/NSPopUpButtonCell.m
* Source/NSTabView.m
* Source/NSTextContainer.m
* Source/NSTextFieldCell.m
* Source/NSTextField.m
* Source/NSTextView.m
* Source/NSWindowController.m: Remaining improvements and stability
changes contributed by testplant.
2021-10-27 Gregory John Casamento <greg.casamento@gmail.com>
@ -78,6 +71,9 @@
* Source/NSBitmapImageRep.m: Change initWithBitmapDataPlanes:...
to conform to Apple documented behavior and return nil if it
cannot initialize with the given arguments.
* Source/NSWindowController.m: Manual merge of all relevant
keysight/eggplant changes to the code since the divergence of
the gnustep_testplant_branch several years back.
2021-10-03 Gregory John Casamento <greg.casamento@gmail.com>

View file

@ -45,7 +45,8 @@ Images_RESOURCE_FILES = \
LogoGNUstep.tiff \
MagnifyGlass.tiff \
NSAddTemplate.tiff\
NSComboArrow.tiff \
NSDropDownIndicatorTemplate.png\
NSDropDownIndicatorTemplate-reversed.png\ NSComboArrow.tiff \
NSRatingLevelIndicator.tiff \
NSRemoveTemplate.tiff\
common_2DCheckMark.tiff \

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -755,6 +755,11 @@ Fills in all glyph holes up to last. only looking at levels below level
(last - glyphs->glyph_length) * (glyphs->char_length / (glyphs->glyph_length + 1));
[self _generateGlyphsUpToCharacter: char_last];
// TESTPLANT-MAL-08152017: Not sure why but there are times that this condition
// happens causing an infinite loop...
if (char_last > glyphs->char_length)
break;
}
}
@ -3218,8 +3223,10 @@ forStartingGlyphAtIndex: (NSUInteger)glyph
glyph_run_t *run;
int i;
unsigned int gpos, cpos;
NSSize advances[length];
// TESTPLANT-MAL-07312017: Would be nice to optimize this...
// but we've been seeing stack overwrite crashes due to this...
NSSize *advances = NSZoneMalloc(NSDefaultMallocZone(), sizeof(NSSize)*length);
run = [self run_for_character_index: index : &gpos : &cpos];
if (!run)
{
@ -3245,6 +3252,9 @@ forStartingGlyphAtIndex: (NSUInteger)glyph
length: length
forStartingGlyphAtIndex: glyph
characterIndex: index];
// Cleanup...
NSZoneFree(NSDefaultMallocZone(), advances);
}
- (NSUInteger) layoutOptions

View file

@ -1099,7 +1099,7 @@
* if highlighting is set (when a button is pushed it's
* content is changed to the face of reversed state).
*/
if (mask & NSContentsCellMask)
if (mask & (NSContentsCellMask | NSChangeBackgroundCellMask))
{
imageToDisplay = _altImage;
if (!imageToDisplay)

View file

@ -442,6 +442,10 @@ static NSString *placeholderItem = nil;
x += _itemSize.width + _horizontalMargin;
}
if (_maxNumberOfColumns == 1)
itemFrame.size.width = self.frame.size.width;
return itemFrame;
}
@ -474,6 +478,19 @@ static NSString *placeholderItem = nil;
{
[item setSelected: YES];
}
// GJC: I realize this isn't being used, but it seems informational... we can
// remove it before the final merge.
// Frank LeGrand 4/25/13:
// We set this initial rect as a workaround for a weird display
// issue in our app where the item view would get drawn in front
// of another view (a transparent NSBox) whereas it should stay
// behind.
#if 0
NSRect initRect = NSMakeRect (-10000,-10000,100,100);
[[item view] setFrame:initRect];
#endif
[self addSubview: [item view]];
RELEASE(item);
}

View file

@ -1873,6 +1873,15 @@ static inline NSRect buttonCellFrameFromRect(NSRect cellRect)
- (void) _setSelectedItem: (NSInteger)index
{
_selectedItem = index;
if (index == -1)
{
[self setStringValue: nil];
}
else
{
[self setStringValue: [self _stringValueAtIndex: index]];
}
}
- (void) _loadButtonCell

View file

@ -93,13 +93,15 @@ fb04 'ffl'
characterIndex: (NSUInteger*)index
{
// Try to get enough space for all glyphs
NSGlyph glyphs[2 * num];
// TESTPLANT-MAL-09132018: Would be nice to optimize this...
// but we've been seeing stack overwrite crashes due to this...
NSGlyph *glyphs = NSZoneMalloc(NSDefaultMallocZone(), 2 * num * sizeof(NSGlyph));
NSGlyph *g;
NSGlyph gl;
NSAttributedString *attrstr = [storage attributedString];
GSFontInfo *fi;
int i;
unichar buf[num];
unichar *buf = NSZoneMalloc(NSDefaultMallocZone(), num * sizeof(unichar));
unsigned int cstart = 0;
NSRange maxRange = NSMakeRange(*index, num);
NSRange curRange;
@ -285,7 +287,11 @@ fb04 'ffl'
}
// Send all remaining glyphs
SEND_GLYPHS();
SEND_GLYPHS();
// Cleanup...
NSZoneFree(NSDefaultMallocZone(), glyphs);
NSZoneFree(NSDefaultMallocZone(), buf);
}
@end

View file

@ -1939,154 +1939,182 @@ static NSMapTable *mimeMap = NULL;
{
if (the_server == nil)
{
NSString *host;
NSString *description;
//
// NOTE: This is a bit strange and bears review, I believe what TP is doing here is
// using an external pasteboard server instead of gpbs.
//
// TESTPLANT-MAL-12112017: If the pasteboard server class it available
// the use it directly to avoid windows issue with the GPBS communications...
if (NSClassFromString(@"PasteboardServer") != nil)
{
the_server = [[NSClassFromString(@"PasteboardServer") alloc] init];
}
else // Otherwise fallback to using GPBS...
{
NSString *host;
NSString *description;
host = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
if (host == nil)
{
host = @"";
}
else
{
NSHost *h;
/*
* If we have a host specified, but it is the current host,
* we do not need to ask for a host by name (nameserver lookup
* can be faster) and the empty host name can be used to
* indicate that we may start a pasteboard server locally.
*/
h = [NSHost hostWithName: host];
if (h == nil)
{
NSLog(@"Unknown NSHost (%@) ignored", host);
host = @"";
}
else if ([h isEqual: [NSHost currentHost]] == YES)
{
host = @"";
}
else
{
host = [h name];
}
}
if ([host length] == 0)
{
description = @"local host";
}
else
{
description = host;
}
the_server = (id<GSPasteboardSvr>)[NSConnection
rootProxyForConnectionWithRegisteredName: PBSNAME host: host];
if (the_server == nil && [host length] > 0)
{
NSString *service;
service = [PBSNAME stringByAppendingFormat: @"-%@", host];
the_server = (id<GSPasteboardSvr>)[NSConnection
rootProxyForConnectionWithRegisteredName: service host: @"*"];
}
if (RETAIN((id)the_server) != nil)
{
NSConnection *conn = [(id)the_server connectionForProxy];
Protocol *p = @protocol(GSPasteboardSvr);
[conn enableMultipleThreads];
[conn setReplyTimeout:2.0];
[(id)the_server setProtocolForProxy: p];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_lostServer:)
name: NSConnectionDidDieNotification
object: conn];
}
else
{
static BOOL recursion = NO;
static NSString *cmd = nil;
if (cmd == nil && recursion ==NO)
{
cmd = RETAIN([NSTask launchPathForTool: @"gpbs"]);
}
if (recursion == YES || cmd == nil)
{
NSLog(@"Unable to contact pasteboard server - "
@"please ensure that gpbs is running for %@.", description);
return nil;
}
else
{
NSNotificationCenter *nc;
NSMutableArray *startIndicator;
NSArray *args = nil;
NSDate *timeoutDate;
NSDebugLLog(@"NSPasteboard",
@"\nI couldn't contact the pasteboard server for %@ -\n"
@"so I'm attempting to start one - which might take a few seconds.\n"
@"Trying to launch gpbs from %@ or a machine/operating-system subdirectory.\n",
description, [cmd stringByDeletingLastPathComponent]);
if ([host length] > 0)
{
args = [[NSArray alloc] initWithObjects:
@"-NSHost", host,
@"-GSStartupNotification", @"GSStartup-GPBS",
@"--auto",
nil];
}
else
{
args = [[NSArray alloc] initWithObjects:
@"-GSStartupNotification",@"GSStartup-GPBS",
@"--auto",
nil];
}
/*
Trick: To avoid having to use global variables or new methods
to track whether the notification has been received or not, we
use a mutable array as an indicator. When the notification is
received, the array is emptied, so we just check the count.
*/
startIndicator = [[NSMutableArray alloc] initWithObjects:
AUTORELEASE([[NSObject alloc] init]), nil];
nc = [NSDistributedNotificationCenter defaultCenter];
[nc addObserver: startIndicator
selector: @selector(removeAllObjects)
name: @"GSStartup-GPBS"
object: nil];
host = [[NSUserDefaults standardUserDefaults] stringForKey: @"NSHost"];
if (host == nil)
{
host = @"";
}
else
{
NSHost *h;
/*
* If we have a host specified, but it is the current host,
* we do not need to ask for a host by name (nameserver lookup
* can be faster) and the empty host name can be used to
* indicate that we may start a pasteboard server locally.
*/
h = [NSHost hostWithName: host];
if (h == nil)
{
NSLog(@"Unknown NSHost (%@) ignored", host);
host = @"";
}
else if ([h isEqual: [NSHost currentHost]] == YES)
{
host = @"";
}
else
{
host = [h name];
}
}
if ([host length] == 0)
{
description = @"local host";
}
else
{
description = host;
}
the_server = (id<GSPasteboardSvr>)[NSConnection
rootProxyForConnectionWithRegisteredName: PBSNAME host: host];
if (the_server == nil && [host length] > 0)
{
NSString *service;
service = [PBSNAME stringByAppendingFormat: @"-%@", host];
the_server = (id<GSPasteboardSvr>)[NSConnection
rootProxyForConnectionWithRegisteredName: service host: @"*"];
}
if (RETAIN((id)the_server) != nil)
{
NSConnection *conn = [(id)the_server connectionForProxy];
Protocol *p = @protocol(GSPasteboardSvr);
[conn enableMultipleThreads];
[conn setReplyTimeout:2.0];
[(id)the_server setProtocolForProxy: p];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_lostServer:)
name: NSConnectionDidDieNotification
object: conn];
}
else
{
static BOOL recursion = NO;
static NSString *cmd = nil;
if (cmd == nil && recursion ==NO)
{
cmd = RETAIN([NSTask launchPathForTool: @"gpbs"]);
}
if (recursion == YES || cmd == nil)
{
NSLog(@"Unable to contact pasteboard server - "
@"please ensure that gpbs is running for %@.", description);
return nil;
}
else
{
NSNotificationCenter *nc;
NSMutableArray *startIndicator;
NSArray *args = nil;
NSDate *timeoutDate;
NSDebugLLog(@"NSPasteboard",
@"\nI couldn't contact the pasteboard server for %@ -\n"
@"so I'm attempting to start one - which might take a few seconds.\n"
@"Trying to launch gpbs from %@ or a machine/operating-system subdirectory.\n",
description, [cmd stringByDeletingLastPathComponent]);
if ([host length] > 0)
{
args = [[NSArray alloc] initWithObjects:
@"-NSHost", host,
@"-GSStartupNotification", @"GSStartup-GPBS",
@"--auto",
nil];
}
else
{
args = [[NSArray alloc] initWithObjects:
@"-GSStartupNotification",@"GSStartup-GPBS",
@"--auto",
nil];
}
/*
Trick: To avoid having to use global variables or new methods
to track whether the notification has been received or not, we
use a mutable array as an indicator. When the notification is
received, the array is emptied, so we just check the count.
*/
startIndicator = [[NSMutableArray alloc] initWithObjects:
AUTORELEASE([[NSObject alloc] init]), nil];
nc = [NSDistributedNotificationCenter defaultCenter];
[nc addObserver: startIndicator
selector: @selector(removeAllObjects)
name: @"GSStartup-GPBS"
object: nil];
[NSTask launchedTaskWithLaunchPath: cmd arguments: args];
RELEASE(args);
timeoutDate = [NSDate dateWithTimeIntervalSinceNow: 5.0];
while ([startIndicator count]
&& [timeoutDate timeIntervalSinceNow] > 0.0)
{
[[NSRunLoop currentRunLoop]
runMode: NSDefaultRunLoopMode
beforeDate: timeoutDate];
}
[nc removeObserver: startIndicator];
DESTROY(startIndicator);
recursion = YES;
[self _pbs];
recursion = NO;
}
}
#if defined(__MINGW32__)
//
// NOTE: By ePF they mean the parent process... not sure if this is needed.
//
// Testplant-MAL-10042016: keeping branch code
// Needed in order to avoid sub-tasks from inheriting and writing to
// ePF log files...
NSTask *task = AUTORELEASE([NSTask new]);
[task setStandardError:[NSFileHandle fileHandleForWritingAtPath:@"NUL"]];
[task setStandardOutput:[NSFileHandle fileHandleForWritingAtPath:@"NUL"]];
[task setLaunchPath:cmd];
[task setArguments:args];
[task launch];
#else
[NSTask launchedTaskWithLaunchPath: cmd arguments: args];
#endif
RELEASE(args);
timeoutDate = [NSDate dateWithTimeIntervalSinceNow: 5.0];
while ([startIndicator count]
&& [timeoutDate timeIntervalSinceNow] > 0.0)
{
[[NSRunLoop currentRunLoop]
runMode: NSDefaultRunLoopMode
beforeDate: timeoutDate];
}
[nc removeObserver: startIndicator];
DESTROY(startIndicator);
recursion = YES;
[self _pbs];
recursion = NO;
}
}
}
}
return the_server;
}

View file

@ -232,6 +232,14 @@ this to return nil to indicate that we have no context menu.
[_cell removeItemAtIndex: index];
[self synchronizeTitleAndSelectedItem];
// TESTPLANT-MAL-09182017: removing causes a multiple sequence eventually
// deselecting any item - after multiple attempts to try to avoid the sequence
// we'll just override the selection at this point...
if ([_cell usesItemFromMenu] && ([self selectedItem] == nil) && ([self numberOfItems] > 0))
{
[self selectItemAtIndex: [self numberOfItems]-1];
}
}
/** <p>Returns the selected item</p>

View file

@ -157,7 +157,7 @@
[super setFont: f];
}
- (NSAttributedString *)_replacementAttributedString
- (NSAttributedString *) _replacementAttributedString
{
NSDictionary *attributes;
NSMutableString *string;
@ -183,7 +183,7 @@
- (NSAttributedString*) _drawAttributedString
{
if (_echosBullets)
if (_echosBullets && (0 < [[self stringValue] length]))
{
if (!_cell.is_disabled)
{
@ -207,22 +207,27 @@
attributes: newAttribs]);
}
}
else
{
/* .. do nothing. */
return nil;
}
// Default to super return on null/empty string...i.e. placeholder...
return [super _drawAttributedString];
}
- (NSText *) setUpFieldEditorAttributes: (NSText *)textObject
{
NSSecureTextView *secureView;
if ([self echosBullets])
{
NSSecureTextView *secureView;
/* Replace the text object with a secure instance. It's not shared. */
secureView = AUTORELEASE([[NSSecureTextView alloc] init]);
/* Replace the text object with a secure instance. It's not shared. */
secureView = AUTORELEASE([[NSSecureTextView alloc] init]);
[secureView setEchosBullets: [self echosBullets]];
return [super setUpFieldEditorAttributes: secureView];
[secureView setEchosBullets: [self echosBullets]];
return [super setUpFieldEditorAttributes: secureView];
}
// Otherwise...
return [super setUpFieldEditorAttributes: textObject];
}
- (id) initWithCoder: (NSCoder *)decoder
@ -233,7 +238,17 @@
if ([decoder allowsKeyedCoding])
{
_echosBullets = [decoder decodeBoolForKey: @"GSEchoBullets"];
// Default to on...
[self setEchosBullets: YES];
if ([decoder containsValueForKey: @"GSEchoBullets"])
{
_echosBullets = [decoder decodeBoolForKey: @"GSEchoBullets"]; // XIB5 decoding...
}
else if ([decoder containsValueForKey: @"NSEchosBullets"])
{
_echosBullets = [decoder decodeBoolForKey: @"NSEchosBullets"];
}
}
else
{
@ -263,7 +278,7 @@
glyphIndex: (NSUInteger*)glyph
characterIndex: (NSUInteger*)index
{
NSGlyph glyphs[num];
NSGlyph *glyphs = NSZoneMalloc(NSDefaultMallocZone(), (sizeof(NSGlyph) * num));
NSGlyph gl;
NSAttributedString *attrstr = [storage attributedString];
GSFontInfo *fi;
@ -293,6 +308,9 @@
length: num
forStartingGlyphAtIndex: *glyph
characterIndex: *index];
// Cleanup
NSZoneFree(NSDefaultMallocZone(), glyphs);
}
@end

View file

@ -113,30 +113,38 @@ extern NSString *GSSpellServerName(NSString *checkerDictionary, NSString *langua
}
id<NSSpellServerPrivateProtocol> proxy = nil;
NSDictionary *spellCheckers = [_allServices objectForKey: @"BySpell"];
NSDictionary *checkerDictionary = [spellCheckers objectForKey: language];
NSString *spellServicePath = [checkerDictionary objectForKey: @"ServicePath"];
NSString *vendor = [checkerDictionary objectForKey: @"NSSpellChecker"];
NSDate *finishBy;
NSString *port = GSSpellServerName(vendor, language);
double seconds = 30.0;
NSLog(@"Language: %@", language);
NSLog(@"Service to start: %@", spellServicePath);
NSLog(@"Port: %@",port);
finishBy = [NSDate dateWithTimeIntervalSinceNow: seconds];
proxy = GSContactApplication(spellServicePath, port, finishBy);
if (proxy == nil)
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"GSDisableSpellCheckerServer"])
{
NSLog(@"Failed to contact spell checker for language '%@'", language);
GSOnceMLog(@"WARNING: spell checker disabled - reset 'GSDisableSpellCheckerServer' to NO in defaults to re-enable");
}
else
{
NSLog(@"Set proxy");
[(NSDistantObject *)proxy setProtocolForProxy:
@protocol(NSSpellServerPrivateProtocol)];
NSDictionary *spellCheckers = [_allServices objectForKey: @"BySpell"];
NSDictionary *checkerDictionary = [spellCheckers objectForKey: language];
NSString *spellServicePath = [checkerDictionary objectForKey: @"ServicePath"];
NSString *vendor = [checkerDictionary objectForKey: @"NSSpellChecker"];
NSDate *finishBy;
NSString *port = GSSpellServerName(vendor, language);
double seconds = 30.0;
NSLog(@"Language: %@", language);
NSLog(@"Service to start: %@", spellServicePath);
NSLog(@"Port: %@",port);
finishBy = [NSDate dateWithTimeIntervalSinceNow: seconds];
proxy = GSContactApplication(spellServicePath, port, finishBy);
if (proxy == nil)
{
NSLog(@"Failed to contact spell checker for language '%@'", language);
}
else
{
NSLog(@"Set proxy");
[(NSDistantObject *)proxy setProtocolForProxy:
@protocol(NSSpellServerPrivateProtocol)];
}
}
return proxy;

View file

@ -134,7 +134,7 @@ static Class textFieldCellClass;
*/
- (BOOL) isSelectable
{
return [_cell isSelectable];
return [_cell isSelectable] && [self isEnabled];
}
/** <p>Sets whether the NSTextField's cell and the NSText object is editable.