/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\   EZ_03.C    \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/* Le fichier projet associ‚ est:      EZ_03.PRJ                        */
/* dans lequel nous pouvons voir que ce Programme comporte deux         */
/* modules:                                                             */
/*                                     EZ_03.C  gerant la fenetre       */
/*    principale. La compilation de ce module donne EZ_03.O             */
/*                                                                      */
/*                                     EZ_INFO.C gerant la fenetre      */
/*    d'information.  La compilation de ce module donne EZ_INFO.O       */
/*                                                                      */
/* Lors de la phase de linkage ces deux modules seront li‚s pour        */
/* former le programme final CHARVIEW.APP                               */
/* Le source C ci dessous est celui du module: EZ_03.O                  */
/*                                                                      */
/* Dans cet exemple nous allons gerer un dialogue affichant les         */
/* caractŠres d'une police, et permettant de selectionner une serie de  */
/* caracteres afin de pouvoir les copier dans un texte.                 */
/* seront decrits: LES LISTBOX                                          */
/*                 LES PAINTBOX                                         */
/*                 LES EDITABLES                                        */
/*                                                                      */
/* Nous allons aussi voir comment creer un programme qui se lance       */
/* aussi bien en ACC que APP ou PRG. (Ultra simple avec EAZY_GEM!!!)    */
/*                                                                      */
/*CHARGER LE PROJET DE CE PROGRAMME:                                    */
/*----------------------------------                                    */
/* selectionner … l'aide de, titre: "Project", option: "Select" du      */
/* du menu de Pure C, le fichier: EZ_03.PRJ.                            */
/* Ce programme tout simple ouvre une fenetre EAZY_GEM contenant un     */
/* dialogue d'un fichier ressource CHARVIEW.RSC                         */
/* Les nombreux commentaires permettent de s'y retrouver, et servent    */
/* de troisieme le‡on de programmation EAZY_GEM.                        */
/* Ne vous effrayez pas devant la taille de ce source, enlevez les      */
/* commentaires et vous verez qu'il est ridiculement petit et facile    */
/* de g‚rer et ouvrir une fenetre sous EAZY_GEM.                        */
/* Le fichier: EZ_03.TXT est ce fichier source ‚pur‚ de tous les trucs  */
/*     inutiles et commentaires 413 lignes                              */
/*                                                                      */
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\ I N C L U D E S \\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*--------------------- INCLUDES DES AUTRES MODULES DU PROGRAMME -------*/
#include <EAZY_GEM.H>  /* inclure les definitions des fonctions que le  */
                       /* que le module EAZY_GEM.LIB met … votre et     */
                       /* notre disposition                             */
                       /* et inclure les definitions des variables      */
                       /* globales  d'EAZY_GEM                          */
                       /* Je rappelle que le fichier EAZY_GEM.H et le   */
                       /* fichier EAZY_GEM.LIB doivent se trouver dans  */
                       /* les repertoires INCLUDE (pour le .H) et LIB   */
                       /* (pour le .LIB) de votre Pure C.               */
/* C'est … cause de cette ligne que vous avez le droit d'utiliser les   */
/* fonctions d'EAZY_GEM.                                                */
/* La lecture de ce fichier peut vous renseigner sur tout un tas de     */
/* choses. Il est toujours instructif de regarder les fichiers .H       */

/*--------------------- INCLURE LES DEFINITIONS SYMBOLIQUES ------------*/
/*                      que l'‚diteur de ressource g‚nŠre               */
/*                      lors de la cr‚ation de la ressource             */
#include "CHARVIEW.RSC\CHARVIEW.RSH"
                      /* l'inclusion des d‚finitions symboliques permet */
                      /* d'utiliser des symboles literaux plus parlants */
                      /* qu'un nombre, pour les numero d'objets.        */
                      /* Il est ‚vident qu'il est imp‚ratif de nommer   */
                      /* les objets dans votre editeur de ressources    */
                      /* pour que le fichier.H correspondant soit       */
                      /* interessant.                                   */
                      
#include "CHARVIEW.RSC\CHARMESG.H"; /* definitions des messages        */
/*ð........................... End Of Include ..........................*/

/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\ D E F I N E S  \\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
#define M_DRAG_OFF  0                 /* souris non capturee            */
#define M_DRAG_ON   2                 /* deplacement drag en cours      */

#define DRAG_ERASE  0      /* restitue juste le fond                    */
#define DRAG_DRAW   1      /* restitue le fond et dessine nouvel bitmap */

/*                         TYPAGE DES FENETRES                          */
/*----------------------------------------------------------------------*/
/* Dans EAZY_GEM, chaque fenetre doit avoir un num‚ro unique. Celui-ci  */
/* permet par la suite d'interroger EAZY_GEM pour savoir si la fenetre  */
/* correspondant … ce numero existe, ou est ouverte, ou etc....         */
/* Par exemple j'‚cris un programme comportant deux dialogues: un pour  */
/* parametrer les couleurs, et un autre affichant un choix de trames    */
/* couleurs. Chacun de ses dialogues ‚tant dans une fenetre diff‚rente, */
/* lorsque je modifie les couleurs avec le premier dialogue, il faut    */
/* repercuter la modification de couleur, sur tous les autre dialogues  */
/* concern‚s afin de les mettre … jour. Pour cela il me faut savoir si  */
/* ils existent, et sont ouverts, et auquel cas les mettre … jour, et   */
/* envoyer un message leur demandant de reafficher les ‚l‚ments         */
/* concern‚s par la modification du premier dialogue.                   */
/* On peut appeler ‡a g‚rer les multi-d‚pendances inter-dialogue.       */

/* Plutot que de manipuler un nombre abstrait qui ne me dit rien  je    */
/* pr‚fŠre d‚finir un symbole plus parlant, que j'utiliserai par la     */
/* suite dans le programme … la place du nombre, d'ou les lignes:       */
/* #define ci_dessous. (ici deux lignes car deux fenetres)              */
 
#define W_EZ_03       1     /* (identificateur ou type) de la Fenetre   */
                            /* on peut choisir n'importe quel nombre    */
                            /* entre 1 et 32000 (‡'est assez non ?)     */
                            /* Il est imp‚ratif que deux fenetres n'    */
                            /* aient pas le meme nombre.                */
#define W_RINFO       2     /* ID Fenetre information traitee dans le   */
                            /* module EZ_INFO.C                         */

/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\ T Y P E D E F \\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

/*.................. Structures speciales … MAGIC ......................*/
/*                   pour recuperer numero de version                   */
typedef struct
{
     long magic;                   /* muž $87654321 sein         */
     void *membot;                 /* Ende der AES- Variablen    */
     void *aes_start;              /* Startadresse               */
     long magic2;                  /* ist 'MAGX'                 */
     long date;                    /* Erstelldatum               */
     void (*chgres)(WORD res, WORD txt);  /* Aufl”sung „ndern    */
     void (**shel_vector)(VOID);   /* residentes Desktop         */
     char *aes_bootdrv;            /* von hieraus wurde gebootet */
     int  *vdi_device;             /* vom AES benutzter Treiber  */
     void *reservd1;               /* reserviert                 */
     void *reservd2;               /* reserviert                 */
     void *reservd3;               /* reserviert                 */
     int  version;                 /* Version ($0201 ist V2.1)   */
     int  release;                 /* 0=alpha..3=release         */
} AESVARS;

typedef struct
       {long     config_status;
        void    *dosvars;
        AESVARS *aesvars;
        void    *res1;
        void    *hddrv_functions;
        long    status_bits;
       } MAGX_COOKIE;

/*.................... table de touches de MAGIC .......................*/
/*         en fait cette structure stocke les trois pointeurs           */
/*         classiques du TOS: unshift, shift, caps eux meme             */
/*         donnant le caractere correspondant au scan_code clavier.     */
/*         pour MAGIC six autres tables supplementaires sont gerees:    */
/*         altgr_unshift, altgr_shift, altgr_caps,                      */
/*         alt_unshift, alt_shift, alt_caps.                            */
/*         Chacune de ces tables comporte 128 caracteres.               */
/*         Le scan code clavier, (de 0 … 127 selon touche appuy‚e)      */
/*         permet d'acceder au caractere qui lui est destine, en lisant */
/*         directement dans la table, … la position de son code, le     */
/*         caractere present.                                           */
/* exemple: le caractere ASCII obtenu par le scan code 23 est pour la   */
/*          table unshift (aucune touche: SHIFT ALT CAPS appuyee):      */
/*          MGkeytab.unshift[23]                                        */
/*          Bien entendu l'exemple n'est valable que si les pointeurs   */
/*          de la structure MGkeytab  ont ete initialises sur les       */
/*          bons pointeurs.                                             */

typedef struct 
   {char *unshift;
    char *shift;
    char *caps;
    char *altgr_unshift;
    char *altgr_shift;
    char *altgr_caps;
    char *alt_unshift;
    char *alt_shift;
    char *alt_caps;
   } MGKEYTAB;
   
extern Clip_p( int, int, int, int );
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\ V A R I A B L E S    G L O B A L E S \\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*........ instancier une structure de pointeurs de tables clavier .....*/
MGKEYTAB  MagicKeyTbl;
int       MagXVers = 0; /* contiendra version magic (0 si pas present)  */
/*............ reserver zone memoire des tables clavier ................*/
char     KeytabMemory[128 * 9];

void    *AdrMessRSC   = 0;  /* adresse de chargement ressource messages */
char   **TxtPtStrMess = 0;  /* pointera sur tableau de messages         */
/*..................... Chaines de la listbox ...........................*/
/*                      de choix des tables                              */
char *LSTBOX_TAB_STR[9]=  {"Unshift         ",        /* 0  */
                           "Shift           ",        /* 1  */
                           "CapsLock        ",        /* 2  */
                           "AltGr           ",        /* 3  */
                           "AltGr Shift     ",        /* 4  */
                           "AltGr Caps      ",        /* 5  */
                           "Alt             ",        /* 6  */
                           "Alt Shift       ",        /* 7  */
                           "Alt Caps        ",        /* 8  */
                          }; 
char *TAB_NAME[9]      =  {"table Unshift",
                           "table Shift",
                           "table Caps",
                           "table AltGr",
                           "table AltGr Shift",
                           "table AltGr Caps",
                           "table Alt"
                           "table Alt Shift"
                           "table Alt Caps"
                          };
static char PathAppli[256];      /* chemin ds lequel on stockera le chemin du programme */
static char PathSys[256];        /* chemin du dossier CHARVIEW.RSC                      */
static char PathKeyTab[256];     /* chemin de la table clavier chargee (si elle existe) */
static char NomKeyTab[128];      /* nom de la table clavier chargee (si elle existe)    */
static char PathVABuff[256];     /* chemin du fichier lance avec VA_START               */

static int Mstate   = M_DRAG_OFF; /* sert pour capturer action souris           */
static int Moldx    = -1;
static int Moldy    = -1;
static int *DragFnc = 0L;
static int CarPt    = -1;
static int ScanCode = 0;
int *ZoomCarBack;      /* contiendra l'adresse memoire du fond ecran    */
                       /* lors du zoom d'un caractŠre                   */
int ZoomCarBackX;      /* contiendra coordonnee X du fond ecran sauv‚.  */
int ZoomCarBackY;      /* contiendra coordonnee Y du fond ecran sauv‚.  */
int AccMenID;          /* entree de menu octroyee par le GEM lors       */
                       /* demarrage en accessoire.                      */
DID_HELP VIEWHLP;      /* structure d'aide que l'on doir remplir avant  */
                       /* d'appeler l'accessoire DIDEROT                */

/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\ P R O T O T Y P E S  F O N C T I O N S \\\\\\\\\\\\\\\*/
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/

/*................ FONCTIONS CALLBACK DE FENETRES ......................*/
/* Dans EAZY_GEM, … chaque fenetre est associ‚e une fonction CALLBACK.  */
/* CALLBACK veut dire mot … mot: appel arriŠre, en plus clair une       */
/* fonction CALLBACK, veut dire une fonction de rappel.                 */
/* Le principe est que vous DONNEZ … EAZY_GEM l'adresse de la fonction  */
/* de gestion qui va g‚rer la fenetre que vous d‚sirez ouvrir, et que   */
/* c'est EAZY_GEM, qui RAPELLERA votre fonction selon les diff‚rentes   */
/* actions et ‚v‚nements la concernant. L'int‚rˆt c'est qu'EAZY_GEM     */
/* traite pour vous tout un tas de choses ennuyeuses et difficiles, et  */
/* qu'il vous fait signe et laisse … votre charge ce qu'il ne peut pas  */
/* traiter ni pr‚voir, en rappelant votre fonction.                     */
/* Cette fa‡on de faire permet aussi une meilleure structuration des    */
/* programmes car pour chaque fenetre il existe une seule fonction de   */
/* traitement.                                                          */
/* Toute la messagerie et l'‚vŠnementiel GEM classique est transmis …   */
/* la fonction CALLBACK de Fenetre, plus d'autres messages sp‚cifiques  */
/* … EAZY_GEM, que nous verons petit … petit dans les exemples.         */
/* En r‚ponse aux messages et ‚vŠnements GEM il est possible de les     */
/* traiter tout … fait classiquement, ou comme je vous le conseille de  */
/* faire appel aux fonctions qu'EAZY_GEM met … votre disposition.       */
/* L'acc‚s aux fonctions ‚tendues de gestion de ressource en fenetre et */
/* autres aspect pointus d'EAZY_GEM ne se fait bien ‚videment qu'au     */
/* travers des fonctions pr‚vues pour cela.                             */
/*                                                                      */
/* Ces principes de programmation peuvent apparaitre difficiles pour    */
/* ceux qui n'y sont pas habitu‚s, mais apr‚s un effort d'adaptation    */
/* minime, l'on regrette de ne pas l'avoir fait avant, tellement la     */
/* programmation sous GEM semble ensuite facile !!!.                    */

/*.......... definies dans le module EZ_03.C (ici)......................*/
/* ICI je d‚clare le nom et le prototype de la fonction par defaut qui  */
/* traitera tout les messages avant qu'une fenetre soit ouverte.        */

static CALLBACK DefautCallbackProc(int w_ind, EVNT_O *Evnt);

/* ICI je d‚clare le nom et le prototype de la fonction de fenetre qui  */
/* traitera tout ce qui concerne la fenetre que l'on va ouvrir.         */

static CALLBACK WindProcEZ_03(int w_ind, EVNT_O *Evnt);

