home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xcoral16.zip / MAIN_BUF.C < prev    next >
C/C++ Source or Header  |  1993-01-15  |  19KB  |  1,030 lines

  1. /*
  2. ** Copyright 1989, 1992 by Lionel Fournigault
  3. **
  4. ** Permission to use, copy, and distribute for non-commercial purposes,
  5. ** is hereby granted without fee, providing that the above copyright
  6. ** notice appear in all copies and that both the copyright notice and this
  7. ** permission notice appear in supporting documentation.
  8. ** The software may be modified for your own purposes, but modified versions
  9. ** may not be distributed.
  10. ** This software is provided "as is" without any expressed or implied warranty.
  11. **
  12. **
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <malloc.h>
  17. #include <string.h>
  18.  
  19. #include "buffer.h"
  20.  
  21. static void MoreBuffer ();
  22. static int HoleSize ();
  23.  
  24. #ifdef DEBUG
  25. static void StatBuf ();
  26. #endif
  27.  
  28. /*
  29. **    Les fonctions suivantes creent et manipulent
  30. **    un buffer a bulle. La structure de celui-ci
  31. **    est illustree ci-dessous.
  32. **    
  33. **    turlututu chapeau pointu
  34. **            ^
  35. **           |
  36. **        curseur
  37. **
  38. **    turlutu_............._tu chapeau pointu
  39. **     ^      ^             ^                ^
  40. **     |      |             |                |
  41. **    top   l_cur          r_cur           bottom
  42. **    
  43.  */
  44.  
  45. /*
  46. **    Function name : GetBuffer
  47. **
  48. **    Description : Retourne une structure Buf contenant
  49. **        les pointeurs suivants :
  50. **            l_cur, r_cur : position de la bulle.
  51. **            top : le debut du buffer
  52. **            bottom : la fin du buffer
  53. **
  54. **    Input : la taille souhaitee pour le buffer.
  55. **    Ouput : Un pointeur sur Buf.
  56. */
  57. Buf *GetBuffer ( size )
  58.     register unsigned int size;
  59. {
  60.     Buf    *buf;
  61.  
  62.     buf = (Buf *) malloc ((unsigned) sizeof (Buf));
  63.  
  64.     /* 
  65.      * Alloue la place necessaire pour le buffer.
  66.      */
  67.     if ( size <= 0 ) size = SIZEOF_BUFFER;
  68.     buf -> top = ( char * ) malloc ( size );
  69.     if ( buf -> top == 0 ) 
  70.         return ( ( Buf *) 0 );
  71.     /*
  72.      * Positionne la bulle initiale.
  73.      */    
  74.     buf -> l_cur = buf -> top;
  75.     buf -> bottom = buf -> top  + ( size - 1 );
  76.     buf -> r_cur = buf -> bottom;
  77.     
  78.     return ( buf );
  79. }
  80.  
  81.  
  82. /*
  83. **    Function name : DeleteBuffer
  84. **
  85. **    Description : Comme son nom l'indique.
  86. **
  87. **    Input : Le buffer.
  88. **    Ouput : 
  89. */
  90. void DeleteBuffer ( buf )
  91. Buf *buf;
  92. {
  93.        if ( buf -> top != 0 )
  94.         (void) free ( buf -> top );       /* Le buffer */
  95.        if ( buf != 0 )
  96.         (void) free ( (char *) buf ); /* La structure associee */
  97. }
  98.  
  99.  
  100. /*
  101. **    Function name : ClearBuffer
  102. **
  103. **    Description : Pour 'effacer' le contenu du buffer,
  104. **        il suffit de positionner les pointeurs de la
  105. **        bulle pour que celle-ci occupe tout le buffer.
  106. **
  107. **    Input : un buffer
  108. **    Ouput :
  109. */
  110. void ClearBuffer ( buf )
  111. Buf *buf;
  112. {
  113.     buf -> l_cur = buf -> top;
  114.     buf -> r_cur = buf -> bottom;
  115. }
  116.  
  117.  
  118. /*
  119. **    Function name : MoreBuffer
  120. **
  121. **    Description : Augmente la taille du buffer.
  122. **
  123. **    Input : un buffer, n bytes
  124. **    Ouput :
  125. */
  126. static void MoreBuffer ( buf, n )
  127. Buf *buf;
  128. register int n;
  129. {
  130.     register int size, r_size, l_size;
  131.     char *b;
  132.  
  133.     /*
  134.      * Sauvegarde du contexte
  135.      */
  136.     l_size = buf -> l_cur - buf -> top;
  137.     r_size = buf -> bottom - buf -> r_cur;
  138.     
  139.     /*
  140.      * Calcul de la nouvelle taille
  141.      */
  142.     size = (( buf -> bottom - buf -> top + 1 + n ) / PSIZE  + 1 ) * PSIZE;
  143. #ifdef DEBUG
  144.     (void) fprintf ( stderr, 
  145.         "More buffer l_size = %d r_size = %d size = %d\n", 
  146.         l_size, r_size, size );
  147. #endif
  148.     /*
  149.      * Le nouveau buffer
  150.      */
  151.     if ( (b = ( char * ) malloc ( (unsigned) size )) == 0 )
  152.         (void) fprintf ( stderr, "Malloc error\n" );
  153.  
  154.     /* 
  155.      * On recopie l'ancien contexte
  156.      */
  157.     if ( l_size != 0 )
  158.         bcopy ( buf -> top, b, l_size );
  159.     if ( r_size != 0 )
  160.         bcopy ( buf -> r_cur, b + ( size - 1 ) - r_size, r_size );
  161.     
  162.     /*
  163.      * Liberation de l'ancien buffer
  164.      */
  165.     if ( buf -> top != 0 )
  166.         (void) free ( (char *) buf -> top ); 
  167.  
  168.     /*
  169.      * On positionne les nouveaux pointeurs
  170.      */
  171.     buf -> top = b;
  172.     buf -> l_cur = buf -> top + l_size;
  173.     buf -> bottom = buf -> top + ( size - 1 );
  174.     buf -> r_cur = buf -> bottom - r_size;
  175. #ifdef DEBUG
  176.     StatBuf ( buf );
  177. #endif
  178. }
  179.  
  180.  
  181. /*
  182. **    Function name : HoleSize
  183. **
  184. **    Description : Quelle est la place disponible dans
  185. **        le buffer.
  186. **
  187. **    Input : Le buffer
  188. **    Ouput : Retourne en octets l'espace libre.
  189. */
  190. static int HoleSize ( buf )
  191. Buf *buf;
  192. {
  193.     return ( buf -> r_cur - buf -> l_cur + 1 );
  194. }
  195.  
  196.  
  197. /*
  198. **    Function name : LoadFileInBuffer
  199. **
  200. **    Description : Copie le fichier, reference par fd, dans
  201. **        le buffer
  202. **
  203. **    Input : Le buffer, le fichier, la taille en octects
  204. **        du fichier, un flag
  205. **    Ouput : 0 si Ok ou -1 si problemes
  206. */
  207. int LoadFileInBuffer ( buf, fd, len, flag )
  208.     Buf         *buf;
  209.     FILE        *fd;
  210.     register int     len, flag;
  211. {
  212.     register char   *pp;
  213.  
  214.     /*
  215.      * L'espace libre est-il suffisant ?
  216.      */
  217.     if ( HoleSize ( buf ) < len ) {
  218.         MoreBuffer ( buf, len );
  219.     }
  220.  
  221.     /*
  222.      * Le fichier est-il a inserer dans le buffer
  223.      * ou pas ?
  224.      */
  225.     if ( flag == NEW ) {
  226.         pp = buf -> bottom - len + 1;
  227.         buf -> l_cur = buf -> top;
  228.         buf -> r_cur = buf -> bottom - len;
  229.     }
  230.     else { /* Insert */
  231.         pp = buf -> r_cur - len + 1;
  232.         buf -> r_cur -= len;
  233.     }
  234.     
  235.     /* 
  236.      * Copie
  237.      */
  238.     while ( len >= PSIZE ) {
  239.         if ( fread( pp, PSIZE, 1, fd) != 1 ) {
  240.             perror("Read error\n");
  241.             return ( -1 );
  242.             }
  243.         len -= PSIZE;
  244.         pp += PSIZE;
  245.     }
  246.     if (len) {
  247.         if ( fread ( pp, len, 1, fd ) != 1 ) {
  248.             perror ("Read error\n");
  249.             return ( -1 );
  250.         }
  251.     }
  252. #ifdef DEBUG
  253.     StatBuf ( buf );
  254. #endif
  255.     return 0;
  256. }
  257.  
  258.  
  259. /*
  260. **    Function name : WriteCurrentFile
  261. **
  262. **    Description : Copie du buffer dans le fichier reference
  263. **        par df.
  264. **
  265. **    Input : Le buffer, le fichier
  266. **    Ouput : La taille en octets du fichier.
  267. */
  268. int WriteCurrentFile ( buf, fd )
  269.     Buf *buf;
  270.     FILE *fd;
  271. {
  272.     /* 
  273.      * La taille des parties droite et gauche
  274.      * (de part et d'autre du curseur).
  275.      */
  276.     register int l_size = buf -> l_cur - buf -> top;
  277.     register int r_size = buf -> bottom - buf -> r_cur;
  278.  
  279.     /*
  280.      * Ecriture partie gauche
  281.      */
  282.     if ( l_size ) {
  283. #ifdef DEBUG
  284.     (void) fprintf ( stderr, "l_size = %d\n", l_size );
  285. #endif DEBUG
  286.         if ( fwrite ( buf -> top, l_size, 1, fd ) != 1 ) {
  287.             perror ( "Write error\n" );
  288.             return (-1);
  289.         }
  290.     }
  291.     /*
  292.      * Ecriture partie droite
  293.      */
  294.     if ( r_size ) {
  295. #ifdef DEBUG
  296.     (void) fprintf ( stderr, "r_size = %d\n", r_size );
  297. #endif DEBUG
  298.         if ( fwrite ( buf -> r_cur + 1, r_size, 1, fd ) != 1 ) {
  299.             perror ( "Write error\n" );
  300.             return (-1);
  301.         }
  302.     }
  303.     return ( l_size + r_size );
  304. }
  305.  
  306.  
  307. /*
  308. **    Function name : MoveToLine
  309. **
  310. **    Description : Deplacement a la ligne n.
  311. **        L'argument n est relatif par rappor a la
  312. **        ligne courante (e.g -1 ligne precedante).
  313. **
  314. **    Input : Le buffer, ligne
  315. **    Ouput : 0 si OK ou -1 si problemes.
  316. */
  317. int MoveToLine ( buf, n )
  318.     Buf *buf;
  319.     register int n;
  320. {
  321.     int len = 0;
  322.  
  323.     if (n == 0)
  324.         return 0;
  325.  
  326.     /*
  327.      * Just pour avoir la longueur du deplacement
  328.      */
  329.     if ( n > 0 ) 
  330.         (void)  GetForwardLine ( buf, n, &len );
  331.     else
  332.         (void)  GetBackwardLine ( buf, n, &len );
  333.  
  334.     if ( ! len )
  335.         return -1;
  336.  
  337.     if ( MoveHole ( buf, len ) == -1 ) {
  338.            (void) fprintf ( stderr, "Internal Error 6\n" );
  339.         return -1;
  340.      }
  341.     else
  342.         return 0;
  343. }
  344.  
  345.  
  346. /*
  347. **    Function name : MoveHole
  348. **
  349. **    Description : Deplacement de la bulle de n octets
  350. **
  351. **    Input : Le buffer, n octets.
  352. **    Ouput : 0 si OK ou -1 si problemes.
  353. */
  354. int MoveHole ( buf, n )
  355.     register Buf *buf;
  356.     register int n;
  357. {
  358.     if ( n == 0 ) {
  359. #ifdef DEBUG
  360.       (void) fprintf ( stderr, "n = 0\n" );
  361. #endif
  362.         return 0;
  363.     }
  364.  
  365.     /*
  366.      * Deplacement a droite
  367.      */
  368.     if ( n > 0 ) {
  369.         /*
  370.          * Va-t on aux fraises ?
  371.          */
  372.         if ( buf -> r_cur + n > buf -> bottom )  
  373.              return (-1);
  374.         /*
  375.          * 1 octet seulement.
  376.          */
  377.         if ( n == 1 ) {
  378.             buf -> r_cur ++;
  379.             *buf -> l_cur = *buf -> r_cur;
  380.             buf -> l_cur ++;
  381. #ifdef DEBUG
  382.              StatBuf ( buf );
  383. #endif
  384.             return 0;
  385.         }
  386.  
  387.         /*
  388.          * Plusieurs caracteres
  389.          */
  390.         bcopy ( buf -> r_cur + 1, buf -> l_cur, n );
  391.         buf -> r_cur += n;
  392.         buf -> l_cur += n;
  393. #ifdef DEBUG
  394.         StatBuf ( buf );
  395. #endif
  396.     }
  397.  
  398.     /*
  399.      * Deplacement a gauche.
  400.      */
  401.     else {
  402.         if ( buf -> l_cur - ( - n ) < buf -> top )
  403.             return ( -1 );
  404. #ifdef DEBUG
  405.          (void) fprintf ( stderr, "Left Move n = %d\n", n );
  406. #endif
  407.         if ( n == -1 ) {
  408.             buf -> l_cur --;
  409.             *buf -> r_cur = *buf -> l_cur;
  410.             buf -> r_cur --;
  411. #ifdef DEBUG
  412.             StatBuf ( buf );
  413. #endif
  414.             return 0;
  415.           }
  416.         buf -> l_cur -= ( -n );
  417.         buf -> r_cur -= ( -n );
  418.         bcopy ( buf -> l_cur, buf -> r_cur + 1 , -n );
  419.  
  420. #ifdef DEBUG
  421.         StatBuf ( buf );
  422. #endif
  423.     }
  424.     return 0;
  425. }
  426.  
  427.  
  428. /*
  429. **    Function name : StatBuf
  430. **
  431. **    Description : Pour le mode DEBUG. Imprime les infos.
  432. **
  433. **    Input : Le buffer
  434. **    Ouput :
  435. */
  436. #ifdef DEBUG
  437. static void StatBuf ( buf )
  438.     Buf *buf;
  439. {
  440.       (void) fprintf ( stderr, 
  441.         "Hole : buf = %d top = %d bottom = %d l_cur = %d r_cur = %d\n", 
  442.            buf, buf -> top, buf -> bottom, buf -> l_cur, buf -> r_cur );
  443. }
  444. #endif DEBUG
  445.  
  446.  
  447. /*
  448. **    Function name : HoleToRight
  449. **
  450. **    Description : Deplacement de la bulle completement
  451. **        a droite. Cela revient a deplacer le curseur
  452. **        en fin de buffer.
  453. **
  454. **    Input : Le buffer
  455. **    Ouput :
  456. */
  457. void HoleToRight ( buf )
  458.     Buf *buf;
  459. {
  460.  
  461. #ifdef DEBUG
  462.       (void) fprintf ( stderr, "HoleToRight\n" );
  463. #endif
  464.  
  465.       if ( MoveHole ( buf, buf -> bottom - buf -> r_cur ) == -1 )
  466.         (void) fprintf ( stderr,"Internal Error 7...\n" );
  467. }
  468.  
  469.  
  470. /*
  471. **    Function name : HoleToLeft
  472. **
  473. **    Description : Deplacement de la bulle completement
  474. **        a gauche. Cela revient a deplacer le curseur
  475. **        au debut du buffer.
  476. **
  477. **    Input : Le buffer
  478. **    Ouput :
  479. */
  480. void HoleToLeft ( buf )
  481.     Buf *buf;
  482. {
  483.  
  484. #ifdef DEBUG
  485.       (void) fprintf ( stderr, "HoleToleft\n" );
  486. #endif
  487.  
  488.     if ( MoveHole ( buf, buf -> top - buf -> l_cur ) == -1 )
  489.         (void) fprintf ( stderr, "Internal Error 8...\n" );    
  490. }
  491.  
  492.  
  493. /*
  494. **    Function name : InsertNchar
  495. **
  496. **    Description : Insere n caracteres a partir de la 
  497. **        position courante.
  498. **
  499. **    Input : Le buffer, chaine a inserer, sa taille.
  500. **    Ouput : 
  501. */
  502. void InsertNchar ( buf, s, n )
  503.     Buf *buf;
  504.     register char *s;
  505.     register int n;
  506. {
  507.     /*
  508.      * Reste-il de la place ?
  509.      */
  510.     if ( HoleSize ( buf ) < n ) {
  511.         (void) MoreBuffer ( buf, n );
  512.     }
  513.             
  514.     if ( n == 1 ) {
  515.         *buf -> l_cur = *s;
  516.         buf -> l_cur ++;
  517.         return;
  518.     }
  519.  
  520.        bcopy ( s, buf -> l_cur, n );
  521.     buf -> l_cur += n;
  522.     return;
  523. }
  524.  
  525.  
  526. /*
  527. **    Function name : DeleteNchar
  528. **
  529. **    Description : Efface n caracteres a partir de la 
  530. **        position courante.
  531. **
  532. **    Input : Le buffer, nb de caracteres a effacer.
  533. **    Ouput :
  534. */
  535. void DeleteNchar ( buf, n )
  536.     Buf *buf;
  537.     register int n;
  538. {
  539.  
  540. #ifdef DEBUG
  541.     (void) fprintf ( stderr, "Delete n = %d\n", n );
  542. #endif DEBUG
  543.  
  544.        if ( buf -> l_cur <= buf -> top )
  545.               return;
  546.  
  547.        if ( buf -> l_cur == buf -> r_cur )
  548.         (void) fprintf ( stderr, "End of buf\n" );
  549.        buf -> l_cur -= n;
  550. }
  551.  
  552.  
  553. /*
  554. **    Function name : GetForwardLine
  555. **
  556. **    Description : Recherche a partir de la position 
  557. **        courante, le debut de la n-ieme ligne
  558. **          
  559. **    Input : Le buffer, no ligne, deplacement ( il
  560. **        s'agit du nombres de caracteres entre
  561. **        la position courante et la position
  562. **        recherchee );
  563. **    Ouput : pointeur sur n-ieme ligne ou 0 si problemes.
  564. */
  565. char *GetForwardLine ( buf, n, len )
  566.     register Buf *buf;
  567.     register int n;
  568.     register int *len;    /* Return */
  569.  
  570. {
  571.     register char *p;
  572.     register int i = 0;
  573.  
  574.     p = buf -> r_cur + 1 ;
  575.  
  576.     while ( p <= buf -> bottom ) { 
  577.         if ( *p == '\n' )
  578.             n--;
  579.         if ( n == 0 ) {
  580.             if ( p == buf -> bottom ) {
  581.                 *len = ++i;
  582.                 return 0;
  583.             }
  584.             else {
  585.                 *len = ++i;
  586.                 return ++p;
  587.             }
  588.         }
  589.         p++;
  590.         i++;
  591.     }
  592.     return 0;
  593. }
  594.  
  595.  
  596. /*
  597. **    Function name : GetBackwardLine
  598. **
  599. **    Description : Recherche a partir de la position 
  600. **        courante, le debut de la n-ieme ligne
  601. **          
  602. **    Input : Le buffer, no ligne, deplacement ( il
  603. **        s'agit du nombres de caracteres entre
  604. **        la position courante et la position
  605. **        recherchee );
  606. **    Ouput : pointeur sur n-ieme ligne ou 0.
  607. */
  608. char *GetBackwardLine ( buf, n, len )
  609.     register Buf *buf;
  610.     register int n;
  611.     register int *len; /* Return */
  612. {
  613.     register char *p;
  614.     register int i = 0;
  615.  
  616.     p = buf -> l_cur - 1;
  617.     n --;
  618.     while ( p > buf -> top ) {
  619.         if ( *p == '\n' ) n++;
  620.         if ( n == 0 ) {
  621.             *len = - ( i );
  622.             return ++p;
  623.         }
  624.         p--;
  625.         i++;
  626.     }
  627.     /* Debut du buffer */
  628.  
  629.     if ( (n <= -2) && (*buf -> top != '\n') ) {
  630.         *len = 0;
  631.         return 0;
  632.     }
  633.     if ( (n < -2) && (*buf -> top == '\n') ) {
  634.         *len = 0;
  635.         return 0;
  636.     }
  637.     /* Cas special si 1 ere ligne vide */
  638.     if ( (*buf -> top == '\n') && (n == -1) ) {
  639.         *len = -i;
  640.         return ++p;
  641.     }
  642.     else {
  643.         *len = - (i+1);
  644.         return p;
  645.     }
  646. }
  647.  
  648.  
  649. /*
  650. **    Function name : GetCurrentLine
  651. **
  652. **    Description : Assemblage de la ligne courante.
  653. **        Cette fonction est le coeur de l'application.
  654. **        
  655. **    Input : Le buffer, la taille (return)
  656. **    Ouput : Le pointeur sur la ligne courante.
  657. */
  658. char *GetCurrentLine ( buf, len )
  659.     register Buf *buf;
  660.     register int *len; /* Return */
  661. {
  662. #define MAX_SLEN    64
  663.     static int mbuf_len = 0;
  664.     static char sbuf [MAX_SLEN], *mbuf, *mbuf_save = 0;
  665.     register int i, j;
  666.     register char *p, *pp;
  667.  
  668.     *len = 0;
  669.     /*
  670.      * Partie gauche : positionnement du pointeur et calcul
  671.      *    du deplacement par rapport a la position
  672.      *    courante.
  673.      */
  674.     p = buf -> l_cur - 1;
  675.     j = 0;
  676.     while ( p > buf -> top ) {
  677.         if ( *p == '\n' )
  678.             break;
  679.         p--;
  680.         j++;
  681.     }
  682.     if ( p != buf -> top )
  683.         p++;
  684.     else {    
  685.         /*
  686.          * Debut du buffer
  687.          */
  688.         if ( *p != '\n' ) 
  689.             j++;
  690.         else
  691.             /*
  692.              * 1er ligne : vide
  693.              */
  694.             p++;
  695.     }
  696.     *len = j;
  697.  
  698.     /*
  699.      * On garde p pour plus tard
  700.      */
  701.     pp = p;
  702. #ifdef DEBUG
  703.     (void) fprintf ( stderr, 
  704.         "len = %d Left side s = %s\n", *len, sbuf );
  705. #endif
  706.     /*
  707.      * Partie droite : positionnement du pointeur et calcul
  708.      *    du deplacement par rapport a la position
  709.      *    courante.
  710.      */
  711.     p = buf -> r_cur + 1;
  712.     i = 0;
  713.     while ( p < buf -> bottom ) {
  714.         if ( *p == '\n' )
  715.             break;
  716.         p++;
  717.         i++;
  718.     }
  719.     /*
  720.      * On teste si la longueur de la ligne est > a MAX_SLEN.
  721.      */
  722.     if ( ( i + j + 8 ) > MAX_SLEN ) {
  723.         /*
  724.          * Il faut de la place
  725.          */
  726.         if ( mbuf_save ) {
  727.             /*
  728.              * Si le buffer deja alloue est assez grand on prend
  729.              * celui-ci, sinon on en alloue un autre.
  730.              */
  731.             if (( i + j + 8 ) > mbuf_len) {
  732.                          if ( mbuf_save != 0 )
  733.                     (void) free ( mbuf_save );
  734.                 mbuf_len = ( 2 * ( i + j + 8 ));
  735.                 mbuf = ( char *) malloc ( (unsigned int) mbuf_len );
  736.                 mbuf_save = mbuf;
  737.             }
  738.             else
  739.                 mbuf = mbuf_save;
  740.         }
  741.         else {
  742.             mbuf_len = i + j + 8;
  743.             mbuf = ( char *) malloc ( (unsigned int) mbuf_len );
  744.             mbuf_save = mbuf;
  745.         }
  746.         bzero ( mbuf, mbuf_len  );
  747.     }
  748.     else {
  749.         /*
  750.          * On se sert du buffer static
  751.          */
  752.         bzero ( sbuf, MAX_SLEN );
  753.         mbuf = sbuf;
  754.     }
  755.     /*
  756.      * On copie la partie gauche
  757.      */
  758.     (void) strncpy ( mbuf, pp, j );
  759.     j = 0;
  760.     
  761.     /*
  762.      * Fin du buffer et pas de retour chariot
  763.      */
  764.     if ( (p == buf -> bottom) && (*p != '\n') ) {
  765.         *len += 1;
  766.         /*
  767.          * On ajoute la partie droite
  768.          */
  769.         (void) strncat ( mbuf, p - i, i + 1 );
  770.         j = 1;
  771.     }
  772.     else
  773.         /*
  774.          * On ajoute la partie droite
  775.          */
  776.         (void) strncat ( mbuf, p - i, i );
  777.  
  778.     *len += i;
  779.     (void) strncat ( mbuf, "\n", 1 ); 
  780. #ifdef DEBUG
  781.     (void) fprintf ( stderr,
  782.         "i = %d len = %d Current line : %s\n", i, *len, mbuf );
  783.     (void) fprintf ( stderr, "Deplace = %d\n", i+1 );
  784. #endif
  785.     return mbuf;
  786. }
  787.  
  788.  
  789. /*
  790. **    Function name : GetNcFromLeft
  791. **
  792. **    Description : Recherche le debut de la ligne
  793. **        courante.
  794. **
  795. **    Input : Le buffer
  796. **    Ouput : Le nombre de caracteres pour aller en debut
  797. **        de ligne.
  798. */
  799. int GetNcFromLeft ( buf )
  800.     Buf *buf;
  801. {
  802.        register int n = 0;
  803.        register char *p = buf -> l_cur - 1;
  804.  
  805.        while ( p > buf -> top ) {
  806.               if ( *p == '\n' )
  807.                  break;
  808.           p--;
  809.           n++;
  810.        }
  811.  
  812.        /*
  813.      * Est-ce la 1 ere ligne et traitement
  814.      * du cas ou celle-ci est vide
  815.      */
  816.        if ( (p == buf -> top) && (*p != '\n') )
  817.               n++;
  818.        return n;
  819. }
  820.  
  821.  
  822. /*
  823. **    Function name : GetNcFromRight
  824. **
  825. **    Description : Recherche de la fin de ligne.
  826. **
  827. **    Input : Le buffer
  828. **    Ouput : Le nombre de caracteres pour aller en fin
  829. **        de ligne (le '\n' n'est pas compte).
  830. */
  831. int GetNcFromRight ( buf )
  832.     Buf *buf;
  833. {
  834.        register int n = 0;
  835.        register char *p = buf -> r_cur + 1;
  836.  
  837.        while ( p < buf -> bottom ) {
  838.               if ( *p == '\n' ) {
  839.             break;
  840.           }
  841.           p++;
  842.           n++;
  843.        }
  844.        if ( (p == buf -> bottom) && (*p != '\n') ) {
  845.           n++;
  846.         }
  847.        return n;
  848. }
  849.  
  850.  
  851. /*
  852. **    Function name : GetNumberOfLineInBuf
  853. **
  854. **    Description : Combien de lignes dans le buffer.
  855. **
  856. **    Input : Le buffer
  857. **    Ouput : Le nombre de lignes.
  858. */
  859. int GetNumberOfLineInBuf ( buf )
  860.     Buf *buf;
  861. {
  862.     register int n = 1;
  863.     register char *p = buf -> top;
  864.  
  865.     /*
  866.      * Partie gauche
  867.      */
  868.     while ( p < buf -> l_cur ) {
  869.         if ( *p == '\n' )
  870.             n++;
  871.         p++;
  872.     }
  873.     
  874.     /*
  875.      * Partie droite
  876.      */
  877.     p = buf -> r_cur + 1;
  878.     while ( p < buf -> bottom ) {
  879.         if ( *p == '\n' )
  880.             n++;
  881.         p++;
  882.     }
  883.  
  884.     /*
  885.      * Traitement du '\n' en fin de buffer
  886.      */
  887.     if ( (buf -> bottom != buf -> r_cur)
  888.         && (*(buf -> bottom) == '\n' ))
  889.         n++;
  890.  
  891. #ifdef DEBUG
  892.     (void) fprintf ( stderr, " nb lines = %d\n", n );
  893. #endif DEBUG
  894.  
  895.        return n;
  896. }
  897.  
  898.  
  899. /*
  900. **    Function name : GetNewLine
  901. **
  902. **    Description : Recherche dans un chaine de longueur
  903. **        donnee, le nombre de ligne.
  904. **
  905. **    Input : La chaine, la longueur de celle-ci.
  906. **    Ouput : Le nombre de 'new_line'
  907. */
  908. int GetNewLine ( t, len )
  909.     register char *t; /* le texte */
  910.     register int len; /* la longeur du texte */
  911. {
  912.     register char *start = t;
  913.     register int nl = 0;
  914.  
  915.     if ( len == 0 ) return nl;
  916.  
  917.     if ( len > 0 ) {
  918.         while ( t < (start + len) ) {
  919.             if ( *t == '\n' ) nl++;
  920.             t++;
  921.         }
  922.         return nl;
  923.     }
  924.     else {
  925.         while ( t > (start + len) ) {
  926.             if ( *t == '\n' ) nl++;
  927.             t--;
  928.         }
  929.         return nl;
  930.     }
  931. }
  932.  
  933.  
  934. /*
  935. **    Function name : GetCurrentChar
  936. **
  937. **    Description : Donne le caractere courant.
  938. **
  939. **    Input : Le buffer
  940. **    Ouput :
  941. */
  942. void GetCurrentChar ( buf, c )
  943. Buf *buf;
  944. register char *c; /* Return */
  945. {
  946.     if ( (buf -> r_cur) == buf -> bottom )
  947.         *c  = '\0';
  948.     else
  949.         (void) strncpy ( c, buf -> r_cur + 1, 1 );
  950. }
  951.  
  952.  
  953. /*
  954. **    Function name : GetPrevChar
  955. **
  956. **    Description : Donne le caractere precedent.
  957. **
  958. **    Input : Le buffer
  959. **    Ouput :
  960. */
  961. void GetPrevChar ( buf, c )
  962. Buf *buf;
  963. register char *c;
  964. {
  965.        if ( buf -> l_cur <= buf -> top )
  966.               *c = '\0';
  967.        else
  968.           (void) strncpy ( c, buf -> l_cur -1, 1 );
  969. }
  970.  
  971.  
  972. /*
  973. **    Function name : DeleteLines
  974. **
  975. **    Description : Efface n lines a partir de la position courante.
  976. **        Positionne le nombre de caracteres et de lignes
  977. **        effectivement effacees. Comme toujours les resultats ne
  978. **        sont pas les memes suivant que le buffer se termine
  979. **        ou non par un new-line.
  980. **    Input : Le buffer
  981. **    Ouput : Position courante ( curseur droit ) apres effacement
  982. **        des lignes
  983. */
  984. char *DeleteLines ( buf, n, len, dn )
  985.     Buf *buf;
  986.     register int n;      /* nb lignes demandees */
  987.     register int *len;   /* caracteres deletes (return) */
  988.     register int *dn;    /* nb lignes deletees (return) */
  989. {
  990.     register int i = 0;
  991.     register int end_line = 0;
  992.     register char *p = buf -> r_cur + 1;
  993.  
  994.     if ( n == 0 ) return 0;
  995.     if ( n == 1 ) end_line = 1;
  996.  
  997.     *dn = 0;
  998.  
  999.     if ( n > 1 ) 
  1000.         i++;
  1001.  
  1002.     while ( p < buf -> bottom ) {
  1003.         if ( *p == '\n' ) {
  1004.             n --;
  1005.             (*dn) ++;
  1006.         }
  1007.         if ( n == 0 ) {
  1008.             if ( end_line == 1 ) {  /* Delete end of line */
  1009.                 *dn = 0;
  1010.                 if ( (*p == '\n') && (i == 0)) { /* Ligne vide */
  1011.                     *dn = i = 1;;
  1012.                 }
  1013.             }
  1014.             break;
  1015.         }
  1016.         i ++;
  1017.         p++;
  1018.     }
  1019.     if ( p == buf -> bottom ) {  /* Fin du buffer */
  1020.         if ( end_line == 0 )     /* Plusieurs lignes */
  1021.             (*dn) ++; 
  1022.         if ( (end_line == 1) && ( *p != '\n' ) )
  1023.             i++;
  1024.     }
  1025.     p = buf -> r_cur + 1;
  1026.     buf -> r_cur += i;
  1027.     *len = i;
  1028.     return p;
  1029. }
  1030.