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

  1. /*
  2.  *  Copyright (c) 1992, 1994 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include <string.h>
  7.  
  8. #include "config.h"
  9. #include "buffer.h"
  10. #include "ins.h"
  11. #include "line.h"
  12. #include "screen.h"
  13. #include "window.h"
  14. #include "misc.h"
  15. #include "paste.h"
  16. #include "vterm.h"
  17. #include "ledit.h"
  18. #include "undo.h"
  19.  
  20. int Suspend_Screen_Update = 0;
  21.  
  22. void update_generic_marks(register Mark *m, register int type, int n)
  23. {
  24.    int tmp;
  25.    if (m == NULL) return;
  26.    
  27.    if (type == CINSERT) while(m != NULL)
  28.      {
  29.     if ((m->line == CLine) && (m->point > Point))
  30.       {
  31.          m->point += n;
  32.       }
  33.     m = m->next;
  34.      }
  35.    else if (type == CDELETE) while(m != NULL)
  36.      {
  37.     if ((m->line == CLine) && (m->point > Point))
  38.       {
  39.          /* BCC generates wrong code here with optimization */
  40.          tmp = m->point;
  41.          tmp -= n;
  42.          if (tmp < Point) tmp = Point;
  43.          m->point = tmp;
  44.          
  45.          /*
  46.           BAD CODE:
  47.          m->point -= n;
  48.          if (m->point < Point) m->point = Point; */
  49.       }
  50.     m = m->next;
  51.      }
  52.    
  53.    
  54.    /* called by line deletion routines */
  55.    else if (type == LDELETE) while(m != NULL)
  56.      {
  57.     if (CLine == m->line)
  58.       {
  59.          if (CLine->prev != NULL)
  60.            {
  61.           m->line = CLine->prev;
  62.            }
  63.          else m->line = CBuf->beg;
  64.          m->point = 0;
  65.       }
  66.     if (LineNum + CBuf->nup <= m->n) m->n -= 1;
  67.     m = m->next;
  68.      }
  69.    
  70.    /* newline added-- affects only marks onward from insertion point */
  71.     else if (type == NLINSERT) while(m != NULL)
  72.       {
  73.      /* This is a bit controversial if the mark corresponds to JWindow->beg.
  74.         In this case, JWindow beg gets shifted if Point = 0.  */
  75.      
  76.      if ((LineNum + CBuf->nup < m->n) 
  77.          || ((LineNum + CBuf->nup == m->n) && (m->point > Point))) m->n += 1;
  78.         
  79.      if ((m->line == CLine) && (m->point > Point))
  80.             {
  81.            m->line = CLine->next;
  82.            m->point -= Point;
  83.            if (m->point > m->line->len) m->point = m->line->len;
  84.             }
  85.      m = m->next;
  86.       }
  87.    
  88.    /* deletion performed at end of a line (CLine->prev)  */
  89.     else if (type == NLDELETE) while(m != NULL)
  90.       {
  91.      if (m->line == CLine)
  92.        {
  93.           m->line = CLine->prev;
  94.           m->point += Point;
  95.        }
  96.      if (LineNum + CBuf->nup <= m->n) m->n -= 1;
  97.      m = m->next;
  98.       }
  99. }
  100.  
  101. void update_marks(int type, int n)
  102. {
  103.    register Window_Type *w;
  104.    register Buffer *b = CBuf;
  105.    Mark *m;
  106.    
  107.    if (!n) return;
  108.    Cursor_Motion = 0;
  109.    if (b->flags & UNDO_ENABLED)
  110.      {
  111.     if (b->undo == NULL) create_undo_ring();
  112.     Undo_Buf_Unch_Flag = !(b->flags & BUFFER_TRASHED);
  113.      }
  114.    
  115.    mark_buffer_modified(&Number_One);
  116.    if ((m = b->spots) != NULL) update_generic_marks(m, type, n);
  117.    if ((m = b->marks) != NULL) update_generic_marks(m, type, n);
  118.    if ((m = b->user_marks) != NULL) update_generic_marks(m, type, n);
  119.    
  120.    w = JWindow;
  121.    do
  122.      {
  123.     if (w->buffer == b)
  124.       {
  125.          update_generic_marks(&w->mark, type, n);
  126.          update_generic_marks(&w->beg, type, n);
  127.       }
  128.  
  129.     w = w->next;
  130.      }
  131.    while(w != JWindow);
  132.  
  133.    if (!Suspend_Screen_Update) register_change(type);
  134. }
  135.  
  136. void ins(char c)
  137. {
  138.    register unsigned char *p, *p1, *p2;
  139.  
  140.     if (CLine == NULL)
  141.       {
  142.           exit_error("ins: CLine is NULL", 1);
  143.       }
  144.  
  145.     if (CLine->space <= CLine->len + 1)
  146.       {
  147.           remake_line(CLine->space + 15);
  148.       }
  149.  
  150.     p = CLine->data + Point;
  151.     if (Point < CLine->len)
  152.       {
  153.           p1 = CLine->data + (CLine->len - 1);
  154.      p2 = p1 + 1;
  155.           while(p1 >= p)
  156.             {
  157.            *p2 = *p1;
  158.            p2 = p1;
  159.            p1--;
  160.            /* *(p1 + 1) = *p1; p1--; */
  161.             }
  162.       }
  163.     *p = c;
  164.     CLine->len += 1;
  165.     update_marks(CINSERT,1);
  166.    if ((c != '\n') || (CBuf == MiniBuffer)) record_insertion(1);
  167.     Point++;
  168. }
  169.  
  170.  
  171.  
  172. void del_newline(void)
  173. {
  174.    CHECK_READ_ONLY_VOID
  175.    
  176.    if (!eol() || eobp()) return;
  177. #ifdef DEBUG_JED
  178.    if (CLine->len == 0)
  179.      {
  180.     exit_error("del(): empty line", 1);
  181.      }
  182. #endif
  183.    
  184.    CLine->len -= 1;
  185.    update_marks(CDELETE,1);
  186.    record_deletion((unsigned char *) "\n", 1);
  187.    splice_line();
  188. }
  189.  
  190. /* del *np chars up until newline.  Return actual number deleted */
  191. int deln(int *np)
  192. {
  193.    int n = *np;
  194.    register int nn;
  195.    register unsigned char *p, *pmax;
  196.    
  197.    if ((n == 0) || !CLine->len) return(0);
  198.    
  199.    nn = CLine->len - 1;
  200.    p = CLine->data + nn;
  201.    if ((*p == '\n') && (CBuf != MiniBuffer)) nn = nn - Point; else nn = nn - Point + 1;
  202.    
  203.    p = CLine->data + Point;
  204.  
  205.    nn = nn > n ? n : nn;
  206.    if (!nn) return (0);
  207.    update_marks(CDELETE, nn);
  208.    record_deletion(p, nn);
  209.    CLine->len -= nn;
  210.    pmax = CLine->data + CLine->len;
  211.    while (p < pmax)
  212.      {
  213.     *p = *(p + nn);
  214.     p++;
  215.      }
  216.    return(nn);
  217. }
  218.  
  219.  
  220. /* delete n characters, crossing nl if necessary */
  221. void generic_deln(int *np)
  222. {
  223.    int n = *np;
  224.  
  225.    CHECK_READ_ONLY_VOID
  226.    
  227.    while(n > 0)
  228.      {
  229.     if (eobp())
  230.       {
  231.          msg_error("End of Buffer.");
  232.          return;
  233.       }
  234.     n -= deln(&n);
  235.     if (n) del_newline();
  236.     n--;
  237.      }
  238. }
  239.  
  240.  
  241. void del()
  242. {
  243.    generic_deln(&Number_One);
  244. }
  245.  
  246. void quick_insert(register unsigned char *s, int n)
  247. {
  248.    register unsigned char *p, *p1;
  249.    int nl = 0;
  250.    
  251.    if (n == 0) return;
  252.    if ((*(s + (n - 1)) == '\n') && (CBuf != MiniBuffer))
  253.      {
  254.     n--;
  255.     nl = 1;
  256.      }
  257.    
  258.    if (CLine->space <= CLine->len + n + 1)
  259.      {
  260.     remake_line(CLine->space + n + 8);
  261.      }
  262.    
  263.    /* shove n chars over to make space */
  264.    p = CLine->data + Point;
  265.    if (Point < CLine->len)   /* could be equal for last line of buffer */
  266.      {
  267.     p1 = CLine->data + CLine->len - 1;
  268.     while(p1 >= p)
  269.       {
  270.          *(p1 + n) = *p1;
  271.          p1--;
  272.       }
  273.      }
  274.    CLine->len += n;
  275.    MEMCPY((char *) p, (char *) s, n);
  276.    
  277.    update_marks(CINSERT, n);
  278.    record_insertion(n);
  279.    Point += n;
  280.  
  281.    if (nl)
  282.      {
  283.     split_line();
  284.     ins('\n');
  285.     CLine = CLine->next;
  286.     LineNum++;
  287.     Point = 0;
  288.      }
  289. }
  290.  
  291.  
  292.  
  293.  
  294. void ins_chars(unsigned char *ss, int n)
  295. {
  296.    register unsigned char nl, *pmax;
  297.    register unsigned char *p, *p1, *s = ss;
  298.    int n1;
  299.    
  300.    if (CBuf == MiniBuffer) nl = 0; else nl = '\n';
  301.    
  302.    p = p1 = s;
  303.    
  304.    /* count the number until a new line is reached */
  305.    pmax = p1 + n;
  306.    while((p1 < pmax) && (*p1 != nl)) p1++;
  307.  
  308.    n1 = (int) (p1 - p);
  309.    if (p1 != pmax) n1++;
  310.    quick_insert(s, n1);
  311.    if (p1++ == pmax) return;
  312.    ins_chars(p1, n - n1);
  313. }
  314.  
  315. /* This needs fixed to handle large n */
  316. void ins_char_n_times(char c, int n)
  317. {
  318.     char b[256], *p;
  319.     int n1;
  320.  
  321.     if (n == 0) return;
  322.     if (n > 255) n = 255;
  323.     p = b;
  324.     n1 = n;
  325.     while(n1--) *p++ = c;
  326.     ins_chars((unsigned char *) b, n);
  327. }
  328.  
  329. void insert_buffer(Buffer *b)
  330. {
  331.    Buffer *cb;
  332.  
  333.    if ((cb = CBuf) == b) return;
  334.  
  335.    switch_to_buffer(b);
  336.    push_spot();
  337.    bob(); push_mark();
  338.    eob();
  339.    copy_region_to_buffer(cb);
  340.    pop_spot();
  341.    switch_to_buffer(cb);
  342.  
  343.    touch_window();
  344. }
  345.  
  346. int No_Screen_Update;
  347.  
  348. void fast_ins(char ch)
  349. {
  350.     if (JWindow == JWindow->next) No_Screen_Update = 1;
  351.     vins(ch);
  352.     ins(ch);
  353. }
  354.  
  355. void fast_del()
  356. {
  357.     if (JWindow == JWindow->next) No_Screen_Update = 1;
  358.     vdel();
  359.     del();
  360. }
  361.  
  362. void replace_char(unsigned char ch)
  363. {
  364.    if (ch == '\n') return;
  365.    if (*(CLine->data + Point) == ch) return;
  366.    ins(ch); del(); Point--;
  367. }
  368.