Added application-level Input Method support.
This commit is contained in:
parent
092fd95579
commit
f043a733e6
10 changed files with 12902 additions and 85 deletions
46
src/i18n.c
46
src/i18n.c
|
|
@ -35,12 +35,33 @@
|
|||
#include "i18n.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* (Trouble building this for 10.2.8 target; bjk & mf 2006.01.14) */
|
||||
#ifndef __APPLE_10_2_8__
|
||||
#include <wchar.h>
|
||||
#else
|
||||
#undef FORKED_FONTS
|
||||
#define wchar_t char
|
||||
#define wcslen strlen
|
||||
#define towupper toupper
|
||||
#define iswprint isprint
|
||||
#define OLD_UPPERCASE_CODE
|
||||
#endif
|
||||
|
||||
#ifndef OLD_UPPERCASE_CODE
|
||||
#include <wctype.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Globals: */
|
||||
|
||||
static int langint = LANG_EN;
|
||||
|
||||
const char *lang_prefixes[NUM_LANGS] = {
|
||||
"af",
|
||||
"ar",
|
||||
|
|
@ -279,9 +300,9 @@ void set_langstr(const char *s)
|
|||
void ctype_utf8(void)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
char *names[] = {"en_US.UTF8","en_US.UTF-8","UTF8","UTF-8",};
|
||||
const char *names[] = {"en_US.UTF8","en_US.UTF-8","UTF8","UTF-8",};
|
||||
int i = sizeof(names)/sizeof(names[0]);
|
||||
while(i-- && !iswprint((wchar_t)0xf7) && !setlocale(LC_CTYPE,names[i]))
|
||||
while(i && !iswprint((wchar_t)0xf7) && !setlocale(LC_CTYPE,names[--i]))
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -291,7 +312,7 @@ void ctype_utf8(void)
|
|||
void set_current_language(void)
|
||||
{
|
||||
char *loc;
|
||||
int lang, i, found;
|
||||
int i, found;
|
||||
|
||||
bindtextdomain("tuxpaint", LOCALEDIR);
|
||||
/* Old version of glibc does not have bind_textdomain_codeset() */
|
||||
|
|
@ -302,7 +323,7 @@ void set_current_language(void)
|
|||
|
||||
/* Default... */
|
||||
|
||||
lang = LANG_EN;
|
||||
langint = LANG_EN;
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
|
|
@ -343,24 +364,30 @@ void set_current_language(void)
|
|||
// Case-insensitive (both "pt_BR" and "pt_br" work, etc.)
|
||||
if (strncasecmp(loc, lang_prefixes[i], strlen(lang_prefixes[i])) == 0)
|
||||
{
|
||||
lang = i;
|
||||
langint = i;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lang_prefix = lang_prefixes[lang];
|
||||
need_own_font = search_int_array(lang, lang_use_own_font);
|
||||
need_right_to_left = search_int_array(lang, lang_use_right_to_left);
|
||||
lang_prefix = lang_prefixes[langint];
|
||||
need_own_font = search_int_array(langint, lang_use_own_font);
|
||||
need_right_to_left = search_int_array(langint, lang_use_right_to_left);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "DEBUG: Language is %s (%d)\n", lang_prefix, lang);
|
||||
fprintf(stderr, "DEBUG: Language is %s (%d)\n", lang_prefix, langint);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
int get_current_language(void)
|
||||
{
|
||||
return langint;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: All this should REALLY be array-based!!! */
|
||||
/* Show available languages: */
|
||||
void show_lang_usage(FILE * f, const char *const prg)
|
||||
|
|
@ -586,6 +613,7 @@ void setup_language(const char *const prg)
|
|||
setlocale(LC_ALL, "");
|
||||
ctype_utf8();
|
||||
free(langstr);
|
||||
langstr = NULL;
|
||||
}
|
||||
|
||||
set_current_language();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
|
||||
#ifndef I18N_H
|
||||
#define I18N_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* Possible languages: */
|
||||
|
||||
|
|
@ -118,6 +122,7 @@ extern const language_to_locale_struct language_to_locale_array[];
|
|||
|
||||
void set_langstr(const char *s);
|
||||
void set_current_language(void);
|
||||
int get_current_language(void);
|
||||
void show_lang_usage(FILE * f, const char *const prg);
|
||||
void show_locale_usage(FILE * f, const char *const prg);
|
||||
void setup_language(const char *const prg);
|
||||
|
|
|
|||
63
src/im.h
Normal file
63
src/im.h
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
im.h
|
||||
|
||||
Input method handling
|
||||
Copyright (c) 2007 by Mark K. Kim and others
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
(See COPYING.txt)
|
||||
|
||||
$Id$
|
||||
*/
|
||||
|
||||
#ifndef TUXPAINT_IM_H
|
||||
#define TUXPAINT_IM_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include "i18n.h"
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
* TYPES
|
||||
*/
|
||||
|
||||
typedef struct IM_DATA {
|
||||
int lang; /* Language used in sequence translation */
|
||||
wchar_t s[8]; /* Characters that should be displayed */
|
||||
const char* tip_text; /* Tip text, read-only please */
|
||||
|
||||
/* For use by language-specific im_event_<lang> calls. PRIVATE! */
|
||||
wchar_t buf[8]; /* Buffered characters */
|
||||
int discard; /* Discard parameter */
|
||||
int request; /* Event request */
|
||||
} IM_DATA;
|
||||
|
||||
|
||||
/* ***************************************************************************
|
||||
* FUNCTIONS
|
||||
*/
|
||||
|
||||
void im_init(IM_DATA* im, int lang); /* Initialize IM */
|
||||
void im_fullreset(IM_DATA* im); /* Full Reset IM */
|
||||
void im_softreset(IM_DATA* im); /* Soft Reset IM */
|
||||
void im_free(IM_DATA* im); /* Free IM resources */
|
||||
|
||||
int im_read(IM_DATA* im, SDL_keysym ks);
|
||||
|
||||
|
||||
#endif /* TUXPAINT_IM_H */
|
||||
|
||||
/* vim:ts=8
|
||||
*/
|
||||
148
src/tuxpaint.c
148
src/tuxpaint.c
|
|
@ -391,6 +391,8 @@ typedef struct safer_dirent
|
|||
#include "tip_tux.h"
|
||||
#include "great.h"
|
||||
|
||||
#include "im.h"
|
||||
|
||||
|
||||
#ifdef DEBUG_MALLOC
|
||||
#include "malloc.c"
|
||||
|
|
@ -1045,6 +1047,7 @@ static int eraser_scroll, shape_scroll; // dummy variables for now
|
|||
|
||||
static int eraser_sound;
|
||||
|
||||
static IM_DATA im_data;
|
||||
static wchar_t texttool_str[256];
|
||||
static unsigned int texttool_len;
|
||||
|
||||
|
|
@ -1802,6 +1805,9 @@ static void mainloop(void)
|
|||
|
||||
if (cur_tool == TOOL_TEXT && cursor_x != -1 && cursor_y != -1)
|
||||
{
|
||||
static int discard = 0;
|
||||
wchar_t* im_cp = im_data.s;
|
||||
|
||||
key_down = key;
|
||||
key_unicode = event.key.keysym.unicode;
|
||||
|
||||
|
|
@ -1829,81 +1835,102 @@ static void mainloop(void)
|
|||
#endif
|
||||
#endif
|
||||
|
||||
if (key_down == SDLK_BACKSPACE)
|
||||
{
|
||||
hide_blinking_cursor();
|
||||
if (texttool_len > 0)
|
||||
{
|
||||
texttool_len--;
|
||||
texttool_str[texttool_len] = 0;
|
||||
playsound(screen, 0, SND_KEYCLICK, 0, SNDPOS_CENTER,
|
||||
SNDDIST_NEAR);
|
||||
/* Discard previous # of instructed characters */
|
||||
if((int)texttool_len <= discard) texttool_len = 0;
|
||||
else texttool_len -= discard;
|
||||
texttool_str[texttool_len] = L'\0';
|
||||
|
||||
do_render_cur_text(0);
|
||||
/* Read IM, remember how many to discard next iteration */
|
||||
discard = im_read(&im_data, event.key.keysym);
|
||||
|
||||
/* Queue each character to be displayed */
|
||||
while(*im_cp) {
|
||||
if (*im_cp == L'\b')
|
||||
{
|
||||
hide_blinking_cursor();
|
||||
if (texttool_len > 0)
|
||||
{
|
||||
texttool_len--;
|
||||
texttool_str[texttool_len] = 0;
|
||||
playsound(screen, 0, SND_KEYCLICK, 0, SNDPOS_CENTER,
|
||||
SNDDIST_NEAR);
|
||||
|
||||
do_render_cur_text(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (key_down == SDLK_RETURN)
|
||||
{
|
||||
int font_height;
|
||||
|
||||
hide_blinking_cursor();
|
||||
if (texttool_len > 0)
|
||||
else if (*im_cp == L'\r')
|
||||
{
|
||||
rec_undo_buffer();
|
||||
do_render_cur_text(1);
|
||||
texttool_len = 0;
|
||||
cursor_textwidth = 0;
|
||||
int font_height;
|
||||
|
||||
hide_blinking_cursor();
|
||||
if (texttool_len > 0)
|
||||
{
|
||||
rec_undo_buffer();
|
||||
do_render_cur_text(1);
|
||||
texttool_len = 0;
|
||||
cursor_textwidth = 0;
|
||||
}
|
||||
font_height = TTF_FontHeight(getfonthandle(cur_font));
|
||||
|
||||
cursor_x = cursor_left;
|
||||
cursor_y = min(cursor_y + font_height, canvas->h - font_height);
|
||||
|
||||
playsound(screen, 0, SND_RETURN, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
|
||||
im_softreset(&im_data);
|
||||
}
|
||||
font_height = TTF_FontHeight(getfonthandle(cur_font));
|
||||
|
||||
cursor_x = cursor_left;
|
||||
cursor_y = min(cursor_y + font_height, canvas->h - font_height);
|
||||
|
||||
playsound(screen, 0, SND_RETURN, 1, SNDPOS_RIGHT, SNDDIST_NEAR);
|
||||
}
|
||||
else if (key_down == SDLK_TAB)
|
||||
{
|
||||
if (texttool_len > 0)
|
||||
else if (*im_cp == L'\t')
|
||||
{
|
||||
rec_undo_buffer();
|
||||
do_render_cur_text(1);
|
||||
cursor_x = min(cursor_x + cursor_textwidth, canvas->w);
|
||||
texttool_len = 0;
|
||||
cursor_textwidth = 0;
|
||||
if (texttool_len > 0)
|
||||
{
|
||||
rec_undo_buffer();
|
||||
do_render_cur_text(1);
|
||||
cursor_x = min(cursor_x + cursor_textwidth, canvas->w);
|
||||
texttool_len = 0;
|
||||
cursor_textwidth = 0;
|
||||
}
|
||||
im_softreset(&im_data);
|
||||
}
|
||||
}
|
||||
else if (iswprint(key_unicode))
|
||||
{
|
||||
if (texttool_len < (sizeof(texttool_str) / sizeof(wchar_t)) - 1)
|
||||
else if (iswprint(*im_cp))
|
||||
{
|
||||
int old_cursor_textwidth = cursor_textwidth;
|
||||
#ifdef DEBUG
|
||||
wprintf(L" key = <%c>\nunicode = <%lc> 0x%04x %d\n\n",
|
||||
key_down, key_unicode, key_unicode, key_unicode);
|
||||
if (texttool_len < (sizeof(texttool_str) / sizeof(wchar_t)) - 1)
|
||||
{
|
||||
int old_cursor_textwidth = cursor_textwidth;
|
||||
#ifdef DEBUG
|
||||
wprintf(L" key = <%c>\nunicode = <%lc> 0x%04x %d\n\n",
|
||||
key_down, key_unicode, key_unicode, key_unicode);
|
||||
#endif
|
||||
|
||||
texttool_str[texttool_len++] = key_unicode;
|
||||
texttool_str[texttool_len] = 0;
|
||||
texttool_str[texttool_len++] = *im_cp;
|
||||
texttool_str[texttool_len] = 0;
|
||||
|
||||
do_render_cur_text(0);
|
||||
do_render_cur_text(0);
|
||||
|
||||
|
||||
if (cursor_x + old_cursor_textwidth <= canvas->w - 50 &&
|
||||
cursor_x + cursor_textwidth > canvas->w - 50)
|
||||
{
|
||||
playsound(screen, 0, SND_KEYCLICKRING, 1, SNDPOS_RIGHT,
|
||||
SNDDIST_NEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Might be fun to position the
|
||||
sound based on keyboard layout...? */
|
||||
if (cursor_x + old_cursor_textwidth <= canvas->w - 50 &&
|
||||
cursor_x + cursor_textwidth > canvas->w - 50)
|
||||
{
|
||||
playsound(screen, 0, SND_KEYCLICKRING, 1, SNDPOS_RIGHT,
|
||||
SNDDIST_NEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Might be fun to position the
|
||||
sound based on keyboard layout...? */
|
||||
|
||||
playsound(screen, 0, SND_KEYCLICK, 0, SNDPOS_CENTER,
|
||||
SNDDIST_NEAR);
|
||||
}
|
||||
playsound(screen, 0, SND_KEYCLICK, 0, SNDPOS_CENTER,
|
||||
SNDDIST_NEAR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
im_cp++;
|
||||
} /* while(*im_cp) */
|
||||
|
||||
/* Show IM tip text */
|
||||
if(im_data.tip_text) {
|
||||
draw_tux_text(TUX_DEFAULT, im_data.tip_text, 1);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6461,6 +6488,7 @@ static void setup(int argc, char *argv[])
|
|||
|
||||
|
||||
setup_language(getfilename(argv[0]));
|
||||
im_init(&im_data, get_current_language());
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue