Skip to content
Snippets Groups Projects
sdl_con.c 35.6 KiB
Newer Older
deuce's avatar
deuce committed
	SDL_mutexV(sdl_vstatlock);

	last_blink=this_blink;
	p=last_vmem;
	last_vmem=newvmem;
	free(p);

	sdl_draw_cursor();
	if(rcount)
		SDL_UpdateRects(win,rcount,rects);
	free(rects);
deuce's avatar
deuce committed
	return(0);
unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, unsigned int unicode)
{
	int i;

	for(i=0;sdl_keyval[i].keysym;i++) {
		if(sdl_keyval[i].keysym==keysym) {
			if(mod & (KMOD_META|KMOD_ALT))
				return(sdl_keyval[i].alt);
			if(mod & KMOD_CTRL)
				return(sdl_keyval[i].ctrl);
			if(mod & KMOD_SHIFT)
				return(sdl_keyval[i].shift);
			return(sdl_keyval[i].key);
		}
	}
	if(unicode  && unicode < 256)
		return(unicode);
	return(0x01ffff);
}

/* Called from events thread only */
struct mainparams {
	int	argc;
	char	**argv;
};

/* Called from events thread only */
deuce's avatar
deuce committed
int sdl_runmain(void *data)
	sdl_exitcode=CIOLIB_main(mp->argc, mp->argv);
	ev.type=SDL_QUIT;
	while(SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
deuce's avatar
deuce committed
	return(0);
/* Mouse event/keyboard thread */
deuce's avatar
deuce committed
int sdl_mouse_thread(void *data)
{
	while(1) {
		if(mouse_wait())
			sdl_add_key(CIO_KEY_MOUSE);
	}
}

/* Event Thread */
int main(int argc, char **argv)
{
deuce's avatar
deuce committed
	unsigned int i;
	SDL_Event	ev;
	struct mainparams mp;

	mp.argc=argc;
	mp.argv=argv;
	SDL_Init(SDL_INIT_VIDEO);

	sdl_key_pending=SDL_CreateSemaphore(0);
	sdl_init_complete=SDL_CreateSemaphore(0);
deuce's avatar
deuce committed
	sdl_updlock=SDL_CreateMutex();
	sdl_keylock=SDL_CreateMutex();
deuce's avatar
deuce committed
	sdl_vstatlock=SDL_CreateMutex();
#if !defined(NO_X) && defined(__unix__)
	sdl_pastebuf_set=SDL_CreateSemaphore(0);
	sdl_pastebuf_copied=SDL_CreateSemaphore(0);
	sdl_copybuf_mutex=SDL_CreateMutex();
#endif

	SDL_CreateThread(sdl_runmain, &mp);

	while(1) {
		if(SDL_WaitEvent(&ev)==1) {
			switch (ev.type) {
				case SDL_ACTIVEEVENT:		/* Focus change */
					break;
				case SDL_KEYDOWN:			/* Keypress */
deuce's avatar
deuce committed
					if(ev.key.keysym.unicode > 0 && ev.key.keysym.unicode <= 0x7f) {		/* ASCII Key (Whoopee!) */
						/* Need magical handling here... 
						 * if ALT is pressed, run 'er through 
						 * sdl_get_char_code() ANYWAYS */
						if(ev.key.keysym.mod & (KMOD_META|KMOD_ALT))
							sdl_add_key(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode));
						else
							sdl_add_key(ev.key.keysym.unicode&0x7f);
					}
					else 
						sdl_add_key(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode));
					break;
				case SDL_KEYUP:				/* Ignored (handled in KEYDOWN event) */
					break;
				case SDL_MOUSEMOTION:
deuce's avatar
deuce committed
					SDL_mutexP(sdl_vstatlock);
					ciomouse_gotevent(CIOLIB_MOUSE_MOVE,ev.motion.x/(vstat.charwidth*vstat.scaling)+1,ev.motion.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
					SDL_mutexV(sdl_vstatlock);
					break;
				case SDL_MOUSEBUTTONDOWN:
					switch(ev.button.button) {
						case SDL_BUTTON_LEFT:
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
							break;
					}
					break;
				case SDL_MOUSEBUTTONUP:
					switch(ev.button.button) {
						case SDL_BUTTON_LEFT:
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
					return(sdl_exitcode);
				case SDL_VIDEORESIZE:
					if(ev.resize.w > 0 && ev.resize.h > 0) {
						FREE_AND_NULL(last_vmem);
deuce's avatar
deuce committed
						SDL_mutexP(sdl_vstatlock);
						vstat.scaling=(int)(ev.resize.w/(vstat.charwidth*vstat.cols));
						if(vstat.scaling < 1)
							vstat.scaling=1;
						if(fullscreen)
							win=SDL_SetVideoMode(
								 vstat.charwidth*vstat.cols*vstat.scaling
								,vstat.charheight*vstat.rows*vstat.scaling
								,32
								,SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN
							);
						else
							win=SDL_SetVideoMode(
								 vstat.charwidth*vstat.cols*vstat.scaling
								,vstat.charheight*vstat.rows*vstat.scaling
								,8
								,SDL_HWSURFACE|SDL_HWPALETTE|SDL_RESIZABLE
							);
						if(win!=NULL) {
							if(sdl_cursor!=NULL)
								SDL_FreeSurface(sdl_cursor);
							sdl_cursor=SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCCOLORKEY, vstat.charwidth, vstat.charheight, 8, 0, 0, 0, 0);
						    /* Update font. */
						    sdl_load_font(NULL);
						    sdl_setup_colours(win,0);
							sdl_full_screen_redraw();
						}
						else if(sdl_init_good) {
							ev.type=SDL_QUIT;
							sdl_exitcode=1;
							SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
						}
deuce's avatar
deuce committed
						SDL_mutexV(sdl_vstatlock);
					FREE_AND_NULL(last_vmem);
					sdl_full_screen_redraw();
					break;
				case SDL_USEREVENT: {
					/* Tell SDL to do various stuff... */
					switch(ev.user.code) {
						case SDL_USEREVENT_UPDATERECT:
							sdl_full_screen_redraw();
							break;
						case SDL_USEREVENT_SETTITLE:
							SDL_WM_SetCaption((char *)ev.user.data1,NULL);
							free(ev.user.data1);
							break;
						case SDL_USEREVENT_SETVIDMODE:
							FREE_AND_NULL(last_vmem);
deuce's avatar
deuce committed
							SDL_mutexP(sdl_vstatlock);
							if(fullscreen)
								win=SDL_SetVideoMode(
									 vstat.charwidth*vstat.cols*vstat.scaling
									,vstat.charheight*vstat.rows*vstat.scaling
									,8
									,SDL_SWSURFACE|SDL_HWPALETTE|SDL_FULLSCREEN
								);
							else
								win=SDL_SetVideoMode(
									 vstat.charwidth*vstat.cols*vstat.scaling
									,vstat.charheight*vstat.rows*vstat.scaling
									,8
									,SDL_HWSURFACE|SDL_HWPALETTE|SDL_RESIZABLE
								);
								vstat.scaling=(int)(win->w/(vstat.charwidth*vstat.cols));
								if(vstat.scaling < 1)
									vstat.scaling=1;
								sdl_setup_colours(win,0);
								if(sdl_cursor!=NULL)
									SDL_FreeSurface(sdl_cursor);
								sdl_cursor=SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCCOLORKEY, vstat.charwidth, vstat.charheight, 8, 0, 0, 0, 0);
								/* Update font. */
								sdl_load_font(NULL);
								sdl_full_screen_redraw();
							}
							else if(sdl_init_good) {
								ev.type=SDL_QUIT;
								sdl_exitcode=1;
								SDL_PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
							}
							free(ev.user.data1);
							free(ev.user.data2);
deuce's avatar
deuce committed
							SDL_mutexV(sdl_vstatlock);
							break;
						case SDL_USEREVENT_HIDEMOUSE:
							SDL_ShowCursor(SDL_DISABLE);
							break;
						case SDL_USEREVENT_SHOWMOUSE:
							SDL_ShowCursor(SDL_ENABLE);
							break;
						case SDL_USEREVENT_INIT:
							if(!sdl_init_good) {
								if(SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO) {
									if(win != NULL) {
										SDL_EnableUNICODE(1);
										SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);

										SDL_CreateThread(sdl_blinker_thread, NULL);
										SDL_CreateThread(sdl_mouse_thread, NULL);
										sdl_init_good=1;
									}
								}
							}
							SDL_SemPost(sdl_init_complete);
							break;
						case SDL_USEREVENT_COPY:
#if !defined(NO_X) && defined(__unix__)
							if(sdl_x11available && sdl_using_x11()) {
								SDL_SysWMinfo	wmi;

								SDL_VERSION(&(wmi.version));
								SDL_GetWMInfo(&wmi);
								sdl_x11.XSetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD, wmi.info.x11.window, CurrentTime);
							}
#endif
							break;
						case SDL_USEREVENT_PASTE:
#if !defined(NO_X) && defined(__unix__)
							if(sdl_x11available && sdl_using_x11()) {
								Window sowner=None;
								SDL_SysWMinfo	wmi;

								SDL_VERSION(&(wmi.version));
								SDL_GetWMInfo(&wmi);

								sowner=sdl_x11.XGetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD);
								if(sowner==wmi.info.x11.window) {
									/* Get your own primary selection */
									if(sdl_copybuf==NULL) {
										FREE_AND_NULL(sdl_pastebuf);
									}
									else
										sdl_pastebuf=(unsigned char *)malloc(strlen(sdl_copybuf)+1);
									if(sdl_pastebuf!=NULL)
										strcpy(sdl_pastebuf,sdl_copybuf);
									/* Set paste buffer */
									SDL_SemPost(sdl_pastebuf_set);
									SDL_SemWait(sdl_pastebuf_copied);
									FREE_AND_NULL(sdl_pastebuf);
								}
								else if(sowner!=None) {
									sdl_x11.XConvertSelection(wmi.info.x11.display, CONSOLE_CLIPBOARD, XA_STRING, None, wmi.info.x11.window, CurrentTime);
								}
								else {
									/* Set paste buffer */
									FREE_AND_NULL(sdl_pastebuf);
									SDL_SemPost(sdl_pastebuf_set);
									SDL_SemWait(sdl_pastebuf_copied);
								}
							}
#endif
					}
					break;
				}
				case SDL_SYSWMEVENT:			/* ToDo... This is where Copy/Paste needs doing */
