Skip to content
Snippets Groups Projects
sdl_con.c 37.5 KiB
Newer Older
#if (defined(__MACH__) && defined(__APPLE__))
#include <Carbon/Carbon.h>
#endif

#include <stdarg.h>
#include <stdio.h>		/* NULL */
deuce's avatar
deuce committed
#include <stdlib.h>

#include "gen_defs.h"
#include "genwrap.h"
deuce's avatar
deuce committed
#include "threadwrap.h"
#if (defined CIOLIB_IMPORTS)
 #undef CIOLIB_IMPORTS
#endif
#if (defined CIOLIB_EXPORTS)
 #undef CIOLIB_EXPORTS
#endif

#include "keys.h"
#include "vidmodes.h"
deuce's avatar
deuce committed
#include "bitmap_con.h"
deuce's avatar
deuce committed
#include "SDL_thread.h"
deuce's avatar
deuce committed

#include "sdlfuncs.h"

deuce's avatar
deuce committed
int bitmap_width,bitmap_height;

/* 256 bytes so I can cheat */
unsigned char		sdl_keybuf[256];		/* Keyboard buffer */
unsigned char		sdl_key=0;				/* Index into keybuf for next key in buffer */
unsigned char		sdl_keynext=0;			/* Index into keybuf for next free position */
int sdl_exitcode=0;
deuce's avatar
deuce committed
SDL_Surface	*win=NULL;
SDL_Surface	*sdl_icon=NULL;
deuce's avatar
deuce committed
SDL_Surface	*new_rect=NULL;
deuce's avatar
deuce committed
/* *nix copy/paste stuff */
SDL_sem	*sdl_pastebuf_set;
SDL_sem	*sdl_pastebuf_copied;
SDL_mutex	*sdl_copybuf_mutex;
static SDL_Thread *mouse_thread;
deuce's avatar
deuce committed
char *sdl_copybuf=NULL;
char *sdl_pastebuf=NULL;

SDL_mutex *sdl_ufunc_lock;
SDL_sem *sdl_ufunc_ret;
int sdl_ufunc_retval;
int fullscreen=0;
deuce's avatar
deuce committed
SDL_sem *sdl_init_complete;
int	sdl_init_good=0;
SDL_mutex *sdl_keylock;
SDL_sem *sdl_key_pending;
static unsigned int sdl_pending_mousekeys=0;

struct sdl_keyvals {
	int	keysym
		,key
		,shift
		,ctrl
		,alt;
};

deuce's avatar
deuce committed
struct update_rect {
	int		x;
	int		y;
	int		width;
	int		height;
	unsigned char *data;
};

enum {
	 SDL_USEREVENT_UPDATERECT
	,SDL_USEREVENT_SETTITLE
	,SDL_USEREVENT_SETICON
	,SDL_USEREVENT_SETVIDMODE
	,SDL_USEREVENT_SHOWMOUSE
	,SDL_USEREVENT_HIDEMOUSE
	,SDL_USEREVENT_INIT
	,SDL_USEREVENT_COPY
	,SDL_USEREVENT_PASTE
	,SDL_USEREVENT_QUIT
};

