test/testime.c
author Sam Lantinga <slouken@libsdl.org>
Fri, 28 Nov 2014 04:51:33 -0800
changeset 9246 a761913e5e91
parent 8149 681eb46b8ac4
child 9619 b94b6d0bff0f
permissions -rw-r--r--
Fixed bug 2786 - "UCS-2-INTERNAL" iconv encoding is not supported everywhere, use UTF-16LE instead

Jonas Kulla

src/main/windows/SDL_windows_main.c:137:
cmdline = SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)(text), (SDL_wcslen(text)+1)*sizeof(WCHAR));

I'm trying to compile an SDL2 application for windows using the mingw-w64 32bit toolchain provided by my distro (Fedora 19). However, even the simplest test program that does nothing at all fails to startup with a "Fatal error - out of memory" message because the mingw iconv library provided by my distro does not support the "UCS-2-INTERNAL" encoding and the conversion returns null.

From my little bit of research, it turns out that even though this encoding is supported by the external GNU libiconv library, some glibc versions (?) don't support it with their internal iconv routines, and will instead provide the native endian encoding when "UCS-2" is specified.

Nonetheless, I wonder why the native endianness is considered in the first place when Windows doesn't even run on any big endian archs (to my knowledge). And true enough, 'WIN_StringToUTF8' from core/windows/SDL_windows.h is used everywhere else in the windows backend, which is just a macro to iconv with "UTF-16LE" as source. Therefore it would IMO make sense to use this macro here as well, which would solve my problem (patch attached).
slouken@5535
     1
/*
slouken@8149
     2
  Copyright (C) 1997-2014 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@6251
    12
/* A simple program to test the Input Method support in the SDL library (2.0+) */
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@6785
    23
#include "SDL_test_common.h"
dimitris@6318
    24
slouken@3280
    25
#define DEFAULT_PTSIZE  30
slouken@5150
    26
#define DEFAULT_FONT    "/System/Library/Fonts/华文细黑.ttf"
slouken@3280
    27
#define MAX_TEXT_LENGTH 256
slouken@3280
    28
slouken@6785
    29
static SDLTest_CommonState *state;
dimitris@6318
    30
static SDL_Rect textRect, markedRect;
dimitris@6318
    31
static SDL_Color lineColor = {0,0,0,0};
dimitris@6318
    32
static SDL_Color backColor = {255,255,255,0};
dimitris@6318
    33
static SDL_Color textColor = {0,0,0,0};
dimitris@6318
    34
static char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
dimitris@6318
    35
static int cursor = 0;
slouken@3280
    36
#ifdef HAVE_SDL_TTF
dimitris@6318
    37
static TTF_Font *font;
slouken@3280
    38
#endif
dewyatt@4757
    39
slouken@5150
    40
size_t utf8_length(unsigned char c)
slouken@5150
    41
{
slouken@5150
    42
    c = (unsigned char)(0xff & c);
slouken@5150
    43
    if (c < 0x80)
slouken@5150
    44
        return 1;
slouken@5150
    45
    else if ((c >> 5) ==0x6)
slouken@5150
    46
        return 2;
slouken@5150
    47
    else if ((c >> 4) == 0xe)
slouken@5150
    48
        return 3;
slouken@5150
    49
    else if ((c >> 3) == 0x1e)
slouken@5150
    50
        return 4;
slouken@5150
    51
    else
slouken@5150
    52
        return 0;
slouken@5150
    53
}
slouken@5150
    54
slouken@5150
    55
char *utf8_next(char *p)
slouken@5150
    56
{
slouken@5150
    57
    size_t len = utf8_length(*p);
slouken@5150
    58
    size_t i = 0;
slouken@5150
    59
    if (!len)
slouken@5150
    60
        return 0;
slouken@5150
    61
slouken@5150
    62
    for (; i < len; ++i)
slouken@5150
    63
    {
slouken@5150
    64
        ++p;
slouken@5150
    65
        if (!*p)
slouken@5150
    66
            return 0;
slouken@5150
    67
    }
slouken@5150
    68
    return p;
slouken@5150
    69
}
dewyatt@4757
    70
