Newer
Older
#if (defined(__MACH__) && defined(__APPLE__))
#include <Carbon/Carbon.h>
#define USE_PASTEBOARD
#include "pasteboard.h"
#include <stdarg.h>
#include <stdio.h> /* NULL */
#include <string.h>
#include "gen_defs.h"
#include "genwrap.h"
#include "dirwrap.h"
#include "xpbeep.h"
#ifdef __unix__
#include <xp_dl.h>
#endif
#if (defined CIOLIB_IMPORTS)
#undef CIOLIB_IMPORTS
#endif
#if (defined CIOLIB_EXPORTS)
#undef CIOLIB_EXPORTS
#endif
#include "ciolib.h"
#include "vidmodes.h"
#define BITMAP_CIOLIB_DRIVER
#include "SDL.h"
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 */
SDL_mutex *win_mutex;
SDL_mutex *newrect_mutex;
SDL_mutex *bitmap_init_mutex;
static int bitmap_initialized = 0;
int paste_needs_events;
int copy_needs_events;
SDL_sem *sdl_pastebuf_set;
SDL_sem *sdl_pastebuf_copied;
SDL_mutex *sdl_copybuf_mutex;
char *sdl_copybuf=NULL;
char *sdl_pastebuf=NULL;
SDL_sem *sdl_ufunc_ret;
SDL_sem *sdl_ufunc_rec;
SDL_mutex *sdl_ufunc_mtx;
SDL_sem *sdl_flush_sem;
int pending_updates=0;
int sdl_init_good=0;
SDL_mutex *sdl_keylock;
SDL_sem *sdl_key_pending;
static unsigned int sdl_pending_mousekeys=0;
static int sdl_using_directx=0;
static int sdl_using_quartz=0;
static int sdl_using_x11=0;
static int sdl_x11available=0;
static struct video_stats cvstat;
struct yuv_settings {
int enabled;
int win_width;
int win_height;
static struct yuv_settings yuv={0,0,0,0,0,0,0,NULL};
struct sdl_keyvals {
int keysym
,key
,shift
,ctrl
,alt;
};
static SDL_mutex *sdl_headlock;
static struct rectlist *update_list = NULL;
static struct rectlist *update_list_tail = NULL;
SDL_USEREVENT_FLUSH
,SDL_USEREVENT_SETTITLE
,SDL_USEREVENT_SETNAME
,SDL_USEREVENT_SETVIDMODE
,SDL_USEREVENT_SHOWMOUSE
,SDL_USEREVENT_HIDEMOUSE
,SDL_USEREVENT_COPY
,SDL_USEREVENT_PASTE
};
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},
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
{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_QUOTE, '\'', '"', 0, 0x2800},
{SDLK_COMMA, ',', '<', 0, 0x3300},
{SDLK_PERIOD, '.', '>', 0, 0x3400},
{SDLK_BACKQUOTE, '`', '~', 0, 0x2900},
{0, 0, 0, 0, 0} /** END **/
};
void sdl_setscaling(int new_value);
#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
/* 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
static void RGBtoYUV(Uint8 r, Uint8 g, Uint8 b, Uint8 *yuv_array)
//yuv_array[0] = (Uint8)((0.257 * r) + (0.504 * g) + (0.098 * b) + 16);
i = (r*263+g*516+b*100+16384);
yuv_array[0] = i >> 10;
//yuv_array[1] = (Uint8)(128 - (0.148 * r) - (0.291 * g) + (0.439 * b));
i = 131072 - 152*r - 298*g + 450*b;
yuv_array[1] = i >> 10;
//yuv_array[2] = (Uint8)(128 + (0.439 * r) - (0.368 * g) - (0.071 * b));
i = 131072 + 450*r - 377*g - 73*b;
yuv_array[2] = i >> 10;
static void yuv_fillrect(SDL_Overlay *restrict overlay, SDL_Rect *restrict r, Uint8 *restrict yuvc)
int uplane,vplane; /* Planar formats */
int y0pack, y1pack, u0pack, v0pack; /* Packed formats */
if(!overlay)
return;
if(r->x > overlay->w || r->y > overlay->h)
return;
if(r->x + r->w > overlay->w)
r->w=overlay->w-r->x;
if(r->y + r->h > overlay->h)
r->h=overlay->h-r->y;
yuv.changed=1;
switch(overlay->format) {
case SDL_IYUV_OVERLAY:
/* YUV 4:2:0 NxM Y followed by (N/2)x(M/2) U and V (12bpp) */
uplane=1;
vplane=2;
goto planar;
case SDL_YV12_OVERLAY:
/* YUV 4:2:0 NxM Y followed by (N/2)x(M/2) V and U (12bpp) */
goto planar;
case SDL_YUY2_OVERLAY:
y0pack=0;
u0pack=1;
v0pack=3;
goto packed;
case SDL_UYVY_OVERLAY:
goto packed;
case SDL_YVYU_OVERLAY:
y1pack=2;
u0pack=3;
goto packed;
}
return;
planar:
sdl.LockYUVOverlay(overlay);
Uint8 *Y,*U,*V;
int odd_line;
int uvlen=(r->w)>>1;
int uvoffset=overlay->pitches[1]*((r->y+1)>>1)+((r->x+1)>>1);
odd_line=(r->y)&1;
Y=overlay->pixels[0]+overlay->pitches[0]*(r->y)+(r->x);
U=overlay->pixels[uplane]+uvoffset;
V=overlay->pixels[vplane]+uvoffset;
for(y=0; y<r->h; y++)
{
Y+=overlay->pitches[0];
if(odd_line) {
U+=overlay->pitches[uplane];
V+=overlay->pitches[vplane];
}
else {
memset(U, yuvc[1], uvlen);
memset(V, yuvc[2], uvlen);
sdl.UnlockYUVOverlay(overlay);
return;
packed:
sdl.LockYUVOverlay(overlay);
{
int x,y;
Uint32 colour;
Uint32 *offset;
colour_array[y0pack]=yuvc[0];
colour_array[y1pack]=yuvc[0];
colour_array[u0pack]=yuvc[1];
colour_array[v0pack]=yuvc[2];
offset=(Uint32 *)(overlay->pixels[0]+overlay->pitches[0]*(r->y));
for(y=0; y<r->h; y++)
{
for(x=0; x<r->w; x+=2)
sdl.UnlockYUVOverlay(overlay);
{
va_list argptr;
ev.type=SDL_USEREVENT;
ev.user.data1=NULL;
ev.user.data2=NULL;
ev.user.code=func;
sdl.mutexP(sdl_ufunc_mtx);
/* Drain the swamp */
if(sdl_x11available && sdl_using_x11)
while(sdl.SemWaitTimeout(sdl_ufunc_rec, 0)==0);
switch(func) {
case SDL_USEREVENT_SETICON:
ev.user.data1=va_arg(argptr, void *);
if((ev.user.data2=(unsigned long *)malloc(sizeof(unsigned long)))==NULL) {
sdl.mutexV(sdl_ufunc_mtx);
va_end(argptr);
return;
}
*(unsigned long *)ev.user.data2=va_arg(argptr, unsigned long);
break;
case SDL_USEREVENT_SETNAME:
case SDL_USEREVENT_SETTITLE:
if((ev.user.data1=strdup(va_arg(argptr, char *)))==NULL) {
sdl.mutexV(sdl_ufunc_mtx);
va_end(argptr);
return;
}
break;
case SDL_USEREVENT_COPY:
case SDL_USEREVENT_PASTE:
case SDL_USEREVENT_SHOWMOUSE:
case SDL_USEREVENT_HIDEMOUSE:
case SDL_USEREVENT_FLUSH:
break;
default:
while((rv = sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff))!=1)
if(sdl_x11available && sdl_using_x11)
if ((rv = sdl.SemWaitTimeout(sdl_ufunc_rec, 2000)) != 0)
continue;
sdl.mutexV(sdl_ufunc_mtx);
/* Called from main thread only */
va_list argptr;
SDL_Event ev;
ev.type=SDL_USEREVENT;
ev.user.data1=NULL;
ev.user.data2=NULL;
ev.user.code=func;
va_start(argptr, func);
sdl.mutexP(sdl_ufunc_mtx);
/* Drain the swamp */
if(sdl_x11available && sdl_using_x11)
while(sdl.SemWaitTimeout(sdl_ufunc_rec, 0)==0);
while(1) {
switch(func) {
case SDL_USEREVENT_SETVIDMODE:
case SDL_USEREVENT_INIT:
case SDL_USEREVENT_QUIT:
while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff)!=1)
YIELD();
break;
default:
sdl.mutexV(sdl_ufunc_mtx);
/*
* This is needed for lost event detection.
* Lost events only occur on SYSWMEVENT which is what
* we need for copy/paste on X11.
* This hack can be removed for SDL2
*/
if(sdl_x11available && sdl_using_x11)
if((rv = sdl.SemWaitTimeout(sdl_ufunc_rec, 2000))!=0)
continue;
rv = sdl.SemWait(sdl_ufunc_ret);
if(rv==0)
sdl.mutexV(sdl_ufunc_mtx);
va_end(argptr);
return(sdl_ufunc_retval);
}
{
sdl_user_func_ret(SDL_USEREVENT_QUIT);
}
void sdl_copytext(const char *text, size_t buflen)
{
#if (defined(__MACH__) && defined(__APPLE__))
#if defined(USE_PASTEBOARD)
if (text && buflen)
OSX_copytext(text, buflen);
return;
#endif
#if defined(USE_SCRAP_MANAGER)
ScrapRef scrap;
if(text && buflen) {
if(!ClearCurrentScrap()) { /* purge the current contents of the scrap. */
if(!GetCurrentScrap(&scrap)) { /* obtain a reference to the current scrap. */
PutScrapFlavor(scrap, kScrapFlavorTypeText, /* kScrapFlavorMaskTranslated */ kScrapFlavorMaskNone, buflen, text); /* write the data to the scrap */
}
}
#endif
#if !defined(NO_X) && defined(__unix__)
if(sdl_x11available && sdl_using_x11) {
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);
}
FREE_AND_NULL(sdl_copybuf);
return;
}
char *sdl_getcliptext(void)
{
char *ret=NULL;
#if (defined(__MACH__) && defined(__APPLE__))
#if defined(USE_PASTEBOARD)
return OSX_getcliptext();
#endif
#if defined(USE_SCRAP_MANAGER)
ScrapRef scrap;
UInt32 fl;
Size scraplen;
if(!GetCurrentScrap(&scrap)) { /* obtain a reference to the current scrap. */
if(!GetScrapFlavorFlags(scrap, kScrapFlavorTypeText, &fl) /* && (fl & kScrapFlavorMaskTranslated) */) {
if(!GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &scraplen)) {
ret=(char *)malloc(scraplen+1);
if(ret!=NULL) {
if(GetScrapFlavorData(scrap, kScrapFlavorTypeText, &scraplen, sdl_pastebuf))
ret[scraplen]=0;
}
}
}
return ret;
#endif
#if !defined(NO_X) && defined(__unix__)
if(sdl_x11available && sdl_using_x11) {
sdl_user_func(SDL_USEREVENT_PASTE,0,0,0,0);
if(sdl_pastebuf!=NULL) {
ret=(char *)malloc(strlen(sdl_pastebuf)+1);
if(ret!=NULL)
strcpy(ret,sdl_pastebuf);
}
else
ret=NULL;
sdl.SemPost(sdl_pastebuf_copied);
return(ret);
}
void sdl_drawrect(struct rectlist *data)
data->next = NULL;
sdl.mutexP(sdl_headlock);
if (update_list == NULL)
update_list = update_list_tail = data;
else {
update_list_tail->next = data;
update_list_tail = data;
sdl_user_func(SDL_USEREVENT_FLUSH);
int oldcols;
sdl_user_func(SDL_USEREVENT_FLUSH);
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height);
if(yuv.enabled)
vstat.scaling = 2;
/* Deal with 40 col doubling */
else {
if(oldcols != vstat.cols) {
vstat.scaling /= 2;
if(vstat.cols == 40)
vstat.scaling *= 2;
if(vstat.scaling < 1)
vstat.scaling = 1;
if(vstat.vmultiplier < 1)
vstat.vmultiplier = 1;
cvstat = vstat;
pthread_mutex_unlock(&vstatlock);
sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE);
return(0);
/* Called from main thread only (Passes Event) */
#if !defined(NO_X) && defined(__unix__)
dll_handle dl;
const char *libnames[2]={"X11", NULL};
if(init_sdl_video()) {
fprintf(stderr, "SDL Video Init Failed\n");
bitmap_drv_init(sdl_drawrect, sdl_flush);
sdl.mutexP(bitmap_init_mutex);
bitmap_initialized=1;
sdl.mutexV(bitmap_init_mutex);
if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
fullscreen=1;
yuv.enabled=1;
if(mode==CIOLIB_MODE_SDL_YUV_FULLSCREEN) {
yuv.enabled=1;
fullscreen=1;
}
#if (SDL_MAJOR_VERSION > 1) || (SDL_MINOR_VERSION > 2) || (SDL_PATCHLEVEL > 9)
if(yuv.enabled) {
if(linked->major > 1 || linked->minor > 2 || linked->patch > 9) {
yuv.screen_width=sdl.initial_videoinfo.current_w;
yuv.screen_height=sdl.initial_videoinfo.current_h;
}
if(yuv.enabled && yuv.overlay==NULL) {
fprintf(stderr, "YUV Enabled, but overlay is NULL\n");
sdl_init_good=0;
sdl_user_func_ret(SDL_USEREVENT_INIT);
if(sdl_init_good) {
cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
FreeConsole();
#endif
#if !defined(NO_X) && defined(__unix__)
dl=xp_dlopen(libnames,RTLD_LAZY|RTLD_GLOBAL,7);
if(dl!=NULL) {
sdl_x11available=TRUE;
if(sdl_x11available && (sdl_x11.XFree=xp_dlsym(dl,XFree))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XGetSelectionOwner=xp_dlsym(dl,XGetSelectionOwner))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XConvertSelection=xp_dlsym(dl,XConvertSelection))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XGetWindowProperty=xp_dlsym(dl,XGetWindowProperty))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XChangeProperty=xp_dlsym(dl,XChangeProperty))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XSendEvent=xp_dlsym(dl,XSendEvent))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
if(sdl_x11available && (sdl_x11.XSetSelectionOwner=xp_dlsym(dl,XSetSelectionOwner))==NULL) {
xp_dlclose(dl);
sdl_x11available=FALSE;
}
}
#else
sdl_x11available=FALSE;
cio_api.options |= CONIO_OPT_PALETTE_SETTING | CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON;
void sdl_setscaling(int new_value)
{
if (yuv.enabled)
return;
pthread_mutex_lock(&vstatlock);
cvstat.scaling = vstat.scaling = new_value;
pthread_mutex_unlock(&vstatlock);
}
int sdl_getscaling(void)
{
if (yuv.enabled)
return 1;
/* Called from main thread only */
int sdl_kbhit(void)
{
int ret;
ret=(sdl_key!=sdl_keynext);
return(ret);
}
/* Called from main thread only */
int sdl_getch(void)
{
int ch;
/* This always frees up space in keybuf for one more char */
ch=sdl_keybuf[sdl_key++];
/* If we have missed mouse keys, tack them on to the end of the buffer now */
if(sdl_pending_mousekeys) {
if(sdl_pending_mousekeys & 1) /* Odd number... second char */
sdl_keybuf[sdl_keynext++]=CIO_KEY_MOUSE >> 8;
else /* Even number... first char */
sdl_keybuf[sdl_keynext++]=CIO_KEY_MOUSE & 0xff;
sdl.SemPost(sdl_key_pending);
sdl_pending_mousekeys--;
}
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);
int sdl_get_window_info(int *width, int *height, int *xpos, int *ypos)
{
sdl.mutexP(win_mutex);
if(xpos)
*xpos=-1;
if(ypos)
*ypos=-1;
sdl.mutexV(win_mutex);
return(1);
int char_width;
int char_height;
int flags=SDL_HWSURFACE|SDL_ANYFORMAT;
SDL_Surface *tmp_rect;
SDL_Event ev;
int charwidth, charheight, cols, scaling, rows, vmultiplier;
if(fullscreen)
flags |= SDL_FULLSCREEN;
else
flags |= SDL_RESIZABLE;
sdl.mutexP(win_mutex);
charwidth = cvstat.charwidth;
charheight = cvstat.charheight;
cols = cvstat.cols;
scaling = cvstat.scaling;
rows = cvstat.rows;
vmultiplier = cvstat.vmultiplier;
char_width=charwidth*cols*scaling;
char_height=charheight*rows*scaling*vmultiplier;
if(yuv.enabled) {
if(!yuv.win_width)
if(fullscreen && yuv.screen_width && yuv.screen_height)
win=sdl.SetVideoMode(yuv.screen_width,yuv.screen_height,0,flags);
else
win=sdl.SetVideoMode(yuv.win_width,yuv.win_height,0,flags);
}
else
win=sdl.SetVideoMode(char_width,char_height,0,flags);
#if !defined(NO_X) && defined(__unix__)
if(sdl_x11available && sdl_using_x11) {
XEvent respond;
SDL_SysWMinfo wmi;
SDL_VERSION(&(wmi.version));
sdl.GetWMInfo(&wmi);
respond.type=ConfigureNotify;
respond.xconfigure.height = win->h;
respond.xconfigure.width = win->w;
sdl_x11.XSendEvent(wmi.info.x11.display,wmi.info.x11.window,0,0,&respond);
}
sdl.mutexP(newrect_mutex);
if(new_rect)
sdl.FreeSurface(new_rect);
new_rect=NULL;
tmp_rect=sdl.CreateRGBSurface(SDL_HWSURFACE
, char_width
, char_height
if(tmp_rect) {
if(yuv.enabled) {
new_rect=tmp_rect;
}
else {
new_rect=sdl.DisplayFormat(tmp_rect);
sdl.FreeSurface(tmp_rect);
}
}
sdl.mutexV(newrect_mutex);
if(yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
if(yuv.best_format==0) {
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YV12_OVERLAY, win);
if(yuv.overlay)
yuv.best_format=yuv.overlay->format;
if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
if (yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YUY2_OVERLAY, win);
if(yuv.overlay)
yuv.best_format=yuv.overlay->format;
if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
if (yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_YVYU_OVERLAY, win);
if(yuv.overlay)
yuv.best_format=yuv.overlay->format;
if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
if (yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_UYVY_OVERLAY, win);
if(yuv.overlay)
yuv.best_format=yuv.overlay->format;
if(yuv.overlay==NULL || !yuv.overlay->hw_overlay) {
if (yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, SDL_IYUV_OVERLAY, win);
if(yuv.overlay)
yuv.best_format=yuv.overlay->format;
}
}
}
}
if(yuv.overlay)
sdl.FreeYUVOverlay(yuv.overlay);
}
yuv.overlay=sdl.CreateYUVOverlay(char_width,char_height, yuv.best_format, win);
}
sdl.mutexP(newrect_mutex);
sdl.mutexV(newrect_mutex);
bitmap_drv_request_pixels();
}
else if(sdl_init_good) {
ev.type=SDL_QUIT;
sdl_exitcode=1;
sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, 0xffffffff);
}
sdl.mutexV(win_mutex);
/* Called from event thread only */
{
if(keyval==0xa600) {
fullscreen=!fullscreen;
if(yuv.enabled)
cio_api.mode=fullscreen?CIOLIB_MODE_SDL_YUV_FULLSCREEN:CIOLIB_MODE_SDL_YUV;
else
cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
setup_surfaces();
return;
}
if(keyval <= 0xffff) {
if(sdl_keynext+1==sdl_key) {
return;
}
if((sdl_keynext+2==sdl_key) && keyval > 0xff) {
if(keyval==CIO_KEY_MOUSE)
sdl_pending_mousekeys+=2;
else
return;
}
sdl_keybuf[sdl_keynext++]=keyval & 0xff;
if(keyval>0xff) {
sdl_keybuf[sdl_keynext++]=keyval >> 8;
}
}
static unsigned int cp437_convert(unsigned int unicode)
if(unicode < 0x80)
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);