Skip to content

Commit

Permalink
Partial utf-8 support
Browse files Browse the repository at this point in the history
  • Loading branch information
mittorn committed Dec 9, 2015
1 parent 782f4b1 commit e3e53b2
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 14 deletions.
2 changes: 1 addition & 1 deletion engine/client/cl_main.c
Expand Up @@ -1628,7 +1628,7 @@ void CL_InitLocal( void )
//Cvar_Get( "ex_maxerrordistance", "0", 0, "" );
cl_allow_fragment = Cvar_Get( "cl_allow_fragment", "0", CVAR_ARCHIVE, "allow downloading files directly from game server" );
cl_timeout = Cvar_Get( "cl_timeout", "60", 0, "connect timeout (in seconds)" );
cl_charset = Cvar_Get( "cl_charset", "cp1251", CVAR_ARCHIVE, "1-byte charset to use (iconv style)" );
cl_charset = Cvar_Get( "cl_charset", "utf-8", CVAR_ARCHIVE, "1-byte charset to use (iconv style)" );

rcon_client_password = Cvar_Get( "rcon_password", "", 0, "remote control client password" );
rcon_address = Cvar_Get( "rcon_address", "", 0, "remote control address" );
Expand Down
1 change: 1 addition & 0 deletions engine/client/client.h
Expand Up @@ -760,6 +760,7 @@ void Con_DrawDebug( void );
void Con_RunConsole( void );
void Con_DrawConsole( void );
void Con_DrawVersion( void );
int Con_UtfProcessChar( int in );
void Con_DrawStringLen( const char *pText, int *length, int *height );
int Con_DrawString( int x, int y, const char *string, rgba_t setColor );
int Con_DrawCharacter( int x, int y, int number, rgba_t color );
Expand Down
168 changes: 160 additions & 8 deletions engine/common/console.c
Expand Up @@ -25,6 +25,10 @@ convar_t *scr_conspeed;
convar_t *con_fontsize;
convar_t *con_maxfrac;
convar_t *con_halffrac;
convar_t *con_charset;

static int g_codepage = 0;
static qboolean g_utf8 = false;

#define CON_TIMES 5 // need for 4 lines
#define COLOR_DEFAULT '7'
Expand Down Expand Up @@ -506,6 +510,132 @@ static void Con_LoadConchars( void )

}

// CP1251 table

int table_cp1251[64] = {
0x0402, 0x0403, 0x201A, 0x0453, 0x201E, 0x2026, 0x2020, 0x2021,
0x20AC, 0x2030, 0x0409, 0x2039, 0x040A, 0x040C, 0x040B, 0x040F,
0x0452, 0x2018, 0x2019, 0x201C, 0x201D, 0x2022, 0x2013, 0x2014,
0x007F, 0x2122, 0x0459, 0x203A, 0x045A, 0x045C, 0x045B, 0x045F,
0x00A0, 0x040E, 0x045E, 0x0408, 0x00A4, 0x0490, 0x00A6, 0x00A7,
0x0401, 0x00A9, 0x0404, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0407,
0x00B0, 0x00B1, 0x0406, 0x0456, 0x0491, 0x00B5, 0x00B6, 0x00B7,
0x0451, 0x2116, 0x0454, 0x00BB, 0x0458, 0x0405, 0x0455, 0x0457
};

/*
============================
Con_UtfProcessChar
Convert utf char to current font's single-byte encoding
============================
*/
int Con_UtfProcessChar( int in )
{
static int m = -1, k = 0; //multibyte state
static int uc = 0; //unicode char

if( !in )
{
m = -1;
k = 0;
uc = 0;
return 0;
}

// Get character length
if(m == -1)
{
uc = 0;
if( in >= 0xF8 )
return 0;
else if( in >= 0xF0 )
uc = in & 0x07, m = 3;
else if( in >= 0xE0 )
uc = in & 0x0F, m = 2;
else if( in >= 0xC0 )
uc = in & 0x1F, m = 1;
else if( in <= 0x7F)
return in; //ascii
// return 0 if we need more chars to decode one
k=0;
return 0;
}
// get more chars
else if( k <= m )
{
uc <<= 6;
uc += in & 0x3F;
k++;
}
if( in > 0xBF || m < 0 )
{
m = -1;
return 0;
}
if( k == m )
{
k = m = -1;
if( g_codepage == 1251 )
{
// cp1251 now
if( uc >= 0x0410 && uc <= 0x042F )
return uc - 0x410 + 0xC0;
if( uc >= 0x0430 && uc <= 0x044F )
return uc - 0x430 + 0xE0;
else
{
int i;
for( i = 0; i < 64; i++ )
if( table_cp1251[i] == uc )
return i + 0x80;
}
}
// not implemented yet
return '?';
}
return 0;
}

/*
=================
Con_UtfMoveLeft
get position of previous printful char
=================
*/
static int Con_UtfMoveLeft( char *str, int pos )
{
int i, j, k = 0;
Con_UtfProcessChar( 0 );
if(pos == 1) return 0;
for( i = 0; i < pos-1; i++ )
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
k = i+1;
Con_UtfProcessChar( 0 );
return k;
}

/*
=================
Con_UtfMoveRight
get next of previous printful char
=================
*/
static int Con_UtfMoveRight( char *str, int pos, int length )
{
int i;
Con_UtfProcessChar( 0 );
for( i = pos; i <= length; i++ )
{
if( Con_UtfProcessChar( (unsigned char)str[i] ) )
return i+1;
}
Con_UtfProcessChar( 0 );
return pos+1;
}

