/***************************************************************************** Gestionnaire de terminal Unix: menus.h (c) Pierre Adriaans 1994 ------------------------------------------------------------------------------ Include de menus.c Ce module permet la realisation de menus deroulants a partir du sommet de l'ecran. La disposition et les coordonnees des fenetres sont calculees automatiquement par les fonctions. Le seule chose a faire est l'enfilement des options. Le module contient trois variables globales memorisant les caracteristiques par defaut des coordonnees des menus: - ligne d'affichage des intitules (MENU_LINE) - Colonne d'affichage des intitules (MENU_COL) - ligne d'affichage des fenetres (MENUWIN_LINE) Ces variables sont modifiables et recuperables par les fonctions d'encapsulations Get...() et Set...(). En cas de modification, il faut les faire avant toute initialisation d'options ou de fenetre. Ce module gere trois types de donnees: HotKey_t: LLU d'entiers permettant d'activer certaines options par le clavier sans deplacer la barre inverse. Plusieurs codes claviers sont utilisables pour chaque option, ce qui justifie l'emploi de LLUs. MenuWindow_t: LLB de descripteurs d'options de menus. Chaque element de ce type est une entree dans une fenetre de menu. En plus des deux pointeurs de liste, il contient: - la chaine de caracteres a afficher - le nombre de combinaisons clavier (Hot Keys) permettant d'activer cette option directement. - un pointeur sur de l'entier (en fait sur un tableau d'entiers d'un nombre de case egal au champ precedent) qui contient la liste des codes claviers activant cette options directement. Ce tableau est construit a partir d'une LLU de HotKeys_t. MenuItem_t: Descripteur de menu. Chaque element de ce type est un menu individuel (une fenetre). Il contient tous les elements necessaires a l'affichage de la fenetre et de ses elements. Toutes ces caracteristiques sont calculees automatiquement par les fonctions. Les champs sont: - nom du menu dans la barre de menu - pointeur sur la LLB d'options (type MenuWindow_t) - colonne d'affichage du nom de menu (la ligne est toujours la numero 1) - colonne, longueur et hauteur de la fenetre contenant les options. La ligne est toujours celle directement en dessous de la ligne de noms de menus. Schema d'utilisation: --------------------- Il faut repecter une marche a suivre determinee pour utiliser ces menus: (1) Reserver un tableau statique ou dynamique d'elemnets de type MenuItem_t d'autant de cases qu'il y aura de menus deroulants. Notez qu'il est possible d'avoir un menu sans fenetre associee (fonction unique). (2) Construire un a un chaque menu deroulant et les enregistrer dans le tableau declare en (1). Pour chaque option, il faut: - construire une LLU de Hot Keys s'il y a lieu avant d'enregistrer l'option - enregistrer l'option dans le descripteur voulu. Si pas de Hot Key, passer (HotKey_t *)NULL comme dernier parametre. - liberer la liste de Hot Keys (3) Enregistrer le menu deroulant defini, ce qui permet de calculer toutes les caracteristiques d'affichage. Chaque menu doit etre construit et enregistre dans l'odre d'affichage: - de haut en bas pour les options dans chaque fenetre - de gauche a droite pour les fenetres dans le tableau menu. Exemple: #define NB_MENUS 3 MenuItem_t Menu[NB_MENUS]; HotKey_t *HotKey; (* Construction du premier menu *) (* Le premiere option sera activable par entree de 'v' ou de F4 *) AddHotKey(&HotKey,(int)'v'); AddHotKey(&HotKey,K_F4); AddMenuWindowItem(&(Menu[0].MenuWindow),"View/Edit: F4",HotKey); InitHotKey(&HotKey); (* Voici comment inserer un separateur (barre transversale) *) AddMenuWindowItem(&(Menu[0].MenuWindow),MENU_SEPARATOR,(HotKey_t *)NULL); (* Le seconde option sera activable par entree de 'c' ou de F5 *) AddHotKey(&HotKey,(int)'c'); AddHotKey(&HotKey,K_F5); AddMenuWindowItem(&(Menu[0].MenuWindow),"Copy: F5",HotKey); InitHotKey(&HotKey); (* Enregistrement du menu dans le tableau: le dernier parametre est le numero d'ordre du menu dans la barre de menu. En general, c'est l'indice de la case traitee. *) AddMenuItem(Menu,Menu[0].MenuWindow,"File",0); (* Construction du second menu *) (* Le premiere option sera activable par entree de 'a' ou de F1 *) AddHotKey(&HotKey,(int)'a'); AddHotKey(&HotKey,K_F1); AddMenuWindowItem(&(Menu[1].MenuWindow),"Help: F1",HotKey); InitHotKey(&HotKey); (* Le seconde option sera activable par entree de 'a' *) AddHotKey(&HotKey,(int)'a'); AddMenuWindowItem(&(Menu[1].MenuWindow),"About...",HotKey); InitHotKey(&HotKey); (* Enregistrement du menu dans le tableau *) AddMenuItem(Menu,Menu[1].MenuWindow,"Help",1); (* Etc... *) Une fois les menus deroulants tous initialises, il faut provoquer l'affichage des intitules de menus sur la premiere ligne de l'ecran: DisplayMenuBar(Menu,REVERSE,NB_MENUS); Dans le cours du programme, il faut definir une touche qui permettra l'acces aux menus deroulants. Cet acces induira l'ouverture d'une des fenetres, selon un parametre. La fonction renvoie 0 si une option a ete choisie, -1 si l'utilisateur a annule. Il faut passer deux parametres par adresse pour recuperer le numero du menu dnas lequel une option a ete choisie et le numero de cette option. Les numeros renvoyes commencent a 1 !!! Il est a noter qu'un separateur introduit dans un menu compte pour un numero d'ordre d'option. Il y aura donc un ecart de deux entre les numeros des options de part et d'autre d'un separateur. Dans la fonction ActivateMenu(), le 4eme parametre est le numero d'ordre (a partir de 1) du menu a ouvrir en premier lieu. int ChosenMenu,ChosenOption; .... if(ActivateMenu(Menu,REVERSE,BOLD,1,NB_MENUS, &ChosenMenu,&ChosenItem) == 0) switch(ChosenMenu) { case 1: switch(ChosenItem) { case 1: ... (* 3 car il y a un separateur *) case 3: ... } break; case 2: switch(ChosenItem) { case 1: ... case 2: ... } break; } Attention: ne jamais terminer une liste d'options de menus par un separateur, ce serait le SIGSEGV assure etant donne qu'un separateur est toujours saute pour passer a l'option suivante: il faut donc toujours une option apres un separateur de menu. *****************************************************************************/ #ifndef _MENUS_H_ #define _MENUS_H_ /* String enfilee dans le cas d'un separateur de menu */ #define MENU_SEPARATOR "&~#{[|^@]}$_Menu_Separator_" /* Ligne d'affichage des intitules de menus */ #define MENU_LINE (1) /* Colonne d'affichage du premier intitule de menu */ #define MENU_COL (3) /* Ligne d'affichage des fenetres d'options */ #define MENUWIN_LINE (MENU_LINE + 1) struct HotKey_s { int Key; struct HotKey_s *Suivant; }; typedef struct HotKey_s HotKey_t; struct MenuWindow_s { char *Str; int NbHotKeys,*HotKey; struct MenuWindow_s *Suivant, *Prec; }; typedef struct MenuWindow_s MenuWindow_t; struct MenuItem_s { char *Title; MenuWindow_t *MenuWindow; int ColTitle, ColWin,LengthWin,HeightWin; }; typedef struct MenuItem_s MenuItem_t; void SetMenuCol(int Col); void SetMenuLine(int Line); void SetMenuWinLine(int Line); int GetMenuCol(void); int GetMenuLine(void); int GetMenuWinLine(void); void InitHotKey(HotKey_t **Liste); int AddHotKey(HotKey_t **Liste,int Key); int GetHKNbreItems(HotKey_t *Liste); void InitMenuWindow(MenuWindow_t **Window); int AddMenuWindowItem(MenuWindow_t **Window,char *Str,HotKey_t *HotKey); int GetMWNbreItems(MenuWindow_t *Liste); void AddMenuItem(MenuItem_t Menu[],MenuWindow_t *Window,char *Title,int Num); void DisplayMenuBar(MenuItem_t Menu[],char Att,int Size); int ActivateMenu(MenuItem_t Menu[],char AttBox,char AttInv,int Num,int Size, int *ChosenMenu,int *ChosenItem); #endif