src/events/SDL_events.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 12 Nov 2008 17:23:40 +0000
branchSDL-1.2
changeset 4158 96ce26f24b01
parent 3975 e85e65aec22f
child 4159 a1b03ba2fcd0
permissions -rw-r--r--
Date: Sun, 7 Sep 2008 15:17:00 +0200
From: c2woody@gmx.net
Subject: [SDL] SDL 1.2 doube free/pointer zeroing missing

Hello,

this is about a crash/debug breakage for the current SDL 1.2
source tree (today's svn checkout, same problem in 1.2.13 and
before as far as relevant).
In some places memory is free()d but the associated pointer
is not zeroed, leading to for example double free()s.

For me this happened because SDL_StopEventThread() was executed
twice (during restart of the subsystems), once for the close
down in SDL_VideoQuit() and once at the startup, right at the
beginning of SDL_StartEventLoop(). Thus the code
SDL_DestroyMutex(SDL_EventQ.lock);
(see SDL_events.c) was called twice and executed the SDL_free(mutex);
twice as well, leading to a crash (msvc 64bit for which it was noticed).

I've tried to check all other occurrences of SDL_free and similar
code in msvc, see the attached patch (udiff against revision 4082).
Non-windows only codepaths have neither been checked nor touched.

Comments/ideas welcome.

Attached patch: NULLifies some pointers after they have been free()d.
slouken@0
     1
/*
slouken@0
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@0
     4
slouken@0
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@0
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@0
     9
slouken@0
    10
    This library is distributed in the hope that it will be useful,
slouken@0
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@0
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@0
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@0
    18
slouken@0
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@0
    21
*/
slouken@1402
    22
#include "SDL_config.h"
slouken@0
    23
slouken@0
    24
/* General event handling code for SDL */
slouken@0
    25
slouken@0
    26
#include "SDL.h"
slouken@0
    27
#include "SDL_syswm.h"
slouken@0
    28
#include "SDL_sysevents.h"
slouken@1361
    29
#include "SDL_events_c.h"
slouken@1361
    30
#include "../timer/SDL_timer_c.h"
slouken@1361
    31
#if !SDL_JOYSTICK_DISABLED
slouken@1361
    32
#include "../joystick/SDL_joystick_c.h"
slouken@1361
    33
#endif
slouken@0
    34
slouken@0
    35
/* Public data -- the event filter */
slouken@0
    36
SDL_EventFilter SDL_EventOK = NULL;
slouken@0
    37
Uint8 SDL_ProcessEvents[SDL_NUMEVENTS];
slouken@0
    38
static Uint32 SDL_eventstate = 0;
slouken@0
    39
slouken@0
    40
/* Private data -- event queue */
slouken@0
    41
#define MAXEVENTS	128
slouken@0
    42
static struct {
slouken@0
    43
	SDL_mutex *lock;
slouken@0
    44
	int active;
slouken@0
    45
	int head;
slouken@0
    46
	int tail;
slouken@0
    47
	SDL_Event event[MAXEVENTS];
slouken@0
    48
	int wmmsg_next;
slouken@0
    49
	struct SDL_SysWMmsg wmmsg[MAXEVENTS];
slouken@0
    50
} SDL_EventQ;
slouken@0
    51
slouken@0
    52
/* Private data -- event locking structure */
slouken@0
    53
static struct {
slouken@0
    54
	SDL_mutex *lock;
slouken@0
    55
	int safe;
slouken@0
    56
} SDL_EventLock;
slouken@0
    57
slouken@0
    58
/* Thread functions */
slouken@0
    59
static SDL_Thread *SDL_EventThread = NULL;	/* Thread handle */
slouken@0
    60
static Uint32 event_thread;			/* The event thread id */
slouken@0
    61
slouken@0
    62
