home *** CD-ROM | disk | FTP | other *** search
/ Der Mediaplex Sampler - Die 6 von Plex / 6_v_plex.zip / 6_v_plex / DISK5 / DOS_50 / PVIC.ZIP / EDIT.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  8KB  |  354 lines

  1. /* 
  2.  *
  3.  * The main edit loop as well as some other simple cursor movement routines.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include "pvic.h"
  8. #include "locdefs.h"
  9.  
  10. /*
  11.  * This flag is used to make auto-indent work right on lines where only
  12.  * a <RETURN> or <ESC> is typed. It is set when an auto-indent is done,
  13.  * and reset when any other editting is done on the line. If an <ESC>
  14.  * or <RETURN> is received, and did_ai is (1), the line is truncated.
  15.  */
  16. int     did_ai = (0);
  17.  
  18. void edit()
  19. {
  20.     extern  int     need_redraw;
  21.     int     c;
  22.     register char   *p, *q;
  23.  
  24.     prenum = 0;
  25.  
  26.     /* position the display and the cursor at the top of the file. */
  27.     *top_char = *file_memory;
  28.     *cursor_char = *file_memory;
  29.     cursor_row = cursor_column = 0;
  30.  
  31.     update_screen(0);
  32.  
  33.     for ( ;; ) {
  34.  
  35.         /* Figure out where the cursor is based on cursor_char. */
  36.         update_cursor(0);
  37.  
  38.         if(!is_input_pending())
  39.         {
  40.             if(need_redraw)update_screen(0);
  41.             goto_screen_pos(cursor_row,cursor_column);
  42.         }
  43.  
  44.         c = get_char_from_input_buffer();
  45.  
  46.         if (current_status == STATUS_NORMAL) {
  47.  
  48.             /* We're in the normal (non-insert) mode. */
  49.  
  50.             /* Pick up any leading digits and compute 'prenum' */
  51.             if ( (prenum>0 && is_digit(c)) || (is_digit(c) && c!='0') ){
  52.                 prenum = prenum*10 + (c-'0');
  53.                 continue;
  54.             }
  55.             /* execute the command */
  56.             normal(c);
  57.             prenum = 0;
  58.  
  59.         } else {
  60.  
  61.         /*
  62.          * Insert or Replace mode.
  63.          */
  64.             changed=1;
  65.             switch (c) {
  66.  
  67.             case ESC:       /* an escape ends input mode */
  68.  
  69.                 /*
  70.                  * If we just did an auto-indent, truncate the
  71.                  * line, and put the cursor back.
  72.                  */
  73.                 if (did_ai) {
  74.                     cursor_char->linep->s[0] = '\0';
  75.                     cursor_char->index = 0;
  76.                     did_ai = (0);
  77.                 }
  78.  
  79.                 set_wanted_cursor_column = (1);
  80.  
  81.                 /* Don't end up on a '\n' if you can help it. */
  82.                 if (gchar(cursor_char) == '\0' && cursor_char->index != 0)
  83.                     dec(cursor_char);
  84.  
  85.                 /*
  86.                  * The cursor should end up on the last inserted
  87.                  * character. This is an attempt to match the real
  88.                  * 'vi', but it may not be quite right yet.
  89.                  */
  90.                 if (cursor_char->index != 0 && !end_of_line(cursor_char))
  91.                     dec(cursor_char);
  92.  
  93.                 current_status = STATUS_NORMAL;
  94.                 msg("");
  95.  
  96.                 /* construct the Redo buffer */
  97.                 p=redo_buffer;
  98.                 q=insert_buffer;
  99.                 while ( q < insert_pointer )
  100.                     *p++ = *q++;
  101.                 *p++ = ESC;
  102.                 *p = '\0';
  103.                 update_screen(0);
  104.                 break;
  105.  
  106.             case CTRL_D:
  107.                 /*
  108.                  * Control-D is treated as a backspace in insert
  109.                  * mode to make auto-indent easier. This isn't
  110.                  * completely compatible with vi, but it's a lot
  111.                  * easier than doing it exactly right, and the
  112.                  * difference isn't very noticeable.
  113.                  */
  114.             case CTRL_H:
  115.                 /* can't backup past starting point */
  116.                 if (cursor_char->linep == start_insert->linep &&
  117.                     cursor_char->index <= start_insert->index) {
  118.                     beep();
  119.                     break;
  120.                 }
  121.  
  122.                 /* can't backup to a previous line */
  123.                 if (cursor_char->linep != start_insert->linep &&
  124.                     cursor_char->index <= 0) {
  125.                     beep();
  126.                     break;
  127.                 }
  128.  
  129.                 did_ai = (0);
  130.                 dec(cursor_char);
  131.                 if (current_status == STATUS_INSERT)
  132.                     delete_char((1));
  133.                 /*
  134.                  * It's a little strange to put backspaces into
  135.                  * the redo buffer, but it makes auto-indent a
  136.                  * lot easier to deal with.
  137.                  */
  138.                 *insert_pointer++ = CTRL_H;
  139.                 insert_n++;
  140.                 update_cursor(0);
  141.                 update_line(0);
  142.                 break;
  143.  
  144.                 case CTRL_J:
  145.                 case CTRL_M:
  146.                 if (current_status == STATUS_REPLACE)    
  147.                 {
  148.                     current_status = STATUS_NORMAL;
  149.                     msg("");
  150.  
  151.                     /* construct the Redo buffer */
  152.                     p=redo_buffer;
  153.                     q=insert_buffer;
  154.                     while ( q < insert_pointer )
  155.                         *p++ = *q++;
  156.                     *p++ = ESC;
  157.                     *p = '\0';
  158.                     if (!line_empty())
  159.                         inc(cursor_char);
  160.                     u_save_line();
  161.                     do_start_insert(mkstr(c), (0));
  162.                 }
  163.                 *insert_pointer++ = '\n';
  164.                 insert_n++;
  165.                 open_command(SEARCH_FORWARD, (1));          /* open a new line */
  166.                 break;
  167.  
  168.             default:
  169.                 did_ai = (0);
  170.                 insert_char(c);
  171.                 break;
  172.             }
  173.         }
  174.     }
  175. }
  176.  
  177. void insert_char(c)
  178. int     c;
  179. {
  180.     inschar(c);
  181.     *insert_pointer++ = c;
  182.     insert_n++;
  183.     /*
  184.      * The following kludge avoids overflowing the statically
  185.      * allocated insert buffer. Just dump the user back into
  186.      * command mode, and print a message.
  187.      */
  188.     if (insert_pointer+10 >= &insert_buffer[1024]) {
  189.         put_string_into_input_buffer(mkstr(ESC));
  190.         error_message("No buffer space, returning to command mode");
  191.         loop_n_seconds(3);
  192.     }
  193.     update_line();
  194. }
  195.  
  196. void get_out()
  197. {
  198.     goto_screen_pos(current_lines-1,0);
  199.     putc('\n',stdout);
  200.     pvic_exit(0);
  201. }
  202.  
  203. void scroll_down(nlines)
  204. int     nlines;
  205. {
  206.     register LPTR   *p;
  207.     register int    done = 0;       /* total # of physical lines done */
  208.  
  209.     /* Scroll up 'nlines' lines. */
  210.     while (nlines--) {
  211.         if ((p = previous_line(top_char)) == NULL)
  212.             break;
  213.         done += plines(p);
  214.         *top_char = *p;
  215.         /*
  216.          * If the cursor is on the bottom line, we need to
  217.          * make sure it gets moved up the appropriate number
  218.          * of lines so it stays on the screen.
  219.          */
  220.         if (cursor_char->linep == bottom_char->linep->prev) {
  221.             int     i = 0;
  222.             while (i < done) {
  223.                 i += plines(cursor_char);
  224.                 *cursor_char = *previous_line(cursor_char);
  225.             }
  226.         }
  227.     }
  228. }
  229.  
  230. void scroll_up(nlines)
  231. int     nlines;
  232. {
  233.     register LPTR   *p;
  234.     register int    done = 0;       /* total # of physical lines done */
  235.     register int    pl;             /* # of plines for the current line */
  236.  
  237.     /* Scroll down 'nlines' lines. */
  238.     while (nlines--) {
  239.         pl = plines(top_char);
  240.         if ((p = next_line(top_char)) == NULL)
  241.             break;
  242.         done += pl;
  243.         if (cursor_char->linep == top_char->linep)
  244.             *cursor_char = *p;
  245.         *top_char = *p;
  246.  
  247.     }
  248. }
  249.  
  250. /*
  251.  * one_right
  252.  * one_left
  253.  * one_down
  254.  * one_up
  255.  *
  256.  * Move one char {right,left,down,up}.  Return (1) when
  257.  * successful, (0) when we hit a boundary (of a line, or the file).
  258.  */
  259.  
  260. int one_right()
  261. {
  262.     set_wanted_cursor_column = (1);
  263.  
  264.     switch (inc(cursor_char)) {
  265.  
  266.     case 0:
  267.         return (1);
  268.  
  269.     case 1:
  270.         dec(cursor_char);          /* crossed a line, so back up */
  271.         /* fall through */
  272.     }
  273.     /*NOTREACHED*/
  274.     return (0);             /* v1.1 cut out Turbo C complaints */
  275. }
  276.  
  277. int one_left()
  278. {
  279.     set_wanted_cursor_column = (1);
  280.  
  281.     switch (dec(cursor_char)) {
  282.  
  283.     case 0:
  284.         return (1);
  285.  
  286.     case 1:
  287.         inc(cursor_char);          /* crossed a line, so back up */
  288.         /* fall through */
  289.     }
  290.     /*NOTREACHED*/
  291.     return (0);             /* v1.1 cut out Turbo C complaints */
  292. }
  293.  
  294. void begin_line(flag)
  295. int     flag;
  296. {
  297.     while ( one_left() )
  298.         ;
  299.     if (flag) {
  300.         while (is_space(gchar(cursor_char)) && one_right())
  301.             ;
  302.     }
  303.     set_wanted_cursor_column = (1);
  304. }
  305.  
  306. int one_up(n)
  307. int     n;
  308. {
  309.     LPTR    p, *np;
  310.     register int    k;
  311.  
  312.     p = *cursor_char;
  313.     for ( k=0; k<n; k++ ) {
  314.         /* Look for the previous line */
  315.         if ( (np=previous_line(&p)) == NULL ) {
  316.             /* If we've at least backed up a little .. */
  317.             if ( k > 0 )
  318.                 break;  /* to update the cursor, etc. */
  319.             else
  320.                 return (0);
  321.         }
  322.         p = *np;
  323.     }
  324.     *cursor_char = p;
  325.     /* This makes sure top_char gets updated so the complete line */
  326.     /* is one the screen. */
  327.     update_cursor(0);
  328.     /* try to advance to the column we want to be at */
  329.     *cursor_char = *advance_column(&p, wanted_cursor_column);
  330.     return (1);
  331. }
  332.  
  333. int one_down(n)
  334. int     n;
  335. {
  336.     LPTR    p, *np;
  337.     register int    k;
  338.  
  339.     p = *cursor_char;
  340.     for ( k=0; k<n; k++ ) {
  341.         /* Look for the next line */
  342.         if ( (np=next_line(&p)) == NULL ) {
  343.             if ( k > 0 )
  344.                 break;
  345.             else
  346.                 return (0);
  347.         }
  348.         p = *np;
  349.     }
  350.     /* try to advance to the column we want to be at */
  351.     *cursor_char = *advance_column(&p, wanted_cursor_column);
  352.     return (1);
  353. }
  354.