home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 10 / c_colu / editor.c next >
Text File  |  1988-08-30  |  22KB  |  746 lines

  1. /* ----------------------- editor.c ---------------------- */
  2.  
  3. #include <stdio.h>
  4. #include <ctype.h>
  5. #include <conio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <mem.h>
  9. #include <ctype.h>
  10. #include <alloc.h>
  11. #include "window.h"
  12. #include "editor.h"
  13.  
  14. #define NEXTTAB (TAB-(ev.curr_x%TAB))
  15. #define LASTTAB ((ev.wwd/TAB)*TAB)
  16. #define PREVTAB (((ev.curr_x-1)%TAB)+1)
  17.  
  18. struct edit_env ev;         /* the editor environment      */
  19. int do_display_text = TRUE; /* turns display on/off        */
  20. extern struct wn wkw;       /* the current window          */
  21. int forcechar;              /* externally force a kb char  */
  22. void (*status_line)(void);  /* called once each keystroke  */
  23. void (*editfunc)(int);      /* for unknown keystrokes      */
  24.  
  25. /* ---------- local function prototypes ----------- */
  26. static int lastword(void);
  27. static void last_char(void);
  28. static void test_para(int);
  29. static int trailing_spaces(int);
  30. static int first_wordlen(int);
  31. static int last_wordlen(void);
  32. static void paraform(int);
  33. static int blankline(int);
  34. static void delete_word(void);
  35. static void delete_line(void);
  36. static void delete_block(void);
  37. static void mvblock(int);
  38. static void carrtn(int);
  39. static void backspace(void);
  40. static void fore_word(void);
  41. static int spaceup(void);
  42. static void back_word(void);
  43. static int spacedn(void);
  44. static void forward(void);
  45. static int downward(void);
  46. static void upward(void);
  47. static void display_text(int);
  48. static void disp_line(int y);
  49. static void findlast(void);
  50.  
  51. /* ----- Process text entry for a window. ---- */
  52. int text_editor(char *bf, int editlines, int editwidth)
  53. {
  54.     int depart, i, c;
  55.     int svx, svlw, tx, tabctr, wraplen;
  56.  
  57.     current_window();
  58.     depart = FALSE;
  59.     tabctr = 0;
  60.     if (ev.envinuse == FALSE)    {
  61.         ev.wdo = &wkw;
  62.         ev.wwd = editwidth;
  63.         ev.wsz = ev.wwd * ev.wdo->ht;
  64.         ev.topptr = ev.bfptr = bf;
  65.         ev.nolines = editlines;
  66.         ev.endptr = bf + ev.wwd * ev.nolines;
  67.         ev.edinsert  = INSERTING;
  68.         ev.reforming = REFORMING;
  69.         ev.envinuse = TRUE;
  70.     }
  71.     set_cursor_type(ev.edinsert ? 0x0106 : 0x0607);
  72.     display_text(0);
  73.     findlast();
  74.     /* ------- read text/command from the keyboard ------ */
  75.     while (depart == FALSE)    {
  76.         ev.nowptr = curr(ev.curr_x, ev.curr_y);
  77.         if (status_line)
  78.             (*status_line)(); /* external status line func */
  79.         gotoxy(ev.curr_x + 2, ev.curr_y + 2);
  80.         if (tabctr)    {          /* expand typed tabs */
  81.             --tabctr;
  82.             c = ' ';
  83.         }
  84.         else
  85.             c = forcechar ? forcechar : getkey();
  86.         forcechar = 0;
  87.         switch (c)    {
  88. /* ------------ fixed editor commands ----------------- */
  89.             case '\r':
  90.                 carrtn(ev.edinsert);
  91.                 break;
  92.             case UP:
  93.                 upward();
  94.                 break;
  95.             case DN:
  96.                 downward();
  97.                 break;
  98.             case FWD:
  99.                 forward();
  100.                 break;
  101.             case '\b':
  102.             case BS:
  103.                 if (!(ev.curr_x || ev.curr_y))
  104.                     break;
  105.                 backspace();
  106.                 if (ev.curr_x == ev.wwd - 1)
  107.                     last_char();
  108.                 if (c == BS)
  109.                     break;
  110.                 ev.nowptr = curr(ev.curr_x, ev.curr_y);
  111.             case DEL:
  112.                 movmem(ev.nowptr+1,ev.nowptr,
  113.                     ev.wwd-1-ev.curr_x);
  114.                 *(ev.nowptr+ev.wwd-1-ev.curr_x) = ' ';
  115.                 disp_line(ev.curr_y);
  116.                 test_para(ev.curr_x+1);
  117.                 ev.text_changed = TRUE;
  118.                 break;
  119.             case PGUP:
  120.                 ev.curr_y = 0;
  121.                 do_display_text = FALSE;
  122.                 for (i = 0; i < ev.wdo->ht; i++)
  123.                     upward();
  124.                 do_display_text = TRUE;
  125.                 display_text(0);
  126.                 break;
  127.             case PGDN:
  128.                 ev.curr_y = ev.wdo->ht-1;
  129.                 do_display_text = FALSE;
  130.                 for (i = 0; i < ev.wdo->ht; i++)
  131.                     downward();
  132.                 do_display_text = TRUE;
  133.                 display_text(0);
  134.                 ev.curr_y = 0;
  135.                 break;
  136.             case '\t':
  137.                 if (ev.curr_x + NEXTTAB < ev.wwd)    {
  138.                     if (ev.edinsert)
  139.                         tabctr = NEXTTAB;
  140.                     else
  141.                         ev.curr_x += NEXTTAB;
  142.                 }
  143.                 else
  144.                     carrtn(ev.edinsert);
  145.                 break;
  146. /* -------- configured editor commands --------------- */
  147.             case REPAINT:
  148.                 display_text(ev.curr_y);
  149.                 break;
  150.             case BACKTAB:
  151.                 if (ev.curr_x < TAB)    {
  152.                     upward();
  153.                     ev.curr_x = LASTTAB;
  154.                 }
  155.                 else
  156.                     ev.curr_x -= PREVTAB;
  157.                 break;
  158.             case NEXTWORD:
  159.                 fore_word();
  160.                 break;
  161.             case PREVWORD:
  162.                 back_word();
  163.                 break;
  164.             case BOTSCREEN:
  165.                 ev.curr_y = ev.wdo->ht - 1;
  166.                 break;
  167.             case TOPSCREEN:
  168.                 ev.curr_y = 0;
  169.                 break;
  170.             case BEGIN_BUFFER:
  171.                 ev.curr_x = ev.curr_y = 0;
  172.                 ev.bfptr = ev.topptr;
  173.                 display_text(0);
  174.                 break;
  175.             case END_BUFFER:
  176.                 do_display_text = FALSE;
  177.                 ev.curr_x = 0;
  178.                 while (downward())
  179.                     if (curr(0,ev.curr_y) >= ev.lstptr)
  180.                         break;
  181.                 do_display_text = TRUE;
  182.                 display_text(0);
  183.                 break;
  184.             case BEGIN_LINE:
  185.                 ev.curr_x = 0;
  186.                 break;
  187.             case END_LINE:
  188.                 last_char();
  189.                 break;
  190.             case DELETE_LINE:
  191.                 delete_line();
  192.                 ev.text_changed = TRUE;
  193.                 break;
  194.             case DELETE_WORD:
  195.                 delete_word();
  196.                 ev.text_changed = TRUE;
  197.                 test_para(ev.curr_x);
  198.                 break;
  199.             case INSERT:
  200.                 ev.edinsert ^= TRUE;
  201.                 set_cursor_type(ev.edinsert ? 0x106 : 0x607);
  202.                 break;
  203.             case ESC:
  204.             case QUIT:
  205.                 depart = TRUE;
  206.                 break;
  207.             case PARAGRAPH:
  208.                 paraform(0);
  209.                 ev.text_changed = TRUE;
  210.                 break;
  211.             case BEGIN_BLOCK:
  212.                 ev.blkbeg = lineno(ev.curr_y) + 1;
  213.                 if (ev.blkbeg > ev.blkend)
  214.                     ev.blkend = ev.blkbeg;
  215.                 display_text(0);
  216.                 break;
  217.             case END_BLOCK:
  218.                 ev.blkend = lineno(ev.curr_y) + 1;
  219.                 if (ev.blkend < ev.blkbeg)
  220.                     ev.blkbeg = ev.blkend;
  221.                 display_text(0);
  222.                 break;
  223.             case MOVE_BLOCK:
  224.                 mvblock(TRUE);
  225.                 ev.text_changed = TRUE;
  226.                 break;
  227.             case COPY_BLOCK:
  228.                 mvblock(FALSE);
  229.                 ev.text_changed = TRUE;
  230.                 break;
  231.             case DELETE_BLOCK:
  232.                 delete_block();
  233.                 ev.text_changed = TRUE;
  234.                 display_text(0);
  235.                 break;
  236.             case HIDE_BLOCK:
  237.                 ev.blkbeg = ev.blkend = 0;
  238.                 display_text(0);
  239.                 break;
  240.             default:
  241.                 if (!isprint(c))    {
  242.                     /* ---- not recognized by editor --- */
  243.                     if (editfunc)    {
  244.                         /* --- extended commands --- */
  245.                         (*editfunc)(c);
  246.                         findlast();
  247.                         display_text(0);
  248.                     }
  249.                     else
  250.                         putch(BELL);
  251.                     break;
  252.                 }
  253.                 /* --- displayable char: put in buffer --- */
  254.                 if (ev.nowptr == ev.endptr-1 ||
  255.                    (lineno(ev.curr_y)+1 >=
  256.                        ev.nolines && ev.edinsert &&
  257.                        *curr(ev.wwd-2, ev.curr_y) != ' '))  {
  258.                     error_message("End of buffer...");
  259.                     break;
  260.                 }
  261.                 if (ev.edinsert) /* --- if insert mode --- */
  262.                     movmem(ev.nowptr,ev.nowptr+1,
  263.                         ev.wwd-1-ev.curr_x);
  264.                 if (ev.nowptr < ev.endptr)    {
  265.                     if (ev.nowptr >= ev.lstptr)
  266.                         ev.lstptr = ev.nowptr + 1;
  267.                     *ev.nowptr = (char) c; /* put in buff */
  268.                     disp_line(ev.curr_y);
  269.                 }
  270.                 if (ev.nowptr == curr(ev.wwd-1, ev.curr_y) &&
  271.                     c == ' ' && ev.edinsert)    {
  272.                     if (strncmp(curr(0,ev.curr_y+1),
  273.                             "        ",TAB) == 0)    {
  274.                         carrtn(TRUE);
  275.                         break;
  276.                     }
  277.                 }
  278.                 else if (ev.endptr &&
  279.                         *curr(ev.wwd-1, ev.curr_y) != ' ')    {
  280.                     /* ------- word wrap is needed ------- */
  281.                     ev.nowptr = curr(ev.wwd-1, ev.curr_y);
  282.                     svx = ev.curr_x;   /* save x vector */
  283.                     svlw = lastword(); /* last word on line?*/
  284.                     ev.curr_x = ev.wwd-1;
  285.                     if (*(ev.nowptr-1) != ' ')
  286.                         back_word();
  287.                     tx = ev.curr_x;
  288.                     wraplen = last_wordlen();
  289.                     if (trailing_spaces(ev.curr_y+1) <
  290.                             wraplen+2)
  291.                         carrtn(TRUE);
  292.                     else if (strncmp(curr(0,ev.curr_y+1),
  293.                             "        ",TAB) == 0)
  294.                         carrtn(TRUE);
  295.                     else    {
  296.                         ev.nowptr = curr(0, ev.curr_y+1);
  297.                         movmem(ev.nowptr,ev.nowptr+wraplen+1,
  298.                             ev.wwd-wraplen-1);
  299.                         setmem(ev.nowptr, wraplen+1, ' ');
  300.                         movmem(curr(ev.curr_x,ev.curr_y),
  301.                             ev.nowptr,wraplen);
  302.                         setmem(curr(ev.curr_x,ev.curr_y),
  303.                             wraplen, ' ');
  304.                         disp_line(ev.curr_y);
  305.                         downward();
  306.                         disp_line(ev.curr_y);
  307.                     }
  308.                     if (svlw)
  309.                         ev.curr_x = svx-tx;
  310.                     else
  311.                         ev.curr_x = svx, --ev.curr_y;
  312.                 }
  313.                 forward();
  314.                 ev.text_changed = TRUE;
  315.                 break;
  316.         }
  317.     }
  318.     return c;
  319. }
  320.  
  321. /* ----- see if a word is the last word on the line ------ */
  322. static int lastword()
  323. {
  324.     int x = ev.curr_x;
  325.     char *bf = curr(ev.curr_x, ev.curr_y);
  326.     while (x++ < ev.wwd-1)
  327.         if (*bf++ == ' ')
  328.             return 0;
  329.     return 1;
  330. }
  331.  
  332. /* --- go to last displayable character on the line --- */
  333. static void last_char()
  334. {
  335.     char *bf = curr(0, ev.curr_y);
  336.     ev.curr_x = ev.wwd-1;
  337.     while (ev.curr_x && *(bf + ev.curr_x) == ' ')
  338.         --ev.curr_x;
  339.     if (ev.curr_x && ev.curr_x < ev.wwd - 1)
  340.         ev.curr_x++;
  341. }
  342.  
  343. /* ----- test to see if paragraph should be reformed ----- */
  344. static void test_para(int x)
  345. {
  346.     int ts, fw;
  347.     int svb, sve;
  348.  
  349.     if (ev.reforming && ev.curr_y < ev.nolines)    {
  350.         ts = trailing_spaces(ev.curr_y);
  351.         fw = first_wordlen(ev.curr_y+1);
  352.         if (fw && ts > fw)    {
  353.             svb = ev.blkbeg, sve = ev.blkend;
  354.             ev.blkbeg = ev.blkend = 0;
  355.             paraform(x);
  356.             ev.blkbeg = svb, ev.blkend = sve;
  357.             if (svb)
  358.                 display_text(0);
  359.         }
  360.     }
  361. }
  362.  
  363. /* ---- count the trailing spaces on a line ----- */
  364. static int trailing_spaces(int y)
  365. {
  366.     int x = ev.wwd-1, ct = 0;
  367.     char *bf = curr(0, y);
  368.     while (x >= 0)    {
  369.         if (*(bf + x) != ' ')
  370.             break;
  371.         --x;
  372.         ct++;
  373.     }
  374.     return ct;
  375. }
  376.  
  377. /* ----- count the length of the first word on a line --- */
  378. static int first_wordlen(int y)
  379. {
  380.     int ct = 0, x = 0;
  381.     char *bf = curr(0, y);
  382.     while (x < ev.wwd-1 && *bf == ' ')
  383.         x++, bf++;
  384.     while (x < ev.wwd-1 && *bf != ' ')
  385.         ct++, x++, bf++;
  386.     return ct;
  387. }
  388.  
  389. /* ----- count the length of the last word on a line --- */
  390. static int last_wordlen()
  391. {
  392.     int ct = 0, x = ev.wwd-1;
  393.     char *bf = curr(x, ev.curr_y);
  394.     while (x && *bf == ' ')
  395.         --x, --bf;
  396.     while (x && *bf != ' ')
  397.         --x, --bf, ct++;
  398.     return ct;
  399. }
  400.  
  401. /* ------------ form a paragraph -------------- */
  402. static void paraform(int x)
  403. {
  404.     char *cp1, *cp2, *cpend, *svcp;
  405.     int x1, y1, firstline = TRUE;
  406.     int y = ev.curr_y;
  407.  
  408.     if (!ev.blkbeg)    {    /* ---- if block not marked ---- */
  409.         if (blankline(lineno(y)+1))
  410.             return;        /* next line is blank, no reform */
  411.         ev.blkbeg=ev.blkend=lineno(y)+1; /* pseudoblock */
  412.         ev.blkend++;
  413.         y1 = y+1;
  414.         while (ev.blkend < ev.nolines)    { /* look for para */
  415.             if (strncmp(curr(0, y1++), "        ", TAB) == 0)
  416.                 break;
  417.             ev.blkend++;
  418.         }
  419.         --ev.blkend;
  420.     }
  421.     if (lineno(y) != ev.blkbeg-1)
  422.         x = 0;
  423.     x1 = x;
  424.     cp1 = cp2 = ev.topptr + (ev.blkbeg - 1) * ev.wwd + x;
  425.     cpend = ev.topptr + ev.blkend * ev.wwd;
  426.     while (cp2 < cpend)    {
  427.         while (*cp2 == ' ' && cp2 < cpend)    {
  428.             if (firstline)
  429.                 *cp1++ = *cp2, x1++;
  430.             cp2++;
  431.         }
  432.         firstline = FALSE;
  433.         if (cp2 == cpend)
  434.             break;
  435.         /* ---- at a word ---- */
  436.         while (*cp2 != ' ' && cp2 < cpend)    {
  437.             if (x1 >= ev.wwd-1)    {
  438.                 /* wrap the word */
  439.                 svcp = cp1 + (ev.wwd - x1);
  440.                 while (*--cp1 != ' ')
  441.                     *cp1 = ' ',    --cp2;
  442.                 x1 = 0;
  443.                 ev.blkbeg++;
  444.                 cp1 = svcp;
  445.                 if (y < ev.wdo->ht)
  446.                     disp_line(y++);
  447.             }
  448.             *cp1++ = *cp2++;
  449.             x1++;
  450.         }
  451.         if (cp2 < cpend)
  452.             *cp1++ = ' ', x1++;
  453.     }
  454.     while (cp1 < cpend)
  455.         *cp1++ = ' ';
  456.      ev.blkbeg++;
  457.     if (y < ev.wdo->ht)
  458.         disp_line(y++);
  459.     firstline = ev.blkbeg;
  460.      if (ev.blkbeg <= ev.blkend)    {
  461.         delete_block();
  462.         display_text(y);
  463.     }
  464.     ev.blkbeg = ev.blkend = 0;
  465.     if (firstline)
  466.         display_text(0);
  467. }
  468.  
  469. /* ------- test for a blank line ---------- */
  470. static int blankline(int line)
  471. {
  472.     char *cp = ev.topptr + (line-1) * ev.wwd;
  473.     int x = ev.wwd;
  474.     while (x--)
  475.         if (*cp++ != ' ')
  476.             break;
  477.     return !(x > -1);
  478. }
  479.  
  480. /* ------------- delete a word -------------- */
  481. static void delete_word()
  482. {
  483.     int wct = 0;
  484.     char *cp1, *cp2;
  485.  
  486.     cp1 = cp2 = curr(ev.curr_x, ev.curr_y);
  487.     if (*cp2 == ' ')
  488.         while (*cp2 == ' ' && ev.curr_x + wct < ev.wwd)
  489.             wct++, cp2++;
  490.     else    {
  491.         while (*cp2 != ' ' && ev.curr_x + wct < ev.wwd)
  492.             wct++, cp2++;
  493.         while (*cp2 == ' ' && ev.curr_x + wct < ev.wwd)
  494.             wct++, cp2++;
  495.     }
  496.     movmem(cp2, cp1, ev.wwd - ev.curr_x - wct);
  497.     setmem(cp1 + ev.wwd - ev.curr_x - wct, wct, ' ');
  498.     disp_line(ev.curr_y);
  499. }
  500.  
  501. /* ----------- delete a line --------------- */
  502. static void delete_line()
  503. {
  504.     char *cp1, *cp2;
  505.     int len;
  506.  
  507.     cp1 = ev.bfptr + ev.curr_y * ev.wwd;
  508.     cp2 = cp1 + ev.wwd;
  509.     if (cp1 < ev.lstptr)    {
  510.         len = ev.endptr - cp2;
  511.         movmem(cp2, cp1, len);
  512.         ev.lstptr -= ev.wwd;
  513.         setmem(ev.endptr - ev.wwd, ev.wwd, ' ');
  514.         display_text(ev.curr_y);
  515.     }
  516. }
  517.  
  518. /* ----------- delete a block ------------- */
  519. static void delete_block()
  520. {
  521.     char *cp1, *cp2;
  522.     int len;
  523.  
  524.     if (!ev.blkbeg || !ev.blkend)    {
  525.         error_message("No block marked ...");
  526.         return;
  527.     }
  528.     cp1 = ev.topptr + ev.blkend * ev.wwd;
  529.     cp2 = ev.topptr + (ev.blkbeg - 1) * ev.wwd;
  530.     len = ev.endptr - cp1;
  531.     movmem(cp1, cp2, len);
  532.     setmem(cp2 + len, ev.endptr - (cp2 + len), ' ');
  533.     ev.blkbeg = ev.blkend = 0;
  534.     ev.lstptr -= cp1 - cp2;
  535. }
  536.  
  537. /* ------- move and copy text blocks -------- */
  538. static void mvblock(int moving)
  539. {
  540.     char *cp1, *cp2, *hd;
  541.     unsigned len;
  542.  
  543.     if (!ev.blkbeg || !ev.blkend)    {
  544.         error_message("No block marked ...");
  545.         return;
  546.     }
  547.     if (lineno(ev.curr_y) >= ev.blkbeg-1
  548.             && lineno(ev.curr_y) <= ev.blkend-1)    {
  549.         error_message("Don't move/copy a block into itself");
  550.         return;
  551.     }
  552.     len = (ev.blkend - ev.blkbeg + 1) * ev.wwd;
  553.     if ((hd = malloc(len)) == NULL)
  554.         return;
  555.     cp1 = ev.topptr + (ev.blkbeg-1) * ev.wwd;
  556.     movmem(cp1, hd, len);
  557.     cp2 = ev.topptr + lineno(ev.curr_y) * ev.wwd;
  558.     if (moving)    {
  559.         if (lineno(ev.curr_y) > ev.blkbeg-1)
  560.             cp2 -= len;
  561.         delete_block();
  562.     }
  563.     if (cp2+len <= ev.endptr)    {
  564.         movmem(cp2, cp2 + len, ev.endptr - cp2 - len);
  565.         movmem(hd, cp2, len);
  566.         ev.lstptr += cp1 - cp2;
  567.     }
  568.     else
  569.         error_message("Not enough room...");
  570.     free(hd);
  571.     ev.blkbeg = ev.blkend = 0;
  572.     display_text(0);
  573. }
  574.  
  575. /* ------- find the last character in the buffer -------- */
  576. static void findlast()
  577. {
  578.     char *lp = ev.endptr - 1, *tp = ev.topptr;
  579.     while (lp > tp && *lp == ' ')
  580.         --lp;
  581.     if (*lp != ' ')
  582.         lp++;
  583.     ev.lstptr = lp;
  584. }
  585.  
  586. /* -------- carriage return -------- */
  587. static void carrtn(int insert)
  588. {
  589.     int insct;
  590.     char *cp = curr(ev.curr_x, ev.curr_y);
  591.     char *nl = cp+((cp-ev.topptr)%ev.wwd);
  592.     int ctl = 2;
  593.     if (lineno(ev.curr_y) + 2 < ev.nolines)
  594.         if (insert && nl < ev.endptr)    {
  595.             insct = ev.wwd - ev.curr_x;
  596.             while (ctl--)    {
  597.                 if (ev.endptr > cp + insct)    {
  598.                     movmem(cp, cp+insct, ev.endptr-insct-cp);
  599.                     setmem(cp, insct, ' ');
  600.                 }
  601.                 else if (ctl == 1)
  602.                     setmem(cp, ev.endptr - cp, ' ');
  603.                 cp += insct * 2;
  604.                 insct = ev.curr_x;
  605.             }
  606.         }
  607.     ev.curr_x = 0;
  608.     downward();
  609.     if (insert)    {
  610.         ev.text_changed = TRUE;
  611.         test_para(0);
  612.         display_text(ev.curr_y-1);
  613.         if (lineno(ev.curr_y) + 2 < ev.nolines)
  614.             if ((ev.lstptr + ev.wwd) <= ev.endptr)
  615.                 if (ev.lstptr > curr(ev.curr_x, ev.curr_y))
  616.                     ev.lstptr += ev.wwd;
  617.     }
  618. }
  619.  
  620. /* ------- move the buffer offset back one position ------ */
  621. static void backspace()
  622. {
  623.     if (ev.curr_x == 0)    {
  624.         if (ev.curr_y)
  625.             ev.curr_x = ev.wwd - 1;
  626.         upward();
  627.     }
  628.     else
  629.         --ev.curr_x;
  630. }
  631.  
  632. /* -------- move the buffer offset forward one word ------ */
  633. static void fore_word()
  634. {
  635.     while (*ev.nowptr != ' ')    {
  636.         if (spaceup() == 0)
  637.             return;
  638.         if (ev.curr_x == 0)
  639.             break;
  640.     }
  641.     while (*ev.nowptr == ' ')
  642.         if (spaceup() == 0)
  643.             return;
  644. }
  645.  
  646. static int spaceup()
  647. {
  648.     if (ev.nowptr >= ev.lstptr)
  649.         return 0;
  650.     ev.nowptr++;
  651.     forward();
  652.     return 1;
  653. }
  654.  
  655. /* ------- move the buffer offset backward one word ------ */
  656. static void back_word()
  657. {
  658.     spacedn();
  659.     while (*ev.nowptr == ' ')
  660.         if (spacedn() == 0)
  661.             return;
  662.     while (*ev.nowptr != ' ')    {
  663.         if (ev.curr_x == 0)
  664.             return;
  665.         if (spacedn() == 0)
  666.             return;
  667.     }
  668.     spaceup();
  669. }
  670.  
  671. static int spacedn()
  672. {
  673.     if (ev.nowptr == ev.topptr)
  674.         return 0;
  675.     --ev.nowptr;
  676.     backspace();
  677.     return 1;
  678. }
  679.  
  680. /* ----- move the buffer offset forward one position ----- */
  681. static void forward()
  682. {
  683.     int ww = ev.wwd;
  684.     if (++ev.curr_x == ww)    {
  685.         downward();
  686.         ev.curr_x = 0;
  687.     }
  688. }
  689.  
  690. /* ------- move the buffer offset down one position ------ */
  691. static int downward()
  692. {
  693.     if (ev.curr_y < ev.wdo->ht - 1)    {
  694.         ev.curr_y++;
  695.         return 1;
  696.     }
  697.     else if ((ev.bfptr + ev.wsz) < ev.endptr)    {
  698.         ev.bfptr += ev.wwd;
  699.         if (do_display_text)    {
  700.             scroll_window(1);
  701.             disp_line(ev.wdo->ht-1);
  702.         }
  703.         return 1;
  704.     }
  705.     return 0;
  706. }
  707.  
  708. /* -------- move the buffer offset up one position ------ */
  709. static void upward()
  710. {
  711.     if (ev.curr_y)
  712.         --ev.curr_y;
  713.     else if ((ev.topptr + ev.wwd) <= ev.bfptr)    {
  714.         ev.bfptr -= ev.wwd;
  715.         if (do_display_text)    {
  716.             scroll_window(0);
  717.             disp_line(0);
  718.         }
  719.     }
  720. }
  721.  
  722. /* ---- display lines in a window ------ */
  723. static void display_text(y)
  724. {
  725.     while (y < ev.wdo->ht)
  726.         disp_line(y++);
  727. }
  728.  
  729. /* ---------- Display a line -------- */
  730. static void disp_line(int y)
  731. {
  732.     char ln[81];
  733.  
  734.     if (lineno(y) >= ev.blkbeg-1)
  735.         if (lineno(y) <= ev.blkend-1)    {
  736.             textcolor(BLOCKFG);
  737.             textbackground(BLOCKBG);
  738.         }
  739.     movmem(ev.bfptr+y*ev.wwd, ln, ev.wwd);
  740.     ln[ev.wwd] = '\0';
  741.     writeline(2, y+2, ln);
  742.     textcolor(TEXTFG);
  743.     textbackground(TEXTBG);
  744. }
  745.  
  746.