test/testime.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 09 Oct 2016 20:31:32 +0200
changeset 10503 6f9f7acc9d1e
parent 10416 d6e839e8b339
child 10737 3406a0f8b041
permissions -rw-r--r--
Fixed compiling of three test programs with C++.
     1 /*
     2   Copyright (C) 1997-2016 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    If you build without SDL_ttf, you can use the GNU Unifont hex file instead.
    14    Download at http://unifoundry.com/unifont.html */
    15 
    16 #include <stdlib.h>
    17 #include <stdio.h>
    18 #include <string.h>
    19 
    20 #include "SDL.h"
    21 #ifdef HAVE_SDL_TTF
    22 #include "SDL_ttf.h"
    23 #endif
    24 
    25 #include "SDL_test_common.h"
    26 
    27 #define DEFAULT_PTSIZE 30
    28 #ifdef HAVE_SDL_TTF
    29 #ifdef __MACOSX__
    30 #define DEFAULT_FONT "/System/Library/Fonts/华文细黑.ttf"
    31 #elif __WIN32__
    32 /* Some japanese font present on at least Windows 8.1. */
    33 #define DEFAULT_FONT "C:\\Windows\\Fonts\\yugothic.ttf"
    34 #else
    35 #define DEFAULT_FONT "NoDefaultFont.ttf"
    36 #endif
    37 #else
    38 #define DEFAULT_FONT "unifont-9.0.02.hex"
    39 #endif
    40 #define MAX_TEXT_LENGTH 256
    41 
    42 static SDLTest_CommonState *state;
    43 static SDL_Rect textRect, markedRect;
    44 static SDL_Color lineColor = {0,0,0,255};
    45 static SDL_Color backColor = {255,255,255,255};
    46 static SDL_Color textColor = {0,0,0,255};
    47 static char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
    48 static int cursor = 0;
    49 #ifdef HAVE_SDL_TTF
    50 static TTF_Font *font;
    51 #else
    52 #define UNIFONT_MAX_CODEPOINT 0x1ffff
    53 #define UNIFONT_NUM_GLYPHS 0x20000
    54 /* Using 512x512 textures that are supported everywhere. */
    55 #define UNIFONT_TEXTURE_WIDTH 512
    56 #define UNIFONT_GLYPHS_IN_ROW (UNIFONT_TEXTURE_WIDTH / 16)
    57 #define UNIFONT_GLYPHS_IN_TEXTURE (UNIFONT_GLYPHS_IN_ROW * UNIFONT_GLYPHS_IN_ROW)
    58 #define UNIFONT_NUM_TEXTURES ((UNIFONT_NUM_GLYPHS + UNIFONT_GLYPHS_IN_TEXTURE - 1) / UNIFONT_GLYPHS_IN_TEXTURE)
    59 #define UNIFONT_TEXTURE_SIZE (UNIFONT_TEXTURE_WIDTH * UNIFONT_TEXTURE_WIDTH * 4)
    60 #define UNIFONT_TEXTURE_PITCH (UNIFONT_TEXTURE_WIDTH * 4)
    61 #define UNIFONT_DRAW_SCALE 2
    62 struct UnifontGlyph {
    63     Uint8 width;
    64     Uint8 data[32];
    65 } *unifontGlyph;
    66 static SDL_Texture **unifontTexture;
    67 static Uint8 unifontTextureLoaded[UNIFONT_NUM_TEXTURES] = {0};
    68 
    69 /* Unifont loading code start */
    70 
    71 static Uint8 dehex(char c)
    72 {
    73     if (c >= '0' && c <= '9')
    74         return c - '0';
    75     else if (c >= 'a' && c <= 'f')
    76         return c - 'a' + 10;
    77     else if (c >= 'A' && c <= 'F')
    78         return c - 'A' + 10;
    79     return 255;
    80 }
    81 
    82 static Uint8 dehex2(char c1, char c2)
    83 {
    84     return (dehex(c1) << 4) | dehex(c2);
    85 }
    86 
    87 static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np)
    88 {
    89     Uint32 n = 0;
    90     for (; len > 0; cp++, len--)
    91     {
    92         Uint8 c = dehex(*cp);
    93         if (c == 255)
    94             return 0;
    95         n = (n << 4) | c;
    96     }
    97     if (np != NULL)
    98         *np = n;
    99     return 1;
   100 }
   101 
   102 static void unifont_init(const char *fontname)
   103 {
   104     Uint8 hexBuffer[65];
   105     Uint32 numGlyphs = 0;
   106     int lineNumber = 1;
   107     size_t bytesRead;
   108     SDL_RWops *hexFile;
   109     const size_t unifontGlyphSize = UNIFONT_NUM_GLYPHS * sizeof(struct UnifontGlyph);
   110     const size_t unifontTextureSize = UNIFONT_NUM_TEXTURES * state->num_windows * sizeof(void *);
   111 
   112     /* Allocate memory for the glyph data so the file can be closed after initialization. */
   113     unifontGlyph = (struct UnifontGlyph *)SDL_malloc(unifontGlyphSize);
   114     if (unifontGlyph == NULL)
   115     {
   116         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for glyph data.\n", (int)(unifontGlyphSize + 1023) / 1024);
   117         exit(-1);
   118     }
   119     SDL_memset(unifontGlyph, 0, unifontGlyphSize);
   120 
   121     /* Allocate memory for texture pointers for all renderers. */
   122     unifontTexture = (SDL_Texture **)SDL_malloc(unifontTextureSize);
   123     if (unifontTexture == NULL)
   124     {
   125         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for texture pointer data.\n", (int)(unifontTextureSize + 1023) / 1024);
   126         exit(-1);
   127     }
   128     SDL_memset(unifontTexture, 0, unifontTextureSize);
   129 
   130     hexFile = SDL_RWFromFile(fontname, "rb");
   131     if (hexFile == NULL)
   132     {
   133         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname);
   134         exit(-1);
   135     }
   136 
   137     /* Read all the glyph data into memory to make it accessible later when textures are created. */
   138     do {
   139         int i, codepointHexSize;
   140         size_t bytesOverread;
   141         Uint8 glyphWidth;
   142         Uint32 codepoint;
   143 
   144         bytesRead = SDL_RWread(hexFile, hexBuffer, 1, 9);
   145         if (numGlyphs > 0 && bytesRead == 0)
   146             break; /* EOF */
   147         if ((numGlyphs == 0 && bytesRead == 0) || (numGlyphs > 0 && bytesRead < 9))
   148         {
   149             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unfiont: Unexpected end of hex file.\n");
   150             exit(-1);
   151         }
   152 
   153         /* Looking for the colon that separates the codepoint and glyph data at position 2, 4, 6 and 8. */
   154         if (hexBuffer[2] == ':')
   155             codepointHexSize = 2;
   156         else if (hexBuffer[4] == ':')
   157             codepointHexSize = 4;
   158         else if (hexBuffer[6] == ':')
   159             codepointHexSize = 6;
   160         else if (hexBuffer[8] == ':')
   161             codepointHexSize = 8;
   162         else
   163         {
   164             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Could not find codepoint and glyph data separator symbol in hex file on line %d.\n", lineNumber);
   165             exit(-1);
   166         }
   167 
   168         if (!validate_hex((const char *)hexBuffer, codepointHexSize, &codepoint))
   169         {
   170             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal number in hex file on line %d.\n", lineNumber);
   171             exit(-1);
   172         }
   173         if (codepoint > UNIFONT_MAX_CODEPOINT)
   174             SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Codepoint on line %d exceeded limit of 0x%x.\n", lineNumber, UNIFONT_MAX_CODEPOINT);
   175 
   176         /* If there was glyph data read in the last file read, move it to the front of the buffer. */
   177         bytesOverread = 8 - codepointHexSize;
   178         if (codepointHexSize < 8)
   179             SDL_memmove(hexBuffer, hexBuffer + codepointHexSize + 1, bytesOverread);
   180         bytesRead = SDL_RWread(hexFile, hexBuffer + bytesOverread, 1, 33 - bytesOverread);
   181         if (bytesRead < (33 - bytesOverread))
   182         {
   183             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
   184             exit(-1);
   185         }
   186         if (hexBuffer[32] == '\n')
   187             glyphWidth = 8;
   188         else
   189         {
   190             glyphWidth = 16;
   191             bytesRead = SDL_RWread(hexFile, hexBuffer + 33, 1, 32);
   192             if (bytesRead < 32)
   193             {
   194                 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
   195                 exit(-1);
   196             }
   197         }
   198 
   199         if (!validate_hex((const char *)hexBuffer, glyphWidth * 4, NULL))
   200         {
   201             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal glyph data in hex file on line %d.\n", lineNumber);
   202             exit(-1);
   203         }
   204 
   205         if (codepoint <= UNIFONT_MAX_CODEPOINT)
   206         {
   207             if (unifontGlyph[codepoint].width > 0)
   208                 SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Ignoring duplicate codepoint 0x%08x in hex file on line %d.\n", codepoint, lineNumber);
   209             else
   210             {
   211                 unifontGlyph[codepoint].width = glyphWidth;
   212                 /* Pack the hex data into a more compact form. */
   213                 for (i = 0; i < glyphWidth * 2; i++)
   214                     unifontGlyph[codepoint].data[i] = dehex2(hexBuffer[i * 2], hexBuffer[i * 2 + 1]);
   215                 numGlyphs++;
   216             }
   217         }
   218 
   219         lineNumber++;
   220     } while (bytesRead > 0);
   221 
   222     SDL_RWclose(hexFile);
   223     SDL_Log("unifont: Loaded %u glyphs.\n", numGlyphs);
   224 }
   225 
   226 static void unifont_make_rgba(Uint8 *src, Uint8 *dst, Uint8 width)
   227 {
   228     int i, j;
   229     Uint8 *row = dst;
   230 
   231     for (i = 0; i < width * 2; i++)
   232     {
   233         Uint8 data = src[i];
   234         for (j = 0; j < 8; j++)
   235         {
   236             if (data & 0x80)
   237             {
   238                 row[0] = textColor.r;
   239                 row[1] = textColor.g;
   240                 row[2] = textColor.b;
   241                 row[3] = textColor.a;
   242             }
   243             else
   244             {
   245                 row[0] = 0;
   246                 row[1] = 0;
   247                 row[2] = 0;
   248                 row[3] = 0;
   249             }
   250             data <<= 1;
   251             row += 4;
   252         }
   253 
   254         if (width == 8 || (width == 16 && i % 2 == 1))
   255         {
   256             dst += UNIFONT_TEXTURE_PITCH;
   257             row = dst;
   258         }
   259     }
   260 }
   261 
   262 static void unifont_load_texture(Uint32 textureID)
   263 {
   264     int i;
   265     Uint8 * textureRGBA;
   266 
   267     if (textureID >= UNIFONT_NUM_TEXTURES)
   268     {
   269         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Tried to load out of range texture %u.\n", textureID);
   270         exit(-1);
   271     }
   272 
   273     textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE);
   274     if (textureRGBA == NULL)
   275     {
   276         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024);
   277         exit(-1);
   278     }
   279     SDL_memset(textureRGBA, 0, UNIFONT_TEXTURE_SIZE);
   280 
   281     /* Copy the glyphs into memory in RGBA format. */
   282     for (i = 0; i < UNIFONT_GLYPHS_IN_TEXTURE; i++)
   283     {
   284         Uint32 codepoint = UNIFONT_GLYPHS_IN_TEXTURE * textureID + i;
   285         if (unifontGlyph[codepoint].width > 0)
   286         {
   287             const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
   288             const size_t offset = (cInTex / UNIFONT_GLYPHS_IN_ROW) * UNIFONT_TEXTURE_PITCH * 16 + (cInTex % UNIFONT_GLYPHS_IN_ROW) * 16 * 4;
   289             unifont_make_rgba(unifontGlyph[codepoint].data, textureRGBA + offset, unifontGlyph[codepoint].width);
   290         }
   291     }
   292 
   293     /* Create textures and upload the RGBA data from above. */
   294     for (i = 0; i < state->num_windows; ++i)
   295     {
   296         SDL_Renderer *renderer = state->renderers[i];
   297         SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID];
   298         if (state->windows[i] == NULL || renderer == NULL || tex != NULL)
   299             continue;
   300         tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, UNIFONT_TEXTURE_WIDTH, UNIFONT_TEXTURE_WIDTH);
   301         if (tex == NULL)
   302         {
   303             SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to create texture %u for renderer %d.\n", textureID, i);
   304             exit(-1);
   305         }
   306         unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID] = tex;
   307         SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
   308         if (SDL_UpdateTexture(tex, NULL, textureRGBA, UNIFONT_TEXTURE_PITCH) != 0)
   309         {
   310             SDL_Log("unifont error: Failed to update texture %u data for renderer %d.\n", textureID, i);
   311         }
   312     }
   313 
   314     SDL_free(textureRGBA);
   315     unifontTextureLoaded[textureID] = 1;
   316 }
   317 
   318 static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dstrect)
   319 {
   320     SDL_Texture *texture;
   321     const Uint32 textureID = codepoint / UNIFONT_GLYPHS_IN_TEXTURE;
   322     SDL_Rect srcrect;
   323     srcrect.w = srcrect.h = 16;
   324     if (codepoint > UNIFONT_MAX_CODEPOINT)
   325         return 0;
   326     if (!unifontTextureLoaded[textureID])
   327         unifont_load_texture(textureID);
   328     texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID];
   329     if (texture != NULL)
   330     {
   331         const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
   332         srcrect.x = cInTex % UNIFONT_GLYPHS_IN_ROW * 16;
   333         srcrect.y = cInTex / UNIFONT_GLYPHS_IN_ROW * 16;
   334         SDL_RenderCopy(state->renderers[rendererID], texture, &srcrect, dstrect);
   335     }
   336     return unifontGlyph[codepoint].width;
   337 }
   338 
   339 static void unifont_cleanup()
   340 {
   341     int i, j;
   342     for (i = 0; i < state->num_windows; ++i)
   343     {
   344         SDL_Renderer *renderer = state->renderers[i];
   345         if (state->windows[i] == NULL || renderer == NULL)
   346             continue;
   347         for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
   348         {
   349             SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j];
   350             if (tex != NULL)
   351                 SDL_DestroyTexture(tex);
   352         }
   353     }
   354 
   355     for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
   356           unifontTextureLoaded[j] = 0;
   357 
   358     SDL_free(unifontTexture);
   359     SDL_free(unifontGlyph);
   360 }
   361 
   362 /* Unifont code end */
   363 #endif
   364 
   365 size_t utf8_length(unsigned char c)
   366 {
   367     c = (unsigned char)(0xff & c);
   368     if (c < 0x80)
   369         return 1;
   370     else if ((c >> 5) ==0x6)
   371         return 2;
   372     else if ((c >> 4) == 0xe)
   373         return 3;
   374     else if ((c >> 3) == 0x1e)
   375         return 4;
   376     else
   377         return 0;
   378 }
   379 
   380 char *utf8_next(char *p)
   381 {
   382     size_t len = utf8_length(*p);
   383     size_t i = 0;
   384     if (!len)
   385         return 0;
   386 
   387     for (; i < len; ++i)
   388     {
   389         ++p;
   390         if (!*p)
   391             return 0;
   392     }
   393     return p;
   394 }
   395 
   396 char *utf8_advance(char *p, size_t distance)
   397 {
   398     size_t i = 0;
   399     for (; i < distance && p; ++i)
   400     {
   401         p = utf8_next(p);
   402     }
   403     return p;
   404 }
   405 
   406 Uint32 utf8_decode(char *p, size_t len)
   407 {
   408     Uint32 codepoint = 0;
   409     size_t i = 0;
   410     if (!len)
   411         return 0;
   412 
   413     for (; i < len; ++i)
   414     {
   415         if (i == 0)
   416             codepoint = (0xff >> len) & *p;
   417         else
   418         {
   419             codepoint <<= 6;
   420             codepoint |= 0x3f & *p;
   421         }
   422         if (!*p)
   423             return 0;
   424         p++;
   425     }
   426 
   427     return codepoint;
   428 }
   429 
   430 void usage()
   431 {
   432     SDL_Log("usage: testime [--font fontfile]\n");
   433     exit(0);
   434 }
   435 
   436 void InitInput()
   437 {
   438 
   439     /* Prepare a rect for text input */
   440     textRect.x = textRect.y = 100;
   441     textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
   442     textRect.h = 50;
   443 
   444     text[0] = 0;
   445     markedRect = textRect;
   446     markedText[0] = 0;
   447 
   448     SDL_StartTextInput();
   449 }
   450 
   451 void CleanupVideo()
   452 {
   453     SDL_StopTextInput();
   454 #ifdef HAVE_SDL_TTF
   455     TTF_CloseFont(font);
   456     TTF_Quit();
   457 #else
   458     unifont_cleanup();
   459 #endif
   460 }
   461 
   462 void _Redraw(int rendererID) {
   463     SDL_Renderer * renderer = state->renderers[rendererID];
   464     SDL_Rect drawnTextRect, cursorRect, underlineRect;
   465     drawnTextRect = textRect;
   466     drawnTextRect.w = 0;
   467 
   468     SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
   469     SDL_RenderFillRect(renderer,&textRect);
   470 
   471     if (*text)
   472     {
   473 #ifdef HAVE_SDL_TTF
   474         SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
   475         SDL_Texture *texture;
   476 
   477         /* Vertically center text */
   478         drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
   479         drawnTextRect.w = textSur->w;
   480         drawnTextRect.h = textSur->h;
   481 
   482         texture = SDL_CreateTextureFromSurface(renderer,textSur);
   483         SDL_FreeSurface(textSur);
   484 
   485         SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
   486         SDL_DestroyTexture(texture);
   487 #else
   488         char *utext = text;
   489         Uint32 codepoint;
   490         size_t len;
   491         SDL_Rect dstrect;
   492 
   493         dstrect.x = textRect.x;
   494         dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
   495         dstrect.w = 16 * UNIFONT_DRAW_SCALE;
   496         dstrect.h = 16 * UNIFONT_DRAW_SCALE;
   497         drawnTextRect.y = dstrect.y;
   498         drawnTextRect.h = dstrect.h;
   499 
   500         while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
   501         {
   502             Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
   503             dstrect.x += advance;
   504             drawnTextRect.w += advance;
   505             utext += len;
   506         }
   507 #endif
   508     }
   509 
   510     markedRect.x = textRect.x + drawnTextRect.w;
   511     markedRect.w = textRect.w - drawnTextRect.w;
   512     if (markedRect.w < 0)
   513     {
   514         /* Stop text input because we cannot hold any more characters */
   515         SDL_StopTextInput();
   516         return;
   517     }
   518     else
   519     {
   520         SDL_StartTextInput();
   521     }
   522 
   523     cursorRect = drawnTextRect;
   524     cursorRect.x += cursorRect.w;
   525     cursorRect.w = 2;
   526     cursorRect.h = drawnTextRect.h;
   527 
   528     drawnTextRect.x += drawnTextRect.w;
   529     drawnTextRect.w = 0;
   530 
   531     SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
   532     SDL_RenderFillRect(renderer,&markedRect);
   533 
   534     if (markedText[0])
   535     {
   536 #ifdef HAVE_SDL_TTF
   537         SDL_Surface *textSur;
   538         SDL_Texture *texture;
   539         if (cursor)
   540         {
   541             char *p = utf8_advance(markedText, cursor);
   542             char c = 0;
   543             if (!p)
   544                 p = &markedText[SDL_strlen(markedText)];
   545 
   546             c = *p;
   547             *p = 0;
   548             TTF_SizeUTF8(font, markedText, &drawnTextRect.w, NULL);
   549             cursorRect.x += drawnTextRect.w;
   550             *p = c;
   551         }
   552         textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
   553         /* Vertically center text */
   554         drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
   555         drawnTextRect.w = textSur->w;
   556         drawnTextRect.h = textSur->h;
   557 
   558         texture = SDL_CreateTextureFromSurface(renderer,textSur);
   559         SDL_FreeSurface(textSur);
   560 
   561         SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
   562         SDL_DestroyTexture(texture);
   563 #else
   564         int i = 0;
   565         char *utext = markedText;
   566         Uint32 codepoint;
   567         size_t len;
   568         SDL_Rect dstrect;
   569 
   570         dstrect.x = drawnTextRect.x;
   571         dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
   572         dstrect.w = 16 * UNIFONT_DRAW_SCALE;
   573         dstrect.h = 16 * UNIFONT_DRAW_SCALE;
   574         drawnTextRect.y = dstrect.y;
   575         drawnTextRect.h = dstrect.h;
   576 
   577         while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
   578         {
   579             Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
   580             dstrect.x += advance;
   581             drawnTextRect.w += advance;
   582             if (i < cursor)
   583                 cursorRect.x += advance;
   584             i++;
   585             utext += len;
   586         }
   587 #endif
   588 
   589         if (cursor > 0)
   590         {
   591             cursorRect.y = drawnTextRect.y;
   592             cursorRect.h = drawnTextRect.h;
   593         }
   594 
   595         underlineRect = markedRect;
   596         underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
   597         underlineRect.h = 2;
   598         underlineRect.w = drawnTextRect.w;
   599 
   600         SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
   601         SDL_RenderFillRect(renderer, &underlineRect);
   602     }
   603 
   604     SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
   605     SDL_RenderFillRect(renderer,&cursorRect);
   606 
   607     SDL_SetTextInputRect(&markedRect);
   608 }
   609 
   610 void Redraw() {
   611     int i;
   612     for (i = 0; i < state->num_windows; ++i) {
   613         SDL_Renderer *renderer = state->renderers[i];
   614         if (state->windows[i] == NULL)
   615             continue;
   616         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
   617         SDL_RenderClear(renderer);
   618 
   619         /* Sending in the window id to let the font renderers know which one we're working with. */
   620         _Redraw(i);
   621 
   622         SDL_RenderPresent(renderer);
   623     }
   624 }
   625 
   626 int main(int argc, char *argv[]) {
   627     int i, done;
   628     SDL_Event event;
   629     const char *fontname = DEFAULT_FONT;
   630 
   631     /* Enable standard application logging */
   632     SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
   633 
   634     /* Initialize test framework */
   635     state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
   636     if (!state) {
   637         return 1;
   638     }
   639     for (i = 1; i < argc;i++) {
   640         SDLTest_CommonArg(state, i);
   641     }
   642     for (argc--, argv++; argc > 0; argc--, argv++)
   643     {
   644         if (strcmp(argv[0], "--help") == 0) {
   645             usage();
   646             return 0;
   647         }
   648 
   649         else if (strcmp(argv[0], "--font") == 0)
   650         {
   651             argc--;
   652             argv++;
   653 
   654             if (argc > 0)
   655                 fontname = argv[0];
   656             else {
   657                 usage();
   658                 return 0;
   659             }
   660         }
   661     }
   662 
   663     if (!SDLTest_CommonInit(state)) {
   664         return 2;
   665     }
   666 
   667 
   668 #ifdef HAVE_SDL_TTF
   669     /* Initialize fonts */
   670     TTF_Init();
   671 
   672     font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
   673     if (! font)
   674     {
   675         SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
   676         exit(-1);
   677     }
   678 #else
   679     unifont_init(fontname);
   680 #endif
   681 
   682     SDL_Log("Using font: %s\n", fontname);
   683     atexit(SDL_Quit);
   684 
   685     InitInput();
   686     /* Create the windows and initialize the renderers */
   687     for (i = 0; i < state->num_windows; ++i) {
   688         SDL_Renderer *renderer = state->renderers[i];
   689         SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
   690         SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
   691         SDL_RenderClear(renderer);
   692     }
   693     Redraw();
   694     /* Main render loop */
   695     done = 0;
   696     while (!done) {
   697         /* Check for events */
   698         while (SDL_PollEvent(&event)) {
   699             SDLTest_CommonEvent(state, &event, &done);
   700             switch(event.type) {
   701                 case SDL_KEYDOWN: {
   702                     switch (event.key.keysym.sym)
   703                     {
   704                         case SDLK_RETURN:
   705                              text[0]=0x00;
   706                              Redraw();
   707                              break;
   708                         case SDLK_BACKSPACE:
   709                             /* Only delete text if not in editing mode. */
   710                              if (!markedText[0])
   711                              {
   712                                  size_t textlen = SDL_strlen(text);
   713 
   714                                  do {
   715                                      if (textlen==0)
   716                                      {
   717                                          break;
   718                                      }
   719                                      if ((text[textlen-1] & 0x80) == 0x00)
   720                                      {
   721                                          /* One byte */
   722                                          text[textlen-1]=0x00;
   723                                          break;
   724                                      }
   725                                      if ((text[textlen-1] & 0xC0) == 0x80)
   726                                      {
   727                                          /* Byte from the multibyte sequence */
   728                                          text[textlen-1]=0x00;
   729                                          textlen--;
   730                                      }
   731                                      if ((text[textlen-1] & 0xC0) == 0xC0)
   732                                      {
   733                                          /* First byte of multibyte sequence */
   734                                          text[textlen-1]=0x00;
   735                                          break;
   736                                      }
   737                                  } while(1);
   738 
   739                                  Redraw();
   740                              }
   741                              break;
   742                     }
   743 
   744                     if (done)
   745                     {
   746                         break;
   747                     }
   748 
   749                     SDL_Log("Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
   750                             event.key.keysym.scancode,
   751                             SDL_GetScancodeName(event.key.keysym.scancode),
   752                             event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
   753                     break;
   754 
   755                 case SDL_TEXTINPUT:
   756                     if (event.text.text[0] == '\0' || event.text.text[0] == '\n' ||
   757                         markedRect.w < 0)
   758                         break;
   759 
   760                     SDL_Log("Keyboard: text input \"%s\"\n", event.text.text);
   761 
   762                     if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
   763                         SDL_strlcat(text, event.text.text, sizeof(text));
   764 
   765                     SDL_Log("text inputed: %s\n", text);
   766 
   767                     /* After text inputed, we can clear up markedText because it */
   768                     /* is committed */
   769                     markedText[0] = 0;
   770                     Redraw();
   771                     break;
   772 
   773                 case SDL_TEXTEDITING:
   774                     SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
   775                             event.edit.text, event.edit.start, event.edit.length);
   776 
   777                     SDL_strlcpy(markedText, event.edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE);
   778                     cursor = event.edit.start;
   779                     Redraw();
   780                     break;
   781                 }
   782                 break;
   783 
   784             }
   785         }
   786     }
   787     CleanupVideo();
   788     SDLTest_CommonQuit(state);
   789     return 0;
   790 }
   791 
   792 
   793 /* vi: set ts=4 sw=4 expandtab: */