test/testime.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 18 May 2013 14:17:52 -0700
changeset 7191 75360622e65f
parent 6785 c094c438c0a6
child 7517 965d57022c01
permissions -rw-r--r--
File style cleanup for the SDL 2.0 release
     1 /*
     2   Copyright (C) 1997-2011 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     printf("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         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
   200         SDL_RenderClear(renderer);
   201 
   202         _Redraw(renderer);
   203 
   204         SDL_RenderPresent(renderer);
   205     }
   206 }
   207 
   208 int main(int argc, char *argv[]) {
   209     int i, done;
   210     SDL_Event event;
   211     const char *fontname = DEFAULT_FONT;
   212 
   213     /* Initialize test framework */
   214     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   215     if (!state) {
   216         return 1;
   217     }
   218     for (i = 1; i < argc;i++) {
   219         SDLTest_CommonArg(state, i);
   220     }
   221     for (argc--, argv++; argc > 0; argc--, argv++)
   222     {
   223         if (strcmp(argv[0], "--help") == 0) {
   224             usage();
   225             return 0;
   226         }
   227 
   228         else if (strcmp(argv[0], "--font") == 0)
   229         {
   230             argc--;
   231             argv++;
   232 
   233             if (argc > 0)
   234                 fontname = argv[0];
   235             else {
   236                 usage();
   237                 return 0;
   238             }
   239         }
   240     }
   241 
   242     if (!SDLTest_CommonInit(state)) {
   243         return 2;
   244     }
   245 
   246 
   247 #ifdef HAVE_SDL_TTF
   248     /* Initialize fonts */
   249     TTF_Init();
   250 
   251     font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
   252     if (! font)
   253     {
   254         fprintf(stderr, "Failed to find font: %s\n", TTF_GetError());
   255         exit(-1);
   256     }
   257 #endif
   258 
   259     printf("Using font: %s\n", fontname);
   260     atexit(SDL_Quit);
   261 
   262     InitInput();
   263     /* Create the windows and initialize the renderers */
   264     for (i = 0; i < state->num_windows; ++i) {
   265         SDL_Renderer *renderer = state->renderers[i];
   266         SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
   267         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   268         SDL_RenderClear(renderer);
   269     }
   270     Redraw();
   271     /* Main render loop */
   272     done = 0;
   273     while (!done) {
   274         /* Check for events */
   275         while (SDL_PollEvent(&event)) {
   276             SDLTest_CommonEvent(state, &event, &done);
   277             switch(event.type) {
   278                 case SDL_KEYDOWN: {
   279                     switch (event.key.keysym.sym)
   280                     {
   281                         case SDLK_RETURN:
   282                              text[0]=0x00;
   283                              Redraw();
   284                              break;
   285                         case SDLK_BACKSPACE:
   286                              {
   287                                  int textlen=SDL_strlen(text);
   288 
   289                                  do {
   290                                      if (textlen==0)
   291                                      {
   292                                          break;
   293                                      }
   294                                      if ((text[textlen-1] & 0x80) == 0x00)
   295                                      {
   296                                          /* One byte */
   297                                          text[textlen-1]=0x00;
   298                                          break;
   299                                      }
   300                                      if ((text[textlen-1] & 0xC0) == 0x80)
   301                                      {
   302                                          /* Byte from the multibyte sequence */
   303                                          text[textlen-1]=0x00;
   304                                          textlen--;
   305                                      }
   306                                      if ((text[textlen-1] & 0xC0) == 0xC0)
   307                                      {
   308                                          /* First byte of multibyte sequence */
   309                                          text[textlen-1]=0x00;
   310                                          break;
   311                                      }
   312                                  } while(1);
   313 
   314                                  Redraw();
   315                              }
   316                              break;
   317                     }
   318 
   319                     if (done)
   320                     {
   321                         break;
   322                     }
   323 
   324                     fprintf(stderr,
   325                             "Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
   326                             event.key.keysym.scancode,
   327                             SDL_GetScancodeName(event.key.keysym.scancode),
   328                             event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
   329                     break;
   330 
   331                 case SDL_TEXTINPUT:
   332                     if (SDL_strlen(event.text.text) == 0 || event.text.text[0] == '\n' ||
   333                         markedRect.w < 0)
   334                         break;
   335 
   336                     fprintf(stderr, "Keyboard: text input \"%s\"\n", event.text.text);
   337 
   338                     if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
   339                         SDL_strlcat(text, event.text.text, sizeof(text));
   340 
   341                     fprintf(stderr, "text inputed: %s\n", text);
   342 
   343                     // After text inputed, we can clear up markedText because it
   344                     // is committed
   345                     markedText[0] = 0;
   346                     Redraw();
   347                     break;
   348 
   349                 case SDL_TEXTEDITING:
   350                     fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n",
   351                             event.edit.text, event.edit.start, event.edit.length);
   352 
   353                     strcpy(markedText, event.edit.text);
   354                     cursor = event.edit.start;
   355                     Redraw();
   356                     break;
   357                 }
   358                 break;
   359 
   360             }
   361         }
   362     }
   363     CleanupVideo();
   364     SDLTest_CommonQuit(state);
   365     return 0;
   366 }
   367 
   368 
   369 /* vi: set ts=4 sw=4 expandtab: */