Unicode support in keyboard editable field for filename

This commit is contained in:
Thomas Bernard 2018-02-15 14:17:53 +01:00
parent 9fb6d650b5
commit 689aebf264
8 changed files with 196 additions and 62 deletions

View File

@ -1901,10 +1901,16 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
T_Fileselector_item * current_item;
current_item = Get_item_by_index(&Filelist, Selector->Position + Selector->Offset);
if (current_item->Type != 0 && !FILENAME_COMPARE(current_item->Full_name,Selector_filename))
{
// current name is a highlighted directory
Selector_filename[0]='\0';
Selector_filename_unicode[0]=0;
}
}
strncpy(filename_ansi, Selector_filename, sizeof(filename_ansi));
if (Selector_filename_unicode[0] == 0 && strlen(Selector_filename) > 0)
Unicode_char_strlcpy(filename_unicode, Selector_filename, sizeof(filename_unicode)/sizeof(word));
else
Unicode_strlcpy(filename_unicode, Selector_filename_unicode, sizeof(filename_unicode)/sizeof(word));
#ifdef ENABLE_FILENAMES_ICONV
{ /* convert from UTF8 to ANSI */
@ -1916,44 +1922,41 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context
*output = '\0';
}
#endif /* ENABLE_FILENAMES_ICONV */
if (Readline(82,48,filename_ansi,27,INPUT_TYPE_FILENAME))
if (Readline_ex_unicode(82,48,filename_ansi,filename_unicode,27,sizeof(filename_ansi)-1,INPUT_TYPE_FILENAME,0))
{
#ifdef ENABLE_FILENAMES_ICONV
/* convert back from ANSI to UTF8 */
char * input = (char *)filename_ansi;
size_t inbytesleft = strlen(input);
/* convert back from UTF16 to UTF8 */
char * input = (char *)filename_unicode;
size_t inbytesleft = 2 * Unicode_strlen(filename_unicode);
char * output = Selector_filename;
size_t outbytesleft = sizeof(Selector_filename)-1;
if(cd_inv != (iconv_t)-1 && (ssize_t)iconv(cd_inv, &input, &inbytesleft, &output, &outbytesleft) >= 0)
if(cd_utf16_inv != (iconv_t)-1 && (ssize_t)iconv(cd_utf16_inv, &input, &inbytesleft, &output, &outbytesleft) >= 0)
*output = '\0';
else
#endif /* ENABLE_FILENAMES_ICONV */
strncpy(Selector_filename, filename_ansi, sizeof(Selector_filename));
Unicode_strlcpy(Selector_filename_unicode, filename_unicode, sizeof(Selector_filename_unicode)/sizeof(word));
// On regarde s'il faut rajouter une extension. C'est-à-dire s'il
// n'y a pas de '.' dans le nom du fichier.
for(temp=0,dummy=0; ((Selector_filename[temp]) && (!dummy)); temp++)
if (Selector_filename[temp]=='.')
dummy=1;
if (!dummy)
{
if (Get_fileformat(Selector->Format_filter)->Default_extension)
{
if(!Directory_exists(Selector_filename))
{
strcat(Selector_filename, ".");
strcat(Selector_filename, Get_fileformat(Selector->Format_filter)->Default_extension);
}
}
else
{
const char * ext = Get_fileformat(Selector->Format_filter)->Default_extension;
// put default extension
// (but maybe we should browse through all available ones until we find
// something suitable ?)
if(!Directory_exists(Selector_filename))
{
strcat(Selector_filename, ".pkm");
}
if (ext == NULL)
ext = "pkm";
strcat(Selector_filename, ".");
strcat(Selector_filename, ext);
Unicode_char_strlcat(Selector_filename_unicode, ".", sizeof(Selector_filename_unicode)/sizeof(word));
Unicode_char_strlcat(Selector_filename_unicode, ext, sizeof(Selector_filename_unicode)/sizeof(word));
}
}
if(load)

View File

@ -768,9 +768,10 @@ GFX2_GLOBAL int Line_number_in_INI_file;
#else
#define FROMCODE "UTF-8"
#endif
GFX2_GLOBAL iconv_t cd;
GFX2_GLOBAL iconv_t cd_inv;
GFX2_GLOBAL iconv_t cd_utf16;
GFX2_GLOBAL iconv_t cd; // FROMCODE => TOCODE
GFX2_GLOBAL iconv_t cd_inv; // TOCODE => FROMCODE
GFX2_GLOBAL iconv_t cd_utf16; // FROMCODE => UTF16
GFX2_GLOBAL iconv_t cd_utf16_inv; // UTF16 => FROMCODE
#endif /* ENABLE_FILENAMES_ICONV */
// -- Specific to SDL

View File

@ -480,8 +480,10 @@ int Init_program(int argc,char * argv[])
cd_inv = iconv_open(FROMCODE, TOCODE); // From ANSI to UTF8
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
cd_utf16 = iconv_open("UTF-16BE", FROMCODE); // From UTF8 to UTF16
cd_utf16_inv = iconv_open(FROMCODE, "UTF-16BE"); // From UTF16 to UTF8
#else
cd_utf16 = iconv_open("UTF-16LE", FROMCODE); // From UTF8 to UTF16
cd_utf16_inv = iconv_open(FROMCODE, "UTF-16LE"); // From UTF16 to UTF8
#endif
#endif /* ENABLE_FILENAMES_ICONV */

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2018 Thomas Bernard
Copyright 2014 Sergii Pylypenko
Copyright 2008 Yves Rizoud
Copyright 2007 Adrien Destugues
@ -41,6 +42,7 @@
#include "windows.h"
#include "input.h"
#include "engine.h"
#include "unicode.h"
#ifdef __WIN32__
#include <windows.h>
@ -67,17 +69,23 @@
#define CURSOR_COLOR MC_Black
#define CURSOR_BACKGROUND_COLOR MC_Dark
// Suppresion d'un caractère à une certaine POSITION dans une CHAINE.
void Remove_character(char * str, byte position)
// remove a character from a string
static void Remove_character(char * str, int position)
{
for (;str[position]!='\0';position++)
str[position]=str[position+1];
}
// remove a character from a string
static void Remove_character_unicode(word * str, int position)
{
for (;str[position]!='\0';position++)
str[position]=str[position+1];
}
void Insert_character(char * str, char letter, byte position)
// Insertion d'une LETTRE à une certaine POSITION
// dans une CHAINE d'une certaine TAILLE.
static void Insert_character(char * str, char letter, int position)
// Insert a character in str at position
{
char temp_char;
@ -94,6 +102,18 @@ void Insert_character(char * str, char letter, byte position)
str[position]='\0';
}
static void Insert_character_unicode(word * str, word c, int position)
{
for (;;)
{
word temp = str[position];
str[position++] = c;
if (c == 0)
return; // we just have written the NULL terminator
c = temp;
}
}
int Prepend_string(char* dest, char* src, int max)
// Insert a string at the start of another. Up to MAX characters only
// Returns actual number of chars inserted
@ -187,7 +207,7 @@ void Cleanup_string(char* str, int input_type)
str[j] = '\0';
}
void Display_whole_string(word x_pos,word y_pos,char * str,byte position)
static void Display_whole_string(word x_pos,word y_pos,const char * str,byte position)
{
char cursor[2];
Print_general(x_pos,y_pos,str,TEXT_COLOR,BACKGROUND_COLOR);
@ -197,6 +217,16 @@ void Display_whole_string(word x_pos,word y_pos,char * str,byte position)
Print_general(x_pos+(position<<3)*Menu_factor_X,y_pos,cursor,CURSOR_COLOR,CURSOR_BACKGROUND_COLOR);
}
static void Display_whole_string_unicode(word x_pos,word y_pos, const word * str_unicode,byte position)
{
char cursor[2];
Print_general_unicode(x_pos,y_pos,str_unicode,TEXT_COLOR,BACKGROUND_COLOR);
cursor[0]=str_unicode[position] ? str_unicode[position] : ' ';
cursor[1]='\0';
Print_general(x_pos+(position<<3)*Menu_factor_X,y_pos,cursor,CURSOR_COLOR,CURSOR_BACKGROUND_COLOR);
}
void Init_virtual_keyboard(word y_pos, word keyboard_width, word keyboard_height)
{
int h_pos;
@ -343,7 +373,7 @@ byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type
byte max_size;
// Grosse astuce pour les noms de fichiers: La taille affichée est différente
// de la taille maximum gérée.
if (input_type == 2)
if (input_type == INPUT_TYPE_FILENAME)
max_size = 255;
else
max_size = visible_size;
@ -354,6 +384,11 @@ byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type
* Enhanced super scanf deluxe pro plus giga mieux :-) *
****************************************************************************/
byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places)
{
return Readline_ex_unicode(x_pos, y_pos, str, NULL, visible_size, max_size, input_type, decimal_places);
}
byte Readline_ex_unicode(word x_pos,word y_pos,char * str,word * str_unicode,byte visible_size,byte max_size, byte input_type, byte decimal_places)
// Paramètres:
// x_pos, y_pos : Coordonnées de la saisie dans la fenêtre
// str : Chaîne recevant la saisie (et contenant éventuellement une valeur initiale)
@ -365,6 +400,8 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
{
char initial_string[256];
char display_string[256];
word initial_string_unicode[256];
word display_string_unicode[256];
byte position;
byte size;
word input_key=0;
@ -375,7 +412,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
// Virtual keyboard
byte use_virtual_keyboard=0;
static byte caps_lock=0;
word keymapping[] =
static const word keymapping[] =
{
SDLK_CLEAR,SDLK_BACKSPACE,SDLK_RETURN,KEY_ESC,
'0','1','2','3','4','5','6','7','8','9','.',',',
@ -528,12 +565,29 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
// Mise à jour des variables se rapportant à la chaîne en fonction de la chaîne initiale
strcpy(initial_string,str);
if (str_unicode != NULL)
{
size = Unicode_strlen(str_unicode);
memcpy(initial_string_unicode, str_unicode, 2*(size+1));
position=(size<max_size)? size:size-1;
if (position-offset>=visible_size)
offset=position-visible_size+1;
// copy only part of the string if it is too long
Unicode_strlcpy(display_string_unicode, str_unicode+offset, visible_size);
if (offset>0)
display_string_unicode[0] = (byte)LEFT_TRIANGLE_CHARACTER;
if (visible_size + offset + 1 < size )
display_string_unicode[visible_size-1] = (byte)RIGHT_TRIANGLE_CHARACTER;
Display_whole_string_unicode(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string_unicode,position - offset);
}
else
{
size=strlen(str);
position=(size<max_size)? size:size-1;
if (position-offset>=visible_size)
offset=position-visible_size+1;
// Formatage d'une partie de la chaine (si trop longue pour tenir)
// copy only part of the string if it is too long
strncpy(display_string, str + offset, visible_size);
display_string[visible_size]='\0';
if (offset>0)
@ -542,6 +596,7 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
}
Update_window_area(x_pos,y_pos,visible_size<<3,8);
Flush_update();
if (Mouse_K)
@ -607,16 +662,24 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
continue; // No clipboard data
Cleanup_string(data, input_type);
// Insert it at the cursor position
nb_added = Prepend_string(str + position, data, max_size - position);
nb_added = Prepend_string(str + position, data, max_size - position);//TODO : unicode
while (nb_added)
{
size++;
if (size<max_size)
{
position++;
if (str_unicode != NULL)
{
if (display_string_unicode[position-offset]==(byte)RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
}
else
{
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
}
}
nb_added--;
}
free(data);
@ -633,6 +696,9 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
case SDLK_DELETE : // Suppr.
if (position<size)
{
if (str_unicode != NULL)
Remove_character_unicode(str_unicode,position);
else
Remove_character(str,position);
size--;
@ -659,8 +725,16 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
position++;
//if (position > visible_size + offset - 2)
//if (offset + visible_size < max_size && (position == size || (position > visible_size + offset - 2)))
if (str_unicode != NULL)
{
if (display_string_unicode[position-offset]==(byte)RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
}
else
{
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
offset++;
}
goto affichage;
}
break;
@ -686,11 +760,14 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
break;
case SDLK_BACKSPACE : // Backspace : combinaison de gauche + suppr
if (position)
if (position > 0)
{
position--;
if (offset > 0 && (position == 0 || position < (offset + 1)))
offset--;
if (str_unicode != NULL)
Remove_character_unicode(str_unicode,position);
else
Remove_character(str,position);
size--;
// Effacement de la chaîne
@ -700,6 +777,8 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
break;
case SDLK_CLEAR : // Clear
str[0]='\0';
if (str_unicode != NULL)
str_unicode[0] = 0;
position=offset=0;
// Effacement de la chaîne
Window_rectangle(x_pos,y_pos,visible_size<<3,8,BACKGROUND_COLOR);
@ -711,6 +790,11 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
// On restaure la chaine initiale
strcpy(str,initial_string);
size=strlen(str);
if (str_unicode != NULL)
{
Unicode_strlcpy(str_unicode, initial_string_unicode, 256);
size = Unicode_strlen(str_unicode);
}
break;
default :
if (size<max_size)
@ -720,6 +804,9 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
if (is_authorized == 1 || (is_authorized == 2 && position == 0 && str[position] != '-'))
{
// ... alors on l'insère ...
if (str_unicode != NULL)
Insert_character_unicode(str_unicode,input_key,position/*,size*/);
else
Insert_character(str,input_key,position/*,size*/);
// ce qui augmente la taille de la chaine
size++;
@ -727,8 +814,18 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
if (size<max_size)
{
position++;
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size)
if (position-offset>=visible_size)
offset++;
else if (str_unicode != NULL)
{
if (display_string_unicode[position-offset]==RIGHT_TRIANGLE_CHARACTER)
offset++;
}
else
{
if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER)
offset++;
}
}
// Enfin, on raffiche la chaine
goto affichage;
@ -737,8 +834,22 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz
break;
affichage:
if (str_unicode != NULL)
{
size=Unicode_strlen(str_unicode);
// only show part of the string if too long
Unicode_strlcpy(display_string_unicode, str_unicode + offset, visible_size);
if (offset>0)
display_string_unicode[0] = (byte)LEFT_TRIANGLE_CHARACTER;
if (visible_size + offset + 0 < size )
display_string_unicode[visible_size-1] = (byte)RIGHT_TRIANGLE_CHARACTER;
Display_whole_string_unicode(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string_unicode,position - offset);
}
else
{
size=strlen(str);
// Formatage d'une partie de la chaine (si trop longue pour tenir)
// only show part of the string if too long
strncpy(display_string, str + offset, visible_size);
display_string[visible_size]='\0';
if (offset>0)
@ -747,6 +858,7 @@ affichage:
display_string[visible_size-1]=RIGHT_TRIANGLE_CHARACTER;
Display_whole_string(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),display_string,position - offset);
}
Update_rect(window_x+(x_pos*Menu_factor_X),window_y+(y_pos*Menu_factor_Y),
visible_size*(Menu_factor_X<<3),(Menu_factor_Y<<3));
} // End du "switch(input_key)"

View File

@ -2,6 +2,7 @@
*/
/* Grafx2 - The Ultimate 256-color bitmap paint program
Copyright 2018 Thomas Bernard
Copyright 2007 Adrien Destugues
Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
@ -55,6 +56,8 @@ byte Readline(word x_pos,word y_pos,char * str,byte visible_size,byte input_type
/// @return 0 if user cancelled (esc), 1 if accepted (return)
byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_size, byte input_type, byte decimal_places);
byte Readline_ex_unicode(word x_pos,word y_pos,char * str, word * unicode_str, byte visible_size,byte max_size, byte input_type, byte decimal_places);
///
/// Converts a double to string.
/// @param str Target string, should be pre-allocated and at least 40 characters, to be safe.

View File

@ -96,3 +96,12 @@ void Unicode_char_strlcpy(word * dst, const char * src, size_t len)
}
*dst = 0;
}
/// Append a regular Latin1 string to an unicode string
void Unicode_char_strlcat(word * dst, const char * src, size_t len)
{
size_t dst_len = Unicode_strlen(dst);
if (dst_len >= len)
return;
Unicode_char_strlcpy(dst + dst_len, src, len - dst_len);
}

View File

@ -39,4 +39,7 @@ int Unicode_char_strcmp(const word * s1, const char * s2);
/// Copy a regular Latin1 string to an unicode string
void Unicode_char_strlcpy(word * dst, const char * src, size_t len);
/// Append a regular Latin1 string to an unicode string
void Unicode_char_strlcat(word * dst, const char * src, size_t len);
#endif

View File

@ -66,6 +66,7 @@ word Palette_cells_X(void);
word Palette_cells_Y(void);
void Print_general(short x,short y,const char * str,byte text_color,byte background_color);
void Print_general_unicode(short x,short y,const word * str,byte text_color,byte background_color);
void Print_in_window(short x,short y,const char * str,byte text_color,byte background_color);
void Print_in_window_unicode(short x,short y,const word * str,byte text_color,byte background_color);
void Print_in_window_limited(short x,short y,const char * str,byte size,byte text_color,byte background_color);