/*........ fonction de la LISTBOX choix des tables .....................*/
int LST_BOX_TabType (LIST_GET_TXT *ptLISTGETTXT);
/*.......... definie dans le module EZ_INFO.C ..........................*/
extern CALLBACK WindProcInfo(int w_ind, EVNT_O *Evnt);
/*.......... definie dans le module EAZY_GEM.C .........................*/
extern void DrawSillonHori(int *vectxy, int thickness);
/*................ FONCTIONS GENERALES ET DIVERSES .....................*/
void DropTxt(char *str, int x, int y, int ksp);
VRECT *NumCaseToVrect(OBJECT *object, int ind_ob, int scan_code, VRECT *pt_vrect);
int  GetMagicVersion(void);
int  OnGrilleCarClick(OBJECT *object, int ob_ret, EVNT_O *Evnt, VRECT *pt_vrect);
int *OpenZoomCar(char *str, int x, int y, int fntid, GRECT *limit_grect, int *rx, int *ry);
int *CloseZommCar(int *back,int x, int y);
void DrawPaintBox(int w_ind, const GRECT *grect);
int  XYtoRef(int x, int y);
void Spy(const char *mes);
void KeyTabBuffToKeyTabSys(MGKEYTAB* magic_keytabl, long magic_vers);
void KeyTabSysToKeyTabBuff(MGKEYTAB* magic_keytabl, long magic_vers);
void DragBitMap(int w_ind, int *adr_icn, int oldx , int oldy, int newx , int newy, int mode);
void ActiveWindow(int ident, long attr, char *title, CALLBACK (*w_proc)(int w_ind, EVNT_O *Evnt));
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/*               € A   C O M M E N C E   I C I   !!!!                   */
/*              Definition des fonctions de ce module                   */
/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
/* CE_APPL.CC L 139 Request for                                         */
/*---------------------------- main ------------------------------------*/
void main (void)
{Pdomain(1);
 /*.............. LES DEUX VARIABLES SUIVANTES DOIVENT ETRE ............*/
 /*           MODIFIEES AVANT APPEL A LA FONCTION: InitEazyGem()        */
 /*       les valeurs par d‚faut suffisent dans la majorit‚ des cas     */
 /*          Ici je les modifie pour montrer comment faire              */
 
 MAX_TTIPS = 100; /* nbr maxi de structures TOOL_TIPS permises.         */
                  /* ici ce programme utilise les fonctions de          */
                  /* ressource en fenetre qui utilisent les bulles      */
                  /* d'aide, donc reserver la place des bulles d'aide   */
                  /* 100 est amplement suffisant.                       */
 MAX_WIND  = 2;   /* nbr maxi de fenetres que notre application, permet */
                  /* de cr‚er en meme temps. Ici on en autorise deux.   */
                  /* celle que l'on va ouvrir, et celle des Alert en    */
                  /* fenetre. Par defaut ce nombre est de 7.            */
 
 /*............ initialiser les pointeurs de table clavier de ...........*/
 /*             la structure de pointeurs de table clavier               */
 MagicKeyTbl.unshift        = &KeytabMemory[128*0];
 MagicKeyTbl.shift          = &KeytabMemory[128*1]; 
 MagicKeyTbl.caps           = &KeytabMemory[128*2]; 
 MagicKeyTbl.altgr_unshift  = &KeytabMemory[128*3]; 
 MagicKeyTbl.altgr_shift    = &KeytabMemory[128*4]; 
 MagicKeyTbl.altgr_caps     = &KeytabMemory[128*5]; 
 MagicKeyTbl.alt_unshift    = &KeytabMemory[128*6]; 
 MagicKeyTbl.alt_shift      = &KeytabMemory[128*7];
 MagicKeyTbl.alt_caps       = &KeytabMemory[128*8];
 /*............. reperer version de Magic pour .........................*/
 /*        connaitre si 9 tables ou 3 tables sont gerees                */
 MagXVers = GetMagicVersion(); /* 0x610 */

 /*............ mettre … zero les tables ...............................*/
 memset( KeytabMemory, 0, 128 * 9);
 
 /*............ Allez maibntenant on s'occupe d'EZ_GZM .................*/
 if (InitEazyGem("CHARVIEW.ACC") != -1) /* Cette fonction initialise le */
                                        /* systŠme d'EAZY_GEM, elle dem-*/
                                        /* ande le nom du programme.    */
                                        /* si elle retourne -1 alors il */
                                        /* est impossible de poursuivre */
   
    {long len_fic;

		/*............ recuperer la table systŠme .............................*/
 		/*             et la copier dans le buffer                             */
 		KeyTabSysToKeyTabBuff(&MagicKeyTbl, MagXVers);

     /*.............. chargement de la ressource de messages ...............*/
     AdrMessRSC   = LoadAppliRsc( "CHARMESG.RSC", NO_SCALE);
     if (AdrMessRSC>(void*)10) TxtPtStrMess = GetFreeStringTab(AdrMessRSC);   
 
     /*............... RUSE nous allons considerer que ce ................*/
     /*          programme tourne toujours comme un accessoire.           */
     /*        si il est lance du bureau alors un faux message AC_OPEN    */
     /*          est imediatement envoy‚ de fa‡on … ce que l'accessoire   */
     /*            s'ouvre, si il est en accessoire on attendra le        */
     /*             message AC_OPEN provenant du menu accessoire          */
     /* Au fait:  _app est allez disons pour simplifier une variable      */
     /*                systŠme qui si egal … zero signifie que le         */
     /*                programme a demarr‚ en ACCESSOIRE, et sinon que le */
     /*                programme a demarr‚ du BUREAU.                     */
     if (!_app)  
        {/*....... si demarre en accessoire installer le titre ds menu......*/
         /*               et attendre le message AC_OPEN                    */
         /*               pour ouvrir la fenetre.                           */
         AccMenID = menu_register( Appl_id, TxtPtStrMess[MENU_TITLE]);
        }
     else
        {/*....... si demarre du bureau.....................................*/
         /*               on va envoyer un faux message AC_OPEN             */
         /*               afin d'ouvrir d'embl‚e la fenetre                 */
         int msgbuf[8];   
         AccMenID = 12345;        /*   creer une entree de menu fantaisie   */
         msgbuf[MESG]=AC_OPEN;    /*   nature du message                    */
         msgbuf[APPL]=Appl_id;    /*   iddentificateur de l'appelant (moi)  */
         msgbuf[SUPL]=0;          /*   message sans surplus                 */
         msgbuf[4]=AccMenID;      /*   placer entree de menu declenchante   */
         appl_write(Appl_id, 16, msgbuf ); 
        }   
     /*.................... Passer la main … EAZY_GEM ......................*/
     /* Ici j'appelle le Noyau d'EAZY_GEM avec en parametre le nom de la    */
     /* fonction qui va gŠrer l'evenementiel GEM en l'absence de fenetre.   */
     /* En effet dans le cas d'un accessoire, la fenetre doit etre ouverte  */
     /* apres un click sur l'option du menu accessoire. Donc il faut bien   */
     /* une fonction gerant l'evenementiel GEM (notamment celui du message  */
     /* AC_OPEN pouvant se manifester avant toute ouverture de fenetre      */
     /* puisque c'est lors de ce message que nous ouvrons la fenetre        */
     /* principale).                                                        */
     /*............ voir si il existe le fichier de configuration ..........*/
     /*             de clavier , et le charger                              */
     /*      pour differencier un VA_START normal (du bureau ou autre)      */
     /*      de celui de demarrage, je place ">" en debut de chaine         */
     
     /*............... relever le chemin du dossier systeme ................*/
     /*                           de CHARVIEW:                              */
     /*    (celui ou se trouvent les .RSC et autre fichiers de config)      */
     /*     et eventuellement relever longuer du fichier de configuration   */
     PathSys[0] = 0;   /* faire commencer la recherche au niveau programme  */
     FindFicSys(PathSys,TxtPtStrMess[PROGNAME], TxtPtStrMess[FIC_INFOTXT]);
     len_fic = Fic_exist(PathSys, TxtPtStrMess[CFG_FIC]);
     /*......... si un nom de table est associe au demarrage ................*/
     /*          demarrer avec cette table                                   */
     
     if (GetPathAppli(PathAppli, TxtPtStrMess[PROGNAME], PathVABuff+1))
        {PathVABuff[0] = '>'; /* pour signaler … VA_START qu'on demarre avec */
        }
     /*........ si le fichier "CHARVIEW.INF" (ds dossier systeme) ...........*/
     /*      indique le chemin d'une table valide demarrer avec cette table  */
     
     else if (len_fic != -1L && len_fic<255)
        {char *pt;
         strcpy(PathVABuff,">");  /* pour signaler … VA_START qu'on demarre avec */
         pt = Bload(PathSys, TxtPtStrMess[CFG_FIC], PathVABuff+1);
         while( (pt>PathVABuff+1) && (isspace(pt[-1])) ) {pt--;}
         *pt = 0;
        }
     /*........ sinon demarrer avec un nom de fichier par defaut ............*/
     else
        {strcpy(PathVABuff, ">"); 
         strcat(PathVABuff, TxtPtStrMess[KTBLS_DEFPATH]);
        }
     
     /*........ voir si le fichier de table proposee par toutes  ............*/
     /*         les solutions plus haut est valide.                          */
     if (Fic_exist(PathVABuff+1, "")==1152L) /* +1 pour sauter ">"           */
        {/*......... noter le nom si valide .................................*/
         strcpy(PathKeyTab, PathVABuff+1);
         PathNomToNomFic(PathKeyTab, NomKeyTab);
         /*......... lancer le VA_START pour demarrer .......................*/
         /*          avec les fichiers                                       */
         Send_VA_START(Appl_id, PathVABuff);
        }
     else
        {*PathVABuff=0;
        }
     /*.......... aller maintenant on lance EZ_GEM .........................*/
     if (AccMenID != -1)  /* si demarrage sans probleme.                    */
        {BouclePrincipale(DefautCallbackProc);  
        }
    }
 /*............... liberer ressource des messages ..........................*/
 if (AdrMessRSC) RscFicUnLoad(AdrMessRSC);
 /*........... appel indispensable pour finir un programme .................*/
 /*                       EZ_GEM proprement                                 */
 ExitEasyGem();   
}

/*----------------------------- GetMagicInfo --------------------------------*/
int GetMagicVersion(void)
{MAGX_COOKIE *cv;
 COOKIE      *cookie;
 cookie = Vq_cookie ('MagX');
 if (cookie==0) return 0;
 cv = (MAGX_COOKIE*) cookie->U_typ.l;
 if (cv && cv->aesvars) return (cv->aesvars->version);
 else                   return 0;
}

/*----------------------------- DefautCallbackProc --------------------------*/
/* Fonction de gestion des evenements GEM en l'absence de fenetre.           */
/* Dans cete exemple je m'en sert pour intercepter les messages AC_OPEN,     */
/* AC_CLOSE afin d'ouvrir la fenetre principale ou de fermer l'application   */

/* En entree: int w_ind est l'indice EAZY_GEM d'une fenetre. Cet indice      */
/* permet dacc‚der … la table de parametres de cette fenetre: Windtab.       */
/* et d'acc‚der … ses ‚l‚ments: par exemple le handle GEM de la fenetre      */
/* est acc‚d‚ comme suit: Windtab[w_ind].w_h                                 */
/* Dans le cas d'une fonction CALLBACK par defaut, w_ind ne sert … rien !    */
/* car la fonction peut etre appel‚e en l'absence de fenetre.                */
/* c'est pourquoi je l'incremente pour que le compilateur ne rale pas.       */

/* En entree: EVNT_O *Evnt est l'adresse (pointe sur) une structure de       */
/* type EVNT_O (voir doc et fichier EAZY_GEM.H) qui contient les donn‚es     */
/* d'‚vŠnements et de messages que la fonction de fenetre est appel‚e …      */
/* traiter.                                                                  */

