/***************************************************************************** Application ASH: cd_tree.c (c) Pierre Adriaans 1994 ------------------------------------------------------------------------------ Module de gestion de l'affichage de l'arbre de la session *****************************************************************************/ #include "ash.h" #define TREEINFO "treeinfo.pash" /* Nom du fichier d'infos */ /* Descripteur de ss-rep: */ struct EleTree_s { char Path[FILENAME_LENGTH]; /* Argument de chdir() */ char DispLine[150]; /* Ligne d'affichage dans la fenetre */ }; /* Element de l'arbre */ struct Tree_s { struct EleTree_s Ele; struct Tree_s *Suivant; struct Tree_s *Prec; }; typedef struct Tree_s Tree_t; static Tree_t *Tree = (Tree_t *)NULL, /* Pointeur de tete de l'arbre */ *EndTree = (Tree_t *)NULL; /* Pointeur sur le dernier element enfile, pour accelerer les insertions en queue */ static int SubDirCount = 0; /* Compteur de ss-rep */ extern char *Home; extern DIR *DummyDir; extern AnswerBoxItem_t *InfoMsg; int SubDir(char *,char *); void InTree(char *,char *); int SearchTree(void); void DispCD_Path(char *,int,int); void DispTreeEntry(char *,char,int,int,int); /***************************************************************************** CD_Tree() ------------------------------------------------------------------------------ Input: / Process: fonction d'affichage d'une fenetre contenant l'arbre de la session de l'utilisateur et permettant de changer de ss-rep dans cette session. Output: 1 si sortie par Enter et donc cd 0 si sortie par Esc et donc rien a faire *****************************************************************************/ int CD_Tree(void) { char Line[80]; /* Ligne transversale */ int Lig,Col,Height,Length, /* Coordonnees exterieures de la fenetre */ ActLig,ActCol, ActHeight,ActLength, /* Cooredonnees de la fenetre d'affichage */ Fini = 0, /* Temoin de fin de boucle */ i,j,Cpt, /* Compteurs */ SelIndex, /* Index de selection */ X,Y, /* Coord du curseur */ rc, /* Code de retour */ NbreEntries, /* Nombre de ss-rep */ InvLig,InvCol; /* Coord de la ligne inverse actuelle */ Tree_t *Current, /* ss-rep actuellement en inverse */ *Dummy = (Tree_t *)NULL, *Temp; /* Pointeurs de manipulation */ char StrTemp[255], /* String tampon */ FileName[80]; /* Nom du fichier treeinfo */ FILE *hf; /* Pour lecture dans le fichier treeinfo */ /* Recuperer la position du curseur */ GetXY(&Y,&X); /* Fixer les coordonnes de la fenetre */ Lig = 3; Col = 6; Height = 20; Length = 70; /* Construire la fenetre */ Line[0] = F_BDSD; for(i=1;i<(Length-7);i++) Line[i] = F_S_HO; Line[i] = F_SDBD; Line[i+1] = 0; OpenWin(Lig,Col,Height,Length,TreeNorm,UNFRAMED,SHADED); Lig +=1; Col += 3; Height -= 2; Length -= 6; ActLig = Lig + 1; ActCol = Col + 2; ActHeight = Height - 6; ActLength = Length - 4; PaintFrame(Lig,Col,Height,Length,TreeNorm,DOUBLE_FRAMED); WriteString(" Directory Tree ",TreeNorm,Lig,33); WriteString(Line,TreeNorm,Lig+Height-5,Col); WriteString("Up/Down arrows to move, Enter to change directory to:", TreeNorm,Lig+Height-4,14); WriteString("Ctrl-R to refresh tree, Ctrl-C (Esc) to cancel.", TreeNorm,Lig+Height-2,17); /* Mettre le curseur hors du chemin */ GotoXY(Y,X); /* Tenter d'ouvrir le fichier treeinfo et de le lire: s'il n'existe pas, le creer */ strcpy(FileName,Home); if(FileName[strlen(FileName) - 1] != PATH_SEPARATOR_CHAR) strcat(FileName,PATH_SEPARATOR_STR); strcat(FileName,TREEINFO); hf = fopen(FileName,"r"); if(hf != (FILE *)NULL) { SubDirCount = 0; while(fgets(StrTemp,254,hf) != NULL) { SubDirCount++; Dummy = (Tree_t *)malloc(sizeof(Tree_t)); if(Dummy == (Tree_t *)NULL) raise(SIGME); Dummy->Suivant = (Tree_t *)NULL; StrTemp[strlen(StrTemp) - 1] = 0; strcpy(Dummy->Ele.Path,StrTemp); fgets(StrTemp,254,hf); StrTemp[strlen(StrTemp) - 1] = 0; strcpy(Dummy->Ele.DispLine,StrTemp); if(Tree == (Tree_t *)NULL) { Tree = Dummy; Tree->Prec = (Tree_t *)NULL; EndTree = Tree; } else { EndTree->Suivant = Dummy; Dummy->Prec = EndTree; EndTree = Dummy; } } fclose(hf); } else if(SearchTree() == -1) { CloseWin(); /* Liberer l'arbre */ Current = Tree; Dummy = (Tree_t *)NULL; while(Current != (Tree_t *)NULL) { Dummy = Current; Current = Current->Suivant; free(Dummy); } Tree = (Tree_t *)NULL; return(0); } /* Initialisation de Current sur le ss-rep courant */ getcwd(Line,64); for(i=0,Current = Tree; (Current != (Tree_t *)NULL) && (strcmp(Current->Ele.Path,Line) != 0); i++,Current = Current->Suivant); if(Current == (Tree_t *)NULL) { /* Non trouve: on est en dehors de la session: mettre le Home en inverse */ Current = Tree; i = 0; } /* i contient le numero d'ordre du ss-rep courant dans la liste: on peut donc tester les possibilites d'affichage */ if(i > ActHeight - 1) { /* Fenetre trop courte pour afficher du debut avec l'inverse sur le ss-rep courant: remonter la liste avec Dummy pour le placer sur le premier ss-rep a afficher */ for(Dummy = Current,j=ActHeight - 1; j > 0 && Dummy != (Tree_t *)NULL; j--,Dummy = Dummy->Prec); /* Afficher a partir de Dummy */ for(Cpt = ActLig; Cpt < (ActLig + ActHeight) && Dummy != (Tree_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DispTreeEntry(Dummy->Ele.DispLine,TreeNorm,Cpt,ActCol,ActLength); /* Fixer les coordonnees de la zone d'inversion */ InvLig = ActLig + ActHeight - 1; InvCol = ActCol; } else { /* Afficher du debut */ for(Cpt = ActLig,Dummy = Tree; Cpt < (ActLig + ActHeight) && Dummy != (Tree_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DispTreeEntry(Dummy->Ele.DispLine,TreeNorm,Cpt,ActCol,ActLength); /* Fixer les coordonnees de la zone d'inversion */ InvLig = ActLig + i; InvCol = ActCol; } /* Inverser l'option courante */ PaintString(InvLig,InvCol,ActLength,TreeInv); /* Affecter les variables de controle */ SelIndex = i; NbreEntries = SubDirCount; /* Afficher le rappel complet du path en dessous */ DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); /* And on y va ! */ while(!Fini) { switch(ReadKbd()) { case CTRL_R: /* Relire l'arbre */ /* Liberer celui en cours */ Current = Tree; Dummy = (Tree_t *)NULL; while(Current != (Tree_t *)NULL) { Dummy = Current; Current = Current->Suivant; free(Dummy); } Tree = (Tree_t *)NULL; SubDirCount = 0; /* Effacer la zone affichable */ ClrZone(ActLig,ActCol,ActHeight,ActLength,TreeNorm); /* Effacer le rapel de ss-rep pointe */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); /* Reconstituer l'arbre */ if(SearchTree() == -1) { CloseWin(); /* Liberer l'arbre */ Current = Tree; Dummy = (Tree_t *)NULL; while(Current != (Tree_t *)NULL) { Dummy = Current; Current = Current->Suivant; free(Dummy); } Tree = (Tree_t *)NULL; return(0); } for(i=0,Current = Tree; (Current != (Tree_t *)NULL) && (strcmp(Current->Ele.Path,Line) != 0); i++,Current = Current->Suivant); if(Current == (Tree_t *)NULL) { /* ss-rep courant absent de la liste: on se trouve en dehors de la session: mettre en inverse le Home */ Current = Tree; i = 0; } /* i contient toujours le numero d'ordre du ss-rep courant dans l'arbre: meme principe que plus haut */ if(i > ActHeight - 1) { /* Fenetre trop courte pour afficher du debut avec l'inverse sur le ss-rep courant: remonter la liste avec Dummy pour le placer sur le premier ss-rep a afficher */ for(Dummy = Current,j=ActHeight - 1; j > 0 && Dummy != (Tree_t *)NULL; j--,Dummy = Dummy->Prec); /* Afficher a partir de Dummy */ for(Cpt = ActLig; Cpt < (ActLig + ActHeight) && Dummy != (Tree_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DispTreeEntry(Dummy->Ele.DispLine,TreeNorm,Cpt,ActCol,ActLength); /* Fixer les coordonnees de la zone d'inversion */ InvLig = ActLig + ActHeight - 1; InvCol = ActCol; } else { /* Afficher du debut */ for(Cpt = ActLig,Dummy = Tree; Cpt < (ActLig + ActHeight) && Dummy != (Tree_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DispTreeEntry(Dummy->Ele.DispLine,TreeNorm,Cpt,ActCol,ActLength); /* Fixer les coordonnees de la zone d'inversion */ InvLig = ActLig + i; InvCol = ActCol; } /* Inverser l'option courante */ PaintString(InvLig,InvCol,ActLength,TreeInv); /* Reaffecter les variables de controle */ SelIndex = i; NbreEntries = SubDirCount; /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); break; case CR: /* Changer de ss-rep */ /* Tester l'accessibilite */ if((DummyDir = opendir(Current->Ele.Path)) == (DIR *)NULL) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, " Sorry, impossible to access the directory "); AddAnswerBoxItem(&InfoMsg,Current->Ele.Path); InfoBox(ErrorNorm,ErrorInv," Change Directory ",InfoMsg,0,0, DOUBLE_FRAMED); } else { closedir(DummyDir); CloseWin(); chdir(Current->Ele.Path); Fini = 1; rc = 1; } break; case DELETE: case CTRL_C: case ESC: /* Quitter sans rien faire */ CloseWin(); Fini = 1; rc = 0; break; case K_UP: if(Current->Prec != (Tree_t *)NULL) { /* Si le choix courant a un predecesseur, y deplacer la barre avec scrolling bas si necessaire */ SelIndex--; PaintString(InvLig,InvCol,ActLength,TreeNorm); Current = Current->Prec; if(InvLig == ActLig) { ScrollDownWin(ActLig,ActCol,ActHeight,ActLength,1); DispTreeEntry(Current->Ele.DispLine,TreeNorm,ActLig,ActCol, ActLength); } else InvLig--; PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; case K_DOWN: /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ if(Current->Suivant != (Tree_t *)NULL) { SelIndex++; /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ PaintString(InvLig,InvCol,ActLength,TreeNorm); Current = Current->Suivant; if(InvLig == ActLig + ActHeight - 1) { ScrollUpWin(ActLig,ActCol,ActHeight,ActLength,1); DispTreeEntry(Current->Ele.DispLine,TreeNorm,ActLig+ActHeight-1, ActCol,ActLength); } else InvLig++; PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; case K_HOME: case CTRL_B: /* Si on est pas deja sur la premiere option, s'y deplacer, avec mise a jour de la porion de liste affichee si necessaire */ if(SelIndex != 0) { if(SelIndex < ActHeight && InvLig - SelIndex >= ActLig) /* L'item 0 est tjs dans la fenetre: simplement deplacer la barre */ PaintString(InvLig,InvCol,ActLength,TreeNorm); else { /* L'item 0 n'est plus dans la fenetre: effacer tous les items et les reafficher a partir du 0, puis y placer la barre */ ClrZone(ActLig,ActCol,ActHeight,ActLength,TreeNorm); for(i = ActLig,Current = Tree; i < (ActLig + ActHeight) && Current != (Tree_t *)NULL; i++,Current = Current->Suivant) DispTreeEntry(Current->Ele.DispLine,TreeNorm,i,ActCol,ActLength); } Current = Tree; SelIndex = 0; InvLig = ActLig; PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; case K_END: case CTRL_E: /* Si on est pas sur la derniere option, s'y placer, avec mise a jour de la porion de liste affichee si necessaire */ if(SelIndex != NbreEntries - 1) { if(InvLig + NbreEntries - SelIndex <= ActLig + ActHeight) /* Le dernier item est deja dans la fenetre: simplement deplacer la barre */ PaintString(InvLig,InvCol,ActLength,TreeNorm); else { /* Le dernier item n'est pas dans la fenetre: effacer tout et les reafficher pour avoir le dernier item en derniere position de la fenetre */ ClrZone(ActLig,ActCol,ActHeight,ActLength,TreeNorm); /* Positionner Current sur le premier item a devoir etre reaffiche en remontant la liste a partir de la fin */ for(i = 0,Current = EndTree; i < ActHeight - 1 && Current != (Tree_t *)NULL; i++,Current = Current->Prec); /* Affichage */ for(i = ActLig; i < (ActLig + ActHeight) && Current != (Tree_t *)NULL; i++,Current = Current->Suivant) DispTreeEntry(Current->Ele.DispLine,TreeNorm,i,ActCol,ActLength); } Current = EndTree; SelIndex = NbreEntries - 1; if(NbreEntries < ActHeight) InvLig = ActLig + SelIndex; else InvLig = ActLig + ActHeight - 1; PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; case CTRL_U: case K_PGUP: /* Si on est au milieu ou a la fin de la fenetre, remonter sur la premiere option Si on est au sommet de la fenetre, rectifier l'affichage vers le haut d'une fenetre moins un element. Si il ne reste pas assez d'elements pour faire ca, reafficher depuis le debut et placer la barre sur le premier element */ if(SelIndex != 0) { PaintString(InvLig,InvCol,ActLength,TreeNorm); if(InvLig != ActLig) { /* La barre est au milieu de la fenetre: simplement la placer au sommet */ for(i=InvLig;i>ActLig;i--,Current = Current->Prec,SelIndex--); InvLig = ActLig; } else { /* La barre est deja au sommet: effacer tout et remonter dans la liste d'un nombre d'items egal a la hauteur de la fenetre. */ for(i = 0; i < ActHeight - 1 && Current != (Tree_t *)NULL; i++,Current = Current->Prec,SelIndex--); /* Si Current est a NULL, c'est que ce qui restait de la liste est plus petit qu'une hauteur de fenetre: on va donc reafficher depuis le debut */ if(Current == (Tree_t *)NULL) { Current = Tree; SelIndex = 0; } /* Affichage */ Temp = Current; ClrZone(ActLig,ActCol,ActHeight,ActLength,TreeNorm); for(i = ActLig; i < (ActLig + ActHeight) && Temp != (Tree_t *)NULL; i++,Temp = Temp->Suivant) DispTreeEntry(Temp->Ele.DispLine,TreeNorm,i,ActCol,ActLength); InvLig = ActLig; } PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; case CTRL_D: case K_PGDN: /* Idem PgUp, mais vers le bas */ if(SelIndex != NbreEntries - 1) { PaintString(InvLig,InvCol,ActLength,TreeNorm); if(InvLig != ActLig + ActHeight - 1) { /* La barre est au milieu de la fenetre: simplement la placer a la fin */ if(NbreEntries < ActHeight) { /* La liste est plus petite que la fenetre */ Current = EndTree; InvLig = ActLig + NbreEntries - 1; SelIndex = NbreEntries - 1; } else { /* La liste est plus grande que la fenetre */ for(i=InvLig;i < ActLig + ActHeight - 1; i++,Current = Current->Suivant,SelIndex++); InvLig = ActLig + ActHeight - 1; } } else { /* La barre est deja a la fin: effacer tout et redescendre dans la liste d'un nombre d'items egal a la hauteur de la fenetre. - Temp memorisera le premier item a etre reaffiche, c-a-d celui qui sera au sommet de la fenetre - Current memorisera celui ou la barre en inverse se trouvera, dans ce cas, toujours sur la derniere ligne de la fenetre */ /* Donc, si il reste plus qu'une hauteur de fenetre dans la liste, lors d'un PGDN, l'item qui etait en inverse lorsque la barre est en fin de fenetre sera celui qui commencera les affichage a la fenetre suivante */ Temp = Current; /* Tester si il reste plus d'un fenetre a afficher */ for(i = 0; i < ActHeight - 1 && Current != (Tree_t *)NULL; i++,Current = Current->Suivant,SelIndex++); /* Si Current est a NULL, c'est que ce qui restait de la liste est plus petit qu'une hauteur de fenetre: on va donc reafficher une fenetre ayant le dernier item sur la derniere ligne */ if(Current == (Tree_t *)NULL) { /* Positionner Temp sur le premier item a devoir etre reaffiche en remontant la liste a partir de la fin. Current sera dans ce cas toujour le dernier item de la liste */ for(i = 0,Current = EndTree,Temp = EndTree, SelIndex = NbreEntries - 1; i < ActHeight - 1 && Temp != (Tree_t *)NULL; i++,Temp = Temp->Prec); } /* Affichage */ ClrZone(ActLig,ActCol,ActHeight,ActLength,TreeNorm); for(i = ActLig; i < (ActLig + ActHeight) && Temp != (Tree_t *)NULL; i++,Temp = Temp->Suivant) DispTreeEntry(Temp->Ele.DispLine,TreeNorm,i,ActCol,ActLength); InvLig = ActLig + ActHeight - 1; } PaintString(InvLig,InvCol,ActLength,TreeInv); /* Afficher le rappel complet du path en dessous */ ClrZone(Lig+Height-3,ActCol,1,ActLength,TreeNorm); DispCD_Path(Current->Ele.Path,Lig+Height-3,ActLength); } break; } } /* Liberer l'arbre */ Current = Tree; Dummy = (Tree_t *)NULL; while(Current != (Tree_t *)NULL) { Dummy = Current; Current = Current->Suivant; free(Dummy); } Tree = (Tree_t *)NULL; return(rc); } /***************************************************************************** DispTreeEntry() ------------------------------------------------------------------------------ Affichage d'une ligne de l'arbre avec controle de longueur: la ligne sera tronquer si necessaire *****************************************************************************/ void DispTreeEntry(char *Entry,char Attr,int Lig,int Col,int Max) { char Str[255]; if(strlen(Entry) < Max) WriteString(Entry,Attr,Lig,Col); else { strcpy(Str,Entry); Str[Max - 1] = 0; WriteString(Str,Attr,Lig,Col); } } /***************************************************************************** DispCD_Path() ------------------------------------------------------------------------------ Affichage du rappel de ss-rep pointe dans le bas de la fenetre avec controle de longueur: la ligne sera tronquee par le debut si necessaire *****************************************************************************/ void DispCD_Path(char *Path,int Lig,int Max) { char Str[80]; if(strlen(Path) < Max - 2) { strcpy(Str," "); strcat(Str,Path); strcat(Str," "); WriteString(Str,TreeInv,Lig,40 - (strlen(Str) / 2)); } else { strcpy(Str," /..."); strcat(Str,Path + strlen(Path) - Max + 10); strcat(Str," "); WriteString(Str,TreeInv,Lig,40 - (strlen(Str) / 2)); } } /***************************************************************************** SearchTree() ------------------------------------------------------------------------------ Input: / Process: fonction d'initialisation de l'arbre avec construction d'un fichier treeinfo. Output: -1 si interruption 0 sinon *****************************************************************************/ int SearchTree(void) { char StrTemp[FILENAME_LENGTH],FileName[FILENAME_LENGTH]; FILE *hf; Tree_t *Temp = (Tree_t *)NULL; OpenWin(9,20,5,40,DoingNorm,SINGLE_FRAMED,SHADED); WriteString("Processing Directory List...",DoingNorm,10,26); WriteString(" Press any key to cancel.",DoingNorm,12,26); /* Le premier element est le HOME directory du user */ Tree = (Tree_t *)malloc(sizeof(Tree_t)); if(Tree == (Tree_t *)NULL) raise(SIGME); strcpy(Tree->Ele.Path,Home); strcpy(Tree->Ele.DispLine,Tree->Ele.Path); Tree->Suivant = (Tree_t *)NULL; Tree->Prec = (Tree_t *)NULL; EndTree = Tree; strcpy(StrTemp,Tree->Ele.Path); /* Un seul appel a SubDir suffit (fonction recursive) */ if(SubDir(StrTemp," ") == -1) { CloseWin(); return(-1); } CloseWin(); /* Ecriture des infos dans le fichier treeinfo */ OpenWin(11,28,3,24,DoingNorm,SINGLE_FRAMED,SHADED); Printf(" Saving infos..."); fflush(stdout); strcpy(FileName,Home); if(FileName[strlen(FileName) - 1] != PATH_SEPARATOR_CHAR) strcat(FileName,PATH_SEPARATOR_STR); strcat(FileName,TREEINFO); hf = fopen(FileName,"w"); if(hf != (FILE *)NULL) { Temp = Tree; while(Temp != (Tree_t *)NULL) { fprintf(hf,"%s\n",Temp->Ele.Path); fprintf(hf,"%s\n",Temp->Ele.DispLine); Temp = Temp->Suivant; } fclose(hf); } CloseWin(); return(0); } /***************************************************************************** InTree() ------------------------------------------------------------------------------ Input: - specification pour chdir() - ligne d'affichage avec caracteres semi-graphiques Process: insertion en queue d'un element dans l'arbre *****************************************************************************/ void InTree(char *Path,char *DispLine) { Tree_t *New = (Tree_t *)NULL; New = (Tree_t *)malloc(sizeof(Tree_t)); if(New == (Tree_t *)NULL) raise(SIGME); strcpy(New->Ele.Path,Path); strcpy(New->Ele.DispLine,DispLine); New->Suivant = (Tree_t *)NULL; EndTree->Suivant = New; New->Prec = EndTree; EndTree = New; } /***************************************************************************** SubDir() ------------------------------------------------------------------------------ Input: - ss-rep a explorer - chaine a afficher avant chaque entree de ce ss-rep Process: fonction recursive d'exploration d'un ss-rep: chaque repertoire fils sera enfile dans une LLU, puis cette LLU sera relue et la fonction se rappelera pour chaque element enfile. Chaque element defile sera insere dans l'arbre. Output: 0 si OK -1 si interruption utilisateur *****************************************************************************/ int SubDir(char *Path,char *Pre) { /* Structure de donnees pour la LLU temporaire */ struct Ele_s { char Ele[FILENAME_LENGTH]; struct Ele_s *Suivant; }; typedef struct Ele_s Ele_t; Ele_t *Ele = (Ele_t *)NULL,*Cour,*Prec,*New; DIR *fd; DirList_t *List = (DirList_t *)NULL,*Tmp; char TmpName[255],Name[255],Pre2[255],DispLine[80]; int X,Y,rc; /* Boite de dialogue */ AnswerBoxItem_t *Msg = (AnswerBoxItem_t *)NULL, *Choices = (AnswerBoxItem_t *)NULL; /* Interruption utilisateur ? */ if(KeyPressed()) { GetXY(&X,&Y); GotoXY(1,1); ReadKbd(); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); AddAnswerBoxItem(&Msg,"Operation interrupted by user."); AddAnswerBoxItem(&Msg," Do you wish to cancel the search? "); AddAnswerBoxItem(&Choices,"Cancel"); AddAnswerBoxItem(&Choices,"Resume"); rc = AnswerBox(ConfirmNorm,ConfirmInv," Directory Tree ",Msg,Choices, 0,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); GotoXY(X,Y); if(rc == 1) return(-1); } fd = opendir(Path); if(fd == (DIR *)NULL) return(0); closedir(fd); if(Dir(Path,&List) == 0) return(0); if(strcmp(Path,PATH_SEPARATOR_STR) == 0) Path[0] = 0; Tmp = List; while(Tmp != (DirList_t *)NULL) { if(IS_DIR(Tmp->Info.s.st_mode) && !(strcmp(Tmp->Info.Name,".") == 0 || strcmp(Tmp->Info.Name,"..") == 0) ) { New = (Ele_t *)malloc(sizeof(Ele_t)); if(New == (Ele_t *)NULL) raise(SIGME); strcpy(New->Ele,Tmp->Info.Name + 1); New->Suivant = (Ele_t *)NULL; Cour = Ele; Prec = (Ele_t *)NULL; while((Cour != (Ele_t *)NULL) && (strcmp(Cour->Ele,Tmp->Info.Name + 1) < 0)) { Prec = Cour; Cour = Cour->Suivant; } if(Prec == (Ele_t *)NULL) { New->Suivant = Cour; Ele = New; } else { New->Suivant = Cour; Prec->Suivant = New; } } Tmp = Tmp->Suivant; } FreeAllTheList(&List); Cour = Ele; while(Cour != (Ele_t *)NULL) { SubDirCount++; SetCurrentAtt(DoingNorm); GotoXY(11,38); printf("%d",SubDirCount); fflush(stdout); strcpy(Name,Cour->Ele); if(Cour->Suivant != (Ele_t *)NULL) { sprintf(DispLine,"%s%c%c %s",Pre,F_BSSS,F_S_HO,Name); sprintf(Pre2,"%s%c ",Pre,F_S_VE); } else { sprintf(DispLine,"%s%c%c %s",Pre,F_S_LLC,F_S_HO,Name); sprintf(Pre2,"%s ",Pre); } sprintf(TmpName,"%s/%s",Path,Name); InTree(TmpName,DispLine); if(SubDir(TmpName,Pre2) == -1) { Cour = Ele; Prec = (Ele_t *)NULL; while(Cour != (Ele_t *)NULL) { Prec = Cour; Cour = Cour->Suivant; free(Prec); } Cour = (Ele_t *)NULL; return(-1); } Cour = Cour->Suivant; } Cour = Ele; Prec = (Ele_t *)NULL; while(Cour != (Ele_t *)NULL) { Prec = Cour; Cour = Cour->Suivant; free(Prec); } Cour = (Ele_t *)NULL; return(0); }