Skip to content
Snippets Groups Projects
sdl_con.c 38.1 KiB
Newer Older
deuce's avatar
deuce committed
				/* "Extended" syms are always right */
				if(!(mod & (KMOD_META|KMOD_ALT)))	/* Was !unicode */
deuce's avatar
deuce committed
					return(expect);
				if(sdl_keyval[i].key > 255)			/* Extended regular key */
deuce's avatar
deuce committed
					return(expect);
				if(keysym <= 127 && !(mod & (KMOD_META|KMOD_ALT)))					/* The keyboard syms have been cleverly chosen to map to ASCII */
deuce's avatar
deuce committed
				/*
				 * If we don't know that this key should
				 * return the unicode translation, then
				 * we're not right and this is prolly
				 * an AltGr sequence.
				 */
				/* if(unicode==expect) */
				return(sdl_keyval[i].alt);
				/* return(0x0001ffff); */
		if(unicode)
			return(cp437_convert(unicode));
		if(keysym < 0x80 && !(mod & KMOD_META|KMOD_ALT|KMOD_CTRL|KMOD_SHIFT))
			return(keysym);
deuce's avatar
deuce committed
		return(0x0001ffff);
deuce's avatar
deuce committed
	}
	return(cp437_convert(unicode));
/* 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);
	}
}

int sdl_video_event_thread(void *data)
deuce's avatar
deuce committed

	if(!init_sdl_video()) {
deuce's avatar
deuce committed
		while(1) {
			if(sdl.WaitEvent(&ev)==1) {
				switch (ev.type) {
					case SDL_ACTIVEEVENT:		/* Focus change */
						break;
					case SDL_KEYDOWN:			/* Keypress */
						sdl_add_key(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode));
deuce's avatar
deuce committed
					case SDL_KEYUP:				/* Ignored (handled in KEYDOWN event) */
deuce's avatar
deuce committed
					case SDL_MOUSEMOTION:
						if(!ciolib_mouse_initialized)
deuce's avatar
deuce committed
						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
					case SDL_MOUSEBUTTONDOWN:
						if(!ciolib_mouse_initialized)
deuce's avatar
deuce committed
						switch(ev.button.button) {
							case SDL_BUTTON_LEFT:
								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
							case SDL_BUTTON_MIDDLE:
								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
							case SDL_BUTTON_RIGHT:
								ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
deuce's avatar
deuce committed
						break;
					case SDL_MOUSEBUTTONUP:
						if(!ciolib_mouse_initialized)
deuce's avatar
deuce committed
						switch(ev.button.button) {
							case SDL_BUTTON_LEFT:
								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
							case SDL_BUTTON_MIDDLE:
								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
							case SDL_BUTTON_RIGHT:
								ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),ev.button.x/(vstat.charwidth*vstat.scaling)+1,ev.button.y/(vstat.charheight*vstat.scaling)+1);
								break;
						}
						break;
					case SDL_QUIT:
						sdl.SemPost(sdl_exit_sem);