CALLBACK DefautCallbackProc(int w_ind, EVNT_O *Evnt)
{/*..........................R‚pondre aux messages MU_MESAG .................*/
 /* L'‚vŠnement MU_MESAG se manifeste chaque fois qu'EAZY_GEM demande …      */
 /* la fonction de CALLBACK de r‚pondre … un message. ci_dessous nous allons */
 /* r‚pondre aux messages d'ouverture et de fermeture de l'accessoire.       */
   
 if (Evnt->evnt & MU_MESAG)
    {switch (Evnt->pipe[MESG])
       {/*****************************************************************************/
        /*......................... AID_REQUEST (EZGEM message)......................*/
        /* DIDEROT nous demande une aide et une reference pour la fenetre au dessus  */
        /* de laquelle la souris se trouve.                                          */
        /* Ce message est structure comme suit:                                      */
        /*                                                                           */
        /* En: Evnt->pipe[MESG] on trouve le message AID_REQUEST (1502)              */
        /*     Evnt->pipe[APPL] on trouve l'ID de l'appli demandeuse(DIDEROT ou nous)*/
        /*     Evnt->pipe[SUPL] on trouve  0                                         */
        /*     Evnt->pipe[WHND] se trouve le handle de la fenetre pour laquelle      */
        /*                      DIDEROT aimerait qu'on lui renvoie un fichier d'aide */
        /*                                                                           */
        /* La reponse consiste a renvoyer a DIDEROT l'adresse d'une structure:       */
        /* DID_HELP remplie avec les parametres permettant a DIDEROT d'afficher      */
        /* l'aide demandee.                                                          */
        /* La fonction EAZY_GEM: DiderotHelpReply() fait tout ce travail a notre     */
        /* place                                                                     */
        case AID_REQUEST:
             {int ref;
              ref   = XYtoRef(Evnt->x,Evnt->y);
              w_ind = IdentToIndice(W_EZ_03);
              DiderotHelpReply(w_ind,         /* indice de la fenetre pour laquelle  */
                                              /* je fourni l'aide "CHARVIEW.AID"     */
                              Evnt,           /* transmettre les evenements.         */
                              &VIEWHLP,       /* placer adresse variable d'aide.     */
                              TxtPtStrMess[AID_NAME], /* nom du fichier d'aide.              */
                              ref,            /* placer la reference.                */
                              400,            /* largeur de la fenetre.              */
                              500);           /* hauteur de la fenetre.              */
             }
             break;
        /*****************************************************************************/
        /*......................... AC_OPEN (GEM message)............................*/
        /* Cet evenement est re‡u lorsque qu'une entree ou item ou ligne             */
        /* ou option ou un peu ce que vous voulez  du menu accessoire est cliqu‚e.   */
        /* Ici on ouvre le fenetre principale.                                       */
        
        case AC_OPEN:
             if (Evnt->pipe[4] == AccMenID) /* verifier que c'est notre ligne de menu  */
                {ActiveWindow(W_EZ_03,
                              SMALLER|      /* je veux la case d'iconification         */
                              CLOSER |      /* je veux la case de fermeture            */
                              NAME   |      /* je veux la barre de titre.              */
                              MOVER  |      /* je veux bouger la barre de titre        */
                                            /*........ ATTRIBUTS EAZY_GEM .............*/
                              XBORDER|      /* Je veux la bordure sp‚ciale EAZY_GEM    */
                              XMOVER ,      /* je veux la poign‚e de d‚placement       */
                              TxtPtStrMess[WINDTITLE],
                              WindProcEZ_03);
                 }
             break;
        case AP_DRAGDROP:
             /**************************************************************/
             /*........................ AP_DRAGDROP (GEM message)..........*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* un truc a ‚t‚ drag‚ (tir‚) sur sa fenetre.                 */
            {char *data   =  (char*)GetDragDropList(Evnt, 0, 0);
             if (data)
                {/*....... si premier agument pas trop long envoyer VA_START ......*/
                 if (strlen(data)<255)
                    {strcpy(PathVABuff, data);
                     Send_VA_START(Appl_id, PathVABuff);
                    }
                 free(data);
                }  /* endif (len_data)  */
             }  /* endbloc case AP_DRAGDROP: */
             break; 
        case VA_START:          /*  (XGEM message)   */          
             /**************************************************************/
             /*........................ VA_START (GEM message).............*/
             /* Le message VA_START est envoy‚ par une autre application   */
             /* pour demander … la notre de s'activer (il faut bien sur    */
             /* qu'elle ait ete auparavant ete chargee en memoire)         */
             /* exemple dans un systeme multitache notre application est   */
             /* en sommeil, avec toutes ses fenetres en arriere plan et    */
             /* il lui est demandee de s'activer (en general pour charger  */
             /* un fichier ou toute autre chose)                           */
             /* Exemple on a double clique sur un fichier lie … notre appli*/
             /* a partir du bureau, ou on a pose un fichier sur notre appli*/
             /* ou tout simplement double clique sur l'icone de notre appli*/
             /* sans fichier ou ...                                        */
            {int w_ind         =  IsWindExist(W_EZ_03);
             int msgbuf[4];
             char *va_txt      = 0;             
             char *pt          = (char*)(*(long*)&Evnt->pipe[3]); /* pointe sur chaine VA_START               */
             /*............ renvoyer accus‚ de reception VA_START....................*/
             msgbuf[MESG]= VA_AKCNW;           /*   accuse de reception  VA_START    */
             msgbuf[APPL]= Appl_id;            /*   iddentificateur de l'appelant    */
             msgbuf[SUPL]= 0;                  /*   message sans surplus             */
             msgbuf[3]   = Evnt->pipe[3];      /*   il faut retourner l'adresse de   */
             msgbuf[4]   = Evnt->pipe[4];      /*   la chaine c'est comme ‡a !!      */
             appl_write(Evnt->pipe[APPL], 16, msgbuf );  /* on envoie le paquet      */
             /*.................. si accessoire ferme il faut l'ouvrir ..............*/
             if (!_app                                &&  /* si accessoire           */
                (w_ind == -1 || IsWindOpen(w_ind)==0)     /* ferme ou non ouvert     */
                )
                {msgbuf[MESG]= AC_OPEN;    /*   nature du message                    */
                 msgbuf[APPL]= Appl_id;    /*   iddentificateur de l'appelant (moi)  */
                 msgbuf[SUPL]= 0;          /*   message sans surplus                 */
                 msgbuf[4]   = AccMenID;   /*   placer entree de menu declenchante   */
                 /*..... si premier demarrage de l'accessoire ne pas l'ouvrir .......*/
                 /*      on teste pour cela le premier car de VA_START               */
                 /*      mis  a '>' lors de l'envoi du path de demarrage au          */
                 /*      debut du programme.                                         */
                 /*..... demarrage avec fichier glisse sur PRG ......................*/
                 if (pt !=0 && *pt != '>') 
                    {appl_write(Appl_id, 16, msgbuf );
                    }
                 /*..... demarrage lors double click sans fichier....................*/
                 else if (pt==0)          
                    {appl_write(Appl_id, 16, msgbuf );
                    }
                 /*return Evnt->evnt; */
                }
             if (pt && *pt=='>')
                { pt++;                     /* si path de demarrage sauter le '>'    */
                }
             
             /*........... creer le buffer de reception de la chaine VA_START .......*/
             if (pt <= 0 || *pt ==0)                                return 0;
             va_txt   = malloc(strlen(pt)+1); if (va_txt<=0 )       return 0;
             strcpy(va_txt, pt);        /* y copier chaine VA_START                  */
             /*....  si plusieurs fichiers les separer par des zeros de fin .........*/
             pt = va_txt;
             while(*pt) {if (*pt==32)*pt=0; pt++;}
             /*........... exploiter le message VA_START ...........................*/
             if (*va_txt && Fic_exist(va_txt, "")==1152L)
                {long ret       = Fopen( va_txt, FO_READ);
                 int  hdl       = (int)ret;
                 /*..... charger le fichier .........................................*/
                 if (ret >= 0)
                    {ret      = Fread(hdl, 9*128, KeytabMemory);
                     if (ret != (128*9))   goto rd_erreur;
                     /*........ placer la table dans celle systeme .........*/
                     KeyTabBuffToKeyTabSys(&MagicKeyTbl, MagXVers); 
                     /*......... separer path du nom .......................*/
                     strcpy(PathKeyTab, va_txt); 
                     PathNomToNomFic(PathKeyTab, NomKeyTab);
                     /*...... placer nom fichier dans titre fichier ........*/
                     if (w_ind>=0)
                        {OBJECT *object = GETWINDTREE(w_ind);
                         char *scar     = " ";
                         int i          = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
                         *scar          = KeytabMemory[ i * 128 + ScanCode ];
                         ObjcSetTxt (object, ASCCI_TABLE_SCANCAR,  scar); 
                         SendObjectRedraw( Windtab[w_ind].w_h, object, ASCCI_TABLE_SCANCAR); 
                         ObjcSetTxt (object, ASCCI_TABLE_PATH_KEYTAB,  va_txt);
                         SendObjectRedraw( Windtab[w_ind].w_h, object, ASCCI_TABLE_PATH_KEYTAB);
                         if (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)
                            {SendObjectRedraw(Windtab[w_ind].w_h,
                                  Windtab[w_ind].DlgVar.tree,
                                  ASCCI_TABLE_PAINT_BOX1);
                            }
                        }
                     else
                        {strcpy(PathVABuff, va_txt);
                        }
                     rd_erreur:
                     
                     Fclose(hdl);
                    }
                } /* endif (*va_txt)                     */
                /*............ SI chaine VA_START vide c'est que l'on ................*/
                /*          a double clique sur l'icone du programme                  */
                /*          sans fichier donc activer notre programme                 */
                /*          en mettant par exemple nos fenetres au TOP (premier plan) */
                /*          et en activant notre menu                                 */
             else
                {int i;
                 for (i=0; i<MAX_WIND; i++) /* activer nos fenetres si elles existent */
                     {if (Windtab[i].w_flag & W_IS_ICON ||
                          Windtab[i].w_flag & W_IS_ALLICON
                         )
                         {UnconifyWindow(i);
                         }
                      else if (Windtab[i].w_h>-1)
                               SendWindMessage(Windtab[i].w_h, WM_TOPPED, &Windtab[i].GemWorkGrect); /*wind_set(Windtab[i].w_h,WF_TOP); */
                     }
                }
             free (va_txt);
            }      /* end case VA START   */
             break;
        /*****************************************************************************/
        /*......................... AC_CLOSE (GEM message)...........................*/
        /* Je vous laisse deviner ce … quoi peut servir ce message !!!               */
        case AC_CLOSE:                    /* verifier que c'est notre ligne de menu  */
             if (!_app)
                {if (Evnt->pipe[3] == AccMenID)
                    {w_ind = IsWindExist(W_EZ_03); 
                     if (w_ind>-1) SendWindMessage(Windtab[w_ind].w_h, WM_CLOSED, 0);                      
                    }
                }
             break;
       } /* end switch (Evnt->pipe[MESG]) */
    }  /* end if (Evnt->evnt & MU_MESAG) */
 return Evnt->evnt;    /* retourner le flux evenementiel (modifie ou pas)    */
}
/*------------------------------ XYtoRef ---------------------------------*/
int XYtoRef(int x, int y)
{int w_h, w_ind, ob_ind, ref;
 OBJECT *object;
 w_h = wind_find(x,y);
 w_ind = WindHandToIndice(w_h);
 ref = 0;
 if (w_ind < MAX_WIND && Windtab[w_ind].ident==W_EZ_03)
    {object = GETWINDTREE(w_ind);
     ob_ind = objc_find(object,0,20,x,y);
     if ( ob_ind >= 0)
        {switch (ob_ind)
           {case ASCCI_TABLE_ROOT:          ref = 8; break;
            case ASCCI_TABLE_ICONE:         ref = 1; break;
            case ASCCI_TABLE_BULLE_ON_OFF:  ref = 6; break;
            case ASCCI_TABLE_KEYTAB_LOAD:   ref = 4; break;
            case ASCCI_TABLE_KEYTAB_SAVE:   ref = 5; break;
            case ASCCI_TABLE_PAINT_BOX1:    ref = 7; break;
            case ASCCI_TABLE_SAISIE_CAR:    ref = 3; break;
            case ASCCI_TABLE_FONT_LIST:     ref = 2; break;
           }
        }
    }
 return ref;
}

/*------------------------------ WindProcEZ_03 ---------------------------*/
/* Fonction de gestion de la fenetre de ce programme. Dans EAZY_GEM il    */
/* y a une fonction comme celle-ci, par fenetre, qui va etre appell‚e par */
/* EAZY_GEM chaque fois qu'un ‚vŠnement ou message concerne la fenetre …  */
/* laquelle elle est associ‚e.                                            */

/* En entree: int w_ind est l'indice EAZY_GEM de cette fenetre.Cet indice */
/* permet dacc‚der … la table de parametres de cette fenetre: Windtab.    */
/* et d'acc‚der … ses ‚l‚ments: par exemple le handle GEM de la fenetre   */
/* est acc‚d‚ comme suit: Windtab[w_ind].w_h                              */

/* En entree: EVNT_O *Evnt est l'adresse (pointe sur) une structure de    */
/* type EVNT_O (voir doc et fichier EAZY_GEM.H) qui contient les donn‚es  */
/* d'‚vŠnements et de messages que la fonction de fenetre est appel‚e …   */
/* traiter.                                                               */