void SDL_Lock_EventThread(void)
slouken@0
    63
{
slouken@0
    64
	if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) {
slouken@0
    65
		/* Grab lock and spin until we're sure event thread stopped */
slouken@0
    66
		SDL_mutexP(SDL_EventLock.lock);
slouken@0
    67
		while ( ! SDL_EventLock.safe ) {
slouken@0
    68
			SDL_Delay(1);
slouken@0
    69
		}
slouken@0
    70
	}
slouken@0
    71
}
slouken@0
    72
void SDL_Unlock_EventThread(void)
slouken@0
    73
{
slouken@0
    74
	if ( SDL_EventThread && (SDL_ThreadID() != event_thread) ) {
slouken@0
    75
		SDL_mutexV(SDL_EventLock.lock);
slouken@0
    76
	}
slouken@0
    77
}
slouken@0
    78
icculus@1190
    79
#ifdef __OS2__
icculus@1190
    80
/*
icculus@1190
    81
 * We'll increase the priority of GobbleEvents thread, so it will process
icculus@1190
    82
 *  events in time for sure! For this, we need the DosSetPriority() API
icculus@1190
    83
 *  from the os2.h include file.
icculus@1190
    84
 */
icculus@1190
    85
#define INCL_DOSPROCESS
icculus@1190
    86
#include <os2.h>
icculus@1190
    87
#include <time.h>
icculus@1190
    88
#endif
icculus@1190
    89
slouken@1769
    90
static int SDLCALL SDL_GobbleEvents(void *unused)
slouken@0
    91
{
slouken@0
    92
	event_thread = SDL_ThreadID();
icculus@1190
    93
icculus@1190
    94
#ifdef __OS2__
icculus@1190
    95
#ifdef USE_DOSSETPRIORITY
icculus@1190
    96
	/* Increase thread priority, so it will process events in time for sure! */
icculus@1190
    97
	DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +16, 0);
icculus@1190
    98
#endif
icculus@1190
    99
#endif
icculus@1190
   100
slouken@0
   101
	while ( SDL_EventQ.active ) {
slouken@0
   102
		SDL_VideoDevice *video = current_video;
slouken@0
   103
		SDL_VideoDevice *this  = current_video;
slouken@0
   104
slouken@0
   105
		/* Get events from the video subsystem */
slouken@0
   106
		if ( video ) {
slouken@0
   107
			video->PumpEvents(this);
slouken@0
   108
		}
slouken@0
   109
slouken@0
   110
		/* Queue pending key-repeat events */
slouken@0
   111
		SDL_CheckKeyRepeat();
slouken@0
   112
slouken@1361
   113
#if !SDL_JOYSTICK_DISABLED
slouken@0
   114
		/* Check for joystick state change */
slouken@0
   115
		if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) {
slouken@0
   116
			SDL_JoystickUpdate();
slouken@0
   117
		}
slouken@0
   118
#endif
slouken@0
   119
slouken@0
   120
		/* Give up the CPU for the rest of our timeslice */
slouken@0
   121
		SDL_EventLock.safe = 1;
slouken@1028
   122
		if ( SDL_timer_running ) {
slouken@0
   123
			SDL_ThreadedTimerCheck();
slouken@0
   124
		}
slouken@0
   125
		SDL_Delay(1);
slouken@0
   126
slouken@0
   127
		/* Check for event locking.
slouken@0
   128
		   On the P of the lock mutex, if the lock is held, this thread
slouken@0
   129
		   will wait until the lock is released before continuing.  The
slouken@0
   130
		   safe flag will be set, meaning that the other thread can go
slouken@0
   131
		   about it's business.  The safe flag is reset before the V,
slouken@0
   132
		   so as soon as the mutex is free, other threads can see that
slouken@0
   133
		   it's not safe to interfere with the event thread.
slouken@0
   134
		 */
slouken@0
   135
		SDL_mutexP(SDL_EventLock.lock);
slouken@0
   136
		SDL_EventLock.safe = 0;
slouken@0
   137
		SDL_mutexV(SDL_EventLock.lock);