static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
{
int width, height;
Expand All @@ -517,7 +647,10 @@ static int Con_DrawGenericChar( int x, int y, int number, rgba_t color )
if( !con.curFont || !con.curFont->valid )
return 0;

if( number < 32 ) return 0;
if( g_utf8 )
number = Con_UtfProcessChar(number);
else if( number < 32 )
return 0;
if( y < -con.curFont->charHeight )
return 0;

Expand Down Expand Up @@ -592,7 +725,11 @@ void Con_DrawStringLen( const char *pText, int *length, int *height )
continue;
}

curLength += con.curFont->charWidths[c];
// Convert to unicode
if( g_utf8 )
c = Con_UtfProcessChar( c );
if( c )
curLength += con.curFont->charWidths[ c ];
pText++;

if( curLength > *length )
Expand All @@ -617,6 +754,8 @@ int Con_DrawGenericString( int x, int y, const char *string, rgba_t setColor, qb

if( !con.curFont ) return 0; // no font set

Con_UtfProcessChar( 0 );

// draw the colored text
s = string;
*(uint *)color = *(uint *)setColor;
Expand Down Expand Up @@ -679,6 +818,7 @@ void Con_Init( void )
con_fontsize = Cvar_Get( "con_fontsize", "1", CVAR_ARCHIVE, "console font number (0, 1 or 2)" );
con_maxfrac = Cvar_Get( "con_maxfrac", "1.0", CVAR_ARCHIVE, "console max height" );
con_halffrac = Cvar_Get( "con_halffrac", "0.5", CVAR_ARCHIVE, "console half height" );
con_charset = Cvar_Get( "con_charset", "cp1251", CVAR_ARCHIVE, "console font charset" );

Con_CheckResize();

Expand Down Expand Up @@ -1186,24 +1326,25 @@ void Field_KeyDownEvent( field_t *edit, int key )
{
if( edit->cursor > 0 )
{
Q_memmove( edit->buffer + edit->cursor - 1, edit->buffer + edit->cursor, len - edit->cursor + 1 );
edit->cursor--;
int newcursor = Con_UtfMoveLeft( edit->buffer, edit->cursor );
Q_memmove( edit->buffer + newcursor, edit->buffer + edit->cursor, len - edit->cursor + 1 );
edit->cursor = newcursor;
if( edit->scroll ) edit->scroll--;
}
return;
}

if( key == K_RIGHTARROW )
{
if( edit->cursor < len ) edit->cursor++;
if( edit->cursor < len ) edit->cursor = Con_UtfMoveRight( edit->buffer, edit->cursor, edit->widthInChars );
if( edit->cursor >= edit->scroll + edit->widthInChars && edit->cursor <= len )
edit->scroll++;
return;
}

if( key == K_LEFTARROW )
{
if( edit->cursor > 0 ) edit->cursor--;
if( edit->cursor > 0 ) edit->cursor= Con_UtfMoveLeft( edit->buffer, edit->cursor );
if( edit->cursor < edit->scroll ) edit->scroll--;
return;
}
Expand Down Expand Up @@ -1269,7 +1410,7 @@ void Field_CharEvent( field_t *edit, int ch )
}

// ignore any other non printable chars
if( ch < 32 ) return;
//if( ch < 32 ) return;

if( host.key_overstrike )
{
Expand Down Expand Up @@ -1347,6 +1488,7 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
// calc cursor position
str[edit->cursor - prestep] = 0;
Con_DrawStringLen( str, &curPos, NULL );
Con_UtfProcessChar( 0 );

if( host.key_overstrike && cursorChar )
{
Expand All @@ -1357,7 +1499,11 @@ void Field_DrawInputLine( int x, int y, field_t *edit )
pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
Con_DrawGenericChar( x + curPos, y, cursorChar, colorDefault );
}
else Con_DrawCharacter( x + curPos, y, '_', colorDefault );
else
{
Con_UtfProcessChar( 0 );
Con_DrawCharacter( x + curPos, y, '_', colorDefault );
}
}

/*
Expand Down Expand Up @@ -1967,6 +2113,12 @@ void Con_RunConsole( void )
if( con.finalFrac < con.displayFrac )
con.displayFrac = con.finalFrac;
}

// update codepage parameters
g_codepage = 0;
if( !Q_stricmp( con_charset->string, "cp1251" ) )
g_codepage = 1251;
g_utf8 = !Q_stricmp( cl_charset->string, "utf-8" );
}

/*
Expand Down
20 changes: 15 additions & 5 deletions engine/common/sdl/events.c
Expand Up @@ -215,7 +215,7 @@ void SDLash_WheelEvent(SDL_MouseWheelEvent wheel)
void SDLash_InputEvent(SDL_TextInputEvent input)
{
int i, f, t;

#if 0
// Try convert to selected charset
unsigned char buf[32];

Expand All @@ -232,13 +232,23 @@ void SDLash_InputEvent(SDL_TextInputEvent input)
}
if( ( t < 0 ) || ( cd == (SDL_iconv_t)-1 ) )
Q_strncpy( buf, input.text, 32 );

#endif
// Pass characters one by one to Con_CharEvent
for(i = 0; buf[i]; ++i)
for(i = 0; input.text[i]; ++i)
{
Con_CharEvent( (uint)buf[i] );
int ch;

if( !Q_stricmp( cl_charset->string, "utf-8" ) )
ch = (unsigned char)input.text[i];
else
ch = Con_UtfProcessChar( (unsigned char)input.text[i] );

if( !ch )
continue;

Con_CharEvent( ch );
if( cls.key_dest == key_menu )
UI_CharEvent ( (uint)buf[i] );
UI_CharEvent ( ch );
}
}

Expand Down

0 comments on commit e3e53b2

Please sign in to comment.