CALLBACK WindProcEZ_03(int w_ind, EVNT_O *Evnt)
{/*....recuperer l'adresse du premier objet de la ressource....*/
 OBJECT* object = GETWINDTREE(w_ind);
 int w_h        = GETGEMHAND(w_ind);
 int wh_top; 
 wind_get( 0, WF_TOP, &wh_top); /* recuperer handle fen. avt plan.  */
 
 /*............................R‚pondre … l'‚vŠnement MU_KEYBD .........*/
 /* L'‚vŠnement MU_KEYBD se manifeste chaque fois qu'une touche clavier */
 /* est appuy‚e.                                                        */
 /* Dans le cadre d'une ressource en fenetre j'ai cree une fonction qui */
 /* s'occupe de gerer tout ce qui a un rapport avec une touche clavier  */
 /* Notamment l'edition et saisie de texte dans les champs editables et */
 /* les raccourcis clavier.                                             */
 /* Pour une ressource en fenetre il est indispensable que l'evenement  */
 /* MU_KEYBD soit traite avant l'evenement  MU_BUTTON afin de permettre */
 /* un fonctionnement correct des raccourcis clavier. En effet le       */
 /* raccourci clavier d'un objet simule un clic souris sur l'objet.     */
 /* en renvoyant un evenement MU_BUTTON                                 */
 /* Nous v‚rifions avant si la fenetre est au premier plan car si ce    */
 /* n'est pas le cas, elle n'a pas … traiter le clavier.                */
 
 if (Evnt->evnt & MU_KEYBD && Mstate == M_DRAG_OFF)
    {int i          = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
     /*.... relever codes claviers .........*/
     char buft[64];
     ScanCode       = (Evnt->key>>8)&0x00FF;  /* poids fort   */
     /*................ afficher Scan code .............................*/
     ObjcSetTxt (object, ASCCI_TABLE_SCANCODE, itoa(ScanCode, buft ,10));
     ScanCode   = Min(127, ScanCode);
     SendObjectRedraw( w_h, object, ASCCI_TABLE_SCANCODE);
     /*................ afficher caractere pointe par scan code ........*/
     /*i     = Min(6,(Max(0,i));*/
     *buft = KeytabMemory[ i * 128 + ScanCode ]; buft[1]=0;
     ObjcSetTxt (object, ASCCI_TABLE_SCANCAR,  buft); 
     SendObjectRedraw( w_h, object, ASCCI_TABLE_SCANCAR);
     
     if (ZoomCarBack) ZoomCarBack = CloseZommCar(ZoomCarBack, ZoomCarBackX, ZoomCarBackY);
     if (w_h == wh_top ) 
        {VRECT vrect;
         int num_case = -1;
         if (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)
            {num_case = ScanCode;
            }
         else if(Evnt->key&0x00FF)
            {num_case = Evnt->key&0x00FF;
            }
             /*OnGrilleCarClick(object, ASCCI_TABLE_PAINT_BOX1, Evnt, &vrect);*/
         if (num_case>-1)
            {NumCaseToVrect(object, ASCCI_TABLE_PAINT_BOX1, num_case , &vrect);
             Mouse_off();
             Graphmode(3);
             Defline(1,3,0,0,2);
             Deffill(2,1,1);
             Pbox((int*)&vrect);
             Pause_EZ(2);
             Pbox((int*)&vrect);
             Graphmode(1);
             Defline(1,1,0,0,2);
             Mouse_on();
            }
         switch(ScanCode)
             {/*............ touche HELP ...............................*/
              /* nous allons nous envoyer le message AID_REQUEST        */
              /* (comme si s'etait DIDEROT qui l'envoyait) de facon     */
              /* a declencher une reponse vers DIDEROT.                 */
              case  0x62: 
                    SendWindMessage(w_h, AID_REQUEST, 0L);
                    break;
              default:
                    Xform_keybd(w_ind, Evnt);
             }  /* end switch                             */
        }     /* endif (w_h == wh_top )  */
    }       /* endif (Evnt->evnt & MU_KEYBD)          */
  
 /*.......................... R‚pondre … l'‚vŠnement MU_BUTTON .........*/
 /* L'‚vŠnement MU_BUTTON se manifeste chaque fois qu'un bouton de la   */
 /* souris est appuy‚.                                                  */
 /* Dans le cadre d'une ressource en fenetre j'ai cree une fonction qui */
 /* s'occupe de gerer tout ce qui a un rapport avec un appui sur un     */
 /* bouton de souris: Xform_button() .                                  */
 /* Notamment l'appui sur un bouton de la ressource, la selection du    */
 /* texte dans les champs editables, et le placement du curseur de      */
 /* texte dans les champs editables.                                    */
 /* en retour cette fonction donne le num‚ro d'objet cliqu‚, si bien sur*/
 /* un objet de type TOUCHE_EXIT ou SELECTABLE est cliqu‚.              */
 
 if (Evnt->evnt & MU_BUTTON)
 {if(Mstate == M_DRAG_OFF)
    {int ob_ret=0;              /* recevra le numero d'objet cliqu‚     */
     DLG_VAR *dlg;              /* pointeur sur variable ressource      */
     TEDINFO  *tedinfo;         /* pointera sur TEDINFO zone de saisie  */
     XUSERBLK *xuserblk;        /* pointera sur XUSERBLK zone de saisie */
     char buft[256];            /* buffer de manipulation de texte      */
     int txtlen;                /* longueur texte zone de saisie        */
     /*..... initialiser pointeur sur variable ressource ....*/
     dlg = &Windtab[w_ind].DlgVar;
     /*........ relever longueur max de la zone de saisie .........*/
     xuserblk = (XUSERBLK*) object[ASCCI_TABLE_SAISIE_CAR].ob_spec.userblk->ub_parm;
     tedinfo   = xuserblk->tedinfo;
     txtlen    = tedinfo->te_txtlen - 1;
     ob_ret    = Xform_button(w_ind, Evnt);          
     if (ob_ret>0)             /*<<<<SI UN OBJET EST CLIQUE >>>>>>>>>>>*/
        {/*.... empecher propagation message  MU_BUTTON ...............*/
         /*     de fa‡on … ce qu'il ne soit pas possible de            */
         /*     cliquer sur deux fenetres … la fois.                   */
         Evnt->evnt &= ~MU_BUTTON;
         if (ob_ret == ASCCI_TABLE_PAINT_BOX1 && 
             Evnt->k != 2                     &&
             (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)
            )
            {VRECT vrect;
             char buft[64];
             int i          = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
             ScanCode       = OnGrilleCarClick(object, ob_ret, Evnt, &vrect);
             Mouse_off();
             Graphmode(3);
             Defline(1,3,0,0,2);
             Deffill(2,1,1);
             Pbox((int*)&vrect);
             Pause_EZ(2);
             Pbox((int*)&vrect);
             Graphmode(1);
             Defline(1,1,0,0,2);
             Mouse_on();
            /*................ afficher Scan code .............................*/
             ObjcSetTxt (object, ASCCI_TABLE_SCANCODE, itoa(ScanCode, buft ,10));
             ScanCode   = Min(127, ScanCode);
             SendObjectRedraw( w_h, object, ASCCI_TABLE_SCANCODE);
             /*................ afficher caractere pointe par scan code ........*/
             /*i     = Min(6,(Max(0,i));*/
             *buft = KeytabMemory[ i * 128 + ScanCode ]; buft[1]=0;
             ObjcSetTxt (object, ASCCI_TABLE_SCANCAR,  buft); 
             SendObjectRedraw( w_h, object, ASCCI_TABLE_SCANCAR);
            }
         else if (ob_ret == ASCCI_TABLE_PAINT_BOX1 && 
                  Evnt->k != 2 
                 )
            {/*......... gestion du Drag&Drop .......................*/
             if (DragFnc==0)
                {/*........ effacer curseur ancien editable .......*/
                 SetCursObEditOff(dlg);    
                 
                 /*......... recopier le texte de l'editable ............*/
                 strcpy(buft, ObjcGetTxt (object, ASCCI_TABLE_SAISIE_CAR));
                 if (Evnt->click == 2)
                    {buft[1] = 0;
                     xuserblk->BlkEnd = xuserblk->BlkDeb = 0;
                     dlg->PosCursX = 0;
                    }
                 else
                    {/*......... deplacer ce qui est apres le curseur .......*/
                     /*          1 caractere plus loin (faire la place)      */
                     memcpy(buft + dlg->PosCursX+1, 
                            buft + dlg->PosCursX,
                            txtlen - dlg->PosCursX +1 );
                    }        
                 buft[dlg->PosCursX] =  OnGrilleCarClick(object,ob_ret,Evnt, 0);
                
                 /*........ mettre … jour le bloc .......................*/
                 if (xuserblk->BlkEnd == xuserblk->BlkDeb)
                    {xuserblk->BlkDeb = dlg->PosCursX;
                    }
                 
                 /*........ incrementer le curseur ......................*/
                 dlg->PosCursX = Min(txtlen, dlg->PosCursX +1);
                 xuserblk->BlkEnd = Min((int)strlen(buft), dlg->PosCursX);
                 /*...... replacer le texte dans l'editable .............*/
                 ObjcSetTxt (object, ASCCI_TABLE_SAISIE_CAR,buft);
                 
                 /*while(Mousek());*/
                 SendObjectRedraw( w_h, object, ASCCI_TABLE_SAISIE_CAR);
                }
             if (DragFnc==0 && Evnt->k==1 && Mstate == M_DRAG_OFF)
                {VRECT vrect;
                 if (ZoomCarBack) ZoomCarBack = CloseZommCar(ZoomCarBack, ZoomCarBackX, ZoomCarBackY);
                 Mouse_off();
                 CarPt               = OnGrilleCarClick(object, ob_ret, Evnt, &vrect);
                 buft[dlg->PosCursX] = (char)CarPt;
                 DragFnc             = Get((int*)&vrect);
                 Mouse_on();
                 SetCaptureMouse (w_ind);
                 Mstate  = M_DRAG_ON;
                 Moldx   = Evnt->x;
                 Moldy   = Evnt->y;
                }
            }
         else if (ob_ret == ASCCI_TABLE_PAINT_BOX1 && 
                  Evnt->k == 2                     &&
                 !(object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)
                 )
            {char car[2]={0,0};
             car[0] = OnGrilleCarClick(object,ob_ret,Evnt, 0);
             if (ZoomCarBack==0) 
                {SetCursObEditOff(dlg);
                 ZoomCarBack = OpenZoomCar(car,
                                           Evnt->x,
                                           Evnt->y,
                                           (int)FontID[GetSelectedListBoxItem(object, ASCCI_TABLE_FONT_LIST)],
                                           &Windtab[w_ind].ExtGrectUse,
                                           &ZoomCarBackX,
                                           &ZoomCarBackY
                                          );
                }
            }
         else
            {/*.......le remettre en non selectionn‚ et le redessiner......*/
             
             /*.............. ICI ACTION SELON BOUTON CLIQUE..............*/
             /* Ici vous pouvez voir comment  il est  possible de  tester */
             /* et lancer une action selon l'objet cliqu‚. Utilisez les   */
             /* symboles du fichier .H de la ressource (ici CHARVIEW.H)   */
             /* afin de rendre votre programme plus lisible.              */
             switch (ob_ret)             
                 {case ASCCI_TABLE_ICONE:               
                       ActiveWindow(W_RINFO, XMOVER|XBORDER, TxtPtStrMess[WINDTITLE_INFO], WindProcInfo);
                       object[ob_ret].ob_state &= ~SELECTED;
                       SendObjectRedraw( w_h, object, ob_ret);
                       break;
                  case ASCCI_TABLE_KEYTAB_LIST:
                       if (!(object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)) 
                           break;
                  case ASCCI_TABLE_ASCII_SCAN_ICN:
                       SendObjectRedraw(w_h, object, ASCCI_TABLE_PAINT_BOX1);
                       break;
                  case ASCCI_TABLE_PATH_KEYTAB:
                  case ASCCI_TABLE_IC_KEYTAB_LOAD:
                  case ASCCI_TABLE_KEYTAB_LOAD:
                      {char path[256];
                       char name[128];
                       strcpy(path, PathKeyTab);
                       strcpy(name, NomKeyTab);
                       if ( FileSelect (path, name, ".SYS", TxtPtStrMess[FS_LOAD]) >=-1 &&
                            FicLen(path, name)==1152L
                          )
                          {strcpy(PathVABuff, path);
                           strcat(PathVABuff, name);
                           Send_VA_START(Appl_id, PathVABuff);
                          }
                       }
                       object[ob_ret].ob_state &= ~SELECTED;
                       SendObjectRedraw( w_h, object, ob_ret);
                       break;
                  case ASCCI_TABLE_IC_KEYTAB_SAVE:
                  case ASCCI_TABLE_KEYTAB_SAVE:  
                      {char path[256];
                       char name[128];
                       strcpy(path, PathKeyTab);
                       strcpy(name, NomKeyTab);
                       if ( FileSelect (path, name, ".SYS", TxtPtStrMess[FS_SAVE]) != -2L)
                          {long ret;
                           int  hdl;
                           strcat(path, name);
                           ret = Fcreate(path, 0);
                           hdl = (int) ret;
                           if (ret >= 0)
                              {ret      =  Fwrite(hdl, 128*9,   KeytabMemory);
                               if (ret != 128*9)   goto wr_erreur;
                               strcpy(PathKeyTab, path); 
                               PathNomToNomFic(PathKeyTab, NomKeyTab);
                               
                               ObjcSetTxt (object, ASCCI_TABLE_PATH_KEYTAB,  path);
                               SendObjectRedraw( w_h, object, ASCCI_TABLE_PATH_KEYTAB); 
                               
                               wr_erreur:
                                 
                               Fclose(hdl);
                              }
                          }
                       object[ob_ret].ob_state &= ~SELECTED;
                       SendObjectRedraw( w_h, object, ob_ret);
                      } 
                       break;   
                 }  /* end switch ob_ret  */                         
            }  /* endif if ob_ret ==  ASCCI_TABLE_PAINT_BOX1    */
        }  /* endif objet selectable cliqu‚  */ 
     } /* endif(Mstate == M_DRAG_OFF) */
 else  /* else de if(Mstate == M_DRAG_OFF) */
    {Evnt->evnt &= ~MU_BUTTON;
    } /* endelse de if(Mstate == M_DRAG_OFF) */
 } /* endif (Evnt->evnt & MU_BUTTON) */
 
 /*.......................... R‚pondre … l'‚vŠnement MU_TIMER.............*/
 /* L'‚vŠnement MU_TIMER se manifeste approximativement toutes les 200 ms */
 /* Dans le cadre d'une ressource en fenetre la fonction: Xform_timer     */
 /* s'occupe de tout ce que doit gerer le timer notamment le clignote     */
 /* ment du curseur texte dans les champs editables                       */
 /* Nous v‚rifions avant si la fenetre est au premier plan car si ce      */
 /* n'est pas le cas, elle n'a pas … faire clignoter le curseur texte.    */
 
 if (Evnt->evnt & MU_TIMER &&  w_h == wh_top)  
    {/*...... si relachage et drag en cours ........*/
     /*       simuler un MU_MOVE pour traiter       */
     /*       le relachage qui y est traite         */
     if ( Mstate  == M_DRAG_ON && Mousek()==0)
        {Evnt->evnt |= MU_MOVE;
        }
     else if (Mstate  == M_DRAG_OFF && !ZoomCarBack)
        {long state = Kbshift(-1); static long old_state=-1L;
         int sel    = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
         int i;
					if(old_state==state)
					{
						i=10;
					}
					else
					{
						old_state = state;
						i=0;
						if(state&(1|2)) i+=1;				/* SHIFT left and right */
						if(!i && (state&16) ) i+=2; /* CAPSLOCK */
						if(state&8) i+=6;  					/* ALT */
						if((i<3) && (state&128)) i+=3; /* ALTGR */
#if 0
         		switch((int)state)
          	{case K_LRSHIFT: 
          	 case K_LSHIFT:
          	 case K_RSHIFT:        i = 1;   break;
          	 case K_CTRL:          i = 0;   break;   /* ALT GR ou ALT CTRL             */
          	 case 16:              i = 2;   break;   /* CAPS LOCK                      */
          	 default:              i = 10;
         	 }
#endif
					}
         if (i != 10 && sel != i)
            {SetListBoxParam(object,ASCCI_TABLE_KEYTAB_LIST,i,-2,-2,-2,-2,(void*)-2);
             Wobjc_draw(w_ind,object, ASCCI_TABLE_KEYTAB_LIST, 3, 0);
             if (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED)
                 SendObjectRedraw(w_h, object, ASCCI_TABLE_PAINT_BOX1);
            }         
         Xform_timer(w_ind, Evnt);
        }
     if (ZoomCarBack && Mousek() !=2) 
        {ZoomCarBack = CloseZommCar(ZoomCarBack, ZoomCarBackX, ZoomCarBackY);
        }
    }
   
 /*..........................R‚pondre … l'‚vŠnement MU_MOVE ..............*/
 /* L'‚vŠnement MU_MOVE se manifeste chaque fois que la souris a modifie  */
 /* sa position. L'appel … la fonction: Xform_mu_move() permet de traiter */
 /* tout ce qui concerne un mouvement souris au dessus d'une ressource en */
 /* fenetre et le mouvement de la souris au dessus du bord de la fenetre. */
 
 if (Evnt->evnt & MU_MOVE)   /*  (EZGEM evenement)   */
    {int i, ob_ret;
     char *str = " ";
     *str      = (char)CarPt;
     /*.......... si Drag actif evaluer souris au vol .............*/
     /*           car selon systeme un  Evnt->k=0 peut passer      */
     if ( Mstate  == M_DRAG_ON)
        {GRECT grect; 
         GetGemWindExtGRECT(w_h, &grect);
         /*.......... si Drag actif et bouton relache ....................*/
         if ( Evnt->k==0)
            {/*............ replacer dernier fond d'ecran ................*/
             DragBitMap(w_ind, DragFnc,   Moldx , Moldy, Evnt->x , Evnt->y, DRAG_ERASE);
             if (DragFnc) free(DragFnc);
             ob_ret = objc_find(object,0,10,Evnt->x,Evnt->y);
             /*........ SI objet sous souris .................*/  
             if (ob_ret == ASCCI_TABLE_SCANCAR)
                {i    = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
                 KeytabMemory[ i * 128 + ScanCode ] = (char)CarPt;
                 ObjcSetTxt (object, ASCCI_TABLE_SCANCAR,  str); 
                 SendObjectRedraw( w_h, object, ASCCI_TABLE_SCANCAR);
                 /*....... placer dans table systeme ........*/
                 KeyTabBuffToKeyTabSys(&MagicKeyTbl, MagXVers); 
                 ClearCaptureMouse();
                }
             else if ( !IsMouseXYInGrect(Evnt->x, Evnt->y, &grect)  )
                {ClearCaptureMouse();
                 PutDragDropData(str, strlen(str)+1, '.TXT', Evnt->x, Evnt->y, Evnt->ksp);
                }
             else
                {ClearCaptureMouse();
                }
             DragFnc = 0;
             CarPt   = -1;
             Mstate  = M_DRAG_OFF;
            }
         /*.......... sinon Draguer l'icone ..............................*/
         else
            {DragBitMap(w_ind, DragFnc,   Moldx , Moldy, Evnt->x , Evnt->y, DRAG_DRAW);
             Moldx = Evnt->x; 
             Moldy = Evnt->y; 
             Evnt->evnt  &= ~(MU_MOVE|MU_BUTTON); 
            }
        }
     else
        {if (ZoomCarBack) ZoomCarBack = CloseZommCar(ZoomCarBack, ZoomCarBackX, ZoomCarBackY);
         Xform_mu_move(w_ind, Evnt);
        }
    }       
    
 /*..........................R‚pondre aux messages MU_MESAG ..............*/
 /* L'‚vŠnement MU_MESAG se manifeste chaque fois qu'EAZY_GEM demande …   */
 /* la fonction de fenetre de r‚pondre … un message. ci_dessous nous      */
 /* allons r‚pondre aux messages concernant notre fenetre.                */
   
 if (Evnt->evnt & MU_MESAG)
    {switch (Evnt->pipe[MESG])
       {case WM_CONSTRUCT:
             /***********************************************************/
             /*.................... WM_CONSTRUCT (EZGEM message)........*/
             /* Ce message est transmis avant la creation et ouverture  */
             /* de la fenetre associee … notre procedure de fenetre.    */
             /* c'est … cet endroit que vous devez initialiser tout ce  */
             /* qui concerne votre fenetre: Memoire, chargement d'un    */
             /* fichier ressource, modification des dimensions fenetre  */
             /* avant ouverture, declaration des Bulles d'aide associees*/
             /* … cette fenetre, titre de la fenetre.....etc            */
             /* eventuellement si pas deja fait avant: ouverture d'une  */
             /* Station de travail VDI autre que celle d'EAZY_GEM.      */
             /* EAZY_GEM vous laisse toute liberte pour faire ce que    */
             /* vous voulez:                                            */
             /* Vous pouvez tres bien charger votre fichier ressource … */
             /* cet endroit ou avant dans l'application..               */
             /* Lors de ce message il est donn‚ dans:                   */
             /*                  Evnt->pipe[X_B]                        */
             /*                  Evnt->pipe[Y_B]                        */
             /*                  Evnt->pipe[W_B]                        */
             /*                  Evnt->pipe[H_B]                        */
             /*                               les dim exterieures  maxi */
             /* possibles d'ouverture de la fenetre sur l'ecran.        */
             /* c'est par defaut ces dimensions qui sont choisies pour  */
             /* ouvrir une fenetre.Si on veut d'autres dimensions c'est */
             /* ces valeurs qu'il faudra modifier.                      */
             /*                                                         */
             /* REPONDRE AU MESSAGE WM_CONTRUCT:                        */
             /* Il est possible de repondre au message WM_CONSTRUCT     */
             /* de deux manieres equivalentes au point de vue resultat: */
             /* Soit en faisant  Evnt->evnt = WM_ABORT; (ou WM_STANDBY) */
             /* Soit en faisant  return WM_ABORT;       (ou WM_STANDBY) */
             /*                                                         */
             /* Vous pouvez interrompre le processus de creation de la  */
             /* fenetre en retournant le message: WM_ABORT par exemple  */
             /* vous n'avez pas pu reserver toute la memoire souhaitable*/
             /* ou vous n'avez pas trouve un fichier indispensable      */
             /* ou pour toute autre raison liee a votre application.etc.*/
             /*                                                         */
             /* Vous pouvez empecher l'ouverture de la fenetre et donc  */
             /* permettre juste sa creation en retournant le message:   */
             /* WM_STANDBY. Pour ouvrir et afficher la fenetre ulterieu-*/
             /* ment il faudra utiliser la fonction: OpenWindow         */
             /* Si vous ne retournez pas ce message la fenetre s'ouvre  */
             /* dans la foulee (cas le plus utile).                     */
             /*                                                         */
             
             
             /*........... ICI nous allons charger un fichier ..........*/
             /*           de ressource en memoire et integrer           */
             /*           un dialogue (ici le premier et seul arbre) de */
             /*           cette ressource, … notre fenetre              */
             
             
             /*...... Si r‚ussite du chargement de la ressource ........*/
             /*       il faut integrer un des arbres de cette           */
             /*       ressource … la fenetre                            */
             if (WindDialogConstruct(w_ind, 
                                     LoadAppliRsc( "CHARVIEW.RSC", NO_SCALE),
                                     0, RSC_DIAL, Evnt 
                                    ) != WM_ABORT
                )
                {int i;
                 OBJECT* object = GETWINDTREE(w_ind);
                 /*........... Placer la fonction d'affichage ..................*/ 
                 /*            personnelle de la LISTBOX choix des tables       */
                  SetListCallBackFunc (object, ASCCI_TABLE_KEYTAB_LIST, LST_BOX_TabType);
              /* OL    if (MagXVers>=0x610) */
                     i = (int)(sizeof(LSTBOX_TAB_STR)/sizeof(char*)); /* 9 tables pour Magic  */
#if 0
                  else
                     i = 3;        
#endif                                   /* 3 tables pour le TOS */
                  SetListBoxParam(object, ASCCI_TABLE_KEYTAB_LIST,0,0,i+1,i,-2,(void*)-2);  
                 /*.............. nom du fichier charg‚ ................*/
                 if (*PathVABuff != 0)
                    {ObjcSetTxt (object, ASCCI_TABLE_PATH_KEYTAB,  PathVABuff);
                    }
                }                     
             else
                {/*      si echec du chargement annuler la              */
                 /*      creation de la fenetre                         */
                 return WM_ABORT;         
                }
                  
             /*........... placer le tout sous la souris ..................*/
             /* EAZY_GEM met … votre disposition une fonction qui centre   */
             /* le rectangle donn‚ en entr‚e, sur la position de la souris */
             /* tout en restant dans les limites de l'ecran.               */
             /* J'en profite ici pour recentrer la fenetre sur la souris   */
             /* avant son ouverture.                                       */
              AdjustWindCoordToScreen (w_ind, Evnt, (GRECT*)&Evnt->pipe[X_B]);
             break;
             
        case WM_DESTRUCT:       /*  (EZGEM message)   */
             /**************************************************************/
             /*........................ WM_DESTRUCT (EZGEM message)........*/
             /* Ce message est envoy‚ a notre procedure de fenetre avant   */
             /* que le systeme ne la detruise. c'est … cet endroit qu'il   */
             /* convient de desinitialiser tout ce que l'on avait fait     */
             /* auparavant memoire, bulles d'aide, ressources....          */                          
             
             /*            desintegrer l'arbre de la fenetre               */
             /*         (enfin un mot qui prend tout son sens)             */
             Xform_Destruct(w_ind, Evnt);    
             
             /*            decharger la ressource de la memoire            */
             /*                  et liberer la memoire                     */
             RscFicUnLoad(Windtab[w_ind].DlgVar.AdrRsc);                
             break;   
             
        case WM_TT_ON_OFF:      /*  (EZGEM message)   */
             /**************************************************************/
             /*...................... WM_TT_ON_OFF (EZGEM message).........*/
             /* Ce message est envoy‚ … notre fenetre chaque fois qu'il est*/
             /* demand‚ d'activer ou de desactiver l'affichage des bulles  */
             /* d'aide. Il suffit simplement d'appeler la fonction qui suit*/
             /* pour mettre … jour l'objet representant l'etat actif ou    */
             /* inactif de notre ressource (si il existe)                  */
             /* Cet Objet est un objet type BOXTEXT extended type 25 que   */
             /* vous pouvez placer sur tout formulaire.                    */
             /* c'est le petit truc jaune affich‚ en haut … droite de la   */
             /* boite de dialogue.                                         */
             /* Si un objet de ce type est plac‚ dans votre formulaire Il  */
             /* refletera automatiquement l'etat actif ou inactif du       */
             /* systeme de bulle d'aide. L'appel de la fonction:           */
             /* SetBulleState()  recherche tous les objets du type decrit  */
             /* ci-dessus et les met … jour dans votre formulaire.         */
             
             SetBulleState(w_h, Windtab[w_ind].DlgVar.tree);
             break;
                       
        case WM_REDRAW: 
             /**************************************************************/
             /*........................ WM_REDRAW (GEM message)............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* il faut redessiner une partie de la fenetre (par exemple un*/
             /* accessoire qui la recouvrait vient de se fermer, il faut   */
             /* alors retracer la partie de notre fenetre que l'accessoire */
             /* recouvrait. Avant c'etait un veritable enfer, maintenant   */
             /* il vous faut juste appeler la routine: Lister_rectangles   */
             /* qui vous renvoie le message WM_PAINT                       */
             /* et vous n'avez plus … vous occuper de savoir comment faire */
             /* notamment pour traiter la liste des rectangles et leur     */
             /* intersection avec notre fenetre.                           */
             /* Dans cet exemple, tout etant sous forme de ressource,      */
             /* EAZY_GEM ne g‚nŠre pas de message WM_PAINT, car il n'y a   */
             /* pas de surface client … retracer.                          */
             /* Il faut tout de meme appeler la fonction:                  */
             /*         Lister_rectangles() , afin que la ressource soit   */
             /*         retrac‚e.                                          */
             {int redraw_flag = 0;
              char car[2]={0,0};
              DLG_VAR *dlg;        /* pointeur sur variable ressource      */
              /*..... initialiser pointeur sur variable ressource .........*/
              dlg = &Windtab[w_ind].DlgVar;
              if (ZoomCarBack) 
                 {redraw_flag = 1;
                  ZoomCarBack = CloseZommCar(ZoomCarBack, ZoomCarBackX, ZoomCarBackY);
                 }
              Lister_rectangles(w_h,(GRECT*)&Evnt->pipe[X_G]);
              if ( redraw_flag )
                 {car[0] = OnGrilleCarClick(object, ASCCI_TABLE_PAINT_BOX1, Evnt, 0);
                  SetCursObEditOff(dlg);
                  ZoomCarBack = OpenZoomCar(car,
                                            Evnt->x,
                                            Evnt->y,
                                            (int)FontID[GetSelectedListBoxItem(object, ASCCI_TABLE_FONT_LIST)],
                                             &Windtab[w_ind].ExtGrectUse,
                                             &ZoomCarBackX,
                                             &ZoomCarBackY
                                            );
                 }
             }
             break;
             
        case WM_PAINT:
             /**************************************************************/
             /*........................ WM_PAINT (EZGEM message)...........*/
             /* Ce nouveau message est envoy‚ a notre procedure de fenetre */
             /* lorsqu'il faut retracer quelque chose … l'ecran.           */
             /*                                                            */
             /* En: Evnt->pipe[X_G], Evnt->pipe[Y_G], Evnt->pipe[W_G], et  */
             /*     Evnt->pipe[H_G], se trouve le rectangle de clipping    */
             /*                      qui est dej… clipp‚ par EAZY_GEM,     */
             /* En: Evnt->pipe[X_B], Evnt->pipe[Y_B], Evnt->pipe[W_B], et  */
             /*     Evnt->pipe[H_B], se trouve le rectangle de la surface  */
             /*                      client qu'il est  … votre charge de   */
             /*                      redessiner                            */
             /* cette fenetre contient un dialogue simple en fenetre donc  */
             /* pas de surface client, donc pas de message WM_PAINT qui    */
             /* peut donc etre ignore … ce niveau.                         */
             break;  
             
        case WM_PAINTBOX:
             /**************************************************************/
             /*........................ WM_PAINTBOX (EZGEM message)........*/
             /* Ce nouveau message est envoy‚ a notre procedure de fenetre */
             /* lorsqu'il faut retracer la surface d'une boite de type     */
             /* PAINT_BOX (ob-type etendu PAINT_BOX (215).                 */
             /*                                                            */
             /* En: Evnt->pipe[X_G], Evnt->pipe[Y_G], Evnt->pipe[W_G], et  */
             /*     Evnt->pipe[W_G], se trouve le rectangle de clipping    */
             /*                      qui est dej… clipp‚ par EAZY_GEM,     */
             /* En: Evnt->pipe[X_B], Evnt->pipe[Y_B], Evnt->pipe[W_B], et  */
             /*     Evnt->pipe[W_B], se trouve le rectangle de la surface  */
             /*                      client qu'il est  … votre charge de   */
             /*                      redessiner                            */
             /* En: Evnt->pipe[12]   se trouve le numero de l'objet dont   */
             /*                      il faut retracer la surface.          */
             DrawPaintBox(w_ind, (GRECT*) &Evnt->pipe[X_B]);
             break; 
             
        case WM_EXEFUNC:        /*  (EZGEM message)   */
             /**************************************************************/
             /*...................... WM_EXEFUNC .(EZGEM message)..........*/
             /* Ce message est envoy‚ a notre procedure de fenetre chaque  */
             /* fois qu'il est demand‚ d'executer une fonction referencee  */
             /* par un numero de fonction.                                 */
             /* Le message est compose comme suit:                         */
             /* SI  Evnt->pipe[WHND]= RSC_DIAL; le message provient d'une  */
             /*                             ressource.  ET ALORS           */
             /*     Evnt->pipe[X_G] = indice objet declenchant le message  */
             /*     Evnt->pipe[Y_G] = numero de la fonction referencee     */
             /*     *(long*)&Evnt->pipe[W_G] =  adr arbre ou est l'objet   */
             if (Evnt->pipe[Y_G]  == 226 )
                {SendObjectRedraw(w_h,
                                  Windtab[w_ind].DlgVar.tree,
                                  ASCCI_TABLE_PAINT_BOX1);
                }
             break;
        
        case WM_TT_GET_TXT:     /*  (EZGEM message)   */
             /**************************************************************/
             /*...................... WM_TT_GET_TXT .(EZGEM message).......*/
             /* Ce message est envoy‚ a notre procedure de fenetre chaque  */
             /* fois que le systeme d'affichage d'une bulle d'aide desire  */
             /* qu'on lui fournisse un texte … afficher.                   */
             /* Ce texte peut etre affiche sur plusieurs lignes en mettant */
             /* comme separateur le signe | .                              */
             /* Exemple:                                                   */
             /* strcpy(sztt_txt,"Premiere ligne|deuxieme ligne|troisieme");*/
             /* Si vous placez une chaine vide "", la bulle d'aide ne sera */
             /* pas affichee.                                              */
             /*  Exemple: strcpy(sztt_txt,"");                             */
             /*                                                            */
             
             if (Evnt->pipe[X_G]==TT_UPSTOOL)
                {int i;
                 /*........... recuperer l'adresse ou l'on doit ...........*/
                 /*         copier et placer le texte de la bulle          */
                 char *sztt_txt  = (char*) *(long*)(&Evnt->pipe[W_G]); 
                 /*........... selon l'objet survol‚ placer ...............*/
                 /*                 le texte adequat                       */
                 switch ( Evnt->pipe[Y_G])
                   {case ASCCI_TABLE_ICONE:
                         strcpy(sztt_txt,TxtPtStrMess[TT_ICN_INFO]);   
                         break;      
                    case ASCCI_TABLE_IC_KEYTAB_LOAD:
                    case ASCCI_TABLE_KEYTAB_LOAD:
                         strcpy(sztt_txt,TxtPtStrMess[TT_BUT_LOAD]);   
                         break;
                    case ASCCI_TABLE_IC_KEYTAB_SAVE:
                    case ASCCI_TABLE_KEYTAB_SAVE:
                         strcpy(sztt_txt,TxtPtStrMess[TT_BUT_SAVE]);   
                         break;
                    case ASCCI_TABLE_SCANCODE:
                         strcpy(sztt_txt, TxtPtStrMess[TT_SCANC_AFF]);   
                         break;
                    case ASCCI_TABLE_SCANCAR:
                         i = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
                         strcpy(sztt_txt, TxtPtStrMess[TT_CAR_AFF]);
                         strcat(sztt_txt, TAB_NAME[i]);
                         strcat(sztt_txt, ")");
                         break; 
                    case ASCCI_TABLE_PAINT_BOX1:
                         strcpy(sztt_txt,TxtPtStrMess[TT_PAINTBOX]);   
                         break;   
                    case ASCCI_TABLE_SAISIE_CAR:
                         strcpy(sztt_txt,TxtPtStrMess[TT_CARSAISIE]);   
                         break;
                    case ASCCI_TABLE_PATH_KEYTAB:
                         strcpy(sztt_txt,TxtPtStrMess[TT_PATHNAME]);   
                         break;
                    case ASCCI_TABLE_KEYTAB_LIST:
                         i = XYToListBoxItem(w_ind, Evnt->x, Evnt->y);
                         if ( i >= 0)
                            {char *pt_txt;
                             switch(i)
                              {case 0: pt_txt = TxtPtStrMess[TT_LST_UNSHIFT];
                                       break;
                               case 1: pt_txt = TxtPtStrMess[TT_LST_SHIFT];
                                       break;
                               case 2: pt_txt = TxtPtStrMess[TT_LST_CAPS];
                                       break;
                               case 3: pt_txt = TxtPtStrMess[TT_LST_ALTGR];
                                       break;
                               case 4: pt_txt = TxtPtStrMess[TT_LST_ALTGRSHIF];
                                       break;
                               case 5: pt_txt = TxtPtStrMess[TT_LST_ALTGRCAPS];
                                       break;
                               case 6: pt_txt = TxtPtStrMess[TT_LST_ALT];
                                       break;
                               case 7: pt_txt = TxtPtStrMess[TT_LST_ALTSHIFT];
                                       break;
                               case 8: pt_txt = TxtPtStrMess[TT_LST_ALTCAPS];
                                       break;
                              }
                             strcpy( sztt_txt, pt_txt);
                            }
                         else    
                            {strcpy(sztt_txt, TxtPtStrMess[TT_LST_SELECT]);
                            }
                         break;     
                    case ASCCI_TABLE_FONT_LIST:
                         i = XYToListBoxItem(w_ind, Evnt->x, Evnt->y);
                         if ( i >= 0)
                            {strcpy( sztt_txt, GET_FONTNAME(i) );
                            }
                         else    
                            {strcpy(sztt_txt,TxtPtStrMess[TT_LST_FONT]);
                            }
                         break;
                    case ASCCI_TABLE_ASCII_SCAN_ICN:
                         strcpy(sztt_txt,TxtPtStrMess[TT_SCAN_ASCII]);   
                         break;
                    default:
                         strcpy(sztt_txt,"");
                   }
                }
             break;
             
        case WM_BOTTOM:
             /**************************************************************/
             /*........................ WM_BOTTOM (GEM message)............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* on lui demande de se mettre au dernier plan. Il convient   */
             /* de le faire avec la fonction: wind_set(w_h, WF_BOTTOM );   */
             wind_set(w_h, WF_BOTTOM );
             break;
             
        case WM_TOPPED:
             /**************************************************************/
             /*........................ WM_TOPPED (GEM message)............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* on lui demande de se mettre en premier plan. Il convient   */
             /* de le faire avec la fonction: wind_set(w_h, WF_TOP );      */
             wind_set(w_h, WF_TOP ); /* voila c'est fait !! */
             break;
             
        case AP_TERM:
             /**************************************************************/
             /*........................ AP_TERM (GEM message)..............*/
             /* Ce message est envoy‚ … l'application lorsqu'il lui est    */
             /* demand‚e de s'arreter (exemple lorsque il y a changement   */
             /* r‚solution). Il est d'usage de quitter sans demande de     */
             /* comfirmation. Faites les sauvegardes n‚cessaires avant de  */
             /* quitter. Et quittez.                                       */
             /* Ici je mets la variable: EZGemRun … -1, de fa‡on … ce      */
             /* que le programme s'arrete sans demande de confirmation.    */
             EZGemRun = -1;
             break;
             
        case WM_CLOSED:
             /*........................ WM_CLOSED (GEM message)............*/
             /* Ce message est envoy‚ a notre procedure de fenetre         */
             /* lorsqu'une demande de fermeture de la fenetre est demandee */
             /* si vous voulez detruire completement cette fenetre il faut */
             /* appeler imperativement la fonction: DestroyWindow          */
             /* pour la reouvrir ensuite il vous faudra appeler la         */
             /* fonction:                           CreateWindow           */
             /* sinon il vous faut faire un simple: CloseWindow  et la     */
             /* reouvrir par:                       OpenWindow             */
             /* sans etre oblige de tout reinitialiser                     */
             /* CloseWindow(w_ind);                                        */
             
             /* Ici je mets la variable: EZGemRun … -1, de fa‡on … ce      */
             /* que le programme s'arrŠte sans demande de confirmation.    */
             if (!_app)  /* si demarr‚ en accessoire                       */
                {int wind;
                 wind = IsWindExist(W_RINFO); 
                 if (wind>-1) SendWindMessage(Windtab[wind].w_h, WM_CLOSED, 0);
                 ExeAllMessage();
                 DestroyWindow(w_h);
                }
             else        /* si demarr‚ en programme                        */
                {EZGemRun = -1;
                }
             break;
             
        case WM_ALLICONIFY:
             /**************************************************************/
             /*........................ WM_ALLICONIFY (GEM message)........*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* il faut iconifier toutes les fenetres. EAZY_GEM met … votre*/
             /* disposition une fonction s'occupant de tout: AllIconify()  */
             /* vous pouvez lui donner en entree l'adresse d'une structure */
             /* GRECT, contenant des coordonn‚es d'iconification. Si vous  */
             /* placez zero alors EAZY_GEM les calcule pour vous.          */
             AllIconify(0L);
             break;
              
        case WM_ICONIFY:
             /**************************************************************/
             /*........................ WM_ICONIFY (GEM message)...........*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* il faut iconifier une fenetre.EAZY_GEM met … votre service */
             /* une fonction s'occupant de tout: IconifyWindow()           */
             /* Elle demande en entree l'indice EAZY_GEM de la fenetre …   */
             /* iconifier.                                                 */
             /* vous pouvez aussi lui donner en entree l'adresse d'une     */
             /* structure GRECT, contenant des coordonn‚es d'iconification.*/
             /* Si vous placez zero alors EAZY_GEM les calcule pour vous.  */
             IconifyWindow(w_ind, 0L);
             break;
             
        case WM_UNICONIFY:
             /**************************************************************/
             /*........................ WM_UNICONIFY (GEM message).........*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* il faut desiconifier une fenetre.EAZY_GEM met … votre      */
             /* service une fonction s'occupant de tout: UnconifyWindow()  */
             /* Elle demande en entree l'indice EAZY_GEM de la fenetre …   */
             /* iconifier.                                                 */
             UnconifyWindow(w_ind);
             break;
             
        case WM_SIZED:
             /**************************************************************/
             /*........................ WM_SIZED (GEM message).............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* on lui demande de a jour ses dimensions apres une demande  */
             /* de changement de taille lors de l'appui sur une case de    */
             /* dimensionnement, ou lors d'une demande logicielle.         */
             /* ou apres une modification des coordonnes de la fenetre     */
             /* les dimmensions externes de la fenetre sont recuperables   */
             /* la ou classiquement le GEM les place  dans:                */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]   ce qui n'est pas l'endroit logique  */
             /*      ou elles doivent etre selon EZ_GEM.                   */
             /* Donc il vaut mieux les recopier en:                        */
             /*      Evnt->pipe[X_B],Evnt->pipe[Y_B],Evnt->pipe[W_B], et   */
             /*      Evnt->pipe[H_B]  et placer les dimensions interieures */
             /*      apres calcul avec: WindGemBorderToEZWork, en          */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]                                       */
             /* EAZY_GEM met … votre service une fonction s'occupant de    */
             /* tout: OnWm_sized()                                         */
             /* ce dialogue en ressource n'a pas a etre redimensionne donc */
             /* ce message est ignor‚.                                     */
             break;
             
        case WM_MOVED:
             /**************************************************************/
             /*........................ WM_MOVED (GEM message).............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* on lui demande de a jour ses dimensions apres une demande  */
             /* de changement de place de la fenetre. En g‚n‚ral apr‚s     */
             /* d‚placement de la barre de titre ou d'une poignee de       */
             /* d‚placement.                                               */
             /* Les dimmensions externes de la fenetre sont recuperables   */
             /* la ou classiquement le GEM les place  dans:                */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]   ce qui n'est pas l'endroit logique  */
             /*      ou elles doivent etre selon EZ_GEM.                   */
             /* Donc il vaut mieux les recopier en:                        */
             /*      Evnt->pipe[X_B],Evnt->pipe[Y_B],Evnt->pipe[W_B], et   */
             /*      Evnt->pipe[H_B]  et placer les dimensions interieures */
             /*      apres calcul avec: WindGemBorderToEZWork, en          */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]                                       */
             /* EAZY_GEM met … votre service une fonction s'occupant de    */
             /* tout: OnWm_moved()                                         */
             OnWm_moved(w_ind, Evnt);
             break;
             
        case WM_FULLED: 
             /**************************************************************/
             /*........................ WM_FULLED (GEM message)............*/
             /* Ce message est envoy‚ a notre procedure de fenetre lorsque */
             /* on lui demande de a jour ses dimensions apres une demande  */
             /* de changement de taille lors de l'appui sur une case de    */
             /* plein ecran (FULLER), ou lors d'une demande logicielle.    */
             /* les dimmensions externes de la fenetre sont recuperables   */
             /* la ou classiquement le GEM les place  dans:                */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]   ce qui n'est pas l'endroit logique  */
             /*      ou elles doivent etre selon EZ_GEM.                   */
             /* Donc il vaut mieux les recopier en:                        */
             /*      Evnt->pipe[X_B],Evnt->pipe[Y_B],Evnt->pipe[W_B], et   */
             /*      Evnt->pipe[H_B]  et placer les dimensions interieures */
             /*      apres calcul avec: WindGemBorderToEZWork, en          */
             /*      Evnt->pipe[X_G],Evnt->pipe[Y_G],Evnt->pipe[W_G], et   */
             /*      Evnt->pipe[H_G]                                       */
             /* EAZY_GEM met … votre service une fonction s'occupant de    */
             /* tout: OnWm_fulled()                                        */
             /* ce dialogue en ressource n'a pas a etre redimensionne donc */
             /* ce message est ignor‚.                                     */
             break;                                         
       } /* end switch message     */
    } /* end if Evnt & MU_MESSAG  */      
 return Evnt->evnt;    /* retourner le flux evenementiel (modifie ou pas)  */
}