const struct sdl_keyvals sdl_keyval[] =
{
	{SDLK_BACKSPACE, 0x08, 0x08, 0x7f, 0x0e00},
	{SDLK_TAB, 0x09, 0x0f00, 0x9400, 0xa500},
	{SDLK_RETURN, 0x0d, 0x0d, 0x0a, 0xa600},
	{SDLK_ESCAPE, 0x1b, 0x1b, 0x1b, 0x0100},
	{SDLK_SPACE, 0x20, 0x20, 0x0300, 0x20},
	{SDLK_0, '0', ')', 0, 0x8100},
	{SDLK_1, '1', '!', 0, 0x7800},
	{SDLK_2, '2', '@', 0x0300, 0x7900},
	{SDLK_3, '3', '#', 0, 0x7a00},
	{SDLK_4, '4', '$', 0, 0x7b00},
	{SDLK_5, '5', '%', 0, 0x7c00},
	{SDLK_6, '6', '^', 0x1e, 0x7d00},
	{SDLK_7, '7', '&', 0, 0x7e00},
	{SDLK_8, '8', '*', 0, 0x7f00},
	{SDLK_9, '9', '(', 0, 0x8000},
	{SDLK_a, 'a', 'A', 0x01, 0x1e00},
	{SDLK_b, 'b', 'B', 0x02, 0x3000},
	{SDLK_c, 'c', 'C', 0x03, 0x2e00},
	{SDLK_d, 'd', 'D', 0x04, 0x2000},
	{SDLK_e, 'e', 'E', 0x05, 0x1200},
	{SDLK_f, 'f', 'F', 0x06, 0x2100},
	{SDLK_g, 'g', 'G', 0x07, 0x2200},
	{SDLK_h, 'h', 'H', 0x08, 0x2300},
	{SDLK_i, 'i', 'I', 0x09, 0x1700},
	{SDLK_j, 'j', 'J', 0x0a, 0x2400},
	{SDLK_k, 'k', 'K', 0x0b, 0x2500},
	{SDLK_l, 'l', 'L', 0x0c, 0x2600},
	{SDLK_m, 'm', 'M', 0x0d, 0x3200},
	{SDLK_n, 'n', 'N', 0x0e, 0x3100},
	{SDLK_o, 'o', 'O', 0x0f, 0x1800},
	{SDLK_p, 'p', 'P', 0x10, 0x1900},
	{SDLK_q, 'q', 'Q', 0x11, 0x1000},
	{SDLK_r, 'r', 'R', 0x12, 0x1300},
	{SDLK_s, 's', 'S', 0x13, 0x1f00},
	{SDLK_t, 't', 'T', 0x14, 0x1400},
	{SDLK_u, 'u', 'U', 0x15, 0x1600},
	{SDLK_v, 'v', 'V', 0x16, 0x2f00},
	{SDLK_w, 'w', 'W', 0x17, 0x1100},
	{SDLK_x, 'x', 'X', 0x18, 0x2d00},
	{SDLK_y, 'y', 'Y', 0x19, 0x1500},
	{SDLK_z, 'z', 'Z', 0x1a, 0x2c00},
	{SDLK_PAGEUP, 0x4900, 0x4900, 0x8400, 0x9900},
	{SDLK_PAGEDOWN, 0x5100, 0x5100, 0x7600, 0xa100},
	{SDLK_END, 0x4f00, 0x4f00, 0x7500, 0x9f00},
	{SDLK_HOME, 0x4700, 0x4700, 0x7700, 0x9700},
	{SDLK_LEFT, 0x4b00, 0x4b00, 0x7300, 0x9b00},
	{SDLK_UP, 0x4800, 0x4800, 0x8d00, 0x9800},
	{SDLK_RIGHT, 0x4d00, 0x4d00, 0x7400, 0x9d00},
	{SDLK_DOWN, 0x5000, 0x5000, 0x9100, 0xa000},
	{SDLK_INSERT, 0x5200, 0x5200, 0x9200, 0xa200},
	{SDLK_DELETE, 0x5300, 0x5300, 0x9300, 0xa300},
	{SDLK_KP0, 0x5200, 0x5200, 0x9200, 0},
	{SDLK_KP1, 0x4f00, 0x4f00, 0x7500, 0},
	{SDLK_KP2, 0x5000, 0x5000, 0x9100, 0},
	{SDLK_KP3, 0x5100, 0x5100, 0x7600, 0},
	{SDLK_KP4, 0x4b00, 0x4b00, 0x7300, 0},
	{SDLK_KP5, 0x4c00, 0x4c00, 0x8f00, 0},
	{SDLK_KP6, 0x4d00, 0x4d00, 0x7400, 0},
	{SDLK_KP7, 0x4700, 0x4700, 0x7700, 0},
	{SDLK_KP8, 0x4800, 0x4800, 0x8d00, 0},
	{SDLK_KP9, 0x4900, 0x4900, 0x8400, 0},
	{SDLK_KP_MULTIPLY, '*', '*', 0x9600, 0x3700},
	{SDLK_KP_PLUS, '+', '+', 0x9000, 0x4e00},
	{SDLK_KP_MINUS, '-', '-', 0x8e00, 0x4a00},
	{SDLK_KP_PERIOD, 0x7f, 0x7f, 0x5300, 0x9300},
	{SDLK_KP_DIVIDE, '/', '/', 0x9500, 0xa400},
	{SDLK_KP_ENTER, 0x0d, 0x0d, 0x0a, 0xa600},
	{SDLK_F1, 0x3b00, 0x5400, 0x5e00, 0x6800},
	{SDLK_F2, 0x3c00, 0x5500, 0x5f00, 0x6900},
	{SDLK_F3, 0x3d00, 0x5600, 0x6000, 0x6a00},
	{SDLK_F4, 0x3e00, 0x5700, 0x6100, 0x6b00},
	{SDLK_F5, 0x3f00, 0x5800, 0x6200, 0x6c00},
	{SDLK_F6, 0x4000, 0x5900, 0x6300, 0x6d00},
	{SDLK_F7, 0x4100, 0x5a00, 0x6400, 0x6e00},
	{SDLK_F8, 0x4200, 0x5b00, 0x6500, 0x6f00},
	{SDLK_F9, 0x4300, 0x5c00, 0x6600, 0x7000},
	{SDLK_F10, 0x4400, 0x5d00, 0x6700, 0x7100},
	{SDLK_F11, 0x8500, 0x8700, 0x8900, 0x8b00},
	{SDLK_F12, 0x8600, 0x8800, 0x8a00, 0x8c00},
	{SDLK_BACKSLASH, '\\', '|', 0x1c, 0x2b00},
	{SDLK_SLASH, '/', '?', 0, 0x3500},
	{SDLK_MINUS, '-', '_', 0x1f, 0x8200},
	{SDLK_EQUALS, '=', '+', 0, 0x8300},
	{SDLK_LEFTBRACKET, '[', '{', 0x1b, 0x1a00},
	{SDLK_RIGHTBRACKET, ']', '}', 0x1d, 0x1b00},
	{SDLK_SEMICOLON, ';', ':', 0, 0x2700},
	{SDLK_BACKSLASH, '\'', '"', 0, 0x2800},
	{SDLK_COMMA, ',', '<', 0, 0x3300},
	{SDLK_PERIOD, '.', '>', 0, 0x3400},
	{SDLK_BACKQUOTE, '`', '~', 0, 0x2900},
	{0, 0, 0, 0, 0}	/** END **/
};
#if !defined(NO_X) && defined(__unix__)
#include "SDL_syswm.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>
#include <X11/Xatom.h>

