Logo Search packages:      
Sourcecode: jered version File versions  Download package

formulr.c

/**********************************************************************/
/* FORMULR.C: gestion de formulaires de saisie en mode texte            */
/**********************************************************************/

/*
    Copyright (C) 1996, 1997 Free Software Foundation, Inc.
    Ce programme fait partie du package JERED et est soumis, comme le
    reste du package JERED, a la Gnu General Public License version 2
    ou superieure dont voici un extrait et dont vous pouvez lire
    la totalite en consultant le fichier COPYING.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/

#include <ctype.h>
#include "jered.h"
#include "formulr.h"

extern int insert_mode;
extern int language;
extern int resizewin;

static chtype cadres[3][8];

static int esc_clear = OFF;   /* flag vrai si ESCAPE vide les variables */

chtype *carac_attrib(unsigned char *, chtype *, chtype);
static void cadre_zone(PTFORMU, PTFZONE, int);
static int compare_num(char *, char *);
static int homogene(PTFZONE);
static void initialise_cadres(void);
/**********************************************************************/
static void initialise_cadres(void)
{
      chtype *ptc;

      ptc = &cadres[0][0];
      *ptc++ = hg();
      *ptc++ = hm();
      *ptc++ = hd();
      *ptc++ = bg();
      *ptc++ = bd();
      *ptc++ = mg();
      *ptc = (chtype)'\0';

      ptc = &cadres[1][0];
      *ptc++ = hgd();
      *ptc++ = hmd();
      *ptc++ = hdd();
      *ptc++ = bgd();
      *ptc++ = bdd();
      *ptc++ = mgd();
      *ptc = (chtype)'\0';
}
/**********************************************************************/
void set_esc_clear(int action)      /* positionne le mode ESCAPE */
{
      esc_clear = action;
}
/**********************************************************************/
void init_application_fliste(PTFLISTE liste, int (*aide)(PTFORMU, PTFZONE), int typecad, int atoufer, chtype coulcadre, chtype coulfond, chtype coultitre, chtype coultexte, chtype coulzone, chtype coulfill, chtype coulaide)
{
      PTFORMU form;
      PTFZONE zone;
      PTFTEXT text;

      /* pour chacun des formulaires de la liste */
      for (form = liste->ffirst; form != NULL; form = form->fsuiv)
      {
            /* initialise les couleurs du formulaire */
            form->tcolor = coultitre;
            form->fcolor = coulfond;
            form->ccolor = coulcadre;

            /* initialise le type de cadre */
            form->typecadre = typecad;

            /* initialise la fonction d'aide par defaut */
            form->help = aide;

            /* initialise le champ de bits a tout faire */
            form->atoufer = atoufer;


            /* pour chaque zone du formulaire */
            for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
            {
                  /* initialise couleurs de la zone */
                  zone->varcolor = coulzone;
                  zone->fillcolor = coulfill;
                  zone->aidecolor = coulaide;
            }

            /* pour chaque texte du formulaire */
            for (text = form->tfirst; text != NULL; text = text->tsuiv)
            {
                  /* initialise couleur du texte */
                  text->textcolor = coultexte;
            }
      }
}
/**********************************************************************/
PTFTEXT cree_texte_vide(PTFORMU form)
{
      PTFTEXT text;     /* pointeur sur dernier texte ajoute */
      PTFTEXT pt; /* pointeur sur nouveau texte */

      pt = (PTFTEXT)malloc(sizeof(FORMTEXT));

      /* si l'allocation a reussi on initialise la zone */
      if (pt != NULL)
      {
            memset(pt, 0x0000, sizeof(FORMTEXT));

            /* recherche ou inserer */
            for (text = form->tfirst; (text != NULL) && (text->tsuiv != NULL); text = text->tsuiv) ;

            /* si on est sorti avec text = NULL, il n'y a pas encore de texte dans le formulaire */
            if (text == NULL)
            {
                  form->tfirst = pt;
            }
            else
            {
                  text->tsuiv = pt;
            }
      }
      return(pt);
}
/**********************************************************************/
PTFZONE cree_zone_vide(PTFORMU form)
{
      PTFZONE zone;     /* pointeur sur derniere zone ajoutee */
      PTFZONE pz; /* pointeur sur nouvelle zone */

      pz = (PTFZONE)malloc(sizeof(FORMZONE));

      /* si l'allocation a reussi on initialise la zone */
      if (pz != NULL)
      {
            memset(pz, 0x0000, sizeof(FORMZONE));

            /* recherche ou inserer */
            for (zone = form->zfirst; (zone != NULL) && (zone->zsuiv != NULL); zone = zone->zsuiv) ;

            /* si on est sorti avec zone = NULL, il n'y a pas encore de zone dans le formulaire */
            if (zone == NULL)
            {
                  form->zfirst = pz;
            }
            else
            {
                  zone->zsuiv = pz;

                  /* positionne le pointeur vers la zone precedente */
                  zone->zsuiv->zprec = zone;
            }
      }
      return(pz);
}
/**********************************************************************/
PTFORMU cree_formulaire_vide(PTFLISTE liste)
{
      PTFORMU form;     /* pointeur sur les formulaires deja existants */
      PTFORMU pf; /* pointeur sur nouveau formulaire */

      pf = (PTFORMU)malloc(sizeof(FORMULAIRE));

      /* si l'allocation a reussi on indique la fin de la liste */
      /* et on remet tout a vide */
      if (pf != NULL)
      {
            memset((int *)pf, 0x0000, sizeof(FORMULAIRE));

            /* recherche ou inserer */
            for (form = liste->ffirst; (form != NULL) && (form->fsuiv != NULL); form = form->fsuiv) ;

            /* si on est sorti avec (form = NULL) il n'y a pas encore de formulaires */
            if (form == NULL)
            {
                  /* alloue la place pour le premier formulaire */
                  liste->ffirst = pf;
            }
            else
            {
                  /* alloue la place pour un formulaire */
                  form->fsuiv = pf;

                  /* positionne le pointeur vers le formulaire precedent */
                  form->fsuiv->fprec = form;
            }
      }
      return(pf);
}
/**********************************************************************/
void free_allocated_fliste(PTFLISTE liste)
{
      PTFORMU form;
      PTFORMU ff;
      PTFZONE zone;
      PTFZONE zz;
      PTFTEXT text;
      PTFTEXT tt;

      /* on libere l'ensemble des formulaires attaches a liste */
      form = liste->ffirst;
      while (form != NULL)
      {
            ff = form->fsuiv;

            ferme_formulaire(form);    /* ferme a tout hasard le formulaire */

            /* libere l'ensemble des zones du formulaire */
            zone = form->zfirst;
            while (zone != NULL)
            {
                  zz = zone->zsuiv;

                  free(zone);

                  zone = zz;
            }

            /* libere l'ensemble des textes du formulaire */
            text = form->tfirst;
            while (text != NULL)
            {
                  tt = text->tsuiv;

                  free(text);

                  text = tt;
            }

            free(form); /* libere formulaire */

            form = ff;
      }
}
/**********************************************************************/
void centre_formulaire(PTFORMU form)
{
      int maxlig;
      PTFZONE zone;

      maxlig = (JEREDLINES - 1);

      /* si une des zones du formulaire a une aide en ligne */
      /* on utilise une ligne de plus en bas */
      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
      {
            if (zone->aidenlig != NULL)
            {
                  maxlig--;
                  break;
            }
      }

      /* calcul de l'ordonnee du formulaire pour qu'il soit centre */
      form->y = (maxlig / 2) - (form->h / 2);
      if (form->y < 0)
            form->y = 0;

      /* calcul de l'abscisse du formulaire pour qu'il soit centre */
      form->x = ((JEREDCOLS / 2) - (form->l + (form->l & 1)) / 2);
      if (form->x < 0)
            form->x = 0;
}
/**********************************************************************/
void ajuste_formulaire(PTFORMU form)
{
      int posmaxi;      /* position maxi du formulaire */
      int posmax; /* position maximale dans une ligne */
      int pos;    /* position de fin de la zone courante */
      PTFZONE zone;     /* pointeur sur chaque zone du formulaire */
      PTFTEXT text;     /* pointeur sur chaque texte du formulaire */
      int i;            /* compteur de lignes */
      int ligne1; /* si 0 indique si la ligne 1 est utilisee, auquel cas on ne */
                  /* rajoute pas de ligne vide apres la derniere zone */

      ligne1 = 1; /* par defaut ligne 1 non utilisee */

      /* calcul de la hauteur utile du formulaire */
      posmaxi = -1;

      /* calcule ordonnee maxi des zones */
      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
      {
            if (zone->yr == 1)
                  ligne1 = 0; /* si ligne 1 on l'indique */

            if (posmaxi < zone->yr)
                  posmaxi = zone->yr;
      }

      /* calcule ordonnees maxi entre zones et textes */
      for (text = form->tfirst; text != NULL; text = text->tsuiv)
      {
            if (text->yr == 1)
                  ligne1 = 0;

            if (posmaxi < text->yr)
                  posmaxi = text->yr;
      }

      /* stocke maintenant la hauteur utile du formulaire */
      form->h = posmaxi + 2 + ligne1;

      /* calcul de la largeur maxi du formulaire */
      posmaxi = -1;

      /* si titre alors position maxi de depart = 1 + longueur du titre */
      if (form->ftitre != NULL)
            posmaxi = 1 + strlen(form->ftitre);

      /* pour chaque ligne a l'interieur du formulaire */
      for (i = 1; i < (form->h - 1); i++)
      {
            posmax = 0;
            pos = 0;

            /* ajoute la longueur de chacune des zones de cette ligne */
            for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
            {
                  /* la zone appartient a cette ligne */
                  if (zone->yr == i)
                  {
                        /* on rajoute la longueur du format a la position */
                        pos = zone->xr;
                        if (zone->format != NULL)
                              pos += strlen(zone->format);
                        if (posmax < pos)
                              posmax = pos;
                  }
            }

            /* on ajoute ensuite la longueur de chaque texte de cette ligne */
            for (text = form->tfirst; text != NULL; text = text->tsuiv)
            {
                  /* le texte appartient a cette ligne */
                  if (text->yr == i)
                  {
                        /* on rajoute la longueur du texte a sa position */
                        pos = text->xr;
                        if (text->texte != NULL)
                              pos += strlen(text->texte);
                        if (posmax < pos)
                              posmax = pos;
                  }
            }

            /* calcul de la valeur maxi */
            if (posmaxi < posmax)
                  posmaxi = posmax;
      }

      /* on peut maintenant affecter la valeur maxi de la largeur du formulaire */
      form->l = posmaxi + 3;
      if (form->l & 1)
            form->l--;
}
/**********************************************************************/
int ouvre_formulaire(PTFORMU form)
{
      static int first = 1;   /* premier passage */
      chtype *memv;       /* pointeur vers buffer pour sauver fond de l'ecran */
      chtype *memt;       /* pointeur vers buffer pour construire formulaire */
      chtype *ptmemt;     /* pointeur pour construire le formulaire */
      int sizemem;        /* taille memoire necessaire au formulaire */
      int sizelig;        /* taille d'une ligne du formulaire en octets */
      int offset;   /* variable temporaire pour simplifier calculs */
      chtype *tcadre;     /* pointeur vers type de cadre */
      chtype color;       /* variable temporaire pour couleur */
      chtype carcadre;  /* caractere de trace de cadre */
      int i;            /* compteur */
      int j;            /* compteur */
      unsigned char *tit;      /* pointeur vers titre du cadre */

      if (first)
      {
            initialise_cadres();
            first = 0;
      }

      form->ligaide = (JEREDLINES - 2);

      /* si le formulaire courant est deja ouvert on sort */
      if (form->prepa != NULL || form->sauve != NULL)
            return(ALREADYOPEN);

      /* calcul de la taille necessaire */
      sizelig = (form->l + 2) * sizeof(chtype);
      sizemem = sizelig * (form->h + 2);

      /* allocation de la memoire pour construire le formulaire */
      memt = (chtype *)malloc(sizemem);
      if (memt == NULL)
            return(NOTENOUGHMEM);   /* pas assez de memoire */

      /* allocation de la memoire pour sauver l'ecran */
      memv = (chtype *)malloc(sizemem);
      if (memv == NULL)
      {
            free(memt); /* libere memoire allouee sans erreur */
            return(NOTENOUGHMEM);     /* pas assez de memoire */
      }

      /* stocke les pointeurs vers la memoire allouee pour le formulaire */
      form->prepa = memt;
      form->sauve = memv;

      /* sauve l'ecran */
      get_txt(form->x, form->y, form->x + form->l + 1, form->y + form->h, memv);

      /* recupere les parametres du formulaire */
      tcadre = &cadres[form->typecadre][0];
      color = form->ccolor;
      ptmemt = memt;

      /* construit les angles du formulaire en memoire temporaire */
      /* angle en haut a gauche */
      *ptmemt = (*tcadre | color);

      /* angle en bas a gauche */
      offset = (form->h - 1) * form->l;
      *(ptmemt + offset) = (*(tcadre + 3) | color);

      /* angle en bas a droite */
      *(ptmemt + (form->l * form->h) - 1) = (*(tcadre + 4) | color);

      /* angle en haut a droite */
      *(ptmemt + form->l - 1) = (*(tcadre + 2) | color);

      /* trace les montants du cadre */
      ptmemt = memt + form->l;
      carcadre = *(tcadre + 5);
      for (i = 1; i < (form->h - 1); i++)
      {
            *ptmemt = (carcadre | color); /* montant gauche */

            ptmemt += (form->l - 1); /* pointe sur montant droit */

            *ptmemt = (carcadre | color); /* montant droit */

            ptmemt++;         /* pointe sur montant gauche plus bas */
      }

      /* trace les parties horizontales du cadre */
      ptmemt = memt + 1;
      carcadre = *(tcadre + 1);
      for (i = 1; i < (form->l - 1); i++)
      {
            /* partie horizontale haute */
            *ptmemt = (carcadre | color);

            /* partie horizontale basse */
            *(ptmemt + offset) = (carcadre | color);

            /* passe au caractere suivant */
            ptmemt++;
      }

      /* remplit l'interieur du cadre */
      color = form->fcolor;
      ptmemt = memt + form->l + 1;
      for (i = 1; i < (form->h - 1); i++)
      {
            for (j = 1; j < (form->l - 1); j++)
            {
                  *ptmemt++ = (chtype)((chtype)' ' | color);
            }
            ptmemt += 2; /* saute cadre de droite et celui plus bas a gauche */
      }

      /* remplit l'emplacement du titre du cadre */
      ptmemt = memt + 2;      /* saute cadre gauche */
      tit = (unsigned char *)form->ftitre;
      if (tit != NULL)
      {
            i = strlen((char *)tit);
            j = min(i, (form->l - 2));
            color = form->tcolor;
            for (i = 0; i < j; i++)
            {
                  *ptmemt++ = (chtype)((chtype)*tit++ | color);
            }
      }

      /* construit maintenant les zones et messages du formulaire */
      /* et affiche le formulaire */
      affiche_formulaire(form);

      /* renvoie code pour pas d'erreur */
      return(NOERROR);
}
/**********************************************************************/
void ferme_formulaire(PTFORMU form)
{
      /* si le formulaire n'a pas deja ete ferme on le ferme */
      if (form->sauve != NULL)
      {
            /* replace l'ecran comme il etait avant le ouvre_formulaire() */
            put_txt(form->x, form->y, form->x + form->l + 1, form->y + form->h, form->sauve);

            /* libere memoire utilisee par la copie de l'ecran */
            free(form->sauve);
      }

      /* libere memoire utilisee par le formulaire */
      if (form->prepa != NULL)
            free(form->prepa);

      /* et met les pointeurs a une valeur nulle */
      form->sauve = (chtype *)NULL;
      form->prepa = (chtype *)NULL;

      /* remet a zero la derniere touche appuyee du formulaire */
      /* ce qui est utile pour gerer les zones en sortie */
      /* on peut alors lire la derniere touche appuyee du formulaire par */
      /* form->lastzone->lastkey */
      form->lastkey = 0;
}
/**********************************************************************/
void affiche_formulaire(PTFORMU form)
{
      PTFZONE zone;     /* pointeur sur les zones du formulaire */
      PTFTEXT text;     /* pointeur sur les messages du formulaire */

      /* construit tous les messages du formulaire */
      for (text = form->tfirst; text != NULL; text = text->tsuiv)
      {
            construit_texte(form, text);
      }

      /* construit toutes les zones du formulaire */
      /* en cadrant les zones numeriques mais sans afficher */
      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
      {
            cadre_zone(form, zone, 0);
      }

      /* affiche enfin le formulaire */
      put_txt(form->x, form->y, form->x + form->l - 1, form->y + form->h - 1, form->prepa);
}
/**********************************************************************/
int lire_formulaire_simple(PTFORMU form)
{
      int read;   /* code de retour de cette fonction */

      ajuste_formulaire(form); /* ajuste largeur et hauteur automatiquement */
      centre_formulaire(form); /* calcule abscisse et ordonnee automatiquement */
      if (ouvre_formulaire(form) == NOERROR) /* pas d'erreur d'ouverture */
      {
            read = lire_formulaire(form); /* effectue la lecture */
            ferme_formulaire(form);       /* ferme le formulaire */
      }
      else
            read = ERROR;

      return(read);
}
/**********************************************************************/
int lire_formulaire(PTFORMU form)
{
      PTFZONE zone; /* pointeur sur les zones du formulaire */
      int retzone;      /* valeur de retour de la saisie de la zone */
      int test;   /* code de retour pour verification generale */
      int entree; /* indique s'il y a au moins une zone en entree */
      int touche;

      inputmode = DIALOGMODE;

      zone = form->zfirst;    /* premiere zone du formulaire */
      entree = 0;       /* par defaut toutes les zones sont en sortie */
      while (zone != NULL)
      {
            if (! (zone->force & ZONESORTIE))
            {
                  entree = 1; /* une zone est en entree */
                  break;
            }
            else
                  zone = zone->zsuiv;
      }

      if (! entree)           /* si toutes les zones sont en sortie */
      {
            do
            {
                  form->lastkey = touche = fread_key();
            }
            while (touche != KEY_ESCAPE) ;

            inputmode = NORMALMODE;
            if (resizewin)
                  restart_screen_again();

            if (touche == KEY_ESCAPE)
                  return(CANCELBUTTON);
            else
                  return(OKBUTTON);
      }

      retzone = CANCELBUTTON; /* par defaut */
      zone = form->zfirst; /* pointe sur premiere zone du formulaire */
      while (zone != NULL)
      {
            /* indique la zone en cours de saisie */
            form->lastzone = zone;

            /* traite chaque zone */
            retzone = lire_zone(form, zone);
            switch (retzone)
            {
                  case OKBUTTON:
                        /* l'utilisateur a valide sa saisie */
                        /* on controle donc une derniere fois */
                        /* l'ensemble des zones du formulaire de saisie */
                        test = 0;
                        for (zone = form->zfirst; ((zone != NULL) && ((test = valide_zone(zone)) != 0));  zone = zone->zsuiv) ;
                        if (test)
                              zone = NULL;

                        break;

                  case CANCELBUTTON:      /* sortie par escape */
                  case EXITBUTTON:  /* sortie provoquee depuis une fonction appelee */
                        if (esc_clear)          /* ESCAPE ==> effacement */
                        {
                              zone = form->zfirst;
                              while (zone != NULL)
                              {
                                    if (zone->variable != NULL && (! (zone->force & ZONESORTIE)))
                                          *zone->variable = '\0'; /* annule la valeur saisie de chacune des zones en entree */
                                    zone = zone->zsuiv; /* passe a la zone suivante */
                              }
                        }
                        else
                              zone = NULL;

                        break; /* zone vaut NULL donc on sort bien */

                  case NEXTZONE:
                        /* si derniere zone et mode rouleau repointe sur premiere zone */
                        if (zone->zsuiv == NULL)
                        {
                              if (form->atoufer & MODEROULEAU)
                                    zone = form->zfirst;
                        }
                        else
                        {
                              /* ce n'est pas la derniere zone */
                              /* donc on passe a la suivante */
                              zone = zone->zsuiv;
                        }

                        break;

                  case PREVZONE:
                        /* si premiere zone et mode rouleau repointe sur derniere zone */
                        if (zone->zprec == NULL)
                        {
                              if (form->atoufer & MODEROULEAU)
                              {
                                    while (zone->zsuiv != NULL)
                                          zone = zone->zsuiv;
                              }
                        }
                        else
                        {
                              /* ce n'est pas la premiere zone */
                              /* donc on passe a la precedente */
                              zone = zone->zprec;
                        }

                        break;

                  case FIRSTZONE:
                        /* premiere zone */
                        zone = form->zfirst;

                        break;

                  case LASTZONE:
                        /* passe a la derniere zone */
                        while (zone->zsuiv != NULL)
                              zone = zone->zsuiv;

                        break;

                  default:
                        break;
            }
      }

      inputmode = NORMALMODE;
      if (resizewin)
            restart_screen_again();

      /* renvoie la touche appuyee: Echappe ou Entree */
      return(retzone);
}
/**********************************************************************/
void raz_zones(PTFORMU form)
{
      PTFZONE zone;

      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
      {
            if (zone->variable != NULL)
                  *zone->variable = '\0';
      }
}
/**********************************************************************/
void reaffiche_zones(PTFORMU form)
{
      PTFZONE zone;

      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
            cadre_zone(form, zone, 1);
}
/**********************************************************************/
void zones_en_entree(PTFORMU form)
{
      PTFZONE zone;

      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
            zone->force &= (~ ZONESORTIE);
}
/**********************************************************************/
void zones_en_sortie(PTFORMU form)
{
      PTFZONE zone;

      for (zone = form->zfirst; zone != NULL; zone = zone->zsuiv)
            zone->force |= ZONESORTIE;
}
/**********************************************************************/
void maj_zone(PTFORMU form, PTFZONE zone)
{
      chtype *ptmem;      /* pointeur vers la zone de construction du formulaire */

      /* met a jour le texte de la zone dans le buffer */
      construit_zone(form, zone);

      /* pointe sur adresse ou a ete effectue le remplissage de la zone */
      ptmem = form->prepa + zone->xr + (zone->yr * form->l);

      /* et on reaffiche uniquement la zone concernee du formulaire */
      put_txt(form->x + zone->xr, form->y + zone->yr, form->x + zone->xr + strlen(zone->format) - 1, form->y + zone->yr, ptmem);
}
/**********************************************************************/
void construit_texte(PTFORMU form, PTFTEXT text)
{
      chtype *ptw;        /* pointeur vers la zone de construction du formulaire */

      /* pointe sur adresse ou commencer le remplissage de la zone */
      ptw = form->prepa + text->xr + (text->yr * form->l);

      /* construit la chaine dans le formulaire */
      carac_attrib((unsigned char *)text->texte, ptw, text->textcolor);
}
/**********************************************************************/
void construit_zone(PTFORMU form, PTFZONE zone)
{
      chtype *ptmem;     /* pointeur vers la zone de construction du formulaire */

      /* pointe sur adresse ou commencer le remplissage de la zone */
      ptmem = form->prepa + zone->xr + (zone->yr * form->l);

      /* construit la zone de remplissage */
      carac_attrib((unsigned char *)zone->fill, ptmem, zone->fillcolor);

      /* construit la zone saisie */
      carac_attrib((unsigned char *)zone->variable, ptmem, zone->varcolor);
}
/**********************************************************************/
int valide_zone(PTFZONE zone)
{
      int retcode;            /* indique si la zone est acceptee ou non */
      register char *ptr;     /* pointeur vers la chaine saisie */
      register char *ptf;     /* pointeur vers le format de saisie */

      retcode = 1;      /* par defaut la zone est valide */

      /* si la zone est en sortie elle est consideree comme valide */
      if (! (zone->force & ZONESORTIE))
      {
            /* teste si chaque caractere saisi correspond a son format */
            ptr = zone->variable;
            ptf = zone->format;
            while (*ptr && *ptf && valide_caractere(*ptr, *ptf))
            {
                  ptr++;
                  ptf++;
            }

            if (! *ptr)
            {
                  if ((zone->force & FORCESAISIE) && (! *zone->variable))
                        retcode = 0;
                  else
                  {
                        /* si fonction de controle presente */
                        if (zone->controle != NULL)
                        {
                              /* effectue un controle */
                              retcode = zone->controle(zone->variable);
                        }

                        /* si la zone n'a pas encore ete invalidee */
                        if (retcode)
                        {
                              /* s'il n'y a pas de fonction de comparaison */
                              /* alors c'est strcmp */
                              if (zone->compare == NULL)
                              {
                                    if (*zone->format == NUMERIC && homogene(zone))
                                          zone->compare = (int (*)(char *, char *))compare_num;
                                    else
                                          zone->compare = (int (*)(char *, char *))strcmp;
                              }

                              /* s'il y a une valeur minimale */
                              if (zone->valmin != NULL)
                              {
                                    /* si variable < valeur minimale alors erreur */
                                    if (zone->compare(zone->variable, zone->valmin) < 0)
                                          retcode = 0;
                              }

                              /* si toujours pas d'erreur */
                              if (retcode)
                              {
                                    /* s'il y a une valeur maximale */
                                    if (zone->valmax != NULL)
                                    {
                                          /* si variable > valeur maximale alors erreur */
                                          if (zone->compare(zone->variable, zone->valmax) > 0)
                                                retcode = 0;
                                    }
                              }
                        }
                  }
            }
            else
                  retcode = 0; /* on a trouve un caractere ne correspondant pas avec son format */
      }

      /* renvoie 0 si la zone est refusee */
      return(retcode);
}
/**********************************************************************/
static int compare_num(char *n1, char *n2)
{
      return((int)(atol(n1) - atol(n2)));
}
/**********************************************************************/
static int homogene(PTFZONE zone)
{
      int ok;                 /* indique si format homogene ou non */
      register char *ptf;     /* pointeur sur le format de saisie */
      register char form1;    /* 1er caractere du format */

      ok = 1;           /* par defaut format homogene */
      ptf = zone->format;
      form1 = *ptf;

      while (*ptf && *ptf == form1)
            ptf++;
      if (*ptf)
            ok = 0; /* format non homogene */

      return(ok); /* renvoie indicateur homogene ou non */
}
/**********************************************************************/
static void cadre_zone(PTFORMU form, PTFZONE zone, int affiche)
{
      unsigned char bufftmp[160];    /* buffer pour cadrage des numeriques */
      register char *ptxt;    /* pointeur vers les chaines a afficher */
      register unsigned char *ptw;   /* pointeur vers la zone de construction du formulaire */
      chtype *ptmem;            /* pointeur vers la zone de construction du formulaire */
      unsigned char *ptf;            /* pointeur pour cadrage */

      /* pointe sur adresse ou commencer le remplissage de la zone */
      ptmem = form->prepa + zone->xr + (zone->yr * form->l);

      /* construit la zone de remplissage */
      carac_attrib((unsigned char *)zone->fill, ptmem, zone->fillcolor);

      ptxt = zone->variable;
      if (ptxt != NULL && *ptxt)    /* variable non vide */
      {
            /* dans le cas d'un numerique on cadre a droite */
            if (*zone->format == NUMERIC && homogene(zone))
            {
                  ptf = bufftmp + strlen(zone->format) - strlen(ptxt);
                  ptw = bufftmp;
                  while (ptw < ptf)
                        *ptw++ = ' ';
                  while (*ptxt)
                        *ptw++ = *ptxt++;
                  *ptw = '\0';

                  ptxt = (char *)bufftmp;
            }

            /* construit la chaine dans le buffer */
            carac_attrib((unsigned char *)ptxt, ptmem, zone->varcolor);
      }

      /* et on reaffiche uniquement la zone concernee du formulaire */
      if (affiche)
            put_txt(form->x + zone->xr, form->y + zone->yr, form->x + zone->xr + strlen(zone->format) - 1, form->y + zone->yr, ptmem);
}
/**********************************************************************/
int valide_caractere(char carac, char fmt)
{
      int retcode; /* code de retour 0 si le caractere n'est pas dans le format */

      retcode = 0;      /* par defaut le caractere ne correspond pas au format */

      switch (fmt)
      {
            /* format yes/no */
            case YESNO:
                  switch (language)
                  {
                        case FRENCH:      /* Oui               Non */
                              if ((carac == 'O') || (carac == 'N'))
                                    retcode = 1;
                              break;

                                    /* KYLLÄ     EI */
                        case FINNISH:
                              if ((carac == 'K') || (carac == 'E'))
                                    retcode = 1;
                              break;

                        case GERMAN:      /* Ja         Nein */
                              if ((carac == 'J') || (carac == 'N'))
                                    retcode = 1;
                              break;

                        case RUSSIAN:     /* äÁ          îÅÔ */
                              if ((carac == 'ä') || (carac == 'î'))
                                    retcode = 1;
                              break;

                        case SPANISH:     /* SI          NO */
                              if ((carac == 'S') || (carac == 'N'))
                                    retcode = 1;
                              break;

                        case ENGLISH:
                        default:    /* Yes                No */
                              if ((carac == 'Y') || (carac == 'N'))
                                    retcode = 1;
                              break;
                  }
                  break;

            /* format oui/non: french only */
            case OUINON:
                  if (carac == 'O' || carac == 'N')
                        retcode = 1;
                  break;

            /* format hexadecimal majuscule */
            case HHEXA:
                  if ((carac >= '0' && carac <= '9') || (carac >= 'A' && carac <= 'F'))
                        retcode = 1;
                  break;

            /* format hexadecimal minuscule/MAJUSCULE indifferentiées */
            case LHEXA:
                  if (isxdigit(carac))
                        retcode = 1;
                  break;

            /* format ascii libre */
            case ASCNORM:
                  retcode = 1;
                  break;

            /* format ascii transforme en majuscules */
            case HASCNORM:
                  retcode = 1;
                  break;

            /* format numerique seulement */
            case NUMERIC:
                  if (isdigit(carac))
                        retcode = 1;
                  break;

            /* format inconnu */
            default:
                  break;
      }

      return(retcode); /* renvoie 1 si le caractere correspond au format */
}
/**********************************************************************/
int lire_zone(PTFORMU form, PTFZONE zone)
{
      char *ptfmt;        /* pointeur sur le format de saisie */
      int lgmax;    /* longueur maxi de la saisie */
      int xmin, xmax;     /* abscisses minimale et maximale du curseur */
      int quitte;   /* indicateur pour sortir de la boucle de saisie */
      int retcode;        /* code de retour de cette fonction */
      int cur_stat;       /* sauve etat du curseur (insertion/recouvrement) */
      int touche;   /* derniere touche appuyee */
      int pos;      /* position actuelle dans le format et dans la variable */
      char _tmp[80];      /* buffer temporaire pour insertion */
      chtype *bufecr;     /* pour sauver l'ecran sous l'aide en ligne */
      char *newbuf;       /* pour afficher aide en ligne */
      int lgaide;   /* longueur de l'aide en ligne */

      /* si action de debut de zone on l'execute */
      if (zone->actiondeb != NULL)
            zone->actiondeb(form, zone);

      /* recherche le veritable debut du format */
      ptfmt = zone->format;

      /* si la zone est en sortie on doit aller dans la meme direction que */
      /* la fois precedente (pareil si pas de format ou variable=pointeur nul) */
      if ((! *ptfmt) || (zone->variable == NULL) || (zone->force & ZONESORTIE))
      {
            switch (form->lastkey)
            {
                  /* case PAGE_UP : */
                  case KEY_UP:
                  case Shift_TAB:
                  case KEY_BTAB:
                        /* si action de fin de zone on l'execute */
                        if (zone->actionfin != NULL)
                              zone->actionfin(form, zone);

                        if (zone->zprec == NULL)
                              return(LASTZONE);
                        else
                              return(PREVZONE);

                  /* case PAGE_DOWN: */
                  case KEY_DOWN:
                  case KEY_TAB:
                        /* si action de fin de zone on l'execute */
                        if (zone->actionfin != NULL)
                              zone->actionfin(form, zone);

                        if (zone->zsuiv == NULL)
                              return(FIRSTZONE);
                        else
                              return(NEXTZONE);

                  default:
                        /* si action de fin de zone on l'execute */
                        if (zone->actionfin != NULL)
                              zone->actionfin(form, zone);

                        return(NEXTZONE);
            }
      }

      /* si il y a de l'aide en ligne alors on sauve le fond de l'ecran dessous */
      if (zone->aidenlig != NULL)
      {
            bufecr =  (chtype *)malloc((JEREDCOLS + 2) * sizeof(chtype));
            if (bufecr != NULL) /* we try to continue to work if bufecr == NULL */
            {
                  /* sauve fond d'ecran */
                  get_txt(0, form->ligaide, (JEREDCOLS - 1), form->ligaide, bufecr);

                  newbuf = (char *)malloc(JEREDCOLS + 2);
                  if (newbuf != NULL)
                  {
                        /* remplit buffer avec message + espaces */
                        strcpy(newbuf, zone->aidenlig);
                        lgaide = strlen(newbuf);
                        memset(newbuf + lgaide, ' ', JEREDCOLS - lgaide);
                        *(newbuf + JEREDCOLS) = '\0';

                        /* affiche l'aide en ligne de la zone courante */
                        put_statligne(0, form->ligaide, newbuf, zone->aidecolor);

                        free(newbuf);
                  }
            }
      }

      /* calcul des coordonnees initiales du curseur */
      lgmax = strlen(ptfmt);
      xmin = form->x + zone->xr;    /* -1 */
      xmax = xmin + lgmax - 1;

      /* si la variable est vide et qu'il y a une valeur par defaut, on */
      /* recopie celle-ci dans variable */
      if ((! *zone->variable) && (zone->defaut != NULL))
            strcpy(zone->variable, zone->defaut);

      /* place un nul en fin de chaine (donc forcement des AsciiZ) */
      *(zone->variable + lgmax) = '\0';

      /* on positionne le curseur en debut de la chaine de saisie */
      pos = 0;
      form->curx = xmin;

      form->cury = form->y + zone->yr;    /* -1 */

      /* sauve etat du curseur */
      cur_stat = allume_curseur(1); /* shows the cursor */

      /* affiche la zone courante */
      maj_zone(form, zone);

      quitte = 0;
      retcode = CANCELBUTTON; /* par defaut */
      while (! quitte)
      {
            /* positionne le curseur et le met a la bonne taille */
            move(form->cury, form->curx);
            refresh();

            /* calcul de la position dans la chaine de saisie */
            pos = (form->curx - xmin);

            /* lit une touche au clavier */
            form->lastkey = zone->lastkey = touche = fread_key();

            switch (touche)
            {
                  case KEY_ESCAPE:
                        /* si action a realiser on la fait */
                        if (zone->actioncar != NULL)
                              zone->actioncar(form, zone);

                        retcode = CANCELBUTTON;
                        quitte = 1;
                        break;

                  case Shift_TAB:
                  case KEY_UP:
                  case KEY_BTAB:
                        if (valide_zone(zone))
                        {
                              /* ce test evite le clignotement de l'aide en ligne sur la premiere zone */
                              if ((form->atoufer & MODEROULEAU) || (zone->zprec != NULL))
                              {
                                    quitte = 1;
                                    retcode = PREVZONE;
                              }
                        }
                        break;

                  case KEY_TAB:
                  case KEY_DOWN:
                        if (valide_zone(zone))
                        {
                              /* ce test evite le clignotement de l'aide en ligne sur la derniere zone */
                              if ((form->atoufer & MODEROULEAU) || (zone->zsuiv != NULL))
                              {
                                    quitte = 1;
                                    retcode = NEXTZONE;
                              }
                        }
                        break;

                  case KEY_PPAGE:
                        if (valide_zone(zone))
                        {
                              quitte = 1;
                              retcode = FIRSTZONE;
                        }
                        break;

                  case KEY_NPAGE:
                        if (valide_zone(zone))
                        {
                              quitte = 1;
                              retcode = LASTZONE;
                        }
                        break;

                  case KEY_RETURN:
                  case KEY_LINEFEED:
                        retcode = OKBUTTON;
                        quitte = 1;
                        break;

                  case KEY_LEFT:
                        if (form->curx > xmin)
                        {
                              form->curx--;
                        }
                        break;

                  case KEY_RIGHT:
                        if (form->curx < xmax && zone->variable[pos])
                        {
                              form->curx++;
                        }
                        break;

                  case KEY_IC:
                        inverse_insert_mode();
                        break;

                  case KEY_BACKSPACE:
                        if (form->curx > xmin)
                        {
                              zone->variable[pos - 1] = '\0';
                              strcat(zone->variable, zone->variable + pos);
                              form->curx--;
                        }
                        else
                        {
                              if (*zone->variable)
                                    strcpy(zone->variable, zone->variable + 1);
                        }
                        /* si action a realiser on la fait */
                        if (zone->actioncar != NULL)
                              zone->actioncar(form, zone);

                        /* affiche la zone courante */
                        maj_zone(form, zone);

                        break;

                  case KEY_DC:
                        if (zone->variable[pos])
                        {
                              strcpy(zone->variable + pos, zone->variable + pos + 1);

                              /* si action a realiser on la fait */
                              if (zone->actioncar != NULL)
                                    zone->actioncar(form, zone);

                              /* affiche la zone courante */
                              maj_zone(form, zone);
                        }
                        break;

                  case KEY_HOME:
                        form->curx = xmin;
                        break;

#ifdef KEY_END
                  case KEY_END:
                        pos = strlen(zone->variable); /* on veut pointer apres la fin de la variable si possible */
                        form->curx = xmin + pos;
                        if (pos == lgmax)
                              form->curx--;
                        break;
#endif      /* KEY_END */

#ifdef Ctrl_END
                  case Ctrl_END:
                        zone->variable[pos] = '\0';

                        /* si action a realiser on la fait */
                        if (zone->actioncar != NULL)
                              zone->actioncar(form, zone);

                        /* affiche la zone courante */
                        maj_zone(form, zone);
                        break;
#endif /* Ctrl_END */

                  default:
                        if ((touche & 0x00ff) >= 0x20)
                        {
                              touche &= 0x00ff;

                              /* si le format demande des majuscules alors */
                              /* on transforme */
                              if (ptfmt[pos] == YESNO || ptfmt[pos] == OUINON || ptfmt[pos] == HHEXA || ptfmt[pos] == HASCNORM)
                                    touche = toupper(touche);

                              if (valide_caractere((char)touche, ptfmt[pos]))
                              {
                                    if (insert_mode == REPLACE)
                                    {
                                          zone->variable[pos] = (char)touche;
                                    }
                                    else
                                    {
                                          strcpy(_tmp, zone->variable + pos);
                                          *(zone->variable + pos) =  (char)touche;
                                          *(zone->variable + pos + 1) = '\0';
                                          if (lgmax > 1)
                                                strcat(zone->variable, _tmp);
                                    }
                                    *(zone->variable + lgmax) = '\0';

                                    /* on passe a la position suivante */
                                    if (form->curx < xmax)
                                    {
                                          form->curx++;
                                    }

                                    /* si action a realiser on la fait */
                                    if (zone->actioncar != NULL)
                                          zone->actioncar(form, zone);

                                    /* affiche la zone courante */
                                    maj_zone(form, zone);
                              }
                        }
            }
      }

      /* reaffiche le fond sous l'aide en ligne */
      if (zone->aidenlig != NULL)
      {
            if (bufecr != NULL)
            {
                  put_txt(0, form->ligaide, JEREDCOLS - 1, form->ligaide, bufecr);
                  free(bufecr);
            }
      }

      allume_curseur(cur_stat);

      /* en cas de zone numerique on cadre a droite en affichage */
      if (*zone->format == NUMERIC && homogene(zone))
            cadre_zone(form, zone, 1);

      /* s'il y a une action a effectuer en sortant de la zone on la lance */
      if (zone->actionfin != NULL)
            zone->actionfin(form, zone);

      return(retcode);
}
/**********************************************************************/

Generated by  Doxygen 1.6.0   Back to index