/*-------------------------- KeyTabBuffToKeyTabSys ----------------------*/
/* ACTION: copie le contenu de la table systeme dans un buffer de table  */
/* ENTREE: MGKEYTAB* magic_keytabl: structure de pointeur de tables      */
/*         long os: si egal … 'MagX' on considere 9 tables systeme       */
/*                  sinon on considere 3 tables systeme                  */
/* RETOUR: neant.                                                        */
void KeyTabBuffToKeyTabSys(MGKEYTAB* magic_keytabl, long magic_vers)
{		
	if(shel_write(98,2,1152,(void *) magic_keytabl, (void *) NULL)==0) /* ecriture table clavier AES (MyAES seulement) */
	{
		MGKEYTAB *keytab_sys;
 		/*........... copier les 9 autres tables si Magic ..........................*/
 		if (magic_vers >= 0x600)
    {/*.......... recuperer un pointeur sur les tables systeme ..............*/
     	keytab_sys = (MGKEYTAB*) Keytbl((void*)-1L, (void*)-1L, (void*)-1L);
     	/*........... copier les tables ........................................*/
     	memcpy(keytab_sys->unshift,       magic_keytabl->unshift,       128);
     	memcpy(keytab_sys->shift ,        magic_keytabl->shift,         128);
     	memcpy(keytab_sys->caps,          magic_keytabl->caps,          128);
     	memcpy(keytab_sys->altgr_unshift, magic_keytabl->altgr_unshift, 128);
     	memcpy(keytab_sys->altgr_shift,   magic_keytabl->altgr_shift,   128);
     	memcpy(keytab_sys->altgr_caps,    magic_keytabl->altgr_caps,    128);
     	memcpy(keytab_sys->alt_unshift,   magic_keytabl->alt_unshift,   128);
     	memcpy(keytab_sys->alt_shift,     magic_keytabl->alt_shift,     128);
     	memcpy(keytab_sys->alt_caps,      magic_keytabl->alt_caps,      128);
    }
 		else
    {/*........... copier les tables directement  ...........................*/
     /*            plante sous MinT donc utiliser                            */
     /*            solution classique (PB il semble que le GEM ne fait       */
     /*            pas une recopie mais place ses adresses internes sur      */
     /*            celle pass‚es en entr‚e, donc lorsqu'on quitte et ben !!  */
     /*            nos adresse sont plus valides donc ...)                   */
     keytab_sys = (MGKEYTAB*) Keytbl(magic_keytabl->unshift, 
                                     magic_keytabl->shift, 
                                     magic_keytabl->caps
                                    );
    }
	}
}
/*-------------------------- KeyTabSysToKeyTabBuff ----------------------*/
/* ACTION: copie le contenu de la table donnee en entree dans la table   */
/*         systeme et donc modifie le clavier selon cette table.         */
/* ENTREE: MGKEYTAB* magic_keytabl: structure de pointeur de tables      */
/*         long os: si egal … 'MagX' on considere 9 tables systeme       */
/*                  sinon on considere 3 tables systeme                  */
/* RETOUR: neant.                                                        */
void KeyTabSysToKeyTabBuff(MGKEYTAB* magic_keytabl, long magic_vers)
{
	if(shel_write(98,1,1152,(void *) magic_keytabl,(void *) NULL)==0) /* recuper table clavier AES (MyAES seulement) */
	{
 		/*.......... recuperer un pointeur sur les tables systeme ..............*/
 		MGKEYTAB *keytab_sys = (MGKEYTAB*) Keytbl((char *)-1L, (char *)-1L, (char *)-1L);
 		/*........... copier les trois tables classiques .......................*/
 		memcpy(magic_keytabl->unshift,       keytab_sys->unshift,       128);
 		memcpy(magic_keytabl->shift,         keytab_sys->shift,         128);
 		memcpy(magic_keytabl->caps,          keytab_sys->caps,          128);
 		/*........... copier les 6 autres tables si Magic ......................*/
 		if (magic_vers >= 0x610)
    	{
				memcpy(magic_keytabl->altgr_unshift, keytab_sys->altgr_unshift, 128);
    	 	memcpy(magic_keytabl->altgr_shift,   keytab_sys->altgr_shift,   128);
    	 	memcpy(magic_keytabl->altgr_caps,    keytab_sys->altgr_caps,    128);
    	 	memcpy(magic_keytabl->alt_unshift,   keytab_sys->alt_unshift,   128);
    	 	memcpy(magic_keytabl->alt_shift,     keytab_sys->alt_shift,     128);
    	 	memcpy(magic_keytabl->alt_caps,      keytab_sys->alt_caps,      128);
    	}
		}
 }
