/***************************************************************************** Application ASH: ash.c (c) Pierre Adriaans 1994 ------------------------------------------------------------------------------ Module principal. Contient la fonction main(), les fonctions des gestion des elements affiches dans les fenetres, la fonction de conversion de dates, la fenetre d'history, la fonction de confirmation de sortie, la gestion du menu utilisateur. *****************************************************************************/ #define _ASH_SOURCE_CODE_ #include "ash.h" #define KB_DEF_STR "POSIX" #define KB_DEF POSIX_KBD #define MAP_DEF_STR "Termcap" #define MAP_DEF TERMCAP_MAP #define SCR_DEF_STR "VT" #define SCR_DEF VT_SCREEN #define WIN_DEF 2 #define EDIT_DEF "vi" #define PS_DEF "-x" #define COL_DEF "0 1 4" #define PROC_DEF "/proc" #define DISP_DEF_STR "Color" #define DISP_DEF (1) /* True */ /*#define CV_DEBUG*/ /*---------------------------------------------------------------------------- Gestion des fenetres d'affichage des contenus de ss-rep ----------------------------------------------------------------------------*/ /* Nbre effectif de fenetres actives */ int NbWins; /* Variables allant contenir les valeurs de coordonnees des fenetres: */ AshWin_t LEFT_WIN = { 2,1,22,40, /* 1: en mode deux fenetres */ 4,2,17,38 }, RIGHT_WIN = { 2,41,22,40, 4,42,17,38 }, TOP_LEFT_WIN = { 2,1,11,40, /* 2: en mode quatre fentres */ 4,2,6,38 }, TOP_RIGHT_WIN = { 2,41,11,40, 4,42,6,38 }, BOT_LEFT_WIN = { 13,1,11,40, 15,2,6,38 }, BOT_RIGHT_WIN = { 13,41,11,40, 15,42,6,38 }; /* Tableau de structures pouvant contenir les caracteristiques de quatre fenetres maximum */ AshWin_t AshWin[NB_MAX_WINS]; /* Tableau des zones inverses avec une case par fenetre: 4 maximum */ InvZone_t InvZone[NB_MAX_WINS]; /* Pour tester l'accessibilite d'un ss-rep */ DIR *DummyDir; char WorkingDir[NB_MAX_WINS][FILENAME_LENGTH], /* Liste des ss-rep de travail */ DummyStr[DUMMYSTR_SIZE]; /* Tampon */ DirList_t *List[NB_MAX_WINS], /* Contenu des fenetres */ *Dummy,*Dummy2, /* Pointeurs tampons */ *Current[NB_MAX_WINS], /* Pointeur sur le fichier en inverse */ *End[NB_MAX_WINS]; /* Pointeur sur le dernier fichier */ int NbEntries[NB_MAX_WINS], /* Nbre de fichiers dans une fenetre */ SelIndex[NB_MAX_WINS]; /* Index de la barre */ /* Liste active: index dans tous les tableaux */ int AL; /* Entree vide pour faire des blancs */ FileInfo_t BlankEntry; /*---------------------------------------------------------------------------- Macro d'effacement de l'horloge: en relation avec les fonctions CancelClock() et ResumeClock() de clock.c. L'horloge sera suspendue pendant les traitements, ce qui evite bien des problemes (EINTR par exemple) ----------------------------------------------------------------------------*/ #define ClearClock(); SetString(1,72,8,' '); /*---------------------------------------------------------------------------- Gestion des menus deroulants ----------------------------------------------------------------------------*/ #define NB_MENUS 4 MenuItem_t Menu[NB_MENUS]; HotKey_t *HotKey = (HotKey_t *)NULL; int ChosenMenu,ChosenItem; /*---------------------------------------------------------------------------- Variables de conversion des mois pour la gestion des dates ----------------------------------------------------------------------------*/ static char *MoisUnix[12] = { "Jan","Feb","Mar","Apr","May","Jun", "Jul","Aug","Sep","Oct","Nov","Dec" }; static char *MoisDir[12] = { "01/","02/","03/","04/","05/","06/", "07/","08/","09/","10/","11/","12/" }; /*---------------------------------------------------------------------------- Gestion de certaines caracteristiques generales ----------------------------------------------------------------------------*/ char *Home, /* Home directory du user */ *Shell; /* Shell du user */ /*---------------------------------------------------------------------------- Gestion de la ligne de commande ----------------------------------------------------------------------------*/ char CmdLine[CMDLINE_SIZE+1], /* Ligne de commande */ Prompt[64], /* Prompt de saisie */ *CmdBuffer, /* Tampon de manipulation */ *ShiftBuf; /* Tampon de decalage */ int CmdOff = 0, /* Offset d'insertion dans la ligne de commande */ LastCCmd, /* Offset du dernier caractere de la ligne de commande */ TempCmd, /* Compteur de manipulation */ LastAffX, /* Colonne du dernier caractere de la ligne de commande */ NbreCharLeft, /* Compteur de caracteres a passer sous le prompt */ ToMove, /* Compteur */ AfficheX,AfficheY, /* Coordonnees du curseur */ ViewX1,ViewY1, /* Coordonnees de la zone de saisie */ ViewX2,ViewY2; /*---------------------------------------------------------------------------- Gestion de la liste de commandes tapees (History) ----------------------------------------------------------------------------*/ #define HISTORY 50 /* Nombre de commandes memorisees par defaut */ int History, /* Taille maximale de l'history: HISTORY ou la valeur specifiee dans .ashrc */ ListSize = 0; /* Taille actuelle de l'history */ HistList_t *HistList, /* Pointeur de tete */ *DummyList; /* Pointeur de parcours */ /*---------------------------------------------------------------------------- Gestion des processus ----------------------------------------------------------------------------*/ /* Variables utilisees par Process() pour decripter le format d'affichage de la commande ps selectionnee */ char *ProgName, /* Nom du programme courant */ TermID[10], /* Terminal ou il tourne */ Pid[15], /* pid */ **argv2; /* Copie des arguments */ /* SS-rep ou est monte le /proc filesystem */ char ProcSystem[255]; /* Utilisation du /proc */ int ProcSystemOn = 0; /* Commande a accrocher a ps dans la recherche des processus */ char PS_Cmd[80]; /* Coordonnees absolues des elements du ps. Optionnel */ int PidCol,TermIDCol,NameCol; /* Liste des signaux */ ListBoxItem_t *Signals = (ListBoxItem_t *)NULL; /*---------------------------------------------------------------------------- Variables diverses ----------------------------------------------------------------------------*/ /* Pour enfiler 'Process Subdirectories' */ CheckBoxItem_t *RecursiveStr = (CheckBoxItem_t *)NULL; /* Tagging Mask */ char TagMask[TAGMASK_LENGTH+1]; /* LLB pour les InfoBox */ AnswerBoxItem_t *InfoMsg = (AnswerBoxItem_t *)NULL; /* Pour splitter une ligne de commande */ char *Args[NB_ARGS + 1]; /* Nom du fichier d'initialisation */ char InitFile[80]; /* Editeur a utiliser */ char Editor[80]; /* Gestion de la liste de liason programme-extension */ ProgExt_t *ProgExt = (ProgExt_t *)NULL, *PETmp; char Ext[EXT_MAX]; /* Fenetre About */ AnswerBoxItem_t *AboutMsg = (AnswerBoxItem_t *)NULL, *AboutChoices = (AnswerBoxItem_t *)NULL; /* Code de retour de la fenetre About dans la unregistered version */ int AboutRc; /* Registration informations */ AnswerBoxItem_t *RegMsg = (AnswerBoxItem_t *)NULL, *RegChoices = (AnswerBoxItem_t *)NULL; /* Menu des IPC control */ ListBoxItem_t *IPC_Menu = (ListBoxItem_t *)NULL; /* Menu Utilisateur */ UserMenuEntry_t *UserMenuEntries = (UserMenuEntry_t *)NULL; ListBoxItem_t *UserMenu = (ListBoxItem_t *)NULL; /***************************************************************************** Prototypes systemes autres que int *****************************************************************************/ char *ttyname(int); char *getcwd(char *,size_t); /***************************************************************************** P R O G R A M M E P R I N C I P A L *****************************************************************************/ int main(int argc,char *argv[]) { int i,j, /* Compteurs */ Quitter, /* Temoin de fin d'execution */ Key; /* Touche clavier */ HistList_t *HLCour, /* Pour les manipulations a l'interieur */ *HLPrec; /* de l'history */ char *Path, /* Pour recuperer le PATH actuel */ Path2[255], /* Pour le modifier */ *tty; /* Pour recuperer le nom complet du terminal */ /* Recopier les arguments */ argv2 = (char **)malloc(sizeof(char *) * argc); if(argv2 == (char **)NULL) raise(SIGME); for(i=0;i= 0 && argv[0][i] != PATH_SEPARATOR_CHAR; i--,j++) DummyStr[j] = argv[0][i]; DummyStr[j] = 0; ProgName = (char *)malloc(strlen(DummyStr+1)); if(ProgName == (char *)NULL) raise(SIGME); for(i = (strlen(DummyStr) - 1),j = 0; i >= 0; i--,j++) ProgName[j] = DummyStr[i]; ProgName[j] = 0;*/ /* Version 2: copie brute */ ProgName = (char *)malloc(strlen(argv[0]) + 1); if(ProgName == (char *)NULL) raise(SIGME); strcpy(ProgName,argv[0]); /* Recuperer le pid en string */ sprintf(Pid,"%d",getpid()); /* Recuperer le numero du terminal courant */ tty = ttyname(0); tty = strstr(tty,"/tty"); strcpy(TermID,tty+4); /* Recuperer le Home et construire la localisation du fichier d'init. */ Home = getenv("HOME"); strcpy(InitFile,Home); if(InitFile[strlen(InitFile) - 1] != PATH_SEPARATOR_CHAR) strcat(InitFile,PATH_SEPARATOR_STR); strcat(InitFile,INIT_FILE); /* Recuperer le shell */ Shell = getenv("SHELL"); /* Initialiser */ InitAsh(argc); /* Ajout du ss-rep courant au path, juste en cas de sh et non csh */ Path = getenv("PATH"); strcpy(Path2,"PATH=.:/:"); strcat(Path2,Path); putenv(Path2); /* Allouer les tampons de manipulation de la ligne de commande */ CmdBuffer = (char *)malloc(CMDLINE_SIZE+1); if(CmdBuffer == (char *)NULL) raise(SIGME); ShiftBuf = CmdBuffer; /* Initialiser la liste de commandes tapees */ HistList = (HistList_t *)malloc(sizeof(HistList_t)); if(HistList == (HistList_t *)NULL) raise(SIGME); HistList->Prec = (HistList_t *)NULL; HistList->Suivant = (HistList_t *)NULL; DummyList = HistList; /* Initialiser le buffer de split de ligne de commande */ for(i = 0;i <= NB_ARGS;i++) Args[i] = (char *)NULL; /* Initialisation de la configuration de fenetres */ if(NbWins == 2) { AshWin[0] = LEFT_WIN; AshWin[1] = RIGHT_WIN; } else { AshWin[0] = TOP_LEFT_WIN; AshWin[1] = TOP_RIGHT_WIN; AshWin[2] = BOT_LEFT_WIN; AshWin[3] = BOT_RIGHT_WIN; } /* Construire les menus deroulants */ for(i=0;i 4 windows",HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'r'); AddHotKey(&HotKey,(int)'R'); AddHotKey(&HotKey,CTRL_R); AddMenuWindowItem(&(Menu[1].MenuWindow),"Refresh Ctrl-R", HotKey); InitHotKey(&HotKey); AddMenuItem(Menu,Menu[1].MenuWindow,"Window",1); /* Menu Commands */ AddHotKey(&HotKey,(int)'p'); AddHotKey(&HotKey,(int)'P'); AddMenuWindowItem(&(Menu[2].MenuWindow), "display Processes",HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'c'); AddHotKey(&HotKey,(int)'C'); AddMenuWindowItem(&(Menu[2].MenuWindow),"I.P.C. Control",HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'t'); AddHotKey(&HotKey,(int)'T'); AddMenuWindowItem(&(Menu[2].MenuWindow),"directory Tree",HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'d'); AddHotKey(&HotKey,(int)'D'); AddMenuWindowItem(&(Menu[2].MenuWindow),"compare Directories", HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'h'); AddHotKey(&HotKey,(int)'H'); AddMenuWindowItem(&(Menu[2].MenuWindow),"History list", HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'f'); AddHotKey(&HotKey,(int)'F'); AddMenuWindowItem(&(Menu[2].MenuWindow),"Find file", HotKey); InitHotKey(&HotKey); AddMenuItem(Menu,Menu[2].MenuWindow,"Commands",2); /* Menu Help */ AddHotKey(&HotKey,(int)'c'); AddHotKey(&HotKey,(int)'C'); AddHotKey(&HotKey,CTRL_A); AddHotKey(&HotKey,K_F1); AddHotKey(&HotKey,K_HELP); AddMenuWindowItem(&(Menu[3].MenuWindow), "Ctrl-keys list Ctrl-A,F1,Help",HotKey); InitHotKey(&HotKey); AddHotKey(&HotKey,(int)'a'); AddHotKey(&HotKey,(int)'A'); sprintf(DummyStr,"About %s ...",PROG_NAME); AddMenuWindowItem(&(Menu[3].MenuWindow),DummyStr,HotKey); InitHotKey(&HotKey); AddMenuItem(Menu,Menu[3].MenuWindow,"Help",3); /* Construire les listes About */ sprintf(DummyStr,"%s, a full screen shell for Unix.",PROG_NAME); AddAnswerBoxItem(&AboutMsg,DummyStr); AddAnswerBoxItem(&AboutMsg,COPYRIGHT); AddAnswerBoxItem(&AboutMsg,VERSION); AddAnswerBoxItem(&AboutMsg,""); AddAnswerBoxItem(&AboutMsg," Contact: E-Mail:\f"); AddAnswerBoxItem(&AboutMsg," Pierre ADRIAANS xpierre@ibm.net\f"); AddAnswerBoxItem(&AboutMsg," P.O. BOX 13007 \f"); AddAnswerBoxItem(&AboutMsg," Long Beach CA 90803 \f"); AddAnswerBoxItem(&AboutMsg,""); AddAnswerBoxItem(&AboutMsg," This binary version of Pash 2.2 is distributed as a FREEWARE \f"); AddAnswerBoxItem(&AboutMsg," program. Feel free to redistribute it as long as no fee is \f"); AddAnswerBoxItem(&AboutMsg," collected in doing so. Thanks for your support.\f"); AddAnswerBoxItem(&AboutMsg,""); AddAnswerBoxItem(&AboutChoices,"Press Enter to close..."); /* Constituer la liste des signaux pour la gestion de process */ sprintf(DummyStr,"SIGTERM (kill -%d)",SIGTERM); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGINT (kill -%d)",SIGINT); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGQUIT (kill -%d)",SIGQUIT); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGKILL (kill -%d)",SIGKILL); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGHUP (kill -%d)",SIGHUP); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGTRAP (kill -%d)",SIGTRAP); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGABRT (kill -%d)",SIGABRT); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGUSR1 (kill -%d)",SIGUSR1); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGUSR2 (kill -%d)",SIGUSR2); AddListBoxItem(&Signals,DummyStr); sprintf(DummyStr,"SIGALRM (kill -%d)",SIGALRM); AddListBoxItem(&Signals,DummyStr); /* Construire le menu des IPC control */ AddListBoxItem(&IPC_Menu,"Message Queues"); AddListBoxItem(&IPC_Menu,"Semaphores"); AddListBoxItem(&IPC_Menu,"Shared Memories"); AddListBoxItem(&IPC_Menu,"Cancel"); /* Construire l'ecran */ Redraw(); /* Activer la premiere fenetre */ AL = 0; /* Placer la barre inverse sur le premier element de la liste active */ PaintString(InvZone[0].Lig,InvZone[0].Col,InvZone[0].Length, MainWinInv); /* Construction et affichage du prompt de saisie */ SetCurrentAtt(CmdLineNorm); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); SetAtt(CmdLineNorm); Printf("%s",Prompt); /* Initialiser les variables de gestion de la ligne de commande */ GetXY(&AfficheY,&AfficheX); LastAffX = ViewX1 = AfficheX; ViewY1 = ViewY2 = AfficheY; LastCCmd = 0; ViewX2 = 80; NbreCharLeft = 0; CmdLine[0] = 0; /* Initialiser le masque de tagging par defaut */ strcpy(TagMask,"*.*"); /* Placer la string de demande de recursion dans les manipulations de fichier */ AddCheckBoxItem(&RecursiveStr,"Process subdirectories"); /* Balancer tout */ fflush(stdout); #ifdef IS_CLOCK /* Mettre L'horloge */ InitClock(1,72,MainWinTitle,HOUR_MIN_SEC); #endif /* Et on y va ! */ Quitter = 0; while(!Quitter) { /* Lecture d'une touche */ Key = ReadKbd(); #ifdef IS_CLOCK /* Interrompre l'horloge pendant les traitements */ CancelClock(); #endif /* Traitement */ switch(Key) { case K_F1: case K_HELP: case CTRL_A: /* Aide */ ClearClock(); Aide(); break; case CTRL_J: case K_DO: case K_F2: /* User Menu */ ClearClock(); ProcessUserMenu(); break; case CTRL_V: case K_F3: case K_F4: /* Edit */ Edit(); break; case K_F5: case CTRL_O: ClearClock(); Copy(); break; case K_F6: case CTRL_Y: ClearClock(); Move(); break; case K_F7: case CTRL_W: ClearClock(); CreateDir(); break; case K_F8: case CTRL_K: ClearClock(); Delete(); break; case K_F9: case CTRL_G: ClearClock(); if(ActivateMenu(Menu,MenuNorm,MenuInv,1,NB_MENUS, &ChosenMenu,&ChosenItem) == 0) { switch(ChosenMenu) { case 1: switch(ChosenItem) { case 1: ProcessUserMenu(); break; case 2: Edit(); break; case 3: Copy(); break; case 4: Move(); break; case 5: Link(); break; case 6: CreateDir(); break; case 7: Delete(); break; case 9: FullInfo(Current[AL]->Info); break; case 10: ChangeMod(); break; case 11: ChangeOwner(); break; case 12: ChangeGrp(); break; case 14: MultipleTag(); break; case 15: MultipleUntag(); break; case 17: if(TestQuit() == 1) Quitter = 1; break; } break; case 2: switch(ChosenItem) { case 1: ChangeNbWins(); break; case 2: Refresh(); break; } break; case 3: switch(ChosenItem) { case 1: Processes(); break; case 2: IPC_Control(); break; case 3: if(CD_Tree() == 1) { free(Current[AL]->Info.Name); Current[AL]->Info.Name = (char *)malloc(3); if(Current[AL]->Info.Name == (char *)NULL) raise(SIGME); strcpy(Current[AL]->Info.Name,".."); InitWin(AL); PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); CmdLine[0] = 0; if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; fflush(stdout); } break; case 4: CompareDir(); break; case 5: HistoryList(); break; case 6: if(FindFile() == 1) { InitWin(AL); PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); CmdLine[0] = 0; if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; fflush(stdout); } break; } break; case 4: switch(ChosenItem) { case 1: Aide(); break; case 2: AboutRc = AnswerBox(AboutNorm,AboutInv," About this program ", AboutMsg,AboutChoices,1,0,DOUBLE_FRAMED); if(AboutRc == 2) AnswerBox(AboutNorm,AboutInv," Registration Informations ", RegMsg,RegChoices,1,0,DOUBLE_FRAMED); break; } } } break; case K_F10: /* Quitter */ ClearClock(); if(TestQuit() == 1) Quitter = 1; break; case K_SELECT: case CTRL_T: /* Tag */ ClearClock(); MultipleTag(); break; case CTRL_N: /* Untag */ ClearClock(); MultipleUntag(); break; case K_INS: case CTRL_Z: /* Tag/Untag le fichier courant */ if(strcmp(Current[AL]->Info.Name,"..") == 0) break; Current[AL]->Info.Tagged = !(Current[AL]->Info.Tagged); if(Current[AL]->Suivant != (DirList_t *)NULL) { (SelIndex[AL])++; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); Current[AL] = Current[AL]->Suivant; if(InvZone[AL].Lig == AshWin[AL].IntLig + AshWin[AL].IntHeight - 1) { ScrollUpWin(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength,1); DisplayEntry(Current[AL]->Info, AshWin[AL].IntLig + AshWin[AL].IntHeight - 1, AshWin[AL].IntCol); } else InvZone[AL].Lig++; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } else { if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } DisplaySelection(AL); break; case CTRL_P: /* Rappel de la derniere commande */ if(DummyList->Suivant == (HistList_t *)NULL) DummyList = HistList; if(DummyList->Suivant != (HistList_t *)NULL) { DummyList = DummyList->Suivant; strcpy(CmdLine,DummyList->CmdLine); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); for(i=ViewX1,ShiftBuf = CmdLine; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); LastAffX = AfficheX = i; CmdOff = LastCCmd = strlen(CmdLine); ToMove = strlen(ShiftBuf); if(ToMove > 0) CmdOff -= ToMove; NbreCharLeft = 0; GotoXY(AfficheY,AfficheX); fflush(stdout); } break; case CTRL_L: /* Reaffichage de tout l'ecran en cas de parasites */ /* En fait, on reaffiche la memoire video ! */ RestoreScreen(GetVideoMemoryAdress()); GotoXY(CMD_LINE_LIG,1); SetCurrentAtt(CmdLineNorm); Printf("%s",Prompt); for(i=ViewX1,ShiftBuf = CmdLine + NbreCharLeft; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); GotoXY(AfficheY,AfficheX); fflush(stdout); break; case CTRL_R: /* Relecture du contenu de la fenetre */ Refresh(); break; case CR: /* Enter: - si ligne de commande non vide, l'executer - si inverse sur '..', remonter d'un etage - si inverse sur un ss-rep, y descendre - si inverse == 'makefile', executer make - sinon, executer le fichier en inverse */ if(strcmp(CmdLine,"") != 0) { /* Stocker la commande */ if(ListSize == History) { /* Nbre Maximal de commande atteint: virer la derniere commande de la liste */ HLCour = HistList; HLPrec = (HistList_t *)NULL; while(HLCour->Suivant != (HistList_t *)NULL) { HLPrec = HLCour; HLCour = HLCour->Suivant; } free(HLCour->CmdLine); free(HLCour); HLPrec->Suivant = (HistList_t *)NULL; } else ListSize++; HistList->CmdLine = (char *)malloc(strlen(CmdLine) + 1); if(HistList->CmdLine == (char *)NULL) raise(SIGME); strcpy(HistList->CmdLine,CmdLine); DummyList = (HistList_t *)malloc(sizeof(HistList_t)); if(DummyList == (HistList_t *)NULL) raise(SIGME); DummyList->Suivant = HistList; HistList->Prec = DummyList; HistList = DummyList; ConvertArgs(CmdLine,Args,NB_ARGS); if(strcmp(Args[0],"cd") == 0) { if(Args[1] == (char *)NULL) { Args[1] = (char *)malloc(strlen(Home) + 1); if(Args[1] == (char *)NULL) raise(SIGME); strcpy(Args[1],Home); } /* Essayer d'ouvrir le ss-rep destination: si c'est impossible, message d'erreur et pas de changement */ if((DummyDir = opendir(Args[1])) == (DIR *)NULL) { ClearClock(); InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, " Sorry, impossible to access the directory "); AddAnswerBoxItem(&InfoMsg,Args[1]); InfoBox(ErrorNorm,ErrorInv," Change Directory ",InfoMsg,0,0, DOUBLE_FRAMED); /* Reset command line a cause du break */ SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; LastCCmd = 0; CmdOff = 0; CmdLine[0] = 0; fflush(stdout); break; } else closedir(DummyDir); if(chdir(Args[1]) == 0) { strcpy(WorkingDir[AL],Args[1]); free(Current[AL]->Info.Name); Current[AL]->Info.Name = (char *)malloc(3); if(Current[AL]->Info.Name == (char *)NULL) raise(SIGME); strcpy(Current[AL]->Info.Name,".."); InitWin(AL); } else { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, " Sorry, impossible to access the directory "); AddAnswerBoxItem(&InfoMsg,Args[1]); InfoBox(ErrorNorm,ErrorInv," Change Directory ",InfoMsg,0,0, DOUBLE_FRAMED); } } else { ExecuteCommande(CmdLine); Redraw(); } /* Reinitialiser le tableau de split */ for(i = 0;i < NB_ARGS && Args[i] != (char *)NULL;i++) { free(Args[i]); Args[i] = (char *)NULL; } chdir(WorkingDir[AL]); /* Se replacer dans le ss-rep de la fenetre active */ /* Inverser la premiere entree de la fenetre */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); /* Reset de la ligne de commande */ SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); LastAffX = ViewX1 = AfficheX; LastCCmd = 0; CmdOff = 0; CmdLine[0] = 0; fflush(stdout); break; } if(strcmp(Current[AL]->Info.Name,"..") == 0) { /* Recuperer le nom du ss-rep courant et initialiser le fichier courant a ce nom pour forcer la barre inverse a s'y placer */ free(Current[AL]->Info.Name); Current[AL]->Info.Name = (char *)malloc(strlen(WorkingDir[AL])+2); if(Current[AL]->Info.Name == (char *)NULL) raise(SIGME); strcpy(Current[AL]->Info.Name,PATH_SEPARATOR_STR); for(i = (strlen(WorkingDir[AL]) - 1),j=0; WorkingDir[AL][i] != PATH_SEPARATOR_CHAR; i--,j++) DummyStr[j] = WorkingDir[AL][i]; DummyStr[j] = 0; for(i = (strlen(DummyStr) - 1),j = 1; i >= 0; i--,j++) Current[AL]->Info.Name[j] = DummyStr[i]; Current[AL]->Info.Name[j] = 0; if(chdir("..") == -1) chdir(Home); /* Lors de la remontee d'un ss-rep, il faudrait que la barre inverse soit non seulement placee sur le ss-rep qu'on vient de quitter, mais il faudrait aussi qu'elle ne soit pas au sommet de la fenetre. En effet, lors de la demande de remontee, la barre en inverse etait placee sur la premiere ligne de la fenetre (sur ".."). Pour realiser ca, on va recuperer le numero d'ordre du ss-rep qu'on vient de quitter dans le contenu du ss-rep pere et rectifier la hauteur de la barre inverse pour qu'elle soit a cette hauteur. Si le ss-rep est plus bas que la fenetre, la barre sera placee sur la derniere ligne de la fenetre. */ /* Recuperer le contenu du ss-rep pere */ Dir(".",&Dummy2); /* En sortie de boucle, i contient la hauteur du ss-rep dans la fenetre ou la hauteur de la derniere ligne de la fenetre */ for(i=AshWin[AL].IntLig,Dummy = Dummy2; (strcmp(Dummy->Info.Name,Current[AL]->Info.Name) != 0) && (i < (AshWin[AL].IntLig + AshWin[AL].IntHeight - 1)); i++,Dummy = Dummy->Suivant); /* Rectifier la hauteur de la barre a cette hauteur */ InvZone[AL].Lig = i; /* Liberer la pseudo liste */ FreeAllTheList(&Dummy2); /* Rectifier tout */ InitWin(AL); PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; fflush(stdout); break; } /* Descente dans un ss-rep */ if(Current[AL]->Info.Name[0] == PATH_SEPARATOR_CHAR) { /* Essayer d'ouvrir le ss-rep destination: si c'est impossible, message d'erreur et pas de changement */ strcpy(DummyStr,WorkingDir[AL]); if(DummyStr[strlen(DummyStr) - 1] == PATH_SEPARATOR_CHAR) DummyStr[strlen(DummyStr) - 1] = 0; strcat(DummyStr,Current[AL]->Info.Name); if((DummyDir = opendir(DummyStr)) == (DIR *)NULL) { ClearClock(); InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, " Sorry, impossible to access the directory "); AddAnswerBoxItem(&InfoMsg,DummyStr); InfoBox(ErrorNorm,ErrorInv," Change Directory ",InfoMsg,0,0, DOUBLE_FRAMED); break; } else closedir(DummyDir); if(chdir((Current[AL]->Info.Name) + 1) == 0) { free(Current[AL]->Info.Name); Current[AL]->Info.Name = (char *)malloc(3); if(Current[AL]->Info.Name == (char *)NULL) raise(SIGME); strcpy(Current[AL]->Info.Name,".."); InitWin(AL); PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } else { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg, " Sorry, impossible to access the directory "); AddAnswerBoxItem(&InfoMsg,DummyStr); InfoBox(ErrorNorm,ErrorInv," Change Directory ",InfoMsg,0,0, DOUBLE_FRAMED); } SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; fflush(stdout); break; } /* Traitement du fichier en inverse: - si makefile, lancer make - si extension reprise dans la liste, lancer la liaison - sinon, executer le fichier inverse */ if((strcmp(Current[AL]->Info.Name,"makefile") == 0) || (strcmp(Current[AL]->Info.Name,"Makefile") == 0)) strcpy(DummyStr,"make"); else { /* Chercher dans la liste de liaison prog-ext */ GetExt(Current[AL]->Info.Name,Ext); for(PETmp = ProgExt; (PETmp != (ProgExt_t *)NULL) && (strcmp(PETmp->Ext,Ext) != 0); PETmp = PETmp->Suivant); if(PETmp != (ProgExt_t *)NULL) { /* Liaison trouvee */ strcpy(DummyStr,PETmp->Prog); strcat(DummyStr," "); strcat(DummyStr,Current[AL]->Info.Name); } else { /* Liaison non trouvee: executer le fichier en inverse */ strcpy(DummyStr,Current[AL]->Info.Name); } } /* Stocker la commande */ if(ListSize == History) { /* Nbre Maximal de commande atteint: virer la derniere commande de la liste */ HLCour = HistList; HLPrec = (HistList_t *)NULL; while(HLCour->Suivant != (HistList_t *)NULL) { HLPrec = HLCour; HLCour = HLCour->Suivant; } free(HLCour->CmdLine); free(HLCour); HLPrec->Suivant = (HistList_t *)NULL; } else ListSize++; HistList->CmdLine = (char *)malloc(strlen(DummyStr) + 1); if(HistList->CmdLine == (char *)NULL) raise(SIGME); strcpy(HistList->CmdLine,DummyStr); DummyList = (HistList_t *)malloc(sizeof(HistList_t)); if(DummyList == (HistList_t *)NULL) raise(SIGME); DummyList->Suivant = HistList; HistList->Prec = DummyList; HistList = DummyList; ExecuteCommande(DummyStr); Redraw(); chdir(WorkingDir[AL]); PaintString(InvZone[AL].Lig,InvZone[AL].Col,InvZone[AL].Length, MainWinInv); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); LastAffX = AfficheX; LastCCmd = 0; CmdOff = 0; CmdLine[0] = 0; fflush(stdout); break; case TAB: /* Chgt de fenetre */ /* Remettre la ligne inversee en normal */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); /* Changer de numero de fenetre active */ if(AL < NbWins - 1) AL++; else AL = 0; /* Inverser l'entree active de cette fenetre */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); /* Changer de ss-rep */ chdir(WorkingDir[AL]); /* Deplacer la ligne de commande: */ /* Effacer la ligne courante */ SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); /* Sauver la taille du prompt courante */ strcpy(DummyStr,Prompt); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); /* Calculer la difference de taille entre les deux prompts */ j = strlen(Prompt) - strlen(DummyStr); /* Rectifier les varialbes de position */ ViewX1 += j; /* Reafficher la nouvelle ligne */ GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); for(i=ViewX1,ShiftBuf = CmdLine + NbreCharLeft; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); LastAffX = i; AfficheX += j; ToMove = AfficheX - ViewX2; if(ToMove > 0) { AfficheX -= ToMove; CmdOff -= ToMove; } GotoXY(AfficheY,AfficheX); fflush(stdout); break; case K_UP: if(Current[AL]->Prec != (DirList_t *)NULL) { SelIndex[AL]--; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); Current[AL] = Current[AL]->Prec; if(InvZone[AL].Lig == AshWin[AL].IntLig) { ScrollDownWin(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength,1); DisplayEntry(Current[AL]->Info, AshWin[AL].IntLig,AshWin[AL].IntCol); } else InvZone[AL].Lig--; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case K_DOWN: if(Current[AL]->Suivant != (DirList_t *)NULL) { SelIndex[AL]++; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); Current[AL] = Current[AL]->Suivant; if(InvZone[AL].Lig == AshWin[AL].IntLig + AshWin[AL].IntHeight - 1) { ScrollUpWin(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength,1); DisplayEntry(Current[AL]->Info, AshWin[AL].IntLig + AshWin[AL].IntHeight - 1, AshWin[AL].IntCol); } else InvZone[AL].Lig++; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case K_HOME: case CTRL_B: if(SelIndex[AL] != 0) { if((SelIndex[AL] < AshWin[AL].IntHeight) && (InvZone[AL].Lig - SelIndex[AL] >= AshWin[AL].IntLig)) if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); else { ClrZone(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength, MainWinNorm); for(i = AshWin[AL].IntLig,Dummy = List[AL]; i < (AshWin[AL].IntLig + AshWin[AL].IntHeight) && Dummy != (DirList_t *)NULL; i++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info, i,AshWin[AL].IntCol); /* Remplir les blancs si necessaire */ if(i < (AshWin[AL].IntLig + AshWin[AL].IntHeight)) for(; i < (AshWin[AL].IntHeight + AshWin[AL].IntLig); i++) DisplayEntry(BlankEntry,i,AshWin[AL].IntCol); } Current[AL] = List[AL]; SelIndex[AL] = 0; InvZone[AL].Lig = AshWin[AL].IntLig; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case K_END: case CTRL_E: if(SelIndex[AL] != NbEntries[AL] -1) { if(InvZone[AL].Lig + NbEntries[AL] - SelIndex[AL] <= AshWin[AL].IntLig + AshWin[AL].IntHeight) if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); else { ClrZone(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength, MainWinNorm); for(i = 0,Current[AL] = End[AL]; i < AshWin[AL].IntHeight - 1 && Current[AL] != (DirList_t *)NULL; i++,Current[AL] = Current[AL]->Prec); for(i = AshWin[AL].IntLig; i < (AshWin[AL].IntLig + AshWin[AL].IntHeight) && Current[AL] != (DirList_t *)NULL; i++,Current[AL] = Current[AL]->Suivant) DisplayEntry(Current[AL]->Info,i,AshWin[AL].IntCol); } Current[AL] = End[AL]; SelIndex[AL] = NbEntries[AL] - 1; if(NbEntries[AL] < AshWin[AL].IntHeight) InvZone[AL].Lig = AshWin[AL].IntLig + SelIndex[AL]; else InvZone[AL].Lig = AshWin[AL].IntLig + AshWin[AL].IntHeight - 1; if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case K_PGUP: case CTRL_U: if(SelIndex[AL] != 0) { if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); if(InvZone[AL].Lig != AshWin[AL].IntLig) { for(i = InvZone[AL].Lig; i > AshWin[AL].IntLig; i--,Current[AL] = Current[AL]->Prec,SelIndex[AL]--); InvZone[AL].Lig = AshWin[AL].IntLig; } else { for(i=0; i < AshWin[AL].IntHeight - 1 && Current[AL] != (DirList_t *)NULL; i++,Current[AL] = Current[AL]->Prec,SelIndex[AL]--); if(Current[AL] == (DirList_t *)NULL) { Current[AL] = List[AL]; SelIndex[AL] = 0; } Dummy = Current[AL]; ClrZone(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength,MainWinNorm); for(i = AshWin[AL].IntLig; i < (AshWin[AL].IntLig + AshWin[AL].IntHeight) && Dummy != (DirList_t *)NULL; i++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,i,AshWin[AL].IntCol); InvZone[AL].Lig = AshWin[AL].IntLig; } if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case K_PGDN: case CTRL_D: if(SelIndex[AL] != NbEntries[AL] - 1) { if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinBold); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinNorm); if(InvZone[AL].Lig != AshWin[AL].IntLig + AshWin[AL].IntHeight - 1) { if(NbEntries[AL] < AshWin[AL].IntHeight) { Current[AL] = End[AL]; InvZone[AL].Lig = AshWin[AL].IntLig + NbEntries[AL] - 1; SelIndex[AL] = NbEntries[AL] - 1; } else { for(i = InvZone[AL].Lig; i < AshWin[AL].IntLig + AshWin[AL].IntHeight - 1; i++,Current[AL] = Current[AL]->Suivant,SelIndex[AL]++); InvZone[AL].Lig = AshWin[AL].IntLig + AshWin[AL].IntHeight - 1; } } else { Dummy = Current[AL]; for(i=0; i < AshWin[AL].IntHeight - 1 && Current[AL] != (DirList_t *)NULL; i++,Current[AL] = Current[AL]->Suivant,SelIndex[AL]++); if(Current[AL] == (DirList_t *)NULL) { for(i = 0,Current[AL] = End[AL],Dummy = End[AL], SelIndex[AL] = NbEntries[AL] - 1; i < AshWin[AL].IntHeight - 1 && Dummy != (DirList_t *)NULL; i++,Dummy = Dummy->Prec); } ClrZone(AshWin[AL].IntLig,AshWin[AL].IntCol, AshWin[AL].IntHeight,AshWin[AL].IntLength,MainWinNorm); for(i = AshWin[AL].IntLig; i < (AshWin[AL].IntLig + AshWin[AL].IntHeight) && Dummy != (DirList_t *)NULL; i++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,i,AshWin[AL].IntCol); InvZone[AL].Lig = AshWin[AL].IntLig + AshWin[AL].IntHeight - 1; } if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } break; case CTRL_F: /* Infos completes sur un fichier */ ClearClock(); FullInfo(Current[AL]->Info); break; case CTRL_C: case ESC: /* Reset ligne de commande */ SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); /* Annuler la recherche dans la liste */ DummyList = HistList; fflush(stdout); GetXY(&AfficheY,&AfficheX); LastAffX = AfficheX; LastCCmd = 0; CmdOff = 0; CmdLine[0] = 0; NbreCharLeft = 0; break; case BACKSP: /* Si le curseur est sur le prompt et qu'il y a des caracteres en dessous du prompt, decaler la ligne de commande pour en ramener 10 ou moins */ SetCurrentAtt(CmdLineNorm); if(AfficheX == ViewX1 && NbreCharLeft > 0) { GotoXY(ViewY1,ViewX1); if(NbreCharLeft >= 10) ToMove = 10; else ToMove = NbreCharLeft; for(i = ViewX1,ShiftBuf = CmdLine + CmdOff - ToMove; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); AfficheX += ToMove; LastAffX += ToMove; if(LastAffX > ViewX2 - 1) LastAffX = ViewX2 - 1; GotoXY(AfficheY,AfficheX); NbreCharLeft -= ToMove; } /* Puis, traitement classique */ if(AfficheX > ViewX1) { if(CmdOff < LastCCmd) { TempCmd = CmdOff; ShiftBuf = CmdBuffer; strncpy(ShiftBuf,CmdLine + CmdOff,LastCCmd - CmdOff); ShiftBuf[LastCCmd - CmdOff] = ' '; ShiftBuf[LastCCmd - CmdOff + 1] = 0; for(;TempCmd != LastCCmd;TempCmd++) CmdLine[TempCmd-1] = CmdLine[TempCmd]; GotoXY(AfficheY,AfficheX - 1); /* Reafficher sans depasser la colonne de droite !! */ for(i = AfficheX - 1; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); /* Ne decrementer l'offset du dernier caractere a l'ecran que s'il n'y en a plus au dela de la colonne de droite */ if(i < ViewX2) LastAffX--; } else { MoveCurs(AfficheY,AfficheX - 1); PutToScr(' '); LastAffX--; } AfficheX--; LastCCmd--; CmdOff--; CmdLine[LastCCmd] = 0; GotoXY(AfficheY,AfficheX); } fflush(stdout); break; case K_LEFT: SetCurrentAtt(CmdLineNorm); if(AfficheX > ViewX1) { AfficheX--; CmdOff--; GotoXY(AfficheY,AfficheX); } else if(NbreCharLeft > 0) { GotoXY(ViewY1,ViewX1); if(NbreCharLeft >= 10) ToMove = 10; else ToMove = NbreCharLeft; for(i = ViewX1,ShiftBuf = CmdLine + CmdOff - ToMove; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); AfficheX += ToMove; LastAffX += ToMove; if(LastAffX > ViewX2 - 1) LastAffX = ViewX2 - 1; GotoXY(AfficheY,AfficheX); NbreCharLeft -= ToMove; } fflush(stdout); break; case K_RIGHT: SetCurrentAtt(CmdLineNorm); if(CmdOff < LastCCmd) { if(AfficheX < ViewX2 - 1) { AfficheX++; CmdOff++; GotoXY(AfficheY,AfficheX); } else { GotoXY(ViewY1,ViewX1); ToMove = 10; for(i = ViewX1,ShiftBuf = CmdLine + NbreCharLeft + ToMove; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); AfficheX -= ToMove; if(i < ViewX2) { LastAffX -= ToMove; /* Completer par des blancs */ for(;i < ViewX2;i++) PutToScr(' '); } GotoXY(AfficheY,AfficheX); NbreCharLeft += ToMove; } fflush(stdout); } break; case K_REMOVE: case CTRL_X: case DELETE: SetCurrentAtt(CmdLineNorm); if(CmdOff != LastCCmd) { TempCmd = CmdOff; ShiftBuf = CmdBuffer; strncpy(ShiftBuf,CmdLine + CmdOff + 1,LastCCmd - CmdOff - 1); ShiftBuf[LastCCmd - CmdOff - 1] = ' '; ShiftBuf[LastCCmd - CmdOff] = 0; for(;TempCmd != LastCCmd;TempCmd++) CmdLine[TempCmd] = CmdLine[TempCmd + 1]; CmdLine[TempCmd] = ' '; LastCCmd--; CmdLine[LastCCmd] = 0; for(i = AfficheX; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); /* Ne decrementer l'offset du dernier caractere a l'ecran que s'il n'y en a plus au dela de la colonne de droite */ if(i < ViewX2) LastAffX--; GotoXY(AfficheY,AfficheX); fflush(stdout); } break; default: SetCurrentAtt(CmdLineNorm); if(isdisplay(Key) && (strlen(CmdLine) < CMDLINE_SIZE)) { if(AfficheX == ViewX2) { if(CmdOff == LastCCmd) { /* Curseur en fin de ligne et insertion en fin de ligne de commande: deplacer la ligne de commande d'un caractere vers la gauche, en dessous du prompt */ /* Se placer juste apres le prompt */ GotoXY(ViewY1,ViewX1); /* Calculer le nombre de caracteres a "passer sous le prompt" */ NbreCharLeft = (strlen(CmdLine) - (ViewX2 - ViewX1) + 1); /* Reecrire la ligne de commande avec i caracteres de moins */ for(ShiftBuf = CmdLine + NbreCharLeft; *ShiftBuf; ShiftBuf++) PutToScr(*ShiftBuf); /* Rectifier les variables de position */ LastAffX--; AfficheX--; GotoXY(AfficheY,AfficheX); } else { /* Curseur en fin de ligne et insertion au milieu de la ligne de commande: decaler vers la gauche d'un caractere jusqu'a la position d'insertion courante */ GotoXY(ViewY1,ViewX1); /* Calculer le nombre de caracteres a "passer sous le prompt" */ NbreCharLeft = (strlen(CmdLine) - (ViewX2 - ViewX1) + 1 - (LastCCmd - CmdOff)); /* Reecrire la ligne de commande avec i caracteres de moins */ for(ShiftBuf = CmdLine + NbreCharLeft,i=ViewX1; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); /* Rectifier les variables de position */ /*LastAffX--;*/ AfficheX--; GotoXY(AfficheY,AfficheX); } } if(CmdOff != LastCCmd) { /* Curseur au millieu de la string: deplacer vers la droite */ TempCmd = LastCCmd; ShiftBuf = CmdBuffer; strncpy(ShiftBuf,CmdLine + CmdOff,LastCCmd - CmdOff); ShiftBuf[LastCCmd - CmdOff] = 0; for(;TempCmd > CmdOff;TempCmd--) CmdLine[TempCmd] = CmdLine[TempCmd - 1]; GotoXY(AfficheY,AfficheX + 1); for(i = AfficheX + 1; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); GotoXY(AfficheY,AfficheX); } CmdLine[CmdOff] = (char)Key; CmdOff++; PutToScr((char)Key); LastCCmd++; LastAffX++; AfficheX++; SetXY(AfficheY,AfficheX); CmdLine[LastCCmd] = 0; fflush(stdout); } } /* switch */ #ifdef IS_CLOCK /* Relancer l'horloge */ ResumeClock(); #endif } /* while */ ClrScr(); ExitScreen(); ExitKeyboard(); return(0); } /***************************************************************************** InitAsh() ------------------------------------------------------------------------------ Input: Nombre d'arguments passes au programme Process: initialisation du programme en fonction du fichier $HOME/.ashrc Output: / *****************************************************************************/ void InitAsh(int argc) { FILE *hf; int KbType = -1,CrtType = -1,Wins = -1,Hi = -1,KbMap = -1,ColorDisplay = -1, i,j; static char Buffer[256],Buffer1[256],Buffer2[256], ExtFile[FILENAME_LENGTH]; char *Args[5]; int Fini; UserMenuEntry_t *UMENew,*UMECour,*UMEPrec; Command_t *CONew,*COCour,*COPrec; for(i=0;i<5;i++) Args[i] = (char *)NULL; PidCol = -1; TermIDCol = -1; NameCol = -1; fprintf(stderr,"\n%s, %s\n",PROG_NAME,VERSION); for(i=1;i= 5) { ConvertArgs(Buffer2,Args,4); PidCol = atoi(Args[0]); TermIDCol = atoi(Args[1]); NameCol = atoi(Args[2]); for(i=0;i<3;i++) if(Args[i] != (char *)NULL) { free(Args[i]); Args[i] = (char *)NULL; } } } if(strcmp(Buffer1,"ProcSystem") == 0) { strcpy(ProcSystem,Buffer2); if(strlen(ProcSystem) == 0) ProcSystemOn = 0; else if(strcmp(ProcSystem,"OFF") == 0) ProcSystemOn = 0; else ProcSystemOn = 1; } if(strcmp(Buffer1,"Display") == 0) { for(i=0;Buffer2[i];i++) Buffer2[i] = (char)toupper((int)Buffer2[i]); if(strcmp(Buffer2,"COLOR") == 0) ColorDisplay = 1; else ColorDisplay = 0; } } fclose(hf); } else { printf("WARNING: initialisation file $HOME/.pashrc not found. This file will be created\n"); printf("using default values for %s\n\n",VERSION); printf("KeyboardType=%s\n",KB_DEF_STR); printf("KeyboardMapping=%s\n",MAP_DEF_STR); printf("ScreenType=%s\n",SCR_DEF_STR); printf("Windows=%d\n",WIN_DEF); printf("History=%d\n",HISTORY); printf("Editor=%s\n",EDIT_DEF); printf("ProcSystem=%s\n",PROC_DEF); printf("PSoption=%s\n",PS_DEF); printf("PScolumns=%s\n",COL_DEF); printf("Display=%s\n\n",DISP_DEF_STR); hf = fopen(InitFile,"w"); if(hf == (FILE *)NULL) { printf("ERROR: cannot create file. Exiting.\n"); exit(0); } fprintf(hf,"# Pash initialisation file created at run-time using default values\n"); fprintf(hf,"# for %s\n",VERSION); fprintf(hf,"# This file might have to be modified for Pash to run correctly on\n"); fprintf(hf,"# your system.\n"); fprintf(hf,"#\n"); fprintf(hf,"# See pash.txt for details and recommanded values.\n"); fprintf(hf,"#\n"); fprintf(hf,"KeyboardType=%s\n",KB_DEF_STR); fprintf(hf,"KeyboardMapping=%s\n",MAP_DEF_STR); fprintf(hf,"ScreenType=%s\n",SCR_DEF_STR); fprintf(hf,"Windows=%d\n",WIN_DEF); fprintf(hf,"History=%d\n",HISTORY); fprintf(hf,"Editor=%s\n",EDIT_DEF); fprintf(hf,"ProcSystem=%s\n",PROC_DEF); fprintf(hf,"PSoption=%s\n",PS_DEF); fprintf(hf,"PScolumns=%s\n",COL_DEF); fprintf(hf,"Display=%s\n\n",DISP_DEF_STR); fclose(hf); KbType = KB_DEF; KbMap = MAP_DEF; CrtType = SCR_DEF; Wins = WIN_DEF; Hi = HISTORY; ColorDisplay = DISP_DEF; strcpy(Editor,EDIT_DEF); strcpy(ProcSystem,PROC_DEF); if(strcmp(ProcSystem,"OFF") == 0) { strcpy(PS_Cmd,PS_DEF); strcpy(Buffer2,COL_DEF); ConvertArgs(Buffer2,Args,4); PidCol = atoi(Args[0]); TermIDCol = atoi(Args[1]); NameCol = atoi(Args[2]); for(i=0;i<3;i++) if(Args[i] != (char *)NULL) { free(Args[i]); Args[i] = (char *)NULL; } ProcSystemOn = 0; } else ProcSystemOn = 1; printf("You might have to modify these default values for Pash to run correctly on\n"); printf("your system.\n\n"); printf("Type pash -h or see pash.txt for informations about this file.\n\n"); printf("[Press Enter to go on...]"); fflush(stdout); fgets(Buffer, sizeof(Buffer), stdin); } for(i=1;iExt,Buffer1); strcpy(PETmp->Prog,Buffer2); fprintf(stderr,".%s \t--> %s\n",Buffer1,Buffer2); if(ProgExt == (ProgExt_t *)NULL) { PETmp->Suivant = (ProgExt_t *)NULL; ProgExt = PETmp; } else { PETmp->Suivant = ProgExt; ProgExt = PETmp; } } fclose(hf); } else fprintf(stderr,"Not found. No Program-Extension association set.\n"); /* Traitement du fichier de menu utilisateur */ strcpy(ExtFile,Home); if(ExtFile[strlen(ExtFile) - 1] != PATH_SEPARATOR_CHAR) strcat(ExtFile,PATH_SEPARATOR_STR); strcat(ExtFile,MNU_FILE); fprintf(stderr,"\nSearching for a User Menu file.\n"); hf = fopen(ExtFile,"r"); if(hf != (FILE *)NULL) { fprintf(stderr,"Found. Reading and processing...\n"); Fini = 0; if(fgets(Buffer,255,hf) == NULL) Fini = 1; while(!Fini) { while(Buffer[0] == '#') if(fgets(Buffer,255,hf) == NULL) Fini = 1; if(Fini) break; Buffer[strlen(Buffer) - 1] = 0; if(strlen(Buffer) == 0) continue; if(Buffer[0] == OPTION_TAG) { UMENew = (UserMenuEntry_t *)malloc(sizeof(UserMenuEntry_t)); if(UMENew == (UserMenuEntry_t *)NULL) raise(SIGME); UMENew->EntryName = (char *)malloc(strlen(Buffer + 1) + 1); if(UMENew->EntryName == (char *)NULL) raise(SIGME); strcpy(UMENew->EntryName,Buffer + 1); UMENew->Commands = (Command_t *)NULL; UMENew->Suivant = (UserMenuEntry_t *)NULL; while(!Fini) { if(fgets(Buffer,255,hf) == NULL) { Fini = 1; break; } if(Buffer[0] == '#') continue; if(Buffer[0] == OPTION_TAG) break; Buffer[strlen(Buffer) - 1] = 0; if(strlen(Buffer) == 0) continue; CONew = (Command_t *)malloc(sizeof(Command_t)); if(CONew == (Command_t *)NULL) raise(SIGME); CONew->Suivant = (Command_t *)NULL; CONew->Command = (char *)malloc(strlen(Buffer) + 1); if(CONew->Command == (char *)NULL) raise(SIGME); strcpy(CONew->Command,Buffer); if(UMENew->Commands == (Command_t *)NULL) UMENew->Commands = CONew; else { COCour = UMENew->Commands; COPrec = (Command_t *)NULL; while(COCour != (Command_t *)NULL) { COPrec = COCour; COCour = COCour->Suivant; } COPrec->Suivant = CONew; } } if(UserMenuEntries == (UserMenuEntry_t *)NULL) UserMenuEntries = UMENew; else { UMECour = UserMenuEntries; UMEPrec = (UserMenuEntry_t *)NULL; while(UMECour != (UserMenuEntry_t *)NULL) { UMEPrec = UMECour; UMECour = UMECour->Suivant; } UMEPrec->Suivant = UMENew; } } } fclose(hf); } else fprintf(stderr,"Not found. No User Menu defined.\n"); /* Constituer le ListBox et afficher le temoin sur stderr */ UMECour = UserMenuEntries; while(UMECour != (UserMenuEntry_t *)NULL) { fprintf(stderr,"%s\n",UMECour->EntryName); AddListBoxItem(&UserMenu,UMECour->EntryName); COCour = UMECour->Commands; while(COCour != (Command_t *)NULL) { fprintf(stderr,"\t%s\n",COCour->Command); COCour = COCour->Suivant; } UMECour = UMECour->Suivant; } InitKeyboard(NULL,KbType,KbMap); InitScreen(CrtType); NbWins = Wins; History = Hi; if(ColorDisplay) { CmdLineNorm = PackAtt(WHITE,BLACK); MainWinNorm = PackAtt(CYAN_B,BLUE); MainWinInv = PackAtt(BLACK,CYAN); MainWinBold = PackAtt(YELLOW_B,BLUE); MainWinTitle = PackAtt(BLACK,CYAN); MainWinTagRev = PackAtt(YELLOW_B,CYAN); MenuNorm = PackAtt(BLACK,CYAN); MenuInv = PackAtt(WHITE_B,BLACK); AboutNorm = PackAtt(BLACK,WHITE); AboutInv = PackAtt(BLACK,CYAN); HelpNorm = PackAtt(BLACK,CYAN); HelpInv = PackAtt(WHITE_B,BLACK); HelpBold = PackAtt(WHITE_B,CYAN); FullInfoNorm = PackAtt(WHITE_B,CYAN); FullInfoInv = PackAtt(WHITE_B,BLACK); FullInfoBold = PackAtt(BLACK,CYAN); BugNorm = PackAtt(BLACK,WHITE); BugInv = PackAtt(BLACK,CYAN); ErrorNorm = PackAtt(WHITE_B,RED); ErrorInv = PackAtt(WHITE_B,BLACK); QuitNorm = PackAtt(BLACK,WHITE); QuitInv = PackAtt(BLACK,CYAN); SelectNorm = PackAtt(BLACK,WHITE); SelectInv = PackAtt(BLACK,CYAN); HistoryNorm = PackAtt(BLACK,WHITE); HistoryInv = PackAtt(BLACK,CYAN); UserMenuNorm = PackAtt(BLACK,WHITE); UserMenuInv = PackAtt(BLACK,CYAN); FileOpNorm = PackAtt(BLACK,WHITE); FileOpInv = PackAtt(BLACK,CYAN); FileOpBar = PackAtt(WHITE,BLACK); ConfirmNorm = PackAtt(WHITE_B,RED); ConfirmInv = PackAtt(WHITE_B,BLACK); DoingNorm = PackAtt(WHITE_B,MAGENTA); ProcessNorm = PackAtt(BLACK,WHITE); ProcessInv = PackAtt(BLACK,CYAN); SignalsNorm = PackAtt(WHITE_B,GREEN); SignalsInv = PackAtt(WHITE_B,BLACK); FindFileNorm = PackAtt(BLACK,CYAN); FindFileInv = PackAtt(WHITE_B,BLACK); FindFileSaveNorm = PackAtt(BLACK,WHITE); FindFileSaveInv = PackAtt(BLACK,CYAN); IPCNorm = PackAtt(BLACK,WHITE); IPCInv = PackAtt(BLACK,CYAN); OpOKNorm = PackAtt(WHITE_B,BLUE); OpOKInv = PackAtt(BLACK,CYAN); TreeNorm = PackAtt(BLACK,WHITE); TreeInv = PackAtt(BLACK,CYAN); } else { CmdLineNorm = PackAtt(NORMAL); MainWinNorm = PackAtt(NORMAL); MainWinInv = PackAtt(REVERSE); MainWinBold = PackAtt(BOLD); MainWinTitle = PackAtt(REVERSE); MainWinTagRev = PackAtt(REVERSE); MenuNorm = PackAtt(REVERSE); MenuInv = PackAtt(BOLD); AboutNorm = PackAtt(REVERSE); AboutInv = PackAtt(BOLD); HelpNorm = PackAtt(NORMAL); HelpInv = PackAtt(REVERSE); HelpBold = PackAtt(BOLD); FullInfoNorm = PackAtt(NORMAL); FullInfoInv = PackAtt(REVERSE); FullInfoBold = PackAtt(BOLD); BugNorm = PackAtt(REVERSE); BugInv = PackAtt(BOLD); ErrorNorm = PackAtt(BOLD); ErrorInv = PackAtt(REVERSE); QuitNorm = PackAtt(REVERSE); QuitInv = PackAtt(BOLD); SelectNorm = PackAtt(REVERSE); SelectInv = PackAtt(BOLD); HistoryNorm = PackAtt(REVERSE); HistoryInv = PackAtt(BOLD); UserMenuNorm = PackAtt(REVERSE); UserMenuInv = PackAtt(BOLD); FileOpNorm = PackAtt(REVERSE); FileOpInv = PackAtt(BOLD); FileOpBar = PackAtt(REVERSE); ConfirmNorm = PackAtt(BOLD); ConfirmInv = PackAtt(REVERSE); DoingNorm = PackAtt(BOLD); ProcessNorm = PackAtt(REVERSE); ProcessInv = PackAtt(BOLD); SignalsNorm = PackAtt(BOLD); SignalsInv = PackAtt(REVERSE); FindFileNorm = PackAtt(REVERSE); FindFileInv = PackAtt(BOLD); FindFileSaveNorm = PackAtt(BOLD); FindFileSaveInv = PackAtt(REVERSE); IPCNorm = PackAtt(REVERSE); IPCInv = PackAtt(BOLD); OpOKNorm = PackAtt(BOLD); OpOKInv = PackAtt(REVERSE); TreeNorm = PackAtt(REVERSE); TreeInv = PackAtt(REVERSE); } } /***************************************************************************** TestQuit() ------------------------------------------------------------------------------ Input: / Process: boite de dialogue de confirmation de sortie Output: 1 si oui, 2 si non. *****************************************************************************/ int TestQuit(void) { AnswerBoxItem_t *Msg = (AnswerBoxItem_t *)NULL, *Choices = (AnswerBoxItem_t *)NULL; int rc; InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); AddAnswerBoxItem(&Msg," You want to quit Pash? "); AddAnswerBoxItem(&Choices,"Yes"); AddAnswerBoxItem(&Choices,"No"); rc = AnswerBox(QuitNorm,QuitInv," Quit ",Msg,Choices,0,0,DOUBLE_FRAMED); InitAnswerBoxItem(&Msg); InitAnswerBoxItem(&Choices); return(rc); } /***************************************************************************** GetNbTagged() ------------------------------------------------------------------------------ Input: - pointeur sur une liste - pointeur sur deux entiers Output: le nombre de fichiers marques et la somme en bytes de leurs tailles. *****************************************************************************/ void GetNbTagged(DirList_t *Liste,int *NbTagged,int *NbBytes) { int t,b; for(t=0,b=0; Liste != (DirList_t *)NULL; Liste = Liste->Suivant) if(Liste->Info.Tagged) { t++; b += Liste->Info.s.st_size; } *NbTagged = t; *NbBytes = b; } /***************************************************************************** GetNbEntries() ------------------------------------------------------------------------------ Input: Un pointeur sur une liste de fichiers Process: calcul du nombre d'entrees dans cette liste Output: ce nombre *****************************************************************************/ int GetNbEntries(DirList_t *Liste) { int i; for(i=0;Liste != (DirList_t *)NULL;Liste = Liste->Suivant,i++); return(i); } /***************************************************************************** DisplayEntry() ------------------------------------------------------------------------------ Input: une entree dans une liste, une ligne et une colonne Process: affichage de l'entree aux coordonnees demandees. Fait la difference entre une entree marquee et non marquee. *****************************************************************************/ void DisplayEntry(FileInfo_t Entry,int Lig,int Col) { char Date[30]; char Att; SetCurrentAtt(MainWinNorm); if(Entry.Name == (char *)NULL) { /* Entree vide */ PutChar(F_S_VE,Lig,Col + 14); PutChar(F_S_VE,Lig,Col + 23); PutChar(F_S_VE,Lig,Col + 32); return; } if(Entry.Tagged) Att = MainWinBold; else Att = MainWinNorm; /* Nom: tronquer si besoin */ if(strlen(Entry.Name) > 14) { strcpy(DummyStr,Entry.Name); DummyStr[13] = '>'; DummyStr[14] = F_S_VE; DummyStr[15] = 0; } else sprintf(DummyStr,"%-14s%c",Entry.Name,F_S_VE); /* Taille */ sprintf(DummyStr + strlen(DummyStr),"%8d%c",Entry.s.st_size,F_S_VE); /* Date et heure */ ConvertDate(Date,Entry.s.st_mtime); Date[8] = F_S_VE; strcat(DummyStr,Date); WriteString(DummyStr,Att,Lig,Col); } /***************************************************************************** ChangeNbWins() ------------------------------------------------------------------------------ Input,Output: / Process: passage 2 fenetres <-> 4 fenetres avec mise a jour complete *****************************************************************************/ void ChangeNbWins(void) { int i; if(NbWins == 2) { /* Reaffectation des record de coordonnees */ AshWin[0] = TOP_LEFT_WIN; AshWin[1] = TOP_RIGHT_WIN; AshWin[2] = BOT_LEFT_WIN; AshWin[3] = BOT_RIGHT_WIN; /* Chgt du nbre de fenetres */ NbWins = 4; /* Reactualisation */ for(i=0;iInfo.Name != (char *)NULL)) strcpy(Current[i]->Info.Name,"."); chdir(WorkingDir[i]); InitWin(i); } /* Repasser dans le ss-rep de la fenetre active */ chdir(WorkingDir[AL]); /* Inverser la premiere option de la fenetre active */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } else { /* Reaffectation des variables de coordonnees */ AshWin[0] = LEFT_WIN; AshWin[1] = RIGHT_WIN; /* Chgt du Nbre de fenetres */ NbWins = 2; /* Si la barre est en dessous, grandir les fenetres du dessous */ if(AL > 1) { strcpy(DummyStr,WorkingDir[0]); strcpy(WorkingDir[0],WorkingDir[2]); strcpy(WorkingDir[2],DummyStr); strcpy(DummyStr,WorkingDir[1]); strcpy(WorkingDir[1],WorkingDir[3]); strcpy(WorkingDir[3],DummyStr); AL -= 2; } /* Redessiner les fenetres */ for(i=0;iInfo.Name != (char *)NULL)) strcpy(Current[i]->Info.Name,"."); chdir(WorkingDir[i]); InitWin(i); } /* Se replacer dans le ss-rep de la fenetre active */ chdir(WorkingDir[AL]); /* Inverser la premiere option de la fenetre active */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } /* Replacer le curseur a sa position */ GotoXY(AfficheY,AfficheX); /* Balancer le tout */ fflush(stdout); } /***************************************************************************** DisplaySelection() ------------------------------------------------------------------------------ Input: numero de la fenetre Process: affichage du nombre de fichiers selectionnes et du nombre de bytes total de la selection en bas de la fenetre correspondante. Output: / *****************************************************************************/ void DisplaySelection(int Nb) { int t,b; char Att; GetNbTagged(List[Nb],&t,&b); sprintf(DummyStr,"Selected: %ld %s, %ld %s",t,(t < 2) ? "file" : "files", b,(b < 2) ? "byte" : "bytes"); SetString(AshWin[Nb].ExtLig + AshWin[Nb].ExtHeight - 2, AshWin[Nb].ExtCol + 2,AshWin[Nb].IntLength - 1,' '); if(t == 0) Att = MainWinNorm; else Att = MainWinBold; WriteString(DummyStr,Att, AshWin[Nb].ExtLig + AshWin[Nb].ExtHeight - 2, AshWin[Nb].ExtCol + (AshWin[Nb].IntLength / 2) - (strlen(DummyStr) / 2)); } /***************************************************************************** RedisplayWin() ------------------------------------------------------------------------------ Input: numero de la fenetre Process: affichage du contenu d'une fenetre sans reinitialisation de quoi que ce soit. A utiliser par exemple apres une operation de copie qui ne modifie pas le contenu de la fenetre. *****************************************************************************/ void RedisplayWin(int Nb) { int Deb,Cpt; Deb = InvZone[Nb].Lig - AshWin[Nb].IntLig; /* Placer Dummy sur le premier fichier a afficher dans la fenetre */ for(Dummy = Current[Nb]; Deb > 0 && Dummy != (DirList_t *)NULL; Deb--,Dummy = Dummy->Prec); /* Afficher a partir de ce premier fichier jusqu'au bout de la fenetre ou de la liste */ for(Cpt=AshWin[Nb].IntLig; Cpt < (AshWin[Nb].IntLig + AshWin[Nb].IntHeight) && Dummy != (DirList_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,Cpt,AshWin[Nb].IntCol); /* Remplir les blancs si necessaire */ if(Cpt < (AshWin[Nb].IntLig + AshWin[Nb].IntHeight)) for(; Cpt < (AshWin[Nb].IntHeight + AshWin[Nb].IntLig); Cpt++) DisplayEntry(BlankEntry,Cpt,AshWin[Nb].IntCol); DisplaySelection(Nb); } /***************************************************************************** InitWin() ------------------------------------------------------------------------------ Input: numero de fenetre Process: Initialisation des variables associees a une fenetre et affichage de cette fenetre. Suppose que le ss-rep courant est celui pointe par la fenetre (il faut effectuer le chdir() avant l'appel). Output: / *****************************************************************************/ void InitWin(int i) { int j,Deb,Cpt; char OldCurrent[FILENAME_LENGTH],OldWorkingDir[FILENAME_LENGTH],Line[50]; DirList_t *OldList,*Dummy2; Line[0] = F_BDSD; for(j=1;j<39;j++) Line[j] = F_S_HO; Line[j] = F_SDBD; Line[j+1] = 0; /* Stocker le nom de l'ancien fichier en inverse, de facon a y replacer la barre. S'il n'existe pas (premier appel), y mettre ".", ce qui force la barre au sommet (non trouve) */ if((Current[i] == (DirList_t *)NULL) || (Current[i]->Info.Name == (char *)NULL)) strcpy(OldCurrent,"."); else strcpy(OldCurrent,Current[i]->Info.Name); /* Stocker l'ancien ss-rep courant: si le ss-rep actuel est le meme, il faut reinitialiser la liste en reportant les fichiers marques. */ strcpy(OldWorkingDir,WorkingDir[i]); /* Dessiner la fenetre a l'ecran */ PaintWin(AshWin[i].ExtLig,AshWin[i].ExtCol, AshWin[i].ExtHeight,AshWin[i].ExtLength, MainWinNorm,DOUBLE_FRAMED,UNSHADED); WriteString(Line,MainWinNorm, AshWin[i].ExtLig + AshWin[i].ExtHeight - 3,AshWin[i].ExtCol); /* Rectifier les jointures avec la verticales */ PutChar(F_DBDS,AshWin[i].ExtLig,AshWin[i].ExtCol + 15); PutChar(F_DBDS,AshWin[i].ExtLig,AshWin[i].ExtCol + 24); PutChar(F_DBDS,AshWin[i].ExtLig,AshWin[i].ExtCol + 33); PutChar(F_SSSB,AshWin[i].ExtLig + AshWin[i].ExtHeight - 3, AshWin[i].ExtCol + 15); PutChar(F_SSSB,AshWin[i].ExtLig + AshWin[i].ExtHeight - 3, AshWin[i].ExtCol + 24); PutChar(F_SSSB,AshWin[i].ExtLig + AshWin[i].ExtHeight - 3, AshWin[i].ExtCol + 33); /* Affichage des titres des colonnes */ GotoXY(AshWin[i].IntLig - 1,AshWin[i].IntCol); SetCurrentAtt(MainWinBold); Printf(" Name "); SetCurrentAtt(MainWinNorm); Printf("%c",F_S_VE); SetCurrentAtt(MainWinBold); Printf(" Size "); SetCurrentAtt(MainWinNorm); Printf("%c",F_S_VE); SetCurrentAtt(MainWinBold); Printf(" Date "); SetCurrentAtt(MainWinNorm); Printf("%c",F_S_VE); SetCurrentAtt(MainWinBold); Printf("Time "); SetCurrentAtt(MainWinNorm); /* Initialiser la chaine de caracteres contenant le ss-rep courant */ if(getcwd(WorkingDir[i],64) == NULL) kill(SIGQUIT,getpid()); /* Affichage du ss-rep au sommet de la fenetre */ strcpy(DummyStr," "); if(strlen(WorkingDir[i]) < AshWin[i].ExtLength - 3) strcat(DummyStr,WorkingDir[i]); else { strcat(DummyStr,"/..."); strcat(DummyStr,WorkingDir[i] + (strlen(WorkingDir[i]) - AshWin[i].ExtLength + 8)); } strcat(DummyStr," "); WriteString(DummyStr,MainWinTitle,AshWin[i].ExtLig, (AshWin[i].ExtCol + (AshWin[i].ExtLength / 2)) - (strlen(DummyStr) / 2)); fflush(stdout); /* Constituer la liste correspondant au ss-rep courant */ if(strcmp(OldWorkingDir,WorkingDir[i]) == 0) { /* Pas de changement de ss-rep: reinitialiser la fenetre de facon aussi proche que possible de l'original en tenant compte des fichiers toujours marques */ /* Recherche dans l'ancienne liste des fichiers marques et transfert du marquage dans la nouvelle liste */ OldList = List[i]; Dir(".",&List[i]); for(Dummy2 = OldList; Dummy2 != (DirList_t *)NULL; Dummy2 = Dummy2->Suivant) if(Dummy2->Info.Tagged) for(Dummy = List[i]; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) if(strcmp(Dummy->Info.Name,Dummy2->Info.Name) == 0) Dummy->Info.Tagged = 1; /* Liberation de l'ancienne liste */ FreeAllTheList(&OldList); } else { /* Il y a eu un chgt de ss-rep: reinitialisation complete */ FreeAllTheList(&List[i]); Dir(".",&(List[i])); } /* Initialiser le nombre d'entrees */ NbEntries[i] = GetNbEntries(List[i]); /* Initialiser le pointeur End sur le dernier element de la liste */ for(Dummy = List[i], End[i] = (DirList_t *)NULL; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) End[i] = Dummy; /* Recherche dans la liste actuelle de la position de l'element en inverse avant la reinitialisation de la fenetre. Son nom est stocke dans OldCurrent. en fin de boucle, deux cas: - si touve: j == numero d'ordre de l'element dans la liste Current[i] pointe sur l'element - si absent: j == Nbre d'elements dans la liste Current[i] pointe sur NULL */ for(j=0,Current[i] = List[i]; (Current[i] != (DirList_t *)NULL) && (strcmp(Current[i]->Info.Name,OldCurrent) != 0); j++,Current[i] = Current[i]->Suivant); if(Current[i] == (DirList_t *)NULL) { /* Absent: reinitialiser la fenetre avec affichage a partir du debut de la liste et barre en inverse placee sur le premier element de la liste. Pour forcer cette operation (cas de la relecture d'une fenetre par Ctrl-R), il suffit d'initialiser Current[AL]->Info.Name a ".". En effet, le fichier "." n'est jamais repris par la fonction Dir() */ /* Affichage de la partie superieure de la liste */ for(j=AshWin[i].IntLig,Dummy = List[i]; j < (AshWin[i].IntLig + AshWin[i].IntHeight) && Dummy != (DirList_t *)NULL; j++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,j,AshWin[i].IntCol); /* Completer les blancs si necessaire */ if(NbEntries[i] < AshWin[i].IntHeight) { for(; j < AshWin[i].IntHeight + AshWin[i].IntLig; j++) DisplayEntry(BlankEntry,j,AshWin[i].IntCol); } /* Initialisation du pointeur d'element courant sur le premier element de la liste */ Current[i] = List[i]; /* Initialisation de la zone d'invertion sur le premier element de la liste */ InvZone[i].Lig = AshWin[i].IntLig; InvZone[i].Col = AshWin[i].IntCol; InvZone[i].Length = AshWin[i].IntLength; /* Initialisation de l'index de selection sur le premier element de la liste */ SelIndex[i] = 0; } else { /* Trouve: il faut redessiner la fenetre de facon aussi proche que possible de ce qu'elle etait avant le reinitialisation en placant la barre en inverse sur le meme fichier. La reinitialisation est guide par j qui contient le numero d'ordre du fichier dans la liste: il faut tester par rapport a la hauteur de la fenetre. Il faut tester les blancs en debut ou en fin de fenetre. */ /* Rectifier l'index de selection (il peut avoir change) */ SelIndex[i] = j; if(j > AshWin[i].IntHeight - 1) { /* Fenetre trop courte pour afficher du debut avec l'inverse */ /* Placer Dummy sur le premier fichier a afficher dans la fenetre */ for(Dummy = Current[i],Deb = AshWin[i].IntHeight - 1; Deb > 0 && Dummy != (DirList_t *)NULL; Deb--,Dummy = Dummy->Prec); /* Afficher a partir de ce premier fichier jusqu'au bout de la fenetre ou de la liste */ for(Cpt=AshWin[i].IntLig; Cpt < (AshWin[i].IntLig + AshWin[i].IntHeight) && Dummy != (DirList_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,Cpt,AshWin[i].IntCol); /* Remplir les blancs si necessaire */ if(Cpt < (AshWin[i].IntLig + AshWin[i].IntHeight)) for(; Cpt < (AshWin[i].IntHeight + AshWin[i].IntLig); Cpt++) DisplayEntry(BlankEntry,Cpt,AshWin[i].IntCol); /* Actualiser la zone d'inversion */ InvZone[i].Lig = AshWin[i].IntLig + AshWin[i].IntHeight - 1; } else { /* Afficher du debut */ /* Afficher a partir de ce premier fichier jusqu'au bout de la fenetre ou de la liste */ for(Cpt=AshWin[i].IntLig,Dummy = List[i]; Cpt < (AshWin[i].IntLig + AshWin[i].IntHeight) && Dummy != (DirList_t *)NULL; Cpt++,Dummy = Dummy->Suivant) DisplayEntry(Dummy->Info,Cpt,AshWin[i].IntCol); /* Remplir les blancs si necessaire */ if(Cpt < (AshWin[i].IntLig + AshWin[i].IntHeight)) for(; Cpt < (AshWin[i].IntHeight + AshWin[i].IntLig); Cpt++) DisplayEntry(BlankEntry,Cpt,AshWin[i].IntCol); /* Fixer la zone d'inversion */ InvZone[i].Lig = AshWin[i].IntLig + j; } } /* Afficher les fichiers selectionnes */ DisplaySelection(i); } /***************************************************************************** Redraw() ------------------------------------------------------------------------------ Input,Output: / Process: reaffichage de l'ecran avec reinitialisation de chaque fenetre. *****************************************************************************/ void Redraw(void) { int i; ClrScr(); /* Titre */ PaintString(1,1,80,MainWinTitle); sprintf(DummyStr,"%s %c",PROG_NAME,F_S_VE); WriteString(DummyStr,MainWinTitle,1,3); DisplayMenuBar(Menu,MainWinTitle,NB_MENUS); WriteString("Ctrl-G = Menu",MainWinTitle,1,50); fflush(stdout); /* Toutes les fenetres */ for(i=0;iInfo.Name); system(DummyStr); SetKeyboard(); Redraw(); if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); chdir(WorkingDir[AL]); if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } SetCurrentAtt(CmdLineNorm); strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s%s",Prompt,CmdLine); GotoXY(AfficheY,AfficheX); fflush(stdout); } /***************************************************************************** MultipleTag() ------------------------------------------------------------------------------ Selection multiple *****************************************************************************/ void MultipleTag(void) { /* Saisir le masque de selection */ if(InputBox(TagMask,TAGMASK_LENGTH,SelectNorm,SelectInv," Select Files ", "Enter selection mask:",0,0,DOUBLE_FRAMED) == 0) { /* Marquer les fichiers dans la liste courante sans prendre les ss-rep */ for(Dummy = List[AL]; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) if(strcmp(Dummy->Info.Name,"..") != 0) { if(IS_DIR(Dummy->Info.s.st_mode)) if(IsInMask(TagMask,(Dummy->Info.Name) + 1)) Dummy->Info.Tagged = 1; else ; else if(IsInMask(TagMask,Dummy->Info.Name)) Dummy->Info.Tagged = 1; } RedisplayWin(AL); if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } } /***************************************************************************** MultipleUntag() ------------------------------------------------------------------------------ Deselection multiple *****************************************************************************/ void MultipleUntag(void) { if(InputBox(TagMask,TAGMASK_LENGTH,SelectNorm,SelectInv," Deselect Files ", "Enter deselection mask:",0,0,DOUBLE_FRAMED) == 0) { for(Dummy = List[AL]; Dummy != (DirList_t *)NULL; Dummy = Dummy->Suivant) if(strcmp(Dummy->Info.Name,"..") != 0) { if(IS_DIR(Dummy->Info.s.st_mode)) if(IsInMask(TagMask,(Dummy->Info.Name) + 1)) Dummy->Info.Tagged = 0; else ; else if(IsInMask(TagMask,Dummy->Info.Name)) Dummy->Info.Tagged = 0; } RedisplayWin(AL); if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); } } /***************************************************************************** Refresh() ------------------------------------------------------------------------------ Relecture de la fenetre courante *****************************************************************************/ void Refresh(void) { int i; /* Verification de la presence du ss-rep suppose courant: s'il n'existe plus, passer sur le Home Directory */ if(chdir(WorkingDir[AL]) == -1) { chdir(Home); strcpy(WorkingDir[AL],Home); i=1; } else i=0; InitWin(AL); /* Inverser le premier fichier */ PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); /* Effacer la lignde de commande */ SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); /* Construction du prompt */ if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); if(i) { GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; LastCCmd = 0; CmdOff = 0; CmdLine[0] = 0; } else { for(i=ViewX1,ShiftBuf = CmdLine + NbreCharLeft; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); GotoXY(AfficheY,AfficheX); } fflush(stdout); } /***************************************************************************** GetHLNbreItems() ------------------------------------------------------------------------------ Input: un pointeur de tete Process: renvoie le nombre d'entrees dans la liste *****************************************************************************/ int GetHLNbreItems(HistList_t *Liste) { int i; for(i=0;Liste != (HistList_t *)NULL;Liste = Liste->Suivant,i++); return(i); } /***************************************************************************** HistoryList() ------------------------------------------------------------------------------ Affiche les commandes tapees dans une boite de liste. *****************************************************************************/ void HistoryList(void) { int Lig,Col,Height,Length; int ActLig,ActCol, /* Coord de la zone exploitable */ ActHeight,ActLength, i, /* Compteur */ SelIndex, /* Index de selection courant */ InvLig,InvCol, /* Coord de la zone inverse */ X,Y, /* Position du curseur avant appel */ NbreItem, Fini = 0; /* Fin d'execution */ HistList_t *Current, /* Choix courant */ *End, /* Dernier choix */ *Liste, /* Copie de la liste */ *Temp; /* Pointeur de parcours */ /* Pas de commandes tapees */ if(HistList->Suivant == (HistList_t *)NULL) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"You haven't typed any command yet."); InfoBox(ErrorNorm,ErrorInv," History List ",InfoMsg,0,0, DOUBLE_FRAMED); return; } /* Constituer la copie de la liste */ for(Liste = (HistList_t *)NULL,Current = HistList->Suivant; Current != (HistList_t *)NULL; Current = Current->Suivant) { Temp = (HistList_t *)malloc(sizeof(HistList_t)); if(Temp == (HistList_t *)NULL) raise(SIGME); Temp->CmdLine = (char *)malloc(strlen(Current->CmdLine) + 1); if(Temp->CmdLine == (char *)NULL) raise(SIGME); strcpy(Temp->CmdLine,Current->CmdLine); if(Liste == (HistList_t *)NULL) { Liste = Temp; Liste->Suivant = (HistList_t *)NULL; Liste->Prec = (HistList_t *)NULL; End = Liste; } else { Temp->Prec = End; Temp->Suivant = (HistList_t *)NULL; End->Suivant = Temp; End = Temp; } } /* Fixer les coordonnees */ Lig = 7; Col = 20; Height = 10; Length = 40; /* Calculer le nombre d'entrees dans la liste */ NbreItem = GetHLNbreItems(Liste); /* Recuperer la position du curseur */ GetXY(&Y,&X); OpenWin(Lig,Col,Height,Length,HistoryNorm,UNFRAMED,SHADED); Lig += 1; Col += 3; Height -=2; Length -=6; PaintFrame(Lig,Col,Height,Length,HistoryNorm,DOUBLE_FRAMED); SetActiveWindow(Lig+1,Col+2,Height-2,Length-4); /* Recuperer la fenetre active d'affichage */ GetActiveWindow(&ActLig,&ActCol,&ActHeight,&ActLength); /* Titre */ WriteString(" History List ",HistoryNorm,Lig,33); /* Virer le cursuer du chemin */ GotoXY(Y,X); /* Initialiser le pointeur End sur le dernier item de la liste */ for(Current = Liste,End = (HistList_t *)NULL; Current != (HistList_t *)NULL; End = Current,Current = Current->Suivant); /* Verifier la longueur de toutes les entrees, et tronquer si besoin */ for(Current = Liste; Current != (HistList_t *)NULL; Current = Current->Suivant) if(strlen(Current->CmdLine) > ActLength-2) (Current->CmdLine)[ActLength-2] = 0; /* Afficher la portion superieure de la liste dans la fenetre */ for(i=ActLig,Current = Liste; i < (ActLig + ActHeight) && Current != (HistList_t *)NULL; i++,Current = Current->Suivant) WriteString(Current->CmdLine,HistoryNorm,i,ActCol+1); /* Par defaut, option 0 */ SelIndex = 0; /* Fixer les coordonnees de la premiere zone d'invertion video */ InvLig = ActLig; InvCol = ActCol; /* Inverser la premiere option */ PaintString(InvLig,InvCol,ActLength,HistoryInv); /* Pour le moment, l'option choisie est la premiere de la liste */ Current = Liste; while(!Fini) { switch(ReadKbd()) { case CR: CloseWin(); Fini = 1; /* Recherche de la vraie commande dans l'history */ for(i=0,Current = HistList->Suivant; iSuivant); SetCurrentAtt(CmdLineNorm); strcpy(CmdLine,Current->CmdLine); SetString(CMD_LINE_LIG,1,79,' '); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); for(i=ViewX1,ShiftBuf = CmdLine; i < ViewX2 && *ShiftBuf; i++,ShiftBuf++) PutToScr(*ShiftBuf); LastAffX = AfficheX = i; CmdOff = LastCCmd = strlen(CmdLine); ToMove = strlen(ShiftBuf); if(ToMove > 0) CmdOff -= ToMove; NbreCharLeft = 0; GotoXY(AfficheY,AfficheX); fflush(stdout); /* Liberer la copie de la liste */ Current = Liste; Temp = (HistList_t *)NULL; while(Current != (HistList_t *)NULL) { Temp = Current; Current = Current->Suivant; free(Temp->CmdLine); free(Temp); } break; case DELETE: case CTRL_C: case ESC: CloseWin(); Fini = 1; Current = Liste; Temp = (HistList_t *)NULL; while(Current != (HistList_t *)NULL) { Temp = Current; Current = Current->Suivant; free(Temp->CmdLine); free(Temp); } break; case K_UP: if(Current->Prec != (HistList_t *)NULL) { /* Si le choix courant a un predecesseur, y deplacer la barre avec scrolling bas si necessaire */ SelIndex--; PaintString(InvLig,InvCol,ActLength,HistoryNorm); Current = Current->Prec; if(InvLig == ActLig) { ScrollDownWin(ActLig,ActCol,ActHeight,ActLength,1); WriteString(Current->CmdLine,HistoryNorm,ActLig,ActCol+1); } else InvLig--; PaintString(InvLig,InvCol,ActLength,HistoryInv); } break; case K_DOWN: /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ if(Current->Suivant != (HistList_t *)NULL) { /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ SelIndex++; PaintString(InvLig,InvCol,ActLength,HistoryNorm); Current = Current->Suivant; if(InvLig == ActLig + ActHeight - 1) { ScrollUpWin(ActLig,ActCol,ActHeight,ActLength,1); WriteString(Current->CmdLine,HistoryNorm,ActLig+ActHeight-1,ActCol+1); } else InvLig++; PaintString(InvLig,InvCol,ActLength,HistoryInv); } 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,HistoryNorm); 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,HistoryNorm); for(i = ActLig,Current = Liste; i < (ActLig + ActHeight) && Current != (HistList_t *)NULL; i++,Current = Current->Suivant) WriteString(Current->CmdLine,HistoryNorm,i,ActCol+1); } Current = Liste; SelIndex = 0; InvLig = ActLig; PaintString(InvLig,InvCol,ActLength,HistoryInv); } 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 != NbreItem - 1) { if(InvLig + NbreItem - SelIndex <= ActLig + ActHeight) /* Le dernier item est deja dans la fenetre: simplement deplacer la barre */ PaintString(InvLig,InvCol,ActLength,HistoryNorm); 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,HistoryNorm); /* Positionner Current sur le premier item a devoir etre reaffiche en remontant la liste a partir de la fin */ for(i = 0,Current = End; i < ActHeight - 1 && Current != (HistList_t *)NULL; i++,Current = Current->Prec); /* Affichage */ for(i = ActLig; i < (ActLig + ActHeight) && Current != (HistList_t *)NULL; i++,Current = Current->Suivant) WriteString(Current->CmdLine,HistoryNorm,i,ActCol+1); } Current = End; SelIndex = NbreItem - 1; if(NbreItem < ActHeight) InvLig = ActLig + SelIndex; else InvLig = ActLig + ActHeight - 1; PaintString(InvLig,InvCol,ActLength,HistoryInv); } 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,HistoryNorm); 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 != (HistList_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 == (HistList_t *)NULL) { Current = Liste; SelIndex = 0; } /* Affichage */ Temp = Current; ClrZone(ActLig,ActCol,ActHeight,ActLength,HistoryNorm); for(i = ActLig; i < (ActLig + ActHeight) && Temp != (HistList_t *)NULL; i++,Temp = Temp->Suivant) WriteString(Temp->CmdLine,HistoryNorm,i,ActCol+1); InvLig = ActLig; } PaintString(InvLig,InvCol,ActLength,MainWinInv); } break; case CTRL_D: case K_PGDN: /* Idem PgUp, mais vers le bas */ if(SelIndex != NbreItem - 1) { PaintString(InvLig,InvCol,ActLength,HistoryNorm); if(InvLig != ActLig + ActHeight - 1) { /* La barre est au milieu de la fenetre: simplement la placer a la fin */ if(NbreItem < ActHeight) { /* La liste est plus petite que la fenetre */ Current = End; InvLig = ActLig + NbreItem - 1; SelIndex = NbreItem - 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 != (HistList_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 == (HistList_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 = End,Temp = End,SelIndex = NbreItem - 1; i < ActHeight - 1 && Temp != (HistList_t *)NULL; i++,Temp = Temp->Prec); } /* Affichage */ ClrZone(ActLig,ActCol,ActHeight,ActLength,HistoryNorm); for(i = ActLig; i < (ActLig + ActHeight) && Temp != (HistList_t *)NULL; i++,Temp = Temp->Suivant) WriteString(Temp->CmdLine,HistoryNorm,i,ActCol+1); InvLig = ActLig + ActHeight - 1; } PaintString(InvLig,InvCol,ActLength,HistoryInv); } break; } } } /***************************************************************************** ProcessUserMenu() ------------------------------------------------------------------------------ Traitement du menu utilisateur. *****************************************************************************/ void ProcessUserMenu(void) { int rc,i,pid,stat,NbOpt; UserMenuEntry_t *UMECour; Command_t *Cour,*Prec; #ifdef SIGACT struct sigaction New,Old; #endif if(UserMenu == (ListBoxItem_t *)NULL) { InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: no User Menu defined."); AddAnswerBoxItem(&InfoMsg," See pash.txt for informations on "); AddAnswerBoxItem(&InfoMsg,"how to create $HOME/pash.mnu"); InfoBox(ErrorNorm,ErrorInv," User Menu ",InfoMsg,0,0,DOUBLE_FRAMED); return; } NbOpt = GetLBNbreItems(UserMenu); if(NbOpt >= 11) rc = ListBox(5,20,15,40,UserMenuNorm,UserMenuInv," User Menu ",UserMenu, LB_DOUBLE,DOUBLE_FRAMED); else rc = ListBox(NBRE_LIG / 2 - NbOpt / 2 - 2,20, NbOpt + 4,40,UserMenuNorm,UserMenuInv," User Menu ",UserMenu, LB_DOUBLE,DOUBLE_FRAMED); if(rc == -1) return; /* Se positionner sur la bonne entree dans le menu */ rc--; for(i=0,UMECour = UserMenuEntries; i < rc; i++) UMECour = UMECour->Suivant; Cls(); fflush(stdout); /* Retablir le terminal */ RestoreKeyboard(); ResetScreen(); /* Ignorer tous les signaux pour le process en attente */ #ifdef SIGACT New.sa_handler = SIG_IGN; sigemptyset(&New.sa_mask); New.sa_flags = 0; for(i=0;iCommands; /* Executer les commandes */ while(Cour != (Command_t *)NULL) { switch(pid=fork()) { case -1: InitAnswerBoxItem(&InfoMsg); AddAnswerBoxItem(&InfoMsg,"ERROR: impossible to fork a child process"); InfoBox(ErrorNorm,ErrorInv," Command execution ",InfoMsg,0,0, DOUBLE_FRAMED); return; break; case 0: /* Mettre tous les signaux a default pour le process fils */ #ifdef SIGACT New.sa_handler = SIG_DFL; sigemptyset(&New.sa_mask); New.sa_flags = 0; for(i=0;i %s\n",WorkingDir[AL],Cour->Command); exit(execlp(Shell,Shell,"-c",Cour->Command,NULL)); break; default: wait(&stat); } Cour = Cour->Suivant; } /* Retablissement du terminal */ SetKeyboard(); /* Retablissement du detournement des interruptions */ _SetSig_(); /* Reconstruire l'ecran */ printf("\n-- Press a key to return to Pash... --"); fflush(stdout); ReadKbd(); Redraw(); chdir(WorkingDir[AL]); /* Se replacer dans le ss-rep de la fenetre active */ /* Inverser la premiere entree de la fenetre */ if(Current[AL]->Info.Tagged) PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinTagRev); else PaintString(InvZone[AL].Lig,InvZone[AL].Col, InvZone[AL].Length,MainWinInv); SetCurrentAtt(CmdLineNorm); SetString(CMD_LINE_LIG,1,79,' '); CmdLine[0] = 0; if(strlen(WorkingDir[AL]) < 40) strcpy(Prompt,WorkingDir[AL]); else { strcpy(Prompt,"/..."); strcat(Prompt,WorkingDir[AL] + (strlen(WorkingDir[AL]) - 33)); } strcat(Prompt,">"); GotoXY(CMD_LINE_LIG,1); Printf("%s",Prompt); GetXY(&AfficheY,&AfficheX); ViewX1 = LastAffX = AfficheX; fflush(stdout); }