#if !defined(NO_X) && defined(__unix__)
					if(sdl_x11available && sdl_using_x11()) {
						XEvent *e;
						e=&ev.syswm.msg->event.xevent;
						switch(e->type) {
							case SelectionClear: {
									XSelectionClearEvent *req;

									req=&(e->xselectionclear);
									SDL_mutexP(sdl_copybuf_mutex);
									if(req->selection==CONSOLE_CLIPBOARD) {
										FREE_AND_NULL(sdl_copybuf);
									}
									SDL_mutexV(sdl_copybuf_mutex);
									break;
							}
							case SelectionNotify: {
									int format=0;
									unsigned long len, bytes_left, dummy;
									Atom type;
									XSelectionEvent *req;
									SDL_SysWMinfo	wmi;

									SDL_VERSION(&(wmi.version));
									SDL_GetWMInfo(&wmi);
									req=&(e->xselection);
									if(req->requestor!=wmi.info.x11.window)
										break;
									sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property, 0, 0, 0, AnyPropertyType, &type, &format, &len, &bytes_left, (unsigned char **)(&sdl_pastebuf));
									if(bytes_left > 0 && format==8)
										sdl_x11.XGetWindowProperty(wmi.info.x11.display, wmi.info.x11.window, req->property,0,bytes_left,0,AnyPropertyType,&type,&format,&len,&dummy,(unsigned char **)&sdl_pastebuf);
									else {
										FREE_AND_NULL(sdl_pastebuf);
									}

									/* Set paste buffer */
									SDL_SemPost(sdl_pastebuf_set);
									SDL_SemWait(sdl_pastebuf_copied);
									if(sdl_pastebuf!=NULL) {
										sdl_x11.XFree(sdl_pastebuf);
										sdl_pastebuf=NULL;
									}
									break;
							}
							case SelectionRequest: {
									XSelectionRequestEvent *req;
									XEvent respond;

									req=&(e->xselectionrequest);
									SDL_mutexP(sdl_copybuf_mutex);
									if(sdl_copybuf==NULL) {
										respond.xselection.property=None;
									}
									else {
										if(req->target==XA_STRING) {
											sdl_x11.XChangeProperty(req->display, req->requestor, req->property, XA_STRING, 8, PropModeReplace, (unsigned char *)sdl_copybuf, strlen(sdl_copybuf));
											respond.xselection.property=req->property;
										}
										else
											respond.xselection.property=None;
									}
									SDL_mutexV(sdl_copybuf_mutex);
									respond.xselection.type=SelectionNotify;
									respond.xselection.display=req->display;
									respond.xselection.requestor=req->requestor;
									respond.xselection.selection=req->selection;
									respond.xselection.target=req->target;
									respond.xselection.time=req->time;
									sdl_x11.XSendEvent(req->display,req->requestor,0,0,&respond);
									break;
							}
						}	/* switch */
					}	/* usingx11 */
#endif				
				
				/* Ignore this stuff */
				case SDL_JOYAXISMOTION:
				case SDL_JOYBALLMOTION:
				case SDL_JOYHATMOTION:
				case SDL_JOYBUTTONDOWN:
				case SDL_JOYBUTTONUP:
				default:
					break;
			}
		}
	}
}