Marcel Taeumel uploaded a new version of FFI-Libraries to project FFI:
http://source.squeak.org/FFI/FFI-Libraries-mt.1.mcz ==================== Summary ==================== Name: FFI-Libraries-mt.1 Author: mt Time: 27 May 2021, 9:37:20.525843 am UUID: a4ac2929-b61c-af4b-bfde-aba6092bec57 Ancestors: New package that provides a base layer for FFI-backed system functions. For now, there are only some rough sketches for platform-specific I/O and an excerpt from LibC to be used in tests. Another candidate for this package could be the interface to SDL2. Note that future development might reveal the need to split up this package. For now, we are fine, I suppose, since its contents only resemble a construction site. :-D ==================== Snapshot ==================== SystemOrganization addCategory: #'FFI-Libraries-LibC'! SystemOrganization addCategory: #'FFI-Libraries-MacOS'! SystemOrganization addCategory: #'FFI-Libraries-Win32'! SystemOrganization addCategory: #'FFI-Libraries-X11'! SharedPool subclass: #Win32Constants instanceVariableNames: '' classVariableNames: 'COLOR_ACTIVEBORDER COLOR_ACTIVECAPTION COLOR_APPWORKSPACE COLOR_BACKGROUND COLOR_BTNFACE COLOR_BTNHIGHLIGHT COLOR_BTNSHADOW COLOR_BTNTEXT COLOR_CAPTIONTEXT COLOR_GRAYTEXT COLOR_HIGHLIGHT COLOR_HIGHLIGHTTEXT COLOR_INACTIVEBORDER COLOR_INACTIVECAPTION COLOR_INACTIVECAPTIONTEXT COLOR_MENU COLOR_MENUTEXT COLOR_SCROLLBAR COLOR_WINDOW COLOR_WINDOWFRAME COLOR_WINDOWTEXT CS_BYTEALIGNCLIENT CS_BYTEALIGNWINDOW CS_CLASSDC CS_DBLCLKS CS_HREDRAW CS_NOCLOSE CS_OWNDC CS_PARENTDC CS_SAVEBITS CS_VREDRAW CW_USEDEFAULT GWL_STYLE HWND_BROADCAST WM_DESTROY WM_MOVE WS_BORDER WS_CAPTION WS_CHILD WS_CHILDWINDOW WS_CLIPCHILDREN WS_CLIPSIBLINGS WS_DISABLED WS_DLGFRAME WS_EX_ACCEPTFILES WS_EX_APPWINDOW WS_EX_CLIENTEDGE WS_EX_CONTEXTHELP WS_EX_CONTROLPARENT WS_EX_DLGMODALFRAME WS_EX_LEFT WS_EX_LEFTSCROLLBAR WS_EX_LTRREADING WS_EX_MDICHILD WS_EX_NOACTIVATE WS_EX_NOPARENTNOTIFY WS_EX_OVERLAPPEDWINDOW WS_EX_PALETTEWINDOW WS_EX_RIGHT WS_EX_RIGHTSCROLLBAR WS_EX_RTLREADING WS_EX_STATICEDGE WS_EX _TOOLWINDOW WS_EX_TOPMOST WS_EX_TRANSPARENT WS_EX_WINDOWEDGE WS_GROUP WS_HSCROLL WS_ICONIC WS_MAXIMIZE WS_MAXIMIZEBOX WS_MINIMIZE WS_MINIMIZEBOX WS_OVERLAPPED WS_OVERLAPPEDWINDOW WS_POPUP WS_POPUPWINDOW WS_SIZEBOX WS_SYSMENU WS_TABSTOP WS_THICKFRAME WS_TILED WS_TILEDWINDOW WS_VISIBLE WS_VSCROLL' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32Constants class>>initialize (in category 'pool initialization') ----- initialize "Win32Constants initialize" self initializeWindowConstants.! ----- Method: Win32Constants class>>initializeWindowConstants (in category 'pool initialization') ----- initializeWindowConstants GWL_STYLE := -16. WS_EX_ACCEPTFILES := 16r10. WS_EX_APPWINDOW := 16r40000. WS_EX_CLIENTEDGE := 16r200. WS_EX_CONTEXTHELP := 16r400. WS_EX_CONTROLPARENT := 16r10000. WS_EX_DLGMODALFRAME := 16r1. WS_EX_LEFT := 16r0. WS_EX_LEFTSCROLLBAR := 16r4000. WS_EX_LTRREADING := 16r0. WS_EX_MDICHILD := 16r40. WS_EX_NOACTIVATE := 16r8000000. WS_EX_NOPARENTNOTIFY := 16r4. WS_EX_OVERLAPPEDWINDOW := 16r300. WS_EX_PALETTEWINDOW := 16r188. WS_EX_RIGHT := 16r1000. WS_EX_RIGHTSCROLLBAR := 16r0. WS_EX_RTLREADING := 16r2000. WS_EX_STATICEDGE := 16r20000. WS_EX_TOOLWINDOW := 16r80. WS_EX_TOPMOST := 16r8. WS_EX_TRANSPARENT := 16r20. WS_EX_WINDOWEDGE := 16r100. WS_BORDER := 16r800000. WS_CAPTION := 16rC00000. WS_CHILD := 16r40000000. WS_CHILDWINDOW := 16r40000000. WS_CLIPCHILDREN := 16r2000000. WS_CLIPSIBLINGS := 16r4000000. WS_DISABLED := 16r8000000. WS_DLGFRAME := 16r400000. WS_GROUP := 16r20000. WS_HSCROLL := 16r100000. WS_ICONIC := 16r20000000. WS_MAXIMIZE := 16r1000000. WS_MAXIMIZEBOX := 16r10000. WS_MINIMIZE := 16r20000000. WS_MINIMIZEBOX := 16r20000. WS_OVERLAPPED := 16r0. WS_OVERLAPPEDWINDOW := 16rCF0000. WS_POPUP := 16r80000000. WS_POPUPWINDOW := 16r80880000. WS_SIZEBOX := 16r40000. WS_SYSMENU := 16r80000. WS_TABSTOP := 16r10000. WS_THICKFRAME := 16r40000. WS_TILED := 16r0. WS_TILEDWINDOW := 16rCF0000. WS_VISIBLE := 16r10000000. WS_VSCROLL := 16r200000. CS_BYTEALIGNCLIENT := 16r1000. CS_BYTEALIGNWINDOW := 16r2000. CS_CLASSDC := 16r40. CS_DBLCLKS := 16r8. CS_HREDRAW := 16r2. CS_NOCLOSE := 16r200. CS_OWNDC := 16r20. CS_PARENTDC := 16r80. CS_SAVEBITS := 16r800. CS_VREDRAW := 16r1. COLOR_ACTIVEBORDER := 10. COLOR_ACTIVECAPTION := 2. COLOR_APPWORKSPACE := 12. COLOR_BACKGROUND := 1. COLOR_BTNFACE := 15. COLOR_BTNHIGHLIGHT := 20. COLOR_BTNSHADOW := 16. COLOR_BTNTEXT := 18. COLOR_CAPTIONTEXT := 9. COLOR_GRAYTEXT := 17. COLOR_HIGHLIGHT := 13. COLOR_HIGHLIGHTTEXT := 14. COLOR_INACTIVEBORDER := 11. COLOR_INACTIVECAPTION := 3. COLOR_INACTIVECAPTIONTEXT := 19. COLOR_MENU := 4. COLOR_MENUTEXT := 7. COLOR_SCROLLBAR := 0. COLOR_WINDOW := 5. COLOR_WINDOWFRAME := 6. COLOR_WINDOWTEXT := 8. CW_USEDEFAULT := 16r80000000. HWND_BROADCAST := 16rFFFF. WM_DESTROY := 16r2. WM_MOVE := 16r3! SharedPool subclass: #Win32ShellErrors instanceVariableNames: 'errorNumber description' classVariableNames: 'ERROR_BAD_FORMAT ERROR_FILE_NOT_FOUND ERROR_PATH_NOT_FOUND OUT_OF_MEMORY_OR_RESOURCES SE_ERR_ACCESSDENIED SE_ERR_ACCOSINCOMPLETE SE_ERR_DDEBUSY SE_ERR_DDEFAIL SE_ERR_DDETIMEOUT SE_ERR_DDLNOTFOUND SE_ERR_FNF SE_ERR_NOASSOC SE_ERR_OOM SE_ERR_PNF SE_ERR_SHARE' poolDictionaries: '' category: 'FFI-Libraries-Win32'! Win32ShellErrors class instanceVariableNames: 'errors'! Win32ShellErrors class instanceVariableNames: 'errors'! ----- Method: Win32ShellErrors class>>initialize (in category 'as yet unclassified') ----- initialize self initializeWindowConstants! ----- Method: Win32ShellErrors class>>initializeWindowConstants (in category 'as yet unclassified') ----- initializeWindowConstants OUT_OF_MEMORY_OR_RESOURCES := self new errorNumber: 0; description: 'The operating system is out of memory or resources'. SE_ERR_FNF := self new errorNumber: 2; description: 'The specified file was not found'. SE_ERR_PNF := self new errorNumber: 3; description: 'The specified path was not found'. SE_ERR_ACCESSDENIED := self new errorNumber: 5; description: 'The operating system denied access to the specified file'. SE_ERR_OOM := self new errorNumber: 8; description: 'There was not enough memory to complete the operation'. ERROR_BAD_FORMAT := self new errorNumber: 11; description: 'The .EXE file is invalid (non-Win32 .EXE or error in .EXE image)'. SE_ERR_SHARE := self new errorNumber: 26; description: 'A sharing violation occurred'. SE_ERR_ACCOSINCOMPLETE := self new errorNumber: 27; description: 'The filename association is incomplete or invalid'. SE_ERR_DDETIMEOUT := self new errorNumber: 28; description: 'The DDE transaction could not be completed because the request timed out'. SE_ERR_DDEFAIL := self new errorNumber: 29; description: 'The DDE transaction failed'. SE_ERR_DDEBUSY := self new errorNumber: 30; description: 'The DDE transaction could not be completed because other DDE transactions were being processed'. SE_ERR_NOASSOC := self new errorNumber: 31; description: 'There is no application associated with the given filename extension'. SE_ERR_DDLNOTFOUND := self new errorNumber: 32; description: 'The specified dynamic-link library was not found'. errors := Dictionary new: (self allInstances size). self allInstances do: [:err| errors at: err errorNumber put: err ].! ----- Method: Win32ShellErrors class>>signal: (in category 'as yet unclassified') ----- signal: code | err | err := errors at: code ifAbsent: [Error signal: 'system error, code:', code]. Error signal: err errorString! ----- Method: Win32ShellErrors>>description (in category 'accessing') ----- description ^ description ! ----- Method: Win32ShellErrors>>description: (in category 'accessing') ----- description: anObject description := anObject. ! ----- Method: Win32ShellErrors>>errorNumber (in category 'accessing') ----- errorNumber ^ errorNumber ! ----- Method: Win32ShellErrors>>errorNumber: (in category 'accessing') ----- errorNumber: anObject errorNumber := anObject. ! ----- Method: Win32ShellErrors>>errorString (in category 'accessing') ----- errorString ^'system error, code: ', errorNumber, ' "', description, '"'! Object subclass: #Win32Error instanceVariableNames: 'errorCode' classVariableNames: 'ErrorCodes' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32Error class>>initialize (in category 'as yet unclassified') ----- initialize "Win32Error initialize" ErrorCodes := Dictionary new. ErrorCodes at: 203 put: #('ERROR_ENVVAR_NOT_FOUND' 'There was no environment variable with that name'); yourself! ----- Method: Win32Error class>>lastError (in category 'as yet unclassified') ----- lastError ^(self new) initializeWithLastError! ----- Method: Win32Error class>>win32GetLastError (in category 'as yet unclassified') ----- win32GetLastError "DWORD WINAPI GetLastError(void);" <apicall: ulong 'GetLastError' () module:'kernel32.dll'> ^nil! ----- Method: Win32Error>>errorCode (in category 'as yet unclassified') ----- errorCode ^errorCode! ----- Method: Win32Error>>errorMessage (in category 'as yet unclassified') ----- errorMessage ^(ErrorCodes at: errorCode) at: 2 ifAbsent: ['Unknown Error: ' , errorCode]! ----- Method: Win32Error>>errorName (in category 'as yet unclassified') ----- errorName ^(ErrorCodes at: errorCode) at: 1 ifAbsent: ['ERROR_UNKNOWN_' , errorCode ]! ----- Method: Win32Error>>initializeWithLastError (in category 'as yet unclassified') ----- initializeWithLastError errorCode := self class win32GetLastError.! Object subclass: #Win32Utils instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! !Win32Utils commentStamp: 'tbn 8/22/2005 23:50' prior: 0! This is an utility class with helpfull methods for Win32 users. Note that it uses FFI and is platform dependent.! ----- Method: Win32Utils class>>apiFreeEnvironmentStrings: (in category 'api calls') ----- apiFreeEnvironmentStrings: extData "Win32Utils apiFreeEnvironmentStrings" <apicall: long 'FreeEnvironmentStrings' (void*) module: 'kernel32.dll'> ^self externalCallFailed! ----- Method: Win32Utils class>>apiGetEnvironmentStrings (in category 'api calls') ----- apiGetEnvironmentStrings "Win32Utils apiGetEnvironmentStrings" <apicall: byte* 'GetEnvironmentStrings' () module: 'kernel32.dll'> ^self externalCallFailed! ----- Method: Win32Utils class>>apiGetEnvironmentVariable:buffer:size: (in category 'api calls') ----- apiGetEnvironmentVariable: name buffer: buffer size: bufferSize "DWORD WINAPI GetEnvironmentVariable( __in_opt LPCTSTR lpName, __out_opt LPTSTR lpBuffer, __in DWORD nSize );" "http://msdn.microsoft.com/en-us/library/ms683188(VS.85).aspx" <apicall: ulong 'GetEnvironmentVariableA' ( char* byte* ulong) module: 'kernel32.dll'> ^self externalCallFailed! ----- Method: Win32Utils class>>apiGetUserBuffer:size: (in category 'api calls') ----- apiGetUserBuffer: buffer size: bufferSize "BOOL WINAPI GetUserNameA( __out_opt LPSTR lpBuffer, __in LPDWORD pcbBuffer );" "https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getusernamea" <apicall: ulong 'GetUserNameA' ( byte* long* ) module: 'Advapi32.dll'> ^self externalCallFailed! ----- Method: Win32Utils class>>apiSetCursorPosX:y: (in category 'api calls') ----- apiSetCursorPosX: x y: y "this is apparently how to control the mouse cursor pragmatically on windows: http://lists.squeakfoundation.org/pipermail/squeak-dev/2011-February/157676.html " <apicall: bool 'SetCursorPos' (long long) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Utils class>>getCommonEnvironmentVariables (in category 'examples') ----- getCommonEnvironmentVariables "Returns a dictionary with common environment variables for Win32 systems" |map| map := Dictionary new. #('ALLUSERSPROFILE' 'APPDATA' 'COMPUTERNAME' 'COMSPEC' 'HOMEDRIVE' 'HOMEPATH' 'LOGONSERVER' 'SYSTEMDRIVE' 'OS' 'PATH' 'SYSTEMROOT' 'TEMP' 'TMP' 'USERDOMAIN' 'USERNAME' 'USERPROFILE' 'WINDIR') do: [:each | map at: each put: (self getEnvironmentVariable: each)]. ^map ! ----- Method: Win32Utils class>>getCurrentUser (in category 'accessing') ----- getCurrentUser " Win32Utils getCurrentUser " | nm sz | sz := (ByteArray new: 8). sz longAt: 1 put: 256 bigEndian: false. self apiGetUserBuffer: (nm := ByteArray new: 256) size: sz. ^(nm copyUpTo: 0) asString! ----- Method: Win32Utils class>>getEnvironmentVariable: (in category 'accessing') ----- getEnvironmentVariable: aString "Win32Utils getEnvironmentVariable: 'windir'" ^ self getEnvironmentVariable: aString ifAbsent: [nil]! ----- Method: Win32Utils class>>getEnvironmentVariable:buffer:ifAbsent: (in category 'accessing') ----- getEnvironmentVariable: name buffer: buffer ifAbsent: block "Win32Utils getEnvironmentVariable: 'APPDATA' " "Win32Utils getEnvironmentVariable: 'APPDATAx' " "http://msdn.microsoft.com/en-us/library/ms683188(VS.85).aspx " | retval err | retval := self apiGetEnvironmentVariable: name buffer: buffer size: buffer byteSize. retval = 0 ifTrue: [ err := Win32Error lastError. ^(err errorName = 'ERROR_ENVVAR_NOT_FOUND') ifTrue: [block value] ifFalse: [ self error: 'Problem with retrieving env var ' , name , '. Code is ' , err errorName. nil ] ]. ^(retval < buffer byteSize) ifTrue: [( buffer copyFrom: 1 to: retval ) asString] ifFalse: [ self getEnvironmentVariable: name buffer: (ByteArray new: retval) ifAbsent: block ]. ! ----- Method: Win32Utils class>>getEnvironmentVariable:ifAbsent: (in category 'accessing') ----- getEnvironmentVariable: name ifAbsent: block "Win32Utils getEnvironmentVariable: 'APPDATA' ifAbsent: [nil]" "Win32Utils getEnvironmentVariable: 'APPDATAx' ifAbsent: [5]" ^self getEnvironmentVariable: name buffer: (ByteArray new: 256) ifAbsent: block! ----- Method: Win32Utils class>>getEnvironmentVariables (in category 'accessing') ----- getEnvironmentVariables "Win32Utils getEnvironmentVariables" | externalData strs | externalData := self apiGetEnvironmentStrings. strs := externalData fromCStrings. self apiFreeEnvironmentStrings: externalData. ^strs ! ExternalPool subclass: #Win32Pool instanceVariableNames: '' classVariableNames: 'WIN32_WINNT_VISTA WIN32_WINNT_WIN10 WIN32_WINNT_WIN7 WIN32_WINNT_WIN8 WIN32_WINNT_WINXP' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32Pool class>>winver (in category 'definitions') ----- winver " self winver writePoolData. self winver readPoolData. " <ffiExternalPool> <ffiPoolDataStorage: #methodSource> <ffiPlatformName: 'Win32'> <ffiCHeaders: #('<sdkddkver.h>')> <ffiVariable: #_WIN32_WINNT_WINXP> <ffiVariable: #_WIN32_WINNT_VISTA> <ffiVariable: #_WIN32_WINNT_WIN7> <ffiVariable: #_WIN32_WINNT_WIN8> <ffiVariable: #_WIN32_WINNT_WIN10> ^ self poolDefinition! ----- Method: Win32Pool class>>winverData (in category 'definitions - data') ----- winverData "Automatically generated." <ffiPoolReadWriter: #ExternalPoolST1ReadWriter> <ffiPoolDataStorage: #methodSource> " Win32Pool winver readPoolDataFrom: #methodSource. Win32Pool winver writePoolDataTo: #methodSource. " ^ { (FFIPlatformDescription name: 'Win32' osVersion: '10.0' subtype: 'IX86' wordSize: 4). Dictionary new at: #WIN32_WINNT_WIN7 put: 16r00000601; at: #WIN32_WINNT_WINXP put: 16r00000501; at: #WIN32_WINNT_VISTA put: 16r00000600; at: #WIN32_WINNT_WIN8 put: 16r00000602; at: #WIN32_WINNT_WIN10 put: 16r00000A00; yourself. } ! ExternalObject subclass: #MacOSShell instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-MacOS'! !MacOSShell commentStamp: 'spd 5/16/2010 22:33' prior: 0! I show how system functions can be called from within the image. WARNING: Under Snow Leopard, the VM (as of 4.2.4 beta) only searches its Resources folder for external libraries. See http://wiki.squeak.org/squeak/5846 for workarounds.! ----- Method: MacOSShell class>>escapeFileName: (in category 'utilities') ----- escapeFileName: aFileName "Try to make the argument suitable for use in 'system'. Just the simple stuff - backlash-prefix for obvious problems - quotes and white space." ^ String streamContents: [ : stream | aFileName do: [ : char | ('''" ()[]{}$&' includes: char) ifTrue: [ stream nextPut: $\ ]. stream nextPut: char. ]].! ----- Method: MacOSShell>>getenv: (in category 'basics') ----- getenv: aString <apicall: char* 'getenv' (char*) module: 'libSystem.dylib'> self externalCallFailed! ----- Method: MacOSShell>>system: (in category 'basics') ----- system: aString "Note that the command will foreground-block the VM unless it ends with &" <apicall: long 'system' (char*) module: 'libSystem.dylib'> self externalCallFailed.! ExternalObject subclass: #Win32File instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32File class>>setReadOnly: (in category 'operations') ----- setReadOnly: fileString "Convenient shorthand." ^ (self new) setReadOnly: fileString! ----- Method: Win32File class>>setReadWrite: (in category 'operations') ----- setReadWrite: fileString "Convenient shorthand" ^ (self new) setReadWrite: fileString! ----- Method: Win32File>>getFileAttributes: (in category 'api calls') ----- getFileAttributes: fileString <apicall: ulong 'GetFileAttributesA' (char*) module: 'Kernel32.dll'> ^ self externalCallFailed! ----- Method: Win32File>>setFileAttributes:lpAttrs: (in category 'api calls') ----- setFileAttributes: fileString lpAttrs: aLong <apicall: ulong 'SetFileAttributesA' (char* ulong) module: 'Kernel32.dll'> ^ self externalCallFailed! ----- Method: Win32File>>setReadOnly: (in category 'operations') ----- setReadOnly: fileString "Set FILE_READ_ONLY (bit 1)" | attrs | attrs := (self getFileAttributes: fileString). attrs < 0 ifTrue: [ self error: 'Cannot get file attributes. System error.' ]. (self setFileAttributes: fileString lpAttrs: (attrs bitOr: 1)) = 0 ifTrue: [ self error: 'Cannot set file attributes. System error.' ].! ----- Method: Win32File>>setReadWrite: (in category 'operations') ----- setReadWrite: fileString "Clear FILE_READ_ONLY (bit 1)" | attrs | attrs := (self getFileAttributes: fileString). attrs < 0 ifTrue: [ self error: 'Cannot get file attributes. System error.' ]. (self setFileAttributes: fileString lpAttrs: (attrs bitClear: 1)) = 0 ifTrue: [ self error: 'Cannot set file attributes. System error.' ].! ExternalObject subclass: #Win32Shell instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! !Win32Shell commentStamp: '<historical>' prior: 0! This class wrappes the Windows 32 shell. Try Win32Shell new shellOpen: 'c:\image.bmp' to open a document Win32Shell new shellOpen: 'c:\myprogram.exe' to start an executable Win32Shell new shellExplore: 'c:\' to explore a directory Win32Shell new shellFind: 'c:\' to initiate a search Note that this class is platform specific. ! ----- Method: Win32Shell>>error: (in category 'operations') ----- error: code Win32ShellErrors signal: code! ----- Method: Win32Shell>>shellExecute: (in category 'operations') ----- shellExecute: aFileString "Opens (without opening a window) the file specified by aFileString. The file can be an executable file, a document file, or a folder." | result fileUrlString | "@@@@ CHECKME - jrd - Hackity, hack, hack, hack. Apparently the Win32 url parser doesn't handle %-encoded colons in file paths properly. So we do the conversion ourselves. I'm not sure if the real problem is that we shouldnt be encoding the colons in the first place." fileUrlString := (aFileString asLowercase beginsWith: 'file:') ifTrue: [(aFileString copyReplaceAll: '%3A' with: ':') copyReplaceAll: '%3a' with: ':' ] ifFalse: [aFileString]. result := self shellExecute: nil lpOperation: 'open' lpFile: fileUrlString lpParameters: nil lpDirectory: nil nShowCmd: 0. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ----- Method: Win32Shell>>shellExecute:arguments:toPath: (in category 'operations') ----- shellExecute: aFileString arguments: arguments toPath: outputPath "Opens (without opening a window) the file specified by aFileString. The file can be an executable file, a document file, or a folder." | result fileUrlString | "@@@@ CHECKME - jrd - Hackity, hack, hack, hack. Apparently the Win32 url parser doesn't handle %-encoded colons in file paths properly. So we do the conversion ourselves. I'm not sure if the real problem is that we shouldnt be encoding the colons in the first place." fileUrlString := (aFileString asLowercase beginsWith: 'file:') ifTrue: [(aFileString copyReplaceAll: '%3A' with: ':') copyReplaceAll: '%3a' with: ':' ] ifFalse: [aFileString]. result := self shellExecute: nil lpOperation: 'open' lpFile: fileUrlString lpParameters: arguments lpDirectory: outputPath nShowCmd: 0. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ----- Method: Win32Shell>>shellExecute:lpOperation:lpFile:lpParameters:lpDirectory:nShowCmd: (in category 'api calls') ----- shellExecute: hwnd lpOperation: opString lpFile: fileString lpParameters: parmString lpDirectory: dirString nShowCmd: anInteger "Opens or prints the specified file, which can be an executable or document file. HINSTANCE ShellExecute( HWND hwnd, // handle to parent window LPCTSTR lpOperation, // pointer to string that specifies operation to perform LPCTSTR lpFile, // pointer to filename or folder name string LPCTSTR lpParameters, // pointer to string that specifies executable-file parameters LPCTSTR lpDirectory, // pointer to string that specifies default directory INT nShowCmd // whether file is shown when opened );" <apicall: long 'ShellExecuteA' (long char* char* char* char* ulong) module:'shell32.dll'>! ----- Method: Win32Shell>>shellExplore: (in category 'operations') ----- shellExplore: aPathString "Explores the folder specified by aPathString" | result | result := self shellExecute: nil lpOperation: 'explore' lpFile: aPathString lpParameters: nil lpDirectory: nil nShowCmd: 1. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ----- Method: Win32Shell>>shellFind: (in category 'operations') ----- shellFind: aPathString "Initiates a search starting from the specified directory." | result | result := self shellExecute: nil lpOperation: 'find' lpFile: nil lpParameters: nil lpDirectory: aPathString nShowCmd: 1. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ----- Method: Win32Shell>>shellOpen: (in category 'operations') ----- shellOpen: aFileString "Opens the file specified by aFileString. The file can be an executable file, a document file, or a folder." | result fileUrlString | "@@@@ CHECKME - jrd - Hackity, hack, hack, hack. Apparently the Win32 url parser doesn't handle %-encoded colons in file paths properly. So we do the conversion ourselves. I'm not sure if the real problem is that we shouldnt be encoding the colons in the first place." fileUrlString := (aFileString asLowercase beginsWith: 'file:') ifTrue: [(aFileString copyReplaceAll: '%3A' with: ':') copyReplaceAll: '%3a' with: ':' ] ifFalse: [aFileString]. result := self shellExecute: nil lpOperation: 'open' lpFile: fileUrlString lpParameters: nil lpDirectory: nil nShowCmd: 1. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ----- Method: Win32Shell>>shellOpen:arguments:toPath: (in category 'operations') ----- shellOpen: aFileString arguments: arguments toPath: outputPath "Opens (without opening a window) the file specified by aFileString. The file can be an executable file, a document file, or a folder." | result fileUrlString | "@@@@ CHECKME - jrd - Hackity, hack, hack, hack. Apparently the Win32 url parser doesn't handle %-encoded colons in file paths properly. So we do the conversion ourselves. I'm not sure if the real problem is that we shouldnt be encoding the colons in the first place." fileUrlString := (aFileString asLowercase beginsWith: 'file:') ifTrue: [(aFileString copyReplaceAll: '%3A' with: ':') copyReplaceAll: '%3a' with: ':' ] ifFalse: [aFileString]. result := self shellExecute: nil lpOperation: 'open' lpFile: fileUrlString lpParameters: arguments lpDirectory: outputPath nShowCmd: 1. (result <= 32 and: [result >= 0]) ifTrue: [self error: result]! ExternalLibrary subclass: #CStandardLibrary instanceVariableNames: '' classVariableNames: 'CheckCStandardLibraryOnStartUp ModuleName' poolDictionaries: '' category: 'FFI-Libraries-LibC'! !CStandardLibrary commentStamp: 'mt 5/26/2021 10:08' prior: 0! The ISO C standard library, also known as "CRT" and "libc." Further reading: https://www.gnu.org/software/libc/ https://docs.microsoft.com/en-us/cpp/c-runtime-library https://www.cplusplus.com/reference/clibrary/ https://www.iso.org/standard/82075.html! ----- Method: CStandardLibrary class>>checkCStandardLibrary (in category 'preferences') ----- checkCStandardLibrary "Try to use C Standard Library. Warn if not possible." [ [self assert: [(self default abs: -5) = 5] ] ifError: [:msg | self notify: 'C standard library not available. Please check module name in preferences.', String cr, String cr, msg] ] fork. "Do not interrupt the startup list."! ----- Method: CStandardLibrary class>>checkCStandardLibraryOnStartUp (in category 'preferences') ----- checkCStandardLibraryOnStartUp <preference: 'Check C standard library on start-up' categoryList: #('FFI Libraries') description: 'When enabled, performs a simple check of the C standard library when Squeak is resuming.' type: #Boolean> ^ CheckCStandardLibraryOnStartUp ifNil: [true]! ----- Method: CStandardLibrary class>>checkCStandardLibraryOnStartUp: (in category 'preferences') ----- checkCStandardLibraryOnStartUp: aBoolean CheckCStandardLibraryOnStartUp := aBoolean.! ----- Method: CStandardLibrary class>>guessModuleName (in category 'preferences') ----- guessModuleName "The the platform's module name for the C library." | platform | platform := FFIPlatformDescription current. platform isMacOS ifTrue: [ ^ platform osVersionMajor >= 11 "Big Sur and beyond" ifTrue:['libSystem.dylib'] ifFalse: [platform osVersionMajor >= 10 ifFalse: ['libc.dylib' "Mac OS 9"] ifTrue: [platform osVersionMinor >= 7 "at least OS X 10.7 (Lion)" ifTrue: ['libobjc.dylib'] ifFalse: [platform osVersionMinor >= 5 "at least Mac OS X 10.5 (Leopard)" ifTrue: ['libgcc_s.1.dylib'] ifFalse: ['libc.dylib']]]]]. platform isWindows ifTrue: [ ^ 'msvcrt.dll']. platform isUnix ifTrue: [ ^ platform osVersion = 'linux-gnu' ifTrue: ['libc.so.6'] ifFalse: ['libc.so']]. ^ nil! ----- Method: CStandardLibrary class>>initialize (in category 'class initialization') ----- initialize " self initialize " Smalltalk addToStartUpList: self after: (Smalltalk classNamed: #FFIPlatformDescription).! ----- Method: CStandardLibrary class>>moduleName (in category 'preferences') ----- moduleName <preference: 'C runtime/standard library (aka. CRT and libc)' categoryList: #('FFI Libraries') description: 'Name for or path to the ISO/IEC 9899 C standard library.' type: #String> ^ ModuleName ifNil: [self guessModuleName]! ----- Method: CStandardLibrary class>>moduleName: (in category 'preferences') ----- moduleName: nameOrNil ModuleName := nameOrNil = String empty ifFalse: [nameOrNil = self guessModuleName ifFalse: [nameOrNil]]. self clearAllCaches. "Check the provided name only if overwritten by clients." ModuleName ifNotNil: [self checkCStandardLibrary].! ----- Method: CStandardLibrary class>>startUp: (in category 'system startup') ----- startUp: resuming resuming ifTrue: [ self checkCStandardLibraryOnStartUp ifTrue: [ self checkCStandardLibrary]].! ----- Method: CStandardLibrary class>>unload (in category 'class initialization') ----- unload Smalltalk removeFromStartUpList: self.! ----- Method: CStandardLibrary>>abs: (in category 'stdlib.h - integer arithmetics') ----- abs: n "Returns the absolute value of parameter n" <cdecl: int32_t abs (int32_t)> ^ self externalCallFailed ! ----- Method: CStandardLibrary>>bsearch:with:with:with:with: (in category 'stdlib.h - searching and sorting') ----- bsearch: key with: base with: num with: size with: compar <cdecl: void* bsearch (const void*, const void*, size_t, size_t, void*)> ^ self externalCallFailed ! ----- Method: CStandardLibrary>>qsort:with:with:with: (in category 'stdlib.h - searching and sorting') ----- qsort: base with: num with: size with: compar <cdecl: void qsort (void*, size_t, size_t, void*)> ^ self externalCallFailed ! CStandardLibrary subclass: #LibC instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-LibC'! !LibC commentStamp: 'mt 5/26/2021 10:09' prior: 0! Just a synonym for convenient reference.! ExternalTypeAlias subclass: #Win32Handle instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! Win32Handle subclass: #Win32HDC instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32HDC>>apiDeleteDC: (in category 'api calls') ----- apiDeleteDC: aHDC <apicall: bool 'DeleteDC' (Win32HDC) module:'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>apiDrawFocusRect:with: (in category 'api calls') ----- apiDrawFocusRect: aHDC with: lpRect "Draws a rectangle in the style used to indicate that the rectangle has the focus." <apicall: bool 'DrawFocusRect' (Win32HDC Win32Rectangle*) module: 'user32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiDrawFrameControl:with:with:with: (in category 'api calls') ----- apiDrawFrameControl: aHDC with: lpRect with: type with: state "Draws a frame control of the specified type and style" <apicall: bool 'DrawFrameControl' (Win32HDC Win32Rectangle* ulong ulong) module: 'user32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiEllipse:with:with:with:with: (in category 'api calls') ----- apiEllipse: aHDC with: left with: top with: right with: bottom <apicall: bool 'Ellipse' (Win32HDC long long long long) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>apiExtFloodFill:with:with:with:with: (in category 'api calls') ----- apiExtFloodFill: aHDC with: x with: y with: colorref with: fillType "fills an area of the display surface with the current brush" <apicall: bool 'ExtFloodFill' (Win32HDC long long ulong ulong) module: 'gdi32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiFillRect:with:with: (in category 'api calls') ----- apiFillRect: aHDC with: lpRect with: brush "Fills a rectangle by using the specified brush. This function includes the left and top borders, but excludes the right and bottom borders of the rectangle. " <apicall: char 'FillRect' (Win32HDC Win32Rectangle* Win32HBrush) module: 'user32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiFrameRect:with:with: (in category 'api calls') ----- apiFrameRect: aHDC with: lpRect with: brush "Draws a border around the specified rectangle by using the specified brush. The width and height of the border are always one logical unit." <apicall: char 'FrameRect' (Win32HDC Win32Rectangle* Win32HBrush) module: 'user32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiLineTo:with:with: (in category 'api calls') ----- apiLineTo: aHDC with: x with: y <apicall: bool 'LineTo' (Win32HDC long long) module:'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>apiMoveToEx:with:with:with: (in category 'api calls') ----- apiMoveToEx: aHDC with: x with: y with: pt <apicall: bool 'MoveToEx' (Win32HDC long long Win32Point*) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>apiRectangle:with:with:with:with: (in category 'api calls') ----- apiRectangle: aHDC with: left with: top with: right with: bottom <apicall: bool 'Rectangle' (Win32HDC long long long long) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>apiRoundRect:with:with:with:with:with:with: (in category 'api calls') ----- apiRoundRect: aHDC with: left with: top with: right with: bottom with: width with: height "Draws a rectangle with rounded corners. The rectangle is outlined by using the current pen and filled by using the current brush" <apicall: bool 'RoundRect' (Win32HDC long long long long long long) module: 'gdi32.dll'> ^ self externalCallFailed! ----- Method: Win32HDC>>apiSelectObject:with: (in category 'api calls') ----- apiSelectObject: aHDC with: aHGDIOBJ <apicall: Win32HGDIObj 'SelectObject' (Win32HDC Win32HGDIObj) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HDC>>delete (in category 'initialize-release') ----- delete handle == nil ifFalse:[self apiDeleteDC: self]. handle := nil.! ----- Method: Win32HDC>>drawFocusRectangle: (in category 'drawing') ----- drawFocusRectangle: aRect "draws a rectangle in the style used to indicate that the rectangle has the focus" self apiDrawFocusRect: self with: (Win32Rectangle fromRectangle: aRect) ! ----- Method: Win32HDC>>drawFrameControl:type:style: (in category 'drawing') ----- drawFrameControl: aRect type: aType style: aStyle "Draws a frame control of the specified type and style (integer values)" self apiDrawFrameControl: self with: (Win32Rectangle fromRectangle: aRect) with: aType with: aStyle! ----- Method: Win32HDC>>ellipse: (in category 'drawing') ----- ellipse: aRect ^self apiEllipse: self with: aRect left with: aRect top with: aRect right with: aRect bottom! ----- Method: Win32HDC>>fillRectangle:color: (in category 'drawing') ----- fillRectangle: aRect color: aColor "fills an area of the display with the given color" | brush | brush := Win32HBrush createSolidBrush: aColor asColorref. self apiFillRect: self with: (Win32Rectangle fromRectangle: aRect) with: brush. brush delete! ----- Method: Win32HDC>>floodFillAt:boundaryColor:fillColor: (in category 'drawing') ----- floodFillAt: aPoint boundaryColor: aColor fillColor: anotherColor "fills an area of the display with the given color" | newBrush oldBrush | newBrush := Win32HBrush createSolidBrush: anotherColor asColorref. oldBrush := self selectObject: newBrush. (self apiExtFloodFill: self with: aPoint x with: aPoint y with: aColor asColorref with: 0) inspect. self selectObject: oldBrush. newBrush delete! ----- Method: Win32HDC>>frameRectangle:brush: (in category 'drawing') ----- frameRectangle: aRect brush: aBrush "Draws a border around the specified rectangle by using the specified brush. The width and height of the border are always one logical unit." self apiFrameRect: self with: (Win32Rectangle fromRectangle: aRect) with: aBrush. ! ----- Method: Win32HDC>>lineTo: (in category 'drawing') ----- lineTo: aPoint ^self apiLineTo: self with: aPoint x with: aPoint y! ----- Method: Win32HDC>>moveTo: (in category 'drawing') ----- moveTo: aPoint ^self apiMoveToEx: self with: aPoint x with: aPoint y with: nil! ----- Method: Win32HDC>>rectangle: (in category 'drawing') ----- rectangle: aRect ^self apiRectangle: self with: aRect left with: aRect top with: aRect right with: aRect bottom! ----- Method: Win32HDC>>roundRectangle:width:height: (in category 'drawing') ----- roundRectangle: aRect width: width height: height ^ self apiRoundRect: self with: aRect left with: aRect top with: aRect right with: aRect bottom with: width with: height! ----- Method: Win32HDC>>selectObject: (in category 'drawing') ----- selectObject: aHGDIOBJ ^self apiSelectObject: self with: aHGDIOBJ! Win32Handle subclass: #Win32HGDIObj instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! Win32HGDIObj subclass: #Win32HBrush instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32HBrush class>>apiCreateHatchBrush:with: (in category 'api calls') ----- apiCreateHatchBrush: aStyle with: colorref "Creates a logical brush that has the specified hatch pattern and color" <apicall: Win32HBrush 'CreateHatchBrush' (long ulong) module: 'gdi32.dll'> ^ self externalCallFailed! ----- Method: Win32HBrush class>>backwardDiagonalWithColor: (in category 'hatch brushes') ----- backwardDiagonalWithColor: aColor "45-degree downward left-to-right hatch brush" ^ self createHatchBrush: 3 color: aColor! ----- Method: Win32HBrush class>>createHatchBrush:color: (in category 'instance creation') ----- createHatchBrush: aStyle color: aColor "Creates an instance of the receiver that has the specified hatch pattern and color" ^ self apiCreateHatchBrush: aStyle with: aColor asColorref! ----- Method: Win32HBrush class>>createSolidBrush: (in category 'instance creation') ----- createSolidBrush: aCOLORREF <apicall: Win32HBrush 'CreateSolidBrush' (ulong) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HBrush class>>crossWithColor: (in category 'hatch brushes') ----- crossWithColor: aColor "Horizontal and vertical crosshatch brush" ^ self createHatchBrush: 4 color: aColor! ----- Method: Win32HBrush class>>diagonalCrossWithColor: (in category 'hatch brushes') ----- diagonalCrossWithColor: aColor "45-degree crosshatch brush" ^ self createHatchBrush: 5 color: aColor! ----- Method: Win32HBrush class>>forwardDiagonalWithColor: (in category 'hatch brushes') ----- forwardDiagonalWithColor: aColor "45-degree upward left-to-right hatch brush" ^ self createHatchBrush: 2 color: aColor! ----- Method: Win32HBrush class>>horizontalWithColor: (in category 'hatch brushes') ----- horizontalWithColor: aColor "Horizontal hatch brush" ^ self createHatchBrush: 0 color: aColor! ----- Method: Win32HBrush class>>verticalWithColor: (in category 'hatch brushes') ----- verticalWithColor: aColor "Horizontal hatch brush" ^ self createHatchBrush: 1 color: aColor ! ----- Method: Win32HGDIObj>>apiDeleteObject: (in category 'api calls') ----- apiDeleteObject: aHGDIOBJ <apicall: bool 'DeleteObject' (Win32HGDIObj) module: 'gdi32.dll'> ^self externalCallFailed! ----- Method: Win32HGDIObj>>delete (in category 'initialize-release') ----- delete self apiDeleteObject: self! ----- Method: Win32Handle class>>originalTypeName (in category 'accessing') ----- originalTypeName "Win32Handle defineFields" "The following really means typedef void* Win32Handle; " ^ 'uintptr_t'! Win32Handle subclass: #Win32Window instanceVariableNames: '' classVariableNames: '' poolDictionaries: 'Win32Constants' category: 'FFI-Libraries-Win32'! !Win32Window commentStamp: '<historical>' prior: 0! Here's a simple Win32 example: | hwnd dc dst | hwnd _ Win32Window getFocus. "fetch the window currently having the focus" dc _ hwnd getDC. "grab the dc or the window" dst _ 100. dc moveTo: 0@0. "draw a rect" dc lineTo: dst@0. dc lineTo: dst@dst. dc lineTo: 0@dst. dc lineTo: 0@0. "and a cross" dc lineTo: dst@dst. dc moveTo: dst@0. dc lineTo: 0@dst. hwnd releaseDC: dc.! ----- Method: Win32Window class>>coloredEllipses (in category 'examples') ----- coloredEllipses "Win32Window coloredEllipses" "Draw a bunch of ellipses" | rnd pt1 pt2 w h colors newBrush oldBrush | colors := Color colorNames collect:[:cName| (Color perform: cName)]. "convert to COLORREF" colors := colors collect:[:c| (c red * 255) asInteger + ((c green * 255) asInteger << 8) + ((c blue * 255) asInteger << 16)]. rnd := Random new. w := Display width. h := Display height. self getFocus getHDCDuring:[:hDC| [Sensor anyButtonPressed] whileFalse:[ newBrush := Win32HBrush createSolidBrush: colors atRandom. oldBrush := hDC selectObject: newBrush. pt1 := (rnd next * w) asInteger @ (rnd next * h) asInteger. pt2 := (rnd next * w) asInteger @ (rnd next * h) asInteger. hDC ellipse: (Rectangle encompassing: (Array with: pt1 with: pt2)). hDC selectObject: oldBrush. newBrush delete. ]. ]. Display forceToScreen.! ----- Method: Win32Window class>>coloredRectangles (in category 'examples') ----- coloredRectangles "Win32Window coloredRectangles" "Draw a bunch of ellipses" | rnd pt1 pt2 w h colors newBrush oldBrush n nPixels time r | colors := Color colorNames collect:[:cName| (Color perform: cName)]. "convert to COLORREF" colors := colors collect:[:c| (c red * 255) asInteger + ((c green * 255) asInteger << 8) + ((c blue * 255) asInteger << 16)]. rnd := Random new. w := Display width. h := Display height. self getFocus getHDCDuring:[:hDC| n := 0. nPixels := 0. time := Time millisecondClockValue. [Sensor anyButtonPressed] whileFalse:[ newBrush := Win32HBrush createSolidBrush: colors atRandom. oldBrush := hDC selectObject: newBrush. pt1 := (rnd next * w) asInteger @ (rnd next * h) asInteger. pt2 := (rnd next * w) asInteger @ (rnd next * h) asInteger. hDC rectangle: (r := Rectangle encompassing: (Array with: pt1 with: pt2)). hDC selectObject: oldBrush. newBrush delete. n := n + 1. nPixels := nPixels + ((r right - r left) * (r bottom - r top)). (n \\ 100) = 0 ifTrue:[ 'Pixel fillRate: ', (nPixels * 1000 // (Time millisecondClockValue - time)) asStringWithCommas displayAt: 0@0]. ]. ]. Display forceToScreen.! ----- Method: Win32Window class>>getDesktopWindow (in category 'accessing') ----- getDesktopWindow "Return the HWND describing the desktop" <apicall: Win32Window 'GetDesktopWindow' (void) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window class>>getFocus (in category 'accessing') ----- getFocus "Return the HWND currently having the input focus" <apicall: Win32Window 'GetFocus' (void) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window class>>getMainWindowText: (in category 'examples') ----- getMainWindowText: aString "Returns the window text of the main window" self new getWindowText: Win32Window getFocus ! ----- Method: Win32Window class>>getWindowLong:index: (in category 'private') ----- getWindowLong: hwnd index: index "Retrieves information about the specified window." <apicall: Win32Window 'GetWindowLongA' (long long) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window class>>getWindowStyle (in category 'private') ----- getWindowStyle "Returns the window style for the focus window" ^self getWindowLong: self getFocus index: GWL_STYLE ! ----- Method: Win32Window class>>setMainWindowText: (in category 'examples') ----- setMainWindowText: aString "Sets the window text of the main window" self new apiSetWindowText: Win32Window getFocus text: aString! ----- Method: Win32Window class>>setNonResizable (in category 'private') ----- setNonResizable " self setNonResizable " | newStyle | newStyle := self getWindowStyle bitClear: ((WS_SIZEBOX bitOr: WS_MINIMIZE) bitOr: WS_MAXIMIZE). self setWindowLong: self getFocus index: GWL_STYLE value: newStyle. ! ----- Method: Win32Window class>>setWindowLong:index:value: (in category 'private') ----- setWindowLong: hwnd index: index value: value "Sets information about the specified window." <apicall: Win32Window 'SetWindowLongA' (long long long) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window class>>win32Draw (in category 'examples') ----- win32Draw "Win32Window win32Draw" "Draw a bunch of lines using the Windows API" | hWnd hDC pt | hWnd := Win32Window getFocus. hDC := hWnd getDC. hDC moveTo: (hWnd screenToClient: Win32Point getCursorPos). [Sensor anyButtonPressed] whileFalse:[ pt := Win32Point getCursorPos. hWnd screenToClient: pt. hDC lineTo: pt. ]. hWnd releaseDC: hDC. Display forceToScreen.! ----- Method: Win32Window>>apiGetDC: (in category 'api calls') ----- apiGetDC: aHWND <apicall: Win32HDC 'GetDC' (Win32Window) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>apiGetParent: (in category 'api calls') ----- apiGetParent: aWindow <apicall: Win32Window 'GetParent' (Win32Window) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>apiGetWindowText:buffer:maxCount: (in category 'api calls') ----- apiGetWindowText: handleWindow buffer: aBuffer maxCount: aNumber <apicall: ulong 'GetWindowTextA' (Win32Window char* long) module: 'user32.dll'> self externalCallFailed! ----- Method: Win32Window>>apiMessageBox:text:title:flags: (in category 'api calls') ----- apiMessageBox: aHWND text: aString title: aTitle flags: flags <apicall: long 'MessageBoxA' (Win32Window char* char* ulong) module:'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>apiReleaseDC:with: (in category 'api calls') ----- apiReleaseDC: aHWND with: aHDC <apicall: long 'ReleaseDC' (Win32Window Win32HDC) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>apiScreenToClient:with: (in category 'api calls') ----- apiScreenToClient: aHWND with: aPOINT <apicall: bool 'ScreenToClient' (Win32Window Win32Point*) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>apiSetWindowPosition:insertAfter:x:y:cx:cy:flags: (in category 'api calls') ----- apiSetWindowPosition: handleWindow insertAfter: handleAfterWindow x: x y: y cx: cx cy: cy flags: flags <apicall: bool 'SetWindowPos' (Win32Window Win32Window ulong ulong ulong ulong ulong) module: 'user32.dll'> ^self primitiveFailed ! ----- Method: Win32Window>>apiSetWindowText:text: (in category 'api calls') ----- apiSetWindowText: handleWindow text: aString <apicall: long 'SetWindowTextA' (Win32Window char*) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Window>>getDC (in category 'accessing') ----- getDC "Return the DC associated with the window" ^self apiGetDC: self! ----- Method: Win32Window>>getHDCDuring: (in category 'accessing') ----- getHDCDuring: aBlock "Provide a Win32 HDC during the execution of aBlock" | hDC | hDC := self getDC. [aBlock value: hDC] ensure:[self releaseDC: hDC].! ----- Method: Win32Window>>getParent (in category 'accessing') ----- getParent | wnd | wnd := self apiGetParent: self. ^wnd handle = 0 ifTrue:[nil] ifFalse:[wnd]! ----- Method: Win32Window>>getWindowText: (in category 'api calls') ----- getWindowText: handleWindow "self new getWindowText: Win32Window getFocus" |buffer maxSize | maxSize := 255. buffer := ByteArray new: maxSize. self apiGetWindowText: handleWindow buffer: buffer maxCount: maxSize. ^buffer asString ! ----- Method: Win32Window>>messageBox: (in category 'accessing') ----- messageBox: aString "Win32Window getFocus messageBox:'Hello World'" ^self messageBox: aString title: 'Squeak'! ----- Method: Win32Window>>messageBox:title: (in category 'accessing') ----- messageBox: aString title: aTitle "Win32Window getFocus messageBox:'Hello World' title:'News from Squeak:'" ^self messageBox: aString title: aTitle flags: 0! ----- Method: Win32Window>>messageBox:title:flags: (in category 'accessing') ----- messageBox: aString title: aTitle flags: flags "Win32Window getFocus messageBox:'Are you ready???' title:'News from Squeak:' flags: 3" ^self apiMessageBox: self text: aString title: aTitle flags: flags! ----- Method: Win32Window>>releaseDC: (in category 'accessing') ----- releaseDC: aHDC "Release the given DC" self apiReleaseDC: self with: aHDC! ----- Method: Win32Window>>screenToClient: (in category 'accessing') ----- screenToClient: aPoint self apiScreenToClient: self with: aPoint. ^aPoint! ExternalTypeAlias subclass: #X11ID instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-X11'! !X11ID commentStamp: 'mt 6/4/2020 19:16' prior: 0! I am an opaque handle in X11.! X11ID subclass: #X11Drawable instanceVariableNames: 'display xid' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-X11'! ----- Method: X11Drawable class>>display: (in category 'instance creation') ----- display: aX11Display ^ self new display: aX11Display! ----- Method: X11Drawable>>display (in category 'accessing') ----- display ^display! ----- Method: X11Drawable>>display: (in category 'accessing') ----- display: aDisplay display := aDisplay! ----- Method: X11Drawable>>printOn: (in category 'printing') ----- printOn: aStream aStream nextPutAll: self class name; nextPut: $(; nextPutAll: self xid printStringHex; nextPut: $) ! ----- Method: X11Drawable>>xid (in category 'accessing') ----- xid ^ xid! ----- Method: X11Drawable>>xid: (in category 'accessing') ----- xid: anUnsignedInteger xid := anUnsignedInteger! ----- Method: X11ID class>>originalTypeName (in category 'field definition') ----- originalTypeName " self defineFields " ^ 'size_t' "or always uint32_t ??"! X11ID subclass: #X11Window instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-X11'! ExternalStructure subclass: #MacPixPatPtr instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-MacOS'! !MacPixPatPtr commentStamp: 'spd 5/16/2010 22:32' prior: 0! See class comment for MacRect.! ----- Method: MacPixPatPtr class>>fields (in category 'field definition') ----- fields "MacPixPatPtr defineFields" "The following really means typedef void* MacPixPatPtr; " ^#(nil 'void*') "For now this is just an opaque handle"! ----- Method: MacPixPatPtr class>>newPixPat (in category 'instance creation') ----- newPixPat <apicall: MacPixPatPtr* 'NewPixPat' (void) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacPixPatPtr>>apiDisposePixPat: (in category 'api calls') ----- apiDisposePixPat: aPixPat <apicall: void 'DisposePixPat' (MacPixPatPtr*) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacPixPatPtr>>apiMakeRGBPat:with: (in category 'api calls') ----- apiMakeRGBPat: aPixPat with: aRGBColor <apicall: void 'MakeRGBPat' (MacPixPatPtr* MacRGBColor*) module: 'ApplicationServices'> ^self externalCallFailed! ----- Method: MacPixPatPtr>>dispose (in category 'initialize-release') ----- dispose handle == nil ifFalse:[ self apiDisposePixPat: self. handle := nil. ].! ----- Method: MacPixPatPtr>>makeRGBPattern: (in category 'accessing') ----- makeRGBPattern: aColor ^self apiMakeRGBPat: self with: (MacRGBColor fromColor: aColor)! ExternalStructure subclass: #MacPoint instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-MacOS'! !MacPoint commentStamp: 'spd 5/16/2010 22:32' prior: 0! See class comment for MacRect.! ----- Method: MacPoint class>>apiLineTo:with: (in category 'api calls') ----- apiLineTo: x with: y <apicall: void 'LineTo' (short short) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacPoint class>>apiMoveTo:with: (in category 'api calls') ----- apiMoveTo: x with: y <apicall: void 'MoveTo' (short short) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacPoint class>>fields (in category 'field definition') ----- fields "MacPoint defineFields" ^#( (v 'short') (h 'short') )! ----- Method: MacPoint class>>lineTo: (in category 'examples') ----- lineTo: aPoint "MacPoint moveTo: 0@0; lineTo: 100@100" ^self apiLineTo: aPoint x with: aPoint y ! ----- Method: MacPoint class>>macDraw (in category 'examples') ----- macDraw "MacPoint macDraw" | pt | pt := self new. pt getMousePoint. self moveTo: pt. [Sensor anyButtonPressed] whileFalse:[ pt getMousePoint. self lineTo: pt. ]. Display forceToScreen.! ----- Method: MacPoint class>>moveTo: (in category 'examples') ----- moveTo: aPoint "MacPoint moveTo: 0@0; lineTo: 100@100" ^self apiMoveTo: aPoint x with: aPoint y ! ----- Method: MacPoint>>apiGetMousePoint: (in category 'api calls') ----- apiGetMousePoint: aMacPoint <apicall: void 'GetMouse' (MacPoint*) module:'Carbon.framework'> ^self externalCallFailed! ----- Method: MacPoint>>getMousePoint (in category 'accessing') ----- getMousePoint ^self apiGetMousePoint: self! ----- Method: MacPoint>>x (in category 'accessing') ----- x ^self h! ----- Method: MacPoint>>x: (in category 'accessing') ----- x: anObject ^self h: anObject! ----- Method: MacPoint>>y (in category 'accessing') ----- y ^self v! ----- Method: MacPoint>>y: (in category 'accessing') ----- y: anObject ^self v: anObject! ExternalStructure subclass: #MacRGBColor instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-MacOS'! !MacRGBColor commentStamp: 'spd 5/16/2010 22:31' prior: 0! See class comment for MacRect.! ----- Method: MacRGBColor class>>fields (in category 'field definition') ----- fields "MacRGBColor defineFields" ^#( (red 'ushort') (green 'ushort') (blue 'ushort') )! ----- Method: MacRGBColor class>>fromColor: (in category 'instance creation') ----- fromColor: aColor ^(self new) red: (aColor red * 16rFFFF) rounded; green: (aColor green * 16rFFFF) rounded; blue: (aColor blue * 16rFFFF) rounded; yourself! ExternalStructure subclass: #MacRect instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-MacOS'! !MacRect commentStamp: 'spd 5/16/2010 22:42' prior: 0! I, with my friends (MacPixPatPtr, MacPoint and MacRGBColor), show how to make calls into a Mac OS framework. The particular library I use in my examples, QuickDraw, is depreciated in OS X 10.4, but the examples still run as of OS X 10.6.2 See http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/QuickDraw_Ref/Reference/reference.html for more information. WARNING: for Snow Leopard, see warning in MacOSShell! ----- Method: MacRect class>>apiFillCOval:with: (in category 'api calls') ----- apiFillCOval: r with: pat <apicall: void 'FillCOval' (MacRect* MacPixPatPtr*) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacRect class>>apiFillCRect:with: (in category 'api calls') ----- apiFillCRect: r with: pat <apicall: void 'FillCRect' (MacRect* MacPixPatPtr*) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacRect class>>apiFrameOval: (in category 'api calls') ----- apiFrameOval: r <apicall: void 'FrameOval' (MacRect*) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacRect class>>apiFrameRect: (in category 'api calls') ----- apiFrameRect: r <apicall: void 'FrameRect' (MacRect*) module:'ApplicationServices'> ^self externalCallFailed! ----- Method: MacRect class>>coloredEllipses (in category 'examples') ----- coloredEllipses "MacRect coloredEllipses" | rnd w h colors n r pat v0 v1 | colors := Color colorNames collect:[:cName| (Color perform: cName)]. "convert to PixPats" colors := colors collect:[:c| MacPixPatPtr newPixPat makeRGBPattern: c]. rnd := Random new. w := Display width. h := Display height. n := 0. r := MacRect new. [Sensor anyButtonPressed] whileFalse:[ pat := colors atRandom. v0 := (rnd next * w) asInteger. v1 := (rnd next * w) asInteger. v0 < v1 ifTrue:[r left: v0; right: v1] ifFalse:[r left: v1; right: v0]. v0 := (rnd next * h) asInteger. v1 := (rnd next * h) asInteger. v0 < v1 ifTrue:[r top: v0; bottom: v1] ifFalse:[r top: v1; bottom: v0]. self apiFillCOval: r with: pat. self apiFrameOval: r. n := n + 1. (n \\ 10) = 0 ifTrue:[n printString displayAt: 0@0]. ]. colors do:[:c| c dispose]. Display forceToScreen.! ----- Method: MacRect class>>coloredRectangles (in category 'examples') ----- coloredRectangles "MacRect coloredRectangles" | rnd w h colors n r pat v0 v1 nPixels time | colors := Color colorNames collect:[:cName| (Color perform: cName)]. "convert to PixPats" colors := colors collect:[:c| MacPixPatPtr newPixPat makeRGBPattern: c]. rnd := Random new. w := Display width. h := Display height. n := 0. r := MacRect new. nPixels := 0. time := Time millisecondClockValue. [Sensor anyButtonPressed] whileFalse:[ pat := colors atRandom. v0 := (rnd next * w) asInteger. v1 := (rnd next * w) asInteger. v0 < v1 ifTrue:[r left: v0; right: v1] ifFalse:[r left: v1; right: v0]. v0 := (rnd next * h) asInteger. v1 := (rnd next * h) asInteger. v0 < v1 ifTrue:[r top: v0; bottom: v1] ifFalse:[r top: v1; bottom: v0]. self apiFillCRect: r with: pat. self apiFrameRect: r. n := n + 1. nPixels := nPixels + ((r right - r left) * (r bottom - r top)). (n \\ 100) = 0 ifTrue:[ 'Pixel fillRate: ', (nPixels * 1000 // (Time millisecondClockValue - time)) asStringWithCommas displayAt: 0@0]. ]. colors do:[:c| c dispose]. Display forceToScreen.! ----- Method: MacRect class>>fields (in category 'field definition') ----- fields "MacRect defineFields" ^#( (top 'short') (left 'short') (bottom 'short') (right 'short') )! ----- Method: MacRect class>>macDraw (in category 'examples') ----- macDraw "MacRect macDraw" ^MacPoint macDraw! ExternalStructure subclass: #Win32Point instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32Point class>>apiGetCursorPos: (in category 'api calls') ----- apiGetCursorPos: pt <apicall: bool 'GetCursorPos' (Win32Point*) module: 'user32.dll'> ^self externalCallFailed! ----- Method: Win32Point class>>fields (in category 'accessing') ----- fields "POINT defineFields" ^#( (x 'long') (y 'long') )! ----- Method: Win32Point class>>getCursorPos (in category 'instance creation') ----- getCursorPos | pt | pt := self new. self apiGetCursorPos: pt. ^pt! ----- Method: Win32Point>>asPoint (in category 'converting') ----- asPoint ^self x @ self y! ExternalStructure subclass: #Win32Rectangle instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-Win32'! ----- Method: Win32Rectangle class>>fields (in category 'accessing') ----- fields "Win32Rectangle defineFields" ^ #(#(#left 'long') #(#top 'long') #(#right 'long') #(#bottom 'long') )! ----- Method: Win32Rectangle class>>fromRectangle: (in category 'instance creation') ----- fromRectangle: rc "returns an instance of the receiver from the given smalltalk rectangle" ^ self new left: rc left top: rc top right: rc right bottom: rc bottom ! ----- Method: Win32Rectangle>>left:top:right:bottom: (in category 'accessing') ----- left: left top: top right: right bottom: bottom "sets the coordinates of the receiver" self left: left. self top: top. self right: right. self bottom: bottom ! ExternalStructure subclass: #X11Display instanceVariableNames: '' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-X11'! ----- Method: X11Display class>>XOpenDisplay: (in category 'instance creation') ----- XOpenDisplay: displayName "X11Display XOpenDisplay: nil" <cdecl: X11Display* 'XOpenDisplay' (char*) module:'X11'> ^self externalCallFailed! ----- Method: X11Display class>>coloredEllipses (in category 'examples') ----- coloredEllipses "X11Display coloredEllipses" | display window gc colors rnd w h pt1 pt2 r | display := X11Display XOpenDisplay: nil. window := display ourWindow. gc := X11GC on: window. colors := Color colorNames collect:[:n| (Color perform: n) pixelWordForDepth: 32]. rnd := Random new. w := Display width. h := Display height. [Sensor anyButtonPressed] whileFalse:[ pt1 := (rnd next * w) asInteger @ (rnd next * h) asInteger. pt2 := (rnd next * w) asInteger @ (rnd next * h) asInteger. r := Rectangle encompassing: (Array with: pt1 with: pt2). gc foreground: colors atRandom. gc fillOval: r. gc foreground: 0. gc drawOval: r. display sync. ]. gc free. display closeDisplay. Display forceToScreen.! ----- Method: X11Display class>>coloredRectangles (in category 'examples') ----- coloredRectangles "X11Display coloredRectangles" | display window gc colors rnd w h pt1 pt2 r nPixels time n | display := X11Display XOpenDisplay: nil. window := display ourWindow. gc := X11GC on: window. colors := Color colorNames collect:[:cn| (Color perform: cn) pixelWordForDepth: 32]. rnd := Random new. w := Display width. h := Display height. n := 0. nPixels := 0. time := Time millisecondClockValue. [Sensor anyButtonPressed] whileFalse:[ pt1 := (rnd next * w) asInteger @ (rnd next * h) asInteger. pt2 := (rnd next * w) asInteger @ (rnd next * h) asInteger. r := Rectangle encompassing: (Array with: pt1 with: pt2). gc foreground: colors atRandom. gc fillRectangle: r. gc foreground: 0. gc drawRectangle: r. display sync. n := n + 1. nPixels := nPixels + ((r right - r left) * (r bottom - r top)). (n \\ 100) = 0 ifTrue:[ 'Pixel fillRate: ', (nPixels * 1000 // (Time millisecondClockValue - time)) asStringWithCommas displayAt: 0@0]. ]. gc free. display closeDisplay. Display forceToScreen.! ----- Method: X11Display class>>fields (in category 'field definition') ----- fields "X11Display defineFields" "Note: The structure of Display is internal and only pointers to X11Display are used" ^#()! ----- Method: X11Display class>>new (in category 'instance creation') ----- new ^ self on: nil! ----- Method: X11Display class>>on: (in category 'instance creation') ----- on: aStringOrNil ^ self XOpenDisplay: aStringOrNil! ----- Method: X11Display class>>x11Draw (in category 'examples') ----- x11Draw "X11Display x11Draw" | display window gc nextPt lastPt ptr | display := X11Display XOpenDisplay: nil. window = display ourWindow. gc := X11GC on: window. gc foreground: 0. lastPt := nil. [ptr := display queryPointer: window. "{root. child. root pos. win pos. mask}" ptr last anyMask: 256] whileFalse:[ nextPt := ptr fourth. nextPt = lastPt ifFalse:[ lastPt ifNotNil: [ gc drawLineFrom: lastPt to: nextPt. display sync]. lastPt := nextPt]. ]. gc free. display closeDisplay. Display forceToScreen.! ----- Method: X11Display>>None (in category 'xlib calls') ----- None ^ 0! ----- Method: X11Display>>XCloseDisplay: (in category 'xlib calls') ----- XCloseDisplay: aDisplay <cdecl: void 'XCloseDisplay' (X11Display*) module:'X11'> ^self externalCallFailed! ----- Method: X11Display>>XDisplayString: (in category 'xlib calls') ----- XDisplayString: aDisplay <cdecl: char* 'XDisplayString' (X11Display*) module:'X11'> ^self externalCallFailed! ----- Method: X11Display>>XFlush: (in category 'xlib calls') ----- XFlush: xDisplay <cdecl: void 'XFlush' (X11Display*) module:'X11'> ^self externalCallFailed! ----- Method: X11Display>>XGetInputFocus:with:with: (in category 'xlib calls') ----- XGetInputFocus: display with: focus with: revert <cdecl: void 'XGetInputFocus' (X11Display* ulong* long*) module: 'X11'> ^self externalCallFailed! ----- Method: X11Display>>XQueryPointer:window:returnRoot:child:rootX:rootY:winX:winY:mask: (in category 'xlib calls') ----- XQueryPointer: display window: w returnRoot: root child: child rootX: rootX rootY: rootY winX: winX winY: winY mask: mask <cdecl: bool 'XQueryPointer' (X11Display* ulong ulong* ulong* long* long* long* long* long*) module: 'X11'> ^self externalCallFailed! ----- Method: X11Display>>XSync: (in category 'xlib calls') ----- XSync: xDisplay <cdecl: void 'XSync' (X11Display*) module:'X11'> ^self externalCallFailed! ----- Method: X11Display>>XWarpPointer:sourceWindow:destWindow:sourceX:sourceY:sourceWidth:sourceHeight:destX:destY: (in category 'xlib calls') ----- XWarpPointer: display sourceWindow: srcWindowID destWindow: destWindowID sourceX: srcX sourceY: srcY sourceWidth: srcWidth sourceHeight: srcHeight destX: destX destY: destY <cdecl: bool 'XWarpPointer' (X11Display* ulong ulong long long ulong ulong long long) module: 'X11'> ^self externalCallFailed! ----- Method: X11Display>>closeDisplay (in category 'initialize-release') ----- closeDisplay handle == nil ifFalse:[ self XCloseDisplay: self. handle := nil].! ----- Method: X11Display>>displayString (in category 'accessing') ----- displayString ^self XDisplayString: self! ----- Method: X11Display>>flush (in category 'initialize-release') ----- flush self XFlush: self! ----- Method: X11Display>>getInputFocus (in category 'accessing') ----- getInputFocus | focus revert | focus := WordArray new: 1. revert := WordArray new: 1. self XGetInputFocus: self with: focus with: revert. ^ X11Window new xid: focus first! ----- Method: X11Display>>ourWindow (in category 'accessing') ----- ourWindow "Guess the window to draw on." | window ptr child | window := self getInputFocus. ptr := self queryPointer: window. "{root. child. root pos. win pos. mask}" child := ptr second. child xid = 0 ifTrue: [^ window]. ^ child! ----- Method: X11Display>>queryPointer: (in category 'accessing') ----- queryPointer: aX11Window | root child rootX rootY winX winY mask | root := WordArray new: 1. child := WordArray new: 1. rootX := WordArray new: 1. rootY := WordArray new: 1. winX := WordArray new: 1. winY := WordArray new: 1. mask := WordArray new: 1. self XQueryPointer: self window: aX11Window xid returnRoot: root child: child rootX: rootX rootY: rootY winX: winX winY: winY mask: mask. ^{ X11Window new xid: root first. X11Window new xid: child first. rootX first @ rootY first. winX first @ winY first. mask first}! ----- Method: X11Display>>sync (in category 'initialize-release') ----- sync ^self XSync: self! ----- Method: X11Display>>warpPointerBy: (in category 'accessing') ----- warpPointerBy: aPoint "Moves the mouse pointer from its current location to its current location + aPoint. Generates a mouse move event if the squeak window is active" ^ self XWarpPointer: self sourceWindow: self None destWindow: self None sourceX: 0 sourceY: 0 sourceWidth: 0 sourceHeight: 0 destX: aPoint x destY: aPoint y! ----- Method: X11Display>>warpPointerFrom:in:To:in: (in category 'accessing') ----- warpPointerFrom: aRectangle in: sourceWindow To: aPoint in: destWindow "Moves the mouse pointer to aPoint relative to the top-left corner of a window" ^ self XWarpPointer: self sourceWindow: sourceWindow xid destWindow: destWindow xid sourceX: aRectangle left sourceY: aRectangle top sourceWidth: aRectangle width sourceHeight: aRectangle height destX: aPoint x destY: aPoint y! ----- Method: X11Display>>warpPointerTo:in: (in category 'accessing') ----- warpPointerTo: aPoint in: aWindow "Moves the mouse pointer to aPoint relative to the top-left corner of a window" ^ self XWarpPointer: self sourceWindow: self None destWindow: aWindow xid sourceX: 0 sourceY: 0 sourceWidth: 0 sourceHeight: 0 destX: aPoint x destY: aPoint y! ExternalStructure subclass: #X11GC instanceVariableNames: 'drawable' classVariableNames: '' poolDictionaries: '' category: 'FFI-Libraries-X11'! ----- Method: X11GC class>>XCreateGC:with:with:with: (in category 'xlib calls') ----- XCreateGC: xDisplay with: aDrawable with: valueMask with: values <cdecl: X11GC 'XCreateGC' (X11Display* X11Drawable ulong long*) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC class>>fields (in category 'field definition') ----- fields "X11GC defineFields" ^#( nil 'void*' )! ----- Method: X11GC class>>on: (in category 'instance creation') ----- on: aDrawable | xgc | xgc := self XCreateGC: aDrawable display with: aDrawable with: 0 with: nil. xgc drawable: aDrawable. ^xgc! ----- Method: X11GC>>XDrawArc:with:with:with:with:with:with:with:with: (in category 'xlib calls') ----- XDrawArc: xDisplay with: xDrawable with: xGC with: x with: y with: w with: h with: a1 with: a2 <cdecl: void 'XDrawArc' (X11Display* X11Drawable X11GC long long ulong ulong long long) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XDrawLine:with:with:with:with:with:with: (in category 'xlib calls') ----- XDrawLine: xDisplay with: aDrawable with: xGC with: x0 with: y0 with: x1 with: y1 <cdecl: long 'XDrawLine' (X11Display* X11Drawable X11GC long long long long) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XDrawRectangle:with:with:with:with:with:with: (in category 'xlib calls') ----- XDrawRectangle: xDisplay with: xDrawable with: xGC with: x with: y with: w with: h <cdecl: void 'XDrawRectangle' (X11Display* X11Drawable X11GC long long ulong ulong) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XFillArc:with:with:with:with:with:with:with:with: (in category 'xlib calls') ----- XFillArc: xDisplay with: xDrawable with: xGC with: x with: y with: w with: h with: a1 with: a2 <cdecl: void 'XFillArc' (X11Display* X11Drawable X11GC long long ulong ulong long long) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XFillRectangle:with:with:with:with:with:with: (in category 'xlib calls') ----- XFillRectangle: xDisplay with: xDrawable with: xGC with: x with: y with: w with: h <cdecl: void 'XFillRectangle' (X11Display* X11Drawable X11GC long long ulong ulong) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XFreeGC:with: (in category 'xlib calls') ----- XFreeGC: xDisplay with: xGC <cdecl: long 'XFreeGC' (X11Display* X11GC) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XSetBackground:with:with: (in category 'xlib calls') ----- XSetBackground: xDisplay with: xGC with: bg <cdecl: void 'XSetBackground' (X11Display* X11GC long) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>XSetForeground:with:with: (in category 'xlib calls') ----- XSetForeground: xDisplay with: xGC with: fg <cdecl: void 'XSetForeground' (X11Display* X11GC long) module: 'X11'> ^self externalCallFailed! ----- Method: X11GC>>background: (in category 'drawing') ----- background: pixelValue self XSetBackground: self display with: self with: pixelValue! ----- Method: X11GC>>display (in category 'accessing') ----- display ^drawable display! ----- Method: X11GC>>drawLineFrom:to: (in category 'drawing') ----- drawLineFrom: pt1 to: pt2 self XDrawLine: self display with: drawable with: self with: pt1 x with: pt1 y with: pt2 x with: pt2 y! ----- Method: X11GC>>drawOval: (in category 'drawing') ----- drawOval: aRectangle self XDrawArc: self display with: drawable with: self with: aRectangle left with: aRectangle top with: aRectangle width with: aRectangle height with: 0 with: 64*360! ----- Method: X11GC>>drawRectangle: (in category 'drawing') ----- drawRectangle: aRectangle self XDrawRectangle: self display with: drawable with: self with: aRectangle left with: aRectangle top with: aRectangle width with: aRectangle height! ----- Method: X11GC>>drawable (in category 'accessing') ----- drawable ^drawable! ----- Method: X11GC>>drawable: (in category 'accessing') ----- drawable: aDrawable drawable := aDrawable! ----- Method: X11GC>>fillOval: (in category 'drawing') ----- fillOval: aRectangle self XFillArc: self display with: drawable with: self with: aRectangle left with: aRectangle top with: aRectangle width with: aRectangle height with: 0 with: 64*360! ----- Method: X11GC>>fillRectangle: (in category 'drawing') ----- fillRectangle: aRectangle self XFillRectangle: self display with: drawable with: self with: aRectangle left with: aRectangle top with: aRectangle width with: aRectangle height! ----- Method: X11GC>>foreground: (in category 'drawing') ----- foreground: pixelValue self XSetForeground: self display with: self with: pixelValue ! ----- Method: X11GC>>free (in category 'initialize-release') ----- free handle == nil ifFalse:[ self XFreeGC: self display with: self. handle := nil. ].! |
Free forum by Nabble | Edit this page |