Support for unicode names in directory listing

This commit is contained in:
Thomas Bernard 2018-02-12 12:53:41 +01:00
parent a1f0f36062
commit 3322529804
7 changed files with 139 additions and 22 deletions

View File

@ -541,7 +541,7 @@ OBJS = main.o init.o graph.o sdlscreen.o misc.o special.o \
transform.o pversion.o factory.o $(PLATFORMOBJ) \
fileformats.o miscfileformats.o libraw2crtc.o \
brush_ops.o buttons_effects.o layers.o \
oldies.o tiles.o colorred.o
oldies.o tiles.o colorred.o unicode.o
OBJ = $(addprefix $(OBJDIR)/,$(OBJS))
SKINS = skin_classic.png skin_modern.png skin_DPaint.png \

View File

@ -60,6 +60,7 @@
#include "readline.h"
#include "input.h"
#include "help.h"
#include "unicode.h"
#include "filesel.h"
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de
@ -205,13 +206,15 @@ void Free_fileselector_list(T_Fileselector *list)
// On fait avancer la tête de la liste
list->First=list->First->Next;
// Et on efface l'ancien premier élément de la liste
free(temp_item->Unicode_full_name);
free(temp_item->Unicode_short_name);
free(temp_item);
temp_item = NULL;
}
Recount_files(list);
}
int Position_last_dot(const char * fname)
static int Position_last_dot(const char * fname)
{
int pos_last_dot = -1;
int c = 0;
@ -222,6 +225,83 @@ int Position_last_dot(const char * fname)
return pos_last_dot;
}
static int Position_last_dot_unicode(const word * fname)
{
int pos_last_dot = -1;
int c = 0;
for (c = 0; fname[c]!='\0'; c++)
if (fname[c]=='.')
pos_last_dot = c;
return pos_last_dot;
}
word * Format_filename_unicode(const word * fname, word max_length, int type)
{
static word result[40];
int c;
int other_cursor;
int pos_last_dot;
// safety
if (max_length>40)
max_length=40;
if (Unicode_char_strcmp(fname,PARENT_DIR)==0)
{
Unicode_char_strlcpy(result, "\x11 PARENT DIRECTORY", 40);
// Append spaces
for (c=18; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
}
else if (fname[0]=='.' || type==1 || type==2)
{
// Files ".something" or drives or directories: Aligned left on (max_length-1) chars max
// Initialize as all spaces
for (c=0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
for (c=0;fname[c]!='\0' && c < max_length-1;c++)
result[c]=fname[c];
// A special character indicates the filename is truncated
if (c >= max_length-1)
result[max_length-2]=(byte)ELLIPSIS_CHARACTER;
}
else
{
// Initialize as all spaces
for (c = 0; c<max_length-1; c++)
result[c]=' ';
result[c]='\0';
result[max_length-5]='.';
// Look for the last dot in filename
pos_last_dot = Position_last_dot_unicode(fname);
// Copy the part before the dot
for (c=0; c!=pos_last_dot && fname[c]!='\0'; c++)
{
if (c > max_length-6)
{
result[max_length-6]=(byte)ELLIPSIS_CHARACTER;
break;
}
result[c]=fname[c];
}
// Ensuite on recopie la partie qui suit le point (si nécessaire):
if (pos_last_dot != -1)
{
for (c = pos_last_dot+1,other_cursor=max_length-4;fname[c]!='\0' && other_cursor < max_length-1;c++,other_cursor++)
result[other_cursor]=fname[c];
}
}
return result;
}
char * Format_filename(const char * fname, word max_length, int type)
{
static char result[40];
@ -305,17 +385,20 @@ char * Format_filename(const char * fname, word max_length, int type)
// -- Rajouter a la liste des elements de la liste un element ---------------
void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon)
T_Fileselector_item * Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon)
// Cette procedure ajoute a la liste chainee un fichier passé en argument.
{
// Working element
T_Fileselector_item * temp_item;
size_t short_name_len;
short_name_len = strlen(short_name) + 1;
// Allocate enough room for one struct + the visible label
temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item)+strlen(short_name));
temp_item=(T_Fileselector_item *)malloc(sizeof(T_Fileselector_item)+short_name_len);
memset(temp_item, 0, sizeof(T_Fileselector_item));
// Initialize element
strcpy(temp_item->Short_name,short_name);
memcpy(temp_item->Short_name,short_name,short_name_len);
strcpy(temp_item->Full_name,full_name);
temp_item->Type = type;
temp_item->Icon = icon;
@ -329,6 +412,7 @@ void Add_element_to_list(T_Fileselector *list, const char * full_name, const cha
// Put new element at the beginning
list->First=temp_item;
return temp_item;
}
///
@ -374,8 +458,8 @@ struct Read_dir_pdata
static void Read_dir_callback(void * pdata, const char *file_name, const word *unicode_name, byte is_file, byte is_directory, byte is_hidden)
{
T_Fileselector_item * item;
struct Read_dir_pdata * p = (struct Read_dir_pdata *)pdata;
(void)unicode_name;
if (p == NULL) // error !
return;
@ -401,7 +485,9 @@ static void Read_dir_callback(void * pdata, const char *file_name, const word *u
return;
// Add to list
Add_element_to_list(p->list, file_name, Format_filename(file_name, 19, 1), 1, ICON_NONE);
item = Add_element_to_list(p->list, file_name, Format_filename(file_name, 19, 1), 1, ICON_NONE);
item->Unicode_full_name = Unicode_strdup(unicode_name);
item->Unicode_short_name = Unicode_strdup(Format_filename_unicode(unicode_name, 19, 1));
p->list->Nb_directories++;
}
else if (is_file && // It's a file
@ -413,7 +499,9 @@ static void Read_dir_callback(void * pdata, const char *file_name, const word *u
if (Check_extension(file_name, ext))
{
// Add to list
Add_element_to_list(p->list, file_name, Format_filename(file_name, 19, 0), 0, ICON_NONE);
item = Add_element_to_list(p->list, file_name, Format_filename(file_name, 19, 0), 0, ICON_NONE);
item->Unicode_full_name = Unicode_strdup(unicode_name);
item->Unicode_short_name = Unicode_strdup(Format_filename_unicode(unicode_name, 19, 0));
p->list->Nb_files++;
// Stop searching
break;
@ -871,9 +959,15 @@ void Display_file_list(T_Fileselector *list, short offset_first,short selector_o
// Name preceded by an icon
Print_in_window(16,95+index*8,current_item->Short_name,text_color,background_color);
Window_display_icon_sprite(8,95+index*8,current_item->Icon);
} else
}
else
{
// Name without icon
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color);
if (current_item->Unicode_short_name)
Print_in_window_utf16(8,95+index*8,current_item->Unicode_short_name,text_color,background_color);
else
Print_in_window(8,95+index*8,current_item->Short_name,text_color,background_color);
}
// On passe à la ligne suivante
selector_offset--;

View File

@ -31,7 +31,7 @@
byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context *context);
void Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon);
T_Fileselector_item * Add_element_to_list(T_Fileselector *list, const char * full_name, const char *short_name, int type, byte icon);
///
/// Formats a display name for a file, directory, or similar name (drive, volume).
/// The returned value is a pointer to a single static buffer of maximum 40 characters