#define CONSOLE_CLIPBOARD	XA_PRIMARY

int sdl_x11available=0;

/* X functions */
struct x11 {
	int		(*XFree)		(void *data);
	Window	(*XGetSelectionOwner)	(Display*, Atom);
	int		(*XConvertSelection)	(Display*, Atom, Atom, Atom, Window, Time);
	int		(*XGetWindowProperty)	(Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **);
	int		(*XChangeProperty)		(Display*, Window, Atom, Atom, int, int, _Xconst unsigned char*, int);
	Status	(*XSendEvent)	(Display*, Window, Bool, long, XEvent*);
	int		(*XSetSelectionOwner)	(Display*, Atom, Window, Time);
};
struct x11 sdl_x11;
#endif

void sdl_user_func(int func, ...)
{
	unsigned int	*i;
	va_list argptr;
	void	**args;
	SDL_Event	ev;
	ev.type=SDL_USEREVENT;
	ev.user.data1=NULL;
	ev.user.data2=NULL;
	ev.user.code=func;
	va_start(argptr, func);
	switch(func) {
		case SDL_USEREVENT_UPDATERECT:
deuce's avatar
deuce committed
			ev.user.data1=va_arg(argptr, struct update_rect *);
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
		case SDL_USEREVENT_SETNAME:
			if((ev.user.data1=strdup(va_arg(argptr, char *)))==NULL) {
				va_end(argptr);
				return;
			}
deuce's avatar
deuce committed
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
		case SDL_USEREVENT_SETICON:
			ev.user.data1=va_arg(argptr, void *);
			if((ev.user.data2=(unsigned long *)malloc(sizeof(unsigned long)))==NULL) {
				va_end(argptr);
				return;
			}
			*(unsigned long *)ev.user.data2=va_arg(argptr, unsigned long);
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
			break;
		case SDL_USEREVENT_SETTITLE:
			if((ev.user.data1=strdup(va_arg(argptr, char *)))==NULL) {
deuce's avatar
deuce committed
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
			break;
		case SDL_USEREVENT_SETVIDMODE:
			if((ev.user.data1=(void *)malloc(sizeof(int)))==NULL) {
			*((int *)ev.user.data1)=va_arg(argptr, int);
			if((ev.user.data2=(void *)malloc(sizeof(int)))==NULL) {
				free(ev.user.data1);
			*((int *)ev.user.data2)=va_arg(argptr, int);
deuce's avatar
deuce committed
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
		case SDL_USEREVENT_COPY:
		case SDL_USEREVENT_PASTE:
		case SDL_USEREVENT_SHOWMOUSE:
		case SDL_USEREVENT_HIDEMOUSE:
		case SDL_USEREVENT_INIT:
deuce's avatar
deuce committed
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
/* Called from main thread only */
int sdl_user_func_ret(int func, ...)
{
	unsigned int	*i;
	va_list argptr;
	void	**args;
	SDL_Event	ev;
	int		passed=FALSE;
	char	*p;

	sdl.mutexP(sdl_ufunc_lock);
	ev.type=SDL_USEREVENT;
	ev.user.data1=NULL;
	ev.user.data2=NULL;
	ev.user.code=func;
	va_start(argptr, func);
	switch(func) {
		case SDL_USEREVENT_QUIT:
			while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1);
			passed=TRUE;
			break;
	}
	if(passed)
		sdl.SemWait(sdl_ufunc_ret);
	else
		sdl_ufunc_retval=-1;
	sdl.mutexV(sdl_ufunc_lock);
	va_end(argptr);
	return(sdl_ufunc_retval);
}

void exit_sdl_con(void)
{
	sdl_user_func_ret(SDL_USEREVENT_QUIT);
}

#if (defined(__MACH__) && defined(__APPLE__))
int sdl_using_quartz=0;
#endif

#if !defined(NO_X) && defined(__unix__)
int sdl_using_x11()
{
	char	driver[16];

deuce's avatar
deuce committed
	if(sdl.VideoDriverName(driver, sizeof(driver))==NULL)
		return(FALSE);
	if(!strcmp(driver,"x11"))
		return(TRUE);
	if(!strcmp(driver,"dga"))
		return(TRUE);
	return(FALSE);
}
#endif

void sdl_copytext(const char *text, size_t buflen)
{
#if (defined(__MACH__) && defined(__APPLE__))
	if(sdl_using_quartz) {
deuce's avatar
deuce committed
		sdl.mutexP(sdl_copybuf_mutex);
		FREE_AND_NULL(sdl_copybuf);

		sdl_copybuf=(char *)malloc(buflen+1);
		if(sdl_copybuf!=NULL) {
			strcpy(sdl_copybuf, text);
			sdl_user_func(SDL_USEREVENT_COPY,0,0,0,0);
deuce's avatar
deuce committed
		sdl.mutexV(sdl_copybuf_mutex);
#if !defined(NO_X) && defined(__unix__)
	if(sdl_x11available && sdl_using_x11()) {
deuce's avatar
deuce committed
		sdl.mutexP(sdl_copybuf_mutex);
		FREE_AND_NULL(sdl_copybuf);

		sdl_copybuf=(char *)malloc(buflen+1);
		if(sdl_copybuf!=NULL) {
			strcpy(sdl_copybuf, text);
			sdl_user_func(SDL_USEREVENT_COPY,0,0,0,0);
		}
deuce's avatar
deuce committed
		sdl.mutexV(sdl_copybuf_mutex);
deuce's avatar
deuce committed
	sdl.mutexP(sdl_copybuf_mutex);
	FREE_AND_NULL(sdl_copybuf);

	sdl_copybuf=(char *)malloc(buflen+1);
	if(sdl_copybuf!=NULL)
		strcpy(sdl_copybuf, text);
deuce's avatar
deuce committed
	sdl.mutexV(sdl_copybuf_mutex);
	return;
}

char *sdl_getcliptext(void)
{
	char *ret=NULL;

#if (defined(__MACH__) && defined(__APPLE__))
	if(sdl_using_quartz) {
		sdl_user_func(SDL_USEREVENT_PASTE,0,0,0,0);
deuce's avatar
deuce committed
		sdl.SemWait(sdl_pastebuf_set);
		if(sdl_pastebuf!=NULL) {
			ret=(char *)malloc(strlen(sdl_pastebuf)+1);
			if(ret!=NULL)
				strcpy(ret,sdl_pastebuf);
deuce's avatar
deuce committed
			sdl.SemPost(sdl_pastebuf_copied);
#if !defined(NO_X) && defined(__unix__)
	if(sdl_x11available && sdl_using_x11()) {
		sdl_user_func(SDL_USEREVENT_PASTE,0,0,0,0);
deuce's avatar
deuce committed
		sdl.SemWait(sdl_pastebuf_set);
		if(sdl_pastebuf!=NULL) {
			ret=(char *)malloc(strlen(sdl_pastebuf)+1);
			if(ret!=NULL)
				strcpy(ret,sdl_pastebuf);
deuce's avatar
deuce committed
			sdl.SemPost(sdl_pastebuf_copied);
deuce's avatar
deuce committed
	sdl.mutexP(sdl_copybuf_mutex);
	ret=(char *)malloc(strlen(sdl_pastebuf)+1);
	if(ret!=NULL)
		strcpy(ret,sdl_copybuf);
deuce's avatar
deuce committed
	sdl.mutexV(sdl_copybuf_mutex);
deuce's avatar
deuce committed
void sdl_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data)
deuce's avatar
deuce committed
	struct update_rect *rect;

	rect=(struct update_rect *)malloc(sizeof(struct update_rect));
	if(sdl_init_good) {
		rect->x=xoffset;
		rect->y=yoffset;
		rect->width=width;
		rect->height=height;
		rect->data=data;
		sdl_user_func(SDL_USEREVENT_UPDATERECT, rect);
    struct video_params vmode;
    int idx;			/* Index into vmode */
    int i;
    int oldcols=vstat.cols;
deuce's avatar
deuce committed
	bitmap_init_mode(mode, &bitmap_width, &bitmap_height);
	/* Deal with 40 col doubling */
	if(oldcols != vstat.cols) {
		if(oldcols == 40)
			vstat.scaling /= 2;
		if(vstat.cols == 40)
			vstat.scaling *= 2;
	}

	if(vstat.scaling < 1)
		vstat.scaling = 1;

	sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols*vstat.scaling, vstat.charheight*vstat.rows*vstat.scaling);
/* Called from main thread only (Passes Event) */
int sdl_init(int mode)
#if !defined(NO_X) && defined(__unix__)
	void *dl;
#endif

	if(init_sdl_video())
deuce's avatar
deuce committed
		return(-1);

deuce's avatar
deuce committed
	bitmap_init(sdl_drawrect);
	if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
		fullscreen=1;
	sdl_init_mode(3);
	sdl_user_func(SDL_USEREVENT_INIT);
deuce's avatar
deuce committed
	sdl.SemWait(sdl_init_complete);
deuce's avatar
deuce committed
	if(sdl_init_good) {
		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
deuce's avatar
deuce committed
#ifdef _WIN32
#endif
#if !defined(NO_X) && defined(__unix__)
	#if defined(__APPLE__) && defined(__MACH__) && defined(__POWERPC__)
		dl=dlopen("/usr/X11R6/lib/libX11.dylib",RTLD_LAZY|RTLD_GLOBAL);
		if((dl=dlopen("libX11.so",RTLD_LAZY))==NULL)
			if((dl=dlopen("libX11.so.7",RTLD_LAZY))==NULL)
				if((dl=dlopen("libX11.so.6",RTLD_LAZY))==NULL)
					dl=dlopen("libX11.so.5",RTLD_LAZY);
			sdl_x11available=TRUE;
			if(sdl_x11available && (sdl_x11.XFree=dlsym(dl,"XFree"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XGetSelectionOwner=dlsym(dl,"XGetSelectionOwner"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XConvertSelection=dlsym(dl,"XConvertSelection"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XGetWindowProperty=dlsym(dl,"XGetWindowProperty"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XChangeProperty=dlsym(dl,"XChangeProperty"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XSendEvent=dlsym(dl,"XSendEvent"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
			if(sdl_x11available && (sdl_x11.XSetSelectionOwner=dlsym(dl,"XSetSelectionOwner"))==NULL) {
				dlclose(dl);
				sdl_x11available=FALSE;
			}
		}
		if(sdl_x11available)
deuce's avatar
deuce committed
			sdl.EventState(SDL_SYSWMEVENT, SDL_ENABLE);
deuce's avatar
deuce committed
#endif
deuce's avatar
deuce committed
	}
}

/* Called from main thread only */
int sdl_kbhit(void)
{
	int ret;

deuce's avatar
deuce committed
	sdl.mutexP(sdl_keylock);
	ret=(sdl_key!=sdl_keynext);
deuce's avatar
deuce committed
	sdl.mutexV(sdl_keylock);
	return(ret);
}

/* Called from main thread only */
int sdl_getch(void)
{
	int ch;

deuce's avatar
deuce committed
	sdl.SemWait(sdl_key_pending);
	sdl.mutexP(sdl_keylock);
	ch=sdl_keybuf[sdl_key++];
	if(sdl_pending_mousekeys) {
        sdl_keybuf[sdl_keynext++]=CIO_KEY_MOUSE & 0xff;
        sdl.SemPost(sdl_key_pending);
        sdl_keybuf[sdl_keynext++]=CIO_KEY_MOUSE >> 8;
        sdl.SemPost(sdl_key_pending);
		sdl_pending_mousekeys--;
	}
deuce's avatar
deuce committed
	sdl.mutexV(sdl_keylock);
	return(ch);
}

/* Called from main thread only */
void sdl_textmode(int mode)
{
	sdl_init_mode(mode);
}

/* Called from main thread only (Passes Event) */
int sdl_setname(const char *name)
{
	sdl_user_func(SDL_USEREVENT_SETNAME,name);
	return(0);
}

/* Called from main thread only (Passes Event) */
int sdl_seticon(const void *icon, unsigned long size)
{
	sdl_user_func(SDL_USEREVENT_SETICON,icon,size);
	return(0);
}

/* Called from main thread only (Passes Event) */
int sdl_settitle(const char *title)
{
	sdl_user_func(SDL_USEREVENT_SETTITLE,title);
	return(0);
}

int sdl_showmouse(void)
{
	sdl_user_func(SDL_USEREVENT_SHOWMOUSE);
	return(1);
}

int sdl_hidemouse(void)
{
	sdl_user_func(SDL_USEREVENT_HIDEMOUSE);
deuce's avatar
deuce committed
	return(0);
int sdl_get_window_info(int *width, int *height, int *xpos, int *ypos)
{
	if(width)
		*width=vstat.charwidth*vstat.cols*vstat.scaling;
	if(height)
deuce's avatar
deuce committed
		*height=vstat.charheight*vstat.rows*vstat.scaling;
/* Called from event thread only */
void sdl_add_key(unsigned int keyval)
{
	if(keyval==0xa600) {
		fullscreen=!fullscreen;
deuce's avatar
deuce committed
		cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
		sdl_user_func(SDL_USEREVENT_SETVIDMODE,vstat.charwidth*vstat.cols, vstat.charheight*vstat.rows);
deuce's avatar
deuce committed
		sdl.mutexP(sdl_keylock);
deuce's avatar
deuce committed
			sdl.mutexV(sdl_keylock);
			return;
		}
		if((sdl_keynext+2==sdl_key) && keyval > 0xff) {
			if(keyval==CIO_KEY_MOUSE)
				sdl_pending_mousekeys++;
			else
deuce's avatar
deuce committed
			sdl.mutexV(sdl_keylock);
			return;
		}
		sdl_keybuf[sdl_keynext++]=keyval & 0xff;
deuce's avatar
deuce committed
		sdl.SemPost(sdl_key_pending);
		if(keyval>0xff) {
			sdl_keybuf[sdl_keynext++]=keyval >> 8;
deuce's avatar
deuce committed
			sdl.SemPost(sdl_key_pending);
deuce's avatar
deuce committed
		sdl.mutexV(sdl_keylock);
deuce's avatar
deuce committed
int sdl_setup_colours(SDL_Surface *surf)
deuce's avatar
deuce committed
	SDL_Color	co[sizeof(dac_default)/sizeof(struct dac_colors)];
deuce's avatar
deuce committed
	for(i=0; i<(sizeof(dac_default)/sizeof(struct dac_colors)); i++) {
		co[i].r=dac_default[vstat.palette[i]].red;
		co[i].g=dac_default[vstat.palette[i]].green;
		co[i].b=dac_default[vstat.palette[i]].blue;
deuce's avatar
deuce committed
	sdl.SetColors(surf, co, 0, sizeof(dac_default)/sizeof(struct dac_colors));
unsigned int cp437_convert(unsigned int unicode)
{
deuce's avatar
deuce committed
	if(unicode <= 0x80)
		return(unicode);
	switch(unicode) {
		case 0x00c7:
			return(0x80);
		case 0x00fc:
			return(0x81);
		case 0x00e9:
			return(0x82);
		case 0x00e2:
			return(0x83);
		case 0x00e4:
			return(0x84);
		case 0x00e0:
			return(0x85);
		case 0x00e5:
			return(0x86);
		case 0x00e7:
			return(0x87);
		case 0x00ea:
			return(0x88);
		case 0x00eb:
			return(0x89);
		case 0x00e8:
			return(0x8a);
		case 0x00ef:
			return(0x8b);
		case 0x00ee:
			return(0x8c);
		case 0x00ec:
			return(0x8d);
		case 0x00c4:
			return(0x8e);
		case 0x00c5:
			return(0x8f);
		case 0x00c9:
			return(0x90);
		case 0x00e6:
			return(0x91);
		case 0x00c6:
			return(0x92);
		case 0x00f4:
			return(0x93);
		case 0x00f6:
			return(0x94);
		case 0x00f2:
			return(0x95);
		case 0x00fb:
			return(0x96);
		case 0x00f9:
			return(0x97);
		case 0x00ff:
			return(0x98);
		case 0x00d6:
			return(0x99);
		case 0x00dc:
			return(0x9a);
		case 0x00a2:
			return(0x9b);
		case 0x00a3:
			return(0x9c);
		case 0x00a5:
			return(0x9d);
		case 0x20a7:
			return(0x9e);
		case 0x0192:
			return(0x9f);
		case 0x00e1:
			return(0xa0);
		case 0x00ed:
			return(0xa1);
		case 0x00f3:
			return(0xa2);
		case 0x00fa:
			return(0xa3);
		case 0x00f1:
			return(0xa4);
		case 0x00d1:
			return(0xa5);
		case 0x00aa:
			return(0xa6);
		case 0x00ba:
			return(0xa7);
		case 0x00bf:
			return(0xa8);
		case 0x2310:
			return(0xa9);
		case 0x00ac:
			return(0xaa);
		case 0x00bd:
			return(0xab);
		case 0x00bc:
			return(0xac);
		case 0x00a1:
			return(0xad);
		case 0x00ab:
			return(0xae);
		case 0x00bb:
			return(0xaf);
		case 0x2591:
			return(0xb0);
		case 0x2592:
			return(0xb1);
		case 0x2593:
			return(0xb2);
		case 0x2502:
			return(0xb3);
		case 0x2524:
			return(0xb4);
		case 0x2561:
			return(0xb5);
		case 0x2562:
			return(0xb6);
		case 0x2556:
			return(0xb7);
		case 0x2555:
			return(0xb8);
		case 0x2563:
			return(0xb9);
		case 0x2551:
			return(0xba);
		case 0x2557:
			return(0xbb);
		case 0x255d:
			return(0xbc);
		case 0x255c:
			return(0xbd);
		case 0x255b:
			return(0xbe);
		case 0x2510:
			return(0xbf);
		case 0x2514:
			return(0xc0);
		case 0x2534:
			return(0xc1);
		case 0x252c:
			return(0xc2);
		case 0x251c:
			return(0xc3);
		case 0x2500:
			return(0xc4);
		case 0x253c:
			return(0xc5);
		case 0x255e:
			return(0xc6);
		case 0x255f:
			return(0xc7);
		case 0x255a:
			return(0xc8);
		case 0x2554:
			return(0xc9);
		case 0x2569:
			return(0xca);
		case 0x2566:
			return(0xcb);
		case 0x2560:
			return(0xcc);
		case 0x2550:
			return(0xcd);
		case 0x256c:
			return(0xce);
		case 0x2567:
			return(0xcf);
		case 0x2568:
			return(0xd0);
		case 0x2564:
			return(0xd1);
		case 0x2565:
			return(0xd2);
		case 0x2559:
			return(0xd3);
		case 0x2558:
			return(0xd4);
		case 0x2552:
			return(0xd5);
		case 0x2553:
			return(0xd6);
		case 0x256b:
			return(0xd7);
		case 0x256a:
			return(0xd8);
		case 0x2518:
			return(0xd9);
		case 0x250c:
			return(0xda);
		case 0x2588:
			return(0xdb);
		case 0x2584:
			return(0xdc);
		case 0x258c:
			return(0xdd);
		case 0x2590:
			return(0xde);
		case 0x2580:
			return(0xdf);
		case 0x03b1:
			return(0xe0);
		case 0x00df:
			return(0xe1);
		case 0x0393:
			return(0xe2);
		case 0x03c0:
			return(0xe3);
		case 0x03a3:
			return(0xe4);
		case 0x03c3:
			return(0xe5);
		case 0x00b5:
			return(0xe6);
		case 0x03c4:
			return(0xe7);
		case 0x03a6:
			return(0xe8);
		case 0x0398:
			return(0xe9);
		case 0x03a9:
			return(0xea);
		case 0x03b4:
			return(0xeb);
		case 0x221e:
			return(0xec);
		case 0x03c6:
			return(0xed);
		case 0x03b5:
			return(0xee);
		case 0x2229:
			return(0xef);
		case 0x2261:
			return(0xf0);
		case 0x00b1:
			return(0xf1);
		case 0x2265:
			return(0xf2);
		case 0x2264:
			return(0xf3);
		case 0x2320:
			return(0xf4);
		case 0x2321:
			return(0xf5);
		case 0x00f7:
			return(0xf6);
		case 0x2248:
			return(0xf7);
		case 0x00b0:
			return(0xf8);
		case 0x2219:
			return(0xf9);
		case 0x00b7:
			return(0xfa);
		case 0x221a:
			return(0xfb);
		case 0x207f:
			return(0xfc);
		case 0x00b2:
			return(0xfd);
		case 0x25a0:
			return(0xfe);
		case 0x00a0:
			return(0xff);
	}
	return(0x01ffff);
}

/* Called from event thread only */
unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod, unsigned int unicode)
deuce's avatar
deuce committed
	int expect;
	int i;

#ifdef __DARWIN__
deuce's avatar
deuce committed
	if(unicode==0x7f) {
deuce's avatar
deuce committed
		unicode=0x08;
		keysym=SDLK_BACKSPACE;
	}
#endif
	if((!unicode) || (keysym > SDLK_FIRST && keysym < SDLK_LAST) || (mod & (KMOD_META|KMOD_ALT))) {
deuce's avatar
deuce committed
		for(i=0;sdl_keyval[i].keysym;i++) {
			if(sdl_keyval[i].keysym==keysym) {
				if(mod & KMOD_CTRL)
					expect=sdl_keyval[i].ctrl;
				else if(mod & KMOD_SHIFT)
					expect=sdl_keyval[i].shift;
				else
					expect=sdl_keyval[i].key;

				/*
				 * Apparently, Win32 SDL doesn't interpret keypad with numlock...
				 * So, do that here. *sigh*
				 */
				if(keysym >= SDLK_KP0 && keysym <= SDLK_KP_EQUALS 
						&& (mod & KMOD_NUM)
						&& (!(mod & (KMOD_CTRL|KMOD_SHIFT|KMOD_ALT|KMOD_META) ))) {
					switch(keysym) {
						case SDLK_KP_PERIOD:
						case SDLK_KP_DIVIDE:
						case SDLK_KP_MULTIPLY:
						case SDLK_KP_MINUS:
						case SDLK_KP_PLUS:
						case SDLK_KP_ENTER:
						case SDLK_KP_EQUALS:
deuce's avatar
deuce committed
				/* "Extended" syms are always right */