deuce's avatar
deuce committed
						return(sdl_exitcode);
					case SDL_VIDEORESIZE:
						if(ev.resize.w > 0 && ev.resize.h > 0) {
deuce's avatar
deuce committed
							pthread_mutex_lock(&vstatlock);
deuce's avatar
deuce committed
							vstat.scaling=(int)(ev.resize.w/(vstat.charwidth*vstat.cols));
							if(vstat.scaling < 1)
								vstat.scaling=1;
deuce's avatar
deuce committed
							if(fullscreen) {
deuce's avatar
deuce committed
								win=sdl.SetVideoMode(
									 vstat.charwidth*vstat.cols*vstat.scaling
									,vstat.charheight*vstat.rows*vstat.scaling
deuce's avatar
deuce committed
									,8
deuce's avatar
deuce committed
									,SDL_SWSURFACE|SDL_FULLSCREEN|SDL_ANYFORMAT
deuce's avatar
deuce committed
							}
deuce's avatar
deuce committed
								win=sdl.SetVideoMode(
									 vstat.charwidth*vstat.cols*vstat.scaling
									,vstat.charheight*vstat.rows*vstat.scaling
									,8
deuce's avatar
deuce committed
									,SDL_SWSURFACE|SDL_RESIZABLE|SDL_ANYFORMAT
deuce's avatar
deuce committed
	#if (defined(__MACH__) && defined(__APPLE__))
deuce's avatar
deuce committed
								if(sdl.VideoDriverName(driver, sizeof(driver))!=NULL) {
									if(!strcmp(driver,"Quartz"))
										sdl_using_quartz=TRUE;
								}
deuce's avatar
deuce committed
	#endif
deuce's avatar
deuce committed
								if(new_rect)
									sdl.FreeSurface(new_rect);
								new_rect=NULL;
								tmp_rect=sdl.CreateRGBSurface(SDL_SWSURFACE
deuce's avatar
deuce committed
										, vstat.charwidth*vstat.cols*vstat.scaling
										, vstat.charheight*vstat.rows*vstat.scaling
										, 8, 0, 0, 0, 0);
								if(tmp_rect) {
									new_rect=sdl.DisplayFormat(tmp_rect);
									sdl.FreeSurface(tmp_rect);
								}
deuce's avatar
deuce committed
								pthread_mutex_unlock(&vstatlock);
						    	sdl_setup_colours(win);
						    	sdl_setup_colours(new_rect);
								send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
							}
							else if(sdl_init_good) {
deuce's avatar
deuce committed
								pthread_mutex_unlock(&vstatlock);
								ev.type=SDL_QUIT;
								sdl_exitcode=1;
deuce's avatar
deuce committed
								sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
deuce's avatar
deuce committed
							else
								pthread_mutex_unlock(&vstatlock);
deuce's avatar
deuce committed
						}
						break;
					case SDL_VIDEOEXPOSE:
deuce's avatar
deuce committed
						send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
deuce's avatar
deuce committed
						break;
					case SDL_USEREVENT: {
						/* Tell SDL to do various stuff... */
						switch(ev.user.code) {
							case SDL_USEREVENT_QUIT:
								sdl_ufunc_retval=0;
								sdl.SemPost(sdl_ufunc_ret);
deuce's avatar
deuce committed
							case SDL_USEREVENT_UPDATERECT:
deuce's avatar
deuce committed
								{
									struct update_rect *rect=(struct update_rect *)ev.user.data1;
									SDL_Rect r;
									SDL_Rect dst;
									int x,y;
									for(y=0; y<rect->height; y++) {
										for(x=0; x<rect->width; x++) {
											int dac_entry;
deuce's avatar
deuce committed
											r.w=vstat.scaling;
											r.h=vstat.scaling;
											dac_entry=rect->data[y*rect->width+x];
deuce's avatar
deuce committed
											r.x=x*vstat.scaling;
											r.y=y*vstat.scaling;
											sdl.FillRect(new_rect, &r, sdl_dac_default[dac_entry]);
deuce's avatar
deuce committed
										}
									}
									r.x=0;
									r.y=0;
									r.w=rect->width*vstat.scaling;
									r.h=rect->height*vstat.scaling;
									dst.x=rect->x*vstat.scaling;
									dst.y=rect->y*vstat.scaling;
									dst.w=rect->width*vstat.scaling;
									dst.h=rect->height*vstat.scaling;
									sdl.BlitSurface(new_rect, &r, win, &dst);
									sdl.UpdateRects(win,1,&dst);
									free(rect->data);
									free(rect);
									break;
								}
deuce's avatar
deuce committed
							case SDL_USEREVENT_SETNAME:
								sdl.WM_SetCaption((char *)ev.user.data1,(char *)ev.user.data1);
								free(ev.user.data1);
								break;
							case SDL_USEREVENT_SETICON:
								if(sdl_icon != NULL)
									sdl.FreeSurface(sdl_icon);
								sdl_icon=sdl.CreateRGBSurfaceFrom(ev.user.data1
										, *(unsigned long *)ev.user.data2
										, *(unsigned long *)ev.user.data2
										, 32
										, *(unsigned long *)ev.user.data2*4
										, *(DWORD *)"\377\0\0\0"
										, *(DWORD *)"\0\377\0\0"
										, *(DWORD *)"\0\0\377\0"
										, *(DWORD *)"\0\0\0\377"
								);
								sdl.WM_SetIcon(sdl_icon,NULL);
								free(ev.user.data2);
								break;
deuce's avatar
deuce committed
							case SDL_USEREVENT_SETTITLE:
								sdl.WM_SetCaption((char *)ev.user.data1,NULL);
								free(ev.user.data1);
								break;
							case SDL_USEREVENT_SETVIDMODE:
deuce's avatar
deuce committed
								pthread_mutex_lock(&vstatlock);
deuce's avatar
deuce committed
								if(fullscreen)
									win=sdl.SetVideoMode(
										 vstat.charwidth*vstat.cols*vstat.scaling
										,vstat.charheight*vstat.rows*vstat.scaling
										,8
deuce's avatar
deuce committed
										,SDL_SWSURFACE|SDL_FULLSCREEN|SDL_ANYFORMAT
deuce's avatar
deuce committed
									);
								else
									win=sdl.SetVideoMode(
										 vstat.charwidth*vstat.cols*vstat.scaling
										,vstat.charheight*vstat.rows*vstat.scaling
										,8
deuce's avatar
deuce committed
										,SDL_SWSURFACE|SDL_RESIZABLE|SDL_ANYFORMAT
deuce's avatar
deuce committed
									);
								if(win!=NULL) {
	#if (defined(__MACH__) && defined(__APPLE__))
									char	driver[16];
deuce's avatar
deuce committed
									if(sdl.VideoDriverName(driver, sizeof(driver))!=NULL) {
deuce's avatar
deuce committed
										if(!strcmp(driver,"Quartz"))
											sdl_using_quartz=TRUE;
deuce's avatar
deuce committed
	#endif
									vstat.scaling=(int)(win->w/(vstat.charwidth*vstat.cols));
									if(vstat.scaling < 1)
										vstat.scaling=1;
deuce's avatar
deuce committed
									if(new_rect)
										sdl.FreeSurface(new_rect);
									new_rect=NULL;
									tmp_rect=sdl.CreateRGBSurface(SDL_SWSURFACE
deuce's avatar
deuce committed
											, vstat.charwidth*vstat.cols*vstat.scaling
											, vstat.charheight*vstat.rows*vstat.scaling
											, 8, 0, 0, 0, 0);
									if(tmp_rect) {
										new_rect=sdl.DisplayFormat(tmp_rect);
										sdl.FreeSurface(tmp_rect);
									}
deuce's avatar
deuce committed
									pthread_mutex_unlock(&vstatlock);
						    		sdl_setup_colours(win);
						    		sdl_setup_colours(new_rect);
									send_rectangle(0,0,bitmap_width,bitmap_height,TRUE);
deuce's avatar
deuce committed
								else if(sdl_init_good) {
deuce's avatar
deuce committed
									pthread_mutex_unlock(&vstatlock);
deuce's avatar
deuce committed
									ev.type=SDL_QUIT;
									sdl_exitcode=1;
									sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
								}
deuce's avatar
deuce committed
								else
									pthread_mutex_unlock(&vstatlock);
deuce's avatar
deuce committed
								free(ev.user.data1);
								free(ev.user.data2);
								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);
											mouse_thread=sdl.CreateThread(sdl_mouse_thread, NULL);
deuce's avatar
deuce committed
											sdl_init_good=1;
deuce's avatar
deuce committed
								sdl.SemPost(sdl_init_complete);
deuce's avatar
deuce committed
							case SDL_USEREVENT_COPY:
	#if (defined(__MACH__) && defined(__APPLE__))
								if(sdl_using_quartz) {
									ScrapRef	scrap;
									sdl.mutexP(sdl_copybuf_mutex);
									if(sdl_copybuf!=NULL) {
										if(!ClearCurrentScrap()) {		/* purge the current contents of the scrap. */
											if(!GetCurrentScrap(&scrap)) {		/* obtain a reference to the current scrap. */
												PutScrapFlavor(scrap, kScrapFlavorTypeText, kScrapFlavorMaskTranslated /* kScrapFlavorMaskNone */, strlen(sdl_copybuf), sdl_copybuf); 		/* write the data to the scrap */
											}
										}
									}
									FREE_AND_NULL(sdl_copybuf);
									sdl.mutexV(sdl_copybuf_mutex);
									break;
								}
	#endif
deuce's avatar
deuce committed
	#if !defined(NO_X) && defined(__unix__)
								if(sdl_x11available && sdl_using_x11()) {
									SDL_SysWMinfo	wmi;
deuce's avatar
deuce committed
									sdl.GetWMInfo(&wmi);
									sdl_x11.XSetSelectionOwner(wmi.info.x11.display, CONSOLE_CLIPBOARD, wmi.info.x11.window, CurrentTime);
									break;
								}
	#endif
deuce's avatar
deuce committed
							case SDL_USEREVENT_PASTE:
	#if (defined(__MACH__) && defined(__APPLE__))
								if(sdl_using_quartz) {
									ScrapRef	scrap;
									UInt32	fl;
									Size		scraplen;

									FREE_AND_NULL(sdl_pastebuf);
									if(!GetCurrentScrap(&scrap)) {		/* obtain a reference to the current scrap. */
										if(!GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &fl) && (fl & kScrapFlavorMaskTranslated)) {
											if(!GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scraplen)) {
												sdl_pastebuf=(char *)malloc(scraplen+1);
												if(sdl_pastebuf!=NULL) {
													if(GetScrapFlavorData(scrap, kScrapFlavorTypeText, &scraplen, sdl_pastebuf)) {
														FREE_AND_NULL(sdl_pastebuf);
													}
deuce's avatar
deuce committed
									sdl.SemPost(sdl_pastebuf_set);
									sdl.SemWait(sdl_pastebuf_copied);
									break;
deuce's avatar
deuce committed
	#endif
deuce's avatar
deuce committed
	#if !defined(NO_X) && defined(__unix__)
								if(sdl_x11available && sdl_using_x11()) {
									Window sowner=None;
									SDL_SysWMinfo	wmi;
deuce's avatar
deuce committed
									sdl.GetWMInfo(&wmi);
deuce's avatar
deuce committed
									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);
									}
deuce's avatar
deuce committed
									else if(sowner!=None) {
										sdl_x11.XConvertSelection(wmi.info.x11.display, CONSOLE_CLIPBOARD, XA_STRING, None, wmi.info.x11.window, CurrentTime);
deuce's avatar
deuce committed
										/* Set paste buffer */
										FREE_AND_NULL(sdl_pastebuf);
deuce's avatar
deuce committed
										sdl.SemPost(sdl_pastebuf_set);
										sdl.SemWait(sdl_pastebuf_copied);
deuce's avatar
deuce committed
								}
	#else
								break;
	#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);
deuce's avatar
deuce committed
										sdl.mutexV(sdl_copybuf_mutex);
										break;
								}
								case SelectionNotify: {
										int format=0;
										unsigned long len, bytes_left, dummy;
										Atom type;
										XSelectionEvent *req;
										SDL_SysWMinfo	wmi;

deuce's avatar
deuce committed
										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;
deuce's avatar
deuce committed
										}
										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;
				}
deuce's avatar
deuce committed
	return(0);
	if(init_sdl_video())
		return(-1);
	if(init_sdl_video()==-1)
		return(-1);
	sdl_key_pending=sdl.SDL_CreateSemaphore(0);
	sdl_init_complete=sdl.SDL_CreateSemaphore(0);
	sdl_ufunc_ret=sdl.SDL_CreateSemaphore(0);
	sdl_keylock=sdl.SDL_CreateMutex();
	sdl_ufunc_lock=sdl.SDL_CreateMutex();
#if !defined(NO_X) && defined(__unix__)
	sdl_pastebuf_set=sdl.SDL_CreateSemaphore(0);
	sdl_pastebuf_copied=sdl.SDL_CreateSemaphore(0);
	sdl_copybuf_mutex=sdl.SDL_CreateMutex();
#endif
	run_sdl_drawing_thread(sdl_video_event_thread, exit_sdl_con);