dewyatt@4757
    71
char *utf8_advance(char *p, size_t distance)
dewyatt@4757
    72
{
dewyatt@4757
    73
    size_t i = 0;
dewyatt@4757
    74
    for (; i < distance && p; ++i)
dewyatt@4757
    75
    {
dewyatt@4757
    76
        p = utf8_next(p);
dewyatt@4757
    77
    }
dewyatt@4757
    78
    return p;
dewyatt@4757
    79
}
slouken@3280
    80
slouken@3280
    81
void usage()
slouken@3280
    82
{
aschiffler@7639
    83
    SDL_Log("usage: testime [--font fontfile]\n");
slouken@3280
    84
    exit(0);
slouken@3280
    85
}
slouken@3280
    86
dimitris@6318
    87
void InitInput()
slouken@3280
    88
{
dimitris@6318
    89
dimitris@6318
    90
    /* Prepare a rect for text input */
dimitris@6318
    91
    textRect.x = textRect.y = 100;
dimitris@6318
    92
    textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
dimitris@6318
    93
    textRect.h = 50;
dimitris@6318
    94
dimitris@6318
    95
    text[0] = 0;
dimitris@6318
    96
    markedRect = textRect;
dimitris@6318
    97
    markedText[0] = 0;
dimitris@6318
    98
dimitris@6318
    99
    SDL_StartTextInput();
dimitris@6318
   100
}
dimitris@6318
   101
dimitris@6318
   102
void CleanupVideo()
dimitris@6318
   103
{
dimitris@6318
   104
    SDL_StopTextInput();
dimitris@6318
   105
#ifdef HAVE_SDL_TTF
dimitris@6318
   106
    TTF_CloseFont(font);
dimitris@6318
   107
    TTF_Quit();
dimitris@6318
   108
#endif
dimitris@6318
   109
}
dimitris@6318
   110
dimitris@6318
   111
dimitris@6318
   112
