1 /*
2 *
3 * This file contains routines for maiming bitmaps as well as other
4 * supplemental routines, all for SDL.
5 *
6 * Copyright 2001 Gregory Velichansky (hmaon@bumba.net)
7 * You may use it under the terms of the standard Angband license (below).
8 *
9 * The Angband license states:
10 * This software may be copied and distributed for educational, research,
11 * and not for profit purposes provided that this copyright and statement
12 * are included in all such copies. Other copyrights may also apply.
13 *
14 */
15
16
17 #include "c-angband.h"
18
19 #ifdef USE_SDL
20
21
22 #include <SDL/SDL.h>
23 #include <string.h>
24 #include <math.h> /* for scaling blits */
25
26
27
28
29
30 /*
31 *
32 * Supplemental SDL bitmap manipulation functions.
33 *
34 * These could be moved to a separate file. In mai?-x11.c, similar routines
35 * are separate from the main display module implementation.
36 *
37 */
38
39
40 /* The most pedantic-a%& getpixel and putpixel ever, hopefully. */
41 /* There may still be endianness bugs! These will be fixed after adequte testing. XXX XXX XXX */
SDL_GetPixel(SDL_Surface * f,Uint32 x,Uint32 y,Uint8 * r,Uint8 * g,Uint8 * b)42 static errr SDL_GetPixel (SDL_Surface *f, Uint32 x, Uint32 y, Uint8 *r, Uint8 *g, Uint8 *b)
43 {
44 /*const Uint32 mask[] = {0x0, 0xff, 0xffff, 0xffffff, 0xffffffff};*/
45 Uint32 pixel;
46
47 Uint8 *pp;
48
49 int n; /* general purpose 'n'. */
50
51 if (f == NULL) return -1;
52
53 pp = (Uint8 *) f->pixels;
54
55 if (x >= f->w || y >= f->h) return -1;
56
57 pp += (f->pitch * y);
58
59 pp += (x * f->format->BytesPerPixel);
60
61 /* we do not lock the surface here, it would be inefficient XXX */
62 /* this reads the pixel as though it was a big-endian integer XXX */
63 /* I'm trying to avoid reading part the end of the pixel data by
64 * using a data-type that's larger than the pixels */
65 for (n = 0, pixel = 0; n < f->format->BytesPerPixel; ++n, ++pp)
66 {
67 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
68 pixel >>= 8;
69 pixel |= *pp << (f->format->BitsPerPixel - 8);
70 #else
71 pixel |= *pp;
72 pixel <<= 8;
73 #endif
74 }
75
76 SDL_GetRGB(pixel, f->format, r, g, b);
77 return 0;
78 }
79
80 /* This function looks remarkably similar to the one above. Yes, it's cut
81 * and paste. */
SDL_PutPixel(SDL_Surface * f,Uint32 x,Uint32 y,Uint8 r,Uint8 g,Uint8 b)82 static errr SDL_PutPixel (SDL_Surface *f, Uint32 x, Uint32 y, Uint8 r, Uint8 g, Uint8 b)
83 {
84 Uint32 pixel;
85
86 Uint8 *pp;
87
88 int n;
89
90 if (f == NULL) return -1;
91
92 pp = (Uint8 *) f->pixels;
93
94 if (x >= f->w || y >= f->h) return -1;
95
96 pp += (f->pitch * y);
97
98 pp += (x * f->format->BytesPerPixel);
99
100 pixel = SDL_MapRGB(f->format, r, g, b);
101
102 for (n = 0; n < f->format->BytesPerPixel; ++n, ++pp)
103 {
104 *pp = (Uint8) (pixel & 0xFF);
105 pixel >>= 8;
106 }
107
108 return 0;
109 }
110
ifloor(Uint32 i)111 static Uint32 ifloor(Uint32 i)
112 {
113 return i & 0xFFFF0000;
114 }
115
iceil(Uint32 i)116 static Uint32 iceil(Uint32 i)
117 {
118 return (i & 0xFFFF) ? i : ifloor(i) + (1<<16);
119 }
120
121 /* This routine performs a scaling blit. It will shrink and magnify. :) */
122 /* Integer math version of SDL_ScaleBlit().
123 * Where necessary, a number uses the 16 high bits for the integer
124 * and the 16 low bits for the decimal portion.
125 *
126 * eg:
127 * float a = (float) (b >> 16) + (b & 0xFFFF)/65536.0;
128 */
SDL_ScaleBlit(SDL_Surface * src,SDL_Rect * sr,SDL_Surface * dst,SDL_Rect * dr)129 errr SDL_ScaleBlit(SDL_Surface *src, SDL_Rect *sr, SDL_Surface *dst, SDL_Rect *dr)
130 {
131 Uint8 r, g, b;
132 Uint32 rs, gs, bs; /* sums. */
133
134 /* temp storage for large int multiplies. Uint64 doen't exist anywhere */
135 double farea;
136 Uint32 area;
137
138 Uint32 sx, sy;
139 Uint32 dsx, dsy;
140
141 Uint32 wsx, wsy;
142
143 Uint32 x, y; /* x and y, for sub-area */
144
145 Uint32 tx, ty; /* normal integers */
146 Uint32 lx, ly; /* normal integers */
147
148 Uint32 w, e, n, s; /* temp variables, named after compass directions */
149
150 if (src == NULL || sr == NULL || dst == NULL || dr == NULL) return -1;
151
152 if (!dr->w || !dr->h) return -1;
153
154
155 /* TODO FIXME check for possible overflows! */
156
157 wsx = dsx = (sr->w << 16) / dr->w;
158 if (!(wsx & 0xFFFF0000)) wsx = 1 << 16;
159 wsy = dsy = (sr->h << 16) / dr->h;
160 if (!(wsy & 0xFFFF0000)) wsy = 1 << 16;
161
162 lx = dr->x + dr->w;
163 ly = dr->y + dr->h;
164
165 /* lazy multiplication. Hey, it's only once per blit. :P */
166 farea = ((double)wsx) * ((double)wsy);
167 farea /= (double)(1 << 16);
168 area = (Uint32) farea;
169
170 /* For optimization, those setup routines should be moved into
171 * SDL_ScaleTiledBitmap() for that function.
172 */
173
174 for (ty = dr->y, sy = sr->y << 16; ty < ly; ++ty, sy+=dsy)
175 {
176 for (tx = dr->x, sx = sr->x << 16; tx < lx; ++tx, sx+=dsx)
177 {
178 rs = gs = bs = 0;
179 for (y = ifloor(sy); iceil(sy + wsy) > y; y += (1<<16))
180 {
181 for (x = ifloor(sx); iceil(sx + wsx) > x; x += (1<<16))
182 {
183 w = (x > sx) ? 0 : sx - x;
184 n = (y > sy) ? 0 : sy - y;
185
186 e = (sx+wsx >= x+(1<<16)) ? 1<<16 : sx+wsx - x;
187 s = (sy+wsy >= y+(1<<16)) ? 1<<16 : sy+wsy - y;
188
189 if (w > e || s < n) continue;
190
191 #define gsx ((x >> 16) >= sr->x+sr->w ? sr->x+sr->w-1 : x >> 16)
192 #define gsy ((y >> 16) >= sr->y+sr->h ? sr->y+sr->h-1 : y >> 16)
193
194 SDL_GetPixel (src, gsx, gsy, &r, &g, &b);
195
196 rs += ((e - w)>>8) * ((s - n)>>8) * r;
197 gs += ((e - w)>>8) * ((s - n)>>8) * g;
198 bs += ((e - w)>>8) * ((s - n)>>8) * b;
199 }
200 }
201 rs /= area;
202 gs /= area;
203 bs /= area;
204
205 if (rs >= 256 || gs >= 256 || bs >= 256)
206 {
207 plog("fixed point weighted average overflow!");
208 plog(format("Values: %d, %d, %d\n", rs, gs, bs));
209 }
210
211 r = (Uint8) rs;
212 g = (Uint8) gs;
213 b = (Uint8) bs;
214
215 SDL_PutPixel (dst, tx, ty, r, g, b);
216 }
217 }
218
219 return 0;
220 #undef gsx
221 #undef gsy
222 }
223
224 /* This function will take an SDL_Surface, allocate a new surface to hold
225 * the resized surface, perform the scaling operation, free the old surface
226 * and return the new one. This behaviour is vaguely modeled after C library
227 * string functions. Returns NULL on grievous errors!
228 *
229 * The scaling operation is performed one or more times to accomodate
230 * images comprised by a number of sub-images whose edges must not be blurred
231 * with the edges of adjacent sub-images. (Think fonts and tile sets.)
232 *
233 * If t_oldw and t_oldh are set to src->w and src->h respectively
234 *
235 * t_oldw, t_oldh are the size of the old tiles
236 */
SDL_ScaleTiledBitmap(SDL_Surface * src,Uint32 t_oldw,Uint32 t_oldh,Uint32 t_neww,Uint32 t_newh,int dealloc_src)237 SDL_Surface *SDL_ScaleTiledBitmap (SDL_Surface *src,
238 Uint32 t_oldw,
239 Uint32 t_oldh,
240 Uint32 t_neww,
241 Uint32 t_newh,
242 int dealloc_src)
243 {
244 SDL_Surface *dst;
245 SDL_Rect sr, dr;
246 Uint32 x, y;
247 Uint32 nx, ny;
248 int i;
249
250 if (!t_oldw || !t_oldh || !t_neww || !t_newh || !src) return NULL; /*dummy!*/
251
252 //if (t_oldw == t_neww && t_oldh == t_newh) return src; /* OK... */
253 if (t_oldw == t_neww && t_oldh == t_newh) return NULL; /* HACKZ... */
254
255 /* Get the number of tiles in the image.
256 * Any possible clipped tiles at the edges are ignored.
257 */
258 nx = src->w / t_oldw;
259 ny = src->h / t_oldh;
260
261 /* Allocate a new SDL_Surface of appropriate size, with settings otherwise
262 * identical to src.
263 */
264 dst = SDL_CreateRGBSurface(src->flags, nx * t_neww, ny * t_newh, src->format->BitsPerPixel,
265 src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
266
267 /* Copy palette */
268 if (src->format->BitsPerPixel == 8)
269 {
270 SDL_SetColors(dst, src->format->palette->colors, 0, src->format->palette->ncolors);
271 dst->format->palette->ncolors = src->format->palette->ncolors;
272 }
273
274 /* Do per-tile scaling */
275 for (y = 0; y < ny; ++y)
276 {
277 for (x = 0; x < nx; ++x)
278 {
279 sr.w = t_oldw; sr.h = t_oldh;
280 sr.x = x * t_oldw; sr.y = y * t_oldh;
281
282 dr.w = t_neww; dr.h = t_newh;
283 dr.x = x * t_neww; dr.y = y * t_newh;
284
285 /* scale-blit one tile and check for error
286 * although SDl_ScaleBlit() might not have any errors to return.
287 */
288 if (SDL_ScaleBlit(src, &sr, dst, &dr)) return NULL;
289 /* XXX XXX XXX HACK -- stay online */
290 if (conn_state && randint0(10) < 5) {
291 //Net_packet();
292 update_ticks();
293 do_keepalive();
294 //Net_flush();
295 }
296 }
297 }
298
299 if (dealloc_src) SDL_FreeSurface(src);
300
301 return dst;
302 }
303
SurfaceTo8BIT(SDL_Surface * face,int free_src)304 SDL_Surface* SurfaceTo8BIT(SDL_Surface *face, int free_src)
305 {
306 int y, x;
307 int npal = 0;
308 SDL_Color *pc;
309 SDL_Surface *reface = SDL_CreateRGBSurface(0, face->w, face->h, 8, 0, 0, 0, 0);
310 for (y = 0; y < face->h; y++)
311 {
312 for (x = 0; x < face->w; x++)
313 {
314 byte n;
315 int found = 0;
316 Uint8 r, g, b;
317 Uint8 *dst_px = (Uint8*)((Uint8*)reface->pixels + (y * reface->pitch + x * reface->format->BytesPerPixel));
318 Uint32 *src_px = (Uint32*)((Uint8*)face->pixels + (y * face->pitch + x * face->format->BytesPerPixel));
319 SDL_GetRGB(*src_px, face->format, &r, &g, &b);
320 for (n = 0; n < npal; n++) {
321 pc = &(reface->format->palette->colors[n]);
322 if (pc->r == r && pc->g == g && pc->b == b) {
323 found = 1;
324 break;
325 }
326 }
327 if (!found && npal < 255) {
328 pc = &(reface->format->palette->colors[npal]);
329 pc->r = r; pc->g = g; pc->b = b;
330 n = npal;
331 npal++;
332 }
333 *dst_px = n;
334 }
335 }
336 reface->format->palette->ncolors = npal;
337 if (free_src) SDL_FreeSurface(face);
338 return reface;
339 }
340
formatsdlflags(Uint32 flags)341 char *formatsdlflags(Uint32 flags) {
342 return format ("%s%s%s%s%s%s%s%s%s%s (%x)",
343 (flags & SDL_HWSURFACE) ? "SDL_HWSURFACE " : "",
344 (flags & SDL_ANYFORMAT) ? "SDL_ANYFORMAT " : "",
345 (flags & SDL_HWPALETTE) ? "SDL_HWPALETTE " : "",
346 (flags & SDL_DOUBLEBUF) ? "SDL_DOUBLEBUF " : "",
347 (flags & SDL_FULLSCREEN) ?"SDL_FULLSCREEN " : "",
348 (flags & SDL_RESIZABLE) ? "SDL_RESIZABLE " : "",
349 (flags & SDL_HWACCEL) ? "SDL_HWACCEL " : "",
350 (flags & SDL_SRCCOLORKEY) ? "SDL_SRCCOLRKEY " : "",
351 (flags & SDL_RLEACCEL) ? "SDL_RLEACCEL " : "",
352 (flags & SDL_SRCALPHA) ? "SDL_SRCALPHA " : "",
353 flags);
354 };
355
356
357
358
359
360
361 /* A lot of code for handling keystrokes follow. */
362 typedef struct sdl_keymapt sdl_keymapt;
363
364 struct sdl_keymapt {
365 SDLKey k; /* what we get from SDL */
366 char *s; /* what we feed to the Term_keypress */
367 char *ctrl; /* what if CTRL is pressed? (NULL if the same) */
368 char *shift; /* what if SHIFT is pressed? */
369 };
370
371 /* XXX XXX XXX the following keymap sucks. More comments below. */
372 sdl_keymapt sdl_keymap[] =
373 {
374 /* Note: those are wrong, please see pref-x11.prf for
375 * correct ones. Compare to SDLK_F1-F12 below. */
376 /*{SDLK_UP, "[A", "Oa", "Ox"},
377 {SDLK_DOWN, "[B", "Ob", "Or"},
378 {SDLK_RIGHT, "[C", "Oc", "Ot"},
379 {SDLK_LEFT, "[D", "Od", "Ov"},
380 {SDLK_INSERT, "[2~", "[2^", "Op"},
381 {SDLK_HOME, "[1~", "[1^", "Ow"},
382 {SDLK_END, "[4~", "[4^", "Oq"},
383 {SDLK_PAGEUP, "[5~", "[5^", "Oy"},
384 {SDLK_PAGEDOWN, "[6~", "[6^", "Os"},*/
385 /*
386 {SDLK_F1, "_FFBE", NULL, NULL},
387 {SDLK_F2, "_FFBF", NULL, NULL},
388 {SDLK_F3, "_FFC0", NULL, NULL},
389 {SDLK_F4, "_FFC1", NULL, NULL},
390 {SDLK_F5, "_FFC2", NULL, NULL},
391 {SDLK_F6, "_FFC3", NULL, NULL},
392 {SDLK_F7, "_FFC4", NULL, NULL},
393 {SDLK_F8, "_FFC5", NULL, NULL},
394 {SDLK_F9, "_FFC6", NULL, NULL},
395 {SDLK_F10, "_FFC7", NULL, NULL},
396 {SDLK_F11, "_FFC8", NULL, NULL},
397 {SDLK_F12, "_FFC9", NULL, NULL},
398 */
399 /* I have no machines with F13, F14, F15. Is that a Sun thing? */
400 /*
401 {SDLK_F13, "", NULL, NULL},
402 {SDLK_F14, "", NULL, NULL},
403 {SDLK_F15, "", NULL, NULL},
404 */
405 {SDLK_RSHIFT, "", NULL, NULL},
406 {SDLK_LSHIFT, "", NULL, NULL},
407 {SDLK_RALT, "", NULL, NULL},
408 {SDLK_LALT, "", NULL, NULL},
409 {SDLK_RCTRL, "", NULL, NULL},
410 {SDLK_LCTRL, "", NULL, NULL},
411 {SDLK_RMETA, "", NULL, NULL},
412 {SDLK_LMETA, "", NULL, NULL},
413 {SDLK_NUMLOCK, "", NULL, NULL},
414 {SDLK_CAPSLOCK, "", NULL, NULL},
415 {SDLK_SCROLLOCK, "", NULL, NULL},
416 {SDLK_LSUPER, "", NULL, NULL},
417 {SDLK_RSUPER, "", NULL, NULL},
418 {SDLK_HELP, "?", NULL, NULL},
419 {SDLK_PRINT, "", NULL, NULL},
420 {SDLK_SYSREQ, "", NULL, NULL},
421 {SDLK_BREAK, "", NULL, NULL},
422 {SDLK_MENU, "", NULL, NULL},
423 {SDLK_POWER, "", NULL, NULL},
424 {SDLK_EURO, "", NULL, NULL},
425 {SDLK_0, "0", NULL, ")"}, /* XXX XXX XXX The CTRL-number keys need to be */
426 {SDLK_1, "1", NULL, "!"}, /* defined since they represent digging for */
427 {SDLK_2, "2", NULL, "@"}, /* some people!. Really, this whole table */
428 {SDLK_3, "3", NULL, "#"}, /* should be replaced with something cleaner */
429 {SDLK_4, "4", NULL, "$"}, /* and an SDL pref file should be created. */
430 {SDLK_5, "5", NULL, "%"},
431 {SDLK_6, "6", NULL, "^"},
432 {SDLK_7, "7", NULL, "&"},
433 {SDLK_8, "8", NULL, "*"},
434 {SDLK_9, "9", NULL, "("},
435 {SDLK_SEMICOLON, ";", NULL, ":"},
436 {SDLK_COMMA, ",", NULL, "<"},
437 {SDLK_PERIOD, ".", NULL, ">"},
438 {SDLK_BACKSLASH, "\\", NULL, "|"},
439 {SDLK_BACKQUOTE, "`", NULL, "~"},
440 {SDLK_LEFTBRACKET, "[", NULL, "{"},
441 {SDLK_RIGHTBRACKET, "]", NULL, "}"},
442 {SDLK_MINUS, "-", NULL, "_"},
443 {SDLK_EQUALS, "=", NULL, "+"},
444 {SDLK_SLASH, "/", NULL, "?"},
445 {SDLK_UNKNOWN, NULL, NULL, NULL} /* terminator */
446 };
447
Multikeypress(char * k)448 void Multikeypress(char *k)
449 {
450 while (*k) Term_keypress(*k++);
451 }
452
IsSpecial(SDLKey k)453 int IsSpecial(SDLKey k)
454 {
455 switch (k)
456 {
457 case SDLK_F1: case SDLK_F2:
458 case SDLK_F3: case SDLK_F4:
459 case SDLK_F5: case SDLK_F6:
460 case SDLK_F7: case SDLK_F8:
461 case SDLK_F9: case SDLK_F10:
462 case SDLK_F11: case SDLK_F12:
463 case SDLK_TAB:
464 return TRUE;
465 default:
466 return FALSE;
467 }
468 return 1234567; /* all good children go to heaven */
469 }
470
IsMovement(SDLKey k)471 int IsMovement(SDLKey k)
472 {
473 switch (k)
474 {
475 case SDLK_UP:
476 case SDLK_DOWN:
477 case SDLK_RIGHT:
478 case SDLK_LEFT:
479 case SDLK_INSERT:
480 case SDLK_HOME:
481 case SDLK_END:
482 case SDLK_PAGEUP:
483 case SDLK_PAGEDOWN:
484 case SDLK_KP0:
485 case SDLK_KP1:
486 case SDLK_KP2:
487 case SDLK_KP3:
488 case SDLK_KP4:
489 case SDLK_KP5:
490 case SDLK_KP6:
491 case SDLK_KP7:
492 case SDLK_KP8:
493 case SDLK_KP9:
494 return TRUE;
495
496 default:
497 return FALSE;
498 }
499 return 1234567; /* all good children go to heaven */
500 }
501
502
503 /* *** Arrow keys combiner *** */
504 int sdl_combine_arrowkeys = 1; /* ON/OFF */
505 Uint16 sdl_combiner_delay = 20;
506 /* Delayed key */
507 SDL_keysym delayed_keysym; /* Actual key (with mods) */
508 bool has_dlks = FALSE; /* We have one */
509 Uint32 event_timestamp = 0; /* Book-keeping */
510 Uint32 timestamp_dlks = 0;
511
CombinedMovement(SDLKey a,SDLKey b)512 static SDLKey CombinedMovement(SDLKey a, SDLKey b)
513 {
514 const SDLKey keys9x9[4][4] = {
515 { SDLK_HOME, SDLK_UP, SDLK_PAGEUP },
516 { SDLK_LEFT, 0, SDLK_RIGHT },
517 { SDLK_END, SDLK_DOWN, SDLK_PAGEDOWN },
518 };
519 int _dx = 0, _dy = 0;
520 if (a == SDLK_UP || b == SDLK_UP) _dy = -1;
521 else if (a == SDLK_DOWN || b == SDLK_DOWN) _dy = 1;
522 if (a == SDLK_LEFT || b == SDLK_LEFT) _dx = -1;
523 else if (a == SDLK_RIGHT || b == SDLK_RIGHT) _dx = 1;
524 if (_dx && _dy)
525 {
526 return keys9x9[_dy + 1][_dx + 1];
527 }
528 return 0;
529 }
Storedelayedkey(SDL_keysym * ks)530 void Storedelayedkey(SDL_keysym *ks)
531 {
532 memcpy(&delayed_keysym, ks, sizeof(delayed_keysym));
533 has_dlks = 1;
534 timestamp_dlks = event_timestamp;
535 }
536 char *SDL_keysymtostr(SDL_keysym *ks); /* forward dec */
Flushdelayedkey(bool execute,bool force_flush,SDLKey ks,Uint32 timestamp)537 void Flushdelayedkey(bool execute, bool force_flush, SDLKey ks, Uint32 timestamp)
538 {
539 bool flush = FALSE;
540 if (force_flush == TRUE) {
541 flush = TRUE;
542 }
543 else if (ks && has_dlks && delayed_keysym.sym == ks)
544 {
545 flush = TRUE;
546 }
547 else if (timestamp && has_dlks) {
548 if (timestamp - timestamp_dlks > sdl_combiner_delay) flush = TRUE;
549 }
550 if (flush)
551 {
552 if (execute)
553 {
554 int old = sdl_combine_arrowkeys;
555 sdl_combine_arrowkeys = 0;
556 Multikeypress(SDL_keysymtostr(&delayed_keysym));
557 sdl_combine_arrowkeys = old;
558 }
559 has_dlks = 0;
560 }
561 }
562
SDL_keysymtostr(SDL_keysym * ks)563 char *SDL_keysymtostr(SDL_keysym *ks)
564 {
565 #ifdef bufsize
566 #error bufsize steps on previous define!
567 #endif
568 #define bufsize 32
569 int bufused = 0;
570
571 /* I am returning a pointer to the below variable.
572 * I /think/ this is legal but I am not sure! XXX XXX XXX
573 * It certainly seems to work fine, at least under GCC.
574 * It can easily be changed to a pointer passed as an argument.
575 */
576 static char buf[bufsize];
577 Uint8 ch;
578 Uint32 i;
579
580 /* cat for strings and app[end] for characters */
581 #define sdlkcat(a) strncat(buf,(a),bufsize-bufused-1); bufused+=strlen((a));
582 #define sdlkapp(a) if(bufused<bufsize-1) { buf[bufused]=a; buf[bufused+1]='\0'; bufused++; }
583
584 buf[0] = '\0';
585
586 if(ks->unicode && !(ks->unicode & 0xff80)) {
587 ch = (Uint8)ks->unicode;
588 if (ch) sdlkapp(ch);
589 return buf;
590 }
591
592 /* HACK -- combine two arrow keys pressed at the same time. */
593 if (sdl_combine_arrowkeys)
594 {
595 if (ks->sym == SDLK_LEFT || ks->sym == SDLK_RIGHT ||
596 ks->sym == SDLK_UP || ks->sym == SDLK_DOWN)
597 {
598 if (has_dlks)
599 {
600 SDLKey rekey = CombinedMovement(ks->sym, delayed_keysym.sym);
601 Flushdelayedkey(FALSE, TRUE, 0, 0);
602 if (rekey) {
603 /* Is replacing keysym.sym evil? Should work fine */
604 ks->sym = rekey;
605 ks->mod = delayed_keysym.mod;
606 }
607 } else {
608 Storedelayedkey(ks);
609 return buf;
610 }
611 }
612 }
613
614 for (i = 0; ; ++i)
615 {
616 if (sdl_keymap[i].k == ks->sym)
617 {
618 if (sdl_keymap[i].s && strlen(sdl_keymap[i].s))
619 {
620 if (ks->mod & KMOD_ALT)
621 {
622 sdlkapp('');
623 }
624 if (ks->mod & KMOD_CTRL)
625 {
626 if (sdl_keymap[i].ctrl)
627 {
628 sdlkcat(sdl_keymap[i].ctrl);
629 break;
630 }
631 } else
632 if (ks->mod & KMOD_SHIFT)
633 {
634 if(sdl_keymap[i].shift)
635 {
636 sdlkcat(sdl_keymap[i].shift);
637 break;
638 }
639 }
640 sdlkcat(sdl_keymap[i].s);
641 }
642 break; /* out of the for() loop */
643 } else
644 if (sdl_keymap[i].k == SDLK_UNKNOWN)
645 {
646 if (IsMovement(ks->sym) || IsSpecial(ks->sym))
647 {
648 sprintf(buf, "%c%s%s%s%s_%lX%c", 31,
649 ks->mod & KMOD_CTRL ? "N" : "",
650 ks->mod & KMOD_SHIFT ? "S" : "",
651 ks->mod & KMOD_ALT ? "O" : "",
652 ks->mod & KMOD_META ? "M" : "",
653 (unsigned long) ks->sym, 13);
654 ch = 0;
655 }
656 else
657 {
658 if (ks->mod & KMOD_ALT)
659 {
660 sdlkapp('');
661 }
662 ch = ks->sym;
663 /* alphanumeric keys aren't part of the keymap because
664 * typing them in would be way too tedious */
665 if (ch <= 'z' && ch >= 'a') {
666 if (ks->mod & KMOD_CTRL)
667 {
668 ch = 1 + ch - 'a';
669 } else
670 if (ks->mod & KMOD_SHIFT)
671 {
672 ch += ('A' - 'a');
673 }
674 }
675 }
676
677 if (ch) sdlkapp(ch);
678 break; /* end the for loop; we're at the end of keymap */
679 }
680 } /* for... */
681
682 /*puts(buf);*/
683 return buf;
684 #undef bufsize
685 #undef sdlkcat
686 #undef sdlkapp
687
688 } /* SDL_keystring */
689
690 #endif
691