/*-------------------------- DrawPaintBox -------------------------------*/
void DrawPaintBox(int w_ind, const GRECT *grect)
{GRECT pgrect;   /* rectangle de la PAINTBOX  */
 OBJECT *object = GETWINDTREE(w_ind);
 char scan_mode = (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED);
 char   *keytbl;
 int w_car_rect, h_car_rect, x_o, y_o;
 int i, u, t, x, y ,x1 ,y1;
 char car[2]={0,0};
 
 pgrect = *grect;   /* rectangle de la PAINTBOX  */
    
 /*............ tracer les rectangles ........................*/
 Graphmode(1);
 Defline(1,1,0,0,8);
 
 pgrect.g_w -= 2;
 pgrect.g_h -= 2;
 h_car_rect  = pgrect.g_h>>3;      /* divise par 8   */
 if (scan_mode) u = 16;            /* nbr de case horizontales = 16   */
 else           u = 32;            /* nbr de case horizontales = 32   */
 
 w_car_rect = pgrect.g_w/u;   /*divise par 16 ou 32 (8*32=256) (8*16=128)  */
 x_o        = (pgrect.g_w - (w_car_rect*u))>>1;
 y_o        = (pgrect.g_h - (h_car_rect<<3))>>1;
 x  = pgrect.g_x + x_o;
 y  = pgrect.g_y + pgrect.g_h - y_o - 1;
 y1 = pgrect.g_y + y_o;
 
 for (i=0; i<=u; i++)
     {Line_p(x, y1, x, y);
      x += w_car_rect;
     }
 x  = pgrect.g_x + pgrect.g_w - x_o - 1;
 y  = pgrect.g_y + y_o;
 x1 = pgrect.g_x + x_o;
 for (i=0; i<9; i++)
     {Line_p(x1, y, x, y);
      y += h_car_rect;
     }
 
 /*...... r‚cuperer la police affich‚e par la LISTBOX ........*/
 i      = GetSelectedListBoxItem(object, ASCCI_TABLE_FONT_LIST);
 /*...... recuperer la table de caracteres en cours ..........*/
 t      = GetSelectedListBoxItem(object, ASCCI_TABLE_KEYTAB_LIST);
 keytbl = &KeytabMemory[128*t];
 /*........... afficher les caracteres .......................*/
 Graphmode(2);   
 
 if (scan_mode)
    {Deftext(1,0,0,9,(int)FontID[0]);
     vst_point( VDIhandle, 10,&i, &i, &i, &t );
     vst_alignment( VDIhandle, 1, 5, &x, &y );
     y  = pgrect.g_y + y_o + ((h_car_rect-t)>1) +1;
     x  = pgrect.g_x + x_o + (w_car_rect>>1) + 1;
     u   = 0;
     for (i=0; i<128; i++)
         {car[0] = keytbl[i];
          vst_color(VDIhandle,1);
          vst_point( VDIhandle, 10,&t, &t, &t, &t );
          VdiText(x,y-2,car);
          vst_color(VDIhandle,2);
          vst_point( VDIhandle, 6,&t, &t, &t, &t );
          VdiText(x,y+14,itoa(i,"                               ",10));
          u++;
          if (u == 16 ) 
             {u  = 0;
              x  = pgrect.g_x + x_o + (w_car_rect>>1);
              y += h_car_rect;
              }
          else
              {x += w_car_rect;
              }
         } /*endfor (i=0; i<256; i++) */
    }
 else
    {Deftext(1,0,0,9,(int)FontID[i]);
     vst_point( VDIhandle, 10,&i, &i, &i, &u );
     vst_alignment( VDIhandle, 1, 5, &x, &y );
     y  = pgrect.g_y + y_o + ((h_car_rect-u)>1) +1;
     x  = pgrect.g_x + x_o + (w_car_rect>>1) + 1;
     u   = 0;
     for (i=0; i<256; i++)
         {VdiText(x,y,car);
          u++;
          car[0]++;
          if (u == 32 ) 
             {u  = 0;
              x  = pgrect.g_x + x_o + (w_car_rect>>1);
              y += h_car_rect;
              }
          else
              {x += w_car_rect;
              }
         } /*endfor (i=0; i<256; i++) */
    } /* end else de if (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED) */
}

