--- a/Win32OperatingSystem.st Wed Feb 01 12:14:27 2006 +0100
+++ b/Win32OperatingSystem.st Fri Feb 03 16:19:09 2006 +0100
@@ -65,6 +65,13 @@
privateIn:Win32OperatingSystem
!
+Win32OperatingSystem::Win32Handle subclass:#Win32SerialPortHandle
+ instanceVariableNames:''
+ classVariableNames:''
+ poolDictionaries:''
+ privateIn:Win32OperatingSystem
+!
+
Win32OperatingSystem::Win32Handle subclass:#Win32SocketHandle
instanceVariableNames:''
classVariableNames:''
@@ -6732,6 +6739,12 @@
^ RegistryEntry
! !
+!Win32OperatingSystem class methodsFor:'serial port support'!
+
+serialPortAccessor
+ ^ Win32SerialPortHandle
+! !
+
!Win32OperatingSystem class methodsFor:'socket creation'!
socketAccessor
@@ -8715,6 +8728,62 @@
"
! !
+!Win32OperatingSystem::RegistryEntry class methodsFor:'misc queries'!
+
+executableForMimeType:mimeType
+ "given a mimeType, retrieve the path to an application from the registry"
+
+ |k suffix|
+
+ k := self key:'HKEY_CLASSES_ROOT\MIME\Database\Content Type\',mimeType.
+ k notNil ifTrue:[
+ suffix := k valueNamed:'extension'.
+ suffix notNil ifTrue:[
+ ^ self executableForSuffix:suffix
+ ].
+ ].
+ ^ nil
+
+ "
+ self executableForMimeType:'application/pdf'
+ self executableForMimeType:'audio/mp3'
+ self executableForMimeType:'video/avi'
+ self executableForMimeType:'application/x-zip-compressed'
+ "
+!
+
+executableForSuffix:suffixArg
+ "given a suffix, retrieve the path to an application from the registry"
+
+ |k fkey cmd suffix|
+
+ suffix := suffixArg.
+ (suffix startsWith:'.') ifTrue:[
+ suffix := suffix copyFrom:2
+ ].
+ k := self key:'HKEY_CLASSES_ROOT\.',suffix.
+
+ k notNil ifTrue:[
+ fkey := (k valueNamed:'').
+ ].
+ fkey isNil ifTrue:[
+ fkey := suffix,'_auto_file'
+ ].
+ fkey notEmptyOrNil ifTrue:[
+ k := Win32OperatingSystem::RegistryEntry key:('HKEY_CLASSES_ROOT\' , fkey , '\shell\open\command').
+ k notNil ifTrue:[
+ cmd := k valueNamed:''
+ ].
+ ].
+
+ ^ cmd
+
+ "
+ self executableForSuffix:'pdf'
+ self executableForSuffix:'zip'
+ "
+! !
+
!Win32OperatingSystem::RegistryEntry class methodsFor:'registry access'!
stringValueFor:valueName atKey:keyPath
@@ -9396,7 +9465,7 @@
"some entry has been collected - close it"
handle notNil ifTrue:[
- self closeKey.
+ self closeKey.
]
"Created: / 19.5.1999 / 22:39:52 / cg"
@@ -9446,7 +9515,7 @@
!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.191 2006-01-31 09:26:11 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.192 2006-02-03 15:19:09 cg Exp $'
! !
!Win32OperatingSystem::Win32FILEHandle methodsFor:'release'!
@@ -9473,7 +9542,7 @@
!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.191 2006-01-31 09:26:11 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.192 2006-02-03 15:19:09 cg Exp $'
! !
!Win32OperatingSystem::Win32Handle methodsFor:'io'!
@@ -9855,6 +9924,352 @@
^ pid
! !
+!Win32OperatingSystem::Win32SerialPortHandle methodsFor:'opening'!
+
+open:portName baudRate:baudRate stopBitsType:stopBitsType
+ parityType:parityType dataBits:dataBits
+ inFlowCtrl:inFlowCtrlType outFlowCtrl:outFlowCtrlType
+ xOnChar:xOnChar xOffChar:xOffChar
+ "portName: COM%d
+ baudRate: Integer
+ stopBitsType: #stop1, #stop2 or #stop1_5
+ parityType: #odd, #even or #none
+ dataBits: #integer
+ inFlowCtrlType: #xOnOff #hardware
+ outFlowCtrlType: #xOnOff #hardware
+ xOnChar: Character or Integer
+ xOffChar: Character or Integer"
+
+ |errorNumber|
+
+%{
+ HANDLE port;
+ COMMTIMEOUTS timeouts;
+ DCB dcb;
+ char *__portName;
+ int __setBaudRate = 1,
+ __setDataBits = 1,
+ __setXOnChar = 1,
+ __setXOffChar = 1,
+ __setInFlowCtrl = 1,
+ __setOutFlowCtrl = 1,
+ __setStopBits = 1,
+ __setParityType = 1;
+ int __baudRate, __dataBits;
+ int __xOnChar, __xOffChar;
+ int __inFlowCtrl, __outFlowCtrl;
+ int __stopBits, __parityType;
+# define XONOFF 1
+# define HARDWARE 2
+# define STOP1 1
+# define STOP2 2
+# define STOP1_5 3
+# define ODD 1
+# define EVEN 2
+# define NONE 3
+
+ if (__isString(portName)) {
+ __portName = __stringVal(portName);
+ } else {
+ goto failure;
+ }
+ if (__isSmallInteger(baudRate)) {
+ __baudRate = __intVal(baudRate);
+ } else if (baudRate == nil) {
+ __setBaudRate = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(dataBits)) {
+ __dataBits = __intVal(dataBits);
+ } else if (dataBits == nil) {
+ __setDataBits = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(xOnChar)) {
+ __xOnChar = __intVal(xOnChar);
+ } else if (__isCharacter(xOnChar)) {
+ __xOnChar = __intVal(_characterVal(xOnChar));
+ } else if (xOnChar == nil) {
+ __setXOnChar = 0;
+ } else {
+ goto failure;
+ }
+
+ if (__isSmallInteger(xOffChar)) {
+ __xOffChar = __intVal(xOffChar);
+ } else if (__isCharacter(xOffChar)) {
+ __xOffChar = __intVal(_characterVal(xOffChar));
+ } else if (xOffChar == nil) {
+ __setXOffChar = 0;
+ } else {
+ goto failure;
+ }
+
+ if (inFlowCtrlType == @symbol(xOnOff)) {
+ __inFlowCtrl = XONOFF;
+ } else if (inFlowCtrlType == @symbol(hardware)) {
+ __inFlowCtrl = HARDWARE;
+ } else if (inFlowCtrlType == nil) {
+ __setInFlowCtrl = 0;
+ } else {
+ goto failure;
+ }
+
+ if (outFlowCtrlType == @symbol(xOnOff)) {
+ __outFlowCtrl = XONOFF;
+ } else if (outFlowCtrlType == @symbol(hardware)) {
+ __outFlowCtrl = HARDWARE;
+ } else if (outFlowCtrlType == nil) {
+ __setOutFlowCtrl = 0;
+ } else {
+ goto failure;
+ }
+
+ if (stopBitsType == @symbol(stop1)) {
+ __stopBits = STOP1;
+ } else if (stopBitsType == @symbol(stop2)) {
+ __stopBits = STOP2;
+ } else if (stopBitsType == @symbol(stop1_5)) {
+ __stopBits = STOP1_5;
+ } else if (stopBitsType == nil) {
+ __setStopBits = 0;
+ } else {
+ goto failure;
+ }
+
+ port = CreateFile(__portName,
+ GENERIC_READ | GENERIC_WRITE,
+ 0, /* comm devices must be opened with exclusive access */
+ NULL, /* no security attrs */
+ OPEN_EXISTING, /* comm devices must use OPEN_EXISTING */
+ 0, /* no overlapped I/O */
+ NULL /* hTemplate must be NULL for comm devices */
+ );
+ if (port == INVALID_HANDLE_VALUE) {
+ fprintf(stderr, "Win32OS [info]: serial port open failed\n");
+ errorNumber = __mkSmallInteger( __WIN32_ERR(GetLastError()) );
+ goto failure;
+ }
+ /* Flush the driver */
+ PurgeComm( port, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
+
+ /* Set driver buffer sizes */
+ SetupComm( port, 4096 /*SERIAL_IN_QUEUE_SIZE*/, 4096 /*SERIAL_OUT_QUEUE_SIZE*/);
+
+ /* Reset timeout constants */
+ timeouts.ReadIntervalTimeout= 0xFFFFFFFF;
+ timeouts.ReadTotalTimeoutMultiplier = 0;
+ timeouts.ReadTotalTimeoutConstant = 0;
+ timeouts.WriteTotalTimeoutMultiplier = 0;
+ timeouts.WriteTotalTimeoutConstant = 0;
+ SetCommTimeouts( port, &timeouts );
+
+ /* Set communication parameters */
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ if (__setBaudRate) dcb.BaudRate = __baudRate;
+ if (__setDataBits) dcb.ByteSize = __dataBits;
+ if (__setXOnChar) dcb.XonChar = __xOnChar;
+ if (__setXOffChar) dcb.XoffChar = __xOffChar;
+
+ if (__setStopBits) {
+ /* set stop bits */
+ switch(__stopBits) {
+ case STOP1_5: dcb.StopBits = 1; break; /* 1.5 stop bits */
+ case STOP1: dcb.StopBits = 0; break; /* 1 stop bit */
+ case STOP2: dcb.StopBits = 2; break; /* 2 stop bits */
+ default: goto errExit;
+ }
+ }
+
+ if (__setParityType) {
+ /* set parity */
+ switch(__parityType) {
+ case NONE: dcb.Parity = NOPARITY; break;
+ case ODD: dcb.Parity = ODDPARITY; break;
+ case EVEN: dcb.Parity = EVENPARITY; break;
+ default: goto errExit;
+ }
+ }
+
+ if (__setInFlowCtrl) {
+ /* set control flow */
+ dcb.fInX = FALSE;
+ dcb.fDtrControl = FALSE;
+ if (__inFlowCtrl == XONOFF) dcb.fInX = TRUE; /* XOn/XOff handshaking */
+ if (__inFlowCtrl == HARDWARE) dcb.fDtrControl = TRUE; /* hardware handshaking */
+ }
+ if (__setOutFlowCtrl) {
+ dcb.fOutX = FALSE;
+ dcb.fOutxCtsFlow = FALSE;
+
+ if (__outFlowCtrl == XONOFF) dcb.fOutX = TRUE; /* XOn/XOff handshaking */
+ if (__outFlowCtrl == HARDWARE) dcb.fOutxCtsFlow = TRUE; /* hardware handshaking */
+ }
+
+ if (SetCommState(port, &dcb)) {
+ RETURN( true );
+ }
+
+ fprintf(stderr, "Win32OS [info]: serial port comm-setup failed\n");
+ errorNumber = __mkSmallInteger( __WIN32_ERR(GetLastError()) );
+ /* fall into */
+errExit: ;
+ CloseHandle(port);
+
+failure: ;
+# undef XONOFF
+# undef HARDWARE
+# undef STOP1
+# undef STOP2
+# undef STOP1_5
+# undef ODD
+# undef EVEN
+# undef NONE
+%}.
+ errorNumber isNil ifTrue:[
+ self error:'invalid argument(s)'.
+ ] ifFalse:[
+ (OperatingSystem errorHolderForNumber:errorNumber) reportError
+ ].
+! !
+
+!Win32OperatingSystem::Win32SerialPortHandle methodsFor:'release'!
+
+closeFile
+ "close the handle"
+
+%{
+ HANDLE port = (HANDLE)(__externalAddressVal(self));
+
+ if (port) {
+ __externalAddressVal(self) = (HANDLE)0;
+ PurgeComm( port, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR );
+ CloseHandle(port);
+ }
+%}.
+! !
+
+!Win32OperatingSystem::Win32SerialPortHandle methodsFor:'setup'!
+
+baudRate:newRate
+%{
+ HANDLE port = (HANDLE)(__externalAddressVal(self));
+
+ if (port
+ && __isSmallInteger(newRate)) {
+ DCB dcb;
+
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ dcb.BaudRate = __intVal(newRate);
+
+ if (! SetCommState(port, &dcb)) {
+ RETURN(false);
+ }
+ RETURN(true);
+ }
+%}.
+ self primitiveFailed.
+!
+
+dataBits:newNumberOfBits
+%{
+ HANDLE port = (HANDLE)(__externalAddressVal(self));
+
+ if (port
+ && __isSmallInteger(newNumberOfBits)) {
+ DCB dcb;
+
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ dcb.ByteSize = __intVal(newNumberOfBits);
+
+ if (! SetCommState(port, &dcb)) {
+ RETURN(false);
+ }
+ RETURN(true);
+ }
+%}.
+ self primitiveFailed.
+!
+
+parityType:newParityTypeSymbol
+ "newParityTypeSymbol must be one of #odd, #even or #none (or nil)"
+
+%{
+ HANDLE port = (HANDLE)(__externalAddressVal(self));
+
+ if (port) {
+ DCB dcb;
+
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+
+ if ((newParityTypeSymbol == nil) || (newParityTypeSymbol == @symbol(none))) {
+ dcb.Parity = NOPARITY;
+ } else if (newParityTypeSymbol == @symbol(odd)) {
+ dcb.Parity = ODDPARITY;
+ } else if (newParityTypeSymbol == @symbol(even)) {
+ dcb.Parity = EVENPARITY;
+ } else {
+ goto failure;
+ }
+
+ if (! SetCommState(port, &dcb)) {
+ RETURN(false);
+ }
+ RETURN(true);
+ }
+ failure: ;
+%}.
+ self primitiveFailed.
+!
+
+stopBitsType:newStopBitsSymbol
+ "newParityTypeSymbol must be one of #stop1, #stop2 or #stop1_5"
+%{
+ HANDLE port = (HANDLE)(__externalAddressVal(self));
+
+ if (port) {
+ DCB dcb;
+
+ ZeroMemory(&dcb, sizeof(dcb));
+ dcb.DCBlength = sizeof(dcb);
+ GetCommState(port, &dcb);
+
+ if (newStopBitsSymbol == @symbol(stop1)) {
+ dcb.Parity = 0 /* STOP1 */;
+ } else if (newStopBitsSymbol == @symbol(stop2)) {
+ dcb.Parity = 2 /* STOP2 */;
+ } else if (newStopBitsSymbol == @symbol(stop1_5)) {
+ dcb.Parity = 1 /* STOP1_5 */;
+ } else {
+ goto failure;
+ }
+
+ if (! SetCommState(port, &dcb)) {
+ RETURN(false);
+ }
+ RETURN(true);
+ }
+ failure: ;
+%}.
+ self primitiveFailed.
+! !
+
!Win32OperatingSystem::Win32SocketHandle class methodsFor:'constants'!
protocolCodeOf:aNameOrNumber
@@ -10493,7 +10908,7 @@
!Win32OperatingSystem class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.191 2006-01-31 09:26:11 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.192 2006-02-03 15:19:09 cg Exp $'
! !
Win32OperatingSystem initialize!