void _Redraw(SDL_Renderer * renderer) {
dimitris@6318
   113
    int w = 0, h = textRect.h;
dimitris@6318
   114
    SDL_Rect cursorRect, underlineRect;
dimitris@6318
   115
dimitris@6318
   116
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
dimitris@6318
   117
    SDL_RenderFillRect(renderer,&textRect);
dimitris@6318
   118
dimitris@6318
   119
#ifdef HAVE_SDL_TTF
dimitris@6318
   120
    if (*text)
dimitris@6318
   121
    {
dimitris@6318
   122
        SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
dimitris@6318
   123
        SDL_Rect dest = {textRect.x, textRect.y, textSur->w, textSur->h };
dimitris@6318
   124
dimitris@6318
   125
        SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
dimitris@6318
   126
        SDL_FreeSurface(textSur);
dimitris@6318
   127
dimitris@6318
   128
        SDL_RenderCopy(renderer,texture,NULL,&dest);
dimitris@6318
   129
        SDL_DestroyTexture(texture);
dimitris@6318
   130
        TTF_SizeUTF8(font, text, &w, &h);
dimitris@6318
   131
    }
dimitris@6318
   132
#endif
dimitris@6318
   133
dimitris@6318
   134
    markedRect.x = textRect.x + w;
dimitris@6318
   135
    markedRect.w = textRect.w - w;
dimitris@6318
   136
    if (markedRect.w < 0)
dimitris@6318
   137
    {
gabomdq@7663
   138
        /* Stop text input because we cannot hold any more characters */
dimitris@6318
   139
        SDL_StopTextInput();
dimitris@6318
   140
        return;
dimitris@6318
   141
    }
dimitris@6318
   142
    else
dimitris@6318
   143
    {
dimitris@6318
   144
        SDL_StartTextInput();
dimitris@6318
   145
    }
dimitris@6318
   146
dimitris@6318
   147
    cursorRect = markedRect;
dimitris@6318
   148
    cursorRect.w = 2;
dimitris@6318
   149
    cursorRect.h = h;
dimitris@6318
   150
dimitris@6318
   151
    SDL_SetRenderDrawColor(renderer, 255,255,255,255);
dimitris@6318
   152
    SDL_RenderFillRect(renderer,&markedRect);
dimitris@6318
   153
dimitris@6318
   154
    if (markedText[0])
dimitris@6318
   155
    {
dimitris@6318
   156
#ifdef HAVE_SDL_TTF
dimitris@6318
   157
        if (cursor)
dimitris@6318
   158
        {
dimitris@6318
   159
            char *p = utf8_advance(markedText, cursor);
dimitris@6318
   160
            char c = 0;
dimitris@6318
   161
            if (!p)
dimitris@6318
   162
                p = &markedText[strlen(markedText)];
dimitris@6318
   163
dimitris@6318
   164
            c = *p;
dimitris@6318
   165
            *p = 0;
dimitris@6318
   166
            TTF_SizeUTF8(font, markedText, &w, 0);
dimitris@6318
   167
            cursorRect.x += w;
dimitris@6318
   168
            *p = c;
dimitris@6318
   169
        }
dimitris@6318
   170
        SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
dimitris@6318
   171
        SDL_Rect dest = {markedRect.x, markedRect.y, textSur->w, textSur->h };
dimitris@6318
   172
        TTF_SizeUTF8(font, markedText, &w, &h);
dimitris@6318
   173
        SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
dimitris@6318
   174
        SDL_FreeSurface(textSur);
dimitris@6318
   175
dimitris@6318
   176
        SDL_RenderCopy(renderer,texture,NULL,&dest);
dimitris@6318
   177
        SDL_DestroyTexture(texture);
dimitris@6318
   178
#endif
dimitris@6318
   179
dimitris@6318
   180
        underlineRect = markedRect;
dimitris@6318
   181
        underlineRect.y += (h - 2);
dimitris@6318
   182
        underlineRect.h = 2;
dimitris@6318
   183
        underlineRect.w = w;
dimitris@6318
   184
dimitris@6318
   185
        SDL_SetRenderDrawColor(renderer, 0,0,0,0);
dimitris@6318
   186
        SDL_RenderFillRect(renderer,&markedRect);
dimitris@6318
   187
    }
dimitris@6318
   188
dimitris@6318
   189
    SDL_SetRenderDrawColor(renderer, 0,0,0,0);
dimitris@6318
   190
    SDL_RenderFillRect(renderer,&cursorRect);
dimitris@6318
   191
dimitris@6318
   192
    SDL_SetTextInputRect(&markedRect);
dimitris@6318
   193
}
dimitris@6318
   194
dimitris@6318
   195
void Redraw() {
dimitris@6318
   196
    int i;
dimitris@6318
   197
    for (i = 0; i < state->num_windows; ++i) {
dimitris@6318
   198
        SDL_Renderer *renderer = state->renderers[i];
slouken@7787
   199
        if (state->windows[i] == NULL)
slouken@7787
   200
            continue;
dimitris@6318
   201
        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
dimitris@6318
   202
        SDL_RenderClear(renderer);
dimitris@6318
   203
dimitris@6318
   204
        _Redraw(renderer);
dimitris@6318
   205
dimitris@6318
   206
        SDL_RenderPresent(renderer);
dimitris@6318
   207
    }
dimitris@6318
   208
}
dimitris@6318
   209
dimitris@6318
   210
