/* * * This file contains routines for maiming bitmaps as well as other * supplemental routines, all for SDL. * * Copyright 2001 Gregory Velichansky (hmaon@bumba.net) * You may use it under the terms of the standard Angband license (below) or * the GNU General Public License (GPL) Version 2 or greater. (see below) * * The Angband license states: * This software may be copied and distributed for educational, research, * and not for profit purposes provided that this copyright and statement * are included in all such copies. Other copyrights may also apply. * * The GNU GPL notice: main-sdl.c - SDL (http://libsdl.org) Term implementation for Angband. Copyright (C) 2001 Gregory Velichansky (hmaon@bumba.net) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, please see http://www.gnu.org/copyleft/gpl.html Please see the file COPYING for more detail regarding Angband's current license situation. */ #include "angband.h" #if defined(USE_ISO) || defined(USE_LUA_GUI) #include "SDL/SDL.h" #include #include /* for scaling blits */ //#include "bits/nan.h" /* * * Supplemental SDL bitmap manipulation functions. * * These could be moved to a separate file. In mai?-x11.c, similar routines * are separate from the main display module implementation. * */ /* The most pedantic-a%& getpixel and putpixel ever, hopefully. */ /* There may still be endianness bugs! These will be fixed after adequte testing. XXX XXX XXX */ inline errr SDL_GetPixel (SDL_Surface *f, Uint32 x, Uint32 y, Uint8 *r, Uint8 *g, Uint8 *b) { /*const Uint32 mask[] = {0x0, 0xff, 0xffff, 0xffffff, 0xffffffff};*/ Uint32 pixel; Uint8 *pp; int n; /* general purpose 'n'. */ if (f == NULL) return -1; pp = (Uint8 *) f->pixels; if (x >= f->w || y >= f->h) return -1; pp += (f->pitch * y); pp += (x * f->format->BytesPerPixel); /* we do not lock the surface here, it would be inefficient XXX */ /* this reads the pixel as though it was a big-endian integer XXX */ /* I'm trying to avoid reading part the end of the pixel data by * using a data-type that's larger than the pixels */ for (n = 0, pixel = 0; n < f->format->BytesPerPixel; ++n, ++pp) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN pixel >>= 8; pixel |= *pp << (f->format->BitsPerPixel - 8); #else pixel |= *pp; pixel <<= 8; #endif } SDL_GetRGB(pixel, f->format, r, g, b); return 0; } /* This function looks remarkably similar to the one above. Yes, it's cut * and paste. */ inline errr SDL_PutPixel (SDL_Surface *f, Uint32 x, Uint32 y, Uint8 r, Uint8 g, Uint8 b) { Uint32 pixel; Uint8 *pp; int n; if (f == NULL) return -1; pp = (Uint8 *) f->pixels; if (x >= f->w || y >= f->h) return -1; pp += (f->pitch * y); pp += (x * f->format->BytesPerPixel); pixel = SDL_MapRGB(f->format, r, g, b); for (n = 0; n < f->format->BytesPerPixel; ++n, ++pp) { *pp = (Uint8) (pixel & 0xFF); pixel >>= 8; } return 0; } /* This routine performs a scaling blit. It will shrink and magnify. :) */ /* It uses floating point arithmetic (because I am lazy) so it's not too fast * but I only intend for it to be used in pre-processing, that is image * processing at load time. It's fast enough for that, at least. * Actually on my machine it IS fast enough to scale fonts and bitmaps * in real-time. :) * This routine uses a weighted average, the weight being based on overlapping * pixel area. */ inline errr SDL_ScaleBlit(SDL_Surface *src, SDL_Rect *sr, SDL_Surface *dst, SDL_Rect *dr) { Uint8 r, g, b; float rs, gs, bs; /* sums */ float area; float sx, sy; /* current source x and y */ float dsx, dsy; /* source increment, per increment of 1 in destination */ float wsx, wsy; /* width of source box. Equal to dsx,dsy except when either of then are * smaller than 1. This is a hack for smoother magnification. XXX */ float x, y; /* x and y in sub-area */ Uint32 tx, ty; /* "to" x and y */ Uint32 lx, ly; float w, e, n, s; /* some temporary variables, named after orientations */ if (src == NULL || sr == NULL || dst == NULL || dr == NULL) return -1; /* these are meaningless and would cause a divide by zero: */ if (!dr->w || !dr->h) return -1; wsx = dsx = ((float) sr->w) / dr->w; if (wsx < 1) wsx = 1; wsy = dsy = ((float) sr->h) / dr->h; if (wsy < 1) wsy = 1; lx = dr->x + dr->w; ly = dr->y + dr->h; area = wsx * wsy; for (ty = dr->y, sy = (float)sr->y; ty < ly; ++ty, sy += dsy) { for (tx = dr->x, sx = (float)sr->x; tx < lx; ++tx, sx += dsx) { rs = gs = bs = 0.0; for (y = floor(sy) - 1; ceil(sy + wsy) > y; ++y) { for (x = floor(sx) - 1; ceil(sx + wsx) > x; ++x) { w = (x > sx) ? 0 : sx - x; n = (y > sy) ? 0 : sy - y; e = (sx + wsx >= x + 1) ? 1 : sx + wsx - x; s = (sy + wsy >= y + 1) ? 1 : sy + wsy - y; if (w > e || s < n ) continue; #define gsx ((Uint32)x >= sr->x+sr->w ? sr->x+sr->w-1 : (Uint32)x) #define gsy ((Uint32)y >= sr->y+sr->h ? sr->y+sr->h-1 : (Uint32)y) SDL_GetPixel (src, gsx, gsy, &r, &g, &b); rs += (e - w) * (s - n) * (float)r; gs += (e - w) * (s - n) * (float)g; bs += (e - w) * (s - n) * (float)b; } } rs /= area; gs /= area; bs /= area; if (rs >= 256.0 || gs >= 256.0 || bs > 256.0) { plog("weighted average error!"); plog(format("Values: %f, %f, %f\n", rs, gs, bs)); /**((char *)0) = 0;*/ } if (rs > 255.0) rs = 255.0; if (gs > 255.0) gs = 255.0; if (bs > 255.0) bs = 255.0; r = (Uint8)rs; g = (Uint8)gs; b = (Uint8)bs; SDL_PutPixel (dst, tx, ty, r, g, b); } } return 0; #undef gsx #undef gsy } /* Integer math version of SDL_ScaleBlit(). * Where necessary, a number uses the 16 high bits for the integer * and the 16 low bits for the decimal portion. * * eg: * float a = (float) (b >> 16) + (b & 0xFFFF)/65536.0; */ inline Uint32 ifloor(Uint32 i) { return i & 0xFFFF0000; } inline Uint32 iceil(Uint32 i) { return (i & 0xFFFF) ? i : ifloor(i) + (1 << 16); } errr SDL_FastScaleBlit(SDL_Surface *src, SDL_Rect *sr, SDL_Surface *dst, SDL_Rect *dr) { Uint8 r, g, b; Uint32 rs, gs, bs; /* sums. */ /* temp storage for large int multiplies. Uint64 doen't exist anywhere */ double farea; Uint32 area; Uint32 sx, sy; Uint32 dsx, dsy; Uint32 wsx, wsy; Uint32 x, y; /* x and y, for sub-area */ Uint32 tx, ty; /* normal integers */ Uint32 lx, ly; /* normal integers */ Uint32 w, e, n, s; /* temp variables, named after compass directions */ if (src == NULL || sr == NULL || dst == NULL || dr == NULL) return -1; if (!dr->w || !dr->h) return -1; /* TODO FIXME check for possible overflows! */ wsx = dsx = (sr->w << 16) / dr->w; if (!(wsx & 0xFFFF0000)) wsx = 1 << 16; wsy = dsy = (sr->h << 16) / dr->h; if (!(wsy & 0xFFFF0000)) wsy = 1 << 16; lx = dr->x + dr->w; ly = dr->y + dr->h; /* lazy multiplication. Hey, it's only once per blit. :P */ farea = ((double)wsx) * ((double)wsy); farea /= (double)(1 << 16); area = (Uint32) farea; /* For optimization, those setup routines should be moved into * SDL_ScaleTiledBitmap() for that function. */ for (ty = dr->y, sy = sr->y << 16; ty < ly; ++ty, sy += dsy) { for (tx = dr->x, sx = sr->x << 16; tx < lx; ++tx, sx += dsx) { rs = gs = bs = 0; for (y = ifloor(sy); iceil(sy + wsy) > y; y += (1 << 16)) { for (x = ifloor(sx); iceil(sx + wsx) > x; x += (1 << 16)) { w = (x > sx) ? 0 : sx - x; n = (y > sy) ? 0 : sy - y; e = (sx + wsx >= x + (1 << 16)) ? 1 << 16 : sx + wsx - x; s = (sy + wsy >= y + (1 << 16)) ? 1 << 16 : sy + wsy - y; if (w > e || s < n) continue; #define gsx ((x >> 16) >= sr->x+sr->w ? sr->x+sr->w-1 : x >> 16) #define gsy ((y >> 16) >= sr->y+sr->h ? sr->y+sr->h-1 : y >> 16) SDL_GetPixel (src, gsx, gsy, &r, &g, &b); rs += ((e - w) >> 8) * ((s - n) >> 8) * r; gs += ((e - w) >> 8) * ((s - n) >> 8) * g; bs += ((e - w) >> 8) * ((s - n) >> 8) * b; } } rs /= area; gs /= area; bs /= area; if (rs >= 256 || gs >= 256 || bs >= 256) { plog("fixed point weighted average overflow!"); plog(format("Values: %d, %d, %d\n", rs, gs, bs)); } r = (Uint8) rs; g = (Uint8) gs; b = (Uint8) bs; SDL_PutPixel (dst, tx, ty, r, g, b); } } return 0; #undef gsx #undef gsy } #if 0 /* the procedure above is a more generalized version of the one below */ /* The following is a function to perform a Blit while magnifying */ /* Anti-aliasing is performed. :) */ /* It is probably very SLOW on most systems. Use it for pre-processing. XXX */ /* a Blit while shrinking is handled by a different function */ errr SDL_StretchBlit(SDL_Surface *src, SDL_Rect *sr, SDL_Surface *dst, SDL_Rect *dr) { double sx, sy; /* current source x and y */ Uint32 isx, isy; /* temp. values for convenience in calculation code */ double dsx, dsy; /* source increment, per increment of 1 in destination */ double wx, wy; /* temp. weight values for the color mixing calculations */ double weight; /* temp. weight of pixel */ /* coordinates to get pixels from: ... */ #undef gsx #define gsx (isx >= sr->x+sr->w ? sr->x+sr->w-1 : isx) #undef gsy #define gsy (isy >= sr->y+sr->h ? sr->y+sr->h-1 : isy) Uint32 tx, ty; /* "to" x and y. "dx, dy" would be too confusing. */ Uint32 lx, ly; /* end x and y in destination, not inclusive */ double r, g, b; /* temporary values on which we perform calculations */ /*double s;*/ /* scale factor calculation thing. gross hack. don't ask. */ Uint8 ir, ig, ib; /* same here. */ if (src == NULL || sr == NULL || dst == NULL || dr == NULL) return -1; /* these are meaningless and would cause a divide by zero: */ if (!dr->w || !dr->h) return -1; dsx = ((double) sr->w) / dr->w; dsy = ((double) sr->h) / dr->h; lx = dr->x + dr->w; ly = dr->y + dr->h; for (ty = dr->y, sy = (double)sr->y; ty < ly; ++ty, sy += dsy) { for (tx = dr->x, sx = (double)sr->x; tx < lx; ++tx, sx += dsx) { /* here we must consider four pixels and mix them together */ /* the further away we are from a pixel, the less weight it has * when we mix in its color. Hence the "1 - hypot(..." etc. * Actually, no. Let's not use hypot(). */ /* * upper left pixel */ wx = ((floor(sx) + 1) - sx); wy = ((floor(sy) + 1) - sy); isx = (Uint32) floor(sx); isy = (Uint32) floor(sy); if (SDL_GetPixel(src, gsx, gsy, &ir, &ig, &ib)) return -1; weight = wx * wy; /* the area of the overlap of our hypothetical and real pixel!!! */ if (weight < 1 / 1024.0) weight = 0; r = weight * (double)ir; g = weight * (double)ig; b = weight * (double)ib; /*s = weight * 255.0;*/ /* * upper right pixel */ wx = 1 - wx; isx += 1; if (SDL_GetPixel(src, gsx, gsy, &ir, &ig, &ib)) return -1; weight = wx * wy; if (weight < 1 / 1024.0) weight = 0; r += weight * (double)ir; g += weight * (double)ig; b += weight * (double)ib; /*s += weight * 255.0;*/ /* * lower right pixel */ wy = 1 - wy; isy += 1; if (SDL_GetPixel(src, gsx, gsy, &ir, &ig, &ib)) return -1; weight = wx * wy; if (weight < 1 / 1024.0) weight = 0; r += weight * (double)ir; g += weight * (double)ig; b += weight * (double)ib; /*s += weight * 255.0;*/ /* * lower left pixel */ wx = 1 - wx; isx -= 1; if (SDL_GetPixel(src, gsx, gsy, &ir, &ig, &ib)) return -1; weight = wx * wy; if (weight < 1 / 1024.0) weight = 0; r += weight * (double)ir; g += weight * (double)ig; b += weight * (double)ib; /*s += weight * 255.0;*/ /* r = 255 * (r/s); g = 255 * (g/s); b = 255 * (b/s); */ if (r >= 256.0 || g >= 256.0 || b > 256.0) { plog("mixing error!"); plog(format("Values: %f, %f, %f\n", (double)r, (double)g, (double)b)); /**((char *)0) = 0;*/ } if (r > 255.0) r = 255.0; if (g > 255.0) g = 255.0; if (b > 255.0) b = 255.0; ir = (Uint8) r; ig = (Uint8) g; ib = (Uint8) b; SDL_PutPixel(dst, tx, ty, ir, ig, ib); } } return 0; } #endif /* This function will take an SDL_Surface, allocate a new surface to hold * the resized surface, perform the scaling operation, free the old surface * and return the new one. This behaviour is vaguely modeled after C library * string functions. Returns NULL on grievous errors! * * The scaling operation is performed one or more times to accomodate * images comprised by a number of sub-images whose edges must not be blurred * with the edges of adjacent sub-images. (Think fonts and tile sets.) * * If t_oldw and t_oldh are set to src->w and src->h respectively * * t_oldw, t_oldh are the size of the old tiles */ SDL_Surface *SDL_ScaleTiledBitmap (SDL_Surface *src, Uint32 t_oldw, Uint32 t_oldh, Uint32 t_neww, Uint32 t_newh, int dealloc_src) { SDL_Surface *dst; SDL_Rect sr, dr; Uint32 x, y; Uint32 nx, ny; if (!t_oldw || !t_oldh || !t_neww || !t_newh || !src) return NULL; /*dummy!*/ if (t_oldw == t_neww && t_oldh == t_newh) return src; /* OK... */ /* Get the number of tiles in the image. * Any possible clipped tiles at the edges are ignored. */ nx = src->w / t_oldw; ny = src->h / t_oldh; /* Allocate a new SDL_Surface of appropriate size, with settings otherwise * identical to src. */ dst = SDL_CreateRGBSurface(src->flags, nx * t_neww, ny * t_newh, /*src->format->BitsPerPixel,*/ 16, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); for (y = 0; y < ny; ++y) { for (x = 0; x < nx; ++x) { sr.w = t_oldw; sr.h = t_oldh; sr.x = x * t_oldw; sr.y = y * t_oldh; dr.w = t_neww; dr.h = t_newh; dr.x = x * t_neww; dr.y = y * t_newh; /*printf("%d,%d -> %d,%d (%d,%d -> %d, %d)\n", sr.x, sr.y, dr.x, dr.y, sr.w, sr.h, dr.w, dr.h);*/ /* scale-blit one tile and check for error * although SDl_ScaleBlit() might not have any errors to return. */ if (SDL_FastScaleBlit(src, &sr, dst, &dr)) return NULL; } } if (dealloc_src) SDL_FreeSurface(src); return dst; } /* The following function will extract height and width info from a filename * such as 16x16.xyz or 8X13.bar or even argle8ook16.foo * * I realize now that it's also useful for reading integers out of an argument * such as --fooscale1=2 */ errr strtoii(const char *str, Uint32 *w, Uint32 *h) { char buf[1024]; char *s = buf; char *tok; char *numeric = "0123456789"; size_t l; /* length of numeric string */ if (!str || !w || !h) return -1; if (strlen(str) < 3) return -1; /* must have room for at least "1x1" */ strncpy(buf, str, 1023); buf[1023] = '\0'; tok = strpbrk(buf, numeric); if (!tok) return -1; l = strspn(tok, numeric); if (!l) return -1; tok[l] = '\0'; s = tok + l + 1; if (!sscanf(tok, "%d", w)) return -1; /* next token */ tok = strpbrk(s, numeric); if (!tok) return -1; l = strspn(tok, numeric); if (!l) return -1; tok[l] = '\0'; /* no need to set s since this is the last token */ if (!sscanf(tok, "%d", h)) return -1; return 0; } char *formatsdlflags(Uint32 flags) { return format ("%s%s%s%s%s%s%s%s%s%s (%x)", (flags & SDL_HWSURFACE) ? "SDL_HWSURFACE " : "", (flags & SDL_ANYFORMAT) ? "SDL_ANYFORMAT " : "", (flags & SDL_HWPALETTE) ? "SDL_HWPALETTE " : "", (flags & SDL_DOUBLEBUF) ? "SDL_DOUBLEBUF " : "", (flags & SDL_FULLSCREEN) ? "SDL_FULLSCREEN " : "", (flags & SDL_RESIZABLE) ? "SDL_RESIZABLE " : "", (flags & SDL_HWACCEL) ? "SDL_HWACCEL " : "", (flags & SDL_SRCCOLORKEY) ? "SDL_SRCCOLRKEY " : "", (flags & SDL_RLEACCEL) ? "SDL_RLEACCEL " : "", (flags & SDL_SRCALPHA) ? "SDL_SRCALPHA " : "", flags); }; /* A lot of code for handling keystrokes follow. */ typedef struct sdl_keymapt sdl_keymapt; struct sdl_keymapt { SDLKey k; /* what we get from SDL */ char *s; /* what we feed to the Term_keypress */ char *ctrl; /* what if CTRL is pressed? (NULL if the same) */ char *shift; /* what if SHIFT is pressed? */ }; /* XXX XXX XXX the following keymap sucks. More comments below. */ sdl_keymapt sdl_keymap[] = { /*{SDLK_UP, "", "Oa", "Ox"}, {SDLK_DOWN, "", "Ob", "Or"}, {SDLK_RIGHT, "", "Oc", "Ot"}, {SDLK_LEFT, "", "Od", "Ov"}, {SDLK_INSERT, "[2~", "[2^", "Op"}, {SDLK_HOME, "[1~", "[1^", "Ow"}, {SDLK_END, "[4~", "[4^", "Oq"}, {SDLK_PAGEUP, "[5~", "[5^", "Oy"}, {SDLK_PAGEDOWN, "[6~", "[6^", "Os"},*/ {SDLK_F1, "[[A", NULL, NULL}, {SDLK_F2, "[[B", NULL, NULL}, {SDLK_F3, "[[C", NULL, NULL}, {SDLK_F4, "[[D", NULL, NULL}, {SDLK_F5, "[[E", NULL, NULL}, {SDLK_F6, "[[17~", NULL, NULL}, {SDLK_F7, "[[18~", NULL, NULL}, {SDLK_F8, "[[19~", NULL, NULL}, {SDLK_F9, "[[20~", NULL, NULL}, {SDLK_F10, "[[21~", NULL, NULL}, {SDLK_F11, "[[23~", NULL, NULL}, {SDLK_F12, "[[24~", NULL, NULL}, /* I have no machines with F13, F14, F15. Is that a Sun thing? */ {SDLK_F13, "", NULL, NULL}, {SDLK_F14, "", NULL, NULL}, {SDLK_F15, "", NULL, NULL}, {SDLK_RSHIFT, "", NULL, NULL}, {SDLK_LSHIFT, "", NULL, NULL}, {SDLK_RALT, "", NULL, NULL}, {SDLK_LALT, "", NULL, NULL}, {SDLK_RCTRL, "", NULL, NULL}, {SDLK_LCTRL, "", NULL, NULL}, {SDLK_RMETA, "", NULL, NULL}, {SDLK_LMETA, "", NULL, NULL}, {SDLK_NUMLOCK, "", NULL, NULL}, {SDLK_CAPSLOCK, "", NULL, NULL}, {SDLK_SCROLLOCK, "", NULL, NULL}, {SDLK_LSUPER, "", NULL, NULL}, {SDLK_RSUPER, "", NULL, NULL}, {SDLK_HELP, "?", NULL, NULL}, {SDLK_PRINT, "", NULL, NULL}, {SDLK_SYSREQ, "", NULL, NULL}, {SDLK_BREAK, "", NULL, NULL}, {SDLK_MENU, "", NULL, NULL}, {SDLK_POWER, "", NULL, NULL}, {SDLK_EURO, "", NULL, NULL}, {SDLK_0, "0", NULL, ")"}, /* XXX XXX XXX The CTRL-number keys need to be */ {SDLK_1, "1", NULL, "!"}, /* defined since they represent digging for */ {SDLK_2, "2", NULL, "@"}, /* some people!. Really, this whole table */ {SDLK_3, "3", NULL, "#"}, /* should be replaced with something cleaner */ {SDLK_4, "4", NULL, "$"}, /* and an SDL pref file should be created. */ {SDLK_5, "5", NULL, "%"}, {SDLK_6, "6", NULL, "^"}, {SDLK_7, "7", NULL, "&"}, {SDLK_8, "8", NULL, "*"}, {SDLK_9, "9", NULL, "("}, {SDLK_SEMICOLON, ";", NULL, ":"}, {SDLK_COMMA, ",", NULL, "<"}, {SDLK_PERIOD, ".", NULL, ">"}, {SDLK_BACKSLASH, "\\", NULL, "|"}, {SDLK_BACKQUOTE, "`", NULL, "~"}, {SDLK_LEFTBRACKET, "[", NULL, "{"}, {SDLK_RIGHTBRACKET, "]", NULL, "}"}, {SDLK_MINUS, "-", NULL, "_"}, {SDLK_EQUALS, "=", NULL, "+"}, {SDLK_SLASH, "/", NULL, "?"}, {SDLK_UNKNOWN, NULL, NULL, NULL} /* terminator */ }; void Multikeypress(char *k) { printf("zog : '%s'\n", k); while (*k) Term_keypress(*k++); } int IsMovement(SDLKey k) { switch (k) { case SDLK_UP: case SDLK_DOWN: case SDLK_RIGHT: case SDLK_LEFT: case SDLK_INSERT: case SDLK_HOME: case SDLK_END: case SDLK_PAGEUP: case SDLK_PAGEDOWN: case SDLK_KP0: case SDLK_KP1: case SDLK_KP2: case SDLK_KP3: case SDLK_KP4: case SDLK_KP5: case SDLK_KP6: case SDLK_KP7: case SDLK_KP8: case SDLK_KP9: return TRUE; default: return FALSE; } return 1234567; /* all good children go to heaven */ } char *SDL_keysymtostr(SDL_keysym *ks) { #ifdef bufsize #error bufsize steps on previous define! #endif #define bufsize 1024 int bufused = 0; /* I am returning a pointer to the below variable. * I /think/ this is legal but I am not sure! XXX XXX XXX * It certainly seems to work fine, at least under GCC. * It can easily be changed to a pointer passed as an argument. */ static char buf[bufsize]; Uint8 ch; /* cat for strings and app[end] for characters */ #define sdlkcat(a) strncat(buf,(a),bufsize-bufused-1); bufused+=strlen((a)); #define sdlkapp(a) if(bufusedunicode); if (IsMovement(ks->sym)) { sprintf(buf, "%c%s%s%s%s_%lX%c", 31, ks->mod & KMOD_CTRL ? "N" : "", ks->mod & KMOD_SHIFT ? "S" : "", "", /* for future expansion. */ ks->mod & KMOD_ALT ? "M" : "", (unsigned long) ks->sym, 13); ch = 0; } else { if (ks->mod & KMOD_ALT) { sdlkapp(''); } ch = ks->unicode; } if (ch) sdlkapp(ch); return buf; #undef bufsize #undef sdlkcat #undef sdlkapp } /* SDL_keystring */ /* Cursor hack, for testing of ideas. XXX XXX XXX */ SDL_Surface *sdl_screen_cursor = NULL; SDL_Rect sdl_screen_cursor_sr; /* it must be true that w * h * 4 <= maxUint32 */ errr SDL_init_screen_cursor(Uint32 w, Uint32 h) { Uint32 i; sdl_screen_cursor_sr.x = sdl_screen_cursor_sr.y = 0; sdl_screen_cursor_sr.w = w; sdl_screen_cursor_sr.h = h; sdl_screen_cursor = NULL; sdl_screen_cursor = SDL_CreateRGBSurface(SDL_SRCALPHA, w, h, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000); if (!sdl_screen_cursor) return -1; SDL_SetAlpha(sdl_screen_cursor, SDL_SRCALPHA | SDL_RLEACCEL, 0x80); for (i = 0; i < w*h*4; ++i) { ((Uint8 *)(sdl_screen_cursor->pixels))[i] = !(i & 2) ? 0x80 : 0xFF; } return 0; } errr SDL_DrawCursor(SDL_Surface *dst, SDL_Rect *dr) { if (!dst || !dr || !sdl_screen_cursor) return -1; if (SDL_BlitSurface(sdl_screen_cursor, &sdl_screen_cursor_sr, dst, dr)) return -1; SDL_UpdateRect(dst, dr->x, dr->y, dr->w, dr->h); return 0; } #endif