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

jered.c

/**********************************************************************/
/* JERED.C : Editeur de texte facile d'utilisation                */
/*         Editor of text easy of use                             */
/**********************************************************************/

/*
    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.

    See ENGLISH.DOC section 18.6 for a note on the English translation.
*/

#if HAVE_STRSTR == 0
#error      This program needs a library containing the 'strstr()' function
#endif

#define _JE_TABCOUL_

#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>

#if HAVE_UNISTD_H
#include <unistd.h>
#endif

#if HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif      /* HAVE_SYS_WAIT_H */

#ifndef WEXITSTATUS
#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
#endif      /* WEXISTATUS */

#ifndef WIFEXITED
#define WIFEXITED(stat_val)   (((stat_val) & 255) == 0)
#endif /* WIFEXITED */

#include <signal.h>
#include <pwd.h>
#include <sys/types.h>
#include "jered.h"
#include "formulr.h"
#include "mappable.h"
#include "messages.h"

#define NORMALSAVE      0
#define AUTOSAVE  1

static char *usage =
      "\nJERED v%s (C) 1996-1999 Free Software Foundation\n\nusage:  jered  file1  file2  ...  fileN\n\n"
      "JERED comes with ABSOLUTELY NO WARRANTY\n"
      "This is free software, and you are welcome to redistribute it under certain\n"
      "conditions; refer to the Gnu General Public License for details.\n"
      "\nPlease e-mail bugs to: alet@unice.fr (Jerome Alet)"
      "\nEnglish Doc & Many Ideas from joeh@sugar-river.net (Joseph L. Hartmann)"
      "\nIdeas & Bug fixes from bero@in-trier.de (Bernhard Rosenkraenzer)"
      "\nIdeas & GNU compliant build tree from proff@iki.fi (Antti K. Barck)\n\n";

static char buftmp[SZBUF + 2];      /* buffer de travail */
                        /* buffer of work */

FILELIST *debut_liste;        /* pointeur vers debut de la liste des fichiers */
                        /* pointer toward beginning of the list of the files */

int inputmode = NORMALMODE;   /* indique   si on est en train de saisir un formulaire ou une boite d' alerte */
                        /* indicates if we are typing         a  form   or a   box   of alert */

int autoplay;                 /* indique si on veut jouer automatiquement les macros ou non */
int language;
int insert_mode;        /* mode d'insertion/recouvrement */
                        /* mode of insertion/replacement */
int macro = NOMACRO;          /* etat de la macro eventuelle */
                        /* state of the macro possible ??? */
FILE *fmacro = NULL;          /* pointeur vers le  fichier de macro */
                        /* pointer  to     the file    of macro */
int JEREDCOLS;
int JEREDLINES;
int XMAX;               /* abscisse maxi du texte */
                        /* height <abscissa> maximum of the text */
int YMAX;               /* ordonnee maxi du texte */
                        /* width <ordinate> maximum of the the text */
int tabsize;                  /* valeur des tabulations */
                        /* value  of the tabsize */
int backup;             /* indique si oui ou non on veut une copie de sauvegarde */
                        /* indicate if yes or no  we want one copy  of the backup */
int savetabs;                 /* indicates if we save files with their tabs or with spaces */
int escape_mode;        /* mode escape */
time_t autosave;        /* delay between two autosaves of a file */
int autowordwrap;       /* indicates if autowordwrapping is enabled or not */
int wordwrapbegin;            /* beginning column */
int wordwrapend;        /* end column */
int locking;                  /* locking type for edited files */
chtype couleur[NBCOULEURS];   /* table des couleurs */
                        /* table of  colors */

extern PTFORMU fcherche;      /* the Find & Replace form */
extern PTFORMU fcmdline;      /* The Command Line form */
extern char vcmdline[66];     /* variable in which the command line will be typed in */
extern char vachercher[42];   /* variable in which string to find will be typed in */
extern char vremplacer[42];   /* variable in which replace string will be typed in */
extern char vignorer[2];      /* variable in which ignore case Y/N will be typed in */