slouken@0
   138
	}
slouken@0
   139
	SDL_SetTimerThreaded(0);
slouken@0
   140
	event_thread = 0;
slouken@0
   141
	return(0);
slouken@0
   142
}
slouken@0
   143
slouken@0
   144
static int SDL_StartEventThread(Uint32 flags)
slouken@0
   145
{
slouken@0
   146
	/* Reset everything to zero */
slouken@0
   147
	SDL_EventThread = NULL;
slouken@1336
   148
	SDL_memset(&SDL_EventLock, 0, sizeof(SDL_EventLock));
slouken@0
   149
slouken@0
   150
	/* Create the lock and set ourselves active */
slouken@1361
   151
#if !SDL_THREADS_DISABLED
slouken@0
   152
	SDL_EventQ.lock = SDL_CreateMutex();
slouken@0
   153
	if ( SDL_EventQ.lock == NULL ) {
slouken@1402
   154
#ifdef __MACOS__ /* MacOS classic you can't multithread, so no lock needed */
slouken@0
   155
		;
slouken@0
   156
#else
slouken@0
   157
		return(-1);
slouken@0
   158
#endif
slouken@0
   159
	}
slouken@1361
   160
#endif /* !SDL_THREADS_DISABLED */
slouken@0
   161
	SDL_EventQ.active = 1;
slouken@0
   162
slouken@0
   163
	if ( (flags&SDL_INIT_EVENTTHREAD) == SDL_INIT_EVENTTHREAD ) {
slouken@0
   164
		SDL_EventLock.lock = SDL_CreateMutex();
slouken@0
   165
		if ( SDL_EventLock.lock == NULL ) {
slouken@0
   166
			return(-1);
slouken@0
   167
		}
slouken@0
   168
		SDL_EventLock.safe = 0;
slouken@0
   169
slouken@1028
   170
		/* The event thread will handle timers too */
slouken@1028
   171
		SDL_SetTimerThreaded(2);
icculus@3975
   172
#if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC) && !defined(__SYMBIAN32__)
slouken@1330
   173
#undef SDL_CreateThread
slouken@1330
   174
		SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL, NULL, NULL);
slouken@1330
   175
#else
slouken@0
   176
		SDL_EventThread = SDL_CreateThread(SDL_GobbleEvents, NULL);
slouken@1330
   177
#endif
slouken@0
   178
		if ( SDL_EventThread == NULL ) {
slouken@0
   179
			return(-1);
slouken@0
   180
		}
slouken@0
   181
	} else {
slouken@0
   182
		event_thread = 0;
slouken@0
   183
	}
slouken@0
   184
	return(0);
slouken@0
   185
}
slouken@0
   186
slouken@0
   187
static void SDL_StopEventThread(void)
slouken@0
   188
{
slouken@0
   189
	SDL_EventQ.active = 0;
slouken@0
   190
	if ( SDL_EventThread ) {
slouken@0
   191
		SDL_WaitThread(SDL_EventThread, NULL);
slouken@0
   192
		SDL_EventThread = NULL;
slouken@0
   193
		SDL_DestroyMutex(SDL_EventLock.lock);
slouken@4158
   194
		SDL_EventLock.lock = NULL;
slouken@0
   195
	}
icculus@1140
   196
#ifndef IPOD
slouken@0
   197
	SDL_DestroyMutex(SDL_EventQ.lock);
slouken@4158
   198
	SDL_EventQ.lock = NULL;
icculus@1140
   199
#endif
slouken@0
   200
}
slouken@0
   201
slouken@0
   202
Uint32 SDL_EventThreadID(void)
slouken@0
   203
{
slouken@0
   204
	return(event_thread);
slouken@0
   205
}
slouken@0
   206
slouken@0
   207
/* Public functions */
slouken@0
   208
slouken@0
   209
