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@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 |
{
|
dimitris@6318
|
83 |
printf("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 |
{
|
dimitris@6318
|
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];
|
dimitris@6318
|
199 |
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
|
dimitris@6318
|
200 |
SDL_RenderClear(renderer);
|
dimitris@6318
|
201 |
|
dimitris@6318
|
202 |
_Redraw(renderer);
|
dimitris@6318
|
203 |
|
dimitris@6318
|
204 |
SDL_RenderPresent(renderer);
|
dimitris@6318
|
205 |
}
|
dimitris@6318
|
206 |
}
|
dimitris@6318
|
207 |
|
dimitris@6318
|
208 |
int main(int argc, char *argv[]) {
|
dimitris@6318
|
209 |
int i, done;
|
dimitris@6318
|
210 |
SDL_Event event;
|
slouken@3280
|
211 |
const char *fontname = DEFAULT_FONT;
|
slouken@3280
|
212 |
|
dimitris@6318
|
213 |
/* Initialize test framework */
|
slouken@6785
|
214 |
state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
|
dimitris@6318
|
215 |
if (!state) {
|
dimitris@6318
|
216 |
return 1;
|
dimitris@6318
|
217 |
}
|
dimitris@6318
|
218 |
for (i = 1; i < argc;i++) {
|
slouken@6785
|
219 |
SDLTest_CommonArg(state, i);
|
dimitris@6318
|
220 |
}
|
slouken@3280
|
221 |
for (argc--, argv++; argc > 0; argc--, argv++)
|
slouken@3280
|
222 |
{
|
dimitris@6318
|
223 |
if (strcmp(argv[0], "--help") == 0) {
|
slouken@3280
|
224 |
usage();
|
dimitris@6318
|
225 |
return 0;
|
dimitris@6318
|
226 |
}
|
slouken@3280
|
227 |
|
slouken@3280
|
228 |
else if (strcmp(argv[0], "--font") == 0)
|
slouken@3280
|
229 |
{
|
slouken@3280
|
230 |
argc--;
|
slouken@3280
|
231 |
argv++;
|
slouken@3280
|
232 |
|
slouken@3280
|
233 |
if (argc > 0)
|
slouken@3280
|
234 |
fontname = argv[0];
|
dimitris@6318
|
235 |
else {
|
slouken@3280
|
236 |
usage();
|
dimitris@6318
|
237 |
return 0;
|
dimitris@6318
|
238 |
}
|
slouken@3280
|
239 |
}
|
slouken@3280
|
240 |
}
|
slouken@7191
|
241 |
|
slouken@6785
|
242 |
if (!SDLTest_CommonInit(state)) {
|
dimitris@6318
|
243 |
return 2;
|
dimitris@6318
|
244 |
}
|
slouken@3280
|
245 |
|
slouken@3280
|
246 |
|
slouken@3280
|
247 |
#ifdef HAVE_SDL_TTF
|
slouken@3280
|
248 |
/* Initialize fonts */
|
slouken@3280
|
249 |
TTF_Init();
|
slouken@3280
|
250 |
|
slouken@3280
|
251 |
font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
|
slouken@3280
|
252 |
if (! font)
|
slouken@3280
|
253 |
{
|
bob@3281
|
254 |
fprintf(stderr, "Failed to find font: %s\n", TTF_GetError());
|
slouken@3280
|
255 |
exit(-1);
|
slouken@3280
|
256 |
}
|
slouken@3280
|
257 |
#endif
|
slouken@3280
|
258 |
|
slouken@3280
|
259 |
printf("Using font: %s\n", fontname);
|
slouken@3280
|
260 |
atexit(SDL_Quit);
|
slouken@3280
|
261 |
|
dimitris@6318
|
262 |
InitInput();
|
dimitris@6318
|
263 |
/* Create the windows and initialize the renderers */
|
dimitris@6318
|
264 |
for (i = 0; i < state->num_windows; ++i) {
|
dimitris@6318
|
265 |
SDL_Renderer *renderer = state->renderers[i];
|
dimitris@6318
|
266 |
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
|
dimitris@6318
|
267 |
SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
|
dimitris@6318
|
268 |
SDL_RenderClear(renderer);
|
slouken@3280
|
269 |
}
|
slouken@7191
|
270 |
Redraw();
|
dimitris@6318
|
271 |
/* Main render loop */
|
dimitris@6318
|
272 |
done = 0;
|
dimitris@6318
|
273 |
while (!done) {
|
dimitris@6318
|
274 |
/* Check for events */
|
dimitris@6318
|
275 |
while (SDL_PollEvent(&event)) {
|
slouken@6785
|
276 |
SDLTest_CommonEvent(state, &event, &done);
|
dimitris@6318
|
277 |
switch(event.type) {
|
dimitris@6318
|
278 |
case SDL_KEYDOWN: {
|
dimitris@6318
|
279 |
switch (event.key.keysym.sym)
|
dimitris@6318
|
280 |
{
|
dimitris@6318
|
281 |
case SDLK_RETURN:
|
dimitris@6318
|
282 |
text[0]=0x00;
|
dimitris@6318
|
283 |
Redraw();
|
dimitris@6318
|
284 |
break;
|
dimitris@6318
|
285 |
case SDLK_BACKSPACE:
|
dimitris@6318
|
286 |
{
|
dimitris@6318
|
287 |
int textlen=SDL_strlen(text);
|
slouken@3280
|
288 |
|
dimitris@6318
|
289 |
do {
|
dimitris@6318
|
290 |
if (textlen==0)
|
dimitris@6318
|
291 |
{
|
dimitris@6318
|
292 |
break;
|
dimitris@6318
|
293 |
}
|
dimitris@6318
|
294 |
if ((text[textlen-1] & 0x80) == 0x00)
|
dimitris@6318
|
295 |
{
|
dimitris@6318
|
296 |
/* One byte */
|
dimitris@6318
|
297 |
text[textlen-1]=0x00;
|
dimitris@6318
|
298 |
break;
|
dimitris@6318
|
299 |
}
|
dimitris@6318
|
300 |
if ((text[textlen-1] & 0xC0) == 0x80)
|
dimitris@6318
|
301 |
{
|
dimitris@6318
|
302 |
/* Byte from the multibyte sequence */
|
dimitris@6318
|
303 |
text[textlen-1]=0x00;
|
dimitris@6318
|
304 |
textlen--;
|
dimitris@6318
|
305 |
}
|
dimitris@6318
|
306 |
if ((text[textlen-1] & 0xC0) == 0xC0)
|
dimitris@6318
|
307 |
{
|
dimitris@6318
|
308 |
/* First byte of multibyte sequence */
|
dimitris@6318
|
309 |
text[textlen-1]=0x00;
|
dimitris@6318
|
310 |
break;
|
dimitris@6318
|
311 |
}
|
dimitris@6318
|
312 |
} while(1);
|
dimitris@6318
|
313 |
|
dimitris@6318
|
314 |
Redraw();
|
dimitris@6318
|
315 |
}
|
dimitris@6318
|
316 |
break;
|
dimitris@6318
|
317 |
}
|
dimitris@6318
|
318 |
|
dimitris@6318
|
319 |
if (done)
|
dimitris@6318
|
320 |
{
|
dimitris@6318
|
321 |
break;
|
dimitris@6318
|
322 |
}
|
dimitris@6318
|
323 |
|
dimitris@6318
|
324 |
fprintf(stderr,
|
dimitris@6318
|
325 |
"Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
|
dimitris@6318
|
326 |
event.key.keysym.scancode,
|
dimitris@6318
|
327 |
SDL_GetScancodeName(event.key.keysym.scancode),
|
dimitris@6318
|
328 |
event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
|
dimitris@6318
|
329 |
break;
|
dimitris@6318
|
330 |
|
dimitris@6318
|
331 |
case SDL_TEXTINPUT:
|
dimitris@6318
|
332 |
if (SDL_strlen(event.text.text) == 0 || event.text.text[0] == '\n' ||
|
dimitris@6318
|
333 |
markedRect.w < 0)
|
dimitris@6318
|
334 |
break;
|
dimitris@6318
|
335 |
|
dimitris@6318
|
336 |
fprintf(stderr, "Keyboard: text input \"%s\"\n", event.text.text);
|
dimitris@6318
|
337 |
|
dimitris@6318
|
338 |
if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
|
dimitris@6318
|
339 |
SDL_strlcat(text, event.text.text, sizeof(text));
|
dimitris@6318
|
340 |
|
dimitris@6318
|
341 |
fprintf(stderr, "text inputed: %s\n", text);
|
dimitris@6318
|
342 |
|
dimitris@6318
|
343 |
// After text inputed, we can clear up markedText because it
|
dimitris@6318
|
344 |
// is committed
|
dimitris@6318
|
345 |
markedText[0] = 0;
|
dimitris@6318
|
346 |
Redraw();
|
dimitris@6318
|
347 |
break;
|
dimitris@6318
|
348 |
|
dimitris@6318
|
349 |
case SDL_TEXTEDITING:
|
dimitris@6318
|
350 |
fprintf(stderr, "text editing \"%s\", selected range (%d, %d)\n",
|
dimitris@6318
|
351 |
event.edit.text, event.edit.start, event.edit.length);
|
dimitris@6318
|
352 |
|
dimitris@6318
|
353 |
strcpy(markedText, event.edit.text);
|
dimitris@6318
|
354 |
cursor = event.edit.start;
|
dimitris@6318
|
355 |
Redraw();
|
dimitris@6318
|
356 |
break;
|
dimitris@6318
|
357 |
}
|
dimitris@6318
|
358 |
break;
|
slouken@7191
|
359 |
|
dimitris@6318
|
360 |
}
|
dimitris@6318
|
361 |
}
|
slouken@3280
|
362 |
}
|
dimitris@6318
|
363 |
CleanupVideo();
|
slouken@6785
|
364 |
SDLTest_CommonQuit(state);
|
dimitris@6318
|
365 |
return 0;
|
slouken@3280
|
366 |
}
|
slouken@3280
|
367 |
|
slouken@5244
|
368 |
|
slouken@5244
|
369 |
/* vi: set ts=4 sw=4 expandtab: */
|