mirror of https://github.com/encounter/SDL.git
os2: add port files for SDL2-2.0.4 from Andrey Vasilkin
only geniconv/iconv.h (was from LGPL libiconv) is replaced with a generic minimal iconv.h based on public knowledge.
This commit is contained in:
parent
93e1449764
commit
74cfb81dbb
|
@ -0,0 +1,472 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_AUDIO_DRIVER_OS2
|
||||
|
||||
/* Allow access to a raw mixing buffer */
|
||||
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "SDL_audio.h"
|
||||
#include "../SDL_audio_c.h"
|
||||
#include "SDL_os2audio.h"
|
||||
|
||||
/*
|
||||
void lockIncr(volatile int *piVal);
|
||||
#pragma aux lockIncr = \
|
||||
" lock add [eax], 1 "\
|
||||
parm [eax];
|
||||
|
||||
void lockDecr(volatile int *piVal);
|
||||
#pragma aux lockDecr = \
|
||||
" lock sub [eax], 1 "\
|
||||
parm [eax];
|
||||
*/
|
||||
|
||||
|
||||
static ULONG _getEnvULong(PSZ pszName, ULONG ulMax, ULONG ulDefault)
|
||||
{
|
||||
ULONG ulValue;
|
||||
PCHAR pcEnd;
|
||||
PSZ pszEnvVal = SDL_getenv( pszName );
|
||||
|
||||
if ( pszEnvVal == NULL )
|
||||
return ulDefault;
|
||||
|
||||
ulValue = SDL_strtoul( (const char *)pszEnvVal, &pcEnd, 10 );
|
||||
return ( pcEnd == pszEnvVal ) || ( ulValue > ulMax ) ? ulDefault : ulMax;
|
||||
}
|
||||
|
||||
static int _MCIError(PSZ pszFunc, ULONG ulResult)
|
||||
{
|
||||
CHAR acBuf[128];
|
||||
|
||||
mciGetErrorString( ulResult, (PCHAR)&acBuf, sizeof(acBuf) );
|
||||
return SDL_SetError( "[%s] %s", pszFunc, &acBuf );
|
||||
}
|
||||
|
||||
static void _mixIOError(PSZ pszFunction, ULONG ulRC)
|
||||
{
|
||||
debug( "%s() - failed, rc = 0x%X (%s)",
|
||||
pszFunction, ulRC,
|
||||
ulRC == MCIERR_INVALID_MODE ? "Mixer mode does not match request"
|
||||
: ulRC == MCIERR_INVALID_BUFFER ? "Caller sent an invalid buffer"
|
||||
: "unknown" );
|
||||
}
|
||||
|
||||
LONG APIENTRY cbAudioWriteEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
||||
ULONG ulFlags)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)pBuffer->ulUserParm;
|
||||
ULONG ulRC;
|
||||
|
||||
if ( ulFlags != MIX_WRITE_COMPLETE )
|
||||
{
|
||||
debug( "flags = 0x%X", ulFlags );
|
||||
return 0;
|
||||
}
|
||||
|
||||
// lockDecr( (int *)&pAData->ulQueuedBuf );
|
||||
ulRC = DosPostEventSem( pAData->hevBuf );
|
||||
if ( ( ulRC != NO_ERROR ) && ( ulRC != ERROR_ALREADY_POSTED ) )
|
||||
debug( "DosPostEventSem(), rc = %u", ulRC );
|
||||
|
||||
return 1; // It seems, return value is not matter.
|
||||
}
|
||||
|
||||
LONG APIENTRY cbAudioReadEvent(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
|
||||
ULONG ulFlags)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)pBuffer->ulUserParm;
|
||||
ULONG ulRC;
|
||||
|
||||
if ( ulFlags != MIX_READ_COMPLETE )
|
||||
{
|
||||
debug( "flags = 0x%X", ulFlags );
|
||||
return 0;
|
||||
}
|
||||
|
||||
pAData->stMCIMixSetup.pmixRead( pAData->stMCIMixSetup.ulMixHandle, pBuffer,
|
||||
1 );
|
||||
|
||||
ulRC = DosPostEventSem( pAData->hevBuf );
|
||||
if ( ( ulRC != NO_ERROR ) && ( ulRC != ERROR_ALREADY_POSTED ) )
|
||||
debug( "DosPostEventSem(), rc = %u", ulRC );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void OS2_DetectDevices(void)
|
||||
{
|
||||
MCI_SYSINFO_PARMS stMCISysInfo;
|
||||
CHAR acBuf[256];
|
||||
ULONG ulDevicesNum;
|
||||
MCI_SYSINFO_LOGDEVICE stLogDevice;
|
||||
MCI_SYSINFO_PARMS stSysInfoParams;
|
||||
ULONG ulRC;
|
||||
ULONG ulHandle = 0;
|
||||
|
||||
acBuf[0] = '\0';
|
||||
stMCISysInfo.pszReturn = &acBuf;
|
||||
stMCISysInfo.ulRetSize = sizeof(acBuf);
|
||||
stMCISysInfo.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||
ulRC = mciSendCommand( 0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_QUANTITY,
|
||||
&stMCISysInfo, 0 );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "MCI_SYSINFO, MCI_SYSINFO_QUANTITY - failed, rc = 0x%X", ulRC );
|
||||
return;
|
||||
}
|
||||
|
||||
ulDevicesNum = atol( stMCISysInfo.pszReturn );
|
||||
|
||||
for( stSysInfoParams.ulNumber = 0; stSysInfoParams.ulNumber < ulDevicesNum;
|
||||
stSysInfoParams.ulNumber++ )
|
||||
{
|
||||
// Get device install name.
|
||||
stSysInfoParams.pszReturn = &acBuf;
|
||||
stSysInfoParams.ulRetSize = sizeof( acBuf );
|
||||
stSysInfoParams.usDeviceType = MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||
ulRC = mciSendCommand( 0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_INSTALLNAME,
|
||||
&stSysInfoParams, 0 );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "MCI_SYSINFO, MCI_SYSINFO_INSTALLNAME - failed, rc = 0x%X", ulRC );
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get textual product description.
|
||||
stSysInfoParams.ulItem = MCI_SYSINFO_QUERY_DRIVER;
|
||||
stSysInfoParams.pSysInfoParm = &stLogDevice;
|
||||
strcpy( &stLogDevice.szInstallName, stSysInfoParams.pszReturn );
|
||||
ulRC = mciSendCommand( 0, MCI_SYSINFO, MCI_WAIT | MCI_SYSINFO_ITEM,
|
||||
&stSysInfoParams, 0 );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "MCI_SYSINFO, MCI_SYSINFO_ITEM - failed, rc = 0x%X", ulRC );
|
||||
continue;
|
||||
}
|
||||
|
||||
ulHandle++;
|
||||
SDL_AddAudioDevice( 0, &stLogDevice.szProductInfo, (void *)(ulHandle) );
|
||||
ulHandle++;
|
||||
SDL_AddAudioDevice( 1, &stLogDevice.szProductInfo, (void *)(ulHandle) );
|
||||
}
|
||||
}
|
||||
|
||||
static void OS2_WaitDevice(_THIS)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)this->hidden;
|
||||
ULONG ulRC;
|
||||
|
||||
/* Wait for an audio chunk to finish */
|
||||
ulRC = DosWaitEventSem( pAData->hevBuf, 5000 );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosWaitEventSem(), rc = %u", ulRC );
|
||||
}
|
||||
|
||||
static Uint8 *OS2_GetDeviceBuf(_THIS)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)this->hidden;
|
||||
|
||||
return pAData->aMixBuffers[pAData->ulNextBuf].pBuffer;
|
||||
}
|
||||
|
||||
static void OS2_PlayDevice(_THIS)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)this->hidden;
|
||||
ULONG ulRC;
|
||||
PMCI_MIX_BUFFER pMixBuffer = &pAData->aMixBuffers[pAData->ulNextBuf];
|
||||
|
||||
/* Queue it up */
|
||||
// lockIncr( (int *)&pAData->ulQueuedBuf );
|
||||
ulRC = pAData->stMCIMixSetup.pmixWrite( pAData->stMCIMixSetup.ulMixHandle,
|
||||
pMixBuffer, 1 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
_mixIOError( "pmixWrite", ulRC );
|
||||
else
|
||||
pAData->ulNextBuf = (pAData->ulNextBuf + 1) % pAData->cMixBuffers;
|
||||
}
|
||||
|
||||
static void OS2_WaitDone(_THIS)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)this->hidden;
|
||||
|
||||
DosWaitEventSem( pAData->hevBuf, 3000 );
|
||||
}
|
||||
|
||||
static void OS2_CloseDevice(_THIS)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData = (PSDL_PrivateAudioData)this->hidden;
|
||||
MCI_GENERIC_PARMS sMCIGenericParms;
|
||||
ULONG ulRC;
|
||||
|
||||
if ( pAData == NULL )
|
||||
return;
|
||||
|
||||
/* Close up audio */
|
||||
|
||||
if ( pAData->usDeviceId != (USHORT)~0 )
|
||||
{
|
||||
// Device is open.
|
||||
|
||||
if ( pAData->stMCIMixSetup.ulBitsPerSample != 0 )
|
||||
{
|
||||
// Mixer was initialized.
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_DEINIT,
|
||||
&pAData->stMCIMixSetup, 0 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
debug( "MCI_MIXSETUP, MCI_MIXSETUP_DEINIT - failed" );
|
||||
}
|
||||
|
||||
if ( pAData->cMixBuffers != 0 )
|
||||
{
|
||||
// Buffers was allocated.
|
||||
MCI_BUFFER_PARMS stMCIBuffer;
|
||||
|
||||
stMCIBuffer.ulBufferSize = pAData->aMixBuffers[0].ulBufferLength;
|
||||
stMCIBuffer.ulNumBuffers = pAData->cMixBuffers;
|
||||
stMCIBuffer.pBufList = &pAData->aMixBuffers;
|
||||
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_BUFFER,
|
||||
MCI_WAIT | MCI_DEALLOCATE_MEMORY, &stMCIBuffer, 0 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
debug( "MCI_BUFFER, MCI_DEALLOCATE_MEMORY - failed" );
|
||||
}
|
||||
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_CLOSE, MCI_WAIT,
|
||||
&sMCIGenericParms, 0 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
debug( "MCI_CLOSE - failed" );
|
||||
}
|
||||
|
||||
if ( pAData->hevBuf != NULLHANDLE )
|
||||
DosCloseEventSem( pAData->hevBuf );
|
||||
|
||||
SDL_free( pAData );
|
||||
this->hidden = NULL;
|
||||
}
|
||||
|
||||
static int OS2_OpenDevice(_THIS, void *handle, const char *devname,
|
||||
int iscapture)
|
||||
{
|
||||
PSDL_PrivateAudioData pAData;
|
||||
SDL_AudioFormat SDLAudioFmt;
|
||||
MCI_AMP_OPEN_PARMS stMCIAmpOpen = { 0 };
|
||||
MCI_BUFFER_PARMS stMCIBuffer = { 0 };
|
||||
ULONG ulRC;
|
||||
ULONG ulIdx;
|
||||
|
||||
for( SDLAudioFmt = SDL_FirstAudioFormat( this->spec.format );
|
||||
SDLAudioFmt != 0; SDLAudioFmt = SDL_NextAudioFormat() )
|
||||
{
|
||||
if ( ( SDLAudioFmt == AUDIO_U8 ) || ( SDLAudioFmt == AUDIO_S16 ) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( SDLAudioFmt == 0 )
|
||||
{
|
||||
debug( "Unsupported audio format, AUDIO_S16 used" );
|
||||
SDLAudioFmt = AUDIO_S16;
|
||||
this->spec.freq = AUDIO_S16;
|
||||
}
|
||||
|
||||
pAData = SDL_calloc( 1, sizeof(SDL_PrivateAudioData) );
|
||||
if ( pAData == NULL )
|
||||
return SDL_OutOfMemory();
|
||||
this->hidden = pAData;
|
||||
|
||||
ulRC = DosCreateEventSem( NULL, &pAData->hevBuf, DCE_AUTORESET, TRUE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosCreateEventSem() failed, rc = %u", ulRC );
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Open audio device
|
||||
stMCIAmpOpen.usDeviceID = handle != NULL ? ( ((ULONG)handle) - 1 ) : 0;
|
||||
stMCIAmpOpen.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
|
||||
ulRC = mciSendCommand( 0, MCI_OPEN,
|
||||
_getEnvULong( "SDL_AUDIO_SHARE", 1, 0 ) != 0
|
||||
? MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE
|
||||
: MCI_WAIT | MCI_OPEN_TYPE_ID,
|
||||
&stMCIAmpOpen, 0 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
{
|
||||
stMCIAmpOpen.usDeviceID = (USHORT)~0;
|
||||
OS2_CloseDevice( this );
|
||||
return _MCIError( "MCI_OPEN", ulRC );
|
||||
}
|
||||
pAData->usDeviceId = stMCIAmpOpen.usDeviceID;
|
||||
|
||||
if ( iscapture != 0 )
|
||||
{
|
||||
MCI_CONNECTOR_PARMS stMCIConnector = { 0 };
|
||||
MCI_AMP_SET_PARMS stMCIAmpSet = { 0 };
|
||||
BOOL fLineIn = _getEnvULong( "SDL_AUDIO_LINEIN", 1, 0 );
|
||||
|
||||
// Set particular connector.
|
||||
stMCIConnector.ulConnectorType = fLineIn ? MCI_LINE_IN_CONNECTOR
|
||||
: MCI_MICROPHONE_CONNECTOR;
|
||||
mciSendCommand( stMCIAmpOpen.usDeviceID, MCI_CONNECTOR,
|
||||
MCI_WAIT | MCI_ENABLE_CONNECTOR |
|
||||
MCI_CONNECTOR_TYPE, &stMCIConnector, 0 );
|
||||
|
||||
// Disable monitor.
|
||||
stMCIAmpSet.ulItem = MCI_AMP_SET_MONITOR;
|
||||
mciSendCommand( stMCIAmpOpen.usDeviceID, MCI_SET,
|
||||
MCI_WAIT | MCI_SET_OFF | MCI_SET_ITEM,
|
||||
&stMCIAmpSet, 0 );
|
||||
|
||||
|
||||
// Set record volume.
|
||||
stMCIAmpSet.ulLevel = _getEnvULong( "SDL_AUDIO_RECVOL", 100, 90 );
|
||||
stMCIAmpSet.ulItem = MCI_AMP_SET_AUDIO;
|
||||
stMCIAmpSet.ulAudio = MCI_SET_AUDIO_ALL; // Both cnannels.
|
||||
stMCIAmpSet.ulValue = fLineIn ? MCI_LINE_IN_CONNECTOR
|
||||
: MCI_MICROPHONE_CONNECTOR ;
|
||||
|
||||
mciSendCommand( stMCIAmpOpen.usDeviceID, MCI_SET,
|
||||
MCI_WAIT | MCI_SET_AUDIO | MCI_AMP_SET_GAIN,
|
||||
&stMCIAmpSet, 0 );
|
||||
}
|
||||
|
||||
this->spec.format = SDLAudioFmt;
|
||||
this->spec.channels = this->spec.channels > 1 ? 2 : 1;
|
||||
if ( this->spec.freq < 8000 )
|
||||
this->spec.freq = 8000;
|
||||
if ( this->spec.freq > 48000 )
|
||||
this->spec.freq = 48000;
|
||||
|
||||
// Setup mixer.
|
||||
pAData->stMCIMixSetup.ulFormatTag = MCI_WAVE_FORMAT_PCM;
|
||||
pAData->stMCIMixSetup.ulBitsPerSample = SDL_AUDIO_BITSIZE( SDLAudioFmt );
|
||||
pAData->stMCIMixSetup.ulSamplesPerSec = this->spec.freq;
|
||||
pAData->stMCIMixSetup.ulChannels = this->spec.channels;
|
||||
pAData->stMCIMixSetup.ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
|
||||
if ( iscapture == 0 )
|
||||
{
|
||||
pAData->stMCIMixSetup.ulFormatMode = MCI_PLAY;
|
||||
pAData->stMCIMixSetup.pmixEvent = cbAudioWriteEvent;
|
||||
}
|
||||
else
|
||||
{
|
||||
pAData->stMCIMixSetup.ulFormatMode = MCI_RECORD;
|
||||
pAData->stMCIMixSetup.pmixEvent = cbAudioReadEvent;
|
||||
}
|
||||
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0 );
|
||||
if ( ( ulRC != MCIERR_SUCCESS ) && ( this->spec.freq > 44100 ) )
|
||||
{
|
||||
pAData->stMCIMixSetup.ulSamplesPerSec = 44100;
|
||||
this->spec.freq = 44100;
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_MIXSETUP,
|
||||
MCI_WAIT | MCI_MIXSETUP_INIT, &pAData->stMCIMixSetup, 0 );
|
||||
}
|
||||
|
||||
debug( "Setup mixer [BPS: %u, Freq.: %u, Channels: %u]: %s",
|
||||
pAData->stMCIMixSetup.ulBitsPerSample,
|
||||
pAData->stMCIMixSetup.ulSamplesPerSec,
|
||||
pAData->stMCIMixSetup.ulChannels,
|
||||
ulRC == MCIERR_SUCCESS ? "SUCCESS" : "FAIL" );
|
||||
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
{
|
||||
pAData->stMCIMixSetup.ulBitsPerSample = 0;
|
||||
OS2_CloseDevice( this );
|
||||
return _MCIError( "MCI_MIXSETUP", ulRC );
|
||||
}
|
||||
|
||||
this->spec.samples = pAData->stMCIMixSetup.ulSamplesPerSec;
|
||||
/* Update the fragment size as size in bytes */
|
||||
SDL_CalculateAudioSpec( &this->spec );
|
||||
|
||||
// Allocate memory buffers
|
||||
|
||||
stMCIBuffer.ulBufferSize = (this->spec.freq / 1000) * 100;// this->spec.size;
|
||||
stMCIBuffer.ulNumBuffers = NUM_BUFFERS;
|
||||
stMCIBuffer.pBufList = &pAData->aMixBuffers;
|
||||
|
||||
ulRC = mciSendCommand( pAData->usDeviceId, MCI_BUFFER,
|
||||
MCI_WAIT | MCI_ALLOCATE_MEMORY, &stMCIBuffer, 0 );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
{
|
||||
OS2_CloseDevice( this );
|
||||
return _MCIError( "MCI_BUFFER", ulRC );
|
||||
}
|
||||
pAData->cMixBuffers = stMCIBuffer.ulNumBuffers;
|
||||
this->spec.size = stMCIBuffer.ulBufferSize;
|
||||
|
||||
// Fill all device buffers with data
|
||||
|
||||
for( ulIdx = 0; ulIdx < stMCIBuffer.ulNumBuffers; ulIdx++ )
|
||||
{
|
||||
pAData->aMixBuffers[ulIdx].ulFlags = 0;
|
||||
pAData->aMixBuffers[ulIdx].ulBufferLength = stMCIBuffer.ulBufferSize;
|
||||
pAData->aMixBuffers[ulIdx].ulUserParm = (ULONG)pAData;
|
||||
|
||||
memset( ((PMCI_MIX_BUFFER)stMCIBuffer.pBufList)[ulIdx].pBuffer,
|
||||
this->spec.silence, stMCIBuffer.ulBufferSize );
|
||||
}
|
||||
|
||||
// Write buffers to kick off the amp mixer
|
||||
// pAData->ulQueuedBuf = 1;//stMCIBuffer.ulNumBuffers;
|
||||
ulRC = pAData->stMCIMixSetup.pmixWrite( pAData->stMCIMixSetup.ulMixHandle,
|
||||
&pAData->aMixBuffers,
|
||||
1 );//stMCIBuffer.ulNumBuffers );
|
||||
if ( ulRC != MCIERR_SUCCESS )
|
||||
{
|
||||
_mixIOError( "pmixWrite", ulRC );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int OS2_Init(SDL_AudioDriverImpl * impl)
|
||||
{
|
||||
/* Set the function pointers */
|
||||
impl->DetectDevices = OS2_DetectDevices;
|
||||
impl->OpenDevice = OS2_OpenDevice;
|
||||
impl->PlayDevice = OS2_PlayDevice;
|
||||
impl->WaitDevice = OS2_WaitDevice;
|
||||
impl->WaitDone = OS2_WaitDone;
|
||||
impl->GetDeviceBuf = OS2_GetDeviceBuf;
|
||||
impl->CloseDevice = OS2_CloseDevice;
|
||||
|
||||
// [Digi]: SDL 2.0 does not support recording yet (2016-02-24).
|
||||
// impl->HasCaptureSupport = SDL_TRUE;
|
||||
|
||||
return 1; /* this audio target is available. */
|
||||
}
|
||||
|
||||
|
||||
AudioBootStrap OS2AUDIO_bootstrap = { "MMOS2", "OS/2 DART", OS2_Init, 0 };
|
||||
|
||||
#endif /* SDL_AUDIO_DRIVER_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_os2mm_h
|
||||
#define _SDL_os2mm_h
|
||||
|
||||
#include "../SDL_sysaudio.h"
|
||||
|
||||
#define INCL_OS2MM
|
||||
#define INCL_PM
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#include <os2me.h>
|
||||
|
||||
/* Hidden "this" pointer for the audio functions */
|
||||
#define _THIS SDL_AudioDevice *this
|
||||
|
||||
#define NUM_BUFFERS 3
|
||||
|
||||
typedef struct SDL_PrivateAudioData
|
||||
{
|
||||
USHORT usDeviceId;
|
||||
MCI_MIXSETUP_PARMS stMCIMixSetup;
|
||||
HEV hevBuf;
|
||||
ULONG ulNextBuf;
|
||||
ULONG cMixBuffers;
|
||||
MCI_MIX_BUFFER aMixBuffers[NUM_BUFFERS];
|
||||
// ULONG ulQueuedBuf;
|
||||
} SDL_PrivateAudioData, *PSDL_PrivateAudioData;
|
||||
|
||||
#endif /* _SDL_os2mm_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if defined(__OS2__)
|
||||
|
||||
#include "core/os2/geniconv/geniconv.h"
|
||||
|
||||
// SDL_OS2Quit() will be called from SDL_QuitSubSystem().
|
||||
|
||||
void SDL_OS2Quit()
|
||||
{
|
||||
// Unload DLL used for iconv. We can do it at any time and use iconv again -
|
||||
// dynamic library will be loaded on first call iconv_open() (see geniconv).
|
||||
libiconv_clean();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef _SDL_os2_h
|
||||
#define _SDL_os2_h
|
||||
|
||||
#include "SDL_log.h"
|
||||
#include "SDL_stdinc.h"
|
||||
#include ".\src\core\os2\geniconv\geniconv.h"
|
||||
|
||||
#if OS2DEBUG==SDLOUTPUT
|
||||
|
||||
# define debug(s,...) SDL_LogDebug( SDL_LOG_CATEGORY_APPLICATION, \
|
||||
__func__"(): "##s, ##__VA_ARGS__ )
|
||||
|
||||
#elif defined(OS2DEBUG)
|
||||
|
||||
# define debug(s,...) printf( __func__"(): "##s"\n", ##__VA_ARGS__ )
|
||||
|
||||
#else
|
||||
|
||||
# define debug(s,...)
|
||||
|
||||
#endif // OS2DEBUG
|
||||
|
||||
|
||||
// StrUTF8New() - geniconv\sys2utf8.c.
|
||||
#define OS2_SysToUTF8(S) StrUTF8New( 1, S, SDL_strlen( S ) + 1 )
|
||||
#define OS2_UTF8ToSys(S) StrUTF8New( 0, (char *)(S), SDL_strlen( S ) + 1 )
|
||||
|
||||
// SDL_OS2Quit() will be called from SDL_QuitSubSystem().
|
||||
void SDL_OS2Quit();
|
||||
|
||||
#endif // _SDL_os2_h
|
|
@ -0,0 +1,143 @@
|
|||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#define INCL_DOSMODULEMGR /* Module Manager values */
|
||||
#define INCL_DOSERRORS /* Error values */
|
||||
#include <os2.h>
|
||||
#include <iconv.h>
|
||||
|
||||
//#define DEBUG
|
||||
|
||||
#ifdef DEBUG
|
||||
# include <stdio.h>
|
||||
# define debug(s,...) printf(__func__"(): "##s"\n" ,##__VA_ARGS__)
|
||||
#else
|
||||
# define debug(s,...)
|
||||
#endif
|
||||
|
||||
// Exports from os2iconv.c.
|
||||
extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode);
|
||||
extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft, char* * outbuf,
|
||||
size_t *outbytesleft);
|
||||
extern int _System os2_iconv_close(iconv_t cd);
|
||||
|
||||
// Functions pointers types.
|
||||
typedef iconv_t _System (*FNICONV_OPEN)(const char* tocode, const char* fromcode);
|
||||
typedef size_t _System (*FNICONV)(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft, char* * outbuf,
|
||||
size_t *outbytesleft);
|
||||
typedef int _System (*FNICONV_CLOSE)(iconv_t cd);
|
||||
|
||||
// Used DLL module handle.
|
||||
static HMODULE hmIconv = NULLHANDLE;
|
||||
// Functions pointers.
|
||||
static FNICONV_OPEN fn_iconv_open = NULL;
|
||||
static FNICONV fn_iconv = NULL;
|
||||
static FNICONV_CLOSE fn_iconv_close = NULL;
|
||||
|
||||
|
||||
static BOOL _loadDLL(PSZ pszName, PSZ pszIconvOpen, PSZ pszIconv,
|
||||
PSZ pszIconvClose)
|
||||
{
|
||||
ULONG ulRC;
|
||||
CHAR acError[256];
|
||||
|
||||
ulRC = DosLoadModule( &acError, sizeof(acError), pszName, &hmIconv );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DLL not loaded: %s", &acError );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconvOpen, (PFN *)&fn_iconv_open );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconvOpen, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconv, (PFN *)&fn_iconv );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconv, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
ulRC = DosQueryProcAddr( hmIconv, 0, pszIconvClose, (PFN *)&fn_iconv_close );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Error: cannot find entry %s in %s", pszIconvClose, pszName );
|
||||
break;
|
||||
}
|
||||
|
||||
debug( "DLL %s used", pszName );
|
||||
return TRUE;
|
||||
}
|
||||
while( FALSE );
|
||||
|
||||
DosFreeModule( hmIconv );
|
||||
hmIconv = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void _init()
|
||||
{
|
||||
if ( fn_iconv_open != NULL )
|
||||
// Already was initialized.
|
||||
return;
|
||||
|
||||
// Try to load kiconv.dll, iconv2.dll or iconv.dll.
|
||||
if ( !_loadDLL( "KICONV", "_libiconv_open", "_libiconv", "_libiconv_close" )
|
||||
&& !_loadDLL( "ICONV2", "_libiconv_open", "_libiconv", "_libiconv_close" )
|
||||
&& !_loadDLL( "ICONV", "_iconv_open", "_iconv", "_iconv_close" ) )
|
||||
{
|
||||
// No one DLL was loaded - use OS/2 conversion objects API.
|
||||
|
||||
debug( "Uni*() API used" );
|
||||
fn_iconv_open = os2_iconv_open;
|
||||
fn_iconv = os2_iconv;
|
||||
fn_iconv_close = os2_iconv_close;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Public routines.
|
||||
// ----------------
|
||||
|
||||
// Non-standard function for iconv to unload the used dynamic library.
|
||||
void libiconv_clean()
|
||||
{
|
||||
if ( hmIconv != NULLHANDLE )
|
||||
{
|
||||
DosFreeModule( hmIconv );
|
||||
hmIconv = NULLHANDLE;
|
||||
|
||||
fn_iconv_open = NULL;
|
||||
fn_iconv = NULL;
|
||||
fn_iconv_close = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_t libiconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
_init();
|
||||
return fn_iconv_open( tocode, fromcode );
|
||||
}
|
||||
|
||||
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
return fn_iconv( cd, inbuf, inbytesleft, outbuf, outbytesleft );
|
||||
}
|
||||
|
||||
int libiconv_close(iconv_t cd)
|
||||
{
|
||||
return fn_iconv_close( cd );
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Universal iconv implementation for OS/2.
|
||||
|
||||
Andrey Vasilkin, 2016.
|
||||
*/
|
||||
|
||||
#ifndef GENICONV_H
|
||||
#define GENICONV_H
|
||||
|
||||
#include <iconv.h>
|
||||
|
||||
#ifdef iconv_open
|
||||
#undef iconv_open
|
||||
#endif
|
||||
#define iconv_open libiconv_open
|
||||
|
||||
#ifdef iconv
|
||||
#undef iconv
|
||||
#endif
|
||||
#define iconv libiconv
|
||||
|
||||
#ifdef iconv_close
|
||||
#undef iconv_close
|
||||
#endif
|
||||
#define iconv_close libiconv_close
|
||||
|
||||
#define iconv_clean libiconv_clean
|
||||
|
||||
// Non-standard function for iconv to unload the used dynamic library.
|
||||
void libiconv_clean();
|
||||
|
||||
iconv_t libiconv_open(const char* tocode, const char* fromcode);
|
||||
size_t libiconv(iconv_t cd, char* * inbuf, size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft);
|
||||
int libiconv_close(iconv_t cd);
|
||||
|
||||
// System codepage <-> UTF-8.
|
||||
|
||||
// StrUTF8()
|
||||
// Coverts string from system cp. to UTF-8 (fToUTF8 is not 0) or from UTF-8 to
|
||||
// the system cp. (fToUTF8 is 0). Converted ASCIIZ string will be placed at the
|
||||
// buffer pcDst, up to cbDst - 1 (for sys->utf8) or 2 (for utf8->sys) bytes.
|
||||
// Returns the number of bytes written into pcDst, not counting the terminating
|
||||
// 0 byte(s) or -1 on error.
|
||||
int StrUTF8(int fToUTF8, char *pcDst, int cbDst, char *pcSrc, int cbSrc);
|
||||
|
||||
// StrUTF8New()
|
||||
// Coverts string from system cp. to UTF-8 (fToUTF8 is not 0) or from UTF-8 to
|
||||
// the system cp. (fToUTF8 is 0). Memory for the new string is obtained by
|
||||
// using libc malloc().
|
||||
// Returns converted string, terminating two bytes 0 is appended to the result.
|
||||
// Returns null on error.
|
||||
char *StrUTF8New(int fToUTF8, char *pcStr, int cbStr);
|
||||
|
||||
// StrUTF8Free()
|
||||
// Deallocates the memory block located by StrUTF8New() (just libc free()).
|
||||
void StrUTF8Free(char *pszStr);
|
||||
|
||||
#endif // GENICONV_H
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef ICONV_H_ /* minimal iconv.h header based on public knowledge */
|
||||
#define ICONV_H_
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
#include <errno.h>
|
||||
|
||||
typedef void *iconv_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern iconv_t iconv_open(const char *, const char *);
|
||||
extern size_t iconv(iconv_t, char **, size_t *, char **, size_t *);
|
||||
extern int iconv_close(iconv_t);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ICONV_H_ */
|
|
@ -0,0 +1,37 @@
|
|||
#
|
||||
# Universal iconv implementation for OS/2.
|
||||
#
|
||||
# OpenWatcom makefile to build a library that uses kiconv.dll / iconv2.dll /
|
||||
# iconv.dll or OS/2 Uni*() API.
|
||||
#
|
||||
# Andrey Vasilkin, 2016.
|
||||
#
|
||||
|
||||
LIBFILE = geniconv.lib
|
||||
|
||||
all: $(LIBFILE) test.exe .symbolic
|
||||
|
||||
CFLAGS = -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h -I. -bt=os2 -q -d0 -w2
|
||||
|
||||
SRCS = geniconv.c os2cp.c os2iconv.c
|
||||
SRCS+= sys2utf8.c
|
||||
|
||||
OBJS = $(SRCS:.c=.obj)
|
||||
|
||||
LIBS = libuls.lib libconv.lib $(LIBFILE)
|
||||
|
||||
test.exe: $(LIBFILE) test.obj
|
||||
wlink op quiet system os2v2 file test.obj lib {$(LIBS)} name $*
|
||||
|
||||
$(LIBFILE): $(OBJS)
|
||||
@if exist $@ rm $@
|
||||
@for %f in ($(OBJS)) do wlib -q -b $* +%f
|
||||
|
||||
.c.obj:
|
||||
wcc386 $(CFLAGS) -fo=$^@ $<
|
||||
|
||||
clean: .SYMBOLIC
|
||||
@if exist *.obj rm *.obj
|
||||
@if exist *.err rm *.err
|
||||
@if exist $(LIBFILE) rm $(LIBFILE)
|
||||
@if exist test.exe rm test.exe
|
|
@ -0,0 +1,383 @@
|
|||
#include "os2cp.h"
|
||||
#define INCL_DOSNLS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef struct _CP2NAME {
|
||||
ULONG ulCode;
|
||||
PSZ pszName;
|
||||
} CP2NAME;
|
||||
|
||||
typedef struct _NAME2CP {
|
||||
PSZ pszName;
|
||||
ULONG ulCode;
|
||||
} NAME2CP;
|
||||
|
||||
static CP2NAME aCP2Name[] =
|
||||
{
|
||||
{367, "ANSI_X3.4-1968"},
|
||||
{813, "ECMA-118"},
|
||||
{819, "CP819"},
|
||||
{850, "850"},
|
||||
{862, "862"},
|
||||
{866, "866"},
|
||||
{874, "ISO-IR-166"},
|
||||
{878, "KOI8-R"},
|
||||
{896, "JISX0201-1976"},
|
||||
{901, "ISO-8859-13"},
|
||||
{912, "ISO-8859-2"},
|
||||
{913, "ISO-8859-3"},
|
||||
{914, "ISO-8859-4"},
|
||||
{915, "CYRILLIC"},
|
||||
{920, "ISO-8859-9"},
|
||||
{923, "ISO-8859-15"},
|
||||
{943, "MS_KANJI"},
|
||||
{954, "EUC-JP"},
|
||||
{964, "EUC-TW"},
|
||||
{970, "EUC-KR"},
|
||||
{1051, "HP-ROMAN8"},
|
||||
{1089, "ARABIC"},
|
||||
{1129, "VISCII"},
|
||||
{1168, "KOI8-U"},
|
||||
{1200, "ISO-10646-UCS-2"},
|
||||
{1202, "UTF-16LE"},
|
||||
{1204, "UCS-2BE"},
|
||||
{1208, "UTF-8"},
|
||||
{1232, "UTF-32BE"},
|
||||
{1234, "UTF-32LE"},
|
||||
{1236, "ISO-10646-UCS-4"},
|
||||
{1250, "CP1250"},
|
||||
{1251, "CP1251"},
|
||||
{1252, "CP1252"},
|
||||
{1253, "CP1253"},
|
||||
{1254, "CP1254"},
|
||||
{1255, "CP1255"},
|
||||
{1256, "CP1256"},
|
||||
{1257, "CP1257"},
|
||||
{1275, "MAC"},
|
||||
{1383, "CN-GB"},
|
||||
{1386, "GBK"},
|
||||
{1392, "GB18030"},
|
||||
{62210, "HEBREW"}
|
||||
};
|
||||
|
||||
static NAME2CP aName2CP[] =
|
||||
{
|
||||
{"850", 850},
|
||||
{"862", 862},
|
||||
{"866", 866},
|
||||
{"ANSI_X3.4-1968", 367},
|
||||
{"ANSI_X3.4-1986", 367},
|
||||
{"ARABIC", 1089},
|
||||
{"ASCII", 367},
|
||||
{"ASMO-708", 1089},
|
||||
{"CN-GB", 1383},
|
||||
{"CP1250", 1250},
|
||||
{"CP1251", 1251},
|
||||
{"CP1252", 1252},
|
||||
{"CP1253", 1253},
|
||||
{"CP1254", 1254},
|
||||
{"CP1255", 1255},
|
||||
{"CP1256", 1256},
|
||||
{"CP1257", 1257},
|
||||
{"CP367", 367},
|
||||
{"CP819", 819},
|
||||
{"CP850", 850},
|
||||
{"CP862", 862},
|
||||
{"CP866", 866},
|
||||
{"CP936", 1386},
|
||||
{"CSASCII", 367},
|
||||
{"CSEUCKR", 970},
|
||||
{"CSEUCPKDFMTJAPANESE", 954},
|
||||
{"CSEUCTW", 964},
|
||||
{"CSGB2312", 1383},
|
||||
{"CSHALFWIDTHKATAKANA", 896},
|
||||
{"CSHPROMAN8", 1051},
|
||||
{"CSIBM866", 866},
|
||||
{"CSISOLATIN1", 819},
|
||||
{"CSISOLATIN2", 912},
|
||||
{"CSISOLATIN3", 913},
|
||||
{"CSISOLATIN4", 914},
|
||||
{"CSISOLATIN5", 920},
|
||||
{"CSISOLATINARABIC", 1089},
|
||||
{"CSISOLATINCYRILLIC", 915},
|
||||
{"CSISOLATINGREEK", 813},
|
||||
{"CSISOLATINHEBREW", 62210},
|
||||
{"CSKOI8R", 878},
|
||||
{"CSKSC56011987", 970},
|
||||
{"CSMACINTOSH", 1275},
|
||||
{"CSPC850MULTILINGUAL", 850},
|
||||
{"CSPC862LATINHEBREW", 862},
|
||||
{"CSSHIFTJIS", 943},
|
||||
{"CSUCS4", 1236},
|
||||
{"CSUNICODE", 1200},
|
||||
{"CSUNICODE11", 1204},
|
||||
{"CSVISCII", 1129},
|
||||
{"CYRILLIC", 915},
|
||||
{"ECMA-114", 1089},
|
||||
{"ECMA-118", 813},
|
||||
{"ELOT_928", 813},
|
||||
{"EUC-CN", 1383},
|
||||
{"EUC-JP", 954},
|
||||
{"EUC-KR", 970},
|
||||
{"EUC-TW", 964},
|
||||
{"EUCCN", 1383},
|
||||
{"EUCJP", 954},
|
||||
{"EUCKR", 970},
|
||||
{"EUCTW", 964},
|
||||
{"EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE", 954},
|
||||
{"GB18030", 1392},
|
||||
{"GB2312", 1383},
|
||||
{"GBK", 1386},
|
||||
{"GREEK", 813},
|
||||
{"GREEK8", 813},
|
||||
{"HEBREW", 62210},
|
||||
{"HP-ROMAN8", 1051},
|
||||
{"IBM367", 367},
|
||||
{"IBM819", 819},
|
||||
{"IBM850", 850},
|
||||
{"IBM862", 862},
|
||||
{"IBM866", 866},
|
||||
{"ISO-10646-UCS-2", 1200},
|
||||
{"ISO-10646-UCS-4", 1236},
|
||||
{"ISO-8859-1", 819},
|
||||
{"ISO-8859-13", 901},
|
||||
{"ISO-8859-15", 923},
|
||||
{"ISO-8859-2", 912},
|
||||
{"ISO-8859-3", 913},
|
||||
{"ISO-8859-4", 914},
|
||||
{"ISO-8859-5", 915},
|
||||
{"ISO-8859-6", 1089},
|
||||
{"ISO-8859-7", 813},
|
||||
{"ISO-8859-8", 62210},
|
||||
{"ISO-8859-9", 920},
|
||||
{"ISO-IR-100", 819},
|
||||
{"ISO-IR-101", 912},
|
||||
{"ISO-IR-109", 913},
|
||||
{"ISO-IR-110", 914},
|
||||
{"ISO-IR-126", 813},
|
||||
{"ISO-IR-127", 1089},
|
||||
{"ISO-IR-138", 62210},
|
||||
{"ISO-IR-144", 915},
|
||||
{"ISO-IR-148", 920},
|
||||
{"ISO-IR-149", 970},
|
||||
{"ISO-IR-166", 874},
|
||||
{"ISO-IR-179", 901},
|
||||
{"ISO-IR-203", 923},
|
||||
{"ISO-IR-6", 367},
|
||||
{"ISO646-US", 367},
|
||||
{"ISO8859-1", 819},
|
||||
{"ISO8859-13", 901},
|
||||
{"ISO8859-15", 923},
|
||||
{"ISO8859-2", 912},
|
||||
{"ISO8859-3", 913},
|
||||
{"ISO8859-4", 914},
|
||||
{"ISO8859-5", 915},
|
||||
{"ISO8859-6", 1089},
|
||||
{"ISO8859-7", 813},
|
||||
{"ISO8859-8", 62210},
|
||||
{"ISO8859-9", 920},
|
||||
{"ISO_646.IRV:1991", 367},
|
||||
{"ISO_8859-1", 819},
|
||||
{"ISO_8859-13", 901},
|
||||
{"ISO_8859-15", 923},
|
||||
{"ISO_8859-15:1998", 923},
|
||||
{"ISO_8859-1:1987", 819},
|
||||
{"ISO_8859-2", 912},
|
||||
{"ISO_8859-2:1987", 912},
|
||||
{"ISO_8859-3", 913},
|
||||
{"ISO_8859-3:1988", 913},
|
||||
{"ISO_8859-4", 914},
|
||||
{"ISO_8859-4:1988", 914},
|
||||
{"ISO_8859-5", 915},
|
||||
{"ISO_8859-5:1988", 915},
|
||||
{"ISO_8859-6", 1089},
|
||||
{"ISO_8859-6:1987", 1089},
|
||||
{"ISO_8859-7", 813},
|
||||
{"ISO_8859-7:1987", 813},
|
||||
{"ISO_8859-7:2003", 813},
|
||||
{"ISO_8859-8", 62210},
|
||||
{"ISO_8859-8:1988", 62210},
|
||||
{"ISO_8859-9", 920},
|
||||
{"ISO_8859-9:1989", 920},
|
||||
{"JISX0201-1976", 896},
|
||||
{"JIS_X0201", 896},
|
||||
{"KOI8-R", 878},
|
||||
{"KOI8-U", 1168},
|
||||
{"KOREAN", 970},
|
||||
{"KSC_5601", 970},
|
||||
{"KS_C_5601-1987", 970},
|
||||
{"KS_C_5601-1989", 970},
|
||||
{"L1", 819},
|
||||
{"L2", 912},
|
||||
{"L3", 913},
|
||||
{"L4", 914},
|
||||
{"L5", 920},
|
||||
{"L7", 901},
|
||||
{"LATIN-9", 923},
|
||||
{"LATIN1", 819},
|
||||
{"LATIN2", 912},
|
||||
{"LATIN3", 913},
|
||||
{"LATIN4", 914},
|
||||
{"LATIN5", 920},
|
||||
{"LATIN7", 901},
|
||||
{"MAC", 1275},
|
||||
{"MACINTOSH", 1275},
|
||||
{"MACROMAN", 1275},
|
||||
{"MS-ANSI", 1252},
|
||||
{"MS-ARAB", 1256},
|
||||
{"MS-CYRL", 1251},
|
||||
{"MS-EE", 1250},
|
||||
{"MS-GREEK", 1253},
|
||||
{"MS-HEBR", 1255},
|
||||
{"MS-TURK", 1254},
|
||||
{"MS936", 1386},
|
||||
{"MS_KANJI", 943},
|
||||
{"R8", 1051},
|
||||
{"ROMAN8", 1051},
|
||||
{"SHIFT-JIS", 943},
|
||||
{"SHIFT_JIS", 943},
|
||||
{"SJIS", 943},
|
||||
{"TIS-620", 874},
|
||||
{"TIS620", 874},
|
||||
{"TIS620-0", 874},
|
||||
{"TIS620.2529-1", 874},
|
||||
{"TIS620.2533-0", 874},
|
||||
{"TIS620.2533-1", 874},
|
||||
{"UCS-2", 1200},
|
||||
{"UCS-2BE", 1204},
|
||||
{"UCS-4", 1236},
|
||||
{"UNICODE-1-1", 1204},
|
||||
{"UNICODEBIG", 1204},
|
||||
{"US", 367},
|
||||
{"US-ASCII", 367},
|
||||
{"UTF-16", 1204},
|
||||
{"UTF-16BE", 1200},
|
||||
{"UTF-16LE", 1202},
|
||||
{"UTF-32", 1236},
|
||||
{"UTF-32BE", 1232},
|
||||
{"UTF-32LE", 1234},
|
||||
{"UTF-8", 1208},
|
||||
{"VISCII", 1129},
|
||||
{"VISCII1.1-1", 1129},
|
||||
{"WINBALTRIM", 1257},
|
||||
{"WINDOWS-1250", 1250},
|
||||
{"WINDOWS-1251", 1251},
|
||||
{"WINDOWS-1252", 1252},
|
||||
{"WINDOWS-1253", 1253},
|
||||
{"WINDOWS-1254", 1254},
|
||||
{"WINDOWS-1255", 1255},
|
||||
{"WINDOWS-1256", 1256},
|
||||
{"WINDOWS-1257", 1257},
|
||||
{"WINDOWS-936", 1386},
|
||||
{"X0201", 896}
|
||||
};
|
||||
|
||||
char * os2cpToName(unsigned long cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = ( sizeof(aCP2Name) / sizeof(struct _CP2NAME) ) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
|
||||
if ( cp == SYSTEM_CP )
|
||||
{
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
|
||||
if ( DosQueryCp( sizeof(aulCP), &aulCP, &cCP ) != NO_ERROR )
|
||||
return NULL;
|
||||
|
||||
cp = aulCP[0];
|
||||
}
|
||||
|
||||
if ( ( aCP2Name[0].ulCode > cp ) || ( aCP2Name[ulHi].ulCode < cp ) )
|
||||
return NULL;
|
||||
|
||||
if ( aCP2Name[0].ulCode == cp )
|
||||
return aCP2Name[0].pszName;
|
||||
|
||||
if ( aCP2Name[ulHi].ulCode == cp )
|
||||
return aCP2Name[ulHi].pszName;
|
||||
|
||||
while( ( ulHi - ulLo ) > 1 )
|
||||
{
|
||||
ulNext = ( ulLo + ulHi ) / 2;
|
||||
|
||||
if ( aCP2Name[ulNext].ulCode < cp )
|
||||
ulLo = ulNext;
|
||||
else if ( aCP2Name[ulNext].ulCode > cp )
|
||||
ulHi = ulNext;
|
||||
else
|
||||
{
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lFound == -1 ? NULL : aCP2Name[lFound].pszName;
|
||||
}
|
||||
|
||||
unsigned long os2cpFromName(char *cp)
|
||||
{
|
||||
ULONG ulLo = 0;
|
||||
ULONG ulHi = ( sizeof(aName2CP) / sizeof(struct _NAME2CP) ) - 1;
|
||||
ULONG ulNext;
|
||||
LONG lFound = -1;
|
||||
LONG lCmp;
|
||||
PCHAR pcEnd;
|
||||
CHAR acBuf[64];
|
||||
|
||||
if ( cp == NULL )
|
||||
{
|
||||
ULONG aulCP[3];
|
||||
ULONG cCP;
|
||||
|
||||
return DosQueryCp( sizeof(aulCP), &aulCP, &cCP ) != NO_ERROR ? 0 : aulCP[0];
|
||||
}
|
||||
|
||||
while( isspace( *cp ) ) cp++;
|
||||
pcEnd = strchr( cp, ' ' );
|
||||
if ( pcEnd == NULL )
|
||||
pcEnd = strchr( cp, '\0' );
|
||||
|
||||
ulNext = pcEnd - cp;
|
||||
if ( ulNext >= sizeof(acBuf) )
|
||||
return 0;
|
||||
|
||||
memcpy( &acBuf, cp, ulNext );
|
||||
acBuf[ulNext] = '\0';
|
||||
strupr( &acBuf );
|
||||
|
||||
lCmp = strcmp( aName2CP[0].pszName, &acBuf );
|
||||
if ( lCmp > 0 )
|
||||
return 0;
|
||||
else if ( lCmp == 0 )
|
||||
return aName2CP[0].ulCode;
|
||||
|
||||
lCmp = strcmp( aName2CP[ulHi].pszName, &acBuf );
|
||||
if ( lCmp < 0 )
|
||||
return 0;
|
||||
else if ( lCmp == 0 )
|
||||
return aName2CP[ulHi].ulCode;
|
||||
|
||||
while( ( ulHi - ulLo ) > 1 )
|
||||
{
|
||||
ulNext = ( ulLo + ulHi ) / 2;
|
||||
|
||||
lCmp = strcmp( aName2CP[ulNext].pszName, &acBuf );
|
||||
if ( lCmp < 0 )
|
||||
ulLo = ulNext;
|
||||
else if ( lCmp > 0 )
|
||||
ulHi = ulNext;
|
||||
else
|
||||
{
|
||||
lFound = ulNext;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lFound == -1 ? 0 : aName2CP[lFound].ulCode;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef OS2CP_H
|
||||
#define OS2CP_H 1
|
||||
|
||||
#define SYSTEM_CP 0
|
||||
|
||||
char * os2cpToName(unsigned long cp);
|
||||
unsigned long os2cpFromName(char *cp);
|
||||
|
||||
#endif // OS2CP_H
|
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Implementation iconv via OS/2 conversion objects API.
|
||||
|
||||
Andrey Vasilkin.
|
||||
*/
|
||||
|
||||
#define ICONV_THREAD_SAFE 1
|
||||
//#undef ICONV_THREAD_SAFE
|
||||
|
||||
#include "iconv.h"
|
||||
#include <uconv.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
#endif
|
||||
#include "os2cp.h"
|
||||
|
||||
#define MAX_CP_NAME_LEN 64
|
||||
|
||||
typedef struct iuconv_obj {
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int buf_len;
|
||||
UniChar *buf;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
HMTX hMtx;
|
||||
#endif
|
||||
} iuconv_obj;
|
||||
|
||||
|
||||
static int _createUconvObj(const char *code, UconvObject *uobj)
|
||||
{
|
||||
UniChar uc_code[MAX_CP_NAME_LEN];
|
||||
int i;
|
||||
const char *ch = code;
|
||||
|
||||
if ( code == NULL )
|
||||
uc_code[0] = 0;
|
||||
else
|
||||
{
|
||||
for( i = 0; i < MAX_CP_NAME_LEN; i++ )
|
||||
{
|
||||
uc_code[i] = (unsigned short)*ch;
|
||||
if ( !(*ch) ) break;
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
return UniCreateUconvObject( &uc_code, uobj );
|
||||
}
|
||||
|
||||
static int uconv_open(const char *code, UconvObject *uobj)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ( !stricmp( code, "UTF-16" ) )
|
||||
{
|
||||
*uobj = NULL;
|
||||
return ULS_SUCCESS;
|
||||
}
|
||||
|
||||
rc = _createUconvObj( code, uobj );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
unsigned long cp = os2cpFromName( (char *)code );
|
||||
char cp_name[16];
|
||||
|
||||
if ( cp != 0 && _snprintf( &cp_name, sizeof(cp_name), "IBM-%u", cp ) > 0 )
|
||||
rc = _createUconvObj( &cp_name, uobj );
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
extern iconv_t _System os2_iconv_open(const char* tocode, const char* fromcode)
|
||||
{
|
||||
UconvObject uo_tocode;
|
||||
UconvObject uo_fromcode;
|
||||
int rc;
|
||||
iuconv_obj *iuobj;
|
||||
|
||||
if ( tocode == NULL )
|
||||
tocode = "";
|
||||
|
||||
if ( fromcode == NULL )
|
||||
fromcode = "";
|
||||
|
||||
if ( stricmp(tocode, fromcode) != 0 )
|
||||
{
|
||||
rc = uconv_open( fromcode, &uo_fromcode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
|
||||
rc = uconv_open( tocode, &uo_tocode );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
UniFreeUconvObject( uo_fromcode );
|
||||
errno = EINVAL;
|
||||
return (iconv_t)(-1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uo_tocode = NULL;
|
||||
uo_fromcode = NULL;
|
||||
}
|
||||
|
||||
iuobj = malloc( sizeof(iuconv_obj) );
|
||||
iuobj->uo_tocode = uo_tocode;
|
||||
iuobj->uo_fromcode = uo_fromcode;
|
||||
iuobj->buf_len = 0;
|
||||
iuobj->buf = NULL;
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCreateMutexSem( NULL, &iuobj->hMtx, 0, FALSE );
|
||||
#endif
|
||||
|
||||
return iuobj;
|
||||
}
|
||||
|
||||
extern size_t _System os2_iconv(iconv_t cd, char* * inbuf,
|
||||
size_t *inbytesleft,
|
||||
char* * outbuf, size_t *outbytesleft)
|
||||
{
|
||||
UconvObject uo_tocode = ((iuconv_obj *)(cd))->uo_tocode;
|
||||
UconvObject uo_fromcode = ((iuconv_obj *)(cd))->uo_fromcode;
|
||||
size_t nonIdenticalConv = 0;
|
||||
UniChar *uc_buf;
|
||||
size_t uc_buf_len;
|
||||
UniChar **uc_str;
|
||||
size_t *uc_str_len;
|
||||
int rc;
|
||||
size_t ret = (size_t)(-1);
|
||||
|
||||
if ( uo_tocode == NULL && uo_fromcode == NULL )
|
||||
{
|
||||
uc_buf_len = min( *inbytesleft, *outbytesleft );
|
||||
memcpy( *outbuf, *inbuf, uc_buf_len );
|
||||
*inbytesleft -= uc_buf_len;
|
||||
*outbytesleft -= uc_buf_len;
|
||||
outbuf += uc_buf_len;
|
||||
inbuf += uc_buf_len;
|
||||
return uc_buf_len;
|
||||
}
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosRequestMutexSem( ((iuconv_obj *)(cd))->hMtx, SEM_INDEFINITE_WAIT );
|
||||
#endif
|
||||
|
||||
if ( uo_tocode && uo_fromcode &&
|
||||
(( ((iuconv_obj *)(cd))->buf_len >> 1 ) < (*inbytesleft)) )
|
||||
{
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
((iuconv_obj *)(cd))->buf_len = *inbytesleft << 1;
|
||||
((iuconv_obj *)(cd))->buf = (UniChar *)malloc( ((iuconv_obj *)(cd))->buf_len );
|
||||
}
|
||||
|
||||
if ( uo_fromcode )
|
||||
{
|
||||
if ( uo_tocode )
|
||||
{
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len;
|
||||
uc_str = &uc_buf;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)outbuf;
|
||||
uc_buf_len = *outbytesleft;
|
||||
}
|
||||
uc_buf_len = uc_buf_len >> 1;
|
||||
uc_str_len = &uc_buf_len;
|
||||
rc = UniUconvToUcs( uo_fromcode, (void **)inbuf, inbytesleft,
|
||||
uc_str, uc_str_len, &nonIdenticalConv );
|
||||
uc_buf_len = uc_buf_len << 1;
|
||||
if ( !uo_tocode )
|
||||
*outbytesleft = uc_buf_len;
|
||||
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
errno = EILSEQ;
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *inbytesleft && !*uc_str_len )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !uo_tocode )
|
||||
return nonIdenticalConv;
|
||||
|
||||
uc_buf = ((iuconv_obj *)(cd))->buf;
|
||||
uc_buf_len = ((iuconv_obj *)(cd))->buf_len - uc_buf_len;
|
||||
uc_str = &uc_buf;
|
||||
uc_str_len = &uc_buf_len;
|
||||
}
|
||||
else {
|
||||
uc_str = (UniChar **)inbuf;
|
||||
uc_str_len = inbytesleft;
|
||||
}
|
||||
|
||||
*uc_str_len = *uc_str_len>>1;
|
||||
rc = UniUconvFromUcs( uo_tocode, uc_str, uc_str_len, (void **)outbuf,
|
||||
outbytesleft, &nonIdenticalConv );
|
||||
if ( rc != ULS_SUCCESS )
|
||||
{
|
||||
switch ( rc )
|
||||
{
|
||||
case ULS_BUFFERFULL:
|
||||
errno = E2BIG;
|
||||
break;
|
||||
case ULS_ILLEGALSEQUENCE:
|
||||
errno = EILSEQ;
|
||||
break;
|
||||
case ULS_INVALID:
|
||||
errno = EINVAL;
|
||||
break;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
if ( *uc_str_len && !*outbytesleft )
|
||||
{
|
||||
errno = E2BIG;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = nonIdenticalConv;
|
||||
|
||||
done:
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosReleaseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
extern int _System os2_iconv_close(iconv_t cd)
|
||||
{
|
||||
if ( !cd )
|
||||
return 0;
|
||||
|
||||
#ifdef ICONV_THREAD_SAFE
|
||||
DosCloseMutexSem( ((iuconv_obj *)(cd))->hMtx );
|
||||
#endif
|
||||
if ( ((iuconv_obj *)(cd))->uo_tocode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_tocode );
|
||||
if ( ((iuconv_obj *)(cd))->uo_fromcode != NULL )
|
||||
UniFreeUconvObject( ((iuconv_obj *)(cd))->uo_fromcode );
|
||||
|
||||
if ( ( ((iuconv_obj *)(cd))->buf ) != NULL )
|
||||
free( ((iuconv_obj *)(cd))->buf );
|
||||
|
||||
free(cd);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
#include <iconv.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int StrUTF8(int fToUTF8, char *pcDst, int cbDst, char *pcSrc, int cbSrc)
|
||||
{
|
||||
size_t rc;
|
||||
char *pcDstStart = pcDst;
|
||||
iconv_t cd;
|
||||
char *pszToCP, *pszFromCP;
|
||||
int fError = 0;
|
||||
|
||||
if ( cbDst < 4 )
|
||||
return -1;
|
||||
|
||||
if ( fToUTF8 )
|
||||
{
|
||||
pszToCP = "UTF-8";
|
||||
pszFromCP = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
pszToCP = "";
|
||||
pszFromCP = "UTF-8";
|
||||
}
|
||||
|
||||
cd = iconv_open( pszToCP, pszFromCP );
|
||||
if ( cd == (iconv_t)-1 )
|
||||
return -1;
|
||||
|
||||
while( cbSrc > 0 )
|
||||
{
|
||||
rc = iconv( cd, &pcSrc, (size_t *)&cbSrc, &pcDst, (size_t *)&cbDst );
|
||||
if ( rc == (size_t)-1 )
|
||||
{
|
||||
if ( errno == EILSEQ )
|
||||
{
|
||||
// Try to skip invalid character.
|
||||
pcSrc++;
|
||||
cbSrc--;
|
||||
continue;
|
||||
}
|
||||
|
||||
fError = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iconv_close( cd );
|
||||
|
||||
// Write trailing ZERO (1 byte for UTF-8, 2 bytes for the system cp.).
|
||||
|
||||
if ( fToUTF8 )
|
||||
{
|
||||
if ( cbDst < 1 )
|
||||
{
|
||||
pcDst--;
|
||||
fError = 1; // The destination buffer overflow.
|
||||
}
|
||||
*pcDst = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( cbDst < 2 )
|
||||
{
|
||||
pcDst -= ( cbDst == 0 ) ? 2 : 1;
|
||||
fError = 1; // The destination buffer overflow.
|
||||
}
|
||||
*((short *)pcDst) = '\0';
|
||||
}
|
||||
|
||||
return fError ? -1 : ( pcDst - pcDstStart );
|
||||
}
|
||||
|
||||
char *StrUTF8New(int fToUTF8, char *pcStr, int cbStr)
|
||||
{
|
||||
int cbNewStr = ( ( cbStr > 4 ? cbStr : 4 ) + 1 ) * 2;
|
||||
char *pszNewStr = malloc( cbNewStr );
|
||||
|
||||
if ( pszNewStr == NULL )
|
||||
return NULL;
|
||||
|
||||
cbNewStr = StrUTF8( fToUTF8, pszNewStr, cbNewStr, pcStr, cbStr );
|
||||
if ( cbNewStr != -1 )
|
||||
{
|
||||
pcStr = realloc( pszNewStr, cbNewStr + ( fToUTF8 ? 1 : sizeof(short) ) );
|
||||
if ( pcStr != NULL )
|
||||
return pcStr;
|
||||
}
|
||||
|
||||
free( pszNewStr );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void StrUTF8Free(char *pszStr)
|
||||
{
|
||||
free( pszStr );
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <geniconv.h>
|
||||
|
||||
void main()
|
||||
{
|
||||
char acBuf[128];
|
||||
char *inbuf = "ôÅÓÔ - ÐÒÏ×ÅÒËÁ"; // KOI8-R string.
|
||||
size_t inbytesleft = strlen( inbuf );
|
||||
char *outbuf = &acBuf;
|
||||
size_t outbytesleft = sizeof( acBuf );
|
||||
iconv_t ic;
|
||||
|
||||
// KOI8 -> system cp.
|
||||
|
||||
ic = iconv_open( "", "KOI8-R" );
|
||||
if ( ic == (iconv_t)(-1) )
|
||||
{
|
||||
puts( "iconv_open() fail" );
|
||||
return;
|
||||
}
|
||||
|
||||
iconv( ic, &inbuf, &inbytesleft, &outbuf, &outbytesleft );
|
||||
printf( "KOI8-R to system cp.: %s\n", &acBuf );
|
||||
|
||||
iconv_close( ic );
|
||||
|
||||
// System cp. -> UTF-8 -> system cp.
|
||||
|
||||
// System cp. -> UTF-8 by StrUTF8New().
|
||||
inbuf = StrUTF8New( 1, &acBuf, strlen( &acBuf ) );
|
||||
|
||||
// UTF-8 -> system cp. by StrUTF8().
|
||||
if ( StrUTF8( 0, &acBuf, sizeof(acBuf), inbuf, strlen( inbuf ) ) == -1 )
|
||||
puts( "StrUTF8() failed" );
|
||||
else
|
||||
printf( "system cp. -> UTF-8 -> system cp.: %s\n", &acBuf );
|
||||
|
||||
free( inbuf );
|
||||
|
||||
// Unload used DLL.
|
||||
iconv_clean();
|
||||
|
||||
puts( "Done." );
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_OS2
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent filesystem routines */
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_filesystem.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <direct.h>
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
|
||||
char *
|
||||
SDL_GetBasePath(void)
|
||||
{
|
||||
PTIB tib;
|
||||
PPIB pib;
|
||||
ULONG ulRC = DosGetInfoBlocks( &tib, &pib );
|
||||
PCHAR pcEnd;
|
||||
ULONG cbResult;
|
||||
CHAR acBuf[_MAX_PATH];
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosGetInfoBlocks() failed, rc = %u", ulRC );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pcEnd = SDL_strrchr( pib->pib_pchcmd, '\\' );
|
||||
if ( pcEnd != NULL )
|
||||
pcEnd++;
|
||||
else
|
||||
{
|
||||
if ( pib->pib_pchcmd[1] == ':' )
|
||||
pcEnd = &pib->pib_pchcmd[2];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cbResult = pcEnd - pib->pib_pchcmd;
|
||||
SDL_memcpy( &acBuf, pib->pib_pchcmd, cbResult );
|
||||
acBuf[cbResult] = '\0';
|
||||
|
||||
return OS2_SysToUTF8( acBuf );
|
||||
}
|
||||
|
||||
char *
|
||||
SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
PSZ pszPath = SDL_getenv( "HOME" );
|
||||
CHAR acBuf[_MAX_PATH];
|
||||
LONG lPosApp, lPosOrg;
|
||||
PSZ pszApp, pszOrg = OS2_UTF8ToSys( org );
|
||||
|
||||
if ( pszOrg == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( pszPath == NULL )
|
||||
{
|
||||
pszPath = SDL_getenv( "ETC" );
|
||||
if ( pszPath == NULL )
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lPosApp = SDL_snprintf( &acBuf, sizeof(acBuf) - 1, "%s\\%s", pszPath, pszOrg );
|
||||
SDL_free( pszOrg );
|
||||
if ( lPosApp == -1 )
|
||||
return NULL;
|
||||
|
||||
mkdir( &acBuf );
|
||||
|
||||
pszApp = OS2_UTF8ToSys( app );
|
||||
if ( pszApp == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lPosOrg = SDL_snprintf( &acBuf[lPosApp], sizeof(acBuf) - lPosApp - 1, "\\%s",
|
||||
pszApp );
|
||||
SDL_free( pszApp );
|
||||
if ( lPosOrg == -1 )
|
||||
return NULL;
|
||||
|
||||
mkdir( &acBuf );
|
||||
*((PUSHORT)&acBuf[lPosApp + lPosOrg]) = (USHORT)'\0\\';
|
||||
|
||||
return OS2_SysToUTF8( &acBuf );
|
||||
}
|
||||
|
||||
#endif /* SDL_FILESYSTEM_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifdef SDL_LOADSO_OS2
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
/* System dependent library loading routines */
|
||||
|
||||
#include "SDL_loadso.h"
|
||||
#include ".\core\os2\SDL_os2.h"
|
||||
|
||||
#define INCL_DOSMODULEMGR
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
void *
|
||||
SDL_LoadObject(const char *sofile)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMODULE hModule;
|
||||
PSZ pszModName = OS2_UTF8ToSys( sofile );
|
||||
CHAR acError[256];
|
||||
|
||||
ulRC = DosLoadModule( &acError, sizeof(acError), pszModName, &hModule );
|
||||
SDL_free( pszModName );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
SDL_SetError( "Failed loading, module: %s", pszModName );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)hModule;
|
||||
}
|
||||
|
||||
void *
|
||||
SDL_LoadFunction(void *handle, const char *name)
|
||||
{
|
||||
ULONG ulRC;
|
||||
PFN pFN;
|
||||
|
||||
ulRC = DosQueryProcAddr( (HMODULE)handle, 0, name, &pFN );
|
||||
if ( ulRC )
|
||||
{
|
||||
SDL_SetError( "Failed loading, procedure: %s", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)pFN;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_UnloadObject(void *handle)
|
||||
{
|
||||
if ( handle != NULL )
|
||||
DosFreeModule( (HMODULE)handle );
|
||||
}
|
||||
|
||||
#endif /* SDL_LOADSO_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_THREAD_OS2
|
||||
|
||||
/* An implementation of mutexes for OS/2 */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "SDL_systhread_c.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
struct SDL_mutex
|
||||
{
|
||||
ULONG ulHandle;
|
||||
};
|
||||
|
||||
/* Create a mutex */
|
||||
SDL_mutex *
|
||||
SDL_CreateMutex(void)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMTX hMtx;
|
||||
|
||||
ulRC = DosCreateMutexSem( NULL, &hMtx, 0, FALSE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosCreateMutexSem(), rc = %u", ulRC );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (SDL_mutex *)hMtx;
|
||||
}
|
||||
|
||||
/* Free the mutex */
|
||||
void
|
||||
SDL_DestroyMutex(SDL_mutex * mutex)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMTX hMtx = (HMTX)mutex;
|
||||
|
||||
ulRC = DosCloseMutexSem( hMtx );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosCloseMutexSem(), rc = %u", ulRC );
|
||||
}
|
||||
|
||||
/* Lock the mutex */
|
||||
int
|
||||
SDL_LockMutex(SDL_mutex * mutex)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMTX hMtx = (HMTX)mutex;
|
||||
|
||||
if ( hMtx == NULLHANDLE )
|
||||
return SDL_SetError( "Passed a NULL mutex" );
|
||||
|
||||
ulRC = DosRequestMutexSem( hMtx, SEM_INDEFINITE_WAIT );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosRequestMutexSem(), rc = %u", ulRC );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* try Lock the mutex */
|
||||
int
|
||||
SDL_TryLockMutex(SDL_mutex * mutex)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMTX hMtx = (HMTX)mutex;
|
||||
|
||||
if ( hMtx == NULLHANDLE )
|
||||
return SDL_SetError( "Passed a NULL mutex" );
|
||||
|
||||
ulRC = DosRequestMutexSem( hMtx, SEM_IMMEDIATE_RETURN );
|
||||
|
||||
if ( ulRC == ERROR_TIMEOUT )
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosRequestMutexSem(), rc = %u", ulRC );
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlock the mutex */
|
||||
int
|
||||
SDL_UnlockMutex(SDL_mutex * mutex)
|
||||
{
|
||||
ULONG ulRC;
|
||||
HMTX hMtx = (HMTX)mutex;
|
||||
|
||||
if ( hMtx == NULLHANDLE )
|
||||
return SDL_SetError( "Passed a NULL mutex" );
|
||||
|
||||
ulRC = DosReleaseMutexSem( hMtx );
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosReleaseMutexSem(), rc = %u", ulRC );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,196 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_THREAD_OS2
|
||||
|
||||
/* An implementation of semaphores for OS/2 */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSMISC
|
||||
#include <os2.h>
|
||||
|
||||
struct SDL_semaphore {
|
||||
HEV hEv;
|
||||
HMTX hMtx;
|
||||
ULONG cPost;
|
||||
};
|
||||
|
||||
|
||||
SDL_sem *
|
||||
SDL_CreateSemaphore(Uint32 initial_value)
|
||||
{
|
||||
ULONG ulRC;
|
||||
SDL_sem *pSDLSem = SDL_malloc( sizeof(SDL_sem) );
|
||||
|
||||
if ( pSDLSem == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulRC = DosCreateEventSem( NULL, &pSDLSem->hEv, DCE_AUTORESET, FALSE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosCreateEventSem(), rc = %u", ulRC );
|
||||
SDL_free( pSDLSem );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulRC = DosCreateMutexSem( NULL, &pSDLSem->hMtx, 0, FALSE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosCreateMutexSem(), rc = %u", ulRC );
|
||||
DosCloseEventSem( pSDLSem->hEv );
|
||||
SDL_free( pSDLSem );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSDLSem->cPost = initial_value;
|
||||
|
||||
return pSDLSem;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_DestroySemaphore(SDL_sem * sem)
|
||||
{
|
||||
if ( sem == NULL )
|
||||
return;
|
||||
|
||||
DosCloseMutexSem( sem->hMtx );
|
||||
DosCloseEventSem( sem->hEv );
|
||||
SDL_free( sem );
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWaitTimeout(SDL_sem * sem, Uint32 timeout)
|
||||
{
|
||||
ULONG ulRC;
|
||||
ULONG ulStartTime, ulCurTime;
|
||||
ULONG ulTimeout;
|
||||
ULONG cPost;
|
||||
|
||||
if ( sem == NULL )
|
||||
return SDL_SetError( "Passed a NULL sem" );
|
||||
|
||||
if ( timeout != SEM_INDEFINITE_WAIT )
|
||||
DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &ulStartTime, sizeof(ULONG) );
|
||||
|
||||
while( TRUE )
|
||||
{
|
||||
ulRC = DosRequestMutexSem( sem->hMtx, SEM_INDEFINITE_WAIT );
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosRequestMutexSem() failed, rc = %u", ulRC );
|
||||
|
||||
cPost = sem->cPost;
|
||||
if ( sem->cPost != 0 )
|
||||
sem->cPost--;
|
||||
|
||||
DosReleaseMutexSem( sem->hMtx );
|
||||
|
||||
if ( cPost != 0 )
|
||||
break;
|
||||
|
||||
if ( timeout == SEM_INDEFINITE_WAIT )
|
||||
ulTimeout = SEM_INDEFINITE_WAIT;
|
||||
else
|
||||
{
|
||||
DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, &ulCurTime, sizeof(ULONG) );
|
||||
ulTimeout = ulCurTime - ulStartTime;
|
||||
if ( timeout < ulTimeout )
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
ulTimeout = timeout - ulTimeout;
|
||||
}
|
||||
|
||||
ulRC = DosWaitEventSem( sem->hEv, ulTimeout );
|
||||
if ( ulRC == ERROR_TIMEOUT )
|
||||
return SDL_MUTEX_TIMEDOUT;
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosWaitEventSem() failed, rc = %u", ulRC );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemTryWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout( sem, 0 );
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemWait(SDL_sem * sem)
|
||||
{
|
||||
return SDL_SemWaitTimeout( sem, SDL_MUTEX_MAXWAIT );
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_SemValue(SDL_sem * sem)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( sem == NULL )
|
||||
{
|
||||
SDL_SetError( "Passed a NULL sem" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ulRC = DosRequestMutexSem( sem->hMtx, SEM_INDEFINITE_WAIT );
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosRequestMutexSem() failed, rc = %u", ulRC );
|
||||
|
||||
ulRC = sem->cPost;
|
||||
DosReleaseMutexSem( sem->hMtx );
|
||||
|
||||
return ulRC;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SemPost(SDL_sem * sem)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( sem == NULL )
|
||||
return SDL_SetError( "Passed a NULL sem" );
|
||||
|
||||
ulRC = DosRequestMutexSem( sem->hMtx, SEM_INDEFINITE_WAIT );
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosRequestMutexSem() failed, rc = %u", ulRC );
|
||||
|
||||
sem->cPost++;
|
||||
|
||||
ulRC = DosPostEventSem( sem->hEv );
|
||||
if ( ( ulRC != NO_ERROR ) && ( ulRC != ERROR_ALREADY_POSTED ) )
|
||||
debug( "DosPostEventSem() failed, rc = %u", ulRC );
|
||||
|
||||
DosReleaseMutexSem( sem->hMtx );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_THREAD_OS2
|
||||
|
||||
/* Thread management routines for SDL */
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
#include "../SDL_systhread.h"
|
||||
#include "SDL_systls_c.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
#ifndef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
/* We'll use the C library from this DLL */
|
||||
#include <process.h>
|
||||
|
||||
/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
|
||||
#if (defined(__MINGW32__) && (__GNUC__ < 4))
|
||||
typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned (__stdcall *func)(void *), void *arg,
|
||||
unsigned, unsigned *threadID);
|
||||
typedef void (__cdecl *pfnSDL_CurrentEndThread)(unsigned code);
|
||||
|
||||
#elif defined(__WATCOMC__)
|
||||
/* This is for Watcom targets except OS2 */
|
||||
#if __WATCOMC__ < 1240
|
||||
#define __watcall
|
||||
#endif
|
||||
typedef unsigned long (__watcall * pfnSDL_CurrentBeginThread) (void *,
|
||||
unsigned,
|
||||
unsigned
|
||||
(__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg,
|
||||
unsigned,
|
||||
unsigned
|
||||
*threadID);
|
||||
typedef void (__watcall * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
|
||||
#else
|
||||
typedef uintptr_t(__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned,
|
||||
unsigned (__stdcall *
|
||||
func) (void
|
||||
*),
|
||||
void *arg, unsigned,
|
||||
unsigned *threadID);
|
||||
typedef void (__cdecl * pfnSDL_CurrentEndThread) (unsigned code);
|
||||
#endif
|
||||
#endif /* !SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
|
||||
|
||||
typedef struct ThreadStartParms {
|
||||
void *args;
|
||||
pfnSDL_CurrentEndThread pfnCurrentEndThread;
|
||||
} tThreadStartParms, *pThreadStartParms;
|
||||
|
||||
static void RunThread(void *data)
|
||||
{
|
||||
pThreadStartParms pThreadParms = (pThreadStartParms) data;
|
||||
pfnSDL_CurrentEndThread pfnEndThread = pThreadParms->pfnCurrentEndThread;
|
||||
void *args = pThreadParms->args;
|
||||
|
||||
SDL_free( pThreadParms );
|
||||
|
||||
if ( ppSDLTLSData != NULL )
|
||||
*ppSDLTLSData = NULL;
|
||||
|
||||
SDL_RunThread( args );
|
||||
|
||||
if ( pfnEndThread != NULL )
|
||||
pfnEndThread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args,
|
||||
pfnSDL_CurrentBeginThread pfnBeginThread,
|
||||
pfnSDL_CurrentEndThread pfnEndThread)
|
||||
#else
|
||||
int
|
||||
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
|
||||
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
|
||||
{
|
||||
pThreadStartParms pThreadParms = SDL_malloc( sizeof(tThreadStartParms) );
|
||||
|
||||
if ( pThreadParms == NULL )
|
||||
return SDL_OutOfMemory();
|
||||
|
||||
// Save the function which we will have to call to clear the RTL of calling app!
|
||||
pThreadParms->pfnCurrentEndThread = pfnEndThread;
|
||||
// Also save the real parameters we have to pass to thread function
|
||||
pThreadParms->args = args;
|
||||
|
||||
// Start the thread using the runtime library of calling app!
|
||||
thread->handle = (SYS_ThreadHandle)
|
||||
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
|
||||
( (size_t) pfnBeginThread( RunThread, NULL, 65535, pThreadParms ) );
|
||||
#else
|
||||
_beginthread( RunThread, NULL, 65535, pThreadParms );
|
||||
#endif
|
||||
|
||||
if ( thread->handle == -1 )
|
||||
return SDL_SetError( "Not enough resources to create thread" );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_SetupThread(const char *name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_threadID
|
||||
SDL_ThreadID(void)
|
||||
{
|
||||
PTIB tib;
|
||||
PPIB pib;
|
||||
|
||||
DosGetInfoBlocks( &tib, &pib );
|
||||
return tib->tib_ptib2->tib2_ultid;
|
||||
}
|
||||
|
||||
int
|
||||
SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
ulRC = DosSetPriority( PRTYS_THREAD,
|
||||
priority == SDL_THREAD_PRIORITY_LOW
|
||||
? PRTYC_IDLETIME
|
||||
: priority == SDL_THREAD_PRIORITY_HIGH
|
||||
? PRTYC_TIMECRITICAL
|
||||
: PRTYC_REGULAR ,
|
||||
0, 0 );
|
||||
if ( ulRC != NO_ERROR )
|
||||
return SDL_SetError( "DosSetPriority() failed, rc = %u", ulRC );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_WaitThread(SDL_Thread * thread)
|
||||
{
|
||||
ULONG ulRC = DosWaitThread( (PTID)&thread->handle, DCWW_WAIT );
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosWaitThread() failed, rc = %u", ulRC );
|
||||
}
|
||||
|
||||
void
|
||||
SDL_SYS_DetachThread(SDL_Thread * thread)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
typedef int SYS_ThreadHandle;
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_THREAD_OS2
|
||||
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#include "SDL_thread.h"
|
||||
#include "../SDL_thread_c.h"
|
||||
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSERRORS
|
||||
#include <os2.h>
|
||||
|
||||
SDL_TLSData **ppSDLTLSData = NULL;
|
||||
|
||||
static ULONG cTLSAlloc = 0;
|
||||
|
||||
// SDL_OS2TLSAlloc() called from SDL_InitSubSystem()
|
||||
void SDL_OS2TLSAlloc()
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( ( cTLSAlloc == 0 ) || ( ppSDLTLSData == NULL ) )
|
||||
{
|
||||
// First call - allocate the thread local memory (1 DWORD).
|
||||
ulRC = DosAllocThreadLocalMemory( 1, (PULONG *)&ppSDLTLSData );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosAllocThreadLocalMemory() failed, rc = %u", ulRC );
|
||||
}
|
||||
cTLSAlloc++;
|
||||
}
|
||||
|
||||
// SDL_OS2TLSFree() called from SDL_QuitSubSystem()
|
||||
void SDL_OS2TLSFree()
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( cTLSAlloc != 0 )
|
||||
cTLSAlloc--;
|
||||
|
||||
if ( ( cTLSAlloc == 0 ) && ( ppSDLTLSData != NULL ) )
|
||||
{
|
||||
// Last call - free the thread local memory.
|
||||
ulRC = DosFreeThreadLocalMemory( (PULONG)ppSDLTLSData );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosFreeThreadLocalMemory() failed, rc = %u", ulRC );
|
||||
else
|
||||
ppSDLTLSData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_TLSData *SDL_SYS_GetTLSData()
|
||||
{
|
||||
return ppSDLTLSData == NULL ? NULL : *ppSDLTLSData;
|
||||
}
|
||||
|
||||
int SDL_SYS_SetTLSData(SDL_TLSData *data)
|
||||
{
|
||||
if ( ppSDLTLSData == NULL )
|
||||
return -1;
|
||||
|
||||
*ppSDLTLSData = data;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SDL_THREAD_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_THREAD_OS2
|
||||
|
||||
#include "../SDL_thread_c.h"
|
||||
|
||||
extern SDL_TLSData **ppSDLTLSData;
|
||||
|
||||
// SDL_OS2TLSAlloc() called from SDL_InitSubSystem()
|
||||
void SDL_OS2TLSAlloc();
|
||||
|
||||
// SDL_OS2TLSFree() called from SDL_QuitSubSystem()
|
||||
void SDL_OS2TLSFree();
|
||||
|
||||
#endif /* SDL_THREAD_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_TIMER_OS2
|
||||
|
||||
#include "SDL_timer.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSMISC
|
||||
#define INCL_DOSPROFILE
|
||||
#define INCL_DOSSEMAPHORES
|
||||
#define INCL_DOSDATETIME
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSEXCEPTIONS
|
||||
#include <os2.h>
|
||||
|
||||
// No need to switch priorities in SDL_Delay() for OS/2 versions > Warp3 fp 42.
|
||||
//#define _SWITCH_PRIORITY
|
||||
|
||||
typedef unsigned long long ULLONG;
|
||||
|
||||
static ULONG ulTmrFreq = 0;
|
||||
static ULLONG ullTmrStart;
|
||||
|
||||
void
|
||||
SDL_TicksInit(void)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
ulRC = DosTmrQueryFreq( &ulTmrFreq );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosTmrQueryFreq() failed, rc = %u", ulRC );
|
||||
}
|
||||
else
|
||||
{
|
||||
ulRC = DosTmrQueryTime( (PQWORD)&ullTmrStart );
|
||||
if ( ulRC == NO_ERROR )
|
||||
return;
|
||||
|
||||
debug( "DosTmrQueryTime() failed, rc = %u", ulRC );
|
||||
}
|
||||
|
||||
ulTmrFreq = 0; // Error - use DosQuerySysInfo() for timer.
|
||||
|
||||
DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PULONG)&ullTmrStart,
|
||||
sizeof(ULONG) );
|
||||
}
|
||||
|
||||
void
|
||||
SDL_TicksQuit(void)
|
||||
{
|
||||
}
|
||||
|
||||
Uint32
|
||||
SDL_GetTicks(void)
|
||||
{
|
||||
ULONG ulResult;
|
||||
ULLONG ullTmrNow;
|
||||
|
||||
if ( ulTmrFreq == 0 )
|
||||
// Was not initialized.
|
||||
SDL_TicksInit();
|
||||
|
||||
if ( ulTmrFreq != 0 )
|
||||
{
|
||||
DosTmrQueryTime( (PQWORD)&ullTmrNow );
|
||||
ulResult = ( ullTmrNow - ullTmrStart ) * 1000 / ulTmrFreq;
|
||||
}
|
||||
else
|
||||
{
|
||||
DosQuerySysInfo( QSV_MS_COUNT, QSV_MS_COUNT, (PULONG)&ullTmrNow,
|
||||
sizeof(ULONG) );
|
||||
ulResult = (ULONG)ullTmrNow - (ULONG)ullTmrStart;
|
||||
}
|
||||
|
||||
return ulResult;
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetPerformanceCounter(void)
|
||||
{
|
||||
QWORD qwTmrNow;
|
||||
|
||||
if ( ( ulTmrFreq == 0 ) || ( DosTmrQueryTime( &qwTmrNow ) != NO_ERROR ) )
|
||||
return SDL_GetTicks();
|
||||
|
||||
return *((Uint64 *)&qwTmrNow);
|
||||
}
|
||||
|
||||
Uint64
|
||||
SDL_GetPerformanceFrequency(void)
|
||||
{
|
||||
return ulTmrFreq == 0 ? 1000 : (Uint64)ulTmrFreq;
|
||||
}
|
||||
|
||||
void
|
||||
SDL_Delay(Uint32 ms)
|
||||
{
|
||||
HTIMER hTimer = NULLHANDLE;
|
||||
ULONG ulRC;
|
||||
#ifdef _SWITCH_PRIORITY
|
||||
PPIB pib;
|
||||
PTIB tib;
|
||||
BOOL fSetPriority = ms < 50;
|
||||
ULONG ulSavePriority;
|
||||
ULONG ulNesting;
|
||||
#endif
|
||||
HEV hevTimer;
|
||||
|
||||
if ( ms == 0 )
|
||||
{
|
||||
DosSleep( 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
ulRC = DosCreateEventSem( NULL, &hevTimer, DC_SEM_SHARED, FALSE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosAsyncTimer() failed, rc = %u", ulRC );
|
||||
DosSleep( ms );
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _SWITCH_PRIORITY
|
||||
if ( fSetPriority )
|
||||
{
|
||||
if ( DosGetInfoBlocks( &tib, &pib ) != NO_ERROR )
|
||||
fSetPriority = FALSE;
|
||||
else
|
||||
{
|
||||
ulSavePriority = tib->tib_ptib2->tib2_ulpri;
|
||||
if ( ( (ulSavePriority & 0xFF00) == 0x0300 ) || // already have high pr.
|
||||
( DosEnterMustComplete( &ulNesting ) != NO_ERROR ) )
|
||||
fSetPriority = FALSE;
|
||||
else
|
||||
DosSetPriority( PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0 );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DosResetEventSem( hevTimer, &ulRC );
|
||||
ulRC = DosAsyncTimer( ms, (HSEM)hevTimer, &hTimer );
|
||||
|
||||
#ifdef _SWITCH_PRIORITY
|
||||
if ( fSetPriority )
|
||||
{
|
||||
if ( DosSetPriority( PRTYS_THREAD, (ulSavePriority >> 8) & 0xFF, 0, 0 ) ==
|
||||
NO_ERROR )
|
||||
DosSetPriority( PRTYS_THREAD, 0, ulSavePriority & 0xFF, 0 );
|
||||
|
||||
DosExitMustComplete( &ulNesting );
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosAsyncTimer() failed, rc = %u", ulRC );
|
||||
else
|
||||
DosWaitEventSem( hevTimer, SEM_INDEFINITE_WAIT );
|
||||
|
||||
if ( ulRC != NO_ERROR )
|
||||
DosSleep( ms );
|
||||
|
||||
DosCloseEventSem( hevTimer );
|
||||
}
|
||||
|
||||
#endif /* SDL_TIMER_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,348 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#include <os2.h>
|
||||
#define _MEERROR_H_
|
||||
#include <mmioos2.h>
|
||||
#include <os2me.h>
|
||||
#define INCL_MM_OS2
|
||||
#include <dive.h>
|
||||
#include <fourcc.h>
|
||||
#include "SDL_os2output.h"
|
||||
|
||||
typedef struct _VODATA {
|
||||
HDIVE hDive;
|
||||
PVOID pBuffer;
|
||||
ULONG ulDIVEBufNum;
|
||||
FOURCC fccColorEncoding;
|
||||
ULONG ulWidth;
|
||||
ULONG ulHeight;
|
||||
BOOL fBlitterReady;
|
||||
} VODATA;
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo);
|
||||
static PVODATA voOpen();
|
||||
static VOID voClose(PVODATA pVOData);
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible);
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize);
|
||||
static VOID voVideoBufFree(PVODATA pVOData);
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects);
|
||||
|
||||
OS2VIDEOOUTPUT voDive = {
|
||||
voQueryInfo,
|
||||
voOpen,
|
||||
voClose,
|
||||
voSetVisibleRegion,
|
||||
voVideoBufAlloc,
|
||||
voVideoBufFree,
|
||||
voUpdate
|
||||
};
|
||||
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo)
|
||||
{
|
||||
DIVE_CAPS sDiveCaps = { 0 };
|
||||
FOURCC fccFormats[100] = { 0 };
|
||||
|
||||
// Query information about display hardware from DIVE.
|
||||
|
||||
sDiveCaps.pFormatData = &fccFormats;
|
||||
sDiveCaps.ulFormatLength = 100;
|
||||
sDiveCaps.ulStructLen = sizeof(DIVE_CAPS);
|
||||
|
||||
if ( DiveQueryCaps( &sDiveCaps, DIVE_BUFFER_SCREEN ) )
|
||||
{
|
||||
debug( "DiveQueryCaps() failed." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( sDiveCaps.ulDepth < 8 )
|
||||
{
|
||||
debug( "Not enough screen colors to run DIVE. "
|
||||
"Must be at least 256 colors." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pInfo->ulBPP = sDiveCaps.ulDepth;
|
||||
pInfo->fccColorEncoding = sDiveCaps.fccColorEncoding;
|
||||
pInfo->ulScanLineSize = sDiveCaps.ulScanLineBytes;
|
||||
pInfo->ulHorizResolution = sDiveCaps.ulHorizontalResolution;
|
||||
pInfo->ulVertResolution = sDiveCaps.ulVerticalResolution;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PVODATA voOpen()
|
||||
{
|
||||
PVODATA pVOData = SDL_calloc( 1, sizeof(VODATA) );
|
||||
|
||||
if ( pVOData == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ( DiveOpen( &pVOData->hDive, FALSE, NULL ) != DIVE_SUCCESS )
|
||||
{
|
||||
SDL_free( pVOData );
|
||||
SDL_SetError( "DIVE: A display engine instance open failed" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pVOData;
|
||||
}
|
||||
|
||||
static VOID voClose(PVODATA pVOData)
|
||||
{
|
||||
voVideoBufFree( pVOData );
|
||||
DiveClose( pVOData->hDive );
|
||||
SDL_free( pVOData );
|
||||
}
|
||||
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible)
|
||||
{
|
||||
HPS hps;
|
||||
HRGN hrgn;
|
||||
RGNRECT rgnCtl;
|
||||
PRECTL prectl = NULL;
|
||||
ULONG ulRC;
|
||||
|
||||
if ( !fVisible )
|
||||
{
|
||||
if ( pVOData->fBlitterReady )
|
||||
{
|
||||
pVOData->fBlitterReady = FALSE;
|
||||
DiveSetupBlitter( pVOData->hDive, 0 );
|
||||
debug( "DIVE blitter is tuned off" );
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Query visible rectangles
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
hrgn = GpiCreateRegion( hps, 0, NULL );
|
||||
if ( hrgn == NULLHANDLE )
|
||||
{
|
||||
WinReleasePS( hps );
|
||||
SDL_SetError( "GpiCreateRegion() failed" );
|
||||
}
|
||||
else
|
||||
{
|
||||
WinQueryVisibleRegion( hwnd, hrgn );
|
||||
if ( hrgnShape != NULLHANDLE )
|
||||
GpiCombineRegion( hps, hrgn, hrgn, hrgnShape, CRGN_AND );
|
||||
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = 0;
|
||||
rgnCtl.ulDirection = 1;
|
||||
GpiQueryRegionRects( hps, hrgn, NULL, &rgnCtl, NULL );
|
||||
if ( rgnCtl.crcReturned != 0 )
|
||||
{
|
||||
prectl = SDL_malloc( rgnCtl.crcReturned * sizeof(RECTL) );
|
||||
if ( prectl != NULL )
|
||||
{
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = rgnCtl.crcReturned;
|
||||
rgnCtl.ulDirection = 1;
|
||||
GpiQueryRegionRects( hps, hrgn, NULL, &rgnCtl, prectl );
|
||||
}
|
||||
else
|
||||
SDL_OutOfMemory();
|
||||
}
|
||||
GpiDestroyRegion( hps, hrgn );
|
||||
WinReleasePS( hps );
|
||||
|
||||
if ( prectl != NULL )
|
||||
{
|
||||
// Setup DIVE blitter.
|
||||
SETUP_BLITTER sSetupBlitter;
|
||||
SWP swp;
|
||||
POINTL pointl = { 0 };
|
||||
|
||||
WinQueryWindowPos( hwnd, &swp );
|
||||
WinMapWindowPoints( hwnd, HWND_DESKTOP, &pointl, 1 );
|
||||
|
||||
sSetupBlitter.ulStructLen = sizeof(SETUP_BLITTER);
|
||||
sSetupBlitter.fccSrcColorFormat = pVOData->fccColorEncoding;
|
||||
sSetupBlitter.fInvert = FALSE;
|
||||
sSetupBlitter.ulSrcWidth = pVOData->ulWidth;
|
||||
sSetupBlitter.ulSrcHeight = pVOData->ulHeight;
|
||||
sSetupBlitter.ulSrcPosX = 0;
|
||||
sSetupBlitter.ulSrcPosY = 0;
|
||||
sSetupBlitter.ulDitherType = 0;
|
||||
sSetupBlitter.fccDstColorFormat = FOURCC_SCRN;
|
||||
sSetupBlitter.ulDstWidth = swp.cx;
|
||||
sSetupBlitter.ulDstHeight = swp.cy;
|
||||
sSetupBlitter.lDstPosX = 0;
|
||||
sSetupBlitter.lDstPosY = 0;
|
||||
sSetupBlitter.lScreenPosX = pointl.x;
|
||||
sSetupBlitter.lScreenPosY = pointl.y;
|
||||
|
||||
sSetupBlitter.ulNumDstRects = rgnCtl.crcReturned;
|
||||
sSetupBlitter.pVisDstRects = prectl;
|
||||
|
||||
ulRC = DiveSetupBlitter( pVOData->hDive, &sSetupBlitter );
|
||||
SDL_free( prectl );
|
||||
|
||||
if ( ulRC == DIVE_SUCCESS )
|
||||
{
|
||||
pVOData->fBlitterReady = TRUE;
|
||||
WinInvalidateRect( hwnd, NULL, TRUE );
|
||||
debug( "DIVE blitter is ready now." );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
SDL_SetError( "DiveSetupBlitter(), rc = 0x%X", ulRC );
|
||||
} // if ( prectl != NULL )
|
||||
} // if ( hrgn == NULLHANDLE ) else
|
||||
|
||||
pVOData->fBlitterReady = FALSE;
|
||||
DiveSetupBlitter( pVOData->hDive, 0 );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, FOURCC fccColorEncoding,
|
||||
PULONG pulScanLineSize)
|
||||
{
|
||||
ULONG ulRC;
|
||||
ULONG ulScanLineSize = ulWidth * (ulBPP >> 3);
|
||||
|
||||
// Destroy previous buffer.
|
||||
voVideoBufFree( pVOData );
|
||||
|
||||
if ( ( ulWidth == 0 ) || ( ulHeight == 0 ) || ( ulBPP == 0 ) )
|
||||
return NULL;
|
||||
|
||||
// Bytes per line.
|
||||
ulScanLineSize = ( ulScanLineSize + 3 ) & ~3; /* 4-byte aligning */
|
||||
*pulScanLineSize = ulScanLineSize;
|
||||
|
||||
ulRC = DosAllocMem( &pVOData->pBuffer,
|
||||
(ulHeight * ulScanLineSize) + sizeof(ULONG),
|
||||
PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosAllocMem(), rc = %u", ulRC );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ulRC = DiveAllocImageBuffer( pVOData->hDive, &pVOData->ulDIVEBufNum,
|
||||
fccColorEncoding, ulWidth, ulHeight,
|
||||
ulScanLineSize, pVOData->pBuffer );
|
||||
if ( ulRC != DIVE_SUCCESS )
|
||||
{
|
||||
debug( "DiveAllocImageBuffer(), rc = 0x%X", ulRC );
|
||||
DosFreeMem( pVOData->pBuffer );
|
||||
pVOData->pBuffer = NULL;
|
||||
pVOData->ulDIVEBufNum = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pVOData->fccColorEncoding = fccColorEncoding;
|
||||
pVOData->ulWidth = ulWidth;
|
||||
pVOData->ulHeight = ulHeight;
|
||||
|
||||
debug( "buffer: 0x%P, DIVE buffer number: %u",
|
||||
pVOData->pBuffer, pVOData->ulDIVEBufNum );
|
||||
|
||||
return pVOData->pBuffer;
|
||||
}
|
||||
|
||||
static VOID voVideoBufFree(PVODATA pVOData)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( pVOData->ulDIVEBufNum != 0 )
|
||||
{
|
||||
ulRC = DiveFreeImageBuffer( pVOData->hDive, pVOData->ulDIVEBufNum );
|
||||
if ( ulRC != DIVE_SUCCESS )
|
||||
debug( "DiveFreeImageBuffer(,%u), rc = %u", pVOData->ulDIVEBufNum, ulRC );
|
||||
else
|
||||
debug( "DIVE buffer %u destroyed", pVOData->ulDIVEBufNum );
|
||||
|
||||
pVOData->ulDIVEBufNum = 0;
|
||||
}
|
||||
|
||||
if ( pVOData->pBuffer != NULL )
|
||||
{
|
||||
ulRC = DosFreeMem( pVOData->pBuffer );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosFreeMem(), rc = %u", ulRC );
|
||||
|
||||
pVOData->pBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( !pVOData->fBlitterReady || ( pVOData->ulDIVEBufNum == 0 ) )
|
||||
{
|
||||
debug( "DIVE blitter is not ready" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( pSDLRects != 0 )
|
||||
{
|
||||
PBYTE pbLineMask;
|
||||
|
||||
pbLineMask = SDL_stack_alloc( BYTE, pVOData->ulHeight );
|
||||
if ( pbLineMask == NULL )
|
||||
{
|
||||
debug( "Not enough stack size" );
|
||||
return FALSE;
|
||||
}
|
||||
memset( pbLineMask, 0, pVOData->ulHeight );
|
||||
|
||||
for( ; ((LONG)cSDLRects) > 0; cSDLRects--, pSDLRects++ )
|
||||
memset( &pbLineMask[pSDLRects->y], 1, pSDLRects->h );
|
||||
|
||||
ulRC = DiveBlitImageLines( pVOData->hDive, pVOData->ulDIVEBufNum,
|
||||
DIVE_BUFFER_SCREEN, pbLineMask );
|
||||
SDL_stack_free( pbLineMask );
|
||||
|
||||
if ( ulRC != DIVE_SUCCESS )
|
||||
debug( "DiveBlitImageLines(), rc = 0x%X", ulRC );
|
||||
}
|
||||
else
|
||||
{
|
||||
ulRC = DiveBlitImage( pVOData->hDive, pVOData->ulDIVEBufNum,
|
||||
DIVE_BUFFER_SCREEN );
|
||||
if ( ulRC != DIVE_SUCCESS )
|
||||
debug( "DiveBlitImage(), rc = 0x%X", ulRC );
|
||||
}
|
||||
|
||||
return ulRC == DIVE_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_OS2
|
||||
|
||||
/* Display a OS/2 message box */
|
||||
|
||||
#include "SDL.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
#include "SDL_os2video.h"
|
||||
#define INCL_WIN
|
||||
#include <os2.h>
|
||||
|
||||
#define IDD_TEXT_MESSAGE 1001
|
||||
#define IDD_BITMAP 1002
|
||||
#define IDD_PB_FIRST 1003
|
||||
|
||||
typedef struct _MSGBOXDLGDATA {
|
||||
USHORT cb;
|
||||
HWND hwndUnder;
|
||||
} MSGBOXDLGDATA, *PMSGBOXDLGDATA;
|
||||
|
||||
static VOID _wmInitDlg(HWND hwnd, PMSGBOXDLGDATA pDlgData)
|
||||
{
|
||||
HPS hps = WinGetPS( hwnd );
|
||||
POINTL aptText[TXTBOX_COUNT];
|
||||
HENUM hEnum;
|
||||
HWND hWndNext;
|
||||
CHAR acBuf[256];
|
||||
ULONG cbBuf;
|
||||
ULONG cButtons = 0;
|
||||
ULONG ulButtonsCY = 0;
|
||||
ULONG ulButtonsCX = 0;
|
||||
RECTL rectl;
|
||||
ULONG ulX;
|
||||
ULONG ulIdx;
|
||||
struct _BUTTON {
|
||||
HWND hwnd; // Button window handle.
|
||||
ULONG ulCX; // Button width in dialog coordinates.
|
||||
} aButtons[32];
|
||||
RECTL rectlItem;
|
||||
HAB hab = WinQueryAnchorBlock( hwnd );
|
||||
|
||||
/* --- Align the buttons to the right/bottom. --- */
|
||||
|
||||
// Collect window handles of all buttons in dialog.
|
||||
|
||||
hEnum = WinBeginEnumWindows( hwnd );
|
||||
|
||||
while( ( hWndNext = WinGetNextWindow( hEnum ) ) != NULLHANDLE )
|
||||
{
|
||||
if ( WinQueryClassName( hWndNext, sizeof(acBuf), &acBuf ) == 0 )
|
||||
continue;
|
||||
|
||||
if ( strcmp( &acBuf, "#3" ) == 0 ) // Class name of button.
|
||||
{
|
||||
if ( cButtons < sizeof(aButtons) / sizeof(struct _BUTTON) )
|
||||
{
|
||||
aButtons[cButtons].hwnd = hWndNext;
|
||||
cButtons++;
|
||||
}
|
||||
}
|
||||
}
|
||||
WinEndEnumWindows( hEnum );
|
||||
|
||||
// Query size of text for each button, get width of each button, total
|
||||
// buttons width (ulButtonsCX) and max. height (ulButtonsCX) in _dialog
|
||||
// coordinates_.
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
|
||||
for( ulIdx = 0; ulIdx < cButtons; ulIdx++ )
|
||||
{
|
||||
// Query size of text in window coordinates.
|
||||
cbBuf = WinQueryWindowText( aButtons[ulIdx].hwnd, sizeof(acBuf), &acBuf );
|
||||
GpiQueryTextBox( hps, cbBuf, acBuf, TXTBOX_COUNT, &aptText );
|
||||
aptText[TXTBOX_TOPRIGHT].x -= aptText[TXTBOX_BOTTOMLEFT].x;
|
||||
aptText[TXTBOX_TOPRIGHT].y -= aptText[TXTBOX_BOTTOMLEFT].y;
|
||||
// Convert text size to dialog coordinates.
|
||||
WinMapDlgPoints( hwnd, &aptText[TXTBOX_TOPRIGHT], 1, FALSE );
|
||||
// Add vertical and horizontal space for button's frame (dialog coord.).
|
||||
if ( aptText[TXTBOX_TOPRIGHT].x < 30 ) // Minimal button width.
|
||||
aptText[TXTBOX_TOPRIGHT].x = 30;
|
||||
else
|
||||
aptText[TXTBOX_TOPRIGHT].x += 4;
|
||||
aptText[TXTBOX_TOPRIGHT].y += 3;
|
||||
|
||||
aButtons[ulIdx].ulCX = aptText[TXTBOX_TOPRIGHT].x; // Store button width.
|
||||
ulButtonsCX += aptText[TXTBOX_TOPRIGHT].x + 2; // Add total btn. width.
|
||||
// Get max. height for buttons.
|
||||
if ( ulButtonsCY < aptText[TXTBOX_TOPRIGHT].y )
|
||||
ulButtonsCY = aptText[TXTBOX_TOPRIGHT].y + 1;
|
||||
}
|
||||
|
||||
WinReleasePS( hps );
|
||||
|
||||
// Expand horizontal size of the window to fit all buttons and move window
|
||||
// to the center of parent window.
|
||||
|
||||
// Convert total width of buttons to window coordinates.
|
||||
aptText[0].x = ulButtonsCX + 4;
|
||||
WinMapDlgPoints( hwnd, &aptText[0], 1, TRUE );
|
||||
// Check width of the window and expand as needed.
|
||||
WinQueryWindowRect( hwnd, &rectlItem );
|
||||
if ( rectlItem.xRight <= aptText[0].x )
|
||||
rectlItem.xRight = aptText[0].x;
|
||||
|
||||
// Move window rectangle to the center of owner window.
|
||||
WinQueryWindowRect( pDlgData->hwndUnder, &rectl );
|
||||
// Left-bottom point of centered dialog on owner window.
|
||||
rectl.xLeft = ( rectl.xRight - rectlItem.xRight ) / 2;
|
||||
rectl.yBottom = ( rectl.yTop - rectlItem.yTop ) / 2;
|
||||
// Map left-bottom point to desktop.
|
||||
WinMapWindowPoints( pDlgData->hwndUnder, HWND_DESKTOP, (PPOINTL)&rectl, 1 );
|
||||
WinOffsetRect( hab, &rectlItem, rectl.xLeft, rectl.yBottom );
|
||||
|
||||
// Set new rectangle for the window.
|
||||
WinSetWindowPos( hwnd, HWND_TOP, rectlItem.xLeft, rectlItem.yBottom,
|
||||
rectlItem.xRight - rectlItem.xLeft,
|
||||
rectlItem.yTop - rectlItem.yBottom,
|
||||
SWP_SIZE | SWP_MOVE );
|
||||
|
||||
// Set buttons positions.
|
||||
|
||||
// Get horizontal position for the first button.
|
||||
WinMapDlgPoints( hwnd, (PPOINTL)&rectlItem, 2, FALSE ); // Win size to dlg coord.
|
||||
ulX = rectlItem.xRight - rectlItem.xLeft - ulButtonsCX - 2; // First button position.
|
||||
|
||||
// Set positions and sizes for all buttons.
|
||||
for( ulIdx = 0; ulIdx < cButtons; ulIdx++ )
|
||||
{
|
||||
// Get poisition and size for the button in dialog coordinates.
|
||||
aptText[0].x = ulX;
|
||||
aptText[0].y = 2;
|
||||
aptText[1].x = aButtons[ulIdx].ulCX;
|
||||
aptText[1].y = ulButtonsCY;
|
||||
// Convert to window coordinates.
|
||||
WinMapDlgPoints( hwnd, &aptText, 2, TRUE );
|
||||
|
||||
WinSetWindowPos( aButtons[ulIdx].hwnd, HWND_TOP,
|
||||
aptText[0].x, aptText[0].y, aptText[1].x, aptText[1].y,
|
||||
SWP_MOVE | SWP_SIZE );
|
||||
|
||||
// Offset horizontal position for the next button.
|
||||
ulX += aButtons[ulIdx].ulCX + 2;
|
||||
}
|
||||
|
||||
// Set right bound of the text to right bound of the last button and
|
||||
// bottom bound of the text just above the buttons.
|
||||
|
||||
aptText[2].x = 25; // Left bound of text in dlg coordinates.
|
||||
aptText[2].y = ulButtonsCY + 3; // Bottom bound of the text in dlg coords.
|
||||
WinMapDlgPoints( hwnd, &aptText[2], 1, TRUE ); // Convert ^^^ to win. coords.
|
||||
hWndNext = WinWindowFromID( hwnd, IDD_TEXT_MESSAGE );
|
||||
WinQueryWindowRect( hWndNext, &rectlItem );
|
||||
rectlItem.xLeft = aptText[2].x;
|
||||
rectlItem.yBottom = aptText[2].y;
|
||||
// Right bound of the text equals right bound of the last button.
|
||||
rectlItem.xRight = aptText[0].x + aptText[1].x;
|
||||
WinSetWindowPos( hWndNext, HWND_TOP, rectlItem.xLeft, rectlItem.yBottom,
|
||||
rectlItem.xRight - rectlItem.xLeft,
|
||||
rectlItem.yTop - rectlItem.yBottom,
|
||||
SWP_MOVE | SWP_SIZE );
|
||||
}
|
||||
|
||||
MRESULT EXPENTRY DynDlgProc(HWND hwnd, USHORT message, MPARAM mp1, MPARAM mp2)
|
||||
{
|
||||
switch( message )
|
||||
{
|
||||
case WM_INITDLG:
|
||||
_wmInitDlg( hwnd, (PMSGBOXDLGDATA)mp2 );
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
switch( SHORT1FROMMP(mp1) )
|
||||
{
|
||||
case DID_OK:
|
||||
WinDismissDlg( hwnd, FALSE );
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return( WinDefDlgProc( hwnd, message, mp1, mp2 ) );
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static HWND _makeDlg(const SDL_MessageBoxData *messageboxdata)
|
||||
{
|
||||
SDL_MessageBoxButtonData *pSDLBtnData =
|
||||
(SDL_MessageBoxButtonData *)messageboxdata->buttons;
|
||||
ULONG cSDLBtnData = messageboxdata->numbuttons;
|
||||
|
||||
PSZ pszTitle = OS2_UTF8ToSys( (PSZ)messageboxdata->title );
|
||||
ULONG cbTitle = pszTitle == NULL ?
|
||||
0 : strlen( pszTitle );
|
||||
PSZ pszText = OS2_UTF8ToSys( (PSZ)messageboxdata->message );
|
||||
ULONG cbText = pszText == NULL ?
|
||||
0 : strlen( pszText );
|
||||
|
||||
PDLGTEMPLATE pTemplate;
|
||||
ULONG cbTemplate;
|
||||
ULONG ulIdx;
|
||||
PCHAR pcDlgData;
|
||||
PDLGTITEM pDlgItem;
|
||||
PSZ pszBtnText;
|
||||
ULONG cbBtnText;
|
||||
HWND hwnd;
|
||||
SDL_MessageBoxColor *pSDLColors = messageboxdata->colorScheme == NULL
|
||||
? NULL
|
||||
: (SDL_MessageBoxColor *)&messageboxdata->colorScheme->colors;
|
||||
SDL_MessageBoxColor *pSDLColor;
|
||||
MSGBOXDLGDATA stDlgData;
|
||||
|
||||
/* Build a dialog tamplate in memory */
|
||||
|
||||
// Size of template (cbTemplate).
|
||||
|
||||
cbTemplate = sizeof(DLGTEMPLATE) + ( (2 + cSDLBtnData) * sizeof(DLGTITEM) ) +
|
||||
sizeof(ULONG) + // First item data - frame control data.
|
||||
cbTitle + 1 + // First item data - frame title + ZERO.
|
||||
cbText + 1 + // Second item data - ststic text + ZERO.
|
||||
3; // Third item data - system icon Id.
|
||||
// Button items datas - text for buttons.
|
||||
for( ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++ )
|
||||
{
|
||||
pszBtnText = (PSZ)pSDLBtnData[ulIdx].text;
|
||||
cbTemplate += pszBtnText == NULL ? 1 : ( strlen( pszBtnText ) + 1 );
|
||||
}
|
||||
// Presentation parameter space.
|
||||
if ( pSDLColors != NULL )
|
||||
cbTemplate += 26 /* PP for frame. */ + 26 /* PP for static text. */ +
|
||||
( 48 * cSDLBtnData ); /* PP for buttons. */
|
||||
|
||||
// Allocate memory for the dialog template.
|
||||
pTemplate = SDL_malloc( cbTemplate );
|
||||
// Pointer on data for dialog items in allocated memory.
|
||||
pcDlgData = &((PCHAR)pTemplate)[ sizeof(DLGTEMPLATE) +
|
||||
( (2 + cSDLBtnData) * sizeof(DLGTITEM) ) ];
|
||||
|
||||
/* Header info */
|
||||
|
||||
pTemplate->cbTemplate = cbTemplate; /* size of dialog template to pass to WinCreateDlg() */
|
||||
pTemplate->type = 0; /* Currently always 0. */
|
||||
pTemplate->codepage = 0;
|
||||
pTemplate->offadlgti = 14; /* Offset to array of DLGTITEMs. */
|
||||
pTemplate->fsTemplateStatus = 0; /* Reserved field? */
|
||||
|
||||
/* Index in array of dlg items of item to get focus, */
|
||||
/* if 0 then focus goes to first control that can have focus. */
|
||||
pTemplate->iItemFocus = 0;
|
||||
pTemplate->coffPresParams = 0;
|
||||
|
||||
/* First item info - frame */
|
||||
|
||||
pDlgItem = &pTemplate->adlgti;
|
||||
pDlgItem->fsItemStatus = 0; /* Reserved? */
|
||||
/* Number of dialog item child windows owned by this item. */
|
||||
pDlgItem->cChildren = 2 + cSDLBtnData; // Ststic text + buttons.
|
||||
/* Length of class name, if 0 then offClassname contains a WC_ value. */
|
||||
pDlgItem->cchClassName = 0;
|
||||
pDlgItem->offClassName = (USHORT)WC_FRAME;
|
||||
/* Length of text. */
|
||||
pDlgItem->cchText = cbTitle + 1; /* +1 - trailing ZERO. */
|
||||
pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to title text. */
|
||||
/* Copy text for the title into the dialog template. */
|
||||
if ( pszTitle != NULL )
|
||||
strcpy( pcDlgData, pszTitle );
|
||||
else
|
||||
*pcDlgData = '\0';
|
||||
pcDlgData += pDlgItem->cchText;
|
||||
|
||||
pDlgItem->flStyle = WS_GROUP | WS_VISIBLE | WS_CLIPSIBLINGS |
|
||||
FS_DLGBORDER | WS_SAVEBITS;
|
||||
pDlgItem->x = 100;
|
||||
pDlgItem->y = 100;
|
||||
pDlgItem->cx = 175;
|
||||
pDlgItem->cy = 65;
|
||||
pDlgItem->id = DID_OK; /* An ID value? */
|
||||
if ( pSDLColors == NULL )
|
||||
pDlgItem->offPresParams = 0;
|
||||
else
|
||||
{
|
||||
// Presentation parameter for the frame - dialog colors.
|
||||
pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
|
||||
((PPRESPARAMS)pcDlgData)->cb = 22;
|
||||
pcDlgData += 4;
|
||||
((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].r;
|
||||
pcDlgData += 11;
|
||||
((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].r;
|
||||
pcDlgData += 11;
|
||||
}
|
||||
|
||||
/* Offset to ctl data. */
|
||||
pDlgItem->offCtlData = pcDlgData - (PCHAR)pTemplate;
|
||||
/* Put CtlData for the dialog in here */
|
||||
*((PULONG)pcDlgData) = FCF_TITLEBAR | FCF_SYSMENU;
|
||||
pcDlgData += sizeof(ULONG);
|
||||
|
||||
/* Second item info - static text (message). */
|
||||
|
||||
pDlgItem++;
|
||||
pDlgItem->fsItemStatus = 0;
|
||||
/* No children since its a control, it could have child control */
|
||||
/* (ex. a group box). */
|
||||
pDlgItem->cChildren = 0;
|
||||
/* Length of class name, 0 - offClassname contains a WC_ constant. */
|
||||
pDlgItem->cchClassName = 0;
|
||||
pDlgItem->offClassName = (USHORT)WC_STATIC;
|
||||
|
||||
pDlgItem->cchText = cbText + 1;
|
||||
pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to the text. */
|
||||
/* Copy message text into the dialog template. */
|
||||
if ( pszText != NULL )
|
||||
strcpy( pcDlgData, pszText );
|
||||
else
|
||||
*pcDlgData = '\0';
|
||||
pcDlgData += pDlgItem->cchText;
|
||||
|
||||
pDlgItem->flStyle = SS_TEXT | DT_TOP | DT_LEFT | DT_WORDBREAK | WS_VISIBLE;
|
||||
// It will be really set in _wmInitDlg().
|
||||
pDlgItem->x = 25;
|
||||
pDlgItem->y = 13;
|
||||
pDlgItem->cx = 147;
|
||||
pDlgItem->cy = 62; // It will be used.
|
||||
|
||||
pDlgItem->id = IDD_TEXT_MESSAGE; /* an ID value */
|
||||
if ( pSDLColors == NULL )
|
||||
pDlgItem->offPresParams = 0;
|
||||
else
|
||||
{
|
||||
// Presentation parameter for the static text - dialog colors.
|
||||
pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
|
||||
((PPRESPARAMS)pcDlgData)->cb = 22;
|
||||
pcDlgData += 4;
|
||||
((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT].r;
|
||||
pcDlgData += 11;
|
||||
((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BACKGROUND].r;
|
||||
pcDlgData += 11;
|
||||
}
|
||||
pDlgItem->offCtlData = 0;
|
||||
|
||||
/* Third item info - static bitmap. */
|
||||
|
||||
pDlgItem++;
|
||||
pDlgItem->fsItemStatus = 0;
|
||||
pDlgItem->cChildren = 0;
|
||||
pDlgItem->cchClassName = 0;
|
||||
pDlgItem->offClassName = (USHORT)WC_STATIC;
|
||||
|
||||
pDlgItem->cchText = 3; // 0xFF, low byte of the icon Id, high byte of icon Id.
|
||||
pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to the Id. */
|
||||
/* Write susyem icon ID into dialog template. */
|
||||
*pcDlgData = 0xFF; // First byte is 0xFF - next 2 bytes is system pointer Id.
|
||||
pcDlgData++;
|
||||
*((PUSHORT)pcDlgData) =
|
||||
(messageboxdata->flags & SDL_MESSAGEBOX_ERROR) != 0
|
||||
? SPTR_ICONERROR
|
||||
: (messageboxdata->flags & SDL_MESSAGEBOX_WARNING) != 0
|
||||
? SPTR_ICONWARNING : SPTR_ICONINFORMATION;
|
||||
pcDlgData += 2;
|
||||
|
||||
pDlgItem->flStyle = SS_SYSICON | WS_VISIBLE;
|
||||
|
||||
pDlgItem->x = 4;
|
||||
pDlgItem->y = 45; // It will be really set in _wmInitDlg().
|
||||
pDlgItem->cx = 0;
|
||||
pDlgItem->cy = 0;
|
||||
|
||||
pDlgItem->id = IDD_BITMAP;
|
||||
pDlgItem->offPresParams = 0;
|
||||
pDlgItem->offCtlData = 0;
|
||||
|
||||
/* Next items - buttons. */
|
||||
|
||||
for( ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++ )
|
||||
{
|
||||
pDlgItem++;
|
||||
|
||||
pDlgItem->fsItemStatus = 0;
|
||||
pDlgItem->cChildren = 0; /* No children. */
|
||||
pDlgItem->cchClassName = 0; /* 0 - offClassname is WC_ constant. */
|
||||
pDlgItem->offClassName = (USHORT)WC_BUTTON;
|
||||
|
||||
pszBtnText = OS2_UTF8ToSys( (PSZ)pSDLBtnData[ulIdx].text );
|
||||
cbBtnText = ( pszBtnText == NULL ?
|
||||
0 : strlen( pszBtnText ) );
|
||||
pDlgItem->cchText = cbBtnText + 1;
|
||||
pDlgItem->offText = pcDlgData - (PCHAR)pTemplate; /* Offset to the text. */
|
||||
/* Copy text for the button into the dialog template. */
|
||||
if ( pszBtnText != NULL )
|
||||
strcpy( pcDlgData, pszBtnText );
|
||||
else
|
||||
*pcDlgData = '\0';
|
||||
pcDlgData += pDlgItem->cchText;
|
||||
SDL_free( pszBtnText );
|
||||
|
||||
pDlgItem->flStyle = BS_PUSHBUTTON | WS_TABSTOP | WS_VISIBLE;
|
||||
if ( pSDLBtnData[ulIdx].flags == SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT )
|
||||
{
|
||||
pDlgItem->flStyle |= BS_DEFAULT;
|
||||
pTemplate->iItemFocus = ulIdx + 3; // +3 - frame, static text and icon.
|
||||
pSDLColor = &pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED];
|
||||
}
|
||||
else
|
||||
pSDLColor = &pSDLColors[SDL_MESSAGEBOX_COLOR_TEXT];
|
||||
|
||||
// It will be really set in _wmInitDlg()
|
||||
pDlgItem->x = 10;
|
||||
pDlgItem->y = 10;
|
||||
pDlgItem->cx = 70;
|
||||
pDlgItem->cy = 15;
|
||||
|
||||
pDlgItem->id = IDD_PB_FIRST + ulIdx; /* an ID value */
|
||||
if ( pSDLColors == NULL )
|
||||
pDlgItem->offPresParams = 0;
|
||||
else
|
||||
{
|
||||
// Presentation parameter for the button - dialog colors.
|
||||
pDlgItem->offPresParams = pcDlgData - (PCHAR)pTemplate;
|
||||
((PPRESPARAMS)pcDlgData)->cb = 44;
|
||||
pcDlgData += 4;
|
||||
((PPARAM)pcDlgData)->id = PP_FOREGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColor->b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColor->g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColor->r;
|
||||
pcDlgData += 11;
|
||||
((PPARAM)pcDlgData)->id = PP_BACKGROUNDCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND].r;
|
||||
pcDlgData += 11;
|
||||
((PPARAM)pcDlgData)->id = PP_BORDERLIGHTCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].r;
|
||||
pcDlgData += 11;
|
||||
((PPARAM)pcDlgData)->id = PP_BORDERDARKCOLOR;
|
||||
((PPARAM)pcDlgData)->cb = 3;
|
||||
((PPARAM)pcDlgData)->ab[0] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].b;
|
||||
((PPARAM)pcDlgData)->ab[1] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].g;
|
||||
((PPARAM)pcDlgData)->ab[2] = pSDLColors[SDL_MESSAGEBOX_COLOR_BUTTON_BORDER].r;
|
||||
pcDlgData += 11;
|
||||
}
|
||||
pDlgItem->offCtlData = 0;
|
||||
}
|
||||
// Check, end of templ. data: &((PCHAR)pTemplate)[cbTemplate] == pcDlgData
|
||||
|
||||
// Create the dialog from template.
|
||||
|
||||
stDlgData.cb = sizeof(MSGBOXDLGDATA);
|
||||
stDlgData.hwndUnder = ( messageboxdata->window != NULL ) &&
|
||||
( messageboxdata->window->driverdata != NULL )
|
||||
? ((PWINDATA)messageboxdata->window->driverdata)->hwnd
|
||||
: HWND_DESKTOP;
|
||||
|
||||
hwnd = WinCreateDlg( HWND_DESKTOP, // Parent is desktop.
|
||||
stDlgData.hwndUnder,
|
||||
(PFNWP)DynDlgProc, pTemplate, &stDlgData );
|
||||
SDL_free( pTemplate );
|
||||
SDL_free( pszTitle );
|
||||
SDL_free( pszText );
|
||||
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
|
||||
int OS2_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
|
||||
{
|
||||
HWND hwnd;
|
||||
ULONG ulRC;
|
||||
SDL_MessageBoxButtonData
|
||||
*pSDLBtnData =
|
||||
(SDL_MessageBoxButtonData *)messageboxdata->buttons;
|
||||
ULONG cSDLBtnData = messageboxdata->numbuttons;
|
||||
BOOL fVideoInitialized = SDL_WasInit( SDL_INIT_VIDEO );
|
||||
HAB hab;
|
||||
HMQ hmq;
|
||||
BOOL fSuccess = FALSE;
|
||||
|
||||
if ( !fVideoInitialized )
|
||||
{
|
||||
PTIB tib;
|
||||
PPIB pib;
|
||||
|
||||
DosGetInfoBlocks( &tib, &pib );
|
||||
if ( pib->pib_ultype == 2 || pib->pib_ultype == 0 )
|
||||
{
|
||||
// VIO windowable or fullscreen protect-mode session.
|
||||
pib->pib_ultype = 3; // Presentation Manager protect-mode session.
|
||||
}
|
||||
|
||||
hab = WinInitialize( 0 );
|
||||
if ( hab == NULLHANDLE )
|
||||
{
|
||||
debug( "WinInitialize() failed" );
|
||||
return -1;
|
||||
}
|
||||
hmq = WinCreateMsgQueue( hab, 0 );
|
||||
if ( hmq == NULLHANDLE )
|
||||
{
|
||||
debug( "WinCreateMsgQueue() failed" );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Create dynamic dialog.
|
||||
hwnd = _makeDlg( messageboxdata );
|
||||
// Show dialog and obtain button Id.
|
||||
ulRC = WinProcessDlg( hwnd );
|
||||
// Destroy dialog,
|
||||
WinDestroyWindow( hwnd );
|
||||
|
||||
if ( ulRC == DID_CANCEL )
|
||||
{
|
||||
// Window closed by ESC, Alt+F4 or system menu.
|
||||
ULONG ulIdx;
|
||||
|
||||
for( ulIdx = 0; ulIdx < cSDLBtnData; ulIdx++, pSDLBtnData++ )
|
||||
{
|
||||
if ( pSDLBtnData->flags == SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT )
|
||||
{
|
||||
*buttonid = pSDLBtnData->buttonid;
|
||||
fSuccess = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Button pressed.
|
||||
ulRC -= IDD_PB_FIRST;
|
||||
if ( ulRC < cSDLBtnData )
|
||||
{
|
||||
*buttonid = pSDLBtnData[ulRC].buttonid;
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !fVideoInitialized )
|
||||
{
|
||||
WinDestroyMsgQueue( hmq );
|
||||
WinTerminate( hab );
|
||||
}
|
||||
|
||||
return fSuccess ? 0 : -1;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_OS2
|
||||
|
||||
extern int OS2_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid);
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_OS2 */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_OS2
|
||||
|
||||
#include "SDL_os2video.h"
|
||||
#include "../../events/SDL_mouse_c.h"
|
||||
#include "SDL_os2util.h"
|
||||
|
||||
HPOINTER hptrCursor = NULLHANDLE;
|
||||
|
||||
static SDL_Cursor* OS2_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
|
||||
{
|
||||
ULONG ulMaxW = WinQuerySysValue( HWND_DESKTOP, SV_CXPOINTER );
|
||||
ULONG ulMaxH = WinQuerySysValue( HWND_DESKTOP, SV_CYPOINTER );
|
||||
HPOINTER hptr;
|
||||
SDL_Cursor *pSDLCursor;
|
||||
|
||||
if ( ( surface->w > ulMaxW ) || ( surface->h > ulMaxH ) )
|
||||
{
|
||||
debug( "Given image size is %u x %u, maximum allowed size is %u x %u",
|
||||
surface->w, surface->h, ulMaxW, ulMaxH );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hptr = utilCreatePointer( surface, hot_x, ulMaxH - hot_y - 1 );
|
||||
if ( hptr == NULLHANDLE )
|
||||
return NULL;
|
||||
|
||||
pSDLCursor = SDL_calloc( 1, sizeof(SDL_Cursor) );
|
||||
if ( pSDLCursor == NULL )
|
||||
{
|
||||
WinDestroyPointer( hptr );
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSDLCursor->driverdata = (void *)hptr;
|
||||
return pSDLCursor;
|
||||
}
|
||||
|
||||
static SDL_Cursor* OS2_CreateSystemCursor(SDL_SystemCursor id)
|
||||
{
|
||||
SDL_Cursor* pSDLCursor;
|
||||
LONG lSysId;
|
||||
HPOINTER hptr;
|
||||
|
||||
switch( id )
|
||||
{
|
||||
case SDL_SYSTEM_CURSOR_ARROW: lSysId = SPTR_ARROW; break;
|
||||
case SDL_SYSTEM_CURSOR_IBEAM: lSysId = SPTR_TEXT; break;
|
||||
case SDL_SYSTEM_CURSOR_WAIT: lSysId = SPTR_WAIT; break;
|
||||
case SDL_SYSTEM_CURSOR_CROSSHAIR: lSysId = SPTR_MOVE; break;
|
||||
case SDL_SYSTEM_CURSOR_WAITARROW: lSysId = SPTR_WAIT; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENWSE: lSysId = SPTR_SIZENWSE; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENESW: lSysId = SPTR_SIZENESW; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEWE: lSysId = SPTR_SIZEWE; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZENS: lSysId = SPTR_SIZENS; break;
|
||||
case SDL_SYSTEM_CURSOR_SIZEALL: lSysId = SPTR_MOVE; break;
|
||||
case SDL_SYSTEM_CURSOR_NO: lSysId = SPTR_ILLEGAL; break;
|
||||
case SDL_SYSTEM_CURSOR_HAND: lSysId = SPTR_ARROW; break;
|
||||
default:
|
||||
debug( "Unknown cursor id: %u", id );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// On eCS SPTR_WAIT for last paramether fCopy=TRUE/FALSE gives different
|
||||
// "wait" icons. -=8( )
|
||||
hptr = WinQuerySysPointer( HWND_DESKTOP, lSysId,
|
||||
id == SDL_SYSTEM_CURSOR_WAIT );
|
||||
if ( hptr == NULLHANDLE )
|
||||
{
|
||||
debug( "Cannot load OS/2 system pointer %u for SDL cursor id %u",
|
||||
lSysId, id );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSDLCursor = SDL_calloc( 1, sizeof(SDL_Cursor) );
|
||||
if ( pSDLCursor == NULL )
|
||||
{
|
||||
WinDestroyPointer( hptr );
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSDLCursor->driverdata = (void *)hptr;
|
||||
return pSDLCursor;
|
||||
}
|
||||
|
||||
static void OS2_FreeCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
HPOINTER hptr = (HPOINTER)cursor->driverdata;
|
||||
|
||||
WinDestroyPointer( hptr );
|
||||
SDL_free( cursor );
|
||||
}
|
||||
|
||||
static int OS2_ShowCursor(SDL_Cursor *cursor)
|
||||
{
|
||||
hptrCursor = cursor != NULL ? (HPOINTER)cursor->driverdata : NULLHANDLE;
|
||||
|
||||
return ( ( SDL_GetMouseFocus() == NULL ) ||
|
||||
WinSetPointer( HWND_DESKTOP, hptrCursor ) ) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void OS2_WarpMouse(SDL_Window * window, int x, int y)
|
||||
{
|
||||
PWINDATA pWinData = (PWINDATA)window->driverdata;
|
||||
POINTL pointl;
|
||||
|
||||
pointl.x = x;
|
||||
pointl.y = window->h - y;
|
||||
WinMapWindowPoints( pWinData->hwnd, HWND_DESKTOP, &pointl, 1 );
|
||||
// pWinData->lSkipWMMouseMove++; ???
|
||||
WinSetPointerPos( HWND_DESKTOP, pointl.x, pointl.y );
|
||||
}
|
||||
|
||||
static int OS2_WarpMouseGlobal(int x, int y)
|
||||
{
|
||||
WinSetPointerPos( HWND_DESKTOP, x,
|
||||
WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - y );
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int OS2_CaptureMouse(SDL_Window *window)
|
||||
{
|
||||
return WinSetCapture( HWND_DESKTOP,
|
||||
window == NULL ? NULLHANDLE
|
||||
: ((PWINDATA)window->driverdata)->hwnd )
|
||||
? 0 : -1;
|
||||
}
|
||||
|
||||
static Uint32 OS2_GetGlobalMouseState(int *x, int *y)
|
||||
{
|
||||
POINTL pointl;
|
||||
ULONG ulRes;
|
||||
|
||||
WinQueryPointerPos( HWND_DESKTOP, &pointl );
|
||||
*x = pointl.x;
|
||||
*y = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN ) - pointl.y - 1;
|
||||
|
||||
ulRes = WinGetKeyState( HWND_DESKTOP, VK_BUTTON1 ) & 0x8000
|
||||
? SDL_BUTTON_LMASK : 0;
|
||||
if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON2 ) & 0x8000 )
|
||||
ulRes |= SDL_BUTTON_RMASK;
|
||||
if ( WinGetKeyState( HWND_DESKTOP, VK_BUTTON3 ) & 0x8000 )
|
||||
ulRes |= SDL_BUTTON_MMASK;
|
||||
|
||||
return ulRes;
|
||||
}
|
||||
|
||||
|
||||
void OS2_InitMouse(_THIS, ULONG hab)
|
||||
{
|
||||
SDL_Mouse *pSDLMouse = SDL_GetMouse();
|
||||
|
||||
pSDLMouse->CreateCursor = OS2_CreateCursor;
|
||||
pSDLMouse->CreateSystemCursor = OS2_CreateSystemCursor;
|
||||
pSDLMouse->ShowCursor = OS2_ShowCursor;
|
||||
pSDLMouse->FreeCursor = OS2_FreeCursor;
|
||||
pSDLMouse->WarpMouse = OS2_WarpMouse;
|
||||
pSDLMouse->WarpMouseGlobal = OS2_WarpMouseGlobal;
|
||||
pSDLMouse->CaptureMouse = OS2_CaptureMouse;
|
||||
pSDLMouse->GetGlobalMouseState = OS2_GetGlobalMouseState;
|
||||
|
||||
SDL_SetDefaultCursor( OS2_CreateSystemCursor( SDL_SYSTEM_CURSOR_ARROW ) );
|
||||
if ( hptrCursor == NULLHANDLE )
|
||||
hptrCursor = WinQuerySysPointer( HWND_DESKTOP, SPTR_ARROW, TRUE );
|
||||
|
||||
SDL_SetDoubleClickTime( WinQuerySysValue( HWND_DESKTOP, SV_DBLCLKTIME ) );
|
||||
}
|
||||
|
||||
void OS2_QuitMouse(_THIS)
|
||||
{
|
||||
SDL_Mouse *pSDLMouse = SDL_GetMouse();
|
||||
|
||||
if ( pSDLMouse->def_cursor != NULL )
|
||||
{
|
||||
SDL_free( pSDLMouse->def_cursor );
|
||||
pSDLMouse->def_cursor = NULL;
|
||||
pSDLMouse->cur_cursor = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_OS2 */
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_os2mouse_h
|
||||
#define _SDL_os2mouse_h
|
||||
|
||||
extern HPOINTER hptrCursor;
|
||||
|
||||
extern void OS2_InitMouse(_THIS, ULONG hab);
|
||||
extern void OS2_QuitMouse(_THIS);
|
||||
|
||||
#endif /* _SDL_os2mouse_h */
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#ifndef _SDL_os2output_
|
||||
#define _SDL_os2output_
|
||||
|
||||
#include ".\core\os2\SDL_os2.h"
|
||||
|
||||
typedef struct _VODATA *PVODATA;
|
||||
|
||||
typedef struct _VIDEOOUTPUTINFO {
|
||||
ULONG ulBPP;
|
||||
ULONG fccColorEncoding;
|
||||
ULONG ulScanLineSize;
|
||||
ULONG ulHorizResolution;
|
||||
ULONG ulVertResolution;
|
||||
} VIDEOOUTPUTINFO, *PVIDEOOUTPUTINFO;
|
||||
|
||||
typedef struct _OS2VIDEOOUTPUT {
|
||||
BOOL (*QueryInfo)(PVIDEOOUTPUTINFO pInfo);
|
||||
PVODATA (*Open)();
|
||||
VOID (*Close)(PVODATA pVOData);
|
||||
BOOL (*SetVisibleRegion)(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode, HRGN hrgnShape,
|
||||
BOOL fVisible);
|
||||
PVOID (*VideoBufAlloc)(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize);
|
||||
VOID (*VideoBufFree)(PVODATA pVOData);
|
||||
BOOL (*Update)(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects);
|
||||
} OS2VIDEOOUTPUT, *POS2VIDEOOUTPUT;
|
||||
|
||||
extern OS2VIDEOOUTPUT voDive;
|
||||
extern OS2VIDEOOUTPUT voVMan;
|
||||
|
||||
#endif // _SDL_os2output_
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_OS2
|
||||
|
||||
#include "SDL_os2util.h"
|
||||
|
||||
|
||||
HPOINTER utilCreatePointer(SDL_Surface *surface, ULONG ulHotX, ULONG ulHotY)
|
||||
{
|
||||
HBITMAP hbm;
|
||||
BITMAPINFOHEADER2 bmih = { 0 };
|
||||
BITMAPINFO bmi = { 0 };
|
||||
HPS hps;
|
||||
PULONG pulBitmap;
|
||||
PULONG pulDst, pulSrc, pulDstMask;
|
||||
ULONG ulY, ulX;
|
||||
HPOINTER hptr = NULLHANDLE;
|
||||
|
||||
if ( surface->format->format != SDL_PIXELFORMAT_ARGB8888 )
|
||||
{
|
||||
debug( "Image format should be SDL_PIXELFORMAT_ARGB8888" );
|
||||
return NULLHANDLE;
|
||||
}
|
||||
|
||||
pulBitmap = SDL_malloc( surface->h * surface->w * 4 * 2 );
|
||||
if ( pulBitmap == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULLHANDLE;
|
||||
}
|
||||
|
||||
// pulDst - last line of surface (image) part of the result bitmap's
|
||||
pulDst = &pulBitmap[ (surface->h - 1) * surface->w ];
|
||||
// pulDstMask - last line of mask part of the result bitmap's
|
||||
pulDstMask = &pulBitmap[ (2 * surface->h - 1) * surface->w ];
|
||||
// pulSrc - first line of source image
|
||||
pulSrc = (PULONG)surface->pixels;
|
||||
|
||||
for( ulY = 0; ulY < surface->h; ulY++ )
|
||||
{
|
||||
for( ulX = 0; ulX < surface->w; ulX++ )
|
||||
{
|
||||
if ( (pulSrc[ulX] & 0xFF000000) == 0 )
|
||||
{
|
||||
pulDst[ulX] = 0;
|
||||
pulDstMask[ulX] = 0xFFFFFFFF;
|
||||
}
|
||||
else
|
||||
{
|
||||
pulDst[ulX] = pulSrc[ulX] & 0xFFFFFF;
|
||||
pulDstMask[ulX] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Set image and mask pointers on one line up
|
||||
pulDst -= surface->w;
|
||||
pulDstMask -= surface->w;
|
||||
// Set source image pointer to the next line
|
||||
pulSrc = (PULONG)( ((PCHAR)pulSrc) + surface->pitch );
|
||||
}
|
||||
|
||||
// Create system bitmap object.
|
||||
|
||||
bmih.cbFix = sizeof(BITMAPINFOHEADER2);
|
||||
bmih.cx = surface->w;
|
||||
bmih.cy = 2 * surface->h;
|
||||
bmih.cPlanes = 1;
|
||||
bmih.cBitCount = 32;
|
||||
bmih.ulCompression = BCA_UNCOMP;
|
||||
bmih.cbImage = bmih.cx * bmih.cy * 4;
|
||||
|
||||
bmi.cbFix = sizeof(BITMAPINFOHEADER);
|
||||
bmi.cx = bmih.cx;
|
||||
bmi.cy = bmih.cy;
|
||||
bmi.cPlanes = 1;
|
||||
bmi.cBitCount = 32;
|
||||
|
||||
hps = WinGetPS( HWND_DESKTOP );
|
||||
hbm = GpiCreateBitmap( hps, (PBITMAPINFOHEADER2)&bmih, CBM_INIT,
|
||||
(PBYTE)pulBitmap, (PBITMAPINFO2)&bmi );
|
||||
if ( hbm == GPI_ERROR )
|
||||
debug( "GpiCreateBitmap() failed" );
|
||||
else
|
||||
{
|
||||
// Create a system pointer object.
|
||||
hptr = WinCreatePointer( HWND_DESKTOP, hbm, TRUE, ulHotX, ulHotY );
|
||||
if ( hptr == NULLHANDLE )
|
||||
debug( "WinCreatePointer() failed" );
|
||||
}
|
||||
GpiDeleteBitmap( hbm );
|
||||
|
||||
WinReleasePS( hps );
|
||||
SDL_free( pulBitmap );
|
||||
|
||||
return hptr;
|
||||
}
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_OS2 */
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef _SDL_os2util_h
|
||||
#define _SDL_os2util_h
|
||||
|
||||
#include "SDL_log.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include "../../core/os2/SDL_os2.h"
|
||||
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#include <os2.h>
|
||||
|
||||
/*#define debug(s,...) SDL_LogDebug( SDL_LOG_CATEGORY_VIDEO, \
|
||||
__func__"(): "##s, ##__VA_ARGS__ )*/
|
||||
|
||||
HPOINTER utilCreatePointer(SDL_Surface *surface, ULONG ulHotX, ULONG ulHotY);
|
||||
|
||||
#endif // _SDL_os2util_h
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
|
||||
#ifndef _SDL_os2video_h
|
||||
#define _SDL_os2video_h
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
#include ".\core\os2\SDL_os2.h"
|
||||
|
||||
#define INCL_DOS
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#define INCL_OS2MM
|
||||
#define INCL_DOSMEMMGR
|
||||
#include <os2.h>
|
||||
//#include <gradd.h> // Defines FOURCC_xxxx
|
||||
|
||||
|
||||
#include "SDL_os2mouse.h"
|
||||
#include "SDL_os2output.h"
|
||||
|
||||
typedef struct SDL_VideoData {
|
||||
HAB hab;
|
||||
HMQ hmq;
|
||||
POS2VIDEOOUTPUT pOutput; // Video output routines.
|
||||
} SDL_VideoData, *PSDL_VideoData;
|
||||
|
||||
typedef struct _WINDATA {
|
||||
SDL_Window *window;
|
||||
POS2VIDEOOUTPUT pOutput; // Video output routines.
|
||||
HWND hwndFrame;
|
||||
HWND hwnd;
|
||||
PFNWP fnUserWndProc;
|
||||
PFNWP fnWndFrameProc;
|
||||
|
||||
PVODATA pVOData; // Video output data.
|
||||
|
||||
HRGN hrgnShape;
|
||||
HPOINTER hptrIcon;
|
||||
RECTL rectlBeforeFS;
|
||||
|
||||
LONG lSkipWMSize;
|
||||
LONG lSkipWMMove;
|
||||
LONG lSkipWMMouseMove;
|
||||
LONG lSkipWMVRNEnabled;
|
||||
LONG lSkipWMAdjustFramePos;
|
||||
} WINDATA, *PWINDATA;
|
||||
|
||||
typedef struct _DISPLAYDATA {
|
||||
ULONG ulDPIHor;
|
||||
ULONG ulDPIVer;
|
||||
ULONG ulDPIDiag;
|
||||
} DISPLAYDATA, *PDISPLAYDATA;
|
||||
|
||||
typedef struct _MODEDATA {
|
||||
ULONG ulDepth;
|
||||
ULONG fccColorEncoding;
|
||||
ULONG ulScanLineBytes;
|
||||
} MODEDATA, *PMODEDATA;
|
||||
|
||||
|
||||
#endif /* _SDL_os2video_h */
|
|
@ -0,0 +1,512 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "../SDL_sysvideo.h"
|
||||
#define INCL_DOSERRORS
|
||||
#define INCL_DOSPROCESS
|
||||
#define INCL_DOSMODULEMGR
|
||||
#define INCL_WIN
|
||||
#define INCL_GPI
|
||||
#define INCL_GPIBITMAPS // GPI bit map functions
|
||||
#include <os2.h>
|
||||
#define INCL_GRE_DEVICE
|
||||
#define INCL_GRE_DEVMISC
|
||||
#include <pmddi.h>
|
||||
#include "SDL_os2output.h"
|
||||
#include "gradd.h"
|
||||
#include "SDL_os2video.h"
|
||||
|
||||
typedef struct _VODATA {
|
||||
PVOID pBuffer;
|
||||
HRGN hrgnVisible;
|
||||
ULONG ulBPP;
|
||||
ULONG ulScanLineSize;
|
||||
ULONG ulWidth;
|
||||
ULONG ulHeight;
|
||||
ULONG ulScreenHeight;
|
||||
ULONG ulScreenBytesPerLine;
|
||||
RECTL rectlWin;
|
||||
|
||||
PRECTL pRectl;
|
||||
ULONG cRectl;
|
||||
PBLTRECT pBltRect;
|
||||
ULONG cBltRect;
|
||||
} VODATA;
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo);
|
||||
static PVODATA voOpen();
|
||||
static VOID voClose(PVODATA pVOData);
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible);
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize);
|
||||
static VOID voVideoBufFree(PVODATA pVOData);
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects);
|
||||
|
||||
OS2VIDEOOUTPUT voVMan = {
|
||||
voQueryInfo,
|
||||
voOpen,
|
||||
voClose,
|
||||
voSetVisibleRegion,
|
||||
voVideoBufAlloc,
|
||||
voVideoBufFree,
|
||||
voUpdate
|
||||
};
|
||||
|
||||
|
||||
static HMODULE hmodVMan = NULLHANDLE;
|
||||
static FNVMIENTRY *pfnVMIEntry = NULL;
|
||||
static ULONG ulVRAMAddress = 0;
|
||||
|
||||
VOID APIENTRY ExitVMan(VOID)
|
||||
{
|
||||
if ( ( ulVRAMAddress != 0 ) && ( hmodVMan != NULLHANDLE ) )
|
||||
{
|
||||
pfnVMIEntry( 0, VMI_CMD_TERMPROC, NULL, NULL );
|
||||
DosFreeModule( hmodVMan );
|
||||
}
|
||||
|
||||
DosExitList( EXLST_EXIT, (PFNEXITLIST)NULL );
|
||||
}
|
||||
|
||||
static BOOL _vmanInit()
|
||||
{
|
||||
ULONG ulRC;
|
||||
CHAR acBuf[255];
|
||||
INITPROCOUT stInitProcOut;
|
||||
|
||||
if ( hmodVMan != NULLHANDLE )
|
||||
// Already was initialized.
|
||||
return TRUE;
|
||||
|
||||
// Load vman.dll
|
||||
ulRC = DosLoadModule( &acBuf, sizeof(acBuf), "VMAN", &hmodVMan );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Could not load VMAN.DLL, rc = %u : %s", ulRC, &acBuf );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Get VMIEntry.
|
||||
ulRC = DosQueryProcAddr( hmodVMan, 0L, "VMIEntry", (PFN *)&pfnVMIEntry );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "Could not query address of pfnVMIEntry func. of VMAN.DLL, "
|
||||
"rc = %u", ulRC );
|
||||
DosFreeModule( hmodVMan );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// VMAN initialization.
|
||||
stInitProcOut.ulLength = sizeof(stInitProcOut);
|
||||
ulRC = pfnVMIEntry( 0, VMI_CMD_INITPROC, NULL, &stInitProcOut );
|
||||
if ( ulRC != RC_SUCCESS )
|
||||
{
|
||||
debug( "Could not initialize VMAN for this process" );
|
||||
pfnVMIEntry = NULL;
|
||||
DosFreeModule( hmodVMan );
|
||||
hmodVMan = NULLHANDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Store video memory virtual address.
|
||||
ulVRAMAddress = stInitProcOut.ulVRAMVirt;
|
||||
// We use exit list for VMI_CMD_TERMPROC.
|
||||
if ( DosExitList( EXLST_ADD | 0x00001000, (PFNEXITLIST)ExitVMan )
|
||||
!= NO_ERROR )
|
||||
debug( "DosExitList() failed" );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PRECTL _getRectlArray(PVODATA pVOData, ULONG cRects)
|
||||
{
|
||||
PRECTL pRectl;
|
||||
|
||||
if ( pVOData->cRectl >= cRects )
|
||||
return pVOData->pRectl;
|
||||
|
||||
pRectl = SDL_realloc( pVOData->pRectl, cRects * sizeof(RECTL) );
|
||||
if ( pRectl == NULL )
|
||||
return NULL;
|
||||
|
||||
pVOData->pRectl = pRectl;
|
||||
pVOData->cRectl = cRects;
|
||||
return pRectl;
|
||||
}
|
||||
|
||||
static PBLTRECT _getBltRectArray(PVODATA pVOData, ULONG cRects)
|
||||
{
|
||||
PBLTRECT pBltRect;
|
||||
|
||||
if ( pVOData->cBltRect >= cRects )
|
||||
return pVOData->pBltRect;
|
||||
|
||||
pBltRect = SDL_realloc( pVOData->pBltRect, cRects * sizeof(BLTRECT) );
|
||||
if ( pBltRect == NULL )
|
||||
return NULL;
|
||||
|
||||
pVOData->pBltRect = pBltRect;
|
||||
pVOData->cBltRect = cRects;
|
||||
return pBltRect;
|
||||
}
|
||||
|
||||
|
||||
static BOOL voQueryInfo(PVIDEOOUTPUTINFO pInfo)
|
||||
{
|
||||
ULONG ulRC;
|
||||
GDDMODEINFO sCurModeInfo;
|
||||
|
||||
if ( !_vmanInit() )
|
||||
return FALSE;
|
||||
|
||||
// Query current (desktop) mode.
|
||||
ulRC = pfnVMIEntry( 0, VMI_CMD_QUERYCURRENTMODE, NULL, &sCurModeInfo );
|
||||
if ( ulRC != RC_SUCCESS )
|
||||
{
|
||||
debug( "Could not query desktop video mode." );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pInfo->ulBPP = sCurModeInfo.ulBpp;
|
||||
pInfo->ulHorizResolution = sCurModeInfo.ulHorizResolution;
|
||||
pInfo->ulVertResolution = sCurModeInfo.ulVertResolution;
|
||||
pInfo->ulScanLineSize = sCurModeInfo.ulScanLineSize;
|
||||
pInfo->fccColorEncoding = sCurModeInfo.fccColorEncoding;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static PVODATA voOpen()
|
||||
{
|
||||
PVODATA pVOData;
|
||||
|
||||
if ( !_vmanInit() )
|
||||
return NULL;
|
||||
|
||||
pVOData = SDL_calloc( 1, sizeof(VODATA) );
|
||||
if ( pVOData == NULL )
|
||||
{
|
||||
SDL_OutOfMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pVOData;
|
||||
}
|
||||
|
||||
static VOID voClose(PVODATA pVOData)
|
||||
{
|
||||
if ( pVOData->pRectl != NULL )
|
||||
SDL_free( pVOData->pRectl );
|
||||
|
||||
if ( pVOData->pBltRect != NULL )
|
||||
SDL_free( pVOData->pBltRect );
|
||||
|
||||
voVideoBufFree( pVOData );
|
||||
}
|
||||
|
||||
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd,
|
||||
SDL_DisplayMode *pSDLDisplayMode,
|
||||
HRGN hrgnShape, BOOL fVisible)
|
||||
{
|
||||
HPS hps;
|
||||
BOOL fSuccess = FALSE;
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
|
||||
if ( pVOData->hrgnVisible != NULLHANDLE )
|
||||
{
|
||||
GpiDestroyRegion( hps, pVOData->hrgnVisible );
|
||||
pVOData->hrgnVisible = NULLHANDLE;
|
||||
}
|
||||
|
||||
if ( fVisible )
|
||||
{
|
||||
// Query visible rectangles
|
||||
|
||||
pVOData->hrgnVisible = GpiCreateRegion( hps, 0, NULL );
|
||||
if ( pVOData->hrgnVisible == NULLHANDLE )
|
||||
{
|
||||
SDL_SetError( "GpiCreateRegion() failed" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( WinQueryVisibleRegion( hwnd, pVOData->hrgnVisible ) == RGN_ERROR )
|
||||
{
|
||||
GpiDestroyRegion( hps, pVOData->hrgnVisible );
|
||||
pVOData->hrgnVisible = NULLHANDLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( hrgnShape != NULLHANDLE )
|
||||
GpiCombineRegion( hps, pVOData->hrgnVisible, pVOData->hrgnVisible,
|
||||
hrgnShape, CRGN_AND );
|
||||
fSuccess = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
WinQueryWindowRect( hwnd, &pVOData->rectlWin );
|
||||
WinMapWindowPoints( hwnd, HWND_DESKTOP, (PPOINTL)&pVOData->rectlWin, 2 );
|
||||
|
||||
if ( pSDLDisplayMode != NULL )
|
||||
{
|
||||
pVOData->ulScreenHeight = pSDLDisplayMode->h;
|
||||
pVOData->ulScreenBytesPerLine =
|
||||
((PMODEDATA)pSDLDisplayMode->driverdata)->ulScanLineBytes;
|
||||
}
|
||||
}
|
||||
|
||||
WinReleasePS( hps );
|
||||
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight,
|
||||
ULONG ulBPP, ULONG fccColorEncoding,
|
||||
PULONG pulScanLineSize)
|
||||
{
|
||||
ULONG ulRC;
|
||||
ULONG ulScanLineSize = ulWidth * (ulBPP >> 3);
|
||||
|
||||
// Destroy previous buffer.
|
||||
voVideoBufFree( pVOData );
|
||||
|
||||
if ( ( ulWidth == 0 ) || ( ulHeight == 0 ) || ( ulBPP == 0 ) )
|
||||
return NULL;
|
||||
|
||||
// Bytes per line.
|
||||
ulScanLineSize = ( ulScanLineSize + 3 ) & ~3; /* 4-byte aligning */
|
||||
*pulScanLineSize = ulScanLineSize;
|
||||
|
||||
ulRC = DosAllocMem( &pVOData->pBuffer,
|
||||
(ulHeight * ulScanLineSize) + sizeof(ULONG),
|
||||
PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE );
|
||||
if ( ulRC != NO_ERROR )
|
||||
{
|
||||
debug( "DosAllocMem(), rc = %u", ulRC );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pVOData->ulBPP = ulBPP;
|
||||
pVOData->ulScanLineSize = ulScanLineSize;
|
||||
pVOData->ulWidth = ulWidth;
|
||||
pVOData->ulHeight = ulHeight;
|
||||
|
||||
return pVOData->pBuffer;
|
||||
}
|
||||
|
||||
static VOID voVideoBufFree(PVODATA pVOData)
|
||||
{
|
||||
ULONG ulRC;
|
||||
|
||||
if ( pVOData->pBuffer == NULL )
|
||||
return;
|
||||
|
||||
ulRC = DosFreeMem( pVOData->pBuffer );
|
||||
if ( ulRC != NO_ERROR )
|
||||
debug( "DosFreeMem(), rc = %u", ulRC );
|
||||
else
|
||||
pVOData->pBuffer = NULL;
|
||||
}
|
||||
|
||||
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects,
|
||||
ULONG cSDLRects)
|
||||
{
|
||||
PRECTL prectlDst, prectlScan;
|
||||
HPS hps;
|
||||
HRGN hrgnUpdate;
|
||||
RGNRECT rgnCtl;
|
||||
SDL_Rect stSDLRectDef;
|
||||
BMAPINFO bmiSrc;
|
||||
BMAPINFO bmiDst;
|
||||
PPOINTL pptlSrcOrg;
|
||||
PBLTRECT pbrDst;
|
||||
HWREQIN sHWReqIn;
|
||||
BITBLTINFO sBitbltInfo = { 0 };
|
||||
ULONG ulIdx;
|
||||
// RECTL rectlScreenUpdate;
|
||||
|
||||
if ( pVOData->pBuffer == NULL )
|
||||
return FALSE;
|
||||
|
||||
if ( pVOData->hrgnVisible == NULLHANDLE )
|
||||
return TRUE;
|
||||
|
||||
bmiSrc.ulLength = sizeof(BMAPINFO);
|
||||
bmiSrc.ulType = BMAP_MEMORY;
|
||||
bmiSrc.ulWidth = pVOData->ulWidth;
|
||||
bmiSrc.ulHeight = pVOData->ulHeight;
|
||||
bmiSrc.ulBpp = pVOData->ulBPP;
|
||||
bmiSrc.ulBytesPerLine = pVOData->ulScanLineSize;
|
||||
bmiSrc.pBits = (PBYTE)pVOData->pBuffer;
|
||||
|
||||
bmiDst.ulLength = sizeof(BMAPINFO);
|
||||
bmiDst.ulType = BMAP_VRAM;
|
||||
bmiDst.pBits = (PBYTE)ulVRAMAddress;
|
||||
bmiDst.ulWidth = bmiSrc.ulWidth;
|
||||
bmiDst.ulHeight = bmiSrc.ulHeight;
|
||||
bmiDst.ulBpp = bmiSrc.ulBpp;
|
||||
bmiDst.ulBytesPerLine = pVOData->ulScreenBytesPerLine;
|
||||
|
||||
// List of update rectangles. This is the intersection of requested
|
||||
// rectangles and visible rectangles.
|
||||
|
||||
if ( cSDLRects == 0 )
|
||||
{
|
||||
// Full update requested.
|
||||
stSDLRectDef.x = 0;
|
||||
stSDLRectDef.y = 0;
|
||||
stSDLRectDef.w = bmiSrc.ulWidth;
|
||||
stSDLRectDef.h = bmiSrc.ulHeight;
|
||||
pSDLRects = &stSDLRectDef;
|
||||
cSDLRects = 1;
|
||||
}
|
||||
|
||||
// Make list of destionation rectangles (prectlDst) list from the source
|
||||
// list (prectl).
|
||||
prectlDst = _getRectlArray( pVOData, cSDLRects );
|
||||
if ( prectlDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
return FALSE;
|
||||
}
|
||||
prectlScan = prectlDst;
|
||||
for( ulIdx = 0; ulIdx < cSDLRects; ulIdx++, pSDLRects++, prectlScan++ )
|
||||
{
|
||||
prectlScan->xLeft = pSDLRects->x;
|
||||
prectlScan->yTop = pVOData->ulHeight - pSDLRects->y;
|
||||
prectlScan->xRight = prectlScan->xLeft + pSDLRects->w;
|
||||
prectlScan->yBottom = prectlScan->yTop - pSDLRects->h;
|
||||
}
|
||||
|
||||
hps = WinGetPS( hwnd );
|
||||
if ( hps == NULLHANDLE )
|
||||
return FALSE;
|
||||
|
||||
// Make destination region to update.
|
||||
hrgnUpdate = GpiCreateRegion( hps, cSDLRects, prectlDst );
|
||||
// "AND" on visible and destination regions, result is region to update.
|
||||
GpiCombineRegion( hps, hrgnUpdate, hrgnUpdate, pVOData->hrgnVisible,
|
||||
CRGN_AND );
|
||||
|
||||
// Get rectangles of the region to update.
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = 0;
|
||||
rgnCtl.ulDirection = 1;
|
||||
rgnCtl.crcReturned = 0;
|
||||
GpiQueryRegionRects( hps, hrgnUpdate, NULL, &rgnCtl, NULL );
|
||||
if ( rgnCtl.crcReturned == 0 )
|
||||
{
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
return TRUE;
|
||||
}
|
||||
// We don't need prectlDst, use it again to store update regions.
|
||||
prectlDst = _getRectlArray( pVOData, rgnCtl.crcReturned );
|
||||
if ( prectlDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
return FALSE;
|
||||
}
|
||||
rgnCtl.ircStart = 1;
|
||||
rgnCtl.crc = rgnCtl.crcReturned;
|
||||
rgnCtl.ulDirection = 1;
|
||||
GpiQueryRegionRects( hps, hrgnUpdate, NULL, &rgnCtl, prectlDst );
|
||||
GpiDestroyRegion( hps, hrgnUpdate );
|
||||
WinReleasePS( hps );
|
||||
cSDLRects = rgnCtl.crcReturned;
|
||||
// Now cRect/prectlDst is a list of regions in window (update && visible).
|
||||
|
||||
// Make lists for blitting from update regions.
|
||||
|
||||
pbrDst = _getBltRectArray( pVOData, cSDLRects );
|
||||
if ( pbrDst == NULL )
|
||||
{
|
||||
debug( "Not enough memory" );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
prectlScan = prectlDst;
|
||||
pptlSrcOrg = (PPOINTL)prectlDst; // Yes, this memory block will be used again.
|
||||
for( ulIdx = 0; ulIdx < cSDLRects; ulIdx++, prectlScan++, pptlSrcOrg++ )
|
||||
{
|
||||
pbrDst[ulIdx].ulXOrg = pVOData->rectlWin.xLeft + prectlScan->xLeft;
|
||||
pbrDst[ulIdx].ulYOrg = pVOData->ulScreenHeight -
|
||||
( pVOData->rectlWin.yBottom + prectlScan->yTop );
|
||||
pbrDst[ulIdx].ulXExt = prectlScan->xRight - prectlScan->xLeft;
|
||||
pbrDst[ulIdx].ulYExt = prectlScan->yTop - prectlScan->yBottom;
|
||||
pptlSrcOrg->x = prectlScan->xLeft;
|
||||
pptlSrcOrg->y = bmiSrc.ulHeight - prectlScan->yTop;
|
||||
}
|
||||
pptlSrcOrg = (PPOINTL)prectlDst;
|
||||
|
||||
// Request HW
|
||||
sHWReqIn.ulLength = sizeof(HWREQIN);
|
||||
sHWReqIn.ulFlags = REQUEST_HW;
|
||||
sHWReqIn.cScrChangeRects = 1;
|
||||
sHWReqIn.arectlScreen = &pVOData->rectlWin;
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_REQUESTHW, &sHWReqIn, NULL ) != RC_SUCCESS )
|
||||
{
|
||||
debug( "pfnVMIEntry(,VMI_CMD_REQUESTHW,,) failed" );
|
||||
sHWReqIn.cScrChangeRects = 0; // for fail signal only.
|
||||
}
|
||||
else
|
||||
{
|
||||
RECTL rclSrcBounds;
|
||||
|
||||
rclSrcBounds.xLeft = 0;
|
||||
rclSrcBounds.yBottom = 0;
|
||||
rclSrcBounds.xRight = bmiSrc.ulWidth;
|
||||
rclSrcBounds.yTop = bmiSrc.ulHeight;
|
||||
|
||||
sBitbltInfo.ulLength = sizeof(BITBLTINFO);
|
||||
sBitbltInfo.ulBltFlags = BF_DEFAULT_STATE | BF_ROP_INCL_SRC | BF_PAT_HOLLOW;
|
||||
sBitbltInfo.cBlits = cSDLRects;
|
||||
sBitbltInfo.ulROP = ROP_SRCCOPY;
|
||||
sBitbltInfo.pSrcBmapInfo = &bmiSrc;
|
||||
sBitbltInfo.pDstBmapInfo = &bmiDst;
|
||||
sBitbltInfo.prclSrcBounds = &rclSrcBounds;
|
||||
sBitbltInfo.prclDstBounds = &pVOData->rectlWin;
|
||||
sBitbltInfo.aptlSrcOrg = pptlSrcOrg;
|
||||
sBitbltInfo.abrDst = pbrDst;
|
||||
|
||||
// Screen update.
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_BITBLT, &sBitbltInfo, NULL ) != RC_SUCCESS )
|
||||
{
|
||||
debug( "pfnVMIEntry(,VMI_CMD_BITBLT,,) failed" );
|
||||
sHWReqIn.cScrChangeRects = 0; // for fail signal only.
|
||||
}
|
||||
|
||||
// Release HW.
|
||||
sHWReqIn.ulFlags = 0;
|
||||
if ( pfnVMIEntry( 0, VMI_CMD_REQUESTHW, &sHWReqIn, NULL ) != RC_SUCCESS )
|
||||
debug( "pfnVMIEntry(,VMI_CMD_REQUESTHW,,) failed" );
|
||||
}
|
||||
|
||||
return sHWReqIn.cScrChangeRects != 0;
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely.
|
||||
*/
|
||||
|
||||
#include "testnative.h"
|
||||
|
||||
#ifdef TEST_NATIVE_OS2
|
||||
|
||||
#define WIN_CLIENT_CLASS "SDL Test"
|
||||
|
||||
static void *CreateWindowNative(int w, int h);
|
||||
static void DestroyWindowNative(void *window);
|
||||
|
||||
NativeWindowFactory OS2WindowFactory = {
|
||||
"OS/2",
|
||||
CreateWindowNative,
|
||||
DestroyWindowNative
|
||||
};
|
||||
|
||||
static void *CreateWindowNative(int w, int h)
|
||||
{
|
||||
HWND hwnd;
|
||||
HWND hwndFrame;
|
||||
ULONG ulFrameFlags = FCF_TASKLIST | FCF_DLGBORDER | FCF_TITLEBAR |
|
||||
FCF_SYSMENU | FCF_SHELLPOSITION |
|
||||
FCF_SIZEBORDER | FCF_MINBUTTON | FCF_MAXBUTTON;
|
||||
|
||||
WinRegisterClass( 0, WIN_CLIENT_CLASS, WinDefWindowProc,
|
||||
CS_SIZEREDRAW | CS_MOVENOTIFY,
|
||||
sizeof(ULONG) ); // We should have minimum 4 bytes.
|
||||
|
||||
hwndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulFrameFlags,
|
||||
WIN_CLIENT_CLASS, "SDL Test", 0, 0, 1, &hwnd );
|
||||
if ( hwndFrame == NULLHANDLE )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
WinSetWindowPos( hwndFrame, HWND_TOP, 0, 0, w, h,
|
||||
SWP_ZORDER | SWP_ACTIVATE | SWP_SIZE | SWP_SHOW );
|
||||
|
||||
return (void *)hwndFrame; // We may returns client or frame window handle
|
||||
// for SDL_CreateWindowFrom().
|
||||
}
|
||||
|
||||
static void DestroyWindowNative(void *window)
|
||||
{
|
||||
WinDestroyWindow( (HWND)window );
|
||||
}
|
||||
|
||||
#endif /* TEST_NATIVE_OS2 */
|
Loading…
Reference in New Issue