void SDL_StopEventLoop(void)
slouken@0
   210
{
slouken@0
   211
	/* Halt the event thread, if running */
slouken@0
   212
	SDL_StopEventThread();
slouken@0
   213
slouken@1123
   214
	/* Shutdown event handlers */
slouken@1123
   215
	SDL_AppActiveQuit();
slouken@1123
   216
	SDL_KeyboardQuit();
slouken@1123
   217
	SDL_MouseQuit();
slouken@1123
   218
	SDL_QuitQuit();
slouken@1123
   219
slouken@0
   220
	/* Clean out EventQ */
slouken@0
   221
	SDL_EventQ.head = 0;
slouken@0
   222
	SDL_EventQ.tail = 0;
slouken@0
   223
	SDL_EventQ.wmmsg_next = 0;
slouken@0
   224
}
slouken@0
   225
slouken@0
   226
/* This function (and associated calls) may be called more than once */
slouken@0
   227
int SDL_StartEventLoop(Uint32 flags)
slouken@0
   228
{
slouken@0
   229
	int retcode;
slouken@0
   230
slouken@0
   231
	/* Clean out the event queue */
slouken@0
   232
	SDL_EventThread = NULL;
slouken@0
   233
	SDL_EventQ.lock = NULL;
slouken@0
   234
	SDL_StopEventLoop();
slouken@0
   235
slouken@0
   236
	/* No filter to start with, process most event types */
slouken@0
   237
	SDL_EventOK = NULL;
slouken@1336
   238
	SDL_memset(SDL_ProcessEvents,SDL_ENABLE,sizeof(SDL_ProcessEvents));
slouken@0
   239
	SDL_eventstate = ~0;
slouken@0
   240
	/* It's not save to call SDL_EventState() yet */
slouken@0
   241
	SDL_eventstate &= ~(0x00000001 << SDL_SYSWMEVENT);
slouken@0
   242
	SDL_ProcessEvents[SDL_SYSWMEVENT] = SDL_IGNORE;
slouken@0
   243
slouken@0
   244
	/* Initialize event handlers */
slouken@0
   245
	retcode = 0;
slouken@0
   246
	retcode += SDL_AppActiveInit();
slouken@0
   247
	retcode += SDL_KeyboardInit();
slouken@0
   248
	retcode += SDL_MouseInit();
slouken@0
   249
	retcode += SDL_QuitInit();
slouken@0
   250
	if ( retcode < 0 ) {
slouken@0
   251
		/* We don't expect them to fail, but... */
slouken@0
   252
		return(-1);
slouken@0
   253
	}
slouken@0
   254
slouken@0
   255
	/* Create the lock and event thread */
slouken@0
   256
	if ( SDL_StartEventThread(flags) < 0 ) {
slouken@0
   257
		SDL_StopEventLoop();
slouken@0
   258
		return(-1);
slouken@0
   259
	}
slouken@0
   260
	return(0);
slouken@0
   261
}
slouken@0
   262
slouken@0
   263
slouken@0
   264
/* Add an event to the event queue -- called with the queue locked */
slouken@0
   265
static int SDL_AddEvent(SDL_Event *event)
slouken@0
   266
{
slouken@0
   267
	int tail, added;
slouken@0
   268
slouken@0
   269
	tail = (SDL_EventQ.tail+1)%MAXEVENTS;
slouken@0
   270
	if ( tail == SDL_EventQ.head ) {
slouken@0
   271
		/* Overflow, drop event */
slouken@0
   272
		added = 0;
slouken@0
   273
	} else {
slouken@0
   274
		SDL_EventQ.event[SDL_EventQ.tail] = *event;
slouken@0
   275
		if (event->type == SDL_SYSWMEVENT) {
slouken@0
   276
			/* Note that it's possible to lose an event */
slouken@0
   277
			int next = SDL_EventQ.wmmsg_next;
slouken@0
   278
			SDL_EventQ.wmmsg[next] = *event->syswm.msg;
slouken@0
   279
		        SDL_EventQ.event[SDL_EventQ.tail].syswm.msg =
slouken@0
   280
						&SDL_EventQ.wmmsg[next];
slouken@0
   281
			SDL_EventQ.wmmsg_next = (next+1)%MAXEVENTS;
slouken@0
   282
		}
slouken@0
   283
		SDL_EventQ.tail = tail;
slouken@0
   284
		added = 1;
slouken@0
   285
	}
slouken@0
   286
	return(added);
slouken@0
   287
}
slouken@0
   288
