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