int main(int argc, char *argv[]) {
dimitris@6318
   211
    int i, done;
dimitris@6318
   212
    SDL_Event event;
slouken@3280
   213
    const char *fontname = DEFAULT_FONT;
slouken@3280
   214
aschiffler@7639
   215
    /* Enable standard application logging */
aschiffler@7639
   216
    SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
aschiffler@7639
   217
dimitris@6318
   218
    /* Initialize test framework */
slouken@6785
   219
    state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
dimitris@6318
   220
    if (!state) {
dimitris@6318
   221
        return 1;
dimitris@6318
   222
    }
dimitris@6318
   223
    for (i = 1; i < argc;i++) {
slouken@6785
   224
        SDLTest_CommonArg(state, i);
dimitris@6318
   225
    }
slouken@3280
   226
    for (argc--, argv++; argc > 0; argc--, argv++)
slouken@3280
   227
    {
dimitris@6318
   228
        if (strcmp(argv[0], "--help") == 0) {
slouken@3280
   229
            usage();
dimitris@6318
   230
            return 0;
dimitris@6318
   231
        }
slouken@3280
   232
slouken@3280
   233
        else if (strcmp(argv[0], "--font") == 0)
slouken@3280
   234
        {
slouken@3280
   235
            argc--;
slouken@3280
   236
            argv++;
slouken@3280
   237
slouken@3280
   238
            if (argc > 0)
slouken@3280
   239
                fontname = argv[0];
dimitris@6318
   240
            else {
slouken@3280
   241
                usage();
dimitris@6318
   242
                return 0;
dimitris@6318
   243
            }
slouken@3280
   244
        }
slouken@3280
   245
    }
slouken@7191
   246
slouken@6785
   247
    if (!SDLTest_CommonInit(state)) {
dimitris@6318
   248
        return 2;
dimitris@6318
   249
    }
slouken@3280
   250
slouken@3280
   251
slouken@3280
   252
#ifdef HAVE_SDL_TTF
slouken@3280
   253
    /* Initialize fonts */
slouken@3280
   254
    TTF_Init();
slouken@3280
   255
slouken@3280
   256
    font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
slouken@3280
   257
    if (! font)
slouken@3280
   258
    {
aschiffler@7639
   259
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
slouken@3280
   260
        exit(-1);
slouken@3280
   261
    }
slouken@3280
   262
#endif
slouken@3280
   263
aschiffler@7639
   264
    SDL_Log("Using font: %s\n", fontname);
slouken@3280
   265
    atexit(SDL_Quit);
slouken@3280
   266
dimitris@6318
   267
    InitInput();
dimitris@6318
   268
    /* Create the windows and initialize the renderers */
dimitris@6318
   269
    for (i = 0; i < state->num_windows; ++i) {
dimitris@6318
   270
        SDL_Renderer *renderer = state->renderers[i];
dimitris@6318
   271
        SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
dimitris@6318
   272
        SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
dimitris@6318
   273
        SDL_RenderClear(renderer);
slouken@3280
   274
    }
slouken@7191
   275
    Redraw();
dimitris@6318
   276
    /* Main render loop */
dimitris@6318
   277
    done = 0;
dimitris@6318
   278
    while (!done) {
dimitris@6318
   279
        /* Check for events */
dimitris@6318
   280
        while (SDL_PollEvent(&event)) {
slouken@6785
   281
            SDLTest_CommonEvent(state, &event, &done);
dimitris@6318
   282
            switch(event.type) {
dimitris@6318
   283
                case SDL_KEYDOWN: {
dimitris@6318
   284
                    switch (event.key.keysym.sym)
dimitris@6318
   285
                    {
dimitris@6318
   286
                        case SDLK_RETURN:
dimitris@6318
   287
                             text[0]=0x00;
dimitris@6318
   288
                             Redraw();
dimitris@6318
   289
                             break;
dimitris@6318
   290
                        case SDLK_BACKSPACE:
dimitris@6318
   291
                             {
dimitris@6318
   292
                                 int textlen=SDL_strlen(text);
slouken@3280
   293
dimitris@6318
   294
                                 do {
dimitris@6318
   295
                                     if (textlen==0)
dimitris@6318
   296
                                     {
dimitris@6318
   297
                                         break;
dimitris@6318
   298
                                     }
dimitris@6318
   299
                                     if ((text[textlen-1] & 0x80) == 0x00)
dimitris@6318
   300
                                     {
dimitris@6318
   301
                                         /* One byte */
dimitris@6318
   302
                                         text[textlen-1]=0x00;
dimitris@6318
   303
                                         break;
dimitris@6318
   304
                                     }
dimitris@6318
   305
                                     if ((text[textlen-1] & 0xC0) == 0x80)
dimitris@6318
   306
                                     {
dimitris@6318
   307
                                         /* Byte from the multibyte sequence */
dimitris@6318
   308
                                         text[textlen-1]=0x00;
dimitris@6318
   309
                                         textlen--;
dimitris@6318
   310
                                     }
dimitris@6318
   311
                                     if ((text[textlen-1] & 0xC0) == 0xC0)
dimitris@6318
   312
                                     {
dimitris@6318
   313
                                         /* First byte of multibyte sequence */
dimitris@6318
   314
                                         text[textlen-1]=0x00;
dimitris@6318
   315
                                         break;
dimitris@6318
   316
                                     }
dimitris@6318
   317
                                 } while(1);
dimitris@6318
   318
dimitris@6318
   319
                                 Redraw();
dimitris@6318
   320
                             }
dimitris@6318
   321
                             break;
dimitris@6318
   322
                    }
dimitris@6318
   323
dimitris@6318
   324
                    if (done)
dimitris@6318
   325
                    {
dimitris@6318
   326
                        break;
dimitris@6318
   327
                    }
dimitris@6318
   328
aschiffler@7639
   329
                    SDL_Log("Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
dimitris@6318
   330
                            event.key.keysym.scancode,
dimitris@6318
   331
                            SDL_GetScancodeName(event.key.keysym.scancode),
dimitris@6318
   332
                            event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
dimitris@6318
   333
                    break;
dimitris@6318
   334
dimitris@6318
   335
                case SDL_TEXTINPUT:
slouken@7721
   336
                    if (event.text.text[0] == '\0' || event.text.text[0] == '\n' ||
dimitris@6318
   337
                        markedRect.w < 0)
dimitris@6318
   338
                        break;
dimitris@6318
   339
aschiffler@7639
   340
                    SDL_Log("Keyboard: text input \"%s\"\n", event.text.text);
dimitris@6318
   341
dimitris@6318
   342
                    if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
dimitris@6318
   343
                        SDL_strlcat(text, event.text.text, sizeof(text));
dimitris@6318
   344
aschiffler@7639
   345
                    SDL_Log("text inputed: %s\n", text);
dimitris@6318
   346
gabomdq@7663
   347
                    /* After text inputed, we can clear up markedText because it */
gabomdq@7677
   348
                    /* is committed */
dimitris@6318
   349
                    markedText[0] = 0;
dimitris@6318
   350
                    Redraw();
dimitris@6318
   351
                    break;
dimitris@6318
   352
dimitris@6318
   353
                case SDL_TEXTEDITING:
aschiffler@7639
   354
                    SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
dimitris@6318
   355
                            event.edit.text, event.edit.start, event.edit.length);
dimitris@6318
   356
dimitris@6318
   357
                    strcpy(markedText, event.edit.text);
dimitris@6318
   358
                    cursor = event.edit.start;
dimitris@6318
   359
                    Redraw();
dimitris@6318
   360
                    break;
dimitris@6318
   361
                }
dimitris@6318
   362
                break;
slouken@7191
   363
dimitris@6318
   364
            }
dimitris@6318
   365
        }
slouken@3280
   366
    }
dimitris@6318
   367
    CleanupVideo();
slouken@6785
   368
    SDLTest_CommonQuit(state);
dimitris@6318
   369
    return 0;
slouken@3280
   370
}
slouken@3280
   371
slouken@5244
   372
slouken@5244
   373
/* vi: set ts=4 sw=4 expandtab: */