GUI skins and fileselectors: cleaned up a little

git-svn-id: svn://pulkomandy.tk/GrafX2/trunk@886 416bcca6-2ee7-4201-b75f-2eb2f807beb1
This commit is contained in:
Yves Rizoud 2009-06-28 18:19:21 +00:00
parent ab9671b286
commit 67dbb218a2
6 changed files with 233 additions and 177 deletions

View File

@ -958,15 +958,13 @@ void Button_Settings(void)
Set_number_of_backups(Config.Max_undo_pages); Set_number_of_backups(Config.Max_undo_pages);
} }
// POSIX calls it strcasecmp, Windows uses stricmp... no ANSI standard. // Data for skin selector
#ifdef __linux__ T_Fileselector Skin_files_list;
#define stricmp strcasecmp
#endif
// Add a skin to the list // Add a skin to the list
void Add_skin(const char *name) void Add_skin(const char *name)
{ {
char * fname; const char * fname;
int namelength; int namelength;
// Cut the long name to keep only filename (no directory) // Cut the long name to keep only filename (no directory)
@ -976,43 +974,28 @@ void Add_skin(const char *name)
else else
fname=name; fname=name;
namelength = strlen(fname); namelength = strlen(fname);
if (namelength>=5 && fname[0]!='_' && (!stricmp(fname+namelength-4,".png") || !stricmp(fname+namelength-4,".gif"))) if (namelength>=5 && fname[0]!='_' && (!strcasecmp(fname+namelength-4,".png") || !strcasecmp(fname+namelength-4,".gif")))
{ {
Add_element_to_list(name, 0); Add_element_to_list(&Skin_files_list, name, 0);
Filelist_nb_elements++;
if (fname[0]=='\0') if (fname[0]=='\0')
return; return;
strcpy(Filelist->Full_name, fname); strcpy(Skin_files_list.First->Full_name, fname);
// Reformat the short name differently
// Reformat the short name strcpy(Skin_files_list.First->Short_name,Format_filename(Skin_files_list.First->Full_name, 0));
strcpy(Filelist->Short_name,Format_filename(Filelist->Full_name, 0));
} }
} }
T_Fileselector_item * Get_selected_skin(word index)
{
T_Fileselector_item * current_item;
// Fast-forward to the requested item.
current_item=Filelist;
for (;index>0;index--)
current_item=current_item->Next;
// I know it's highly inefficient (O(n²)) but there shouldn't be dozens
// of skins in the directory...
return current_item;
}
// Callback to display a skin name in the list // Callback to display a skin name in the list
void Draw_one_skin_name(word x, word y, word index, byte highlighted) void Draw_one_skin_name(word x, word y, word index, byte highlighted)
{ {
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
if (Filelist_nb_elements>0) if (Skin_files_list.Nb_elements)
{ {
current_item = Get_selected_skin(index); current_item = Get_item_by_index(&Skin_files_list, index);
Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light); Print_in_window(x,y,current_item->Short_name, MC_Black, (highlighted)?MC_Dark:MC_Light);
} }
} }
@ -1046,15 +1029,14 @@ void Button_Skins(void)
// Here we use the same data container as the fileselectors. // Here we use the same data container as the fileselectors.
// Reinitialize the list // Reinitialize the list
Free_fileselector_list(); Free_fileselector_list(&Skin_files_list);
Filelist_nb_elements=0;
// Browse the "skins" directory // Browse the "skins" directory
strcpy(skinsdir,Data_directory); strcpy(skinsdir,Data_directory);
strcat(skinsdir,"skins"); strcat(skinsdir,"skins");
// Add each found file to the list // Add each found file to the list
For_each_file(skinsdir, Add_skin); For_each_file(skinsdir, Add_skin);
// Sort it // Sort it
Sort_list_of_files(); Sort_list_of_files(&Skin_files_list);
// -------------------------------------------------------------- // --------------------------------------------------------------
@ -1075,7 +1057,7 @@ void Button_Skins(void)
// Fileselector // Fileselector
Window_set_special_button(8,FILESEL_Y+1,144,80), // 2 Window_set_special_button(8,FILESEL_Y+1,144,80), // 2
// Scroller du fileselector // Scroller du fileselector
(file_scroller = Window_set_scroller_button(160,FILESEL_Y+1,82,Filelist_nb_elements,10,selector_position)), // 3 (file_scroller = Window_set_scroller_button(160,FILESEL_Y+1,82,Skin_files_list.Nb_elements,10,selector_position)), // 3
Draw_one_skin_name); // 4 Draw_one_skin_name); // 4
// Boutons de fontes // Boutons de fontes
@ -1226,7 +1208,7 @@ void Button_Skins(void)
{ {
quicksearch_filename[temp]=Key_ANSI; quicksearch_filename[temp]=Key_ANSI;
quicksearch_filename[temp+1]='\0'; quicksearch_filename[temp+1]='\0';
most_matching_filename=Find_filename_match(quicksearch_filename); most_matching_filename=Find_filename_match(Skin_files_list, quicksearch_filename);
if ( (most_matching_filename) ) if ( (most_matching_filename) )
{ {
temp=Main_fileselector_position+Main_fileselector_offset; temp=Main_fileselector_position+Main_fileselector_offset;
@ -1255,7 +1237,7 @@ void Button_Skins(void)
strcpy(skinsdir,"skins/"); strcpy(skinsdir,"skins/");
strcat( strcat(
skinsdir, skinsdir,
Get_selected_skin(skin_list->List_start+skin_list->Cursor_position)->Full_name); Get_item_by_index(&Skin_files_list, skin_list->List_start+skin_list->Cursor_position)->Full_name);
gfx=Load_graphics(skinsdir); gfx=Load_graphics(skinsdir);
if (gfx == NULL) // Error if (gfx == NULL) // Error
{ {

309
filesel.c
View File

@ -64,14 +64,58 @@
#define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de repértoire sélectionnée #define SELECTED_DIRECTORY_COLOR MC_Light // color du texte pour une ligne de repértoire sélectionnée
#define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne sélectionnée #define SELECTED_BACKGROUND_COLOR MC_Dark // color du fond pour une ligne sélectionnée
// -- Fileselector data
T_Fileselector Filelist;
// Conventions: // Conventions:
// //
// * Le fileselect modifie le répertoire courant. Ceci permet de n'avoir // * Le fileselect modifie le répertoire courant. Ceci permet de n'avoir
// qu'un findfirst dans le répertoire courant à faire: // qu'un findfirst dans le répertoire courant à faire:
void Recount_files(T_Fileselector *list)
{
T_Fileselector_item *item;
// -- Déstruction de la liste chaînée --------------------------------------- list->Nb_files=0;
void Free_fileselector_list(void) list->Nb_directories=0;
list->Nb_elements=0;
for (item = list->First; item != NULL; item = item->Next)
{
if (item->Type == 0)
list->Nb_files ++;
else
list->Nb_directories ++;
list->Nb_elements ++;
}
if (list->Index)
{
free(list->Index);
list->Index = NULL;
}
if (list->Nb_elements>0)
{
int i;
list->Index = (T_Fileselector_item **) malloc(list->Nb_elements * sizeof(T_Fileselector_item **));
if (list->Index)
{
// Fill the index
for (item = list->First, i=0; item != NULL; item = item->Next, i++)
{
list->Index[i] = item;
}
}
// If the malloc failed, we're probably in trouble, but I don't know
// how to recover from that..I'll just make the index bulletproof.
}
}
// -- Destruction de la liste chaînée ---------------------------------------
void Free_fileselector_list(T_Fileselector *list)
// Cette procédure détruit la chaine des fichiers. Elle doit être appelée // Cette procédure détruit la chaine des fichiers. Elle doit être appelée
// avant de rappeler la fonction Read_list_of_files, ainsi qu'en fin de // avant de rappeler la fonction Read_list_of_files, ainsi qu'en fin de
// programme. // programme.
@ -79,23 +123,19 @@ void Free_fileselector_list(void)
// Pointeur temporaire de destruction // Pointeur temporaire de destruction
T_Fileselector_item * temp_item; T_Fileselector_item * temp_item;
while (Filelist!=NULL) while (list->First!=NULL)
{ {
// On mémorise l'adresse du premier élément de la liste // On mémorise l'adresse du premier élément de la liste
temp_item =Filelist; temp_item =list->First;
// On fait avancer la tête de la liste // On fait avancer la tête de la liste
Filelist=Filelist->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); free(temp_item);
} }
Recount_files(list);
} }
char * Format_filename(const char * fname, int type)
///
/// 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 19 characters
/// including the '\0'.
char * Format_filename(char * fname, int type)
{ {
static char result[19]; static char result[19];
int c; int c;
@ -148,7 +188,7 @@ char * Format_filename(char * fname, 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(char * fname, int type) void Add_element_to_list(T_Fileselector *list, const char * fname, int type)
// Cette procedure ajoute a la liste chainee un fichier passé en argument. // Cette procedure ajoute a la liste chainee un fichier passé en argument.
{ {
// Pointeur temporaire d'insertion // Pointeur temporaire d'insertion
@ -162,12 +202,12 @@ void Add_element_to_list(char * fname, int type)
strcpy(temp_item->Full_name,fname); strcpy(temp_item->Full_name,fname);
temp_item->Type = type; temp_item->Type = type;
temp_item->Next =Filelist; temp_item->Next =list->First;
temp_item->Previous=NULL; temp_item->Previous=NULL;
if (Filelist!=NULL) if (list->First!=NULL)
Filelist->Previous=temp_item; list->First->Previous=temp_item;
Filelist=temp_item; list->First=temp_item;
} }
// -- Vérification si un fichier a l'extension demandée. // -- Vérification si un fichier a l'extension demandée.
@ -203,7 +243,7 @@ int Check_extension(const char *filename, char * filter)
// -- Lecture d'une liste de fichiers --------------------------------------- // -- Lecture d'une liste de fichiers ---------------------------------------
void Read_list_of_files(byte selected_format) void Read_list_of_files(T_Fileselector *list, byte selected_format)
// Cette procédure charge dans la liste chainée les fichiers dont l'extension // Cette procédure charge dans la liste chainée les fichiers dont l'extension
// correspond au format demandé. // correspond au format demandé.
{ {
@ -218,10 +258,8 @@ void Read_list_of_files(byte selected_format)
filter = File_formats[selected_format-1].Extension; filter = File_formats[selected_format-1].Extension;
// Ensuite, on vide la liste actuelle: // Ensuite, on vide la liste actuelle:
Free_fileselector_list(); Free_fileselector_list(list);
// Après effacement, il ne reste ni fichier ni répertoire dans la liste // Après effacement, il ne reste ni fichier ni répertoire dans la liste
Filelist_nb_files=0;
Filelist_nb_directories=0;
// On lit tous les répertoires: // On lit tous les répertoires:
current_path=getcwd(NULL,0); current_path=getcwd(NULL,0);
@ -243,8 +281,8 @@ void Read_list_of_files(byte selected_format)
!isHidden(entry))) !isHidden(entry)))
{ {
// On rajoute le répertoire à la liste // On rajoute le répertoire à la liste
Add_element_to_list(entry->d_name, 1); Add_element_to_list(list, entry->d_name, 1);
Filelist_nb_directories++; list->Nb_directories++;
} }
else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier else if (S_ISREG(Infos_enreg.st_mode) && //Il s'agit d'un fichier
(Config.Show_hidden_files || //Il n'est pas caché (Config.Show_hidden_files || //Il n'est pas caché
@ -253,21 +291,21 @@ void Read_list_of_files(byte selected_format)
if (Check_extension(entry->d_name, filter)) if (Check_extension(entry->d_name, filter))
{ {
// On rajoute le fichier à la liste // On rajoute le fichier à la liste
Add_element_to_list(entry->d_name, 0); Add_element_to_list(list, entry->d_name, 0);
Filelist_nb_files++; list->Nb_files++;
} }
} }
} }
#if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__) #if defined(__MORPHOS__) || defined(__AROS__) || defined (__amigaos4__) || defined(__amigaos__)
Add_element_to_list("/",1); // on amiga systems, / means parent. And there is no .. Add_element_to_list(list, "/",1); // on amiga systems, / means parent. And there is no ..
Filelist_nb_directories ++; list->Nb_directories ++;
#endif #endif
closedir(current_directory); closedir(current_directory);
free(current_path); free(current_path);
Filelist_nb_elements=Filelist_nb_directories+Filelist_nb_files; Recount_files(list);
} }
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
@ -290,14 +328,14 @@ void bstrtostr( BSTR in, STRPTR out, TEXT max )
#endif #endif
// -- Lecture d'une liste de lecteurs / volumes ----------------------------- // -- Lecture d'une liste de lecteurs / volumes -----------------------------
void Read_list_of_drives(void) void Read_list_of_drives(T_Fileselector *list)
{ {
// Empty the current content of fileselector: // Empty the current content of fileselector:
Free_fileselector_list(); Free_fileselector_list(list);
// Reset number of items // Reset number of items
Filelist_nb_files=0; list->Nb_files=0;
Filelist_nb_directories=0; list->Nb_directories=0;
#if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__) #if defined(__amigaos4__) || defined(__AROS__) || defined(__MORPHOS__) || defined(__amigaos__)
{ {
@ -311,8 +349,8 @@ void Read_list_of_drives(void)
{ {
bstrtostr( dl->dol_Name, tmp, 254 ); bstrtostr( dl->dol_Name, tmp, 254 );
strcat( tmp, ":" ); strcat( tmp, ":" );
Add_element_to_list( tmp, 2 ); Add_element_to_list(list, tmp, 2 );
Filelist_nb_directories++; list->Nb_directories++;
} }
UnLockDosList( LDF_VOLUMES | LDF_READ ); UnLockDosList( LDF_VOLUMES | LDF_READ );
} }
@ -354,8 +392,8 @@ void Read_list_of_drives(void)
break; break;
} }
drive_name[0]='A'+bit_index; drive_name[0]='A'+bit_index;
Add_element_to_list(drive_name,2); Add_element_to_list(list, drive_name,2);
Filelist_nb_directories++; list->Nb_directories++;
drive_index++; drive_index++;
} }
} }
@ -368,7 +406,7 @@ void Read_list_of_drives(void)
// Ensuite on utilise read_file_system_list pour compléter // Ensuite on utilise read_file_system_list pour compléter
struct mount_entry* Liste_points_montage; struct mount_entry* mount_points_list;
struct mount_entry* next; struct mount_entry* next;
#if defined(__BEOS__) || defined(__HAIKU__) #if defined(__BEOS__) || defined(__HAIKU__)
@ -376,42 +414,42 @@ void Read_list_of_drives(void)
#else #else
char * home_dir = getenv("HOME"); char * home_dir = getenv("HOME");
#endif #endif
Add_element_to_list("/", 2); Add_element_to_list(list, "/", 2);
Filelist_nb_directories++; list->Nb_directories++;
if(home_dir) if(home_dir)
{ {
Add_element_to_list(home_dir, 2); Add_element_to_list(list, home_dir, 2);
Filelist_nb_directories++; list->Nb_directories++;
} }
Liste_points_montage = read_file_system_list(0); mount_points_list = read_file_system_list(0);
while(Liste_points_montage != NULL) while(mount_points_list != NULL)
{ {
if(Liste_points_montage->me_dummy == 0 && strcmp(Liste_points_montage->me_mountdir,"/") && strcmp(Liste_points_montage->me_mountdir,"/home")) if(mount_points_list->me_dummy == 0 && strcmp(mount_points_list->me_mountdir,"/") && strcmp(mount_points_list->me_mountdir,"/home"))
{ {
Add_element_to_list(Liste_points_montage->me_mountdir,2); Add_element_to_list(list, mount_points_list->me_mountdir,2);
Filelist_nb_directories++; list->Nb_directories++;
} }
next = Liste_points_montage -> me_next; next = mount_points_list -> me_next;
#if !(defined(__macosx__) || defined(__FreeBSD__)) #if !(defined(__macosx__) || defined(__FreeBSD__))
free(Liste_points_montage -> me_type); free(mount_points_list -> me_type);
#endif #endif
free(Liste_points_montage -> me_devname); free(mount_points_list -> me_devname);
free(Liste_points_montage -> me_mountdir); free(mount_points_list -> me_mountdir);
free(Liste_points_montage); free(mount_points_list);
Liste_points_montage = next; mount_points_list = next;
} }
} }
#endif #endif
Filelist_nb_elements=Filelist_nb_directories+Filelist_nb_files; Recount_files(list);
} }
// -- Tri de la liste des fichiers et répertoires --------------------------- // -- Tri de la liste des fichiers et répertoires ---------------------------
void Sort_list_of_files(void) void Sort_list_of_files(T_Fileselector *list)
// Tri la liste chainée existante dans l'ordre suivant: // Tri la liste chainée existante dans l'ordre suivant:
// //
// * Les répertoires d'abord, dans l'ordre alphabétique de leur nom // * Les répertoires d'abord, dans l'ordre alphabétique de leur nom
@ -426,14 +464,14 @@ void Sort_list_of_files(void)
// Avant de trier quoi que ce soit, on vérifie qu'il y ait suffisamment // Avant de trier quoi que ce soit, on vérifie qu'il y ait suffisamment
// d'éléments pour qu'il soit possibles qu'ils soient en désordre: // d'éléments pour qu'il soit possibles qu'ils soient en désordre:
if (Filelist_nb_elements>1) if (list->Nb_elements>1)
{ {
do do
{ {
// Par défaut, on considère que la liste est triée // Par défaut, on considère que la liste est triée
list_is_sorted=1; list_is_sorted=1;
current_item=Filelist; current_item=list->First;
next_item=current_item->Next; next_item=current_item->Next;
while ( (current_item!=NULL) && (next_item!=NULL) ) while ( (current_item!=NULL) && (next_item!=NULL) )
@ -478,8 +516,8 @@ void Sort_list_of_files(void)
next_to_next_item->Previous=current_item; next_to_next_item->Previous=current_item;
// On fait bien attention à modifier la tête de liste en cas de besoin // On fait bien attention à modifier la tête de liste en cas de besoin
if (current_item==Filelist) if (current_item==list->First)
Filelist=next_item; list->First=next_item;
// Ensuite, on se prépare à étudier les éléments précédents: // Ensuite, on se prépare à étudier les éléments précédents:
current_item=prev_item; current_item=prev_item;
@ -499,11 +537,34 @@ void Sort_list_of_files(void)
} }
while (!list_is_sorted); while (!list_is_sorted);
} }
// Force a recount / re-index
Recount_files(list);
}
T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index)
{
if (list->Index)
{
return list->Index[index];
}
else
{
// Index not available.
// Can only happen in case of malloc error.
// Fall back anyway on iterative search
T_Fileselector_item * item = list->First;
for (;index>0;index--)
item = item->Next;
return item;
}
} }
// -- Affichage des éléments de la liste de fichier / répertoire ------------ // -- Affichage des éléments de la liste de fichier / répertoire ------------
void Display_file_list(short offset_first,short selector_offset) void Display_file_list(T_Fileselector *list, short offset_first,short selector_offset)
// //
// offset_first = Décalage entre le premier fichier visible dans le // offset_first = Décalage entre le premier fichier visible dans le
// sélecteur et le premier fichier de la liste // sélecteur et le premier fichier de la liste
@ -519,12 +580,10 @@ void Display_file_list(short offset_first,short selector_offset)
// On vérifie s'il y a au moins 1 fichier dans la liste: // On vérifie s'il y a au moins 1 fichier dans la liste:
if (Filelist_nb_elements>0) if (list->Nb_elements>0)
{ {
// On commence par chercher à pointer sur le premier fichier visible: // On commence par chercher à pointer sur le premier fichier visible:
current_item=Filelist; current_item = Get_item_by_index(list, offset_first);
for (;offset_first>0;offset_first--)
current_item=current_item->Next;
// Pour chacun des 10 éléments inscriptibles à l'écran // Pour chacun des 10 éléments inscriptibles à l'écran
for (index=0;index<10;index++) for (index=0;index<10;index++)
@ -566,7 +625,7 @@ void Display_file_list(short offset_first,short selector_offset)
// -- Récupérer le libellé d'un élément de la liste ------------------------- // -- Récupérer le libellé d'un élément de la liste -------------------------
void Get_selected_item(short offset_first,short selector_offset,char * label,int *type) void Get_selected_item(T_Fileselector *list, short offset_first,short selector_offset,char * label,int *type)
// //
// offset_first = Décalage entre le premier fichier visible dans le // offset_first = Décalage entre le premier fichier visible dans le
// sélecteur et le premier fichier de la liste // sélecteur et le premier fichier de la liste
@ -582,16 +641,11 @@ void Get_selected_item(short offset_first,short selector_offset,char * label,int
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
// On vérifie s'il y a au moins 1 fichier dans la liste: // On vérifie s'il y a au moins 1 fichier dans la liste:
if (Filelist_nb_elements>0) if (list->Nb_elements>0)
{ {
// On commence par chercher à pointer sur le premier fichier visible: // On commence par chercher à pointer sur le premier fichier visible:
current_item=Filelist;
for (;offset_first>0;offset_first--)
current_item=current_item->Next;
// Ensuite, on saute autant d'éléments que le décalage demandé: // Ensuite, on saute autant d'éléments que le décalage demandé:
for (;selector_offset>0;selector_offset--) current_item = Get_item_by_index(list, offset_first + selector_offset);
current_item=current_item->Next;
// On recopie la chaîne // On recopie la chaîne
strcpy(label, current_item->Full_name); strcpy(label, current_item->Full_name);
@ -608,12 +662,12 @@ void Selector_scroll_down(short * offset_first,short * selector_offset)
// Fait scroller vers le bas le sélecteur de fichier... (si possible) // Fait scroller vers le bas le sélecteur de fichier... (si possible)
{ {
if ( ((*selector_offset)<9) if ( ((*selector_offset)<9)
&& ( (*selector_offset)+1 < Filelist_nb_elements ) ) && ( (*selector_offset)+1 < Filelist.Nb_elements ) )
// Si la sélection peut descendre // Si la sélection peut descendre
Display_file_list(*offset_first,++(*selector_offset)); Display_file_list(&Filelist, *offset_first,++(*selector_offset));
else // Sinon, descendre la fenêtre (si possible) else // Sinon, descendre la fenêtre (si possible)
if ((*offset_first)+10<Filelist_nb_elements) if ((*offset_first)+10<Filelist.Nb_elements)
Display_file_list(++(*offset_first),*selector_offset); Display_file_list(&Filelist, ++(*offset_first),*selector_offset);
} }
@ -622,38 +676,38 @@ void Selector_scroll_up(short * offset_first,short * selector_offset)
{ {
if ((*selector_offset)>0) if ((*selector_offset)>0)
// Si la sélection peut monter // Si la sélection peut monter
Display_file_list(*offset_first,--(*selector_offset)); Display_file_list(&Filelist, *offset_first,--(*selector_offset));
else // Sinon, monter la fenêtre (si possible) else // Sinon, monter la fenêtre (si possible)
if ((*offset_first)>0) if ((*offset_first)>0)
Display_file_list(--(*offset_first),*selector_offset); Display_file_list(&Filelist, --(*offset_first),*selector_offset);
} }
void Selector_page_down(short * offset_first,short * selector_offset, short lines) void Selector_page_down(short * offset_first,short * selector_offset, short lines)
{ {
if (Filelist_nb_elements-1>*offset_first+*selector_offset) if (Filelist.Nb_elements-1>*offset_first+*selector_offset)
{ {
if (*selector_offset<9) if (*selector_offset<9)
{ {
if (Filelist_nb_elements<10) if (Filelist.Nb_elements<10)
{ {
*offset_first=0; *offset_first=0;
*selector_offset=Filelist_nb_elements-1; *selector_offset=Filelist.Nb_elements-1;
} }
else *selector_offset=9; else *selector_offset=9;
} }
else else
{ {
if (Filelist_nb_elements>*offset_first+18) if (Filelist.Nb_elements>*offset_first+18)
*offset_first+=lines; *offset_first+=lines;
else else
{ {
*offset_first=Filelist_nb_elements-10; *offset_first=Filelist.Nb_elements-10;
*selector_offset=9; *selector_offset=9;
} }
} }
} }
Display_file_list(*offset_first,*selector_offset); Display_file_list(&Filelist, *offset_first,*selector_offset);
} }
@ -671,29 +725,29 @@ void Selector_page_up(short * offset_first,short * selector_offset, short lines)
*offset_first=0; *offset_first=0;
} }
} }
Display_file_list(*offset_first,*selector_offset); Display_file_list(&Filelist, *offset_first,*selector_offset);
} }
void Selector_end(short * offset_first,short * selector_offset) void Selector_end(short * offset_first,short * selector_offset)
{ {
if (Filelist_nb_elements<10) if (Filelist.Nb_elements<10)
{ {
*offset_first=0; *offset_first=0;
*selector_offset=Filelist_nb_elements-1; *selector_offset=Filelist.Nb_elements-1;
} }
else else
{ {
*offset_first=Filelist_nb_elements-10; *offset_first=Filelist.Nb_elements-10;
*selector_offset=9; *selector_offset=9;
} }
Display_file_list(*offset_first,*selector_offset); Display_file_list(&Filelist, *offset_first,*selector_offset);
} }
void Selector_home(short * offset_first,short * selector_offset) void Selector_home(short * offset_first,short * selector_offset)
{ {
Display_file_list((*offset_first)=0,(*selector_offset)=0); Display_file_list(&Filelist, (*offset_first)=0,(*selector_offset)=0);
} }
@ -708,8 +762,8 @@ short Compute_click_offset_in_fileselector(void)
short computed_offset; short computed_offset;
computed_offset=(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-95)>>3; computed_offset=(((Mouse_Y-Window_pos_Y)/Menu_factor_Y)-95)>>3;
if (computed_offset>=Filelist_nb_elements) if (computed_offset>=Filelist.Nb_elements)
computed_offset=Filelist_nb_elements-1; computed_offset=Filelist.Nb_elements-1;
return computed_offset; return computed_offset;
} }
@ -803,22 +857,21 @@ void Print_filename_in_fileselector(void)
int Selected_type; // Utilisé pour mémoriser le type d'entrée choisi int Selected_type; // Utilisé pour mémoriser le type d'entrée choisi
// dans le selecteur de fichier. // dans le selecteur de fichier.
void Prepare_and_display_filelist(short Position, short offset, void Prepare_and_display_filelist(short Position, short offset, T_Scroller_button * button)
T_Scroller_button * button)
{ {
button->Nb_elements=Filelist_nb_elements; button->Nb_elements=Filelist.Nb_elements;
button->Position=Position; button->Position=Position;
Compute_slider_cursor_height(button); Compute_slider_cursor_height(button);
Window_draw_slider(button); Window_draw_slider(button);
// On efface les anciens noms de fichier: // On efface les anciens noms de fichier:
Window_rectangle(8-1,95-1,144+2,80+2,MC_Black); Window_rectangle(8-1,95-1,144+2,80+2,MC_Black);
// On affiche les nouveaux: // On affiche les nouveaux:
Display_file_list(Position,offset); Display_file_list(&Filelist, Position,offset);
Update_window_area(8-1,95-1,144+2,80+2); Update_window_area(8-1,95-1,144+2,80+2);
// On récupère le nom du schmilblick à "accéder" // On récupère le nom du schmilblick à "accéder"
Get_selected_item(Position,offset,Main_filename,&Selected_type); Get_selected_item(&Filelist, Position,offset,Main_filename,&Selected_type);
// On affiche le nouveau nom de fichier // On affiche le nouveau nom de fichier
Print_filename_in_fileselector(); Print_filename_in_fileselector();
// On affiche le nom du répertoire courant // On affiche le nom du répertoire courant
@ -826,11 +879,10 @@ void Prepare_and_display_filelist(short Position, short offset,
} }
void Reload_list_of_files(byte filter, short Position, short offset, void Reload_list_of_files(byte filter, short Position, short offset, T_Scroller_button * button)
T_Scroller_button * button)
{ {
Read_list_of_files(filter); Read_list_of_files(&Filelist, filter);
Sort_list_of_files(); Sort_list_of_files(&Filelist);
Prepare_and_display_filelist(Position,offset,button); Prepare_and_display_filelist(Position,offset,button);
} }
@ -848,7 +900,7 @@ void Scroll_fileselector(T_Scroller_button * file_scroller)
Window_draw_slider(file_scroller); Window_draw_slider(file_scroller);
} }
// On récupére le nom du schmilblick à "accéder" // On récupére le nom du schmilblick à "accéder"
Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type);
if (strcmp(old_filename,Main_filename)) if (strcmp(old_filename,Main_filename))
New_preview_is_needed=1; New_preview_is_needed=1;
@ -858,12 +910,12 @@ void Scroll_fileselector(T_Scroller_button * file_scroller)
} }
short Find_file_in_fileselector(char * fname) short Find_file_in_fileselector(T_Fileselector *list, char * fname)
{ {
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
short index; short index;
for (index=0, current_item=Filelist; for (index=0, current_item=list->First;
((current_item!=NULL) && (strcmp(current_item->Full_name,fname))); ((current_item!=NULL) && (strcmp(current_item->Full_name,fname)));
index++,current_item=current_item->Next); index++,current_item=current_item->Next);
@ -875,18 +927,18 @@ void Highlight_file(char * fname)
{ {
short index; short index;
index=Find_file_in_fileselector(fname); index=Find_file_in_fileselector(&Filelist, fname);
if ((Filelist_nb_elements<=10) || (index<5)) if ((Filelist.Nb_elements<=10) || (index<5))
{ {
Main_fileselector_position=0; Main_fileselector_position=0;
Main_fileselector_offset=index; Main_fileselector_offset=index;
} }
else else
{ {
if (index>=Filelist_nb_elements-5) if (index>=Filelist.Nb_elements-5)
{ {
Main_fileselector_position=Filelist_nb_elements-10; Main_fileselector_position=Filelist.Nb_elements-10;
Main_fileselector_offset=index-Main_fileselector_position; Main_fileselector_offset=index-Main_fileselector_position;
} }
else else
@ -898,18 +950,16 @@ void Highlight_file(char * fname)
} }
char FFF_best_name[MAX_PATH_CHARACTERS]; char * Find_filename_match(T_Fileselector *list, char * fname)
char * Find_filename_match(char * fname)
{ {
char * best_name_ptr; char * best_name_ptr;
T_Fileselector_item * current_item; T_Fileselector_item * current_item;
byte matching_letters=0; byte matching_letters=0;
byte counter; byte counter;
strcpy(FFF_best_name,Main_filename);
best_name_ptr=NULL; best_name_ptr=NULL;
for (current_item=Filelist; current_item!=NULL; current_item=current_item->Next) for (current_item=list->First; current_item!=NULL; current_item=current_item->Next)
{ {
if ( (!Config.Find_file_fast) if ( (!Config.Find_file_fast)
|| (Config.Find_file_fast==(current_item->Type+1)) ) || (Config.Find_file_fast==(current_item->Type+1)) )
@ -919,7 +969,6 @@ char * Find_filename_match(char * fname)
if (counter>matching_letters) if (counter>matching_letters)
{ {
matching_letters=counter; matching_letters=counter;
strcpy(FFF_best_name,current_item->Full_name);
best_name_ptr=current_item->Full_name; best_name_ptr=current_item->Full_name;
} }
} }
@ -1118,12 +1167,12 @@ byte Button_Load_or_Save(byte load, byte image)
break; break;
case 3 : // Delete case 3 : // Delete
if (Filelist_nb_elements && (*Main_filename!='.') && Selected_type!=2) if (Filelist.Nb_elements && (*Main_filename!='.') && Selected_type!=2)
{ {
char * message; char * message;
Hide_cursor(); Hide_cursor();
// On affiche une demande de confirmation // On affiche une demande de confirmation
if (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) if (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories)
{ {
message="Delete file ?"; message="Delete file ?";
} }
@ -1134,7 +1183,7 @@ byte Button_Load_or_Save(byte load, byte image)
if (Confirmation_box(message)) if (Confirmation_box(message))
{ {
// Si c'est un fichier // Si c'est un fichier
if (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) if (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories)
// On efface le fichier (si on peut) // On efface le fichier (si on peut)
temp=(!remove(Main_filename)); temp=(!remove(Main_filename));
else // Si c'est un repertoire else // Si c'est un repertoire
@ -1144,7 +1193,7 @@ byte Button_Load_or_Save(byte load, byte image)
if (temp) // temp indique si l'effacement s'est bien passé if (temp) // temp indique si l'effacement s'est bien passé
{ {
// On remonte si c'était le dernier élément de la liste // On remonte si c'était le dernier élément de la liste
if (Main_fileselector_position+Main_fileselector_offset==Filelist_nb_elements-1) if (Main_fileselector_position+Main_fileselector_offset==Filelist.Nb_elements-1)
{ {
if (Main_fileselector_position) if (Main_fileselector_position)
Main_fileselector_position--; Main_fileselector_position--;
@ -1155,7 +1204,7 @@ byte Button_Load_or_Save(byte load, byte image)
else // Si ce n'était pas le dernier, il faut faire gaffe à ce else // Si ce n'était pas le dernier, il faut faire gaffe à ce
{ // que ses copains d'en dessous ne remontent pas trop. { // que ses copains d'en dessous ne remontent pas trop.
if ( (Main_fileselector_position) if ( (Main_fileselector_position)
&& (Main_fileselector_position+10==Filelist_nb_elements) ) && (Main_fileselector_position+10==Filelist.Nb_elements) )
{ {
Main_fileselector_position--; Main_fileselector_position--;
Main_fileselector_offset++; Main_fileselector_offset++;
@ -1192,11 +1241,11 @@ byte Button_Load_or_Save(byte load, byte image)
Main_fileselector_offset=temp; Main_fileselector_offset=temp;
// On récupére le nom du schmilblick à "accéder" // On récupére le nom du schmilblick à "accéder"
Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type);
// On affiche le nouveau nom de fichier // On affiche le nouveau nom de fichier
Print_filename_in_fileselector(); Print_filename_in_fileselector();
// On affiche à nouveau la liste // On affiche à nouveau la liste
Display_file_list(Main_fileselector_position,Main_fileselector_offset); Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset);
// On vient de changer de nom de fichier, donc on doit s'appreter // On vient de changer de nom de fichier, donc on doit s'appreter
// a rafficher une preview // a rafficher une preview
@ -1209,8 +1258,8 @@ byte Button_Load_or_Save(byte load, byte image)
// faut mettre le nom de fichier au nom du répertoire. Sinon, dans // faut mettre le nom de fichier au nom du répertoire. Sinon, dans
// certains cas, on risque de sauvegarder avec le nom du fichier // certains cas, on risque de sauvegarder avec le nom du fichier
// actuel au lieu de changer de répertoire. // actuel au lieu de changer de répertoire.
if (Main_fileselector_position+Main_fileselector_offset<Filelist_nb_directories) if (Main_fileselector_position+Main_fileselector_offset<Filelist.Nb_directories)
Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type);
has_clicked_ok=1; has_clicked_ok=1;
New_preview_is_needed=1; New_preview_is_needed=1;
@ -1225,11 +1274,11 @@ byte Button_Load_or_Save(byte load, byte image)
Hide_cursor(); Hide_cursor();
Main_fileselector_position=Window_attribute2; Main_fileselector_position=Window_attribute2;
// On récupére le nom du schmilblick à "accéder" // On récupére le nom du schmilblick à "accéder"
Get_selected_item(Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type); Get_selected_item(&Filelist, Main_fileselector_position,Main_fileselector_offset,Main_filename,&Selected_type);
// On affiche le nouveau nom de fichier // On affiche le nouveau nom de fichier
Print_filename_in_fileselector(); Print_filename_in_fileselector();
// On affiche à nouveau la liste // On affiche à nouveau la liste
Display_file_list(Main_fileselector_position,Main_fileselector_offset); Display_file_list(&Filelist, Main_fileselector_position,Main_fileselector_offset);
Display_cursor(); Display_cursor();
New_preview_is_needed=1; New_preview_is_needed=1;
*quicksearch_filename=0; *quicksearch_filename=0;
@ -1323,8 +1372,8 @@ byte Button_Load_or_Save(byte load, byte image)
Main_fileselector_position=0; Main_fileselector_position=0;
Main_fileselector_offset=0; Main_fileselector_offset=0;
// Affichage des premiers fichiers visibles: // Affichage des premiers fichiers visibles:
Read_list_of_drives(); Read_list_of_drives(&Filelist);
Sort_list_of_files(); Sort_list_of_files(&Filelist);
Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller); Prepare_and_display_filelist(Main_fileselector_position,Main_fileselector_offset,file_scroller);
Display_cursor(); Display_cursor();
New_preview_is_needed=1; New_preview_is_needed=1;
@ -1463,7 +1512,7 @@ byte Button_Load_or_Save(byte load, byte image)
case SDLK_BACKSPACE : // Backspace case SDLK_BACKSPACE : // Backspace
*quicksearch_filename=0; *quicksearch_filename=0;
// Si le choix ".." est bien en tête des propositions... // Si le choix ".." est bien en tête des propositions...
if (!strcmp(Filelist->Full_name,PARENT_DIR)) if (!strcmp(Filelist.First->Full_name,PARENT_DIR))
{ {
// On va dans le répertoire parent. // On va dans le répertoire parent.
strcpy(Main_filename,PARENT_DIR); strcpy(Main_filename,PARENT_DIR);
@ -1485,7 +1534,7 @@ byte Button_Load_or_Save(byte load, byte image)
{ {
quicksearch_filename[temp]=Key_ANSI; quicksearch_filename[temp]=Key_ANSI;
quicksearch_filename[temp+1]='\0'; quicksearch_filename[temp+1]='\0';
most_matching_filename=Find_filename_match(quicksearch_filename); most_matching_filename=Find_filename_match(&Filelist, quicksearch_filename);
if ( (most_matching_filename) ) if ( (most_matching_filename) )
{ {
temp=Main_fileselector_position+Main_fileselector_offset; temp=Main_fileselector_position+Main_fileselector_offset;
@ -1530,8 +1579,8 @@ byte Button_Load_or_Save(byte load, byte image)
getcwd(Main_current_directory,256); getcwd(Main_current_directory,256);
// On lit le nouveau répertoire // On lit le nouveau répertoire
Read_list_of_files(Main_format); Read_list_of_files(&Filelist, Main_format);
Sort_list_of_files(); Sort_list_of_files(&Filelist);
// On place la barre de sélection sur le répertoire d'où l'on vient // On place la barre de sélection sur le répertoire d'où l'on vient
Highlight_file(previous_directory); Highlight_file(previous_directory);
} }
@ -1592,7 +1641,7 @@ byte Button_Load_or_Save(byte load, byte image)
if (Timer_state==1) // Il faut afficher la preview if (Timer_state==1) // Il faut afficher la preview
{ {
if ( (Main_fileselector_position+Main_fileselector_offset>=Filelist_nb_directories) && (Filelist_nb_elements) ) if ( (Main_fileselector_position+Main_fileselector_offset>=Filelist.Nb_directories) && (Filelist.Nb_elements) )
{ {
strcpy(Main_file_directory,Main_current_directory); strcpy(Main_file_directory,Main_current_directory);
@ -1639,7 +1688,7 @@ byte Button_Load_or_Save(byte load, byte image)
Unselect_button((load)?BUTTON_LOAD:BUTTON_SAVE); Unselect_button((load)?BUTTON_LOAD:BUTTON_SAVE);
Display_cursor(); Display_cursor();
Free_fileselector_list(); Free_fileselector_list(&Filelist);
Pixel_load_function=Pixel_load_in_current_screen; Pixel_load_function=Pixel_load_in_current_screen;

View File

@ -23,3 +23,18 @@
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
byte Button_Load_or_Save(byte load, byte image); byte Button_Load_or_Save(byte load, byte image);
void Add_element_to_list(T_Fileselector *list, const char * fname, int type);
///
/// 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 19 characters
/// including the '\0'.
char * Format_filename(const char * fname, int type);
void Free_fileselector_list(T_Fileselector *list);
void Sort_list_of_files(T_Fileselector *list);
void Recount_files(T_Fileselector *list);
T_Fileselector_item * Get_item_by_index(T_Fileselector *list, short index);

View File

@ -881,17 +881,6 @@ GFX2_GLOBAL struct
Func_action Action; ///< Function to call Func_action Action; ///< Function to call
} Operation[NB_OPERATIONS][3][OPERATION_STACK_SIZE]; } Operation[NB_OPERATIONS][3][OPERATION_STACK_SIZE];
// -- Fileselector data
/// Number of elements in the current fileselector's ::Filelist
GFX2_GLOBAL short Filelist_nb_elements;
/// Number of files in the current fileselector's ::Filelist
GFX2_GLOBAL short Filelist_nb_files;
/// Number of directories in the current fileselector's ::Filelist
GFX2_GLOBAL short Filelist_nb_directories;
/// Head of the linked list for the fileselector.
GFX2_GLOBAL T_Fileselector_item * Filelist;
// -- misc // -- misc
/// ///

2
main.c
View File

@ -355,7 +355,7 @@ int Init_program(int argc,char * argv[])
Brush_fileformat =Main_fileformat; Brush_fileformat =Main_fileformat;
// On initialise ce qu'il faut pour que les fileselects ne plantent pas: // On initialise ce qu'il faut pour que les fileselects ne plantent pas:
Filelist=NULL; // Au début, il n'y a pas de fichiers dans la liste
Main_fileselector_position=0; // Au début, le fileselect est en haut de la liste des fichiers Main_fileselector_position=0; // Au début, le fileselect est en haut de la liste des fichiers
Main_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers Main_fileselector_offset=0; // Au début, le fileselect est en haut de la liste des fichiers
Main_format=0; Main_format=0;

View File

@ -33,6 +33,12 @@
#include "const.h" #include "const.h"
// POSIX calls it strcasecmp, Windows uses stricmp... no ANSI standard.
#ifdef WIN32
#define strcasecmp stricmp
#endif
// Definition of the base data types // Definition of the base data types
/// 8bit unsigned integer /// 8bit unsigned integer
#define byte uint8_t #define byte uint8_t
@ -158,6 +164,21 @@ typedef struct T_Fileselector_item
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.
} T_Fileselector_item; } T_Fileselector_item;
/// Data for a fileselector
typedef struct T_Fileselector
{
/// Number of elements in the current fileselector's ::Filelist
short Nb_elements;
/// Number of files in the current fileselector's ::Filelist
short Nb_files;
/// Number of directories in the current fileselector's ::Filelist
short Nb_directories;
/// Head of the linked list for the fileselector.
T_Fileselector_item * First;
/// Index for direct access to element number N
T_Fileselector_item ** Index;
} T_Fileselector;
typedef struct T_List_button typedef struct T_List_button
{ {
short Number; ///< Unique identifier for all controls short Number; ///< Unique identifier for all controls