Newer
Older
#include <stdio.h> /* NULL */
#include <string.h>
#include "gen_defs.h"
#include "genwrap.h"
#include "dirwrap.h"
#include "xpbeep.h"
#include <xp_dl.h>
#if (defined CIOLIB_IMPORTS)
#undef CIOLIB_IMPORTS
#endif
#if (defined CIOLIB_EXPORTS)
#undef CIOLIB_EXPORTS
#endif
#include "ciolib.h"
#include "utf8_codepages.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 */
bool internal_scaling = true; // Protected by the win mutex
SDL_Renderer *renderer=NULL;
SDL_Texture *texture=NULL;
pthread_mutex_t win_mutex;
sem_t sdl_ufunc_ret;
sem_t sdl_ufunc_rec;
pthread_mutex_t sdl_ufunc_mtx;
sem_t sdl_flush_sem;
pthread_mutex_t sdl_keylock;
sem_t sdl_key_pending;
struct sdl_keyvals {
int keysym
,key
,shift
,ctrl
,alt;
};
static pthread_mutex_t 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_GETWINPOS
};
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},
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
{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, CIO_KEY_IC, CIO_KEY_SHIFT_IC, CIO_KEY_CTRL_IC, CIO_KEY_ALT_IC},
{SDLK_DELETE, CIO_KEY_DC, CIO_KEY_SHIFT_DC, CIO_KEY_CTRL_DC, CIO_KEY_ALT_DC},
{SDLK_KP_0, 0x5200, 0x5200, 0x9200, 0},
{SDLK_KP_1, 0x4f00, 0x4f00, 0x7500, 0},
{SDLK_KP_2, 0x5000, 0x5000, 0x9100, 0},
{SDLK_KP_3, 0x5100, 0x5100, 0x7600, 0},
{SDLK_KP_4, 0x4b00, 0x4b00, 0x7300, 0},
{SDLK_KP_5, 0x4c00, 0x4c00, 0x8f00, 0},
{SDLK_KP_6, 0x4d00, 0x4d00, 0x7400, 0},
{SDLK_KP_7, 0x4700, 0x4700, 0x7700, 0},
{SDLK_KP_8, 0x4800, 0x4800, 0x8d00, 0},
{SDLK_KP_9, 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 **/
};
static void setup_surfaces(struct video_stats *vs);
{
va_list argptr;
ev.type=SDL_USEREVENT;
ev.user.data1=NULL;
ev.user.data2=NULL;
ev.user.code=func;
pthread_mutex_lock(&sdl_ufunc_mtx);
switch(func) {
case SDL_USEREVENT_SETICON:
ev.user.data1=va_arg(argptr, void *);
if((ev.user.data2=(unsigned long *)malloc(sizeof(unsigned long)))==NULL) {
pthread_mutex_unlock(&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) {
pthread_mutex_unlock(&sdl_ufunc_mtx);
va_end(argptr);
return;
}
break;
case SDL_USEREVENT_MOUSEPOINTER:
ev.user.data1 = (void *)(intptr_t)va_arg(argptr, int);
break;
case SDL_USEREVENT_SHOWMOUSE:
case SDL_USEREVENT_HIDEMOUSE:
case SDL_USEREVENT_FLUSH:
break;
default:
while((rv = sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT))!=1)
YIELD();
break;
}
pthread_mutex_unlock(&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);
pthread_mutex_lock(&sdl_ufunc_mtx);
/* Drain the swamp */
while(1) {
switch(func) {
ev.user.data1 = (void *)(intptr_t)va_arg(argptr, int);
ev.user.data2 = (void *)(intptr_t)va_arg(argptr, int);
while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)!=1)
YIELD();
break;
case SDL_USEREVENT_GETWINPOS:
ev.user.data1 = va_arg(argptr, void *);
ev.user.data2 = va_arg(argptr, void *);
// Fallthrough
case SDL_USEREVENT_INIT:
case SDL_USEREVENT_QUIT:
while(sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)!=1)
YIELD();
break;
pthread_mutex_unlock(&sdl_ufunc_mtx);
rv = sem_wait(&sdl_ufunc_ret);
if(rv==0)
pthread_mutex_unlock(&sdl_ufunc_mtx);
va_end(argptr);
return(sdl_ufunc_retval);
}
void exit_sdl_con(void)
// Avoid calling exit(0) from an atexit() function...
ciolib_reaper = 0;
sdl_user_func_ret(SDL_USEREVENT_QUIT);
void sdl_copytext(const char *text, size_t buflen)
{
}
char *sdl_getcliptext(void)
{
uint8_t *u8;
u8 = (uint8_t *)sdl.GetClipboardText();
sdl.free(u8);
return ret;
void sdl_drawrect(struct rectlist *data)
data->next = NULL;
pthread_mutex_lock(&sdl_headlock);
if (update_list == NULL)
update_list = update_list_tail = data;
else {
update_list_tail->next = data;
update_list_tail = data;
pthread_mutex_unlock(&sdl_headlock);
sdl_user_func(SDL_USEREVENT_FLUSH);
static int sdl_init_mode(int mode, bool init)
if (mode != CIOLIB_MODE_CUSTOM) {
pthread_mutex_lock(&vstatlock);
pthread_mutex_unlock(&vstatlock);
return 0;
}
pthread_mutex_unlock(&vstatlock);
}
sdl_user_func(SDL_USEREVENT_FLUSH);
if (sdl.GetDisplayUsableBounds(0, &r) == 0) {
w = r.w;
h = r.h;
bitmap_drv_init_mode(mode, &bitmap_width, &bitmap_height, w, h);
if (init) {
internal_scaling = (ciolib_initial_scaling_type == CIOLIB_SCALING_INTERNAL);
if (ciolib_initial_scaling) {
bitmap_get_scaled_win_size(ciolib_initial_scaling, &vstat.winwidth, &vstat.winheight, 0, 0);
}
pthread_mutex_lock(&sdl_mode_mutex);
sdl_mode = true;
pthread_mutex_unlock(&sdl_mode_mutex);
pthread_mutex_unlock(&vstatlock);
sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE, vstat.winwidth, vstat.winheight);
return(0);
/* Called from main thread only (Passes Event) */
bitmap_drv_init(sdl_drawrect, sdl_flush);
if(mode==CIOLIB_MODE_SDL_FULLSCREEN)
fullscreen=1;
// Needs to be *after* bitmap_drv_init()
sem_post(&startsdl_sem);
sdl_user_func_ret(SDL_USEREVENT_INIT);
sdl_init_mode(ciolib_initial_mode, true);
if(sdl_init_good) {
cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
FreeConsole();
cio_api.options |= CONIO_OPT_PALETTE_SETTING | CONIO_OPT_SET_TITLE | CONIO_OPT_SET_NAME | CONIO_OPT_SET_ICON | CONIO_OPT_EXTERNAL_SCALING;
ciolib_reaper = 0;
sdl_user_func_ret(SDL_USEREVENT_QUIT);
static void
update_cvstat(struct video_stats *vs)
{
if (vs != NULL && vs != &vstat) {
vstat.scaling = sdl_getscaling();
*vs = vstat;
pthread_mutex_unlock(&vstatlock);
}
}
static void internal_setwinsize(struct video_stats *vs, bool force)
bool changed = true;
w = vs->winwidth;
h = vs->winheight;
if (w > 16384)
w = 16384;
if (h > 16384)
h = 16384;
if (w < vs->scrnwidth)
w = vs->scrnwidth;
if (h < vs->scrnheight)
h = vs->scrnheight;
pthread_mutex_lock(&vstatlock);
if (w == vstat.winwidth && h == vstat.winheight)
changed = force;
else {
vs->winwidth = vstat.winwidth = w;
vs->winheight = vstat.winheight = h;
}
if (changed) {
pthread_mutex_unlock(&vstatlock);
}
else {
pthread_mutex_lock(&win_mutex);
sdl.GetWindowSize(win, &w, &h);
pthread_mutex_unlock(&win_mutex);
if (w != vs->winwidth || h != vs->winheight)
changed = true;
vstat.scaling = sdl_getscaling();
if (changed)
sdl_user_func_ret(SDL_USEREVENT_SETVIDMODE, w, h);
pthread_mutex_lock(&win_mutex);
pthread_mutex_unlock(&win_mutex);
}
void sdl_getwinsize_locked(int *w, int *h)
{
if (w)
}
void sdl_getwinsize(int *w, int *h)
{
pthread_mutex_lock(&vstatlock);
sdl_getwinsize_locked(w, h);
pthread_mutex_unlock(&vstatlock);
/* Called from main thread only */
int sdl_kbhit(void)
{
int ret;
pthread_mutex_lock(&sdl_keylock);
ret=(sdl_key!=sdl_keynext);
pthread_mutex_unlock(&sdl_keylock);
return(ret);
}
/* Called from main thread only */
int sdl_getch(void)
{
int ch;
sem_wait(&sdl_key_pending);
pthread_mutex_lock(&sdl_keylock);
/* 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;
sem_post(&sdl_key_pending);
sdl_pending_mousekeys--;
}
pthread_mutex_unlock(&sdl_keylock);
return(ch);
}
/* Called from main thread only */
void sdl_textmode(int mode)
{
/* Called from main thread only (Passes Event) */
void sdl_setname(const char *name)
{
sdl_user_func(SDL_USEREVENT_SETNAME,name);
}
/* Called from main thread only (Passes Event) */
void sdl_seticon(const void *icon, unsigned long size)
{
sdl_user_func(SDL_USEREVENT_SETICON,icon,size);
}
/* Called from main thread only (Passes Event) */
void sdl_settitle(const char *title)
{
sdl_user_func(SDL_USEREVENT_SETTITLE,title);
}
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)
{
if (xpos || ypos) {
sdl_user_func_ret(SDL_USEREVENT_GETWINPOS, &wx, &wy);
if(xpos)
*xpos=wx;
if(ypos)
*ypos=wy;
}
if (width || height) {
pthread_mutex_lock(&vstatlock);
if(width)
if(height)
pthread_mutex_unlock(&vstatlock);
}
return(1);
static void
sdl_bughack_minsize(int w, int h, bool new)
{
static int lw = -1;
static int lh = -1;
if ((!new) && w == lw && h == lh)
return;
lw = w;
lh = h;
sdl.SetWindowMinimumSize(win, w, h);
}
static void setup_surfaces(struct video_stats *vs)
SDL_Texture *newtexture;
flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
flags |= SDL_WINDOW_RESIZABLE;
#if (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL >= 1)
flags |= SDL_WINDOW_ALLOW_HIGHDPI;
#endif
pthread_mutex_lock(&vstatlock);
bitmap_get_scaled_win_size(1.0, &idealmw, &idealmh, 0, 0);
pthread_mutex_unlock(&vstatlock);
pthread_mutex_lock(&win_mutex);
idealw = vs->winwidth;
idealh = vs->winheight;
sdl.SetHint(SDL_HINT_RENDER_SCALE_QUALITY, internal_scaling ? "0" : "2");
if (win == NULL) {
// SDL2: This is slow sometimes... not sure why.
if (sdl.CreateWindowAndRenderer(vs->winwidth, vs->winheight, flags, &win, &renderer) == 0) {
vs->winwidth = idealw;
vs->winheight = idealh;
sdl.RenderClear(renderer);
if (internal_scaling) {
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, idealw, idealh);
}
else {
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, vs->scrnwidth, vs->scrnheight);
sdl.DestroyTexture(texture);
texture = newtexture;
}
else {
win = NULL;
renderer = NULL;
sdl_bughack_minsize(idealmw, idealmh, false);
sdl.SetWindowSize(win, idealw, idealh);
vs->winwidth = idealw;
vs->winheight = idealh;
if (internal_scaling) {
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, idealw, idealh);
}
else {
newtexture = sdl.CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, vs->scrnwidth, vs->scrnheight);
sdl.RenderClear(renderer);
if (texture)
sdl.DestroyTexture(texture);
texture = newtexture;
if (vs != &vstat) {
pthread_mutex_lock(&vstatlock);
vstat.winwidth = vs->winwidth;
vstat.winheight = vs->winheight;
sdl_bughack_minsize(idealmw, idealmh, new_win);
bitmap_drv_request_pixels();
}
else if(sdl_init_good) {
ev.type=SDL_QUIT;
sdl_exitcode=1;
sdl.PeepEvents(&ev, 1, SDL_ADDEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT);
pthread_mutex_unlock(&win_mutex);
vstat.scaling = sdl_getscaling();
/* Called from event thread only */
static void sdl_add_key(unsigned int keyval, struct video_stats *vs)
fullscreen=!fullscreen;
cio_api.mode=fullscreen?CIOLIB_MODE_SDL_FULLSCREEN:CIOLIB_MODE_SDL;
sdl.SetWindowFullscreen(win, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
if (!fullscreen) {
int w, h;
// Get current window size
sdl.GetWindowSize(win, &w, &h);
// Limit to max window size if available
SDL_Rect r;
if (sdl.GetDisplayUsableBounds(0, &r) == 0) {
if (w > r.w)
w = r.w;
if (h > r.h)
h = r.h;
}
// Set size based on current max
vs->scaling = bitmap_double_mult_inside(w, h);
bitmap_get_scaled_win_size(vs->scaling, &vs->winwidth, &vs->winheight, w, h);
}
return;
}
if(keyval <= 0xffff) {
pthread_mutex_lock(&sdl_keylock);
if(sdl_keynext+1==sdl_key) {
pthread_mutex_unlock(&sdl_keylock);
return;
}
if((sdl_keynext+2==sdl_key) && keyval > 0xff) {
if(keyval==CIO_KEY_MOUSE)
sdl_pending_mousekeys+=2;
else
pthread_mutex_unlock(&sdl_keylock);
return;
}
sdl_keybuf[sdl_keynext++]=keyval & 0xff;
sem_post(&sdl_key_pending);
if(keyval>0xff) {
sdl_keybuf[sdl_keynext++]=keyval >> 8;
sem_post(&sdl_key_pending);
pthread_mutex_unlock(&sdl_keylock);
}
}
static void
sdl_add_key_uc(unsigned int keyval, struct video_stats *vs)
{
if (keyval < 128)
keyval = cpchar_from_unicode_cpoint(getcodepage(), keyval, keyval);
sdl_add_key(keyval, vs);
}
/* Called from event thread only */
static unsigned int sdl_get_char_code(unsigned int keysym, unsigned int mod)
/* We don't handle META */
if (mod & KMOD_GUI)
return(0x0001ffff);
/* Glah! */
if(keysym==0x7f && !(mod & KMOD_CTRL)) {
keysym=0x08;
/* Find the SDL keysym */
for(i=0;sdl_keyval[i].keysym;i++) {
if(sdl_keyval[i].keysym==keysym) {
/* KeySym found in table */
/*
* Using the modifiers, look up the expected scan code.
*/
if(mod & KMOD_ALT)
expect = sdl_keyval[i].alt;
else if(mod & KMOD_CTRL)
expect=sdl_keyval[i].ctrl;
else if(mod & KMOD_SHIFT) {
if((mod & KMOD_CAPS) && keysym != '\t')
expect=sdl_keyval[i].key;
else
expect=sdl_keyval[i].shift;
}
else {
if(mod & KMOD_CAPS && (toupper(sdl_keyval[i].key) == sdl_keyval[i].shift))
expect=sdl_keyval[i].shift;
else
expect=sdl_keyval[i].key;
}
return(expect);
* Well, we can't find it in our table, or it's a regular key.
if(keysym > 0 && keysym < 128) {
if (isalpha(keysym)) {
/*
* If CAPS and SHIFT are not in the same state,
* upper-case.
*/
if(!!(mod & KMOD_CAPS) != !!(mod & KMOD_SHIFT))
return toupper(keysym);
}
return keysym;
}
/* Give up. It's not working out for us. */
return(0x0001ffff);
static void
sdl_add_keys(uint8_t *utf8s, struct video_stats *vs)
{
char *chars;
char *p;
chars = utf8_to_cp(getcodepage(), utf8s, '\x00', strlen((char *)utf8s), NULL);
if (chars) {
for (p = chars; *p; p++) {
}
free(chars);
}
}
/* Mouse event/keyboard thread */
while(1) {
if(mouse_wait())
static int win_to_text_xpos(int winpos, struct video_stats *vs)
int ret;
ret = winpos/(((float)vs->winwidth)/vs->cols)+1;
if (ret > vs->cols)
ret = vs->cols;
static int win_to_text_ypos(int winpos, struct video_stats *vs)
int ret;
ret = winpos/(((float)vs->winheight)/vs->rows)+1;
if (ret > vs->rows)
ret = vs->rows;
static int win_to_res_xpos(int winpos, struct video_stats *vs)
{
int ret;
ret = winpos * (vs->scrnwidth) / vs->winwidth;
return ret;
}
static int win_to_res_ypos(int winpos, struct video_stats *vs)
{
int ret;
ret = winpos * (vs->scrnheight) / vs->winheight;
return ret;
}
{
SDL_Event ev;
int block_text = 0;
static SDL_Keycode last_sym = SDLK_UNKNOWN;
static Uint16 last_mod = 0;
struct video_stats cvstat = vstat;
if(sdl.WaitEventTimeout(&ev, 1)!=1)
continue;
switch (ev.type) {
case SDL_KEYDOWN: /* Keypress */
last_mod = ev.key.keysym.mod;
last_sym = ev.key.keysym.sym;
if ((ev.key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_GUI)) && !(ev.key.keysym.mod & KMOD_MODE)) {
block_text = 1;
if ((ev.key.keysym.mod & KMOD_ALT) &&
(ev.key.keysym.sym == SDLK_LEFT ||
// Don't allow ALT-DIR to change size when maximized...
if ((sdl.GetWindowFlags(win) & SDL_WINDOW_MAXIMIZED) == 0) {
int w, h;
SDL_Rect r;
if (sdl.GetDisplayUsableBounds(0, &r) == 0) {
w = r.w;
h = r.h;
pthread_mutex_lock(&vstatlock);
bitmap_snap(ev.key.keysym.sym == SDLK_RIGHT, w, h);
pthread_mutex_unlock(&vstatlock);
update_cvstat(&cvstat);
}
if (ev.key.keysym.mod & KMOD_RALT) { // Possible AltGr, let textinput sort it out...
block_text = 0;
}
if ((ev.key.keysym.mod & KMOD_SHIFT) && (ev.key.keysym.sym == '\t'))
block_text = 1;
if (block_text || ev.key.keysym.sym < 0 || ev.key.keysym.sym > 127) {
// NUMLOCK makes
if (ev.key.keysym.sym == SDLK_KP_DIVIDE
|| ev.key.keysym.sym == SDLK_KP_MULTIPLY
|| ev.key.keysym.sym == SDLK_KP_MINUS
|| ev.key.keysym.sym == SDLK_KP_PLUS)
break;
if ((ev.key.keysym.mod & KMOD_NUM) && ((ev.key.keysym.sym >= SDLK_KP_1 && ev.key.keysym.sym <= SDLK_KP_0) || (ev.key.keysym.sym == SDLK_KP_PERIOD)))
sdl_add_key_uc(sdl_get_char_code(ev.key.keysym.sym, ev.key.keysym.mod), &cvstat);
}
else if (!isprint(ev.key.keysym.sym)) {
if (ev.key.keysym.sym < 128)
sdl_add_key_uc(ev.key.keysym.sym, &cvstat);
}
break;
case SDL_TEXTINPUT:
if (!block_text) {
unsigned int charcode = sdl_get_char_code(last_sym, last_mod & ~(KMOD_ALT));
// If the key is exactly what we would expect, use sdl_get_char_code()
if (*(uint8_t *)ev.text.text == charcode)
sdl_add_key_uc(sdl_get_char_code(last_sym, last_mod), &cvstat);
sdl_add_keys((uint8_t *)ev.text.text, &cvstat);
}
break;
case SDL_KEYUP:
last_mod = ev.key.keysym.mod;
if (!(ev.key.keysym.mod & (KMOD_CTRL|KMOD_ALT|KMOD_GUI)))
block_text = 0;
break;
case SDL_MOUSEMOTION:
pthread_once(&ciolib_mouse_initialized, init_mouse);
ciomouse_gotevent(CIOLIB_MOUSE_MOVE,win_to_text_xpos(ev.motion.x, &cvstat),win_to_text_ypos(ev.motion.y, &cvstat), win_to_res_xpos(ev.motion.x, &cvstat), win_to_res_ypos(ev.motion.y, &cvstat));
pthread_once(&ciolib_mouse_initialized, init_mouse);
switch(ev.button.button) {
case SDL_BUTTON_LEFT:
ciomouse_gotevent(CIOLIB_BUTTON_PRESS(1),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
ciomouse_gotevent(CIOLIB_BUTTON_PRESS(2),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
ciomouse_gotevent(CIOLIB_BUTTON_PRESS(3),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
pthread_once(&ciolib_mouse_initialized, init_mouse);
#if (SDL_MINOR_VERSION > 0) || (SDL_PATCHLEVEL > 3)
if (ev.wheel.direction == SDL_MOUSEWHEEL_FLIPPED)
ev.wheel.y = 0 - ev.wheel.y;
if (ev.wheel.y > 0)
ciomouse_gotevent(CIOLIB_BUTTON_PRESS(4), -1, -1, -1, -1);
if (ev.wheel.y < 0)
ciomouse_gotevent(CIOLIB_BUTTON_PRESS(5), -1, -1, -1, -1);
}
break;
case SDL_MOUSEBUTTONUP:
pthread_once(&ciolib_mouse_initialized, init_mouse);
switch(ev.button.button) {
case SDL_BUTTON_LEFT:
ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(1),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(2),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
ciomouse_gotevent(CIOLIB_BUTTON_RELEASE(3),win_to_text_xpos(ev.button.x, &cvstat),win_to_text_ypos(ev.button.y, &cvstat), win_to_res_xpos(ev.button.x, &cvstat), win_to_res_ypos(ev.button.y, &cvstat));
break;
}
break;
case SDL_QUIT:
/*
* SDL2: Do we still need the reaper?
* This is what exit()s programs when the
* X is hit.
*/
if (ciolib_reaper)
sdl_user_func(SDL_USEREVENT_QUIT);
else