help with declare

Hello,
thru macOSlibrsry I am trying to get availableMembersOfFontFamily

Function AvailableMembersOfFontFamily(theFamily as string) As String()
#if TargetMacOS
declare function availableMembersOfFontFamily lib CocoaLib selector “availableMembersOfFontFamily:” (id as Ptr, name as CFStringRef) as Ptr

return GetStringValues(new NSArray(availableMembersOfFontFamily(self, theFamily)))

#endif
End Function

Running the following code I get a TypeMismatchException

dim ns as new Cocoa.NSFontManager
dim s() as String = ns.AvailableFontFamilies

for i as Integer = 0 to UBound(s)
if s(i) = fontPopup(0).text then//for instance “Palatino”
dim t() as string = ns.availableMembersOfFontFamily(s(i)) //here: TypeMismatchException
MsgBox Join(t, EndOfLine)
Return
end if
next

Any suggestion how to solve this problem? Thanks.

So I guess the declare in macOSlib is wrong.
Thanks.

How is getStringValues defined?

The current issue of XDev Magazine has a great article on OS X fonts (and Xojo declares) by Marc Zeedar, btw., and he mentions this thread https://forum.xojo.com/26247-use-the-light-version-of-a-font/p1 as a good starting point.

Carlo, the declare is probably correct.
Just you can’t expect a Xojo array back. The function returns a NSArray.

I thought so too, but it returns the result of GetStringValues that seems to be a conversion from NSArray to String().

Ahhh right Ulrich :wink:

Since I’m not proficient on declares, I just take what I see. In this particular case: “Function AvailableMembersOfFontFamily(theFamily as string) As String()” I thought that I could just rely on a Xojo array; but it fails.

Could you post the code for the method mentioned above? As Massimo wrote, the declare looks okay. It is either a problem with the NSArray constructor or (which I suspect more) the GetStringValues method.

Do you mean these two functions? Or something else?
BTW: in macOSlib, the other instances of getStringValue return valid data (for instance, an array of available fonts).

Function AvailableMembersOfFontFamily(theFamily as string) As String()
#if TargetMacOS
declare function availableMembersOfFontFamily lib CocoaLib selector “availableMembersOfFontFamily:” (id as Ptr, name as CFStringRef) as Ptr

return GetStringValues(new NSArray(availableMembersOfFontFamily(self, theFamily)))
#endif
End Function

Private Shared Function GetStringValues(theArray as NSArray) As String()
return theArray.StringValues
End Function

Thanks, Carlo!
Looks good up to here. One mystery stays (sorry, don’t have the time right now to check that myself): Could you post the code from NSArray.StringValues? Or, if your project allows it, a link to the code itself?

Let me guess that it tries to put the contents of an NSArray as String values to a Xojo array of Strings. That should be the problem. Apple’s doc about AvailableMembersOfFontFamily says:

[quote]Each entry of the returned NSArray is another NSArray with four members, as follows:

  1. The PostScript font name, as an NSString object.

  2. The part of the font name used in the font panel that’s not the font name, as an NSString object. This value is not localized—for example, “Roman”, “Italic”, or “Bold”.

  3. The font’s weight, as an NSNumber.

  4. The font’s traits, as an NSNumber.[/quote]

Instead of a String the content is another array, and you’d have to build an extended method that returns you the string values of a specified item of it.

Ulrich,
I understand your last point, although it would be far off my experience to implementi it. Thank you.
Here is the stringValue code:

Function StringValues() As string()
#if TargetMacOS
dim result() as string
for i as integer = 0 to me.Count - 1
dim p as Ptr = me.Value( i )
if Cocoa.InheritsFromClass(p, “NSString”) then
dim nss as new NSString§
result.Append nss.StringValue
else
raise new TypeMismatchException
end if
next

return result

#endif
End Function

Well, at least that’s where your TypeMismatchError is created!
The method is quite smart and returns a StringValue only if the Array.Value(i) is a (subclass of) String.

In your case, Array.Value(i) is a ptr to another NSArray. You would have to use this and create another NSArray from it:

Dim FontInfoArray as New NSArray(FirstArray.Value(i))

The first two values, index 0 and 1, are NSStrings. So depending on if you want the PostScriptFontName or the type identifier, what you want is Return New NSString (FontInfoArray.Value(0 OR 1)).StringValue
(OR not to be taken literally codewise – it’s either 0 or 1)

Does that help a bit?

I understand what you say, but as for implementing it I’m at a loss.

Should be something like

Function AvailablePostScriptMembersOfFontFamily(theFamily as string) As String() #if TargetMacOS declare function availableMembersOfFontFamily lib CocoaLib selector "availableMembersOfFontFamily:" (id as Ptr, name as CFStringRef) as Ptr dim mainArray as new NSArray(availableMembersOfFontFamily(self, theFamily))) dim result() as string for q as integer = 0 to mainArray.Count - 1 dim InfoArray as new nsarray (mainarray.value(q)) dim psname as new nsstring(infoarray.value(0)) result.append psname.stringvalue next return result #endif End Function

and the same as availableFontTypeMembersofFontFamily with a nsstring for infoarray.value(1)

Excellent. Thank you, Ulrich.