test/testime.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Wed, 02 Mar 2016 20:24:43 +0100
changeset 10097 06085b9c73ef
parent 9998 f67cf37e9cd4
child 10100 a18ec339c8d3
permissions -rw-r--r--
Replaced strlen() with SDL_strlen() in IME test program.
     1 /*
     2   Copyright (C) 1997-2016 Sam Lantinga <slouken@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[SDL_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                                  size_t 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: */