Xcode-iOS/Demos/src/keyboard.c
changeset 6159 fb6f363032fd
parent 5364 fec676157db5
child 6310 f830e73e2acf
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/Xcode-iOS/Demos/src/keyboard.c	Thu Jan 05 21:41:55 2012 -0500
     1.3 @@ -0,0 +1,319 @@
     1.4 +/*
     1.5 + *	keyboard.c
     1.6 + *	written by Holmes Futrell
     1.7 + *	use however you want
     1.8 + */
     1.9 +
    1.10 +#import "SDL.h"
    1.11 +#import "common.h"
    1.12 +
    1.13 +#define GLYPH_SIZE_IMAGE 16     /* size of glyphs (characters) in the bitmap font file */
    1.14 +#define GLYPH_SIZE_SCREEN 32    /* size of glyphs (characters) as shown on the screen */
    1.15 +
    1.16 +static SDL_Texture *texture; /* texture where we'll hold our font */
    1.17 +
    1.18 +/* iPhone SDL addition keyboard related function definitions */
    1.19 +extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardShow(SDL_Window * window);
    1.20 +extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardHide(SDL_Window * window);
    1.21 +extern DECLSPEC SDL_bool SDLCALL SDL_iPhoneKeyboardIsShown(SDL_Window *
    1.22 +                                                           window);
    1.23 +extern DECLSPEC int SDLCALL SDL_iPhoneKeyboardToggle(SDL_Window * window);
    1.24 +
    1.25 +/* function declarations */
    1.26 +void cleanup(void);
    1.27 +void drawBlank(int x, int y);
    1.28 +
    1.29 +static SDL_Renderer *renderer;
    1.30 +static int numChars = 0;        /* number of characters we've typed so far */
    1.31 +static SDL_bool lastCharWasColon = 0;   /* we use this to detect sequences such as :) */
    1.32 +static SDL_Color bg_color = { 50, 50, 100, 255 };       /* color of background */
    1.33 +
    1.34 +/* this structure maps a scancode to an index in our bitmap font.
    1.35 +   it also contains data about under which modifiers the mapping is valid
    1.36 +   (for example, we don't want shift + 1 to produce the character '1',
    1.37 +   but rather the character '!')
    1.38 +*/
    1.39 +typedef struct
    1.40 +{
    1.41 +    SDL_ScanCode scancode;      /* scancode of the key we want to map */
    1.42 +    int allow_no_mod;           /* is the map valid if the key has no modifiers? */
    1.43 +    SDLMod mod;                 /* what modifiers are allowed for the mapping */
    1.44 +    int index;                  /* what index in the font does the scancode map to */
    1.45 +} fontMapping;
    1.46 +
    1.47 +#define TABLE_SIZE 51           /* size of our table which maps keys and modifiers to font indices */
    1.48 +
    1.49 +/* Below is the table that defines the mapping between scancodes and modifiers to indices in the
    1.50 +   bitmap font.  As an example, then line '{ SDL_SCANCODE_A, 1, KMOD_SHIFT, 33 }' means, map
    1.51 +   the key A (which has scancode SDL_SCANCODE_A) to index 33 in the font (which is a picture of an A),
    1.52 +   The '1' means that the mapping is valid even if there are no modifiers, and KMOD_SHIFT means the
    1.53 +   mapping is also valid if the user is holding shift.
    1.54 +*/
    1.55 +fontMapping map[TABLE_SIZE] = {
    1.56 +
    1.57 +    {SDL_SCANCODE_A, 1, KMOD_SHIFT, 33},        /* A */
    1.58 +    {SDL_SCANCODE_B, 1, KMOD_SHIFT, 34},        /* B */
    1.59 +    {SDL_SCANCODE_C, 1, KMOD_SHIFT, 35},        /* C */
    1.60 +    {SDL_SCANCODE_D, 1, KMOD_SHIFT, 36},        /* D */
    1.61 +    {SDL_SCANCODE_E, 1, KMOD_SHIFT, 37},        /* E */
    1.62 +    {SDL_SCANCODE_F, 1, KMOD_SHIFT, 38},        /* F */
    1.63 +    {SDL_SCANCODE_G, 1, KMOD_SHIFT, 39},        /* G */
    1.64 +    {SDL_SCANCODE_H, 1, KMOD_SHIFT, 40},        /* H */
    1.65 +    {SDL_SCANCODE_I, 1, KMOD_SHIFT, 41},        /* I */
    1.66 +    {SDL_SCANCODE_J, 1, KMOD_SHIFT, 42},        /* J */
    1.67 +    {SDL_SCANCODE_K, 1, KMOD_SHIFT, 43},        /* K */
    1.68 +    {SDL_SCANCODE_L, 1, KMOD_SHIFT, 44},        /* L */
    1.69 +    {SDL_SCANCODE_M, 1, KMOD_SHIFT, 45},        /* M */
    1.70 +    {SDL_SCANCODE_N, 1, KMOD_SHIFT, 46},        /* N */
    1.71 +    {SDL_SCANCODE_O, 1, KMOD_SHIFT, 47},        /* O */
    1.72 +    {SDL_SCANCODE_P, 1, KMOD_SHIFT, 48},        /* P */
    1.73 +    {SDL_SCANCODE_Q, 1, KMOD_SHIFT, 49},        /* Q */
    1.74 +    {SDL_SCANCODE_R, 1, KMOD_SHIFT, 50},        /* R */
    1.75 +    {SDL_SCANCODE_S, 1, KMOD_SHIFT, 51},        /* S */
    1.76 +    {SDL_SCANCODE_T, 1, KMOD_SHIFT, 52},        /* T */
    1.77 +    {SDL_SCANCODE_U, 1, KMOD_SHIFT, 53},        /* U */
    1.78 +    {SDL_SCANCODE_V, 1, KMOD_SHIFT, 54},        /* V */
    1.79 +    {SDL_SCANCODE_W, 1, KMOD_SHIFT, 55},        /* W */
    1.80 +    {SDL_SCANCODE_X, 1, KMOD_SHIFT, 56},        /* X */
    1.81 +    {SDL_SCANCODE_Y, 1, KMOD_SHIFT, 57},        /* Y */
    1.82 +    {SDL_SCANCODE_Z, 1, KMOD_SHIFT, 58},        /* Z */
    1.83 +    {SDL_SCANCODE_0, 1, 0, 16}, /* 0 */
    1.84 +    {SDL_SCANCODE_1, 1, 0, 17}, /* 1 */
    1.85 +    {SDL_SCANCODE_2, 1, 0, 18}, /* 2 */
    1.86 +    {SDL_SCANCODE_3, 1, 0, 19}, /* 3 */
    1.87 +    {SDL_SCANCODE_4, 1, 0, 20}, /* 4 */
    1.88 +    {SDL_SCANCODE_5, 1, 0, 21}, /* 5 */
    1.89 +    {SDL_SCANCODE_6, 1, 0, 22}, /* 6 */
    1.90 +    {SDL_SCANCODE_7, 1, 0, 23}, /* 7 */
    1.91 +    {SDL_SCANCODE_8, 1, 0, 24}, /* 8 */
    1.92 +    {SDL_SCANCODE_9, 1, 0, 25}, /* 9 */
    1.93 +    {SDL_SCANCODE_SPACE, 1, 0, 0},      /*' ' */
    1.94 +    {SDL_SCANCODE_1, 0, KMOD_SHIFT, 1}, /* ! */
    1.95 +    {SDL_SCANCODE_SLASH, 0, KMOD_SHIFT, 31},    /* ? */
    1.96 +    {SDL_SCANCODE_SLASH, 1, 0, 15},     /* / */
    1.97 +    {SDL_SCANCODE_COMMA, 1, 0, 12},     /* , */
    1.98 +    {SDL_SCANCODE_SEMICOLON, 1, 0, 27}, /* ; */
    1.99 +    {SDL_SCANCODE_SEMICOLON, 0, KMOD_SHIFT, 26},        /* : */
   1.100 +    {SDL_SCANCODE_PERIOD, 1, 0, 14},    /* . */
   1.101 +    {SDL_SCANCODE_MINUS, 1, 0, 13},     /* - */
   1.102 +    {SDL_SCANCODE_EQUALS, 0, KMOD_SHIFT, 11},   /* = */
   1.103 +    {SDL_SCANCODE_APOSTROPHE, 1, 0, 7}, /* ' */
   1.104 +    {SDL_SCANCODE_APOSTROPHE, 0, KMOD_SHIFT, 2},        /* " */
   1.105 +    {SDL_SCANCODE_5, 0, KMOD_SHIFT, 5}, /* % */
   1.106 +
   1.107 +};
   1.108 +
   1.109 +/*
   1.110 +	This function maps an SDL_KeySym to an index in the bitmap font.
   1.111 +	It does so by scanning through the font mapping table one entry
   1.112 +	at a time.
   1.113 + 
   1.114 +	If a match is found (scancode and allowed modifiers), the proper
   1.115 +	index is returned.
   1.116 + 
   1.117 +	If there is no entry for the key, -1 is returned
   1.118 +*/
   1.119 +int
   1.120 +keyToIndex(SDL_KeySym key)
   1.121 +{
   1.122 +    int i, index = -1;
   1.123 +    for (i = 0; i < TABLE_SIZE; i++) {
   1.124 +        fontMapping compare = map[i];
   1.125 +        if (key.scancode == compare.scancode) {
   1.126 +            /* if this entry is valid with no key mod and we have no keymod, or if
   1.127 +               the key's modifiers are allowed modifiers for that mapping */
   1.128 +            if ((compare.allow_no_mod && key.mod == 0)
   1.129 +                || (key.mod & compare.mod)) {
   1.130 +                index = compare.index;
   1.131 +                break;
   1.132 +            }
   1.133 +        }
   1.134 +    }
   1.135 +    return index;
   1.136 +}
   1.137 +
   1.138 +/* 
   1.139 +	This function returns and x,y position for a given character number.
   1.140 +    It is used for positioning each character of text
   1.141 +*/
   1.142 +void
   1.143 +getPositionForCharNumber(int n, int *x, int *y)
   1.144 +{
   1.145 +    int x_padding = 16;         /* padding space on left and right side of screen */
   1.146 +    int y_padding = 32;         /* padding space at top of screen */
   1.147 +    /* figure out the number of characters that can fit horizontally across the screen */
   1.148 +    int max_x_chars = (SCREEN_WIDTH - 2 * x_padding) / GLYPH_SIZE_SCREEN;
   1.149 +    int line_separation = 5;    /* pixels between each line */
   1.150 +    *x = (n % max_x_chars) * GLYPH_SIZE_SCREEN + x_padding;
   1.151 +    *y = (n / max_x_chars) * (GLYPH_SIZE_SCREEN + line_separation) +
   1.152 +        y_padding;
   1.153 +}
   1.154 +
   1.155 +void
   1.156 +drawIndex(int index)
   1.157 +{
   1.158 +    int x, y;
   1.159 +    getPositionForCharNumber(numChars, &x, &y);
   1.160 +    SDL_Rect srcRect =
   1.161 +        { GLYPH_SIZE_IMAGE * index, 0, GLYPH_SIZE_IMAGE, GLYPH_SIZE_IMAGE };
   1.162 +    SDL_Rect dstRect = { x, y, GLYPH_SIZE_SCREEN, GLYPH_SIZE_SCREEN };
   1.163 +    drawBlank(x, y);
   1.164 +    SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
   1.165 +}
   1.166 +
   1.167 +/*  draws the cursor icon at the current end position of the text */
   1.168 +void
   1.169 +drawCursor(void)
   1.170 +{
   1.171 +    drawIndex(29);              /* cursor is at index 29 in the bitmap font */
   1.172 +}
   1.173 +
   1.174 +/* paints over a glyph sized region with the background color
   1.175 +   in effect it erases the area
   1.176 +*/
   1.177 +void
   1.178 +drawBlank(int x, int y)
   1.179 +{
   1.180 +    SDL_Rect rect = { x, y, GLYPH_SIZE_SCREEN, GLYPH_SIZE_SCREEN };
   1.181 +    SDL_SetRenderDrawColor(renderer, bg_color.r, bg_color.g, bg_color.b,
   1.182 +                           bg_color.unused);
   1.183 +    SDL_RenderFillRect(renderer, &rect);
   1.184 +}
   1.185 +
   1.186 +/* moves backwards one character, erasing the last one put down */
   1.187 +void
   1.188 +backspace(void)
   1.189 +{
   1.190 +    int x, y;
   1.191 +    if (numChars > 0) {
   1.192 +        getPositionForCharNumber(numChars, &x, &y);
   1.193 +        drawBlank(x, y);
   1.194 +        numChars--;
   1.195 +        getPositionForCharNumber(numChars, &x, &y);
   1.196 +        drawBlank(x, y);
   1.197 +        drawCursor();
   1.198 +    }
   1.199 +}
   1.200 +
   1.201 +/* this function loads our font into an SDL_Texture and returns the SDL_Texture  */
   1.202 +SDL_Texture*
   1.203 +loadFont(void)
   1.204 +{
   1.205 +
   1.206 +    SDL_Surface *surface = SDL_LoadBMP("kromasky_16x16.bmp");
   1.207 +
   1.208 +    if (!surface) {
   1.209 +        printf("Error loading bitmap: %s\n", SDL_GetError());
   1.210 +        return 0;
   1.211 +    } else {
   1.212 +        /* set the transparent color for the bitmap font (hot pink) */
   1.213 +        SDL_SetColorKey(surface, 1, SDL_MapRGB(surface->format, 238, 0, 252));
   1.214 +        /* now we convert the surface to our desired pixel format */
   1.215 +        int format = SDL_PIXELFORMAT_ABGR8888;  /* desired texture format */
   1.216 +        Uint32 Rmask, Gmask, Bmask, Amask;      /* masks for desired format */
   1.217 +        int bpp;                /* bits per pixel for desired format */
   1.218 +        SDL_PixelFormatEnumToMasks(format, &bpp, &Rmask, &Gmask, &Bmask,
   1.219 +                                   &Amask);
   1.220 +        SDL_Surface *converted =
   1.221 +            SDL_CreateRGBSurface(0, surface->w, surface->h, bpp, Rmask, Gmask,
   1.222 +                                 Bmask, Amask);
   1.223 +        SDL_BlitSurface(surface, NULL, converted, NULL);
   1.224 +        /* create our texture */
   1.225 +        texture =
   1.226 +            SDL_CreateTextureFromSurface(renderer, converted);
   1.227 +        if (texture == 0) {
   1.228 +            printf("texture creation failed: %s\n", SDL_GetError());
   1.229 +        } else {
   1.230 +            /* set blend mode for our texture */
   1.231 +            SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
   1.232 +        }
   1.233 +        SDL_FreeSurface(surface);
   1.234 +        SDL_FreeSurface(converted);
   1.235 +        return texture;
   1.236 +    }
   1.237 +}
   1.238 +
   1.239 +int
   1.240 +main(int argc, char *argv[])
   1.241 +{
   1.242 +
   1.243 +    int index;                  /* index of last key we pushed in the bitmap font */
   1.244 +    SDL_Window *window;
   1.245 +    SDL_Event event;            /* last event received */
   1.246 +    SDLMod mod;                 /* key modifiers of last key we pushed */
   1.247 +    SDL_ScanCode scancode;      /* scancode of last key we pushed */
   1.248 +
   1.249 +    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
   1.250 +        printf("Error initializing SDL: %s", SDL_GetError());
   1.251 +    }
   1.252 +    /* create window */
   1.253 +    window = SDL_CreateWindow("iPhone keyboard test", 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0);
   1.254 +    /* create renderer */
   1.255 +    renderer = SDL_CreateRenderer(window, -1, 0);
   1.256 +
   1.257 +    /* load up our font */
   1.258 +    loadFont();
   1.259 +
   1.260 +    /* draw the background, we'll just paint over it */
   1.261 +    SDL_SetRenderDrawColor(renderer, bg_color.r, bg_color.g, bg_color.b,
   1.262 +                           bg_color.unused);
   1.263 +    SDL_RenderFillRect(renderer, NULL);
   1.264 +    SDL_RenderPresent(renderer);
   1.265 +
   1.266 +    int done = 0;
   1.267 +    /* loop till we get SDL_Quit */
   1.268 +    while (SDL_WaitEvent(&event)) {
   1.269 +        switch (event.type) {
   1.270 +        case SDL_QUIT:
   1.271 +            done = 1;
   1.272 +            break;
   1.273 +        case SDL_KEYDOWN:
   1.274 +            index = keyToIndex(event.key.keysym);
   1.275 +            scancode = event.key.keysym.scancode;
   1.276 +            mod = event.key.keysym.mod;
   1.277 +            if (scancode == SDL_SCANCODE_DELETE) {
   1.278 +                /* if user hit delete, delete the last character */
   1.279 +                backspace();
   1.280 +                lastCharWasColon = 0;
   1.281 +            } else if (lastCharWasColon && scancode == SDL_SCANCODE_0
   1.282 +                       && (mod & KMOD_SHIFT)) {
   1.283 +                /* if our last key was a colon and this one is a close paren, the make a hoppy face */
   1.284 +                backspace();
   1.285 +                drawIndex(32);  /* index for happy face */
   1.286 +                numChars++;
   1.287 +                drawCursor();
   1.288 +                lastCharWasColon = 0;
   1.289 +            } else if (index != -1) {
   1.290 +                /* if we aren't doing a happy face, then just draw the normal character */
   1.291 +                drawIndex(index);
   1.292 +                numChars++;
   1.293 +                drawCursor();
   1.294 +                lastCharWasColon =
   1.295 +                    (event.key.keysym.scancode == SDL_SCANCODE_SEMICOLON
   1.296 +                     && (event.key.keysym.mod & KMOD_SHIFT));
   1.297 +            }
   1.298 +            /* check if the key was a colon */
   1.299 +            /* draw our updates to the screen */
   1.300 +            SDL_RenderPresent(renderer);
   1.301 +            break;
   1.302 +#ifdef __IPHONEOS__
   1.303 +        case SDL_MOUSEBUTTONUP:
   1.304 +            /*      mouse up toggles onscreen keyboard visibility
   1.305 +               this function is available ONLY on iPhone OS
   1.306 +             */
   1.307 +            SDL_iPhoneKeyboardToggle(window);
   1.308 +            break;
   1.309 +#endif
   1.310 +        }
   1.311 +    }
   1.312 +    cleanup();
   1.313 +    return 0;
   1.314 +}
   1.315 +
   1.316 +/* clean up after ourselves like a good kiddy */
   1.317 +void
   1.318 +cleanup(void)
   1.319 +{
   1.320 +    SDL_DestroyTexture(texture);
   1.321 +    SDL_Quit();
   1.322 +}