Reworked my NSBlock code a bit into a module.
Hopefully it works
Once a NSBlockWithPtr is created, make sure it stays at the same memory location !
Module code
Code: Select all
; NSBlock module by Wilbert
; last update July 17, 2015
DeclareModule NSBlock
Structure NSBlock
*isa
flags.l
reserved.l
*invoke
*descriptor
EndStructure
Structure NSBlockWithPtr
*block.NSBlock
_block.NSBlock
EndStructure
Declare InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
EndDeclareModule
Module NSBlock
Global.i NSConcreteGlobalBlock, NSConcreteStackBlock, DyLib
DyLib = OpenLibrary(#PB_Any, "libSystem.dylib")
If DyLib
NSConcreteGlobalBlock = GetFunction(DyLib, "_NSConcreteGlobalBlock")
NSConcreteStackBlock = GetFunction(DyLib, "_NSConcreteStackBlock")
CloseLibrary(DyLib)
EndIf
If Not NSConcreteGlobalBlock
MessageRequester("Error", "Unable to access _NSConcreteGlobalBlock symbol")
End
EndIf
DataSection
NSBlockDescriptor:
Data.i 0, SizeOf(NSBlock), 0, 0
EndDataSection
Procedure InitNSBlockWithPtr(*NSBlockWithPtr.NSBlockWithPtr, *Invoke, IsGlobal = #True)
*NSBlockWithPtr\block = @*NSBlockWithPtr\_block
With *NSBlockWithPtr\_block
If IsGlobal
\isa = NSConcreteGlobalBlock
\flags = $30000000
Else
\isa = NSConcreteStackBlock
\flags = $20000000
EndIf
\invoke = *Invoke
\descriptor = ?NSBlockDescriptor
EndWith
EndProcedure
EndModule
; *** End of NSBlock module ***
Example 1
Code: Select all
UseModule NSBlock
ProcedureC EventMonitor(*Block.NSBlock, Event)
AddGadgetItem(0, -1, "test")
ProcedureReturn Event
EndProcedure
InitNSBlockWithPtr(@MyBlockWithPtr.NSBlockWithPtr, @EventMonitor())
CocoaMessage(0, 0, "NSEvent addLocalMonitorForEventsMatchingMask:", 2, "handler:@", @MyBlockWithPtr)
; *** Main code ***
If OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
EditorGadget(0, 10, 10, 175, 240)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Example 2
Code: Select all
UseModule NSBlock
ProcedureC BlockEnumeration(*Block.NSBlock, id, idx, *stop.Byte)
Debug PeekS(CocoaMessage(0, id, "UTF8String"), -1, #PB_UTF8)
If idx = 2
*stop\b = #True; stop after index 2 (string 3)
EndIf
EndProcedure
InitNSBlockWithPtr(@MyBlockWithPtr.NSBlockWithPtr, @BlockEnumeration())
NSMutableArray = CocoaMessage(0, 0, "NSMutableArray arrayWithCapacity:", 3)
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 1")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 2")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 3")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 4")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 5")
CocoaMessage(0, NSMutableArray, "enumerateObjectsUsingBlock:@", @MyBlockWithPtr)
Previous 2 examples combined with a Map.
This is to show it's possible to use a Map but it might be better to use global variables since it are supposed to be global blocks
Code: Select all
UseModule NSBlock
NewMap Block.NSBlockWithPtr()
ProcedureC EventMonitor(*Block.NSBlock, Event)
AddGadgetItem(0, -1, "test")
ProcedureReturn Event
EndProcedure
ProcedureC BlockEnumeration(*Block.NSBlock, id, idx, *stop.Byte)
Debug PeekS(CocoaMessage(0, id, "UTF8String"), -1, #PB_UTF8)
If idx = 2
*stop\b = #True; stop after index 2 (string 3)
EndIf
EndProcedure
InitNSBlockWithPtr(@Block("EventMonitor"), @EventMonitor())
InitNSBlockWithPtr(@Block("BlockEnumeration"), @BlockEnumeration())
NSMutableArray = CocoaMessage(0, 0, "NSMutableArray arrayWithCapacity:", 3)
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 1")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 2")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 3")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 4")
CocoaMessage(0, NSMutableArray, "addObject:$", @"String 5")
CocoaMessage(0, NSMutableArray, "enumerateObjectsUsingBlock:@", @Block("BlockEnumeration"))
CocoaMessage(0, 0, "NSEvent addLocalMonitorForEventsMatchingMask:", 2, "handler:@", @Block("EventMonitor"))
; *** Main code ***
If OpenWindow(0, 100, 200, 195, 260, "PureBasic Window", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
EditorGadget(0, 10, 10, 175, 240)
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Great example from Shardik for a modal sheet
http://www.purebasic.fr/english/viewtop ... 43#p471843