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

blocks.c

/**********************************************************************/
/* BLOCKS.C: Gestion des blocks de lignes pour l'editeur JERED        */
/**********************************************************************/

/*
    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"
#include "messages.h"

extern int wordwrapbegin;
extern int wordwrapend;

static struct _BLOC_
/* PURPOSE OF STRUCT:
This struct is the structure which represents the current marked block of
lines.
There are:
        a pointer to the FICHIER structure for the file in which the block is.
        the beginning of block line number
        the end of block line number
        a pointer to the LIGNE structure for the beginning of block line
        a pointer to the LIGNE structure for the end of block line

        fichier <==> file
        debut <==> beginning (debuter <==> to begin)
        fin <==> end (ending ?) (finir <==> to finish, to end (if it exists))
        numero <==> number
 .................................*/
        {
                FICHIER *fichier;   /* fichier dans lequel est le bloc */
                int numdeb;         /* numero de ligne de debut du bloc */
                int numfin;         /* numero de ligne de fin du bloc */
                LIGNE *lignedeb;    /* pointeur vers ligne de debut de bloc */
                LIGNE *lignefin;    /* pointeur vers ligne de fin du bloc */
        }
        bloc;

char *find_lastword(char *string);
/**********************************************************************/
int bloc_dans_ce_fichier(FICHIER *fichier)
/* PURPOSE OF FUNCTION:
This function returns 1 if the block is in the file pointed by the arg
'fichier', or 0 otherwise. The test is an equality test between the
pointer to the current file which is the arg 'fichier' and the 'fichier
' field of the block structure.
 ..............................*/
{
        if (fichier == bloc.fichier) /* le bloc est-il dans ce fichier ? */
            return(1);
        else
            return(0);
}
/**********************************************************************/
void demarquer_bloc(void)
/* PURPOSE OF FUNCTION:
This function unmarks the current marked block, it is called on each
press on the F7 key. It is also called one time at the beginning of
the program to create an empty block.
 .................................*/
{
        static int first = 1;   /* pour initialisation */
        LIGNE *courante;

        if (! first)
        {
                /* on demarque toutes les lignes du bloc */
                if (bloc.lignedeb != NULL)
                {
                        for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                                courante->debut_marque = courante->fin_marque = NOTMARKED;
                }
        }
        else
                first = 0;  /* ce n'est plus le premier passage */

        bloc.numdeb = bloc.numfin = NOTMARKED;
        bloc.lignedeb = bloc.lignefin = NULL;
        bloc.fichier = NULL;
}
/**********************************************************************/
void marquer_bloc(FICHIER *fichier)
/* PURPOSE OF FUNCTION:
This function adds lines to the already existing block or create a
new non empty block if none exists. This function verifies that the
user don't mark the first line or the last line of the current file.
This functions don't do anything if the user is marking lines in a
file and an already marked block exists in another file.
 ...................................*/
{
        LIGNE *courante;

        /* pas le droit de marquer la premiere ou la derniere ligne */
        if ((fichier->courante->precedente == NULL) || (fichier->courante->suivante == NULL))
                return;

        /* if the line is already marked, we stop */
        /* bug corrected, Feb 09 1997, J. ALET */
        if (fichier->courante->debut_marque != NOTMARKED)
                return;

        /* debut de marquage ? */
        if (bloc.fichier == NULL)
        {
                bloc.fichier = fichier;
                bloc.lignedeb = bloc.lignefin = fichier->courante;
                bloc.numdeb = bloc.numfin = fichier->numcourante;
                fichier->courante->debut_marque = 0;    /* par exemple */
                fichier->courante->fin_marque = 1;  /* par exemple */
        }
        else
        {
                /* si c'est le meme fichier */
                /* on autorise la poursuite du marquage */
                if (fichier == bloc.fichier)
                {
                        /* positionne la deuxieme borne du bloc */
                        /* si debut de bloc > fin de bloc */
                        /* on echange les bornes */
                        if (bloc.numdeb > fichier->numcourante)
                        {
                                bloc.lignedeb = fichier->courante;
                                bloc.numdeb = fichier->numcourante;
                        }
                        else
                        {
                                bloc.lignefin = fichier->courante;
                                bloc.numfin = fichier->numcourante;
                        }

                        /* marque les lignes du bloc */
                        for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                        {
                                courante->debut_marque = 0; /* par exemple */
                                courante->fin_marque = 1;   /* par exemple */
                        }
                }
        }
}
/**********************************************************************/
int copier_bloc(FICHIER *fichier)
/* PURPOSE OF FUNCTION:
This function copies the current block to the line just under the
cursor, even if the block is in another file than the current file.
Then it marks the file in which it copies the block as modified
(non saved since the last modification)
 ..................................*/
{
        LIGNE *pl;
        LIGNE *courante;
        int blocksize;  /* to correct a small bug */
        
        /* si un bloc est marque et que la ligne courante est hors */
        /* du bloc ou alors sur sa derniere ligne ou alors que le fichier */
        /* dans lequel on va copier est different du fichier dans lequel est le bloc */
        if ((bloc.fichier != NULL) && (fichier->courante != fichier->derniere) && ((! bloc_dans_ce_fichier(fichier)) || (fichier->numcourante < bloc.numdeb) || (fichier->numcourante >= bloc.numfin)))
        {
                for (courante = fichier->courante, pl = bloc.lignedeb; pl != bloc.lignefin->suivante; pl = pl->suivante)
                {
                        courante = insere_ligne(fichier, pl->texte, courante, courante->suivante);
                        if (courante == NULL)
                        {
                                erreur(message[MSG_ERROR_MEMORY], NULL);
                                break;
                        }
                }
                
                /* 13 May 1997, Jerome Alet */
                /* bug correction: we must compute new numbers for the begin */
                /* line and end line if the block was copied before itself */
                /* in the same file */
                if (bloc_dans_ce_fichier(fichier) && (fichier->numcourante < bloc.numdeb))
                {
                        blocksize = bloc.numfin - bloc.numdeb + 1;
                        bloc.numdeb += blocksize;
                        bloc.numfin += blocksize;
                }

                /* le fichier a ete modifie */
                fichier->saved = 0;
                
                return(0);
        }
        else
                return(-1);
}
/**********************************************************************/
void deplacer_bloc(FICHIER *fichier)
/* PURPOSE OF FUNCTION:
This function moves the current block to the line under the cursor.
It is done very easily, just by calling copier_bloc() to copy the
block and calling supprimer_bloc() to delete it. The file is marked
as modified (see above).
 ....................................*/
{
        /* bug correction, 14 August 1997 */
        if (! copier_bloc(fichier))
                supprimer_bloc(DONTASKCONFIRMATION);

        /* le fichier a ete modifie */
        fichier->saved = 0;
}
/**********************************************************************/
void supprimer_bloc(int ask)
/* PURPOSE OF FUNCTION:
This function deletes the current block of lines. The main difficulty
is that the line which is at the beginning of the screen may change,
so we must ensure that current line pointer, beginning of screen line
pointer and all their co-ordinates will be correctly modified.
Then the file is marked as modified and we set the _BLOC_ structure
as being empty (the block doesn't exist anymore).
................................*/
{
        LIGNE *avant;       /* pointe sur la ligne avant le bloc */
        int nbl1, nbl2;     /* nombre de lignes du bloc */

        /* si un bloc est defini et que la ligne courante n'est pas dans ce bloc */
        if (bloc.fichier != NULL)
        {
                if (((ask == ASKCONFIRMATION) && confirmation(message[MSG_QUESTION_REMOVE]))
                      || (ask == DONTASKCONFIRMATION))
                {
                        if (bloc.fichier->courante->debut_marque != NOTMARKED)
                        {
                                /* we stop screen refreshing */
                                set_refresh(OFF);

                                /* if the block is above the current line */
                                /* go up to the beginning of the block */
                                while ((bloc.fichier->numcourante >= bloc.numdeb) && remonter_ligne(bloc.fichier))
                                        ;

                                /* if the block is under the current line */
                                /* go down to the beginning of the block */
                                while ((bloc.fichier->numcourante < (bloc.numdeb - 1)) && descendre_ligne(bloc.fichier))
                                        ;

                                /* we allow screen refreshing */
                                set_refresh(ON);
                                refresh();
                        }

                        /* nombre de lignes du bloc */
                        nbl1 = bloc.numfin - bloc.numdeb + 1;

                        /* si la ligne courante est situee avant le bloc il */
                        /* n'y a rien a faire */
                        if (bloc.fichier->numcourante > bloc.numdeb)
                        {
                                /* sinon si le debut d'ecran est avant le bloc */
                                /* la ligne courante est, d'apres les tests */
                                /* precedents, situee plus bas que le bloc */
                                /* en d'autres termes le bloc est a l'ecran */
                                /* mais avant la ligne courante */
                                if (bloc.fichier->numdebecr < bloc.numdeb)
                                {
                                        /* on change le numero de ligne courante */
                                        /* ainsi que la ligne du curseur */
                                        bloc.fichier->ligne -= nbl1;
                                        bloc.fichier->numcourante -= nbl1;
                                }
                                else
                                {
                                        /* si le debut d'ecran est dans le bloc */
                                        if (bloc.fichier->numdebecr <= bloc.numfin)
                                        {
                                                nbl2 = bloc.numfin - bloc.fichier->numdebecr + 1;
                                                bloc.fichier->numdebecr += (nbl2 - nbl1);
                                                bloc.fichier->ligne -= nbl2;
                                                bloc.fichier->numcourante -= nbl1;
                                                bloc.fichier->debut_ecran = bloc.lignefin->suivante;
                                        }
                                        else
                                        {
                                                /* le bloc est au dessus de l'ecran */
                                                /* la ligne de debut d'ecran ne change pas */
                                                bloc.fichier->numdebecr -= nbl1;
                                                bloc.fichier->numcourante -= nbl1;
                                        }
                                }
                        }

                        /* supprime les lignes marquees */
                        avant = bloc.lignedeb->precedente;
                        while (nbl1 > 0)
                        {
                                supprime_ligne(bloc.fichier, avant->suivante);
                                nbl1--;
                        }

                        /* le fichier a ete modifie */
                        bloc.fichier->saved = 0;

                        /* on demarque le bloc mais pas avec demarquer_bloc() */
                        /* car les lignes n'existent plus */
                        bloc.numdeb = bloc.numfin = NOTMARKED;
                        bloc.lignedeb = bloc.lignefin = NULL;
                        bloc.fichier = NULL;
                }
        }
}
/**********************************************************************/
void uppercaseblock(FICHIER *fichier)
{
        LIGNE *courante;
        char *ptr;

        /* if a block exists */
        if (bloc.fichier != NULL)
        {
                /* for each line in the block */
                for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                {
                        /* for each char in that line */
                        for (ptr = courante->texte; *ptr; ptr++)
                        {
                                /* if it is lower cased, then convert it to upper case */
                                if (islower(*ptr))
                                        *ptr = toupper(*ptr);
                        }
                }

                /* the file was modified */
                bloc.fichier->saved = 0;
        }
}
/**********************************************************************/
void lowercaseblock(FICHIER *fichier)
{
        LIGNE *courante;
        char *ptr;

        /* if a block exists */
        if (bloc.fichier != NULL)
        {
                /* for each line in the block */
                for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                {
                        /* for each char in that line */
                        for (ptr = courante->texte; *ptr; ptr++)
                        {
                                /* if it is upper cased, then convert it to lower case */
                                if (isupper(*ptr))
                                        *ptr = tolower(*ptr);
                        }
                }

                /* the file was modified */
                bloc.fichier->saved = 0;
        }
}
/**********************************************************************/
void alignblock(FICHIER *fichier)
{
        char buffer[SZBUF + 2];
        LIGNE *courante;
        int ref;
        int decalage;
        int offset;
        char *ptr;

        /* if a block exists */
        if (bloc.fichier != NULL)
        {
                /* computes the number of spaces at the beginning of the first line of the block */
                for (ptr = bloc.lignedeb->texte; *ptr == ' '; ptr++) ;
                ref = (ptr - bloc.lignedeb->texte);

                /* for each line in the block */
                for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                {
                        strcpy(buffer, courante->texte);

                        /* computes the number of spaces at the beginning of the current line of the block */
                        for (ptr = buffer; *ptr == ' '; ptr++) ;
                        decalage = (ptr - buffer);

                        /* we want to keep original alignement if possible */
                        if (decalage > ref)
                                offset = (decalage - ref);
                        else
                                offset = 0;

                        aligne_ligne(buffer, fichier->colonne + fichier->premier_caractere + 1 + offset);
                        realloue_texte(courante, buffer);
                }

                /* the file was modified */
                bloc.fichier->saved = 0;
        }
}
/**********************************************************************/
void wrapblock(FICHIER *fichier)
{
        char newbuff[SZBUF + 2]; /* buffer to build a new line */
        char *buffer;            /* buffer to store all marked lines */
        LIGNE *courante;         /* pointer to current line */
        int length;              /* length of one line */
        char *ptw;               /* pointer to write */
        char *ptr;               /* pointer to read */
        char *ptend;             /* pointer to new end of line */
        int i;                   /* counter */
        struct _BLOC_ saveblock; /* to save current block */

        /* if a block exists */
        if (bloc.fichier != NULL)
        {
                /* computes the total length of all the lines in the block */
                length = 0;
                for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                        length += strlen(courante->texte) + 1;

                /* allocates memory to store all the text of the block */
                buffer = (char *)malloc(length + 1);
                if (buffer == NULL)
                        erreur(message[MSG_ERROR_MEMORY], NULL);
                else
                {
                        /* concatenates each line of the block in buffer */
                        *buffer = '\0';
                        ptw = buffer;
                        for (courante = bloc.lignedeb; courante != bloc.lignefin->suivante; courante = courante->suivante)
                        {
                                ptr = courante->texte;

                                /* skip all space chars at the beginning of the current line */
                                while (isspace(*ptr)) /* '\0' is not a space char ! */
                                        ptr++;

                                if (*ptr)
                                {
                                        strcpy(ptw, ptr);

                                        /* removes all space chars from the end of the current line */
                                        ptw += (strlen(ptr) - 1);
                                        while ((ptw >= buffer) && isspace(*ptw))
                                                *ptw-- = '\0';
                                        ptw++;

                                        /* add a space char */
                                        *ptw++ = ' ';

                                        /* then mark the new end of buffer */
                                        *ptw = '\0';
                                }
                        }

                        /* we stop screen refreshing */
                        set_refresh(OFF);

                        /* if the block is above the current line */
                        /* go up to the beginning of the block */
                        while ((bloc.fichier->numcourante >= bloc.numdeb) && remonter_ligne(bloc.fichier))
                                ;

                        /* if the block is under the current line */
                        /* go down to the beginning of the block */
                        while ((bloc.fichier->numcourante < (bloc.numdeb - 1)) && descendre_ligne(bloc.fichier))
                                ;

                        /* then we delete the block */
                        /* after we have saved it */
                        saveblock = bloc;
                        supprimer_bloc(DONTASKCONFIRMATION);

                        /* now we create new lines, all beginning with WORDWRAPBEGIN-1 */
                        /* spaces and which length is less or equal than WORDWRAPEND */
                        ptr = buffer;
                        courante = saveblock.fichier->courante;
                        while (*ptr)
                        {
                                ptw = newbuff;
                                for (i = 0; i < (wordwrapbegin - 1); i++)
                                        *ptw++ = ' ';

                                ptend = find_lastword(ptr);
                                if (ptend != ptr)
                                {
                                        while (ptr < ptend)
                                                *ptw++ = *ptr++;
                                }
                                else
                                {
                                        for (i = 0; i <= (wordwrapend - wordwrapbegin); i++)
                                                *ptw++ = *ptr++;
                                }
                                *ptw = '\0';

                                courante = insere_ligne(saveblock.fichier, newbuff, courante, courante->suivante);
                                if (courante == NULL)
                                {
                                        erreur(message[MSG_ERROR_MEMORY], NULL);
                                        break;
                                }
                        }

                        /* the file was modified */
                        saveblock.fichier->saved = 0;

                        /* we free the allocated memory */
                        free(buffer);

                        /* we allow screen refreshing */
                        set_refresh(ON);
                        refresh();
                }

        }
}
/**********************************************************************/
char *find_lastword(char *string)
{
        char *ptr;
        int i;

        /* we want to find the last beginning of a word in the text */
        /* delimited by wordwrapbegin and wordwrapend */
        ptr = string;
        while (*ptr && ((ptr - string) <= (wordwrapend - wordwrapbegin)))
                ptr++;
        if (! *ptr)
                return(ptr);
        else
        {
                i = (int)(ptr - string);
                if (i > 0)
                {
                        do
                        {
                                i--;
                        }
                        while ((i >= 0) && isspace(string[i])) ;
                }

                if (i > 0)
                {
                        do
                        {
                                i--;
                        }
                        while ((i > 0) && (! isspace(string[i]))) ;
                }

                if (string[i] && isspace(string[i]))
                        i++;

                return((char *)(string + i));
        }
}
/**********************************************************************/
void test_and_correct_block(FICHIER *fichier)
{
        /* if we want to suppress a line which is above a marked block in */
        /* the current file, we must adjust lines numbers in the block. */
        if ((bloc.fichier != NULL) && bloc_dans_ce_fichier(fichier))
        {
                if (fichier->numcourante < bloc.numdeb)
                {
                        bloc.numdeb--;
                        bloc.numfin--;
                }
        }
}
/**********************************************************************/

Generated by  Doxygen 1.6.0   Back to index