slouken@0
   289
/* Cut an event, and return the next valid spot, or the tail */
slouken@0
   290
/*                           -- called with the queue locked */
slouken@0
   291
static int SDL_CutEvent(int spot)
slouken@0
   292
{
slouken@0
   293
	if ( spot == SDL_EventQ.head ) {
slouken@0
   294
		SDL_EventQ.head = (SDL_EventQ.head+1)%MAXEVENTS;
slouken@0
   295
		return(SDL_EventQ.head);
slouken@0
   296
	} else
slouken@0
   297
	if ( (spot+1)%MAXEVENTS == SDL_EventQ.tail ) {
slouken@0
   298
		SDL_EventQ.tail = spot;
slouken@0
   299
		return(SDL_EventQ.tail);
slouken@0
   300
	} else
slouken@0
   301
	/* We cut the middle -- shift everything over */
slouken@0
   302
	{
slouken@0
   303
		int here, next;
slouken@0
   304
slouken@1336
   305
		/* This can probably be optimized with SDL_memcpy() -- careful! */
slouken@0
   306
		if ( --SDL_EventQ.tail < 0 ) {
slouken@0
   307
			SDL_EventQ.tail = MAXEVENTS-1;
slouken@0
   308
		}
slouken@0
   309
		for ( here=spot; here != SDL_EventQ.tail; here = next ) {
slouken@0
   310
			next = (here+1)%MAXEVENTS;
slouken@0
   311
			SDL_EventQ.event[here] = SDL_EventQ.event[next];
slouken@0
   312
		}
slouken@0
   313
		return(spot);
slouken@0
   314
	}
slouken@0
   315
	/* NOTREACHED */
slouken@0
   316
}
slouken@0
   317
slouken@0
   318
/* Lock the event queue, take a peep at it, and unlock it */
slouken@0
   319
int SDL_PeepEvents(SDL_Event *events, int numevents, SDL_eventaction action,
slouken@0
   320
								Uint32 mask)
slouken@0
   321
{
slouken@0
   322
	int i, used;
slouken@0
   323
slouken@0
   324
	/* Don't look after we've quit */
slouken@0
   325
	if ( ! SDL_EventQ.active ) {
slouken@276
   326
		return(-1);
slouken@0
   327
	}
slouken@0
   328
	/* Lock the event queue */
slouken@0
   329
	used = 0;
slouken@0
   330
	if ( SDL_mutexP(SDL_EventQ.lock) == 0 ) {
slouken@0
   331
		if ( action == SDL_ADDEVENT ) {
slouken@0
   332
			for ( i=0; i<numevents; ++i ) {
slouken@0
   333
				used += SDL_AddEvent(&events[i]);
slouken@0
   334
			}
slouken@0
   335
		} else {
slouken@0
   336
			SDL_Event tmpevent;
slouken@0
   337
			int spot;
slouken@0
   338
slouken@0
   339
			/* If 'events' is NULL, just see if they exist */
slouken@0
   340
			if ( events == NULL ) {
slouken@0
   341
				action = SDL_PEEKEVENT;
slouken@0
   342
				numevents = 1;
slouken@0
   343
				events = &tmpevent;
slouken@0
   344
			}
slouken@0
   345
			spot = SDL_EventQ.head;
slouken@0
   346
			while ((used < numevents)&&(spot != SDL_EventQ.tail)) {
slouken@0
   347
				if ( mask & SDL_EVENTMASK(SDL_EventQ.event[spot].type) ) {
slouken@0
   348
					events[used++] = SDL_EventQ.event[spot];
slouken@0
   349
					if ( action == SDL_GETEVENT ) {
slouken@0
   350
						spot = SDL_CutEvent(spot);
slouken@0
   351
					} else {
slouken@0
   352
						spot = (spot+1)%MAXEVENTS;
slouken@0
   353
					}
slouken@0
   354
				} else {
slouken@0
   355
					spot = (spot+1)%MAXEVENTS;
slouken@0
   356
				}
slouken@0
   357
			}
slouken@0
   358
		}
slouken@0
   359
		SDL_mutexV(SDL_EventQ.lock);
slouken@0
   360
	} else {
slouken@0
   361
		SDL_SetError("Couldn't lock event queue");
slouken@0
   362
		used = -1;
slouken@0
   363
	}
slouken@0
   364
	return(used);
slouken@0
   365
}
slouken@0
   366
