Created
July 15, 2017 06:55
-
-
Save drm343/4e146ebb708502ebd0417e53658a24e0 to your computer and use it in GitHub Desktop.
SDL2 處理中文輸入
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Use `gcc sdl2_text_input_utf8.c -lSDL2 -lSDL2_ttf -o test_program`. | |
// | |
// You must use CJK font for SDL2_ttf and put the same directory with test_program. | |
// This example use "NotoSansMonoCJKtc-Regular.otf". | |
#include <stdio.h> | |
#include <string.h> | |
#include <stdbool.h> | |
#include <stdint.h> | |
#include <SDL2/SDL.h> | |
#include <SDL2/SDL_ttf.h> | |
#define GAME_TITLE "輸入文字" | |
#define WIDTH 800 | |
#define HEIGHT 600 | |
int GRID_LENGTH = 24; | |
size_t strlen_utf8(char *str) { | |
size_t max_counter = strlen(str); | |
size_t move_position = 0; | |
int64_t len = 0; | |
unsigned char check = 0; | |
for(size_t index = 0; index < max_counter; index += move_position) { | |
check = str[index]; | |
len++; | |
if(check < 0b11000000) { | |
move_position = 1; | |
} | |
else if(check < 0b11100000 && check > 0b11000000) { | |
move_position = 2; | |
} | |
else if(check < 0b11110000 && check > 0b11100000) { | |
move_position = 3; | |
} | |
else if(check > 0b11110000) { | |
move_position = 4; | |
} | |
else if(check == 0) { | |
break; | |
} | |
else { | |
printf("bug\n"); | |
break; | |
} | |
} | |
return len; | |
} | |
size_t calculate_grid_width_utf8(char *str) { | |
size_t max_counter = strlen(str); | |
size_t move_position = 0; | |
int64_t len = 0; | |
unsigned char check = 0; | |
for(size_t index = 0; index < max_counter; index += move_position) { | |
check = str[index]; | |
len += 2; | |
if(check < 0b11000000) { | |
move_position = 1; | |
len--; | |
} | |
else if(check < 0b11100000 && check > 0b11000000) { | |
move_position = 2; | |
} | |
else if(check < 0b11110000 && check > 0b11100000) { | |
move_position = 3; | |
} | |
else if(check > 0b11110000) { | |
move_position = 4; | |
} | |
else if(check == 0) { | |
break; | |
} | |
else { | |
printf("bug\n"); | |
break; | |
} | |
} | |
return len * (GRID_LENGTH / 2); | |
} | |
void remove_last_utf8(char **str) { | |
size_t index = strlen(*str); | |
unsigned char check = 0; | |
for(index; index > 0; index--) { | |
check = (unsigned char)((*str)[index - 1]) & 0b11000000; | |
if(check == 0b10000000) { | |
(*str)[index - 1] = 0; | |
} | |
else { | |
(*str)[index - 1] = 0; | |
break; | |
} | |
} | |
} | |
int main(int argc, char *argv[]) { | |
SDL_Color white = {255, 255, 255}; | |
SDL_Window *win; | |
SDL_Renderer *render; | |
bool running = true; | |
char *text = malloc(100); | |
size_t target = 0; | |
memset(text, 0, 100); | |
SDL_Init(SDL_INIT_EVERYTHING); | |
if (TTF_Init() != 0) { | |
goto INIT_FAILED; | |
} | |
SDL_StartTextInput(); | |
win = SDL_CreateWindow(GAME_TITLE, 0, 0, WIDTH, HEIGHT, SDL_WINDOW_OPENGL); | |
render = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED|SDL_RENDERER_PRESENTVSYNC); | |
TTF_Font* font = TTF_OpenFont("./NotoSansMonoCJKtc-Regular.otf", 512); | |
SDL_Surface* surfaceMessage = NULL; | |
SDL_Texture *access = NULL; | |
SDL_Rect rect = {.x = 0, .y = 0, .w = 1 * GRID_LENGTH, .h = GRID_LENGTH}; | |
while (running) { | |
SDL_Event event; | |
while (SDL_PollEvent(&event)) { | |
SDL_RenderClear(render); | |
switch (event.type) { | |
case SDL_QUIT: | |
running = false; | |
break; | |
case SDL_TEXTINPUT: | |
case SDL_KEYDOWN: | |
if(event.key.keysym.sym == SDLK_BACKSPACE && target > 0) { | |
if(event.type == SDL_KEYDOWN && event.key.repeat == 0) { | |
remove_last_utf8(&text); | |
} | |
} | |
else if(event.type == SDL_TEXTINPUT) { | |
strcat(text, event.text.text); | |
} | |
target = strlen_utf8(text); | |
rect.w = calculate_grid_width_utf8(text); | |
surfaceMessage = TTF_RenderUTF8_Solid(font, | |
text, | |
white); | |
access = SDL_CreateTextureFromSurface(render, surfaceMessage); | |
SDL_FreeSurface(surfaceMessage); | |
break; | |
default: | |
break; | |
} | |
SDL_SetRenderDrawColor(render, 0, 0, 0, SDL_ALPHA_OPAQUE); | |
SDL_RenderCopy(render, access, NULL, &(rect)); | |
SDL_RenderPresent(render); | |
} | |
} | |
TTF_CloseFont(font); | |
SDL_DestroyRenderer(render); | |
SDL_DestroyWindow(win); | |
INIT_FAILED: | |
SDL_StopTextInput(); | |
TTF_Quit(); | |
SDL_Quit(); | |
free(text); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment