Skip to content

Instantly share code, notes, and snippets.

@drm343
Created July 15, 2017 06:55
Show Gist options
  • Save drm343/4e146ebb708502ebd0417e53658a24e0 to your computer and use it in GitHub Desktop.
Save drm343/4e146ebb708502ebd0417e53658a24e0 to your computer and use it in GitHub Desktop.
SDL2 處理中文輸入
// 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