slouken@0
   367
/* Run the system dependent event loops */
slouken@0
   368
void SDL_PumpEvents(void)
slouken@0
   369
{
slouken@0
   370
	if ( !SDL_EventThread ) {
slouken@0
   371
		SDL_VideoDevice *video = current_video;
slouken@0
   372
		SDL_VideoDevice *this  = current_video;
slouken@0
   373
slouken@0
   374
		/* Get events from the video subsystem */
slouken@0
   375
		if ( video ) {
slouken@0
   376
			video->PumpEvents(this);
slouken@0
   377
		}
slouken@0
   378
slouken@0
   379
		/* Queue pending key-repeat events */
slouken@0
   380
		SDL_CheckKeyRepeat();
slouken@0
   381
slouken@1361
   382
#if !SDL_JOYSTICK_DISABLED
slouken@0
   383
		/* Check for joystick state change */
slouken@0
   384
		if ( SDL_numjoysticks && (SDL_eventstate & SDL_JOYEVENTMASK) ) {
slouken@0
   385
			SDL_JoystickUpdate();
slouken@0
   386
		}
slouken@0
   387
#endif
slouken@0
   388
	}
slouken@0
   389
}
slouken@0
   390
slouken@0
   391
/* Public functions */
slouken@0
   392
slouken@0
   393
int SDL_PollEvent (SDL_Event *event)
slouken@0
   394
{
slouken@0
   395
	SDL_PumpEvents();
slouken@0
   396
slouken@352
   397
	/* We can't return -1, just return 0 (no event) on error */
slouken@352
   398
	if ( SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS) <= 0 )
slouken@352
   399
		return 0;
slouken@352
   400
	return 1;
slouken@0
   401
}
slouken@0
   402
slouken@0
   403
int SDL_WaitEvent (SDL_Event *event)
slouken@0
   404
{
slouken@0
   405
	while ( 1 ) {
slouken@0
   406
		SDL_PumpEvents();
slouken@0
   407
		switch(SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_ALLEVENTS)) {
slouken@353
   408
		    case -1: return 0;
slouken@0
   409
		    case 1: return 1;
slouken@0
   410
		    case 0: SDL_Delay(10);
slouken@0
   411
		}
slouken@0
   412
	}
slouken@0
   413
}
slouken@0
   414
slouken@0
   415
int SDL_PushEvent(SDL_Event *event)
slouken@0
   416
{
slouken@384
   417
	if ( SDL_PeepEvents(event, 1, SDL_ADDEVENT, 0) <= 0 )
slouken@384
   418
		return -1;
slouken@384
   419
	return 0;
slouken@0
   420
}
slouken@0
   421
slouken@0
   422
void SDL_SetEventFilter (SDL_EventFilter filter)
slouken@0
   423
{
slouken@0
   424
	SDL_Event bitbucket;
slouken@0
   425
slouken@0
   426
	/* Set filter and discard pending events */
slouken@0
   427
	SDL_EventOK = filter;
slouken@0
   428
	while ( SDL_PollEvent(&bitbucket) > 0 )
slouken@0
   429
		;
slouken@0
   430
}
slouken@0
   431