/*-------------------------- NumCaseToVrect -----------------------------*/
VRECT *NumCaseToVrect(OBJECT *object, int ind_ob, int scan_code, VRECT *pt_vrect)
{char scan_mode = (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED);
 GRECT pgrect;
 VRECT vrect;
 int w_car_rect, h_car_rect, x_o, y_o;
 int col, lig, u;
 /*............ recuperer dimensions PAINTBOX ........................*/ 
 pgrect = *(GRECT*) &object[ind_ob].ob_x;
 objc_offset(object, ind_ob, &pgrect.g_x, &pgrect.g_y);

 if (scan_mode) u = 16;            /* nbr de case horizontales = 16   */
 else           u = 32;            /* nbr de case horizontales = 32   */
 /*............. calcul du rectangle des cases de lettres ............*/  
 pgrect.g_w   -= 2;
 pgrect.g_h   -= 2;
 w_car_rect    = pgrect.g_w/u;   /*divise par 16 ou 32 (8*32=256) (8*16=128)  */
 h_car_rect    = pgrect.g_h>>3;   /* divise par 8   */
 x_o           = (pgrect.g_w - (w_car_rect*u))>>1;
 y_o           = (pgrect.g_h - (h_car_rect<<3))>>1;
 vrect.left    = pgrect.g_x + x_o;
 vrect.top     = pgrect.g_y + y_o;
 vrect.right   = pgrect.g_x + pgrect.g_w - x_o - 1;
 vrect.bottom  = pgrect.g_y + pgrect.g_h - y_o - 1;
 /*............. calcul de la colone et ligne ................*/
 lig = scan_code / u;
 col = scan_code - lig * u;
 /*........ calcul et retour du rectangle ....................*/
 pt_vrect->left     = vrect.left      + col * w_car_rect;
 pt_vrect->right    = pt_vrect->left  + w_car_rect;
 pt_vrect->top      = vrect.top       + lig * h_car_rect;
 pt_vrect->bottom   = pt_vrect->top   + h_car_rect;
 return pt_vrect;
}

/*---------------------------- OnGrilleCarClick --------------------------*/
/* ACTION: cette fonction est appellee pour connaitre la case de          */
/*         caractere au dessus de laquelle la souris se trouve.           */
/* ENTREE:                                                                */
/*         OBJECT *object l'on  place l'adresse de l'arbre (1er objet)    */
/*                        ou se situe l'objet grille PAINTBOX             */
/*         int ind_ob l'on doit placer l'indice de l'objet grille.        */
/*         EVNT_O *Evnt structure de flux evenementiel (on en tire la     */
/*                      position de la souris en Evnt->x et Evnt->y )     */
/* RETOUR: numero de la case cliquee (ici 0 … 255 ou 0 …127)              */

int OnGrilleCarClick(OBJECT *object, int ind_ob, EVNT_O *Evnt, VRECT *pt_vrect)
{char scan_mode = (object[ASCCI_TABLE_ASCII_SCAN_ICN].ob_state & SELECTED);
 GRECT pgrect; 
 VRECT vrect;
 int w_car_rect, h_car_rect, x_o, y_o;
 int i, u, x, y , nb_col;
 
 /*............ recuperer dimensions PAINTBOX ........................*/ 
 pgrect = *(GRECT*) &object[ind_ob].ob_x;
 objc_offset(object, ind_ob, &pgrect.g_x, &pgrect.g_y);

 if (scan_mode) nb_col = 16;            /* nbr de case horizontales = 16   */
 else           nb_col = 32;            /* nbr de case horizontales = 32   */

 /*............. calcul du rectangle des cases de lettres ............*/  
 pgrect.g_w -= 2;
 pgrect.g_h -= 2;
 w_car_rect = pgrect.g_w/nb_col;   /*divise par 16 ou 32 (8*32=256) (8*16=128)  */
 h_car_rect = pgrect.g_h>>3;   /* divise par 8   */
 x_o        = (pgrect.g_w - (w_car_rect*nb_col))>>1;
 y_o        = (pgrect.g_h - (h_car_rect<<3))>>1;            
 vrect.left   = pgrect.g_x + x_o;
 vrect.top    = pgrect.g_y + y_o;
 vrect.right  = pgrect.g_x + pgrect.g_w - x_o - 1;
 vrect.bottom = pgrect.g_y + pgrect.g_h - y_o - 1;
 /*............ tester la case survol‚e ..............................*/
 if (IsMouseXYInVrect(Evnt->x, Evnt->y, &vrect))
    {/* VRECT_to_GRECT(&vrect,&pgrect); */
     /*............. tester en X .....................*/     
     x = Evnt->x - vrect.left;        /* relativiser au rectangle */
     i =  x / w_car_rect;
     /*............. tester en Y .....................*/     
     y = Evnt->y - vrect.top;         /* relativiser au rectangle */
     u =  y / h_car_rect;
    }
 if (pt_vrect)
    {pt_vrect->left     = vrect.left      + i * w_car_rect;
     pt_vrect->right    = pt_vrect->left  + w_car_rect;
     pt_vrect->top      = vrect.top       + u * h_car_rect;
     pt_vrect->bottom   = pt_vrect->top   + h_car_rect;
    }
 return u * nb_col + i ;
}

/*-------------------------- ActiveWindow -------------------------------*/
/* ACTION: Cette fonction active une fenetre specifiee. Soit elle        */
/*         existe deja et alors elle est activee par mise au premier     */
/*         plan,desiconification, ouverture eventuelle. Soit elle        */
/*         n'existe pas et alors elle est creee.                         */
/* ENTREE:                                                               */
/*  long w_attr: attributs GEM classique d'une fenetre                   */
/*               trois attributs de plus:                                */
/*                         XBORDER permet d'avoir un cadre epais en      */
/*                                  relief autour de la fenetre.         */
/*                         XMOVER permet d'avoir une poign‚e de deplace- */
/*                                ment sur le bord sup du cadre epais    */
/*                         XSIZER permet l'agrandissement de la fenetre  */
/*                                en cliquant sur le cadre epais         */
/*  int Ident:  nbr arbitraire(jamais nul) que vous devez donner. Cela   */
/*              peut servir … reperer tel ou tel type de fenetre dans    */
/*              votre programme. Exemple votre application comporte      */
/*              plusieurs fenetres dont une de menu … laquelle vous      */
/*              donnez int ident=2 lors de sa cr‚ation. Il est           */
/*              alors facile pour le programme de savoir si la fenetre   */
/*              menu est ouverte en faisant appel … la fonction          */
/*              int IdentToIndice(2); qui vous retourne l'indice de la   */
/*              fenetre (si elle n'existe pas l'indice est >= MAX_WIND ) */
/*              pensez … utiliser des type symboliques declar‚s avec:    */
/*              #define FENETRE_TRUC 2  plutot qu'un nombre sans sens.   */
/*                                                                       */
/* char *title: titre de la fenetre                                      */
/*              de meme le titre de la fenetre peut etre modifie au sein */
/*              de la procedure de fenetre lors du traitement du message */
/*              WM_CONTRUCT.                                             */
/*                                                                       */
/*  CALLBACK (*w_proc)(int w_ind, EVNT_O *Evnt): L… vous donnez le nom   */
/*              fonction qui sera charg‚e de gerer tous les evenements   */
/*              de cette fenetre. Cette fonction sera appelee par la     */
/*              sur couche EAZY_GEM.                                     */

void ActiveWindow(int ident, long attr, char *title, CALLBACK (*w_proc)(int w_ind, EVNT_O *Evnt))
{int w_ind;
 w_ind = IsWindExist(ident);
 if (w_ind==-1)                 /* << SI existe pas la creer         */
    {CreateWindow(attr, ident,0L,w_proc, 0,20+((Ecran_h-20)>>1),Ecran_l,(Ecran_h-20)>>1, title);
    }
 else                           /* << SI elle existe                  */
    {if (Windtab[w_ind].w_flag & W_IS_ICON || 
     Windtab[w_ind].w_flag & W_IS_ALLICON
     )
     {UnconifyWindow(w_ind); 
     }
     else if (IsWindOpen(w_ind)>0)     /*        SI ouverte la mettre au top */
        {wind_set(Windtab[w_ind].w_h,WF_TOP);
        }
     else                       /*        SI pas ouverte l'ouvrir     */
        {OpenWindow(w_ind, &Windtab[w_ind].ExtGrectUse);
        } 
    } 
}

