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