home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1988 / 11 / stevens.asc < prev    next >
Text File  |  1988-10-21  |  25KB  |  855 lines

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