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