home *** CD-ROM | disk | FTP | other *** search
/ Best Objectech Shareware Selections / UNTITLED.iso / boss / word / text / 019 / cmds.c < prev    next >
C/C++ Source or Header  |  1993-01-19  |  23KB  |  1,154 lines

  1. /*
  2.  *  Copyright (c) 1992 John E. Davis  (davis@amy.tch.harvard.edu)
  3.  *  All Rights Reserved.
  4.  */
  5. #include <stdio.h>
  6. #include <string.h>
  7.  
  8. #include "slang.h"
  9. #include "buffer.h"
  10. #include "screen.h"
  11. #include "window.h"
  12. #include "ins.h"
  13. #include "ledit.h"
  14. #include "cmds.h"
  15. #include "line.h"
  16. #include "paste.h"
  17. #include "display.h"
  18. #include "vterm.h"
  19. #include "sysdep.h"
  20. #include "text.h"
  21. #include "file.h"
  22. #include "misc.h"
  23. #include "search.h"
  24.  
  25. int Last_Command_Char;
  26. int Blink_Flag = 1;
  27.  
  28. static char *Top_Of_Buffer_Error = "Top Of Buffer.";
  29. static char *End_Of_Buffer_Error = "End Of Buffer.";
  30.  
  31. /* return 1 if line extends beyond the screen */
  32. int long_line(void)
  33. {
  34.     int p, col;
  35.  
  36.     col = Screen_Col;
  37.     p = Point;
  38.     Point = CLine->len - 1;
  39.     if (*(CLine->data + Point) != '\n') Point++;
  40.     if (calculate_column() >= Window->width - 1)
  41.       {
  42.       Point = p;
  43.       Screen_Col = col;
  44.       return(1);
  45.       }
  46.     Screen_Col = col;
  47.     Point = p;
  48.     return(0);
  49. }
  50.  
  51. #define FAST_NOT_OK ((Repeat_Factor != NULL) || Window->trashed\
  52.         || (ch < ' ') || (ch > 126)\
  53.         || (Screen_Col >= Window->width - 2) || (Window->column > 1)\
  54.     || input_pending(2, 0) || long_line() || tabs_present())
  55.  
  56. /* This routine moves CLine and point to the matching '{' or whatever.  It
  57.    returns 1 if it lies outside the screen, 0 if inside and -1 if not found
  58.    and -2 if it looked back for more than 100 lines and not found.  It
  59.    can get messed up if there are delimeters in comments unless they are
  60.    properly enclosed like the above */
  61.  
  62. /* count is the number of lines to go back and shift is distance back to
  63.    start searching from. (usually 0, 1, or 2) */
  64. int find_matching(char ch, int count, int shift)
  65. {
  66.    int n = 1, slash, ret = 0, lang = ! (CBuf->modes == WRAP_MODE);
  67.    unsigned char *p, *prev, *p1;
  68.    char ch1, in, save;
  69.    char quote = '\\';
  70.    char cb1 = '/', cb2 = '*', ce1 = '*', ce2  = '/';
  71.    int inc = 0;
  72.    
  73.  
  74.     ch1 = '(';
  75.     if (ch == '}') ch1 = '{'; else if (ch == ']') ch1 = '[';
  76.  
  77.     p = CLine->data + Point - shift;
  78.     if (p < CLine->data)
  79.       {
  80.           if (CLine->prev == NULL) return(-1);
  81.           if (CLine == Window->beg.line) ret = 1;
  82.           CLine = CLine->prev;
  83.       p = CLine->data + (CLine->len - 1);
  84.        }
  85.      in = 0;
  86.      if (Point > 1) prev = p - 1; else prev = p;
  87.  
  88.     while(count)
  89.       {
  90.      p1  = p - 1;
  91.      if (lang && !inc && ((*p == '\'') || (*p == '"')))
  92.        {
  93.           slash = 0;
  94.           save = *p;
  95.           while((p > CLine->data) && (*(p - 1) == quote))
  96.         {
  97.            p--;
  98.            slash = !slash;
  99.         }
  100.  
  101.           if (!slash)
  102.         {
  103.            if (in == 0) in = save; else if (in == save) in = 0;
  104.         }
  105.        }
  106.      
  107.           
  108.           if (!in)
  109.             {
  110.            /* This is specific to C.  I need to generalize to other languages. */
  111.            if (lang && (ce2 == *p) && (p > CLine->data)
  112.            && (*p1 == ce1))
  113.          {
  114.             p = p1;
  115.             inc = 1;
  116.          }
  117.            else if (lang && (cb2 == *p) && (p > CLine->data) 
  118.            && (*p1 == cb1))
  119.          {
  120.             if (inc == 0) return (-2);
  121.             p = p1;
  122.             inc = 0;
  123.          }
  124.            
  125.            if (!inc && ((*p == '[') || (*p == '{') || (*p == '('))) n--;
  126.            else if (!inc && ((*p == '}') || (*p == ']') || (*p == ')'))) n++;
  127.             }
  128.  
  129.           if (!n) break;
  130.           if ((p == CLine->data) && (CLine == Window->beg.line)) ret = 1;
  131.           if (p == CLine->data)
  132.             {
  133.                 if (CLine->prev == NULL) break;
  134.                 CLine = CLine->prev;
  135.                 count--;
  136.                 p = CLine->data + (CLine->len - 1);
  137.             }
  138.           else p--;
  139.       }
  140.     Point = (int) (p - CLine->data);
  141.     if ((n == 0) && (*p == ch1)) return(ret);
  142.     if (lang) if ((*prev == '\'') || (*prev == '"')) return(-2);
  143.     return(-1);
  144. }
  145.  
  146. /* blink the matching fence.  This assumes that the window is ok */
  147. void blink_match(char ch)
  148. {
  149.    Line *save;
  150.    int pnt, code, matchp;
  151.    char buf[600];
  152.  
  153.    if (!Blink_Flag || (Repeat_Factor != NULL) || Window->trashed) return;
  154.    pnt = Point;
  155.    save = CLine;
  156.    code = find_matching(ch, 100, 2);
  157.    if (code == -1)
  158.      {
  159.     if ((! (CBuf->modes == WRAP_MODE)) && (!IS_MINIBUFFER)) message("Mismatch??");
  160.      }
  161.    else if (code == 0)
  162.      {
  163.     point_cursor();
  164.     fflush(stdout);
  165.     input_pending(2,1);   /* sleep((unsigned) 1); */
  166.     Point = pnt;
  167.     CLine = save;
  168.     point_cursor();
  169.     return;
  170.      }
  171.    else if (code == 1)
  172.      {
  173.     matchp = Point;
  174.     Point = 0;
  175.     strcpy(buf, "Matches ");
  176.     skip_whitespace();
  177.     if ((matchp == Point) && prevline(&Number_One))
  178.       {
  179.          Point = 0;
  180.          strcat(buf, buffer_substring());
  181.          nextline(&Number_One);
  182.          Point = 0;
  183.       }
  184.     strcat(buf, buffer_substring());
  185.     message(buf);
  186.      }
  187.    Point = pnt;
  188.    CLine = save;
  189. }
  190.  
  191. int goto_match()
  192. {
  193.     char *p;
  194.     Line *save;
  195.     int pnt, code;
  196.  
  197.     p = (char *) (CLine->data + Point);
  198.     if ((*p != ')') && (*p != '}') && (*p != ']')) return(0);
  199.     save = CLine;
  200.     pnt = Point;
  201.     code = find_matching(*p, -1, 1);  /* -1 since we want to shif back 1 */
  202.     if (code == -1)
  203.       {
  204.      if (!IS_MINIBUFFER) msg_error("Mismatch!!");
  205.      CLine = save;
  206.      Point = pnt;
  207.      return(0);
  208.       }
  209.     return(1);
  210. }
  211.  
  212. int newline()
  213. {
  214.     int push = 0;
  215.  
  216.     if (bolp() && (CLine->prev != NULL))
  217.       {
  218.           push = 1;
  219.           push_spot();
  220.           CLine = CLine->prev;
  221.       Point = 0;
  222.           eol();
  223.       }
  224.  
  225.     split_line();
  226.     ins('\n');
  227.     if (push)
  228.       {
  229.           pop_spot();
  230.           return(1);
  231.       }
  232.  
  233.     Point--;
  234.     forwchars(&Number_One);
  235.     return(1);
  236. }
  237.  
  238. int previous_char_cmd()
  239. {
  240.    int pnt;
  241.    Cursor_Motion = 1;
  242.    if (bobp())
  243.      {
  244.     msg_error(Top_Of_Buffer_Error);
  245.     return(0);
  246.      }
  247.  
  248.    pnt = Point - 1;
  249.    backwchars(&Number_One);
  250.    Goal_Column = calculate_column();
  251.    return((pnt == -1) || Window->trashed);
  252. }
  253.  
  254. /* Slang calls by reference so make this a pointer ! */
  255. void insert_whitespace(int *n)
  256. {
  257.    int tab = User_Vars.tab;
  258.    int c1, c2, i, k, nspace;
  259.  
  260.    if ((nspace = *n) <= 0) return;
  261.    c1 = calculate_column() - 1;
  262.    c2 = c1 + nspace;
  263.  
  264.    if (tab)
  265.      {
  266.     i = c1 / tab;
  267.     k = c2 / tab - i;
  268.     if (k) nspace = c2 - (i + k) * tab;
  269.     ins_char_n_times('\t', k);
  270.      }
  271.    ins_char_n_times(' ', nspace);
  272. }
  273.  
  274. /* check from point to end of line looking for tabs */
  275. int tabs_present(void)
  276. {
  277.     unsigned char *p, *pmax;
  278.  
  279.     if (!User_Vars.tab) return(0);
  280.     pmax = CLine->data + CLine->len;
  281.     p = CLine->data + Point;
  282.  
  283.     while (p < pmax) if (*p++ == '\t') return(1);
  284.     return(0);
  285. }
  286.  
  287. int delete_char_cmd()
  288. {
  289.     int upd;
  290.     char ch;
  291.  
  292.     if (eobp())
  293.       {
  294.           msg_error(End_Of_Buffer_Error);
  295.           return(0);
  296.       }
  297.  
  298.     ch = *(CLine->data + Point);
  299.  
  300.     if (FAST_NOT_OK)
  301.       {
  302.           del();
  303.           upd = 1;
  304.       }
  305.     else
  306.       {
  307.           fast_del();
  308.           tt_delete_char();
  309.           upd = 0;
  310.       }
  311.  
  312.     return(upd);
  313. }
  314.  
  315. int backward_delete_char_cmd()
  316. {
  317.     char ch;
  318.  
  319.     if (bobp())
  320.       {
  321.           msg_error(Top_Of_Buffer_Error);
  322.           return(0);
  323.       }
  324.  
  325.     if (bolp())
  326.       {
  327.           backwchars(&Number_One);
  328.           del();
  329.           return(1);
  330.       }
  331.  
  332.     ch = *(CLine->data + (Point - 1));
  333.  
  334.     if (FAST_NOT_OK)
  335.       {
  336.       backwchars(&Number_One);
  337.       del();
  338.       return(1);
  339.       }
  340.  
  341.     backwchars(&Number_One);
  342.     putc('\b',stdout);
  343.     Screen_Col--;
  344.     fast_del();
  345.     tt_delete_char();
  346.     return(0);
  347. }
  348.  
  349. int backward_delete_char_untabify()
  350. {
  351.     unsigned char *p;
  352.     int n;
  353.  
  354.     p = CLine->data + (Point - 1);
  355.  
  356.     /* note that short circuit is assumed to avoid seg fault */
  357.     if (!Point || bobp() || (*p != '\t') || !User_Vars.tab) return backward_delete_char_cmd();
  358.  
  359.     n = calculate_column() - 1;
  360.     backwchars(&Number_One);
  361.     del();
  362.     n = n - calculate_column();
  363.     ins_char_n_times(' ', n);
  364.  
  365.     return(1);
  366. }
  367.  
  368. int previous_line_cmd()
  369. {
  370.    int ret, gc;
  371.  
  372.    if (CLine == CBuf->beg)
  373.      {
  374.           msg_error(Top_Of_Buffer_Error);
  375.           return(0