test/threadwin.c
changeset 1895 c121d94672cb
parent 1769 290b5baf2fca
child 2117 40888832d785
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
    13 
    13 
    14 /* Is the cursor visible? */
    14 /* Is the cursor visible? */
    15 static int visible = 1;
    15 static int visible = 1;
    16 
    16 
    17 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    17 /* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
    18 static void quit(int rc)
    18 static void
    19 {
    19 quit(int rc)
    20 	SDL_Quit();
    20 {
    21 	exit(rc);
    21     SDL_Quit();
    22 }
    22     exit(rc);
    23 
    23 }
    24 SDL_Surface *LoadIconSurface(char *file, Uint8 **maskp)
    24 
    25 {
    25 SDL_Surface *
    26 	SDL_Surface *icon;
    26 LoadIconSurface(char *file, Uint8 ** maskp)
    27 	Uint8       *pixels;
    27 {
    28 	Uint8       *mask;
    28     SDL_Surface *icon;
    29 	int          mlen, i;
    29     Uint8 *pixels;
    30 
    30     Uint8 *mask;
    31 	*maskp = NULL;
    31     int mlen, i;
    32 
    32 
    33 	/* Load the icon surface */
    33     *maskp = NULL;
    34 	icon = SDL_LoadBMP(file);
    34 
    35 	if ( icon == NULL ) {
    35     /* Load the icon surface */
    36 		fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
    36     icon = SDL_LoadBMP(file);
    37 		return(NULL);
    37     if (icon == NULL) {
    38 	}
    38         fprintf(stderr, "Couldn't load %s: %s\n", file, SDL_GetError());
    39 
    39         return (NULL);
    40 	/* Check width and height */
    40     }
    41 	if ( (icon->w%8) != 0 ) {
    41 
    42 		fprintf(stderr, "Icon width must be a multiple of 8!\n");
    42     /* Check width and height */
    43 		SDL_FreeSurface(icon);
    43     if ((icon->w % 8) != 0) {
    44 		return(NULL);
    44         fprintf(stderr, "Icon width must be a multiple of 8!\n");
    45 	}
    45         SDL_FreeSurface(icon);
    46 	if ( icon->format->palette == NULL ) {
    46         return (NULL);
    47 		fprintf(stderr, "Icon must have a palette!\n");
    47     }
    48 		SDL_FreeSurface(icon);
    48     if (icon->format->palette == NULL) {
    49 		return(NULL);
    49         fprintf(stderr, "Icon must have a palette!\n");
    50 	}
    50         SDL_FreeSurface(icon);
    51 
    51         return (NULL);
    52 	/* Set the colorkey */
    52     }
    53 	SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *)icon->pixels));
    53 
    54 
    54     /* Set the colorkey */
    55 	/* Create the mask */
    55     SDL_SetColorKey(icon, SDL_SRCCOLORKEY, *((Uint8 *) icon->pixels));
    56 	pixels = (Uint8 *)icon->pixels;
    56 
    57 	printf("Transparent pixel: (%d,%d,%d)\n",
    57     /* Create the mask */
    58 				icon->format->palette->colors[*pixels].r,
    58     pixels = (Uint8 *) icon->pixels;
    59 				icon->format->palette->colors[*pixels].g,
    59     printf("Transparent pixel: (%d,%d,%d)\n",
    60 				icon->format->palette->colors[*pixels].b);
    60            icon->format->palette->colors[*pixels].r,
    61 	mlen = icon->w*icon->h;
    61            icon->format->palette->colors[*pixels].g,
    62 	mask = (Uint8 *)malloc(mlen/8);
    62            icon->format->palette->colors[*pixels].b);
    63 	if ( mask == NULL ) {
    63     mlen = icon->w * icon->h;
    64 		fprintf(stderr, "Out of memory!\n");
    64     mask = (Uint8 *) malloc(mlen / 8);
    65 		SDL_FreeSurface(icon);
    65     if (mask == NULL) {
    66 		return(NULL);
    66         fprintf(stderr, "Out of memory!\n");
    67 	}
    67         SDL_FreeSurface(icon);
    68 	memset(mask, 0, mlen/8);
    68         return (NULL);
    69 	for ( i=0; i<mlen; ) {
    69     }
    70 		if ( pixels[i] != *pixels )
    70     memset(mask, 0, mlen / 8);
    71 			mask[i/8] |= 0x01;
    71     for (i = 0; i < mlen;) {
    72 		++i;
    72         if (pixels[i] != *pixels)
    73 		if ( (i%8) != 0 )
    73             mask[i / 8] |= 0x01;
    74 			mask[i/8] <<= 1;
    74         ++i;
    75 	}
    75         if ((i % 8) != 0)
    76 	*maskp = mask;
    76             mask[i / 8] <<= 1;
    77 	return(icon);
    77     }
    78 }
    78     *maskp = mask;
    79 
    79     return (icon);
    80 int SDLCALL FilterEvents(const SDL_Event *event)
    80 }
    81 {
    81 
    82 	static int reallyquit = 0;
    82 int SDLCALL
    83 
    83 FilterEvents(void *userdata, SDL_Event * event)
    84 	switch (event->type) {
    84 {
    85 
    85     static int reallyquit = 0;
    86 		case SDL_ACTIVEEVENT:
    86 
    87 			/* See what happened */
    87     switch (event->type) {
    88 			printf("App %s ",
    88 
    89 				event->active.gain ? "gained" : "lost");
    89     case SDL_ACTIVEEVENT:
    90 			if ( event->active.state & SDL_APPACTIVE )
    90         /* See what happened */
    91 				printf("active ");
    91         printf("App %s ", event->active.gain ? "gained" : "lost");
    92 			if ( event->active.state & SDL_APPMOUSEFOCUS )
    92         if (event->active.state & SDL_APPACTIVE)
    93 				printf("mouse ");
    93             printf("active ");
    94 			if ( event->active.state & SDL_APPINPUTFOCUS )
    94         if (event->active.state & SDL_APPMOUSEFOCUS)
    95 				printf("input ");
    95             printf("mouse ");
    96 			printf("focus\n");
    96         if (event->active.state & SDL_APPINPUTFOCUS)
    97 
    97             printf("input ");
    98 			/* See if we are iconified or restored */
    98         printf("focus\n");
    99 			if ( event->active.state & SDL_APPACTIVE ) {
    99 
   100 				printf("App has been %s\n",
   100         /* See if we are iconified or restored */
   101 					event->active.gain ?
   101         if (event->active.state & SDL_APPACTIVE) {
   102 						 "restored" : "iconified");
   102             printf("App has been %s\n",
   103 			}
   103                    event->active.gain ? "restored" : "iconified");
   104 			return(0);
   104         }
   105 
   105         return (0);
   106 		/* This is important!  Queue it if we want to quit. */
   106 
   107 		case SDL_QUIT:
   107         /* This is important!  Queue it if we want to quit. */
   108 			if ( ! reallyquit ) {
   108     case SDL_QUIT:
   109 				reallyquit = 1;
   109         if (!reallyquit) {
   110 				printf("Quit requested\n");
   110             reallyquit = 1;
   111 				return(0);
   111             printf("Quit requested\n");
   112 			}
   112             return (0);
   113 			printf("Quit demanded\n");
   113         }
   114 			return(1);
   114         printf("Quit demanded\n");
   115 
   115         return (1);
   116 		/* Mouse and keyboard events go to threads */
   116 
   117 		case SDL_MOUSEMOTION:
   117         /* Mouse and keyboard events go to threads */
   118 		case SDL_MOUSEBUTTONDOWN:
   118     case SDL_MOUSEMOTION:
   119 		case SDL_MOUSEBUTTONUP:
   119     case SDL_MOUSEBUTTONDOWN:
   120 		case SDL_KEYDOWN:
   120     case SDL_MOUSEBUTTONUP:
   121 		case SDL_KEYUP:
   121     case SDL_KEYDOWN:
   122 			return(1);
   122     case SDL_KEYUP:
   123 
   123         return (1);
   124 		/* Drop all other events */
   124 
   125 		default:
   125         /* Drop all other events */
   126 			return(0);
   126     default:
   127 	}
   127         return (0);
   128 }
   128     }
   129 
   129 }
   130 int SDLCALL HandleMouse(void *unused)
   130 
   131 {
   131 int SDLCALL
   132 	SDL_Event events[10];
   132 HandleMouse(void *unused)
   133 	int i, found;
   133 {
   134 	Uint32 mask;
   134     SDL_Event events[10];
   135 
   135     int i, found;
   136 	/* Handle mouse events here */
   136     Uint32 mask;
   137 	mask = (SDL_MOUSEMOTIONMASK|SDL_MOUSEBUTTONDOWNMASK|SDL_MOUSEBUTTONUPMASK);
   137 
   138 	while ( ! done ) {
   138     /* Handle mouse events here */
   139 		found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
   139     mask =
   140 		for ( i=0; i<found; ++i ) {
   140         (SDL_MOUSEMOTIONMASK | SDL_MOUSEBUTTONDOWNMASK |
   141 			switch(events[i].type) {
   141          SDL_MOUSEBUTTONUPMASK);
   142 				/* We want to toggle visibility on buttonpress */
   142     while (!done) {
   143 				case SDL_MOUSEBUTTONDOWN:
   143         found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
   144 				case SDL_MOUSEBUTTONUP:
   144         for (i = 0; i < found; ++i) {
   145 					if ( events[i].button.state == SDL_PRESSED ) {
   145             switch (events[i].type) {
   146 						visible = !visible;
   146                 /* We want to toggle visibility on buttonpress */
   147 						SDL_ShowCursor(visible);
   147             case SDL_MOUSEBUTTONDOWN:
   148 					}
   148             case SDL_MOUSEBUTTONUP:
   149 					printf("Mouse button %d has been %s\n",
   149                 if (events[i].button.state == SDL_PRESSED) {
   150 						events[i].button.button,
   150                     visible = !visible;
   151 						(events[i].button.state == SDL_PRESSED) ?
   151                     SDL_ShowCursor(visible);
   152 						"pressed" : "released");
   152                 }
   153 					break;
   153                 printf("Mouse button %d has been %s\n",
   154 				/* Show relative mouse motion */
   154                        events[i].button.button,
   155 				case SDL_MOUSEMOTION:
   155                        (events[i].button.state == SDL_PRESSED) ?
   156 					printf("Mouse relative motion: {%d,%d}\n",
   156                        "pressed" : "released");
   157 							events[i].motion.xrel, events[i].motion.yrel);
   157                 break;
   158 					break;
   158                 /* Show relative mouse motion */
   159 			}
   159             case SDL_MOUSEMOTION:
   160 		}
   160                 printf("Mouse relative motion: {%d,%d}\n",
   161 		/* Give up some CPU to allow events to arrive */
   161                        events[i].motion.xrel, events[i].motion.yrel);
   162 		SDL_Delay(20);
   162                 break;
   163 	}
   163             }
   164 	return(0);
   164         }
   165 }
   165         /* Give up some CPU to allow events to arrive */
   166 
   166         SDL_Delay(20);
   167 int SDLCALL HandleKeyboard(void *unused)
   167     }
   168 {
   168     return (0);
   169 	SDL_Event events[10];
   169 }
   170 	int i, found;
   170 
   171 	Uint32 mask;
   171 int SDLCALL
   172 
   172 HandleKeyboard(void *unused)
   173 	/* Handle mouse events here */
   173 {
   174 	mask = (SDL_KEYDOWNMASK|SDL_KEYUPMASK);
   174     SDL_Event events[10];
   175 	while ( ! done ) {
   175     int i, found;
   176 		found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
   176     Uint32 mask;
   177 		for ( i=0; i<found; ++i ) {
   177 
   178 			switch(events[i].type) {
   178     /* Handle mouse events here */
   179 			    /* We want to toggle visibility on buttonpress */
   179     mask = (SDL_KEYDOWNMASK | SDL_KEYUPMASK);
   180 			    case SDL_KEYDOWN:
   180     while (!done) {
   181 			    case SDL_KEYUP:
   181         found = SDL_PeepEvents(events, 10, SDL_GETEVENT, mask);
   182 			    	printf("Key '%c' has been %s\n",
   182         for (i = 0; i < found; ++i) {
   183 						events[i].key.keysym.unicode,
   183             switch (events[i].type) {
   184 					(events[i].key.state == SDL_PRESSED) ?
   184                 /* We want to toggle visibility on buttonpress */
   185 						"pressed" : "released");
   185             case SDL_KEYDOWN:
   186 
   186             case SDL_KEYUP:
   187 			    	/* Allow hitting <ESC> to quit the app */
   187                 printf("Key '%c' has been %s\n",
   188 			    	if ( events[i].key.keysym.sym == SDLK_ESCAPE ) {
   188                        events[i].key.keysym.unicode,
   189 			    		done = 1;
   189                        (events[i].key.state == SDL_PRESSED) ?
   190 			    	}
   190                        "pressed" : "released");
   191 
   191 
   192 					/* skip events now that aren't KEYUPs... */
   192                 /* Allow hitting <ESC> to quit the app */
   193 					if (events[i].key.state == SDL_PRESSED)
   193                 if (events[i].key.keysym.sym == SDLK_ESCAPE) {
   194 						break;
   194                     done = 1;
   195 
   195                 }
   196 			    	if ( events[i].key.keysym.sym == SDLK_f ) {
   196 
   197 						int rc = 0;
   197                 /* skip events now that aren't KEYUPs... */
   198 						printf("attempting to toggle fullscreen...\n");
   198                 if (events[i].key.state == SDL_PRESSED)
   199 						rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
   199                     break;
   200                         printf("SDL_WM_ToggleFullScreen returned %d.\n", rc);
   200 
   201 			    	}
   201                 if (events[i].key.keysym.sym == SDLK_f) {
   202 
   202                     int rc = 0;
   203 			    	if ( events[i].key.keysym.sym == SDLK_g ) {
   203                     printf("attempting to toggle fullscreen...\n");
   204 						SDL_GrabMode m;
   204                     rc = SDL_WM_ToggleFullScreen(SDL_GetVideoSurface());
   205 						m = SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON ?
   205                     printf("SDL_WM_ToggleFullScreen returned %d.\n", rc);
   206 								SDL_GRAB_OFF : SDL_GRAB_ON;
   206                 }
   207 						printf("attempting to toggle input grab to %s...\n",
   207 
   208                                 m == SDL_GRAB_ON ? "ON" : "OFF");
   208                 if (events[i].key.keysym.sym == SDLK_g) {
   209                         SDL_WM_GrabInput(m);
   209                     SDL_GrabMode m;
   210 						printf("attempt finished.\n");
   210                     m = SDL_WM_GrabInput(SDL_GRAB_QUERY) ==
   211 			    	}
   211                         SDL_GRAB_ON ? SDL_GRAB_OFF : SDL_GRAB_ON;
   212 
   212                     printf
   213 			    	break;
   213                         ("attempting to toggle input grab to %s...\n",
   214 			}
   214                          m == SDL_GRAB_ON ? "ON" : "OFF");
   215 		}
   215                     SDL_WM_GrabInput(m);
   216 		/* Give up some CPU to allow events to arrive */
   216                     printf("attempt finished.\n");
   217 		SDL_Delay(20);
   217                 }
   218 	}
   218 
   219 	return(0);
   219                 break;
   220 }
   220             }
   221 
   221         }
   222 int main(int argc, char *argv[])
   222         /* Give up some CPU to allow events to arrive */
   223 {
   223         SDL_Delay(20);
   224 	SDL_Surface *screen;
   224     }
   225 	SDL_Surface *icon;
   225     return (0);
   226 	Uint8 *icon_mask;
   226 }
   227 	int i, parsed;
   227 
   228 	Uint8 *buffer;
   228 int
   229 	SDL_Color palette[256];
   229 main(int argc, char *argv[])
   230 	Uint32 init_flags;
   230 {
   231 	Uint8  video_bpp;
   231     SDL_Surface *screen;
   232 	Uint32 video_flags;
   232     SDL_Surface *icon;
   233 	SDL_Thread *mouse_thread;
   233     Uint8 *icon_mask;
   234 	SDL_Thread *keybd_thread;
   234     int i, parsed;
   235 
   235     Uint8 *buffer;
   236 	/* Set the options, based on command line arguments */
   236     SDL_Color palette[256];
   237 	init_flags = SDL_INIT_VIDEO;
   237     Uint32 init_flags;
   238 	video_bpp = 8;
   238     Uint8 video_bpp;
   239 	video_flags = SDL_SWSURFACE;
   239     Uint32 video_flags;
   240 	parsed = 1;
   240     SDL_Thread *mouse_thread;
   241 	while ( parsed ) {
   241     SDL_Thread *keybd_thread;
   242 		/* If the threaded option is enabled, and the SDL library hasn't
   242 
   243 		   been compiled with threaded events enabled, then the mouse and
   243     /* Set the options, based on command line arguments */
   244 		   keyboard won't respond.
   244     init_flags = SDL_INIT_VIDEO;
   245 		 */
   245     video_bpp = 8;
   246 		if ( (argc >= 2) && (strcmp(argv[1], "-threaded") == 0) ) {
   246     video_flags = SDL_SWSURFACE;
   247 			init_flags |= SDL_INIT_EVENTTHREAD;
   247     parsed = 1;
   248 			argc -= 1;
   248     while (parsed) {
   249 			argv += 1;
   249         /* If the threaded option is enabled, and the SDL library hasn't
   250 			printf("Running with threaded events\n");
   250            been compiled with threaded events enabled, then the mouse and
   251 		} else
   251            keyboard won't respond.
   252 		if ( (argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0) ) {
   252          */
   253 			video_flags |= SDL_FULLSCREEN;
   253         if ((argc >= 2) && (strcmp(argv[1], "-threaded") == 0)) {
   254 			argc -= 1;
   254             init_flags |= SDL_INIT_EVENTTHREAD;
   255 			argv += 1;
   255             argc -= 1;
   256 		} else
   256             argv += 1;
   257 		if ( (argc >= 3) && (strcmp(argv[1], "-bpp") == 0) ) {
   257             printf("Running with threaded events\n");
   258 			video_bpp = atoi(argv[2]);
   258         } else if ((argc >= 2) && (strcmp(argv[1], "-fullscreen") == 0)) {
   259 			argc -= 2;
   259             video_flags |= SDL_FULLSCREEN;
   260 			argv += 2;
   260             argc -= 1;
   261 		} else {
   261             argv += 1;
   262 			parsed = 0;
   262         } else if ((argc >= 3) && (strcmp(argv[1], "-bpp") == 0)) {
   263 		}
   263             video_bpp = atoi(argv[2]);
   264 	}
   264             argc -= 2;
   265 
   265             argv += 2;
   266 	/* Initialize SDL with the requested flags */
   266         } else {
   267 	if ( SDL_Init(init_flags) < 0 ) {
   267             parsed = 0;
   268 		fprintf(stderr,
   268         }
   269 			"Couldn't initialize SDL: %s\n", SDL_GetError());
   269     }
   270 		return(1);
   270 
   271 	}
   271     /* Initialize SDL with the requested flags */
   272 
   272     if (SDL_Init(init_flags) < 0) {
   273 	/* Set the icon -- this must be done before the first mode set */
   273         fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
   274 	icon = LoadIconSurface("icon.bmp", &icon_mask);
   274         return (1);
   275 	if ( icon != NULL ) {
   275     }
   276 		SDL_WM_SetIcon(icon, icon_mask);
   276 
   277 	}
   277     /* Set the icon -- this must be done before the first mode set */
   278 	if ( icon_mask != NULL )
   278     icon = LoadIconSurface("icon.bmp", &icon_mask);
   279 		free(icon_mask);
   279     if (icon != NULL) {
   280 
   280         SDL_WM_SetIcon(icon, icon_mask);
   281 	/* Initialize the display */
   281     }
   282 	screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags);
   282     if (icon_mask != NULL)
   283 	if (  screen == NULL ) {
   283         free(icon_mask);
   284 		fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
   284 
   285 						video_bpp, SDL_GetError());
   285     /* Initialize the display */
   286 		quit(1);
   286     screen = SDL_SetVideoMode(640, 480, video_bpp, video_flags);
   287 	}
   287     if (screen == NULL) {
   288 	printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
   288         fprintf(stderr, "Couldn't set 640x480x%d video mode: %s\n",
   289 						"fullscreen" : "windowed");
   289                 video_bpp, SDL_GetError());
   290 
   290         quit(1);
   291 	/* Enable printable characters */
   291     }
   292 	SDL_EnableUNICODE(1);
   292     printf("Running in %s mode\n", screen->flags & SDL_FULLSCREEN ?
   293 
   293            "fullscreen" : "windowed");
   294 	/* Set an event filter that discards everything but QUIT */
   294 
   295 	SDL_SetEventFilter(FilterEvents);
   295     /* Enable printable characters */
   296 
   296     SDL_EnableUNICODE(1);
   297 	/* Create the event handling threads */
   297 
   298 	mouse_thread = SDL_CreateThread(HandleMouse, NULL);
   298     /* Set an event filter that discards everything but QUIT */
   299 	keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
   299     SDL_SetEventFilter(FilterEvents, NULL);
   300 
   300 
   301 	/* Set the surface pixels and refresh! */
   301     /* Create the event handling threads */
   302 	for ( i=0; i<256; ++i ) {
   302     mouse_thread = SDL_CreateThread(HandleMouse, NULL);
   303 		palette[i].r = 255-i;
   303     keybd_thread = SDL_CreateThread(HandleKeyboard, NULL);
   304 		palette[i].g = 255-i;
   304 
   305 		palette[i].b = 255-i;
   305     /* Set the surface pixels and refresh! */
   306 	}
   306     for (i = 0; i < 256; ++i) {
   307 	SDL_SetColors(screen, palette, 0, 256);
   307         palette[i].r = 255 - i;
   308 	if ( SDL_LockSurface(screen) < 0 ) {
   308         palette[i].g = 255 - i;
   309 		fprintf(stderr, "Couldn't lock display surface: %s\n",
   309         palette[i].b = 255 - i;
   310 							SDL_GetError());
   310     }
   311 		quit(2);
   311     SDL_SetColors(screen, palette, 0, 256);
   312 	}
   312     if (SDL_LockSurface(screen) < 0) {
   313 	buffer = (Uint8 *)screen->pixels;
   313         fprintf(stderr, "Couldn't lock display surface: %s\n",
   314 	for ( i=0; i<screen->h; ++i ) {
   314                 SDL_GetError());
   315 		memset(buffer,(i*255)/screen->h,
   315         quit(2);
   316 				screen->w*screen->format->BytesPerPixel);
   316     }
   317 		buffer += screen->pitch;
   317     buffer = (Uint8 *) screen->pixels;
   318 	}
   318     for (i = 0; i < screen->h; ++i) {
   319 	SDL_UnlockSurface(screen);
   319         memset(buffer, (i * 255) / screen->h,
   320 	SDL_UpdateRect(screen, 0, 0, 0, 0);
   320                screen->w * screen->format->BytesPerPixel);
   321 
   321         buffer += screen->pitch;
   322 	/* Loop, waiting for QUIT */
   322     }
   323 	while ( ! done ) {
   323     SDL_UnlockSurface(screen);
   324 		if ( ! (init_flags & SDL_INIT_EVENTTHREAD) ) {
   324     SDL_UpdateRect(screen, 0, 0, 0, 0);
   325 			SDL_PumpEvents(); /* Needed when event thread is off */
   325 
   326 		}
   326     /* Loop, waiting for QUIT */
   327 		if ( SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK) ) {
   327     while (!done) {
   328 			done = 1;
   328         if (!(init_flags & SDL_INIT_EVENTTHREAD)) {
   329 		}
   329             SDL_PumpEvents();   /* Needed when event thread is off */
   330 		/* Give up some CPU so the events can accumulate */
   330         }
   331 		SDL_Delay(20);
   331         if (SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_QUITMASK)) {
   332 	}
   332             done = 1;
   333 	SDL_WaitThread(mouse_thread, NULL);
   333         }
   334 	SDL_WaitThread(keybd_thread, NULL);
   334         /* Give up some CPU so the events can accumulate */
   335 	SDL_Quit();
   335         SDL_Delay(20);
   336 	return(0);
   336     }
   337 }
   337     SDL_WaitThread(mouse_thread, NULL);
       
   338     SDL_WaitThread(keybd_thread, NULL);
       
   339     SDL_Quit();
       
   340     return (0);
       
   341 }