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