slouken@0
   432
SDL_EventFilter SDL_GetEventFilter(void)
slouken@0
   433
{
slouken@0
   434
	return(SDL_EventOK);
slouken@0
   435
}
slouken@0
   436
slouken@0
   437
Uint8 SDL_EventState (Uint8 type, int state)
slouken@0
   438
{
slouken@0
   439
	SDL_Event bitbucket;
slouken@0
   440
	Uint8 current_state;
slouken@0
   441
slouken@0
   442
	/* If SDL_ALLEVENTS was specified... */
slouken@0
   443
	if ( type == 0xFF ) {
slouken@0
   444
		current_state = SDL_IGNORE;
slouken@0
   445
		for ( type=0; type<SDL_NUMEVENTS; ++type ) {
slouken@0
   446
			if ( SDL_ProcessEvents[type] != SDL_IGNORE ) {
slouken@0
   447
				current_state = SDL_ENABLE;
slouken@0
   448
			}
slouken@0
   449
			SDL_ProcessEvents[type] = state;
slouken@0
   450
			if ( state == SDL_ENABLE ) {
slouken@0
   451
				SDL_eventstate |= (0x00000001 << (type));
slouken@0
   452
			} else {
slouken@0
   453
				SDL_eventstate &= ~(0x00000001 << (type));
slouken@0
   454
			}
slouken@0
   455
		}
slouken@0
   456
		while ( SDL_PollEvent(&bitbucket) > 0 )
slouken@0
   457
			;
slouken@0
   458
		return(current_state);
slouken@0
   459
	}
slouken@0
   460
slouken@0
   461
	/* Just set the state for one event type */
slouken@0
   462
	current_state = SDL_ProcessEvents[type];
slouken@0
   463
	switch (state) {
slouken@0
   464
		case SDL_IGNORE:
slouken@0
   465
		case SDL_ENABLE:
slouken@0
   466
			/* Set state and discard pending events */
slouken@0
   467
			SDL_ProcessEvents[type] = state;
slouken@0
   468
			if ( state == SDL_ENABLE ) {
slouken@0
   469
				SDL_eventstate |= (0x00000001 << (type));
slouken@0
   470
			} else {
slouken@0
   471
				SDL_eventstate &= ~(0x00000001 << (type));
slouken@0
   472
			}
slouken@0
   473
			while ( SDL_PollEvent(&bitbucket) > 0 )
slouken@0
   474
				;
slouken@0
   475
			break;
slouken@0
   476
		default:
slouken@0
   477
			/* Querying state? */
slouken@0
   478
			break;
slouken@0
   479
	}
slouken@0
   480
	return(current_state);
slouken@0
   481
}
slouken@0
   482
slouken@0
   483
/* This is a generic event handler.
slouken@0
   484
 */
slouken@0
   485
int SDL_PrivateSysWMEvent(SDL_SysWMmsg *message)
slouken@0
   486
{
slouken@0
   487
	int posted;
slouken@0
   488
slouken@0
   489
	posted = 0;
slouken@0
   490
	if ( SDL_ProcessEvents[SDL_SYSWMEVENT] == SDL_ENABLE ) {
slouken@0
   491
		SDL_Event event;
slouken@1336
   492
		SDL_memset(&event, 0, sizeof(event));
slouken@0
   493
		event.type = SDL_SYSWMEVENT;
slouken@0
   494
		event.syswm.msg = message;
slouken@0
   495
		if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
slouken@0
   496
			posted = 1;
slouken@0
   497
			SDL_PushEvent(&event);
slouken@0
   498
		}
slouken@0
   499
	}
slouken@0
   500
	/* Update internal event state */
slouken@0
   501
	return(posted);
slouken@0
   502
}