Home | History | Annotate | Download | only in test
      1 /*
      2   Copyright (C) 1997-2014 Sam Lantinga <slouken (at) libsdl.org>
      3 
      4   This software is provided 'as-is', without any express or implied
      5   warranty.  In no event will the authors be held liable for any damages
      6   arising from the use of this software.
      7 
      8   Permission is granted to anyone to use this software for any purpose,
      9   including commercial applications, and to alter it and redistribute it
     10   freely.
     11 */
     12 /* A simple program to test the Input Method support in the SDL library (2.0+) */
     13 
     14 #include <stdlib.h>
     15 #include <stdio.h>
     16 #include <string.h>
     17 
     18 #include "SDL.h"
     19 #ifdef HAVE_SDL_TTF
     20 #include "SDL_ttf.h"
     21 #endif
     22 
     23 #include "SDL_test_common.h"
     24 
     25 #define DEFAULT_PTSIZE  30
     26 #define DEFAULT_FONT    "/System/Library/Fonts/.ttf"
     27 #define MAX_TEXT_LENGTH 256
     28 
     29 static SDLTest_CommonState *state;
     30 static SDL_Rect textRect, markedRect;
     31 static SDL_Color lineColor = {0,0,0,0};
     32 static SDL_Color backColor = {255,255,255,0};
     33 static SDL_Color textColor = {0,0,0,0};
     34 static char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
     35 static int cursor = 0;
     36 #ifdef HAVE_SDL_TTF
     37 static TTF_Font *font;
     38 #endif
     39 
     40 size_t utf8_length(unsigned char c)
     41 {
     42     c = (unsigned char)(0xff & c);
     43     if (c < 0x80)
     44         return 1;
     45     else if ((c >> 5) ==0x6)
     46         return 2;
     47     else if ((c >> 4) == 0xe)
     48         return 3;
     49     else if ((c >> 3) == 0x1e)
     50         return 4;
     51     else
     52         return 0;
     53 }
     54 
     55 char *utf8_next(char *p)
     56 {
     57     size_t len = utf8_length(*p);
     58     size_t i = 0;
     59     if (!len)
     60         return 0;
     61 
     62     for (; i < len; ++i)
     63     {
     64         ++p;
     65         if (!*p)
     66             return 0;
     67     }
     68     return p;
     69 }
     70 
     71 char *utf8_advance(char *p, size_t distance)
     72 {
     73     size_t i = 0;
     74     for (; i < distance && p; ++i)
     75     {
     76         p = utf8_next(p);
     77     }
     78     return p;
     79 }
     80 
     81 void usage()
     82 {
     83     SDL_Log("usage: testime [--font fontfile]\n");
     84     exit(0);
     85 }
     86 
     87 void InitInput()
     88 {
     89 
     90     /* Prepare a rect for text input */
     91     textRect.x = textRect.y = 100;
     92     textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
     93     textRect.h = 50;
     94 
     95     text[0] = 0;
     96     markedRect = textRect;
     97     markedText[0] = 0;
     98 
     99     SDL_StartTextInput();
    100 }
    101 
    102 void CleanupVideo()
    103 {
    104     SDL_StopTextInput();
    105 #ifdef HAVE_SDL_TTF
    106     TTF_CloseFont(font);
    107     TTF_Quit();
    108 #endif
    109 }
    110 
    111 
    112 void _Redraw(SDL_Renderer * renderer) {
    113     int w = 0, h = textRect.h;
    114     SDL_Rect cursorRect, underlineRect;
    115 
    116     SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    117     SDL_RenderFillRect(renderer,&textRect);
    118 
    119 #ifdef HAVE_SDL_TTF
    120     if (*text)
    121     {
    122         SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
    123         SDL_Rect dest = {textRect.x, textRect.y, textSur->w, textSur->h };
    124 
    125         SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
    126         SDL_FreeSurface(textSur);
    127 
    128         SDL_RenderCopy(renderer,texture,NULL,&dest);
    129         SDL_DestroyTexture(texture);
    130         TTF_SizeUTF8(font, text, &w, &h);
    131     }
    132 #endif
    133 
    134     markedRect.x = textRect.x + w;
    135     markedRect.w = textRect.w - w;
    136     if (markedRect.w < 0)
    137     {
    138         /* Stop text input because we cannot hold any more characters */
    139         SDL_StopTextInput();
    140         return;
    141     }
    142     else
    143     {
    144         SDL_StartTextInput();
    145     }
    146 
    147     cursorRect = markedRect;
    148     cursorRect.w = 2;
    149     cursorRect.h = h;
    150 
    151     SDL_SetRenderDrawColor(renderer, 255,255,255,255);
    152     SDL_RenderFillRect(renderer,&markedRect);
    153 
    154     if (markedText[0])
    155     {
    156 #ifdef HAVE_SDL_TTF
    157         if (cursor)
    158         {
    159             char *p = utf8_advance(markedText, cursor);
    160             char c = 0;
    161             if (!p)
    162                 p = &markedText[strlen(markedText)];
    163 
    164             c = *p;
    165             *p = 0;
    166             TTF_SizeUTF8(font, markedText, &w, 0);
    167             cursorRect.x += w;
    168             *p = c;
    169         }
    170         SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
    171         SDL_Rect dest = {markedRect.x, markedRect.y, textSur->w, textSur->h };
    172         TTF_SizeUTF8(font, markedText, &w, &h);
    173         SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
    174         SDL_FreeSurface(textSur);
    175 
    176         SDL_RenderCopy(renderer,texture,NULL,&dest);
    177         SDL_DestroyTexture(texture);
    178 #endif
    179 
    180         underlineRect = markedRect;
    181         underlineRect.y += (h - 2);
    182         underlineRect.h = 2;
    183         underlineRect.w = w;
    184 
    185         SDL_SetRenderDrawColor(renderer, 0,0,0,0);
    186         SDL_RenderFillRect(renderer,&markedRect);
    187     }
    188 
    189     SDL_SetRenderDrawColor(renderer, 0,0,0,0);
    190     SDL_RenderFillRect(renderer,&cursorRect);
    191 
    192     SDL_SetTextInputRect(&markedRect);
    193 }
    194 
    195 void Redraw() {
    196     int i;
    197     for (i = 0; i < state->num_windows; ++i) {
    198         SDL_Renderer *renderer = state->renderers[i];
    199         if (state->windows[i] == NULL)
    200             continue;
    201         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
    202         SDL_RenderClear(renderer);
    203 
    204         _Redraw(renderer);
    205 
    206         SDL_RenderPresent(renderer);
    207     }
    208 }
    209 
    210 int main(int argc, char *argv[]) {
    211     int i, done;
    212     SDL_Event event;
    213     const char *fontname = DEFAULT_FONT;
    214 
    215     /* Enable standard application logging */
    216     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
    217 
    218     /* Initialize test framework */
    219     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
    220     if (!state) {
    221         return 1;
    222     }
    223     for (i = 1; i < argc;i++) {
    224         SDLTest_CommonArg(state, i);
    225     }
    226     for (argc--, argv++; argc > 0; argc--, argv++)
    227     {
    228         if (strcmp(argv[0], "--help") == 0) {
    229             usage();
    230             return 0;
    231         }
    232 
    233         else if (strcmp(argv[0], "--font") == 0)
    234         {
    235             argc--;
    236             argv++;
    237 
    238             if (argc > 0)
    239                 fontname = argv[0];
    240             else {
    241                 usage();
    242                 return 0;
    243             }
    244         }
    245     }
    246 
    247     if (!SDLTest_CommonInit(state)) {
    248         return 2;
    249     }
    250 
    251 
    252 #ifdef HAVE_SDL_TTF
    253     /* Initialize fonts */
    254     TTF_Init();
    255 
    256     font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
    257     if (! font)
    258     {
    259         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
    260         exit(-1);
    261     }
    262 #endif
    263 
    264     SDL_Log("Using font: %s\n", fontname);
    265     atexit(SDL_Quit);
    266 
    267     InitInput();
    268     /* Create the windows and initialize the renderers */
    269     for (i = 0; i < state->num_windows; ++i) {
    270         SDL_Renderer *renderer = state->renderers[i];
    271         SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
    272         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
    273         SDL_RenderClear(renderer);
    274     }
    275     Redraw();
    276     /* Main render loop */
    277     done = 0;
    278     while (!done) {
    279         /* Check for events */
    280         while (SDL_PollEvent(&event)) {
    281             SDLTest_CommonEvent(state, &event, &done);
    282             switch(event.type) {
    283                 case SDL_KEYDOWN: {
    284                     switch (event.key.keysym.sym)
    285                     {
    286                         case SDLK_RETURN:
    287                              text[0]=0x00;
    288                              Redraw();
    289                              break;
    290                         case SDLK_BACKSPACE:
    291                              {
    292                                  int textlen=SDL_strlen(text);
    293 
    294                                  do {
    295                                      if (textlen==0)
    296                                      {
    297                                          break;
    298                                      }
    299                                      if ((text[textlen-1] & 0x80) == 0x00)
    300                                      {
    301                                          /* One byte */
    302                                          text[textlen-1]=0x00;
    303                                          break;
    304                                      }
    305                                      if ((text[textlen-1] & 0xC0) == 0x80)
    306                                      {
    307                                          /* Byte from the multibyte sequence */
    308                                          text[textlen-1]=0x00;
    309                                          textlen--;
    310                                      }
    311                                      if ((text[textlen-1] & 0xC0) == 0xC0)
    312                                      {
    313                                          /* First byte of multibyte sequence */
    314                                          text[textlen-1]=0x00;
    315                                          break;
    316                                      }
    317                                  } while(1);
    318 
    319                                  Redraw();
    320                              }
    321                              break;
    322                     }
    323 
    324                     if (done)
    325                     {
    326                         break;
    327                     }
    328 
    329                     SDL_Log("Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
    330                             event.key.keysym.scancode,
    331                             SDL_GetScancodeName(event.key.keysym.scancode),
    332                             event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
    333                     break;
    334 
    335                 case SDL_TEXTINPUT:
    336                     if (event.text.text[0] == '\0' || event.text.text[0] == '\n' ||
    337                         markedRect.w < 0)
    338                         break;
    339 
    340                     SDL_Log("Keyboard: text input \"%s\"\n", event.text.text);
    341 
    342                     if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
    343                         SDL_strlcat(text, event.text.text, sizeof(text));
    344 
    345                     SDL_Log("text inputed: %s\n", text);
    346 
    347                     /* After text inputed, we can clear up markedText because it */
    348                     /* is committed */
    349                     markedText[0] = 0;
    350                     Redraw();
    351                     break;
    352 
    353                 case SDL_TEXTEDITING:
    354                     SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
    355                             event.edit.text, event.edit.start, event.edit.length);
    356 
    357                     strcpy(markedText, event.edit.text);
    358                     cursor = event.edit.start;
    359                     Redraw();
    360                     break;
    361                 }
    362                 break;
    363 
    364             }
    365         }
    366     }
    367     CleanupVideo();
    368     SDLTest_CommonQuit(state);
    369     return 0;
    370 }
    371 
    372 
    373 /* vi: set ts=4 sw=4 expandtab: */
    374