Support for unicode names in directory listing
This commit is contained in:
parent
a1f0f36062
commit
3322529804
@ -541,7 +541,7 @@ OBJS = main.o init.o graph.o sdlscreen.o misc.o special.o \
|
|||||||
transform.o pversion.o factory.o $(PLATFORMOBJ) \
|
transform.o pversion.o factory.o $(PLATFORMOBJ) \
|
||||||
fileformats.o miscfileformats.o libraw2crtc.o \
|
fileformats.o miscfileformats.o libraw2crtc.o \
|
||||||
brush_ops.o buttons_effects.o layers.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))
|
OBJ = $(addprefix $(OBJDIR)/,$(OBJS))
|
||||||
|
|
||||||
SKINS = skin_classic.png skin_modern.png skin_DPaint.png \
|
SKINS = skin_classic.png skin_modern.png skin_DPaint.png \
|
||||||
|
|||||||
116
src/filesel.c
116
src/filesel.c
@ -60,6 +60,7 @@
|
|||||||
#include "readline.h"
|
#include "readline.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "help.h"
|
#include "help.h"
|
||||||
|
#include "unicode.h"
|
||||||
#include "filesel.h"
|
#include "filesel.h"
|
||||||
|
|
||||||
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de
|
#define NORMAL_FILE_COLOR MC_Light // color du texte pour une ligne de
|
||||||
@ -205,23 +206,102 @@ void Free_fileselector_list(T_Fileselector *list)
|
|||||||
// On fait avancer la tête de la liste
|
// On fait avancer la tête de la liste
|
||||||
list->First=list->First->Next;
|
list->First=list->First->Next;
|
||||||
// Et on efface l'ancien premier élément de la liste
|
// 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);
|
free(temp_item);
|
||||||
temp_item = NULL;
|
temp_item = NULL;
|
||||||
}
|
}
|
||||||
Recount_files(list);
|
Recount_files(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Position_last_dot(const char * fname)
|
static int Position_last_dot(const char * fname)
|
||||||
{
|
{
|
||||||
int pos_last_dot = -1;
|
int pos_last_dot = -1;
|
||||||
int c = 0;
|
int c = 0;
|
||||||
|
|
||||||
for (c = 0; fname[c]!='\0'; c++)
|
for (c = 0; fname[c]!='\0'; c++)
|
||||||
if (fname[c]=='.')
|
if (fname[c]=='.')
|
||||||
pos_last_dot = c;
|
pos_last_dot = c;
|
||||||
return pos_last_dot;
|
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)
|
char * Format_filename(const char * fname, word max_length, int type)
|
||||||
{
|
{
|
||||||
static char result[40];
|
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 ---------------
|
// -- 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.
|
// Cette procedure ajoute a la liste chainee un fichier passé en argument.
|
||||||
{
|
{
|
||||||
// Working element
|
// Working element
|
||||||
T_Fileselector_item * temp_item;
|
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
|
// 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
|
// 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);
|
strcpy(temp_item->Full_name,full_name);
|
||||||
temp_item->Type = type;
|
temp_item->Type = type;
|
||||||
temp_item->Icon = icon;
|
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
|
// Put new element at the beginning
|
||||||
list->First=temp_item;
|
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)
|
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;
|
struct Read_dir_pdata * p = (struct Read_dir_pdata *)pdata;
|
||||||
(void)unicode_name;
|
|
||||||
|
|
||||||
if (p == NULL) // error !
|
if (p == NULL) // error !
|
||||||
return;
|
return;
|
||||||
@ -401,7 +485,9 @@ static void Read_dir_callback(void * pdata, const char *file_name, const word *u
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Add to list
|
// 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++;
|
p->list->Nb_directories++;
|
||||||
}
|
}
|
||||||
else if (is_file && // It's a file
|
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))
|
if (Check_extension(file_name, ext))
|
||||||
{
|
{
|
||||||
// Add to list
|
// 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++;
|
p->list->Nb_files++;
|
||||||
// Stop searching
|
// Stop searching
|
||||||
break;
|
break;
|
||||||
@ -871,9 +959,15 @@ void Display_file_list(T_Fileselector *list, short offset_first,short selector_o
|
|||||||
// Name preceded by an icon
|
// Name preceded by an icon
|
||||||
Print_in_window(16,95+index*8,current_item->Short_name,text_color,background_color);
|
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);
|
Window_display_icon_sprite(8,95+index*8,current_item->Icon);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// Name without icon
|
// 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
|
// On passe à la ligne suivante
|
||||||
selector_offset--;
|
selector_offset--;
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
byte Button_Load_or_Save(T_Selector_settings *settings, byte load, T_IO_Context *context);
|
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).
|
/// 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
|
/// The returned value is a pointer to a single static buffer of maximum 40 characters
|
||||||
|
|||||||
@ -770,6 +770,7 @@ GFX2_GLOBAL int Line_number_in_INI_file;
|
|||||||
#endif
|
#endif
|
||||||
GFX2_GLOBAL iconv_t cd;
|
GFX2_GLOBAL iconv_t cd;
|
||||||
GFX2_GLOBAL iconv_t cd_inv;
|
GFX2_GLOBAL iconv_t cd_inv;
|
||||||
|
GFX2_GLOBAL iconv_t cd_utf16;
|
||||||
#endif /* ENABLE_FILENAMES_ICONV */
|
#endif /* ENABLE_FILENAMES_ICONV */
|
||||||
|
|
||||||
// -- Specific to SDL
|
// -- Specific to SDL
|
||||||
|
|||||||
33
src/io.c
33
src/io.c
@ -51,6 +51,7 @@
|
|||||||
#include "struct.h"
|
#include "struct.h"
|
||||||
#include "io.h"
|
#include "io.h"
|
||||||
#include "realpath.h"
|
#include "realpath.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
// Lit un octet
|
// Lit un octet
|
||||||
// Renvoie -1 si OK, 0 en cas d'erreur
|
// 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,
|
/// 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)
|
void For_each_directory_entry(const char * directory_name, void * pdata, T_File_dir_cb Callback)
|
||||||
{
|
{
|
||||||
// Pour scan de répertoire
|
DIR* current_directory; // current directory
|
||||||
DIR* current_directory; //Répertoire courant
|
struct dirent* entry; // directory entry struct
|
||||||
struct dirent* entry; // Structure de lecture des éléments
|
|
||||||
char full_filename[MAX_PATH_CHARACTERS];
|
char full_filename[MAX_PATH_CHARACTERS];
|
||||||
word * unicode_filename = NULL;
|
word * unicode_filename = NULL;
|
||||||
|
word unicode_buffer[MAX_PATH_CHARACTERS];
|
||||||
int filename_position;
|
int filename_position;
|
||||||
|
|
||||||
strcpy(full_filename, directory_name);
|
current_directory=opendir(directory_name);
|
||||||
current_directory=opendir(full_filename);
|
if(current_directory == NULL) return; // Invalid directory
|
||||||
if(current_directory == NULL) return; // Répertoire invalide ...
|
|
||||||
filename_position = strlen(full_filename);
|
filename_position = strlen(directory_name);
|
||||||
|
memcpy(full_filename, directory_name, filename_position+1);
|
||||||
#if defined(__AROS__)
|
#if defined(__AROS__)
|
||||||
if (filename_position==0 || (strcmp(full_filename+filename_position-1,PATH_SEPARATOR) && strcmp(full_filename+filename_position-1,":")))
|
if (filename_position==0 || (strcmp(full_filename+filename_position-1,PATH_SEPARATOR) && strcmp(full_filename+filename_position-1,":")))
|
||||||
#else
|
#else
|
||||||
@ -416,6 +418,23 @@ void For_each_directory_entry(const char * directory_name, void * pdata, T_File_
|
|||||||
while ((entry=readdir(current_directory)))
|
while ((entry=readdir(current_directory)))
|
||||||
{
|
{
|
||||||
struct stat Infos_enreg;
|
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);
|
strcpy(&full_filename[filename_position], entry->d_name);
|
||||||
stat(full_filename,&Infos_enreg);
|
stat(full_filename,&Infos_enreg);
|
||||||
Callback(
|
Callback(
|
||||||
|
|||||||
@ -496,6 +496,7 @@ int Init_program(int argc,char * argv[])
|
|||||||
// utilisé pour convertir les noms de fichiers
|
// utilisé pour convertir les noms de fichiers
|
||||||
cd = iconv_open(TOCODE, FROMCODE); // From UTF8 to ANSI
|
cd = iconv_open(TOCODE, FROMCODE); // From UTF8 to ANSI
|
||||||
cd_inv = iconv_open(FROMCODE, TOCODE); // From ANSI to UTF8
|
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 */
|
#endif /* ENABLE_FILENAMES_ICONV */
|
||||||
|
|
||||||
// On en profite pour le mémoriser dans le répertoire principal:
|
// On en profite pour le mémoriser dans le répertoire principal:
|
||||||
|
|||||||
@ -180,9 +180,11 @@ typedef struct T_Fileselector_item
|
|||||||
|
|
||||||
struct T_Fileselector_item * Next; ///< Pointer to next item of the current fileselector.
|
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.
|
struct T_Fileselector_item * Previous;///< Pointer to previous item of the current fileselector.
|
||||||
|
|
||||||
|
word * Unicode_full_name; ///< Pointer to allocated unicode string. Filesystem name
|
||||||
|
word * Unicode_short_name; ///< Pointer to allocated unicode string. Name to display
|
||||||
|
|
||||||
word Length_short_name; ///< Number of bytes allocated for :Short_name
|
#if __GNUC__ < 3
|
||||||
#if __GNUC__ < 3
|
|
||||||
char Short_name[0]; ///< Name to display.
|
char Short_name[0]; ///< Name to display.
|
||||||
#else
|
#else
|
||||||
char Short_name[]; ///< Name to display.
|
char Short_name[]; ///< Name to display.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user