void load_profile(void);
void reset_alarm_handler(void); /* prototype declarations */
void stop_alarm_handler(void);
void do_autosave(int sig);
LIGNE *bas(FICHIER *fichier); /* bas <> base , fichier <> file */
LIGNE *haut(FICHIER *fichier); /* haut <> height */
int saisir_ligne(FICHIER *fichier); /* saisir_ligne <> keyboard-entry_line */
void strip(FILE *fpo, char *buffer); /* fpo <> ??? */
void expand(char *texte, char *buffer); /* texte <> text */
int chargement(FILE *fpi, FICHIER *fichier); /* chargement <> loaded */
void dechargement(FILE *fpo, FICHIER *fichier); /* dechargement <> unloading */
int edition(FICHIER *fichier);
void insertion_ligne(FICHIER *fichier); /* insertion_ligne <> insertion_line */
void descendre_page(FICHIER *fichier); /* descendre_page <> go-forward_page  */
void remonter_page(FICHIER *fichier); /* remonter_page <> go-back_page */
void appelle_shell(void); /* appele_shell <> call_shell */
int create_forms(void);
void delete_forms(void);
int execute_commande(FICHIER *fichier); /* execute_command */
void chercher_remplacer(FICHIER *fichier); /* chercher_remplacer <> search_replace */
char *cherche(char *, char *); /* cherche <> search */
int sauvegarder(FICHIER *fichier, int isautosave); /* sauvegarder <> backup */
void liberation_memoire(FICHIER *fichier); /* liberation_memoire <> freed_memory */
int initialise_fichier(FICHIER *fichier); /* initialise_fichier <> initialize_file */
FILELIST *ajoute_fichier_dans_liste(FICHIER *fichier); /* ajoute_fichier_dans_liste <> add_file_to_list */
FILELIST *supprime_fichier_de_liste(FILELIST *courant); /* supprime_fichier_de_liste <> suppress_file_of_list,    courant<> current */
void goto_line(FICHIER *fichier, int num);
void top_of_file(FICHIER *fichier);
void remonter_paragraphe(FICHIER *fichier); /* remonter_paragraphe <> go_back_paragraph */
void descendre_paragraphe(FICHIER *fichier); /* descendre_paragraphe <> go-forward_paragraph */
int empty_line(char *text);
void lock_file(FICHIER *fichier);
void unlock_file(FICHIER *fichier);
/**********************************************************************/
int main(int argc, char **argv)      /* JE starts here */
{
      int retcode = 0;  /* code de retour */
                        /* code of return */

      if ((argc < 2) || ((argc == 2) && ((! strcmp(argv[1], "--version")) || (! strcmp(argv[1], "-h"))
       || (! strcmp(argv[1], "-?")) || (! strcmp(argv[1], "--help")))))
      {
            /*
                  If the user did not type any filename on the command line, or type 'jered -h'
                  or 'jered -?' or 'jered --help' or type 'jered --version', then the copyright notice
                  is written on stdout and the program exits with a code of 0.
            */
            fprintf(stdout, usage, VERSION);
            exit(0);
      }

      /*
            The routine debute_ecran() in the file 'ECRAN.C' is called to do curses
            initialisation.
      */
      debute_ecran(); /* debute_ecran <> begin_screen */

      /* process the user's preferences */
      load_profile();

      move(0, 0);       /* curses call to move the cursor to the top left corner */
      printw("%s", message[MSG_PLEASEWAIT]); /* curses call to display Please wait */
      refresh();        /* really does the output to the screen */

      /* the following line is not needed anymore since we are in raw mode */
      /* signal(SIGINT, SIG_IGN); ignores Ctrl_C */

      /*
            The function create_forms() in the file 'DIALOGUE.C' is called to build all
            the forms needed.
      */
      if (! create_forms())
      {
            /* on passe en mode insertion et on efface l'ecran */
            /* we pass  to mode insertion and we delete the screen */
            insert_mode = INSERT;
            allume_curseur(1); /* allume_curseur <> lighted_cursor */
                           /* petit curseur <==> small cursor */
            escape_mode = 0;   /* we are in normal mode (not escape mode) */

            /* on commence sans    bloc */
            /* we begin    without block */
            demarquer_bloc();

            /* et avec une liste vide */
            /* and with one list  empty */
            debut_liste = NULL; /* debute_liste <> begining_list */
            while ((--argc) && (! retcode))
                  retcode = edite_autre_fichier(argv[argc]); /* edite_autre_fichier <> edit_other_file */
            /*
                  All the files you want to edit are loaded into the memory in a circular list,
                  through the functions edite_autre_fichier(), ajoute_fichier_dans_liste() and
                  initialise_fichier(). This last function reads each file from disk, reading
                  and linking together each line of a file.

                  The function initialise_fichier() sets the correct function for displaying
                  each file according to the extension of the filename. If the filename
                  indicates a C/C++ family file, then the C/C++ colorization function is
                  set in the struct FICHIER of the current file. Otherwise, a display
                  only function is set in this struct. After having read the file,
                  it closes it. Some information is initialised for each file: cursor's
                  position, etc... by the function top_of_file() which is called by
                  initialise_fichier().
            */

            /* efface l'ecran */
            /* erase  the screen */
            clr_scr();

            reset_alarm_handler(); /* for autosave */

            /* si pas d'erreur on a        la liste    circulaire des fichiers et */
            /* if not of error we have got the list    circular   of    files  and */
            /* ils      sont tous charges en   memoire */
            /* they are  all  loaded  into memory */
            if (! retcode)
            {
                  /* si la  liste      des fichiers n'est pas vide */
                  /* if the list    of the files      is    not empty */
                  if (debut_liste != NULL) /* ce      test est normalement en    trop ! */
                                    /* this test is    normally    while too many */
                  {
                        /* debut_liste      pointe sur le    dernier fichier */
                        /* beginning_list points on  the last      file */
                        /* on le fait donc pointer sur le  premier */
                        /* we it make then point   on  the first */
                        debut_liste = debut_liste->suivant;
                        /* begining_list = beginning_list->next; */

                        /* tant que la    liste des    fichiers n'est pas vide */
                        /* while    the list  of the files    is    not empty */
                        /*
                              Now we have got a linked circular list off files, all loaded in memory.
                              The first file in the list is edited by calling the edition() function.
                              If this function returns a code of QUITTE then the memory reserved for this
                              file is freed and the file is deleted from the circular list by the function
                              supprime_fichier_de_liste(). Then we go automatically to the next file
                              to edit it. The memory is freed by the function liberation_memoire().
                              This function begins by de-marking the block eventually marked if it
                              is in the file we want to free. The test is made by bloc_dans_ce_fichier()
                              which can be translated in English by 'block_in_this_file?()'.
                              If the function returns a code of FICHIER_SUIVANT then we go to the
                              next file to edit it but the current file remains in the list.
                              If the functions returns another thing, an error message is displayed.
                        */
                        while (debut_liste != NULL)
                        {
                              retcode = edition(debut_liste->fichier);
                              if (retcode == QUITTE)
                              {
                                    liberation_memoire(debut_liste->fichier);
                                    debut_liste = supprime_fichier_de_liste(debut_liste);
                              }
                              else if (retcode == FICHIERSUIVANT)
                                    debut_liste = debut_liste->suivant;
                              else
                                    erreur(message[MSG_ERROR_UNEXPECTED], NULL);
                        }
                  }
                  retcode = 0; /* no error */
            }
      }
      /*
            When all files were edited and "quit", the list is empty, so we can quit
            the program. The forms are deleted from memory by delete_forms() wich is
            the opposite of create_forms(). The curses mode is stopped by termine_ecran()
            which is the opposite of debute_ecran().
      */
      delete_forms();

      demap_all_keys();

      termine_ecran(); /* terminate_display */

      system("tput init"); /* solves some problems on some terminals */

      exit(retcode);
}
/**********************************************************************/
void load_profile(void)
{
      struct passwd *pw;
      char *envprofilename;
      char profilename[1024];
      char *sysprofilename = "/etc/jeredrc";
      char commande[2048];

      envprofilename = (char *)getenv("JEPROFILE");
      if (envprofilename == NULL)
      {
            /* pas de variable prédéfinie donc on cherche le fichier ~/.jeredrc */
            pw = getpwuid(getuid());
            if (pw != NULL)
                  sprintf(profilename, "%s/.jeredrc", pw->pw_dir);
            else
            {
                  /* erreur bizarre */
                  /* on essaie de charger sans le copier le fichier /etc/jeredrc */
                  strcpy(profilename, sysprofilename);
            }
      }
      else
            strcpy(profilename, envprofilename);

      /* si le profile n'existe pas a l'endroit specifié alors on le crée */
      /* en recopiant le fichier profile système */
      if (access(profilename, R_OK))
      {
            /* on ne recopie que si le fichier à créer n'est pas le profile systeme */
            if (strcmp(sysprofilename, profilename))
            {
                  /* on espere que la commande cp est dans le PATH */
                  sprintf(commande, "cp %s %s", sysprofilename, profilename);
                  system(commande);
            }
      }
      initialise_profile(profilename);
}
/**********************************************************************/
int edite_autre_fichier(char *filename) /* edite_autre_fichier <> edit_other_file */
{
      int retcode = -1;       /* code de retour */
                              /* code of return */
      FICHIER *fichier_courant;     /* pointeur sur fichier courant */
                              /* pointer  at    file  current */
      struct stat bufstat;    /* to retreive current attributes for the file */
      int status; /* indicator */

      /* if the file is a directory we skip it */
      status = stat(filename, &bufstat);
      if ((! status) && S_ISDIR(bufstat.st_mode))
            return(0);

      /* alloue    memoire pour fichier courant */
      /* allocates memory  for  file        current */
      fichier_courant = (FICHIER *)malloc(sizeof(FICHIER));
      if (fichier_courant != NULL)
      {
            /* on l'ajoute dans la  liste */
            /* we add      in   the list */
            debut_liste = ajoute_fichier_dans_liste(fichier_courant); /* ajoute_fichier_dans_liste <> add_file_in_list */
            if (debut_liste != NULL)
            {
                  fichier_courant->filename = filename;

                  /* we save the actual protection information for this file */
                  if (status)
                  {
                        /* if the file doesn't exist */
                        fichier_courant->statmode = umask(0);
                        umask(fichier_courant->statmode);
                        fichier_courant->statmode ^= 0777;
                  }
                  else
                        fichier_courant->statmode = bufstat.st_mode;

                  retcode = initialise_fichier(fichier_courant);
            }
            else
                  erreur(message[MSG_ERROR_MEMORY], NULL);
      }
      else
            erreur(message[MSG_ERROR_MEMORY], NULL);

      return(retcode);
}
/**********************************************************************/
FILELIST *supprime_fichier_de_liste(FILELIST *courant) /* suppres_file_from-the_list */
{
      FILELIST *precedent;

      if (courant->suivant == courant)    /* dernier element de la liste ? */
                                    /* final   element of the list ? */
      {
            /* on le libere */
            /* we the free */
            free(courant);

            /* et on indique que la fin de la liste est atteinte */
            /* and we indicate that the end of the list  is  reached */
            return(NULL);
      }
      else
      {
            /* cherche l'element   precedent  le  courant dans la liste */
            /* search  the element preceeding the current in   the list */
            for (precedent = courant; precedent->suivant != courant; precedent = precedent->suivant) ;

            /* on casse    la  liaison     vers    le  courant */
            /* we break the connecting  towards the current */
            precedent->suivant = courant->suivant;

            /* on libere l'entree courante */
            /* we free   the entry current */
            free(courant);

            /* et  on renvoie   un pointeur vers   l'  element suivant dans la  liste */
            /* and we send back a  pointer      toward the element next    in the list */
            return(precedent->suivant); /* previous->next */
      }
}
/**********************************************************************/
FILELIST *ajoute_fichier_dans_liste(FICHIER *fichier) /* add_file_in_list(FICHIER *file) */
{
      FILELIST *nouveau_debut; /* new_beginning */

      nouveau_debut = (FILELIST *)malloc(sizeof(FILELIST));
      if (nouveau_debut != NULL)
      {
            /* si liste non vide */
            /* if list  not empty */
            if (debut_liste != NULL)
            {
                  nouveau_debut->fichier = fichier;
                  nouveau_debut->suivant = debut_liste->suivant;
                  debut_liste->suivant = nouveau_debut;
                  return(debut_liste);
            }
            else
            {
                  nouveau_debut->fichier = fichier;
                  nouveau_debut->suivant = nouveau_debut;
            }
      }
      return(nouveau_debut);
}
/**********************************************************************/
void liberation_memoire(FICHIER *fichier) /* freeing_memory(FICHIER *file) */
{
      LIGNE *courante;  /* ptr sur ligne courante */
                /* pointer on  line  current */
      LIGNE *suivante;  /* ptr sur ligne suivante */
                /* pointer on  line  next */

      /* si le  bloc    est dans le  fichier que  l'on        libere */
      /* if the block is  in   the file    that someone frees */
      /* alors on demarque le  bloc  pour ne pas avoir */
      /* then      we unmark   the block for  not        having */
      /* un bloc pointant vers des lignes inexistantes */
      /* a  block pointing toward the lines  non-existant */
      if (bloc_dans_ce_fichier(fichier))  /* block_in_this_file */
            demarquer_bloc();       /* unmark_block */

      /*  (current  = file->   first->   next;     current  != file->next;        current =  next) */
      for (courante = fichier->premiere->suivante; courante != fichier->derniere; courante = suivante)
      {
            /* libere la  ligne courante */
            /* free       the line  current */
            suivante = courante->suivante;      /* sauve pointeur vers   suivante */
            /* next      = current-> next;         save      pointer  toward next */
            if (courante->texte != NULL)
                  free(courante->texte);  /* libere texte de la ligne */
                                    /* free       text      of the line */
            free(courante); /* libere la  ligne elle-meme */
                        /* free       the line  itself */
      }
      free(fichier->premiere);
      free(fichier->derniere);

      unlock_file(fichier);

      free(fichier);
}
/**********************************************************************/
int sauvegarder(FICHIER *fichier, int isautosave) /* backup(FICHIER *file, int isautosave) */
{
      char tmp[256];          /* pour nom  de       fichier temporaire */
                        /* for      name of the file    temporary */
      FILE *fpo;        /* id fichier temporaire */
                        /* id file    temporary */
      FILE *fpi;        /* id du fichier que l' on    edite */
                        /* id of file      which      someone edits */
      char *ptl;        /* pointeur vers    ligne */
                        /* pointer  towards line */
      char *extension;  /* extension for backup file */
      char filename[256];     /* file name to save the file */

      /* si le  fichier vient d' etre      sauve on    ne    fait rien */
      /* if the file      comes of being saved we do not make nothing */
      if (fichier->saved)
            return(0);

      if (isautosave == AUTOSAVE)
      {
            /* displays the message for autosave */
            /* it will not disappear until a key is pressed */
            /* so we know that the file was autosaved */
            strcpy(tmp, message[MSG_AUTOSAVE]);
      }
      else
      {
            /* affiche le  message comme quoi la sauvegarde est en cours */
            /* display the message like  what the backup    is  being done */
            strcpy(tmp, message[MSG_SAVING]);
      }
      beautify_filename(tmp, fichier->filename);
      put_statligne(0, (JEREDLINES - 1), tmp, couleur[COULEUR_AIDE]);

      /* si copie de sauvegarde on essaie de l'effectuer */
      if (backup == OUI)
      {
            if (isautosave == AUTOSAVE)
                  extension = "bak~";    /* backup ext for automatic save */
            else
                  extension = "bak";     /* normal backup ext */

            /* we must temporarily unlock the file */
            /* to copy it, then we relock it immediately */
            unlock_file(fichier);
            sprintf(tmp, "cp %s %s.%s 1>/dev/null 2>/dev/null", fichier->filename, fichier->filename, extension);
            system(tmp);
            lock_file(fichier);
      }

      /* cree un nom de fichier temporaire */
      *tmp = '\0'; /* a little bug correction */
      if (tmpnam(tmp) == NULL)
            strcpy(tmp, "jetempje.jet");

      /* maintenant on cree le fichier */
      fpo = fopen(tmp, "w+t");
      if (fpo == NULL)
      {
            erreur(message[MSG_ERROR_CREATING], tmp);
            return(-1);
      }
      else
      {
            /* on sauve le texte dans le fichier */
            dechargement(fpo, fichier);

            /* on se replace en debut de fichier temporaire */
            rewind(fpo);

            /* on ne peut pas renommer le fichier temporaire */
            /* sinon on prend les droits de l'utilisateur actuel */
            /* il faut donc le copier dans le fichier que l'on edite */
            /* apres l'avoir remis a zero (wt) */
            strcpy(filename, fichier->filename);
            if (isautosave == AUTOSAVE)
                  strcat(filename, "~");  /* indicates an automatically saved file */
            else
                  unlock_file(fichier);   /* we must unlock it temporarily */

            fpi = fopen(filename, "w+t");
            if (fpi != NULL)
            {
                  while ((ptl = fgets(buftmp, SZBUF, fpo)) != NULL)
                        fputs(buftmp, fpi);

                  /* on ferme le fichier d'entree */
                  fclose(fpi);

                  /* on ferme le fichier temporaire */
                  fclose(fpo);

                  /* we must relock the file immediately */
                  if (isautosave == NORMALSAVE)
                        lock_file(fichier);

                  /* et comme tout est ok: on l'efface */
                  if (unlink(tmp))
                        erreur(message[MSG_ERROR_UNLINKING], tmp);

                  /* indicates that the file has been saved */
                  /* only if it is not an automatic save */
                  if (isautosave == NORMALSAVE)
                        fichier->saved = 1;

                  return(0);
            }
            else
            {
                  /* on ferme le fichier temporaire */
                  /* mais on ne l'efface pas !!! */
                  fclose(fpo);

                  erreur(message[MSG_ERROR_ACCESSING], filename);
                  return(-1);
            }
      }
}
/**********************************************************************/
void lock_file(FICHIER *fichier)
{
      int mask;   /* to mask some bits */

      /* we set file locking mode according to the */
      /* locking variable in the profile file */
      mask = fichier->statmode & (~0777);
      if (locking == LOCK_STRICT)
            chmod(fichier->filename, mask);
      else if (locking == LOCK_READONLY)
            chmod(fichier->filename, (mask | (fichier->statmode & 0555)));
}
/**********************************************************************/
void unlock_file(FICHIER *fichier)
{
      /* we reset the original protection of this file */
      if (locking != LOCK_NONE)
            chmod(fichier->filename, fichier->statmode);
}
/**********************************************************************/
int initialise_fichier(FICHIER *fichier)
{
      int retcode = 0;  /* par defaut pas d'erreur */
      FILE *fpi;        /* pointeur sur fichier d'entree */

      fichier->first = 1;     /* premier passage dans ce fichier */
      fichier->saved = 1;     /* il n'y a pas encore eu de modifications */

      /* si c'est un fichier de type C/C++ */
      /* on colorise, sinon non */
      if (cfamily(fichier->filename))
            fichier->affiche_ligne = put_ligne;
      else
            fichier->affiche_ligne = print_ligne;

      /* on ouvre le fichier mais on ne tient pas compte de l'echec */
      /* car on peut vouloir editer un fichier qui n'existe pas encore */
      fpi = fopen(fichier->filename, "rt");

      /* alloue la premiere et la derniere ligne */
      fichier->premiere = (LIGNE *)malloc(sizeof(LIGNE));
      fichier->derniere = (LIGNE *)malloc(sizeof(LIGNE));
      if ((fichier->premiere == NULL) || (fichier->derniere == NULL))
      {
            erreur(message[MSG_ERROR_MEMORY], NULL);
            retcode = -1;
      }
      else
      {
            fichier->premiere->suivante = fichier->derniere;
            fichier->derniere->precedente = fichier->premiere;
            fichier->premiere->precedente = fichier->derniere->suivante = NULL;
            fichier->premiere->texte = message[MSG_TOF];
            fichier->derniere->texte = message[MSG_EOF];
            fichier->premiere->debut_marque = fichier->derniere->debut_marque = NOTMARKED;
            fichier->premiere->fin_marque = fichier->derniere->fin_marque = NOTMARKED;

            if (chargement(fpi, fichier))
            {
                  erreur(message[MSG_ERROR_READING], fichier->filename);
                  retcode = -1;
            }
            else
            {
                  top_of_file(fichier);
                  retcode = 0;      /* chargement OK */
            }
            if (fpi != NULL)
            {
                  fclose(fpi);      /* ferme le fichier d'entree */

                  lock_file(fichier);
            }
      }
      return(retcode);
}
/**********************************************************************/
void top_of_file(FICHIER *fichier)
{
      fichier->debut_ecran = fichier->premiere;
      fichier->courante = fichier->premiere->suivante;
      fichier->numcourante = 1;
      fichier->numdebecr = 0;
      fichier->ligne = YMIN + 1;
      fichier->colonne = 0;
      fichier->premier_caractere = 0;
}
/**********************************************************************/
int edition(FICHIER *fichier)
{
      int quitte;       /* indicateur de sortie */
      int saisie;       /* indic de sortie de saisie de ligne */

      /* we ensure that the cursor is shown on the screen */
      allume_curseur(1);

      affiche_ecran(fichier, 0, NULL);
      quitte = 0;
      while (! quitte)
      {
            saisie = saisir_ligne(fichier);
            switch (saisie)
            {
                  case COMMANDE:
                        quitte = execute_commande(fichier);
                        break;

                  case CHERCHE:
                        chercher_remplacer(fichier);
                        break;

                  case QUITTE:
                        quitte = QUITTE;
                        break;

                  case FICHIERSUIVANT:
                        quitte = FICHIERSUIVANT;
                        break;

                  case SAUVE:
                        sauvegarder(fichier, NORMALSAVE);
                        break;

                  case SHELL:
                        appelle_shell();
                        break;

                  case REMONTE_PAGE:
                        remonter_page(fichier);
                        break;

                  case DESCEND_PAGE:
                        descendre_page(fichier);
                        break;

                  case REMONTE_LIGNE:
                        remonter_ligne(fichier);
                        break;

                  case DESCEND_LIGNE:
                        descendre_ligne(fichier);
                        break;

                  case REMONTE_PARAGRAPHE:
                        remonter_paragraphe(fichier);
                        break;

                  case DESCEND_PARAGRAPHE:
                        descendre_paragraphe(fichier);
                        break;

                  case INSERE_LIGNE:
                        insertion_ligne(fichier);
                        fichier->saved = 0; /* le fichier a ete modifie */
                        break;

                  case DETRUIT_LIGNE:
                        destruction_ligne(fichier);
                        fichier->saved = 0; /* le fichier a ete modifie */
                        break;

                  case DEMARQUER_BLOC:
                        demarquer_bloc();
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case MARQUER_BLOC:
                        marquer_bloc(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case COPIER_BLOC:
                        copier_bloc(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case DEPLACER_BLOC:
                        deplacer_bloc(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case SUPPRIMER_BLOC:
                        supprimer_bloc(ASKCONFIRMATION);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case MAJUSCULE_BLOC:
                        uppercaseblock(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case MINUSCULE_BLOC:
                        lowercaseblock(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case ALIGNE_BLOC:
                        alignblock(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  case WRAP_BLOC:
                        wrapblock(fichier);
                        affiche_ecran(fichier, 0, NULL);
                        break;

                  default:
                        beep();
                        erreur(message[MSG_ERROR_FUNKNOWN], NULL);
                        break;
            }
      }
      return(quitte);
}
/**********************************************************************/
void remonter_paragraphe(FICHIER *fichier)
{
      set_refresh(OFF);
      while (remonter_ligne(fichier) && (! empty_line(fichier->courante->texte))) ;
      set_refresh(ON);
      refresh();
}
/**********************************************************************/
void descendre_paragraphe(FICHIER *fichier)
{
      set_refresh(OFF);
      while (descendre_ligne(fichier) && (! empty_line(fichier->courante->texte))) ;
      set_refresh(ON);
      refresh();
}
/**********************************************************************/
int empty_line(char *text)    /* is the line empty ? */
{
      while (isspace(*text))  /* while there is a space char */
            text++;           /* according to isspace's man page, '\0' is not a space char */

      if (*text)
            return(0);  /* the line is not empty */
      else
            return(1);  /* the line is empty (only space chars) */
}
/**********************************************************************/
void chercher_remplacer(FICHIER *fichier)
{
      static int first = 1;   /* premier passage */
      char *ptrouve;          /* pointeur sur code trouve */
      char *ptr;        /* pointeur pour la recherche */
      int touche;       /* code de retour de la question */
      int fini;         /* indique la fin de la recherche */
      char buf[SZBUF + 2];    /* pour remplacements */
      char *pts;        /* pointeur source pour remplacement */
      char *ptd;        /* pointeur destination pour remplacement */
      int diff;         /* offset du motif trouve dans la ligne */
      int tous;         /* pour tout remplacer */
      FICHIER sauvefichier;   /* sauve les infos sur le fichier courant */

      sauvefichier = *fichier;
      if (first)
      {
            raz_zones(fcherche);
            first = 0;
      }
      if (! *vignorer)
            strcpy(vignorer, message[MSG_N]);

       /* la touche escape vide les champs de saisie */
       /* utile si on a remplace une chaine par un espace */
       /* si l'on ne s'en souvient plus la fois suivante */
       /* ca peut faire quelque chose d'indesirable */
       set_esc_clear(ON);

      if (lire_formulaire_simple(fcherche) == OKBUTTON)
      {
            set_refresh(OFF);
            tous = 0;
            fini = 0;
            while ((fichier->courante->suivante != NULL) && (! fini))
            {
                  ptr = fichier->courante->texte;
                  while (((ptrouve = cherche(ptr, vachercher)) != NULL) && (! fini))
                  {
                        /* affiche l'ecran et place le curseur sous la chaine trouvee */
                        diff = (int)(ptrouve - fichier->courante->texte);
                        fichier->premier_caractere = (diff / JEREDCOLS) * JEREDCOLS;
                        fichier->colonne = (diff % JEREDCOLS);
                        fichier->affiche_ligne(fichier->courante, fichier->ligne, fichier->courante->texte, fichier->premier_caractere);
                        affiche_ecran(fichier, fichier->premier_caractere, fichier->courante);
                        affiche_status_line(fichier, diff + 1);
                        move(fichier->ligne, fichier->colonne);
                        refresh();
                        set_refresh(OFF);

                        sauvefichier = *fichier;

                        ptr = ptrouve + strlen(vachercher);

                        touche = 0; /* evite warning */
                        if (! tous)
                        {
                              touche = askquestion();
                              if (touche == 'A')
                                    tous = 1;
                        }

                        if (tous || (touche == 'R'))
                        {
                              /* si pas le test sur *vremplacer et qu'on appuie sur 'T' */
                              /* alors toutes les occurences sont supprimees */
                              /* or, on n'autorise les suppressions que */
                              /* si l'on appuie sur 'R' car sur 'T' */
                              /* c'est trop dangereux !!! */
                              if ((*vremplacer && tous) || (touche == 'R'))
                              {
                                    ptd = buf;
                                    pts = fichier->courante->texte;
                                    while (pts < ptrouve)
                                          *ptd++ = *pts++;
                                    strcpy(ptd, vremplacer);
                                    strcat(ptd, ptr);

                                    realloue_texte(fichier->courante, buf);
                                    ptr = fichier->courante->texte + diff + strlen(vremplacer);

                                    /* reaffiche la ligne modifiee */
                                    fichier->affiche_ligne(fichier->courante, fichier->ligne, fichier->courante->texte, fichier->premier_caractere);
                                    refresh(); /* valide reaffichage */

                                    /* le fichier a ete modifie */
                                    /* on l'indique pour les 2 car s'il n'y a */
                                    /* qu'une seule occurence, le fichier n'est pas */
                                    /* marque comme modifie */
                                    fichier->saved = sauvefichier.saved = 0;
                              }
                        }
                        else if (touche != 'C')
                              fini = 1;
                  }
                  descendre_ligne(fichier);
            }
      }

       /* retablit le fonctionnement normal de Escape dans un formulaire */
       set_esc_clear(OFF);

      *fichier = sauvefichier;
      affiche_ecran(fichier, 0, NULL);
}
/**********************************************************************/
char *cherche(char *ligne, char *motif)
{
      char sauvlig[SZBUF + 2];
      char sauvmotif[80];
      char *ptr;
      char ignorecase;

      strcpy(sauvlig, ligne);
      strcpy(sauvmotif, motif);

      /* we must translate the ignore case choice into English */
      switch (language)
      {
            case FINNISH:
                  if (*vignorer == 'E')
                        ignorecase = 'N';
                  else
                        ignorecase = 'N';
                  break;

            case RUSSIAN:
                  if (*vignorer == 'î')
                        ignorecase = 'N';
                  else
                        ignorecase = 'N';
                  break;

                  /* in ENGLISH, FRENCH, SPANISH and GERMAN, the NO answers all */
                  /* begin with a N : NO, NON, NO, NEIN */
                  /* so we have nothing to do */
            case GERMAN:
            case FRENCH:
            case SPANISH:
            case ENGLISH:
            default:
                  ignorecase = *vignorer;
                  break;
      }

      if (ignorecase != 'N')   /* si on doit ignorer les MAJ/min */
      {
            for (ptr = sauvlig; *ptr; ptr++)
                  *ptr = (char)toupper((unsigned int)(unsigned char)*ptr);
            for (ptr = sauvmotif; *ptr; ptr++)
                  *ptr = (char)toupper((unsigned int)(unsigned char)*ptr);
      }

      ptr = strstr(sauvlig, sauvmotif);
      if (ptr != NULL)
            ptr = ligne + (int)(ptr - sauvlig);
      return(ptr);
}
/**********************************************************************/
void goto_line(FICHIER *fichier, int num)
{
      top_of_file(fichier);   /* on se place en debut de fichier */

      set_refresh(OFF);
      while ((fichier->courante->suivante != NULL) && (fichier->numcourante != num))
            descendre_ligne(fichier);
      affiche_ecran(fichier, 0, NULL);
}
/**********************************************************************/
void set_default_macro(char *macroname)
{
      char cmd[256];          /* command line */
      char macrofname[256];   /* file name for the macro */
      char *macrosdir;  /* macros directory */
      int found = 0;          /* indicates if we have found the macro */

      if (*macroname)
      {
            if (access(macroname, R_OK)) /* does the macro exist ? */
            {
                  macrosdir = getenv("JEMACROS");
                  if (macrosdir != NULL)  /* does the variable JEMACROS exist ? */
                  {
                        /* Yes, so we try in the JEMACROS directory */
                        strcpy(macrofname, macrosdir);
                        strcat(macrofname, "/");
                        strcat(macrofname, macroname);
                        if (! access(macrofname, R_OK))
                              found = 1;
                  }
            }
            else
            {
                  strcpy(macrofname, macroname); /* it exists */
                  found = 1;
            }

            if (found)
            {
                  sprintf(cmd, "cp %s %s >/dev/null 2>/dev/null", macrofname, MACROFILE);
                  system(cmd); /* copy the macro to the default macro */
            }
            else
                  erreur(message[MSG_MACRO_NOTFOUND], macroname);
      }
}
/**********************************************************************/
int execute_commande(FICHIER *fichier)
{
      int num;
      char *fname;
      static int first = 1;   /* on ne remet la zone a zero qu'au premier passage */

      if (first)
      {
            /* la prochaine fois pas de remise a zero */
            /* pour eviter de taper 2 fois la meme commande */
            raz_zones(fcmdline);
            first = 0;
      }

      if (lire_formulaire_simple(fcmdline) == OKBUTTON)
      {
            /* est-ce une commande interne ? */
            if (*vcmdline == ':')
            {
                  if (! strncasecmp(vcmdline + 1, "macro ", 6))
                  {
                        /* copie la macro demandee sur la macro par defaut */
                        set_default_macro(vcmdline + 7);
                  }
                  else if (! strncasecmp(vcmdline + 1, "edit ", 5))
                  {
                        if (*(vcmdline + 6))
                        {
                              /* il n'y aura jamais de free() pour le malloc() suivant ! */
                              fname = (char *)malloc(strlen(vcmdline + 6) + 1);
                              if (fname != NULL)
                              {
                                    strcpy(fname, vcmdline + 6);
                                    edite_autre_fichier(fname);
                                    return(FICHIERSUIVANT);
                              }
                              else
                                    erreur(message[MSG_ERROR_MEMORY], NULL);
                        }
                  }
                  else if (! strcasecmp(vcmdline + 1, "help"))
                  {
                        return(function_help(fichier, NULL, 0));
                  }
                  else if (isdigit(*(vcmdline + 1)))
                  {
                        num = atoi(vcmdline + 1);
                        if (num >= 1)
                              goto_line(fichier, num);
                  }
                  else
                  {
                        test_config(vcmdline + 1); /* try to handle profile variables */
                        function_redraw(fichier, NULL, 0); /* in case we changed a color */
                  }
            }
            else
                  launch_external_command(vcmdline, ATTENDSTOUCHE);
      }
      return(0);
}
/**********************************************************************/
void appelle_shell(void)
{
      chtype *buffer;
      pid_t pid;
      int status;
      char *shell;
      char *ps1;
      char sauvps1[80];
      char newps1[80];

      /* we must stop the autosave function */
      /* to not disturb display within the shell */
      stop_alarm_handler();

      buffer = sauve_ecran();
      if (buffer != NULL)
      {
            pid = fork();
            if (pid == -1)
            {
                  /* rien ne prouve que cette boite d'alerte fonctionne */
                  /* mais rien ne prouve le contraire non plus */
                  erreur(message[MSG_ERROR_FORKING], NULL);
            }
            else if (! pid)
            {
                  if ((shell = (char *)getenv("SHELL")) == NULL)
                        shell = "/bin/sh";

                  if ((ps1 = (char *)getenv("PS1")) == NULL)
                        strcpy(sauvps1, "$");
                  else
                        strcpy(sauvps1, ps1);

                  strcpy(newps1, "PS1=<< jered >> ");
                  strcat(newps1, sauvps1);
#if HAVE_PUTENV
                  putenv(newps1);
#endif
                  move(0, 0);
                  printw("%s", message[MSG_TYPE_EXIT]);
                  refresh();

                  execl(shell, shell, NULL);

                  /* les lignes suivantes ne sont normalement jamais atteintes */
                  /* sauf si l'exec lui meme echoue */
                  strcpy(newps1, "PS1=");
                  strcat(newps1, sauvps1);
#if HAVE_PUTENV
                  putenv(newps1);
#endif

                  move(0, 0);
                  printw("%s", message[MSG_ERROR_EXECING]);
                  refresh();

                  exit(0);
            }
            else
                  wait(&status);

            restaure_ecran(buffer, NATTENDSPAS);

            if (! WIFEXITED(status))
                  erreur(message[MSG_ERROR_RUNNING], NULL);
      }

      /* we can re-activate the autosave function */
      reset_alarm_handler();
}
/**********************************************************************/
void remonter_page(FICHIER *fichier)
{
      int i;

      set_refresh(OFF);
      for (i = 0; i < (YMAX - YMIN); i++)
            remonter_ligne(fichier);
      set_refresh(ON);
      refresh();
}
/**********************************************************************/
void descendre_page(FICHIER *fichier)
{
      int i;

      set_refresh(OFF);
      for (i = 0; i < (YMAX - YMIN); i++)
            descendre_ligne(fichier);
      set_refresh(ON);
      refresh();
}
/**********************************************************************/
int remonter_ligne(FICHIER *fichier)
{
      LIGNE *nouveau;         /* pour calcul nouveau debut d'ecran */


      if (fichier->courante->precedente != NULL)
      {
            fichier->numcourante--;
            fichier->courante = fichier->courante->precedente;
            nouveau = haut(fichier);
            if (nouveau != fichier->debut_ecran)
            {
                  fichier->debut_ecran = nouveau;
                  fichier->affiche_ligne(fichier->courante, YMIN, fichier->courante->texte, 0);
            }
            return(1);
      }
      return(0);
}
/**********************************************************************/
int descendre_ligne(FICHIER *fichier)
{
      LIGNE *nouveau;         /* pour calcul nouveau debut d'ecran */


      if (fichier->courante->suivante != NULL)
      {
            fichier->numcourante++;
            fichier->courante = fichier->courante->suivante;
            nouveau = bas(fichier);
            if (nouveau != fichier->debut_ecran)
            {
                  fichier->debut_ecran = nouveau;
                  fichier->affiche_ligne(fichier->courante, YMAX, fichier->courante->texte, 0);
            }
            return(1);
      }
      return(0);
}
/**********************************************************************/
void insertion_ligne(FICHIER *fichier)
{
      LIGNE *nouvelle;  /* pour calcul nouvelle ligne courante */


      if (fichier->courante->suivante == NULL) /* on est sur la derniere ligne */
            beep();
      else
      {
            fichier->numcourante++;

            fichier->debut_ecran = bas(fichier);

            nouvelle = insere_ligne(fichier, NULL, fichier->courante, fichier->courante->suivante);
            if (nouvelle == NULL)
                  beep();
            else
            {
                  fichier->courante = nouvelle;
                  affiche_ecran(fichier, 0, NULL);
            }
      }
}
/**********************************************************************/
void destruction_ligne(FICHIER *fichier)
{
      LIGNE *nouvelle;  /* pour calcul nouvelle ligne courante */

      /* si premiere ou derniere ligne */
      if ((fichier->courante->precedente == NULL) || (fichier->courante->suivante == NULL))
            beep();
      else
      {
            nouvelle = fichier->courante->suivante;
            if (fichier->debut_ecran == fichier->courante)
            {
                  fichier->debut_ecran = nouvelle;
            }
            supprime_ligne(fichier, fichier->courante);
            fichier->courante = nouvelle;
            affiche_ecran(fichier, 0, NULL);
      }
}
/**********************************************************************/
void affiche_ecran(FICHIER *fichier, int decalage, LIGNE *ignore)
{
      int i;            /* compteur */
      LIGNE *debut;     /* pointeur vers la ligne de debut de l'ecran */
      int sauvex; /* pour sauver l'abscisse */
      int sauvey; /* pour sauver l'ordonnee */

      set_refresh(OFF);
      getyx(stdscr, sauvey, sauvex);
      for (debut = fichier->debut_ecran, i = YMIN; i <= YMAX; i++)
      {
            move(i, XMIN);
            if (debut->texte != NULL)
            {
                  if ((ignore == NULL) || (debut != ignore))
                        fichier->affiche_ligne(debut, i, debut->texte, decalage);
            }
            if (debut->suivante == NULL && (i < YMAX))    /* derniere ligne */
            {
                  move(i + 1, XMIN);
                  clrtobot();
                  move(i, XMIN);
                  break;
            }
            else
            {
                  debut = debut->suivante;
            }
      }
      move(sauvey, sauvex);
      set_refresh(ON);
      refresh();
}
/**********************************************************************/
LIGNE *bas(FICHIER *fichier)
{
      LIGNE *debecr;

      debecr = fichier->debut_ecran;
      if (fichier->ligne < YMAX)
            fichier->ligne++;
      else
      {
            if (debecr->suivante == NULL)
                  beep();
            else
            {
                  debecr = debecr->suivante;
                  fichier->numdebecr++;

                  scrollup(YMIN, YMAX);
            }
      }
      return(debecr);
}
/**********************************************************************/
LIGNE *haut(FICHIER *fichier)
{
      LIGNE *debecr;

      debecr = fichier->debut_ecran;
      if (fichier->ligne > YMIN)
            fichier->ligne--;
      else
      {
            if (debecr->precedente == NULL)
                  beep();
            else
            {
                  debecr = debecr->precedente;
                  fichier->numdebecr--;

                  scrolldown(YMIN, YMAX);
            }
      }
      return(debecr);
}
/**********************************************************************/
void supprime_ligne(FICHIER *fichier, LIGNE *courante)
{
      if (courante != NULL)
      {
            /* bug correction, 24 August 1997 */
            test_and_correct_block(fichier);

            courante->precedente->suivante = courante->suivante;
            courante->suivante->precedente = courante->precedente;
            if (courante->texte != NULL)
                  free(courante->texte);
            free(courante);

            fichier->nblignes--;
      }
}
/**********************************************************************/
int chargement(FILE *fpi, FICHIER *fichier)
{
      int retcode;            /* code de retour */
      LIGNE *courante;  /* ligne courante */
      char *ptr;        /* pointeur dans buftmp */

      retcode = 0;
      fichier->nblignes = 0;
      if (fpi != NULL)
      {
            courante = fichier->premiere;
            while (fgets(buftmp, SZBUF, fpi) != NULL)
            {
                  ptr = buftmp + strlen(buftmp) - 1;
                  while (ptr >= buftmp)
                  {
                        if ((*ptr == '\n') || (*ptr == '\r'))
                              *ptr-- = '\0';
                        else
                              break;
                  }

                  if ((courante = insere_ligne(fichier, buftmp, courante, fichier->derniere)) == NULL)
                  {
                        retcode = -3;
                        break;
                  }
            }
      }
      if (! fichier->nblignes)
      {
            if ((courante = insere_ligne(fichier, NULL, fichier->premiere, fichier->derniere)) == NULL)
                  retcode = -3;
      }
      return(retcode);
}
/**********************************************************************/
void dechargement(FILE *fpo, FICHIER *fichier)
{
      LIGNE *courante;  /* ptr sur ligne courante */

      for (courante = fichier->premiere->suivante; courante != fichier->derniere; courante = courante->suivante)
      {
            /* ecrit ligne courante dans fichier */
            if (courante->texte != NULL)
                  strip(fpo, courante->texte);
      }
}
/**********************************************************************/
void stop_alarm_handler(void)
{
      signal(SIGALRM, SIG_DFL); /* reset the signal handler to its default behaviour */
      alarm(0);           /* we don't want any other signal */
}
/**********************************************************************/
void reset_alarm_handler(void)
{
      signal(SIGALRM, do_autosave); /* reset the signal handler to the do_autosave function */
      alarm(autosave);        /* we want a signal in AUTOSAVE seconds */
}
/**********************************************************************/
void do_autosave(int sig)
{
      FILELIST *plist;

      /* we have received the SIGALRM signal, which indicates */
      /* that the timer has reached the AUTOSAVE value, so */
      /* we follow the list of files loaded into the memory */
      /* to save each not yes saved file */
      plist = debut_liste;
      do
      {
            sauvegarder(plist->fichier, AUTOSAVE); /* save the file */
            plist = plist->suivant;              /* skip to next file */
      }
      while (plist != debut_liste); /* is the circular list finished ? */

      reset_alarm_handler();
}
/**********************************************************************/
int saisir_ligne(FICHIER *fichier)
{
      int quitte;       /* indicateur de sortie */
      int touche;       /* touche lue au clavier */
      int pos;          /* position caractere courant */
      char buffer[SZBUF + 2]; /* buffer de travail */
      char *ptr;        /* pointeur pour comptage d'espaces */
      int i;                  /* compteur */
      static int decalage = 0; /* decalage a faire vers la droite */

      if (fichier->courante->texte != NULL)
            strcpy(buffer, fichier->courante->texte);
      else
      {
            memset(buffer, ' ', decalage);
            *(buffer + decalage) = '\0';
      }

      fichier->premier_caractere = 0;

      i = strlen(buffer);
      if (fichier->colonne <= i)
      {
            pos = decalage;
            if (fichier->colonne < pos)
                  i = pos;
            else
                  i = fichier->colonne;
      }

      /* on se place sur le premier caractere significatif */
      /* trouver quelque chose de mieux pour ce qui depasse l'ecran */
      set_refresh(OFF);
      fichier->colonne = 0;
      while (i > 0)
      {
            droite(fichier, buffer, 0, 0);
            i--;
      }
      fichier->affiche_ligne(fichier->courante, fichier->ligne, buffer, fichier->premier_caractere);
      if ((fichier->colonne + fichier->premier_caractere) > (JEREDCOLS - 1))
            affiche_ecran(fichier, fichier->premier_caractere, fichier->courante);
      set_refresh(ON);
      refresh();

      quitte = 0;
      while (! quitte)
      {
            set_refresh(OFF);
            pos = fichier->colonne + fichier->premier_caractere;
            affiche_status_line(fichier, pos + 1);
            affiche_help_line();
            set_refresh(ON);
            move(fichier->ligne, fichier->colonne);
            refresh();

            touche = fread_key();
            switch (touche)
            {
                  case KEY_ESCAPE:
                        quitte = handle_escape_key(fichier, buffer, pos);
                        break;

                  default:
                        if (ismapped(touche))
                              quitte = handle_normal_key(touche, fichier, buffer, pos);
                        else
                        {
                              if ((macro == RECORDING) && (fmacro != NULL))
                                    fprintf(fmacro, "TEXT_%c\n", (touche & 0x00ff));

                              quitte = handle_normal_char(touche, fichier, buffer, pos);
                        }
                        break;
            }
      }

      for (ptr = buffer; *ptr == ' '; ptr++) ;
      decalage = (ptr - buffer);

      if ((fichier->courante->precedente != NULL) && (fichier->courante->suivante != NULL))
            realloue_texte(fichier->courante, buffer);
      fichier->affiche_ligne(fichier->courante, fichier->ligne, fichier->courante->texte, 0);
      affiche_ecran(fichier, 0, fichier->courante);

      return(quitte);
}
/**********************************************************************/
int type_text(char *text, FICHIER *fichier, char *buf, int position)
{
      while (*text)
      {
            handle_normal_char((unsigned int)(unsigned char)*text, fichier, buf, fichier->colonne + fichier->premier_caractere);
            text++;
      }
      return(0);
}
/**********************************************************************/
int handle_normal_char(int key, FICHIER *fichier, char *buf, int position)
{
      /* le fichier a ete modifie */
      fichier->saved = 0;

      if ((fichier->courante->precedente != NULL) && (fichier->courante->suivante != NULL))
      {
            if (key >= ' ' && key <= 255)
            {
                  if ((insert_mode == REPLACE) && buf[position])
                  {
                        /* correction bug */
                        buf[position] = (char)key;
                  }
                  else
                  {
                        strcpy(buftmp, buf + position);
                        *(buf + position) = (char)key;
                        *(buf + position + 1) = '\0';
                        strcat(buf, buftmp);
                  }
                  *(buf + SZBUF) = '\0';

                  droite(fichier, buf, 1, 0);
                  if (fichier->colonne + fichier->premier_caractere > (JEREDCOLS - 1))
                        affiche_ecran(fichier, fichier->premier_caractere, fichier->courante);
            }
      }
      return(0);
}
/**********************************************************************/
void droite(FICHIER *fichier, char *buf, int affiche, int end)
{
      do
      {
            if ((fichier->colonne < XMAX) && buf[fichier->colonne])
                  fichier->colonne++;
            else
            {
                  if ((fichier->colonne + fichier->premier_caractere < SZBUF) && (buf[fichier->colonne + fichier->premier_caractere]))
                  {
                        fichier->premier_caractere++;
                        affiche = 1;
                  }
                  else
                  {
                        /* si c'est la touche END */
                        if (end)
                              end = 0;
                  }
            }
      }
      while (end) ;

      if (affiche)
            fichier->affiche_ligne(fichier->courante, fichier->ligne, buf, fichier->premier_caractere);
}
/**********************************************************************/
void gauche(FICHIER *fichier, char *buf, int affiche, int home)
{
      do
      {
            if (fichier->colonne > XMIN)
                  fichier->colonne--;
            else
            {
                  if (fichier->premier_caractere)
                  {
                        fichier->premier_caractere--;
                        affiche = 1;
                  }
                  else
                  {
                        /* si c'est la touche HOME */
                        if (home)
                              home = 0;
                  }
            }
      }
      while (home) ;

      if (affiche)
            fichier->affiche_ligne(fichier->courante, fichier->ligne, buf, fichier->premier_caractere);
}
/**********************************************************************/
void expand(char *texte, char *buffer)
{
      int nbspaces;     /* nbre d'espaces pou arriver a une tab */
      char *ptr;  /* pointeur dans ligne courante */
      char *ptw;  /* pointeur dans buffer */

      if (texte != NULL)
      {
            ptw = buffer;
            ptr = texte;
            while (*ptr)
            {
                  if (*ptr == '\t')
                  {
                        nbspaces = tabsize - ((ptw - buffer) % tabsize);
                        while (nbspaces--)
                              *ptw++ = ' ';
                  }
                  else
                        *ptw++ = *ptr;
                  ptr++;
            }

            *ptw = '\0';      /* corrects a disfunctionning with macro files */

#ifdef SUPPRESS_TAILING_SPACES
            /* we don't want to suppress tailing spaces any more */
            *ptw = ' ';
            while ((ptw >= buffer) && isspace(*ptw))
                  *ptw-- = '\0';
#endif
      }
      else
            *buffer = '\0';
}
/**********************************************************************/
void strip(FILE *fpo, char *buffer)
{
      char ligne[SZBUF + 2];  /* buffer de travail */
      int guillemet;          /* ne strippe pas les chaines entre guillemets */
      char *ptr;        /* pointeur dans buffer */
      char *ptw;        /* pointeur dans ligne */
      int nbspaces;
      int nbtabs;
      int position;


      if (savetabs == OUI)    /* do we want to convert spaces to tabs on saving ??? */
      {
            ptr = buffer;
            ptw = ligne;
            guillemet = 0;
            position = 1;
            nbtabs = nbspaces = 0;
            for (position = 1; *ptr; ++position)
            {
                  if (*ptr == '\"')
                        guillemet++;

                  if (! (guillemet & 1))
                  {
                        if (*ptr == ' ')
                        {
                              if (position % TABSIZE)
                                    nbspaces++;
                              else
                              {
                                    if ((! nbspaces) && (*(ptr + 1) != ' '))
                                          nbspaces++;
                                    else
                                    {
                                          nbspaces = 0;
                                          nbtabs++;
                                    }
                              }
                        }
                        else
                        {
                              for ( ; nbtabs > 0; --nbtabs)
                                    *ptw++ = '\t';
                              for ( ; nbspaces > 0; --nbspaces)
                                    *ptw++ = ' ';
                              *ptw++ = *ptr;
                        }
                  }
                  else
                  {
                        for ( ; nbtabs > 0; --nbtabs)
                              *ptw++ = '\t';
                        for ( ; nbspaces > 0; --nbspaces)
                              *ptw++ = ' ';
                        *ptw++ = *ptr;
                  }
                  ptr++;
            }
            *ptw = '\0';
      }
      else
            strcpy(ligne, buffer);  /* we don't save tabs, we save spaces */

      fprintf(fpo, "%s\n", ligne);
}
/**********************************************************************/
int realloue_texte(LIGNE *plig, char *texte)
{
      char *ptr;        /* pointeur tempo pour alloc */

      if (plig != NULL)
      {
            ptr = (char *)malloc(strlen(texte) + 1);
            if (ptr != NULL)
            {
                  if (plig->texte != NULL)
                        free(plig->texte);

                  plig->texte = ptr;
                  strcpy(plig->texte, texte);
                  return(0);
            }
            else
                  return(-1);
      }
      else
            return(-1);
}
/**********************************************************************/
LIGNE *insere_ligne(FICHIER *fichier, char *buf, LIGNE *avant, LIGNE *apres)
{
      LIGNE *courante;  /* pointeur sur ligne courante */
      char buffer[SZBUF + 2]; /* buffer de travail */

      courante = (LIGNE *)malloc(sizeof(LIGNE));
      if (courante != NULL)
      {
            courante->precedente = avant;
            courante->suivante = apres;
            avant->suivante = courante;
            apres->precedente = courante;

            if (buf != NULL)
            {
                  expand(buf, buffer);
                  courante->texte = (char *)malloc(strlen(buffer) + 1);
                  if (courante->texte != NULL)
                  {
                        strcpy(courante->texte, buffer);
                        courante->debut_marque = courante->fin_marque = NOTMARKED;
                        fichier->nblignes++;
                  }
                  else
                  {
                        avant->suivante = apres;
                        apres->precedente = avant;
                        free(courante);
                        courante = NULL;
                  }
            }
            else
            {
                  courante->texte = NULL;
                  courante->debut_marque = courante->fin_marque = NOTMARKED;
                  fichier->nblignes++;
            }
      }
      return(courante);
}
/**********************************************************************/
char *inserespace(char *string, int pos, int nbre)
{
      char buffer[SZBUF + 2]; /* buffer temporaire */
      char *ptw;        /* pointeur pour ecrire */
      int lg;                 /* longueur de la chaine en entree */

      lg = strlen(string);
      if (lg < pos)
            return(NULL);
      else
      {
            strncpy(buffer, string, pos);
            ptw = buffer + pos;
            while (nbre--)
                  *ptw++ = ' ';
            strcpy(ptw, string + pos);
            strcpy(string, buffer);

            return(string);
      }
}
/**********************************************************************/
void aligne_ligne(char *string, int col)
{
      char buffer[SZBUF + 2];        /* temporary buffer */
      char *ptr;              /* read pointer */
      char *ptw;              /* write buffer */

      /* first we delete all spaces at the beginning of string */
      for (ptr = string; *ptr && isspace(*ptr); ptr++) ;

      /* now we put col-1 spaces at the beginning of buffer */
      ptw = buffer;
      while (col > 1)
      {
            *ptw++ = ' ';
            col--;
      }

      /* now we concatenate all remaining chars from string */
      strcpy(ptw, ptr);

      /* then we copy buffer to string */
      strcpy(string, buffer);
}
/**********************************************************************/
void current_word(char *buffer, int position, char *dest)
{
      char *ptd;
      char *ptw;

      ptd = buffer + position;
      while ((ptd >= buffer) && (isalnum(*ptd) || (*ptd == '_')))
            ptd--;
      ptd++;

      ptw = dest;
      while (*ptd && (isalnum(*ptd) || (*ptd == '_')))
            *ptw++ = *ptd++;
      *ptw = '\0';
}
/**********************************************************************/
void launch_external_command(char *jvcmdline, int mustwait)
{
      chtype *buffer;

      /* we must stop the autosave function */
      /* to not disturb display within the shell */
      stop_alarm_handler();

      /* because we want an external command */
      buffer = sauve_ecran();
      if (buffer != NULL)
      {
            system(jvcmdline);
            restaure_ecran(buffer, mustwait);
      }

      /* we can re-activate the autosave function */
      reset_alarm_handler();
}
/**********************************************************************/

Generated by  Doxygen 1.6.0   Back to index