home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
125.lha
/
Menucure
/
Menucure.c
< prev
next >
Wrap
C/C++ Source or Header
|
1986-11-20
|
20KB
|
750 lines
/*********************************************************************
***********************************************************************
** **
** Menucure.c **
** **
** Historique Nom Description **
** ---------- ------------ ---------------------------------- **
** 06-05-88 Eric Le Saux Version originale **
** Jean Pepin **
** **
***********************************************************************
*********************************************************************/
/*********************************************************************
***********************************************************************
** **
** Club Amiga Montréal (CAM) **
** C.P. 195 STATION "N" **
** Montréal (Québec) **
** H2X 3M2, CANADA **
** **
** Je veux être propagé comme un virus ! **
** **
** DOMAINE PUBLIC - Distribution non-commerciale **
** PUBLIC DOMAIN - Freely redistributable **
** **
***********************************************************************
*********************************************************************/
#include <Menucure.h>
/*********************************************************************
***********************************************************************
**
** Comparaisons de chaînes de caractères avec wildcards.
**
** Certains titres d'écrans et de fenêtres ont des parties variantes,
** pour les reconnaître, on permet l'usage de certaines wildcards.
**
** '?' pour empecher la comparaison
** '#' pour arreter la comparaison
**
** Retourne TRUE quand les chaînes sont identiques.
*/
BOOL StrCmp (S1, S2)
STRPTR S1, S2;
{
FOREVER
{
if ( (*S1 != '\0') && (*S1 != '\0') )
{
if ( (*S1 != '?') && (*S2 != '?') )
{
if ( (*S1 == '#') || (*S2 == '#') ) return (TRUE);
if (*S1 != *S2) return (FALSE);
}
}
else return (*S1 == *S2);
S1++;
S2++;
}
return (*(S1-1) == *(S2-1));
}
/*********************************************************************
***********************************************************************
**
** Copie d'une chaîne de caractères dans une autre.
**
** N est la taille du buffer S1, incluant le terminateur '\0'.
** On copie jusqu'à N-1 caractères de S2 vers S1.
**
** Si S2 est trop grande, l'avant-dernier caractère a être mis dans S1
** est celui de troncation : '#'.
**
*/
void StrNCpy (S1, S2, N)
UBYTE *S1, *S2;
SHORT N;
{
while ( --N && (*S1++ = *S2++) );
if (!N)
{
*S1 = '\0';
*(S1-1)='#';
}
}
/*********************************************************************
***********************************************************************
**
** Calcule le nombre d'occurences d'un caractère dans un fichier
**
*/
SHORT Occurences (Fichier, Car)
FILE *Fichier;
UBYTE Car;
{
LONG Pos;
SHORT C;
SHORT N = 0;
Pos = ftell (Fichier);
while ( (C=getc(Fichier)) != EOF ) if ( C == SEP ) N++;
fseek (Fichier, Pos, 0);
return (N);
}
/*********************************************************************
***********************************************************************
**
** Modification de la largeur d'un menu et de ses items.
**
*/
void ChangeLargeur(Item, LargeurFonte, LargeurEcran)
struct MenuItem * Item;
SHORT LargeurFonte;
SHORT LargeurEcran;
{
struct MenuItem * Ptr = Item;
SHORT Max = 0, L;
SHORT LargeurTotale;
SHORT CoteGauche = Item->LeftEdge;
BOOL Commandes = FALSE;
BOOL CheckMarks = FALSE;
while (Ptr)
{
if ( (L=strlen(((IT *)Ptr->ItemFill)->IText)) > Max )
Max = L;
if (Ptr->Flags & COMMSEQ) Commandes = TRUE;
if (Ptr->Flags & CHECKIT) CheckMarks = TRUE;
Ptr = Ptr->NextItem;
}
LargeurTotale = LargeurFonte * Max;
if (Commandes) LargeurTotale += COMWIDTH;
if (CheckMarks) LargeurTotale += COMWIDTH/2;
if ( (L=CoteGauche+LargeurTotale+20) > LargeurEcran )
CoteGauche -= (L-LargeurEcran);
Ptr = Item;
while (Ptr)
{
Ptr->LeftEdge = CoteGauche;
Ptr->Width = LargeurTotale;
Ptr = Ptr->NextItem;
}
}
/*********************************************************************
***********************************************************************
**
** Modification de menus
**
*/
void ChangeMenus (Table, N)
struct TableCom *Table;
SHORT N;
{
struct Screen * Ecran;
struct Window * Fenetre;
struct Menu * Menu;
struct Menu * BandeMenu;
struct MenuItem * Item;
struct MenuItem * SubItem;
ULONG Lock;
Lock = LockIBase (0L);
Ecran = PREMIER_ECRAN;
while (Ecran)
{
if (StrCmp(Ecran->Title,Table->NomEcran))
{
Fenetre = Ecran->FirstWindow;
while (Fenetre)
{
if (StrCmp(Fenetre->Title,Table->NomFenetre))
{
BandeMenu = Menu = Fenetre->MenuStrip;
ClearMenuStrip (Fenetre);
while (Menu)
{
if (StrCmp(Menu->MenuName,Table->NomMenu))
{
Item = Menu->FirstItem;
while (Item && ( (Item->Flags & ITEMTEXT) || (Item->SubItem) ) )
{
if (StrCmp (((IT *)Item->ItemFill)->IText,Table->NomItem))
{
if (Table->NomSubItem[0]) /* s'il y a un sous-item */
{
SubItem = Item->SubItem;
while (SubItem && (SubItem->Flags & ITEMTEXT) )
{
if (StrCmp (((IT *)SubItem->ItemFill)->IText,Table->NomSubItem))
{
SubItem->Command = Table->Commande;
if (Table->Commande != NOCOM)
{
if ( ! (SubItem->Flags & COMMSEQ) )
{
SubItem->Flags |= COMMSEQ;
ChangeLargeur (Item->SubItem,
Fenetre->RPort->Font->tf_XSize,
Ecran->Width);
}
}
else if (SubItem->Flags & COMMSEQ)
{
SubItem->Flags &= ~COMMSEQ;
ChangeLargeur (Item->SubItem,
Fenetre->RPort->Font->tf_XSize,
Ecran->Width);
}
Table->Modifie = TRUE;
}
SubItem = SubItem->NextItem;
Table++;
}
}
else /* Item */
{
Item->Command = Table->Commande;
if (Table->Commande != NOCOM)
{
if ( ! (Item->Flags & COMMSEQ) )
{
Item->Flags |= COMMSEQ;
ChangeLargeur (Menu->FirstItem,
Fenetre->RPort->Font->tf_XSize,
Ecran->Width);
}
}
else if (Item->Flags & COMMSEQ)
{
Item->Flags &= ~COMMSEQ;
ChangeLargeur (Menu->FirstItem,
Fenetre->RPort->Font->tf_XSize,
Ecran->Width);
}
Table->Modifie = TRUE;
Table++;
}
}
Item = Item->NextItem;
}
}
Menu = Menu->NextMenu;
}
SetMenuStrip (Fenetre, BandeMenu);
}
Fenetre = Fenetre->NextWindow;
}
}
Ecran = Ecran->NextScreen;
}
UnlockIBase (Lock);
}
/*********************************************************************
***********************************************************************
**
** Lecture de la prochaine string dans le fichier
**
** TRUE si le séparateur attendu est rencontré.
*/
BOOL LectureString (Fichier, StrPtr)
FILE *Fichier;
STRPTR StrPtr;
{
STRPTR Ptr = StrPtr;
SHORT Car;
SHORT N = 0;
while ( ((Car=getc(Fichier)) != EOF) && (Car != SEP) && (N<(MAX-1)) )
{
*Ptr++ = Car;
N++;
}
if (Car == EOF) return (FALSE);
if ( (Car == SEP) || (N == (MAX-1)) ) *Ptr = '\0';
return (TRUE);
}
/*********************************************************************
***********************************************************************
**
** Allocation de la table des menus
**
*/
LONG AlloueTable (Table, NbMenus)
struct TableCom **Table;
SHORT NbMenus;
{
LONG BytesRequises;
BytesRequises = NbMenus * sizeof (struct TableCom);
*Table = AllocMem (BytesRequises, MEMF_PUBLIC|MEMF_CLEAR);
return (BytesRequises);
}
/*********************************************************************
***********************************************************************
**
** Lecture des menus à partir du fichier passé en paramètre
**
*/
void LectureMenus (Fichier, CLI)
FILE *Fichier;
BOOL CLI;
{
struct TableCom *Table;
SHORT Car;
SHORT NbMenus;
LONG Taille;
SHORT N, M;
/*** Allocation de la table des menus ***/
if ( ! (NbMenus = Occurences (Fichier,SEP) / 6 ) ) return;
if ( ! (Taille = AlloueTable (&Table,NbMenus)) )
{
if (CLI) printf (ERRMEM);
else DisplayBeep (NULL);
return;
}
/*** Lecture du fichier ***/
for (N=0; N<NbMenus; N++)
{
while ( ((Car=getc(Fichier)) != EOF) && (Car != SEP) );
if (Car == EOF) break;
if (!LectureString(Fichier,Table[N].NomEcran)) break;
if (!LectureString(Fichier,Table[N].NomFenetre)) break;
if (!LectureString(Fichier,Table[N].NomMenu)) break;
if (!LectureString(Fichier,Table[N].NomItem)) break;
if (!LectureString(Fichier,Table[N].NomSubItem)) break;
Table[N].Commande = getc(Fichier);
Table[N].Modifie = FALSE;
}
/*** Application de la table ***/
ChangeMenus (Table, N);
/*** Messages d'erreurs pour les menus non-modifiés ***/
for (M=0; M<N; M++)
if (!Table[M].Modifie)
if (CLI)
{
printf ("%s->%s->%s->%s->%s non-modifié pour '%c'\n",
Table[M].NomEcran, Table[M].NomFenetre,
Table[M].NomMenu, Table[M].NomItem,
Table[M].NomSubItem, Table[M].Commande);
}
else
{
DisplayBeep (NULL);
}
/*** Déallocation de la table des menus ***/
FreeMem (Table, Taille);
}
/*********************************************************************
***********************************************************************
**
** Affichage des menus
**
** Deux passes : la première pour compter le nb de menus à enregistrer,
** la deuxième pour les enregistrer.
**
** Retourne FALSE s'il a manqué de mémoire pour la table.
*/
BOOL AfficheMenus (Fichier, CLI)
FILE * Fichier;
BOOL CLI;
{
struct Screen * Ecran;
struct Window * Fenetre;
struct Menu * Menu;
struct MenuItem * Item;
struct MenuItem * SubItem;
ULONG Lock;
SHORT Passe;
SHORT NbMenus = 0;
struct TableCom * Table;
struct TableCom * Ptr;
struct TableCom * Ptr2;
LONG Taille;
/*** Création de la table de menus ***/
Lock = LockIBase (0L); /* Accès sécuritaire à IntuitionBase */
for (Passe=0; Passe<2; Passe++)
{
if (Passe==1)
{
if (!NbMenus) /* Impossible à partir du WB */
{
printf (ERRNBMENUS);
UnlockIBase (Lock);
return (FALSE);
}
if ( ! (Taille = AlloueTable (&Table,NbMenus)) )
{
if (CLI) printf (ERRMEM);
else DisplayBeep (NULL);
UnlockIBase (Lock);
return (FALSE);
}
Ptr2 = Ptr = Table;
}
Ecran = PREMIER_ECRAN;
while (Ecran)
{
Fenetre = Ecran->FirstWindow;
while (Fenetre)
{
Menu = Fenetre->MenuStrip;
while (Menu)
{
Item = Menu->FirstItem;
while (Item)
{
SubItem = Item->SubItem;
if (SubItem) while (SubItem)
{
if (SubItem->Flags & ITEMTEXT)
{
if (Passe==1)
{
StrNCpy (Ptr->NomEcran,Ecran->Title,MAX);
StrNCpy (Ptr->NomFenetre,Fenetre->Title,MAX);
StrNCpy (Ptr->NomMenu,Menu->MenuName,MAX);
StrNCpy (Ptr->NomItem,((IT *)Item->ItemFill)->IText,MAX);
StrNCpy (Ptr->NomSubItem,((IT *)SubItem->ItemFill)->IText,MAX);
Ptr->Commande = (SubItem->Flags & COMMSEQ)?SubItem->Command:NOCOM;
Ptr++;
}
else NbMenus++;
}
SubItem = SubItem->NextItem;
}
else
{
if (Item->Flags & ITEMTEXT)
{
if (Passe==1)
{
StrNCpy (Ptr->NomEcran,Ecran->Title,MAX);
StrNCpy (Ptr->NomFenetre,Fenetre->Title,MAX);
StrNCpy (Ptr->NomMenu,Menu->MenuName,MAX);
StrNCpy (Ptr->NomItem,((IT *)Item->ItemFill)->IText,MAX);
Ptr->NomSubItem[0] = '\0';
Ptr->Commande = (Item->Flags & COMMSEQ)?Item->Command:NOCOM;
Ptr++;
}
else NbMenus++;
}
}
Item = Item->NextItem;
}
Menu = Menu->NextMenu;
}
Fenetre = Fenetre->NextWindow;
}
Ecran = Ecran->NextScreen;
}
}
UnlockIBase (Lock); /* On repermet l'accès à IntuitionBase */
/*** Envoi de la table dans le fichier ***/
while (Ptr2 < Ptr)
{
fprintf (Fichier, "¹%s¹%s¹%s¹%s¹%s¹%c\n",
Ptr2->NomEcran,
Ptr2->NomFenetre,
Ptr2->NomMenu,
Ptr2->NomItem,
Ptr2->NomSubItem,
Ptr2->Commande
);
Ptr2++;
}
/*** Déallocation de la table des menus ***/
FreeMem (Table, Taille);
return (TRUE);
}
/*********************************************************************
***********************************************************************
**
** Création d'une liste de menus exécutable du WB
**
*/
void CreeWBListe (NomOutil)
UBYTE *NomOutil;
{
FILE * Fichier;
SHORT NbBytes;
BOOL Resultat;
/*** On écrit le fichier de données ***/
Fichier = fopen (NOM_DATA, "w");
if (!Fichier) return;
Resultat = AfficheMenus (Fichier, FALSE);
fclose (Fichier);
if (!Resultat) unlink (NOM_DATA);
/*** On crée son .info ***/
Fichier = fopen (NOM_DATA_INFO, "w");
if (!Fichier) return;
for (NbBytes=0; NbBytes<LONGUEUR_INFO; NbBytes++)
putc (DataInfo[NbBytes], Fichier);
fprintf (Fichier, "%c%s", (UBYTE)strlen(NomOutil), NomOutil);
fclose (Fichier);
}
/*********************************************************************
***********************************************************************
**
** Lectures des menus passés en paramètres du WB
**
** S'il n'y a pas d'argument, l'usager veut que l'on crée une liste
** des menus des fenêtres actuellement ouvertes.
*/
void WBArguments (WBMsg)
struct WBStartup *WBMsg;
{
struct WBArg *Arg = WBMsg->sm_ArgList;
SHORT NbArgs;
FILE *Fichier;
UBYTE *NomOutil = (UBYTE *) Arg->wa_Name;
Arg++; /* On saute l'outil lui-même */
if (WBMsg->sm_NumArgs==1)
CreeWBListe (NomOutil);
else
for (NbArgs=1; NbArgs<WBMsg->sm_NumArgs; NbArgs++)
{
Fichier = fopen (Arg->wa_Name, "r");
if (Fichier)
{
LectureMenus (Fichier, FALSE);
fclose (Fichier);
}
Arg++;
}
}
/*********************************************************************
***********************************************************************
**
** Programme principal
**
** Workbench:
** Outil : crée un fichier de menus NOM_DATA avec icône.
** Projet(s) : applique les menus du(des) projet(s).
** CLI:
** 1> Menucure ; crée un fichier de menus NOM_DATA.
** 1> Menucure Fichier ; applique les menus du Fichier.
** 1> Menucure -f Fichier ; crée un fichier de menus Fichier.
*/
main (argc, argv)
SHORT argc;
STRPTR argv[];
{
FILE *Fichier;
BOOL Resultat;
IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 33L);
if (!IntuitionBase)
{
if (argc) printf ("Nécessite intuition.library v33 et +\n");
exit (0);
}
if (argv[1] == '?') argc = 10; /* force l'aide */
switch (argc)
{
case 0 : WBArguments (WBenchMsg);
break;
case 1 : Fichier = fopen (NOM_DATA, "w");
if (Fichier)
{
Resultat = AfficheMenus (Fichier, TRUE);
fclose (Fichier);
if (Resultat)
printf ("Fichier %s créé par défaut\n", NOM_DATA);
else
unlink (NOM_DATA);
}
else
{
printf ("Ne peut ouvrir le fichier de sortie\n");
}
break;
case 3 : if ( *(argv[1]+1) == 'f' )
{
Fichier = fopen (argv[2], "w");
if (Fichier)
{
Resultat = AfficheMenus (Fichier, TRUE);
fclose (Fichier);
if (!Resultat) unlink (argv[2]);
}
else
{
printf ("Ne peut ouvrir '%s'\n", argv[2]);
}
break;
}
else
{
printf ("Option inconnue.\n");
}
/** L'option 2 après 3, sinon on exécute le else de ce dernier ***/
case 2 : if ( *argv[1] != '?' )
{
Fichier = fopen (argv[1], "r");
if (!Fichier)
{
printf ("Fichier '%s' introuvable\n", argv[1]);
break;
}
LectureMenus (Fichier, TRUE);
fclose (Fichier);
break;
}
/* Sinon il va aboutir dans le default: */
default:
printf ("\n
== Club Amiga Montréal ==
\n");
printf ("
Eric Le Saux & Jean Pepin
\n");
printf ("\n
USAGE
\n\n");
printf (" %s ; crée le fichier de menus '%s'\n", argv[0], NOM_DATA);
printf (" %s Fichier ; applique les menus de 'Fichier'\n", argv[0]);
printf (" %s -f Fichier ; crée un fichier de menus 'Fichier'\n\n", argv[0]);
break;
}
CloseLibrary (IntuitionBase);
}