home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / AP / JED / JED097-1.TAR / jed / src / buffer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-12  |  18.6 KB  |  983 lines

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <setjmp.h>
  8. #if defined (msdos) || defined (__os2_16__)
  9. #include <process.h>
  10. #include <dos.h>
  11. #endif
  12. #include <limits.h>
  13. #include <string.h>
  14.  
  15. #include "config.h"
  16. #include "buffer.h"
  17. #include "window.h"
  18. #include "file.h"
  19. #include "ins.h"
  20. #include "misc.h"
  21. #include "paste.h"
  22. #include "sysdep.h"
  23.  
  24. extern int Goal_Column;
  25.  
  26. typedef struct
  27. {
  28.    jmp_buf b;
  29. } jmp_buf_struct;
  30.  
  31. extern jmp_buf_struct Jump_Buffer, *Jump_Buffer_Ptr;
  32.  
  33.  
  34. typedef struct Buffer_List_Type
  35.   {
  36.       Buffer *buf;
  37.       struct Buffer_List_Type *next;
  38.   }
  39. Buffer_List_Type;
  40.  
  41. Buffer_List_Type *Buffer_Stack;   /* a filo */
  42.  
  43. #ifndef ULONG_MAX
  44. #define MAX_LONG (0xFFFFFFFFL | (0xFFFFFFFFL << (sizeof(long) / 8)))
  45. #else
  46. #define MAX_LONG ULONG_MAX
  47. #endif
  48.  
  49.  
  50. Buffer *CBuf;
  51. Line *CLine;
  52. Buffer_Local_Type Buffer_Local = {8, 0};
  53.  
  54. int Number_One = 1;               /* these should be const but  */
  55. int Number_Zero = 0;               /* some compilers complain */
  56. int Number_Two = 2;
  57. int Number_Ten = 10;
  58. char *Read_Only_Error = (char *) "Buffer is read only!";
  59.  
  60. unsigned int LineNum = 1;
  61. unsigned int Max_LineNum;
  62. int Point = 0;
  63.  
  64. /* move point to top of buffer */
  65. int bob()
  66. {
  67.    CLine = CBuf->beg;
  68.    Point = 0;
  69.    LineNum = 1;
  70.    return(1);
  71. }
  72.  
  73. int eob()                      /* point to end of buffer */
  74. {
  75.    CLine = CBuf->end;
  76.    LineNum = Max_LineNum;
  77.    if (CLine == NULL)
  78.      {
  79.     Point = 0;
  80.     return(0);
  81.      }
  82.  
  83.     Point = CLine->len - 1;
  84.     if (Point < 0)
  85.       {
  86.           Point = 0;
  87.           return(1);
  88.       }
  89.  
  90.     if ((CLine->data[Point] != '\n') || (CBuf == MiniBuffer)) Point++;
  91.     return(1);
  92. }
  93.  
  94. int bol()
  95. {
  96.     Point = 0;
  97.     Goal_Column = 1;
  98.     return(1);
  99. }
  100.  
  101. int eol()
  102. {
  103.     int newline = 1;
  104.     if (CLine != NULL)
  105.       {
  106.           Point = CLine->len - 1;
  107.           if (Point < 0)
  108.             {
  109.                 Point = 0;
  110.                 return(0);
  111.             }
  112.  
  113.           if (((CLine->data)[Point] != '\n') || (CBuf == MiniBuffer)) newline = 0;
  114.           if (!newline) Point++;
  115.       }
  116.  
  117.     else Point = 0;
  118.     return(1);
  119. }
  120.  
  121. int bobp()                /* returns 1 if top line of buffer, 0 otherwise */
  122. {
  123.     if ((CBuf->beg == CLine) && (Point == 0)) return(1); else return(0);
  124. }
  125.  
  126. int eolp()
  127. {
  128.    int len;
  129.  
  130.    if (CLine == NULL) return(1);
  131.    len = CLine->len;
  132.    if (len == 0) return(1);
  133.    if (Point < len - 1) return(0);
  134.    
  135.    if (CBuf == MiniBuffer)
  136.      {
  137.     if (Point < len) return 0; else return (1);
  138.      }
  139.    
  140.  
  141.     /* Point is either len or len - 1 */
  142.  
  143.    if ((CLine->data)[len-1] == '\n') return (1);
  144.  
  145.    if (Point == len) return(1);
  146.    Point = len - 1;
  147.    return(0);
  148. }
  149.  
  150. int eobp()
  151. {
  152.     if (CLine != CBuf->end) return(0);
  153.     return(eolp());
  154. }
  155.  
  156. int bolp()
  157. {
  158.     if (Point) return(0); else return(1);
  159. }
  160.  
  161. /*  Attempt to goback n lines, return actual number. */
  162. int prevline(int *n)
  163. {
  164.     int i = 0;
  165.     Line *prev;
  166.  
  167.     Point = 0;     /* return to beginning of this line */
  168.     while (i < *n)
  169.       {
  170.           prev = CLine->prev;
  171.           while((prev != NULL) && (prev->len == 0)) prev = prev->prev;
  172.           if (prev == NULL) break;
  173.           i++;
  174.           CLine = prev;
  175.       }
  176.  
  177.    if (i) eol();
  178.    LineNum -= (unsigned int) i;
  179.    return(i);
  180. }
  181.  
  182. int nextline(int *np)
  183. {
  184.    register Line *next;
  185.    register int i = 0, n = *np;
  186.  
  187.     while(i < n)
  188.       {
  189.      next = CLine->next;
  190.      if (next == NULL) break;
  191.      CLine = next;
  192.      i++;
  193.       }
  194.  
  195.    if (i) Point = 0;
  196.    LineNum += (unsigned int) i;
  197.    return(i);
  198. }
  199.  
  200. /* The algorithm:  go to Point = len - 1.  Then forward a line counted as 1 */
  201. int forwchars(int *np)
  202. {
  203.    int len, total = 0;
  204.    unsigned char *p;
  205.    Line *next;
  206.    int n = *np;
  207.  
  208.    if (n < 0) return 0;
  209.    if (CBuf == MiniBuffer)
  210.      {
  211.     total = CLine->len - Point;
  212.     if (n > total) n = total;
  213.     Point += n;
  214.     return n;
  215.      }
  216.     
  217.     while(1)
  218.       {
  219.           len = CLine->len;
  220.           /* if (Point == len) return(total); */
  221.           p = CLine->data + Point;
  222.           while(n && (Point < len) && (*p != '\n'))
  223.             {
  224.                 Point++;
  225.                 n--;
  226.                 p++;
  227.                 total++;
  228.             }
  229.           if (!n) return(total);
  230.           if (*p == '\n')
  231.             {
  232.                 total++;
  233.                 n--;
  234.             }
  235.  
  236.           if (NULL == (next = CLine->next))
  237.             {
  238.                 if (*p == '\n') total--;
  239.                 return(total);
  240.             }
  241.  
  242.           Point = 0;
  243.           CLine = next;
  244.      LineNum++;
  245.       }
  246. }
  247.  
  248. int backwchars(int *np)
  249. {
  250.    int total = 0;
  251.    int n = *np;
  252.    
  253.    if (n < 0) return 0;
  254.    if (CBuf == MiniBuffer)
  255.      {
  256.     if (n > Point) n = Point;
  257.     Point -= n;
  258.     return (n);
  259.      }
  260.    
  261.  
  262.     do
  263.       {
  264.           if (n <= Point)
  265.             {
  266.                 total += n;
  267.                 Point = Point - n;
  268.                 return(total);
  269.             }
  270.           n = n - Point - 1;   /* Point + newline */
  271.           total += Point + 1;   /* ditto */
  272.       }
  273.     while(prevline(&Number_One));
  274.  
  275.     return(total - 1);
  276. }
  277. /* assuming 8 bit bytes */
  278. #define BUNCH_SIZE 8 * sizeof(long)
  279. static unsigned char NewLine_Buffer[1] = {'\n'};
  280. typedef struct Bunch_Lines_Type
  281. {
  282.    struct Bunch_Lines_Type *next;
  283.    unsigned long flags;                   /* describes which are free */
  284.    Line lines[BUNCH_SIZE];
  285. } Bunch_Lines_Type;
  286.  
  287. static int Next_Free_Offset = BUNCH_SIZE;
  288. static int Last_Free_Offset;
  289. static Bunch_Lines_Type *Last_Free_Group;
  290. static Bunch_Lines_Type *Bunch_Lines;
  291. static unsigned int Number_Freed;      /* amount of Lines available */
  292.  
  293. static Line *create_line_from_bunch(void)
  294. {
  295.    register Bunch_Lines_Type *b, *bsave;
  296.    Line *l;
  297.    unsigned long flags;
  298.    int count;
  299.    
  300.    if (Last_Free_Group != NULL) 
  301.      {
  302.     l = &Last_Free_Group->lines[Last_Free_Offset];
  303.     flags = ((unsigned long) 1L << Last_Free_Offset);
  304.     if ((Last_Free_Group->flags & flags) == 0) 
  305.       {
  306.          exit_error("create group: internal error 1", 1);
  307.       }
  308.     
  309.     Last_Free_Group->flags &= ~flags;
  310.     Last_Free_Group = NULL;
  311.     Number_Freed--;
  312.     return (l);
  313.      }
  314.    
  315.    if (Next_Free_Offset < BUNCH_SIZE)
  316.      {
  317.     flags = ((unsigned long) 1L << Next_Free_Offset);
  318.     if ((Bunch_Lines->flags & flags) == 0) 
  319.       {
  320.          exit_error("free group: internal error 2", 1);
  321.       }
  322.     
  323.     
  324.     Bunch_Lines->flags &= ~flags;
  325.     Number_Freed--;
  326.     return(&Bunch_Lines->lines[Next_Free_Offset++]);
  327.      }
  328.    
  329.    /* search list */
  330.    b = Bunch_Lines;
  331.    if (b != NULL)
  332.      {
  333.     b = b->next;
  334.      }
  335.    
  336.    if ((b != NULL) && Number_Freed)
  337.      {
  338.     bsave = b;
  339.     do
  340.       {
  341.          if (b->flags)
  342.            {
  343.           flags = b->flags;
  344.           count = 0;
  345.           while ((flags & 1) == 0) 
  346.             {
  347.                flags = flags >> 1;
  348.                count++;
  349.             }
  350.           l = &b->lines[count];
  351.           flags = (unsigned long) 1 << count;
  352.           if ((b->flags & flags) == 0) 
  353.             {
  354.                     exit_error("free group: internal error 2", 1);
  355.             } 
  356.           b->flags &= ~flags;
  357.           Number_Freed--;
  358.           return (l);
  359.            }
  360.          b = b->next;
  361.       }
  362.     while (b != bsave);
  363.      }
  364.    
  365.    /* failed so now malloc new bunch */
  366.    
  367.    if (NULL != (b = (Bunch_Lines_Type *) SLMALLOC(sizeof(Bunch_Lines_Type))))
  368.      {
  369.     if (Bunch_Lines == NULL)
  370.       {
  371.          Bunch_Lines = b;
  372.          b->next = b;
  373.       }
  374.     else
  375.       {
  376.          b->next = Bunch_Lines->next;
  377.          Bunch_Lines->next = b;
  378.          Bunch_Lines = b;
  379.       }
  380.  
  381.     b->flags = MAX_LONG;
  382.     Next_Free_Offset = 1;
  383.     b->flags &= ~(unsigned long) 1;
  384.     Number_Freed += BUNCH_SIZE - 1;
  385.     return(&b->lines[0]);
  386.      }
  387.    return(NULL);
  388. }
  389.    
  390.  
  391. void destroy_bunch_line(Line *l)
  392. {
  393. #ifdef _MSC_VER
  394.    Line *ll;
  395. #else
  396.    register Line *ll;
  397. #endif
  398.    
  399.    register Bunch_Lines_Type *b, *bsave, *last, *next;
  400.    static Bunch_Lines_Type *slast;
  401.  
  402.    if (slast != NULL) last = slast;
  403.    else last = Bunch_Lines;
  404.    
  405.    b = bsave = last;
  406.    
  407.    do
  408.      {
  409.     ll = b->lines;
  410.     if (
  411. #if (defined (msdos) && !defined(__WATCOMC__)) || defined (__os2_16__)
  412.          /* stupid DOS and its memory segmentation forces me to consider
  413.             segment then offset */
  414.         (FP_SEG(ll) == FP_SEG(l)) &&
  415. #endif
  416.         ((ll <= l) && (l < ll + BUNCH_SIZE)))
  417.       {
  418.          while (ll != l) ll++;
  419.          Last_Free_Offset = (int) (l - b->lines);
  420.          if (b->flags & (1L << Last_Free_Offset)) 
  421.            {
  422.           exit_error("free group: internal error 2", 1);
  423.            }
  424.          
  425.          b->flags |= (unsigned long) 1L << Last_Free_Offset;
  426.          
  427.          /* if this whole structure is free, free it */
  428.          if (b->flags == MAX_LONG)
  429.            {
  430.           if (last == b)
  431.             {
  432.                while ((next = last->next) != b) last = next;
  433.             }
  434.           
  435.           last->next = b->next;
  436.  
  437.           if (b == Bunch_Lines)
  438.             {
  439.                if (last == b)
  440.              {
  441.                 last = NULL;
  442.                 /*
  443.                  last = last->next;
  444.                  if (last == b) last = NULL; */
  445.              }
  446.  
  447.                Bunch_Lines = last;
  448.                Next_Free_Offset = BUNCH_SIZE;
  449.             }
  450.           
  451.           SLFREE(b);
  452.           
  453.           if (last == b) last = NULL;
  454.           b = NULL;
  455.           Number_Freed -= BUNCH_SIZE - 1;
  456.           slast = last;
  457.            }
  458.          else 
  459.            {
  460.           Number_Freed++;
  461.            }
  462.          
  463.          Last_Free_Group = b;
  464.          if (Bunch_Lines == NULL) goto L1;
  465.          return;
  466.       }
  467.     last = b;
  468.     b = b->next;
  469.      }
  470.    while (b != bsave);
  471.    L1:
  472.    exit_error("destroy_bunch_line: internal error 1", 1);
  473. }
  474.  
  475. Line *make_line1(int size)
  476. {
  477.    Line *new_line;
  478.    unsigned char *data = NULL;
  479.    char buff[80];
  480.    unsigned int chunk;
  481.  
  482.    /* 4 byte chunks */
  483. #ifdef msdos
  484.    chunk = (unsigned) (size + 3) & 0xFFFC;
  485. #else
  486.    chunk = (unsigned) (size + 3) & 0xFFFFFFFC; 
  487. #endif
  488.    new_line = (Line *) create_line_from_bunch();
  489.    if (new_line != NULL) 
  490.      {
  491.     if (size == 1) 
  492.       {
  493.          data = NewLine_Buffer;
  494.          chunk = 1;
  495.       }
  496.     else data = (unsigned char *) SLMALLOC(chunk);   /* was chunk + 1 */
  497.      }
  498.  
  499.    if ((new_line == NULL) || (data == NULL))
  500.      {
  501.     *Error_Buffer = 0;           /* this is critical */
  502.     sprintf(buff, "Malloc Error in make_line: requested size: %d.", size);
  503.     msg_error(buff);
  504.     longjmp(Jump_Buffer_Ptr->b, 1);
  505.     /* exit_error(buff); */
  506.      }
  507.    new_line->data = data;
  508.    new_line->len = 0;
  509.    new_line->space = chunk;
  510.    return(new_line);
  511.  }
  512.  
  513. /* adds a new link to list of lines at current point */
  514. unsigned char *make_line(int size)
  515. {
  516.     Line *new_line;
  517.  
  518.     new_line = make_line1(size);
  519.     /* if CLine is Null, then we are at the top of a NEW buffer.  Make this
  520.        explicit. */
  521.     if (CLine == NULL)
  522.       {
  523.           new_line -> prev = NULL;
  524.           new_line -> next = NULL;
  525.           CBuf -> beg = CBuf ->end = new_line;
  526.       }
  527.     else if (CLine == CBuf->end) /* at end of buffer */
  528.       {
  529.           CBuf->end  = new_line;
  530.           new_line->next = NULL;
  531.           new_line->prev = CLine;
  532.           CLine->next = new_line;
  533.       }
  534.     else
  535.       {
  536.           new_line -> next = CLine -> next;
  537.           if (CLine->next != NULL) CLine->next->prev = new_line;
  538.           CLine->next = new_line;
  539.           new_line->prev = CLine;
  540.       }
  541.  
  542.    if (CLine == NULL)
  543.      {
  544.     Max_LineNum = LineNum = 1;
  545.      }
  546.    else
  547.      {
  548.     Max_LineNum++;
  549.     LineNum++;
  550.      }
  551.    CLine = new_line;
  552.    
  553.    return(CLine->data);
  554. }
  555.  
  556. void free_line(Line *line)
  557. {
  558.    register unsigned char *dat = line->data;
  559.    
  560.    if (dat != NewLine_Buffer) SLFREE(dat);
  561.    destroy_bunch_line(line);
  562. }
  563.  
  564. /* deletes the line we are on and returns the prev one.  It does not
  565.  * delete the top line of the buffer.   Furthermore, it does not
  566.  *  update any marks.  */
  567.  
  568. int delete_line()
  569. {
  570.     Line *n, *p, *tthis;
  571.  
  572.     p = CLine -> prev;
  573.     if (p == NULL) return(1);
  574.  
  575.     n = CLine -> next;
  576.     tthis = CLine;
  577.     if (n == NULL)
  578.       {
  579.           CBuf->end = p;
  580.           p->next = NULL;
  581.       }
  582.     else
  583.       {
  584.           p->next = n;
  585.           n->prev = p;
  586.       }
  587.  
  588.     free_line(tthis);
  589.     CLine = p;
  590.    LineNum--;
  591.    Max_LineNum--;
  592.    
  593.    return(0);
  594. }
  595.  
  596. unsigned char *remake_line(int size)
  597. {
  598.    char buf[80];
  599.    unsigned char *d = CLine->data;
  600. #ifdef msdos   
  601.    size = (unsigned) (size + 7) & 0xFFF8u;   /* 16 byte chunks */
  602. #else
  603.    size = (unsigned) (size + 15) & 0xFFFFFFF0;
  604. #endif
  605.    
  606.    if (d == NewLine_Buffer)
  607.      {
  608.     if (NULL != (d = (unsigned char *) SLMALLOC(size))) *d = '\n';
  609.      }
  610.    else d = (unsigned char *) SLREALLOC(d, size);
  611.    if (d == NULL)
  612.      {
  613.     *Error_Buffer = 0;           /* critical error */
  614.     sprintf(buf, "remake_line: realloc error!, size = %d", size);
  615.     msg_error(buf);
  616.     longjmp(Jump_Buffer_Ptr->b, 1);
  617.     /* exit_error(buf); */
  618.      }
  619.  
  620.    CLine->space = size;
  621.    CLine->data = d;
  622.    return(d);
  623. }
  624.  
  625. void uniquely_name_buffer(char *trry)
  626. {
  627.     Buffer *b;
  628.     int exists, version = 0, n;
  629.     char neew[48];
  630.  
  631.     *CBuf->name = 0;
  632.     strncpy(neew, trry, 45);  neew[45] = 0;
  633.    n = strlen(neew);
  634.     while (1)
  635.       {
  636.       exists = 0;
  637.       b = CBuf->next;
  638.       while(b != CBuf)
  639.         {
  640.         if (!strcmp(neew, b->name)) exists = 1;
  641.         b = b->next;
  642.         }
  643.       if (!exists)
  644.         {
  645.         strcpy(CBuf->name,neew);
  646.         return;
  647.         }
  648.       version++;
  649.       sprintf(neew + n, "<%d>", version);
  650.       }
  651. }
  652.  
  653. /* make a buffer and insert it in the list */
  654. Buffer *make_buffer()
  655. {
  656.     Buffer *newB;
  657.  
  658.    /* SLCALLOC used since it zeros region too */
  659.     newB = (Buffer *) SLCALLOC(sizeof(Buffer), 1);
  660.     if (newB == (Buffer *) NULL)
  661.       {
  662.           exit_error("make_buffer: malloc error", 0);
  663.       }
  664.  
  665.    MEMSET ((char *) newB, sizeof(Buffer), 0);
  666.    
  667.    newB->keymap = Global_Map;
  668.    newB->c_time = sys_time();
  669.    newB->tab = User_Vars.tab;
  670. #ifdef HAS_ABBREVS
  671.    newB->abbrev_table_handle = -1;
  672. #endif
  673.    
  674.    if (CBuf == NULL)
  675.      {
  676.     newB->next = newB;
  677.     newB->prev = newB;
  678.      }
  679.    else
  680.      {
  681.     newB->next = CBuf;
  682.     newB->prev = CBuf->prev;
  683.     CBuf->prev->next = newB;
  684.     CBuf->prev = newB;
  685.      }
  686.  
  687. #ifdef pc_system
  688.    newB->flags |= ADD_CR_ON_WRITE_FLAG;
  689. #endif
  690.    
  691.    return(newB);
  692. }
  693.  
  694. /* if there is a window attached to this buffer, then there are problems
  695.  *  if we get to update() without attaching another one to it.  So
  696.  *  beware! Always make sure CBuf is set too!   kill_buffer command
  697.  *  takes care of this */
  698. void delete_buffer(Buffer *buf)
  699. {
  700.    Line *l,*n;
  701.    Mark *m, *m1;
  702.  
  703.    while (buf->narrow != NULL) widen_buffer(buf);
  704.    if (buf -> beg != NULL) for (l = buf -> beg; l != NULL; l = n)
  705.      {
  706.     n = l -> next;
  707.     free_line(l);
  708.     /* SLFREE( l->data); SLFREE( l); */
  709.      }
  710.    m = buf->marks;
  711.    while (m != NULL)
  712.       {
  713.      m1 = m->next;
  714.      if (m == &buf->mark_array[buf->mark_ptr - 1])
  715.        {
  716.           buf->mark_ptr--;
  717.        }
  718.      else SLFREE(m);
  719.      m = m1;
  720.       }
  721.    m = buf->spots;
  722.    while (m != NULL)
  723.      {
  724.     m1 = m->next;
  725.     if (m == &buf->spot_array[buf->spot_ptr - 1])
  726.       {
  727.          buf->spot_ptr--;
  728.       }
  729.     else SLFREE(m);
  730.     m = m1;
  731.      }
  732.    
  733.    if (buf->user_marks != NULL) free_user_marks (buf);
  734.  
  735.    if (buf->undo != NULL) delete_undo_ring(buf);
  736.    buf->prev->next = buf->next;
  737.    buf->next->prev = buf->prev;
  738.  
  739.    SLFREE( buf);
  740. }
  741.  
  742. /* need to make this exploit MaxLine info! */
  743. void goto_line(int *np)
  744. {
  745.    unsigned int n;
  746.    unsigned int half1 = LineNum / 2;
  747.    unsigned int half2 = (Max_LineNum + LineNum) / 2;
  748.    
  749.    if (*np <= 1) n = 0; else n = (unsigned int) *np;
  750.    
  751.    if (n < LineNum)
  752.      {
  753.     if (n > half1) 
  754.       {
  755.          n = LineNum - n;
  756.          prevline((int *) &n);
  757.       }
  758.     else
  759.       {
  760.          bob(); n--;
  761.          nextline((int *) &n);
  762.       }
  763.      }
  764.    else if (n < half2)
  765.      {
  766.     n = n - LineNum;
  767.     nextline((int *) &n);
  768.      }
  769.    else
  770.      {
  771.     eob();
  772.     n = Max_LineNum - n;
  773.     prevline((int *) &n);
  774.      }
  775.    
  776. }
  777.  
  778. Line *dup_line(Line *l)
  779. {
  780.     Line *neew;
  781.     int n;
  782.     unsigned char *p, *q;
  783.  
  784.     neew = (Line *) SLMALLOC(sizeof(Line));
  785.     if ((neew == NULL) ||
  786.         (NULL == (neew->data = (unsigned char *) SLMALLOC(l->space))))
  787.       {
  788.           exit_error("Malloc Error in dup_line.", 0);
  789.       }
  790.     neew->next = l->next;
  791.     neew->prev = l->prev;
  792.     neew->len = l->len;
  793.     n = neew->space = l->space;
  794.     p = neew->data;
  795.     q = l->data;
  796.  
  797.     while (n--) *p++ = *q++;
  798.     return(neew);
  799. }
  800.  
  801. Buffer *find_buffer(char *name)
  802. {
  803.     Buffer *b;
  804.  
  805.     b = CBuf;
  806.     do
  807.       {
  808.       if (!strcmp(b->name, name)) return(b);
  809.       b = b->next;
  810.       }
  811.     while(b != CBuf);
  812.    
  813. #ifdef __os2__
  814.    b = CBuf;
  815.    do {
  816.       if (!strcmpi(b->name, name)) return(b);
  817.       b = b->next;
  818.    } while(b != CBuf);
  819. #endif
  820.     return(NULL);
  821. }
  822.  
  823. int buffer_exists(Buffer *b)
  824. {
  825.    Buffer *c = CBuf;
  826.    do
  827.      {
  828.     if (b == c) return 1;
  829.     c = c->next;
  830.      }
  831.    while (c != CBuf);
  832.    return 0;
  833. }
  834.  
  835. int switch_to_buffer(Buffer *buf)
  836. {
  837.    /* unlink buf */
  838.    /*  save this buffer position */
  839.    CBuf->line = CLine;
  840.    CBuf->point = Point;
  841.    CBuf->linenum = LineNum;
  842.    CBuf->max_linenum = Max_LineNum;
  843.    /* local variables */
  844.    CBuf->tab = Buffer_Local.tab;
  845.    CBuf->sd = Buffer_Local.sd;
  846.    
  847.    if (buf == CBuf) return(0);
  848.    buf->prev->next = buf->next;
  849.    buf->next->prev = buf->prev;
  850.  
  851.    buf->next = CBuf;
  852.    buf->prev = CBuf->prev;
  853.    CBuf->prev->next = buf;
  854.    CBuf->prev = buf;
  855.  
  856.  
  857.    /* now restore new buffer */
  858.    CBuf = buf;
  859.    CLine = CBuf->line;
  860.    Point = CBuf->point;
  861.    
  862.    /* Buffer local variables */
  863.    Buffer_Local.tab = CBuf->tab;
  864.    Buffer_Local.sd = CBuf->sd;
  865.    
  866.    LineNum = CBuf->linenum;
  867.    Max_LineNum = CBuf->max_linenum;
  868.    
  869.    if (CLine == NULL)
  870.      {
  871.     make_line(25);
  872.     Point = 0;
  873.      }
  874.    CBuf->line = CLine;
  875.    CBuf->point = Point;
  876.    return(1);
  877. }
  878.  
  879. /* we assume that file has already been expanded--- that is, canonical. */
  880. Buffer *find_file_buffer(char *file)
  881. {
  882.    Buffer *b;
  883.    char *f;
  884.    long n, m;
  885.    
  886.    f = extract_file(file);
  887.    n = f - file;
  888.    
  889.    b = CBuf;
  890.     do
  891.       {
  892.      m = strlen(b->dir);
  893. #ifndef __os2__
  894.      if ((m == n) && (!strcmp(b->file,f))
  895.          && (!strncmp(b->dir, file, (int) n)))
  896. #else
  897.       if ((m == n) && (!strcmpi(b->file,f))
  898.           && (!strncmpi(b->dir, file, (int) n)))
  899. #endif
  900.        return(b);
  901.           b = b->next;
  902.       }
  903.     while (b != CBuf);
  904.  
  905.     return(NULL);
  906. }
  907.  
  908. /* take a dir and a filename, expand them then put in buffer structure */
  909. void buffer_filename(char *dir, char *file)
  910. {
  911.    strcpy(CBuf->dir, dir);
  912.    if ((file == NULL) || (*file == 0))
  913.      {
  914.     file = extract_file(CBuf->dir);
  915.     strcpy(CBuf->file, file);
  916.     *file = 0;
  917.      }
  918.    else strcpy(CBuf->file, file);
  919.    uniquely_name_buffer(CBuf->file);
  920. }
  921.  
  922.  
  923. /* This kills all undo information! */
  924. int erase_buffer()
  925. {
  926.    Line *beg, *tthis;
  927.  
  928.    /* CLine = CBuf->end; */
  929.    beg = CBuf->beg;
  930.    bob();
  931.    CLine = CLine->next; LineNum++;
  932.    Suspend_Screen_Update = 1;
  933.    while(CLine != NULL)
  934.      {
  935.     tthis = CLine;
  936.     beg->next = tthis->next;
  937.     tthis->prev = beg;
  938.  
  939.     update_marks(LDELETE, 1);
  940.     CLine = tthis->next;
  941.     Max_LineNum--;
  942.     free_line(tthis);
  943.      }
  944.    
  945.    CLine = CBuf->beg; LineNum = 1;
  946.    Point = 0;
  947.    update_marks(CDELETE, CLine->len);
  948.    CLine->len = 0;
  949.    /*   CLine->next = NULL; */
  950.    if (CBuf->undo != NULL) delete_undo_ring(CBuf);
  951.    CBuf->undo = NULL;
  952.    CBuf->end = CLine;
  953.    touch_screen_for_buffer(CBuf);
  954.    return(1);
  955. }
  956.  
  957. void mark_buffer_modified(int *flag)
  958. {
  959.    unsigned long now;
  960.  
  961.    if (*flag)
  962.      {
  963.     if (CBuf->flags & BUFFER_TRASHED) return;
  964.     now = sys_time();
  965.     CBuf->m_time = now;
  966.     CBuf->flags |= BUFFER_TRASHED;
  967.     return;
  968.      }
  969.    else CBuf->flags &= ~BUFFER_TRASHED;
  970. }
  971.  
  972. void check_line()
  973. {
  974.    if ((CLine->len == 1) && (*CLine->data == '\n') && (CLine->data != NewLine_Buffer))
  975.      {
  976.     SLFREE(CLine->data);
  977.     CLine->data = NewLine_Buffer;
  978.     CLine->space = 1;
  979.      }
  980. }
  981.  
  982.     
  983.