test/testime.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 22 Aug 2010 12:39:27 -0700
changeset 4763 518d1679d2d0
parent 4638 08d22c54a21f
parent 4757 140be6839185
child 5150 1435f8a6425c
permissions -rw-r--r--
Merged Daniel's Google Summer of Code work from SDL-gsoc2010_IME
     1 /* A simple program to test the Input Method support in the SDL library (1.3+) */
     2 
     3 #include <stdlib.h>
     4 #include <stdio.h>
     5 #include <string.h>
     6 
     7 #include "SDL.h"
     8 #ifdef HAVE_SDL_TTF
     9 #include "SDL_ttf.h"
    10 #endif
    11 
    12 #define DEFAULT_PTSIZE  30
    13 #ifdef __QNXNTO__
    14     #define DEFAULT_FONT    "/usr/photon/font_repository/tt0003m_.ttf"
    15 #else
    16     #define DEFAULT_FONT    "/System/Library/Fonts/华文细黑.ttf"
    17 #endif
    18 #define MAX_TEXT_LENGTH 256
    19 
    20 SDL_Surface *screen;
    21 
    22 #ifdef HAVE_SDL_TTF
    23 TTF_Font *font;
    24 #endif
    25 SDL_Rect textRect, markedRect;
    26 Uint32 lineColor, backColor;
    27 SDL_Color textColor = { 0, 0, 0 };
    28 char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
    29 int cursor = 0;
    30 
    31 size_t utf8_length(unsigned char c)
    32 {
    33     c = (unsigned char)(0xff & c);
    34     if (c < 0x80)
    35         return 1;
    36     else if ((c >> 5) ==0x6)
    37         return 2;
    38     else if ((c >> 4) == 0xe)
    39         return 3;
    40     else if ((c >> 3) == 0x1e)
    41         return 4;
    42     else
    43         return 0;
    44 }
    45 
    46 char *utf8_next(char *p)
    47 {
    48     size_t len = utf8_length(*p);
    49     size_t i = 0;
    50     if (!len)
    51         return 0;
    52 
    53     for (; i < len; ++i)
    54     {
    55         ++p;
    56         if (!*p)
    57             return 0;
    58     }
    59     return p;
    60 }
    61 
    62 char *utf8_advance(char *p, size_t distance)
    63 {
    64     size_t i = 0;
    65     for (; i < distance && p; ++i)
    66     {
    67         p = utf8_next(p);
    68     }
    69     return p;
    70 }
    71 
    72 void usage()
    73 {
    74     printf("usage: testime [--font fontfile] [--fullscreen]\n");
    75     exit(0);
    76 }
    77 
    78 void InitVideo(int argc, char *argv[])
    79 {
    80     int width = 640, height = 480;
    81     int flags = SDL_HWSURFACE;
    82     const char *fontname = DEFAULT_FONT;
    83     int fullscreen = 0;
    84 
    85     for (argc--, argv++; argc > 0; argc--, argv++)
    86     {
    87         if (strcmp(argv[0], "--help") == 0)
    88             usage();
    89 
    90         else if (strcmp(argv[0], "--fullscreen") == 0)
    91             fullscreen = 1;
    92 
    93         else if (strcmp(argv[0], "--font") == 0)
    94         {
    95             argc--;
    96             argv++;
    97 
    98             if (argc > 0)
    99                 fontname = argv[0];
   100             else
   101                 usage();
   102         }
   103     }
   104 
   105     SDL_setenv("SDL_VIDEO_WINDOW_POS", "center", 1);
   106     if (SDL_Init(SDL_INIT_VIDEO) < 0)
   107     {
   108         fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError());
   109         exit(-1);
   110     }
   111 
   112 #ifdef HAVE_SDL_TTF
   113     /* Initialize fonts */
   114     TTF_Init();
   115 
   116     font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
   117     if (! font)
   118     {
   119         fprintf(stderr, "Failed to find font: %s\n", TTF_GetError());
   120         exit(-1);
   121     }
   122 #endif
   123 
   124     printf("Using font: %s\n", fontname);
   125     atexit(SDL_Quit);
   126 
   127     if (fullscreen)
   128     {
   129         SDL_DisplayMode mode;
   130         SDL_GetDesktopDisplayMode(&mode);
   131 
   132         width = mode.w;
   133         height = mode.h;
   134         fprintf(stderr, "%dx%d\n", width, height);
   135         flags |= SDL_FULLSCREEN;
   136     }
   137 
   138     /* Create window */
   139     screen = SDL_SetVideoMode(width, height, 32, flags);
   140     if (screen == NULL)
   141     {
   142         fprintf(stderr, "Unable to set %dx%d video: %s\n",
   143                 width, height, SDL_GetError());
   144         exit(-1);
   145     }
   146 }
   147 
   148 void CleanupVideo()
   149 {
   150     SDL_StopTextInput();
   151 #ifdef HAVE_SDL_TTF
   152     TTF_CloseFont(font);
   153     TTF_Quit();
   154 #endif
   155 }
   156 
   157 void InitInput()
   158 {
   159     backColor = SDL_MapRGB(screen->format, 0xFF, 0xFF, 0xFF);
   160     lineColor = SDL_MapRGB(screen->format, 0x0, 0x0, 0x0);
   161 
   162     /* Prepare a rect for text input */
   163     textRect.x = textRect.y = 100;
   164     textRect.w = screen->w - 2 * textRect.x;
   165     textRect.h = 50;
   166 
   167     text[0] = 0;
   168     markedRect = textRect;
   169     markedText[0] = 0;
   170 
   171     SDL_StartTextInput();
   172 }
   173 
   174 #ifdef HAVE_SDL_TTF
   175 static void RenderText(SDL_Surface *sur,
   176                         TTF_Font *font,
   177                         const char *text,
   178                         int x, int y,
   179                         SDL_Color color)
   180 {
   181     if (text && *text) {
   182         SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, color);
   183         SDL_Rect dest = { x, y, textSur->w, textSur->h };
   184 
   185         SDL_BlitSurface(textSur, NULL, sur, &dest);
   186         SDL_FreeSurface(textSur);
   187     }
   188 }
   189 #endif
   190 
   191 void Redraw()
   192 {
   193     int w = 0, h = textRect.h;
   194     SDL_Rect cursorRect, underlineRect;
   195 
   196     SDL_FillRect(screen, &textRect, backColor);
   197 
   198 #ifdef HAVE_SDL_TTF
   199     if (*text)
   200     {
   201         RenderText(screen, font, text, textRect.x, textRect.y, textColor);
   202         TTF_SizeUTF8(font, text, &w, &h);
   203     }
   204 #endif
   205 
   206     markedRect.x = textRect.x + w;
   207     markedRect.w = textRect.w - w;
   208     if (markedRect.w < 0)
   209     {
   210         SDL_Flip(screen);
   211         // Stop text input because we cannot hold any more characters
   212         SDL_StopTextInput();
   213         return;
   214     }
   215     else
   216     {
   217         SDL_StartTextInput();
   218     }
   219 
   220     cursorRect = markedRect;
   221     cursorRect.w = 2;
   222     cursorRect.h = h;
   223 
   224     SDL_FillRect(screen, &markedRect, backColor);
   225     if (markedText[0])
   226     {
   227 #ifdef HAVE_SDL_TTF
   228         if (cursor)
   229         {
   230             char *p = utf8_advance(markedText, cursor);
   231             char c = 0;
   232             if (!p)
   233                 p = &markedText[strlen(markedText)];
   234 
   235             c = *p;
   236             *p = 0;
   237             TTF_SizeUTF8(font, markedText, &w, 0);
   238             cursorRect.x += w;
   239             *p = c;
   240         }
   241         RenderText(screen, font, markedText, markedRect.x, markedRect.y, textColor);
   242         TTF_SizeUTF8(font, markedText, &w, &h);
   243 #endif
   244 
   245         underlineRect = markedRect;
   246         underlineRect.y += (h - 2);
   247         underlineRect.h = 2;
   248         underlineRect.w = w;
   249 
   250         SDL_FillRect(screen, &underlineRect, lineColor);
   251     }
   252 
   253     SDL_FillRect(screen, &cursorRect, lineColor);
   254 
   255     SDL_Flip(screen);
   256 
   257     SDL_SetTextInputRect(&markedRect);
   258 }
   259 
   260 void
   261 HotKey_ToggleFullScreen(void)
   262 {
   263     SDL_Surface *screen;
   264 
   265     screen = SDL_GetVideoSurface();
   266     if (SDL_WM_ToggleFullScreen(screen)) {
   267         printf("Toggled fullscreen mode - now %s\n",
   268                (screen->flags & SDL_FULLSCREEN) ? "fullscreen" : "windowed");
   269     } else {
   270         printf("Unable to toggle fullscreen mode\n");
   271     }
   272 }
   273 
   274 int main(int argc, char *argv[])
   275 {
   276     SDL_Event event;
   277     int done = 0;
   278 
   279     InitVideo(argc, argv);
   280     InitInput();
   281     Redraw();
   282 
   283     while (! done && SDL_WaitEvent(&event))
   284     {
   285         switch (event.type)
   286         {
   287         case SDL_KEYDOWN:
   288             switch (event.key.keysym.sym)
   289             {
   290                 case SDLK_ESCAPE:
   291                      done = 1;
   292                      break;
   293                 case SDLK_RETURN:
   294                      text[0]=0x00;
   295                      Redraw();
   296                      break;
   297                 case SDLK_BACKSPACE:
   298                      {
   299                          int textlen=SDL_strlen(text);
   300 
   301                          do {
   302                              if (textlen==0)
   303                              {
   304                                  break;
   305                              }
   306                              if ((text[textlen-1] & 0x80) == 0x00)
   307                              {
   308                                  /* One byte */
   309                                  text[textlen-1]=0x00;
   310                                  break;
   311                              }
   312                              if ((text[textlen-1] & 0xC0) == 0x80)
   313                              {
   314                                  /* Byte from the multibyte sequence */
   315                                  text[textlen-1]=0x00;
   316                                  textlen--;
   317                              }
   318                              if ((text[textlen-1] & 0xC0) == 0xC0)
   319                              {
   320                                  /* First byte of multibyte sequence */
   321                                  text[textlen-1]=0x00;
   322                                  break;
   323                              }
   324                          } while(1);
   325 
   326                          Redraw();
   327                      }
   328                      break;
   329             }
   330 
   331             if (done)
   332             {
   333                 break;
   334             }
   335 
   336             fprintf(stderr,
   337                     "Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
   338                     event.key.keysym.scancode,
   339                     SDL_GetScancodeName(event.key.keysym.scancode),
   340                     event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
   341             break;
   342 
   343         case SDL_TEXTINPUT:
   344             if (SDL_strlen(event.text.text) == 0 || event.text.text[0] == '\n' ||
   345                 markedRect.w < 0)
   346                 break;
   347 
   348             fprintf(stderr, "Keyboard: text input \"%s\"\n", event.text.text);
   349 
   350             if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
   351                 SDL_strlcat(text, event.text.text, sizeof(text));
   352 
   353             fprintf(stderr, "text inputed: %s\n", text);
   354 
   355             // After text inputed, we can clear up markedText because it
   356             // is committed
   357             markedText[0] = 0;
   358             Redraw();
   359             break;
   360 
   361         case SDL_TEXTEDITING:
   362             fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n",
   363                     event.edit.text, event.edit.start, event.edit.length);
   364 
   365             strcpy(markedText, event.edit.text);
   366             cursor = event.edit.start;
   367             Redraw();
   368             break;
   369 
   370         case SDL_QUIT:
   371             done = 1;
   372             break;
   373 
   374         default:
   375             break;
   376         }
   377     }
   378 
   379     CleanupVideo();
   380     return 0;
   381 }