/*------------------------------ OpenZoomCar -----------------------------*/
/* ACTION: cette fonction est appellee pour afficher le zoom d'un         */
/*         caractere au dessus duquel la souris se trouve.                */
/*         Cet affichage se fait par l'intermediare d'une boite rectangu- */
/*         laire dans lequel le caractere agrandi s'affiche.              */
/* ENTREE:                                                                */
/*         char *str: pointe sur une chaine d'un caractere (celui …       */
/*                   afficher).                                           */
/*         int x, int y: coordonnees du centre de la boite de zoom.       */
/*         int fntid:  indice VDI de la fonte a afficher.                 */
/*         GRECT *limit_grect: pointeur sur une structure de rectangle    */
/*                donnant les coordonn‚es du rectangle que la boite de    */
/*                zoom ne doit pas depasser.                              */
/* SORTIE:                                                                */
/*         int *x: adresse d'un int (pointeur sur un int) dans lequel la  */
/*                 fonction placera la coordonnee X de langle sup gauche  */
/*                 du rectangle ecran sauvegard‚.                         */
/*         int *y: adresse d'un int (pointeur sur un int) dans lequel la  */
/*                 fonction placera la coordonnee Y de langle sup gauche  */
/*                 du rectangle ecran sauvegard‚.                         */
/* RETOUR: int *: adresse de stockage du fond de la boite. Cette adresse  */
/*                est reservee par la fonction et doit etre liberee       */
/*                apres usage de la boite. Utilisez CloseZoomCar().       */

int *OpenZoomCar(char *str, int x, int y, int fntid, GRECT *limit_grect, int *rx, int *ry)
{VRECT vrect;
 GRECT grectzommback;
 GRECT client_grect; 
 char buft[32];
 int *back, xt ,yt;
 grectzommback.g_w = 80;
 grectzommback.g_h = 80;
 grectzommback.g_x = x - (grectzommback.g_w>>1);
 grectzommback.g_y = y - (grectzommback.g_h>>1);
 AdjustGrectToGrect(limit_grect, &grectzommback);                       
 Mouse_off();
 back = GetGRECT(&grectzommback);
 if (back)
    {ClipGrect(&grectzommback);
     /*.......... Tracer une boite ombree ........................*/
     DrawEnjolivedGrectBox(&grectzommback, &client_grect,5);
     /*......... Tracer le caractere principal ...................*/     
     Graphmode(2);   
     Deftext(1,0,0,30,fntid); 
     vst_alignment( VDIhandle, 1, 5, &x, &y );
     xt  = client_grect.g_x + (client_grect.g_w>>1);
     yt  = client_grect.g_y +2;
     VdiText(xt,yt,str);          
     /*.......... Tracer code acii en haut a gauche .....*/
     Deftext(1,0,0,4,1);
     VdiText(client_grect.g_x + 10 , client_grect.g_y + 2, itoa(*str,buft,10)); 
     Deftext(4,0,0,4,1);
     VdiText(client_grect.g_x + 56 , client_grect.g_y + 2, itoa(*str,buft,16));
     /*......... Tracer le petit rectangle en bas a droite.......*/   
     GRECT_to_VRECT(&client_grect, &vrect);
     Graphmode(1);
     vrect.left    = vrect.right  - 20;
     vrect.top     = vrect.bottom - 20;
     Deffill(0,0,0);     
     Pbox((int*)&vrect);  
     Box((int*)&vrect);
     /*.......... Tracer caractere en bas a droite ......*/     
     Graphmode(2);
     Deftext(1,0,0,10,1);
     VdiText(vrect.left + 10 , vrect.top+2, str);   
     /*......... Tracer le petit rectangle en haut a gauche.....*/      
     /*
     GRECT_to_VRECT(&client_grect, &vrect);
     Graphmode(1);
     vrect.right   = vrect.left  + 20;
     vrect.bottom  = vrect.top   + 8;     
     Deffill(0,0,0);     
     Pbox((int*)&vrect);  
     Box((int*)&vrect);           
     */
     /*.......... Tracer code acii en haut a gauche .....*/
     /*
     Graphmode(2);
     Deftext(1,0,0,4,1);
     VdiText(vrect.left + 10 , vrect.top+2, itoa(*str,buft,10));  
     */
    }
 *rx = grectzommback.g_x;
 *ry = grectzommback.g_y;   
 return back;   
}

/*------------------------------ DragBitMap --------------------------------------*/
void DragBitMap(int w_ind, int *adr_icn, int oldx , int oldy, int newx , int newy, int mode)
{GRECT grect,r1,grectint,grectext, pgrect;
 OBJECT *object = GETWINDTREE(w_ind);
 int w_h        = Windtab[w_ind].w_h; 
 int w, h;
 if (adr_icn == 0)    return;
 
 w = adr_icn[0]+1; 
 h = adr_icn[1]+1; 
 Mouse_off();
 /*............. coordonnees de la case de menu ..................*/
 grect.g_x  = oldx - (w>>1);
 grect.g_y  = oldy - (h>>1);
 grect.g_w  = w;
 grect.g_h  = h;   
 
 /*............ recuperer dimensions PAINTBOX ........................*/
 pgrect = *(GRECT*) &object[ASCCI_TABLE_PAINT_BOX1].ob_x;
 objc_offset(object, ASCCI_TABLE_PAINT_BOX1, &pgrect.g_x, &pgrect.g_y);
 
 /*............ Restaurer l'ecran deriere l'icone .................*/
 /*............. rectangle interieur aux bords epais EZ_GEM .......*/
 /*                     car il faut cliper dessus                  */
 GetGemWindExtGRECT(w_h, &grectext);
 WindGemBorderToEZWork(Windtab[w_ind].w_attr, &grectext, &grectint);
 /*........ on se sert de grectext pour sauver grectint............*/
 /*          qui se fait detruire par Rc_intersect()               */
 grectext = grectint;  
 if ( Rc_intersect( &grect, &grectint)) /* cliper sur grectint     */
    {wind_update(BEG_UPDATE);
     Wobjc_draw(w_ind, object, ASCCI_TABLE_ROOT, 8, &grectint);
     wind_update(END_UPDATE);
     /*........ dessiner paint box avec liste rectangles ..........*/
     wind_update(BEG_UPDATE);
     wind_get( w_h, WF_FIRSTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
     while (r1.g_w && r1.g_h)
       {if ( Rc_intersect(&grectint, &r1) && Rc_intersect( &grect, &grectext)) 
           {ClipGrect(&r1); 
            DrawPaintBox(w_ind, &pgrect);
           } 
        wind_get(w_h, WF_NEXTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
       } /* endwile */
     wind_update(END_UPDATE);
    }
 if (mode == DRAG_ERASE) return;
 
 /*.............. dessiner la nouvelle position icone ...............*/
 grect.g_x = newx - (w>>1);
 grect.g_y = newy - (h>>1);
 Mouse_off();
 wind_update(BEG_UPDATE);
 wind_get( w_h, WF_FIRSTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
 while (r1.g_w && r1.g_h)
  {if ( Rc_intersect(&r1, &grectext) && Rc_intersect( &grect, &grectext)) 
      {ClipGrect(&grectext); /* on se sert de grectext pour grectint */
       if (adr_icn[2]>1) Put( grect.g_x, grect.g_y, adr_icn, 3);
       else              Put_mono(grect.g_x, grect.g_y, adr_icn ,1); 
      } 
   wind_get(w_h, WF_NEXTXYWH, &r1.g_x, &r1.g_y, &r1.g_w, &r1.g_h);
  }/* endwile */
 wind_update(END_UPDATE);
 Mouse_on();
}

/*------------------------------ CloseZommCar ----------------------------*/
/* ACTION: cette fonction est appellee pour afficher le zoom d'un         */
/*         caractere au dessus duquel la souris se trouve.                */
/*         Cet affichage se fait par l'intermediare d'une boite rectangu- */
/*         laire dans lequel le caractere agrandi s'affiche.              */
/* ENTREE:                                                                */
/*         char *back: pointe sur zone de sauvegarde ecran de la boite    */
/*                     de zoom.                                           */
/*         int x, int y: coordonnees de l'angle sup gauche de la zone de  */
/*                       sauvegarde de la boite de zoom.                  */
/* RETOUR: int *: adresse de stockage du fond de la boite. Cette adresse  */
/*                est reservee par la fonction OpenZommCar(): et est      */
/*                liberee  par cette fonction  CloseZoomCar():  qui       */
/*                retourne zero.                                          */
                                      
int *CloseZommCar(int *back, int x, int y)
{if (back)
    {Mouse_off();
     Put(x, y, back, 3);        
     free(back); 
     Mouse_on();
    }
 return 0;
}

/*------------------------- LST_BOX_TabType -------------------------------*/
/* ACTION: routine d'affichage des elements d'une LISTBOX choix du type de */
/*         table en cours pour                                             */
/*         case elle fait appel … notre routine avec en entree la struct-  */
/*         re LIST_GET_TXT *ptLISTGETTXT permettant de savoir quelle       */
/*         partie de la list box il faut afficher.                         */
/*         Cette fonction un peu delirante affiche les couleurs dans des   */
/*         ellipses.                                                       */
/* les coordonn‚es de l'element … afficher peuvent etre calculees en       */
/* faisant:                                                                */
/*          coord.left    = ptLISTGETTXT->grect.g_x;                       */
/*          coord.top     = ptLISTGETTXT->grect.g_y  +                     */
/*                          ptLISTGETTXT->h_lign     *                     */
/*                         (ptLISTGETTXT->lign + 1)                        */
/*          coord.right   = ptLISTGETTXT->grect.g_x  +                     */
/*                          ptLISTGETTXT->grect.g_w  - 1                   */
/*          coord.bottom  = coord.top  + ptLISTGETTXT->h_lign -1           */
/*                                                                         */
/* ENTREE:  *ptLISTGETTXT  (pointeur sur structure  LIST_GET_TXT )         */
/*                                                                         */
/* Rappel sur la structure d'entree LIST_GET_TXT:                          */
/* Distinguons deux types d'elements:                                      */
/*            a) ceux de notre liste … afficher : element liste            */
/*                        exemple liste des polices caractere              */
/*                        exemple liste des couleurs etc..                 */
/*            b) ceux de la boite listbox :       element listbox          */
/*                        element de la boite de selection                 */
/*                        premier element de la listbox                    */
/*                        dernier element de la list box                   */
/* typedef struct                                                          */
/*      {int lign;     Nø de l'element listbox … afficher                  */
/*                        que l'on nous demande d'afficher                 */
/*                        si -1 c'est celui de la boite de selection       */
/*                        si zero c'est celui sous la boite de selection   */
/*                        si un c'est le suivant                           */
/*                        si deux le suivant etc...                        */
/*                                                                         */
/*       int preml;   Nø de l'element liste … afficher en zero listbox     */
/*       int pointl;  Nø de l'element liste selectionn‚ … afficher en -1   */
/*       int h_lign;  hauteur en pixel d'un element listbox                */
/*       GRECT grect; coordonn‚es de la liste en absolu pix. ecran         */
/*       GRECT clipgrect; coordonn‚es de clipping en absolu pix. ecran     */
/*       void *LstBoxParam; parametre optionnel de transmission            */
/*                          par lequel l'on re‡oit des info specifiques    */
/*                          au type de list box                            */
/*                          (adresse d'une table, adresse d'un texte...)   */
/*                          ici inutilise                                  */
/*     }LIST_GET_TXT;                                                      */

int LST_BOX_TabType (LIST_GET_TXT *ptLISTGETTXT)
{int vectxy[4];
 int i, nb_lgn_max;    
 int idxref;  
 RECT coord;
 GRECT lstgrect;
 /*.......... nombre de ligne max de la LISTBOX .....................*/
 /* if (MagXVers>=0x610) */
     nb_lgn_max = (int)(sizeof(LSTBOX_TAB_STR)/sizeof(char*)); /* 9 tables pour Magic  */
 /* else
     nb_lgn_max = 3;
*/ 
 /*.............. determiner et calculer coordonnees ................*/
 /*               de la case (ou ligne) qu'il nous                   */
 /*                    est demand‚e d'afficher                       */
 coord.left    = ptLISTGETTXT->grect.g_x;                       
 coord.top     = ptLISTGETTXT->grect.g_y  +                     
                 ptLISTGETTXT->h_lign     *                     
                (ptLISTGETTXT->lign + 1);                       
 coord.right   = ptLISTGETTXT->grect.g_x  +                     
                 ptLISTGETTXT->grect.g_w  - 1;                  
 coord.bottom  = coord.top  + ptLISTGETTXT->h_lign -1;          
 
 /*.......... determiner l'element de la liste, qu'il convient .......*/
 /*           d'afficher, en fonction de la ligne qu'il est demand‚   */
 /*                           d'afficher.                             */
 /*                                                                   */
 /*                    SI il est demande d'afficher la premiere case  */
 /*                       de la LISTBOX, (ptLISTGETTXT->lign == -1)   */
 /*                       il faut afficher l'element selectionn‚      */
 /*                       (ptLISTGETTXT->pointl) dans notre liste.    */
 /*                                                                   */
 if   (ptLISTGETTXT->lign == -1) idxref = ptLISTGETTXT->pointl;
 
 /*                    SI il est demande d'afficher une autre case    */
 /*                       de la LISTBOX, il faut afficher la liste …  */
 /*                       partir du premier devant etre affiche en    */
 /*                       deuxieme ligne.                             */
 /*                                                                   */
 else  idxref = ptLISTGETTXT->preml + ptLISTGETTXT->lign;
 
 
 /*.......... tracer le rectangle blanc .................*/
 Deffill(1,0,0);                                          
 Graphmode(1); 
 Defline(1,1,0,0,1);
 /*........... dessiner rectangle boite selection ......*/
 if (ptLISTGETTXT->lign == -1)        
    {vectxy[0]=coord.left   + 2;
     vectxy[1]=coord.top    + 2;     
     vectxy[2]=coord.right  - 1;
     vectxy[3]=coord.bottom - 1; 
     vr_recfl(VDIhandle,vectxy);            
     Box(vectxy); 
    }
 /*............ afficher taille en points ........*/   
 VRECT_to_GRECT((VRECT*)&coord, &lstgrect);  
 if ( idxref< nb_lgn_max       /*9 ou 3 */ && 
      Rc_intersect(&ptLISTGETTXT->clipgrect,&lstgrect)
    )
    {ClipGrect(&lstgrect);           
     Graphmode(MD_TRANS);    
     vst_alignment (VDIhandle,0,ALI_TOP, &i, &i );  
     vst_font(VDIhandle,0);    
     vst_point(VDIhandle,  9, &i, &i, &i, &i);
     vst_color (VDIhandle,1);
     v_gtext(VDIhandle,coord.left + 5, coord.top + 5 , LSTBOX_TAB_STR[idxref]);
    }
 
 /*.......... tracer sillon de separation entre deux elements .........*/
 /*          que si on affiche un element different de celui de        */
 /*                        la premiere ligne                           */
 if (ptLISTGETTXT->lign != -1)
    {vectxy[0]=coord.left;
     vectxy[1]=coord.top;     
     vectxy[2]=coord.right;
     vectxy[3]=vectxy[1];
     DrawSillonHori(vectxy, 1);
    } 
 return 1;
}  

void Spy(const char *mes)
{puts("\33H");
 printf("%s","                                                                                                                                                                 ");
 puts("\33H");
 printf("%s",mes);
 /* getch(); */
}