diff options
Diffstat (limited to 'src/maim-iso.c')
-rw-r--r-- | src/maim-iso.c | 873 |
1 files changed, 873 insertions, 0 deletions
diff --git a/src/maim-iso.c b/src/maim-iso.c new file mode 100644 index 00000000..c217ca84 --- /dev/null +++ b/src/maim-iso.c @@ -0,0 +1,873 @@ +/* + * + * 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 <string.h> +#include <math.h> /* 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, "[A", "Oa", "Ox"}, + {SDLK_DOWN, "[B", "Ob", "Or"}, + {SDLK_RIGHT, "[C", "Oc", "Ot"}, + {SDLK_LEFT, "[D", "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(bufused<bufsize-1) { buf[bufused]=a; buf[bufused+1]='\0'; bufused++; } + + buf[0] = '\0'; + + // printf("%c\n", ks->unicode); + + + 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 |