diff --git a/src/filesel.c b/src/filesel.c index fb2edeb8..8077c52f 100644 --- a/src/filesel.c +++ b/src/filesel.c @@ -1901,11 +1901,17 @@ 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)); - Unicode_strlcpy(filename_unicode, Selector_filename_unicode, sizeof(filename_unicode)/sizeof(word)); + 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 */ char * input = (char *)Selector_filename; @@ -1916,20 +1922,22 @@ 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++) @@ -1937,23 +1945,18 @@ byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context 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 + if(!Directory_exists(Selector_filename)) { + 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) diff --git a/src/global.h b/src/global.h index ff180be1..d8bb6974 100644 --- a/src/global.h +++ b/src/global.h @@ -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 diff --git a/src/main.c b/src/main.c index 04a83500..641df1a6 100644 --- a/src/main.c +++ b/src/main.c @@ -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 */ diff --git a/src/readline.c b/src/readline.c index ed5838b8..11b73b79 100644 --- a/src/readline.c +++ b/src/readline.c @@ -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 @@ -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,20 +565,38 @@ 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=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; - size=strlen(str); - position=(size=visible_size) - offset=position-visible_size+1; - // Formatage d'une partie de la chaine (si trop longue pour tenir) - strncpy(display_string, str + offset, visible_size); - display_string[visible_size]='\0'; - if (offset>0) - display_string[0]=LEFT_TRIANGLE_CHARACTER; - if (visible_size + offset + 1 < size ) - display_string[visible_size-1]=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=visible_size) + offset=position-visible_size+1; + // 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) + display_string[0]=LEFT_TRIANGLE_CHARACTER; + if (visible_size + offset + 1 < size ) + 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); + 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,15 +662,23 @@ 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=visible_size) - offset++; + 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--; } @@ -633,7 +696,10 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz case SDLK_DELETE : // Suppr. if (position visible_size + offset - 2) //if (offset + visible_size < max_size && (position == size || (position > visible_size + offset - 2))) - if (display_string[position-offset]==RIGHT_TRIANGLE_CHARACTER || position-offset>=visible_size) - offset++; + 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,12 +760,15 @@ 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--; - Remove_character(str,position); + if (str_unicode != NULL) + Remove_character_unicode(str_unicode,position); + else + Remove_character(str,position); size--; // Effacement de la chaîne Window_rectangle(x_pos,y_pos,visible_size<<3,8,BACKGROUND_COLOR); @@ -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=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,16 +834,31 @@ byte Readline_ex(word x_pos,word y_pos,char * str,byte visible_size,byte max_siz break; affichage: - size=strlen(str); - // Formatage d'une partie de la chaine (si trop longue pour tenir) - strncpy(display_string, str + offset, visible_size); - display_string[visible_size]='\0'; - if (offset>0) - display_string[0]=LEFT_TRIANGLE_CHARACTER; - if (visible_size + offset + 0 < size ) - 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); + 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); + // only show part of the string if too long + strncpy(display_string, str + offset, visible_size); + display_string[visible_size]='\0'; + if (offset>0) + display_string[0]=LEFT_TRIANGLE_CHARACTER; + if (visible_size + offset + 0 < size ) + 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)" diff --git a/src/readline.h b/src/readline.h index 99e6a2f2..d7dcff8f 100644 --- a/src/readline.h +++ b/src/readline.h @@ -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. diff --git a/src/unicode.c b/src/unicode.c index 9a9db9f4..341ffde1 100644 --- a/src/unicode.c +++ b/src/unicode.c @@ -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); +} diff --git a/src/unicode.h b/src/unicode.h index 202befd6..10d353c2 100644 --- a/src/unicode.h +++ b/src/unicode.h @@ -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 diff --git a/src/windows.h b/src/windows.h index 3631720d..6a530b07 100644 --- a/src/windows.h +++ b/src/windows.h @@ -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);