/***************************************************************************** Gestionnaire de terminal Unix: menus.c (c) Pierre Adriaans 1994 *****************************************************************************/ #include "keyboard.h" #include "screen.h" #include "printf.h" #include "menus.h" /* Variables globales de caracteristiques par defaut */ int _MenuCol_ = MENU_COL, _MenuLine_ = MENU_LINE, _MenuWinLine_ = MENUWIN_LINE; /***************************************************************************** Fonctions d'encapsulation *****************************************************************************/ void SetMenuCol(int Col) { _MenuCol_ = Col; } void SetMenuLine(int Line) { _MenuLine_ = Line; } void SetMenuWinLine(int Line) { _MenuWinLine_ = Line; } int GetMenuCol(void) { return(_MenuCol_); } int GetMenuLine(void) { return(_MenuLine_); } int GetMenuWinLine(void) { return(_MenuWinLine_); } /***************************************************************************** InitHotKey() ------------------------------------------------------------------------------ Destruction d'une LLU de Hot Keys *****************************************************************************/ void InitHotKey(HotKey_t **Liste) { HotKey_t *Cour,*Temp; Cour = *Liste; while(Cour != (HotKey_t *)NULL) { Temp = Cour; Cour = Cour->Suivant; free(Temp); } *Liste = (HotKey_t *)NULL; } /***************************************************************************** AddHotKey() ------------------------------------------------------------------------------ Ajout d'une HotKey a une liste. *****************************************************************************/ int AddHotKey(HotKey_t **Liste,int Key) { HotKey_t *Cour,*Prec, *Temp = (HotKey_t *)NULL; Temp = (HotKey_t *)malloc(sizeof(HotKey_t)); if(Temp == (HotKey_t *)NULL) raise(SIGME); Temp->Key = Key; Temp->Suivant = (HotKey_t *)NULL; if(*Liste == (HotKey_t *)NULL) *Liste = Temp; else { Cour = *Liste; Prec = (HotKey_t *)NULL; while(Cour != (HotKey_t *)NULL) { Prec = Cour; Cour = Cour->Suivant; } Prec->Suivant = Temp; } return(0); } /***************************************************************************** GetHKNbreItems() ------------------------------------------------------------------------------ Renvoie le nombre de Hot Keys dans une liste. *****************************************************************************/ int GetHKNbreItems(HotKey_t *Liste) { int i; for(i=0;Liste != (HotKey_t *)NULL;Liste = Liste->Suivant,i++); return(i); } /***************************************************************************** InitMenuWindow() ------------------------------------------------------------------------------ Initialisation a vide d'un descripteur d'options de fenetre menu. *****************************************************************************/ void InitMenuWindow(MenuWindow_t **Window) { MenuWindow_t *Cour,*Temp; Cour = *Window; while(Cour != (MenuWindow_t *)NULL) { free(Cour->Str); if(Cour->HotKey != (int *)NULL) free(Cour->HotKey); Temp = Cour; Cour = Cour->Suivant; free(Temp); } *Window = (MenuWindow_t *)NULL; } /***************************************************************************** AddMenuWindowItem() ------------------------------------------------------------------------------ Ajout d'une option de fentre menu a une liste. *****************************************************************************/ int AddMenuWindowItem(MenuWindow_t **Window,char *Str,HotKey_t *HotKey) { MenuWindow_t *Cour,*Prec, *Temp = (MenuWindow_t *)NULL; HotKey_t *Ptr; int i; /* Allocation du nouvel element */ Temp = (MenuWindow_t *)malloc(sizeof(MenuWindow_t)); if(Temp == (MenuWindow_t *)NULL) raise(SIGME); /* Allocation et initilisation du champ string */ Temp->Str = (char *)malloc(strlen(Str) + 1); if(Temp->Str == (char *)NULL) raise(SIGME); strcpy(Temp->Str,Str); /* Allocation et initialisation du tableau de HotKeys */ Temp->NbHotKeys = GetHKNbreItems(HotKey); if(Temp->NbHotKeys > 0) { Temp->HotKey = (int *)malloc(sizeof(int) * Temp->NbHotKeys); if(Temp->HotKey == (int *)NULL) raise(SIGME); for(Ptr = HotKey,i = 0; Ptr != (HotKey_t *)NULL; i++,Ptr = Ptr->Suivant) Temp->HotKey[i] = Ptr->Key; } /* Mise a jour du chainage */ Temp->Suivant = (MenuWindow_t *)NULL; if(*Window == (MenuWindow_t *)NULL) { *Window = Temp; (*Window)->Prec = (MenuWindow_t *)NULL; } else { Cour = *Window; Prec = (MenuWindow_t *)NULL; while(Cour != (MenuWindow_t *)NULL) { Prec = Cour; Cour = Cour->Suivant; } Prec->Suivant = Temp; Temp->Prec = Prec; } return(0); } /***************************************************************************** GetMWNbreItem() ------------------------------------------------------------------------------ Renvoie le nombre d'options d'une fenetre menu dans une liste *****************************************************************************/ int GetMWNbreItems(MenuWindow_t *Liste) { int i; for(i=0;Liste != (MenuWindow_t *)NULL;Liste = Liste->Suivant,i++); return(i); } /***************************************************************************** AddMenuItem() ------------------------------------------------------------------------------ Enregistrement d'une fenetre menu dans un tableau de MenuItem_t avec calcul de toutes les coordonnees. *****************************************************************************/ void AddMenuItem(MenuItem_t Menu[],MenuWindow_t *Window,char *Title,int Num) { int Length, /* Calcul de longueur d'options */ L,H, /* Lignes et colonnes d'ombrage */ NbCol,NbLig; /* Resolution d'ecran */ char A; /* Attribut d'ombrage */ MenuWindow_t *Ptr; /* Pointeur de parcours */ /* Recuperer les caracteristiques d'ombrage et la resolution d'ecran */ GetShading(&L,&H,&A); GetScreenRes(&NbLig,&NbCol); /* Reservation et Initialisation du champ intitule de menu */ Menu[Num].Title = (char *)malloc(strlen(Title) + 3); if(Menu[Num].Title == (char *)NULL) raise(SIGME); sprintf(Menu[Num].Title," %s ",Title); /* Initialisation du champs liste d'options */ Menu[Num].MenuWindow = Window; /* Calcul de la colonne d'affichage du titre: si c'est le premier menu, on prend le #define, sinon, on calcule a partir du precedent. */ if(Num > 0) Menu[Num].ColTitle = Menu[Num-1].ColTitle + strlen(Menu[Num-1].Title); else Menu[0].ColTitle = _MenuCol_; /* S'il y a une fenetre menu associee, calculer ses corrdonnees: */ if(Window != (MenuWindow_t *)NULL) { /* Hauteur: nbre d'options + 2 */ Menu[Num].HeightWin = GetMWNbreItems(Window) + 2; /* Calculer la longueur de l'option la plus longue */ for(Length=0,Ptr = Window; Ptr != (MenuWindow_t *)NULL; Ptr = Ptr->Suivant) if(strcmp(Ptr->Str,MENU_SEPARATOR) != 0) if(strlen(Ptr->Str) > Length) Length = strlen(Ptr->Str); /* Largeur de la fenetre = cette longueur + 4 */ Menu[Num].LengthWin = Length + 4; /* Colonne d'affichage: si c'est possible, une colonne a gauche de l'intitule de menu. Sinon, derniere colonne d'ecran - largeur de la fenetre */ if((Menu[Num].ColTitle - 1 + Menu[Num].LengthWin + L) < NbCol) Menu[Num].ColWin = Menu[Num].ColTitle - 1; else Menu[Num].ColWin = NbCol - L - Menu[Num].LengthWin + 1; } } /***************************************************************************** DisplayMenuBar() ------------------------------------------------------------------------------ Affichage de la barre d'intitules de menus *****************************************************************************/ void DisplayMenuBar(MenuItem_t Menu[],char Att,int Size) { int X,Y,i; char OldAtt; GetXY(&Y,&X); OldAtt = GetCurrentAtt(); GotoXY(_MenuLine_,_MenuCol_); SetCurrentAtt(Att); for(i=0;iSuivant); Line[0] = F_BSSS; for(i=1;iSuivant) if(strcmp(Current->Str,MENU_SEPARATOR) == 0) WriteString(Line,AttBox,i,ActCol - 1); else WriteString(Current->Str,AttBox,i,ActCol+1); /* Fixer les coordonnees de la premiere zone d'invertion video */ InvLig = ActLig; InvCol = ActCol; /* Inverser la premiere option */ PaintString(InvLig,InvCol,ActLength,AttInv); /* Pour le moment, l'option choisie est la premiere de la liste */ Current = Menu[MenuIndex].MenuWindow; } else { /* Pas de fenetre associee: c'est donc termine */ PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); *ChosenItem = SelIndex + 1; *ChosenMenu = MenuIndex + 1; rc = 0; Fini = 1; } } else { /* La fenetre etait deja ouverte: on enregistre le choix */ if(IsWindow) CloseWin(); PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); *ChosenItem = SelIndex + 1; *ChosenMenu = MenuIndex + 1; rc = 0; Fini = 1; } break; case DELETE: case CTRL_C: case ESC: if(IsWindow && WindowDown) CloseWin(); rc = -1; Fini = 1; PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); break; case K_UP: if(!WindowDown) break; if(!IsWindow) break; if(Current->Prec != (MenuWindow_t *)NULL) { /* Si le choix courant a un predecesseur, y deplacer la barre avec scrolling bas si necessaire */ PaintString(InvLig,InvCol,ActLength,AttBox); Current = Current->Prec; if(strcmp(Current->Str,MENU_SEPARATOR) == 0) { Current = Current->Prec; InvLig -= 2; SelIndex -= 2; } else { InvLig--; SelIndex--; } PaintString(InvLig,InvCol,ActLength,AttInv); } else { /* Sinon, aller sur le dernier choix (wraparoud) */ PaintString(InvLig,InvCol,ActLength,AttBox); Current = End; SelIndex = NbreItem - 1; InvLig = ActLig + SelIndex; PaintString(InvLig,InvCol,ActLength,AttInv); } break; case K_DOWN: if(!WindowDown) break; if(!IsWindow) break; /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ if(Current->Suivant != (MenuWindow_t *)NULL) { /* Si le choix courant a un suivant, y deplacer la barre avec scrolling haut si necessaire */ PaintString(InvLig,InvCol,ActLength,AttBox); Current = Current->Suivant; if(strcmp(Current->Str,MENU_SEPARATOR) == 0) { Current = Current->Suivant; SelIndex += 2; InvLig += 2; } else { InvLig++; SelIndex++; } PaintString(InvLig,InvCol,ActLength,AttInv); } else { PaintString(InvLig,InvCol,ActLength,AttBox); Current = Menu[MenuIndex].MenuWindow; SelIndex = 0; InvLig = ActLig; PaintString(InvLig,InvCol,ActLength,AttInv); } break; case K_HOME: case CTRL_B: if(!WindowDown) break; if(!IsWindow) break; /* 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) { PaintString(InvLig,InvCol,ActLength,AttBox); Current = Menu[MenuIndex].MenuWindow; SelIndex = 0; InvLig = ActLig; PaintString(InvLig,InvCol,ActLength,AttInv); } break; case K_END: case CTRL_E: if(!WindowDown) break; if(!IsWindow) break; /* 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) { PaintString(InvLig,InvCol,ActLength,AttBox); Current = End; SelIndex = NbreItem - 1; InvLig = ActLig + SelIndex; PaintString(InvLig,InvCol,ActLength,AttInv); } break; case K_LEFT: PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); MenuIndex--; if(MenuIndex < 0) MenuIndex = Size - 1; SelIndex = 0; if(IsWindow && WindowDown) CloseWin(); PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttInv); if(Menu[MenuIndex].MenuWindow == (MenuWindow_t *)NULL) IsWindow = 0; else IsWindow = 1; if(IsWindow && WindowDown) { /* Calculer le nombre d'entrees dans la liste */ NbreItem = GetMWNbreItems(Menu[MenuIndex].MenuWindow); /* Recuperer la position du curseur */ GetXY(&Y,&X); OpenWin(_MenuWinLine_,Menu[MenuIndex].ColWin,Menu[MenuIndex].HeightWin, Menu[MenuIndex].LengthWin,AttBox,SINGLE_FRAMED,SHADED); /* Recuperer la fenetre active d'affichage */ GetActiveWindow(&ActLig,&ActCol,&ActHeight,&ActLength); ActCol -= 1; ActLength += 2; /* Virer le cursuer du chemin */ GotoXY(Y,X); /* Initialiser le pointeur End sur le dernier item de la liste */ for(Current = Menu[MenuIndex].MenuWindow,End = (MenuWindow_t *)NULL; Current != (MenuWindow_t *)NULL; End = Current,Current = Current->Suivant); Line[0] = F_BSSS; for(i=1;iSuivant) if(strcmp(Current->Str,MENU_SEPARATOR) == 0) WriteString(Line,AttBox,i,ActCol - 1); else WriteString(Current->Str,AttBox,i,ActCol+1); /* Fixer les coordonnees de la premiere zone d'invertion video */ InvLig = ActLig; InvCol = ActCol; /* Inverser la premiere option */ PaintString(InvLig,InvCol,ActLength,AttInv); /* Pour le moment, l'option choisie est la premiere de la liste */ Current = Menu[MenuIndex].MenuWindow; } break; case K_RIGHT: PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); MenuIndex++; if(MenuIndex == Size) MenuIndex = 0; SelIndex = 0; if(IsWindow && WindowDown) CloseWin(); PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttInv); if(Menu[MenuIndex].MenuWindow == (MenuWindow_t *)NULL) IsWindow = 0; else IsWindow = 1; if(IsWindow && WindowDown) { /* Calculer le nombre d'entrees dans la liste */ NbreItem = GetMWNbreItems(Menu[MenuIndex].MenuWindow); /* Recuperer la position du curseur */ GetXY(&Y,&X); OpenWin(_MenuWinLine_,Menu[MenuIndex].ColWin,Menu[MenuIndex].HeightWin, Menu[MenuIndex].LengthWin,AttBox,SINGLE_FRAMED,SHADED); /* Recuperer la fenetre active d'affichage */ GetActiveWindow(&ActLig,&ActCol,&ActHeight,&ActLength); ActCol -= 1; ActLength += 2; /* Virer le cursuer du chemin */ GotoXY(Y,X); /* Initialiser le pointeur End sur le dernier item de la liste */ for(Current = Menu[MenuIndex].MenuWindow,End = (MenuWindow_t *)NULL; Current != (MenuWindow_t *)NULL; End = Current,Current = Current->Suivant); Line[0] = F_BSSS; for(i=1;iSuivant) if(strcmp(Current->Str,MENU_SEPARATOR) == 0) WriteString(Line,AttBox,i,ActCol - 1); else WriteString(Current->Str,AttBox,i,ActCol+1); /* Fixer les coordonnees de la premiere zone d'invertion video */ InvLig = ActLig; InvCol = ActCol; /* Inverser la premiere option */ PaintString(InvLig,InvCol,ActLength,AttInv); /* Pour le moment, l'option choisie est la premiere de la liste */ Current = Menu[MenuIndex].MenuWindow; break; } default: if(!WindowDown) break; if(!IsWindow) break; KeyFound = 0; for(Temp = Menu[MenuIndex].MenuWindow,i=0; !KeyFound && Temp != (MenuWindow_t *)NULL; Temp = Temp->Suivant,i++) for(j=0;!KeyFound && jNbHotKeys;j++) if(Temp->HotKey[j] == Key) KeyFound = 1; if(KeyFound) { if(IsWindow) CloseWin(); PaintString(_MenuLine_,Menu[MenuIndex].ColTitle, strlen(Menu[MenuIndex].Title),AttBox); *ChosenItem = i; *ChosenMenu = MenuIndex + 1; rc = 0; Fini = 1; } } } free(Line); return(rc); }