View File

@ -770,6 +770,7 @@ GFX2_GLOBAL int Line_number_in_INI_file;
#endif
GFX2_GLOBAL iconv_t cd;
GFX2_GLOBAL iconv_t cd_inv;
GFX2_GLOBAL iconv_t cd_utf16;
#endif /* ENABLE_FILENAMES_ICONV */
// -- Specific to SDL

View File

@ -51,6 +51,7 @@
#include "struct.h"
#include "io.h"
#include "realpath.h"
#include "global.h"
// Lit un octet
// Renvoie -1 si OK, 0 en cas d'erreur
@ -393,17 +394,18 @@ void For_each_file(const char * directory_name, void Callback(const char *))
/// Scans a directory, calls Callback for each file or directory in it,
void For_each_directory_entry(const char * directory_name, void * pdata, T_File_dir_cb Callback)
{
// Pour scan de répertoire
DIR* current_directory; //Répertoire courant
struct dirent* entry; // Structure de lecture des éléments
DIR* current_directory; // current directory
struct dirent* entry; // directory entry struct
char full_filename[MAX_PATH_CHARACTERS];
word * unicode_filename = NULL;
word unicode_buffer[MAX_PATH_CHARACTERS];
int filename_position;
strcpy(full_filename, directory_name);
current_directory=opendir(full_filename);
if(current_directory == NULL) return; // Répertoire invalide ...
filename_position = strlen(full_filename);
current_directory=opendir(directory_name);
if(current_directory == NULL) return; // Invalid directory
filename_position = strlen(directory_name);
memcpy(full_filename, directory_name, filename_position+1);
#if defined(__AROS__)
if (filename_position==0 || (strcmp(full_filename+filename_position-1,PATH_SEPARATOR) && strcmp(full_filename+filename_position-1,":")))
#else
@ -416,6 +418,23 @@ void For_each_directory_entry(const char * directory_name, void * pdata, T_File_
while ((entry=readdir(current_directory)))
{
struct stat Infos_enreg;
#ifdef ENABLE_FILENAMES_ICONV
char * input = entry->d_name;
size_t inbytesleft = strlen(entry->d_name);
char * output = (char *)unicode_buffer;
size_t outbytesleft = sizeof(unicode_buffer) - 2;
unicode_filename = NULL;
if (cd_utf16 != (iconv_t)-1)
{
size_t r = iconv(cd_utf16, &input, &inbytesleft, &output, &outbytesleft);
if (r != (size_t)-1)
{
output[0] = '\0';
output[1] = '\0';
unicode_filename = unicode_buffer;
}
}
#endif
strcpy(&full_filename[filename_position], entry->d_name);
stat(full_filename,&Infos_enreg);
Callback(

View File

@ -496,6 +496,7 @@ int Init_program(int argc,char * argv[])
// utilisé pour convertir les noms de fichiers
cd = iconv_open(TOCODE, FROMCODE); // From UTF8 to ANSI
cd_inv = iconv_open(FROMCODE, TOCODE); // From ANSI to UTF8
cd_utf16 = iconv_open("UTF-16LE", FROMCODE); // From UTF8 to UTF16
#endif /* ENABLE_FILENAMES_ICONV */
// On en profite pour le mémoriser dans le répertoire principal:

View File

@ -181,8 +181,10 @@ typedef struct T_Fileselector_item
struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector.
struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector.
word Length_short_name; ///< Number of bytes allocated for :Short_name
#if __GNUC__ < 3
word * Unicode_full_name; ///< Pointer to allocated unicode string. Filesystem name
word * Unicode_short_name; ///< Pointer to allocated unicode string. Name to display
#if __GNUC__ < 3
char Short_name[0]; ///< Name to display.
#else
char Short_name[]; ///< Name to display.